diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc index 13dc549d8..a6aaa8ee0 100644 --- a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc +++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc @@ -113,7 +113,7 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con std::cout << "Sample rate: " << sample_rate_ << " Sps\n"; - enable_ovf_check_buffer_monitor_ = 0; // check buffer overflow and buffer monitor disabled by default + enable_ovf_check_buffer_monitor_active_ = false; // check buffer overflow and buffer monitor disabled by default if (switch_position_ == 0) // Inject file(s) via DMA { @@ -295,12 +295,15 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con } } - // when the receiver is working in real-time mode via AD9361 perform buffer overflow checking and buffer monitoring - enable_ovf_check_buffer_monitor_ = 1; - enable_buffer_monitor_ = configuration->property(role + ".enable_buffer_monitor", false); // only buffer overflow checking by default + // when the receiver is working in real-time mode via AD9361 perform buffer overflow checking, + // and if dump is enabled perform buffer monitoring + enable_ovf_check_buffer_monitor_active_ = true; std::string device_io_name_buffer_monitor; + dump_ = configuration->property(role + ".dump", false); + std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); + // find the uio device file corresponding to the buffer monitor if (find_uio_dev_file_name(device_io_name_buffer_monitor, buffer_monitor_device_name, 0) < 0) { @@ -309,7 +312,7 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con } uint32_t num_freq_bands = (freq_band.compare("L1L2")) ? 1 : 2; - buffer_monitor_fpga = std::make_shared(device_io_name_buffer_monitor, num_freq_bands); + buffer_monitor_fpga = std::make_shared(device_io_name_buffer_monitor, num_freq_bands, dump_, dump_filename); thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); }); } @@ -385,7 +388,7 @@ Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource() // disable buffer overflow checking and buffer monitoring std::unique_lock lock(buffer_monitor_mutex); - enable_ovf_check_buffer_monitor_ = false; + enable_ovf_check_buffer_monitor_active_ = false; lock.unlock(); if (thread_buffer_monitor.joinable()) @@ -683,14 +686,10 @@ void Ad9361FpgaSignalSource::run_buffer_monitor_process() while (enable_ovf_check_buffer_monitor_active) { - buffer_monitor_fpga->check_buffer_overflow(); - if (enable_buffer_monitor_) - { - buffer_monitor_fpga->monitor_buffer_status(); - } + buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status(); std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms)); std::unique_lock lock(buffer_monitor_mutex); - if (enable_ovf_check_buffer_monitor_ == false) + if (enable_ovf_check_buffer_monitor_active_ == false) { enable_ovf_check_buffer_monitor_active = false; } diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h index 92beee3f0..7ee3c9b2a 100644 --- a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h +++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h @@ -77,7 +77,7 @@ private: const std::string switch_device_name = "AXIS_Switch_v1_0_0"; // Switch UIO device name const std::string dyn_bit_sel_device_name = "dynamic_bits_selector"; // Switch dhnamic bit selector device name const std::string buffer_monitor_device_name = "buffer_monitor"; // buffer monitor device name - + const std::string default_dump_filename = std::string("FPGA_buffer_monitor_dump.dat"); // perform dynamic bit selection every 500 ms by default static const uint32_t Gain_control_period_ms = 500; // check buffer overflow and perform buffer monitoring every 1s by default @@ -146,8 +146,9 @@ private: bool rx2_enable_; bool enable_DMA_; bool enable_dynamic_bit_selection_; - bool enable_buffer_monitor_; + bool enable_ovf_check_buffer_monitor_active_; bool enable_ovf_check_buffer_monitor_; + bool dump_; bool rf_shutdown_; }; diff --git a/src/algorithms/signal_source/libs/CMakeLists.txt b/src/algorithms/signal_source/libs/CMakeLists.txt index 1bea34b05..30bb8f5d8 100644 --- a/src/algorithms/signal_source/libs/CMakeLists.txt +++ b/src/algorithms/signal_source/libs/CMakeLists.txt @@ -92,6 +92,13 @@ if(ENABLE_FMCOMMS2 OR ENABLE_AD9361) endif() endif() +if(ENABLE_FPGA OR ENABLE_AD9361) + target_link_libraries(signal_source_libs + PUBLIC + algorithms_libs + ) +endif() + if(ENABLE_CLANG_TIDY) if(CLANG_TIDY_EXE) set_target_properties(signal_source_libs diff --git a/src/algorithms/signal_source/libs/fpga_buffer_monitor.cc b/src/algorithms/signal_source/libs/fpga_buffer_monitor.cc index 40cbad008..a984e569e 100644 --- a/src/algorithms/signal_source/libs/fpga_buffer_monitor.cc +++ b/src/algorithms/signal_source/libs/fpga_buffer_monitor.cc @@ -20,14 +20,20 @@ */ #include "fpga_buffer_monitor.h" +#include "gnss_sdr_create_directory.h" +#include "gnss_sdr_filesystem.h" #include +#include // for time, localtime #include // for open, O_RDWR, O_SYNC +#include // for string, ofstream #include // for cout #include // for mmap -Fpga_buffer_monitor::Fpga_buffer_monitor(const std::string &device_name, uint32_t num_freq_bands) +Fpga_buffer_monitor::Fpga_buffer_monitor(const std::string &device_name, uint32_t num_freq_bands, bool dump, std::string dump_filename) { d_num_freq_bands = num_freq_bands; + d_dump = dump; + d_dump_filename = dump_filename; // open device descriptor if ((d_device_descriptor = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1) @@ -59,18 +65,82 @@ Fpga_buffer_monitor::Fpga_buffer_monitor(const std::string &device_name, uint32_ DLOG(INFO) << "FPGA buffer monitor class created"; // initialize maximum buffer occupancy in case buffer monitoring is enabled - max_buff_occ_freq_band_0 = 0; - max_buff_occ_freq_band_1 = 0; + d_max_buff_occ_freq_band_0 = 0; + d_max_buff_occ_freq_band_1 = 0; + + if (d_dump) + { + std::string dump_path; + // Get path + if (d_dump_filename.find_last_of('/') != std::string::npos) + { + const std::string dump_filename_ = d_dump_filename.substr(d_dump_filename.find_last_of('/') + 1); + dump_path = d_dump_filename.substr(0, d_dump_filename.find_last_of('/')); + d_dump_filename = dump_filename_; + } + else + { + dump_path = std::string("."); + } + if (d_dump_filename.empty()) + { + d_dump_filename = "FPGA_buffer_monitor"; + } + // remove extension if any + if (d_dump_filename.substr(1).find_last_of('.') != std::string::npos) + { + d_dump_filename = d_dump_filename.substr(0, d_dump_filename.find_last_of('.')); + } + d_dump_filename = dump_path + fs::path::preferred_separator + d_dump_filename; + // create directory + if (!gnss_sdr_create_directory(dump_path)) + { + std::cerr << "GNSS-SDR cannot create dump file for the Buffer Monitor block. Wrong permissions?\n"; + d_dump = false; + } + + std::string dump_filename_ = d_dump_filename; + dump_filename_.append(".dat"); + + if (!d_dump_file.is_open()) + { + try + { + d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit); + d_dump_file.open(dump_filename_.c_str(), std::ios::out | std::ios::binary); + LOG(INFO) << "FPGA buffer monitor dump enabled. Log file: " << dump_filename_.c_str(); + } + catch (const std::ifstream::failure &e) + { + LOG(WARNING) << "Exception opening FPGA buffer monitor dump file " << e.what(); + } + } + } } Fpga_buffer_monitor::~Fpga_buffer_monitor() { close_device(); + + if (d_dump) + { + if (d_dump_file.is_open()) + { + try + { + d_dump_file.close(); + } + catch (const std::exception &ex) + { + LOG(WARNING) << "Exception in FPGA buffer monitor destructor: " << ex.what(); + } + } + } } -void Fpga_buffer_monitor::check_buffer_overflow() +void Fpga_buffer_monitor::check_buffer_overflow_and_monitor_buffer_status(void) { // check buffer overflow flags uint32_t buffer_overflow_status = d_map_base[overflow_flags_reg_addr]; @@ -89,32 +159,57 @@ void Fpga_buffer_monitor::check_buffer_overflow() throw std::exception(); } } -} - -void Fpga_buffer_monitor::monitor_buffer_status(void) -{ - uint32_t current_buff_occ_freq_band_0 = d_map_base[current_buff_occ_freq_band_0_reg_addr] * num_sapmples_per_buffer_element; - uint32_t temp_max_buff_occ_freq_band_0 = d_map_base[max_buff_occ_freq_band_0_reg_addr] * num_sapmples_per_buffer_element; - if (temp_max_buff_occ_freq_band_0 > max_buff_occ_freq_band_0) + if (d_dump == 1) { - max_buff_occ_freq_band_0 = temp_max_buff_occ_freq_band_0; - } - std::cout << "current buffer occupancy frequency band 0 = " << current_buff_occ_freq_band_0 << " samples " << std::endl; - std::cout << "temporary maximum buffer occupancy frequency band 0 = " << temp_max_buff_occ_freq_band_0 << " samples " << std::endl; - std::cout << "maximum buffer occupancy frequency band 0 = " << max_buff_occ_freq_band_0 << " samples " << std::endl; - - if (d_num_freq_bands > 1) - { - uint32_t current_buff_occ_freq_band_1 = d_map_base[current_buff_occ_freq_band_1_reg_addr] * num_sapmples_per_buffer_element; - uint32_t temp_max_buff_occ_freq_band_1 = d_map_base[max_buff_occ_freq_band_1_reg_addr] * num_sapmples_per_buffer_element; - if (temp_max_buff_occ_freq_band_1 > max_buff_occ_freq_band_1) + uint32_t current_buff_occ_freq_band_0 = d_map_base[current_buff_occ_freq_band_0_reg_addr] * num_sapmples_per_buffer_element; + uint32_t temp_max_buff_occ_freq_band_0 = d_map_base[max_buff_occ_freq_band_0_reg_addr] * num_sapmples_per_buffer_element; + if (temp_max_buff_occ_freq_band_0 > d_max_buff_occ_freq_band_0) { - max_buff_occ_freq_band_1 = temp_max_buff_occ_freq_band_1; + d_max_buff_occ_freq_band_0 = temp_max_buff_occ_freq_band_0; + } + + time_t rawtime; + struct tm *timeinfo; + char buff_time_ch[80]; + + time(&rawtime); + timeinfo = localtime(&rawtime); + + strftime(buff_time_ch, sizeof(buff_time_ch), "%d-%m-%Y %H:%M:%S", timeinfo); + std::string buffer_time(buff_time_ch); + d_dump_file << buffer_time << std::endl; + + std::string buffer_txt; + // current buffer occupancy frequency band 0 + buffer_txt = std::to_string(current_buff_occ_freq_band_0); + d_dump_file << buffer_txt << std::endl; + // temporary maximum buffer occupancy frequency band 0 + buffer_txt = std::to_string(temp_max_buff_occ_freq_band_0); + d_dump_file << buffer_txt << std::endl; + // maximum buffer occupancy frequency band 0 + buffer_txt = std::to_string(d_max_buff_occ_freq_band_0); + d_dump_file << buffer_txt << std::endl; + + if (d_num_freq_bands > 1) + { + uint32_t current_buff_occ_freq_band_1 = d_map_base[current_buff_occ_freq_band_1_reg_addr] * num_sapmples_per_buffer_element; + uint32_t temp_max_buff_occ_freq_band_1 = d_map_base[max_buff_occ_freq_band_1_reg_addr] * num_sapmples_per_buffer_element; + if (temp_max_buff_occ_freq_band_1 > d_max_buff_occ_freq_band_1) + { + d_max_buff_occ_freq_band_1 = temp_max_buff_occ_freq_band_1; + } + + // current buffer occupancy frequency band 1 + buffer_txt = std::to_string(current_buff_occ_freq_band_1); + d_dump_file << buffer_txt << std::endl; + // temporary maximum buffer occupancy frequency band 1 + buffer_txt = std::to_string(temp_max_buff_occ_freq_band_1); + d_dump_file << buffer_txt << std::endl; + // maximum buffer occupancy frequency band 1 + buffer_txt = std::to_string(d_max_buff_occ_freq_band_1); + d_dump_file << buffer_txt << std::endl; } - std::cout << "current buffer occupancy frequency band 1 = " << current_buff_occ_freq_band_1 << " samples " << std::endl; - std::cout << "temporary maximum buffer occupancy frequency band 1 = " << temp_max_buff_occ_freq_band_1 << " samples " << std::endl; - std::cout << "maximum buffer occupancy frequency band 1 = " << max_buff_occ_freq_band_1 << " samples " << std::endl; } } diff --git a/src/algorithms/signal_source/libs/fpga_buffer_monitor.h b/src/algorithms/signal_source/libs/fpga_buffer_monitor.h index 7c6405811..6aa552e1c 100644 --- a/src/algorithms/signal_source/libs/fpga_buffer_monitor.h +++ b/src/algorithms/signal_source/libs/fpga_buffer_monitor.h @@ -13,7 +13,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 * * ----------------------------------------------------------------------------- @@ -22,8 +22,8 @@ #ifndef GNSS_SDR_FPGA_BUFFER_MONITOR_H #define GNSS_SDR_FPGA_BUFFER_MONITOR_H -#include -#include +#include // for int32_t +#include // for string, ofstream /** \addtogroup Signal_Source * \{ */ @@ -40,7 +40,7 @@ public: /*! * \brief Constructor */ - explicit Fpga_buffer_monitor(const std::string& device_name, uint32_t num_freq_bands); + explicit Fpga_buffer_monitor(const std::string& device_name, uint32_t num_freq_bands, bool dump, std::string dump_filename); /*! * \brief Destructor @@ -48,14 +48,9 @@ public: ~Fpga_buffer_monitor(); /*! - * \brief This function checks the status of the buffer overflow flags in the FPGA + * \brief This function checks buffer overflow and monitors the FPGA buffer status */ - void check_buffer_overflow(void); - - /*! - * \brief This function monitors the FPGA buffer status - */ - void monitor_buffer_status(void); + void check_buffer_overflow_and_monitor_buffer_status(void); private: static const size_t FPGA_PAGE_SIZE = 0x10000; @@ -83,8 +78,12 @@ private: uint32_t d_num_freq_bands; - uint32_t max_buff_occ_freq_band_0; - uint32_t max_buff_occ_freq_band_1; + uint32_t d_max_buff_occ_freq_band_0; + uint32_t d_max_buff_occ_freq_band_1; + + bool d_dump; + std::string d_dump_filename; + std::ofstream d_dump_file; };