Fix DMR FEC/CRC/RAS Implementation Issues;

This commit is contained in:
lwvmobile 2023-01-21 05:43:42 -05:00
parent ac752029bd
commit d0f9bb4bad
10 changed files with 165 additions and 66 deletions

View File

@ -199,18 +199,10 @@ uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DM
}
}
/* R(0) to R(2) may be used to transport some
* Restricted Access System (RAS) information,
* So save these three bytes before reset all of them
* See patent US 2013/0288643 A1 */
R[0] = DataMatrix[0][2]; /* Save R(0) */
R[1] = DataMatrix[0][1]; /* Save R(1) */
R[2] = DataMatrix[0][0]; /* Save R(2) */
/* Set to 0 R(0) to R(2) - See DMR standard chapter B1.1 BPTC (196,96) */
DataMatrix[0][0] = 0; /* R(2) */
DataMatrix[0][1] = 0; /* R(1) */
DataMatrix[0][2] = 0; /* R(0) */
// DataMatrix[0][0] = 0; /* R(2) */
// DataMatrix[0][1] = 0; /* R(1) */
// DataMatrix[0][2] = 0; /* R(0) */
/* Init the Hamming (15,11,3) library
* Not needed because it has already been done
@ -363,6 +355,14 @@ uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DM
}
}
/* R(0) to R(2) may be used to transport some
* Restricted Access System (RAS) information,
* So save these three bits after hamming correction
* See patent US 2013/0288643 A1 */
R[0] = DataMatrix[0][2]; /* Save R(0) */
R[1] = DataMatrix[0][1]; /* Save R(1) */
R[2] = DataMatrix[0][0]; /* Save R(2) */
/* Return the number of irrecoverable Hamming errors */
return HammingIrrecoverableErrorNb;
} /* End BPTC_196x96_Extract_Data() */

View File

@ -247,11 +247,11 @@ void dmr_dheader (dsd_opts * opts, dsd_state * state, uint8_t dheader[], uint32_
fprintf (stderr, "%s ", KNRM);
//let user know the data header may have errors
fprintf (stderr, "%s", KRED);
if (CRCCorrect == 1) ; //CRCCorrect 1 is good, else is bad CRC; no print on good
else if(IrrecoverableErrors == 0) fprintf(stderr, " (FEC OK)");
else fprintf(stderr, " (FEC/CRC ERR)");
fprintf (stderr, "%s", KNRM);
// fprintf (stderr, "%s", KRED);
// if (CRCCorrect == 1) ; //CRCCorrect 1 is good, else is bad CRC; no print on good
// else if(IrrecoverableErrors == 0) fprintf(stderr, " (FEC OK)");
// else fprintf(stderr, " (FEC/CRC ERR)");
// fprintf (stderr, "%s", KNRM);
}
@ -387,6 +387,12 @@ void dmr_block_assembler (dsd_opts * opts, dsd_state * state, uint8_t block_byte
CRCCorrect = 1;
IrrecoverableErrors = 0;
}
else
{
fprintf (stderr, "%s", KRED);
fprintf(stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
}
//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);

View File

@ -753,7 +753,7 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state)
fprintf (stderr,"%s ", getTime());
fprintf (stderr,"Sync: DMR ");
fprintf (stderr, "%s", KRED);
fprintf (stderr, "| VOICE TACT/SYNC ERR");
fprintf (stderr, "| VOICE CACH/SYNC ERR");
fprintf (stderr, "%s", KNRM);
//run LFSR if either slot had an active MI in it.
if (state->payload_algid >= 0x21)

View File

@ -299,7 +299,8 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
info[(2*i) + 99] = (1 & dibit); // bit 0
}
dmr_data_burst_handler(opts, state, (uint8_t *)info, burst);
//don't run on MS Reverse Channel Data
if (state->dmr_ms_rc == 0) dmr_data_burst_handler(opts, state, (uint8_t *)info, burst);
//don't run cach on simplex or mono
if (state->dmr_ms_mode == 0 || opts->dmr_mono == 0)

View File

@ -46,6 +46,7 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
uint8_t R[3];
uint8_t BPTCReservedBits = 0;
uint8_t is_ras = 0;
uint8_t crc_original_validity = 0;
uint32_t crcmask = 0;
uint8_t crclen = 0;
@ -156,6 +157,7 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
break;
//special types (not real data 'sync' bursts)
case 0xEB: //Embedded Signalling
crclen = 5;
is_emb = 1;
pdu_len = 9;
break;
@ -252,15 +254,19 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
else CRCCorrect = 0;
}
//set the 'RAS Flag', if no irrecoverable errors but bad crc
if (CRCCorrect == 0 && IrrecoverableErrors == 0 && BPTCReservedBits == 4) is_ras = 1; //!=0, or == 0x4, or just R[2] == 1
//set the 'RAS Flag', if no irrecoverable errors but bad crc, only when enabled by user (to prevent a lot of bad data CSBKs)
if (opts->aggressive_framesync == 0 && CRCCorrect == 0 && IrrecoverableErrors == 0 && BPTCReservedBits == 4) is_ras = 1; //!=0, or == 0x4, or just R[2] == 1
//make sure the system type isn't Hytera, but could just be bad decodes on bad sample
if (BPTCDmrDataByte[1] == 0x68) is_ras = 0;
//if this is a RAS system, set the CRC to okay if irrecoverable errors is okay
//if we don't do this, then we can't view some data (CSBKs on RAS enabled systems)
if (is_ras == 1) CRCCorrect = 1;
if (is_ras == 1)
{
crc_original_validity = CRCCorrect;
CRCCorrect = 1;
}
if (databurst == 0x04 || databurst == 0x06) //MBC Header, Data Header
{
@ -330,11 +336,7 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
IrrecoverableErrors = BPTC_128x77_Extract_Data(BptcDataMatrix, LC_DataBit);
/* Reconstitute the 5 bit CRC */
CRCExtracted = (LC_DataBit[72] & 1) << 4;
CRCExtracted |= (LC_DataBit[73] & 1) << 3;
CRCExtracted |= (LC_DataBit[74] & 1) << 2;
CRCExtracted |= (LC_DataBit[75] & 1) << 1;
CRCExtracted |= (LC_DataBit[76] & 1) << 0;
CRCExtracted = (uint32_t)ConvertBitIntoBytes(&LC_DataBit[72], 5);
/* Compute the 5 bit CRC */
CRCComputed = ComputeCrc5Bit(LC_DataBit);
@ -451,15 +453,43 @@ void dmr_data_burst_handler(dsd_opts * opts, dsd_state * state, uint8_t info[196
}
if (databurst == 0x05) dmr_block_assembler (opts, state, DMR_PDU, pdu_len, databurst, 2);
//set the original CRCCorrect back to its original value if the RAS flag was tripped
if (is_ras == 1) CRCCorrect = crc_original_validity;
//start printing relevant fec/crc/ras messages, don't print on idle or MBC continuation blocks (handled in dmr_block.c)
if (CRCCorrect == 1 && databurst != 0x09 && databurst != 0x05) ; //fprintf(stderr, "(CRC OK)");
if (IrrecoverableErrors == 0 && CRCCorrect == 0 && databurst != 0x09 && databurst != 0x05)
{
fprintf (stderr, "%s", KYEL);
fprintf(stderr, " (FEC OK)");
fprintf (stderr, "%s", KNRM);
}
if (IrrecoverableErrors != 0 && databurst != 0x09 && databurst != 0x05)
{
fprintf (stderr, "%s", KRED);
fprintf(stderr, " (FEC ERR)");
fprintf (stderr, "%s", KNRM);
}
//print whether or not the 'RAS Field' bits are set to indicate RAS enabled (to be verified)
if (is_ras == 1)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " CRC/RAS ");
fprintf (stderr, " -RAS ");
//the value of this field seems to always, or usually, be 4, or just R[2] bit is set
if (opts->payload == 1) fprintf (stderr, "%X ", BPTCReservedBits);
fprintf (stderr, "%s", KNRM);
}
if (CRCCorrect == 0 && databurst != 0x09 && databurst != 0x05)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR) ");
fprintf (stderr, "%s", KNRM);
}
//print the unified PDU format here, if not slot idle
if (opts->payload == 1 && databurst != 0x09)

View File

@ -42,18 +42,18 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
source = (uint32_t)ConvertBitIntoBytes(&lc_bits[48], 24);
//look for Cap+ on VLC header, then set source and/or rest channel appropriately
if (type == 1 && fid == 0x10 && (flco == 0x04 || flco == 0x07) ) //0x07 appears to be a cap+ txi private call
if (IrrecoverableErrors == 0 && type == 1 && fid == 0x10 && (flco == 0x04 || flco == 0x07) ) //0x07 appears to be a cap+ txi private call
{
is_cap_plus = 1;
capsite = (uint8_t)ConvertBitIntoBytes(&lc_bits[48], 4); //can't verify, just speculating
restchannel = (int)ConvertBitIntoBytes(&lc_bits[52], 4); //was 48,8
source = (uint32_t)ConvertBitIntoBytes(&lc_bits[56], 16);
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
// sprintf (state->dmr_branding, "%s", "Motorola");
// sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
}
if (IrrecoverableErrors == 0 && CRCCorrect == 1)
if (IrrecoverableErrors == 0)
{
//Embedded Talker Alias Header Only (format and len storage)
if (type == 3 && flco == 0x04)
@ -90,7 +90,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
//will want to continue to observe for different flco and fid combinations to find out their meaning
//Standard Addressing/Cap+ Addressing (trying to avoid embedded alias and gps, etc)
if(IrrecoverableErrors == 0 && is_alias == 0 && is_gps == 0 && CRCCorrect == 1)
if(IrrecoverableErrors == 0 && is_alias == 0 && is_gps == 0)
{
//set overarching manufacturer in use when non-standard feature id set is up
//may not want to set moto 0x10 here either, lots of radios use that set as well
@ -273,10 +273,10 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
fprintf(stderr, "Call ");
fprintf (stderr, "%s", KRED);
if (CRCCorrect == 1) ; //CRCCorrect 1 is good, else is bad CRC; no print on good
else if(IrrecoverableErrors == 0) ; //fprintf(stderr, "(FEC OK)");
else fprintf(stderr, "(FEC/CRC ERR) ");
// fprintf (stderr, "%s", KRED);
// if (CRCCorrect == 1) ; //fprintf(stderr, "(CRC OK)"); //CRCCorrect 1 is good, else is bad CRC; no print on good
// else if(IrrecoverableErrors == 0) ; //fprintf(stderr, "(FEC OK)");
// else fprintf(stderr, "(FEC ERR) ");
//check Cap+ rest channel info if available and good fec
if (is_cap_plus == 1)
@ -321,6 +321,16 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
}
if(IrrecoverableErrors != 0)
{
if (type != 3) fprintf (stderr, "\n");
fprintf (stderr, "%s", KRED);
fprintf (stderr, " SLOT %d", state->currentslot+1);
fprintf (stderr, " FLCO FEC ERR ");
fprintf (stderr, "%s", KNRM);
}
}
//externalized dmr cach - tact and slco fragment handling
@ -626,18 +636,20 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
fprintf (stderr, " SLCO Activity Update TS1: %X Hash: %02X TS2: %X Hash: %02X", ts1_act, ts1_hash, ts2_act, ts2_hash); //102 361-2 7.1.3.2
else if (slco == 0x9)
{
state->dmr_mfid = 0x10;
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf (state->dmr_branding_sub, "%s", "Con+ ");
//remove all setting of branding/sub from SLCO, can cause false positives even with seeming good CRC
// state->dmr_mfid = 0x10;
// sprintf (state->dmr_branding, "%s", "Motorola");
// sprintf (state->dmr_branding_sub, "%s", "Con+ ");
fprintf (stderr, " SLCO Connect Plus Voice Channel - Net ID: %d Site ID: %d", con_netid, con_siteid);
sprintf (state->dmr_site_parms, "%d-%d ", con_netid, con_siteid);
}
else if (slco == 0xA)
{
state->dmr_mfid = 0x10;
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf (state->dmr_branding_sub, "%s", "Con+ ");
// state->dmr_mfid = 0x10;
// sprintf (state->dmr_branding, "%s", "Motorola");
// sprintf (state->dmr_branding_sub, "%s", "Con+ ");
fprintf (stderr, " SLCO Connect Plus Control Channel - Net ID: %d Site ID: %d", con_netid, con_siteid);
sprintf (state->dmr_site_parms, "%d-%d ", con_netid, con_siteid);
@ -651,11 +663,11 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
else if (slco == 0xF)
{
state->dmr_mfid = 0x10;
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
// state->dmr_mfid = 0x10;
// sprintf (state->dmr_branding, "%s", "Motorola");
// sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
fprintf (stderr, " SLCO Capacity Plus Site: %d - Rest Channel %d - RS: %02X", capsite+1, restchannel, cap_reserved);
state->dmr_rest_channel = restchannel;
// state->dmr_rest_channel = restchannel; //test without, may work better
//assign to cc freq if available
if (state->trunk_chan_map[restchannel] != 0)
{
@ -663,7 +675,7 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
}
//nullify any previous TIII data (bugfix for bad assignments or system type switching)
sprintf(state->dmr_site_parms, "%s", "");
// sprintf(state->dmr_site_parms, "%s", "");
}
else fprintf (stderr, " SLCO Unknown - %d ", slco);

View File

@ -180,7 +180,6 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
crc_extracted = crc_extracted ^ 0x7A;
crc_computed = crc7((uint8_t *) sbrc_return, 11);
if (crc_extracted == crc_computed) crc_okay = 1;
if (opts->payload == 1) fprintf (stderr, " CRC EXT %02X, CRC CMP %02X", crc_extracted, crc_computed);
}
else crc_okay = 1; //SB
@ -203,6 +202,7 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
fprintf (stderr, "%s", KRED);
fprintf (stderr, " (CRC ERR)");
fprintf (stderr, "%s", KNRM);
if (opts->payload == 1) fprintf (stderr, " CRC EXT %02X, CRC CMP %02X", crc_extracted, crc_computed);
}
}

View File

@ -186,6 +186,22 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
sync[24] = 0;
//test for RC sync pattern in MS sourced audio
if ( strcmp (sync, DMR_RC_DATA_SYNC) == 0)
{
state->dmr_ms_rc = 1;
fprintf (stderr, "%s ", getTime());
if (opts->inverted_dmr == 0)
{
fprintf (stderr,"Sync: +DMR MS/DM MODE/MONO ");
}
else fprintf (stderr,"Sync: -DMR MS/DM MODE/MONO ");
fprintf (stderr, "| RC ");
fprintf (stderr, "\n");
}
for(i = 0; i < 8; i++) EmbeddedSignalling[i] = syncdata[i];
for(i = 0; i < 8; i++) EmbeddedSignalling[i + 8] = syncdata[i + 40];
@ -265,17 +281,20 @@ void dmrMS (dsd_opts * opts, dsd_state * state)
memcpy (m2, ambe_fr2, sizeof(m2));
memcpy (m3, ambe_fr3, sizeof(m3));
if (state->directmode == 0)
if (state->dmr_ms_rc == 0)
{
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
}
else
{
processMbeFrame (opts, state, NULL, ambe_fr4, NULL); //play duplicate of 2 here to smooth audio on tdma direct
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
if (state->directmode == 0)
{
processMbeFrame (opts, state, NULL, ambe_fr, NULL);
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
}
else
{
processMbeFrame (opts, state, NULL, ambe_fr4, NULL); //play duplicate of 2 here to smooth audio on tdma direct
processMbeFrame (opts, state, NULL, ambe_fr2, NULL);
processMbeFrame (opts, state, NULL, ambe_fr3, NULL);
}
}
if (vc == 6)

View File

@ -52,7 +52,7 @@ char * FM_banner[9] = {
" ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝",
" 'Lite' Edition v2.0.0-20-gd2d750e Windows 32-bit RC2b "
" 'Lite' Edition v2.0.0-21-gbb5da93 Windows 32-bit RC2c "
};
int
@ -967,9 +967,8 @@ usage ()
//printf (" (4 Level, not 8 Level LSM) (this is honestly unknown since I can't verify what local systems are using)\n");
printf (" -F Relax P25 Phase 2 MAC_SIGNAL CRC Checksum Pass/Fail\n");
printf (" Use this feature to allow MAC_SIGNAL even if CRC errors.\n");
printf (" -F Relax DMR CACH/Burst FEC Pass/Fail - Passive Frame Sync\n");
printf (" Use if skipping occurs, but may cause wonky audio due to loss of good sync\n");
printf (" -F Relax DMR CACH/Burst FEC or RAS/CRC CSBK Pass/Fail\n");
printf (" Enabling on some systems could lead to bad voice/data decoding if bad or marginal signal\n");
printf ("\n");
printf (" -K <dec> Manually Enter Basic Privacy Key (Decimal Value of Key Number)\n");
printf ("\n");
@ -1535,7 +1534,7 @@ main (int argc, char **argv)
fprintf (stderr, "%s", KYEL);
//fprintf (stderr,"DMR Stereo Aggressive Resync Disabled!\n");
fprintf (stderr, "Relax P25 Phase 2 MAC_SIGNAL CRC Checksum Pass/Fail\n");
fprintf (stderr, "Relax DMR CACH/Burst FEC Pass/Fail\n");
fprintf (stderr, "Relax DMR CACH/Burst FEC or RAS/CRC CSBK Pass/Fail\n");
fprintf (stderr, "%s", KNRM);
break;

View File

@ -2053,7 +2053,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->ncurses_compact == 1)
{
printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - Win32 %s \n", "v2.0.0-20-gd2d750e RC2b");
printw ("| Digital Speech Decoder: Florida Man Edition - Win32 %s \n", "v2.0.0-21-gbb5da93 RC2c");
}
if (opts->ncurses_compact == 0)
{
@ -2064,8 +2064,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (i == 1) printw (" ESC to Menu");
if (i == 2) printw (" 'q' to Quit ");
if (i == 4) printw (" MBElib %s", versionstr);
if (i == 5) printw (" %s ", "Win32 RC2b"); //printw (" %s \n", GIT_TAG);
if (i == 6) printw (" %s \n", "v2.0.0-20-gd2d750e"); //printw (" %s \n", GIT_TAG);
if (i == 5) printw (" %s ", "Win32 RC2c"); //printw (" %s \n", GIT_TAG);
if (i == 6) printw (" %s \n", "v2.0.0-21-gbb5da93"); //printw (" %s \n", GIT_TAG);
else printw ("\n");
}
attroff(COLOR_PAIR(6)); //6
@ -3254,6 +3254,38 @@ if (opts->p25_trunk == 1 && c == 103) //'g' key, toggle tune group calls
else opts->trunk_tune_group_calls = 1;
}
if (c == 70) //'F' key - toggle agressive sync/crc failure/ras
{
if (opts->aggressive_framesync == 0) opts->aggressive_framesync = 1;
else opts->aggressive_framesync = 0;
}
if (c == 68) //'D' key - Reset DMR Site Parms/Call Strings, etc.
{
//dmr trunking/ncurses stuff
state->dmr_rest_channel = -1; //init on -1
state->dmr_mfid = -1; //
//dmr mfid branding and site parms
sprintf(state->dmr_branding_sub, "%s", "");
sprintf(state->dmr_branding, "%s", "");
sprintf (state->dmr_site_parms, "%s", "");
//DMR Location Area - DMRLA B***S***
opts->dmr_dmrla_is_set = 0;
opts->dmr_dmrla_n = 0;
}
//Debug/Troubleshooting Option
if (c == 90) //'Z' key - Simulate NoCarrier/No VC/CC sync to zero out more stuff (capital Z)
{
// opts->p25_is_tuned = 0;
state->last_cc_sync_time = 0;
state->last_vc_sync_time = 0;
noCarrier(opts, state);
}
//anything with an entry box will need the inputs and outputs stopped first
//so probably just write a function to handle c input, and when c = certain values
//needing an entry box, then stop all of those