OpenLcbCLib 1.0 Alpha
OpenSource C Library to create OpenLcb/Lcc Nodes
Loading...
Searching...
No Matches
protocol_datagram_handler.c File Reference

Datagram protocol handler — reliable 0–72 byte addressed transfers. More...

Macros

#define DATAGRAM_TIMEOUT_TICKS   30
 Default datagram timeout in 100ms ticks (3 seconds).
 
#define DATAGRAM_MAX_RETRIES   3
 Maximum datagram retry attempts before abandoning.
 

Functions

void ProtocolDatagramHandler_initialize (const interface_protocol_datagram_handler_t *interface_protocol_datagram_handler)
 Stores the callback interface. Call once at startup.
 
void ProtocolDatagramHandler_datagram (openlcb_statemachine_info_t *statemachine_info)
 Main entry point — switches on payload[0] command byte.
 
void ProtocolDatagramHandler_load_datagram_received_ok_message (openlcb_statemachine_info_t *statemachine_info, uint16_t reply_pending_time_in_seconds)
 Build a Datagram Received OK message (MTI 0x0A28).
 
void ProtocolDatagramHandler_load_datagram_rejected_message (openlcb_statemachine_info_t *statemachine_info, uint16_t return_code)
 Build a Datagram Rejected message (MTI 0x0A48).
 
void ProtocolDatagramHandler_datagram_received_ok (openlcb_statemachine_info_t *statemachine_info)
 Handle incoming Datagram Received OK (MTI 0x0A28).
 
void ProtocolDatagramHandler_datagram_rejected (openlcb_statemachine_info_t *statemachine_info)
 Handle incoming Datagram Rejected (MTI 0x0A48).
 
void ProtocolDatagramHandler_clear_resend_datagram_message (openlcb_node_t *openlcb_node)
 Free stored datagram and clear resend flag for a node.
 
void ProtocolDatagramHandler_100ms_timer_tick (uint8_t current_tick)
 Periodic timer tick for datagram timeout tracking.
 
void ProtocolDatagramHandler_check_timeouts (uint8_t current_tick)
 Scans for timed-out or max-retried pending datagrams and frees them.
 

Detailed Description

Datagram protocol handler — reliable 0–72 byte addressed transfers.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Dispatches incoming datagrams to per-address-space callbacks for read, write, write-under-mask, and stream variants (both datagram- and stream-transport). Callback-based: the application populates an interface_protocol_datagram_handler_t with handler pointers; NULL pointers cause automatic rejection with SUBCOMMAND_UNKNOWN.

Also handles Datagram Received OK / Rejected replies including retry logic for temporary errors.

Author
Jim Kueneman
Date
4 Mar 2026
See also
protocol_datagram_handler.h
DatagramTransportS.pdf
MemoryConfigurationS.pdf

Macro Definition Documentation

◆ DATAGRAM_TIMEOUT_TICKS

#define DATAGRAM_TIMEOUT_TICKS   30

Default datagram timeout in 100ms ticks (3 seconds).

◆ DATAGRAM_MAX_RETRIES

#define DATAGRAM_MAX_RETRIES   3

Maximum datagram retry attempts before abandoning.

Function Documentation

◆ ProtocolDatagramHandler_initialize()

void ProtocolDatagramHandler_initialize ( const interface_protocol_datagram_handler_t * interface_protocol_datagram_handler)

Stores the callback interface. Call once at startup.

Stores the callback interface. Call once at startup before any datagram processing.

Algorithm:

  1. Cast away const and store the pointer in module-level static
* @param interface_protocol_datagram_handler  Populated callback table.
* 
Warning
Structure must remain valid for application lifetime.

◆ ProtocolDatagramHandler_datagram()

void ProtocolDatagramHandler_datagram ( openlcb_statemachine_info_t * statemachine_info)

Main entry point — switches on payload[0] command byte.

Processes an incoming datagram. Dispatches to the appropriate handler based on the command byte (payload[0]).

Algorithm:

  1. If payload[0] == CONFIG_MEM_CONFIGURATION (0x20), delegate to _handle_datagram_memory_configuration_command()
  2. Otherwise reject with COMMAND_UNKNOWN
* @param statemachine_info  Context with the received datagram.
* 

◆ ProtocolDatagramHandler_load_datagram_received_ok_message()

void ProtocolDatagramHandler_load_datagram_received_ok_message ( openlcb_statemachine_info_t * statemachine_info,
uint16_t reply_pending_time_in_seconds )

Build a Datagram Received OK message (MTI 0x0A28).

Builds a Datagram Received OK message (MTI 0x0A28).

Algorithm:

  1. Convert reply_pending_time_in_seconds to a 4-bit power-of-2 exponent (1 = 2 s, 2 = 4 s, … 15 = 32768 s)
  2. Build MTI_DATAGRAM_OK_REPLY addressed back to the sender
  3. If reply_pending, store DATAGRAM_OK_REPLY_PENDING | exponent in payload[0]
  4. Mark outgoing message valid
* @param statemachine_info               Current context.
* @param reply_pending                   true if a reply datagram will follow.
* @param reply_pending_time_in_seconds   Seconds until reply (rounded up to 2^N).
*                                        Ignored when reply_pending is false.
* 

◆ ProtocolDatagramHandler_load_datagram_rejected_message()

void ProtocolDatagramHandler_load_datagram_rejected_message ( openlcb_statemachine_info_t * statemachine_info,
uint16_t return_code )

Build a Datagram Rejected message (MTI 0x0A48).

Builds a Datagram Rejected message (MTI 0x0A48).

Algorithm:

  1. Build MTI_DATAGRAM_REJECTED_REPLY addressed back to the sender
  2. Copy 16-bit return_code into payload[0..1]
  3. Mark outgoing message valid
* @param statemachine_info  Current context.
* @param return_code        OpenLCB error code (0x1xxx permanent, 0x2xxx temporary).
* 

◆ ProtocolDatagramHandler_datagram_received_ok()

void ProtocolDatagramHandler_datagram_received_ok ( openlcb_statemachine_info_t * statemachine_info)

Handle incoming Datagram Received OK (MTI 0x0A28).

Handles an incoming Datagram Received OK reply. Clears the resend flag and frees the stored datagram awaiting acknowledgement.

Algorithm:

  1. Clear resend flag and free the stored datagram buffer
  2. Set outgoing_msg_info.valid = false (nothing to send)
* @param statemachine_info  Context with the received OK reply.
* 

◆ ProtocolDatagramHandler_datagram_rejected()

void ProtocolDatagramHandler_datagram_rejected ( openlcb_statemachine_info_t * statemachine_info)

Handle incoming Datagram Rejected (MTI 0x0A48).

Handles an incoming Datagram Rejected reply. Sets the resend flag for temporary errors; clears retry state for permanent errors.

Algorithm:

  1. Extract error code from payload word 0
  2. If ERROR_TEMPORARY bit set and a stored datagram exists: a. Read retry count from timer.datagram.retry_count b. Increment retry count c. If retries < DATAGRAM_MAX_RETRIES, store new retry count and fresh tick snapshot, set resend_datagram flag d. If retries >= DATAGRAM_MAX_RETRIES, abandon (clear and free)
  3. If permanent error, clear resend flag and free stored buffer
  4. Set outgoing_msg_info.valid = false
* @param statemachine_info  Context with the received rejection.
* 

◆ ProtocolDatagramHandler_clear_resend_datagram_message()

void ProtocolDatagramHandler_clear_resend_datagram_message ( openlcb_node_t * openlcb_node)

Free stored datagram and clear resend flag for a node.

Frees any stored datagram and clears the resend flag for the node.

Algorithm:

  1. If last_received_datagram exists, lock/free/unlock it and NULL the pointer
  2. Clear resend_datagram flag
* @param openlcb_node  Target node.
* 
Note
Safe to call when no datagram is stored.

◆ ProtocolDatagramHandler_100ms_timer_tick()

void ProtocolDatagramHandler_100ms_timer_tick ( uint8_t current_tick)

Periodic timer tick for datagram timeout tracking.

Called from the main loop with the current global tick. Currently a placeholder — timeout scanning is done by ProtocolDatagramHandler_check_timeouts().

* @param current_tick  Current value of the global 100ms tick counter.
* 

◆ ProtocolDatagramHandler_check_timeouts()

void ProtocolDatagramHandler_check_timeouts ( uint8_t current_tick)

Scans for timed-out or max-retried pending datagrams and frees them.

Must be called from the main processing loop, not from an interrupt. Acquires the shared resource lock internally.

* @param current_tick  Current value of the global 100ms tick, passed from the main loop.
* 

Copyright (c) 2026 Jim Kueneman all rights reserved. See the License