SafeAPI RBC 2oo2 Generic Application
IL/CTC route and train logic for the safeAPIRBC2oo2 reference RBC
Loading...
Searching...
No Matches
ab_ga_il_wire.c
Go to the documentation of this file.
1
5
6#include "ab_ga_il_wire.h"
7
8#include "safeapi/oal/memory/sapi_mem_util.h"
9#include "safeapi/utils/buffer/sapi_buffer.h"
10
11/* ---- little-endian int32 helpers (the flat IL codec uses sapi_buffer for
12 * u16/u32 and raw byte indexing for u8; do the same here, plus this
13 * one wrapper so the -1 sentinel round-trips as a bit pattern). ---- */
14
15static bool read_i32_le(const uint8_t *frame, size_t off, int32_t *out)
16{
17 sapi_buffer_t buf;
18 uint32_t raw = 0U;
19
20 if (sapi_buffer_init(&buf, (uint8_t *)frame, RBC_ENVELOPE_WIRE_SIZE) != SAPI_STATUS_OK)
21 {
22 return false;
23 }
24 (void)sapi_buffer_set_length(&buf, RBC_ENVELOPE_WIRE_SIZE);
25 if (sapi_buffer_read_u32_le(&buf, off, &raw) != SAPI_STATUS_OK)
26 {
27 return false;
28 }
29 *out = (int32_t)raw;
30 return true;
31}
32
33static void write_i32_le(uint8_t *frame, size_t off, int32_t value)
34{
35 sapi_buffer_t buf;
36
37 if (sapi_buffer_init(&buf, frame, RBC_ENVELOPE_WIRE_SIZE) != SAPI_STATUS_OK)
38 {
39 return;
40 }
41 (void)sapi_buffer_set_length(&buf, off);
42 (void)sapi_buffer_write_u32_le(&buf, (uint32_t)value);
43}
44
45/* ---- range checks -------------------------------------------------------- */
46
47static bool id_field_valid(int32_t v)
48{
49 /* -1 (unset) or any non-negative id. */
50 return (v >= -1);
51}
52
53static bool flag_valid(uint8_t v)
54{
55 return (v <= 1U);
56}
57
58/* ---- decode ------------------------------------------------------------- */
59
60bool ab_ga_il_wire_decode_route_cmd(const uint8_t frame[RBC_ENVELOPE_WIRE_SIZE],
62{
64 uint8_t route_type;
65 uint8_t route_status;
66 uint8_t degraded_status;
67 uint8_t release_req;
68 uint8_t first_in_path;
69
70 if ((frame == NULL) || (out == NULL) || (frame[0] != (uint8_t)RBC_MSG_IL_ROUTE_CMD))
71 {
72 return false;
73 }
74
75 route_type = frame[2];
76 route_status = frame[3];
77 degraded_status = frame[4];
78 release_req = frame[5];
79 first_in_path = frame[6];
80
81 if (route_type > (uint8_t)RBC_IL_ROUTE_TYPE_LOCKED)
82 {
83 return false;
84 }
85 if (route_status > (uint8_t)RBC_IL_ROUTE_STATUS_DEGRADED)
86 {
87 return false;
88 }
89 if (degraded_status > (uint8_t)RBC_IL_DEGRADED_STATUS_HIGH)
90 {
91 return false;
92 }
93 if (!flag_valid(release_req) || !flag_valid(first_in_path))
94 {
95 return false;
96 }
97
98 if (!read_i32_le(frame, 8U, &d.route_id) ||
99 !read_i32_le(frame, 12U, &d.start_signal) ||
100 !read_i32_le(frame, 16U, &d.end_signal))
101 {
102 return false;
103 }
104 if (!id_field_valid(d.route_id) || !id_field_valid(d.start_signal) || !id_field_valid(d.end_signal))
105 {
106 return false;
107 }
108
109 d.route_type = (rbc_il_route_type_t)route_type;
110 d.route_status = (rbc_il_route_status_t)route_status;
111 d.degraded_status = (rbc_il_degraded_status_t)degraded_status;
112 d.release_route_request = (release_req == 1U);
113 d.first_route_in_path = (first_in_path == 1U);
114
115 *out = d;
116 return true;
117}
118
119bool ab_ga_il_wire_decode_status(const uint8_t frame[RBC_ENVELOPE_WIRE_SIZE],
121{
122 uint8_t il_status;
123
124 if ((frame == NULL) || (out == NULL) || (frame[0] != (uint8_t)RBC_MSG_IL_STATUS))
125 {
126 return false;
127 }
128 il_status = frame[1];
129 if (il_status > (uint8_t)RBC_IL_STATUS_UP)
130 {
131 return false;
132 }
133 out->il_status = (rbc_il_status_t)il_status;
134 return true;
135}
136
137/* ---- encode ----------------------------------------------------------- */
138
139void ab_ga_il_wire_encode_route_indication(uint8_t frame[RBC_ENVELOPE_WIRE_SIZE],
141{
142 if ((frame == NULL) || (in == NULL))
143 {
144 return;
145 }
146
147 sapi_mem_set(frame, 0, RBC_ENVELOPE_WIRE_SIZE);
148 frame[0] = (uint8_t)RBC_MSG_IL_ROUTE_INDICATION;
149 frame[1] = 0U;
150 frame[2] = in->train_in_route ? 1U : 0U;
151 frame[3] = in->train_has_ma_in_route ? 1U : 0U;
152 frame[4] = in->emergency_in_route ? 1U : 0U;
153 /* emergency_type is a SIGNED int8 on the wire (-1 = none). */
154 frame[5] = (uint8_t)(int8_t)in->emergency_type;
155 frame[6] = in->route_fsm_state;
156 frame[7] = in->route_fsm_is_stub ? 1U : 0U;
157
158 write_i32_le(frame, 8U, in->route_id);
159 write_i32_le(frame, 12U, in->start_signal);
160 write_i32_le(frame, 16U, in->end_signal);
161 write_i32_le(frame, 20U, in->allocated_train_nid_engine);
162}
bool ab_ga_il_wire_decode_route_cmd(const uint8_t frame[RBC_ENVELOPE_WIRE_SIZE], ab_ga_il_route_cmd_t *out)
Decodes + fully range-validates an RBC_MSG_IL_ROUTE_CMD frame.
void ab_ga_il_wire_encode_route_indication(uint8_t frame[RBC_ENVELOPE_WIRE_SIZE], const ab_ga_il_route_indication_t *in)
Encodes an RBC_MSG_IL_ROUTE_INDICATION frame (zero-fills the whole RBC_ENVELOPE_WIRE_SIZE slot first)...
bool ab_ga_il_wire_decode_status(const uint8_t frame[RBC_ENVELOPE_WIRE_SIZE], ab_ga_il_status_msg_t *out)
Decodes + validates an RBC_MSG_IL_STATUS frame. Same contract.
Dedicated IL <-> RBC message payloads and codec (wire kinds RBC_MSG_IL_ROUTE_CMD / RBC_MSG_IL_STATUS ...
Decoded RBC_MSG_IL_ROUTE_CMD payload.
RBC_MSG_IL_ROUTE_INDICATION payload (RBC -> IL).
rbc_il_emergency_type_t emergency_type
Decoded RBC_MSG_IL_STATUS payload.