Skip to content

Commit 0a94b0d

Browse files
committed
Add the LICH CRC.
1 parent 242cf50 commit 0a94b0d

File tree

4 files changed

+101
-30
lines changed

4 files changed

+101
-30
lines changed

M17CRC.cpp

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2020 by Jonathan Naylor G4KLX
2+
* Copyright (C) 2020,2021 by Jonathan Naylor G4KLX
33
*
44
* This program is free software; you can redistribute it and/or modify
55
* it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
2121
#include <cstdio>
2222
#include <cassert>
2323

24-
const uint16_t CRC_TABLE[] = {0x0000U, 0x5935U, 0xB26AU, 0xEB5FU, 0x3DE1U, 0x64D4U, 0x8F8BU, 0xD6BEU, 0x7BC2U, 0x22F7U, 0xC9A8U,
24+
const uint16_t CRC16_TABLE[] = {0x0000U, 0x5935U, 0xB26AU, 0xEB5FU, 0x3DE1U, 0x64D4U, 0x8F8BU, 0xD6BEU, 0x7BC2U, 0x22F7U, 0xC9A8U,
2525
0x909DU, 0x4623U, 0x1F16U, 0xF449U, 0xAD7CU, 0xF784U, 0xAEB1U, 0x45EEU, 0x1CDBU, 0xCA65U, 0x9350U,
2626
0x780FU, 0x213AU, 0x8C46U, 0xD573U, 0x3E2CU, 0x6719U, 0xB1A7U, 0xE892U, 0x03CDU, 0x5AF8U, 0xB63DU,
2727
0xEF08U, 0x0457U, 0x5D62U, 0x8BDCU, 0xD2E9U, 0x39B6U, 0x6083U, 0xCDFFU, 0x94CAU, 0x7F95U, 0x26A0U,
@@ -46,12 +46,30 @@ const uint16_t CRC_TABLE[] = {0x0000U, 0x5935U, 0xB26AU, 0xEB5FU, 0x3DE1U, 0x64D
4646
0xAC02U, 0xF537U, 0x2389U, 0x7ABCU, 0x91E3U, 0xC8D6U, 0x65AAU, 0x3C9FU, 0xD7C0U, 0x8EF5U, 0x584BU,
4747
0x017EU, 0xEA21U, 0xB314U};
4848

49-
bool CM17CRC::checkCRC(const unsigned char* in, unsigned int nBytes)
49+
const uint8_t CRC4_TABLE[] = {
50+
0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc, 0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6,
51+
0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1, 0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb,
52+
0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf, 0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5,
53+
0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2, 0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8,
54+
0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa, 0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0,
55+
0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7, 0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd,
56+
0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9, 0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3,
57+
0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4, 0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe,
58+
0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0, 0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa,
59+
0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd, 0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7,
60+
0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3, 0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9,
61+
0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe, 0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4,
62+
0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6, 0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc,
63+
0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb, 0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1,
64+
0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5, 0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf,
65+
0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8, 0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2};
66+
67+
bool CM17CRC::checkCRC16(const unsigned char* in, unsigned int nBytes)
5068
{
5169
assert(in != NULL);
5270
assert(nBytes > 2U);
5371

54-
uint16_t crc = createCRC(in, nBytes - 2U);
72+
uint16_t crc = createCRC16(in, nBytes - 2U);
5573

5674
uint8_t temp[2U];
5775
temp[0U] = (crc >> 8) & 0xFFU;
@@ -60,26 +78,67 @@ bool CM17CRC::checkCRC(const unsigned char* in, unsigned int nBytes)
6078
return temp[0U] == in[nBytes - 2U] && temp[1U] == in[nBytes - 1U];
6179
}
6280

63-
void CM17CRC::encodeCRC(unsigned char* in, unsigned int nBytes)
81+
void CM17CRC::encodeCRC16(unsigned char* in, unsigned int nBytes)
6482
{
6583
assert(in != NULL);
6684
assert(nBytes > 2U);
6785

68-
uint16_t crc = createCRC(in, nBytes - 2U);
86+
uint16_t crc = createCRC16(in, nBytes - 2U);
6987

7088
in[nBytes - 2U] = (crc >> 8) & 0xFFU;
7189
in[nBytes - 1U] = (crc >> 0) & 0xFFU;
7290
}
7391

74-
uint16_t CM17CRC::createCRC(const unsigned char* in, unsigned int nBytes)
92+
uint16_t CM17CRC::createCRC16(const unsigned char* in, unsigned int nBytes)
7593
{
7694
assert(in != NULL);
7795

7896
uint16_t crc = 0xFFFFU;
7997

8098
for (unsigned int i = 0U; i < nBytes; i++)
81-
crc = (crc << 8) ^ CRC_TABLE[((crc >> 8) ^ uint16_t(in[i])) & 0x00FFU];
99+
crc = (crc << 8) ^ CRC16_TABLE[((crc >> 8) ^ uint16_t(in[i])) & 0x00FFU];
82100

83101
return crc;
84102
}
85103

104+
bool CM17CRC::checkCRC8(unsigned char* in, unsigned int nBytes)
105+
{
106+
assert(in != NULL);
107+
assert(nBytes > 1U);
108+
109+
uint8_t save = in[nBytes - 1U] & 0x0FU;
110+
111+
// Mask out the 4-bit CRC location
112+
in[nBytes - 1U] &= 0xF0U;
113+
114+
uint8_t crc = createCRC8(in, nBytes);
115+
116+
// Restore the original CRC
117+
in[nBytes - 1U] |= save;
118+
119+
return save == crc;
120+
}
121+
122+
void CM17CRC::encodeCRC8(unsigned char* in, unsigned int nBytes)
123+
{
124+
assert(in != NULL);
125+
assert(nBytes > 1U);
126+
127+
in[nBytes - 1U] &= 0xF0U;
128+
129+
uint8_t crc = createCRC8(in, nBytes);
130+
131+
in[nBytes - 1U] |= crc & 0x0FU;
132+
}
133+
134+
uint8_t CM17CRC::createCRC8(const unsigned char* in, unsigned int nBytes)
135+
{
136+
assert(in != NULL);
137+
138+
uint8_t crc = 0x0FU;
139+
140+
for (unsigned int i = 0U; i < nBytes; i++)
141+
crc = CRC4_TABLE[crc ^ in[i]];
142+
143+
return crc;
144+
}

M17CRC.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2020 by Jonathan Naylor G4KLX
2+
* Copyright (C) 2020,2021 by Jonathan Naylor G4KLX
33
*
44
* This program is free software; you can redistribute it and/or modify
55
* it under the terms of the GNU General Public License as published by
@@ -24,11 +24,15 @@
2424
class CM17CRC
2525
{
2626
public:
27-
static bool checkCRC(const unsigned char* in, unsigned int nBytes);
28-
static void encodeCRC(unsigned char* in, unsigned int nBytes);
27+
static bool checkCRC16(const unsigned char* in, unsigned int nBytes);
28+
static void encodeCRC16(unsigned char* in, unsigned int nBytes);
29+
30+
static bool checkCRC8(unsigned char* in, unsigned int nBytes);
31+
static void encodeCRC8(unsigned char* in, unsigned int nBytes);
2932

3033
private:
31-
static uint16_t createCRC(const unsigned char* in, unsigned int nBytes);
34+
static uint16_t createCRC16(const unsigned char* in, unsigned int nBytes);
35+
static uint8_t createCRC8(const unsigned char* in, unsigned int nBytes);
3236
};
3337

3438
#endif

M17Control.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
169169
unsigned char frame[M17_LSF_LENGTH_BYTES];
170170
conv.decodeLinkSetup(data + 2U + M17_SYNC_LENGTH_BYTES, frame);
171171

172-
bool valid = CM17CRC::checkCRC(frame, M17_LSF_LENGTH_BYTES);
172+
bool valid = CM17CRC::checkCRC16(frame, M17_LSF_LENGTH_BYTES);
173173
if (valid) {
174174
m_rfLSF.setLinkSetup(frame);
175175

@@ -196,6 +196,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
196196
return true;
197197
} else {
198198
m_rfState = RS_RF_LATE_ENTRY;
199+
return false;
199200
}
200201
}
201202

@@ -216,6 +217,9 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
216217
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
217218
CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich);
218219

220+
if (!CM17CRC::checkCRC8(lich, M17_LICH_FRAGMENT_LENGTH_BYTES))
221+
return false;
222+
219223
m_rfLSFn = (lich4 >> 5) & 0x07U;
220224
m_rfLSF.setFragment(lich, m_rfLSFn);
221225

@@ -253,7 +257,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
253257
unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
254258
conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame);
255259

256-
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
260+
bool valid = CM17CRC::checkCRC16(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
257261
if (valid) {
258262
m_rfFN = (frame[0U] << 8) + (frame[1U] << 0);
259263
} else {
@@ -279,7 +283,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
279283
}
280284

281285
// Add the CRC
282-
CM17CRC::encodeCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
286+
CM17CRC::encodeCRC16(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
283287
}
284288

285289
unsigned char rfData[2U + M17_FRAME_LENGTH_BYTES];
@@ -293,12 +297,15 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
293297
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
294298
m_rfLSF.getFragment(lich, m_rfLSFn);
295299

300+
// Add the fragment number
301+
lich[5U] = (m_rfLSFn & 0x07U) << 5;
302+
303+
// Add the CRC
304+
CM17CRC::encodeCRC8(lich, M17_LICH_FRAGMENT_LENGTH_BYTES);
305+
296306
unsigned int frag1, frag2, frag3, frag4;
297307
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);
298308

299-
// Add the fragment number
300-
frag4 |= (m_rfLSFn & 0x07U) << 5;
301-
302309
// Add Golay to the LICH fragment here
303310
unsigned int lich1 = CGolay24128::encode24128(frag1);
304311
unsigned int lich2 = CGolay24128::encode24128(frag2);
@@ -362,11 +369,9 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
362369
LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits));
363370
writeEndRF();
364371
}
365-
366-
return true;
367372
}
368373

369-
return false;
374+
return true;
370375
}
371376

372377
unsigned int CM17Control::readModem(unsigned char* data)
@@ -511,15 +516,18 @@ void CM17Control::writeNetwork()
511516
m_netFrames++;
512517

513518
// Add the fragment LICH
514-
unsigned char lich[M17_LSF_FRAGMENT_LENGTH_BYTES];
519+
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
515520
m_netLSF.getFragment(lich, m_netLSFn);
516521

522+
// Add the fragment number
523+
lich[5U] = (m_netLSFn & 0x07U) << 5;
524+
525+
// Add the CRC
526+
CM17CRC::encodeCRC8(lich, M17_LICH_FRAGMENT_LENGTH_BYTES);
527+
517528
unsigned int frag1, frag2, frag3, frag4;
518529
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);
519530

520-
// Add the fragment number
521-
frag4 |= (m_netLSFn & 0x07U) << 4;
522-
523531
// Add Golay to the LICH fragment here
524532
unsigned int lich1 = CGolay24128::encode24128(frag1);
525533
unsigned int lich2 = CGolay24128::encode24128(frag2);
@@ -533,7 +541,7 @@ void CM17Control::writeNetwork()
533541
::memcpy(payload, netData + 28U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);
534542

535543
// Add the CRC
536-
CM17CRC::encodeCRC(payload, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
544+
CM17CRC::encodeCRC16(payload, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
537545

538546
// Add the Convolution FEC
539547
CM17Convolution conv;

M17LSF.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ void CM17LSF::getLinkSetup(unsigned char* data) const
162162

163163
::memcpy(data, m_lsf, M17_LSF_LENGTH_BYTES);
164164

165-
CM17CRC::encodeCRC(data, M17_LSF_LENGTH_BYTES);
165+
CM17CRC::encodeCRC16(data, M17_LSF_LENGTH_BYTES);
166166
}
167167

168168
void CM17LSF::setLinkSetup(const unsigned char* data)
@@ -171,14 +171,14 @@ void CM17LSF::setLinkSetup(const unsigned char* data)
171171

172172
::memcpy(m_lsf, data, M17_LSF_LENGTH_BYTES);
173173

174-
m_valid = CM17CRC::checkCRC(m_lsf, M17_LSF_LENGTH_BYTES);
174+
m_valid = CM17CRC::checkCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
175175
}
176176

177177
void CM17LSF::getFragment(unsigned char* data, unsigned int n) const
178178
{
179179
assert(data != NULL);
180180

181-
CM17CRC::encodeCRC(m_lsf, M17_LSF_LENGTH_BYTES);
181+
CM17CRC::encodeCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
182182

183183
::memcpy(data, m_lsf + (n * M17_LSF_FRAGMENT_LENGTH_BYTES), M17_LSF_FRAGMENT_LENGTH_BYTES);
184184
}
@@ -189,5 +189,5 @@ void CM17LSF::setFragment(const unsigned char* data, unsigned int n)
189189

190190
::memcpy(m_lsf + (n * M17_LSF_FRAGMENT_LENGTH_BYTES), data, M17_LSF_FRAGMENT_LENGTH_BYTES);
191191

192-
m_valid = CM17CRC::checkCRC(m_lsf, M17_LSF_LENGTH_BYTES);
192+
m_valid = CM17CRC::checkCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
193193
}

0 commit comments

Comments
 (0)