Files
IR-protocol/ref/IR_TX_MODES.md

5.6 KiB
Raw Permalink Blame History

Режимы 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

Это режим по умолчанию. Старые проекты могут ничего не менять:

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);