proper implementation for P25 confirmed PDU CRC-9;

pull/1/head
Bryan Biedenkapp 5 years ago
parent 9694600e1f
commit cfe4c99478

@ -68,20 +68,21 @@ const uint8_t CRC8_TABLE[] = {
0xFA, 0xFD, 0xF4, 0xF3, 0x01 };
const uint16_t CRC9_TABLE[] = {
0x1E7, 0x1F3, 0x1F9, 0x1FC, 0x0D2, 0x045, 0x122, 0x0BD, 0x15E, 0x083,
0x141, 0x1A0, 0x0FC, 0x052, 0x005, 0x102, 0x0AD, 0x156, 0x087, 0x143,
0x1A1, 0x1D0, 0x0C4, 0x04E, 0x00B, 0x105, 0x182, 0x0ED, 0x176, 0x097,
0x14B, 0x1A5, 0x1D2, 0x0C5, 0x162, 0x09D, 0x14E, 0x08B, 0x145, 0x1A2,
0x0FD, 0x17E, 0x093, 0x149, 0x1A4, 0x0FE, 0x053, 0x129, 0x194, 0x0E6,
0x05F, 0x12F, 0x197, 0x1CB, 0x1E5, 0x1F2, 0x0D5, 0x16A, 0x099, 0x14C,
0x08A, 0x069, 0x134, 0x0B6, 0x077, 0x13B, 0x19D, 0x1CE, 0x0CB, 0x165,
0x1B2, 0x0F5, 0x17A, 0x091, 0x148, 0x088, 0x068, 0x018, 0x020, 0x03C,
0x032, 0x035, 0x11A, 0x0A1, 0x150, 0x084, 0x06E, 0x01B, 0x10D, 0x186,
0x0EF, 0x177, 0x1BB, 0x1DD, 0x1EE, 0x0DB, 0x16D, 0x1B6, 0x0F7, 0x17B,
0x1BD, 0x1DE, 0x0C3, 0x161, 0x1B0, 0x0F4, 0x056, 0x007, 0x103, 0x181,
0x1C0, 0x0CC, 0x04A, 0x009, 0x104, 0x0AE, 0x07B, 0x13D, 0x19E, 0x0E3,
0x171, 0x1B8, 0x0F0, 0x054, 0x006, 0x02F, 0x117, 0x18B, 0x1C5, 0x1E2,
0x0DD, 0x16E, 0x09B, 0x14D, 0x1A6 };
0x1E7U, 0x1F3U, 0x1F9U, 0x1FCU, 0x0D2U, 0x045U, 0x122U, 0x0BDU, 0x15EU, 0x083,
0x141U, 0x1A0U, 0x0FCU, 0x052U, 0x005U, 0x102U, 0x0ADU, 0x156U, 0x087U, 0x143,
0x1A1U, 0x1D0U, 0x0C4U, 0x04EU, 0x00BU, 0x105U, 0x182U, 0x0EDU, 0x176U, 0x097,
0x14BU, 0x1A5U, 0x1D2U, 0x0C5U, 0x162U, 0x09DU, 0x14EU, 0x08BU, 0x145U, 0x1A2,
0x0FDU, 0x17EU, 0x093U, 0x149U, 0x1A4U, 0x0FEU, 0x053U, 0x129U, 0x194U, 0x0E6,
0x05FU, 0x12FU, 0x197U, 0x1CBU, 0x1E5U, 0x1F2U, 0x0D5U, 0x16AU, 0x099U, 0x14C,
0x08AU, 0x069U, 0x134U, 0x0B6U, 0x077U, 0x13BU, 0x19DU, 0x1CEU, 0x0CBU, 0x165,
0x1B2U, 0x0F5U, 0x17AU, 0x091U, 0x148U, 0x088U, 0x068U, 0x018U, 0x020U, 0x03C,
0x032U, 0x035U, 0x11AU, 0x0A1U, 0x150U, 0x084U, 0x06EU, 0x01BU, 0x10DU, 0x186,
0x0EFU, 0x177U, 0x1BBU, 0x1DDU, 0x1EEU, 0x0DBU, 0x16DU, 0x1B6U, 0x0F7U, 0x17B,
0x1BDU, 0x1DEU, 0x0C3U, 0x161U, 0x1B0U, 0x0F4U, 0x056U, 0x007U, 0x103U, 0x181,
0x1C0U, 0x0CCU, 0x04AU, 0x009U, 0x104U, 0x0AEU, 0x07BU, 0x13DU, 0x19EU, 0x0E3,
0x171U, 0x1B8U, 0x0F0U, 0x054U, 0x006U, 0x02FU, 0x117U, 0x18BU, 0x1C5U, 0x1E2,
0x0DDU, 0x16EU, 0x09BU, 0x14DU, 0x1A6U
};
const uint16_t CCITT16_TABLE1[] = {
0x0000U, 0x1189U, 0x2312U, 0x329bU, 0x4624U, 0x57adU, 0x6536U, 0x74bfU,
@ -409,21 +410,24 @@ uint8_t CRC::crc8(const uint8_t *in, uint32_t length)
/// Generate 9-bit CRC.
/// </summary>
/// <param name="in">Input byte array.</param>
/// <param name="length">Length of byte array (in bits).</param>
/// <param name="bitlen">Length of byte array in bits.</param>
/// <returns>Calculated 9-bit CRC value.</returns>
uint16_t CRC::crc9(const uint8_t* in, uint32_t length)
uint16_t CRC::crc9(const uint8_t* in, uint32_t bitlen)
{
assert(in != NULL);
uint16_t crc = 0U;
uint16_t crc = 0x00U;
uint32_t n = 0U;
for (uint32_t i = 0U; i < length; i++, n++) {
bool bit = READ_BIT(in, n);
if (bit) {
for (uint32_t i = 0; i < bitlen; i++) {
bool b = READ_BIT(in, i);
if (b) {
crc ^= CRC9_TABLE[i];
}
}
crc = ~crc;
crc &= 0x1FFU;
crc ^= 0x1FFU;
return crc;
}

@ -64,7 +64,8 @@ namespace edac
/// <summary>Generate 8-bit CRC.</summary>
static uint8_t crc8(const uint8_t* in, uint32_t length);
/// <summary>Generate 9-bit CRC.</summary>
/// <summary></summary>
static uint16_t crc9(const uint8_t* in, uint32_t length);
};
} // namespace edac

@ -92,15 +92,17 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader header)
return false;
}
// determine the number of user data bytes
uint32_t count = P25_PDU_CONFIRMED_DATA_LENGTH_BYTES;
if (m_serialNo == (header.getBlocksToFollow() - 1) ||
(m_headerSap == PDU_SAP_EXT_ADDR && m_serialNo == 0U))
count = P25_PDU_CONFIRMED_DATA_LENGTH_BYTES - 4U;
// Utils::dump(1U, "PDU Confirmed Data Block", buffer, P25_PDU_CONFIRMED_LENGTH_BYTES);
m_serialNo = (buffer[0] & 0xFEU) >> 1; // Confirmed Data Serial No.
uint16_t crc = ((buffer[0] & 0x01U) << 8) + buffer[1]; // CRC-9 Check Sum
uint32_t count = P25_PDU_CONFIRMED_LENGTH_BYTES;
if (m_serialNo == (header.getBlocksToFollow() - 1))
count = P25_PDU_CONFIRMED_LENGTH_BYTES - 4U;
::memset(m_data, 0x00U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
// if this is extended addressing and the first block decode the SAP and LLId
@ -119,14 +121,10 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader header)
}
}
// compute CRC-9 for the packet
uint8_t crcBuffer[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U];
::memset(crcBuffer, 0x00U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U);
crcBuffer[0U] = (m_serialNo & 0xFEU) << 1;
Utils::setBitRange(m_data, crcBuffer, 7U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES * 8U);
// Utils::dump(1U, "PDU Data", m_data, count);
uint16_t computedCRC = edac::CRC::crc9(crcBuffer, 135U);
// compute CRC-9 for the packet
uint16_t computedCRC = confirmedCRC9(buffer);
if (crc != computedCRC) {
LogWarning(LOG_P25, "P25_DUID_PDU, fmt = $%02X, invalid crc = $%04X != $%04X (computed)", m_fmt, crc, computedCRC);
@ -162,21 +160,10 @@ void DataBlock::encode(uint8_t* data)
assert(m_data != NULL);
if (m_fmt == PDU_FMT_CONFIRMED) {
// compute CRC-9 for the packet
uint8_t crcBuffer[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U];
::memset(crcBuffer, 0x00U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES + 1U);
crcBuffer[0U] = (m_serialNo & 0xFEU) << 1;
Utils::setBitRange(m_data, crcBuffer, 7U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES * 8U);
uint16_t computedCRC = edac::CRC::crc9(crcBuffer, 135U);
uint8_t buffer[P25_PDU_CONFIRMED_LENGTH_BYTES];
::memset(buffer, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES);
buffer[0U] = ((m_serialNo & 0xFEU) << 1) + // Confirmed Data Serial No.
(computedCRC >> 8); // CRC-9 Check Sum (b8)
buffer[1U] = (computedCRC & 0xFFU); // CRC-9 Check Sum (b0 - b7)
buffer[0U] = ((m_serialNo & 0xFEU) << 1); // Confirmed Data Serial No.
// if this is extended addressing and the first block decode the SAP and LLId
if (m_headerSap == PDU_SAP_EXT_ADDR && m_serialNo == 0U) {
@ -192,6 +179,10 @@ void DataBlock::encode(uint8_t* data)
::memcpy(buffer + 2U, m_data, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
}
uint16_t crc = confirmedCRC9(buffer);
buffer[0U] = buffer[0U] + ((crc >> 8) & 0x01U); // CRC-9 Check Sum (b8)
buffer[1U] = (crc & 0xFFU); // CRC-9 Check Sum (b0 - b7)
// Utils::dump(1U, "PDU Confirmed Data Block", buffer, P25_PDU_CONFIRMED_LENGTH_BYTES);
m_trellis.encode34(buffer, data);
@ -277,3 +268,25 @@ uint32_t DataBlock::getData(uint8_t* buffer) const
return 0U;
}
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
uint16_t DataBlock::confirmedCRC9(const uint8_t* buffer)
{
// generate 135-bit CRC buffer
uint8_t* crcBuffer = new uint8_t[17U];
::memset(crcBuffer, 0x00U, 17U);
Utils::setBitRange(buffer, crcBuffer, 0U, 7U);
uint8_t* data = new uint8_t[P25_PDU_CONFIRMED_DATA_LENGTH_BYTES];
Utils::getBitRange(buffer, data, 16U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES * 8);
Utils::setBitRange(data, crcBuffer, 7U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES * 8);
return edac::CRC::crc9(crcBuffer, 135U);
}

@ -88,6 +88,9 @@ namespace p25
uint8_t m_headerSap;
uint8_t* m_data;
/// <summary></summary>
uint16_t confirmedCRC9(const uint8_t* buffer);
};
} // namespace data
} // namespace p25

Loading…
Cancel
Save

Powered by TurnKey Linux.