M17 - Tweaks to LSF Frame Decoding;

This commit is contained in:
lwvmobile 2024-04-04 08:39:13 -04:00
parent 7d8a081e3f
commit bceac916fe
1 changed files with 184 additions and 113 deletions

297
src/m17.c
View File

@ -707,41 +707,29 @@ void processM17STR(dsd_opts * opts, dsd_state * state)
} //end processM17STR
//original version using nxdn convolutional decoder
void processM17LSF(dsd_opts * opts, dsd_state * state)
{
//WIP: Switch to libM17 Viterbi Decoder for better performance
//Not yet working on actual signal, but debug version works
//most likely frame sync / demodulation related issue
//NOTE: Viterbi Decoder seems to respnd better
//when the 112-bit nonce value isn't all zeroes
//TODO: Work on implementing a symbol buffer of some sort
//when the preamble starts?
//NOTE: Works now with decisions based on previous bit, but still
//not quite as good as it needs to be, need better decision making on the punctured bit
int i, j, k, x;
uint8_t dbuf[184]; //384-bit (192 symbol) frame - 16-bit (8 symbol) sync pattern (184 dibits)
uint8_t dbuf[184]; //384-bit frame - 16-bit (8 symbol) sync pattern (184 dibits)
uint8_t m17_rnd_bits[368]; //368 bits that are still scrambled (randomized)
uint8_t m17_int_bits[368]; //368 bits that are still interleaved
uint8_t m17_rnd_bits[368]; //368 bits that are still scrambled
uint16_t m17_bits[368]; //368 bits that have been de-interleaved and de-scrambled
uint16_t m17_depunc[488]; //488 weighted byte representation of bits after depuncturing
uint8_t lsf_bytes[31];
uint8_t lsf_packed[30];
uint32_t v_err = 0; //errors in viterbi decoder
UNUSED(v_err);
uint8_t m17_bits[368]; //368 bits that have been de-interleaved and de-scramble
uint8_t m17_depunc[500]; //488 bits after depuncturing
memset (dbuf, 0, sizeof(dbuf));
memset (state->m17_lsf, 0, sizeof(state->m17_lsf));
memset (m17_rnd_bits, 0, sizeof(m17_rnd_bits));
memset (m17_int_bits, 0, sizeof(m17_int_bits));
memset (m17_bits, 0, sizeof(m17_bits));
memset (m17_rnd_bits, 0, sizeof(m17_rnd_bits));
memset (m17_depunc, 0, sizeof(m17_depunc));
memset (lsf_packed, 0, sizeof(lsf_packed));
memset (lsf_bytes, 0, sizeof(lsf_bytes));
//load dibits into dibit buffer
for (i = 0; i < 184; i++)
dbuf[i] = getDibit(opts, state);
dbuf[i] = (uint8_t) getDibit(opts, state);
//convert dbuf into a bit array
for (i = 0; i < 184; i++)
@ -762,108 +750,57 @@ void processM17LSF(dsd_opts * opts, dsd_state * state)
m17_bits[i] = m17_int_bits[x];
}
//P1 Depuncture & Add Weights
x = 0;
j = 0; k = 0; x = 0;
// P1 Depuncture
for (i = 0; i < 488; i++)
{
if (p1[i%61] == 1)
m17_depunc[i] = m17_bits[x++];
else m17_depunc[i] = 0;
//assign any puncture as a 0
// if (p1[k++] == 1) m17_depunc[x++] = m17_bits[j++];
// else m17_depunc[x++] = 0;
if (m17_depunc[i])
m17_depunc[i] = 0xFFFF;
else m17_depunc[i] = 0x7FFF;
}
//trailing zeroes
// for (i = 484; i < 488; i++)
// m17_depunc[i] = 0x7FFF;
//seems to be better if we use the last bit as an educated guess on what the next bit should be
//this pseudo logic is based purely on 0xFFFFFFFFFF as Broadcast, and all zeroes as the Meta(IV)
//debug -- fill all of the byte array
// memset (m17_depunc, 0xFFFF, sizeof(m17_depunc));
//debug
// fprintf (stderr, "\n depunc: \n");
// for (i = 0; i < 488; i++)
// fprintf (stderr, " %04X", m17_depunc[i]);
//use the libM17 Viterbi Decoder
uint16_t len = 488;
v_err = viterbi_decode(lsf_bytes, m17_depunc, len);
// v_err -= 3932040; //cost negation (double check this as well as unit, meaning, etc)
//debug
// fprintf (stderr, "\n lsf_bytes: \n");
// for (i = 0; i < 31; i++)
// fprintf (stderr, " %02X", lsf_bytes[i]);
//copy + left shift one octet
memcpy (lsf_packed, lsf_bytes+1, 30);
//Unpack bytes into m17_lsf bits
k = 0;
for (j = 0; j < 30; j++)
{
for (i = 0; i < 8; i++)
state->m17_lsf[k++] = (lsf_packed[j] >> 7-i) & 1;
}
uint16_t crc_cmp = crc16m17(lsf_packed, 28);
uint16_t crc_ext = (lsf_packed[28] << 8) + (lsf_packed[29] << 0);
int crc_err = 0;
if (crc_cmp != crc_ext) crc_err = 1;
if (crc_err == 0)
M17decodeLSF(state);
else if (opts->aggressive_framesync == 0)
M17decodeLSF(state);
if (opts->payload == 1)
{
fprintf (stderr, "\n LSF: ");
for (i = 0; i < 30; i++)
//DST, or META field
if (i < 48 || i > 96)
{
if (i == 15) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", lsf_packed[i]);
if (p1[k++] == 1) m17_depunc[x++] = m17_bits[j++];
else if (m17_depunc[x-2] == 1) m17_depunc[x++] = 1;
else m17_depunc[x++] = 0;
}
// fprintf (stderr, " V Err: %d", v_err);
else //any other field
{
if (p1[k++] == 1) m17_depunc[x++] = m17_bits[j++];
else m17_depunc[x++] = 0;
}
if (k == 61) k = 0; //61 -- should reset 8 times againt the array
}
//debug
// fprintf (stderr, " E-%04X; C-%04X (CRC CHK)", crc_ext, crc_cmp);
//debug -- values seem okay at end of run
// fprintf (stderr, "K = %d; J = %d; X = %d", k, j, x);
if (crc_err == 1) fprintf (stderr, " CRC ERR");
//debug deinterleaved bits
// fprintf (stderr, "\n DEINT: ");
// for (i = 0; i < 368; i++)
// fprintf (stderr, "%d,", m17_bits[i]);
//zero out after decoding
memset (state->m17_lsf, 0, sizeof(state->m17_lsf));
//ending linebreak
fprintf (stderr, "\n");
} //end processM17LSF
//This version is the older method, skipping the depuncturing and just doing deconv
void processM17LSF_debug(dsd_opts * opts, dsd_state * state, uint8_t * m17_depunc)
{
//NOTE: This version has been stripped down, but will not be used,
//but will keep in case of future debug for ease of use
int i, x; UNUSED(x);
uint8_t m17_int_bits[368]; //368 bits that are still interleaved
uint8_t m17_bits[368]; //368 bits that have been de-interleaved and de-scramble
memset (m17_int_bits, 0, sizeof(m17_int_bits));
memset (m17_bits, 0, sizeof(m17_bits));
//debug depunctured bits
// fprintf (stderr, "\n DEPUNC: ");
// for (i = 0; i < 488; i++)
// fprintf (stderr, "%d,", m17_depunc[i]);
//setup the convolutional decoder
uint8_t temp[488];
uint8_t temp[500];
uint8_t s0;
uint8_t s1;
uint8_t m_data[30];
uint8_t trellis_buf[240]; //30*8 = 240
uint8_t m_data[32];
uint8_t trellis_buf[260]; //30*8 = 240
memset (trellis_buf, 0, sizeof(trellis_buf));
memset (temp, 0, sizeof (temp));
memset (m_data, 0, sizeof (m_data));
@ -914,7 +851,7 @@ void processM17LSF_debug(dsd_opts * opts, dsd_state * state, uint8_t * m17_depun
if (crc_err == 0)
M17decodeLSF(state);
else if (opts->aggressive_framesync == 0)
M17decodeLSF(state);
M17decodeLSF(state);
if (opts->payload == 1)
{
@ -924,10 +861,144 @@ void processM17LSF_debug(dsd_opts * opts, dsd_state * state, uint8_t * m17_depun
if (i == 15) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", lsf_packed[i]);
}
fprintf (stderr, " (CRC CHK) E-%04X; C-%04X;", crc_ext, crc_cmp);
}
if (crc_err == 1) fprintf (stderr, " CRC ERR");
//ending linebreak
fprintf (stderr, "\n");
} //end processM17LSF
//This version is the older method, skipping the depuncturing and just doing deconv
void processM17LSF_debug(dsd_opts * opts, dsd_state * state, uint8_t * m17_rnd_bits)
{
//NOTE: Why is this being a pain in the ass now?
int i, j, k, x;
uint8_t m17_int_bits[368]; //368 bits that are still interleaved
uint8_t m17_bits[368]; //368 bits that have been de-interleaved and de-scramble
uint8_t m17_depunc[500]; //488 bits after depuncturing
memset (m17_int_bits, 0, sizeof(m17_int_bits));
memset (m17_bits, 0, sizeof(m17_bits));
memset (m17_depunc, 0, sizeof(m17_depunc));
//descramble the frame
for (i = 0; i < 368; i++)
m17_int_bits[i] = (m17_rnd_bits[i] ^ m17_scramble[i]) & 1;
//deinterleave the bit array using Quadratic Permutation Polynomial
//function π(x) = (45x + 92x^2 ) mod 368
for (i = 0; i < 368; i++)
{
x = ((45*i)+(92*i*i)) % 368;
m17_bits[i] = m17_int_bits[x];
}
//debug
// fprintf (stderr, " E-%04X; C-%04X (CRC CHK)", crc_ext, crc_cmp);
j = 0; k = 0; x = 0;
// P1 Depuncture
for (i = 0; i < 488; i++)
{
//assign any puncture as a 0
// if (p1[k++] == 1) m17_depunc[x++] = m17_bits[j++];
// else m17_depunc[x++] = 0;
//seems to be better if we use the last bit as an educated guess on what the next bit should be
//this pseudo logic is based purely on 0xFFFFFFFFFF as Broadcast, and all zeroes as the Meta(IV)
//DST, or META field
if (i < 48 || i > 96)
{
if (p1[k++] == 1) m17_depunc[x++] = m17_bits[j++];
else if (m17_depunc[x-2] == 1) m17_depunc[x++] = 1;
else m17_depunc[x++] = 0;
}
else //any other field
{
if (p1[k++] == 1) m17_depunc[x++] = m17_bits[j++];
else m17_depunc[x++] = 0;
}
if (k == 61) k = 0; //61 -- should reset 8 times againt the array
}
//setup the convolutional decoder
uint8_t temp[500];
uint8_t s0;
uint8_t s1;
uint8_t m_data[32];
uint8_t trellis_buf[260]; //30*8 = 240
memset (trellis_buf, 0, sizeof(trellis_buf));
memset (temp, 0, sizeof (temp));
memset (m_data, 0, sizeof (m_data));
for (i = 0; i < 488; i++)
temp[i] = m17_depunc[i] << 1;
CNXDNConvolution_start();
for (i = 0; i < 244; i++)
{
s0 = temp[(2*i)];
s1 = temp[(2*i)+1];
CNXDNConvolution_decode(s0, s1);
}
CNXDNConvolution_chainback(m_data, 240);
//244/8 = 30, last 4 (244-248) are trailing zeroes
for(i = 0; i < 30; i++)
{
trellis_buf[(i*8)+0] = (m_data[i] >> 7) & 1;
trellis_buf[(i*8)+1] = (m_data[i] >> 6) & 1;
trellis_buf[(i*8)+2] = (m_data[i] >> 5) & 1;
trellis_buf[(i*8)+3] = (m_data[i] >> 4) & 1;
trellis_buf[(i*8)+4] = (m_data[i] >> 3) & 1;
trellis_buf[(i*8)+5] = (m_data[i] >> 2) & 1;
trellis_buf[(i*8)+6] = (m_data[i] >> 1) & 1;
trellis_buf[(i*8)+7] = (m_data[i] >> 0) & 1;
}
memset (state->m17_lsf, 0, sizeof(state->m17_lsf));
memcpy (state->m17_lsf, trellis_buf, 240);
uint8_t lsf_packed[30];
memset (lsf_packed, 0, sizeof(lsf_packed));
//need to pack bytes for the sw5wwp variant of the crc (might as well, may be useful in the future)
for (i = 0; i < 30; i++)
lsf_packed[i] = (uint8_t)ConvertBitIntoBytes(&state->m17_lsf[i*8], 8);
uint16_t crc_cmp = crc16m17(lsf_packed, 28);
uint16_t crc_ext = (uint16_t)ConvertBitIntoBytes(&state->m17_lsf[224], 16);
int crc_err = 0;
if (crc_cmp != crc_ext) crc_err = 1;
if (crc_err == 0)
M17decodeLSF(state);
else if (opts->aggressive_framesync == 0)
M17decodeLSF(state);
if (opts->payload == 1)
{
fprintf (stderr, "\n LSF: ");
for (i = 0; i < 30; i++)
{
if (i == 15) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", lsf_packed[i]);
}
fprintf (stderr, " (CRC CHK) E-%04X; C-%04X;", crc_ext, crc_cmp);
}
if (crc_err == 1) fprintf (stderr, " CRC ERR");
@ -2089,7 +2160,7 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state)
fprintf (stderr, "\n M17 LSF (ENCODER): ");
if (opts->monitor_input_audio == 0)
processM17LSF_debug2(opts, state, m17_lsfs);
processM17LSF_debug(opts, state, m17_lsfs);
else fprintf (stderr, " To Audio Out Device Type: %d; ", opts->audio_out_type);
//convert bit array into symbols and RF/Audio
@ -2822,7 +2893,7 @@ void encodeM17PKT(dsd_opts * opts, dsd_state * state)
{
fprintf (stderr, "\n M17 LSF (ENCODER): ");
processM17LSF_debug2(opts, state, m17_lsfs);
processM17LSF_debug(opts, state, m17_lsfs);
//convert bit array into symbols and RF/Audio
memset (nil, 0, sizeof(nil));