mirror of
https://github.com/g4klx/MMDVMHost.git
synced 2025-12-06 05:32:00 +01:00
Add the LICH CRC.
This commit is contained in:
parent
242cf50240
commit
0a94b0deb6
75
M17CRC.cpp
75
M17CRC.cpp
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020,2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
const uint16_t CRC_TABLE[] = {0x0000U, 0x5935U, 0xB26AU, 0xEB5FU, 0x3DE1U, 0x64D4U, 0x8F8BU, 0xD6BEU, 0x7BC2U, 0x22F7U, 0xC9A8U,
|
||||
const uint16_t CRC16_TABLE[] = {0x0000U, 0x5935U, 0xB26AU, 0xEB5FU, 0x3DE1U, 0x64D4U, 0x8F8BU, 0xD6BEU, 0x7BC2U, 0x22F7U, 0xC9A8U,
|
||||
0x909DU, 0x4623U, 0x1F16U, 0xF449U, 0xAD7CU, 0xF784U, 0xAEB1U, 0x45EEU, 0x1CDBU, 0xCA65U, 0x9350U,
|
||||
0x780FU, 0x213AU, 0x8C46U, 0xD573U, 0x3E2CU, 0x6719U, 0xB1A7U, 0xE892U, 0x03CDU, 0x5AF8U, 0xB63DU,
|
||||
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
|
|||
0xAC02U, 0xF537U, 0x2389U, 0x7ABCU, 0x91E3U, 0xC8D6U, 0x65AAU, 0x3C9FU, 0xD7C0U, 0x8EF5U, 0x584BU,
|
||||
0x017EU, 0xEA21U, 0xB314U};
|
||||
|
||||
bool CM17CRC::checkCRC(const unsigned char* in, unsigned int nBytes)
|
||||
const uint8_t CRC4_TABLE[] = {
|
||||
0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc, 0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6,
|
||||
0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1, 0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb,
|
||||
0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf, 0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5,
|
||||
0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2, 0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8,
|
||||
0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa, 0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0,
|
||||
0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7, 0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd,
|
||||
0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9, 0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3,
|
||||
0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4, 0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe,
|
||||
0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0, 0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa,
|
||||
0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd, 0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7,
|
||||
0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3, 0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9,
|
||||
0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe, 0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4,
|
||||
0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6, 0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc,
|
||||
0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb, 0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1,
|
||||
0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5, 0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf,
|
||||
0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8, 0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2};
|
||||
|
||||
bool CM17CRC::checkCRC16(const unsigned char* in, unsigned int nBytes)
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(nBytes > 2U);
|
||||
|
||||
uint16_t crc = createCRC(in, nBytes - 2U);
|
||||
uint16_t crc = createCRC16(in, nBytes - 2U);
|
||||
|
||||
uint8_t temp[2U];
|
||||
temp[0U] = (crc >> 8) & 0xFFU;
|
||||
|
|
@ -60,26 +78,67 @@ bool CM17CRC::checkCRC(const unsigned char* in, unsigned int nBytes)
|
|||
return temp[0U] == in[nBytes - 2U] && temp[1U] == in[nBytes - 1U];
|
||||
}
|
||||
|
||||
void CM17CRC::encodeCRC(unsigned char* in, unsigned int nBytes)
|
||||
void CM17CRC::encodeCRC16(unsigned char* in, unsigned int nBytes)
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(nBytes > 2U);
|
||||
|
||||
uint16_t crc = createCRC(in, nBytes - 2U);
|
||||
uint16_t crc = createCRC16(in, nBytes - 2U);
|
||||
|
||||
in[nBytes - 2U] = (crc >> 8) & 0xFFU;
|
||||
in[nBytes - 1U] = (crc >> 0) & 0xFFU;
|
||||
}
|
||||
|
||||
uint16_t CM17CRC::createCRC(const unsigned char* in, unsigned int nBytes)
|
||||
uint16_t CM17CRC::createCRC16(const unsigned char* in, unsigned int nBytes)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = 0xFFFFU;
|
||||
|
||||
for (unsigned int i = 0U; i < nBytes; i++)
|
||||
crc = (crc << 8) ^ CRC_TABLE[((crc >> 8) ^ uint16_t(in[i])) & 0x00FFU];
|
||||
crc = (crc << 8) ^ CRC16_TABLE[((crc >> 8) ^ uint16_t(in[i])) & 0x00FFU];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
bool CM17CRC::checkCRC8(unsigned char* in, unsigned int nBytes)
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(nBytes > 1U);
|
||||
|
||||
uint8_t save = in[nBytes - 1U] & 0x0FU;
|
||||
|
||||
// Mask out the 4-bit CRC location
|
||||
in[nBytes - 1U] &= 0xF0U;
|
||||
|
||||
uint8_t crc = createCRC8(in, nBytes);
|
||||
|
||||
// Restore the original CRC
|
||||
in[nBytes - 1U] |= save;
|
||||
|
||||
return save == crc;
|
||||
}
|
||||
|
||||
void CM17CRC::encodeCRC8(unsigned char* in, unsigned int nBytes)
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(nBytes > 1U);
|
||||
|
||||
in[nBytes - 1U] &= 0xF0U;
|
||||
|
||||
uint8_t crc = createCRC8(in, nBytes);
|
||||
|
||||
in[nBytes - 1U] |= crc & 0x0FU;
|
||||
}
|
||||
|
||||
uint8_t CM17CRC::createCRC8(const unsigned char* in, unsigned int nBytes)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint8_t crc = 0x0FU;
|
||||
|
||||
for (unsigned int i = 0U; i < nBytes; i++)
|
||||
crc = CRC4_TABLE[crc ^ in[i]];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
|
|
|||
12
M17CRC.h
12
M17CRC.h
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020,2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -24,11 +24,15 @@
|
|||
class CM17CRC
|
||||
{
|
||||
public:
|
||||
static bool checkCRC(const unsigned char* in, unsigned int nBytes);
|
||||
static void encodeCRC(unsigned char* in, unsigned int nBytes);
|
||||
static bool checkCRC16(const unsigned char* in, unsigned int nBytes);
|
||||
static void encodeCRC16(unsigned char* in, unsigned int nBytes);
|
||||
|
||||
static bool checkCRC8(unsigned char* in, unsigned int nBytes);
|
||||
static void encodeCRC8(unsigned char* in, unsigned int nBytes);
|
||||
|
||||
private:
|
||||
static uint16_t createCRC(const unsigned char* in, unsigned int nBytes);
|
||||
static uint16_t createCRC16(const unsigned char* in, unsigned int nBytes);
|
||||
static uint8_t createCRC8(const unsigned char* in, unsigned int nBytes);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
|
|||
unsigned char frame[M17_LSF_LENGTH_BYTES];
|
||||
conv.decodeLinkSetup(data + 2U + M17_SYNC_LENGTH_BYTES, frame);
|
||||
|
||||
bool valid = CM17CRC::checkCRC(frame, M17_LSF_LENGTH_BYTES);
|
||||
bool valid = CM17CRC::checkCRC16(frame, M17_LSF_LENGTH_BYTES);
|
||||
if (valid) {
|
||||
m_rfLSF.setLinkSetup(frame);
|
||||
|
||||
|
|
@ -196,6 +196,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
|
|||
return true;
|
||||
} else {
|
||||
m_rfState = RS_RF_LATE_ENTRY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -216,6 +217,9 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
|
|||
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
|
||||
CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich);
|
||||
|
||||
if (!CM17CRC::checkCRC8(lich, M17_LICH_FRAGMENT_LENGTH_BYTES))
|
||||
return false;
|
||||
|
||||
m_rfLSFn = (lich4 >> 5) & 0x07U;
|
||||
m_rfLSF.setFragment(lich, m_rfLSFn);
|
||||
|
||||
|
|
@ -253,7 +257,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
|
|||
unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
|
||||
conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame);
|
||||
|
||||
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
|
||||
bool valid = CM17CRC::checkCRC16(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
|
||||
if (valid) {
|
||||
m_rfFN = (frame[0U] << 8) + (frame[1U] << 0);
|
||||
} else {
|
||||
|
|
@ -279,7 +283,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
|
|||
}
|
||||
|
||||
// Add the CRC
|
||||
CM17CRC::encodeCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
|
||||
CM17CRC::encodeCRC16(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
|
||||
}
|
||||
|
||||
unsigned char rfData[2U + M17_FRAME_LENGTH_BYTES];
|
||||
|
|
@ -293,12 +297,15 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
|
|||
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
|
||||
m_rfLSF.getFragment(lich, m_rfLSFn);
|
||||
|
||||
// Add the fragment number
|
||||
lich[5U] = (m_rfLSFn & 0x07U) << 5;
|
||||
|
||||
// Add the CRC
|
||||
CM17CRC::encodeCRC8(lich, M17_LICH_FRAGMENT_LENGTH_BYTES);
|
||||
|
||||
unsigned int frag1, frag2, frag3, frag4;
|
||||
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);
|
||||
|
||||
// Add the fragment number
|
||||
frag4 |= (m_rfLSFn & 0x07U) << 5;
|
||||
|
||||
// Add Golay to the LICH fragment here
|
||||
unsigned int lich1 = CGolay24128::encode24128(frag1);
|
||||
unsigned int lich2 = CGolay24128::encode24128(frag2);
|
||||
|
|
@ -362,11 +369,9 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
|
|||
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));
|
||||
writeEndRF();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int CM17Control::readModem(unsigned char* data)
|
||||
|
|
@ -511,15 +516,18 @@ void CM17Control::writeNetwork()
|
|||
m_netFrames++;
|
||||
|
||||
// Add the fragment LICH
|
||||
unsigned char lich[M17_LSF_FRAGMENT_LENGTH_BYTES];
|
||||
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
|
||||
m_netLSF.getFragment(lich, m_netLSFn);
|
||||
|
||||
// Add the fragment number
|
||||
lich[5U] = (m_netLSFn & 0x07U) << 5;
|
||||
|
||||
// Add the CRC
|
||||
CM17CRC::encodeCRC8(lich, M17_LICH_FRAGMENT_LENGTH_BYTES);
|
||||
|
||||
unsigned int frag1, frag2, frag3, frag4;
|
||||
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);
|
||||
|
||||
// Add the fragment number
|
||||
frag4 |= (m_netLSFn & 0x07U) << 4;
|
||||
|
||||
// Add Golay to the LICH fragment here
|
||||
unsigned int lich1 = CGolay24128::encode24128(frag1);
|
||||
unsigned int lich2 = CGolay24128::encode24128(frag2);
|
||||
|
|
@ -533,7 +541,7 @@ void CM17Control::writeNetwork()
|
|||
::memcpy(payload, netData + 28U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);
|
||||
|
||||
// Add the CRC
|
||||
CM17CRC::encodeCRC(payload, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
|
||||
CM17CRC::encodeCRC16(payload, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
|
||||
|
||||
// Add the Convolution FEC
|
||||
CM17Convolution conv;
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ void CM17LSF::getLinkSetup(unsigned char* data) const
|
|||
|
||||
::memcpy(data, m_lsf, M17_LSF_LENGTH_BYTES);
|
||||
|
||||
CM17CRC::encodeCRC(data, M17_LSF_LENGTH_BYTES);
|
||||
CM17CRC::encodeCRC16(data, M17_LSF_LENGTH_BYTES);
|
||||
}
|
||||
|
||||
void CM17LSF::setLinkSetup(const unsigned char* data)
|
||||
|
|
@ -171,14 +171,14 @@ void CM17LSF::setLinkSetup(const unsigned char* data)
|
|||
|
||||
::memcpy(m_lsf, data, M17_LSF_LENGTH_BYTES);
|
||||
|
||||
m_valid = CM17CRC::checkCRC(m_lsf, M17_LSF_LENGTH_BYTES);
|
||||
m_valid = CM17CRC::checkCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
|
||||
}
|
||||
|
||||
void CM17LSF::getFragment(unsigned char* data, unsigned int n) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
CM17CRC::encodeCRC(m_lsf, M17_LSF_LENGTH_BYTES);
|
||||
CM17CRC::encodeCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
|
||||
|
||||
::memcpy(data, m_lsf + (n * M17_LSF_FRAGMENT_LENGTH_BYTES), M17_LSF_FRAGMENT_LENGTH_BYTES);
|
||||
}
|
||||
|
|
@ -189,5 +189,5 @@ void CM17LSF::setFragment(const unsigned char* data, unsigned int n)
|
|||
|
||||
::memcpy(m_lsf + (n * M17_LSF_FRAGMENT_LENGTH_BYTES), data, M17_LSF_FRAGMENT_LENGTH_BYTES);
|
||||
|
||||
m_valid = CM17CRC::checkCRC(m_lsf, M17_LSF_LENGTH_BYTES);
|
||||
m_valid = CM17CRC::checkCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue