mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-18 19:13:58 +00:00
feat(rx): always-on счётчики причин RX-событий (rxReasonCnt) + RXSTAT-сводка
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>
This commit is contained in:
@ -145,9 +145,19 @@ const __FlashStringHelper *IR_DecoderRaw::rxBriefReasonTag(RxBriefReason reason)
|
||||
default: return F("UNK");
|
||||
}
|
||||
}
|
||||
#endif // IR_RX_BRIEF_LOG (rxBriefReasonTag)
|
||||
|
||||
// Безусловна: always-on счёт причин RX-событий (наблюдаемость по контракту
|
||||
// живучести — счётчики живут и в проде без печати); печать — только под флагом.
|
||||
void IR_DecoderRaw::rxBriefLog(RxBriefReason reason, uint16_t a, uint16_t b, uint32_t tUs)
|
||||
{
|
||||
const uint8_t ri = (uint8_t)reason;
|
||||
if (ri < 14U)
|
||||
rxReasonCnt[ri]++;
|
||||
#if !IR_RX_BRIEF_LOG
|
||||
(void)a; (void)b; (void)tUs;
|
||||
return;
|
||||
#else
|
||||
#if IR_RX_BRIEF_LOG_REJECT_ONLY
|
||||
if (reason == RxBriefReason::Ok || reason == RxBriefReason::Preamble)
|
||||
return;
|
||||
@ -220,8 +230,26 @@ void IR_DecoderRaw::rxBriefLog(RxBriefReason reason, uint16_t a, uint16_t b, uin
|
||||
break;
|
||||
}
|
||||
Serial.println();
|
||||
#endif // IR_RX_BRIEF_LOG (печать)
|
||||
}
|
||||
|
||||
void IR_DecoderRaw::printRxReasonStats(Print &out) const
|
||||
{
|
||||
static const char *const kTags[14] = {"?", "MUTEB", "MUTEE", "QRAW", "QFLT", "HOLD",
|
||||
"GLITCH", "TIME", "PREAMB", "SYNC", "BUF",
|
||||
"TIMEOUT", "CRC", "OK"};
|
||||
out.print(F("RXSTAT"));
|
||||
for (uint8_t i = 1; i < 14U; i++)
|
||||
{
|
||||
out.print(',');
|
||||
out.print(kTags[i]);
|
||||
out.print('=');
|
||||
out.print(rxReasonCnt[i]);
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
|
||||
#if IR_RX_BRIEF_LOG
|
||||
void IR_DecoderRaw::rxBriefNoteMuteBlockedIsr(uint32_t tUs)
|
||||
{
|
||||
(void)tUs;
|
||||
@ -373,10 +401,8 @@ inline void IR_DecoderRaw::checkTimeout()
|
||||
#if defined(IRDEBUG_SERIAL_PACK)
|
||||
packTraceOnTimeoutOrAbort(false);
|
||||
#endif
|
||||
#if IR_RX_BRIEF_LOG
|
||||
const uint16_t expected = (i_dataBuffer >= 8U) ? uint16_t(dataBuffer[0] & IR_MASK_MSG_INFO) : 0U;
|
||||
rxBriefLog(RxBriefReason::Timeout, i_dataBuffer, expected, micros());
|
||||
#endif
|
||||
isRecive = false; // приём завершён
|
||||
msgTypeReceive = 0;
|
||||
// Как после listenStart(): без сброса isReciveRaw + firstRX() декодер остаётся
|
||||
@ -487,9 +513,7 @@ void IR_DecoderRaw::processDecodedFront(const FrontStorage ¤tFront)
|
||||
if (short_low_glitch)
|
||||
{
|
||||
errors.other++;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Glitch, 1, 0, currentFront.time);
|
||||
#endif
|
||||
#if IR_GLITCH_REJECT_PHASE_NUDGE
|
||||
irGlitchPhaseNudge(currentFront.time, riseSyncTime, prevRise);
|
||||
#endif
|
||||
@ -504,9 +528,7 @@ void IR_DecoderRaw::processDecodedFront(const FrontStorage ¤tFront)
|
||||
if (micro_gap_rise)
|
||||
{
|
||||
errors.other++;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Glitch, 1, 0, currentFront.time);
|
||||
#endif
|
||||
#if IR_GLITCH_REJECT_PHASE_NUDGE
|
||||
irGlitchPhaseNudge(currentFront.time, riseSyncTime, prevRise);
|
||||
#endif
|
||||
@ -516,9 +538,7 @@ void IR_DecoderRaw::processDecodedFront(const FrontStorage ¤tFront)
|
||||
if (candRp <= riseTimeMax / 4U && !highCount && !lowCount)
|
||||
{
|
||||
errors.other++;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Timing, irClampU16(candRp), 0, currentFront.time);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -582,11 +602,9 @@ void IR_DecoderRaw::processDecodedFront(const FrontStorage ¤tFront)
|
||||
if (risePeriod > IR_timeout || isBufferOverflow || risePeriod < riseTimeMin || isWrongPack)
|
||||
// ~Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц
|
||||
{
|
||||
#if IR_RX_BRIEF_LOG
|
||||
if (!isBufferOverflow && !isWrongPack)
|
||||
rxBriefLog(RxBriefReason::Timing, irClampU16((uint32_t)risePeriod),
|
||||
irClampU16((uint32_t)highTime), currentFront.time);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -752,9 +770,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
if (i_dataBuffer >= dataByteSizeMax * 8)
|
||||
{ // проверка переполнения (>=: иначе при i_dataBuffer==dataByteSizeMax*8 запись dataBuffer[38] за границей массива — B3)
|
||||
isBufferOverflow = true;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::BufferOverflow, i_dataBuffer, 0, micros());
|
||||
#endif
|
||||
#if defined(IRDEBUG_SERIAL_PACK)
|
||||
if (packTraceOpen)
|
||||
packTraceEmitErrorFlash(F("ERROR: buffer overflow"));
|
||||
@ -831,9 +847,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
#endif
|
||||
{
|
||||
isWrongPack = true;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Sync, err_syncBit, 0, micros());
|
||||
#endif
|
||||
#if defined(IRDEBUG_SERIAL_PACK)
|
||||
packTraceEmitErrorFlash(F("ERROR: Wrong sync bit"));
|
||||
#endif
|
||||
@ -935,12 +949,10 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
#endif
|
||||
const uint16_t errSum =
|
||||
uint16_t(errors.lowSignal) + uint16_t(errors.highSignal) + uint16_t(errors.other);
|
||||
#if IR_RX_BRIEF_LOG
|
||||
if (isAvailable)
|
||||
rxBriefLog(RxBriefReason::Ok, packSize, errSum, micros());
|
||||
else
|
||||
rxBriefLog(RxBriefReason::Crc, packSize, errSum, micros());
|
||||
#endif
|
||||
if (!isAvailable && packSize > 0 && packSize <= dataByteSizeMax) {
|
||||
memcpy(rejectBuffer, dataBuffer, packSize);
|
||||
rejectPackSize = static_cast<uint8_t>(packSize);
|
||||
@ -1486,9 +1498,7 @@ void IR_DecoderRaw::pulseFilterPushRaw(const FrontStorage &e)
|
||||
if (pulseFilterHoldCount >= kPulseFilterHoldCap)
|
||||
{
|
||||
pulseFilterDropHoldOverflow++;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::HoldOverflow, irClampU16(pulseFilterDropHoldOverflow), 0, e.time);
|
||||
#endif
|
||||
pulseFilterShiftLeft(1);
|
||||
}
|
||||
|
||||
@ -1513,9 +1523,7 @@ bool IR_DecoderRaw::pulseFilterTryTakeConfirmed(FrontStorage &out, uint32_t logT
|
||||
if (dt < minUs)
|
||||
{
|
||||
pulseFilterDropGlitchPairs++;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Glitch, irClampU16(pulseFilterDropGlitchPairs), 0, logTime);
|
||||
#endif
|
||||
pulseFilterShiftLeft(2);
|
||||
continue;
|
||||
}
|
||||
@ -1545,9 +1553,7 @@ bool IR_DecoderRaw::pulseFilterTryFlushOne(uint32_t nowUs, FrontStorage &out)
|
||||
if (dt < IR_INPUT_MIN_PULSE_US)
|
||||
{
|
||||
pulseFilterDropGlitchPairs++;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Glitch, irClampU16(pulseFilterDropGlitchPairs), 0, nowUs);
|
||||
#endif
|
||||
pulseFilterShiftLeft(2);
|
||||
continue;
|
||||
}
|
||||
@ -1623,9 +1629,7 @@ bool IR_DecoderRaw::preambleProcessEdge(const FrontStorage &front)
|
||||
{
|
||||
if ((uint32_t)(front.time - preambleCandidateLastEdgeTime) > candTimeout)
|
||||
{
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Preamble, preambleGoodPeriods, 0, front.time);
|
||||
#endif
|
||||
preambleStartCandidate(front);
|
||||
}
|
||||
|
||||
@ -1646,9 +1650,7 @@ bool IR_DecoderRaw::preambleProcessEdge(const FrontStorage &front)
|
||||
{
|
||||
preambleGoodPeriods = 0;
|
||||
preambleMeanPeriod = 0;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Preamble, 0, irClampU16(period), front.time);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1669,9 +1671,7 @@ bool IR_DecoderRaw::preambleProcessEdge(const FrontStorage &front)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Preamble, preambleGoodPeriods, irClampU16(period), front.time);
|
||||
#endif
|
||||
preambleGoodPeriods = 1;
|
||||
preambleMeanPeriod = (uint16_t)period;
|
||||
}
|
||||
|
||||
@ -65,6 +65,14 @@ public:
|
||||
uint16_t edgeTraceFlushChunk(Print &out, uint16_t maxRec = 48);
|
||||
#endif
|
||||
|
||||
/// Always-on счётчики RX-событий по причинам (см. RxBriefReason: 6=Glitch,
|
||||
/// 7=Timing, 8=Preamble, 9=Sync, 10=BufOverflow, 11=Timeout, 12=Crc, 13=Ok).
|
||||
/// MuteBegin/End и RawOverflow(1..3) тикают только при IR_RX_BRIEF_LOG (ISR-агрегат).
|
||||
const uint16_t *rxReasonCounters() const { return rxReasonCnt; }
|
||||
void rxReasonCountersClear() { for (uint8_t i = 0; i < 14; i++) rxReasonCnt[i] = 0; }
|
||||
/// Однострочная сводка: "RXSTAT,GLITCH=..,TIME=..,PREAMB=..,SYNC=..,BUF=..,TIMEOUT=..,CRC=..,OK=.."
|
||||
void printRxReasonStats(Print &out) const;
|
||||
|
||||
/// Кадр собран по длине из заголовка, но CRC не сошёлся — один раз можно прочитать копию сырых байтов.
|
||||
bool availableReject();
|
||||
uint8_t getRejectSize() const { return rejectPackSize; }
|
||||
@ -235,9 +243,13 @@ bool isReciveRaw = false;
|
||||
/// @return Результат
|
||||
uint16_t ceil_div(uint16_t val, uint16_t divider);
|
||||
|
||||
// rxBriefLog безусловен: ВСЕГДА инкрементирует rxReasonCnt[reason]
|
||||
// (always-on наблюдаемость по контракту живучести), печать события —
|
||||
// только при IR_RX_BRIEF_LOG. Вызовы в местах отказов тоже безусловны.
|
||||
void rxBriefLog(RxBriefReason reason, uint16_t a = 0, uint16_t b = 0, uint32_t tUs = 0);
|
||||
uint16_t rxReasonCnt[14] = {}; // индекс = (uint8_t)RxBriefReason, 1..13
|
||||
#if IR_RX_BRIEF_LOG
|
||||
static const __FlashStringHelper *rxBriefReasonTag(RxBriefReason reason);
|
||||
void rxBriefLog(RxBriefReason reason, uint16_t a = 0, uint16_t b = 0, uint32_t tUs = 0);
|
||||
void rxBriefNoteMuteBlockedIsr(uint32_t tUs);
|
||||
void rxBriefNoteRawOverflowIsr(uint32_t tUs);
|
||||
void rxBriefFlushDeferredIsrLogs();
|
||||
|
||||
Reference in New Issue
Block a user