1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-14 04:00:34 +00:00

Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into pps_lime

This commit is contained in:
Javier Arribas 2021-04-19 15:23:10 +02:00
commit 261a9ae264
12 changed files with 540 additions and 24 deletions

View File

@ -13,10 +13,16 @@ SPDX-FileCopyrightText: 2011-2021 Carles Fernandez-Prades <carles.fernandez@cttc
### Improvements in Availability:
- Added the reading of reduced clock and ephemeris data (CED) in the Galileo E1B
INAV message introduced in Galileo ICD v2.0. If the reduced CED is available
before the full ephemeris set, it is used for PVT computation until the full
set has not yet been received. This can contribute to shorten the
INAV message introduced in Galileo OS SIS ICD Issue 2.0. If the reduced CED is
available before the full ephemeris set, it is used for PVT computation until
the full set has not yet been received. This can contribute to shorten the
Time-To-First-Fix.
- Added the exploitation of the FEC2 Erasure Correction in the Galileo E1B INAV
message introduced in Galileo OS SIS ICD Issue 2.0. This can contribute to
shorten the Time-To-First-Fix. Since the added computational cost could break
some real-time configurations, this feature is disabled by default. It can be
activated from the configuration file by adding
`TelemetryDecoder_1B.enable_reed_solomon=true`.
### Improvements in Maintainability:

View File

@ -72,6 +72,9 @@ static inline void volk_gnsssdr_32fc_32f_high_dynamic_rotator_dot_prod_32fc_xn_g
lv_32fc_t phase_doppler = (*phase);
int n_vec;
unsigned int n;
#if _WIN32
const float arga = cargf(phase_inc_rate);
#endif
for (n_vec = 0; n_vec < num_a_vectors; n_vec++)
{
result[n_vec] = lv_cmake(0.0f, 0.0f);
@ -89,8 +92,13 @@ static inline void volk_gnsssdr_32fc_32f_high_dynamic_rotator_dot_prod_32fc_xn_g
}
tmp32_1 = *in_common++ * (*phase);
phase_doppler *= phase_inc;
#if _WIN32
const float theta = (float)(n * n) * arga;
phase_doppler_rate = lv_cmake(cosf(theta), sinf(theta));
#else
phase_doppler_rate = cpowf(phase_inc_rate, lv_cmake((float)(n * n), 0.0f));
phase_doppler_rate /= hypotf(lv_creal(phase_doppler_rate), lv_cimag(phase_doppler_rate));
#endif
(*phase) = phase_doppler * phase_doppler_rate;
for (n_vec = 0; n_vec < num_a_vectors; n_vec++)

View File

@ -32,6 +32,7 @@ GalileoE1BTelemetryDecoder::GalileoE1BTelemetryDecoder(
{
DLOG(INFO) << "role " << role;
tlm_parameters_.SetFromConfiguration(configuration, role);
tlm_parameters_.enable_reed_solomon = configuration->property(role + ".enable_reed_solomon", false);
// make telemetry decoder object
telemetry_decoder_ = galileo_make_telemetry_decoder_gs(satellite_, tlm_parameters_, 1); // unified galileo decoder set to INAV (frame_type=1)
DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")";

View File

@ -94,7 +94,10 @@ galileo_telemetry_decoder_gs::galileo_telemetry_decoder_gs(
d_codelength = static_cast<int32_t>(d_frame_length_symbols);
d_datalength = (d_codelength / d_nn) - d_mm;
d_max_symbols_without_valid_frame = GALILEO_INAV_PAGE_SYMBOLS * 30; // rise alarm 60 seconds without valid tlm
if (conf.enable_reed_solomon == true)
{
d_inav_nav.enable_reed_solomon();
}
break;
}
case 2: // FNAV
@ -599,10 +602,6 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
// 1. Copy the current tracking output
current_symbol = in[0][0];
d_band = current_symbol.Signal[0];
if (d_band == '1')
{
d_inav_nav.enable_reed_solomon();
}
// add new symbol to the symbol queue
switch (d_frame_type)

View File

@ -22,6 +22,7 @@ Tlm_Conf::Tlm_Conf()
dump = false;
dump_mat = false;
remove_dat = false;
enable_reed_solomon = false;
}

View File

@ -38,6 +38,7 @@ public:
bool dump;
bool dump_mat;
bool remove_dat;
bool enable_reed_solomon; // for INAV message in Galileo E1B
};

View File

@ -116,6 +116,12 @@ target_link_libraries(core_system_parameters
Glog::glog
)
# for gnss_sdr_make_unique.h
target_include_directories(core_system_parameters
PUBLIC
${CMAKE_SOURCE_DIR}/src/algorithms/libs
)
if(ENABLE_CLANG_TIDY)
if(CLANG_TIDY_EXE)
set_target_properties(core_system_parameters

View File

@ -1,7 +1,7 @@
/*!
* \file galileo_inav_message.cc
* \brief Implementation of a Galileo I/NAV Data message
* as described in Galileo OS SIS ICD Issue 1.1 (Sept. 2010)
* as described in Galileo OS SIS ICD Issue 2.0 (Jan. 2021)
* \author Mara Branzanti 2013. mara.branzanti(at)gmail.com
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
@ -10,7 +10,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@ -18,12 +18,14 @@
#include "galileo_inav_message.h"
#include "galileo_reduced_ced.h"
#include "reed_solomon.h"
#include <boost/crc.hpp> // for boost::crc_basic, boost::crc_optimal
#include <boost/dynamic_bitset.hpp> // for boost::dynamic_bitset
#include <glog/logging.h> // for DLOG
#include <algorithm> // for reverse
#include <iostream> // for operator<<
#include <limits> // for std::numeric_limits
#include <numeric> // for std::accumulate
using CRC_Galileo_INAV_type = boost::crc_optimal<24, 0x1864CFBU, 0x0, 0x0, false, false>;
@ -32,9 +34,16 @@ using CRC_Galileo_INAV_type = boost::crc_optimal<24, 0x1864CFBU, 0x0, 0x0, false
Galileo_Inav_Message::Galileo_Inav_Message()
{
rs_buffer = std::vector<uint8_t>(INAV_RS_BUFFER_LENGTH, 0);
// Instantiate ReedSolomon without encoding capabilities, saves some memory
rs = std::make_unique<ReedSolomon>(60, 29, 1, 195, 0, 137);
inav_rs_pages = std::vector<int>(8, 0);
}
// here the compiler knows how to destrcut rs
Galileo_Inav_Message::~Galileo_Inav_Message() = default;
bool Galileo_Inav_Message::CRC_test(const std::bitset<GALILEO_DATA_FRAME_BITS>& bits, uint32_t checksum) const
{
CRC_Galileo_INAV_type CRC_Galileo;
@ -243,6 +252,116 @@ bool Galileo_Inav_Message::have_new_ephemeris() // Check if we have a new ephem
return true;
}
}
if (enable_rs)
{
// Implement FEC2 Erasure Correction defined in Galileo ICD 2.0
if (std::accumulate(inav_rs_pages.begin(), inav_rs_pages.end(), 0) == 4)
{
// Four different INAV pages received with CRC ok
// so we can decode the buffer and retrieve data from missing pages
// Generate erasure vector
std::vector<int> erasure_positions;
erasure_positions.reserve(60); // max number of erasure positions
if (inav_rs_pages[0] == 0)
{
// we always know rs_buffer[0], so we start at 1
for (int i = 1; i < 16; i++)
{
erasure_positions.push_back(i);
}
}
if (inav_rs_pages[1] == 0)
{
for (int i = 16; i < 30; i++)
{
erasure_positions.push_back(i);
}
}
if (inav_rs_pages[2] == 0)
{
for (int i = 30; i < 44; i++)
{
erasure_positions.push_back(i);
}
}
if (inav_rs_pages[3] == 0)
{
for (int i = 44; i < 58; i++)
{
erasure_positions.push_back(i);
}
}
if (inav_rs_pages[4] == 0)
{
for (int i = 58; i < 73; i++)
{
erasure_positions.push_back(i + 137); // erasure position refers to the unshortened code, so we add 137
}
}
if (inav_rs_pages[5] == 0)
{
for (int i = 73; i < 88; i++)
{
erasure_positions.push_back(i + 137);
}
}
if (inav_rs_pages[6] == 0)
{
for (int i = 88; i < 103; i++)
{
erasure_positions.push_back(i + 137);
}
}
if (inav_rs_pages[7] == 0)
{
for (int i = 103; i < 118; i++)
{
erasure_positions.push_back(i + 137);
}
}
// Decode rs_buffer
int result = rs->decode(rs_buffer, erasure_positions);
// if decoding ok
if (result >= 0)
{
if (inav_rs_pages[0] == 0)
{
std::bitset<GALILEO_DATA_JK_BITS> missing_bits = regenerate_page_1(rs_buffer);
read_page_1(missing_bits);
}
if (inav_rs_pages[1] == 0)
{
std::bitset<GALILEO_DATA_JK_BITS> missing_bits = regenerate_page_2(rs_buffer);
read_page_2(missing_bits);
}
if (inav_rs_pages[2] == 0)
{
std::bitset<GALILEO_DATA_JK_BITS> missing_bits = regenerate_page_3(rs_buffer);
read_page_3(missing_bits);
}
if (inav_rs_pages[3] == 0)
{
std::bitset<GALILEO_DATA_JK_BITS> missing_bits = regenerate_page_4(rs_buffer);
read_page_4(missing_bits);
}
// Reset flags
inav_rs_pages = std::vector<int>(8, 0);
flag_ephemeris_1 = false; // clear the flag
flag_ephemeris_2 = false; // clear the flag
flag_ephemeris_3 = false; // clear the flag
flag_ephemeris_4 = false; // clear the flag
flag_all_ephemeris = true;
IOD_ephemeris = IOD_nav_1;
DLOG(INFO) << "Batch number: " << IOD_ephemeris;
return true;
}
}
}
return false;
}
@ -458,6 +577,8 @@ Galileo_Ephemeris Galileo_Inav_Message::get_reduced_ced() const
{
Galileo_Reduced_CED ced{};
ced.PRN = SV_ID_PRN_4;
// From ICD: TOTRedCED is the start time of transmission of the
// Reduced CED word 16 in GST
if (TOW_5 > TOW_6)
{
ced.TOTRedCED = WN_5 * 604800 + TOW_5 + 4; // According to ICD 2.0, Table 38
@ -595,6 +716,104 @@ void Galileo_Inav_Message::read_page_4(const std::bitset<GALILEO_DATA_JK_BITS>&
}
std::bitset<GALILEO_DATA_JK_BITS> Galileo_Inav_Message::regenerate_page_1(const std::vector<uint8_t>& decoded) const
{
std::bitset<GALILEO_DATA_JK_BITS> data_bits;
// Set page type to 1
data_bits.set(5);
std::bitset<8> c0(decoded[0]);
std::bitset<8> c1(decoded[1]);
for (int i = 0; i < 8; i++)
{
data_bits[6 + i] = c1[i];
}
data_bits[14] = c0[6];
data_bits[15] = c0[7];
for (int k = 2; k < 16; k++)
{
std::bitset<8> octet(decoded[k]);
for (int i = 0; i < 8; i++)
{
data_bits[i + k * 8] = octet[i];
}
}
return data_bits;
}
std::bitset<GALILEO_DATA_JK_BITS> Galileo_Inav_Message::regenerate_page_2(const std::vector<uint8_t>& decoded) const
{
std::bitset<GALILEO_DATA_JK_BITS> data_bits;
// Set page type to 2
data_bits.set(4);
std::bitset<10> iodnav(current_IODnav);
for (int i = 0; i < 10; i++)
{
data_bits[6 + i] = iodnav[i];
}
for (int k = 0; k < 14; k++)
{
std::bitset<8> octet(decoded[k + 16]);
for (int i = 0; i < 8; i++)
{
data_bits[16 + i + k * 8] = octet[i];
}
}
return data_bits;
}
std::bitset<GALILEO_DATA_JK_BITS> Galileo_Inav_Message::regenerate_page_3(const std::vector<uint8_t>& decoded) const
{
std::bitset<GALILEO_DATA_JK_BITS> data_bits;
// Set page type to 3
data_bits.set(4);
data_bits.set(5);
std::bitset<10> iodnav(current_IODnav);
for (int i = 0; i < 10; i++)
{
data_bits[6 + i] = iodnav[i];
}
for (int k = 0; k < 14; k++)
{
std::bitset<8> octet(decoded[k + 30]);
for (int i = 0; i < 8; i++)
{
data_bits[16 + i + k * 8] = octet[i];
}
}
return data_bits;
}
std::bitset<GALILEO_DATA_JK_BITS> Galileo_Inav_Message::regenerate_page_4(const std::vector<uint8_t>& decoded) const
{
std::bitset<GALILEO_DATA_JK_BITS> data_bits;
// Set page type to 4
data_bits.set(3);
std::bitset<10> iodnav(current_IODnav);
for (int i = 0; i < 10; i++)
{
data_bits[6 + i] = iodnav[i];
}
for (int k = 0; k < 14; k++)
{
std::bitset<8> octet(decoded[k + 44]);
for (int i = 0; i < 8; i++)
{
data_bits[16 + i + k * 8] = octet[i];
}
}
return data_bits;
}
int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
{
const std::string data_jk_string = data_jk;
@ -619,6 +838,8 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
// IODnav changed, reset buffer
current_IODnav = IOD_nav_1;
rs_buffer = std::vector<uint8_t>(INAV_RS_BUFFER_LENGTH, 0);
// Reed-Solomon data is invalid
inav_rs_pages = std::vector<int>(8, 0);
}
// Store RS information vector C_{RS,0}
@ -633,6 +854,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
rs_buffer[i] = read_octet_unsigned(data_jk_bits, info_octet_bits);
start_bit += BITS_IN_OCTET;
}
inav_rs_pages[0] = 1;
}
break;
@ -652,6 +874,8 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
// IODnav changed, reset buffer
current_IODnav = IOD_nav_2;
rs_buffer = std::vector<uint8_t>(INAV_RS_BUFFER_LENGTH, 0);
// Reed-Solomon data is invalid
inav_rs_pages = std::vector<int>(8, 0);
}
// Store RS information vector C_{RS,1}
@ -663,6 +887,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
rs_buffer[i] = read_octet_unsigned(data_jk_bits, info_octet_bits);
start_bit += BITS_IN_OCTET;
}
inav_rs_pages[1] = 1;
}
break;
}
@ -680,6 +905,8 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
// IODnav changed, reset buffer
current_IODnav = IOD_nav_3;
rs_buffer = std::vector<uint8_t>(INAV_RS_BUFFER_LENGTH, 0);
// Reed-Solomon data is invalid
inav_rs_pages = std::vector<int>(8, 0);
}
// Store RS information vector C_{RS,2}
@ -691,6 +918,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
rs_buffer[i] = read_octet_unsigned(data_jk_bits, info_octet_bits);
start_bit += BITS_IN_OCTET;
}
inav_rs_pages[2] = 1;
}
break;
}
@ -709,6 +937,8 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
// IODnav changed, reset buffer
current_IODnav = IOD_nav_4;
rs_buffer = std::vector<uint8_t>(INAV_RS_BUFFER_LENGTH, 0);
// Reed-Solomon data is invalid
inav_rs_pages = std::vector<int>(8, 0);
}
// Store RS information vector C_{RS,3}
@ -720,6 +950,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
rs_buffer[i] = read_octet_unsigned(data_jk_bits, info_octet_bits);
start_bit += BITS_IN_OCTET;
}
inav_rs_pages[3] = 1;
}
break;
}
@ -988,6 +1219,14 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
{
IODnav_LSB17 = read_octet_unsigned(data_jk_bits, RS_IODNAV_LSBS);
DLOG(INFO) << "IODnav 2 LSBs in Word type 17: " << static_cast<float>(IODnav_LSB17);
if (IODnav_LSB17 != static_cast<uint8_t>((current_IODnav % 4)))
{
// IODnav changed, information vector is invalid
inav_rs_pages[0] = 0;
inav_rs_pages[1] = 0;
inav_rs_pages[2] = 0;
inav_rs_pages[3] = 0;
}
// Store RS parity vector gamma_{RS,0}
std::vector<std::pair<int32_t, int32_t>> gamma_octet_bits({{FIRST_RS_BIT, BITS_IN_OCTET}});
rs_buffer[INAV_RS_INFO_VECTOR_LENGTH] = read_octet_unsigned(data_jk_bits, gamma_octet_bits);
@ -998,6 +1237,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
rs_buffer[INAV_RS_INFO_VECTOR_LENGTH + i] = read_octet_unsigned(data_jk_bits, gamma_octet_bits);
start_bit += BITS_IN_OCTET;
}
inav_rs_pages[4] = 1;
}
break;
}
@ -1008,6 +1248,14 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
{
IODnav_LSB18 = read_octet_unsigned(data_jk_bits, RS_IODNAV_LSBS);
DLOG(INFO) << "IODnav 2 LSBs in Word type 18: " << static_cast<float>(IODnav_LSB18);
if (IODnav_LSB18 != static_cast<uint8_t>((current_IODnav % 4)))
{
// IODnav changed, information vector is invalid
inav_rs_pages[0] = 0;
inav_rs_pages[1] = 0;
inav_rs_pages[2] = 0;
inav_rs_pages[3] = 0;
}
// Store RS parity vector gamma_{RS,1}
std::vector<std::pair<int32_t, int32_t>> gamma_octet_bits({{FIRST_RS_BIT, BITS_IN_OCTET}});
rs_buffer[INAV_RS_INFO_VECTOR_LENGTH + INAV_RS_SUBVECTOR_LENGTH] = read_octet_unsigned(data_jk_bits, gamma_octet_bits);
@ -1018,6 +1266,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
rs_buffer[INAV_RS_INFO_VECTOR_LENGTH + i] = read_octet_unsigned(data_jk_bits, gamma_octet_bits);
start_bit += BITS_IN_OCTET;
}
inav_rs_pages[5] = 1;
}
break;
}
@ -1028,6 +1277,14 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
{
IODnav_LSB19 = read_octet_unsigned(data_jk_bits, RS_IODNAV_LSBS);
DLOG(INFO) << "IODnav 2 LSBs in Word type 19: " << static_cast<float>(IODnav_LSB19);
if (IODnav_LSB19 != static_cast<uint8_t>((current_IODnav % 4)))
{
// IODnav changed, information vector is invalid
inav_rs_pages[0] = 0;
inav_rs_pages[1] = 0;
inav_rs_pages[2] = 0;
inav_rs_pages[3] = 0;
}
// Store RS parity vector gamma_{RS,2}
std::vector<std::pair<int32_t, int32_t>> gamma_octet_bits({{FIRST_RS_BIT, BITS_IN_OCTET}});
rs_buffer[INAV_RS_INFO_VECTOR_LENGTH + 2 * INAV_RS_SUBVECTOR_LENGTH] = read_octet_unsigned(data_jk_bits, gamma_octet_bits);
@ -1038,6 +1295,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
rs_buffer[INAV_RS_INFO_VECTOR_LENGTH + i] = read_octet_unsigned(data_jk_bits, gamma_octet_bits);
start_bit += BITS_IN_OCTET;
}
inav_rs_pages[6] = 1;
}
break;
}
@ -1048,6 +1306,14 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
{
IODnav_LSB20 = read_octet_unsigned(data_jk_bits, RS_IODNAV_LSBS);
DLOG(INFO) << "IODnav 2 LSBs in Word type 20: " << static_cast<float>(IODnav_LSB20);
if (IODnav_LSB20 != static_cast<uint8_t>((current_IODnav % 4)))
{
// IODnav changed, information vector is invalid
inav_rs_pages[0] = 0;
inav_rs_pages[1] = 0;
inav_rs_pages[2] = 0;
inav_rs_pages[3] = 0;
}
// Store RS parity vector gamma_{RS,4}
std::vector<std::pair<int32_t, int32_t>> gamma_octet_bits({{FIRST_RS_BIT, BITS_IN_OCTET}});
rs_buffer[INAV_RS_INFO_VECTOR_LENGTH + 3 * INAV_RS_SUBVECTOR_LENGTH] = read_octet_unsigned(data_jk_bits, gamma_octet_bits);
@ -1058,6 +1324,7 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
rs_buffer[INAV_RS_INFO_VECTOR_LENGTH + i] = read_octet_unsigned(data_jk_bits, gamma_octet_bits);
start_bit += BITS_IN_OCTET;
}
inav_rs_pages[7] = 1;
}
break;
}
@ -1065,11 +1332,14 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk)
case 0: // Word type 0: I/NAV Spare Word
Time_0 = static_cast<int32_t>(read_navigation_unsigned(data_jk_bits, TIME_0_BIT));
DLOG(INFO) << "Time_0= " << Time_0;
WN_0 = static_cast<int32_t>(read_navigation_unsigned(data_jk_bits, WN_0_BIT));
DLOG(INFO) << "WN_0= " << WN_0;
TOW_0 = static_cast<int32_t>(read_navigation_unsigned(data_jk_bits, TOW_0_BIT));
DLOG(INFO) << "TOW_0= " << TOW_0;
DLOG(INFO) << "flag_tow_set" << flag_TOW_set;
if (Time_0 == 2) // valid data
{
WN_0 = static_cast<int32_t>(read_navigation_unsigned(data_jk_bits, WN_0_BIT));
DLOG(INFO) << "WN_0= " << WN_0;
TOW_0 = static_cast<int32_t>(read_navigation_unsigned(data_jk_bits, TOW_0_BIT));
DLOG(INFO) << "TOW_0= " << TOW_0;
DLOG(INFO) << "flag_tow_set" << flag_TOW_set;
}
break;
default:

View File

@ -1,7 +1,7 @@
/*!
* \file galileo_inav_message.h
* \brief Implementation of a Galileo I/NAV Data message
* as described in Galileo OS SIS ICD Issue 1.2 (Nov. 2015)
* as described in Galileo OS SIS ICD Issue 2.0 (Jan. 2021)
* \author Mara Branzanti 2013. mara.branzanti(at)gmail.com
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
@ -10,7 +10,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@ -24,12 +24,16 @@
#include "galileo_ephemeris.h"
#include "galileo_iono.h"
#include "galileo_utc_model.h"
#include "gnss_sdr_make_unique.h" // for std::unique_ptr in C++11
#include <bitset>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
class ReedSolomon; // Forward declaration of the ReedSolomon class
/** \addtogroup Core
* \{ */
/** \addtogroup System_Parameters
@ -46,6 +50,8 @@ class Galileo_Inav_Message
public:
Galileo_Inav_Message();
~Galileo_Inav_Message();
/*
* \brief Takes in input a page (Odd or Even) of 120 bit, split it according ICD 4.3.2.3 and join Data_k with Data_j
*/
@ -210,6 +216,10 @@ private:
void read_page_2(const std::bitset<GALILEO_DATA_JK_BITS>& data_bits);
void read_page_3(const std::bitset<GALILEO_DATA_JK_BITS>& data_bits);
void read_page_4(const std::bitset<GALILEO_DATA_JK_BITS>& data_bits);
std::bitset<GALILEO_DATA_JK_BITS> regenerate_page_1(const std::vector<uint8_t>& decoded) const;
std::bitset<GALILEO_DATA_JK_BITS> regenerate_page_2(const std::vector<uint8_t>& decoded) const;
std::bitset<GALILEO_DATA_JK_BITS> regenerate_page_3(const std::vector<uint8_t>& decoded) const;
std::bitset<GALILEO_DATA_JK_BITS> regenerate_page_4(const std::vector<uint8_t>& decoded) const;
std::string page_Even{};
@ -366,7 +376,9 @@ private:
int32_t current_IODnav{};
std::vector<uint8_t> rs_buffer; // Reed-Solomon buffer
std::vector<uint8_t> rs_buffer; // Reed-Solomon buffer
std::unique_ptr<ReedSolomon> rs; // The Reed-Solomon decoder
std::vector<int> inav_rs_pages; // Pages 1,2,3,4,17,18,19,20. Holds 1 if the page has arrived, 0 otherwise.
uint8_t IODnav_LSB17{};
uint8_t IODnav_LSB18{};

View File

@ -739,18 +739,19 @@ void ReedSolomon::encode_rs_8(const uint8_t* data, uint8_t* parity) const
int ReedSolomon::decode(std::vector<uint8_t>& data_to_decode, const std::vector<int>& erasure_positions) const
{
int result = -1;
if (data_to_decode.size() != d_data_symbols_shortened)
{
std::cerr << "Reed Solomon usage error: wrong vector input size in decode method.\n";
return result;
}
if (erasure_positions.size() > std::size_t(d_nroots))
{
std::cerr << "Reed Solomon usage error: too much erasure positions.\n";
return result;
}
size_t size_buffer = data_to_decode.size();
if ((size_buffer != d_data_symbols_shortened) && (size_buffer != static_cast<size_t>(d_symbols_per_block)))
{
std::cerr << "Reed Solomon usage error: wrong vector input size in decode method.\n";
return result;
}
if (d_shortening == 0)
if (d_shortening == 0 || (size_buffer == static_cast<size_t>(d_symbols_per_block)))
{
result = decode_rs_8(data_to_decode.data(), erasure_positions.data(), erasure_positions.size());
}

View File

@ -103,6 +103,7 @@ endmacro()
add_benchmark(benchmark_copy)
add_benchmark(benchmark_preamble core_system_parameters)
add_benchmark(benchmark_detector core_system_parameters)
add_benchmark(benchmark_reed_solomon core_system_parameters)
if(has_std_plus_void)
target_compile_definitions(benchmark_detector PRIVATE -DCOMPILER_HAS_STD_PLUS_VOID=1)

View File

@ -0,0 +1,210 @@
/*!
* \file benchmark_redd_solomon.cc
* \brief Benchmark for Reed Solomon decoder
* \author Carles Fernandez-Prades, 2021. cfernandez(at)cttc.es
*
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "gnss_sdr_make_unique.h" // for std::unique_ptr in C++11
#include "reed_solomon.h"
#include <benchmark/benchmark.h>
#include <memory>
#include <vector>
void bm_e1b_erasurecorrection_shortened(benchmark::State& state)
{
std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};
auto rs = std::make_unique<ReedSolomon>(60, 29, 1, 195, 0, 137);
// Use case: We have received Word 1, Word 3, Word 18, Word 20
// So we have: c_0, c_2, g_1, g_3
// Delete c_1
for (int i = 16; i < 30; i++)
{
code_vector[i] = 0;
}
// Delete c_3
for (int i = 44; i < 58; i++)
{
code_vector[i] = 0;
}
// Delete g_0
for (int i = 58; i < 73; i++)
{
code_vector[i] = 0;
}
// Delete g_2
for (int i = 88; i < 103; i++)
{
code_vector[i] = 0;
}
std::vector<uint8_t> code_vector_missing = code_vector;
while (state.KeepRunning())
{
std::vector<int> erasure_positions;
erasure_positions.reserve(60);
for (int i = 16; i < 30; i++)
{
erasure_positions.push_back(i);
}
// Delete c_3
for (int i = 44; i < 58; i++)
{
erasure_positions.push_back(i);
}
// Delete g_0
for (int i = 58; i < 73; i++)
{
erasure_positions.push_back(i + 137); // erasure position refers to the unshortened code, so we add 137
}
// Delete g_2
for (int i = 88; i < 103; i++)
{
erasure_positions.push_back(i + 137);
}
int result = rs->decode(code_vector, erasure_positions);
if (result < 0)
{
state.SkipWithError("Failed to decode data!");
break;
}
state.PauseTiming();
code_vector = code_vector_missing;
state.ResumeTiming();
}
}
void bm_e1b_erasurecorrection_unshortened(benchmark::State& state)
{
std::vector<uint8_t> code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242};
auto rs = std::make_unique<ReedSolomon>(60, 29, 1, 195, 0, 137);
// Use case: We have received Word 1, Word 3, Word 18, Word 20
// So we have: c_0, c_2, g_1, g_3
// Delete c_1
for (int i = 16; i < 30; i++)
{
code_vector[i] = 0;
}
// Delete c_3
for (int i = 44; i < 58; i++)
{
code_vector[i] = 0;
}
// Delete g_0
for (int i = 137 + 58; i < 137 + 73; i++)
{
code_vector[i] = 0;
}
// Delete g_2
for (int i = 137 + 88; i < 137 + 103; i++)
{
code_vector[i] = 0;
}
std::vector<uint8_t> code_vector_missing = code_vector;
while (state.KeepRunning())
{
std::vector<int> erasure_positions;
erasure_positions.reserve(60);
for (int i = 16; i < 30; i++)
{
erasure_positions.push_back(i);
}
// Delete c_3
for (int i = 44; i < 58; i++)
{
erasure_positions.push_back(i);
}
// Delete g_0
for (int i = 58; i < 73; i++)
{
erasure_positions.push_back(i + 137); // erasure position refers to the unshortened code, so we add 137
}
// Delete g_2
for (int i = 88; i < 103; i++)
{
erasure_positions.push_back(i + 137);
}
int result = rs->decode(code_vector, erasure_positions);
if (result < 0)
{
state.SkipWithError("Failed to decode data!");
break;
}
state.PauseTiming();
code_vector = code_vector_missing;
state.ResumeTiming();
}
}
void bm_e6b_correction(benchmark::State& state)
{
const std::vector<uint8_t> expected_output = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
std::vector<uint8_t> encoded_input = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
// Introduce t = (n-k)/2 = 111 errors:
for (int i = 0; i < 222; i += 2)
{
encoded_input[i] = 0;
}
std::vector<uint8_t> code_vector_missing = encoded_input;
auto rs = std::make_unique<ReedSolomon>();
while (state.KeepRunning())
{
int result = rs->decode(encoded_input);
if (result < 0)
{
state.SkipWithError("Failed to decode data!");
break;
}
state.PauseTiming();
encoded_input = code_vector_missing;
state.ResumeTiming();
}
}
BENCHMARK(bm_e1b_erasurecorrection_shortened);
BENCHMARK(bm_e1b_erasurecorrection_unshortened);
BENCHMARK(bm_e6b_correction);
BENCHMARK_MAIN();