DMR -- Implement Best/Surviving Path on 3/4 Rate;

This commit is contained in:
lwvmobile
2023-10-02 08:32:34 -04:00
parent 5e0f64a7c2
commit 9dfbcc886f

View File

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