diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.cc index 41db4747b..736e7751d 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.cc @@ -30,6 +30,7 @@ #include "galileo_iono.h" // for Galileo_Iono #include "galileo_utc_model.h" // for Galileo_Utc_Model #include "gnss_synchro.h" +#include "tlm_crc_stats.h" #include "tlm_utils.h" #include #include @@ -81,6 +82,12 @@ galileo_telemetry_decoder_gs::galileo_telemetry_decoder_gs( d_frame_type = frame_type; DLOG(INFO) << "Initializing GALILEO UNIFIED TELEMETRY DECODER"; + d_dump_crc_stats = conf.dump_crc_stats; + if (d_dump_crc_stats) + { + // initialize the telemetry CRC statistics class + d_Tlm_CRC_Stats.initialize(conf.dump_crc_stats_filename); + } switch (d_frame_type) { case 1: // INAV @@ -616,6 +623,13 @@ void galileo_telemetry_decoder_gs::set_channel(int32_t channel) } } } + + if (d_dump_crc_stats) + { + // set the channel number for the telemetry CRC statistics + // disable the telemetry CRC statistics if there is a problem opening the output file + d_dump_crc_stats = d_Tlm_CRC_Stats.set_channel(d_channel); + } } @@ -787,6 +801,13 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__(( return -1; break; } + + if (d_dump_crc_stats) + { + // update CRC statistics + d_Tlm_CRC_Stats.update_CRC_stats(d_inav_nav.get_flag_CRC_test() or d_fnav_nav.get_flag_CRC_test() or d_cnav_nav.get_flag_CRC_test()); + } + d_preamble_index = d_sample_counter; // record the preamble sample stamp (t_P) if (d_inav_nav.get_flag_CRC_test() == true or d_fnav_nav.get_flag_CRC_test() == true or d_cnav_nav.get_flag_CRC_test() == true) { diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.h b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.h index 3e602041f..04300d2d6 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.h +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_telemetry_decoder_gs.h @@ -26,6 +26,7 @@ #include "gnss_block_interface.h" #include "gnss_satellite.h" #include "tlm_conf.h" +#include "tlm_crc_stats.h" #include #include // for block #include // for gr_vector_const_void_star @@ -105,6 +106,10 @@ private: Galileo_Inav_Message d_inav_nav; Galileo_Fnav_Message d_fnav_nav; + // CRC statistics + bool d_dump_crc_stats; + Tlm_CRC_Stats d_Tlm_CRC_Stats; + double d_delta_t; // GPS-GALILEO time offset uint64_t d_sample_counter; diff --git a/src/algorithms/telemetry_decoder/libs/CMakeLists.txt b/src/algorithms/telemetry_decoder/libs/CMakeLists.txt index ae9693543..da1e1d33e 100644 --- a/src/algorithms/telemetry_decoder/libs/CMakeLists.txt +++ b/src/algorithms/telemetry_decoder/libs/CMakeLists.txt @@ -11,6 +11,7 @@ set(TELEMETRY_DECODER_LIB_SOURCES tlm_conf.cc tlm_utils.cc viterbi_decoder.cc + tlm_crc_stats.cc ) set(TELEMETRY_DECODER_LIB_HEADERS @@ -18,6 +19,7 @@ set(TELEMETRY_DECODER_LIB_HEADERS viterbi_decoder.h convolutional.h tlm_utils.h + tlm_crc_stats.h ) list(SORT TELEMETRY_DECODER_LIB_HEADERS) diff --git a/src/algorithms/telemetry_decoder/libs/tlm_conf.cc b/src/algorithms/telemetry_decoder/libs/tlm_conf.cc index a293f5517..22dadfa11 100644 --- a/src/algorithms/telemetry_decoder/libs/tlm_conf.cc +++ b/src/algorithms/telemetry_decoder/libs/tlm_conf.cc @@ -23,6 +23,7 @@ Tlm_Conf::Tlm_Conf() dump_mat = false; remove_dat = false; enable_reed_solomon = false; + dump_crc_stats = false; } @@ -34,4 +35,7 @@ void Tlm_Conf::SetFromConfiguration(const ConfigurationInterface *configuration, dump = configuration->property(role + ".dump", false); dump_mat = configuration->property(role + ".dump_mat", dump); remove_dat = configuration->property(role + ".remove_dat", false); + dump_crc_stats = configuration->property(role + ".dump_crc_stats", false); + const std::string default_crc_stats_dumpname("telemetry_crc_stats"); + dump_crc_stats_filename = configuration->property(role + ".dump_crc_stats_filename", default_crc_stats_dumpname); } diff --git a/src/algorithms/telemetry_decoder/libs/tlm_conf.h b/src/algorithms/telemetry_decoder/libs/tlm_conf.h index e61be8842..b67c07ced 100644 --- a/src/algorithms/telemetry_decoder/libs/tlm_conf.h +++ b/src/algorithms/telemetry_decoder/libs/tlm_conf.h @@ -39,6 +39,8 @@ public: bool dump_mat; bool remove_dat; bool enable_reed_solomon; // for INAV message in Galileo E1B + bool dump_crc_stats; // telemetry CRC statistics + std::string dump_crc_stats_filename; }; diff --git a/src/algorithms/telemetry_decoder/libs/tlm_crc_stats.cc b/src/algorithms/telemetry_decoder/libs/tlm_crc_stats.cc new file mode 100644 index 000000000..031f73ab8 --- /dev/null +++ b/src/algorithms/telemetry_decoder/libs/tlm_crc_stats.cc @@ -0,0 +1,148 @@ +/*! + * \file tlm_crc_stats.cc + * \brief Class that computes the telemetry CRC statistics + * \author Marc Majoral, 2021. mmajoral(at)cttc.es + * + * ----------------------------------------------------------------------------- + * + * 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) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#include "tlm_crc_stats.h" +#include "gnss_sdr_create_directory.h" +#include "gnss_sdr_filesystem.h" +#include +#include // for std::setw() +#include // for cerr, cout + + +Tlm_CRC_Stats::Tlm_CRC_Stats() +{ + enable_crc_stats = false; +} + +void Tlm_CRC_Stats::initialize(std::string dump_crc_stats_filename_) +{ + d_dump_crc_stats_filename = dump_crc_stats_filename_; + + enable_crc_stats = true; + num_crc_ok = 0; + num_crc_not_ok = 0; +} + +bool Tlm_CRC_Stats::set_channel(int32_t channel_) +{ + std::string dump_path; + + channel = channel_; + + // Get path + if (d_dump_crc_stats_filename.find_last_of('/') != std::string::npos) + { + std::string dump_filename_ = d_dump_crc_stats_filename.substr(d_dump_crc_stats_filename.find_last_of('/') + 1); + dump_path = d_dump_crc_stats_filename.substr(0, d_dump_crc_stats_filename.find_last_of('/')); + d_dump_crc_stats_filename = dump_filename_; + } + else + { + dump_path = std::string("."); + } + // remove extension if any + if (d_dump_crc_stats_filename.substr(1).find_last_of('.') != std::string::npos) + { + d_dump_crc_stats_filename = d_dump_crc_stats_filename.substr(0, d_dump_crc_stats_filename.find_last_of('.')); + } + + d_dump_crc_stats_filename.append("_ch"); + d_dump_crc_stats_filename.append(std::to_string(channel)); + d_dump_crc_stats_filename.append(".txt"); + d_dump_crc_stats_filename = dump_path + fs::path::preferred_separator + d_dump_crc_stats_filename; + + // create directory + if (!gnss_sdr_create_directory(dump_path)) + { + std::cerr << "GNSS-SDR cannot create telemetry CRC stats dump file for the Telemetry block. The telemetry CRC statistics has been disabled. Wrong permissions?\n"; + enable_crc_stats = false; + } + d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit); + try + { + d_dump_file.open(d_dump_crc_stats_filename.c_str(), std::ios::out); + } + catch (const std::ifstream::failure &e) + { + LOG(WARNING) << "Exception opening telemetry CRC stats dump file " << e.what(); + enable_crc_stats = false; + } + + return true; +} + +void Tlm_CRC_Stats::update_CRC_stats(bool CRC) +{ + if (CRC) + { + num_crc_ok++; + } + else + { + num_crc_not_ok++; + } +} + +Tlm_CRC_Stats::~Tlm_CRC_Stats() +{ + uint32_t num_crc_tests = num_crc_ok + num_crc_not_ok; + float success_rate = 0.0; + + if (num_crc_tests > 0) + { + success_rate = static_cast(num_crc_ok) / static_cast(num_crc_tests); + } + std::string txt_num_crc_tests("Num CRC Tests"); + uint32_t align_num_crc_tests = txt_num_crc_tests.length(); + std::string txt_success_tests(" | Successful Tests"); + uint32_t align_success_tests = txt_success_tests.length(); + std::string txt_success_rate(" | Success rate"); + uint32_t align_success_rate = txt_success_rate.length(); + std::string txt_delimiter(" |"); + uint32_t align_delimiter = txt_delimiter.length(); + if (enable_crc_stats) + { + // write results to the telemetry CRC statistics output file + try + { + d_dump_file << txt_num_crc_tests << txt_success_tests << txt_success_rate << std::endl; + d_dump_file << std::setw(align_num_crc_tests) << num_crc_tests << txt_delimiter << std::setw(align_success_tests - align_delimiter) << num_crc_ok << txt_delimiter << std::setw(align_success_rate - align_delimiter) << std::setprecision(4) << success_rate << std::endl; + } + catch (const std::exception &ex) + { + DLOG(INFO) << "Telemetry CRC stats cannot write on the output file " << d_dump_crc_stats_filename.c_str(); + } + + + const auto pos = d_dump_file.tellp(); + try + { + d_dump_file.close(); + } + catch (const std::exception &ex) + { + LOG(WARNING) << "Exception in destructor closing the telemetry CRC stats dump file " << ex.what(); + } + if (pos == 0) + { + errorlib::error_code ec; + if (!fs::remove(fs::path(d_dump_crc_stats_filename), ec)) + { + std::cerr << "Problem removing telemetry CRC stats temporary file " << d_dump_crc_stats_filename << '\n'; + } + } + } +} diff --git a/src/algorithms/telemetry_decoder/libs/tlm_crc_stats.h b/src/algorithms/telemetry_decoder/libs/tlm_crc_stats.h new file mode 100644 index 000000000..1753ab7fa --- /dev/null +++ b/src/algorithms/telemetry_decoder/libs/tlm_crc_stats.h @@ -0,0 +1,66 @@ +/*! + * \file tlm_crc_stats.h + * \brief Class that computes the telemetry CRC statistics + * \author Marc Majoral, 2021. mmajoral(at)cttc.es + * + * ----------------------------------------------------------------------------- + * + * 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) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_CRC_STATS_H +#define GNSS_SDR_CRC_STATS_H + +#include // for std::ofstream +#include // for std::string + +/** \addtogroup Telemetry_Decoder + * \{ */ +/** \addtogroup Telemetry_Decoder_libs telemetry_decoder_libs + * \{ */ + +/*! + * \brief Class that computes the telemetry CRC statistics + */ +class Tlm_CRC_Stats +{ +public: + Tlm_CRC_Stats(); + + ~Tlm_CRC_Stats(); + + /*! + * \brief Initialize the telemetry CRC statistics + */ + void initialize(std::string dump_crc_stats_filename_); + + /*! + * \brief Initialize the channel number and output file + */ + bool set_channel(int32_t channel_); + + /*! + * \brief Update the CRC statistics + */ + void update_CRC_stats(bool CRC); + +private: + bool enable_crc_stats; + uint32_t num_crc_ok; + uint32_t num_crc_not_ok; + int32_t channel; + + std::ofstream d_dump_file; + std::string d_dump_crc_stats_filename; +}; + + +/** \} */ +/** \} */ +#endif // GNSS_SDR_CRC_STATS_H