5.6 KiB
Режимы IR TX в библиотеке
Этот документ описывает, как в библиотеке выбирается путь передачи IR и как его правильно использовать в проектах Arduino STM32.
Кратко
У библиотеки есть три варианта TX:
legacy ISR— внутренний ISR-путь без внешнего backend. Это путь по умолчанию для обратной совместимости.buffered ISR— внутренний ISR-путь с предварительной подготовкой BSRR-слов и кольцевым буфером.external backend— передача делегируется проекту черезIR_Encoder::setExternalTxBackend(...), например в DMA backend.
Порядок выбора такой:
- Если зарегистрирован
external backend, используется он. - Иначе используется внутренний ISR библиотеки.
- Для внутреннего ISR:
- по умолчанию включён
legacy ISR buffered ISRвключается явно: нужно привязать storage к encoder и переключить режим
- по умолчанию включён
1. Legacy ISR
Это режим по умолчанию. Старые проекты могут ничего не менять:
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.
Для явного выбора можно написать:
IR_Encoder::setTxIsrLegacyMode(true);
IR_Encoder::begin(&timer, 1, TIM11_IRQn, 0);
2. Buffered ISR
Этот режим использует внутренний буферный ISR-путь библиотеки. Он включается только явно:
#include <IrTxIsrBufferedStorage.h>
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:
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_Encoder::begin(...);
Итог: legacy ISR
Нужен новый внутренний буферный ISR
Включить явно:
#include <IrTxIsrBufferedStorage.h>
static IrTxIsrBufferedStorage<> txStorage;
enc.enableBufferedIsr(txStorage);
IR_Encoder::begin(...);
Итог: buffered ISR
Нужен проектный DMA или другой свой транспорт
Подключить внешний backend:
IR_Encoder::beginClockOnly(...);
IR_Encoder::setExternalTxBackend(...);
Итог: external backend
Рекомендация для совместимости
Для старых проектов безопаснее не вызывать setTxIsrLegacyMode(false), если нет явной причины переходить на buffered ISR.
Если задача — сохранить старое поведение без неожиданного роста нагрузки на TX-логику, оставляйте default legacy ISR или задавайте его явно:
IR_Encoder::setTxIsrLegacyMode(true);