diff options
author | Balint Seeber <balint@ettus.com> | 2014-10-01 17:20:20 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2014-10-09 10:50:37 +0200 |
commit | 15740bcc3b3e1d5adff8c77306d84741a26ebdad (patch) | |
tree | 29aba02634aaf58079064084d8bb2cc3fa5c319e /host/utils/latency/include/Responder.hpp | |
parent | ea5c8a39e43913e29936acde89745a7cdf5b18a8 (diff) | |
download | uhd-15740bcc3b3e1d5adff8c77306d84741a26ebdad.tar.gz uhd-15740bcc3b3e1d5adff8c77306d84741a26ebdad.tar.bz2 uhd-15740bcc3b3e1d5adff8c77306d84741a26ebdad.zip |
utils: Added latency measurement utility
Diffstat (limited to 'host/utils/latency/include/Responder.hpp')
-rw-r--r-- | host/utils/latency/include/Responder.hpp | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/host/utils/latency/include/Responder.hpp b/host/utils/latency/include/Responder.hpp new file mode 100644 index 000000000..a9f616a24 --- /dev/null +++ b/host/utils/latency/include/Responder.hpp @@ -0,0 +1,299 @@ +// +// Copyright 2010-2013 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef RESPONDER_H +#define RESPONDER_H + +#include <curses.h> +#include <map> +#include <ctime> +#include <stdint.h> + +#include <uhd/usrp/multi_usrp.hpp> +#include <uhd/utils/msg.hpp> + +using namespace std; + + +class Responder +{ + 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; + bool invert; + bool output_value; + bool no_delay; + bool allow_late_bursts; + + uint64_t level_calibration_count() const + { + 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 + { + 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(); + + // Public method to inject UHD messages in the main ncurses window. + void print_uhd_late_handler(uhd::msg::type_t type, const std::string& msg); + + int get_return_code(){return _return_code;} + + protected: + private: + // These 2 variables are used for ncurses output. + WINDOW* _window; + std::stringstream _ss; + + // 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 |