perf(tx): таблица ранов кадра строится по границам ранов, а не по тактам несущей

buildGateRuns/buildPhysicalGateRuns крутили автомат передачи по одному такту (пинг 10 байт =
8728 тактов) — на 12 МГц это ~30 мс между вызовом send и стартом DMA, на каждой передаче
(задний ~20 мс). Обход по границам (txWalkRuns: ран = toggleCounter+1 тактов уровня state)
даёт ту же последовательность за число шагов = число ранов (225). Эквивалентность проверена на
хосте: 12480 случаев, len 1..38, множитель 2..8, логические и физические раны совпадают
бит-в-бит (len=39 — чтение за буфером в sync-фазе автомата у обеих версий, на эфире ≤31).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeA1K5dBUKrnoXVwyoVjzq
This commit is contained in:
2026-09-07 17:33:20 +03:00
parent 86956bcf99
commit d103d2a3ae
2 changed files with 54 additions and 41 deletions

View File

@ -214,6 +214,8 @@ private:
static bool txAdvanceBoundary(TxFsmState &st, const uint8_t *sendBufferLocal);
static bool txAdvanceAfterOutput(TxFsmState &st, const uint8_t *sendBufferLocal);
static bool txEmitTick(TxFsmState &st, const uint8_t *sendBufferLocal, bool &gateOut);
template <typename Emit>
static bool txWalkRuns(TxFsmState &st, const uint8_t *sendBufferLocal, Emit emit);
void loadTxFsmFromMembers(TxFsmState &st) const;
void storeTxFsmToMembers(const TxFsmState &st);
bool shouldUseBufferedIsr() const;