diff options
Diffstat (limited to 'host/utils/latency')
-rw-r--r-- | host/utils/latency/include/Responder.hpp | 538 | ||||
-rw-r--r-- | host/utils/latency/lib/Responder.cpp | 1089 | ||||
-rw-r--r-- | host/utils/latency/responder.cpp | 47 |
3 files changed, 835 insertions, 839 deletions
diff --git a/host/utils/latency/include/Responder.hpp b/host/utils/latency/include/Responder.hpp index 0d690bcd6..81b5e84f9 100644 --- a/host/utils/latency/include/Responder.hpp +++ b/host/utils/latency/include/Responder.hpp @@ -8,279 +8,299 @@ #ifndef RESPONDER_H #define RESPONDER_H +#include <uhd/usrp/multi_usrp.hpp> #include <curses.h> -#include <map> -#include <ctime> #include <stdint.h> - -#include <uhd/usrp/multi_usrp.hpp> +#include <ctime> +#include <map> using namespace std; class Responder { - public: - enum ReturnCodes +public: + enum ReturnCodes { + RETCODE_OK = 0, + RETCODE_BAD_ARGS = -1, + RETCODE_RUNTIME_ERROR = -2, + RETCODE_UNKNOWN_EXCEPTION = -3, + RETCODE_RECEIVE_TIMEOUT = -4, + RETCODE_RECEIVE_FAILED = -5, + RETCODE_MANUAL_ABORT = -6, + RETCODE_BAD_PACKET = -7, + RETCODE_OVERFLOW = -8 + }; + + struct Options + { + string device_args; + double delay; + double sample_rate; + double trigger_level; + float output_scale; + double response_duration; + double dc_offset_delay; + double init_delay; + double timeout; + size_t samps_per_buff; + size_t samps_per_packet; + double level_calibration_duration; + std::string test_title; + std::string stats_filename; + std::string stats_filename_prefix; + std::string stats_filename_suffix; + double delay_min; + double delay_max; + double delay_step; + double pulse_detection_threshold; + uint64_t test_iterations; + size_t end_test_after_success_count; + size_t skip_iterations; + double simulate_frequency; + double time_mul; + size_t flush_count; + size_t optimize_padding; + double rt_priority; + bool ignore_simulation_check; + bool test_iterations_is_sample_count; + bool skip_eob; + bool adjust_simulation_rate; + bool optimize_simulation_rate; + bool no_stats_file; + bool log_file; + bool batch_mode; + bool skip_if_results_exist; + bool skip_send; + bool combine_eob; + bool pause; + bool realtime; + float invert; + float output_value; + bool no_delay; + bool allow_late_bursts; + + uint64_t level_calibration_count() const { - RETCODE_OK = 0, - RETCODE_BAD_ARGS = -1, - RETCODE_RUNTIME_ERROR = -2, - RETCODE_UNKNOWN_EXCEPTION = -3, - RETCODE_RECEIVE_TIMEOUT = -4, - RETCODE_RECEIVE_FAILED = -5, - RETCODE_MANUAL_ABORT = -6, - RETCODE_BAD_PACKET = -7, - RETCODE_OVERFLOW = -8 - }; - - struct Options - { - string device_args; - double delay; - double sample_rate; - double trigger_level; - float output_scale; - double response_duration; - double dc_offset_delay; - double init_delay; - double timeout; - size_t samps_per_buff; - size_t samps_per_packet; - double level_calibration_duration; - std::string test_title; - std::string stats_filename; - std::string stats_filename_prefix; - std::string stats_filename_suffix; - double delay_min; - double delay_max; - double delay_step; - double pulse_detection_threshold; - uint64_t test_iterations; - size_t end_test_after_success_count; - size_t skip_iterations; - double simulate_frequency; - double time_mul; - size_t flush_count; - size_t optimize_padding; - double rt_priority; - bool ignore_simulation_check; - bool test_iterations_is_sample_count; - bool skip_eob; - bool adjust_simulation_rate; - bool optimize_simulation_rate; - bool no_stats_file; - bool log_file; - bool batch_mode; - bool skip_if_results_exist; - bool skip_send; - bool combine_eob; - bool pause; - bool realtime; - float invert; - float output_value; - bool no_delay; - bool allow_late_bursts; - - uint64_t level_calibration_count() const - { - return (uint64_t)(sample_rate * level_calibration_duration); - } + return (uint64_t)(sample_rate * level_calibration_duration); + } - uint64_t response_length() const - { - return (uint64_t)(sample_rate * response_duration); - } - - uint64_t highest_delay_samples(const double delay) const - { - return (uint64_t)(delay * (double)sample_rate); - } - - uint64_t simulate_duration(const double simulate_frequency) const - { - if(simulate_frequency > 0.0) { - return (uint64_t)((double)sample_rate / simulate_frequency); - } - return 0; - } - }; - - typedef struct Stats + uint64_t response_length() const { - double delay; - uint64_t detected; - uint64_t missed; - uint64_t skipped; - } STATS; + return (uint64_t)(sample_rate * response_duration); + } - typedef std::map<uint64_t,STATS> StatsMap; + uint64_t highest_delay_samples(const double delay) const + { + return (uint64_t)(delay * (double)sample_rate); + } - struct DebugInfo + uint64_t simulate_duration(const double simulate_frequency) const { - time_t start_time; - time_t end_time; - time_t start_time_test; - time_t end_time_test; - time_t first_send_timeout; - }; - Responder(Options& opt); - virtual ~Responder(); - - // Main entry point after constructor. - int run(); - - int get_return_code(){return _return_code;} - - protected: - private: - // These 2 variables are used for ncurses output. - WINDOW* _window; - std::stringstream _ss; - std::stringstream _ss_cerr; - - // struct which holds all arguments as constants settable from outside the class - const Options _opt; - - string _stats_filename; // Specify name of statistics file - string _stats_log_filename; // Specify name for log file. - double _delay; // may be altered in all modes. - size_t _samps_per_packet; // This is one of the options of interest. Find out how well it performs. - double _delay_step; // may be altered in interactive mode - double _simulate_frequency; // updated during automatic test iterations - - // additional attributes - bool _allow_late_bursts; // may be altered in interactive mode - bool _no_delay; // may be altered in interactive mode - - // dependent variables - uint64_t _response_length; - int64_t _init_delay_count; - int64_t _dc_offset_countdown; - int64_t _level_calibration_countdown; - uint64_t _simulate_duration; - uint64_t _original_simulate_duration; - - // these variables store test conditions - uint64_t _num_total_samps; // printed on exit - size_t _overruns; // printed on exit - StatsMap _mapStats; // store results - uint64_t _max_success; // < 0 --> write results to file - int _return_code; - - // Hold USRP, streams and commands - uhd::usrp::multi_usrp::sptr _usrp; - uhd::tx_streamer::sptr _tx_stream; - uhd::rx_streamer::sptr _rx_stream; - uhd::stream_cmd_t _stream_cmd; - - // Keep track of number of timeouts. - uint64_t _timeout_burst_count; - uint64_t _timeout_eob_count; - - // Transmit attributes - float* _pResponse; - - // Control print parameters. - int _y_delay_pos; - int _x_delay_pos; // Remember the cursor position of delay line - uint64_t _last_overrun_count; - - // Hold debug info during test. Will be included in log file. - DebugInfo _dbginfo; - - /* - * Here are the class's member methods. - */ - // These methods are used for ncurses output - void create_ncurses_window(); - void FLUSH_SCREEN(); - void FLUSH_SCREEN_NL(); - - // Variable calculation helpers - inline uint64_t get_response_length(double sample_rate, double response_duration) - {return (uint64_t)(sample_rate * response_duration);} - int calculate_dependent_values(); - - // make sure existing results are not overwritten accidently - bool set_stats_filename(string test_id); - bool check_for_existing_results(); - - // Functions that may cause Responder to finish - void register_stop_signal_handler(); - bool test_finished(size_t success_count); - int test_step_finished(uint64_t trigger_count, uint64_t num_total_samps_test, STATS statsCurrent, size_t success_count); - - // Check if sent burst could be transmitted. - bool tx_burst_is_late(); - - // Handle receiver errors such as overflows. - bool handle_rx_errors(uhd::rx_metadata_t::error_code_t err, size_t num_rx_samps); - - // In interactive mode, handle Responder control and output. - bool handle_interactive_control(); - void print_interactive_msg(std::string msg); - - // calibration important for interactive mode with 2nd USRP connected. - float calibrate_usrp_for_test_run(); - - // Run actual test - void run_test(float threshold = 0.0f ); - - // Detect falling edge - bool get_new_state(uint64_t total_samps, uint64_t simulate_duration, float val, float threshold); - uint64_t detect_respond_pulse_count(STATS &statsCurrent, std::vector<std::complex<float> > &buff, uint64_t trigger_count, size_t num_rx_samps, float threshold, uhd::time_spec_t rx_time); - - // Hold test results till they are printed to a file - void add_stats_to_results(STATS statsCurrent, double delay); - - // Control USRP and necessary streamers - uhd::usrp::multi_usrp::sptr create_usrp_device(); - void set_usrp_rx_dc_offset(uhd::usrp::multi_usrp::sptr usrp, bool ena); - void stop_usrp_stream(); - uhd::tx_streamer::sptr create_tx_streamer(uhd::usrp::multi_usrp::sptr usrp); - uhd::rx_streamer::sptr create_rx_streamer(uhd::usrp::multi_usrp::sptr usrp); - - // Send burst and handle results. - bool send_tx_burst(uhd::time_spec_t rx_time, size_t n); - void handle_tx_timeout(int burst, int eob); - float* alloc_response_buffer_with_data(uint64_t response_length); - uhd::tx_metadata_t get_tx_metadata(uhd::time_spec_t rx_time, size_t n); - - // Control test parameters - void update_and_print_parameters(const STATS& statsPrev, const double delay); - double get_simulate_frequency(double delay, uint64_t response_length, uint64_t original_simulate_duration); - double get_max_possible_frequency(uint64_t highest_delay_samples, uint64_t response_length); - - // Helper methods to print status during test. - void print_init_test_status(); - void print_test_title(); - void print_usrp_status(); - void print_create_usrp_msg(); - void print_tx_stream_status(); - void print_rx_stream_status(); - void print_test_parameters(); - void print_formatted_delay_line(const uint64_t simulate_duration, const uint64_t old_simulate_duration, const STATS& statsPrev, const double delay, const double simulate_frequency); - void print_overrun_msg(); - void print_error_msg(std::string msg); - void print_timeout_msg(); - void print_final_statistics(); - void print_msg_and_wait(std::string msg); - void print_msg(std::string msg); - - // Safe results of test to file. - void write_statistics_to_file(StatsMap mapStats); - void safe_write_statistics_to_file(StatsMap mapStats, uint64_t max_success, int return_code); - void write_log_file(); - - // Write debug info to log file if requested. - void write_debug_info(ofstream& logs); - std::string get_gmtime_string(time_t time); - std::string enum2str(int return_code); - std::vector<std::map<std::string,std::string> > read_eth_info(); - uhd::device_addr_t get_usrp_info(); - std::map<std::string, std::string> get_hw_info(); - std::string get_ip_subnet_addr(std::string ip); + if (simulate_frequency > 0.0) { + return (uint64_t)((double)sample_rate / simulate_frequency); + } + return 0; + } + }; + + typedef struct Stats + { + double delay; + uint64_t detected; + uint64_t missed; + uint64_t skipped; + } STATS; + + typedef std::map<uint64_t, STATS> StatsMap; + + struct DebugInfo + { + time_t start_time; + time_t end_time; + time_t start_time_test; + time_t end_time_test; + time_t first_send_timeout; + }; + Responder(Options& opt); + virtual ~Responder(); + + // Main entry point after constructor. + int run(); + + int get_return_code() + { + return _return_code; + } + +protected: +private: + // These 2 variables are used for ncurses output. + WINDOW* _window; + std::stringstream _ss; + std::stringstream _ss_cerr; + + // struct which holds all arguments as constants settable from outside the class + const Options _opt; + + string _stats_filename; // Specify name of statistics file + string _stats_log_filename; // Specify name for log file. + double _delay; // may be altered in all modes. + size_t _samps_per_packet; // This is one of the options of interest. Find out how well + // it performs. + double _delay_step; // may be altered in interactive mode + double _simulate_frequency; // updated during automatic test iterations + + // additional attributes + bool _allow_late_bursts; // may be altered in interactive mode + bool _no_delay; // may be altered in interactive mode + + // dependent variables + uint64_t _response_length; + int64_t _init_delay_count; + int64_t _dc_offset_countdown; + int64_t _level_calibration_countdown; + uint64_t _simulate_duration; + uint64_t _original_simulate_duration; + + // these variables store test conditions + uint64_t _num_total_samps; // printed on exit + size_t _overruns; // printed on exit + StatsMap _mapStats; // store results + uint64_t _max_success; // < 0 --> write results to file + int _return_code; + + // Hold USRP, streams and commands + uhd::usrp::multi_usrp::sptr _usrp; + uhd::tx_streamer::sptr _tx_stream; + uhd::rx_streamer::sptr _rx_stream; + uhd::stream_cmd_t _stream_cmd; + + // Keep track of number of timeouts. + uint64_t _timeout_burst_count; + uint64_t _timeout_eob_count; + + // Transmit attributes + float* _pResponse; + + // Control print parameters. + int _y_delay_pos; + int _x_delay_pos; // Remember the cursor position of delay line + uint64_t _last_overrun_count; + + // Hold debug info during test. Will be included in log file. + DebugInfo _dbginfo; + + /* + * Here are the class's member methods. + */ + // These methods are used for ncurses output + void create_ncurses_window(); + void FLUSH_SCREEN(); + void FLUSH_SCREEN_NL(); + + // Variable calculation helpers + inline uint64_t get_response_length(double sample_rate, double response_duration) + { + return (uint64_t)(sample_rate * response_duration); + } + int calculate_dependent_values(); + + // make sure existing results are not overwritten accidently + bool set_stats_filename(string test_id); + bool check_for_existing_results(); + + // Functions that may cause Responder to finish + void register_stop_signal_handler(); + bool test_finished(size_t success_count); + int test_step_finished(uint64_t trigger_count, + uint64_t num_total_samps_test, + STATS statsCurrent, + size_t success_count); + + // Check if sent burst could be transmitted. + bool tx_burst_is_late(); + + // Handle receiver errors such as overflows. + bool handle_rx_errors(uhd::rx_metadata_t::error_code_t err, size_t num_rx_samps); + + // In interactive mode, handle Responder control and output. + bool handle_interactive_control(); + void print_interactive_msg(std::string msg); + + // calibration important for interactive mode with 2nd USRP connected. + float calibrate_usrp_for_test_run(); + + // Run actual test + void run_test(float threshold = 0.0f); + + // Detect falling edge + bool get_new_state( + uint64_t total_samps, uint64_t simulate_duration, float val, float threshold); + uint64_t detect_respond_pulse_count(STATS& statsCurrent, + std::vector<std::complex<float>>& buff, + uint64_t trigger_count, + size_t num_rx_samps, + float threshold, + uhd::time_spec_t rx_time); + + // Hold test results till they are printed to a file + void add_stats_to_results(STATS statsCurrent, double delay); + + // Control USRP and necessary streamers + uhd::usrp::multi_usrp::sptr create_usrp_device(); + void set_usrp_rx_dc_offset(uhd::usrp::multi_usrp::sptr usrp, bool ena); + void stop_usrp_stream(); + uhd::tx_streamer::sptr create_tx_streamer(uhd::usrp::multi_usrp::sptr usrp); + uhd::rx_streamer::sptr create_rx_streamer(uhd::usrp::multi_usrp::sptr usrp); + + // Send burst and handle results. + bool send_tx_burst(uhd::time_spec_t rx_time, size_t n); + void handle_tx_timeout(int burst, int eob); + float* alloc_response_buffer_with_data(uint64_t response_length); + uhd::tx_metadata_t get_tx_metadata(uhd::time_spec_t rx_time, size_t n); + + // Control test parameters + void update_and_print_parameters(const STATS& statsPrev, const double delay); + double get_simulate_frequency( + double delay, uint64_t response_length, uint64_t original_simulate_duration); + double get_max_possible_frequency( + uint64_t highest_delay_samples, uint64_t response_length); + + // Helper methods to print status during test. + void print_init_test_status(); + void print_test_title(); + void print_usrp_status(); + void print_create_usrp_msg(); + void print_tx_stream_status(); + void print_rx_stream_status(); + void print_test_parameters(); + void print_formatted_delay_line(const uint64_t simulate_duration, + const uint64_t old_simulate_duration, + const STATS& statsPrev, + const double delay, + const double simulate_frequency); + void print_overrun_msg(); + void print_error_msg(std::string msg); + void print_timeout_msg(); + void print_final_statistics(); + void print_msg_and_wait(std::string msg); + void print_msg(std::string msg); + + // Safe results of test to file. + void write_statistics_to_file(StatsMap mapStats); + void safe_write_statistics_to_file( + StatsMap mapStats, uint64_t max_success, int return_code); + void write_log_file(); + + // Write debug info to log file if requested. + void write_debug_info(ofstream& logs); + std::string get_gmtime_string(time_t time); + std::string enum2str(int return_code); + std::vector<std::map<std::string, std::string>> read_eth_info(); + uhd::device_addr_t get_usrp_info(); + std::map<std::string, std::string> get_hw_info(); + std::string get_ip_subnet_addr(std::string ip); }; #endif // RESPONDER_H diff --git a/host/utils/latency/lib/Responder.cpp b/host/utils/latency/lib/Responder.cpp index 5597c0fcd..0d7a307dd 100644 --- a/host/utils/latency/lib/Responder.cpp +++ b/host/utils/latency/lib/Responder.cpp @@ -6,60 +6,55 @@ // #include "Responder.hpp" - -#include <iostream> -#include <iomanip> -#include <fstream> +#include <uhd/property_tree.hpp> +#include <uhd/utils/thread.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/filesystem.hpp> +#include <boost/format.hpp> +#include <boost/thread/condition_variable.hpp> +#include <cmath> #include <complex> #include <csignal> -#include <cmath> +#include <fstream> +#include <iomanip> +#include <iostream> #include <sstream> -#include <boost/format.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/thread/condition_variable.hpp> -#include <boost/filesystem.hpp> -#include <uhd/utils/thread.hpp> -#include <uhd/property_tree.hpp> - const std::string _eth_file("eths_info.txt"); // Redirect output to stderr -struct cerr_redirect { - cerr_redirect( std::streambuf * new_buffer ) - : old( std::cerr.rdbuf( new_buffer ) ) - { } +struct cerr_redirect +{ + cerr_redirect(std::streambuf* new_buffer) : old(std::cerr.rdbuf(new_buffer)) {} - ~cerr_redirect( ) { - std::cerr.rdbuf( old ); + ~cerr_redirect() + { + std::cerr.rdbuf(old); } private: - std::streambuf * old; + std::streambuf* old; }; - // Catch keyboard interrupts for clean manual abort static bool s_stop_signal_called = false; -static int s_signal = 0; +static int s_signal = 0; static void sig_int_handler(int signal) { s_stop_signal_called = true; - s_signal = signal; + s_signal = signal; } // member of Responder to register sig int handler -void -Responder::register_stop_signal_handler() +void Responder::register_stop_signal_handler() { std::signal(SIGINT, &sig_int_handler); } // For ncurses. Print everything in stream to screen -void -Responder::FLUSH_SCREEN() +void Responder::FLUSH_SCREEN() { printw(_ss.str().c_str()); refresh(); @@ -67,13 +62,12 @@ Responder::FLUSH_SCREEN() } // Like FLUSH_SCREEN but with new line -void -Responder::FLUSH_SCREEN_NL() +void Responder::FLUSH_SCREEN_NL() { do { int y, x; getyx(_window, y, x); - if (x > 0){ + if (x > 0) { printw("\n"); y++; } @@ -82,33 +76,39 @@ Responder::FLUSH_SCREEN_NL() } // Constructor -Responder::Responder( Options& opt) - : _opt(opt), - _stats_filename(opt.stats_filename), - _delay(opt.delay), - _samps_per_packet(opt.samps_per_packet), - _delay_step(opt.delay_step), - _simulate_frequency(opt.simulate_frequency), - _allow_late_bursts(opt.allow_late_bursts), - _no_delay(opt.no_delay), - //Initialize atributes not given by Options - _num_total_samps(0), // printed on exit - _overruns(0), // printed on exit - _max_success(0), // < 0 --> write results to file - _return_code(RETCODE_OK), - _stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS), - _timeout_burst_count(0), - _timeout_eob_count(0), - _y_delay_pos(-1), - _x_delay_pos(-1), // Remember the cursor position of delay line. +Responder::Responder(Options& opt) + : _opt(opt) + , _stats_filename(opt.stats_filename) + , _delay(opt.delay) + , _samps_per_packet(opt.samps_per_packet) + , _delay_step(opt.delay_step) + , _simulate_frequency(opt.simulate_frequency) + , _allow_late_bursts(opt.allow_late_bursts) + , _no_delay(opt.no_delay) + , + // Initialize atributes not given by Options + _num_total_samps(0) + , // printed on exit + _overruns(0) + , // printed on exit + _max_success(0) + , // < 0 --> write results to file + _return_code(RETCODE_OK) + , _stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS) + , _timeout_burst_count(0) + , _timeout_eob_count(0) + , _y_delay_pos(-1) + , _x_delay_pos(-1) + , // Remember the cursor position of delay line. _last_overrun_count(0) { - time( &_dbginfo.start_time ); // for debugging + time(&_dbginfo.start_time); // for debugging // Disable logging to console uhd::log::set_console_level(uhd::log::off); - if (uhd::set_thread_priority_safe(_opt.rt_priority, _opt.realtime) == false) // try to set realtime scheduling + if (uhd::set_thread_priority_safe(_opt.rt_priority, _opt.realtime) + == false) // try to set realtime scheduling { cerr << "Failed to set real-time" << endl; } @@ -120,16 +120,12 @@ Responder::Responder( Options& opt) create_ncurses_window(); print_create_usrp_msg(); - try - { + try { _usrp = create_usrp_device(); - } - catch (const std::runtime_error& e) - { - print_msg(e.what() ); + } catch (const std::runtime_error& e) { + print_msg(e.what()); _return_code = RETCODE_RUNTIME_ERROR; - } - catch(...){ + } catch (...) { print_msg("unhandled ERROR"); _return_code = RETCODE_UNKNOWN_EXCEPTION; print_msg_and_wait("create USRP device failed!\nPress key to abort test..."); @@ -141,12 +137,10 @@ Responder::Responder( Options& opt) // ensure that filename is set string test_id = _usrp->get_mboard_name(); - if (set_stats_filename(test_id) ) - { + if (set_stats_filename(test_id)) { _return_code = RETCODE_BAD_ARGS; // make sure run() does return! FLUSH_SCREEN(); - if (_opt.batch_mode == false) - { + if (_opt.batch_mode == false) { print_msg_and_wait("Press any key to end..."); } return; @@ -156,20 +150,19 @@ Responder::Responder( Options& opt) register_stop_signal_handler(); } -int -Responder::calculate_dependent_values() +int Responder::calculate_dependent_values() { - _response_length = _opt.response_length(); - _init_delay_count = (int64_t)(_opt.sample_rate * _opt.init_delay); - _dc_offset_countdown = (int64_t)(_opt.sample_rate * _opt.dc_offset_delay); + _response_length = _opt.response_length(); + _init_delay_count = (int64_t)(_opt.sample_rate * _opt.init_delay); + _dc_offset_countdown = (int64_t)(_opt.sample_rate * _opt.dc_offset_delay); _level_calibration_countdown = (int64_t)_opt.level_calibration_count(); - _original_simulate_duration = _simulate_duration = _opt.simulate_duration(_simulate_frequency); + _original_simulate_duration = _simulate_duration = + _opt.simulate_duration(_simulate_frequency); - if (_simulate_duration > 0) - { + if (_simulate_duration > 0) { // Skip settling period and calibration - _init_delay_count = 0; - _dc_offset_countdown = 0; + _init_delay_count = 0; + _dc_offset_countdown = 0; _level_calibration_countdown = 0; double highest_delay = 0.0; @@ -179,70 +172,78 @@ Responder::calculate_dependent_values() highest_delay = _delay; uint64_t highest_delay_samples = _opt.highest_delay_samples(highest_delay); - if ((highest_delay_samples + _response_length + _opt.flush_count) > _simulate_duration) - { - if (_opt.adjust_simulation_rate) // This is now done DURING the simulation based on active delay + if ((highest_delay_samples + _response_length + _opt.flush_count) + > _simulate_duration) { + if (_opt.adjust_simulation_rate) // This is now done DURING the simulation + // based on active delay { //_simulate_frequency = max_possible_rate; - //_simulate_duration = (uint64_t)((double)sample_rate / _simulate_frequency); - } - else - { - cerr << boost::format("Highest delay and response duration will exceed the pulse simulation rate (%ld + %ld > %ld samples)") % highest_delay_samples % _response_length % _simulate_duration << endl; - int max_possible_rate = (int) get_max_possible_frequency(highest_delay_samples, _response_length); - double max_possible_delay = (double)(_simulate_duration - (_response_length + _opt.flush_count)) / (double)_opt.sample_rate; - cerr << boost::format("Simulation rate must be less than %i Hz, or maximum delay must be less than %f s") % max_possible_rate % max_possible_delay << endl; + //_simulate_duration = (uint64_t)((double)sample_rate / + //_simulate_frequency); + } else { + cerr << boost::format( + "Highest delay and response duration will exceed the pulse " + "simulation rate (%ld + %ld > %ld samples)") + % highest_delay_samples % _response_length + % _simulate_duration + << endl; + int max_possible_rate = (int)get_max_possible_frequency( + highest_delay_samples, _response_length); + double max_possible_delay = + (double)(_simulate_duration - (_response_length + _opt.flush_count)) + / (double)_opt.sample_rate; + cerr << boost::format("Simulation rate must be less than %i Hz, or " + "maximum delay must be less than %f s") + % max_possible_rate % max_possible_delay + << endl; if (_opt.ignore_simulation_check == 0) return RETCODE_BAD_ARGS; } } - } - else - { - boost::format fmt("Simulation frequency too high (%f Hz with sample_rate %f Msps)"); - fmt % _simulate_frequency % (_opt.sample_rate/1e6); + } else { + boost::format fmt( + "Simulation frequency too high (%f Hz with sample_rate %f Msps)"); + fmt % _simulate_frequency % (_opt.sample_rate / 1e6); cerr << fmt << endl; return RETCODE_BAD_ARGS; } - if (_opt.test_iterations > 0) // Force certain settings during test mode + if (_opt.test_iterations > 0) // Force certain settings during test mode { - _no_delay = false; + _no_delay = false; _allow_late_bursts = false; - _delay = _opt.delay_min; + _delay = _opt.delay_min; } return RETCODE_OK; // default return code } // print test title to ncurses window -void -Responder::print_test_title() +void Responder::print_test_title() { - if (_opt.test_title.empty() == false) - { + if (_opt.test_title.empty() == false) { std::string title(_opt.test_title); boost::replace_all(title, "%", "%%"); print_msg(title + "\n"); } } -void -Responder::print_usrp_status() +void Responder::print_usrp_status() { std::string msg; - msg += (boost::format("Using device:\n%s\n") % _usrp->get_pp_string() ).str(); - msg += (boost::format("Setting RX rate: %f Msps\n") % (_opt.sample_rate/1e6)).str(); - msg += (boost::format("Actual RX rate: %f Msps\n") % (_usrp->get_rx_rate()/1e6) ).str(); - msg += (boost::format("Setting TX rate: %f Msps\n") % (_opt.sample_rate/1e6) ).str(); - msg += (boost::format("Actual TX rate: %f Msps") % (_usrp->get_tx_rate()/1e6) ).str(); + msg += (boost::format("Using device:\n%s\n") % _usrp->get_pp_string()).str(); + msg += (boost::format("Setting RX rate: %f Msps\n") % (_opt.sample_rate / 1e6)).str(); + msg += (boost::format("Actual RX rate: %f Msps\n") % (_usrp->get_rx_rate() / 1e6)) + .str(); + msg += (boost::format("Setting TX rate: %f Msps\n") % (_opt.sample_rate / 1e6)).str(); + msg += + (boost::format("Actual TX rate: %f Msps") % (_usrp->get_tx_rate() / 1e6)).str(); print_msg(msg); print_tx_stream_status(); print_rx_stream_status(); } -void -Responder::print_test_parameters() +void Responder::print_test_parameters() { // Some status output shoud be printed here! size_t rx_max_num_samps = _rx_stream->get_max_num_samps(); @@ -250,52 +251,58 @@ Responder::print_test_parameters() std::string msg; msg += (boost::format("Samples per buffer: %d\n") % _opt.samps_per_buff).str(); - msg += (boost::format("Maximum number of samples: RX = %d, TX = %d\n") % rx_max_num_samps % tx_max_num_samps).str(); - msg += (boost::format("Response length: %ld samples (%f us)") % _response_length % (_opt.response_duration * 1e6) ).str(); + msg += (boost::format("Maximum number of samples: RX = %d, TX = %d\n") + % rx_max_num_samps % tx_max_num_samps) + .str(); + msg += (boost::format("Response length: %ld samples (%f us)") % _response_length + % (_opt.response_duration * 1e6)) + .str(); if (_simulate_duration > 0) - msg += (boost::format("\nSimulating pulses at %f Hz (every %ld samples)") % _simulate_frequency % _simulate_duration ).str(); + msg += (boost::format("\nSimulating pulses at %f Hz (every %ld samples)") + % _simulate_frequency % _simulate_duration) + .str(); - if (_opt.test_iterations > 0) - { - msg += (boost::format("\nTest coverage: %f -> %f (%f steps)") % _opt.delay_min % _opt.delay_max % _opt.delay_step ).str(); + if (_opt.test_iterations > 0) { + msg += (boost::format("\nTest coverage: %f -> %f (%f steps)") % _opt.delay_min + % _opt.delay_max % _opt.delay_step) + .str(); if (_opt.end_test_after_success_count > 0) - msg += (boost::format("\nTesting will end after %d successful delays") % _opt.end_test_after_success_count ).str(); + msg += (boost::format("\nTesting will end after %d successful delays") + % _opt.end_test_after_success_count) + .str(); } - if ((_dc_offset_countdown == 0) && (_simulate_frequency == 0.0)) - { + if ((_dc_offset_countdown == 0) && (_simulate_frequency == 0.0)) { msg += "\nDC offset disabled"; } print_msg(msg); } -// e.g. B200 doesn't support this command. Check if possible and only set rx_dc_offset if available -void -Responder::set_usrp_rx_dc_offset(uhd::usrp::multi_usrp::sptr usrp, bool ena) +// e.g. B200 doesn't support this command. Check if possible and only set rx_dc_offset if +// available +void Responder::set_usrp_rx_dc_offset(uhd::usrp::multi_usrp::sptr usrp, bool ena) { uhd::property_tree::sptr tree = usrp->get_device()->get_tree(); // FIXME: Path needs to be build in a programmatic way. - bool dc_offset_exists = tree->exists( uhd::fs_path("/mboards/0/rx_frontends/A/dc_offset") ); - if(dc_offset_exists) - { + bool dc_offset_exists = + tree->exists(uhd::fs_path("/mboards/0/rx_frontends/A/dc_offset")); + if (dc_offset_exists) { usrp->set_rx_dc_offset(ena); } } -void -Responder::print_create_usrp_msg() +void Responder::print_create_usrp_msg() { std::string msg("Creating the USRP device"); if (_opt.device_args.empty() == false) - msg.append( (boost::format(" with args \"%s\"") % _opt.device_args ).str() ); + msg.append((boost::format(" with args \"%s\"") % _opt.device_args).str()); msg.append("..."); print_msg(msg); } -uhd::usrp::multi_usrp::sptr -Responder::create_usrp_device() +uhd::usrp::multi_usrp::sptr Responder::create_usrp_device() { uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(_opt.device_args); usrp->set_rx_rate(_opt.sample_rate); // set the rx sample rate @@ -307,22 +314,19 @@ Responder::create_usrp_device() return usrp; } -uhd::rx_streamer::sptr -Responder::create_rx_streamer(uhd::usrp::multi_usrp::sptr usrp) +uhd::rx_streamer::sptr Responder::create_rx_streamer(uhd::usrp::multi_usrp::sptr usrp) { - uhd::stream_args_t stream_args("fc32"); //complex floats - if (_samps_per_packet > 0) - { + uhd::stream_args_t stream_args("fc32"); // complex floats + if (_samps_per_packet > 0) { stream_args.args["spp"] = str(boost::format("%d") % _samps_per_packet); } uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); - _samps_per_packet = rx_stream->get_max_num_samps(); + _samps_per_packet = rx_stream->get_max_num_samps(); return rx_stream; } -void -Responder::print_rx_stream_status() +void Responder::print_rx_stream_status() { std::string msg; msg += (boost::format("Samples per packet set to: %d\n") % _samps_per_packet).str(); @@ -332,27 +336,22 @@ Responder::print_rx_stream_status() print_msg(msg); } -uhd::tx_streamer::sptr -Responder::create_tx_streamer(uhd::usrp::multi_usrp::sptr usrp) +uhd::tx_streamer::sptr Responder::create_tx_streamer(uhd::usrp::multi_usrp::sptr usrp) { - uhd::stream_args_t tx_stream_args("fc32"); //complex floats - if (_allow_late_bursts == false) - { + uhd::stream_args_t tx_stream_args("fc32"); // complex floats + if (_allow_late_bursts == false) { tx_stream_args.args["underflow_policy"] = "next_burst"; } uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(tx_stream_args); return tx_stream; } -void -Responder::print_tx_stream_status() +void Responder::print_tx_stream_status() { std::string msg; - if (_allow_late_bursts == false) - { + if (_allow_late_bursts == false) { msg += "Underflow policy set to drop late bursts"; - } - else + } else msg += "Underflow policy set to allow late bursts"; if (_opt.skip_send) msg += "\nNOT sending bursts"; @@ -362,35 +361,36 @@ Responder::print_tx_stream_status() } // handle transmit timeouts properly -void -Responder::handle_tx_timeout(int burst, int eob) +void Responder::handle_tx_timeout(int burst, int eob) { - if(_timeout_burst_count == 0 && _timeout_eob_count == 0) - time( &_dbginfo.first_send_timeout ); + if (_timeout_burst_count == 0 && _timeout_eob_count == 0) + time(&_dbginfo.first_send_timeout); _timeout_burst_count += burst; _timeout_eob_count += eob; print_timeout_msg(); } -void -Responder::print_timeout_msg() +void Responder::print_timeout_msg() { - move(_y_delay_pos+3, _x_delay_pos); - print_msg( (boost::format("Send timeout, burst_count = %ld\teob_count = %ld\n") % _timeout_burst_count % _timeout_eob_count ).str() ); + move(_y_delay_pos + 3, _x_delay_pos); + print_msg((boost::format("Send timeout, burst_count = %ld\teob_count = %ld\n") + % _timeout_burst_count % _timeout_eob_count) + .str()); } uhd::tx_metadata_t Responder::get_tx_metadata(uhd::time_spec_t rx_time, size_t n) { uhd::tx_metadata_t tx_md; tx_md.start_of_burst = true; - tx_md.end_of_burst = false; + tx_md.end_of_burst = false; if ((_opt.skip_eob == false) && (_opt.combine_eob)) { tx_md.end_of_burst = true; } if (_no_delay == false) { tx_md.has_time_spec = true; - tx_md.time_spec = rx_time + uhd::time_spec_t(0, n, _opt.sample_rate) + uhd::time_spec_t(_delay); + tx_md.time_spec = + rx_time + uhd::time_spec_t(0, n, _opt.sample_rate) + uhd::time_spec_t(_delay); } else { tx_md.has_time_spec = false; } @@ -402,22 +402,25 @@ bool Responder::send_tx_burst(uhd::time_spec_t rx_time, size_t n) if (_opt.skip_send == true) { return false; } - //send a single packet + // send a single packet uhd::tx_metadata_t tx_md = get_tx_metadata(rx_time, n); - const size_t length_to_send = _response_length + (_opt.flush_count - (tx_md.end_of_burst ? 0 : 1)); + const size_t length_to_send = + _response_length + (_opt.flush_count - (tx_md.end_of_burst ? 0 : 1)); - size_t num_tx_samps = _tx_stream->send(_pResponse, length_to_send, tx_md, _opt.timeout); // send pulse! + size_t num_tx_samps = + _tx_stream->send(_pResponse, length_to_send, tx_md, _opt.timeout); // send pulse! if (num_tx_samps < length_to_send) { handle_tx_timeout(1, 0); } if (_opt.skip_eob == false && _opt.combine_eob == false) { tx_md.start_of_burst = false; - tx_md.end_of_burst = true; - tx_md.has_time_spec = false; + tx_md.end_of_burst = true; + tx_md.has_time_spec = false; const size_t eob_length_to_send = 1; - size_t eob_num_tx_samps = _tx_stream->send(&_pResponse[length_to_send], eob_length_to_send, tx_md); // send EOB + size_t eob_num_tx_samps = _tx_stream->send( + &_pResponse[length_to_send], eob_length_to_send, tx_md); // send EOB if (eob_num_tx_samps < eob_length_to_send) { handle_tx_timeout(0, 1); } @@ -427,61 +430,69 @@ bool Responder::send_tx_burst(uhd::time_spec_t rx_time, size_t n) } // ensure that stats_filename is not empty. -bool -Responder::set_stats_filename(string test_id) +bool Responder::set_stats_filename(string test_id) { - if (_stats_filename.empty()) - { + if (_stats_filename.empty()) { string file_friendly_test_id(test_id); boost::replace_all(file_friendly_test_id, " ", "_"); - boost::format fmt = boost::format("%slatency-stats.id_%s-rate_%i-spb_%i-spp_%i%s") % _opt.stats_filename_prefix % file_friendly_test_id % (int)_opt.sample_rate % _opt.samps_per_buff % _samps_per_packet % _opt.stats_filename_suffix; - _stats_filename = str(fmt) + ".txt"; + boost::format fmt = boost::format("%slatency-stats.id_%s-rate_%i-spb_%i-spp_%i%s") + % _opt.stats_filename_prefix % file_friendly_test_id + % (int)_opt.sample_rate % _opt.samps_per_buff + % _samps_per_packet % _opt.stats_filename_suffix; + _stats_filename = str(fmt) + ".txt"; _stats_log_filename = str(fmt) + ".log"; } return check_for_existing_results(); } // Check if results file can be overwritten -bool -Responder::check_for_existing_results() +bool Responder::check_for_existing_results() { bool ex = false; - if ((_opt.skip_if_results_exist) && (boost::filesystem::exists(_stats_filename))) - { - print_msg( (boost::format("Skipping invocation as results file already exists: %s") % _stats_filename).str() ); + if ((_opt.skip_if_results_exist) && (boost::filesystem::exists(_stats_filename))) { + print_msg((boost::format("Skipping invocation as results file already exists: %s") + % _stats_filename) + .str()); ex = true; } return ex; } // Allocate an array with a burst response -float* -Responder::alloc_response_buffer_with_data(uint64_t response_length) // flush_count, output_value, output_scale are const +float* Responder::alloc_response_buffer_with_data( + uint64_t response_length) // flush_count, output_value, output_scale are const { float* pResponse = new float[(response_length + _opt.flush_count) * 2]; for (unsigned int i = 0; i < (response_length * 2); ++i) pResponse[i] = _opt.output_value * _opt.output_scale; - for (unsigned int i = (response_length * 2); i < ((response_length + _opt.flush_count) * 2); ++i) + for (unsigned int i = (response_length * 2); + i < ((response_length + _opt.flush_count) * 2); + ++i) pResponse[i] = 0.0f; return pResponse; } // print test parameters for current delay time -void -Responder::print_formatted_delay_line(const uint64_t simulate_duration, const uint64_t old_simulate_duration, const STATS& statsPrev, const double delay, const double simulate_frequency) +void Responder::print_formatted_delay_line(const uint64_t simulate_duration, + const uint64_t old_simulate_duration, + const STATS& statsPrev, + const double delay, + const double simulate_frequency) { - if(_y_delay_pos < 0 || _x_delay_pos < 0){ // make sure it gets printed to the same position everytime + if (_y_delay_pos < 0 + || _x_delay_pos < 0) { // make sure it gets printed to the same position everytime getyx(_window, _y_delay_pos, _x_delay_pos); } double score = 0.0; if (statsPrev.detected > 0) - score = 100.0 * (double)(statsPrev.detected - statsPrev.missed) / (double)statsPrev.detected; + score = 100.0 * (double)(statsPrev.detected - statsPrev.missed) + / (double)statsPrev.detected; std::string form; boost::format fmt0("Delay now: %.6f (previous delay %.6f scored %.1f%% [%ld / %ld])"); - fmt0 % delay % statsPrev.delay % score % (statsPrev.detected - statsPrev.missed) % statsPrev.detected; + fmt0 % delay % statsPrev.delay % score % (statsPrev.detected - statsPrev.missed) + % statsPrev.detected; form += fmt0.str(); - if (old_simulate_duration != simulate_duration) - { + if (old_simulate_duration != simulate_duration) { boost::format fmt1(" [Simulation rate now: %.1f Hz (%ld samples)]"); fmt1 % simulate_frequency % simulate_duration; form = form + fmt1.str(); @@ -491,8 +502,7 @@ Responder::print_formatted_delay_line(const uint64_t simulate_duration, const ui } // print message and wait for user interaction -void -Responder::print_msg_and_wait(std::string msg) +void Responder::print_msg_and_wait(std::string msg) { msg = "\n" + msg; print_msg(msg); @@ -502,114 +512,103 @@ Responder::print_msg_and_wait(std::string msg) } // print message to ncurses window -void -Responder::print_msg(std::string msg) +void Responder::print_msg(std::string msg) { _ss << msg << endl; FLUSH_SCREEN(); } // Check if error occured during call to receive -bool -Responder::handle_rx_errors(uhd::rx_metadata_t::error_code_t err, size_t num_rx_samps) +bool Responder::handle_rx_errors( + uhd::rx_metadata_t::error_code_t err, size_t num_rx_samps) { // handle errors - if (err == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) - { - std::string msg = (boost::format("Timeout while streaming (received %ld samples)") % _num_total_samps).str(); + if (err == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) { + std::string msg = (boost::format("Timeout while streaming (received %ld samples)") + % _num_total_samps) + .str(); print_error_msg(msg); _return_code = RETCODE_RECEIVE_TIMEOUT; return true; - } - else if (err == uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET) - { - std::string msg = (boost::format("Bad packet (received %ld samples)") % _num_total_samps).str(); + } else if (err == uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET) { + std::string msg = + (boost::format("Bad packet (received %ld samples)") % _num_total_samps).str(); print_error_msg(msg); _return_code = RETCODE_BAD_PACKET; return true; - } - else if ((num_rx_samps == 0) && (err == uhd::rx_metadata_t::ERROR_CODE_NONE)) - { + } else if ((num_rx_samps == 0) && (err == uhd::rx_metadata_t::ERROR_CODE_NONE)) { print_error_msg("Received no samples"); _return_code = RETCODE_RECEIVE_FAILED; return true; - } - else if (err == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) - { + } else if (err == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) { ++_overruns; print_overrun_msg(); // update overrun info on console. - } - else if (err != uhd::rx_metadata_t::ERROR_CODE_NONE) - { - throw std::runtime_error(str(boost::format( - "Unexpected error code 0x%x" - ) % err)); + } else if (err != uhd::rx_metadata_t::ERROR_CODE_NONE) { + throw std::runtime_error(str(boost::format("Unexpected error code 0x%x") % err)); } return false; } // print overrun status message. -void -Responder::print_overrun_msg() +void Responder::print_overrun_msg() { - if (_num_total_samps > (_last_overrun_count + (uint64_t)(_opt.sample_rate * 1.0))) - { + if (_num_total_samps > (_last_overrun_count + (uint64_t)(_opt.sample_rate * 1.0))) { int y, x, y_max, x_max; getyx(_window, y, x); getmaxyx(_window, y_max, x_max); - move(y_max-1, 0); - print_msg( (boost::format("Overruns: %d") % _overruns).str() ); + move(y_max - 1, 0); + print_msg((boost::format("Overruns: %d") % _overruns).str()); move(y, x); _last_overrun_count = _num_total_samps; } } // print error message on last line of ncurses window -void -Responder::print_error_msg(std::string msg) +void Responder::print_error_msg(std::string msg) { int y, x, y_max, x_max; getyx(_window, y, x); getmaxyx(_window, y_max, x_max); - move(y_max-2, 0); + move(y_max - 2, 0); clrtoeol(); print_msg(msg); move(y, x); } // calculate simulate frequency -double -Responder::get_simulate_frequency(double delay, uint64_t response_length, uint64_t original_simulate_duration) +double Responder::get_simulate_frequency( + double delay, uint64_t response_length, uint64_t original_simulate_duration) { - double simulate_frequency = _simulate_frequency; + double simulate_frequency = _simulate_frequency; uint64_t highest_delay_samples = _opt.highest_delay_samples(delay); - if ((_opt.optimize_simulation_rate) || - ((highest_delay_samples + response_length + _opt.flush_count) > original_simulate_duration)) - { - simulate_frequency = get_max_possible_frequency(highest_delay_samples, response_length); + if ((_opt.optimize_simulation_rate) + || ((highest_delay_samples + response_length + _opt.flush_count) + > original_simulate_duration)) { + simulate_frequency = + get_max_possible_frequency(highest_delay_samples, response_length); } return simulate_frequency; } // calculate max possible simulate frequency -double -Responder::get_max_possible_frequency(uint64_t highest_delay_samples, uint64_t response_length) // only 2 args, others are all const! +double Responder::get_max_possible_frequency(uint64_t highest_delay_samples, + uint64_t response_length) // only 2 args, others are all const! { - return std::floor((double)_opt.sample_rate / (double)(highest_delay_samples + response_length + _opt.flush_count + _opt.optimize_padding)); + return std::floor((double)_opt.sample_rate + / (double)(highest_delay_samples + response_length + + _opt.flush_count + _opt.optimize_padding)); } // Check if conditions to finish test are met. -bool -Responder::test_finished(size_t success_count) +bool Responder::test_finished(size_t success_count) { - if (success_count == _opt.end_test_after_success_count) - { - print_msg( (boost::format("\nTest complete after %d successes.") % success_count).str() ); + if (success_count == _opt.end_test_after_success_count) { + print_msg( + (boost::format("\nTest complete after %d successes.") % success_count).str()); return true; } - if (((_opt.delay_min <= _opt.delay_max) && (_delay >= _opt.delay_max)) || - ((_opt.delay_min > _opt.delay_max) && (_delay <= _opt.delay_max))) - { + if (((_opt.delay_min <= _opt.delay_max) && (_delay >= _opt.delay_max)) + || ((_opt.delay_min > _opt.delay_max) && (_delay <= _opt.delay_max))) { print_msg("\nTest complete."); return true; } @@ -617,45 +616,38 @@ Responder::test_finished(size_t success_count) } // handle keyboard input in interactive mode -bool -Responder::handle_interactive_control() +bool Responder::handle_interactive_control() { std::string msg = ""; - int c = wgetch(_window); - if (c > -1) - { + int c = wgetch(_window); + if (c > -1) { // UP/DOWN Keys control delay step width - if ((c == KEY_DOWN) || (c == KEY_UP)) - { + if ((c == KEY_DOWN) || (c == KEY_UP)) { double dMag = log10(_delay_step); - int iMag = (int)floor(dMag); + int iMag = (int)floor(dMag); iMag += ((c == KEY_UP) ? 1 : -1); _delay_step = pow(10.0, iMag); - msg += (boost::format("Step: %f") % _delay_step ).str(); + msg += (boost::format("Step: %f") % _delay_step).str(); } // LEFT/RIGHT Keys control absolute delay length - if ((c == KEY_LEFT) || (c == KEY_RIGHT)) - { + if ((c == KEY_LEFT) || (c == KEY_RIGHT)) { double step = _delay_step * ((c == KEY_RIGHT) ? 1 : -1); if ((_delay + step) >= 0.0) _delay += step; msg += (boost::format("Delay: %f") % _delay).str(); } // Enable/disable fixed delay <--> best effort mode - if (c == 'd') - { + if (c == 'd') { _no_delay = !_no_delay; if (_no_delay) msg += "Delay disabled (best effort)"; else msg += (boost::format("Delay: %f") % _delay).str(); - } - else if (c == 'q') // exit test + } else if (c == 'q') // exit test { return true; // signal test to stop - } - else if (c == 'l') // change late burst policy + } else if (c == 'l') // change late burst policy { _allow_late_bursts = !_allow_late_bursts; @@ -670,16 +662,13 @@ Responder::handle_interactive_control() } // print updated interactive control value -void -Responder::print_interactive_msg(std::string msg) +void Responder::print_interactive_msg(std::string msg) { - if(msg != "") - { + if (msg != "") { // move cursor back to beginning of line int y, x; getyx(_window, y, x); - if (x > 0) - { + if (x > 0) { move(y, 0); clrtoeol(); } @@ -689,36 +678,31 @@ Responder::print_interactive_msg(std::string msg) } // check if transmit burst is late -bool -Responder::tx_burst_is_late() +bool Responder::tx_burst_is_late() { uhd::async_metadata_t async_md; - if (_usrp->get_device()->recv_async_msg(async_md, 0)) - { - if (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_TIME_ERROR) - { + if (_usrp->get_device()->recv_async_msg(async_md, 0)) { + if (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_TIME_ERROR) { return true; } } return false; } -void -Responder::create_ncurses_window() +void Responder::create_ncurses_window() { _window = initscr(); - cbreak(); // Unbuffered key input, except for signals (cf. 'raw') + cbreak(); // Unbuffered key input, except for signals (cf. 'raw') noecho(); nonl(); intrflush(_window, FALSE); - keypad(_window, TRUE); // Enable function keys, arrow keys, ... + keypad(_window, TRUE); // Enable function keys, arrow keys, ... nodelay(_window, 0); timeout(0); } // print all fixed test parameters -void -Responder::print_init_test_status() +void Responder::print_init_test_status() { // Clear the window and write new data. erase(); @@ -740,30 +724,29 @@ Responder::print_init_test_status() } // in interactive mode with second usrp sending bursts. calibrate trigger level -float -Responder::calibrate_usrp_for_test_run() +float Responder::calibrate_usrp_for_test_run() { bool calibration_finished = false; - float threshold = 0.0f; + float threshold = 0.0f; double ave_high = 0, ave_low = 0; int ave_high_count = 0, ave_low_count = 0; - bool level_calibration_stage_2 = false; // 1. stage = rough calibration ; 2. stage = fine calibration + bool level_calibration_stage_2 = + false; // 1. stage = rough calibration ; 2. stage = fine calibration - std::vector<std::complex<float> > buff(_opt.samps_per_buff); - while (not s_stop_signal_called && !calibration_finished && _return_code == RETCODE_OK) - { + std::vector<std::complex<float>> buff(_opt.samps_per_buff); + while ( + not s_stop_signal_called && !calibration_finished && _return_code == RETCODE_OK) { uhd::rx_metadata_t rx_md; - size_t num_rx_samps = _rx_stream->recv(&buff.front(), buff.size(), rx_md, _opt.timeout); + size_t num_rx_samps = + _rx_stream->recv(&buff.front(), buff.size(), rx_md, _opt.timeout); // handle errors - if(handle_rx_errors(rx_md.error_code, num_rx_samps) ) - { + if (handle_rx_errors(rx_md.error_code, num_rx_samps)) { break; } // Wait for USRP for DC offset calibration - if (_dc_offset_countdown > 0) - { + if (_dc_offset_countdown > 0) { _dc_offset_countdown -= (int64_t)num_rx_samps; if (_dc_offset_countdown > 0) continue; @@ -772,8 +755,7 @@ Responder::calibrate_usrp_for_test_run() } // Wait for certain time to minimize POWER UP effects - if (_init_delay_count > 0) - { + if (_init_delay_count > 0) { _init_delay_count -= (int64_t)num_rx_samps; if (_init_delay_count > 0) continue; @@ -782,48 +764,35 @@ Responder::calibrate_usrp_for_test_run() //////////////////////////////////////////////////////////// // detect falling edges and calibrate detection values - if (_level_calibration_countdown > 0) - { - if (level_calibration_stage_2 == false) - { + if (_level_calibration_countdown > 0) { + if (level_calibration_stage_2 == false) { float average = 0.0f; for (size_t n = 0; n < num_rx_samps; n++) average += buff[n].real() * _opt.invert; average /= (float)num_rx_samps; - if (ave_low_count == 0) - { + if (ave_low_count == 0) { ave_low = average; ++ave_low_count; - } - else if (average < ave_low) - { + } else if (average < ave_low) { ave_low = average; ++ave_low_count; } - if (ave_high_count == 0) - { + if (ave_high_count == 0) { ave_high = average; ++ave_high_count; - } - else if (average > ave_high) - { + } else if (average > ave_high) { ave_high = average; ++ave_high_count; } - } - else { - for (size_t n = 0; n < num_rx_samps; n++) - { + } else { + for (size_t n = 0; n < num_rx_samps; n++) { float f = buff[n].real() * _opt.invert; - if (f >= threshold) - { + if (f >= threshold) { ave_high += f; ave_high_count++; - } - else - { + } else { ave_low += f; ave_low_count++; } @@ -832,43 +801,51 @@ Responder::calibrate_usrp_for_test_run() _level_calibration_countdown -= (int64_t)num_rx_samps; - if (_level_calibration_countdown <= 0) - { - if (level_calibration_stage_2 == false) - { - level_calibration_stage_2 = true; + if (_level_calibration_countdown <= 0) { + if (level_calibration_stage_2 == false) { + level_calibration_stage_2 = true; _level_calibration_countdown = _opt.level_calibration_count(); - threshold = ave_low + ((ave_high - ave_low) / 2.0); - print_msg( (boost::format("Phase #1: Ave low: %.3f (#%d), ave high: %.3f (#%d), threshold: %.3f") % ave_low % ave_low_count % ave_high % ave_high_count % threshold).str() ); + threshold = ave_low + ((ave_high - ave_low) / 2.0); + print_msg((boost::format("Phase #1: Ave low: %.3f (#%d), ave high: " + "%.3f (#%d), threshold: %.3f") + % ave_low % ave_low_count % ave_high % ave_high_count + % threshold) + .str()); ave_low_count = ave_high_count = 0; ave_low = ave_high = 0.0f; continue; - } - else - { + } else { ave_low /= (double)ave_low_count; ave_high /= (double)ave_high_count; threshold = ave_low + ((ave_high - ave_low) * _opt.trigger_level); - print_msg( (boost::format("Phase #2: Ave low: %.3f (#%d), ave high: %.3f (#%d), threshold: %.3f\n") % ave_low % ave_low_count % ave_high % ave_high_count % threshold).str() ); - - _stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; + print_msg((boost::format("Phase #2: Ave low: %.3f (#%d), ave high: " + "%.3f (#%d), threshold: %.3f\n") + % ave_low % ave_low_count % ave_high % ave_high_count + % threshold) + .str()); + + _stream_cmd.stream_mode = + uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; _stream_cmd.stream_now = true; _usrp->issue_stream_cmd(_stream_cmd); double diff = std::abs(ave_high - ave_low); - if (diff < _opt.pulse_detection_threshold) - { + if (diff < _opt.pulse_detection_threshold) { _return_code = RETCODE_BAD_ARGS; - print_error_msg( (boost::format("Did not detect any pulses (difference %.6f < detection threshold %.6f)") % diff % _opt.pulse_detection_threshold).str() ); + print_error_msg( + (boost::format("Did not detect any pulses (difference %.6f < " + "detection threshold %.6f)") + % diff % _opt.pulse_detection_threshold) + .str()); break; } - _stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS; + _stream_cmd.stream_mode = + uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS; _stream_cmd.stream_now = true; _usrp->issue_stream_cmd(_stream_cmd); } - } - else + } else continue; } // calibration finished calibration_finished = true; @@ -877,86 +854,82 @@ Responder::calibrate_usrp_for_test_run() } // try to stop USRP properly after tests -void -Responder::stop_usrp_stream() +void Responder::stop_usrp_stream() { - try - { - if (_usrp) - { + try { + if (_usrp) { _stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; - _stream_cmd.stream_now = true; + _stream_cmd.stream_now = true; _usrp->issue_stream_cmd(_stream_cmd); } - } - catch (...) - { + } catch (...) { // } } // after each delay length update test parameters and print them -void -Responder::update_and_print_parameters(const STATS& statsPrev, const double delay) +void Responder::update_and_print_parameters(const STATS& statsPrev, const double delay) { uint64_t old_simulate_duration = _simulate_duration; - _simulate_frequency = get_simulate_frequency(delay, _response_length, _original_simulate_duration); + _simulate_frequency = + get_simulate_frequency(delay, _response_length, _original_simulate_duration); _simulate_duration = _opt.simulate_duration(_simulate_frequency); - print_formatted_delay_line(_simulate_duration, old_simulate_duration, statsPrev, delay, _simulate_frequency); + print_formatted_delay_line( + _simulate_duration, old_simulate_duration, statsPrev, delay, _simulate_frequency); _timeout_burst_count = 0; - _timeout_eob_count = 0; + _timeout_eob_count = 0; } // detect or simulate burst level. -bool -Responder::get_new_state(uint64_t total_samps, uint64_t simulate_duration, float val, float threshold) +bool Responder::get_new_state( + uint64_t total_samps, uint64_t simulate_duration, float val, float threshold) { bool new_state = false; if (simulate_duration > 0) // only simulated input bursts! new_state = (((total_samps) % simulate_duration) == 0); else - new_state = (val >= threshold); // TODO: Just measure difference in fall + new_state = (val >= threshold); // TODO: Just measure difference in fall return new_state; } // detect a pulse, respond to it and count number of pulses. // statsCurrent holds parameters. -uint64_t -Responder::detect_respond_pulse_count(STATS &statsCurrent, std::vector<std::complex<float> > &buff, uint64_t trigger_count, size_t num_rx_samps, float threshold, uhd::time_spec_t rx_time) +uint64_t Responder::detect_respond_pulse_count(STATS& statsCurrent, + std::vector<std::complex<float>>& buff, + uint64_t trigger_count, + size_t num_rx_samps, + float threshold, + uhd::time_spec_t rx_time) { // buff, threshold bool input_state = false; - for (size_t n = 0; n < num_rx_samps; n++) - { + for (size_t n = 0; n < num_rx_samps; n++) { float f = buff[n].real() * _opt.invert; - bool new_state = get_new_state(_num_total_samps + n, _simulate_duration, f, threshold); + bool new_state = + get_new_state(_num_total_samps + n, _simulate_duration, f, threshold); if ((new_state == false) && (input_state)) // == falling_edge { trigger_count++; statsCurrent.detected++; - if ((_opt.test_iterations > 0) - && (_opt.skip_iterations > 0) - && (statsCurrent.skipped == 0) - && (_opt.skip_iterations == statsCurrent.detected)) - { + if ((_opt.test_iterations > 0) && (_opt.skip_iterations > 0) + && (statsCurrent.skipped == 0) + && (_opt.skip_iterations == statsCurrent.detected)) { memset(&statsCurrent, 0x00, sizeof(STATS)); - statsCurrent.delay = _delay; + statsCurrent.delay = _delay; statsCurrent.detected = 1; - statsCurrent.skipped = _opt.skip_iterations; + statsCurrent.skipped = _opt.skip_iterations; trigger_count = 1; } - if( !send_tx_burst(rx_time, n) ) - { + if (!send_tx_burst(rx_time, n)) { statsCurrent.missed++; } - if(tx_burst_is_late() ) - { + if (tx_burst_is_late()) { statsCurrent.missed++; } } @@ -967,34 +940,33 @@ Responder::detect_respond_pulse_count(STATS &statsCurrent, std::vector<std::comp } // this is the actual "work" function. All the fun happens here -void -Responder::run_test(float threshold) +void Responder::run_test(float threshold) { STATS statsCurrent; //, statsPrev; memset(&statsCurrent, 0x00, sizeof(STATS)); - if (_opt.test_iterations > 0) - { + if (_opt.test_iterations > 0) { update_and_print_parameters(statsCurrent, _delay); statsCurrent.delay = _opt.delay_min; } /////////////////////////////////////////////////////////////////////////// - uint64_t trigger_count = 0; - size_t success_count = 0; + uint64_t trigger_count = 0; + size_t success_count = 0; uint64_t num_total_samps_test = 0; - std::vector<std::complex<float> > buff(_opt.samps_per_buff); - while (not s_stop_signal_called && _return_code == RETCODE_OK) - { + std::vector<std::complex<float>> buff(_opt.samps_per_buff); + while (not s_stop_signal_called && _return_code == RETCODE_OK) { // get samples from rx stream. uhd::rx_metadata_t rx_md; - size_t num_rx_samps = _rx_stream->recv(&buff.front(), buff.size(), rx_md, _opt.timeout); + size_t num_rx_samps = + _rx_stream->recv(&buff.front(), buff.size(), rx_md, _opt.timeout); // handle errors - if(handle_rx_errors(rx_md.error_code, num_rx_samps) ) - { + if (handle_rx_errors(rx_md.error_code, num_rx_samps)) { break; } - // detect falling edges, send respond pulse and check if response could be sent in time - trigger_count = detect_respond_pulse_count(statsCurrent, buff, trigger_count, num_rx_samps, threshold, rx_md.time_spec); + // detect falling edges, send respond pulse and check if response could be sent in + // time + trigger_count = detect_respond_pulse_count( + statsCurrent, buff, trigger_count, num_rx_samps, threshold, rx_md.time_spec); // increase counters for single test and overall test samples count. _num_total_samps += num_rx_samps; @@ -1003,40 +975,47 @@ Responder::run_test(float threshold) // control section for interactive mode if (_opt.test_iterations == 0) // == "interactive' { - if(handle_interactive_control() ) + if (handle_interactive_control()) break; } // control section for test mode if (_opt.test_iterations > 0) // == test mode / batch-mode { - int step_return = test_step_finished(trigger_count, num_total_samps_test, statsCurrent, success_count); - if(step_return == -2) // == test is finished with all desired delay steps + int step_return = test_step_finished( + trigger_count, num_total_samps_test, statsCurrent, success_count); + if (step_return == -2) // == test is finished with all desired delay steps break; - else if(step_return == -1) // just continue test + else if (step_return == -1) // just continue test continue; else // test with one delay is finished { - success_count = (size_t) step_return; - trigger_count = 0; + success_count = (size_t)step_return; + trigger_count = 0; num_total_samps_test = 0; - memset(&statsCurrent, 0x00, sizeof(STATS)); // reset current stats for next test iteration + memset(&statsCurrent, + 0x00, + sizeof(STATS)); // reset current stats for next test iteration statsCurrent.delay = _delay; } } // end test mode control section - }// exit outer loop after stop signal is called, test is finished or other break condition is met + } // exit outer loop after stop signal is called, test is finished or other break + // condition is met if (s_stop_signal_called) _return_code = RETCODE_MANUAL_ABORT; } // check if test with one specific delay is finished -int -Responder::test_step_finished(uint64_t trigger_count, uint64_t num_total_samps_test, STATS statsCurrent, size_t success_count) +int Responder::test_step_finished(uint64_t trigger_count, + uint64_t num_total_samps_test, + STATS statsCurrent, + size_t success_count) { - if ( ((_opt.test_iterations_is_sample_count == false) && (trigger_count >= _opt.test_iterations)) || - ((_opt.test_iterations_is_sample_count) && (num_total_samps_test > _opt.test_iterations)) ) - { + if (((_opt.test_iterations_is_sample_count == false) + && (trigger_count >= _opt.test_iterations)) + || ((_opt.test_iterations_is_sample_count) + && (num_total_samps_test > _opt.test_iterations))) { add_stats_to_results(statsCurrent, _delay); if (statsCurrent.missed == 0) // == NO late bursts @@ -1044,7 +1023,7 @@ Responder::test_step_finished(uint64_t trigger_count, uint64_t num_total_samps_t else success_count = 0; - if(test_finished(success_count) ) + if (test_finished(success_count)) return -2; // test is completely finished _delay += _delay_step; // increase delay by one step @@ -1056,58 +1035,50 @@ Responder::test_step_finished(uint64_t trigger_count, uint64_t num_total_samps_t } // save test results -void -Responder::add_stats_to_results(STATS statsCurrent, double delay) +void Responder::add_stats_to_results(STATS statsCurrent, double delay) { - _max_success = max(_max_success, (statsCurrent.detected - statsCurrent.missed)); // > 0 --> save results - uint64_t key = (uint64_t)(delay * 1e6); + _max_success = max(_max_success, + (statsCurrent.detected - statsCurrent.missed)); // > 0 --> save results + uint64_t key = (uint64_t)(delay * 1e6); _mapStats[key] = statsCurrent; } // run tests and handle errors -int -Responder::run() +int Responder::run() { if (_return_code != RETCODE_OK) return _return_code; if (_opt.pause) print_msg_and_wait("Press any key to begin..."); - time( &_dbginfo.start_time_test ); + time(&_dbginfo.start_time_test); // Put some info about the test on the console print_init_test_status(); try { - //setup streaming + // setup streaming _stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS; - _stream_cmd.stream_now = true; + _stream_cmd.stream_now = true; _usrp->issue_stream_cmd(_stream_cmd); - if( !_opt.batch_mode ){ + if (!_opt.batch_mode) { float threshold = calibrate_usrp_for_test_run(); - if (_return_code != RETCODE_OK) - { + if (_return_code != RETCODE_OK) { return _return_code; } run_test(threshold); - } - else - { + } else { run_test(); } - } - catch (const std::runtime_error& e) - { - print_msg(e.what() ); + } catch (const std::runtime_error& e) { + print_msg(e.what()); _return_code = RETCODE_RUNTIME_ERROR; - } - catch (...) - { + } catch (...) { print_msg("Unhandled exception"); _return_code = RETCODE_UNKNOWN_EXCEPTION; } stop_usrp_stream(); - time( &_dbginfo.end_time_test ); + time(&_dbginfo.end_time_test); return (_return_code < 0 ? _return_code : _overruns); } @@ -1116,8 +1087,7 @@ Responder::run() */ // This method should print statistics after ncurses endwin. -void -Responder::print_final_statistics() +void Responder::print_final_statistics() { cout << boost::format("Received %ld samples during test run") % _num_total_samps; if (_overruns > 0) @@ -1126,29 +1096,30 @@ Responder::print_final_statistics() } // safe test results to a log file if enabled -void -Responder::write_log_file() +void Responder::write_log_file() { - try - { - if(_opt.log_file){ + try { + if (_opt.log_file) { std::map<std::string, std::string> hw_info = get_hw_info(); ofstream logs(_stats_log_filename.c_str()); logs << boost::format("title=%s") % _opt.test_title << endl; - logs << boost::format("device=%s") % _usrp->get_mboard_name() << endl; + logs << boost::format("device=%s") % _usrp->get_mboard_name() << endl; logs << boost::format("device_args=%s") % _opt.device_args << endl; - logs << boost::format("type=%s") % hw_info["type"] << endl; - if (hw_info.size() > 0) - { - logs << boost::format("usrp_addr=%s") % hw_info["usrp_addr"] << endl; - logs << boost::format("usrp_name=%s") % hw_info["name"] << endl; - logs << boost::format("serial=%s") % hw_info["serial"] << endl; - logs << boost::format("host_interface=%s") % hw_info["interface"] << endl; - logs << boost::format("host_addr=%s") % hw_info["host_addr"] << endl; - logs << boost::format("host_mac=%s") % hw_info["mac"] << endl; - logs << boost::format("host_vendor=%s (id=%s)") % hw_info["vendor"] % hw_info["vendor_id"] << endl; - logs << boost::format("host_device=%s (id=%s)") % hw_info["device"] % hw_info["device_id"] << endl; + logs << boost::format("type=%s") % hw_info["type"] << endl; + if (hw_info.size() > 0) { + logs << boost::format("usrp_addr=%s") % hw_info["usrp_addr"] << endl; + logs << boost::format("usrp_name=%s") % hw_info["name"] << endl; + logs << boost::format("serial=%s") % hw_info["serial"] << endl; + logs << boost::format("host_interface=%s") % hw_info["interface"] << endl; + logs << boost::format("host_addr=%s") % hw_info["host_addr"] << endl; + logs << boost::format("host_mac=%s") % hw_info["mac"] << endl; + logs << boost::format("host_vendor=%s (id=%s)") % hw_info["vendor"] + % hw_info["vendor_id"] + << endl; + logs << boost::format("host_device=%s (id=%s)") % hw_info["device"] + % hw_info["device_id"] + << endl; } logs << boost::format("sample_rate=%f") % _opt.sample_rate << endl; logs << boost::format("samps_per_buff=%i") % _opt.samps_per_buff << endl; @@ -1158,97 +1129,113 @@ Responder::write_log_file() logs << boost::format("delay_step=%f") % _delay_step << endl; logs << boost::format("delay=%f") % _delay << endl; logs << boost::format("init_delay=%f") % _opt.init_delay << endl; - logs << boost::format("response_duration=%f") % _opt.response_duration << endl; + logs << boost::format("response_duration=%f") % _opt.response_duration + << endl; logs << boost::format("response_length=%ld") % _response_length << endl; logs << boost::format("timeout=%f") % _opt.timeout << endl; - logs << boost::format("timeout_burst_count=%ld") % _timeout_burst_count << endl; + logs << boost::format("timeout_burst_count=%ld") % _timeout_burst_count + << endl; logs << boost::format("timeout_eob_count=%f") % _timeout_eob_count << endl; - logs << boost::format("allow_late_bursts=%s") % (_allow_late_bursts ? "yes" : "no") << endl; + logs << boost::format("allow_late_bursts=%s") + % (_allow_late_bursts ? "yes" : "no") + << endl; logs << boost::format("skip_eob=%s") % (_opt.skip_eob ? "yes" : "no") << endl; - logs << boost::format("combine_eob=%s") % (_opt.combine_eob ? "yes" : "no") << endl; - logs << boost::format("skip_send=%s") % (_opt.skip_send ? "yes" : "no") << endl; + logs << boost::format("combine_eob=%s") % (_opt.combine_eob ? "yes" : "no") + << endl; + logs << boost::format("skip_send=%s") % (_opt.skip_send ? "yes" : "no") + << endl; logs << boost::format("no_delay=%s") % (_no_delay ? "yes" : "no") << endl; logs << boost::format("simulate_frequency=%f") % _simulate_frequency << endl; logs << boost::format("simulate_duration=%ld") % _simulate_duration << endl; - logs << boost::format("original_simulate_duration=%ld") % _original_simulate_duration << endl; + logs << boost::format("original_simulate_duration=%ld") + % _original_simulate_duration + << endl; logs << boost::format("realtime=%s") % (_opt.realtime ? "yes" : "no") << endl; logs << boost::format("rt_priority=%f") % _opt.rt_priority << endl; logs << boost::format("test_iterations=%ld") % _opt.test_iterations << endl; - logs << boost::format("end_test_after_success_count=%i") % _opt.end_test_after_success_count << endl; + logs << boost::format("end_test_after_success_count=%i") + % _opt.end_test_after_success_count + << endl; logs << boost::format("skip_iterations=%i") % _opt.skip_iterations << endl; logs << boost::format("overruns=%i") % _overruns << endl; logs << boost::format("num_total_samps=%ld") % _num_total_samps << endl; - logs << boost::format("return_code=%i\t(%s)") % _return_code % enum2str(_return_code) << endl; + logs << boost::format("return_code=%i\t(%s)") % _return_code + % enum2str(_return_code) + << endl; logs << endl; write_debug_info(logs); - } - } - catch(...) - { + } catch (...) { cerr << "Failed to write log file to: " << _stats_log_filename << endl; } } // write debug info to log file -void -Responder::write_debug_info(ofstream& logs) +void Responder::write_debug_info(ofstream& logs) { logs << endl << "%% DEBUG INFO %%" << endl; - logs << boost::format("dbg_time_start=%s") % get_gmtime_string(_dbginfo.start_time) << endl; - logs << boost::format("dbg_time_end=%s") % get_gmtime_string(_dbginfo.end_time) << endl; - logs << boost::format("dbg_time_duration=%d") % difftime( _dbginfo.end_time, _dbginfo.start_time ) << endl; - logs << boost::format("dbg_time_start_test=%s") % get_gmtime_string(_dbginfo.start_time_test) << endl; - logs << boost::format("dbg_time_end_test=%s") % get_gmtime_string(_dbginfo.end_time_test) << endl; - logs << boost::format("dbg_time_duration_test=%d") % difftime( _dbginfo.end_time_test, _dbginfo.start_time_test ) << endl; - logs << boost::format("dbg_time_first_send_timeout=%s") % get_gmtime_string(_dbginfo.first_send_timeout) << endl; + logs << boost::format("dbg_time_start=%s") % get_gmtime_string(_dbginfo.start_time) + << endl; + logs << boost::format("dbg_time_end=%s") % get_gmtime_string(_dbginfo.end_time) + << endl; + logs << boost::format("dbg_time_duration=%d") + % difftime(_dbginfo.end_time, _dbginfo.start_time) + << endl; + logs << boost::format("dbg_time_start_test=%s") + % get_gmtime_string(_dbginfo.start_time_test) + << endl; + logs << boost::format("dbg_time_end_test=%s") + % get_gmtime_string(_dbginfo.end_time_test) + << endl; + logs << boost::format("dbg_time_duration_test=%d") + % difftime(_dbginfo.end_time_test, _dbginfo.start_time_test) + << endl; + logs << boost::format("dbg_time_first_send_timeout=%s") + % get_gmtime_string(_dbginfo.first_send_timeout) + << endl; } // convert a time string to desired format -std::string -Responder::get_gmtime_string(time_t time) +std::string Responder::get_gmtime_string(time_t time) { tm* ftm; - ftm = gmtime( &time ); + ftm = gmtime(&time); std::string strtime; - strtime.append( (boost::format("%i") % (ftm->tm_year+1900) ).str() ); - strtime.append( (boost::format("-%02i") % ftm->tm_mon).str() ); - strtime.append( (boost::format("-%02i") % ftm->tm_mday).str() ); - strtime.append( (boost::format("-%02i") % ((ftm->tm_hour)) ).str() ); - strtime.append( (boost::format(":%02i") % ftm->tm_min).str() ); - strtime.append( (boost::format(":%02i") % ftm->tm_sec).str() ); + strtime.append((boost::format("%i") % (ftm->tm_year + 1900)).str()); + strtime.append((boost::format("-%02i") % ftm->tm_mon).str()); + strtime.append((boost::format("-%02i") % ftm->tm_mday).str()); + strtime.append((boost::format("-%02i") % ((ftm->tm_hour))).str()); + strtime.append((boost::format(":%02i") % ftm->tm_min).str()); + strtime.append((boost::format(":%02i") % ftm->tm_sec).str()); return strtime; } // read hardware info from file if available to include it in log file -std::map<std::string, std::string> -Responder::get_hw_info() +std::map<std::string, std::string> Responder::get_hw_info() { std::map<std::string, std::string> result; - std::vector<std::map<std::string,std::string> > eths = read_eth_info(); - if(eths.empty()){ + std::vector<std::map<std::string, std::string>> eths = read_eth_info(); + if (eths.empty()) { return result; } uhd::device_addr_t usrp_info = get_usrp_info(); - std::string uaddr = get_ip_subnet_addr(usrp_info["addr"]); + std::string uaddr = get_ip_subnet_addr(usrp_info["addr"]); - for(unsigned int i = 0 ; i < eths.size() ; i++ ) - { - if(get_ip_subnet_addr(eths[i]["addr"]) == uaddr) - { - result["type"] = usrp_info["type"]; + for (unsigned int i = 0; i < eths.size(); i++) { + if (get_ip_subnet_addr(eths[i]["addr"]) == uaddr) { + result["type"] = usrp_info["type"]; result["usrp_addr"] = usrp_info["addr"]; - result["name"] = usrp_info["name"]; - result["serial"] = usrp_info["serial"]; + result["name"] = usrp_info["name"]; + result["serial"] = usrp_info["serial"]; result["interface"] = eths[i]["interface"]; result["host_addr"] = eths[i]["addr"]; - result["mac"] = eths[i]["mac"]; - result["vendor"] = eths[i]["vendor"]; + result["mac"] = eths[i]["mac"]; + result["vendor"] = eths[i]["vendor"]; result["vendor_id"] = eths[i]["vendor_id"]; - result["device"] = eths[i]["device"]; + result["device"] = eths[i]["device"]; result["device_id"] = eths[i]["device_id"]; break; // Use first item found. Imitate device discovery. } @@ -1258,138 +1245,124 @@ Responder::get_hw_info() } // subnet used to identify used network interface -std::string -Responder::get_ip_subnet_addr(std::string ip) +std::string Responder::get_ip_subnet_addr(std::string ip) { return ip.substr(0, ip.rfind(".") + 1); } // get network interface info from file (should include all available interfaces) -std::vector<std::map<std::string,std::string> > -Responder::read_eth_info() +std::vector<std::map<std::string, std::string>> Responder::read_eth_info() { const std::string eth_file(_eth_file); - std::vector<std::map<std::string,std::string> > eths; - try - { + std::vector<std::map<std::string, std::string>> eths; + try { ifstream eth_info(eth_file.c_str()); - if(!eth_info.is_open()){ + if (!eth_info.is_open()) { return eths; } const int len = 256; char cline[len]; - for(; !eth_info.eof() ;) - { + for (; !eth_info.eof();) { eth_info.getline(cline, len); std::string line(cline); - if(line.find("## ETH Interface") != std::string::npos) - { + if (line.find("## ETH Interface") != std::string::npos) { eth_info.getline(cline, len); std::string eth(cline); -// cout << "interface=" << eth << endl; - std::map<std::string,std::string> iface; + // cout << "interface=" << eth << endl; + std::map<std::string, std::string> iface; iface["interface"] = eth; eths.push_back(iface); } const std::string ipstr("\tip "); - if(line.find(ipstr) != std::string::npos) - { - std::string ip( line.replace(line.begin(), line.begin()+ipstr.length(), "") ); -// cout << "ip=" << ip << endl; + if (line.find(ipstr) != std::string::npos) { + std::string ip( + line.replace(line.begin(), line.begin() + ipstr.length(), "")); + // cout << "ip=" << ip << endl; eths.back()["addr"] = ip; } const std::string macstr("\tmac "); - if(line.find(macstr) != std::string::npos) - { - std::string mac( line.replace(line.begin(), line.begin()+macstr.length(), "") ); -// cout << "mac=" << mac << endl; + if (line.find(macstr) != std::string::npos) { + std::string mac( + line.replace(line.begin(), line.begin() + macstr.length(), "")); + // cout << "mac=" << mac << endl; eths.back()["mac"] = mac; } const std::string vstr("\t\tvendor "); - if(line.find(vstr) != std::string::npos) - { - std::string vendor( line.replace(line.begin(), line.begin()+vstr.length(), "") ); - std::string vid( vendor.substr(0,6) ); + if (line.find(vstr) != std::string::npos) { + std::string vendor( + line.replace(line.begin(), line.begin() + vstr.length(), "")); + std::string vid(vendor.substr(0, 6)); vendor.replace(0, 7, ""); -// cout << "id=" << vid << endl; -// cout << "vendor=" << vendor << endl; - eths.back()["vendor"] = vendor; + // cout << "id=" << vid << endl; + // cout << "vendor=" << vendor << endl; + eths.back()["vendor"] = vendor; eths.back()["vendor_id"] = vid; } const std::string dstr("\t\tdevice "); - if(line.find(dstr) != std::string::npos) - { - std::string device( line.replace(line.begin(), line.begin()+dstr.length(), "") ); - std::string did( device.substr(0,6) ); + if (line.find(dstr) != std::string::npos) { + std::string device( + line.replace(line.begin(), line.begin() + dstr.length(), "")); + std::string did(device.substr(0, 6)); device.replace(0, 7, ""); -// cout << "id=" << did << endl; -// cout << "device=" << device << endl; - eths.back()["device"] = device; + // cout << "id=" << did << endl; + // cout << "device=" << device << endl; + eths.back()["device"] = device; eths.back()["device_id"] = did; } } - } - catch(...) - { + } catch (...) { // nothing in yet } return eths; } // get info on used USRP -uhd::device_addr_t -Responder::get_usrp_info() +uhd::device_addr_t Responder::get_usrp_info() { uhd::device_addrs_t device_addrs = uhd::device::find(_opt.device_args); - uhd::device_addr_t device_addr = device_addrs[0]; + uhd::device_addr_t device_addr = device_addrs[0]; return device_addr; } // write statistics of test run to file -void -Responder::write_statistics_to_file(StatsMap mapStats) +void Responder::write_statistics_to_file(StatsMap mapStats) { - try - { + try { ofstream results(_stats_filename.c_str()); - for (StatsMap::iterator it = mapStats.begin(); it != mapStats.end(); ++it) - { + for (StatsMap::iterator it = mapStats.begin(); it != mapStats.end(); ++it) { STATS& stats = it->second; - double d = 0.0; + double d = 0.0; if (stats.detected > 0) d = 1.0 - ((double)stats.missed / (double)stats.detected); - cout << "\t" << setprecision(6) << stats.delay << "\t\t" << setprecision(6) << d << endl; + cout << "\t" << setprecision(6) << stats.delay << "\t\t" << setprecision(6) + << d << endl; - results << (stats.delay * _opt.time_mul) << " " << setprecision(6) << d << endl; + results << (stats.delay * _opt.time_mul) << " " << setprecision(6) << d + << endl; } cout << "Statistics written to: " << _stats_filename << endl; - } - catch (...) - { + } catch (...) { cout << "Failed to write statistics to: " << _stats_filename << endl; } } // make sure write files is intended -void -Responder::safe_write_statistics_to_file(StatsMap mapStats, uint64_t max_success, int return_code) +void Responder::safe_write_statistics_to_file( + StatsMap mapStats, uint64_t max_success, int return_code) { - if ((_opt.test_iterations > 0) && (_stats_filename.empty() == false) && (_opt.no_stats_file == false)) - { - if (mapStats.empty()) - { + if ((_opt.test_iterations > 0) && (_stats_filename.empty() == false) + && (_opt.no_stats_file == false)) { + if (mapStats.empty()) { cout << "No results to output (not writing statistics file)" << endl; - } - else if ((max_success == 0) && (return_code == RETCODE_MANUAL_ABORT)) - { - cout << "Aborted before a single successful timed burst (not writing statistics file)" << endl; - } - else - { + } else if ((max_success == 0) && (return_code == RETCODE_MANUAL_ABORT)) { + cout << "Aborted before a single successful timed burst (not writing " + "statistics file)" + << endl; + } else { write_statistics_to_file(mapStats); } write_log_file(); @@ -1400,10 +1373,10 @@ Responder::safe_write_statistics_to_file(StatsMap mapStats, uint64_t max_success Responder::~Responder() { endwin(); - if(_pResponse != NULL){ + if (_pResponse != NULL) { delete[] _pResponse; } - time( &_dbginfo.end_time ); + time(&_dbginfo.end_time); // Print final info about test run print_final_statistics(); // check conditions and write statistics to file @@ -1412,21 +1385,27 @@ Responder::~Responder() } // make test output more helpful -std::string -Responder::enum2str(int return_code) +std::string Responder::enum2str(int return_code) { - switch(return_code) - { - case RETCODE_OK: return "OK"; - case RETCODE_BAD_ARGS: return "BAD_ARGS"; - case RETCODE_RUNTIME_ERROR: return "RUNTIME_ERROR"; - case RETCODE_UNKNOWN_EXCEPTION: return "UNKNOWN_EXCEPTION"; - case RETCODE_RECEIVE_TIMEOUT: return "RECEIVE_TIMEOUT"; - case RETCODE_RECEIVE_FAILED: return "RECEIVE_FAILED"; - case RETCODE_MANUAL_ABORT: return "MANUAL_ABORT"; - case RETCODE_BAD_PACKET: return "BAD_PACKET"; - case RETCODE_OVERFLOW: return "OVERFLOW"; + switch (return_code) { + case RETCODE_OK: + return "OK"; + case RETCODE_BAD_ARGS: + return "BAD_ARGS"; + case RETCODE_RUNTIME_ERROR: + return "RUNTIME_ERROR"; + case RETCODE_UNKNOWN_EXCEPTION: + return "UNKNOWN_EXCEPTION"; + case RETCODE_RECEIVE_TIMEOUT: + return "RECEIVE_TIMEOUT"; + case RETCODE_RECEIVE_FAILED: + return "RECEIVE_FAILED"; + case RETCODE_MANUAL_ABORT: + return "MANUAL_ABORT"; + case RETCODE_BAD_PACKET: + return "BAD_PACKET"; + case RETCODE_OVERFLOW: + return "OVERFLOW"; } return "UNKNOWN"; } - diff --git a/host/utils/latency/responder.cpp b/host/utils/latency/responder.cpp index 6216f15e6..fd47ad085 100644 --- a/host/utils/latency/responder.cpp +++ b/host/utils/latency/responder.cpp @@ -5,16 +5,15 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include <boost/program_options.hpp> #include <uhd/utils/safe_main.hpp> #include <Responder.hpp> +#include <boost/program_options.hpp> namespace po = boost::program_options; static Responder::Options prog; -po::options_description -get_program_options_description() +po::options_description get_program_options_description() { po::options_description desc("Allowed options"); // clang-format off @@ -71,41 +70,40 @@ get_program_options_description() return desc; } -void -read_program_options(po::variables_map vm) +void read_program_options(po::variables_map vm) { // read out given options prog.realtime = (vm.count("no-realtime") == 0); prog.delay_step = std::abs(prog.delay_step); - if (prog.delay_min > prog.delay_max) - { + if (prog.delay_min > prog.delay_max) { prog.delay_step *= -1; } - prog.allow_late_bursts = (vm.count("allow-late") > 0); + prog.allow_late_bursts = (vm.count("allow-late") > 0); prog.test_iterations_is_sample_count = (vm.count("test-duration") > 0); - prog.invert = ((vm.count("invert") > 0) ? -1.0f : 1.0f); - prog.output_value = ((vm.count("invert-output") > 0) ? -1.0f : 1.0f); - prog.skip_eob = (vm.count("skip-eob") > 0); - prog.no_delay = (vm.count("no-delay") > 0); - prog.adjust_simulation_rate = (vm.count("adjust-simulation-rate") > 0); + prog.invert = ((vm.count("invert") > 0) ? -1.0f : 1.0f); + prog.output_value = ((vm.count("invert-output") > 0) ? -1.0f : 1.0f); + prog.skip_eob = (vm.count("skip-eob") > 0); + prog.no_delay = (vm.count("no-delay") > 0); + prog.adjust_simulation_rate = (vm.count("adjust-simulation-rate") > 0); prog.optimize_simulation_rate = (vm.count("optimize-simulation-rate") > 0); - prog.no_stats_file = (vm.count("no-stats-file") > 0); - prog.log_file = (vm.count("log-file") > 0); - prog.batch_mode = (vm.count("batch-mode") > 0); - prog.skip_if_results_exist = (vm.count("skip-if-exists") > 0); - prog.skip_send = (vm.count("disable-send") > 0); - prog.combine_eob = (vm.count("combine-eob") > 0); - prog.pause = (vm.count("pause") > 0); - prog.ignore_simulation_check = vm.count("ignore-simulation-check"); + prog.no_stats_file = (vm.count("no-stats-file") > 0); + prog.log_file = (vm.count("log-file") > 0); + prog.batch_mode = (vm.count("batch-mode") > 0); + prog.skip_if_results_exist = (vm.count("skip-if-exists") > 0); + prog.skip_send = (vm.count("disable-send") > 0); + prog.combine_eob = (vm.count("combine-eob") > 0); + prog.pause = (vm.count("pause") > 0); + prog.ignore_simulation_check = vm.count("ignore-simulation-check"); } /* * This is the MAIN function! * UHD_SAFE_MAIN catches all errors and prints them to stderr. */ -int UHD_SAFE_MAIN(int argc, char *argv[]){ +int UHD_SAFE_MAIN(int argc, char* argv[]) +{ po::options_description desc = get_program_options_description(); po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -113,13 +111,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ read_program_options(vm); // Print help message instead of executing Responder. - if (vm.count("help")){ + if (vm.count("help")) { cout << boost::format("UHD Latency Test %s") % desc; return Responder::RETCODE_OK; } - //create a new instance of Responder and run it! + // create a new instance of Responder and run it! boost::shared_ptr<Responder> my_responder(new Responder(prog)); return my_responder->run(); } - |