ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
nema_ts2.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file nema_ts2.cpp
6 * @brief NEMA TS 2 SDLC frame codec (see nema_ts2.h).
7 */
8
10#include "shared_primitives/crc.h" // PC_CRC16_X25
11
12#if PC_ENABLE_NEMA_TS2
13
14#include <string.h>
15
16uint16_t pc_nema_ts2_crc(const uint8_t *bytes, size_t len)
17{
18 // CRC-16/X-25: reflected poly 0x8408 (reverse of 0x1021), init 0xFFFF, xorout 0xFFFF. test_crc
19 // diffs the shared engine against the loop that used to live here over every length 0..64.
20 return (uint16_t)pc_crc(&PC_CRC16_X25, bytes, len);
21}
22
23size_t pc_nema_ts2_build(uint8_t address, uint8_t control, uint8_t frame_type, const uint8_t *data, size_t data_len,
24 uint8_t *out, size_t cap)
25{
26 if (!out || (data_len && !data))
27 {
28 return 0;
29 }
30 size_t n = 3 + data_len + 2;
31 if (n > cap)
32 {
33 return 0;
34 }
35 out[0] = address;
36 out[1] = control;
37 out[2] = frame_type;
38 if (data_len)
39 {
40 memcpy(out + 3, data, data_len);
41 }
42 uint16_t crc = pc_nema_ts2_crc(out, 3 + data_len);
43 out[3 + data_len] = (uint8_t)crc; // FCS low byte first
44 out[3 + data_len + 1] = (uint8_t)(crc >> 8);
45 return n;
46}
47
48bool pc_nema_ts2_parse(const uint8_t *frame, size_t len, NemaTs2Frame *out)
49{
50 if (!frame || !out || len < 5) // address + control + frame_type + 2-byte FCS
51 {
52 return false;
53 }
54 size_t body = len - 2;
55 uint16_t want = pc_nema_ts2_crc(frame, body);
56 uint16_t got = (uint16_t)(frame[body] | (frame[body + 1] << 8));
57 if (want != got)
58 {
59 return false;
60 }
61 out->address = frame[0];
62 out->control = frame[1];
63 out->frame_type = frame[2];
64 out->data = (body > 3) ? (frame + 3) : nullptr;
65 out->data_len = body - 3;
66 return true;
67}
68
69#endif // PC_ENABLE_NEMA_TS2
Parameterized CRC engine - one source of truth for every cyclic redundancy check.
constexpr pc_crc_params PC_CRC16_X25
CRC-16/X-25 (HDLC FCS). check = 0x906E. Used by services/radio/thread, mbplus, nema_ts2.
Definition crc.h:190
uint32_t pc_crc(const pc_crc_params *p, const uint8_t *data, size_t len)
One-shot CRC of len octets at data.
Definition crc.h:158
NEMA TS 2 traffic-cabinet SDLC frame codec (PC_ENABLE_NEMA_TS2).