Skip to content

Reset parser after inter-byte timeout to prevent truncated frame corruption - #32

Open
brocci wants to merge 1 commit into
madleech:masterfrom
brocci:fix-inter-byte-timeout
Open

Reset parser after inter-byte timeout to prevent truncated frame corruption#32
brocci wants to merge 1 commit into
madleech:masterfrom
brocci:fix-inter-byte-timeout

Conversation

@brocci

@brocci brocci commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

As reported in issue #28:

[BUG] No inter-byte timeout: a truncated frame corrupts the next frame and applies garbage to outputs

  • Status: still present in v1.7.0 (unchanged; INIT now also flows through this path).
  • Spec: LCS-9.10.1 p.2 (valid-message definition), p.8 §D.2 (the host has a timeout concept; nodes get no guidance — see ambiguities).
  • Code: src/CMRI.cpp:214-233 (DECODE_DATA, DECODE_ESC_DATA); no timer anywhere in the library.
  • Two concrete cases, both verified against the state machine:
    1. A T frame that dies before its ETX leaves the parser in DECODE_DATA. The next real frame's FF FF 02 UA MT bytes are stored into _rx_buffer as if they were output data (until the buffer fills), and the next frame's ETX terminates the ghost frame and returns SET — the sketch then drives layout outputs with 0xFF 0xFF 0x02... garbage.
    2. A frame that dies immediately after a DLE leaves the parser in DECODE_ESC_DATA, which unconditionally consumes the next byte (src/CMRI.cpp:226-233) — i.e., the first SYN of the next frame is eaten as "escaped data," cascading into case 1.
  • Failure scenario: one glitched/brownout-truncated transmission produces visibly wrong turnout/signal states on the next host update, not just a lost frame.
  • Fix: reset _mode to PREAMBLE_1 (and discard the partial buffer) if more than a few character times elapse between bytes; or double-buffer and commit only on ETX.

This PR implements the required fix and adds corresponding tests. This has not been tested on real hardware.

The default INTER_BYTE_TIMEOUT_MS has been calculated based on serial transmission at 9600 bauds 8N2. JMRI uses 19200 bauds as default baud rate for C/MRI, but this default timeout value matches the baud rate used in all examples of this library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant