/*********************************************************************** * RX Hammer **********************************************************************/ void rx_hammer(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_cpu, uhd::rx_streamer::sptr rx_stream){ uhd::set_thread_priority_safe(); //print pre-test summary std::cout << boost::format( "Testing receive rate %f Msps" ) % (usrp->get_rx_rate()/1e6) << std::endl; //setup variables and allocate buffer uhd::rx_metadata_t md; const size_t max_samps_per_packet = rx_stream->get_max_num_samps(); std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(rx_cpu)); std::vector<void *> buffs; for (size_t ch = 0; ch < rx_stream->get_num_channels(); ch++) buffs.push_back(&buff.front()); //same buffer for each channel bool had_an_overflow = false; uhd::time_spec_t last_time; const double rate = usrp->get_rx_rate(); double timeout = 1; uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05); cmd.stream_now = (buffs.size() == 1); srand( time(NULL) ); while (not boost::this_thread::interruption_requested()){ cmd.num_samps = rand() % 100000; rx_stream->issue_stream_cmd(cmd); num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md, timeout, true); //handle the error codes switch(md.error_code){ case uhd::rx_metadata_t::ERROR_CODE_NONE: if (had_an_overflow){ had_an_overflow = false; num_dropped_samps += boost::math::iround((md.time_spec - last_time).get_real_secs()*rate); } break; case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: had_an_overflow = true; last_time = md.time_spec; if (!md.out_of_sequence) num_overflows++; break; default: std::cerr << "Receiver error: " << md.strerror() << std::endl; std::cerr << "Unexpected error on recv, continuing..." << std::endl; break; } } }
/*********************************************************************** * Benchmark RX Rate **********************************************************************/ void benchmark_rx_rate( uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_cpu, uhd::rx_streamer::sptr rx_stream, bool random_nsamps, const boost::posix_time::ptime &start_time, std::atomic<bool>& burst_timer_elapsed ) { uhd::set_thread_priority_safe(); //print pre-test summary std::cout << boost::format( "[%s] Testing receive rate %f Msps on %u channels" ) % NOW() % (usrp->get_rx_rate()/1e6) % rx_stream->get_num_channels() << std::endl; //setup variables and allocate buffer uhd::rx_metadata_t md; const size_t max_samps_per_packet = rx_stream->get_max_num_samps(); std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(rx_cpu)); std::vector<void *> buffs; for (size_t ch = 0; ch < rx_stream->get_num_channels(); ch++) buffs.push_back(&buff.front()); //same buffer for each channel bool had_an_overflow = false; uhd::time_spec_t last_time; const double rate = usrp->get_rx_rate(); uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(INIT_DELAY); cmd.stream_now = (buffs.size() == 1); rx_stream->issue_stream_cmd(cmd); const float burst_pkt_time = std::max<float>(0.100f, (2 * max_samps_per_packet/rate)); float recv_timeout = burst_pkt_time + INIT_DELAY; bool stop_called = false; while (true) { //if (burst_timer_elapsed.load(boost::memory_order_relaxed) and not stop_called) { if (burst_timer_elapsed and not stop_called) { rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); stop_called = true; } if (random_nsamps) { cmd.num_samps = rand() % max_samps_per_packet; rx_stream->issue_stream_cmd(cmd); } try { num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md, recv_timeout)*rx_stream->get_num_channels(); recv_timeout = burst_pkt_time; } catch (uhd::io_error &e) { std::cerr << "[" << NOW() << "] Caught an IO exception. " << std::endl; std::cerr << e.what() << std::endl; return; } //handle the error codes switch(md.error_code){ case uhd::rx_metadata_t::ERROR_CODE_NONE: if (had_an_overflow) { had_an_overflow = false; const long dropped_samps = (md.time_spec - last_time).to_ticks(rate); if (dropped_samps < 0) { std::cerr << "[" << NOW() << "] Timestamp after overrun recovery " "ahead of error timestamp! Unable to calculate " "number of dropped samples." "(Delta: " << dropped_samps << " ticks)\n"; } num_dropped_samps += std::max<long>(1, dropped_samps); } if ((burst_timer_elapsed or stop_called) and md.end_of_burst) { return; } break; // ERROR_CODE_OVERFLOW can indicate overflow or sequence error case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: last_time = md.time_spec; had_an_overflow = true; // check out_of_sequence flag to see if it was a sequence error or overflow if (!md.out_of_sequence) { num_overruns++; } else { num_seqrx_errors++; std::cerr << "[" << NOW() << "] Detected Rx sequence error." << std::endl; } break; case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND: std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << ", restart streaming..."<< std::endl; num_late_commands++; // Radio core will be in the idle state. Issue stream command to restart streaming. cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05); cmd.stream_now = (buffs.size() == 1); rx_stream->issue_stream_cmd(cmd); break; case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: if (burst_timer_elapsed) { return; } std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << ", continuing..." << std::endl; num_timeouts_rx++; break; // Otherwise, it's an error default: std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << std::endl; std::cerr << "[" << NOW() << "] Unexpected error on recv, continuing..." << std::endl; break; } } }