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_ertms_train_packet_codec.c
Go to the documentation of this file.
1
8
10
11#include "rte/utils/cast/rte_cast.h"
12
13bool rbc_codec_read_u8(const uint8_t *buf, size_t len, size_t *offset, uint8_t *val)
14{
15 if (buf == NULL || offset == NULL || val == NULL || *offset >= len)
16 {
17 return false;
18 }
19 *val = buf[*offset];
20 *offset += 1U;
21 return true;
22}
23
24bool rbc_codec_read_u16_be(const uint8_t *buf, size_t len, size_t *offset, uint16_t *val)
25{
26 if (buf == NULL || offset == NULL || val == NULL || (*offset + 2U) > len)
27 {
28 return false;
29 }
30 *val = (uint16_t)(((uint16_t)buf[*offset] << 8) | (uint16_t)buf[*offset + 1U]);
31 *offset += 2U;
32 return true;
33}
34
35bool rbc_codec_read_u32_be(const uint8_t *buf, size_t len, size_t *offset, uint32_t *val)
36{
37 if (buf == NULL || offset == NULL || val == NULL || (*offset + 4U) > len)
38 {
39 return false;
40 }
41 *val = ((uint32_t)buf[*offset] << 24) |
42 ((uint32_t)buf[*offset + 1U] << 16) |
43 ((uint32_t)buf[*offset + 2U] << 8) |
44 ((uint32_t)buf[*offset + 3U]);
45 *offset += 4U;
46 return true;
47}
48
49bool rbc_codec_write_u8(uint8_t *buf, size_t cap, size_t *offset, uint8_t val)
50{
51 if (buf == NULL || offset == NULL || *offset >= cap)
52 {
53 return false;
54 }
55 buf[*offset] = val;
56 *offset += 1U;
57 return true;
58}
59
60bool rbc_codec_write_u16_be(uint8_t *buf, size_t cap, size_t *offset, uint16_t val)
61{
62 if (buf == NULL || offset == NULL || (*offset + 2U) > cap)
63 {
64 return false;
65 }
66 (void)rte_cast_u16_to_u8((val >> 8) & 0xFFU, &buf[*offset]);
67 (void)rte_cast_u16_to_u8(val & 0xFFU, &buf[*offset + 1U]);
68 *offset += 2U;
69 return true;
70}
71
72bool rbc_codec_write_u32_be(uint8_t *buf, size_t cap, size_t *offset, uint32_t val)
73{
74 if (buf == NULL || offset == NULL || (*offset + 4U) > cap)
75 {
76 return false;
77 }
78 (void)rte_cast_u32_to_u8((val >> 24) & 0xFFU, &buf[*offset]);
79 (void)rte_cast_u32_to_u8((val >> 16) & 0xFFU, &buf[*offset + 1U]);
80 (void)rte_cast_u32_to_u8((val >> 8) & 0xFFU, &buf[*offset + 2U]);
81 (void)rte_cast_u32_to_u8(val & 0xFFU, &buf[*offset + 3U]);
82 *offset += 4U;
83 return true;
84}
85
90bool rbc_codec_write_u64_be(uint8_t *buf, size_t cap, size_t *offset, uint64_t val)
91{
92 uint32_t hi = (uint32_t)((val >> 32) & 0xFFFFFFFFU);
93 uint32_t lo = (uint32_t)(val & 0xFFFFFFFFU);
94
95 return rbc_codec_write_u32_be(buf, cap, offset, hi) && rbc_codec_write_u32_be(buf, cap, offset, lo);
96}
97
98/* ========================================================================= */
99/* Packet decode */
100/* ========================================================================= */
101
112bool rbc_packet_read_0_position_report(const uint8_t *buf, size_t len, size_t *offset,
114{
115 uint8_t q_scale = 0U;
116 uint16_t nid_c = 0U;
117 uint16_t nid_bg = 0U;
118 uint32_t d_lrbg = 0U;
119 uint8_t q_dirlrbg = 0U;
120 uint8_t q_dlrbg = 0U;
121 uint32_t l_doubtover = 0U;
122 uint32_t l_doubtunder = 0U;
123 uint16_t v_train = 0U;
124 uint8_t m_mode = 0U;
125 uint8_t m_level = 0U;
126
127 if (out_p0 == NULL ||
128 !rbc_codec_read_u8(buf, len, offset, &q_scale) ||
129 !rbc_codec_read_u16_be(buf, len, offset, &nid_c) ||
130 !rbc_codec_read_u16_be(buf, len, offset, &nid_bg) ||
131 !rbc_codec_read_u32_be(buf, len, offset, &d_lrbg) ||
132 !rbc_codec_read_u8(buf, len, offset, &q_dirlrbg) ||
133 !rbc_codec_read_u8(buf, len, offset, &q_dlrbg) ||
134 !rbc_codec_read_u32_be(buf, len, offset, &l_doubtover) ||
135 !rbc_codec_read_u32_be(buf, len, offset, &l_doubtunder) ||
136 !rbc_codec_read_u16_be(buf, len, offset, &v_train) ||
137 !rbc_codec_read_u8(buf, len, offset, &m_mode) ||
138 !rbc_codec_read_u8(buf, len, offset, &m_level))
139 {
140 return false;
141 }
142
143 out_p0->q_scale = (rbc_q_scale_t)q_scale;
144 out_p0->nid_lrbg.nid_c = nid_c;
145 out_p0->nid_lrbg.nid_bg = nid_bg;
146 out_p0->d_lrbg = d_lrbg;
147 out_p0->q_dirlrbg = (rbc_q_dirlrbg_t)q_dirlrbg;
148 out_p0->q_dlrbg = (rbc_q_dlrbg_t)q_dlrbg;
149 out_p0->l_doubtover = l_doubtover;
150 out_p0->l_doubtunder = l_doubtunder;
151 out_p0->v_train = (rbc_speed_kmh_t)v_train;
152 out_p0->m_mode = (rbc_m_mode_t)m_mode;
153 out_p0->m_level = (rbc_m_level_t)m_level;
154 return true;
155}
156
163bool rbc_packet_read_1_position_report_2bg(const uint8_t *buf, size_t len, size_t *offset,
165{
166 uint16_t nid_c = 0U;
167 uint16_t nid_bg = 0U;
168 uint16_t prv_nid_c = 0U;
169 uint16_t prv_nid_bg = 0U;
170 uint32_t d_lrbg = 0U;
171 uint16_t v_train = 0U;
172 uint8_t m_mode = 0U;
173 uint8_t m_level = 0U;
174
175 if (out_p1 == NULL ||
176 !rbc_codec_read_u16_be(buf, len, offset, &nid_c) ||
177 !rbc_codec_read_u16_be(buf, len, offset, &nid_bg) ||
178 !rbc_codec_read_u16_be(buf, len, offset, &prv_nid_c) ||
179 !rbc_codec_read_u16_be(buf, len, offset, &prv_nid_bg) ||
180 !rbc_codec_read_u32_be(buf, len, offset, &d_lrbg) ||
181 !rbc_codec_read_u16_be(buf, len, offset, &v_train) ||
182 !rbc_codec_read_u8(buf, len, offset, &m_mode) ||
183 !rbc_codec_read_u8(buf, len, offset, &m_level))
184 {
185 return false;
186 }
187
188 out_p1->nid_lrbg.nid_c = nid_c;
189 out_p1->nid_lrbg.nid_bg = nid_bg;
190 out_p1->nid_prvlrbg.nid_c = prv_nid_c;
191 out_p1->nid_prvlrbg.nid_bg = prv_nid_bg;
192 out_p1->d_lrbg = d_lrbg;
193 out_p1->v_train = (rbc_speed_kmh_t)v_train;
194 out_p1->m_mode = (rbc_m_mode_t)m_mode;
195 out_p1->m_level = (rbc_m_level_t)m_level;
196 return true;
197}
198
199/* ========================================================================= */
200/* Packet encode */
201/* ========================================================================= */
202
203bool rbc_packet_write_15_ma(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_15_ma_t *ma)
204{
205 if (ma == NULL)
206 {
207 return false;
208 }
209 return rbc_codec_write_u8(buf, cap, offset, RBC_PACKET_15_LEVEL_2_3_MA_SSP) &&
210 rbc_codec_write_u32_be(buf, cap, offset, ma->ma_seq) &&
211 rbc_codec_write_u32_be(buf, cap, offset, ma->ma_length) &&
212 rbc_codec_write_u16_be(buf, cap, offset, (uint16_t)ma->v_loa) &&
213 rbc_codec_write_u32_be(buf, cap, offset, ma->t_loa_s);
214}
215
216bool rbc_packet_write_21_gradient_profile(uint8_t *buf, size_t cap, size_t *offset,
217 const rbc_packet_21_gradient_profile_t *gradient)
218{
219 uint8_t i;
220
221 if (gradient == NULL)
222 {
223 return false;
224 }
225 if (!rbc_codec_write_u8(buf, cap, offset, RBC_PACKET_21_GRADIENT_PROFILE) ||
226 !rbc_codec_write_u8(buf, cap, offset, gradient->segment_count))
227 {
228 return false;
229 }
230 for (i = 0U; i < gradient->segment_count; i++)
231 {
232 if (!rbc_codec_write_u32_be(buf, cap, offset, gradient->segments[i].d_gradient) ||
233 !rbc_codec_write_u8(buf, cap, offset, (uint8_t)gradient->segments[i].g_a))
234 {
235 return false;
236 }
237 }
238 return true;
239}
240
241bool rbc_packet_write_27_ssp(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_27_ssp_t *ssp)
242{
243 uint8_t i;
244
245 if (ssp == NULL)
246 {
247 return false;
248 }
250 !rbc_codec_write_u8(buf, cap, offset, ssp->segment_count))
251 {
252 return false;
253 }
254 for (i = 0U; i < ssp->segment_count; i++)
255 {
256 if (!rbc_codec_write_u32_be(buf, cap, offset, ssp->segments[i].d_static) ||
257 !rbc_codec_write_u8(buf, cap, offset, (uint8_t)ssp->segments[i].v_static))
258 {
259 return false;
260 }
261 }
262 return true;
263}
264
265bool rbc_packet_write_5_linking(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_5_linking_t *linking)
266{
267 uint8_t i;
268
269 if (linking == NULL)
270 {
271 return false;
272 }
273 if (!rbc_codec_write_u8(buf, cap, offset, RBC_PACKET_5_LINKING_INFO) ||
274 !rbc_codec_write_u8(buf, cap, offset, linking->link_count))
275 {
276 return false;
277 }
278 for (i = 0U; i < linking->link_count; i++)
279 {
280 if (!rbc_codec_write_u16_be(buf, cap, offset, linking->links[i].nid_bg) ||
281 !rbc_codec_write_u32_be(buf, cap, offset, linking->links[i].d_link) ||
282 !rbc_codec_write_u8(buf, cap, offset, (uint8_t)linking->links[i].q_linkdir))
283 {
284 return false;
285 }
286 }
287 return true;
288}
289
290bool rbc_packet_write_3_national_values(uint8_t *buf, size_t cap, size_t *offset,
292{
293 if (nv == NULL)
294 {
295 return false;
296 }
297 return rbc_codec_write_u8(buf, cap, offset, RBC_PACKET_3_NATIONAL_VALUES) &&
298 rbc_codec_write_u16_be(buf, cap, offset, (uint16_t)nv->v_nvshunt) &&
299 rbc_codec_write_u16_be(buf, cap, offset, (uint16_t)nv->v_nvstff) &&
300 rbc_codec_write_u16_be(buf, cap, offset, (uint16_t)nv->v_nvunfit) &&
301 rbc_codec_write_u16_be(buf, cap, offset, nv->t_nvcontact) &&
302 rbc_codec_write_u16_be(buf, cap, offset, nv->d_nvroll);
303}
304
305bool rbc_packet_write_57_ma_request_params(uint8_t *buf, size_t cap, size_t *offset,
307{
308 if (params == NULL)
309 {
310 return false;
311 }
312 return rbc_codec_write_u8(buf, cap, offset, RBC_PACKET_57_MA_REQUEST_PARAMS) &&
313 rbc_codec_write_u32_be(buf, cap, offset, params->t_mar_s) &&
314 rbc_codec_write_u32_be(buf, cap, offset, params->d_mar_m);
315}
316
317bool rbc_packet_write_58_pr_params(uint8_t *buf, size_t cap, size_t *offset,
318 const rbc_packet_58_pr_params_t *params)
319{
320 if (params == NULL)
321 {
322 return false;
323 }
325 rbc_codec_write_u32_be(buf, cap, offset, params->t_cycloc_s) &&
326 rbc_codec_write_u32_be(buf, cap, offset, params->d_cycloc_m);
327}
328
329bool rbc_packet_write_65_tsr(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_65_tsr_t *tsr)
330{
331 if (tsr == NULL)
332 {
333 return false;
334 }
336 rbc_codec_write_u16_be(buf, cap, offset, tsr->nid_tsr) &&
337 rbc_codec_write_u32_be(buf, cap, offset, tsr->d_tsr) &&
338 rbc_codec_write_u32_be(buf, cap, offset, tsr->l_tsr) &&
339 rbc_codec_write_u16_be(buf, cap, offset, (uint16_t)tsr->v_tsr) &&
340 rbc_codec_write_u8(buf, cap, offset, (uint8_t)tsr->q_front);
341}
342
343bool rbc_packet_write_66_tsr_revoke(uint8_t *buf, size_t cap, size_t *offset,
344 const rbc_packet_66_tsr_revoke_t *revoke)
345{
346 if (revoke == NULL)
347 {
348 return false;
349 }
350 return rbc_codec_write_u8(buf, cap, offset, RBC_PACKET_66_TSR_REVOCATION) &&
351 rbc_codec_write_u16_be(buf, cap, offset, revoke->nid_tsr);
352}
353
354bool rbc_packet_write_72_text_message(uint8_t *buf, size_t cap, size_t *offset,
356{
357 uint32_t text_len = 0U;
358 uint32_t i;
359
360 if (text == NULL)
361 {
362 return false;
363 }
364 while ((text_len < (uint32_t)RBC_MAX_TEXT_MESSAGE_LEN) && (text->text[text_len] != '\0'))
365 {
366 text_len++;
367 }
368 if (!rbc_codec_write_u8(buf, cap, offset, RBC_PACKET_72_TEXT_MESSAGE) ||
369 !rbc_codec_write_u8(buf, cap, offset, (uint8_t)(text->ack_required ? 1U : 0U)) ||
370 !rbc_codec_write_u32_be(buf, cap, offset, text->duration_s) ||
371 !rbc_codec_write_u8(buf, cap, offset, (uint8_t)text_len))
372 {
373 return false;
374 }
375 for (i = 0U; i < text_len; i++)
376 {
377 if (!rbc_codec_write_u8(buf, cap, offset, (uint8_t)text->text[i]))
378 {
379 return false;
380 }
381 }
382 return true;
383}
384
385bool rbc_packet_write_131_rbc_transition(uint8_t *buf, size_t cap, size_t *offset,
386 const rbc_packet_131_rbc_transition_t *transition)
387{
388 if (transition == NULL)
389 {
390 return false;
391 }
393 rbc_codec_write_u32_be(buf, cap, offset, transition->d_rbctr) &&
394 rbc_codec_write_u16_be(buf, cap, offset, transition->nid_c) &&
395 rbc_codec_write_u16_be(buf, cap, offset, transition->nid_rbc) &&
396 rbc_codec_write_u64_be(buf, cap, offset, transition->nid_radio);
397}
bool rbc_packet_write_72_text_message(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_72_text_message_t *text)
bool rbc_packet_write_57_ma_request_params(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_57_ma_request_params_t *params)
bool rbc_codec_read_u8(const uint8_t *buf, size_t len, size_t *offset, uint8_t *val)
bool rbc_packet_write_131_rbc_transition(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_131_rbc_transition_t *transition)
Encodes Packet 131 (RBC Transition Order). NOTE: only d_rbctr/nid_c/ nid_rbc/nid_radio are written to...
bool rbc_codec_write_u8(uint8_t *buf, size_t cap, size_t *offset, uint8_t val)
bool rbc_packet_write_21_gradient_profile(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_21_gradient_profile_t *gradient)
bool rbc_codec_read_u32_be(const uint8_t *buf, size_t len, size_t *offset, uint32_t *val)
bool rbc_codec_read_u16_be(const uint8_t *buf, size_t len, size_t *offset, uint16_t *val)
bool rbc_packet_write_27_ssp(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_27_ssp_t *ssp)
bool rbc_codec_write_u16_be(uint8_t *buf, size_t cap, size_t *offset, uint16_t val)
bool rbc_packet_write_65_tsr(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_65_tsr_t *tsr)
bool rbc_packet_write_5_linking(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_5_linking_t *linking)
bool rbc_packet_write_66_tsr_revoke(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_66_tsr_revoke_t *revoke)
bool rbc_packet_read_1_position_report_2bg(const uint8_t *buf, size_t len, size_t *offset, rbc_packet_1_position_report_2bg_t *out_p1)
bool rbc_packet_write_3_national_values(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_3_national_values_t *nv)
bool rbc_packet_write_58_pr_params(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_58_pr_params_t *params)
bool rbc_codec_write_u64_be(uint8_t *buf, size_t cap, size_t *offset, uint64_t val)
bool rbc_packet_write_15_ma(uint8_t *buf, size_t cap, size_t *offset, const rbc_packet_15_ma_t *ma)
bool rbc_codec_write_u32_be(uint8_t *buf, size_t cap, size_t *offset, uint32_t val)
bool rbc_packet_read_0_position_report(const uint8_t *buf, size_t len, size_t *offset, rbc_packet_0_position_report_t *out_p0)
#define RBC_MAX_TEXT_MESSAGE_LEN
#define RBC_PACKET_131_RBC_TRANSITION_ORDER
#define RBC_PACKET_58_POSITION_REPORT_PARAMS
#define RBC_PACKET_65_TEMPORARY_SPEED_RESTRICT
#define RBC_PACKET_66_TSR_REVOCATION
#define RBC_PACKET_57_MA_REQUEST_PARAMS
#define RBC_PACKET_27_STATIC_SPEED_PROFILE
#define RBC_PACKET_72_TEXT_MESSAGE
#define RBC_PACKET_21_GRADIENT_PROFILE
#define RBC_PACKET_15_LEVEL_2_3_MA_SSP
#define RBC_PACKET_3_NATIONAL_VALUES
#define RBC_PACKET_5_LINKING_INFO
rbc_q_scale_t
Distance Scale Qualifier (Q_SCALE) Subset-026 Section 7.5.1.134: 0 = 10 cm (0.1 m) 1 = 1 m 2 = 10 m.
rbc_q_dlrbg_t
Train Orientation relative to LRBG (Q_DLRBG) Subset-026 Section 7.5.1.18: 0 = Reverse 1 = Nominal 2 =...
rbc_q_dirlrbg_t
Balise Group Orientation (Q_DIRLRBG) Subset-026 Section 7.5.1.16: 0 = Reverse 1 = Nominal 2 = Unknown...
rbc_m_mode_t
Train Operating Mode (M_MODE) Subset-026 Section 7.5.1.86.
rbc_m_level_t
ETCS Operating Level (M_LEVEL) Subset-026 Section 7.5.1.84.
uint16_t rbc_speed_kmh_t
Speed in km/h (5 km/h ETCS granularity or exact integer).
rbc_nid_bg_t nid_bg
rbc_gradient_segment_t segments[RBC_MAX_GRADIENT_SEGMENTS]
rbc_speed_segment_t segments[RBC_MAX_SPEED_SEGMENTS]
rbc_linking_item_t links[RBC_MAX_LINKING_ITEMS]
char text[RBC_MAX_TEXT_MESSAGE_LEN]