From 4138f92917df3438d55055214e5819c3c13c448e Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 17 Oct 2022 17:16:22 -0400 Subject: [PATCH] DMR Burst Type FEC Fix; --- src/dmr_data.c | 79 ++++++++----------------------------- src/dmr_ms.c | 92 +++++++++++++++++++++++++++++++++++--------- src/dsd_dibit.c | 12 ++++-- src/dsd_frame_sync.c | 8 ++-- src/dsd_main.c | 7 ++-- src/fec.c | 10 +++++ 6 files changed, 116 insertions(+), 92 deletions(-) diff --git a/src/dmr_data.c b/src/dmr_data.c index ea80c19..996a482 100644 --- a/src/dmr_data.c +++ b/src/dmr_data.c @@ -25,23 +25,17 @@ processDMRdata (dsd_opts * opts, dsd_state * state) int *dibit_p; char sync[25]; char syncdata[48]; - char cachdata[25] = {0}; //increased from 24 to 25 to see if this fixes ubuntu 32 bug + char cachdata[25] = {0}; char cc[5] = {0}; char ccAscii[5] = {0}; char bursttype[5]; unsigned int burst; char info[196]; - // char SlotType[20]; //was char, but I don't think FEC brings back good values when usign that - unsigned char SlotType[20]; //was char, but I don't think FEC brings back good values when usign that + + unsigned char SlotType[20]; unsigned int SlotTypeOk; int cachInterleave[24] = {0, 7, 8, 9, 1, 10, 11, 12, 2, 13, 14, 15, 3, 16, 4, 17, 18, 19, 5, 20, 21, 22, 6, 23}; - - /* Remove warning compiler */ - //UNUSED_VARIABLE(cachdata[0]); - //UNUSED_VARIABLE(cc[0]); - //UNUSED_VARIABLE(ccAscii[0]); - #ifdef DMR_DUMP char syncbits[49]; char cachbits[25]; @@ -51,16 +45,8 @@ processDMRdata (dsd_opts * opts, dsd_state * state) ccAscii[4] = 0; bursttype[4] = 0; - //dibit_p = state->dibit_buf_p - 90; - //using the estimate_symbol method for the dmr_payload_p buffer causes sync - //issues with P25, so only do it when frame_p25p1 == 0, or -fr option - //temp fix to only use dmr_payload_p buffer when no inversion expected, otherwise use dibit_buf - // if (opts->frame_p25p1 == 0 && opts->inverted_dmr == 0) //opts->frame_p25p1 == 0 && opts->inverted_dmr == 0 - // { - // dibit_p = state->dmr_payload_p - 90; - // } dibit_p = state->dmr_payload_p - 90; - // CACH, why aren't we running any FEC on this? + // CACH for (i = 0; i < 12; i++) { dibit = *dibit_p; @@ -73,39 +59,14 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[i]; } - //fprintf(stderr, "%X", dibit); - //cachdata[i] = dibit; cachdata[cachInterleave[(i*2)]] = (1 & (dibit >> 1)); // bit 1 cachdata[cachInterleave[(i*2)+1]] = (1 & dibit); // bit 0 - // cachdata[(i*2)] = (1 & (dibit >> 1)); // bit 1 - // cachdata[(i*2)+1] = (1 & dibit); // bit 0 - if (i == 2) - { - /* Change the current slot only if we are in relayed mode (not in direct mode) */ - // if(state->directmode == 0) state->currentslot = (1 & (dibit >> 1)); //move this until after cach fec performed - // - // if (state->currentslot == 0 && state->dmr_ms_mode == 0) - // { - // state->slot1light[0] = '['; - // state->slot1light[6] = ']'; - // state->slot2light[0] = ' '; - // state->slot2light[6] = ' '; - // } - // //else - // if (state->currentslot == 1 && state->dmr_ms_mode == 0) - // { - // state->slot2light[0] = '['; - // state->slot2light[6] = ']'; - // state->slot1light[0] = ' '; - // state->slot1light[6] = ' '; - // } - - } } - //cachdata[12] = 0; - cachdata[25] = 0; //setting to see if this fixes ubuntu 32 bit bug + + cachdata[25] = 0; + //decode and correct cach and compare int cach_okay = 69; if ( Hamming_7_4_decode (cachdata) ) //is now de-interleaved appropriately @@ -221,10 +182,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[63]; //(int) } -// burst = (unsigned int)((1 & (dibit >> 1)) << 3); -// burst |= (unsigned int)((1 & (dibit >> 0)) << 2); -// bursttype[0] = (1 & (dibit >> 1)) + 48; // bit 1 -// bursttype[1] = (1 & dibit) + 48; // bit 0 + SlotType[4] = (1 & (dibit >> 1)); // bit 1 SlotType[5] = (1 & dibit); // bit 0 @@ -238,10 +196,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) { dibit = (int)state->dmr_stereo_payload[64]; //(int) } -// burst |= (unsigned int)((1 & (dibit >> 1)) << 1); -// burst |= (unsigned int)((1 & (dibit >> 0)) << 0); -// bursttype[2] = (1 & (dibit >> 1)) + 48; // bit 1 -// bursttype[3] = (1 & dibit) + 48; // bit 0 + SlotType[6] = (1 & (dibit >> 1)); // bit 1 SlotType[7] = (1 & dibit); // bit 0 @@ -259,7 +214,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) SlotType[8] = (1 & (dibit >> 1)); // bit 1 SlotType[9] = (1 & dibit); // bit 0 - // signaling data or sync + // signalling data or sync for (i = 0; i < 24; i++) { dibit = *dibit_p; @@ -270,13 +225,15 @@ processDMRdata (dsd_opts * opts, dsd_state * state) } if (state->dmr_stereo == 1) { - dibit = (int)state->dmr_stereo_payload[i+66]; //double check these i+ values make sure we are on the right ones + dibit = (int)state->dmr_stereo_payload[i+66]; } syncdata[2*i] = (1 & (dibit >> 1)); // bit 1 syncdata[(2*i)+1] = (1 & dibit); // bit 0 sync[i] = (dibit | 1) + 48; + + } - sync[24] = 0; //why? + sync[24] = 0; #ifdef DMR_DUMP k = 0; @@ -340,8 +297,8 @@ processDMRdata (dsd_opts * opts, dsd_state * state) } /* Check and correct the SlotType (apply Golay(20,8) FEC check) */ - //pretty sure this isn't working correcty, does not apply corrected bits, due to cast type mismatching - // if(Golay_20_8_decode((unsigned char *)SlotType)) SlotTypeOk = 1; + + // golay (20,8) hamming-weight of 6 reliably corrects at most 2 bit-errors if( Golay_20_8_decode(SlotType) ) { SlotTypeOk = 1; @@ -354,10 +311,8 @@ processDMRdata (dsd_opts * opts, dsd_state * state) } /* Slot Type parity checked => Fill the color code */ - //state->color_code = (unsigned int)((cc[0] << 3) + (cc[1] << 2) + (cc[2] << 1) + cc[3]); state->color_code = (SlotType[0] << 3) + (SlotType[1] << 2) +(SlotType[2] << 1) + (SlotType[3] << 0); state->color_code_ok = SlotTypeOk; - //fprintf(stderr, "| Color Code=%02d ", (int)state->color_code); /* Reconstitute the burst type */ //consider assigning this only when slottypeok or similar check passes, eliminate bad burst types from decoding randomly @@ -594,7 +549,7 @@ processDMRdata (dsd_opts * opts, dsd_state * state) if (SlotTypeOk == 0 || cach_okay == 0) { fprintf (stderr, "%s", KRED); - fprintf (stderr, " **CACH or Burst Type FEC ERR - SKIPPING** "); + fprintf (stderr, "| **CACH or Burst Type FEC ERR ** "); fprintf (stderr, "%s", KNRM); fprintf (stderr, "\n"); } diff --git a/src/dmr_ms.c b/src/dmr_ms.c index 94db81a..0e91c82 100644 --- a/src/dmr_ms.c +++ b/src/dmr_ms.c @@ -26,6 +26,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) int msMode; char cc[4]; unsigned char EmbeddedSignalling[16]; + unsigned char EmbeddedSignallingInverse[16]; int EmbeddedSignallingOk; unsigned int internalcolorcode; int internalslot; @@ -71,8 +72,8 @@ void dmrMS (dsd_opts * opts, dsd_state * state) short int m = 0; - state->dmrburstL = 16; //Use 16 for Voice? - // No CACH in MS/DM Mode? + state->dmrburstL = 16; //Use 16 for Voice + for(i = 0; i < 12; i++) { dibit = getDibit(opts, state); @@ -82,11 +83,7 @@ void dmrMS (dsd_opts * opts, dsd_state * state) } cachdata[i] = dibit; state->dmr_stereo_payload[i] = dibit; - if(i == 2) - { - //state->currentslot = (1 & (dibit >> 1)); - //internalslot = (1 & (dibit >> 1)); - } + } //Setup for first AMBE Frame @@ -193,11 +190,28 @@ void dmrMS (dsd_opts * opts, dsd_state * state) sync[24] = 0; EmbeddedSignallingOk = -1; + + // for (i = 0; i < 16; i++) + // { + // EmbeddedSignallingInverse[i] = EmbeddedSignalling[i] ^ 1; + // } + if(QR_16_7_6_decode(EmbeddedSignalling)) { EmbeddedSignallingOk = 1; } + //test for inverted signal - this should move to data, and have a slottype check here perhaps? + // else if (QR_16_7_6_decode(EmbeddedSignallingInverse)) + // { + // if (opts->inverted_dmr == 0) + // { + // opts->inverted_dmr = 1; + // } + // else opts->inverted_dmr = 0; + // goto END; + // } + internalcolorcode = 69; //set so we know if this value is being set properly if(EmbeddedSignallingOk == 1) { @@ -543,14 +557,13 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) } state->dmrburstL = 16; //Use 16 for Voice? dibit_p = state->dmr_payload_p - 90; - //payload buffer tests + //CACH + First Half Payload + Sync = 12 + 54 + 24 for (i = 0; i < 90; i++) //90 { state->dmr_stereo_payload[i] = *dibit_p; dibit_p++; } - //end payload buffer test for(i = 0; i < 12; i++) { @@ -614,11 +627,12 @@ void dmrMSBootstrap (dsd_opts * opts, dsd_state * state) z++; } - + //Continue Second AMBE Frame, 18 after Sync or EmbeddedSignalling for(i = 0; i < 18; i++) { dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) { dibit = (dibit ^ 2); @@ -770,7 +784,7 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) unsigned char MSSlot[20] = {0}; //10 dibits = 20 bits unsigned char MSBurst[5] = {0}; int cachInterleave[24] = {0, 7, 8, 9, 1, 10, 11, 12, 2, 13, 14, 15, 3, 16, 4, 17, 18, 19, 5, 20, 21, 22, 6, 23}; - //int cachInterleave[24] = {0,} + //add time to mirror sync time_t now; char * getTime(void) //get pretty hh:mm:ss timestamp @@ -789,8 +803,8 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) } b = 0; c = 0; + //CACH + First Half Payload + Sync = 12 + 54 + 24 - //dibit_p = state->dibit_buf_p - 90; dibit_p = state->dmr_payload_p - 90; for (i = 0; i < 90; i++) //90 { @@ -798,7 +812,7 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) dibit_p++; if(opts->inverted_dmr == 1) { - dibit = (dibit ^ 2); + dibit = (dibit ^ 2); } state->dmr_stereo_payload[i] = dibit; //load cach @@ -826,6 +840,10 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) for (i = 0; i < 54; i++) { dibit = getDibit(opts, state); + if(opts->inverted_dmr == 1) + { + dibit = (dibit ^ 2); + } state->dmr_stereo_payload[i+90] = dibit; //load slot, second half if (i < 6) @@ -839,8 +857,8 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) //state->directmode = 0; //flag off for testing - //hide behind payload due to errs in data in MS/DM mode - if (opts->payload == 1 && state->directmode == 0) + //with FEC fix, now we can (hopefully) feel confident in running MS data + if (1 == 1) //opts->payload == 1 && state->directmode == 0 { fprintf (stderr, "%s ", getTime()); if (opts->inverted_dmr == 0) @@ -850,6 +868,34 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) else fprintf (stderr,"Sync: -DMR MS/DM MODE "); } + // decode and correct cach and slot + // golay (20,8) hamming-weight of 6 reliably corrects at most 2 bit-errors + int cach_okay = -1; + if ( Hamming_7_4_decode (MSCach) ) + { + cach_okay = 1; + } + if (cach_okay == 1) + { + //fprintf (stderr, "CACH Okay "); + } + else + { + //fprintf (stderr, "CACH ERR "); + goto END; + } + + int slot_okay = -1; + if(Golay_20_8_decode(MSSlot)) + { + slot_okay = 1; + } + if (slot_okay == 1) + { + //fprintf (stderr, "Slot Okay "); + } + else goto END; + sprintf(state->slot1light, "%s", ""); sprintf(state->slot2light, "%s", ""); @@ -858,23 +904,33 @@ void dmrMSData (dsd_opts * opts, dsd_state * state) state->dmr_stereo = 1; state->dmr_ms_mode = 1; - //only run if payload is set to 1 due to errors with MS data - if (opts->payload == 1 && state->directmode == 0) //don't run on Direct Mode just yet + //with FEC fix, now we can (hopefully) feel confident in running MS data + if (1 == 1) //opts->payload == 1 && state->directmode == 0 { processDMRdata (opts, state); } + END: + if (slot_okay != 1 || cach_okay != 1) + { + fprintf (stderr, "%s", KRED); + fprintf (stderr, "| **CACH or Burst Type FEC ERR ** "); + fprintf (stderr, "%s", KNRM); + fprintf (stderr, "\n"); + } + state->dmr_stereo = 0; state->dmr_ms_mode = 0; state->directmode = 0; //flag off //get potential first half payload dibits and store them in the payload for the next repitition, MS voice or data. skipDibit (opts, state, 144); + //CACH + First Half Payload = 12 + 54 for (i = 0; i < 66; i++) //66 { dibit = getDibit(opts, state); - state->dmr_stereo_payload[i] = dibit; + state->dmr_stereo_payload[i] = dibit; } } diff --git a/src/dsd_dibit.c b/src/dsd_dibit.c index a11b44b..bdb419a 100644 --- a/src/dsd_dibit.c +++ b/src/dsd_dibit.c @@ -170,7 +170,7 @@ use_symbol (dsd_opts* opts, dsd_state* state, int symbol) } // Increase sidx - if (state->sidx == (opts->ssize - 1)) + if (state->sidx >= (opts->ssize - 1)) { state->sidx = 0; @@ -315,13 +315,11 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol) state->last_dibit = dibit; - // store non-inverted values in dibit_buf *state->dibit_buf_p = invert_dibit(dibit); state->dibit_buf_p++; //dmr buffer - *state->dmr_payload_p = invert_dibit(dibit); //invert, or no? - // *state->dmr_payload_p = dibit; //invert, or no? + *state->dmr_payload_p = invert_dibit(dibit); state->dmr_payload_p++; //dmr buffer end @@ -377,9 +375,15 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol) } state->last_dibit = dibit; + *state->dibit_buf_p = dibit; state->dibit_buf_p++; + //dmr buffer + //note to self, perceived bug with initial dibit buffer appears to be caused by + //media player, when playing back from audacity, the initial few dmr frames are + //decoded properly, need to investigate the root cause of what audacity is doing + //vs other audio sources...perhaps just the audio level itself? *state->dmr_payload_p = dibit; state->dmr_payload_p++; //dmr buffer end diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index c7bb4b5..4d5f2e6 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -955,7 +955,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) { pa_simple_flush(opts->pulse_raw_dev_out, NULL); } - //return (33); + return (33); } else { @@ -998,7 +998,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) { pa_simple_flush(opts->pulse_raw_dev_out, NULL); } - //return (33); + return (33); } else { @@ -1100,7 +1100,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) //printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation); } state->lastsynctype = 13; - //return (33); + return (33); } } /* End if(strcmp (synctest, DMR_DIRECT_MODE_TS1_VOICE_SYNC) == 0) */ if(strcmp (synctest, DMR_DIRECT_MODE_TS2_VOICE_SYNC) == 0) @@ -1143,7 +1143,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) { pa_simple_flush(opts->pulse_raw_dev_out, NULL); } - //return (33); + return (33); } } //End if(strcmp (synctest, DMR_DIRECT_MODE_TS2_VOICE_SYNC) == 0) } //End if (opts->frame_dmr == 1) diff --git a/src/dsd_main.c b/src/dsd_main.c index f93f49f..9b2f9d4 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -76,7 +76,6 @@ char * pEnd; //bugfix void noCarrier (dsd_opts * opts, dsd_state * state) { - // state->testcounter = 0; state->dibit_buf_p = state->dibit_buf + 200; memset (state->dibit_buf, 0, sizeof (int) * 200); //dmr buffer @@ -84,9 +83,9 @@ noCarrier (dsd_opts * opts, dsd_state * state) memset (state->dmr_payload_buf, 0, sizeof (int) * 200); //dmr buffer end if (opts->mbe_out_f != NULL) - { - closeMbeOutFile (opts, state); - } + { + closeMbeOutFile (opts, state); + } state->jitter = -1; state->lastsynctype = -1; state->carrier = 0; diff --git a/src/fec.c b/src/fec.c index cfb95f5..b29e21a 100644 --- a/src/fec.c +++ b/src/fec.c @@ -872,11 +872,14 @@ void Golay_20_8_encode(unsigned char *origBits, unsigned char *encodedBits) } } +// golay (20,8) hamming-weight of 6 reliably corrects at most 2 bit-errors bool Golay_20_8_decode(unsigned char *rxBits) { unsigned int syndromeI = 0; // syndrome index int is = 0; int i = 0; + //tally corrections made, exceeding 2 will return false + int correction = 0; for (is = 0; is < 12; is++) { @@ -915,6 +918,7 @@ bool Golay_20_8_decode(unsigned char *rxBits) else { rxBits[Golay_20_8_m_corr[syndromeI][i]] ^= 1; // flip bit + correction++; } } @@ -922,6 +926,12 @@ bool Golay_20_8_decode(unsigned char *rxBits) { return false; } + + //return false due to exceeding the number of allowed corrected bits + if (correction > 2) + { + return false; + } } return true;