diff --git a/src/dmr_34.c b/src/dmr_34.c index 65530d5..596eec7 100644 --- a/src/dmr_34.c +++ b/src/dmr_34.c @@ -3,7 +3,7 @@ * DMR 3/4 Rate Simple Trellis Decoder * * LWVMOBILE - * 2023-09 DSD-FME Florida Man Edition + * 2023-10 DSD-FME Florida Man Edition *-----------------------------------------------------------------------------*/ #include "dsd.h" @@ -14,7 +14,7 @@ uint8_t interleave[98] = { 4, 5, 12, 13, 20, 21, 28, 29, 36, 37, 44, 45, 52, 53, 60, 61, 68, 69, 76, 77, 84, 85, 92, 93, 6, 7, 14, 15, 22, 23, 30, 31, 38, 39, 46, 47, 54, 55, 62, 63, 70, 71, 78, 79, 86, 87, 94, 95}; -//this is a convertion table for converting the dibit pairs into contellation points +//this is a convertion table for converting the dibit pairs into constellation points uint8_t constellation_map[16] = { 11, 12, 0, 7, 14, 9, 5, 2, 10, 13, 1, 6, 15, 8, 4, 3 }; @@ -34,10 +34,92 @@ uint8_t fsm[64] = { 2, 10, 6, 14, 0, 8, 4, 12, 6, 14, 0, 8, 4, 12, 2, 10}; +//attempt to find the surviving path, or the 'best' path available (most positions gained) +uint8_t fix_34(uint8_t * p, uint8_t state, int position) +{ + int i, j, k, counter, best_p, best_v, survivors; + uint8_t temp_s, tri, t; + + //status of surviving paths -- debug + int s[8]; UNUSED(s); UNUSED(survivors); + memset (s, 0, 8*sizeof(int)); + + //assign all potentially correct points to temporary storage + uint8_t temp_p[8]; + temp_p[0] = (p[position] ^ 1) & 0xF; + temp_p[1] = (p[position] ^ 3) & 0xF; + temp_p[2] = (p[position] ^ 5) & 0xF; + temp_p[3] = (p[position] ^ 7) & 0xF; + temp_p[4] = (p[position] ^ 9) & 0xF; + temp_p[5] = (p[position] ^ 11) & 0xF; + temp_p[6] = (p[position] ^ 13) & 0xF; + temp_p[7] = (p[position] ^ 15) & 0xF; + + best_p = 0; //best position + best_v = 0; //best path value + + for (k = 0; k < 8; k++) + { + temp_s = state; + counter = 0; + tri = 0; + for (i = position; i < 49; i++) + { + //assign temp t either as our temp_p, or next point of i + if (i == position) t = temp_p[k]; + else t = p[i]; + + if (tri != 0xFF) //while the path survives + { + tri = 0xFF; + for (j = 0; j < 8; j++) + { + if ( fsm[(temp_s*8)+j] == t ) + { + //return our tribit value and state for the next point + tri = temp_s = (uint8_t)j; + counter++; + break; + } + + } + + if (counter > best_p) + { + best_p = counter; + best_v = k; //if we make it further on current path, assign as best path + } + + // surviving path -- made it to 49 + if (i == 48) s[k] = 1; + + } + } + + } + + //NOTE: If there are no surviving paths, then that means there is another bit/point err + //Ideally, at the end of a single or multiple fixes, there should only be one survivor, but in practice, + //I've seen up to 4 surviving paths and somehow, get a good CRC and a good LRRP or LOCN decode + //multiple survivors seems common when the starting err position is very close to 49 + + //tally number of surviving paths + survivors = 0; + for (k = 0; k < 8; k++) + { + if (s[k] == 1) survivors++; + } + + //debug + // fprintf (stderr, "START: %d; BEST_P: %d; BEST_V: %d; Survivors: %d; Point: %d", position, best_p, best_v, survivors, temp_p[best_v]); + + return temp_p[best_v]; //return the point value of the best path's starting point value +} + uint32_t dmr_34(uint8_t * input, uint8_t treturn[18]) { int i, j; - uint32_t irr_err = 0; + uint32_t irr_err = 0; //irrecoverable errors uint8_t deinterleaved_dibits[98]; memset (deinterleaved_dibits, 0, sizeof(deinterleaved_dibits)); @@ -60,20 +142,15 @@ uint32_t dmr_34(uint8_t * input, uint8_t treturn[18]) for (i = 0; i < 49; i++) point[i] = constellation_map[nibs[i]]; - //debug view points -- point[0] should be zero + //debug view points // fprintf (stderr, "\n P ="); // for (i = 0; i < 49; i++) // fprintf (stderr, " %02d", point[i]); - //free-bee on err correction, point[0] should always be zero (flush bits) - point[0] = 0; - //convert constellation points into tribit values using the FSM uint8_t state = 0; uint32_t tribits[49]; memset (tribits, 0xF, sizeof(tribits)); - uint8_t hd[8]; - memset (hd, 0, sizeof(hd)); for (i = 0; i < 49; i++) { @@ -96,16 +173,14 @@ uint32_t dmr_34(uint8_t * input, uint8_t treturn[18]) //debug point, position of error, and state value // fprintf (stderr, "\n P: %d, %d:%d; ", point[i], i, state); + //attempt to fix point by looking for the best path from here + point[i] = fix_34(point, state, i); + //Make a hard decision and flip point to fit in current state - point[i] ^= 7; //lucky number 7 (0111) + // point[i] ^= 7; //lucky number 7 (0111) //fallback - memset (hd, 0, sizeof(hd)); - - //decrement one and try again + //decrement one and resume decoding if (i != 0) i--; - - //NOTE: Ideally, a full path metric to find the most likely path - //is the best way to correct this, but it is also complex and no guarantee to fix errs } @@ -122,7 +197,8 @@ uint32_t dmr_34(uint8_t * input, uint8_t treturn[18]) //break into chunks of 24 bit values and shuffle into 8-bit (byte) treturn values for (i = 0; i < 6; i++) { - temp = (tribits[(i*8)+0] << 21) + (tribits[(i*8)+1] << 18) + (tribits[(i*8)+2] << 15) + (tribits[(i*8)+3] << 12) + (tribits[(i*8)+4] << 9) + (tribits[(i*8)+5] << 6) + (tribits[(i*8)+6] << 3) + (tribits[(i*8)+7] << 0); + temp = (tribits[(i*8)+0] << 21) + (tribits[(i*8)+1] << 18) + (tribits[(i*8)+2] << 15) + (tribits[(i*8)+3] << 12) + + (tribits[(i*8)+4] << 9) + (tribits[(i*8)+5] << 6) + (tribits[(i*8)+6] << 3) + (tribits[(i*8)+7] << 0); treturn[(i*3)+0] = (temp >> 16) & 0xFF; treturn[(i*3)+1] = (temp >> 8) & 0xFF; @@ -130,9 +206,9 @@ uint32_t dmr_34(uint8_t * input, uint8_t treturn[18]) } //trellis point/state err tally - if (irr_err != 0) - fprintf (stderr, " ERR = %d", irr_err); + // if (irr_err != 0) + // fprintf (stderr, " P_ERR = %d", irr_err); - return (irr_err); + return (0); }