9#include "safeapi/utils/buffer/sapi_buffer.h"
10#include "safeapi/oal/memory/sapi_mem_util.h"
12#include "common_config.h"
14#include "ga_interface.h"
28#define CTC_WIRE_HEADER_SIZE 12U
29#define CTC_WIRE_CONTENT_SIZE_BASE 24U
62static ab_gp_train_context_t g_last_train_ctx[SAFEAPI_EXAMPLE_MAX_TRAINS];
72static void ctc_wire_encode(uint8_t out[RBC_ENVELOPE_WIRE_SIZE],
const rbc_envelope_t *env);
83 uint8_t route_count, uint32_t d_lrbg, uint16_t *out_front_signal,
84 uint32_t *out_dist_to_front, uint16_t *out_target_signal);
96 sapi_mem_set(&env, 0,
sizeof(env));
97 env.kind = RBC_MSG_CTC_CONNECTED;
98 env.train_id = train_id;
108 sapi_mem_set(&env, 0,
sizeof(env));
109 env.kind = RBC_MSG_CTC_MA_GRANTED;
110 env.train_id = train_id;
112 env.ma_length = ma_length;
121 sapi_mem_set(&env, 0,
sizeof(env));
122 env.kind = RBC_MSG_CTC_MA_EXTENDED;
123 env.train_id = train_id;
125 env.ma_length = ma_length;
133 uint32_t ma_seq, uint32_t granted_length,
bool ma_granted,
134 uint16_t front_signal, uint32_t dist_to_front_signal, uint16_t target_signal,
135 uint32_t nid_lrbg, uint32_t v_train, uint32_t m_mode)
140 sapi_mem_set(&env, 0,
sizeof(env));
141 env.kind = RBC_MSG_CTC_TRAIN_INFO;
142 env.train_id = train_id;
145 env.msg_type = ma_granted ? 1U : 0U;
147 env.route_len = (uint32_t)target_signal;
149 env.t_train = (uint32_t)front_signal;
151 env.cycle = dist_to_front_signal;
153 ma_offset = (int32_t)d_lrbg - (int32_t)granted_length;
158 env.ma_length = (uint32_t)ma_offset;
160 env.nid_lrbg = nid_lrbg;
164 env.v_train = v_train;
170 ab_gp_ctc_pending_output_t out[AB_GP_CTC_MAX_PENDING_OUTPUTS])
175 for (i = 0U; i < (uint8_t)SAFEAPI_EXAMPLE_MAX_TRAINS; i++)
177 uint8_t train_id = (uint8_t)(i + 1U);
183 ab_gp_train_context_t tctx;
185 (void)ab_gp_get_train_context(sessions, db, train_id, &tctx);
197 if (tctx.in_use && !tctx.ctc_ma_granted_sent)
200 sapi_mem_copy(out[count].tag,
"CTC_CONNECTED",
sizeof(
"CTC_CONNECTED"));
202 (void)ab_gp_train_session_set_ctc_connected_sent(sessions, train_id,
true);
212 if (tctx.ma_pending_send || tctx.ctc_ma_notify_pending)
214 if (!tctx.ctc_ma_granted_sent)
217 sapi_mem_copy(out[count].tag,
"CTC_MA_GRANTED",
sizeof(
"CTC_MA_GRANTED"));
218 (void)ab_gp_train_session_set_ctc_ma_granted_sent(sessions, train_id,
true);
223 sapi_mem_copy(out[count].tag,
"CTC_MA_EXTENDED",
sizeof(
"CTC_MA_EXTENDED"));
228 AB_GA_CHECKPOINT_MARK();
242 const ab_gp_train_context_t *ctx = &g_last_train_ctx[i];
243 uint16_t front_signal = 0U;
244 uint32_t dist_to_front = 0U;
245 uint16_t target_signal = 0U;
246 bool ma_granted = ctx->has_ma;
251 ma_granted, front_signal, dist_to_front, target_signal, ctx->nid_lrbg,
252 ctx->v_train, ctx->m_mode);
253 sapi_mem_copy(out[count].tag,
"CTC_TRAIN_INFO",
sizeof(
"CTC_TRAIN_INFO"));
270 if (update_type != AB_ROUTE_CONNECTED)
274 SAFEAPI_EXAMPLE_LOG(
"[%s] CTC notified: route %u connected to train %u\n",
g_ga_role_tag,
275 (
unsigned int)ctx->id, (
unsigned int)ctx->train_id);
282 bool nid_lrbg_changed;
283 bool v_train_changed;
285 bool granted_length_changed;
290 if ((ctx->train_id == 0U) || (ctx->train_id > (uint8_t)SAFEAPI_EXAMPLE_MAX_TRAINS))
294 idx = ctx->train_id - 1U;
314 g_last_train_ctx[idx] = *ctx;
320 d_lrbg_changed = (ctx->d_lrbg != g_last_train_ctx[idx].d_lrbg);
321 nid_lrbg_changed = (ctx->nid_lrbg != g_last_train_ctx[idx].nid_lrbg);
322 v_train_changed = (ctx->v_train != g_last_train_ctx[idx].v_train);
323 m_mode_changed = (ctx->m_mode != g_last_train_ctx[idx].m_mode);
324 granted_length_changed = (ctx->granted_length != g_last_train_ctx[idx].granted_length);
325 ma_seq_changed = (ctx->ma_seq != g_last_train_ctx[idx].ma_seq);
326 has_ma_changed = (ctx->has_ma != g_last_train_ctx[idx].has_ma);
328 g_last_train_ctx[idx] = *ctx;
329 if (d_lrbg_changed || nid_lrbg_changed || v_train_changed || m_mode_changed || granted_length_changed ||
330 ma_seq_changed || has_ma_changed)
344 uint8_t route_count, uint32_t d_lrbg, uint16_t *out_front_signal,
345 uint32_t *out_dist_to_front, uint16_t *out_target_signal)
347 uint32_t cumulative = 0U;
348 bool front_found =
false;
352 *out_front_signal = 0U;
353 *out_dist_to_front = 0U;
354 *out_target_signal = 0U;
356 if (route_count == 0U)
366 for (visited = 0U; visited < route_count; visited++)
369 bool prev_is_held =
false;
376 for (j = 0U; j < route_count; j++)
385 cur_id = route_ids[visited];
394 for (visited = 0U; (visited < route_count) && (cur_id != 0U); visited++)
405 boundary = cumulative + rt->
length_m;
406 if (!front_found && (d_lrbg < boundary))
409 *out_dist_to_front = boundary - d_lrbg;
413 cumulative = boundary;
416 for (j = 0U; j < route_count; j++)
420 next_id = route_ids[j];
432 *out_front_signal = *out_target_signal;
433 *out_dist_to_front = 0U;
437static void ctc_wire_encode(uint8_t out[RBC_ENVELOPE_WIRE_SIZE],
const rbc_envelope_t *env)
457 bool is_train_info = (env->kind == RBC_MSG_CTC_TRAIN_INFO);
460 uint16_t l_message = is_train_info ? 76U : (uint16_t)(
CTC_WIRE_HEADER_SIZE + CTC_WIRE_CONTENT_SIZE_BASE);
462 sapi_mem_set(out, 0, RBC_ENVELOPE_WIRE_SIZE);
463 (void)sapi_buffer_init(&buf, out, RBC_ENVELOPE_WIRE_SIZE);
464 out[0] = (uint8_t)env->kind;
465 out[1] = env->train_id;
468 (void)sapi_buffer_set_length(&buf, 4U);
469 (void)sapi_buffer_write_u16_le(&buf, l_message);
470 (void)sapi_buffer_write_u16_le(&buf, 0U);
471 (void)sapi_buffer_write_u32_le(&buf, env->t_train);
473 (void)sapi_buffer_write_u32_le(&buf, env->cycle);
476 (void)sapi_buffer_write_u32_le(&buf, env->d_lrbg);
477 (void)sapi_buffer_write_u32_le(&buf, env->msg_type);
479 (void)sapi_buffer_write_u32_le(&buf, env->route_len);
481 (void)sapi_buffer_write_u32_le(&buf, env->ma_seq);
483 (void)sapi_buffer_write_u32_le(&buf, env->ma_length);
487 (void)sapi_buffer_set_length(&buf, 40U);
488 (void)sapi_buffer_write_u32_le(&buf, env->nid_lrbg);
491 (void)sapi_buffer_set_length(&buf, 64U);
492 (void)sapi_buffer_write_u32_le(&buf, env->v_train);
494 (void)sapi_buffer_set_length(&buf, 72U);
495 (void)sapi_buffer_write_u32_le(&buf, env->m_mode);
void ab_ga_ctc_build_connected(uint8_t out[RBC_ENVELOPE_WIRE_SIZE], uint8_t train_id, uint32_t d_lrbg)
Builds and wire-encodes the outbound CTC_CONNECTED indication for train_id (kind=RBC_MSG_CTC_CONNECTE...
void ab_ga_ctc_build_ma_granted(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 CTC_MA_GRANTED indication for train_id (kind=RBC_MSG_CTC_MA_GRAN...
static void compute_train_info_signals(const uint16_t route_ids[SAFEAPI_EXAMPLE_MAX_ROUTES_PER_TRAIN], uint8_t route_count, uint32_t d_lrbg, uint16_t *out_front_signal, uint32_t *out_dist_to_front, uint16_t *out_target_signal)
static void ctc_wire_encode(uint8_t out[RBC_ENVELOPE_WIRE_SIZE], const rbc_envelope_t *env)
void ab_ga_ctc_build_train_info(uint8_t out[RBC_ENVELOPE_WIRE_SIZE], uint8_t train_id, uint32_t d_lrbg, uint32_t ma_seq, uint32_t granted_length, bool ma_granted, uint16_t front_signal, uint32_t dist_to_front_signal, uint16_t target_signal, uint32_t nid_lrbg, uint32_t v_train, uint32_t m_mode)
Builds and wire-encodes a severity-leveled operational alarm (kind=RBC_MSG_CTC_ALARM) directly into o...
#define CTC_WIRE_HEADER_SIZE
uint8_t ab_ga_ctc_build_outputs(ab_gp_train_session_t *sessions, ab_gp_db_t *db, ab_gp_ctc_pending_output_t out[AB_GP_CTC_MAX_PENDING_OUTPUTS])
Decides which trains need a CTC indication THIS cycle and builds all of them - see this file's own mo...
void ab_ga_ctc_on_train_context_changed(const ab_gp_train_context_t *ctx, ab_gp_train_update_type_t update_type)
GA's dispatch module fans every train-context change here - stores the received snapshot and marks th...
static bool g_train_ctx_known[SAFEAPI_EXAMPLE_MAX_TRAINS]
void ab_ga_ctc_build_ma_extended(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 CTC_MA_EXTENDED indication for train_id (kind=RBC_MSG_CTC_MA_EXT...
static bool g_train_info_pending[SAFEAPI_EXAMPLE_MAX_TRAINS]
void ab_ga_ctc_on_route_context_changed(const ab_gp_route_context_t *ctx, ab_gp_route_update_type_t update_type)
GA's single dispatch module (safeAPIRBC2oo2GA/src/AB/main/ ab_ga_dispatch.c) is the ONLY thing that r...
A/B's own outbound messages to CtcRBCSim. Two layers, same split as AB/GP/train/ab_gp_train....
GA's own site data: route composition, built from GP's raw physical elements (railML interlocking <ro...
const ab_site_ga_route_layout_t * ab_site_ga_get_route(uint16_t route_id)
Looks up a route by its ID.
One route's static layout entry (railML interlocking <route>) - GA's own full definition (not a reduc...