mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-04-28 03:08:08 +00:00
fix timer overflow?
This commit is contained in:
@ -272,22 +272,19 @@ void IR_DecoderRaw::rxBriefFlushDeferredIsrLogs()
|
||||
#endif
|
||||
|
||||
//////////////////////////////////// isr ///////////////////////////////////////////
|
||||
volatile uint32_t time_;
|
||||
|
||||
void IR_DecoderRaw::isr()
|
||||
{
|
||||
// Интервалы между соседними фронтами считаются как (uint32_t)(t1 - t0) — корректно при
|
||||
// паузе < ~35 мин между фронтами; условие «тишина > longSilence» в preambleProcessEdge
|
||||
// переписано без front.time > prevRise (оно ломается при wrap).
|
||||
uint32_t t;
|
||||
noInterrupts();
|
||||
time_ = micros();
|
||||
t = micros();
|
||||
interrupts();
|
||||
if (time_ < oldTime)
|
||||
{
|
||||
time_ += 1000;
|
||||
}
|
||||
oldTime = time_;
|
||||
|
||||
FrontStorage edge;
|
||||
edge.dir = port->IDR & mask;
|
||||
edge.time = time_;
|
||||
edge.time = t;
|
||||
|
||||
#if defined(IR_EDGE_TRACE)
|
||||
edgeTracePush(edge.time, edge.dir ? 1u : 0u,
|
||||
@ -342,8 +339,20 @@ void IR_DecoderRaw::firstRX()
|
||||
preambleResetToIdle();
|
||||
}
|
||||
|
||||
bool IR_DecoderRaw::rxTimeoutPipelineBusy() const
|
||||
{
|
||||
if (pulseFilterHoldCount != 0U)
|
||||
return true;
|
||||
noInterrupts();
|
||||
const bool busy = !subBuffer.isEmpty() || !filteredSubBuffer.isEmpty();
|
||||
interrupts();
|
||||
return busy;
|
||||
}
|
||||
|
||||
void IR_DecoderRaw::listenStart()
|
||||
{
|
||||
if (rxTimeoutPipelineBusy())
|
||||
return;
|
||||
if (isReciveRaw && ((micros() - lastEdgeTime) > IR_timeout * 2U))
|
||||
{
|
||||
#if defined(IRDEBUG_SERIAL_PACK)
|
||||
@ -359,6 +368,8 @@ void IR_DecoderRaw::listenStart()
|
||||
inline void IR_DecoderRaw::checkTimeout()
|
||||
{
|
||||
if (!isRecive) return; // уже не принимаем – нечего проверять
|
||||
if (rxTimeoutPipelineBusy())
|
||||
return;
|
||||
|
||||
if (micros() - lastEdgeTime > IR_timeout * 2U)
|
||||
{
|
||||
@ -371,8 +382,14 @@ inline void IR_DecoderRaw::checkTimeout()
|
||||
#endif
|
||||
isRecive = false; // приём завершён
|
||||
msgTypeReceive = 0;
|
||||
// firstRX(); // подготовка к новому пакету
|
||||
lastEdgeTime = micros(); // защита от повторного срабатывания
|
||||
// Как после listenStart(): без сброса isReciveRaw + firstRX() декодер остаётся
|
||||
// с «сырым» флагом приёма / Locked и не может заново поймать преамбулу до очень
|
||||
// длинной тишины (см. preambleProcessEdge Idle и listenStart).
|
||||
isReciveRaw = false;
|
||||
firstRX();
|
||||
// Не подставлять lastEdgeTime = micros(): при хвосте в subBuffer следующий фронт
|
||||
// имеет edge.time < micros() — откат lastEdgeTime даёт ложный TIMEOUT на следующем tick().
|
||||
// Повторного checkTimeout при тишине нет: isRecive уже false.
|
||||
}
|
||||
}
|
||||
// ====================================================================
|
||||
@ -382,6 +399,10 @@ void IR_DecoderRaw::tick()
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefFlushDeferredIsrLogs();
|
||||
#endif
|
||||
// listenStart/checkTimeout: в конце tick (END) и при отсутствии фронта (ниже).
|
||||
// Не в начале до pop: иначе после checkTimeout lastEdgeTime vs micros() расходятся
|
||||
// с метками ISR из очереди → ложные TIMEOUT (bits=0) каждый пакет.
|
||||
|
||||
FrontStorage currentFront;
|
||||
bool hasCurrentFront = false;
|
||||
FrontStorage rawFront;
|
||||
@ -420,21 +441,8 @@ void IR_DecoderRaw::tick()
|
||||
if (!hasCurrentFront)
|
||||
{
|
||||
isSubBufferOverflow = false;
|
||||
bool rawQueueHasPending = false;
|
||||
bool filteredQueueHasPending = false;
|
||||
noInterrupts();
|
||||
rawQueueHasPending = !subBuffer.isEmpty();
|
||||
if (IR_INPUT_MIN_PULSE_US > 0U)
|
||||
filteredQueueHasPending = !filteredSubBuffer.isEmpty();
|
||||
interrupts();
|
||||
const bool filterHoldHasPending = (IR_INPUT_MIN_PULSE_US > 0U) && (pulseFilterHoldCount > 0U);
|
||||
const bool hasPendingEdges = hasRawFront || rawQueueHasPending || filteredQueueHasPending || filterHoldHasPending;
|
||||
|
||||
if (!hasPendingEdges)
|
||||
{
|
||||
listenStart();
|
||||
checkTimeout();
|
||||
}
|
||||
listenStart();
|
||||
checkTimeout();
|
||||
#if defined(IR_EDGE_TRACE)
|
||||
while (edgeTraceFlushChunk(Serial, 48) > 0) {}
|
||||
#endif
|
||||
@ -722,6 +730,8 @@ void IR_DecoderRaw::tick()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
END:;
|
||||
listenStart();
|
||||
checkTimeout();
|
||||
#if IR_RX_BRIEF_LOG
|
||||
rxBriefFlushDeferredIsrLogs();
|
||||
#endif
|
||||
@ -748,10 +758,12 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
|
||||
}
|
||||
if (isBufferOverflow || isPreamb || isWrongPack)
|
||||
{
|
||||
// Как checkTimeout/listenStart: firstRX() сбрасывает буфер битов, преамбулу и
|
||||
// pulseFilterReset() — при IR_INPUT_MIN_PULSE_US > 0 иначе остаётся «хвост» в hold/filtered.
|
||||
isRecive = false;
|
||||
isReciveRaw = false;
|
||||
preambleResetToIdle();
|
||||
msgTypeReceive = 0;
|
||||
firstRX();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1593,7 +1605,12 @@ bool IR_DecoderRaw::preambleProcessEdge(const FrontStorage &front)
|
||||
{
|
||||
if (isReciveRaw)
|
||||
return false;
|
||||
if (!isReciveRaw && front.dir && front.time > prevRise && (front.time - prevRise) > longSilence)
|
||||
// Не использовать front.time > prevRise: после переполнения micros (~2^32 µs) новое t
|
||||
// меньше prevRise в unsigned-смысле — преамбула никогда не стартует («залипание» RX).
|
||||
// prevRise == 0: как раньше — «длинная тишина» только по абсолютному front.time > longSilence.
|
||||
if (!isReciveRaw && front.dir &&
|
||||
((prevRise == 0U && front.time > longSilence) ||
|
||||
(prevRise != 0U && (uint32_t)(front.time - prevRise) > longSilence)))
|
||||
preambleStartCandidate(front);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user