void init_stream() { boost::this_thread::sleep(boost::posix_time::milliseconds(WARM_UP_TIME)); stream_cmd.time_spec = time_start_recv = uhd::time_spec_t(2.0) + usrp->get_time_now(); cout << "Time to start receiving: " << time_start_recv.get_real_secs() << endl; stream_cmd.stream_now = false; usrp->issue_stream_cmd(stream_cmd); }
bool uhd_device::start() { LOG(INFO) << "Starting USRP..."; if (started) { LOG(ERR) << "Device already started"; return false; } started = true; setPriority(); // Start asynchronous event (underrun check) loop async_event_thrd = new Thread(32768); async_event_thrd->start((void * (*)(void*))async_event_loop, (void*)this); // Start streaming restart(uhd::time_spec_t(0.0)); // Display usrp time double time_now = usrp_dev->get_time_now().get_real_secs(); LOG(INFO) << "The current time is " << time_now << " seconds"; return true; }
/*********************************************************************** * 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; } } }
/*********************************************************************** * Benchmark TX Rate **********************************************************************/ void benchmark_tx_rate( uhd::usrp::multi_usrp::sptr usrp, const std::string &tx_cpu, uhd::tx_streamer::sptr tx_stream, std::atomic<bool>& burst_timer_elapsed, const boost::posix_time::ptime &start_time, bool random_nsamps=false ) { uhd::set_thread_priority_safe(); //print pre-test summary std::cout << boost::format( "[%s] Testing transmit rate %f Msps on %u channels" ) % NOW() % (usrp->get_tx_rate()/1e6) % tx_stream->get_num_channels() << std::endl; //setup variables and allocate buffer uhd::tx_metadata_t md; md.time_spec = usrp->get_time_now() + uhd::time_spec_t(INIT_DELAY); md.has_time_spec = (tx_stream->get_num_channels() > 1); const size_t max_samps_per_packet = tx_stream->get_max_num_samps(); std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(tx_cpu)); std::vector<const void *> buffs; for (size_t ch = 0; ch < tx_stream->get_num_channels(); ch++) buffs.push_back(&buff.front()); //same buffer for each channel md.has_time_spec = (buffs.size() != 1); if (random_nsamps) { std::srand((unsigned int)time(NULL)); while (not burst_timer_elapsed) { size_t total_num_samps = rand() % max_samps_per_packet; size_t num_acc_samps = 0; const float timeout = 1; usrp->set_time_now(uhd::time_spec_t(0.0)); while(num_acc_samps < total_num_samps){ //send a single packet num_tx_samps += tx_stream->send(buffs, max_samps_per_packet, md, timeout)*tx_stream->get_num_channels(); num_acc_samps += std::min(total_num_samps-num_acc_samps, tx_stream->get_max_num_samps()); } } } else { while (not burst_timer_elapsed) { const size_t num_tx_samps_sent_now = tx_stream->send(buffs, max_samps_per_packet, md)*tx_stream->get_num_channels(); num_tx_samps += num_tx_samps_sent_now; if (num_tx_samps_sent_now == 0) { num_timeouts_tx++; if ((num_timeouts_tx % 10000) == 1) { std::cerr << "[" << NOW() << "] Tx timeouts: " << num_timeouts_tx << std::endl; } } md.has_time_spec = false; } } //send a mini EOB packet md.end_of_burst = true; tx_stream->send(buffs, 0, md); }
template<typename samp_type> void send_from_file( uhd::usrp::multi_usrp::sptr usrp, const uhd::io_type_t &io_type, const std::string &file, size_t samps_per_buff, uhd::time_spec_t &send_time ){ uhd::tx_metadata_t md; md.start_of_burst = true; md.end_of_burst = false; std::vector<samp_type> buff(samps_per_buff); std::vector<samp_type> buff_zeros(samps_per_buff); std::ifstream infile(file.c_str(), std::ifstream::binary); uhd::time_spec_t now = usrp->get_time_now(); md.has_time_spec = true; md.time_spec = uhd::time_spec_t(0.5) + now; printf("send time %d %ld\n",md.time_spec.get_full_secs(),md.time_spec.get_tick_count(100e6)); send_time = md.time_spec; //loop until the entire file has been read infile.read((char*)&buff.front(), buff.size()*sizeof(samp_type)); size_t num_tx_samps = infile.gcount()/sizeof(samp_type); printf("%d\n",num_tx_samps); for(int i=0; i<samps_per_buff; i++){ buff_zeros[i] = 0; } int count=0; time_t start_time = time(NULL); time_t system_now = time(NULL); while(not md.end_of_burst){ if(system_now - start_time > run_time) md.end_of_burst = true;//infile.eof(); usrp->get_device()->send( &buff.front(), num_tx_samps, md, io_type, uhd::device::SEND_MODE_FULL_BUFF ); md.start_of_burst = false; md.has_time_spec = false; count++; system_now = time(NULL); } infile.close(); }
void transceive( uhd::usrp::multi_usrp::sptr usrp, uhd::tx_streamer::sptr tx_stream, uhd::rx_streamer::sptr rx_stream, unsigned int npulses, float pulse_time, //std::complex<int16_t>* txbuff, std::vector<std::complex<int16_t> >* txbuff0, std::vector<std::complex<int16_t> >* txbuff1, float tx_ontime, std::complex<int16_t>** outdata, size_t samps_per_pulse ){ int debug = 0; if (debug){ std::cout << "samps_per_pulse: " << samps_per_pulse << std::endl; } //create metadeta tags for transmit streams uhd::time_spec_t start_time = usrp->get_time_now() + 0.05; uhd::tx_metadata_t md; md.start_of_burst = true; md.end_of_burst = false; md.has_time_spec = true; md.time_spec = start_time; std::vector<std::complex<int16_t> *> vec_ptr; vec_ptr.resize(1); //vec_ptr[0] = &txbuff->front(); usrp->set_gpio_attr("RXA","CTRL",0x0, TR_BIT); //GPIO mode usrp->set_gpio_attr("RXA","DDR",TR_BIT, TR_BIT); //Direction out //create metadata tags for receive stream uhd::rx_metadata_t rxmd; std::vector<std::complex<int16_t> > buff(samps_per_pulse,0); if (verbose) std::cout << "rx buff size: " << buff.size() << std::endl; if (verbose) std::cout << "tx buff size: " << txbuff0->size() << std::endl; uhd::stream_cmd_t stream_cmd = uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE; stream_cmd.num_samps = npulses*samps_per_pulse; stream_cmd.stream_now = false; stream_cmd.time_spec = start_time + 22 / usrp->get_rx_rate(); //Digital hardware delay is 22 samples long. Found by experiment. if (verbose) std::cout << "time spec: " << stream_cmd.time_spec.get_real_secs() << std::endl; //loop for every pulse in the sequence size_t spb; std::vector<std::complex<int16_t>* > rx_dptr; rx_dptr.resize(usrp->get_rx_num_channels()); spb = tx_stream->get_max_num_samps(); if (verbose) std::cout << "npulses: " << npulses << std::endl; boost::thread_group rx_threads; boost::thread_group tx_threads; for (int ipulse=0; ipulse<npulses; ipulse++){ if (debug) std::cout << "pulse number: " << ipulse << std::endl; for (size_t ichan=0; ichan<usrp->get_rx_num_channels(); ichan++){ rx_dptr[ichan] = ipulse*samps_per_pulse + outdata[ichan]; } float timeout = 1.1; //usrp->set_command_time(start_time-50e-6,0); //usrp->set_gpio_attr("RXA","OUT",TR_BIT, TR_BIT); if (ipulse==0){ if (verbose) std::cout << "time spec: " << stream_cmd.time_spec.get_real_secs() << std::endl; if (verbose) std::cout << "Issuing stream command to start collecting samples\n"; usrp->issue_stream_cmd(stream_cmd); } //usrp->set_command_time(start_time+tx_ontime,0); //usrp->set_gpio_attr("RXA","OUT",0x0, TR_BIT); size_t acc_samps=0; if (ipulse%2 == 0) { vec_ptr[0] = &txbuff0->front(); } if (ipulse%2 == 1) { vec_ptr[0] = &txbuff1->front(); } if (ipulse != npulses-1) { tx_threads.create_thread(boost::bind(tx_worker, txbuff0->size(), tx_stream, start_time, vec_ptr[0], 0)); } if (ipulse == npulses-1) { tx_threads.create_thread(boost::bind(tx_worker, txbuff0->size(), tx_stream, start_time, vec_ptr[0], 1)); } rx_threads.join_all(); rx_threads.create_thread(boost::bind(rx_worker, rx_stream, samps_per_pulse, rx_dptr)); //for (int k=0; k<10; k++){ // //std::cout << "raw data: " << outdata[0][i][k] << "\t" << outdata[1][i][k] << std::endl; // std::cout << "raw data: " << rx_dptr[0][k] << " " << rx_dptr[1][k] << std::endl; //} //for (int k=0; k<samps_per_pulse; k++) // outdata[i][k] += buff[k]; start_time += float(pulse_time); } tx_threads.join_all(); rx_threads.join_all(); }
/*********************************************************************** * 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; } } }