From 050543b42765564ab6f4988e3a7699fb263220f4 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 24 Aug 2018 12:34:36 +0200 Subject: [PATCH 1/2] Start at 30 dBHz by default --- .../acquisition/acq_performance_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc index 3099d950e..f61727542 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc @@ -64,7 +64,7 @@ DEFINE_int32(acq_test_second_doppler_step, 10, "If --acq_test_make_two_steps is DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration, in s"); DEFINE_int32(acq_test_num_meas, 0, "Number of measurements per run. 0 means the complete file."); -DEFINE_double(acq_test_cn0_init, 33.0, "Initial CN0, in dBHz."); +DEFINE_double(acq_test_cn0_init, 30.0, "Initial CN0, in dBHz."); DEFINE_double(acq_test_cn0_final, 45.0, "Final CN0, in dBHz."); DEFINE_double(acq_test_cn0_step, 3.0, "CN0 step, in dB."); From a7d28c20c1a498189e24208880f1ee43de7fa54c Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Sun, 26 Aug 2018 20:06:30 +0200 Subject: [PATCH 2/2] Adding Galileo INAV and FNAV page decoder unit test --- src/tests/test_main.cc | 1 + .../galileo_fnav_inav_decoder_test.cc | 288 ++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/galileo_fnav_inav_decoder_test.cc diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index c89349d15..64920b9a1 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -158,6 +158,7 @@ DECLARE_string(log_dir); #include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc" #endif +#include "unit-tests/signal-processing-blocks/telemetry_decoder/galileo_fnav_inav_decoder_test.cc" #include "unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc" #include "unit-tests/system-parameters/glonass_gnav_nav_message_test.cc" diff --git a/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/galileo_fnav_inav_decoder_test.cc b/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/galileo_fnav_inav_decoder_test.cc new file mode 100644 index 000000000..070a76e42 --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/telemetry_decoder/galileo_fnav_inav_decoder_test.cc @@ -0,0 +1,288 @@ +/*! + * \file galileo_fnav_inav_decoder_test.cc + * \brief This class implements the unit test for the Galileo FNAV and INAV frames + * according to the Galileo ICD + * \author Javier Arribas, 2018. jarribas(at)cttc.es + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2012-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "galileo_navigation_message.h" +#include "galileo_fnav_message.h" +#include "convolutional.h" +#include +#include +#include +#include +#include +#include +#include + + +class Galileo_FNAV_INAV_test : public ::testing::Test +{ +public: + Galileo_Navigation_Message INAV_decoder; + Galileo_Fnav_Message FNAV_decoder; + // vars for Viterbi decoder + int32_t *out0, *out1, *state0, *state1; + int32_t g_encoder[2]; + const int32_t nn = 2; // Coding rate 1/n + 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) + { + Viterbi(page_part_bits, out0, state0, out1, state1, + page_part_symbols, KK, nn, _datalength); + } + + + void deinterleaver(int32_t rows, int32_t cols, double *in, double *out) + { + for (int32_t r = 0; r < rows; r++) + { + for (int32_t c = 0; c < cols; c++) + { + out[c * rows + r] = in[r * cols + c]; + } + } + } + + + bool decode_INAV_word(double *page_part_symbols, int32_t frame_length) + { + // 1. De-interleave + double *page_part_symbols_deint = static_cast(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment())); + deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint); + + // 2. Viterbi decoder + // 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder) + // 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180ยบ + for (int32_t i = 0; i < frame_length; i++) + { + if ((i + 1) % 2 == 0) + { + page_part_symbols_deint[i] = -page_part_symbols_deint[i]; + } + } + + int32_t *page_part_bits = static_cast(volk_gnsssdr_malloc((frame_length / 2) * sizeof(int32_t), volk_gnsssdr_get_alignment())); + + const int32_t CodeLength = 240; + int32_t DataLength = (CodeLength / nn) - mm; + viterbi_decoder(page_part_symbols_deint, page_part_bits, DataLength); + volk_gnsssdr_free(page_part_symbols_deint); + + // 3. Call the Galileo page decoder + std::string page_String; + for (int32_t i = 0; i < (frame_length / 2); i++) + { + if (page_part_bits[i] > 0) + { + page_String.push_back('1'); + } + else + { + page_String.push_back('0'); + } + } + + bool crc_ok = false; + if (page_part_bits[0] == 1) + { + // DECODE COMPLETE WORD (even + odd) and TEST CRC + INAV_decoder.split_page(page_String, flag_even_word_arrived); + if (INAV_decoder.flag_CRC_test == true) + { + std::cout << "Galileo E1 INAV PAGE CRC correct \n"; + //std::cout << "Galileo E1 CRC correct on channel " << d_channel << " from satellite " << d_satellite << std::endl; + crc_ok = true; + } + flag_even_word_arrived = 0; + } + else + { + // STORE HALF WORD (even page) + INAV_decoder.split_page(page_String.c_str(), flag_even_word_arrived); + flag_even_word_arrived = 1; + } + volk_gnsssdr_free(page_part_bits); + return crc_ok; + } + + bool decode_FNAV_word(double *page_symbols, int32_t frame_length) + { + // 1. De-interleave + double *page_symbols_deint = static_cast(volk_gnsssdr_malloc(frame_length * sizeof(double), volk_gnsssdr_get_alignment())); + deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint); + + // 2. Viterbi decoder + // 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder) + // 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180 + for (int32_t i = 0; i < frame_length; i++) + { + if ((i + 1) % 2 == 0) + { + page_symbols_deint[i] = -page_symbols_deint[i]; + } + } + int32_t *page_bits = static_cast(volk_gnsssdr_malloc((frame_length / 2) * sizeof(int32_t), volk_gnsssdr_get_alignment())); + + const int32_t CodeLength = 488; + int32_t DataLength = (CodeLength / nn) - mm; + viterbi_decoder(page_symbols_deint, page_bits, DataLength); + + volk_gnsssdr_free(page_symbols_deint); + + // 3. Call the Galileo page decoder + std::string page_String; + for (int32_t i = 0; i < frame_length; i++) + { + if (page_bits[i] > 0) + { + page_String.push_back('1'); + } + else + { + page_String.push_back('0'); + } + } + volk_gnsssdr_free(page_bits); + + // DECODE COMPLETE WORD (even + odd) and TEST CRC + FNAV_decoder.split_page(page_String); + if (FNAV_decoder.flag_CRC_test == true) + { + std::cout << "Galileo E5a FNAV PAGE CRC correct \n"; + return true; + } + else + { + return false; + } + } + + Galileo_FNAV_INAV_test() + { + // vars for Viterbi decoder + int32_t max_states = 1 << mm; // 2^mm + g_encoder[0] = 121; // Polynomial G1 + g_encoder[1] = 91; // Polynomial G2 + out0 = static_cast(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment())); + out1 = static_cast(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment())); + state0 = static_cast(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment())); + state1 = static_cast(volk_gnsssdr_malloc(max_states * sizeof(int32_t), volk_gnsssdr_get_alignment())); + // create appropriate transition matrices + nsc_transit(out0, state0, 0, g_encoder, KK, nn); + nsc_transit(out1, state1, 1, g_encoder, KK, nn); + flag_even_word_arrived = 0; + } + + ~Galileo_FNAV_INAV_test() + { + volk_gnsssdr_free(out0); + volk_gnsssdr_free(out1); + volk_gnsssdr_free(state0); + volk_gnsssdr_free(state1); + } +}; + +TEST_F(Galileo_FNAV_INAV_test, ValidationOfResults) +{ + std::chrono::time_point start, end; + std::chrono::duration elapsed_seconds(0); + + 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, + 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, + -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, + -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, + -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, + -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, + -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, + -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, + 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, + -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, + 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, + -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, + 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, + 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1}; + + ASSERT_NO_THROW({ + for (int n = 0; n < repetitions; n++) + { + EXPECT_EQ(decode_FNAV_word(&FNAV_frame[0], 488), true); + } + }) << "Exception during FNAV frame decoding"; + + + // 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, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, + -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, + 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, + -1, -1, 1, 1, 1, 1, -1, -1, -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, + 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, + 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, + -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, + 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, + -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, + 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, + -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, + -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1}; + + ASSERT_NO_THROW({ + for (int n = 0; n < repetitions; n++) + { + decode_INAV_word(&INAV_frame_even[0], 240); + EXPECT_EQ(decode_INAV_word(&INAV_frame_odd[0], 240), true); + } + }) << "Exception during INAV frame decoding"; + + + std::cout << "Galileo FNAV/INAV Test completed in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; +}