mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-18 19:13:58 +00:00
fix(rx): после обрыва кадра не требовать 30 мс тишины перед новым кандидатом преамбулы (releasePreambleGuard)
prevRise (последний декодированный фронт) не сбрасывался при abortFrame, а отброшенные гвардом фронты его не двигают — валидный кадр, начавшийся через <30 мс после обрыва мусора, проглатывался целиком без счётчика. Стенд 09.09: КУ теряла пинг машинки после обрывков чужого заднего и всплеска её дальномера за 24 мс до пинга (V-серия 75–83 %, после правки 100 %). Хост-тест (настоящий IR_DecoderRaw.cpp + шим Arduino): после abort кадр через 5…28 мс — терялся, теперь принимается; чистый конец кадра не тронут (мин. пауза 26.25 мс), хвост оборванного кадра ложных захватов не даёт, 200/200 валидных среди мусора, стресс 166→176/200. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeA1K5dBUKrnoXVwyoVjzq
This commit is contained in:
@ -440,6 +440,19 @@ void IR_DecoderRaw::abortFrame(uint32_t tUs)
|
|||||||
isReciveRaw = false;
|
isReciveRaw = false;
|
||||||
msgTypeReceive = 0;
|
msgTypeReceive = 0;
|
||||||
firstRX();
|
firstRX();
|
||||||
|
releasePreambleGuard(tUs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// После обрыва кадра «длинная тишина» (IR_timeout × 2 ≈ 30 мс) перед новым кандидатом преамбулы не требуется.
|
||||||
|
// prevRise — последний ДЕКОДИРОВАННЫЙ фронт; после abort он свежий, а фронты, отброшенные гвардом, его не двигают,
|
||||||
|
// поэтому валидный кадр, начавшийся через <30 мс после обрыва мусора, проглатывался целиком без счётчика
|
||||||
|
// (стенд 09.09: КУ теряла пинг машинки после обрывков чужого заднего и всплеска её дальномера за 24 мс до пинга).
|
||||||
|
// Ложных захватов это не добавляет: хвост оборванного кадра (период фронтов 962 мкс, синхробиты ~1100) не проходит
|
||||||
|
// грубый фильтр периода преамбулы (2116…3270 мкс), а настоящая преамбула перезапускает кандидата по паузе > IR_timeout.
|
||||||
|
// После чистого конца кадра гвард остаётся: там он отсекает хвост синхробитов.
|
||||||
|
void IR_DecoderRaw::releasePreambleGuard(uint32_t tUs)
|
||||||
|
{
|
||||||
|
prevRise = tUs - IR_timeout * 2U - 1U; // «тишина уже была»: (front.time - prevRise) > longSilence для следующего фронта
|
||||||
}
|
}
|
||||||
|
|
||||||
void IR_DecoderRaw::expirePreambleCandidate()
|
void IR_DecoderRaw::expirePreambleCandidate()
|
||||||
|
|||||||
@ -186,6 +186,7 @@ private:
|
|||||||
RxEndInfo rxEnd;
|
RxEndInfo rxEnd;
|
||||||
void noteRxEnd(RxEndReason reason, uint32_t tUs); // терминал: фиксирует тип/длину/расчётный конец
|
void noteRxEnd(RxEndReason reason, uint32_t tUs); // терминал: фиксирует тип/длину/расчётный конец
|
||||||
void abortFrame(uint32_t tUs); // немедленный сброс битого кадра (sync/длина/overflow)
|
void abortFrame(uint32_t tUs); // немедленный сброс битого кадра (sync/длина/overflow)
|
||||||
|
void releasePreambleGuard(uint32_t tUs); // после abort: новый кандидат преамбулы без ожидания длинной тишины
|
||||||
void expirePreambleCandidate(); // кандидат без фронтов дольше таймаута → Idle
|
void expirePreambleCandidate(); // кандидат без фронтов дольше таймаута → Idle
|
||||||
uint8_t preambleGoodPeriods = 0;
|
uint8_t preambleGoodPeriods = 0;
|
||||||
uint16_t preambleMeanPeriod = 0;
|
uint16_t preambleMeanPeriod = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user