# Режимы IR TX в библиотеке Этот документ описывает, как в библиотеке выбирается путь передачи IR и как его правильно использовать в проектах Arduino STM32. ## Кратко У библиотеки есть три варианта TX: - `legacy ISR` — внутренний ISR-путь без внешнего backend. Это путь по умолчанию для обратной совместимости. - `buffered ISR` — внутренний ISR-путь с предварительной подготовкой BSRR-слов и кольцевым буфером. - `external backend` — передача делегируется проекту через `IR_Encoder::setExternalTxBackend(...)`, например в DMA backend. Порядок выбора такой: 1. Если зарегистрирован `external backend`, используется он. 2. Иначе используется внутренний ISR библиотеки. 3. Для внутреннего ISR: - по умолчанию включён `legacy ISR` - `buffered ISR` включается явно: нужно привязать storage к encoder и переключить режим ## 1. Legacy ISR Это режим по умолчанию. Старые проекты могут ничего не менять: ```cpp static HardwareTimer timer(TIM11); static IR_Encoder enc(PA9, 42, &dec); void setup() { IR_Encoder::begin(&timer, 1, TIM11_IRQn, 0); enc.enable(); } ``` Если проект не регистрирует внешний backend и не переключает режим явно, библиотека работает в `legacy ISR`. Для явного выбора можно написать: ```cpp IR_Encoder::setTxIsrLegacyMode(true); IR_Encoder::begin(&timer, 1, TIM11_IRQn, 0); ``` ## 2. Buffered ISR Этот режим использует внутренний буферный ISR-путь библиотеки. Он включается только явно: ```cpp #include static IrTxIsrBufferedStorage<> txStorage; enc.enableBufferedIsr(txStorage); IR_Encoder::begin(&timer, 1, TIM11_IRQn, 0); ``` Нижнеуровневый вариант API — отдельно привязать storage через `attachBufferedIsrStorage(...)`, но в обычном проекте удобнее использовать `enableBufferedIsr(...)`. Смысл режима: - пакет сначала превращается в `gate runs` - затем в поток слов `GPIO->BSRR` - ISR выдаёт готовые слова из кольцевого буфера ### Важно про RAM В текущей реализации память под буферный ISR вынесена из `IR_Encoder` в отдельный storage-объект. То есть: - `legacy ISR` не тянет buffered-буферы в RAM самого `IR_Encoder` - память под `gate runs` и `BSRR words` появляется только там, где проект сам создал `IrTxIsrBufferedStorage<>` Это важно для STM32 с небольшим объёмом RAM, например для `STM32F401`. ## 3. External backend Если проект хочет полностью взять TX на себя, библиотека позволяет зарегистрировать внешний backend: ```cpp static bool txBusy(void* ctx); static bool txStart(void* ctx, IR_Encoder* enc, const uint8_t* packet, uint8_t len); void setup() { IR_Encoder::beginClockOnly(&timer); IR_Encoder::setExternalTxBackend(txStart, txBusy, nullptr); enc.enable(); } ``` После вызова `setExternalTxBackend(...)` библиотека больше не использует свои внутренние ISR-пути для фактической передачи. В этом режиме: - `setTxIsrLegacyMode(true/false)` игнорируется - завершение передачи должен сигнализировать сам backend через `enc->externalFinishSend()` Подробности по встроенному DMA backend для `STM32G4xx`: см. [IR_DMA_TX_backend.md](IR_DMA_TX_backend.md). ## Когда какой режим использовать ### Старый проект, который ничего не настраивает Использовать как есть: ```cpp IR_Encoder::begin(...); ``` Итог: `legacy ISR` ### Нужен новый внутренний буферный ISR Включить явно: ```cpp #include static IrTxIsrBufferedStorage<> txStorage; enc.enableBufferedIsr(txStorage); IR_Encoder::begin(...); ``` Итог: `buffered ISR` ### Нужен проектный DMA или другой свой транспорт Подключить внешний backend: ```cpp IR_Encoder::beginClockOnly(...); IR_Encoder::setExternalTxBackend(...); ``` Итог: `external backend` ## Рекомендация для совместимости Для старых проектов безопаснее не вызывать `setTxIsrLegacyMode(false)`, если нет явной причины переходить на buffered ISR. Если задача — сохранить старое поведение без неожиданного роста нагрузки на TX-логику, оставляйте default `legacy ISR` или задавайте его явно: ```cpp IR_Encoder::setTxIsrLegacyMode(true); ```