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_db.c
Go to the documentation of this file.
1
7#include "ab_gp_db.h"
8
9#include "rte/utils/buffer/rte_buffer.h"
10#include "rte/oal/memory/rte_mem_util.h"
11#include "rte/utils/lifecycle/rte_lifecycle.h"
12#include "rte/utils/notify/rte_notify.h"
13
14
15/* GA notification registries - module-private storage, same "static
16 * singleton" convention as ab_gp_channel.c's own g_ab_ctx. See ab_gp_db.h's
17 * own "GA notification" doc for why this file fires them (it owns the
18 * mutations) and rte_notify.h's own doc (safeAPIFreamwork, ADR-030)
19 * for the storage shape/why init/register/dispatch are hand-written. */
22
23static ab_gp_db_route_context_list_t g_route_context_subscribers;
24
26{
27 rte_status_t lifecycle_status;
28
29 if (fn == NULL)
30 {
31 return RTE_STATUS_INVALID_PARAM;
32 }
33 lifecycle_status = rte_lifecycle_check_setup_allowed();
34 if (lifecycle_status != RTE_STATUS_OK)
35 {
36 return lifecycle_status;
37 }
39 {
40 return RTE_STATUS_RESOURCE_EXHAUSTED;
41 }
43 g_route_context_subscribers.slots[g_route_context_subscribers.count].context = (void *)context; /* see
44 AB/GP/ma_logic/ab_gp_logic.c's own identical cast for why this is safe - const enters, const-typed
45 fn() is all that's ever done with it */
47 return RTE_STATUS_OK;
48}
49
65static void build_route_context(const ab_gp_db_t *db, int route_idx, uint8_t train_id, ab_gp_route_context_t *out_ctx)
66{
67 const ab_gp_db_route_t *route = &db->routes[route_idx];
68
69 out_ctx->id = route->id;
70 out_ctx->start_signal = route->start_signal;
71 out_ctx->end_signal = route->end_signal;
72 out_ctx->il_status = route->il_status;
73 out_ctx->route_type = route->route_type;
74 out_ctx->used_in_ma = route->used_in_ma;
75 out_ctx->train_id = train_id;
76}
77
83static void notify_route_context(const ab_gp_db_t *db, int route_idx, uint8_t train_id,
84 ab_gp_route_update_type_t update_type)
85{
87 uint32_t i;
88
89 build_route_context(db, route_idx, train_id, &ctx);
90
91 for (i = 0U; i < g_route_context_subscribers.count; i++)
92 {
93 if (g_route_context_subscribers.slots[i].fn != NULL)
94 {
95 g_route_context_subscribers.slots[i].fn(g_route_context_subscribers.slots[i].context, &ctx,
96 update_type);
97 }
98 }
99}
100
110static int find_route_index(const ab_gp_db_t *db, uint16_t route_id)
111{
112 uint32_t i;
113
114 if (db == NULL || route_id == 0U)
115 {
116 return -1;
117 }
118
119 for (i = 0U; i < (uint32_t)RTE_EXAMPLE_MAX_ROUTES; i++)
120 {
121 if (db->routes[i].id == route_id)
122 {
123 return (int)i;
124 }
125 }
126 return -1;
127}
128
131static int find_free_route_slot(const ab_gp_db_t *db)
132{
133 uint32_t i;
134
135 if (db == NULL)
136 {
137 return -1;
138 }
139
140 for (i = 0U; i < (uint32_t)RTE_EXAMPLE_MAX_ROUTES; i++)
141 {
142 if (db->routes[i].id == 0U)
143 {
144 return (int)i;
145 }
146 }
147 return -1;
148}
149
150bool ab_gp_db_route_connect_train(ab_gp_db_t *db, uint16_t route_id, uint8_t train_id)
151{
152 int route_idx;
153 ab_gp_db_train_t *train;
154 uint8_t k;
155
156 if (db == NULL || route_id == 0U)
157 {
158 return false;
159 }
160 route_idx = find_route_index(db, route_id);
161 if (route_idx < 0)
162 {
163 return false;
164 }
165 /* REQ-RBC-005: an out-of-range train_id returns false to the caller before it indexes db->trains[]. */
166 if ((train_id == 0U) || (train_id > (uint8_t)RTE_EXAMPLE_MAX_TRAINS))
167 {
168 return false;
169 }
170 if (db->routes[route_idx].used_in_ma)
171 {
172 return false; /* already assigned - disconnect first, never silently reassigned */
173 }
174
175 train = &db->trains[train_id - 1U];
176 if (train->route_count >= (uint8_t)RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN)
177 {
178 return false; /* this train's own route_ids[] table full */
179 }
180 for (k = 0U; k < train->route_count; k++)
181 {
182 if (train->route_ids[k] == route_id)
183 {
184 return false; /* already allocated to this same train */
185 }
186 }
187
188 train->route_ids[train->route_count] = route_id;
189 train->route_count++;
190
191 db->routes[route_idx].used_in_ma = true;
192 db->routes[route_idx].train_id = train_id;
193 notify_route_context(db, route_idx, train_id, AB_ROUTE_CONNECTED);
194 return true;
195}
196
197bool ab_gp_db_route_disconnect_train(ab_gp_db_t *db, uint16_t route_id)
198{
199 int route_idx;
200 ab_gp_db_train_t *train;
201 uint8_t disconnected_train_id;
202 uint8_t k;
203
204 if (db == NULL || route_id == 0U)
205 {
206 return false;
207 }
208 route_idx = find_route_index(db, route_id);
209 if (route_idx < 0)
210 {
211 return false;
212 }
213 if (!db->routes[route_idx].used_in_ma)
214 {
215 return false; /* nothing to disconnect */
216 }
217
218 disconnected_train_id = db->routes[route_idx].train_id; /* captured before it's cleared below - see
219 notify_route_context()'s own doc */
220 db->routes[route_idx].used_in_ma = false;
221 db->routes[route_idx].train_id = 0U;
222
223 /* REQ-RBC-005: the train_id read back from the route is range-checked before it indexes db->trains[]; an
224 * out-of-range value skips the per-train route list cleanup (the route itself is still released). */
225 if ((disconnected_train_id >= 1U) && (disconnected_train_id <= (uint8_t)RTE_EXAMPLE_MAX_TRAINS))
226 {
227 train = &db->trains[disconnected_train_id - 1U];
228 if (train->route_count > (uint8_t)RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN)
229 {
231 }
232 for (k = 0U; k < train->route_count; k++)
233 {
234 if (train->route_ids[k] == route_id)
235 {
236 uint8_t shift;
237
238 for (shift = k; (uint8_t)(shift + 1U) < train->route_count; shift++)
239 {
240 train->route_ids[shift] = train->route_ids[shift + 1U];
241 }
242 train->route_ids[train->route_count - 1U] = 0U;
243 train->route_count--;
244 break;
245 }
246 }
247 }
248
249 notify_route_context(db, route_idx, disconnected_train_id, AB_ROUTE_DISCONNECTED);
250 return true;
251}
252
253bool ab_gp_db_route_exists(const ab_gp_db_t *db, uint16_t route_id)
254{
255 return find_route_index(db, route_id) >= 0;
256}
257
258bool ab_gp_db_route_add(ab_gp_db_t *db, uint16_t route_id, uint16_t start_signal, uint16_t end_signal)
259{
260 int slot;
261
262 if (find_route_index(db, route_id) >= 0)
263 {
264 return false; /* already tracked - ab_gp_db_route_remove() first to replace it */
265 }
266 slot = find_free_route_slot(db);
267 if (slot < 0)
268 {
269 return false; /* db->routes[] (RTE_EXAMPLE_MAX_ROUTES) full */
270 }
271
272 db->routes[slot].id = route_id;
273 db->routes[slot].start_signal = start_signal;
274 db->routes[slot].end_signal = end_signal;
275 db->routes[slot].occupied = false;
277 db->routes[slot].route_type = 0U; /* RBC_ROUTE_TYPE_FS - rbc_wire_types.h */
278 db->routes[slot].route_fsm_state = 0U; /* AB_GA_ROUTE_STATE_NO_ROUTE - must be
279 * reset here: this slot may be a reused
280 * one whose route_fsm_state still holds
281 * the PREVIOUS route's last state, which
282 * ab_ga_route_fsm_step() would then read
283 * as its "from" and the IL_ROUTE_INDICATION
284 * would report on a freshly-added route. */
285 db->routes[slot].used_in_ma = false;
286 db->routes[slot].train_id = 0U;
288 return true;
289}
290
291bool ab_gp_db_route_remove(ab_gp_db_t *db, uint16_t route_id)
292{
293 int idx = find_route_index(db, route_id);
294
295 if (idx < 0)
296 {
297 return false;
298 }
299 if (db->routes[idx].used_in_ma)
300 {
301 return false; /* still backing a train's MA - ab_gp_db_route_disconnect_train() first */
302 }
303 rte_mem_set(&db->routes[idx], 0, sizeof(db->routes[idx])); /* id becomes 0 again -> slot free */
304 return true;
305}
306
307/* ab_gp_db_route_get_status()/_get_used_in_ma()/_get_type() - REMOVED,
308 * see ab_gp_db.h's own comment at their old declaration. */
309
311{
312 int idx = find_route_index(db, route_id);
313
314 if (idx < 0)
315 {
316 return false;
317 }
318 db->routes[idx].il_status = status;
320 return true;
321}
322
323bool ab_gp_db_get_route_context(const ab_gp_db_t *db, uint16_t route_id, ab_gp_route_context_t *out_ctx)
324{
325 int idx = find_route_index(db, route_id);
326
327 if (idx < 0)
328 {
329 return false;
330 }
331 build_route_context(db, idx, db->routes[idx].train_id, out_ctx);
332 return true;
333}
334
335bool ab_gp_db_route_set_type(ab_gp_db_t *db, uint16_t route_id, uint32_t route_type)
336{
337 int idx = find_route_index(db, route_id);
338
339 if (idx < 0)
340 {
341 return false;
342 }
343 db->routes[idx].route_type = route_type;
344 return true;
345}
346
347bool ab_gp_db_route_set_fsm_state(ab_gp_db_t *db, uint16_t route_id, uint32_t fsm_state)
348{
349 int idx = find_route_index(db, route_id);
350
351 if (idx < 0)
352 {
353 return false;
354 }
355 db->routes[idx].route_fsm_state = fsm_state;
356 return true;
357}
358
359uint32_t ab_gp_db_route_get_fsm_state(const ab_gp_db_t *db, uint16_t route_id)
360{
361 int idx;
362
363 if (db == NULL)
364 {
365 return 0U;
366 }
367 idx = find_route_index(db, route_id);
368 if (idx < 0)
369 {
370 return 0U;
371 }
372 return db->routes[idx].route_fsm_state;
373}
374
376{
377 uint8_t count = 0U;
378 uint8_t i;
379
380 if (db == NULL)
381 {
382 return 0U;
383 }
384
385 for (i = 0U; i < (uint8_t)RTE_EXAMPLE_MAX_ROUTES; i++)
386 {
387 if (db->routes[i].id != 0U)
388 {
389 count++;
390 }
391 }
392 return count;
393}
394
395bool ab_gp_db_route_get_by_index(const ab_gp_db_t *db, uint8_t index, uint16_t *out_route_id,
396 uint16_t *out_start_signal, uint16_t *out_end_signal,
397 uint8_t *out_train_id, bool *out_used_in_ma)
398{
399 if (db == NULL || index >= (uint8_t)RTE_EXAMPLE_MAX_ROUTES)
400 {
401 return false;
402 }
403
404 if (db->routes[index].id == 0U)
405 {
406 return false;
407 }
408
409 if (out_route_id != NULL)
410 {
411 *out_route_id = db->routes[index].id;
412 }
413 if (out_start_signal != NULL)
414 {
415 *out_start_signal = db->routes[index].start_signal;
416 }
417 if (out_end_signal != NULL)
418 {
419 *out_end_signal = db->routes[index].end_signal;
420 }
421 if (out_train_id != NULL)
422 {
423 *out_train_id = db->routes[index].train_id;
424 }
425 if (out_used_in_ma != NULL)
426 {
427 *out_used_in_ma = db->routes[index].used_in_ma;
428 }
429 return true;
430}
431
432/* REQ-RBC-005: ab_gp_db_train_is_connected() and _get_routes() below each check
433 * 1 <= train_id <= RTE_EXAMPLE_MAX_TRAINS before it indexes db->trains[], and otherwise return false to the caller;
434 * neither of them logs. */
435bool ab_gp_db_train_is_connected(const ab_gp_db_t *db, uint8_t train_id)
436{
437 if (db == NULL || train_id < 1U || train_id > (uint8_t)RTE_EXAMPLE_MAX_TRAINS)
438 {
439 return false;
440 }
441 return db->trains[train_id - 1U].connected;
442}
443
444bool ab_gp_db_train_get_routes(const ab_gp_db_t *db, uint8_t train_id,
445 uint16_t out_routes[RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN],
446 uint8_t *out_count)
447{
448 uint8_t i;
449
450 if (db == NULL || train_id < 1U || train_id > (uint8_t)RTE_EXAMPLE_MAX_TRAINS ||
451 out_routes == NULL || out_count == NULL)
452 {
453 return false;
454 }
455
456 uint8_t count = db->trains[train_id - 1U].route_count;
457
458 if (count > (uint8_t)RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN)
459 {
460 count = (uint8_t)RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN;
461 }
462 *out_count = count;
463 for (i = 0U; i < count; i++)
464 {
465 out_routes[i] = db->trains[train_id - 1U].route_ids[i];
466 }
467 for (; i < (uint8_t)RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN; i++)
468 {
469 out_routes[i] = 0U;
470 }
471 return true;
472}
473
474rte_status_t ab_gp_db_encode(const ab_gp_db_t *db, uint8_t *out_bytes, uint32_t out_capacity, uint32_t *out_written)
475{
476 size_t offset = 0U;
477 uint8_t i;
478
479 if (db == NULL || out_bytes == NULL || out_capacity < (uint32_t)RTE_EXAMPLE_DB_WIRE_SIZE)
480 {
481 return RTE_STATUS_INVALID_PARAM;
482 }
483
484 rte_mem_set(out_bytes, 0, (size_t)RTE_EXAMPLE_DB_WIRE_SIZE);
485
486 /* 1. Encode routes (RTE_EXAMPLE_MAX_ROUTES) */
487 for (i = 0U; i < (uint8_t)RTE_EXAMPLE_MAX_ROUTES; i++)
488 {
489 const ab_gp_db_route_t *r = &db->routes[i];
490
491 out_bytes[offset] = (uint8_t)(r->id & 0xFFU);
492 out_bytes[offset + 1U] = (uint8_t)((r->id >> 8) & 0xFFU);
493 offset += 2U;
494
495 out_bytes[offset] = (uint8_t)(r->start_signal & 0xFFU);
496 out_bytes[offset + 1U] = (uint8_t)((r->start_signal >> 8) & 0xFFU);
497 offset += 2U;
498
499 out_bytes[offset] = (uint8_t)(r->end_signal & 0xFFU);
500 out_bytes[offset + 1U] = (uint8_t)((r->end_signal >> 8) & 0xFFU);
501 offset += 2U;
502
503 out_bytes[offset] = (uint8_t)(r->route_type & 0xFFU);
504 out_bytes[offset + 1U] = (uint8_t)((r->route_type >> 8) & 0xFFU);
505 offset += 2U;
506
507 out_bytes[offset] = r->occupied ? 1U : 0U;
508 offset++;
509 out_bytes[offset] = (uint8_t)r->il_status;
510 offset++;
511 out_bytes[offset] = r->used_in_ma ? 1U : 0U;
512 offset++;
513 out_bytes[offset] = r->train_id;
514 offset++;
515 }
516
517 /* 2. Encode trains (RTE_EXAMPLE_MAX_TRAINS) */
518 for (i = 0U; i < (uint8_t)RTE_EXAMPLE_MAX_TRAINS; i++)
519 {
520 const ab_gp_db_train_t *t = &db->trains[i];
521 uint8_t rc = (t->route_count > (uint8_t)RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN)
523 uint32_t j;
524
525 out_bytes[offset] = t->nid_engine;
526 offset++;
527 out_bytes[offset] = t->connected ? 1U : 0U;
528 offset++;
529 out_bytes[offset] = t->has_ma ? 1U : 0U;
530 offset++;
531 out_bytes[offset] = rc;
532 offset++;
533
534 for (j = 0U; j < 4U; j++)
535 {
536 uint16_t rid = (j < (uint32_t)RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN) ? t->route_ids[j] : 0U;
537 out_bytes[offset] = (uint8_t)(rid & 0xFFU);
538 out_bytes[offset + 1U] = (uint8_t)((rid >> 8) & 0xFFU);
539 offset += 2U;
540 }
541
542 out_bytes[offset] = (uint8_t)(t->last_nid_lrbg & 0xFFU);
543 out_bytes[offset + 1U] = (uint8_t)((t->last_nid_lrbg >> 8) & 0xFFU);
544 out_bytes[offset + 2U] = (uint8_t)((t->last_nid_lrbg >> 16) & 0xFFU);
545 out_bytes[offset + 3U] = (uint8_t)((t->last_nid_lrbg >> 24) & 0xFFU);
546 offset += 4U;
547 }
548
549 if (out_written != NULL)
550 {
551 *out_written = (uint32_t)offset;
552 }
553
554 return RTE_STATUS_OK;
555}
556
557rte_status_t ab_gp_db_decode(ab_gp_db_t *db, const uint8_t *in_bytes, uint32_t in_size)
558{
559 rte_buffer_t buf;
560 rte_status_t status;
561 size_t offset = 0U;
562 uint8_t i;
563
564 if (db == NULL || in_bytes == NULL || in_size < (uint32_t)RTE_EXAMPLE_DB_WIRE_SIZE)
565 {
566 return RTE_STATUS_INVALID_PARAM;
567 }
568
569 status = rte_buffer_init(&buf, (void *)in_bytes, (size_t)in_size);
570 if (status != RTE_STATUS_OK)
571 {
572 return status;
573 }
574 status = rte_buffer_set_length(&buf, (size_t)in_size);
575 if (status != RTE_STATUS_OK)
576 {
577 return status;
578 }
579
580 rte_mem_set(db, 0, sizeof(ab_gp_db_t));
581
582 /* 1. Decode routes (RTE_EXAMPLE_MAX_ROUTES) */
583 for (i = 0U; i < (uint8_t)RTE_EXAMPLE_MAX_ROUTES; i++)
584 {
585 ab_gp_db_route_t *r = &db->routes[i];
586 uint16_t u16_val = 0U;
587
588 (void)rte_buffer_read_u16_le(&buf, offset, &r->id);
589 offset += 2U;
590 (void)rte_buffer_read_u16_le(&buf, offset, &r->start_signal);
591 offset += 2U;
592 (void)rte_buffer_read_u16_le(&buf, offset, &r->end_signal);
593 offset += 2U;
594 (void)rte_buffer_read_u16_le(&buf, offset, &u16_val);
595 r->route_type = (uint32_t)u16_val;
596 offset += 2U;
597
598 r->occupied = (in_bytes[offset] != 0U);
599 offset++;
600 r->il_status = (ab_gp_db_route_il_status_t)in_bytes[offset];
601 offset++;
602 r->used_in_ma = (in_bytes[offset] != 0U);
603 offset++;
604 r->train_id = in_bytes[offset];
605 offset++;
606 }
607
608 /* 2. Decode trains (RTE_EXAMPLE_MAX_TRAINS) */
609 for (i = 0U; i < (uint8_t)RTE_EXAMPLE_MAX_TRAINS; i++)
610 {
611 ab_gp_db_train_t *t = &db->trains[i];
612
613 t->nid_engine = in_bytes[offset];
614 offset++;
615 t->connected = (in_bytes[offset] != 0U);
616 offset++;
617 t->has_ma = (in_bytes[offset] != 0U);
618 offset++;
619 if (in_bytes[offset] > (uint8_t)RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN)
620 {
622 }
623 else
624 {
625 t->route_count = in_bytes[offset];
626 }
627 offset++;
628
629 (void)rte_buffer_read_u16_le(&buf, offset, &t->route_ids[0]);
630 offset += 2U;
631 (void)rte_buffer_read_u16_le(&buf, offset, &t->route_ids[1]);
632 offset += 2U;
633 (void)rte_buffer_read_u16_le(&buf, offset, &t->route_ids[2]);
634 offset += 2U;
635 (void)rte_buffer_read_u16_le(&buf, offset, &t->route_ids[3]);
636 offset += 2U;
637
638 (void)rte_buffer_read_u32_le(&buf, offset, &t->last_nid_lrbg);
639 offset += 4U;
640 }
641
642 return RTE_STATUS_OK;
643}
644
645
static ab_gp_db_route_context_list_t g_route_context_subscribers
Definition ab_gp_db.c:23
bool ab_gp_db_get_route_context(const ab_gp_db_t *db, uint16_t route_id, ab_gp_route_context_t *out_ctx)
One-shot pull equivalent of the push notification above - the SAME snapshot-building logic (real impl...
Definition ab_gp_db.c:323
bool ab_gp_db_route_disconnect_train(ab_gp_db_t *db, uint16_t route_id)
Reverses ab_gp_db_route_connect_train(): clears the route's own used_in_ma/train_id and removes it fr...
Definition ab_gp_db.c:197
static void notify_route_context(const ab_gp_db_t *db, int route_idx, uint8_t train_id, ab_gp_route_update_type_t update_type)
Definition ab_gp_db.c:83
bool ab_gp_db_train_is_connected(const ab_gp_db_t *db, uint8_t train_id)
Checks if a train has an active connection session in the DB.
Definition ab_gp_db.c:435
rte_status_t ab_gp_db_register_route_context_notify(ab_gp_route_context_notify_fn fn, const void *context)
Definition ab_gp_db.c:25
bool ab_gp_db_route_set_fsm_state(ab_gp_db_t *db, uint16_t route_id, uint32_t fsm_state)
Get/set the per-route FSM state (ab_ga_route_state_t, raw uint32_t - GA owns the value space,...
Definition ab_gp_db.c:347
static int find_route_index(const ab_gp_db_t *db, uint16_t route_id)
Definition ab_gp_db.c:110
rte_status_t ab_gp_db_decode(ab_gp_db_t *db, const uint8_t *in_bytes, uint32_t in_size)
Decodes the full route and train database from a deterministic wire format.
Definition ab_gp_db.c:557
bool ab_gp_db_route_connect_train(ab_gp_db_t *db, uint16_t route_id, uint8_t train_id)
Connects route_id to train_id: appends the route to that train's own route_ids[] and marks the route ...
Definition ab_gp_db.c:150
bool ab_gp_db_train_get_routes(const ab_gp_db_t *db, uint8_t train_id, uint16_t out_routes[RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN], uint8_t *out_count)
Retrieves routes currently allocated to a train.
Definition ab_gp_db.c:444
bool ab_gp_db_route_remove(ab_gp_db_t *db, uint16_t route_id)
Removes a tracked route from db->routes[], freeing its slot.
Definition ab_gp_db.c:291
uint8_t ab_gp_db_route_get_count(const ab_gp_db_t *db)
Returns total number of active routes currently in the GP database.
Definition ab_gp_db.c:375
bool ab_gp_db_route_set_type(ab_gp_db_t *db, uint16_t route_id, uint32_t route_type)
Definition ab_gp_db.c:335
static int find_free_route_slot(const ab_gp_db_t *db)
Definition ab_gp_db.c:131
static void build_route_context(const ab_gp_db_t *db, int route_idx, uint8_t train_id, ab_gp_route_context_t *out_ctx)
Definition ab_gp_db.c:65
rte_status_t ab_gp_db_encode(const ab_gp_db_t *db, uint8_t *out_bytes, uint32_t out_capacity, uint32_t *out_written)
Encodes the full route and train database into a deterministic wire format.
Definition ab_gp_db.c:474
bool ab_gp_db_route_add(ab_gp_db_t *db, uint16_t route_id, uint16_t start_signal, uint16_t end_signal)
Adds a new route to db->routes[]. New entry starts fully idle: occupied=false, il_status=AB_GP_DB_ROU...
Definition ab_gp_db.c:258
bool ab_gp_db_route_exists(const ab_gp_db_t *db, uint16_t route_id)
Definition ab_gp_db.c:253
bool ab_gp_db_route_get_by_index(const ab_gp_db_t *db, uint8_t index, uint16_t *out_route_id, uint16_t *out_start_signal, uint16_t *out_end_signal, uint8_t *out_train_id, bool *out_used_in_ma)
Retrieves route snapshot by table index for GA/GP route list synchronization.
Definition ab_gp_db.c:395
RTE_DECLARE_CALLBACK_LIST(ab_gp_db_route_context_list_t, ab_gp_route_context_notify_fn, AB_GP_DB_MAX_ROUTE_CONTEXT_SUBSCRIBERS)
bool ab_gp_db_route_set_status(ab_gp_db_t *db, uint16_t route_id, ab_gp_db_route_il_status_t status)
Definition ab_gp_db.c:310
uint32_t ab_gp_db_route_get_fsm_state(const ab_gp_db_t *db, uint16_t route_id)
Definition ab_gp_db.c:359
A/B's own simplified Train/Route database - fixed-size arrays describing the domain objects logic/ (p...
#define AB_GP_DB_MAX_ROUTE_CONTEXT_SUBSCRIBERS
Definition ab_gp_db.h:358
void(*) ab_gp_route_context_notify_fn(const void *context, const ab_gp_route_context_t *ctx, ab_gp_route_update_type_t update_type)
Definition ab_gp_db.h:353
ab_gp_db_route_il_status_t
Definition ab_gp_db.h:54
@ AB_GP_DB_ROUTE_IL_STATUS_UNKNOWN
Definition ab_gp_db.h:55
ab_gp_route_update_type_t
Definition ab_gp_db.h:310
@ AB_ROUTE_STATUS_CHANGED
Definition ab_gp_db.h:312
@ AB_ROUTE_CONNECTED
Definition ab_gp_db.h:313
@ AB_ROUTE_DISCONNECTED
Definition ab_gp_db.h:315
@ AB_ROUTE_ADDED
Definition ab_gp_db.h:311
#define RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN
#define RTE_EXAMPLE_MAX_ROUTES
#define RTE_EXAMPLE_DB_WIRE_SIZE
#define RTE_EXAMPLE_MAX_TRAINS
One track section A/B's simplified layout knows about.
Definition ab_gp_db.h:66
uint16_t start_signal
Definition ab_gp_db.h:68
ab_gp_db_route_il_status_t il_status
Definition ab_gp_db.h:74
uint16_t end_signal
Definition ab_gp_db.h:69
uint8_t train_id
Definition ab_gp_db.h:83
uint32_t route_type
Definition ab_gp_db.h:75
uint32_t route_fsm_state
Definition ab_gp_db.h:86
uint16_t id
Definition ab_gp_db.h:67
ab_gp_db_route_t routes[RTE_EXAMPLE_MAX_ROUTES]
Definition ab_gp_db.h:135
ab_gp_db_train_t trains[RTE_EXAMPLE_MAX_TRAINS]
Definition ab_gp_db.h:134
One train A/B's simplified database knows about.
Definition ab_gp_db.h:99
uint8_t nid_engine
Definition ab_gp_db.h:100
uint8_t route_count
Definition ab_gp_db.h:110
uint16_t route_ids[RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN]
Definition ab_gp_db.h:108
uint32_t last_nid_lrbg
Definition ab_gp_db.h:112
ab_gp_db_route_il_status_t il_status
Definition ab_gp_db.h:335