diff --git a/IrTxBsrrWave.h b/IrTxBsrrWave.h index 31115ff..f5178f4 100644 --- a/IrTxBsrrWave.h +++ b/IrTxBsrrWave.h @@ -65,13 +65,63 @@ public: return out; } + // Заполнение по ранам, а не по словам: тот же поток слов, что даёт nextWord() (состояние + // runIndex_/ticksLeftInRun_/slotInPeriod_ переносится через границы порций), но пауза (gate=0) + // пишется одним циклом записи, а несущая — копией готового шаблона периода. На 12 МГц это + // ~1 мс на 4096 слов вместо ~16 (пословный автомат) — и в предзаполнении перед стартом DMA, + // и в ISR-дозаполнении половин буфера во время передачи. IR_TX_BSRR_WAVE_HOT void fill(uint32_t* dst, uint16_t count) { if (dst == nullptr || count == 0) { return; } - do { - *dst++ = nextWord(); - } while (--count != 0); + while (count != 0) { + if (runIndex_ >= runCount) { + do { *dst++ = resetWord; } while (--count != 0); + return; + } + const bool gate = runs[runIndex_].gate; + uint16_t n = ticksLeftInRun_; // слов до конца текущего рана + if (n == 0) n = 1; // ран нулевой длины: nextWord() выдаёт одно слово и переходит дальше + if (n > count) n = count; + if (!gate) { + slotInPeriod_ = 0; + uint16_t k = n; + do { *dst++ = resetWord; } while (--k != 0); + } else { + uint16_t k = n; + // добить текущий период до слота 0 (если ран начался посреди периода на границе порции) + while (k != 0 && slotInPeriod_ != 0) { + *dst++ = (slotInPeriod_ < powerN_) ? setWord : resetWord; + if (++slotInPeriod_ >= multiply_) slotInPeriod_ = 0; + k--; + } + // целые периоды: powerN_ слов setWord, остальные resetWord + while (k >= multiply_) { + uint16_t i = 0; + for (; i < powerN_; ++i) *dst++ = setWord; + for (; i < multiply_; ++i) *dst++ = resetWord; + k = (uint16_t)(k - multiply_); + } + // хвост неполного периода + while (k != 0) { + *dst++ = (slotInPeriod_ < powerN_) ? setWord : resetWord; + if (++slotInPeriod_ >= multiply_) slotInPeriod_ = 0; + k--; + } + } + count = (uint16_t)(count - n); + if (ticksLeftInRun_ > n) { + ticksLeftInRun_ = (uint16_t)(ticksLeftInRun_ - n); + } else { + ticksLeftInRun_ = 0; + } + if (ticksLeftInRun_ == 0) { + runIndex_++; + if (runIndex_ < runCount) { + ticksLeftInRun_ = runs[runIndex_].lenTicks; + } + } + } } private: