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

Implementation of the application-level Train Control Protocol module. More...

Functions

void OpenLcbApplicationTrain_initialize (const interface_openlcb_application_train_t *interface)
 Initialises the train module and stores the callback interface.
 
train_state_tOpenLcbApplicationTrain_setup (openlcb_node_t *openlcb_node)
 Allocates a train state slot and assigns it to the node.
 
train_state_tOpenLcbApplicationTrain_get_state (openlcb_node_t *openlcb_node)
 Returns the train state for a node.
 
void OpenLcbApplicationTrain_100ms_timer_tick (uint8_t current_tick)
 Decrements the heartbeat countdown for all active train nodes.
 
void OpenLcbApplicationTrain_send_set_speed (openlcb_node_t *openlcb_node, uint16_t train_alias, node_id_t train_node_id, uint16_t speed)
 Sends a Set Speed/Direction command to a train node.
 
void OpenLcbApplicationTrain_send_set_function (openlcb_node_t *openlcb_node, uint16_t train_alias, node_id_t train_node_id, uint32_t fn_address, uint16_t fn_value)
 Sends a Set Function command to a train node.
 
void OpenLcbApplicationTrain_send_emergency_stop (openlcb_node_t *openlcb_node, uint16_t train_alias, node_id_t train_node_id)
 Sends an Emergency Stop command to a train node.
 
void OpenLcbApplicationTrain_send_query_speeds (openlcb_node_t *openlcb_node, uint16_t train_alias, node_id_t train_node_id)
 Sends a Query Speeds command to a train node.
 
void OpenLcbApplicationTrain_send_query_function (openlcb_node_t *openlcb_node, uint16_t train_alias, node_id_t train_node_id, uint32_t fn_address)
 Sends a Query Function command to a train node.
 
void OpenLcbApplicationTrain_send_assign_controller (openlcb_node_t *openlcb_node, uint16_t train_alias, node_id_t train_node_id)
 Sends an Assign Controller command to a train node.
 
void OpenLcbApplicationTrain_send_release_controller (openlcb_node_t *openlcb_node, uint16_t train_alias, node_id_t train_node_id)
 Sends a Release Controller command to a train node.
 
void OpenLcbApplicationTrain_send_noop (openlcb_node_t *openlcb_node, uint16_t train_alias, node_id_t train_node_id)
 Sends a NOOP management command to a train node.
 
void OpenLcbApplicationTrain_set_dcc_address (openlcb_node_t *openlcb_node, uint16_t dcc_address, bool is_long_address)
 Sets the DCC address and address type for a train node.
 
uint16_t OpenLcbApplicationTrain_get_dcc_address (openlcb_node_t *openlcb_node)
 Returns the DCC address for a train node.
 
bool OpenLcbApplicationTrain_is_long_address (openlcb_node_t *openlcb_node)
 Returns true if the train node uses long DCC addressing.
 
void OpenLcbApplicationTrain_set_speed_steps (openlcb_node_t *openlcb_node, uint8_t speed_steps)
 Sets the speed-step mode for a train node.
 
uint8_t OpenLcbApplicationTrain_get_speed_steps (openlcb_node_t *openlcb_node)
 Returns the speed-step mode for a train node.
 

Detailed Description

Implementation of the application-level Train Control Protocol module.

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.

Manages the train state pool, heartbeat timer, and all throttle-side send helpers for the OpenLCB Train Control Protocol.

Author
Jim Kueneman
Date
4 Mar 2026

Function Documentation

◆ OpenLcbApplicationTrain_initialize()

void OpenLcbApplicationTrain_initialize ( const interface_openlcb_application_train_t * interface)

Initialises the train module and stores the callback interface.

Algorithm:

  1. Zero the train state pool.
  2. Reset _train_pool_count to 0.
  3. Store the interface pointer.
* @param interface  Pointer to a interface_openlcb_application_train_t.
* 
Warning
Must be called before any other function in this module.

◆ OpenLcbApplicationTrain_setup()

train_state_t * OpenLcbApplicationTrain_setup ( openlcb_node_t * openlcb_node)

Allocates a train state slot and assigns it to the node.

Algorithm:

  1. Return NULL if openlcb_node is NULL.
  2. If the node already has train_state set, return the existing pointer.
  3. Return NULL if the pool is exhausted.
  4. Take the next pool slot, zero it, and store a pointer in openlcb_node->train_state.
  5. Set state->owner_node back to the node.
  6. Register the standard train event IDs: Train producer, Emergency Off/Stop consumers, Clear Emergency Off/Stop consumers.
  7. Return the new state pointer.
* @param openlcb_node  Pointer to the openlcb_node_t to configure as a train.
* 
Returns
Pointer to the train_state_t, or NULL if the node is NULL or the pool is full.

◆ OpenLcbApplicationTrain_get_state()

train_state_t * OpenLcbApplicationTrain_get_state ( openlcb_node_t * openlcb_node)

Returns the train state for a node.

Algorithm:

  1. Return NULL if openlcb_node is NULL.
  2. Return openlcb_node->train_state.
* @param openlcb_node  Pointer to the openlcb_node_t.
* 
Returns
Pointer to the train_state_t, or NULL.

◆ OpenLcbApplicationTrain_100ms_timer_tick()

void OpenLcbApplicationTrain_100ms_timer_tick ( uint8_t current_tick)

Decrements the heartbeat countdown for all active train nodes.

Algorithm:

  1. Compute ticks elapsed since last call via subtraction.
  2. Skip if no time has elapsed (deduplication).
  3. For each pool slot with heartbeat_timeout_s > 0:
    • Decrement heartbeat_counter_100ms by ticks_elapsed (saturate at 0).
    • At the halfway point, call _send_heartbeat_request() to ping the controller.
    • At zero, set estop_active = true, zero set_speed preserving direction, forward Set Speed 0 to listeners, and fire on_heartbeat_timeout.
* @param current_tick  Current value of the global 100ms tick counter.
* 

◆ OpenLcbApplicationTrain_send_set_speed()

void OpenLcbApplicationTrain_send_set_speed ( openlcb_node_t * openlcb_node,
uint16_t train_alias,
node_id_t train_node_id,
uint16_t speed )

Sends a Set Speed/Direction command to a train node.

Algorithm:

  1. Call _prepare_train_command(); return if it fails.
  2. Set payload byte 0 to TRAIN_SET_SPEED_DIRECTION.
  3. Set payload bytes 1-2 to the 16-bit speed value.
  4. Call send_openlcb_msg().
* @param openlcb_node    Pointer to the sending openlcb_node_t.
* @param train_alias     12-bit CAN alias of the target train node.
* @param train_node_id   48-bit node_id_t of the target train node.
* @param speed           16-bit speed/direction in OpenLCB float16 format.
* 

◆ OpenLcbApplicationTrain_send_set_function()

void OpenLcbApplicationTrain_send_set_function ( openlcb_node_t * openlcb_node,
uint16_t train_alias,
node_id_t train_node_id,
uint32_t fn_address,
uint16_t fn_value )

Sends a Set Function command to a train node.

Algorithm:

  1. Call _prepare_train_command(); return if it fails.
  2. Set payload byte 0 to TRAIN_SET_FUNCTION.
  3. Set payload bytes 1-3 to the 24-bit function address.
  4. Set payload bytes 4-5 to the 16-bit function value.
  5. Call send_openlcb_msg().
* @param openlcb_node    Pointer to the sending openlcb_node_t.
* @param train_alias     12-bit CAN alias of the target train node.
* @param train_node_id   48-bit node_id_t of the target train node.
* @param fn_address      24-bit function address.
* @param fn_value        16-bit function value.
* 

◆ OpenLcbApplicationTrain_send_emergency_stop()

void OpenLcbApplicationTrain_send_emergency_stop ( openlcb_node_t * openlcb_node,
uint16_t train_alias,
node_id_t train_node_id )

Sends an Emergency Stop command to a train node.

Algorithm:

  1. Call _prepare_train_command(); return if it fails.
  2. Set payload byte 0 to TRAIN_EMERGENCY_STOP.
  3. Call send_openlcb_msg().
* @param openlcb_node    Pointer to the sending openlcb_node_t.
* @param train_alias     12-bit CAN alias of the target train node.
* @param train_node_id   48-bit node_id_t of the target train node.
* 

◆ OpenLcbApplicationTrain_send_query_speeds()

void OpenLcbApplicationTrain_send_query_speeds ( openlcb_node_t * openlcb_node,
uint16_t train_alias,
node_id_t train_node_id )

Sends a Query Speeds command to a train node.

Algorithm:

  1. Call _prepare_train_command(); return if it fails.
  2. Set payload byte 0 to TRAIN_QUERY_SPEEDS.
  3. Call send_openlcb_msg().
* @param openlcb_node    Pointer to the sending openlcb_node_t.
* @param train_alias     12-bit CAN alias of the target train node.
* @param train_node_id   48-bit node_id_t of the target train node.
* 

◆ OpenLcbApplicationTrain_send_query_function()

void OpenLcbApplicationTrain_send_query_function ( openlcb_node_t * openlcb_node,
uint16_t train_alias,
node_id_t train_node_id,
uint32_t fn_address )

Sends a Query Function command to a train node.

Algorithm:

  1. Call _prepare_train_command(); return if it fails.
  2. Set payload byte 0 to TRAIN_QUERY_FUNCTION.
  3. Set payload bytes 1-3 to the 24-bit function address.
  4. Call send_openlcb_msg().
* @param openlcb_node    Pointer to the sending openlcb_node_t.
* @param train_alias     12-bit CAN alias of the target train node.
* @param train_node_id   48-bit node_id_t of the target train node.
* @param fn_address      24-bit function address to query.
* 

◆ OpenLcbApplicationTrain_send_assign_controller()

void OpenLcbApplicationTrain_send_assign_controller ( openlcb_node_t * openlcb_node,
uint16_t train_alias,
node_id_t train_node_id )

Sends an Assign Controller command to a train node.

Algorithm:

  1. Call _prepare_train_command(); return if it fails.
  2. Set payload byte 0 to TRAIN_CONTROLLER_CONFIG, byte 1 to TRAIN_CONTROLLER_ASSIGN.
  3. Set payload bytes 2-7 to openlcb_node->id (the throttle's Node ID).
  4. Call send_openlcb_msg().
* @param openlcb_node    Pointer to the sending (throttle) openlcb_node_t.
* @param train_alias     12-bit CAN alias of the target train node.
* @param train_node_id   48-bit node_id_t of the target train node.
* 

◆ OpenLcbApplicationTrain_send_release_controller()

void OpenLcbApplicationTrain_send_release_controller ( openlcb_node_t * openlcb_node,
uint16_t train_alias,
node_id_t train_node_id )

Sends a Release Controller command to a train node.

Algorithm:

  1. Call _prepare_train_command(); return if it fails.
  2. Set payload byte 0 to TRAIN_CONTROLLER_CONFIG, byte 1 to TRAIN_CONTROLLER_RELEASE.
  3. Set payload bytes 2-7 to openlcb_node->id (the throttle's Node ID).
  4. Call send_openlcb_msg().
* @param openlcb_node    Pointer to the sending (throttle) openlcb_node_t.
* @param train_alias     12-bit CAN alias of the target train node.
* @param train_node_id   48-bit node_id_t of the target train node.
* 

◆ OpenLcbApplicationTrain_send_noop()

void OpenLcbApplicationTrain_send_noop ( openlcb_node_t * openlcb_node,
uint16_t train_alias,
node_id_t train_node_id )

Sends a NOOP management command to a train node.

Sends a NOOP (no-operation) management command to a train node.

Algorithm:

  1. Call _prepare_train_command(); return if it fails.
  2. Set payload byte 0 to TRAIN_MANAGEMENT, byte 1 to TRAIN_MGMT_NOOP.
  3. Call send_openlcb_msg().
* @param openlcb_node    Pointer to the sending openlcb_node_t.
* @param train_alias     12-bit CAN alias of the target train node.
* @param train_node_id   48-bit node_id_t of the target train node.
* 

◆ OpenLcbApplicationTrain_set_dcc_address()

void OpenLcbApplicationTrain_set_dcc_address ( openlcb_node_t * openlcb_node,
uint16_t dcc_address,
bool is_long_address )

Sets the DCC address and address type for a train node.

Algorithm:

  1. Return if openlcb_node or train_state is NULL.
  2. Store dcc_address and is_long_address in the train state.
* @param openlcb_node    Pointer to the openlcb_node_t.
* @param dcc_address     DCC address value.
* @param is_long_address true for long addressing, false for short.
* 

◆ OpenLcbApplicationTrain_get_dcc_address()

uint16_t OpenLcbApplicationTrain_get_dcc_address ( openlcb_node_t * openlcb_node)

Returns the DCC address for a train node.

Algorithm:

  1. Return 0 if openlcb_node or train_state is NULL.
  2. Return train_state->dcc_address.
* @param openlcb_node  Pointer to the openlcb_node_t.
* 
Returns
DCC address, or 0 if the node has no train state.

◆ OpenLcbApplicationTrain_is_long_address()

bool OpenLcbApplicationTrain_is_long_address ( openlcb_node_t * openlcb_node)

Returns true if the train node uses long DCC addressing.

Algorithm:

  1. Return false if openlcb_node or train_state is NULL.
  2. Return train_state->is_long_address.
* @param openlcb_node  Pointer to the openlcb_node_t.
* 
Returns
true for long addressing, false otherwise.

◆ OpenLcbApplicationTrain_set_speed_steps()

void OpenLcbApplicationTrain_set_speed_steps ( openlcb_node_t * openlcb_node,
uint8_t speed_steps )

Sets the speed-step mode for a train node.

Algorithm:

  1. Return if openlcb_node or train_state is NULL.
  2. Store speed_steps in train_state->speed_steps.
* @param openlcb_node  Pointer to the openlcb_node_t.
* @param speed_steps   Speed-step count (14, 28, or 128).
* 

◆ OpenLcbApplicationTrain_get_speed_steps()

uint8_t OpenLcbApplicationTrain_get_speed_steps ( openlcb_node_t * openlcb_node)

Returns the speed-step mode for a train node.

Algorithm:

  1. Return 0 if openlcb_node or train_state is NULL.
  2. Return train_state->speed_steps.
* @param openlcb_node  Pointer to the openlcb_node_t.
* 
Returns
Speed-step count, or 0 if the node has no train state.

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