diff --git a/src/3.c b/src/3.c index a4d05fe..c2adde2 100644 --- a/src/3.c +++ b/src/3.c @@ -2,7 +2,7 @@ * 3.c * Placeholder File 3 -- This file is for temporary code storage * - * A 1/2 Rate Convolutional Decoder for NXDN/M17/YSF + * Multiple 1/2 Rate Convolutional Decoders for NXDN/M17/YSF * Used as a secondary decoder in case convolutional decoder fails (second opinion) *-----------------------------------------------------------------------------*/ @@ -87,15 +87,6 @@ void trellis_decode(uint8_t result[], const uint8_t source[], int result_len) */ //Ripped from libM17 - -//prototypes -// uint32_t viterbi_decode(uint8_t* out, const uint16_t* in, const uint16_t len); -// uint32_t viterbi_decode_punctured(uint8_t* out, const uint16_t* in, const uint8_t* punct, const uint16_t in_len, const uint16_t p_len); -// void viterbi_decode_bit(uint16_t s0, uint16_t s1, const size_t pos); -// uint32_t viterbi_chainback(uint8_t* out, size_t pos, uint16_t len); -// void viterbi_reset(void); -// uint16_t q_abs_diff(const uint16_t v1, const uint16_t v2); - #define K 5 //constraint length #define NUM_STATES (1 << (K - 1)) //number of states @@ -106,52 +97,58 @@ static uint32_t currMetricsData[NUM_STATES]; static uint16_t viterbi_history[244]; /** - * @brief Decode unpunctured convolutionally encoded data. - * - * @param out Destination array where decoded data is written. - * @param in Input data. - * @param len Input length in bits. - * @return Number of bit errors corrected. - */ +* @brief Decode unpunctured convolutionally encoded data. +* +* @param out Destination array where decoded data is written. +* @param in Input data. +* @param len Input length in bits. +* @return Number of bit errors corrected. +*/ uint32_t viterbi_decode(uint8_t* out, const uint16_t* in, const uint16_t len) { - if(len > 244*2) + if(len > 244*2) fprintf(stderr, "Input size exceeds max history\n"); - viterbi_reset(); + viterbi_reset(); - size_t pos = 0; - for(size_t i = 0; i < len; i += 2) - { - uint16_t s0 = in[i]; - uint16_t s1 = in[i + 1]; + size_t pos = 0; + for(size_t i = 0; i < len; i += 2) + { + uint16_t s0 = in[i]; + uint16_t s1 = in[i + 1]; - viterbi_decode_bit(s0, s1, pos); - pos++; - } + viterbi_decode_bit(s0, s1, pos); + pos++; + } + uint32_t err = viterbi_chainback(out, pos, len/2); - return viterbi_chainback(out, pos, len/2); + //debug + // fprintf (stderr, "\n vcb: \n"); + // for (size_t i = 0; i < len; i++) + // fprintf (stderr, "%02X", out[i]); + + return err; } /** - * @brief Decode punctured convolutionally encoded data. - * - * @param out Destination array where decoded data is written. - * @param in Input data. - * @param punct Puncturing matrix. - * @param in_len Input data length. - * @param p_len Puncturing matrix length (entries). - * @return Number of bit errors corrected. - */ +* @brief Decode punctured convolutionally encoded data. +* +* @param out Destination array where decoded data is written. +* @param in Input data. +* @param punct Puncturing matrix. +* @param in_len Input data length. +* @param p_len Puncturing matrix length (entries). +* @return Number of bit errors corrected. +*/ uint32_t viterbi_decode_punctured(uint8_t* out, const uint16_t* in, const uint8_t* punct, const uint16_t in_len, const uint16_t p_len) { - if(in_len > 244*2) - fprintf(stderr, "Input size exceeds max history\n"); + if(in_len > 244*2) + fprintf(stderr, "Input size exceeds max history\n"); - uint16_t umsg[244*2]; //unpunctured message - uint8_t p=0; //puncturer matrix entry - uint16_t u=0; //bits count - unpunctured message - uint16_t i=0; //bits read from the input message + uint16_t umsg[244*2]; //unpunctured message + uint8_t p=0; //puncturer matrix entry + uint16_t u=0; //bits count - unpunctured message + uint16_t i=0; //bits read from the input message while(i= m1) - { - viterbi_history[pos]|=(1<= m1) + { + viterbi_history[pos]|=(1<= m3) - { - viterbi_history[pos]|=(1<= m3) + { + viterbi_history[pos]|=(1< 0) - { - bitPos--; - pos--; - uint16_t bit = viterbi_history[pos]&((1<<(state>>4))); - state >>= 1; - if(bit) - { - state |= 0x80; - out[bitPos/8]|=1<<(7-(bitPos%8)); + while(pos > 0) + { + bitPos--; + pos--; + uint16_t bit = viterbi_history[pos]&((1<<(state>>4))); + state >>= 1; + if(bit) + { + state |= 0x80; + out[bitPos/8]|=1<<(7-(bitPos%8)); } - } + } - uint32_t cost = prevMetrics[0]; + uint32_t cost = prevMetrics[0]; - for(size_t i = 0; i < NUM_STATES; i++) - { - uint32_t m = prevMetrics[i]; - if(m < cost) cost = m; - } + for(size_t i = 0; i < NUM_STATES; i++) + { + uint32_t m = prevMetrics[i]; + if(m < cost) cost = m; + } - return cost; + //debug + // fprintf (stderr, "\n cb: \n"); + // for (size_t i = 0; i < len; i++) + // fprintf (stderr, "%02X", out[i]); + + return cost; } /** @@ -283,15 +288,15 @@ void viterbi_reset(void) { memset((uint8_t*)viterbi_history, 0, 2*244); memset((uint8_t*)currMetrics, 0, 4*NUM_STATES); - memset((uint8_t*)prevMetrics, 0, 4*NUM_STATES); - memset((uint8_t*)currMetricsData, 0, 4*NUM_STATES); - memset((uint8_t*)prevMetricsData, 0, 4*NUM_STATES); + memset((uint8_t*)prevMetrics, 0, 4*NUM_STATES); + memset((uint8_t*)currMetricsData, 0, 4*NUM_STATES); + memset((uint8_t*)prevMetricsData, 0, 4*NUM_STATES); } uint16_t q_abs_diff(const uint16_t v1, const uint16_t v2) { - if(v2 > v1) return v2 - v1; - return v1 - v2; + if(v2 > v1) return v2 - v1; + return v1 - v2; } //original sources diff --git a/src/m17.c b/src/m17.c index b8d8ac7..9000f29 100644 --- a/src/m17.c +++ b/src/m17.c @@ -684,26 +684,36 @@ void processM17STR(dsd_opts * opts, dsd_state * state) 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: Have not been able to get this to work successfully, but considering - //there is only one LSF frame at the beginning of TX, its probably just as easy to - //use and rely on the STR frame and embedded LSF chunk, which does work properly - int i, x; - 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) + //TODO: Work on implementing a symbol buffer of some sort + //when the preamble starts? + + int i, j, k, x; + uint8_t dbuf[184]; //384-bit (192 symbol) frame - 16-bit (8 symbol) sync pattern (184 dibits) 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[488]; //488 bits after depuncturing + 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); memset (dbuf, 0, sizeof(dbuf)); - memset (m17_rnd_bits, 0, sizeof(m17_rnd_bits)); + memset (state->m17_lsf, 0, sizeof(state->m17_lsf)); 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] = (uint8_t) getDibit(opts, state); + dbuf[i] = getDibit(opts, state); //convert dbuf into a bit array for (i = 0; i < 184; i++) @@ -724,67 +734,54 @@ void processM17LSF(dsd_opts * opts, dsd_state * state) m17_bits[i] = m17_int_bits[x]; } - // P1 Depuncture + //P1 Depuncture & Add Weights x = 0; for (i = 0; i < 488; i++) { if (p1[i%61] == 1) m17_depunc[i] = m17_bits[x++]; else m17_depunc[i] = 0; + + if (m17_depunc[i]) + m17_depunc[i] = 0xFFFF; + else m17_depunc[i] = 0x7FFF; } - //debug -- values seem okay at end of run - // fprintf (stderr, "K = %d; J = %d; X = %d", k, j, x); + //trailing zeroes + // for (i = 484; i < 488; i++) + // m17_depunc[i] = 0x7FFF; - //setup the convolutional decoder - uint8_t temp[488]; - uint8_t s0; - uint8_t s1; - uint8_t m_data[30]; - uint8_t trellis_buf[240]; //30*8 = 240 - memset (trellis_buf, 0, sizeof(trellis_buf)); - memset (temp, 0, sizeof (temp)); - memset (m_data, 0, sizeof (m_data)); + //debug -- fill all of the byte array + // memset (m17_depunc, 0xFFFF, sizeof(m17_depunc)); - for (i = 0; i < 488; i++) - temp[i] = m17_depunc[i] << 1; + //debug + // fprintf (stderr, "\n depunc: \n"); + // for (i = 0; i < 488; i++) + // fprintf (stderr, " %04X", m17_depunc[i]); - CNXDNConvolution_start(); - for (i = 0; i < 244; 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++) { - s0 = temp[(2*i)]; - s1 = temp[(2*i)+1]; - - CNXDNConvolution_decode(s0, s1); + for (i = 0; i < 8; i++) + state->m17_lsf[k++] = (lsf_packed[j] >> 7-i) & 1; } - 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); + uint16_t crc_ext = (lsf_packed[28] << 8) + (lsf_packed[29] << 0); int crc_err = 0; if (crc_cmp != crc_ext) crc_err = 1; @@ -800,6 +797,7 @@ void processM17LSF(dsd_opts * opts, dsd_state * state) if (i == 15) fprintf (stderr, "\n "); fprintf (stderr, "[%02X]", lsf_packed[i]); } + // fprintf (stderr, " V Err: %d", v_err); } //debug @@ -807,6 +805,9 @@ void processM17LSF(dsd_opts * opts, dsd_state * state) if (crc_err == 1) fprintf (stderr, " CRC ERR"); + //zero out after decoding + memset (state->m17_lsf, 0, sizeof(state->m17_lsf)); + //ending linebreak fprintf (stderr, "\n"); @@ -816,43 +817,15 @@ void processM17LSF(dsd_opts * opts, dsd_state * state) void processM17LSF_debug(dsd_opts * opts, dsd_state * state, uint8_t * m17_depunc) { - //NOTE: Having run a full debug on all steps, I am convinced that the number of punctures - //renders the current convolutional decoder useless to fix the holes in an LSF frame - - //Skipping to the deconvolution step renders the correct frame info and crc value - //We can still send the full LSF as intended over IP frame or RF without this step - - //TODO: Switch to M17 Viterbi Decoder for better performance + //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 - // uint8_t m17_depunc[488]; //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]; - // } - - //P1 Depuncture - // x = 0; - // for (i = 0; i < 488; i++) - // { - // if (p1[i%61] == 1) - // m17_depunc[i] = m17_bits[x++]; - // else m17_depunc[i] = 0; - // } //setup the convolutional decoder uint8_t temp[488]; @@ -925,31 +898,26 @@ void processM17LSF_debug(dsd_opts * opts, dsd_state * state, uint8_t * m17_depun if (crc_err == 1) fprintf (stderr, " CRC ERR"); - //ending linebreak - // fprintf (stderr, "\n"); - } //end processM17LSF_debug -//This will be the stripped out version to switch over to the libM17 viterbi decoder void processM17LSF_debug2(dsd_opts * opts, dsd_state * state, uint8_t * m17_rnd_bits) { - - //NOTE: Having run a full debug on all steps, I am convinced that the number of punctures - //renders the current convolutional decoder useless to fix the holes in an LSF frame - - //Skipping to the deconvolution step renders the correct frame info and crc value - //We can still send the full LSF as intended over IP frame or RF without this step - - //TODO: Switch to M17 Viterbi Decoder for better performance - - int i, x; + //Working: Switched to libM17 Viterbi Decoder + 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[488]; //488 bits after depuncturing + 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); + memset (state->m17_lsf, 0, sizeof(state->m17_lsf)); memset (m17_int_bits, 0, sizeof(m17_int_bits)); memset (m17_bits, 0, sizeof(m17_bits)); memset (m17_depunc, 0, sizeof(m17_depunc)); + memset (lsf_packed, 0, sizeof(lsf_packed)); + memset (lsf_bytes, 0, sizeof(lsf_bytes)); //descramble the frame for (i = 0; i < 368; i++) @@ -963,64 +931,50 @@ void processM17LSF_debug2(dsd_opts * opts, dsd_state * state, uint8_t * m17_rnd_ m17_bits[i] = m17_int_bits[x]; } - //P1 Depuncture + //P1 Depuncture & Add Weights x = 0; for (i = 0; i < 488; i++) { if (p1[i%61] == 1) m17_depunc[i] = m17_bits[x++]; else m17_depunc[i] = 0; + + if (m17_depunc[i]) + m17_depunc[i] = 0xFFFF; + else m17_depunc[i] = 0x7FFF; } - //setup the convolutional decoder - uint8_t temp[488]; - uint8_t s0; - uint8_t s1; - uint8_t m_data[30]; - uint8_t trellis_buf[240]; //30*8 = 240 - memset (trellis_buf, 0, sizeof(trellis_buf)); - memset (temp, 0, sizeof (temp)); - memset (m_data, 0, sizeof (m_data)); + //debug -- fill all of the byte array + // memset (m17_depunc, 0xFFFF, sizeof(m17_depunc)); - for (i = 0; i < 488; i++) - temp[i] = m17_depunc[i] << 1; + //debug + // fprintf (stderr, "\n depunc: \n"); + // for (i = 0; i < 488; i++) + // fprintf (stderr, " %04X", m17_depunc[i]); - CNXDNConvolution_start(); - for (i = 0; i < 244; 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++) { - s0 = temp[(2*i)]; - s1 = temp[(2*i)+1]; - - CNXDNConvolution_decode(s0, s1); + for (i = 0; i < 8; i++) + state->m17_lsf[k++] = (lsf_packed[j] >> 7-i) & 1; } - 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); + uint16_t crc_ext = (lsf_packed[28] << 8) + (lsf_packed[29] << 0); int crc_err = 0; if (crc_cmp != crc_ext) crc_err = 1; @@ -1036,6 +990,7 @@ void processM17LSF_debug2(dsd_opts * opts, dsd_state * state, uint8_t * m17_rnd_ if (i == 15) fprintf (stderr, "\n "); fprintf (stderr, "[%02X]", lsf_packed[i]); } + // fprintf (stderr, " V Err: %d", v_err); } //debug @@ -1824,8 +1779,7 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) fprintf (stderr, "\n M17 LSF (ENCODER): "); if (opts->monitor_input_audio == 0) - processM17LSF_debug(opts, state, m17_lsfc); - // processM17LSF_debug(opts, state, m17_lsfs); + processM17LSF_debug2(opts, state, m17_lsfs); else fprintf (stderr, " To Audio Out Device Type: %d; ", opts->audio_out_type); //encodeM17RF