MBC Header and Blocks CRC;

This commit is contained in:
lwvmobile 2022-12-07 22:58:57 -05:00
parent a2b3da5b5a
commit a5d23d9e12
5 changed files with 96 additions and 20 deletions

View File

@ -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);

View File

@ -277,8 +277,13 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
uint32_t CRCComputed = 0;
uint32_t CRCExtracted = 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
//shim these values for now
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);
}
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));
}

View File

@ -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
{

View File

@ -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);

View File

@ -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)
{