mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-18 19:13:58 +00:00
feat(rx): наблюдаемость приёма по состоянию + airtime кадра формулами
- 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
This commit is contained in:
@ -67,7 +67,25 @@ public:
|
||||
return (isRecive && packSize && !isWrongPack) ? packSize : 0;
|
||||
}
|
||||
// Протокольный МАКСИМУМ длины кадра (байт) — верхняя граница бюджета удержания заднего.
|
||||
static constexpr uint16_t rxMaxPackSize() { return (uint16_t)dataByteSizeMax; }
|
||||
static constexpr uint16_t rxMaxPackSize() { return (uint16_t)irMaxPackSize; }
|
||||
|
||||
// ---- Наблюдаемость приёма по СОСТОЯНИЮ: лок / ожидаемый конец / факт завершения с причиной ----
|
||||
enum class RxEndReason : uint8_t { None = 0, Ok, Crc, Timeout, Abort };
|
||||
struct RxEndInfo {
|
||||
uint16_t seq = 0; // номер завершения (растёт на каждом терминале)
|
||||
RxEndReason reason = RxEndReason::None;
|
||||
uint8_t msgType = 0xFF; // 0xFF = первый байт не был принят
|
||||
uint8_t packSize = 0; // объявленная длина (0 = неизвестна)
|
||||
uint32_t tUs = 0; // micros() терминала
|
||||
uint32_t expectedEndUs = 0; // расчётный конец кадра в эфире (0 = неизвестен)
|
||||
};
|
||||
uint16_t rxLockSeq() const { return rxLockSeqCnt; } // ++ в момент лока преамбулы
|
||||
uint32_t rxLockTimeUs() const { return rxLockTimeUsVal; } // метка фронта лока (ISR-время)
|
||||
/// Тип принимаемого кадра (3 бита) после первого байта; 0xFF пока неизвестен / приём не идёт.
|
||||
uint8_t rxMsgType() const { return (isRecive && packSize) ? (uint8_t)((dataBuffer[0] >> 5) & IR_MASK_MSG_TYPE) : 0xFF; }
|
||||
const RxEndInfo &rxLastEnd() const { return rxEnd; }
|
||||
/// Расчётный момент последнего бита данных текущего кадра (по объявленной длине); 0 = не Locked / длина неизвестна.
|
||||
uint32_t rxExpectedEndUs() const;
|
||||
uint32_t pulseFilterDroppedByFilteredOverflow() const { return 0; }
|
||||
uint32_t pulseFilterDroppedByHoldOverflow() const { return pulseFilterDropHoldOverflow; }
|
||||
uint32_t pulseFilterDroppedGlitchPairs() const { return pulseFilterDropGlitchPairs; }
|
||||
@ -163,6 +181,12 @@ private:
|
||||
Locked = 2
|
||||
};
|
||||
PreambleState preambleState = PreambleState::Idle;
|
||||
uint16_t rxLockSeqCnt = 0;
|
||||
uint32_t rxLockTimeUsVal = 0;
|
||||
RxEndInfo rxEnd;
|
||||
void noteRxEnd(RxEndReason reason, uint32_t tUs); // терминал: фиксирует тип/длину/расчётный конец
|
||||
void abortFrame(uint32_t tUs); // немедленный сброс битого кадра (sync/длина/overflow)
|
||||
void expirePreambleCandidate(); // кандидат без фронтов дольше таймаута → Idle
|
||||
uint8_t preambleGoodPeriods = 0;
|
||||
uint16_t preambleMeanPeriod = 0;
|
||||
uint32_t preambleCandidateLastEdgeTime = 0;
|
||||
|
||||
Reference in New Issue
Block a user