14 #ifndef SATCAT5_CRC_TABLE_BITS
15 #define SATCAT5_CRC_TABLE_BITS 8
20 #if SATCAT5_CRC_TABLE_BITS == 4
21 static const u16 TABLE_KERMIT[16] = {
22 0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387,
23 0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F,
26 static const u16 TABLE_XMODEM[16] = {
27 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
28 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
31 static inline void kermit_update(u16& crc, u8 next) {
32 u16 next1 = next >> 0;
33 u16 next2 = next >> 4;
34 u8 index1 = (crc ^ next1) & 0x0F;
35 crc = (crc >> 4) ^ TABLE_KERMIT[index1];
36 u8 index2 = (crc ^ next2) & 0x0F;
37 crc = (crc >> 4) ^ TABLE_KERMIT[index2];
40 static inline void xmodem_update(u16& crc, u8 next) {
41 u16 next1 = next >> 4;
42 u16 next2 = next >> 0;
43 u8 index1 = ((crc >> 12) ^ next1) & 0x0Ful;
44 crc = (crc << 4) ^ TABLE_XMODEM[index1];
45 u8 index2 = ((crc >> 12) ^ next2) & 0x0Ful;
46 crc = (crc << 4) ^ TABLE_XMODEM[index2];
49 inline u16 kermit_format(u16 crc) {
50 return __builtin_bswap16(crc);
53 inline u16 xmodem_format(u16 crc) {
60 #if SATCAT5_CRC_TABLE_BITS == 8
61 static const u16 TABLE_KERMIT[256] = {
62 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
63 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
64 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
65 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
66 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
67 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
68 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
69 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
70 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
71 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
72 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
73 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
74 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
75 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
76 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
77 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
78 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
79 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
80 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
81 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
82 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
83 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
84 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
85 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
86 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
87 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
88 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
89 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
90 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
91 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
92 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
93 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78,
96 static const u16 TABLE_XMODEM[256] = {
97 0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xA550, 0xC660, 0xE770,
98 0x0881, 0x2991, 0x4AA1, 0x6BB1, 0x8CC1, 0xADD1, 0xCEE1, 0xEFF1,
99 0x3112, 0x1002, 0x7332, 0x5222, 0xB552, 0x9442, 0xF772, 0xD662,
100 0x3993, 0x1883, 0x7BB3, 0x5AA3, 0xBDD3, 0x9CC3, 0xFFF3, 0xDEE3,
101 0x6224, 0x4334, 0x2004, 0x0114, 0xE664, 0xC774, 0xA444, 0x8554,
102 0x6AA5, 0x4BB5, 0x2885, 0x0995, 0xEEE5, 0xCFF5, 0xACC5, 0x8DD5,
103 0x5336, 0x7226, 0x1116, 0x3006, 0xD776, 0xF666, 0x9556, 0xB446,
104 0x5BB7, 0x7AA7, 0x1997, 0x3887, 0xDFF7, 0xFEE7, 0x9DD7, 0xBCC7,
105 0xC448, 0xE558, 0x8668, 0xA778, 0x4008, 0x6118, 0x0228, 0x2338,
106 0xCCC9, 0xEDD9, 0x8EE9, 0xAFF9, 0x4889, 0x6999, 0x0AA9, 0x2BB9,
107 0xF55A, 0xD44A, 0xB77A, 0x966A, 0x711A, 0x500A, 0x333A, 0x122A,
108 0xFDDB, 0xDCCB, 0xBFFB, 0x9EEB, 0x799B, 0x588B, 0x3BBB, 0x1AAB,
109 0xA66C, 0x877C, 0xE44C, 0xC55C, 0x222C, 0x033C, 0x600C, 0x411C,
110 0xAEED, 0x8FFD, 0xECCD, 0xCDDD, 0x2AAD, 0x0BBD, 0x688D, 0x499D,
111 0x977E, 0xB66E, 0xD55E, 0xF44E, 0x133E, 0x322E, 0x511E, 0x700E,
112 0x9FFF, 0xBEEF, 0xDDDF, 0xFCCF, 0x1BBF, 0x3AAF, 0x599F, 0x788F,
113 0x8891, 0xA981, 0xCAB1, 0xEBA1, 0x0CD1, 0x2DC1, 0x4EF1, 0x6FE1,
114 0x8010, 0xA100, 0xC230, 0xE320, 0x0450, 0x2540, 0x4670, 0x6760,
115 0xB983, 0x9893, 0xFBA3, 0xDAB3, 0x3DC3, 0x1CD3, 0x7FE3, 0x5EF3,
116 0xB102, 0x9012, 0xF322, 0xD232, 0x3542, 0x1452, 0x7762, 0x5672,
117 0xEAB5, 0xCBA5, 0xA895, 0x8985, 0x6EF5, 0x4FE5, 0x2CD5, 0x0DC5,
118 0xE234, 0xC324, 0xA014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544,
119 0xDBA7, 0xFAB7, 0x9987, 0xB897, 0x5FE7, 0x7EF7, 0x1DC7, 0x3CD7,
120 0xD326, 0xF236, 0x9106, 0xB016, 0x5766, 0x7676, 0x1546, 0x3456,
121 0x4CD9, 0x6DC9, 0x0EF9, 0x2FE9, 0xC899, 0xE989, 0x8AB9, 0xABA9,
122 0x4458, 0x6548, 0x0678, 0x2768, 0xC018, 0xE108, 0x8238, 0xA328,
123 0x7DCB, 0x5CDB, 0x3FEB, 0x1EFB, 0xF98B, 0xD89B, 0xBBAB, 0x9ABB,
124 0x754A, 0x545A, 0x376A, 0x167A, 0xF10A, 0xD01A, 0xB32A, 0x923A,
125 0x2EFD, 0x0FED, 0x6CDD, 0x4DCD, 0xAABD, 0x8BAD, 0xE89D, 0xC98D,
126 0x267C, 0x076C, 0x645C, 0x454C, 0xA23C, 0x832C, 0xE01C, 0xC10C,
127 0x1FEF, 0x3EFF, 0x5DCF, 0x7CDF, 0x9BAF, 0xBABF, 0xD98F, 0xF89F,
128 0x176E, 0x367E, 0x554E, 0x745E, 0x932E, 0xB23E, 0xD10E, 0xF01E,
131 static inline void kermit_update(u16& crc, u8 next) {
132 u8 index = (crc ^ (u16)next) & 0xFFul;
133 crc = (crc >> 8) ^ TABLE_KERMIT[index];
136 static inline void xmodem_update(u16& crc, u8 next) {
137 u8 index = (crc ^ (u16)next) & 0xFFul;
138 crc = (crc >> 8) ^ TABLE_XMODEM[index];
141 inline u16 kermit_format(u16 crc) {
142 return __builtin_bswap16(crc);
145 inline u16 xmodem_format(u16 crc) {
146 return __builtin_bswap16(crc);
153 const u8* data8 = (
const u8*)data;
155 for (
unsigned a = 0 ; a < nbytes ; ++a)
156 kermit_update(crc, data8[a]);
157 return kermit_format(crc);
162 const u8* data8 = (
const u8*)data;
164 for (
unsigned a = 0 ; a < nbytes ; ++a)
165 xmodem_update(crc, data8[a]);
166 return xmodem_format(crc);
170 : satcat5::io::ChecksumTx<u16,2>(dst, init)
176 bool KermitTx::write_finalize() {
177 u16 fcs = kermit_format(m_chk ^ m_xorout);
178 m_dst->write_u16(fcs);
179 return chk_finalize() && m_dst->write_finalize();
182 void KermitTx::write_next(u8 data) {
184 kermit_update(m_chk, data);
185 m_dst->write_u8(data);
189 : satcat5::io::ChecksumRx<u16,2>(dst, init)
204 : satcat5::io::ChecksumTx<u16,2>(dst, init)
211 u16 fcs = xmodem_format(
m_chk ^ m_xorout);
212 m_dst->write_u16(fcs);
218 xmodem_update(
m_chk, data);
223 : satcat5::io::ChecksumRx<u16,2>(dst, init)
Check and remove FCS from each incoming frame ("KERMIT" variant).
void write_next(u8 data) override
Write the next byte to the underlying buffer or device.
bool write_finalize() override
Mark end of frame and release temporary working data.
Append FCS to each outgoing frame ("KERMIT" variant).
Check and remove FCS from each incoming frame ("XMODEM" variant).
void write_next(u8 data) override
Write the next byte to the underlying buffer or device.
bool write_finalize() override
Mark end of frame and release temporary working data.
Append FCS to each outgoing frame ("XMODEM" variant).
void write_next(u8 data) override
Write the next byte to the underlying buffer or device.
bool write_finalize() override
Mark end of frame and release temporary working data.
bool sreg_match(u16 fcs)
Child class MUST call sreg_match(...) during write_finalize().
bool sreg_push(u8 &data)
Child class MUST call sreg_push(...) during write_next().
bool chk_finalize()
Reset internal state and return true if the frame is valid.
satcat5::io::Writeable *const m_dst
Output object.
unsigned m_frm_len
Length of current frame.
Abstract API for writing byte-streams and packets.
void write_u8(u8 data)
One of many functions for writing integer/floating point values, see details.
virtual bool write_finalize()
Mark end of frame and release temporary working data.
Inline CRC16 Checksum insertion and verification.
u16 xmodem(unsigned nbytes, const void *data)
Directly calculate CRC16 on a block of data.
u16 kermit(unsigned nbytes, const void *data)
Directly calculate CRC16 on a block of data.