mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-01-28 09:54:51 +00:00
Modernize code for Viterbi decoder
This commit is contained in:
parent
4fe8c078ea
commit
589788d2e3
@ -207,14 +207,14 @@ galileo_telemetry_decoder_gs::~galileo_telemetry_decoder_gs()
|
||||
}
|
||||
|
||||
|
||||
void galileo_telemetry_decoder_gs::viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits)
|
||||
void galileo_telemetry_decoder_gs::viterbi_decoder(float *page_part_symbols, int32_t *page_part_bits)
|
||||
{
|
||||
Viterbi(page_part_bits, out0.data(), state0.data(), out1.data(), state1.data(),
|
||||
page_part_symbols, KK, nn, DataLength);
|
||||
}
|
||||
|
||||
|
||||
void galileo_telemetry_decoder_gs::deinterleaver(int32_t rows, int32_t cols, const double *in, double *out)
|
||||
void galileo_telemetry_decoder_gs::deinterleaver(int32_t rows, int32_t cols, const float *in, float *out)
|
||||
{
|
||||
for (int32_t r = 0; r < rows; r++)
|
||||
{
|
||||
@ -226,10 +226,10 @@ void galileo_telemetry_decoder_gs::deinterleaver(int32_t rows, int32_t cols, con
|
||||
}
|
||||
|
||||
|
||||
void galileo_telemetry_decoder_gs::decode_INAV_word(double *page_part_symbols, int32_t frame_length)
|
||||
void galileo_telemetry_decoder_gs::decode_INAV_word(float *page_part_symbols, int32_t frame_length)
|
||||
{
|
||||
// 1. De-interleave
|
||||
std::vector<double> page_part_symbols_deint(frame_length);
|
||||
std::vector<float> page_part_symbols_deint(frame_length);
|
||||
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint.data());
|
||||
|
||||
// 2. Viterbi decoder
|
||||
@ -318,10 +318,10 @@ void galileo_telemetry_decoder_gs::decode_INAV_word(double *page_part_symbols, i
|
||||
}
|
||||
|
||||
|
||||
void galileo_telemetry_decoder_gs::decode_FNAV_word(double *page_symbols, int32_t frame_length)
|
||||
void galileo_telemetry_decoder_gs::decode_FNAV_word(float *page_symbols, int32_t frame_length)
|
||||
{
|
||||
// 1. De-interleave
|
||||
std::vector<double> page_symbols_deint(frame_length);
|
||||
std::vector<float> page_symbols_deint(frame_length);
|
||||
deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint.data());
|
||||
|
||||
// 2. Viterbi decoder
|
||||
|
@ -81,12 +81,12 @@ private:
|
||||
|
||||
galileo_telemetry_decoder_gs(const Gnss_Satellite &satellite, int frame_type, bool dump);
|
||||
|
||||
void viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits);
|
||||
void viterbi_decoder(float *page_part_symbols, int32_t *page_part_bits);
|
||||
|
||||
void deinterleaver(int32_t rows, int32_t cols, const double *in, double *out);
|
||||
void deinterleaver(int32_t rows, int32_t cols, const float *in, float *out);
|
||||
|
||||
void decode_INAV_word(double *page_part_symbols, int32_t frame_length);
|
||||
void decode_FNAV_word(double *page_symbols, int32_t frame_length);
|
||||
void decode_INAV_word(float *page_part_symbols, int32_t frame_length);
|
||||
void decode_FNAV_word(float *page_symbols, int32_t frame_length);
|
||||
|
||||
int d_frame_type;
|
||||
int32_t d_bits_per_preamble;
|
||||
@ -96,7 +96,7 @@ private:
|
||||
uint32_t d_PRN_code_period_ms;
|
||||
uint32_t d_required_symbols;
|
||||
uint32_t d_frame_length_symbols;
|
||||
std::vector<double> d_page_part_symbols;
|
||||
std::vector<float> d_page_part_symbols;
|
||||
|
||||
boost::circular_buffer<float> d_symbol_history;
|
||||
|
||||
|
@ -39,6 +39,8 @@ add_library(telemetry_decoder_libs
|
||||
)
|
||||
|
||||
target_link_libraries(telemetry_decoder_libs
|
||||
PUBLIC
|
||||
Volkgnsssdr::volkgnsssdr
|
||||
PRIVATE
|
||||
Gflags::gflags
|
||||
Glog::glog
|
||||
|
@ -41,7 +41,9 @@
|
||||
#ifndef GNSS_SDR_CONVOLUTIONAL_H_
|
||||
#define GNSS_SDR_CONVOLUTIONAL_H_
|
||||
|
||||
#include <cstdlib> // for calloc
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
/* define constants used throughout the library */
|
||||
const float MAXLOG = 1e7; /* Define infinity */
|
||||
@ -57,7 +59,7 @@ const float MAXLOG = 1e7; /* Define infinity */
|
||||
*
|
||||
* This function is used by nsc_enc_bit(), rsc_enc_bit(), and rsc_tail()
|
||||
*/
|
||||
inline static int parity_counter(int symbol, int length)
|
||||
inline int parity_counter(int symbol, int length)
|
||||
{
|
||||
int counter;
|
||||
int temp_parity = 0;
|
||||
@ -85,7 +87,7 @@ inline static int parity_counter(int symbol, int length)
|
||||
*
|
||||
* This function is used by nsc_transit()
|
||||
*/
|
||||
inline static int nsc_enc_bit(int state_out_p[],
|
||||
inline int nsc_enc_bit(int state_out_p[],
|
||||
int input,
|
||||
int state_in,
|
||||
const int g[],
|
||||
@ -115,7 +117,7 @@ inline static int nsc_enc_bit(int state_out_p[],
|
||||
/*!
|
||||
* \brief Function that creates the transit and output vectors
|
||||
*/
|
||||
inline static void nsc_transit(int output_p[],
|
||||
inline void nsc_transit(int output_p[],
|
||||
int trans_p[],
|
||||
int input,
|
||||
int g[],
|
||||
@ -144,7 +146,7 @@ inline static void nsc_transit(int output_p[],
|
||||
* \param[in] nn The length of the received vector
|
||||
*
|
||||
*/
|
||||
inline static float Gamma(const float rec_array[],
|
||||
inline float Gamma(const float rec_array[],
|
||||
int symbol,
|
||||
int nn)
|
||||
{
|
||||
@ -176,24 +178,20 @@ inline static float Gamma(const float rec_array[],
|
||||
* \param[out] output_u_int[] Hard decisions on the data bits
|
||||
*
|
||||
*/
|
||||
inline static void Viterbi(int output_u_int[],
|
||||
inline void Viterbi(int output_u_int[],
|
||||
const int out0[],
|
||||
const int state0[],
|
||||
const int out1[],
|
||||
const int state1[],
|
||||
const double input_c[],
|
||||
const float input_c[],
|
||||
int KK,
|
||||
int nn,
|
||||
int LL)
|
||||
{
|
||||
int i, t, state, mm, states;
|
||||
int number_symbols;
|
||||
uint32_t max_index;
|
||||
float metric;
|
||||
float *prev_section, *next_section;
|
||||
int *prev_bit;
|
||||
int *prev_state;
|
||||
float *metric_c; /* Set of all possible branch metrics */
|
||||
float *rec_array; /* Received values for one trellis section */
|
||||
float max_val;
|
||||
|
||||
/* some derived constants */
|
||||
@ -201,34 +199,24 @@ inline static void Viterbi(int output_u_int[],
|
||||
states = 1 << mm; /* 2^mm */
|
||||
number_symbols = 1 << nn; /* 2^nn */
|
||||
|
||||
/* dynamically allocate memory */
|
||||
prev_section = static_cast<float *>(calloc(states, sizeof(float)));
|
||||
next_section = static_cast<float *>(calloc(states, sizeof(float)));
|
||||
prev_bit = static_cast<int *>(calloc(states * (LL + mm), sizeof(int)));
|
||||
prev_state = static_cast<int *>(calloc(states * (LL + mm), sizeof(int)));
|
||||
rec_array = static_cast<float *>(calloc(nn, sizeof(float)));
|
||||
metric_c = static_cast<float *>(calloc(number_symbols, sizeof(float)));
|
||||
std::vector<float> prev_section(states, -MAXLOG);
|
||||
std::vector<float> next_section(states, -MAXLOG);
|
||||
std::vector<int> prev_bit(states * (LL + mm), 0);
|
||||
std::vector<int> prev_state(states * (LL + mm), 0);
|
||||
std::vector<float> rec_array(nn);
|
||||
std::vector<float> metric_c(number_symbols);
|
||||
|
||||
/* initialize trellis */
|
||||
for (state = 0; state < states; state++)
|
||||
{
|
||||
prev_section[state] = -MAXLOG;
|
||||
next_section[state] = -MAXLOG;
|
||||
}
|
||||
prev_section[0] = 0; /* start in all-zeros state */
|
||||
prev_section[0] = 0.0; /* start in all-zeros state */
|
||||
|
||||
/* go through trellis */
|
||||
for (t = 0; t < LL + mm; t++)
|
||||
{
|
||||
for (i = 0; i < nn; i++)
|
||||
{
|
||||
rec_array[i] = static_cast<float>(input_c[nn * t + i]);
|
||||
}
|
||||
rec_array.assign(input_c + nn * t, input_c + nn * t + (nn - 1));
|
||||
|
||||
/* precompute all possible branch metrics */
|
||||
for (i = 0; i < number_symbols; i++)
|
||||
{
|
||||
metric_c[i] = Gamma(rec_array, i, nn);
|
||||
metric_c[i] = Gamma(rec_array.data(), i, nn);
|
||||
}
|
||||
|
||||
/* step through all states */
|
||||
@ -258,19 +246,13 @@ inline static void Viterbi(int output_u_int[],
|
||||
}
|
||||
|
||||
/* normalize */
|
||||
max_val = 0;
|
||||
for (state = 0; state < states; state++)
|
||||
{
|
||||
if (next_section[state] > max_val)
|
||||
{
|
||||
max_val = next_section[state];
|
||||
}
|
||||
}
|
||||
for (state = 0; state < states; state++)
|
||||
{
|
||||
prev_section[state] = next_section[state] - max_val;
|
||||
next_section[state] = -MAXLOG;
|
||||
}
|
||||
volk_gnsssdr_32f_index_max_32u(&max_index, next_section.data(), states);
|
||||
max_val = next_section[max_index];
|
||||
prev_section = next_section;
|
||||
std::transform(prev_section.begin(), prev_section.end(), prev_section.begin(),
|
||||
[&max_val](const auto& prev_ele) { return (prev_ele - max_val); });
|
||||
|
||||
std::fill(next_section.begin(), next_section.end(), -MAXLOG);
|
||||
}
|
||||
|
||||
/* trace-back operation */
|
||||
@ -287,14 +269,6 @@ inline static void Viterbi(int output_u_int[],
|
||||
output_u_int[t] = prev_bit[t * states + state];
|
||||
state = prev_state[t * states + state];
|
||||
}
|
||||
|
||||
/* free the dynamically allocated memory */
|
||||
free(prev_section);
|
||||
free(next_section);
|
||||
free(prev_bit);
|
||||
free(prev_state);
|
||||
free(rec_array);
|
||||
free(metric_c);
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,14 +54,14 @@ public:
|
||||
const int32_t KK = 7; // Constraint Length
|
||||
int32_t mm = KK - 1;
|
||||
int32_t flag_even_word_arrived;
|
||||
void viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits, int32_t _datalength)
|
||||
void viterbi_decoder(float *page_part_symbols, int32_t *page_part_bits, int32_t _datalength)
|
||||
{
|
||||
Viterbi(page_part_bits, out0, state0, out1, state1,
|
||||
page_part_symbols, KK, nn, _datalength);
|
||||
}
|
||||
|
||||
|
||||
void deinterleaver(int32_t rows, int32_t cols, const double *in, double *out)
|
||||
void deinterleaver(int32_t rows, int32_t cols, const float *in, float *out)
|
||||
{
|
||||
for (int32_t r = 0; r < rows; r++)
|
||||
{
|
||||
@ -73,10 +73,10 @@ public:
|
||||
}
|
||||
|
||||
|
||||
bool decode_INAV_word(double *page_part_symbols, int32_t frame_length)
|
||||
bool decode_INAV_word(float *page_part_symbols, int32_t frame_length)
|
||||
{
|
||||
// 1. De-interleave
|
||||
auto *page_part_symbols_deint = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
|
||||
auto *page_part_symbols_deint = static_cast<float *>(volk_gnsssdr_malloc(frame_length * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint);
|
||||
|
||||
// 2. Viterbi decoder
|
||||
@ -134,10 +134,10 @@ public:
|
||||
return crc_ok;
|
||||
}
|
||||
|
||||
bool decode_FNAV_word(double *page_symbols, int32_t frame_length)
|
||||
bool decode_FNAV_word(float *page_symbols, int32_t frame_length)
|
||||
{
|
||||
// 1. De-interleave
|
||||
auto *page_symbols_deint = static_cast<double *>(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment()));
|
||||
auto *page_symbols_deint = static_cast<float *>(volk_gnsssdr_malloc(frame_length * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint);
|
||||
|
||||
// 2. Viterbi decoder
|
||||
@ -215,7 +215,7 @@ TEST_F(Galileo_FNAV_INAV_test, ValidationOfResults)
|
||||
start = std::chrono::system_clock::now();
|
||||
int repetitions = 10;
|
||||
// FNAV FULLY ENCODED FRAME
|
||||
double FNAV_frame[488] = {-1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
float FNAV_frame[488] = {-1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
|
||||
-1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1,
|
||||
-1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1,
|
||||
@ -240,7 +240,7 @@ TEST_F(Galileo_FNAV_INAV_test, ValidationOfResults)
|
||||
|
||||
|
||||
// INAV FULLY ENCODED FRAME
|
||||
double INAV_frame_even[240] = {-1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
float INAV_frame_even[240] = {-1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1,
|
||||
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1,
|
||||
@ -256,7 +256,7 @@ TEST_F(Galileo_FNAV_INAV_test, ValidationOfResults)
|
||||
-1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1};
|
||||
|
||||
double INAV_frame_odd[240] = {1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
float INAV_frame_odd[240] = {1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1,
|
||||
1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
|
||||
-1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1,
|
||||
|
Loading…
Reference in New Issue
Block a user