Зависит только от конфигурационных констант (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
Кандидат без фронтов дольше таймаута байта преамбулой быть не может. При 3× (45 мс)
rxLineActive() держал линию «занятой» после паразитных фронтов (засветка своим
дальномером) и откладывал пинг машинки на ~30 мс сверх заданного гэпа.
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
HAL_NVIC_EnableIRQ без SetPriority оставлял DMA-каналы TX на приоритете 0 (уровень
SysTick на G4). Длинный refill кольца BSRR (полубуфер 2048 слов = ~3.3мс при HCLK
12МГц) не вытеснялся, тики SysTick слипались: millis() замедлялся в 1.6x (один
излучатель) / 2.2x (два) на всё время передачи. На машинке это ~37% вранья часов
в каждый ИК-кадр: PID dt, планировщик, тайминги протокола.
Мерено на стенде TofSickHunt 2026-08-11 (Car raw/idle_cur_vs_coup*): прогоны «60с»
шли 85-95 реальных секунд. Фикс: irproto::kDmaTxIrqPriority=8 — ниже EXTI приёмника
(6), выше дна; SysTick честный. ISR-TX путь (F401/КУ) не подвержен: его refill на
TIM-приоритете 14. Верификация дилатации на стенде — раунд 4 (прерван, перезапустить).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Было: 1 сырой фронт за tick() -> RX-пропускная способность привязана к loop;
медленный loop (телеметрия/дисплей/КУ-печать) переполнял ISR-буфер 250 фронтов
(~120мс эфира) и кадры гибли молча (вероятная составляющая 'КУ отвечает не на
каждый пакет'). Стало: до IR_RX_TICK_BATCH фронтов за tick; idle-семантика
сохранена (flush пульс-фильтра только при пустом буфере; listenStart/
checkTimeout как раньше). Переопределяемо дефайном до include.
Компил-чек: LaserTestCheck (G491) собирается.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>