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 //DMR CRC Functions
uint16_t ComputeCrcCCITT(uint8_t * DMRData); 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); uint32_t ComputeAndCorrectFullLinkControlCrc(uint8_t * FullLinkControlDataBytes, uint32_t * CRCComputed, uint32_t CRCMask);
uint8_t ComputeCrc5Bit(uint8_t * DMRData); uint8_t ComputeCrc5Bit(uint8_t * DMRData);

View File

@ -276,9 +276,14 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
uint32_t CRCCorrect = 0; uint32_t CRCCorrect = 0;
uint32_t CRCComputed = 0; uint32_t CRCComputed = 0;
uint32_t CRCExtracted = 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 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 == 1) blocks = state->data_header_blocks[slot] - 1;
if (type == 2) blocks = state->data_block_counter[slot]; 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; 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 uint8_t mbc_block_bits[12*8*3];
CRCCorrect = 1; memset (mbc_block_bits, 0, sizeof(mbc_block_bits));
IrrecoverableErrors = 0; //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); 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 //Full Super Frame Type 1 - Debug Output
if (opts->payload == 1 && type == 1 && state->data_block_counter[slot] == state->data_header_blocks[slot]) 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); fprintf (stderr, "\n Multi Block PDU Superframe - Slot [%d]\n ", slot+1);
for (i = 0; i < ((blocks+1)*block_len); i++) 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 //Full Super Frame MBC - Debug Output
if (opts->payload == 1 && type == 2 && lb == 1) 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); fprintf (stderr, "\n MBC Multi Block PDU Superframe - Slot [%d]\n ", slot+1);
for (i = 0; i < ((blocks+1)*block_len); i++) 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, "\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); 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 //can no longer verify accurate data block reporting
void dmr_reset_blocks (dsd_opts * opts, dsd_state * state) 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_header_blocks, 0, sizeof(state->data_header_blocks));
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid)); 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_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: 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: 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 //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; CRCExtracted = 0;
CRCComputed = 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]; uint8_t tdibits[98];
memset (tdibits, 0, sizeof(tdibits)); 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]; unsigned char TrellisReturn[18];
memset (TrellisReturn, 0, sizeof(TrellisReturn)); 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 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); h1 = Hamming17123 (slco_bits + 0);
//run single - manual would suggest that though this exists, there is no support? or perhaps its manufacturer only thing? //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 else
{ {
err = 1; 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[]) void dmr_embedded_gps (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[])
{ {
fprintf (stderr, "%s", KYEL); 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_a = lc_bits[1];
uint8_t res_b = (uint8_t)ConvertBitIntoBytes(&lc_bits[16], 4); uint8_t res_b = (uint8_t)ConvertBitIntoBytes(&lc_bits[16], 4);
uint8_t pos_err = (uint8_t)ConvertBitIntoBytes(&lc_bits[20], 3); 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 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 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 latstr[3];
char lonstr[3]; char lonstr[3];
sprintf (latstr, "%s", "N"); 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) if (lat_sign)
{ {
lat = 0x800001 - (lat & 0x7FFFFF); lat = 0x800001 - lat;
sprintf (latstr, "%s", "S"); sprintf (latstr, "%s", "S");
} }
latitude = ((double)lat * lat_unit); latitude = ((double)lat * lat_unit);
if (lon_sign) if (lon_sign)
{ {
lon = 0x1000001 - (lon & 0xFFFFFF); lon = 0x1000001 - lon;
sprintf (lonstr, "%s", "W"); sprintf (lonstr, "%s", "W");
} }
longitude = ((double)lon * lon_unit); 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); fprintf (stderr, "%s", KNRM);

View File

@ -9,6 +9,36 @@
#include "dsd.h" #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 // A Hamming (17,12,3) Check for completed SLC message
bool Hamming17123(uint8_t* d) bool Hamming17123(uint8_t* d)
{ {