RTE RBC 2oo2 Reference Application 0.1.0 build 0006685
SIL 4 2oo2 Dual-Site Fault-Tolerant ERTMS Radio Block Centre Reference Architecture
Loading...
Searching...
No Matches
ab_gp_train.c File Reference

Train lifecycle/find/getters/setters against db/'s runtime table, AND the Train-domain wire codec (train_wire_decode()/ _encode() below) - see ab_gp_train.h. More...

#include "ab_gp_train.h"
#include <stdio.h>
#include "rte/utils/buffer/rte_buffer.h"
#include "rte/utils/cast/rte_cast.h"
#include "rte/utils/lifecycle/rte_lifecycle.h"
#include "rte/oal/log/rte_log.h"
#include "rte/oal/memory/rte_mem_util.h"
#include "rte/utils/notify/rte_notify.h"
#include "ab_siteGP.h"
#include "../com/ab_gp_channel_payload.h"
#include "../ertms_procedures/ab_gp_ertms_engine.h"
#include "../ertms_procedures/ab_gp_proc_session.h"
Include dependency graph for ab_gp_train.c:

Go to the source code of this file.

Macros

#define TRAIN_WIRE_HEADER_SIZE   12U
#define TRAIN_WIRE_CONTENT_SIZE_BASE   24U
#define TRAIN_WIRE_CONTENT_SIZE_M146   (TRAIN_WIRE_CONTENT_SIZE_BASE + 4U)
#define TRAIN_WIRE_CONTENT_SIZE_M136   (TRAIN_WIRE_CONTENT_SIZE_BASE + 4U + 40U)

Functions

 RTE_DECLARE_CALLBACK_LIST (ab_gp_train_context_list_t, ab_gp_train_context_notify_fn, AB_GP_TRAIN_MAX_CONTEXT_SUBSCRIBERS)
static bool train_id_in_range (uint8_t train_id)
rte_status_t ab_gp_register_train_context_notify (ab_gp_train_context_notify_fn fn, const void *context)
static bool build_train_context (const ab_gp_train_session_t sessions[], const ab_gp_db_t *db, uint8_t train_id, ab_gp_train_context_t *out_ctx)
static void notify_train_context (const ab_gp_train_session_t sessions[], const ab_gp_db_t *db, uint8_t train_id, ab_gp_train_update_type_t update_type)
void ab_gp_train_notify_context_changed (const ab_gp_train_session_t sessions[], const ab_gp_db_t *db, uint8_t train_id, ab_gp_train_update_type_t update_type)
 Explicit trigger GA calls (through ga_interface.h) once it has finished a multi-step train-context change it owns the sequencing of - a route grant/release (AB/GA/il/ab_ga_il.c's own handle_route_add()/handle_route_release(), which update granted_length/ma_seq/has_ma across several separate setter calls) being the only real case today. NOT fired automatically from any individual setter - see ab_gp_train_set_has_ma()'s own doc for why firing per-setter would either see a half-updated context or fire multiple times for one logical change.
bool ab_gp_get_train_context (const ab_gp_train_session_t sessions[], const ab_gp_db_t *db, uint8_t train_id, ab_gp_train_context_t *out_ctx)
 One-shot pull equivalent of the push notification above - the SAME snapshot-building logic (real impl: ab_gp_train.c's own build_train_context(), shared with notify_train_context()), for a caller that just needs train_id's current state right now rather than reacting to a change. Replaces the individual ab_gp_train_session_get_*()/ab_gp_train_get_has_ma() getters GA used to call one field at a time (later session, on direct request - "it will be enough if GA can getTrainContext / getRouteContext; setters stay separate since they require validation"). Mutation still goes through the individual setters below - this is READ-ONLY, deliberately.
static uint8_t train_wire_nid_message_for_kind (rbc_msg_kind_t kind)
static uint16_t train_wire_content_size_for_kind (rbc_msg_kind_t kind)
static void train_wire_encode (uint8_t out[RBC_ENVELOPE_WIRE_SIZE], const rbc_envelope_t *env)
static bool train_wire_decode (const uint8_t in[RBC_ENVELOPE_WIRE_SIZE], rbc_envelope_t *out_env)
static bool nid_engine_connected_elsewhere (const ab_gp_db_t *db, uint8_t nid_engine, uint8_t exclude_train_id)
bool ab_gp_train_add (ab_gp_db_t *db, uint8_t train_id, uint8_t nid_engine)
 Adds a train on connect: fills db->trains[train_id-1] with nid_engine, connected=true, has_ma=false, and an empty route_ids[]/route_count=0.
bool ab_gp_train_remove (ab_gp_db_t *db, uint8_t train_id)
 Removes a train on disconnect: resets db->trains[train_id-1] back to its all-zero/disconnected state.
ab_gp_db_train_t * ab_gp_train_find (ab_gp_db_t *db, uint8_t train_id)
 Finds a connected train's own slot for direct field access.
bool ab_gp_train_find_by_nid_engine (const ab_gp_db_t *db, uint8_t nid_engine, uint8_t *out_train_id)
 Reverse lookup: which train_id (if any) is nid_engine currently connected as.
bool ab_gp_train_is_connected (const ab_gp_db_t *db, uint8_t train_id)
bool ab_gp_train_get_nid_engine (const ab_gp_db_t *db, uint8_t train_id, uint8_t *out_nid_engine)
bool ab_gp_train_get_route_count (const ab_gp_db_t *db, uint8_t train_id, uint8_t *out_route_count)
bool ab_gp_train_set_nid_engine (ab_gp_db_t *db, uint8_t train_id, uint8_t nid_engine)
bool ab_gp_train_set_has_ma (ab_gp_db_t *db, uint8_t train_id, bool has_ma)
bool ab_gp_train_get_last_position (const ab_gp_db_t *db, uint8_t train_id, uint32_t *out_nid_lrbg)
bool ab_gp_train_set_last_position (ab_gp_db_t *db, uint8_t train_id, uint32_t nid_lrbg)
 Records this train's own most recently reported NID_LRBG - the write side of the field logic/'s own cyclic route-connect sweep reads (ab_gp_logic.h).
bool ab_gp_train_handle_connect (ab_gp_db_t *db, uint8_t train_id)
 Handles an inbound P0 (connect handshake) - wraps ab_gp_train_add() with the same env->train_id-as-nid_engine stand-in caveat as that function's own doc. Idempotent (safe to call again for an already-connected train_id - just returns false, changes nothing, same as ab_gp_train_add() itself).
bool ab_gp_train_handle_position_report (ab_gp_db_t *db, uint8_t train_id, uint32_t nid_lrbg)
 Handles an inbound M136 (Position Report) - adds the train first (ab_gp_train_handle_connect()) if this is the first data seen for it (tolerates M136 arriving before/without a P0, same lenient posture com's own ctx->sessions[] handling takes), then records nid_lrbg via ab_gp_train_set_last_position() if it is nonzero (0 = no real balise reported this cycle, ab_gp_db.h's own sentinel - left unchanged rather than overwritten with "none").
void ab_gp_train_build_position_answer (uint8_t out[RBC_ENVELOPE_WIRE_SIZE], uint8_t train_id, uint32_t cycle, uint32_t d_lrbg, uint32_t msg_type)
 Builds and wire-encodes the outbound M24/M15 Position Report answer for train_id (kind=RBC_MSG_M24_M15) directly into out. msg_type is RTE_EXAMPLE_MSG_M24 or _M15 (common_config.h) - the caller's own decision, not recomputed here.
void ab_gp_train_build_movement_authority (uint8_t out[RBC_ENVELOPE_WIRE_SIZE], uint8_t train_id, uint32_t ma_seq, uint32_t ma_length)
 Builds and wire-encodes the outbound M3 (Movement Authority) envelope for train_id (kind=RBC_MSG_M3) directly into out (same contract as ab_gp_train_build_position_answer() above).
static void handle_envelope_p0 (ab_gp_train_session_t *session, ab_gp_train_session_t sessions[], ab_gp_db_t *db, const rbc_envelope_t *env, uint32_t cycle, rte_example_site_t site, const char *role_tag)
 RBC_MSG_P0 handler: connect a new session, or no-op (logged at DEBUG) if already in use.
static bool handle_envelope_m136 (ab_gp_train_session_t *session, ab_gp_train_session_t sessions[], ab_gp_db_t *db, const rbc_envelope_t *env, uint32_t cycle, rte_example_site_t site, const char *role_tag, uint8_t idx, uint32_t cyc_msg_type_due[], bool cyc_position_reply_due[])
 RBC_MSG_M136 handler: record position, ack with M24. Sets have_channel_data.
static void handle_envelope_m146 (ab_gp_train_session_t *session, const rbc_envelope_t *env, uint32_t cycle, rte_example_site_t site, const char *role_tag)
 RBC_MSG_M146 handler: ack the MA if the sequence number matches.
static void handle_envelope_disconnect (ab_gp_train_session_t *session, ab_gp_train_session_t sessions[], ab_gp_db_t *db, const rbc_envelope_t *env, uint32_t cycle, rte_example_site_t site, const char *role_tag)
 RBC_MSG_TRAIN_DISCONNECT handler: release every held route, then remove the train.
bool ab_gp_train_apply_envelope (ab_gp_train_session_t sessions[], ab_gp_db_t *db, const uint8_t env_bytes[RBC_ENVELOPE_WIRE_SIZE], uint32_t cycle, bool is_role_a, rte_example_site_t site, const char *role_tag, uint32_t cyc_msg_type_due[], bool cyc_position_reply_due[])
 THE single entry point com/'s ab_gp_channel.c calls for every raw envelope popped off its dedicated Train relay channel (P0/M136/M146 - see site_config.h's own rte_example_relay_kind_t doc) - wire-decodes it (this module's own train_wire_decode(), ab_gp_train.c; the old shared rbc_wire_decode() is retired, see this file's own module doc), applies it to sessions (com's own cross-compare/state-transfer table) and to db, and computes the M24/M15 decision (including the D_LRBG fault-injection scenario) for an M136. com/'s ab_gp_channel.c contains no train-specific logic of its own after this - not even train_id bounds-checking or wire decode, both of which this function does itself (same posture every other entry point in this file already takes).
uint8_t ab_gp_train_build_outputs (const ab_gp_train_session_t sessions[], const uint32_t cyc_msg_type_due[], const bool cyc_position_reply_due[], ab_gp_train_pending_output_t out[AB_GP_TRAIN_MAX_PENDING_OUTPUTS])
 Decides which trains need a Train-directed envelope THIS cycle and builds all of them - see this file's own "Outbound envelope building" doc above for the two-layer split this sits on top of. Does not send anything and does not mutate sessions - com/'s ab_gp_channel_forward_to_c_if_needed() owns actually sending each built entry (ab_gp_channel_send_envelope_to_c()) and owns clearing session->ma_pending_send once both this function and AB/GA/ctc/ab_ga_ctc.h's own ab_ga_ctc_build_outputs() have each had their own chance to read it this cycle (the flag is genuinely shared between the two - see ab_gp_channel_forward_to_c_if_needed()'s own doc for why the coordinator, not either domain, clears it).
bool ab_gp_train_session_add_granted_length (ab_gp_train_session_t sessions[], uint8_t train_id, uint32_t delta)
 Adds delta to this session's own granted_length - exposed as an accumulating setter (not a plain set) since that is the only way il/'s own ROUTE_ADD handling ever changes this field.
bool ab_gp_train_session_set_granted_length (ab_gp_train_session_t sessions[], uint8_t train_id, uint32_t granted_length)
 Sets this session's own granted_length directly.
bool ab_gp_train_session_increment_ma_seq (ab_gp_train_session_t sessions[], uint8_t train_id)
 Increments this session's own ma_seq by 1 - exposed as an accumulating setter, same rationale as ab_gp_train_session_add_granted_length() above.
bool ab_gp_train_session_set_ma_pending_send (ab_gp_train_session_t sessions[], uint8_t train_id, bool pending)
bool ab_gp_train_session_set_ma_acked (ab_gp_train_session_t sessions[], uint8_t train_id, bool acked)
bool ab_gp_train_session_set_ctc_connected_sent (ab_gp_train_session_t sessions[], uint8_t train_id, bool sent)
bool ab_gp_train_session_set_ctc_ma_granted_sent (ab_gp_train_session_t sessions[], uint8_t train_id, bool sent)
bool ab_gp_train_session_set_ctc_ma_notify_pending (ab_gp_train_session_t sessions[], uint8_t train_id, bool pending)
static void train_sessions_collector_encode (void *context, const void *items, uint8_t *out)
static void train_sessions_collector_decode (void *context, const uint8_t *in, void *out_items)
rte_status_t ab_gp_train_init (void)
 Registers this module's own ab_gp_train_session_t codec as a payload collector with com/ (AB/GP/com/ab_gp_channel_payload.h's own ab_gp_channel_payload_register_collector()) - this module is ab_gp_train_session_t's own real owner, so it is the one that provides the whole-array wire packing/unpacking ab_gp_channel_payload_encode_collector()/_decode_collector() (and, via those, ab_gp_channel_payload_encode_ab_sample()/ _decode_ab_sample()) call for its own slice - the same registration pattern already used between GA and GP, applied here between two GP submodules instead. Setup-phase only, call once from ab_gp_channel_train_codec_setup() (AB/GP/com/ab_gp_channel.c), before any cycle that might touch the peer link can run.
uint32_t ab_gp_train_payload_collector_id (void)

Variables

static ab_gp_train_context_list_t g_train_context_subscribers
static ab_gp_channel_payload_collector_id_t g_train_payload_collector_id

Detailed Description

Train lifecycle/find/getters/setters against db/'s runtime table, AND the Train-domain wire codec (train_wire_decode()/ _encode() below) - see ab_gp_train.h.

Definition in file ab_gp_train.c.

Macro Definition Documentation

◆ TRAIN_WIRE_HEADER_SIZE

#define TRAIN_WIRE_HEADER_SIZE   12U

Definition at line 170 of file ab_gp_train.c.

◆ TRAIN_WIRE_CONTENT_SIZE_BASE

#define TRAIN_WIRE_CONTENT_SIZE_BASE   24U

Definition at line 171 of file ab_gp_train.c.

◆ TRAIN_WIRE_CONTENT_SIZE_M146

#define TRAIN_WIRE_CONTENT_SIZE_M146   (TRAIN_WIRE_CONTENT_SIZE_BASE + 4U)

Definition at line 172 of file ab_gp_train.c.

◆ TRAIN_WIRE_CONTENT_SIZE_M136

#define TRAIN_WIRE_CONTENT_SIZE_M136   (TRAIN_WIRE_CONTENT_SIZE_BASE + 4U + 40U)

Definition at line 173 of file ab_gp_train.c.

Function Documentation

◆ RTE_DECLARE_CALLBACK_LIST()

RTE_DECLARE_CALLBACK_LIST ( ab_gp_train_context_list_t ,
ab_gp_train_context_notify_fn ,
AB_GP_TRAIN_MAX_CONTEXT_SUBSCRIBERS  )

◆ train_id_in_range()

bool train_id_in_range ( uint8_t train_id)
static

Defined further down this file - forward-declared here since notify_train_context() (below) needs it before its own real definition is reached.

Returns
true if train_id is a valid 1-based db->trains[] slot identity (1..RTE_EXAMPLE_MAX_TRAINS). Uses the framework's own checked bounds helper (rte_cast_bounds_check(), safeAPIFreamwork REQ-COMMON-CAST-005) against the 0-based index this 1-based ID maps to, rather than a hand-rolled comparison. REQ-RBC-005: the range check before any train_id indexes sessions[] or db->trains[] in this file; on the wire path, ab_gp_train_apply_envelope() logs and drops an out-of-range value.

Definition at line 345 of file ab_gp_train.c.

◆ ab_gp_register_train_context_notify()

rte_status_t ab_gp_register_train_context_notify ( ab_gp_train_context_notify_fn fn,
const void * context )

Definition at line 39 of file ab_gp_train.c.

◆ build_train_context()

bool build_train_context ( const ab_gp_train_session_t sessions[],
const ab_gp_db_t * db,
uint8_t train_id,
ab_gp_train_context_t * out_ctx )
static

Builds train_id's own current-state snapshot (from BOTH sessions and db - a train's real state spans both tables, see ab_gp_train_session_t's own doc). Shared by notify_train_context() (push) and the public ab_gp_get_train_context() (pull) below - one builder, two ways to reach it (later session, on direct request: "it will be enough if GA can getTrainContext/getRouteContext" - this is that pull path's own implementation).

Returns
false for an out-of-range train_id (every push call site already validated it before reaching here; the pull path validates it here).

Definition at line 73 of file ab_gp_train.c.

◆ notify_train_context()

void notify_train_context ( const ab_gp_train_session_t sessions[],
const ab_gp_db_t * db,
uint8_t train_id,
ab_gp_train_update_type_t update_type )
static

Fires train_id's own current-state snapshot (build_train_context() above) to every subscriber - the ONE notify path every train-context-changing call now goes through (was two separate notify_registered()/notify_status() helpers - collapsed on direct request, see this file's own module doc).

Definition at line 122 of file ab_gp_train.c.

◆ ab_gp_train_notify_context_changed()

void ab_gp_train_notify_context_changed ( const ab_gp_train_session_t sessions[],
const ab_gp_db_t * db,
uint8_t train_id,
ab_gp_train_update_type_t update_type )

Explicit trigger GA calls (through ga_interface.h) once it has finished a multi-step train-context change it owns the sequencing of - a route grant/release (AB/GA/il/ab_ga_il.c's own handle_route_add()/handle_route_release(), which update granted_length/ma_seq/has_ma across several separate setter calls) being the only real case today. NOT fired automatically from any individual setter - see ab_gp_train_set_has_ma()'s own doc for why firing per-setter would either see a half-updated context or fire multiple times for one logical change.

Parameters
update_typeAlways AB_TRAIN_MA_CHANGED today; the parameter exists so a future multi-step sequence (e.g. a real emergency-reaction handler) can reuse this same explicit-trigger mechanism instead of growing a new one.

Definition at line 143 of file ab_gp_train.c.

◆ ab_gp_get_train_context()

bool ab_gp_get_train_context ( const ab_gp_train_session_t sessions[],
const ab_gp_db_t * db,
uint8_t train_id,
ab_gp_train_context_t * out_ctx )

One-shot pull equivalent of the push notification above - the SAME snapshot-building logic (real impl: ab_gp_train.c's own build_train_context(), shared with notify_train_context()), for a caller that just needs train_id's current state right now rather than reacting to a change. Replaces the individual ab_gp_train_session_get_*()/ab_gp_train_get_has_ma() getters GA used to call one field at a time (later session, on direct request - "it will be enough if GA can getTrainContext / getRouteContext; setters stay separate since they require validation"). Mutation still goes through the individual setters below - this is READ-ONLY, deliberately.

Returns
false if train_id is out of range; otherwise true with *out_ctx fully populated.

Definition at line 149 of file ab_gp_train.c.

◆ train_wire_nid_message_for_kind()

uint8_t train_wire_nid_message_for_kind ( rbc_msg_kind_t kind)
static
Returns
this kind's real Subset-026 NID_MESSAGE (REQ-RBC-001 revised), or 0U for a kind with no real counterpart - see rbc_wire_types.h's own rbc_envelope_t.nid_message doc.

Definition at line 178 of file ab_gp_train.c.

◆ train_wire_content_size_for_kind()

uint16_t train_wire_content_size_for_kind ( rbc_msg_kind_t kind)
static
Returns
this kind's own content length in bytes (excludes TRAIN_WIRE_HEADER_SIZE).

Definition at line 204 of file ab_gp_train.c.

◆ train_wire_encode()

void train_wire_encode ( uint8_t out[RBC_ENVELOPE_WIRE_SIZE],
const rbc_envelope_t * env )
static

Encodes env into its RBC_ENVELOPE_WIRE_SIZE-byte MAXIMUM wire slot - see rbc_wire_types.h's own doc for the field layout this mirrors exactly. env->nid_message/l_message are calculated here from env->kind, not caller-supplied.

Definition at line 230 of file ab_gp_train.c.

◆ train_wire_decode()

bool train_wire_decode ( const uint8_t in[RBC_ENVELOPE_WIRE_SIZE],
rbc_envelope_t * out_env )
static

Decodes an RBC_ENVELOPE_WIRE_SIZE-byte wire slot - see rbc_wire_types.h's own doc.

Returns
true if l_message exactly matched what this codec expects for in's own kind byte (REQ-RBC-001 revised/REQ-RBC-002) - a mismatch is rejected outright, never decoded with only some fields trusted. A kind this file does not otherwise recognize falls to train_wire_content_size_for_kind()'s own default content size (TRAIN_WIRE_CONTENT_SIZE_BASE) here, so it is only accepted at this layer if l_message happens to match that - the real, final rejection for an unrecognized-but-l_message-matching kind is the caller's own switch (ab_gp_train_apply_envelope()), whose default: case already logs and drops it.

Definition at line 277 of file ab_gp_train.c.

◆ nid_engine_connected_elsewhere()

bool nid_engine_connected_elsewhere ( const ab_gp_db_t * db,
uint8_t nid_engine,
uint8_t exclude_train_id )
static
Returns
true if some OTHER already-connected slot (not exclude_train_id, 0 = exclude none) already carries nid_engine - the same physical train can never occupy two slots at once (ab_gp_train_add()/_set_nid_engine()'s own doc).

Definition at line 358 of file ab_gp_train.c.

◆ ab_gp_train_add()

bool ab_gp_train_add ( ab_gp_db_t * db,
uint8_t train_id,
uint8_t nid_engine )

Adds a train on connect: fills db->trains[train_id-1] with nid_engine, connected=true, has_ma=false, and an empty route_ids[]/route_count=0.

Parameters
train_id1..RTE_EXAMPLE_MAX_TRAINS.
Returns
false if train_id is out of range, that slot is already connected (call ab_gp_train_remove() first to replace it), or nid_engine is already connected in a DIFFERENT slot (the same physical train can never occupy two slots at once).

Definition at line 374 of file ab_gp_train.c.

◆ ab_gp_train_remove()

bool ab_gp_train_remove ( ab_gp_db_t * db,
uint8_t train_id )

Removes a train on disconnect: resets db->trains[train_id-1] back to its all-zero/disconnected state.

Returns
false if train_id is out of range, that slot is not connected, or it still has route_count > 0 (release every route via ab_ga_il_route_unassign_train() first, ab_ga_il.h - a train is never dropped while a route's own back-reference still points at it, same posture ab_ga_il_route_remove() already takes for used_in_ma).

Definition at line 406 of file ab_gp_train.c.

◆ ab_gp_train_find()

ab_gp_db_train_t * ab_gp_train_find ( ab_gp_db_t * db,
uint8_t train_id )

Finds a connected train's own slot for direct field access.

Parameters
train_id1..RTE_EXAMPLE_MAX_TRAINS.
Returns
pointer into db->trains[] (caller-owned storage, never free()d), or NULL if train_id is out of range or that slot is not currently connected.

Definition at line 428 of file ab_gp_train.c.

◆ ab_gp_train_find_by_nid_engine()

bool ab_gp_train_find_by_nid_engine ( const ab_gp_db_t * db,
uint8_t nid_engine,
uint8_t * out_train_id )

Reverse lookup: which train_id (if any) is nid_engine currently connected as.

Parameters
out_train_idReceives the 1-based train_id if found. Left unmodified otherwise.
Returns
true if a currently-connected train has this nid_engine.

Definition at line 441 of file ab_gp_train.c.

◆ ab_gp_train_is_connected()

bool ab_gp_train_is_connected ( const ab_gp_db_t * db,
uint8_t train_id )
Returns
true if train_id is in range AND currently connected - never "fails" the way the getters below can, always a plain yes/no.

Definition at line 459 of file ab_gp_train.c.

◆ ab_gp_train_get_nid_engine()

bool ab_gp_train_get_nid_engine ( const ab_gp_db_t * db,
uint8_t train_id,
uint8_t * out_nid_engine )
Returns
false if train_id is out of range or not connected; otherwise true with *out_nid_engine set.

Definition at line 468 of file ab_gp_train.c.

◆ ab_gp_train_get_route_count()

bool ab_gp_train_get_route_count ( const ab_gp_db_t * db,
uint8_t train_id,
uint8_t * out_route_count )
Returns
false if train_id is out of range or not connected; otherwise true with *out_route_count set (read-only view of il/'s own bookkeeping - see this file's own module doc).

Definition at line 478 of file ab_gp_train.c.

◆ ab_gp_train_set_nid_engine()

bool ab_gp_train_set_nid_engine ( ab_gp_db_t * db,
uint8_t train_id,
uint8_t nid_engine )
Returns
false if train_id is out of range, not connected, or nid_engine is already connected in a different slot; otherwise true with the field updated.

Definition at line 488 of file ab_gp_train.c.

◆ ab_gp_train_set_has_ma()

bool ab_gp_train_set_has_ma ( ab_gp_db_t * db,
uint8_t train_id,
bool has_ma )

Definition at line 502 of file ab_gp_train.c.

◆ ab_gp_train_get_last_position()

bool ab_gp_train_get_last_position ( const ab_gp_db_t * db,
uint8_t train_id,
uint32_t * out_nid_lrbg )

Definition at line 522 of file ab_gp_train.c.

◆ ab_gp_train_set_last_position()

bool ab_gp_train_set_last_position ( ab_gp_db_t * db,
uint8_t train_id,
uint32_t nid_lrbg )

Records this train's own most recently reported NID_LRBG - the write side of the field logic/'s own cyclic route-connect sweep reads (ab_gp_logic.h).

Returns
false if train_id is out of range or not connected; otherwise true with the field updated.

Definition at line 532 of file ab_gp_train.c.

◆ ab_gp_train_handle_connect()

bool ab_gp_train_handle_connect ( ab_gp_db_t * db,
uint8_t train_id )

Handles an inbound P0 (connect handshake) - wraps ab_gp_train_add() with the same env->train_id-as-nid_engine stand-in caveat as that function's own doc. Idempotent (safe to call again for an already-connected train_id - just returns false, changes nothing, same as ab_gp_train_add() itself).

Definition at line 542 of file ab_gp_train.c.

◆ ab_gp_train_handle_position_report()

bool ab_gp_train_handle_position_report ( ab_gp_db_t * db,
uint8_t train_id,
uint32_t nid_lrbg )

Handles an inbound M136 (Position Report) - adds the train first (ab_gp_train_handle_connect()) if this is the first data seen for it (tolerates M136 arriving before/without a P0, same lenient posture com's own ctx->sessions[] handling takes), then records nid_lrbg via ab_gp_train_set_last_position() if it is nonzero (0 = no real balise reported this cycle, ab_gp_db.h's own sentinel - left unchanged rather than overwritten with "none").

Definition at line 547 of file ab_gp_train.c.

◆ ab_gp_train_build_position_answer()

void ab_gp_train_build_position_answer ( uint8_t out[RBC_ENVELOPE_WIRE_SIZE],
uint8_t train_id,
uint32_t cycle,
uint32_t d_lrbg,
uint32_t msg_type )

Builds and wire-encodes the outbound M24/M15 Position Report answer for train_id (kind=RBC_MSG_M24_M15) directly into out. msg_type is RTE_EXAMPLE_MSG_M24 or _M15 (common_config.h) - the caller's own decision, not recomputed here.

Parameters
outDestination, exactly RBC_ENVELOPE_WIRE_SIZE bytes. Must not be NULL.

Definition at line 560 of file ab_gp_train.c.

◆ ab_gp_train_build_movement_authority()

void ab_gp_train_build_movement_authority ( uint8_t out[RBC_ENVELOPE_WIRE_SIZE],
uint8_t train_id,
uint32_t ma_seq,
uint32_t ma_length )

Builds and wire-encodes the outbound M3 (Movement Authority) envelope for train_id (kind=RBC_MSG_M3) directly into out (same contract as ab_gp_train_build_position_answer() above).

Definition at line 574 of file ab_gp_train.c.

◆ handle_envelope_p0()

void handle_envelope_p0 ( ab_gp_train_session_t * session,
ab_gp_train_session_t sessions[],
ab_gp_db_t * db,
const rbc_envelope_t * env,
uint32_t cycle,
rte_example_site_t site,
const char * role_tag )
static

RBC_MSG_P0 handler: connect a new session, or no-op (logged at DEBUG) if already in use.

Definition at line 588 of file ab_gp_train.c.

◆ handle_envelope_m136()

bool handle_envelope_m136 ( ab_gp_train_session_t * session,
ab_gp_train_session_t sessions[],
ab_gp_db_t * db,
const rbc_envelope_t * env,
uint32_t cycle,
rte_example_site_t site,
const char * role_tag,
uint8_t idx,
uint32_t cyc_msg_type_due[],
bool cyc_position_reply_due[] )
static

RBC_MSG_M136 handler: record position, ack with M24. Sets have_channel_data.

Returns
true (this envelope kind always counts as fresh channel data).

Definition at line 625 of file ab_gp_train.c.

◆ handle_envelope_m146()

void handle_envelope_m146 ( ab_gp_train_session_t * session,
const rbc_envelope_t * env,
uint32_t cycle,
rte_example_site_t site,
const char * role_tag )
static

RBC_MSG_M146 handler: ack the MA if the sequence number matches.

Definition at line 695 of file ab_gp_train.c.

◆ handle_envelope_disconnect()

void handle_envelope_disconnect ( ab_gp_train_session_t * session,
ab_gp_train_session_t sessions[],
ab_gp_db_t * db,
const rbc_envelope_t * env,
uint32_t cycle,
rte_example_site_t site,
const char * role_tag )
static

RBC_MSG_TRAIN_DISCONNECT handler: release every held route, then remove the train.

Definition at line 707 of file ab_gp_train.c.

◆ ab_gp_train_apply_envelope()

bool ab_gp_train_apply_envelope ( ab_gp_train_session_t sessions[],
ab_gp_db_t * db,
const uint8_t env_bytes[RBC_ENVELOPE_WIRE_SIZE],
uint32_t cycle,
bool is_role_a,
rte_example_site_t site,
const char * role_tag,
uint32_t cyc_msg_type_due[],
bool cyc_position_reply_due[] )

THE single entry point com/'s ab_gp_channel.c calls for every raw envelope popped off its dedicated Train relay channel (P0/M136/M146 - see site_config.h's own rte_example_relay_kind_t doc) - wire-decodes it (this module's own train_wire_decode(), ab_gp_train.c; the old shared rbc_wire_decode() is retired, see this file's own module doc), applies it to sessions (com's own cross-compare/state-transfer table) and to db, and computes the M24/M15 decision (including the D_LRBG fault-injection scenario) for an M136. com/'s ab_gp_channel.c contains no train-specific logic of its own after this - not even train_id bounds-checking or wire decode, both of which this function does itself (same posture every other entry point in this file already takes).

Parameters
sessionscom's own ab_gp_train_session_t table (RTE_EXAMPLE_MAX_TRAINS entries) - mutated in place.
dbAB's own Train/Route database - mutated in place via this file's own ab_gp_train_handle_connect()/ _handle_position_report().
channel_indexWhich Train[index] relay channel this envelope arrived on (0-based) - purely a defensive diagnostic cross-check against the decoded env.train_id (logged, not fatal, on a mismatch): routing itself is already fully structural (this IS the Train channel, by construction of the caller's own per-instance queue drain), so a mismatch here means a misconfigured sim/wrong port, not a misrouted envelope.
env_bytesRaw wire bytes, exactly RBC_ENVELOPE_WIRE_SIZE - not yet decoded.
cycleThis AB cycle's own number (logging only).
is_role_aWhether this channel is role A - only the M136 D_LRBG fault-injection scenario needs this.
siteThis channel's own site (logging only).
role_tagThis channel's own "A/WEST" etc. tag (logging only).
cyc_msg_type_duePer-train scratch array (RTE_EXAMPLE_MAX_TRAINS entries) - set for this envelope's own train_id if it was an M136 (the computed M24/M15 answer); left unmodified otherwise.
cyc_position_reply_duePer-train scratch array, same size - set true alongside cyc_msg_type_due for an M136; left unmodified otherwise.
Returns
true if this envelope produced fresh channel data worth cross-comparing this cycle (an M136); false otherwise (including a malformed frame, an out-of-range train_id, or an unrecognized/foreign kind - all logged and dropped).

Definition at line 749 of file ab_gp_train.c.

◆ ab_gp_train_build_outputs()

uint8_t ab_gp_train_build_outputs ( const ab_gp_train_session_t sessions[],
const uint32_t cyc_msg_type_due[],
const bool cyc_position_reply_due[],
ab_gp_train_pending_output_t out[AB_GP_TRAIN_MAX_PENDING_OUTPUTS] )

Decides which trains need a Train-directed envelope THIS cycle and builds all of them - see this file's own "Outbound envelope building" doc above for the two-layer split this sits on top of. Does not send anything and does not mutate sessions - com/'s ab_gp_channel_forward_to_c_if_needed() owns actually sending each built entry (ab_gp_channel_send_envelope_to_c()) and owns clearing session->ma_pending_send once both this function and AB/GA/ctc/ab_ga_ctc.h's own ab_ga_ctc_build_outputs() have each had their own chance to read it this cycle (the flag is genuinely shared between the two - see ab_gp_channel_forward_to_c_if_needed()'s own doc for why the coordinator, not either domain, clears it).

Parameters
sessionscom's own ab_gp_train_session_t table (RTE_EXAMPLE_MAX_TRAINS entries) - read-only.
cyc_msg_type_dueThis cycle's own per-train scratch array (ab_gp_channel_read_channels()'s own output) - RTE_EXAMPLE_MSG_M24/_M15 per train with cyc_position_reply_due true.
cyc_position_reply_dueThis cycle's own per-train scratch array - true if that train had a fresh M136 this cycle.
outDestination array, AB_GP_TRAIN_MAX_PENDING_OUTPUTS entries. Must not be NULL.
Returns
the number of entries actually filled in out (0..AB_GP_TRAIN_MAX_PENDING_OUTPUTS).

Definition at line 809 of file ab_gp_train.c.

◆ ab_gp_train_session_add_granted_length()

bool ab_gp_train_session_add_granted_length ( ab_gp_train_session_t sessions[],
uint8_t train_id,
uint32_t delta )

Adds delta to this session's own granted_length - exposed as an accumulating setter (not a plain set) since that is the only way il/'s own ROUTE_ADD handling ever changes this field.

Returns
false if train_id is out of range; otherwise true.

Definition at line 848 of file ab_gp_train.c.

◆ ab_gp_train_session_set_granted_length()

bool ab_gp_train_session_set_granted_length ( ab_gp_train_session_t sessions[],
uint8_t train_id,
uint32_t granted_length )

Sets this session's own granted_length directly.

Returns
false if train_id is out of range; otherwise true.

Definition at line 858 of file ab_gp_train.c.

◆ ab_gp_train_session_increment_ma_seq()

bool ab_gp_train_session_increment_ma_seq ( ab_gp_train_session_t sessions[],
uint8_t train_id )

Increments this session's own ma_seq by 1 - exposed as an accumulating setter, same rationale as ab_gp_train_session_add_granted_length() above.

Returns
false if train_id is out of range; otherwise true.

Definition at line 870 of file ab_gp_train.c.

◆ ab_gp_train_session_set_ma_pending_send()

bool ab_gp_train_session_set_ma_pending_send ( ab_gp_train_session_t sessions[],
uint8_t train_id,
bool pending )
Returns
false if train_id is out of range; otherwise true with the field updated.

Definition at line 882 of file ab_gp_train.c.

◆ ab_gp_train_session_set_ma_acked()

bool ab_gp_train_session_set_ma_acked ( ab_gp_train_session_t sessions[],
uint8_t train_id,
bool acked )
Returns
false if train_id is out of range; otherwise true with the field updated.

Definition at line 892 of file ab_gp_train.c.

◆ ab_gp_train_session_set_ctc_connected_sent()

bool ab_gp_train_session_set_ctc_connected_sent ( ab_gp_train_session_t sessions[],
uint8_t train_id,
bool sent )
Returns
false if train_id is out of range; otherwise true with the field updated.

Definition at line 905 of file ab_gp_train.c.

◆ ab_gp_train_session_set_ctc_ma_granted_sent()

bool ab_gp_train_session_set_ctc_ma_granted_sent ( ab_gp_train_session_t sessions[],
uint8_t train_id,
bool sent )
Returns
false if train_id is out of range; otherwise true with the field updated.

Definition at line 917 of file ab_gp_train.c.

◆ ab_gp_train_session_set_ctc_ma_notify_pending()

bool ab_gp_train_session_set_ctc_ma_notify_pending ( ab_gp_train_session_t sessions[],
uint8_t train_id,
bool pending )
Returns
false if train_id is out of range; otherwise true with the field updated - see ab_gp_train_session_t's own doc on why this is a SEPARATE flag from ma_pending_send.

Definition at line 934 of file ab_gp_train.c.

◆ train_sessions_collector_encode()

void train_sessions_collector_encode ( void * context,
const void * items,
uint8_t * out )
static

This module's own registered payload-collector encoder (see ab_gp_train_init()) - packs every RTE_EXAMPLE_MAX_TRAINS ab_gp_train_session_t into its own slice of the combined A<->B payload, RTE_EXAMPLE_TRAIN_SESSION_WIRE_SIZE bytes per session; the loop and field layout are entirely this module's own concern - AB/GP/com/ab_gp_channel_payload.c never sees a ab_gp_train_session_t. context is unused (always NULL, see ab_gp_train_init()).

Definition at line 951 of file ab_gp_train.c.

◆ train_sessions_collector_decode()

void train_sessions_collector_decode ( void * context,
const uint8_t * in,
void * out_items )
static

This module's own registered payload-collector decoder (see ab_gp_train_init()) - see train_sessions_collector_encode()'s own doc. ma_pending_send is deliberately left false (not on the wire) - see ab_gp_train_session_t's own doc. On a malformed/short slot (should never happen - each slot is always exactly RTE_EXAMPLE_TRAIN_SESSION_WIRE_SIZE bytes here), that session's fields are left at their all-zero/false state, same fail-safe posture ab_gp_channel_payload_decode_ab_sample()'s own overall contract takes.

Definition at line 983 of file ab_gp_train.c.

◆ ab_gp_train_init()

rte_status_t ab_gp_train_init ( void )

Registers this module's own ab_gp_train_session_t codec as a payload collector with com/ (AB/GP/com/ab_gp_channel_payload.h's own ab_gp_channel_payload_register_collector()) - this module is ab_gp_train_session_t's own real owner, so it is the one that provides the whole-array wire packing/unpacking ab_gp_channel_payload_encode_collector()/_decode_collector() (and, via those, ab_gp_channel_payload_encode_ab_sample()/ _decode_ab_sample()) call for its own slice - the same registration pattern already used between GA and GP, applied here between two GP submodules instead. Setup-phase only, call once from ab_gp_channel_train_codec_setup() (AB/GP/com/ab_gp_channel.c), before any cycle that might touch the peer link can run.

Returns
RTE_STATUS_OK on success; whatever ab_gp_channel_payload_register_collector() itself returned on failure.

Definition at line 1025 of file ab_gp_train.c.

◆ ab_gp_train_payload_collector_id()

uint32_t ab_gp_train_payload_collector_id ( void )
Returns
This module's own registered payload-collector id (see ab_gp_train_init() above) - pass as the index into ab_gp_channel_payload_encode_collector()/_decode_collector() and ab_gp_channel_payload_encode_ab_sample()'s/_decode_ab_sample()'s own sources/dests arrays (AB/GP/com/ab_gp_channel_payload.h). Only meaningful after ab_gp_train_init() has run.

Definition at line 1032 of file ab_gp_train.c.

Variable Documentation

◆ g_train_context_subscribers

ab_gp_train_context_list_t g_train_context_subscribers
static

Definition at line 37 of file ab_gp_train.c.

◆ g_train_payload_collector_id

ab_gp_channel_payload_collector_id_t g_train_payload_collector_id
static

Definition at line 1023 of file ab_gp_train.c.