mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-04-28 03:08:08 +00:00
Refactor IR decoder and encoder for improved pulse filtering and ISR handling. Removed unused filtered sub-buffer, updated pulse filter methods, and added support for buffered ISR storage in the encoder. Enhanced documentation for clarity on DMA TX backend and ISR modes.
This commit is contained in:
@ -74,7 +74,6 @@ bool IR_DecoderRaw::availableRaw()
|
||||
|
||||
void IR_DecoderRaw::pulseFilterResetStats()
|
||||
{
|
||||
pulseFilterDropFilteredOverflow = 0;
|
||||
pulseFilterDropHoldOverflow = 0;
|
||||
pulseFilterDropGlitchPairs = 0;
|
||||
}
|
||||
@ -344,7 +343,7 @@ bool IR_DecoderRaw::rxTimeoutPipelineBusy() const
|
||||
if (pulseFilterHoldCount != 0U)
|
||||
return true;
|
||||
noInterrupts();
|
||||
const bool busy = !subBuffer.isEmpty() || !filteredSubBuffer.isEmpty();
|
||||
const bool busy = !subBuffer.isEmpty();
|
||||
interrupts();
|
||||
return busy;
|
||||
}
|
||||
@ -403,10 +402,9 @@ void IR_DecoderRaw::tick()
|
||||
// Не в начале до pop: иначе после checkTimeout lastEdgeTime vs micros() расходятся
|
||||
// с метками ISR из очереди → ложные TIMEOUT (bits=0) каждый пакет.
|
||||
|
||||
FrontStorage currentFront;
|
||||
bool hasCurrentFront = false;
|
||||
FrontStorage rawFront;
|
||||
bool hasRawFront = false;
|
||||
bool processedFront = false;
|
||||
noInterrupts();
|
||||
FrontStorage *rawPtr = subBuffer.pop();
|
||||
if (rawPtr != nullptr)
|
||||
@ -419,26 +417,33 @@ void IR_DecoderRaw::tick()
|
||||
if (IR_INPUT_MIN_PULSE_US > 0U)
|
||||
{
|
||||
if (hasRawFront)
|
||||
pulseFilterFeedOneRaw(rawFront);
|
||||
else
|
||||
pulseFilterFlushTimeout(micros());
|
||||
|
||||
noInterrupts();
|
||||
FrontStorage *flt = filteredSubBuffer.pop();
|
||||
if (flt != nullptr)
|
||||
{
|
||||
currentFront = *flt;
|
||||
hasCurrentFront = true;
|
||||
pulseFilterPushRaw(rawFront);
|
||||
FrontStorage confirmedFront;
|
||||
while (pulseFilterTryTakeConfirmed(confirmedFront))
|
||||
{
|
||||
processDecodedFront(confirmedFront);
|
||||
processedFront = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t nowUs = micros();
|
||||
FrontStorage confirmedFront;
|
||||
while (pulseFilterTryFlushOne(nowUs, confirmedFront))
|
||||
{
|
||||
processDecodedFront(confirmedFront);
|
||||
processedFront = true;
|
||||
}
|
||||
}
|
||||
interrupts();
|
||||
}
|
||||
else if (hasRawFront)
|
||||
{
|
||||
currentFront = rawFront;
|
||||
hasCurrentFront = true;
|
||||
processDecodedFront(rawFront);
|
||||
processedFront = true;
|
||||
}
|
||||
|
||||
if (!hasCurrentFront)
|
||||
if (!processedFront)
|
||||
{
|
||||
isSubBufferOverflow = false;
|
||||
listenStart();
|
||||
@ -448,11 +453,22 @@ void IR_DecoderRaw::tick()
|
||||
#endif
|
||||
return;
|
||||
} // Если данных нет - ничего не делаем
|
||||
listenStart();
|
||||
checkTimeout();
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefFlushDeferredIsrLogs();
|
||||
#endif
|
||||
#if defined(IR_EDGE_TRACE)
|
||||
while (edgeTraceFlushChunk(Serial, 48) > 0) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IR_DecoderRaw::processDecodedFront(const FrontStorage ¤tFront)
|
||||
{
|
||||
if (preambleProcessEdge(currentFront))
|
||||
{
|
||||
lastEdgeTime = currentFront.time;
|
||||
goto END;
|
||||
return;
|
||||
}
|
||||
|
||||
lastEdgeTime = currentFront.time; // запоминаем любой фронт
|
||||
@ -478,7 +494,7 @@ void IR_DecoderRaw::tick()
|
||||
#if IR_GLITCH_REJECT_PHASE_NUDGE
|
||||
irGlitchPhaseNudge(currentFront.time, riseSyncTime, prevRise);
|
||||
#endif
|
||||
goto END;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if IR_MICRO_GAP_RISE_REJECT
|
||||
@ -495,7 +511,7 @@ void IR_DecoderRaw::tick()
|
||||
#if IR_GLITCH_REJECT_PHASE_NUDGE
|
||||
irGlitchPhaseNudge(currentFront.time, riseSyncTime, prevRise);
|
||||
#endif
|
||||
goto END;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (candRp <= riseTimeMax / 4U && !highCount && !lowCount)
|
||||
@ -504,7 +520,7 @@ void IR_DecoderRaw::tick()
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Timing, irClampU16(candRp), 0, currentFront.time);
|
||||
#endif
|
||||
goto END;
|
||||
return;
|
||||
}
|
||||
|
||||
if (candRp > riseTimeMax / 4 || highCount || lowCount)
|
||||
@ -557,7 +573,7 @@ void IR_DecoderRaw::tick()
|
||||
}
|
||||
}
|
||||
#ifdef IRDEBUG
|
||||
// goto END; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// return; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#endif
|
||||
//----------------------------------------------------------------------------------
|
||||
#ifdef IRDEBUG
|
||||
@ -572,7 +588,7 @@ void IR_DecoderRaw::tick()
|
||||
rxBriefLog(RxBriefReason::Timing, irClampU16((uint32_t)risePeriod),
|
||||
irClampU16((uint32_t)highTime), currentFront.time);
|
||||
#endif
|
||||
goto END;
|
||||
return;
|
||||
}
|
||||
|
||||
// определить направление фронта
|
||||
@ -727,17 +743,6 @@ void IR_DecoderRaw::tick()
|
||||
else
|
||||
{ // Если ```\__ ↓
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
END:;
|
||||
listenStart();
|
||||
checkTimeout();
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefFlushDeferredIsrLogs();
|
||||
#endif
|
||||
#if defined(IR_EDGE_TRACE)
|
||||
while (edgeTraceFlushChunk(Serial, 48) > 0) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
@ -1455,34 +1460,18 @@ void IR_DecoderRaw::pulseFilterShiftLeft(uint8_t n)
|
||||
pulseFilterHoldCount = newCount;
|
||||
}
|
||||
|
||||
bool IR_DecoderRaw::pulseFilterEmit(const FrontStorage &e)
|
||||
{
|
||||
if (filteredSubBuffer.isFull())
|
||||
{
|
||||
pulseFilterDropFilteredOverflow++;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::FilterOverflow, irClampU16(pulseFilterDropFilteredOverflow), 0, e.time);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
filteredSubBuffer.push(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
void IR_DecoderRaw::pulseFilterReset()
|
||||
{
|
||||
pulseFilterHoldCount = 0;
|
||||
pulseFilterLastRawValid = false;
|
||||
pulseFilterLastRawTime = 0;
|
||||
while (filteredSubBuffer.pop() != nullptr) {}
|
||||
}
|
||||
|
||||
void IR_DecoderRaw::pulseFilterFeedOneRaw(const FrontStorage &e)
|
||||
void IR_DecoderRaw::pulseFilterPushRaw(const FrontStorage &e)
|
||||
{
|
||||
const uint32_t minUs = IR_INPUT_MIN_PULSE_US;
|
||||
if (minUs == 0U)
|
||||
{
|
||||
pulseFilterEmit(e);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1495,44 +1484,53 @@ void IR_DecoderRaw::pulseFilterFeedOneRaw(const FrontStorage &e)
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::HoldOverflow, irClampU16(pulseFilterDropHoldOverflow), 0, e.time);
|
||||
#endif
|
||||
pulseFilterEmit(pulseFilterHoldEdges[0]);
|
||||
pulseFilterShiftLeft(1);
|
||||
}
|
||||
|
||||
pulseFilterHoldEdges[pulseFilterHoldCount++] = e;
|
||||
const uint8_t holdback = irPulseFilterHoldbackEdges();
|
||||
}
|
||||
|
||||
bool IR_DecoderRaw::pulseFilterTryTakeConfirmed(FrontStorage &out, uint32_t logTime)
|
||||
{
|
||||
const uint32_t minUs = IR_INPUT_MIN_PULSE_US;
|
||||
if (minUs == 0U)
|
||||
return false;
|
||||
|
||||
const uint8_t holdback = irPulseFilterHoldbackEdges();
|
||||
if (logTime == 0U)
|
||||
logTime = pulseFilterLastRawTime;
|
||||
for (;;)
|
||||
{
|
||||
if (pulseFilterHoldCount < 2)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const uint32_t dt = pulseFilterHoldEdges[1].time - pulseFilterHoldEdges[0].time;
|
||||
if (dt < minUs)
|
||||
{
|
||||
pulseFilterDropGlitchPairs++;
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefLog(RxBriefReason::Glitch, irClampU16(pulseFilterDropGlitchPairs), 0, e.time);
|
||||
rxBriefLog(RxBriefReason::Glitch, irClampU16(pulseFilterDropGlitchPairs), 0, logTime);
|
||||
#endif
|
||||
pulseFilterShiftLeft(2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pulseFilterHoldCount <= holdback)
|
||||
return;
|
||||
return false;
|
||||
|
||||
pulseFilterEmit(pulseFilterHoldEdges[0]);
|
||||
out = pulseFilterHoldEdges[0];
|
||||
pulseFilterShiftLeft(1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void IR_DecoderRaw::pulseFilterFlushTimeout(uint32_t nowUs)
|
||||
bool IR_DecoderRaw::pulseFilterTryFlushOne(uint32_t nowUs, FrontStorage &out)
|
||||
{
|
||||
if (IR_INPUT_MIN_PULSE_US == 0U || !pulseFilterLastRawValid || pulseFilterHoldCount == 0)
|
||||
return;
|
||||
return false;
|
||||
const uint32_t waitUs = IR_INPUT_MIN_PULSE_US * (uint32_t)IR_INPUT_FILTER_TIMEOUT_MULT;
|
||||
if ((uint32_t)(nowUs - pulseFilterLastRawTime) < waitUs)
|
||||
return;
|
||||
return false;
|
||||
|
||||
while (pulseFilterHoldCount > 0)
|
||||
{
|
||||
@ -1549,9 +1547,11 @@ void IR_DecoderRaw::pulseFilterFlushTimeout(uint32_t nowUs)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pulseFilterEmit(pulseFilterHoldEdges[0]);
|
||||
out = pulseFilterHoldEdges[0];
|
||||
pulseFilterShiftLeft(1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t IR_DecoderRaw::preambleJitterTolUs(uint32_t baselineUs) const
|
||||
|
||||
Reference in New Issue
Block a user