From a00ecbe7d9bbaa6d9121631a20b7e2c22026ad69 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 18 Oct 2020 20:04:44 +0100 Subject: [PATCH] Get the CRC and callsign mangling working correctly. --- M17CRC.cpp | 44 +++++++++++++++++++---------- M17Utils.cpp | 79 ++++++++++++++++++++++------------------------------ 2 files changed, 64 insertions(+), 59 deletions(-) diff --git a/M17CRC.cpp b/M17CRC.cpp index 933f86f..7ba4da6 100644 --- a/M17CRC.cpp +++ b/M17CRC.cpp @@ -21,16 +21,37 @@ #include #include -const uint8_t BIT_MASK_TABLE1[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; - -#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7]) +const uint16_t CRC_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, + 0xF01EU, 0xA92BU, 0x4274U, 0x1B41U, 0x41B9U, 0x188CU, 0xF3D3U, 0xAAE6U, 0x7C58U, 0x256DU, 0xCE32U, + 0x9707U, 0x3A7BU, 0x634EU, 0x8811U, 0xD124U, 0x079AU, 0x5EAFU, 0xB5F0U, 0xECC5U, 0x354FU, 0x6C7AU, + 0x8725U, 0xDE10U, 0x08AEU, 0x519BU, 0xBAC4U, 0xE3F1U, 0x4E8DU, 0x17B8U, 0xFCE7U, 0xA5D2U, 0x736CU, + 0x2A59U, 0xC106U, 0x9833U, 0xC2CBU, 0x9BFEU, 0x70A1U, 0x2994U, 0xFF2AU, 0xA61FU, 0x4D40U, 0x1475U, + 0xB909U, 0xE03CU, 0x0B63U, 0x5256U, 0x84E8U, 0xDDDDU, 0x3682U, 0x6FB7U, 0x8372U, 0xDA47U, 0x3118U, + 0x682DU, 0xBE93U, 0xE7A6U, 0x0CF9U, 0x55CCU, 0xF8B0U, 0xA185U, 0x4ADAU, 0x13EFU, 0xC551U, 0x9C64U, + 0x773BU, 0x2E0EU, 0x74F6U, 0x2DC3U, 0xC69CU, 0x9FA9U, 0x4917U, 0x1022U, 0xFB7DU, 0xA248U, 0x0F34U, + 0x5601U, 0xBD5EU, 0xE46BU, 0x32D5U, 0x6BE0U, 0x80BFU, 0xD98AU, 0x6A9EU, 0x33ABU, 0xD8F4U, 0x81C1U, + 0x577FU, 0x0E4AU, 0xE515U, 0xBC20U, 0x115CU, 0x4869U, 0xA336U, 0xFA03U, 0x2CBDU, 0x7588U, 0x9ED7U, + 0xC7E2U, 0x9D1AU, 0xC42FU, 0x2F70U, 0x7645U, 0xA0FBU, 0xF9CEU, 0x1291U, 0x4BA4U, 0xE6D8U, 0xBFEDU, + 0x54B2U, 0x0D87U, 0xDB39U, 0x820CU, 0x6953U, 0x3066U, 0xDCA3U, 0x8596U, 0x6EC9U, 0x37FCU, 0xE142U, + 0xB877U, 0x5328U, 0x0A1DU, 0xA761U, 0xFE54U, 0x150BU, 0x4C3EU, 0x9A80U, 0xC3B5U, 0x28EAU, 0x71DFU, + 0x2B27U, 0x7212U, 0x994DU, 0xC078U, 0x16C6U, 0x4FF3U, 0xA4ACU, 0xFD99U, 0x50E5U, 0x09D0U, 0xE28FU, + 0xBBBAU, 0x6D04U, 0x3431U, 0xDF6EU, 0x865BU, 0x5FD1U, 0x06E4U, 0xEDBBU, 0xB48EU, 0x6230U, 0x3B05U, + 0xD05AU, 0x896FU, 0x2413U, 0x7D26U, 0x9679U, 0xCF4CU, 0x19F2U, 0x40C7U, 0xAB98U, 0xF2ADU, 0xA855U, + 0xF160U, 0x1A3FU, 0x430AU, 0x95B4U, 0xCC81U, 0x27DEU, 0x7EEBU, 0xD397U, 0x8AA2U, 0x61FDU, 0x38C8U, + 0xEE76U, 0xB743U, 0x5C1CU, 0x0529U, 0xE9ECU, 0xB0D9U, 0x5B86U, 0x02B3U, 0xD40DU, 0x8D38U, 0x6667U, + 0x3F52U, 0x922EU, 0xCB1BU, 0x2044U, 0x7971U, 0xAFCFU, 0xF6FAU, 0x1DA5U, 0x4490U, 0x1E68U, 0x475DU, + 0xAC02U, 0xF537U, 0x2389U, 0x7ABCU, 0x91E3U, 0xC8D6U, 0x65AAU, 0x3C9FU, 0xD7C0U, 0x8EF5U, 0x584BU, + 0x017EU, 0xEA21U, 0xB314U}; bool CM17CRC::checkCRC(const unsigned char* in, unsigned int nBytes) { assert(in != NULL); assert(nBytes > 2U); - uint16_t crc = createCRC(in, nBytes); + uint16_t crc = createCRC(in, nBytes - 2U); uint8_t temp[2U]; temp[0U] = (crc >> 8) & 0xFFU; @@ -44,26 +65,21 @@ void CM17CRC::encodeCRC(unsigned char* in, unsigned int nBytes) assert(in != NULL); assert(nBytes > 2U); - uint16_t crc = createCRC(in, nBytes); + uint16_t crc = createCRC(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) { assert(in != NULL); uint16_t crc = 0xFFFFU; - for (unsigned int i = 0U; i < nBytes; i++) { - bool bit1 = READ_BIT(in, i) != 0x00U; - bool bit2 = (crc & 0x8000U) == 0x8000U; - - crc <<= 1; - - if (bit1 ^ bit2) - crc ^= 0x5935U; - } + for (unsigned int i = 0U; i < nBytes; i++) + crc = (crc << 8) ^ CRC_TABLE[((crc >> 8) ^ uint16_t(in[i])) & 0x00FFU]; return crc; } + diff --git a/M17Utils.cpp b/M17Utils.cpp index 406ebdb..b3d0056 100644 --- a/M17Utils.cpp +++ b/M17Utils.cpp @@ -20,64 +20,53 @@ #include +const std::string M17_CHARS = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."; + void CM17Utils::encodeCallsign(const std::string& callsign, unsigned char* encoded) { assert(encoded != NULL); - std::string call = callsign; - call.resize(8U, ' '); + unsigned int len = callsign.size(); + if (len > 9U) + len = 9U; - uint64_t enc = 0ULL; - for (int i = 7U; i >= 0; i--) { - char c = call.at(i); + uint64_t enc = 0ULL; + for (int i = len - 1; i >= 0; i--) { + size_t pos = M17_CHARS.find(callsign[i]); + if (pos == std::string::npos) + pos = 0ULL; - enc *= 40ULL; + enc *= 40ULL; + enc += pos; + } - // If speed is more important than code space, you can replace this with a lookup into a 256 byte array. - if (c >= 'A' && c <= 'Z') // 1-26 - enc += c - 'A' + 1ULL; - else if (c >= '0' && c <= '9') // 27-36 - enc += c - '0' + 27ULL; - else if (c == '-') // 37 - enc += 37ULL; - - // These are just place holders. If other characters make more sense, change these. - // Be sure to change them in the decode array below too. - else if (c == '/') // 38 - enc += 38ULL; - else if (c == '.') // 39 - enc += 39ULL; - else - // Invalid character or space, represented by 0, decoded as a space. - enc += 0ULL; - } - - encoded[0U] = enc >> 40; - encoded[1U] = enc >> 32; - encoded[2U] = enc >> 24; - encoded[3U] = enc >> 16; - encoded[4U] = enc >> 8; - encoded[5U] = enc >> 0; + encoded[0U] = enc >> 40; + encoded[1U] = enc >> 32; + encoded[2U] = enc >> 24; + encoded[3U] = enc >> 16; + encoded[4U] = enc >> 8; + encoded[5U] = enc >> 0; } void CM17Utils::decodeCallsign(const unsigned char* encoded, std::string& callsign) { - assert(encoded != NULL); + assert(encoded != NULL); - callsign.empty(); + callsign.empty(); - uint64_t enc = (uint64_t(encoded[5U]) << 40) + - (uint64_t(encoded[4U]) << 32) + - (uint64_t(encoded[3U]) << 24) + - (uint64_t(encoded[2U]) << 16) + - (uint64_t(encoded[1U]) << 8) + - (uint64_t(encoded[0U]) << 0); + uint64_t enc = (uint64_t(encoded[0U]) << 40) + + (uint64_t(encoded[1U]) << 32) + + (uint64_t(encoded[2U]) << 24) + + (uint64_t(encoded[3U]) << 16) + + (uint64_t(encoded[4U]) << 8) + + (uint64_t(encoded[5U]) << 0); - if (enc >= 262144000000000ULL) // 40^9 - return; + if (enc >= 262144000000000ULL) // 40^9 + return; - while (enc > 0ULL) { - callsign += " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[enc % 40ULL]; - enc /= 40ULL; - } + while (enc > 0ULL) { + callsign += " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[enc % 40ULL]; + enc /= 40ULL; + } } +