From a5d23d9e128e61063bf4b17fc84632a606716a9a Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 7 Dec 2022 22:58:57 -0500 Subject: [PATCH] MBC Header and Blocks CRC; --- include/dsd.h | 1 + src/dmr_block.c | 59 +++++++++++++++++++++++++++++++++++++++++------- src/dmr_dburst.c | 8 ++++--- src/dmr_flco.c | 18 +++++++-------- src/dmr_utils.c | 30 ++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 20 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index 73a6035..2d34e91 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -846,6 +846,7 @@ rs_12_9_checksum_t *rs_12_9_calc_checksum(rs_12_9_codeword_t *codeword); //DMR CRC Functions uint16_t ComputeCrcCCITT(uint8_t * DMRData); +uint16_t ComputeCrcCCITT16d(const uint8_t buf[], uint8_t len); uint32_t ComputeAndCorrectFullLinkControlCrc(uint8_t * FullLinkControlDataBytes, uint32_t * CRCComputed, uint32_t CRCMask); uint8_t ComputeCrc5Bit(uint8_t * DMRData); diff --git a/src/dmr_block.c b/src/dmr_block.c index 7b2b32d..a8fddff 100644 --- a/src/dmr_block.c +++ b/src/dmr_block.c @@ -276,9 +276,14 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte uint32_t CRCCorrect = 0; uint32_t CRCComputed = 0; uint32_t CRCExtracted = 0; - uint32_t IrrecoverableErrors = 0; + uint32_t IrrecoverableErrors = 0; + uint8_t dmr_pdu_sf_bits[18*8*8]; //8 blocks at 18 bytes at 8 bits //just a large value to have plenty storage space + //MBC Header and Block CRC + uint8_t mbc_crc_good[2]; //header and blocks crc pass/fail local storage + memset (mbc_crc_good, 0, sizeof (mbc_crc_good)); //init on 0 - bad crc + if (type == 1) blocks = state->data_header_blocks[slot] - 1; if (type == 2) blocks = state->data_block_counter[slot]; @@ -344,12 +349,46 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte dmr_pdu_sf_bits[j + 7] = (state->dmr_pdu_sf[slot][i] >> 0) & 0x01; } - //TODO: CRC check on Header and full frames as appropriate + //CRC check on Header and full frames as appropriate (header crc already stored) + //The 16 bit CRC in the header shall include the data carried by the header. + //The 16 bit CRC in the last block shall be performed on + //all MBC blocks (conmbined) except the header block. <-- misleading statement, just like half the dmr manual + + mbc_crc_good[0] = state->data_block_crc_valid[slot][0]; + + CRCExtracted = 0; + //extract crc from last block, apply to completed 'superframe' minus header + for(i = 0; i < 16; i++) + { + CRCExtracted = CRCExtracted << 1; + CRCExtracted = CRCExtracted | (uint32_t)(dmr_pdu_sf_bits[i + 96*(1+blocks) - 16] & 1); + } - //shim these values for now - CRCCorrect = 1; - IrrecoverableErrors = 0; + uint8_t mbc_block_bits[12*8*3]; + memset (mbc_block_bits, 0, sizeof(mbc_block_bits)); + //shift continuation blocks and last block into seperate array for crc check + for (i = 0; i < 12*8*3; i++) + { + mbc_block_bits[i] = dmr_pdu_sf_bits[i+96]; //skip mbc header + } + CRCComputed = ComputeCrcCCITT16d (mbc_block_bits, ((blocks+0)*96)-16 ); + + // fprintf (stderr, " \n CRC EXT %X CRC CMP %X", CRCExtracted, CRCComputed); + + if (CRCComputed == CRCExtracted) mbc_crc_good[1] = 1; + + CRCCorrect = 0; + IrrecoverableErrors = 1; + + //set good on good header and good blocks + if (mbc_crc_good[0] == 1 && mbc_crc_good[1] == 1) + { + CRCCorrect = 1; + IrrecoverableErrors = 0; + } + + //cspdu will only act on any fid/opcodes if good CRC to prevent falsing on control signalling dmr_cspdu (opts, state, dmr_pdu_sf_bits, state->dmr_pdu_sf[slot], CRCCorrect, IrrecoverableErrors); } @@ -358,7 +397,7 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte //Full Super Frame Type 1 - Debug Output if (opts->payload == 1 && type == 1 && state->data_block_counter[slot] == state->data_header_blocks[slot]) { - fprintf (stderr, "%s",KGRN); + fprintf (stderr, "%s", KGRN); fprintf (stderr, "\n Multi Block PDU Superframe - Slot [%d]\n ", slot+1); for (i = 0; i < ((blocks+1)*block_len); i++) { @@ -374,7 +413,7 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte //Full Super Frame MBC - Debug Output if (opts->payload == 1 && type == 2 && lb == 1) { - fprintf (stderr, "%s",KGRN); + fprintf (stderr, "%s", KGRN); fprintf (stderr, "\n MBC Multi Block PDU Superframe - Slot [%d]\n ", slot+1); for (i = 0; i < ((blocks+1)*block_len); i++) { @@ -384,6 +423,9 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte fprintf (stderr, "\n "); } } + fprintf (stderr, "%s", KRED); + if (mbc_crc_good[0] == 0) fprintf (stderr, "MBC Header CRC ERR "); + if (mbc_crc_good[1] == 0) fprintf (stderr, "MBC Blocks CRC ERR "); fprintf (stderr, "%s ", KNRM); } @@ -405,7 +447,7 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte } -//failsafe to clear old data header and block info in case of tact/emb/slottype failures and we +//failsafe to clear old data header, block info, cach, in case of tact/emb/slottype failures and we //can no longer verify accurate data block reporting void dmr_reset_blocks (dsd_opts * opts, dsd_state * state) { @@ -416,4 +458,5 @@ void dmr_reset_blocks (dsd_opts * opts, dsd_state * state) memset (state->data_header_blocks, 0, sizeof(state->data_header_blocks)); memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid)); memset (state->dmr_lrrp_source, 0, sizeof(state->dmr_lrrp_source)); + memset (state->dmr_cach_fragment, 0, sizeof (state->dmr_cach_fragment)); } \ No newline at end of file diff --git a/src/dmr_dburst.c b/src/dmr_dburst.c index 3f4e925..0fa0eb9 100644 --- a/src/dmr_dburst.c +++ b/src/dmr_dburst.c @@ -10,7 +10,6 @@ *-----------------------------------------------------------------------------*/ //TODO: CRC9 on confirmed data blocks; CRC32 on completed data sf; -//TODO: MBC full message CRC16 (does this include the header or not though?) //TODO: Reverse Channel Signalling - RC single burst BPTC/7-bit CRC //TODO: Single Burst Embedded LC - Non-RC single burst LC - Look for Late Entry Alg/Key @@ -325,7 +324,8 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196 { CRCExtracted = 0; CRCComputed = 0; - IrrecoverableErrors = 1; //can't be tested, but maybe can poll trellis decoder for a value in the future + IrrecoverableErrors = 1; + bool trellis_good = TRUE; uint8_t tdibits[98]; memset (tdibits, 0, sizeof(tdibits)); @@ -339,7 +339,9 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196 unsigned char TrellisReturn[18]; memset (TrellisReturn, 0, sizeof(TrellisReturn)); - CDMRTrellisDecode(tdibits, TrellisReturn); + trellis_good = CDMRTrellisDecode(tdibits, TrellisReturn); + if (trellis_good == TRUE) IrrecoverableErrors = 0; + // else (fprintf (stderr, " Trellis Failure")); //debug print for (i = 0; i < pdu_len; i++) //18 { diff --git a/src/dmr_flco.c b/src/dmr_flco.c index ba14a23..9070042 100644 --- a/src/dmr_flco.c +++ b/src/dmr_flco.c @@ -288,7 +288,7 @@ uint8_t dmr_cach (dsd_opts * opts, dsd_state * state, uint8_t cach_bits[25]) h1 = Hamming17123 (slco_bits + 0); //run single - manual would suggest that though this exists, there is no support? or perhaps its manufacturer only thing? - if (h1) dmr_slco (opts, state, slco_bits); + if (h1) ; // dmr_slco (opts, state, slco_bits); //random false positibes for con+, so diabled for now else { err = 1; @@ -593,7 +593,7 @@ void dmr_embedded_alias_blocks (dsd_opts * opts, dsd_state * state, uint8_t lc_b } -//externalize embedded GPS +//externalize embedded GPS - Needs samples to test/fix function void dmr_embedded_gps (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[]) { fprintf (stderr, "%s", KYEL); @@ -603,14 +603,15 @@ void dmr_embedded_gps (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[]) uint8_t res_a = lc_bits[1]; uint8_t res_b = (uint8_t)ConvertBitIntoBytes(&lc_bits[16], 4); uint8_t pos_err = (uint8_t)ConvertBitIntoBytes(&lc_bits[20], 3); - uint32_t lon = (uint32_t)ConvertBitIntoBytes(&lc_bits[23], 25); - uint32_t lat = (uint32_t)ConvertBitIntoBytes(&lc_bits[48], 24); + + uint32_t lon_sign = lc_bits[23]; + uint32_t lon = (uint32_t)ConvertBitIntoBytes(&lc_bits[24], 24); + uint32_t lat_sign = lc_bits[48]; + uint32_t lat = (uint32_t)ConvertBitIntoBytes(&lc_bits[49], 23); double lat_unit = (double)180/ pow (2.0, 24); //180 divided by 2^24 double lon_unit = (double)360/ pow (2.0, 25); //360 divided by 2^25 - uint32_t lat_sign = lat >> 23; - uint32_t lon_sign = lon >> 24; char latstr[3]; char lonstr[3]; sprintf (latstr, "%s", "N"); @@ -627,14 +628,14 @@ void dmr_embedded_gps (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[]) { if (lat_sign) { - lat = 0x800001 - (lat & 0x7FFFFF); + lat = 0x800001 - lat; sprintf (latstr, "%s", "S"); } latitude = ((double)lat * lat_unit); if (lon_sign) { - lon = 0x1000001 - (lon & 0xFFFFFF); + lon = 0x1000001 - lon; sprintf (lonstr, "%s", "W"); } longitude = ((double)lon * lon_unit); @@ -657,7 +658,6 @@ void dmr_embedded_gps (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[]) } - } fprintf (stderr, "%s", KNRM); diff --git a/src/dmr_utils.c b/src/dmr_utils.c index 1461bf8..3ade2fc 100644 --- a/src/dmr_utils.c +++ b/src/dmr_utils.c @@ -9,6 +9,36 @@ #include "dsd.h" +//modified to accept variable payload size and len +uint16_t ComputeCrcCCITT16d(const uint8_t buf[], uint8_t len) +{ + uint32_t i; + uint16_t CRC = 0x0000; /* Initialization value = 0x0000 */ + /* Polynomial x^16 + x^12 + x^5 + 1 + * Normal = 0x1021 + * Reciprocal = 0x0811 + * Reversed = 0x8408 + * Reversed reciprocal = 0x8810 */ + uint16_t Polynome = 0x1021; + for(i = 0; i < len; i++) + { + if(((CRC >> 15) & 1) ^ (buf[i] & 1)) + { + CRC = (CRC << 1) ^ Polynome; + } + else + { + CRC <<= 1; + } + } + + /* Invert the CRC */ + CRC ^= 0xFFFF; + + /* Return the CRC */ + return CRC; +} /* End ComputeCrcCCITTd() */ + // A Hamming (17,12,3) Check for completed SLC message bool Hamming17123(uint8_t* d) {