diff --git a/src/m17.c b/src/m17.c index 8b7200a..8431e27 100644 --- a/src/m17.c +++ b/src/m17.c @@ -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));