mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-21 20:39:35 +00:00
archive: freeze IR-protocol WIP before stepwise integration
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
#include "IR_DecoderRaw.h"
|
||||
#include "IR_Encoder.h"
|
||||
#include "IrInterruptGuard.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
@ -53,9 +54,8 @@ IR_DecoderRaw::IR_DecoderRaw(const uint8_t pin, uint16_t addr, IR_Encoder *encPa
|
||||
|
||||
bool IR_DecoderRaw::isSubOverflow()
|
||||
{
|
||||
noInterrupts();
|
||||
volatile bool ret = isSubBufferOverflow;
|
||||
interrupts();
|
||||
IrInterruptGuard guard;
|
||||
const bool ret = isSubBufferOverflow;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ void IR_DecoderRaw::refreshPairMuteState()
|
||||
++active;
|
||||
}
|
||||
const uint32_t nowUs = micros();
|
||||
noInterrupts();
|
||||
IrInterruptGuard guard;
|
||||
const bool wasActive = (isPairSending != 0);
|
||||
isPairSending = active;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
@ -121,7 +121,6 @@ void IR_DecoderRaw::refreshPairMuteState()
|
||||
rxBriefMuteBlockedEdges = 0;
|
||||
}
|
||||
#endif
|
||||
interrupts();
|
||||
}
|
||||
|
||||
#if IR_RX_BRIEF_LOG
|
||||
@ -142,6 +141,7 @@ const __FlashStringHelper *IR_DecoderRaw::rxBriefReasonTag(RxBriefReason reason)
|
||||
case RxBriefReason::Timeout: return F("TIMEOUT");
|
||||
case RxBriefReason::Crc: return F("CRC");
|
||||
case RxBriefReason::Ok: return F("OK");
|
||||
case RxBriefReason::Count: return F("UNK");
|
||||
default: return F("UNK");
|
||||
}
|
||||
}
|
||||
@ -152,7 +152,7 @@ const __FlashStringHelper *IR_DecoderRaw::rxBriefReasonTag(RxBriefReason reason)
|
||||
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)
|
||||
if (ri < kRxBriefReasonCount)
|
||||
rxReasonCnt[ri]++;
|
||||
#if !IR_RX_BRIEF_LOG
|
||||
(void)a; (void)b; (void)tUs;
|
||||
@ -228,6 +228,8 @@ void IR_DecoderRaw::rxBriefLog(RxBriefReason reason, uint16_t a, uint16_t b, uin
|
||||
Serial.print(b);
|
||||
}
|
||||
break;
|
||||
case RxBriefReason::Count:
|
||||
break;
|
||||
}
|
||||
Serial.println();
|
||||
#endif // IR_RX_BRIEF_LOG (печать)
|
||||
@ -235,11 +237,14 @@ void IR_DecoderRaw::rxBriefLog(RxBriefReason reason, uint16_t a, uint16_t b, uin
|
||||
|
||||
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"};
|
||||
static const char *const kTags[] = {"?", "MUTEB", "MUTEE", "QRAW", "QFLT", "HOLD",
|
||||
"GLITCH", "TIME", "PREAMB", "SYNC", "BUF",
|
||||
"TIMEOUT", "CRC", "OK"};
|
||||
static_assert(sizeof(kTags) / sizeof(kTags[0]) == kRxBriefReasonCount,
|
||||
"RX reason tag table must match RxBriefReason::Count");
|
||||
out.print(F("RXSTAT"));
|
||||
for (uint8_t i = 1; i < 14U; i++)
|
||||
for (uint8_t i = static_cast<uint8_t>(RxBriefReason::MuteBegin);
|
||||
i < kRxBriefReasonCount; ++i)
|
||||
{
|
||||
out.print(',');
|
||||
out.print(kTags[i]);
|
||||
@ -273,22 +278,23 @@ void IR_DecoderRaw::rxBriefFlushDeferredIsrLogs()
|
||||
uint16_t muteEndCnt = 0;
|
||||
uint16_t rawCnt = 0;
|
||||
uint32_t rawLastUs = 0;
|
||||
noInterrupts();
|
||||
muteBeginPending = rxBriefMuteBeginPending;
|
||||
muteBeginUs = rxBriefMuteBeginUs;
|
||||
rxBriefMuteBeginPending = false;
|
||||
rxBriefMuteBeginUs = 0;
|
||||
muteEndPending = rxBriefMuteEndPending;
|
||||
muteEndUs = rxBriefMuteEndUs;
|
||||
muteEndCnt = rxBriefMuteEndCount;
|
||||
rxBriefMuteEndPending = false;
|
||||
rxBriefMuteEndUs = 0;
|
||||
rxBriefMuteEndCount = 0;
|
||||
rawCnt = rxBriefRawOverflowDrops;
|
||||
rawLastUs = rxBriefRawOverflowLastUs;
|
||||
rxBriefRawOverflowDrops = 0;
|
||||
rxBriefRawOverflowLastUs = 0;
|
||||
interrupts();
|
||||
{
|
||||
IrInterruptGuard guard;
|
||||
muteBeginPending = rxBriefMuteBeginPending;
|
||||
muteBeginUs = rxBriefMuteBeginUs;
|
||||
rxBriefMuteBeginPending = false;
|
||||
rxBriefMuteBeginUs = 0;
|
||||
muteEndPending = rxBriefMuteEndPending;
|
||||
muteEndUs = rxBriefMuteEndUs;
|
||||
muteEndCnt = rxBriefMuteEndCount;
|
||||
rxBriefMuteEndPending = false;
|
||||
rxBriefMuteEndUs = 0;
|
||||
rxBriefMuteEndCount = 0;
|
||||
rawCnt = rxBriefRawOverflowDrops;
|
||||
rawLastUs = rxBriefRawOverflowLastUs;
|
||||
rxBriefRawOverflowDrops = 0;
|
||||
rxBriefRawOverflowLastUs = 0;
|
||||
}
|
||||
if (muteBeginPending)
|
||||
rxBriefLog(RxBriefReason::MuteBegin, 0, 0, muteBeginUs);
|
||||
if (muteEndPending)
|
||||
@ -359,7 +365,7 @@ void IR_DecoderRaw::firstRX()
|
||||
#ifdef IRDEBUG
|
||||
wrCounter = 0;
|
||||
#endif
|
||||
memset(dataBuffer, 0x00, dataByteSizeMax);
|
||||
memset(dataBuffer, 0x00, irproto::kMaxWireFrameBytes);
|
||||
pulseFilterReset();
|
||||
preambleResetToIdle();
|
||||
}
|
||||
@ -368,9 +374,8 @@ bool IR_DecoderRaw::rxTimeoutPipelineBusy() const
|
||||
{
|
||||
if (pulseFilterHoldCount != 0U)
|
||||
return true;
|
||||
noInterrupts();
|
||||
IrInterruptGuard guard;
|
||||
const bool busy = !subBuffer.isEmpty();
|
||||
interrupts();
|
||||
return busy;
|
||||
}
|
||||
|
||||
@ -378,7 +383,7 @@ void IR_DecoderRaw::listenStart()
|
||||
{
|
||||
if (rxTimeoutPipelineBusy())
|
||||
return;
|
||||
if (isReciveRaw && ((micros() - lastEdgeTime) > IR_timeout * 2U))
|
||||
if (isReciveRaw && ((micros() - lastEdgeTime) > receiveSilenceTimeoutUs()))
|
||||
{
|
||||
#if defined(IRDEBUG_SERIAL_PACK)
|
||||
packTraceOnTimeoutOrAbort(true);
|
||||
@ -396,7 +401,7 @@ inline void IR_DecoderRaw::checkTimeout()
|
||||
if (rxTimeoutPipelineBusy())
|
||||
return;
|
||||
|
||||
if (micros() - lastEdgeTime > IR_timeout * 2U)
|
||||
if (micros() - lastEdgeTime > receiveSilenceTimeoutUs())
|
||||
{
|
||||
#if defined(IRDEBUG_SERIAL_PACK)
|
||||
packTraceOnTimeoutOrAbort(false);
|
||||
@ -767,8 +772,8 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
#if !defined(IRDEBUG_SERIAL_PACK)
|
||||
(void)packTraceInvertFix;
|
||||
#endif
|
||||
if (i_dataBuffer >= dataByteSizeMax * 8)
|
||||
{ // проверка переполнения (>=: иначе при i_dataBuffer==dataByteSizeMax*8 запись dataBuffer[38] за границей массива — B3)
|
||||
if (i_dataBuffer >= irproto::kMaxWireFrameBytes * 8U)
|
||||
{ // >=: не даёт записать бит за пределом 5-битной wire-длины.
|
||||
isBufferOverflow = true;
|
||||
rxBriefLog(RxBriefReason::BufferOverflow, i_dataBuffer, 0, micros());
|
||||
#if defined(IRDEBUG_SERIAL_PACK)
|
||||
@ -876,7 +881,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
{ // Ппервый байт
|
||||
packSize = dataBuffer[0] & IR_MASK_MSG_INFO;
|
||||
// B1: под-минимальная длина (1..2) физически не несёт CRC (min кадр = msg+crc = 3 байта) → шум/битьё.
|
||||
// Без отсева packSize==1 даёт crcCheck(1-2) → len=255 → OOB-чтение dataBuffer[0..256] (массив 38).
|
||||
// Без отсева packSize==1 даёт crcCheck(1-2) → len=255 → OOB-чтение wire-буфера.
|
||||
// packSize>=3 (в т.ч. будущие компактные кадры) обрабатываются как обычно.
|
||||
if (packSize != 0 && packSize < msgBytes + crcBytes)
|
||||
isWrongPack = true;
|
||||
@ -910,7 +915,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
uint8_t packTraceBfBit = 0;
|
||||
bool packTraceBfMark = false;
|
||||
if (!isAvailable) // Исправление первого бита // Очень большая затычка...
|
||||
for (size_t i = 0; i < min(uint16_t(packSize - crcBytes * 2U), uint16_t(dataByteSizeMax)); ++i)
|
||||
for (size_t i = 0; i < min(uint16_t(packSize - crcBytes * 2U), uint16_t(irproto::kMaxWireFrameBytes)); ++i)
|
||||
{
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
@ -918,7 +923,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
dataBuffer[i] ^= 1 << j;
|
||||
|
||||
isAvailable =
|
||||
crcCheck(min(uint16_t(packSize - crcBytes), uint16_t(dataByteSizeMax - 1U)), crcValue);
|
||||
crcCheck(min(uint16_t(packSize - crcBytes), uint16_t(irproto::kMaxWireFrameBytes - 1U)), crcValue);
|
||||
// обратно инвертируем бит в исходное состояние
|
||||
|
||||
if (isAvailable)
|
||||
@ -953,7 +958,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
rxBriefLog(RxBriefReason::Ok, packSize, errSum, micros());
|
||||
else
|
||||
rxBriefLog(RxBriefReason::Crc, packSize, errSum, micros());
|
||||
if (!isAvailable && packSize > 0 && packSize <= dataByteSizeMax) {
|
||||
if (!isAvailable && packSize > 0 && packSize <= irproto::kMaxWireFrameBytes) {
|
||||
memcpy(rejectBuffer, dataBuffer, packSize);
|
||||
rejectPackSize = static_cast<uint8_t>(packSize);
|
||||
isRejectAvailable = true;
|
||||
@ -1007,38 +1012,34 @@ uint16_t IR_DecoderRaw::ceil_div(uint16_t val, uint16_t divider)
|
||||
void IR_DecoderRaw::edgeTracePush(uint32_t t_us, uint8_t level, uint8_t flags)
|
||||
{
|
||||
const uint16_t cap = static_cast<uint16_t>(IR_EDGE_TRACE_CAPACITY);
|
||||
noInterrupts();
|
||||
IrInterruptGuard guard;
|
||||
const uint16_t w = edgeTrace_w;
|
||||
const uint16_t r = edgeTrace_r;
|
||||
const uint16_t next = static_cast<uint16_t>((w + 1u) % cap);
|
||||
if (next == r)
|
||||
{
|
||||
edgeTrace_overflow = true;
|
||||
interrupts();
|
||||
return;
|
||||
}
|
||||
edgeTrace_buf[w].t_us = t_us;
|
||||
edgeTrace_buf[w].level = level ? 1u : 0u;
|
||||
edgeTrace_buf[w].flags = flags;
|
||||
edgeTrace_w = next;
|
||||
interrupts();
|
||||
}
|
||||
|
||||
void IR_DecoderRaw::edgeTraceClear()
|
||||
{
|
||||
noInterrupts();
|
||||
IrInterruptGuard guard;
|
||||
edgeTrace_w = 0;
|
||||
edgeTrace_r = 0;
|
||||
edgeTrace_overflow = false;
|
||||
interrupts();
|
||||
}
|
||||
|
||||
uint16_t IR_DecoderRaw::edgeTracePendingCount() const
|
||||
{
|
||||
noInterrupts();
|
||||
IrInterruptGuard guard;
|
||||
const uint16_t w = edgeTrace_w;
|
||||
const uint16_t r = edgeTrace_r;
|
||||
interrupts();
|
||||
const uint16_t cap = static_cast<uint16_t>(IR_EDGE_TRACE_CAPACITY);
|
||||
if (w >= r)
|
||||
return static_cast<uint16_t>(w - r);
|
||||
@ -1054,27 +1055,28 @@ uint16_t IR_DecoderRaw::edgeTraceFlushChunk(Print &out, uint16_t maxRec)
|
||||
maxRec = kStackCap;
|
||||
|
||||
const uint16_t cap = static_cast<uint16_t>(IR_EDGE_TRACE_CAPACITY);
|
||||
noInterrupts();
|
||||
const uint16_t w = edgeTrace_w;
|
||||
const uint16_t r = edgeTrace_r;
|
||||
uint16_t avail = (w >= r) ? static_cast<uint16_t>(w - r) : static_cast<uint16_t>(cap - r + w);
|
||||
uint16_t toCopy = (avail > maxRec) ? maxRec : avail;
|
||||
const bool truncated = (avail > toCopy);
|
||||
if (toCopy == 0)
|
||||
{
|
||||
interrupts();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t tmp[kStackCap * 6];
|
||||
for (uint16_t i = 0; i < toCopy; ++i)
|
||||
uint16_t toCopy = 0U;
|
||||
bool truncated = false;
|
||||
bool ovf = false;
|
||||
{
|
||||
const uint16_t idx = static_cast<uint16_t>((r + i) % cap);
|
||||
memcpy(tmp + i * 6u, &edgeTrace_buf[idx], 6u);
|
||||
IrInterruptGuard guard;
|
||||
const uint16_t w = edgeTrace_w;
|
||||
const uint16_t r = edgeTrace_r;
|
||||
const uint16_t avail = (w >= r) ? static_cast<uint16_t>(w - r)
|
||||
: static_cast<uint16_t>(cap - r + w);
|
||||
toCopy = (avail > maxRec) ? maxRec : avail;
|
||||
truncated = (avail > toCopy);
|
||||
if (toCopy == 0U)
|
||||
return 0U;
|
||||
for (uint16_t i = 0; i < toCopy; ++i)
|
||||
{
|
||||
const uint16_t idx = static_cast<uint16_t>((r + i) % cap);
|
||||
memcpy(tmp + i * 6u, &edgeTrace_buf[idx], 6u);
|
||||
}
|
||||
edgeTrace_r = static_cast<uint16_t>((r + toCopy) % cap);
|
||||
ovf = edgeTrace_overflow;
|
||||
}
|
||||
edgeTrace_r = static_cast<uint16_t>((r + toCopy) % cap);
|
||||
const bool ovf = edgeTrace_overflow;
|
||||
interrupts();
|
||||
|
||||
uint8_t meta = 0;
|
||||
if (ovf)
|
||||
@ -1304,7 +1306,7 @@ void IR_DecoderRaw::packTraceForceEndSyncPhase()
|
||||
void IR_DecoderRaw::packTraceEmitHex(uint8_t byteCount) const
|
||||
{
|
||||
Serial.print(F("IR hex:"));
|
||||
for (uint8_t i = 0; i < byteCount && i < dataByteSizeMax; i++)
|
||||
for (uint8_t i = 0; i < byteCount && i < irproto::kMaxWireFrameBytes; i++)
|
||||
{
|
||||
Serial.print(' ');
|
||||
ptPrintHexU8(dataBuffer[i]);
|
||||
@ -1402,8 +1404,8 @@ void IR_DecoderRaw::packTraceEmitErrorFlash(const __FlashStringHelper *msg)
|
||||
Serial.println(msg);
|
||||
{
|
||||
uint16_t nb = i_dataBuffer / 8u;
|
||||
if (nb > dataByteSizeMax)
|
||||
nb = dataByteSizeMax;
|
||||
if (nb > irproto::kMaxWireFrameBytes)
|
||||
nb = irproto::kMaxWireFrameBytes;
|
||||
packTraceEmitHex(static_cast<uint8_t>(nb));
|
||||
}
|
||||
packTraceResetFrame();
|
||||
@ -1436,8 +1438,8 @@ void IR_DecoderRaw::packTraceOnTimeoutOrAbort(bool fromListenStart)
|
||||
return;
|
||||
const uint16_t expected = (i_dataBuffer >= 8) ? uint16_t(dataBuffer[0] & IR_MASK_MSG_INFO) : 0;
|
||||
uint16_t gotBytes = i_dataBuffer / 8;
|
||||
if (gotBytes > dataByteSizeMax)
|
||||
gotBytes = dataByteSizeMax;
|
||||
if (gotBytes > irproto::kMaxWireFrameBytes)
|
||||
gotBytes = irproto::kMaxWireFrameBytes;
|
||||
Serial.println();
|
||||
packTraceEmitRawBitsLine(false);
|
||||
Serial.print(F(" => ERROR: TIMEOUT, rx_data_size = "));
|
||||
@ -1609,7 +1611,7 @@ void IR_DecoderRaw::preambleStartCandidate(const FrontStorage &front)
|
||||
|
||||
bool IR_DecoderRaw::preambleProcessEdge(const FrontStorage &front)
|
||||
{
|
||||
const uint32_t longSilence = IR_timeout * 2U;
|
||||
const uint32_t longSilence = receiveSilenceTimeoutUs();
|
||||
const uint32_t candTimeout = IR_timeout * (uint32_t)IR_PREAMBLE_CANDIDATE_TIMEOUT_MULT;
|
||||
|
||||
if (preambleState == PreambleState::Idle)
|
||||
@ -1696,7 +1698,7 @@ bool IR_DecoderRaw::preambleProcessEdge(const FrontStorage &front)
|
||||
err_syncBit = 0;
|
||||
isWrongPack = false;
|
||||
msgTypeReceive = 0;
|
||||
memset(dataBuffer, 0x00, dataByteSizeMax);
|
||||
memset(dataBuffer, 0x00, irproto::kMaxWireFrameBytes);
|
||||
|
||||
preambleState = PreambleState::Locked;
|
||||
isPreamb = false;
|
||||
|
||||
Reference in New Issue
Block a user