/*********************************************************************** * RX Hammer **********************************************************************/ void rx_hammer(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_cpu, const std::string &rx_otw){ uhd::set_thread_priority_safe(); //create a receive streamer uhd::stream_args_t stream_args(rx_cpu, rx_otw); for (size_t ch = 0; ch < usrp->get_num_mboards(); ch++) //linear channel mapping stream_args.channels.push_back(ch); uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //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 < stream_args.channels.size(); 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; usrp->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; num_overflows++; break; default: std::cerr << "Error code: " << md.error_code << std::endl; std::cerr << "Unexpected error on recv, continuing..." << std::endl; break; } } }
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) { 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(); return rx_stream; }
/*********************************************************************** * recv_to_file function **********************************************************************/ template<typename samp_type> void recv_to_file( uhd::usrp::multi_usrp::sptr usrp, const std::string &cpu_format, const std::string &wire_format, const std::string &file, size_t samps_per_buff, int num_requested_samples, double settling_time, std::vector<size_t> rx_channel_nums ){ int num_total_samps = 0; //create a receive streamer uhd::stream_args_t stream_args(cpu_format,wire_format); stream_args.channels = rx_channel_nums; uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); // Prepare buffers for received samples and metadata uhd::rx_metadata_t md; std::vector <std::vector< samp_type > > buffs( rx_channel_nums.size(), std::vector< samp_type >(samps_per_buff) ); //create a vector of pointers to point to each of the channel buffers std::vector<samp_type *> buff_ptrs; for (size_t i = 0; i < buffs.size(); i++) { buff_ptrs.push_back(&buffs[i].front()); } // Create one ofstream object per channel // (use shared_ptr because ofstream is non-copyable) std::vector<boost::shared_ptr<std::ofstream> > outfiles; for (size_t i = 0; i < buffs.size(); i++) { const std::string this_filename = generate_out_filename(file, buffs.size(), i); outfiles.push_back(boost::shared_ptr<std::ofstream>(new std::ofstream(this_filename.c_str(), std::ofstream::binary))); } UHD_ASSERT_THROW(outfiles.size() == buffs.size()); UHD_ASSERT_THROW(buffs.size() == rx_channel_nums.size()); bool overflow_message = true; double timeout = settling_time + 0.1f; //expected settling time + padding for first recv //setup streaming uhd::stream_cmd_t stream_cmd((num_requested_samples == 0)? uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS: uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE ); stream_cmd.num_samps = num_requested_samples; stream_cmd.stream_now = false; stream_cmd.time_spec = uhd::time_spec_t(settling_time); rx_stream->issue_stream_cmd(stream_cmd); while(not stop_signal_called and (num_requested_samples > num_total_samps or num_requested_samples == 0)){ size_t num_rx_samps = rx_stream->recv(buff_ptrs, samps_per_buff, md, timeout); timeout = 0.1f; //small timeout for subsequent recv if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) { std::cout << boost::format("Timeout while streaming") << std::endl; break; } if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW){ if (overflow_message){ overflow_message = false; std::cerr << boost::format( "Got an overflow indication. Please consider the following:\n" " Your write medium must sustain a rate of %fMB/s.\n" " Dropped samples will not be written to the file.\n" " Please modify this example for your purposes.\n" " This message will not appear again.\n" ) % (usrp->get_rx_rate()*sizeof(samp_type)/1e6); } continue; } if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){ throw std::runtime_error(str(boost::format( "Receiver error %s" ) % md.strerror())); } num_total_samps += num_rx_samps; for (size_t i = 0; i < outfiles.size(); i++) { outfiles[i]->write((const char*) buff_ptrs[i], num_rx_samps*sizeof(samp_type)); } } // Shut down receiver stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; rx_stream->issue_stream_cmd(stream_cmd); // Close files for (size_t i = 0; i < outfiles.size(); i++) { outfiles[i]->close(); } }
template<typename samp_type> void recv_to_file( uhd::usrp::multi_usrp::sptr usrp, const std::string &cpu_format, const std::string &wire_format, const std::string &file, size_t samps_per_buff, unsigned long long num_requested_samples, double time_requested = 0.0, bool bw_summary = false, bool stats = false, bool null = false, bool enable_size_map = false, bool continue_on_bad_packet = false ){ unsigned long long num_total_samps = 0; //create a receive streamer uhd::stream_args_t stream_args(cpu_format,wire_format); uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); uhd::rx_metadata_t md; std::vector<samp_type> buff(samps_per_buff); std::ofstream outfile; if (not null) outfile.open(file.c_str(), std::ofstream::binary); bool overflow_message = true; //setup streaming uhd::stream_cmd_t stream_cmd((num_requested_samples == 0)? uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS: uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE ); stream_cmd.num_samps = num_requested_samples; stream_cmd.stream_now = true; stream_cmd.time_spec = uhd::time_spec_t(); rx_stream->issue_stream_cmd(stream_cmd); boost::system_time start = boost::get_system_time(); unsigned long long ticks_requested = (long)(time_requested * (double)boost::posix_time::time_duration::ticks_per_second()); boost::posix_time::time_duration ticks_diff; boost::system_time last_update = start; unsigned long long last_update_samps = 0; typedef std::map<size_t,size_t> SizeMap; SizeMap mapSizes; while(not stop_signal_called and (num_requested_samples != num_total_samps or num_requested_samples == 0)) { boost::system_time now = boost::get_system_time(); size_t num_rx_samps = rx_stream->recv(&buff.front(), buff.size(), md, 3.0, enable_size_map); if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) { std::cout << boost::format("Timeout while streaming") << std::endl; break; } if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW){ if (overflow_message) { overflow_message = false; std::cerr << boost::format( "Got an overflow indication. Please consider the following:\n" " Your write medium must sustain a rate of %fMB/s.\n" " Dropped samples will not be written to the file.\n" " Please modify this example for your purposes.\n" " This message will not appear again.\n" ) % (usrp->get_rx_rate()*sizeof(samp_type)/1e6); } continue; } if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){ std::string error = str(boost::format("Receiver error: %s") % md.strerror()); if (continue_on_bad_packet){ std::cerr << error << std::endl; continue; } else throw std::runtime_error(error); } if (enable_size_map) { SizeMap::iterator it = mapSizes.find(num_rx_samps); if (it == mapSizes.end()) mapSizes[num_rx_samps] = 0; mapSizes[num_rx_samps] += 1; } num_total_samps += num_rx_samps; if (outfile.is_open()) outfile.write((const char*)&buff.front(), num_rx_samps*sizeof(samp_type)); if (bw_summary) { last_update_samps += num_rx_samps; boost::posix_time::time_duration update_diff = now - last_update; if (update_diff.ticks() > boost::posix_time::time_duration::ticks_per_second()) { double t = (double)update_diff.ticks() / (double)boost::posix_time::time_duration::ticks_per_second(); double r = (double)last_update_samps / t; std::cout << boost::format("\t%f Msps") % (r/1e6) << std::endl; last_update_samps = 0; last_update = now; } } ticks_diff = now - start; if (ticks_requested > 0){ if ((unsigned long long)ticks_diff.ticks() > ticks_requested) break; } } stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; rx_stream->issue_stream_cmd(stream_cmd); if (outfile.is_open()) outfile.close(); if (stats) { std::cout << std::endl; double t = (double)ticks_diff.ticks() / (double)boost::posix_time::time_duration::ticks_per_second(); std::cout << boost::format("Received %d samples in %f seconds") % num_total_samps % t << std::endl; double r = (double)num_total_samps / t; std::cout << boost::format("%f Msps") % (r/1e6) << std::endl; if (enable_size_map) { std::cout << std::endl; std::cout << "Packet size map (bytes: count)" << std::endl; for (SizeMap::iterator it = mapSizes.begin(); it != mapSizes.end(); it++) std::cout << it->first << ":\t" << it->second << std::endl; } } }
int calculateTask( const char* outputFileName, const int binSize, const unsigned long long maximum_samples, uhd::usrp::multi_usrp::sptr& usrp ) { /////////////////////////////////////////////////////////// // //Initialization Section /////////////////////////////////////////////////////////// //Number of bytes in a single-precision float const int FLOAT_SIZE = sizeof(float); //Initialize and open the input/output files FILE *outputFile; if(!openFiles( outputFileName, outputFile )) return 0; //Setup the input buffer and tracking variables int return_code = 1; //Setup the USRP for streaming vector<float complex> usrpBuffer( binSize ); float energy; uhd::stream_args_t stream_args(__USRP_CPU_FMT, __USRP_WIRE_FMT ); uhd::rx_streamer::sptr usrp_rx_stream = usrp->get_rx_stream(stream_args); uhd::rx_metadata_t rx_md; unsigned long long int samples_recorded = 0; unsigned long long int buffer_samples_recorded = 0; uhd::stream_cmd_t usrp_stream_command(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); usrp_stream_command.stream_now = true; usrp_stream_command.time_spec = uhd::time_spec_t(); /////////////////////////////////////////////////////////// // //Work Section /////////////////////////////////////////////////////////// cout << "Begin Data Collection" << endl; //Start streaming! usrp->issue_stream_cmd( usrp_stream_command ); while( (samples_recorded < maximum_samples) and return_code ) { energy = 0.0f; //Read in the I-Q of fft_interval_size samples... buffer_samples_recorded = usrp_rx_stream->recv( &usrpBuffer.front(), usrpBuffer.size(), rx_md ); //Check the USRP for errors (including Overflow indication) if( rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE ) { //There was a USRP-related problem switch( rx_md.error_code ){ case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: cout << "O"; break; case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: cout << "USRP Timeout" << endl; return_code = 0; break; default: cout << "Unexpected USRP Error: " << rx_md.error_code; return_code = 0; } } samples_recorded += buffer_samples_recorded; //Compute magnitude (we don't want to store phase information) for(int i = 0; i < binSize; i++ ) energy += pow(cabsf( usrpBuffer[i] ), 2); //Write results to the output file fwrite(&energy, FLOAT_SIZE, 1, outputFile ); } /////////////////////////////////////////////////////////// // //Cleanup Section /////////////////////////////////////////////////////////// //Toss out any leftovers and cleanup fclose(outputFile); return 1; }
int uhd_device::open(const std::string &args, bool extref) { // Find UHD devices uhd::device_addr_t addr(args); uhd::device_addrs_t dev_addrs = uhd::device::find(addr); if (dev_addrs.size() == 0) { LOG(ALERT) << "No UHD devices found with address '" << args << "'"; return -1; } // Use the first found device LOG(INFO) << "Using discovered UHD device " << dev_addrs[0].to_string(); try { usrp_dev = uhd::usrp::multi_usrp::make(dev_addrs[0]); } catch(...) { LOG(ALERT) << "UHD make failed, device " << dev_addrs[0].to_string(); return -1; } // Check for a valid device type and set bus type if (!parse_dev_type()) return -1; if (extref) set_ref_clk(true); // Create TX and RX streamers uhd::stream_args_t stream_args("sc16"); tx_stream = usrp_dev->get_tx_stream(stream_args); rx_stream = usrp_dev->get_rx_stream(stream_args); // Number of samples per over-the-wire packet tx_spp = tx_stream->get_max_num_samps(); rx_spp = rx_stream->get_max_num_samps(); // Set rates double _tx_rate = select_rate(dev_type, sps); double _rx_rate = _tx_rate / sps; if ((_tx_rate > 0.0) && (set_rates(_tx_rate, _rx_rate) < 0)) return -1; // Create receive buffer size_t buf_len = SAMPLE_BUF_SZ / sizeof(uint32_t); rx_smpl_buf = new smpl_buf(buf_len, rx_rate); // Set receive chain sample offset double offset = get_dev_offset(dev_type, sps); if (offset == 0.0) { LOG(ERR) << "Unsupported configuration, no correction applied"; ts_offset = 0; } else { ts_offset = (TIMESTAMP) (offset * rx_rate); } // Initialize and shadow gain values init_gains(); // Print configuration LOG(INFO) << "\n" << usrp_dev->get_pp_string(); switch (dev_type) { case B100: return RESAMP_64M; case USRP2: case X3XX: return RESAMP_100M; } return NORMAL; }
/*********************************************************************** * recv_to_file function **********************************************************************/ template<typename samp_type> void recv_to_file( uhd::usrp::multi_usrp::sptr usrp, const std::string &cpu_format, const std::string &wire_format, const std::string &file, size_t samps_per_buff, int num_requested_samples, float settling_time, std::vector<size_t> rx_channel_nums ) { int num_total_samps = 0; //create a receive streamer uhd::stream_args_t stream_args(cpu_format,wire_format); stream_args.channels = rx_channel_nums; uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); uhd::rx_metadata_t md; std::vector<samp_type> buff(samps_per_buff); std::ofstream outfile(file.c_str(), std::ofstream::binary); bool overflow_message = true; float timeout = settling_time + 0.1; //expected settling time + padding for first recv //setup streaming uhd::stream_cmd_t stream_cmd((num_requested_samples == 0)? uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS: uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE ); stream_cmd.num_samps = num_requested_samples; stream_cmd.stream_now = false; stream_cmd.time_spec = uhd::time_spec_t(settling_time); rx_stream->issue_stream_cmd(stream_cmd); while(not stop_signal_called and (num_requested_samples != num_total_samps or num_requested_samples == 0)) { size_t num_rx_samps = rx_stream->recv(&buff.front(), buff.size(), md, timeout); timeout = 0.1; //small timeout for subsequent recv if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) { std::cout << boost::format("Timeout while streaming") << std::endl; break; } if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) { if (overflow_message) { overflow_message = false; std::cerr << boost::format( "Got an overflow indication. Please consider the following:\n" " Your write medium must sustain a rate of %fMB/s.\n" " Dropped samples will not be written to the file.\n" " Please modify this example for your purposes.\n" " This message will not appear again.\n" ) % (usrp->get_rx_rate()*sizeof(samp_type)/1e6); } continue; } if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) { throw std::runtime_error(str(boost::format( "Receiver error %s" ) % md.strerror())); } num_total_samps += num_rx_samps; outfile.write((const char*)&buff.front(), num_rx_samps*sizeof(samp_type)); } outfile.close(); }