Skip to content

Handle INIT messages and add set_init_handler() callback#22

Open
brocci wants to merge 1 commit into
madleech:masterfrom
brocci:add-init-callback
Open

Handle INIT messages and add set_init_handler() callback#22
brocci wants to merge 1 commit into
madleech:masterfrom
brocci:add-init-callback

Conversation

@brocci
Copy link
Copy Markdown

@brocci brocci commented May 12, 2026

Route INIT ('I') packets through the data decoder and expose the configuration payload to sketches via an optional callback.

Summary

NMRA CMRInet (LCS-9.10.1) defines four message types: Init (I), Poll (P), Transmit Data / SET (T), and Receive Data / GET (R).
The Init message is the first message sent to a node after power-up, carrying configuration data such as the node type, transmit character delay, and card layout.
Previously the library had two problems:

  1. Init messages were silently discarded — the payload bytes were not consumed from the serial buffer, potentially corrupting the next frame
  2. Even with the payload captured, sketches had no way to access it.

This PR fixes both: Init payloads are decoded and stored, and a
callback mechanism lets the sketch inspect NDP, delay, and option bytes.

Changes

Init message handling (_decode)

Treat I the same as T in DECODE_CMD — enter DECODE_DATA to consume the payload bytes (with DLE un-escaping) until ETX. The existing (unused) _rx_packet_type member stores the current command type, so POSTAMBLE_SET returns either SET or INIT to the caller.

void set_init_handler(void (*handler)(const uint8_t *data, int len))

Registers a callback that fires on every complete INIT packet.

Parameter Description
data Pointer to the raw INIT payload
len Number of bytes in the payload

INIT payload format (NMRA LCS-9.10.1)

Offset Field Description
0 NDP Node Definition Parameter (e.g. C)
1 DLH Transmit delay high byte
2 DLL Transmit delay low byte
3+ Options Node-type-specific configuration bytes
Delay = (DLH * 256 + DLL) * 10 microseconds

Internal changes

  • _rx_packet_type is now written during DECODE_CMD (repurposed from its previous unused declaration)
  • _rx_data_len tracks the actual number of payload bytes received (saved in POSTAMBLE_SET before resetting _rx_index)
  • _init_handler function pointer, default nullptr (no overhead when unused)
  • Callback fires inside process_char() when _decode() returns INIT
  • process_char() returns true for INIT messages (consistent with SET)

No memory allocation, no extra includes, no performance impact when no handler is registered.

Example

void on_init(const uint8_t *data, int len) {
  Serial.print(F("INIT received ("));
  // ...
}
void setup() {
  cmri.set_init_handler(on_init);
}

See examples/init_handler/init_handler.ino for the full example.

Closes #20

Route INIT ('I') packets through the data decoder and expose
the configuration payload to sketches via an optional callback.

Replaces the old behavior of silently discarding INIT payloads.
@brocci brocci force-pushed the add-init-callback branch from 7a96ae0 to 14aa024 Compare May 12, 2026 17:39
@brocci brocci changed the title Add init callback Handle INIT messages and add set_init_handler() callback May 12, 2026
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