fix timer overflow?

This commit is contained in:
2026-04-15 11:00:48 +03:00
parent 8631f23b53
commit 8daff9c46a
7 changed files with 89 additions and 50 deletions

View File

@ -161,7 +161,9 @@ class SimState:
def first_rx(st: SimState) -> None:
"""IR_DecoderRaw::firstRX сброс буфера; isRecive/isReciveRaw в прошивке здесь не меняются."""
"""Аналог IR_DecoderRaw::firstRX: сброс буфера битов, преамбулы, счётчиков ошибок по битам.
В прошивке isRecive / isReciveRaw сбрасывают вызывающие пути (listenStart, checkTimeout, конец кадра);
затем firstRX() обнуляет буфер и preambleResetToIdle()."""
st.is_preamb = True
st.is_wrong_pack = False
st.is_buffer_overflow = False
@ -188,11 +190,18 @@ def tick(
rise_max = rise_sync_time + TOLERANCE_US
irmax = IR_TIMEOUT # упрощ.: без подстройки riseSyncTime в timeout
# listenStart: обрыв незавершённого приёма
if st.is_recive_raw and (t_us - st.prev_rise) > irmax * 2:
# listenStart: как IR_DecoderRaw — пауза по lastEdgeTime (между обработанными фронтами), не по prevRise.
if st.last_edge > 0 and st.is_recive_raw and (t_us - st.last_edge) > irmax * 2:
st.is_recive_raw = False
first_rx(st)
# checkTimeout: как IR_DecoderRaw после фикса — isReciveRaw=0 и firstRX(), иначе залипание FSM.
if st.last_edge > 0 and st.is_recive and (t_us - st.last_edge) > irmax * 2:
st.is_recive = False
st.is_recive_raw = False
first_rx(st)
# Не подставлять last_edge = t_us здесь: как IR_DecoderRaw после фикса.
st.last_edge = t_us
skip_rest = False
@ -307,6 +316,7 @@ def tick(
if st.is_buffer_overflow or st.is_preamb or st.is_wrong_pack:
st.is_recive = False
st.is_recive_raw = False
first_rx(st)
return
if st.buf_bit_pos == st.next_control_bit:
st.next_control_bit += SYNC_BITS if st.is_data else BIT_PER_BYTE
@ -345,7 +355,7 @@ def tick(
st.packets.append((ok, st.pack_size, bytes(st.data_buffer[: st.pack_size])))
st.is_recive = False
st.is_recive_raw = False
# буфер не чистят здесь — как в IR_DecoderRaw; firstRX по listenStart
# Как в IR_DecoderRaw: буфер не чистят на успешном CRC; сброс по listenStart/checkTimeout/firstRX
if around_rise_period(st.rise_period, rise_sync_time):
if st.high_time > st.low_time:

View File

@ -16,7 +16,8 @@ WRONG_PACK_SYNC — отдельное событие с причиной и т
отброшенных фронтов; без флага эти события только в счётчиках сводки.
Не моделирует IRDEBUG_SERIAL_SOFT_REJECT (жёсткий Wrong sync).
Таймауты: между фронтами, если gap > IR_timeout*2 и isRecive — checkTimeout.
Таймауты: как IR_DecoderRaw::tick — listenStart и checkTimeout в начале каждого тика (не только при пустых
очередях), пауза > IR_timeout*2 по lastEdgeTime; при checkTimeout: isReciveRaw=0, firstRX(), lastEdgeTime=now.
"""
from __future__ import annotations
@ -360,8 +361,8 @@ class DecoderSim:
def listen_start(self, now: int) -> None:
to = ir_timeout_us(self.rise_sync_time)
if self.is_recive_raw and (now - self.prev_rise) > to * 2:
self.events.append(f"t={now} listenStart abort raw (gap from prev_rise)")
if self.is_recive_raw and self.last_edge_time > 0 and (now - self.last_edge_time) > to * 2:
self.events.append(f"t={now} listenStart abort raw (gap since last edge, как IR_DecoderRaw)")
self.is_recive_raw = False
self._clear_packet_state()
self.first_rx()
@ -371,9 +372,12 @@ class DecoderSim:
return
to = ir_timeout_us(self.rise_sync_time)
if now - self.last_edge_time > to * 2:
self.events.append(f"t={now} checkTimeout (gap since last edge)")
self.events.append(f"t={now} checkTimeout -> isReciveRaw=0, firstRX() (как IR_DecoderRaw)")
self.is_recive = False
self.last_edge_time = now
self.is_recive_raw = False
self._clear_packet_state()
self.first_rx()
# Не last_edge_time = now: в прошивке убрано — расхождение с метками фронтов из очереди.
def write_to_buffer(self, bit_val: int) -> None:
if self.i_data_buffer > DATA_BYTE_SIZE_MAX * 8:
@ -382,6 +386,7 @@ class DecoderSim:
if self.is_buffer_overflow or self.is_preamb or self.is_wrong_pack:
self.is_recive = False
self.is_recive_raw = False
self.first_rx()
return
if self.buf_bit_pos == self.next_control_bit:
@ -478,6 +483,9 @@ class DecoderSim:
def tick_edge(self, t: int, level: int) -> None:
"""Один фронт: level = состояние линии ПОСЛЕ фронта (как dir в C++)."""
self.listen_start(t)
to = ir_timeout_us(self.rise_sync_time)
if self.is_recive and self.last_edge_time > 0 and (t - self.last_edge_time) > to * 2:
self.check_timeout(t)
self.last_edge_time = t
rising = level == 1
@ -689,9 +697,6 @@ def main() -> int:
dec = DecoderSim(verbose=args.verbose)
for e in edges:
to_us = ir_timeout_us(dec.rise_sync_time)
if dec.is_recive and dec.last_edge_time > 0 and (e.t_us - dec.last_edge_time) > to_us * 2:
dec.check_timeout(e.t_us)
dec.tick_edge(e.t_us, e.level)
print("--- События декодера (первые N), пакеты разделены пустой строкой ---")