Зависит только от конфигурационных констант (bitTime, tolerance, syncBits) — это таймаут байта
(irRxByteTimeoutUs) × 2.7735 = 42 мс; значение не изменилось. Потребителям достаточно IR_config.h.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeA1K5dBUKrnoXVwyoVjzq
- IR_config.h: irFrameAirtimeUs/irFrameDecodeEndUs/irLockToDecodeEndUs/irLockLatencyUs,
irMaxPackSize (31), irDataPackSize/irBackPackSize — все из констант FSM передатчика
(преамбула 6×98 тактов, байт 11 бит × 74 такта, такт = полпериода несущей).
- IR_Encoder::calculateSendTime по той же формуле (раньше синхробиты считались один раз
на кадр → занижение 21-26%, потребители компенсировали +30%).
- IR_DecoderRaw: rxLockSeq/rxLockTimeUs (лок преамбулы), rxMsgType, rxExpectedEndUs
(по объявленной длине), rxLastEnd {seq, reason Ok/Crc/Timeout/Abort, msgType, packSize,
tUs, expectedEndUs}. Терминалы: конец кадра, таймаут тишины, немедленный abort при
sync-ошибке / длине <3 (в т.ч. 0) / переполнении — битый кадр больше не держит
isReciving до конца чужой передачи + 30 мс.
- Порядок в tick: checkTimeout до listenStart (TIMEOUT-лог с реальной длиной), истечение
кандидата преамбулы без фронтов, ложный PREAMB-инкремент на старте кандидата убран.
- rxMaxPackSize() = протокольные 31 (было 38 = размер буфера).
Совместимость: только добавления; существующие сигнатуры не тронуты. Собрано для G4 (Car)
и F4 (КУ).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeA1K5dBUKrnoXVwyoVjzq
Для гейта заднего у машинки (Даша 04.09): держать задний по СОСТОЯНИЮ приёма, но
не дольше airtime кадра — а если объявленный в 1-м байте размер МЕНЬШЕ протокольного
максимума, то ровно до его конца (усиление надёжности). rxDeclaredPackSize() =
packSize из 1-го байта, если валиден (не битый) и идёт приём, иначе 0 (потребитель
берёт rxMaxPackSize() — до CRC значение недоверенное). packAirtimeMs() — публичная
обёртка над calculateSendTime (чистая функция протокольных констант, годна и для RX).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J3Ca6J2JJ1NrptqQjKs8BK
Декодер уже знает состояние приёма (isReciving=локнут; preambleState Idle/
Candidate/Locked). rxLineActive() = локнут ИЛИ формируется ВАЛИДНАЯ преамбула
(>=1 совпавший по периоду фронт — отличает реальный кадр от одиночного шумового
фронта, который лишь заводит Candidate, но не набирает goodPeriods). Для гейта
заднего у машинки: не стрелять, пока на линии идёт/формируется ответ точки —
решение по состоянию, а не по хардкод-длительности (Даша 04.09). Аддитивно, const.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J3Ca6J2JJ1NrptqQjKs8BK
rxBriefLog теперь безусловен: ВСЕГДА инкрементирует rxReasonCnt[reason]
(наблюдаемость по контракту живучести — работает в проде без печати),
печать события — только при IR_RX_BRIEF_LOG. 14 точек вызова развёрнуты
из-под #if (Glitch/Timing/Preamble/Sync/BufOverflow/Timeout/Crc/Ok +
pulse-filter пути); ISR-агрегатные MuteBegin/End/RawOverflow остаются
только при логе (их флаш живёт в brief-механике). Публичное API:
rxReasonCounters() / rxReasonCountersClear() / printRxReasonStats(Print&)
-> 'RXSTAT,GLITCH=..,TIME=..,...,OK=..'.
Компил-чек: LaserTestCheck (G4, флаг выкл) и Plan_B (F4, флаг вкл) — чисто.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>