1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-02-06 14:10:11 +00:00

Merge branch 'convolutional' into next

This commit is contained in:
Carles Fernandez 2019-09-07 11:16:51 +02:00
commit 35063985cd
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
5 changed files with 46 additions and 70 deletions

View File

@ -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(), Viterbi(page_part_bits, out0.data(), state0.data(), out1.data(), state1.data(),
page_part_symbols, KK, nn, DataLength); 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++) 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 // 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()); deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint.data());
// 2. Viterbi decoder // 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 // 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()); deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint.data());
// 2. Viterbi decoder // 2. Viterbi decoder

View File

@ -81,12 +81,12 @@ private:
galileo_telemetry_decoder_gs(const Gnss_Satellite &satellite, int frame_type, bool dump); 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_INAV_word(float *page_part_symbols, int32_t frame_length);
void decode_FNAV_word(double *page_symbols, int32_t frame_length); void decode_FNAV_word(float *page_symbols, int32_t frame_length);
int d_frame_type; int d_frame_type;
int32_t d_bits_per_preamble; int32_t d_bits_per_preamble;
@ -96,7 +96,7 @@ private:
uint32_t d_PRN_code_period_ms; uint32_t d_PRN_code_period_ms;
uint32_t d_required_symbols; uint32_t d_required_symbols;
uint32_t d_frame_length_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; boost::circular_buffer<float> d_symbol_history;

View File

@ -39,6 +39,8 @@ add_library(telemetry_decoder_libs
) )
target_link_libraries(telemetry_decoder_libs target_link_libraries(telemetry_decoder_libs
PUBLIC
Volkgnsssdr::volkgnsssdr
PRIVATE PRIVATE
Gflags::gflags Gflags::gflags
Glog::glog Glog::glog

View File

@ -1,11 +1,13 @@
/*! /*!
* \file convolutional.h * \file convolutional.h
* \brief General functions used to implement convolutional encoding. * \brief General functions used to implement convolutional encoding.
* \author Matthew C. Valenti * \author Matthew C. Valenti, 2006-2008.
* \author C. Fernandez-Prades, 2019.
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
* Copyright (C) 2006-2008 Matthew C. Valenti * Copyright (C) 2006-2008 Matthew C. Valenti
* Copyright (C) 2019 C. Fernandez-Prades
* *
* GNSS-SDR is a software defined Global Navigation * GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver * Satellite Systems receiver
@ -19,8 +21,6 @@
* *
* This file is a derived work of the original file, which had this note: * This file is a derived work of the original file, which had this note:
* *
* Last updated on May 22, 2008
*
* The functions in this file are part of the Iterative Solutions * The functions in this file are part of the Iterative Solutions
* Coded Modulation Library. The Iterative Solutions Coded Modulation * Coded Modulation Library. The Iterative Solutions Coded Modulation
* Library is free software; you can redistribute it and/or modify it * Library is free software; you can redistribute it and/or modify it
@ -41,7 +41,8 @@
#ifndef GNSS_SDR_CONVOLUTIONAL_H_ #ifndef GNSS_SDR_CONVOLUTIONAL_H_
#define GNSS_SDR_CONVOLUTIONAL_H_ #define GNSS_SDR_CONVOLUTIONAL_H_
#include <cstdlib> // for calloc #include <volk_gnsssdr/volk_gnsssdr.h>
#include <vector>
/* define constants used throughout the library */ /* define constants used throughout the library */
const float MAXLOG = 1e7; /* Define infinity */ const float MAXLOG = 1e7; /* Define infinity */
@ -57,7 +58,7 @@ const float MAXLOG = 1e7; /* Define infinity */
* *
* This function is used by nsc_enc_bit(), rsc_enc_bit(), and rsc_tail() * 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 counter;
int temp_parity = 0; int temp_parity = 0;
@ -85,7 +86,7 @@ inline static int parity_counter(int symbol, int length)
* *
* This function is used by nsc_transit() * 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 input,
int state_in, int state_in,
const int g[], const int g[],
@ -115,7 +116,7 @@ inline static int nsc_enc_bit(int state_out_p[],
/*! /*!
* \brief Function that creates the transit and output vectors * \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 trans_p[],
int input, int input,
int g[], int g[],
@ -144,7 +145,7 @@ inline static void nsc_transit(int output_p[],
* \param[in] nn The length of the received vector * \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 symbol,
int nn) int nn)
{ {
@ -176,24 +177,20 @@ inline static float Gamma(const float rec_array[],
* \param[out] output_u_int[] Hard decisions on the data bits * \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 out0[],
const int state0[], const int state0[],
const int out1[], const int out1[],
const int state1[], const int state1[],
const double input_c[], const float input_c[],
int KK, int KK,
int nn, int nn,
int LL) int LL)
{ {
int i, t, state, mm, states; int i, t, state, mm, states;
int number_symbols; int number_symbols;
uint32_t max_index;
float metric; 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; float max_val;
/* some derived constants */ /* some derived constants */
@ -201,34 +198,24 @@ inline static void Viterbi(int output_u_int[],
states = 1 << mm; /* 2^mm */ states = 1 << mm; /* 2^mm */
number_symbols = 1 << nn; /* 2^nn */ number_symbols = 1 << nn; /* 2^nn */
/* dynamically allocate memory */ std::vector<float> prev_section(states, -MAXLOG);
prev_section = static_cast<float *>(calloc(states, sizeof(float))); std::vector<float> next_section(states, -MAXLOG);
next_section = static_cast<float *>(calloc(states, sizeof(float))); std::vector<int> prev_bit(states * (LL + mm), 0);
prev_bit = static_cast<int *>(calloc(states * (LL + mm), sizeof(int))); std::vector<int> prev_state(states * (LL + mm), 0);
prev_state = static_cast<int *>(calloc(states * (LL + mm), sizeof(int))); std::vector<float> rec_array(nn);
rec_array = static_cast<float *>(calloc(nn, sizeof(float))); std::vector<float> metric_c(number_symbols);
metric_c = static_cast<float *>(calloc(number_symbols, sizeof(float)));
/* initialize trellis */ prev_section[0] = 0.0; /* start in all-zeros state */
for (state = 0; state < states; state++)
{
prev_section[state] = -MAXLOG;
next_section[state] = -MAXLOG;
}
prev_section[0] = 0; /* start in all-zeros state */
/* go through trellis */ /* go through trellis */
for (t = 0; t < LL + mm; t++) for (t = 0; t < LL + mm; t++)
{ {
for (i = 0; i < nn; i++) rec_array.assign(input_c + nn * t, input_c + nn * t + (nn - 1));
{
rec_array[i] = static_cast<float>(input_c[nn * t + i]);
}
/* precompute all possible branch metrics */ /* precompute all possible branch metrics */
for (i = 0; i < number_symbols; i++) 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 */ /* step through all states */
@ -258,14 +245,9 @@ inline static void Viterbi(int output_u_int[],
} }
/* normalize */ /* normalize */
max_val = 0; volk_gnsssdr_32f_index_max_32u(&max_index, next_section.data(), states);
for (state = 0; state < states; state++) max_val = next_section[max_index];
{
if (next_section[state] > max_val)
{
max_val = next_section[state];
}
}
for (state = 0; state < states; state++) for (state = 0; state < states; state++)
{ {
prev_section[state] = next_section[state] - max_val; prev_section[state] = next_section[state] - max_val;
@ -287,14 +269,6 @@ inline static void Viterbi(int output_u_int[],
output_u_int[t] = prev_bit[t * states + state]; output_u_int[t] = prev_bit[t * states + state];
state = prev_state[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);
} }

View File

@ -54,14 +54,14 @@ public:
const int32_t KK = 7; // Constraint Length const int32_t KK = 7; // Constraint Length
int32_t mm = KK - 1; int32_t mm = KK - 1;
int32_t flag_even_word_arrived; 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, Viterbi(page_part_bits, out0, state0, out1, state1,
page_part_symbols, KK, nn, _datalength); 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++) 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 // 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); deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint);
// 2. Viterbi decoder // 2. Viterbi decoder
@ -134,10 +134,10 @@ public:
return crc_ok; 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 // 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); deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint);
// 2. Viterbi decoder // 2. Viterbi decoder
@ -215,7 +215,7 @@ TEST_F(Galileo_FNAV_INAV_test, ValidationOfResults)
start = std::chrono::system_clock::now(); start = std::chrono::system_clock::now();
int repetitions = 10; int repetitions = 10;
// FNAV FULLY ENCODED FRAME // 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, -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 // 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, -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,
-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, 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,