Skip to content

Handle Init (I) messages instead of discarding payload#21

Closed
brocci wants to merge 1 commit into
madleech:masterfrom
brocci:add-init-handling
Closed

Handle Init (I) messages instead of discarding payload#21
brocci wants to merge 1 commit into
madleech:masterfrom
brocci:add-init-handling

Conversation

@brocci
Copy link
Copy Markdown

@brocci brocci commented May 10, 2026

Summary

  • Handle Init ('I') messages per NMRA CMRInet spec LCS-9.10.1 v1.1 instead of silently ignoring them
  • The spec defines four message types: Init ('I'), Poll ('P'), Transmit Data ('T'), and Receive Data ('R')
  • Currently, Init messages fall through to POSTAMBLE_OTHER and are discarded without the data payload being consumed
  • This fix consumes the Init payload, returns INIT from process(), and allows the sketch to handle it

Details

Problem: The NMRA CMRInet specification defines the Init message as the first message sent to a node after power-up, carrying configuration data such as the node type, transmit character delay, and card configuration. The current _decode() state machine treats the Init ('I') command byte the same as any other unrecognized command:

case DECODE_CMD:
    if (c == SET)           // 'T'
        _mode = DECODE_DATA;
    else if (c == POLL)     // 'P'
        goto POSTAMBLE_POLL;
    else                    // 'I' and others land here
        _mode = POSTAMBLE_OTHER;
    break;

This means:

  1. The Init payload bytes following 'I' are not consumed from the serial buffer — they linger and may corrupt the next frame.
  2. The calling sketch has no way to know an Init message was received.
  3. JMRI's "Initialise All Nodes" command has no effect on the node.

Fix: Treat 'I' the same as 'T' in DECODE_CMD — enter DECODE_DATA to consume the payload bytes (with DLE un-escaping) until ETX. Also track the received command type so POSTAMBLE_SET can return either SET or INIT to the caller. Update process_char() to return true for INIT messages, using the already-defined CMRI::INIT enum.

The existing _rx_packet_type member variable (declared but never written) is repurposed to store the current command type during DECODE_CMD.

Example

When JMRI sends FF FF 02 41 49 43 00 00 00 00 02 02 03 (Init for node 0, cpNode type, 2 input + 2 output bytes):

  • Before: Parser enters POSTAMBLE_OTHER and flushes only to ETX. _rx_buffer may contain 43 00 00 00 00 02 02 as stale data from Init. process() returns false.
  • After: Parser enters DECODE_DATA, correctly un-escapes and consumes the payload, ETX terminates cleanly. process() returns true and the sketch can check for CMRI::INIT via process_char().

Changes

CMRI.cpp — two changes in _decode() and one in process_char(). The comments in process_char() are updated to reflect that INIT is now handled.

Closes #20

@brocci
Copy link
Copy Markdown
Author

brocci commented May 12, 2026

Superseded by #22 which combines both changes.

@brocci brocci closed this May 12, 2026
@brocci brocci deleted the add-init-handling branch May 12, 2026 18:12
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.

Handle INIT messages and add set_init_handler() callback

1 participant