ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
interbus.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 interbus.cpp
6 * @brief INTERBUS summation-frame codec (see interbus.h).
7 */
8
10
11#if PC_ENABLE_INTERBUS
12
13#include "shared_primitives/crc.h" // PC_CRC16_IBM_3740
14
15uint16_t pc_interbus_fcs(const uint8_t *bytes, size_t len)
16{
17 // CRC-16/CCITT-FALSE: poly 0x1021, init 0xFFFF, no reflection, xorout 0 - cataloged as
18 // CRC-16/IBM-3740. test_crc diffs the shared engine against the loop that used to live here
19 // over every length 0..64, so this is byte-identical to it.
20 return (uint16_t)pc_crc(&PC_CRC16_IBM_3740, bytes, len);
21}
22
23size_t pc_interbus_build(const uint16_t *words, size_t word_count, uint8_t *out, size_t cap)
24{
25 if (!out || (word_count && !words))
26 {
27 return 0;
28 }
29 size_t n = 2 + word_count * 2 + 2; // loopback + words + FCS
30 if (n > cap)
31 {
32 return 0;
33 }
34 size_t i = 0;
35 out[i++] = (uint8_t)(PC_INTERBUS_LOOPBACK >> 8);
36 out[i++] = (uint8_t)PC_INTERBUS_LOOPBACK;
37 for (size_t w = 0; w < word_count; w++)
38 {
39 out[i++] = (uint8_t)(words[w] >> 8); // big-endian
40 out[i++] = (uint8_t)words[w];
41 }
42 uint16_t crc = pc_interbus_fcs(out, i); // FCS over loopback + words
43 out[i++] = (uint8_t)(crc >> 8);
44 out[i++] = (uint8_t)crc;
45 return i;
46}
47
48bool pc_interbus_parse(const uint8_t *frame, size_t len, uint16_t *out_words, size_t max_words, size_t *out_count)
49{
50 if (!frame || !out_words || !out_count || len < 4) // loopback + FCS minimum
51 {
52 return false;
53 }
54 if (((frame[0] << 8) | frame[1]) != PC_INTERBUS_LOOPBACK)
55 {
56 return false;
57 }
58 if ((len - 4) % 2 != 0) // the words region must be whole 16-bit words
59 {
60 return false;
61 }
62 size_t word_count = (len - 4) / 2;
63 if (word_count > max_words)
64 {
65 return false;
66 }
67 uint16_t want = pc_interbus_fcs(frame, len - 2);
68 uint16_t got = (uint16_t)((frame[len - 2] << 8) | frame[len - 1]);
69 if (want != got)
70 {
71 return false;
72 }
73 for (size_t w = 0; w < word_count; w++)
74 {
75 out_words[w] = (uint16_t)((frame[2 + w * 2] << 8) | frame[2 + w * 2 + 1]);
76 }
77 *out_count = word_count;
78 return true;
79}
80
81#endif // PC_ENABLE_INTERBUS
Parameterized CRC engine - one source of truth for every cyclic redundancy check.
constexpr pc_crc_params PC_CRC16_IBM_3740
CRC-16/IBM-3740 (often called CCITT-FALSE). check = 0x29B1.
Definition crc.h:184
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
INTERBUS summation-frame fieldbus codec (PC_ENABLE_INTERBUS).