From 2f5b57680b3a6f59e95ac5639ed22121d7bc5206 Mon Sep 17 00:00:00 2001 From: DashyFox Date: Mon, 20 Apr 2026 14:49:38 +0300 Subject: [PATCH] Add documentation for IR TX modes in the library --- ref/IR_TX_MODES.md | 146 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 ref/IR_TX_MODES.md diff --git a/ref/IR_TX_MODES.md b/ref/IR_TX_MODES.md new file mode 100644 index 0000000..b435c17 --- /dev/null +++ b/ref/IR_TX_MODES.md @@ -0,0 +1,146 @@ +# Режимы 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); +```