|
RTE RBC 2oo2 Reference Application 0.1.0 build 0006685
SIL 4 2oo2 Dual-Site Fault-Tolerant ERTMS Radio Block Centre Reference Architecture
|
A/B's own train lifecycle handling against db/'s runtime table. More...
#include <stdbool.h>#include <stdint.h>#include "rte/utils/status/rte_status.h"#include "../../common/common_config.h"#include "../../common/rbc_wire_types.h"#include "../../common/site_config.h"#include "../db/ab_gp_db.h"Go to the source code of this file.
Data Structures | |
| struct | ab_gp_train_session_t |
| struct | ab_gp_train_context_t |
| struct | ab_gp_train_pending_output_t |
Macros | |
| #define | TRAIN_SESSION_T_DEFINED |
| One connected train's live session - fundamentally train state, not transport state, even though com/'s ab_gp_channel_crosscompare.c/ab_gp_channel_negotiate.c read/wire-encode it (via this module's own registered payload collector - see ab_gp_train_init() below - and its own field-by-field getters/ setters for the direct comparisons crosscompare.c makes). Owned entirely by A/B (the vital 2-channel-voting decision-maker); C is a pure relay with no session state of its own (monitor_c_types.h). Fixed-size array (RTE_EXAMPLE_MAX_TRAINS entries, common_config.h), never a dynamic list (CLAUDE.md: no malloc/free/realloc). | |
| #define | RTE_EXAMPLE_TRAIN_SESSION_WIRE_SIZE 19U |
Functions | |
| 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) |
| 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_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). | |
Inbound envelope handling | |
com/'s own ab_gp_channel.c is now a thin receive-and-dispatch layer (ab_gp_channel_apply_inbound_envelope()): once it has decoded an inbound rbc_envelope_t and applied it to its OWN cross-compare-relevant ctx->sessions[] state (ab_gp_train_session_t, ab_gp_channel_types.h - stays in com/, unaffected by this module), it hands the fields this module actually needs off to the functions below rather than touching db->trains[] itself. Every field is a plain, already-decoded value (train_id, nid_lrbg) - these functions never see raw wire bytes. | |
| 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"). | |
ab_gp_train_session_t getters/setters (the encapsulation boundary for GA) | |
Every ab_gp_train_session_t field AB/GA/il/ab_ga_il.c's and AB/GA/ctc/ab_ga_ctc.c's own code used to touch directly (before this session's own GA/GP opacity pass) now has its own accessor here, all keyed by (sessions, train_id) rather than a live ab_gp_train_session_t * (no pointer into the table itself ever crosses into GA - see AB/GP/db/ ab_gp_db.h's own identical rationale for its route getters/setters). sessions is still ab_gp_train_session_t * here, not something more opaque, because GA's own ab_ga_il_apply_envelope()/ab_ga_ctc_build_outputs() signatures already receive this same array by pointer from com/'s ab_gp_channel.c and must keep passing that exact pointer through unmodified (ab_gp_train_session_t's own storage is com-owned, ab_gp_channel_types.h) - GA never dereferences it itself, only forwards it into these functions. | |
| 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_get_ma_seq (const ab_gp_train_session_t sessions[], uint8_t train_id, uint32_t *out_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. | |
| 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) |
GA notification - train/'s own single GP->GA hook | |
train/ is the module that actually mutates db->trains[]/sessions[] (a train's own connected/has_ma/position status), so train/ is the module that notifies about it - same "whichever GP module performs a mutation is the one that fires the matching notify" rule AB/GP/db/ab_gp_db.h's own route hook follows too. ONE subscription (ab_gp_register_train_context_notify() below) covers every train change - collapsed from two registrations on direct instruction, same rationale as the route side's own collapse (ab_gp_db.h). Fan-out, fail-open (zero subscribers is fine). Setup-phase only (rte_lifecycle_check_setup_allowed()) - GA's own single dispatch module (RBC_GA/src/AB/main/ab_ga_dispatch.c) is the ONLY registrant, called once from its own _init(), itself called once from ab_gp_channel_train_codec_setup() (AB/GP/com/ab_gp_channel.c). | |
| #define | AB_GP_TRAIN_UPDATE_TYPE_T_DEFINED |
| What kind of change a single ab_gp_train_context_notify_fn call is reporting. | |
| #define | AB_GP_TRAIN_CONTEXT_T_DEFINED |
| A flat, fully-visible (NOT opaque, unlike ab_gp_train_session_t itself) snapshot of one train's current state - what ab_gp_train_context_notify_fn hands its subscriber. A copy, not a live pointer into sessions[]/db->trains[] - GA reads real struct fields directly (no getter calls needed for the common case), while still never touching GP's actual internal storage. | |
| #define | AB_GP_TRAIN_NOTIFY_FN_DEFINED |
| #define | AB_GP_TRAIN_MAX_CONTEXT_SUBSCRIBERS 4U |
| enum | ab_gp_train_update_type_t { AB_TRAIN_REGISTERED , AB_TRAIN_REMOVED , AB_TRAIN_POSITION , AB_TRAIN_MA_CHANGED , AB_TRAIN_EMERGENCY_REACTION_RAISED } |
| rte_status_t | ab_gp_register_train_context_notify (ab_gp_train_context_notify_fn fn, const void *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. | |
| 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. | |
Outbound envelope building | |
The other direction of the same split. Two layers:
| |
| #define | AB_GP_TRAIN_MAX_PENDING_OUTPUTS ((uint8_t)(RTE_EXAMPLE_MAX_TRAINS * 2U)) |
| 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). | |
| 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). | |
A/B's own train lifecycle handling against db/'s runtime table.
"train_id" throughout this file is the 1..RTE_EXAMPLE_MAX_TRAINS connection-slot identity (same convention ab_gp_train_session_t.train_id and il/'s ab_ga_il_route_assign_train() already use, ab_ga_il.h) - it is the array position in db->trains[]/sessions[], not ab_gp_db_train_t's own nid_engine (the real Subset-026 identity, a plain data field, not an index). ab_gp_train_find_by_nid_engine() below is the bridge from one to the other.
route_ids[]/route_count are deliberately NOT settable here - those are il/'s own responsibility (ab_ga_il_route_assign_train()/ _unassign_train(), ab_ga_il.h), the only code that keeps a train's own route list and each route's own back-reference consistent with each other. This module only reads them (ab_gp_train_get_route_count()).
Every function takes the caller-owned ab_gp_db_t/ab_gp_train_session_t[] explicitly (same "caller-owned storage, no hidden state" convention as ab_gp_channel_context_t/ab_ga_il.h) - this module holds no state of its own.
Definition in file ab_gp_train.h.
| #define TRAIN_SESSION_T_DEFINED |
One connected train's live session - fundamentally train state, not transport state, even though com/'s ab_gp_channel_crosscompare.c/ab_gp_channel_negotiate.c read/wire-encode it (via this module's own registered payload collector - see ab_gp_train_init() below - and its own field-by-field getters/ setters for the direct comparisons crosscompare.c makes). Owned entirely by A/B (the vital 2-channel-voting decision-maker); C is a pure relay with no session state of its own (monitor_c_types.h). Fixed-size array (RTE_EXAMPLE_MAX_TRAINS entries, common_config.h), never a dynamic list (CLAUDE.md: no malloc/free/realloc).
Cross-site continuity (REQ-RBC-006, Platform_RTE/docs/requirements/ SRS.dox): this whole table is what ab_gp_channel_negotiate.c's apply_state_transfer() carries across a STANDBY->ONLINE promotion (superseding the old single-scalar {cycle, dlrbg, decision} snapshot) - a promoted site must already know every connected train's granted MA length/sequence before the client even notices anything happened, not just the position/decision of one implicit train.
Cross-compare (REQ-RBC-007): the wire-relevant fields below (everything except ma_pending_send, a pure local "have I sent M3 yet this cycle" scratch flag with no cross-compare meaning) are what ab_gp_channel_crosscompare.c's xcompare_recv_local()/_peer() now compare, widened from the old single uint32_t M24/M15 decision.
Definition at line 78 of file ab_gp_train.h.
| #define RTE_EXAMPLE_TRAIN_SESSION_WIRE_SIZE 19U |
One encoded ab_gp_train_session_t's wire size: in_use(1) + train_id(1) + cycle(4) + d_lrbg(4) + granted_length(4) + ma_seq(4) + ma_acked(1) = 19 bytes, little-endian - see ab_gp_train.c's own registered payload collector (ab_gp_train_init() below), shared by both the AB_SAMPLE cross-compare payload and ab_gp_channel_negotiate.c's own extra DATA payload (RTE_EXAMPLE_SITE_EXTRA_PAYLOAD_SESSION_SIZE, common_config.h - must stay equal to this constant; a compile-time check enforces it, see ab_gp_channel_negotiate.c). ma_pending_send is deliberately NOT included - see ab_gp_train_session_t's own doc.
Definition at line 171 of file ab_gp_train.h.
| #define AB_GP_TRAIN_UPDATE_TYPE_T_DEFINED |
What kind of change a single ab_gp_train_context_notify_fn call is reporting.
Definition at line 222 of file ab_gp_train.h.
| #define AB_GP_TRAIN_CONTEXT_T_DEFINED |
A flat, fully-visible (NOT opaque, unlike ab_gp_train_session_t itself) snapshot of one train's current state - what ab_gp_train_context_notify_fn hands its subscriber. A copy, not a live pointer into sessions[]/db->trains[] - GA reads real struct fields directly (no getter calls needed for the common case), while still never touching GP's actual internal storage.
Definition at line 249 of file ab_gp_train.h.
| #define AB_GP_TRAIN_NOTIFY_FN_DEFINED |
Definition at line 280 of file ab_gp_train.h.
| #define AB_GP_TRAIN_MAX_CONTEXT_SUBSCRIBERS 4U |
One subscriber (GA's own dispatch module) with headroom to spare.
Definition at line 286 of file ab_gp_train.h.
| #define AB_GP_TRAIN_MAX_PENDING_OUTPUTS ((uint8_t)(RTE_EXAMPLE_MAX_TRAINS * 2U)) |
Worst case one cycle can ever produce: every train (RTE_EXAMPLE_MAX_TRAINS) with both an M24/M15 AND a pending M3 due in the same cycle.
Definition at line 495 of file ab_gp_train.h.
| Enumerator | |
|---|---|
| AB_TRAIN_REGISTERED | ab_gp_train_add() just registered this train. |
| AB_TRAIN_REMOVED | ab_gp_train_remove() just removed this train - ctx reflects its now-cleared state (in_use=false). |
| AB_TRAIN_POSITION | A fresh M136 just updated cycle/d_lrbg/nid_lrbg/ v_train/m_mode (ab_gp_train_apply_envelope()'s own RBC_MSG_M136 case). |
| AB_TRAIN_MA_CHANGED | granted_length/ma_seq/has_ma just changed (a ROUTE_ADD/_RELEASE-driven grant, flat or ERTMS). |
| AB_TRAIN_EMERGENCY_REACTION_RAISED | Reserved for a future emergency-stop reaction - no real firing site yet (this codebase's own emergency-stop handling is still scaffolding, see root CLAUDE.md's ERTMS notes) - included now so the enum doesn't need another interface-shape change once it is wired up. |
Definition at line 223 of file ab_gp_train.h.
| 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.
Definition at line 1025 of file ab_gp_train.c.
| uint32_t ab_gp_train_payload_collector_id | ( | void | ) |
Definition at line 1032 of file ab_gp_train.c.
| rte_status_t ab_gp_register_train_context_notify | ( | ab_gp_train_context_notify_fn | fn, |
| const void * | context ) |
fn is NULL; RTE_STATUS_INVALID_STATE if the setup phase is already locked; RTE_STATUS_RESOURCE_EXHAUSTED if AB_GP_TRAIN_MAX_CONTEXT_SUBSCRIBERS are already registered. Definition at line 39 of file ab_gp_train.c.
| 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.
Definition at line 149 of file ab_gp_train.c.
| 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.
| update_type | Always 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.
| 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.
| train_id | 1..RTE_EXAMPLE_MAX_TRAINS. |
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.
| 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.
Definition at line 406 of file ab_gp_train.c.
| 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.
| train_id | 1..RTE_EXAMPLE_MAX_TRAINS. |
Definition at line 428 of file ab_gp_train.c.
| 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.
| out_train_id | Receives the 1-based train_id if found. Left unmodified otherwise. |
Definition at line 441 of file ab_gp_train.c.
| bool ab_gp_train_is_connected | ( | const ab_gp_db_t * | db, |
| uint8_t | train_id ) |
Definition at line 459 of file ab_gp_train.c.
| bool ab_gp_train_get_nid_engine | ( | const ab_gp_db_t * | db, |
| uint8_t | train_id, | ||
| uint8_t * | out_nid_engine ) |
Definition at line 468 of file ab_gp_train.c.
| bool ab_gp_train_get_route_count | ( | const ab_gp_db_t * | db, |
| uint8_t | train_id, | ||
| uint8_t * | out_route_count ) |
Definition at line 478 of file ab_gp_train.c.
| bool ab_gp_train_set_nid_engine | ( | ab_gp_db_t * | db, |
| uint8_t | train_id, | ||
| uint8_t | nid_engine ) |
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.
| 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.
| 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.
| 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).
Definition at line 532 of file ab_gp_train.c.
| 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.
| 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.
| 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.
| out | Destination, exactly RBC_ENVELOPE_WIRE_SIZE bytes. Must not be NULL. |
Definition at line 560 of file ab_gp_train.c.
| 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.
| 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).
| sessions | com's own ab_gp_train_session_t table (RTE_EXAMPLE_MAX_TRAINS entries) - read-only. |
| cyc_msg_type_due | This 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_due | This cycle's own per-train scratch array - true if that train had a fresh M136 this cycle. |
| out | Destination array, AB_GP_TRAIN_MAX_PENDING_OUTPUTS entries. Must not be NULL. |
out (0..AB_GP_TRAIN_MAX_PENDING_OUTPUTS). Definition at line 809 of file ab_gp_train.c.
| 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).
| sessions | com's own ab_gp_train_session_t table (RTE_EXAMPLE_MAX_TRAINS entries) - mutated in place. |
| db | AB's own Train/Route database - mutated in place via this file's own ab_gp_train_handle_connect()/ _handle_position_report(). |
| channel_index | Which 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_bytes | Raw wire bytes, exactly RBC_ENVELOPE_WIRE_SIZE - not yet decoded. |
| cycle | This AB cycle's own number (logging only). |
| is_role_a | Whether this channel is role A - only the M136 D_LRBG fault-injection scenario needs this. |
| site | This channel's own site (logging only). |
| role_tag | This channel's own "A/WEST" etc. tag (logging only). |
| cyc_msg_type_due | Per-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_due | Per-train scratch array, same size - set true alongside cyc_msg_type_due for an M136; left unmodified otherwise. |
Definition at line 749 of file ab_gp_train.c.
| 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.
train_id is out of range; otherwise true. Definition at line 848 of file ab_gp_train.c.
| 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.
train_id is out of range; otherwise true. Definition at line 858 of file ab_gp_train.c.
| bool ab_gp_train_session_get_ma_seq | ( | const ab_gp_train_session_t | sessions[], |
| uint8_t | train_id, | ||
| uint32_t * | out_ma_seq ) |
train_id is out of range; otherwise true with *out_ma_seq set. | 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.
train_id is out of range; otherwise true. Definition at line 870 of file ab_gp_train.c.
| bool ab_gp_train_session_set_ma_pending_send | ( | ab_gp_train_session_t | sessions[], |
| uint8_t | train_id, | ||
| bool | pending ) |
train_id is out of range; otherwise true with the field updated. Definition at line 882 of file ab_gp_train.c.
| bool ab_gp_train_session_set_ma_acked | ( | ab_gp_train_session_t | sessions[], |
| uint8_t | train_id, | ||
| bool | acked ) |
train_id is out of range; otherwise true with the field updated. Definition at line 892 of file ab_gp_train.c.
| bool ab_gp_train_session_set_ctc_connected_sent | ( | ab_gp_train_session_t | sessions[], |
| uint8_t | train_id, | ||
| bool | sent ) |
train_id is out of range; otherwise true with the field updated. Definition at line 905 of file ab_gp_train.c.
| bool ab_gp_train_session_set_ctc_ma_granted_sent | ( | ab_gp_train_session_t | sessions[], |
| uint8_t | train_id, | ||
| bool | sent ) |
train_id is out of range; otherwise true with the field updated. Definition at line 917 of file ab_gp_train.c.
| bool ab_gp_train_session_set_ctc_ma_notify_pending | ( | ab_gp_train_session_t | sessions[], |
| uint8_t | train_id, | ||
| bool | pending ) |
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.