void load_fpga_image(const std::string &path) { if (not boost::filesystem::exists("/dev/xdevcfg")) ::system("mknod /dev/xdevcfg c 259 0"); UHD_MSG(status) << "Loading FPGA image: " << path << "..." << std::flush; std::ifstream fpga_file(path.c_str(), std::ios_base::binary); UHD_ASSERT_THROW(fpga_file.good()); std::FILE *wfile; wfile = std::fopen("/dev/xdevcfg", "wb"); UHD_ASSERT_THROW(!(wfile == NULL)); char buff[16384]; // devcfg driver can't handle huge writes do { fpga_file.read(buff, sizeof(buff)); std::fwrite(buff, 1, size_t(fpga_file.gcount()), wfile); } while (fpga_file); fpga_file.close(); std::fclose(wfile); UHD_MSG(status) << " done" << std::endl; }
void send_char(const char ch) { managed_send_buffer::sptr buff = _xport->get_send_buff(); UHD_ASSERT_THROW(bool(buff)); vrt::if_packet_info_t packet_info; packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; packet_info.packet_type = vrt::if_packet_info_t::PACKET_TYPE_CONTEXT; packet_info.num_payload_words32 = 2; packet_info.num_payload_bytes = packet_info.num_payload_words32*sizeof(uint32_t); packet_info.packet_count = _count++; packet_info.sob = false; packet_info.eob = false; packet_info.sid = _sid; packet_info.has_sid = true; packet_info.has_cid = false; packet_info.has_tsi = false; packet_info.has_tsf = false; packet_info.has_tlr = false; uint32_t *packet_buff = buff->cast<uint32_t *>(); vrt::if_hdr_pack_le(packet_buff, packet_info); packet_buff[packet_info.num_header_words32+0] = uhd::htonx(uint32_t(_baud_div)); packet_buff[packet_info.num_header_words32+1] = uhd::htonx(uint32_t(ch)); buff->commit(packet_info.num_packet_words32*sizeof(uint32_t)); }
std::string get_ipv4_addr(unsigned int port_id) { struct in_addr ipv4_addr; int status = uhd_dpdk_get_ipv4_addr(port_id, &ipv4_addr.s_addr, NULL); UHD_ASSERT_THROW(status == 0); char addr_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ipv4_addr, addr_str, sizeof(addr_str)); return std::string(addr_str); }
void n230_eeprom_manager::_transact(const uint32_t command) { //Load request struct _request.flags = uhd::htonx<uint32_t>(N230_FLASH_COMM_FLAGS_ACK | command); _request.seq = uhd::htonx<uint32_t>(_seq_num++); //Send request _flush_xport(); _udp_xport->send(boost::asio::buffer(&_request, sizeof(_request))); //Recv reply const size_t nbytes = _udp_xport->recv(boost::asio::buffer(&_response, sizeof(_response)), UDP_TIMEOUT_IN_SEC); if (nbytes == 0) throw uhd::io_error("n230_eeprom_manager::_transact failure"); //Sanity checks const size_t flags = uhd::ntohx<uint32_t>(_response.flags); UHD_ASSERT_THROW(nbytes == sizeof(_response)); UHD_ASSERT_THROW(_response.seq == _request.seq); UHD_ASSERT_THROW(flags & command); }
void get_freq_and_freq_word( const double requested_freq, const double tick_rate, double &actual_freq, int32_t &freq_word ) { //correct for outside of rate (wrap around) double freq = std::fmod(requested_freq, tick_rate); if (std::abs(freq) > tick_rate/2.0) freq -= boost::math::sign(freq) * tick_rate; //confirm that the target frequency is within range of the CORDIC UHD_ASSERT_THROW(std::abs(freq) <= tick_rate/2.0); /* Now calculate the frequency word. It is possible for this calculation * to cause an overflow. As the requested DSP frequency approaches the * master clock rate, that ratio multiplied by the scaling factor (2^32) * will generally overflow within the last few kHz of tunable range. * Thus, we check to see if the operation will overflow before doing it, * and if it will, we set it to the integer min or max of this system. */ freq_word = 0; static const double scale_factor = std::pow(2.0, 32); if ((freq / tick_rate) >= (MAX_FREQ_WORD / scale_factor)) { /* Operation would have caused a positive overflow of int32. */ freq_word = MAX_FREQ_WORD; } else if ((freq / tick_rate) <= (MIN_FREQ_WORD / scale_factor)) { /* Operation would have caused a negative overflow of int32. */ freq_word = MIN_FREQ_WORD; } else { /* The operation is safe. Perform normally. */ freq_word = int32_t(boost::math::round((freq / tick_rate) * scale_factor)); } actual_freq = (double(freq_word) / scale_factor) * tick_rate; }
/*********************************************************************** * 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(); } }
/*********************************************************************** * Main function **********************************************************************/ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //transmit variables to be set by po std::string tx_args, wave_type, tx_ant, tx_subdev, ref, otw, tx_channels; double tx_rate, tx_freq, tx_gain, wave_freq, tx_bw; float ampl; //receive variables to be set by po std::string rx_args, file, type, rx_ant, rx_subdev, rx_channels; size_t total_num_samps, spb; double rx_rate, rx_freq, rx_gain, rx_bw; double settling; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") ("tx-args", po::value<std::string>(&tx_args)->default_value(""), "uhd transmit device address args") ("rx-args", po::value<std::string>(&rx_args)->default_value(""), "uhd receive device address args") ("file", po::value<std::string>(&file)->default_value("usrp_samples.dat"), "name of the file to write binary samples to") ("type", po::value<std::string>(&type)->default_value("short"), "sample type in file: double, float, or short") ("nsamps", po::value<size_t>(&total_num_samps)->default_value(0), "total number of samples to receive") ("settling", po::value<double>(&settling)->default_value(double(0.2)), "settling time (seconds) before receiving") ("spb", po::value<size_t>(&spb)->default_value(0), "samples per buffer, 0 for default") ("tx-rate", po::value<double>(&tx_rate), "rate of transmit outgoing samples") ("rx-rate", po::value<double>(&rx_rate), "rate of receive incoming samples") ("tx-freq", po::value<double>(&tx_freq), "transmit RF center frequency in Hz") ("rx-freq", po::value<double>(&rx_freq), "receive RF center frequency in Hz") ("ampl", po::value<float>(&l)->default_value(float(0.3)), "amplitude of the waveform [0 to 0.7]") ("tx-gain", po::value<double>(&tx_gain), "gain for the transmit RF chain") ("rx-gain", po::value<double>(&rx_gain), "gain for the receive RF chain") ("tx-ant", po::value<std::string>(&tx_ant), "transmit antenna selection") ("rx-ant", po::value<std::string>(&rx_ant), "receive antenna selection") ("tx-subdev", po::value<std::string>(&tx_subdev), "transmit subdevice specification") ("rx-subdev", po::value<std::string>(&rx_subdev), "receive subdevice specification") ("tx-bw", po::value<double>(&tx_bw), "analog transmit filter bandwidth in Hz") ("rx-bw", po::value<double>(&rx_bw), "analog receive filter bandwidth in Hz") ("wave-type", po::value<std::string>(&wave_type)->default_value("CONST"), "waveform type (CONST, SQUARE, RAMP, SINE)") ("wave-freq", po::value<double>(&wave_freq)->default_value(0), "waveform frequency in Hz") ("ref", po::value<std::string>(&ref)->default_value("internal"), "clock reference (internal, external, mimo)") ("otw", po::value<std::string>(&otw)->default_value("sc16"), "specify the over-the-wire sample mode") ("tx-channels", po::value<std::string>(&tx_channels)->default_value("0"), "which TX channel(s) to use (specify \"0\", \"1\", \"0,1\", etc)") ("rx-channels", po::value<std::string>(&rx_channels)->default_value("0"), "which RX channel(s) to use (specify \"0\", \"1\", \"0,1\", etc)") ("tx-int-n", "tune USRP TX with integer-N tuning") ("rx-int-n", "tune USRP RX with integer-N tuning") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); //print the help message if (vm.count("help")){ std::cout << boost::format("UHD TXRX Loopback to File %s") % desc << std::endl; return ~0; } //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the transmit usrp device with: %s...") % tx_args << std::endl; uhd::usrp::multi_usrp::sptr tx_usrp = uhd::usrp::multi_usrp::make(tx_args); std::cout << std::endl; std::cout << boost::format("Creating the receive usrp device with: %s...") % rx_args << std::endl; uhd::usrp::multi_usrp::sptr rx_usrp = uhd::usrp::multi_usrp::make(rx_args); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("tx-subdev")) tx_usrp->set_tx_subdev_spec(tx_subdev); if (vm.count("rx-subdev")) rx_usrp->set_rx_subdev_spec(rx_subdev); //detect which channels to use std::vector<std::string> tx_channel_strings; std::vector<size_t> tx_channel_nums; boost::split(tx_channel_strings, tx_channels, boost::is_any_of("\"',")); for(size_t ch = 0; ch < tx_channel_strings.size(); ch++){ size_t chan = std::stoi(tx_channel_strings[ch]); if(chan >= tx_usrp->get_tx_num_channels()){ throw std::runtime_error("Invalid TX channel(s) specified."); } else tx_channel_nums.push_back(std::stoi(tx_channel_strings[ch])); } std::vector<std::string> rx_channel_strings; std::vector<size_t> rx_channel_nums; boost::split(rx_channel_strings, rx_channels, boost::is_any_of("\"',")); for(size_t ch = 0; ch < rx_channel_strings.size(); ch++){ size_t chan = std::stoi(rx_channel_strings[ch]); if(chan >= rx_usrp->get_rx_num_channels()){ throw std::runtime_error("Invalid RX channel(s) specified."); } else rx_channel_nums.push_back(std::stoi(rx_channel_strings[ch])); } //Lock mboard clocks tx_usrp->set_clock_source(ref); rx_usrp->set_clock_source(ref); std::cout << boost::format("Using TX Device: %s") % tx_usrp->get_pp_string() << std::endl; std::cout << boost::format("Using RX Device: %s") % rx_usrp->get_pp_string() << std::endl; //set the transmit sample rate if (not vm.count("tx-rate")){ std::cerr << "Please specify the transmit sample rate with --tx-rate" << std::endl; return ~0; } std::cout << boost::format("Setting TX Rate: %f Msps...") % (tx_rate/1e6) << std::endl; tx_usrp->set_tx_rate(tx_rate); std::cout << boost::format("Actual TX Rate: %f Msps...") % (tx_usrp->get_tx_rate()/1e6) << std::endl << std::endl; //set the receive sample rate if (not vm.count("rx-rate")){ std::cerr << "Please specify the sample rate with --rx-rate" << std::endl; return ~0; } std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl; rx_usrp->set_rx_rate(rx_rate); std::cout << boost::format("Actual RX Rate: %f Msps...") % (rx_usrp->get_rx_rate()/1e6) << std::endl << std::endl; //set the transmit center frequency if (not vm.count("tx-freq")){ std::cerr << "Please specify the transmit center frequency with --tx-freq" << std::endl; return ~0; } for(size_t ch = 0; ch < tx_channel_nums.size(); ch++) { size_t channel = tx_channel_nums[ch]; if (tx_channel_nums.size() > 1) { std::cout << "Configuring TX Channel " << channel << std::endl; } std::cout << boost::format("Setting TX Freq: %f MHz...") % (tx_freq/1e6) << std::endl; uhd::tune_request_t tx_tune_request(tx_freq); if(vm.count("tx-int-n")) tx_tune_request.args = uhd::device_addr_t("mode_n=integer"); tx_usrp->set_tx_freq(tx_tune_request, channel); std::cout << boost::format("Actual TX Freq: %f MHz...") % (tx_usrp->get_tx_freq(channel)/1e6) << std::endl << std::endl; //set the rf gain if (vm.count("tx-gain")){ std::cout << boost::format("Setting TX Gain: %f dB...") % tx_gain << std::endl; tx_usrp->set_tx_gain(tx_gain, channel); std::cout << boost::format("Actual TX Gain: %f dB...") % tx_usrp->get_tx_gain(channel) << std::endl << std::endl; } //set the analog frontend filter bandwidth if (vm.count("tx-bw")){ std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % tx_bw << std::endl; tx_usrp->set_tx_bandwidth(tx_bw, channel); std::cout << boost::format("Actual TX Bandwidth: %f MHz...") % tx_usrp->get_tx_bandwidth(channel) << std::endl << std::endl; } //set the antenna if (vm.count("tx-ant")) tx_usrp->set_tx_antenna(tx_ant, channel); } for(size_t ch = 0; ch < rx_channel_nums.size(); ch++) { size_t channel = rx_channel_nums[ch]; if (rx_channel_nums.size() > 1) { std::cout << "Configuring RX Channel " << channel << std::endl; } //set the receive center frequency if (not vm.count("rx-freq")){ std::cerr << "Please specify the center frequency with --rx-freq" << std::endl; return ~0; } std::cout << boost::format("Setting RX Freq: %f MHz...") % (rx_freq/1e6) << std::endl; uhd::tune_request_t rx_tune_request(rx_freq); if(vm.count("rx-int-n")) rx_tune_request.args = uhd::device_addr_t("mode_n=integer"); rx_usrp->set_rx_freq(rx_tune_request, channel); std::cout << boost::format("Actual RX Freq: %f MHz...") % (rx_usrp->get_rx_freq(channel)/1e6) << std::endl << std::endl; //set the receive rf gain if (vm.count("rx-gain")){ std::cout << boost::format("Setting RX Gain: %f dB...") % rx_gain << std::endl; rx_usrp->set_rx_gain(rx_gain, channel); std::cout << boost::format("Actual RX Gain: %f dB...") % rx_usrp->get_rx_gain(channel) << std::endl << std::endl; } //set the receive analog frontend filter bandwidth if (vm.count("rx-bw")){ std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % (rx_bw/1e6) << std::endl; rx_usrp->set_rx_bandwidth(rx_bw, channel); std::cout << boost::format("Actual RX Bandwidth: %f MHz...") % (rx_usrp->get_rx_bandwidth(channel)/1e6) << std::endl << std::endl; } } //set the receive antenna if (vm.count("ant")) rx_usrp->set_rx_antenna(rx_ant); //for the const wave, set the wave freq for small samples per period if (wave_freq == 0 and wave_type == "CONST"){ wave_freq = tx_usrp->get_tx_rate()/2; } //error when the waveform is not possible to generate if (std::abs(wave_freq) > tx_usrp->get_tx_rate()/2){ throw std::runtime_error("wave freq out of Nyquist zone"); } if (tx_usrp->get_tx_rate()/std::abs(wave_freq) > wave_table_len/2){ throw std::runtime_error("wave freq too small for table"); } //pre-compute the waveform values const wave_table_class wave_table(wave_type, ampl); const size_t step = boost::math::iround(wave_freq/tx_usrp->get_tx_rate() * wave_table_len); size_t index = 0; //create a transmit streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) uhd::stream_args_t stream_args("fc32", otw); stream_args.channels = tx_channel_nums; uhd::tx_streamer::sptr tx_stream = tx_usrp->get_tx_stream(stream_args); //allocate a buffer which we re-use for each channel if (spb == 0) spb = tx_stream->get_max_num_samps()*10; std::vector<std::complex<float> > buff(spb); int num_channels = tx_channel_nums.size(); //setup the metadata flags uhd::tx_metadata_t md; md.start_of_burst = true; md.end_of_burst = false; md.has_time_spec = true; md.time_spec = uhd::time_spec_t(0.5); //give us 0.5 seconds to fill the tx buffers //Check Ref and LO Lock detect std::vector<std::string> tx_sensor_names, rx_sensor_names; tx_sensor_names = tx_usrp->get_tx_sensor_names(0); if (std::find(tx_sensor_names.begin(), tx_sensor_names.end(), "lo_locked") != tx_sensor_names.end()) { uhd::sensor_value_t lo_locked = tx_usrp->get_tx_sensor("lo_locked",0); std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } rx_sensor_names = rx_usrp->get_rx_sensor_names(0); if (std::find(rx_sensor_names.begin(), rx_sensor_names.end(), "lo_locked") != rx_sensor_names.end()) { uhd::sensor_value_t lo_locked = rx_usrp->get_rx_sensor("lo_locked",0); std::cout << boost::format("Checking RX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } tx_sensor_names = tx_usrp->get_mboard_sensor_names(0); if ((ref == "mimo") and (std::find(tx_sensor_names.begin(), tx_sensor_names.end(), "mimo_locked") != tx_sensor_names.end())) { uhd::sensor_value_t mimo_locked = tx_usrp->get_mboard_sensor("mimo_locked",0); std::cout << boost::format("Checking TX: %s ...") % mimo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(mimo_locked.to_bool()); } if ((ref == "external") and (std::find(tx_sensor_names.begin(), tx_sensor_names.end(), "ref_locked") != tx_sensor_names.end())) { uhd::sensor_value_t ref_locked = tx_usrp->get_mboard_sensor("ref_locked",0); std::cout << boost::format("Checking TX: %s ...") % ref_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(ref_locked.to_bool()); } rx_sensor_names = rx_usrp->get_mboard_sensor_names(0); if ((ref == "mimo") and (std::find(rx_sensor_names.begin(), rx_sensor_names.end(), "mimo_locked") != rx_sensor_names.end())) { uhd::sensor_value_t mimo_locked = rx_usrp->get_mboard_sensor("mimo_locked",0); std::cout << boost::format("Checking RX: %s ...") % mimo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(mimo_locked.to_bool()); } if ((ref == "external") and (std::find(rx_sensor_names.begin(), rx_sensor_names.end(), "ref_locked") != rx_sensor_names.end())) { uhd::sensor_value_t ref_locked = rx_usrp->get_mboard_sensor("ref_locked",0); std::cout << boost::format("Checking RX: %s ...") % ref_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(ref_locked.to_bool()); } if (total_num_samps == 0){ std::signal(SIGINT, &sig_int_handler); std::cout << "Press Ctrl + C to stop streaming..." << std::endl; } //reset usrp time to prepare for transmit/receive std::cout << boost::format("Setting device timestamp to 0...") << std::endl; tx_usrp->set_time_now(uhd::time_spec_t(0.0)); //start transmit worker thread boost::thread_group transmit_thread; transmit_thread.create_thread(boost::bind(&transmit_worker, buff, wave_table, tx_stream, md, step, index, num_channels)); //recv to file if (type == "double") recv_to_file<std::complex<double> >(rx_usrp, "fc64", otw, file, spb, total_num_samps, settling, rx_channel_nums); else if (type == "float") recv_to_file<std::complex<float> >(rx_usrp, "fc32", otw, file, spb, total_num_samps, settling, rx_channel_nums); else if (type == "short") recv_to_file<std::complex<short> >(rx_usrp, "sc16", otw, file, spb, total_num_samps, settling, rx_channel_nums); else { //clean up transmit worker stop_signal_called = true; transmit_thread.join_all(); throw std::runtime_error("Unknown type " + type); } //clean up transmit worker stop_signal_called = true; transmit_thread.join_all(); //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return EXIT_SUCCESS; }
int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); std::string args, tx_file, rx_file, type, ref, wire_format, cpu_format; double rate, freq, tx_gain, rx_gain, rx_bw, delay, lo_off,seconds_in_future, rx_timeout; rx_bw = RX_BW; rx_gain = RX_GAIN; wire_format = WIRE_FORMAT; cpu_format = CPU_FORMAT; rate = SAMP_RATE; args = ARGS; ref = REF_CLOCK; freq = CENT_FREQ; tx_gain = TX_GAIN; // samples_per_buff = SAMPLES_PER_BUFFER; tx_file = TX_FILENAME; rx_file = RX_FILENAME; seconds_in_future = SYNCH_DELAY; rx_timeout = RX_TIMEOUT; //------------------INIT TX------------------ //Set the scheduling priority on the current thread. Same as set_thread_priority but does not throw on failure. std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Make the usrp by calling the constructor with param the args usrp->set_clock_source(ref); //Set the clock source for the usrp device. This sets the source for a 10 MHz reference clock. Typical options for source: internal, external, MIMO. std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_tx_rate(rate); //Set the sample rate std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl; std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq/1e6) << std::endl; //Set up tuning frequency uhd::tune_request_t tune_request; tune_request = uhd::tune_request_t(freq); //Generate the tune request usrp->set_tx_freq(tune_request); //Tune to CENT_FREQ std::cout << boost::format("Actual TX Freq: %f MHz...") % (usrp->get_tx_freq()/1e6) << std::endl << std::endl; //PRINT Actual CENT_FREQ std::cout << boost::format("Setting TX Gain: %f dB...") % tx_gain << std::endl; usrp->set_tx_gain(tx_gain); //Set the tx_gain std::cout << boost::format("Actual TX Gain: %f dB...") % usrp->get_tx_gain() << std::endl << std::endl; //------------------CHECK STUFF------------------ //Check Ref and LO Lock detect std::vector<std::string> sensor_names; sensor_names = usrp->get_tx_sensor_names(0); if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) { uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked",0); std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } //------------------INIT RX------------------ //IS THIS NECESSARY? //always select the subdevice first, the channel mapping affects the other settings //usrp->set_rx_subdev_spec(subdev); std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_rx_rate(rate); std::cout << boost::format("Actual RX Rate: %f Msps...") % (usrp->get_rx_rate()/1e6) << std::endl << std::endl; //set the center frequency std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6) << std::endl; usrp->set_rx_freq(tune_request); std::cout << boost::format("Actual RX Freq: %f MHz...") % (usrp->get_rx_freq()/1e6) << std::endl << std::endl; std::cout << boost::format("Setting RX Gain: %f dB...") % rx_gain << std::endl; usrp->set_rx_gain(rx_gain); std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow 1sec setup time //------------------CHECK STUFF------------------ //Always check for locked sensor check_locked_sensor(usrp->get_rx_sensor_names(0), "lo_locked", boost::bind(&uhd::usrp::multi_usrp::get_rx_sensor, usrp, _1, 0), 1); //------------------INIT FILES--------------- std::ofstream outfile; outfile.open(rx_file.c_str(), std::ofstream::binary); if(!outfile.good()){ std::cout << "OUT File error\n"; return 0; } std::ifstream infile(tx_file.c_str(), std::ifstream::binary); if(!infile.good()){ std::cout << "IN File error\n"; return 0; } //------------------INIT STREAMS--------------- //Stream ARGS uhd::stream_args_t stream_args(cpu_format, wire_format); //Call the constructor of the class stream_args_t and generate the stream_args object with inputs the cpu_format and wire_format (this is the format per sample) tx_stream = usrp->get_tx_stream(stream_args); //Generate a tx_streamer object named tx_stream using the usrp->get_tx_stream(stream_args). Remember, usrp is already initialized uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //Generate a tx_streamer object named tx_stream using the usrp->get_tx_stream(stream_args). Remember, usrp is already initialized //Setup metadata //Setup tx_metadata tx_md.start_of_burst = true; //Set start of burst to true for the first packet in the chain. ? tx_md.end_of_burst = false; #define SYNCHED_TXRX 1 //For TX if(SYNCHED_TXRX){ tx_md.has_time_spec = true; }else{ tx_md.has_time_spec = false; } //Setup rx_metadata uhd::rx_metadata_t rx_md; //Setup stream command ONLY FOR RX uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); stream_cmd.num_samps = samples_per_buff; //For RX if(SYNCHED_TXRX){ stream_cmd.stream_now = false; // tx_md.time_spec = stream_cmd.time_spec; }else{ stream_cmd.stream_now = true; stream_cmd.time_spec = uhd::time_spec_t(); } if(SYNCHED_TXRX){ //Cannt get any faster than this tx_md.time_spec = stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future)+usrp->get_time_now(); } //Create the buffs std::vector<std::complex<float> > small_rx_buff(samples_per_buff); //Fill the TX buffer for (int i = 0; i < samples_per_buff; ++i){ infile.read((char*)&small_tx_buff.at(i), small_tx_buff.size()*sizeof(std::complex<float>)); } infile.close(); //Close the file pointer //Issue the stream command rx_stream->issue_stream_cmd(stream_cmd); //Print number of maximum buffer size printf("MAX TX: %d\n", (int)tx_stream->get_max_num_samps()); printf("MAX RX %d\n", (int)rx_stream->get_max_num_samps()); size_t num_rx_samps = 0; boost::thread txThread(thread_startTx); //receivotrnsmit txThread.join(); //Strart the thread for tx (tx is f blocking) num_rx_samps = rx_stream->recv(&small_rx_buff.front(), small_rx_buff.size(), rx_md, rx_timeout, false); // Receive buffers containing samples described by the metadata. // num_rx_samps = rx_stream->recv(&small_rx_buff.front(), small_rx_buff.size(), rx_md, rx_timeout, false); // Receive buffers containing samples described by the metadata. //Wait for everything to stop boost::this_thread::sleep(boost::posix_time::milliseconds(2000)); //Cleanup and print what happened usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); // Stop the stream (not really necessary here) double rx_stamp = rx_md.time_spec.get_full_secs() + rx_md.time_spec.get_frac_secs(); double tx_stamp = tx_md.time_spec.get_full_secs() + tx_md.time_spec.get_frac_secs(); double t_diff = rx_stamp - tx_stamp; printf("RX Time stamp: %.12lf\n ΤX Time stamp: %.12lf\n Diff: %.12lf\n",rx_stamp, tx_stamp, t_diff); switch ( rx_md.error_code ) { case uhd::rx_metadata_t::ERROR_CODE_NONE: printf("No error:)\n"); break; case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: printf("MDError 2\n"); break; case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND: printf("MDError 3\n"); break; case uhd::rx_metadata_t::ERROR_CODE_BROKEN_CHAIN: printf("MDError 4\n"); break; case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: printf("MDError 5\n"); break; case uhd::rx_metadata_t::ERROR_CODE_ALIGNMENT: printf("MDError 6\n"); break; case uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET: printf("MDError 7\n"); break; default: printf("WUT\n"); break; } //write the samples if (outfile.is_open()){ outfile.write((const char*)&small_rx_buff.front(), num_rx_samps*sizeof(std::complex<float>)); } outfile.close(); //Close the file pointer //print std::cout << "Transmitted samples: " << num_tx_samps << '\n'; std::cout << "Received samples: " << num_rx_samps << '\n'; return EXIT_SUCCESS; }
int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args, file, type, ant, subdev, ref, wirefmt; size_t spb; double rate, freq, gain, bw, delay, lo_off; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args") ("file", po::value<std::string>(&file)->default_value("usrp_samples.dat"), "name of the file to read binary samples from") ("type", po::value<std::string>(&type)->default_value("short"), "sample type: double, float, or short") ("spb", po::value<size_t>(&spb)->default_value(10000), "samples per buffer") ("rate", po::value<double>(&rate), "rate of outgoing samples") ("freq", po::value<double>(&freq), "RF center frequency in Hz") ("lo_off", po::value<double>(&lo_off), "Offset for frontend LO in Hz (optional)") ("gain", po::value<double>(&gain), "gain for the RF chain") ("ant", po::value<std::string>(&ant), "daughterboard antenna selection") ("subdev", po::value<std::string>(&subdev), "daughterboard subdevice specification") ("bw", po::value<double>(&bw), "daughterboard IF filter bandwidth in Hz") ("ref", po::value<std::string>(&ref)->default_value("internal"), "waveform type (internal, external, mimo)") ("wirefmt", po::value<std::string>(&wirefmt)->default_value("sc16"), "wire format (sc8 or sc16)") ("delay", po::value<double>(&delay)->default_value(0.0), "specify a delay between repeated transmission of file") ("repeat", "repeatedly transmit file") ("int-n", "tune USRP with integer-n tuning") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); //print the help message if (vm.count("help")){ std::cout << boost::format("UHD TX samples from file %s") % desc << std::endl; return ~0; } bool repeat = vm.count("repeat"); //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Lock mboard clocks usrp->set_clock_source(ref); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_tx_subdev_spec(subdev); std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //set the sample rate if (not vm.count("rate")){ std::cerr << "Please specify the sample rate with --rate" << std::endl; return ~0; } std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_tx_rate(rate); std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl; //set the center frequency if (not vm.count("freq")){ std::cerr << "Please specify the center frequency with --freq" << std::endl; return ~0; } std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq/1e6) << std::endl; uhd::tune_request_t tune_request; if(vm.count("lo_off")) tune_request = uhd::tune_request_t(freq, lo_off); else tune_request = uhd::tune_request_t(freq); if(vm.count("int-n")) tune_request.args = uhd::device_addr_t("mode_n=integer"); usrp->set_tx_freq(tune_request); std::cout << boost::format("Actual TX Freq: %f MHz...") % (usrp->get_tx_freq()/1e6) << std::endl << std::endl; //set the rf gain if (vm.count("gain")){ std::cout << boost::format("Setting TX Gain: %f dB...") % gain << std::endl; usrp->set_tx_gain(gain); std::cout << boost::format("Actual TX Gain: %f dB...") % usrp->get_tx_gain() << std::endl << std::endl; } //set the IF filter bandwidth if (vm.count("bw")){ std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % bw << std::endl; usrp->set_tx_bandwidth(bw); std::cout << boost::format("Actual TX Bandwidth: %f MHz...") % usrp->get_tx_bandwidth() << std::endl << std::endl; } //set the antenna if (vm.count("ant")) usrp->set_tx_antenna(ant); boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time //Check Ref and LO Lock detect std::vector<std::string> sensor_names; sensor_names = usrp->get_tx_sensor_names(0); if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) { uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked",0); std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } sensor_names = usrp->get_mboard_sensor_names(0); if ((ref == "mimo") and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") != sensor_names.end())) { uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked",0); std::cout << boost::format("Checking TX: %s ...") % mimo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(mimo_locked.to_bool()); } if ((ref == "external") and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())) { uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked",0); std::cout << boost::format("Checking TX: %s ...") % ref_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(ref_locked.to_bool()); } //set sigint if user wants to receive if(repeat){ std::signal(SIGINT, &sig_int_handler); std::cout << "Press Ctrl + C to stop streaming..." << std::endl; } //send from file do{ if (type == "double") send_from_file<std::complex<double> >(usrp, "fc64", wirefmt, file, spb); else if (type == "float") send_from_file<std::complex<float> >(usrp, "fc32", wirefmt, file, spb); else if (type == "short") send_from_file<std::complex<short> >(usrp, "sc16", wirefmt, file, spb); else throw std::runtime_error("Unknown type " + type); if(repeat and delay != 0.0) boost::this_thread::sleep(boost::posix_time::milliseconds(delay)); } while(repeat and not stop_signal_called); //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return EXIT_SUCCESS; }
int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args, ant, subdev, ref; size_t num_bins; double rate, freq, gain, bw, frame_rate; float ref_lvl, dyn_rng; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args") // hardware parameters ("rate", po::value<double>(&rate), "rate of incoming samples (sps)") ("freq", po::value<double>(&freq), "RF center frequency in Hz") ("gain", po::value<double>(&gain), "gain for the RF chain") ("ant", po::value<std::string>(&ant), "daughterboard antenna selection") ("subdev", po::value<std::string>(&subdev), "daughterboard subdevice specification") ("bw", po::value<double>(&bw), "daughterboard IF filter bandwidth in Hz") // display parameters ("num-bins", po::value<size_t>(&num_bins)->default_value(512), "the number of bins in the DFT") ("frame-rate", po::value<double>(&frame_rate)->default_value(5), "frame rate of the display (fps)") ("ref-lvl", po::value<float>(&ref_lvl)->default_value(0), "reference level for the display (dB)") ("dyn-rng", po::value<float>(&dyn_rng)->default_value(60), "dynamic range for the display (dB)") ("ref", po::value<std::string>(&ref)->default_value("internal"), "waveform type (internal, external, mimo)") ("int-n", "tune USRP with integer-N tuning") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); //print the help message if (vm.count("help") or not vm.count("rate")){ std::cout << boost::format("UHD RX ASCII Art DFT %s") % desc << std::endl; return EXIT_FAILURE; } //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Lock mboard clocks usrp->set_clock_source(ref); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_rx_subdev_spec(subdev); std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //set the sample rate if (not vm.count("rate")){ std::cerr << "Please specify the sample rate with --rate" << std::endl; return EXIT_FAILURE; } std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_rx_rate(rate); std::cout << boost::format("Actual RX Rate: %f Msps...") % (usrp->get_rx_rate()/1e6) << std::endl << std::endl; //set the center frequency if (not vm.count("freq")){ std::cerr << "Please specify the center frequency with --freq" << std::endl; return EXIT_FAILURE; } std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6) << std::endl; uhd::tune_request_t tune_request(freq); if(vm.count("int-n")) tune_request.args = uhd::device_addr_t("mode_n=integer"); usrp->set_rx_freq(tune_request); std::cout << boost::format("Actual RX Freq: %f MHz...") % (usrp->get_rx_freq()/1e6) << std::endl << std::endl; //set the rf gain if (vm.count("gain")){ std::cout << boost::format("Setting RX Gain: %f dB...") % gain << std::endl; usrp->set_rx_gain(gain); std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl; } //set the IF filter bandwidth if (vm.count("bw")){ std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % bw << std::endl; usrp->set_rx_bandwidth(bw); std::cout << boost::format("Actual RX Bandwidth: %f MHz...") % usrp->get_rx_bandwidth() << std::endl << std::endl; } //set the antenna if (vm.count("ant")) usrp->set_rx_antenna(ant); boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time //Check Ref and LO Lock detect std::vector<std::string> sensor_names; sensor_names = usrp->get_rx_sensor_names(0); if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) { uhd::sensor_value_t lo_locked = usrp->get_rx_sensor("lo_locked",0); std::cout << boost::format("Checking RX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } sensor_names = usrp->get_mboard_sensor_names(0); if ((ref == "mimo") and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") != sensor_names.end())) { uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked",0); std::cout << boost::format("Checking RX: %s ...") % mimo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(mimo_locked.to_bool()); } if ((ref == "external") and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())) { uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked",0); std::cout << boost::format("Checking RX: %s ...") % ref_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(ref_locked.to_bool()); } //create a receive streamer uhd::stream_args_t stream_args("fc32"); //complex floats uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //allocate recv buffer and metatdata uhd::rx_metadata_t md; std::vector<std::complex<float> > buff(num_bins); //------------------------------------------------------------------ //-- Initialize //------------------------------------------------------------------ initscr(); //curses init rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); boost::system_time next_refresh = boost::get_system_time(); //------------------------------------------------------------------ //-- Main loop //------------------------------------------------------------------ while (true){ //read a buffer's worth of samples every iteration size_t num_rx_samps = rx_stream->recv( &buff.front(), buff.size(), md ); if (num_rx_samps != buff.size()) continue; //check and update the display refresh condition if (boost::get_system_time() < next_refresh) continue; next_refresh = boost::get_system_time() + boost::posix_time::microseconds(long(1e6/frame_rate)); //calculate the dft and create the ascii art frame acsii_art_dft::log_pwr_dft_type lpdft( acsii_art_dft::log_pwr_dft(&buff.front(), num_rx_samps) ); std::string frame = acsii_art_dft::dft_to_plot( lpdft, COLS, LINES, usrp->get_rx_rate(), usrp->get_rx_freq(), dyn_rng, ref_lvl ); //curses screen handling: clear and print frame clear(); printw("%s", frame.c_str()); //curses key handling: no timeout, any key to exit timeout(0); int ch = getch(); if (ch != KEY_RESIZE and ch != ERR) break; } //------------------------------------------------------------------ //-- Cleanup //------------------------------------------------------------------ rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); endwin(); //curses done //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return EXIT_SUCCESS; }
int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args, file, type, ant, subdev, ref; size_t spb; double rate, freq, gain, bw; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args") ("file", po::value<std::string>(&file)->default_value("usrp_samples.dat"), "name of the file to read binary samples from") ("type", po::value<std::string>(&type)->default_value("float"), "sample type: double, float, or short") ("spb", po::value<size_t>(&spb)->default_value(10000), "samples per buffer") ("rate", po::value<double>(&rate), "rate of outgoing samples") ("freq", po::value<double>(&freq), "RF center frequency in Hz") ("gain", po::value<double>(&gain), "gain for the RF chain") ("ant", po::value<std::string>(&ant), "daughterboard antenna selection") ("subdev", po::value<std::string>(&subdev), "daughterboard subdevice specification") ("bw", po::value<double>(&bw), "daughterboard IF filter bandwidth in Hz") ("ref", po::value<std::string>(&ref)->default_value("INTERNAL"), "waveform type (INTERNAL, EXTERNAL, MIMO)") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); //print the help message if (vm.count("help")){ std::cout << boost::format("UHD TX samples from file %s") % desc << std::endl; return ~0; } //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Lock mboard clocks if (ref == "MIMO") { uhd::clock_config_t clock_config; clock_config.ref_source = uhd::clock_config_t::REF_MIMO; clock_config.pps_source = uhd::clock_config_t::PPS_MIMO; usrp->set_clock_config(clock_config, 0); } else if (ref == "EXTERNAL") { usrp->set_clock_config(uhd::clock_config_t::external(), 0); } else if (ref == "INTERNAL") { usrp->set_clock_config(uhd::clock_config_t::internal(), 0); } //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_tx_subdev_spec(subdev); std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //set the sample rate if (not vm.count("rate")){ std::cerr << "Please specify the sample rate with --rate" << std::endl; return ~0; } std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_tx_rate(rate); std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl; //set the center frequency if (not vm.count("freq")){ std::cerr << "Please specify the center frequency with --freq" << std::endl; return ~0; } std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq/1e6) << std::endl; usrp->set_tx_freq(freq); std::cout << boost::format("Actual TX Freq: %f MHz...") % (usrp->get_tx_freq()/1e6) << std::endl << std::endl; //set the rf gain if (vm.count("gain")){ std::cout << boost::format("Setting TX Gain: %f dB...") % gain << std::endl; usrp->set_tx_gain(gain); std::cout << boost::format("Actual TX Gain: %f dB...") % usrp->get_tx_gain() << std::endl << std::endl; } //set the IF filter bandwidth if (vm.count("bw")){ std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % bw << std::endl; usrp->set_tx_bandwidth(bw); std::cout << boost::format("Actual TX Bandwidth: %f MHz...") % usrp->get_tx_bandwidth() << std::endl << std::endl; } //set the antenna if (vm.count("ant")) usrp->set_tx_antenna(ant); boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time //Check Ref and LO Lock detect std::vector<std::string> sensor_names; sensor_names = usrp->get_tx_sensor_names(0); if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) { uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked",0); std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } sensor_names = usrp->get_mboard_sensor_names(0); if ((ref == "MIMO") and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") != sensor_names.end())) { uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked",0); std::cout << boost::format("Checking TX: %s ...") % mimo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(mimo_locked.to_bool()); } if ((ref == "EXTERNAL") and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())) { uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked",0); std::cout << boost::format("Checking TX: %s ...") % ref_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(ref_locked.to_bool()); } //send from file if (type == "double") send_from_file<std::complex<double> >(usrp, uhd::io_type_t::COMPLEX_FLOAT64, file, spb); else if (type == "float") send_from_file<std::complex<float> >(usrp, uhd::io_type_t::COMPLEX_FLOAT32, file, spb); else if (type == "short") send_from_file<std::complex<short> >(usrp, uhd::io_type_t::COMPLEX_INT16, file, spb); else throw std::runtime_error("Unknown type " + type); //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return 0; }
int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args, file, ant, subdev, ref; size_t total_num_samps; double rate, freq, gain, bw; std::string addr, port; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args") ("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of incoming samples") ("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz") ("gain", po::value<double>(&gain)->default_value(0), "gain for the RF chain") ("ant", po::value<std::string>(&ant), "daughterboard antenna selection") ("subdev", po::value<std::string>(&subdev), "daughterboard subdevice specification") ("bw", po::value<double>(&bw), "daughterboard IF filter bandwidth in Hz") ("port", po::value<std::string>(&port)->default_value("7124"), "server udp port") ("addr", po::value<std::string>(&addr)->default_value("192.168.1.10"), "resolvable server address") ("ref", po::value<std::string>(&ref)->default_value("internal"), "waveform type (internal, external, mimo)") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); //print the help message if (vm.count("help")){ std::cout << boost::format("UHD RX to UDP %s") % desc << std::endl; return ~0; } //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //Lock mboard clocks usrp->set_clock_source(ref); //set the rx sample rate std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_rx_rate(rate); std::cout << boost::format("Actual RX Rate: %f Msps...") % (usrp->get_rx_rate()/1e6) << std::endl << std::endl; //set the rx center frequency std::cout << boost::format("Setting RX Freq: %f Mhz...") % (freq/1e6) << std::endl; usrp->set_rx_freq(freq); std::cout << boost::format("Actual RX Freq: %f Mhz...") % (usrp->get_rx_freq()/1e6) << std::endl << std::endl; //set the rx rf gain std::cout << boost::format("Setting RX Gain: %f dB...") % gain << std::endl; usrp->set_rx_gain(gain); std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl; //set the IF filter bandwidth if (vm.count("bw")){ std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % bw << std::endl; usrp->set_rx_bandwidth(bw); std::cout << boost::format("Actual RX Bandwidth: %f MHz...") % usrp->get_rx_bandwidth() << std::endl << std::endl; } //set the antenna if (vm.count("ant")) usrp->set_rx_antenna(ant); boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time //Check Ref and LO Lock detect std::vector<std::string> sensor_names; sensor_names = usrp->get_rx_sensor_names(0); if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) { uhd::sensor_value_t lo_locked = usrp->get_rx_sensor("lo_locked",0); std::cout << boost::format("Checking RX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } sensor_names = usrp->get_mboard_sensor_names(0); if ((ref == "mimo") and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") != sensor_names.end())) { uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked",0); std::cout << boost::format("Checking RX: %s ...") % mimo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(mimo_locked.to_bool()); } if ((ref == "external") and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())) { uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked",0); std::cout << boost::format("Checking RX: %s ...") % ref_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(ref_locked.to_bool()); } //create a receive streamer uhd::stream_args_t stream_args("fc32"); //complex floats uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); stream_cmd.num_samps = total_num_samps; stream_cmd.stream_now = true; usrp->issue_stream_cmd(stream_cmd); //loop until total number of samples reached size_t num_acc_samps = 0; //number of accumulated samples uhd::rx_metadata_t md; std::vector<std::complex<float> > buff(rx_stream->get_max_num_samps()); uhd::transport::udp_simple::sptr udp_xport = uhd::transport::udp_simple::make_connected(addr, port); while(num_acc_samps < total_num_samps){ size_t num_rx_samps = rx_stream->recv( &buff.front(), buff.size(), md ); //handle the error codes switch(md.error_code){ case uhd::rx_metadata_t::ERROR_CODE_NONE: break; case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: if (num_acc_samps == 0) continue; std::cout << boost::format( "Got timeout before all samples received, possible packet loss, exiting loop..." ) << std::endl; goto done_loop; default: std::cout << boost::format( "Got error code 0x%x, exiting loop..." ) % md.error_code << std::endl; goto done_loop; } //send complex single precision floating point samples over udp udp_xport->send(boost::asio::buffer(buff, num_rx_samps*sizeof(buff.front()))); num_acc_samps += num_rx_samps; } done_loop: //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return 0; }
/*********************************************************************** * Main function **********************************************************************/ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args, wave_type, ant, subdev, ref, otw; size_t spb; double rate, freq, gain, wave_freq, bw; float ampl; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args") ("spb", po::value<size_t>(&spb)->default_value(0), "samples per buffer, 0 for default") ("rate", po::value<double>(&rate), "rate of outgoing samples") ("freq", po::value<double>(&freq), "RF center frequency in Hz") ("ampl", po::value<float>(&l)->default_value(float(0.3)), "amplitude of the waveform [0 to 0.7]") ("gain", po::value<double>(&gain), "gain for the RF chain") ("ant", po::value<std::string>(&ant), "daughterboard antenna selection") ("subdev", po::value<std::string>(&subdev), "daughterboard subdevice specification") ("bw", po::value<double>(&bw), "daughterboard IF filter bandwidth in Hz") ("wave-type", po::value<std::string>(&wave_type)->default_value("CONST"), "waveform type (CONST, SQUARE, RAMP, SINE)") ("wave-freq", po::value<double>(&wave_freq)->default_value(0), "waveform frequency in Hz") ("ref", po::value<std::string>(&ref)->default_value("internal"), "clock reference (internal, external, mimo)") ("otw", po::value<std::string>(&otw)->default_value("sc16"), "specify the over-the-wire sample mode") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); //print the help message if (vm.count("help")){ std::cout << boost::format("UHD TX Waveforms %s") % desc << std::endl; return ~0; } //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Lock mboard clocks usrp->set_clock_source(ref); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_tx_subdev_spec(subdev); std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //set the sample rate if (not vm.count("rate")){ std::cerr << "Please specify the sample rate with --rate" << std::endl; return ~0; } std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_tx_rate(rate); std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl; //set the center frequency if (not vm.count("freq")){ std::cerr << "Please specify the center frequency with --freq" << std::endl; return ~0; } for(size_t chan = 0; chan < usrp->get_tx_num_channels(); chan++) { std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq/1e6) << std::endl; usrp->set_tx_freq(freq, chan); std::cout << boost::format("Actual TX Freq: %f MHz...") % (usrp->get_tx_freq(chan)/1e6) << std::endl << std::endl; //set the rf gain if (vm.count("gain")){ std::cout << boost::format("Setting TX Gain: %f dB...") % gain << std::endl; usrp->set_tx_gain(gain, chan); std::cout << boost::format("Actual TX Gain: %f dB...") % usrp->get_tx_gain(chan) << std::endl << std::endl; } //set the IF filter bandwidth if (vm.count("bw")){ std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % bw << std::endl; usrp->set_tx_bandwidth(bw, chan); std::cout << boost::format("Actual TX Bandwidth: %f MHz...") % usrp->get_tx_bandwidth(chan) << std::endl << std::endl; } //set the antenna if (vm.count("ant")) usrp->set_tx_antenna(ant, chan); } //for the const wave, set the wave freq for small samples per period if (wave_freq == 0 and wave_type == "CONST"){ wave_freq = usrp->get_tx_rate()/2; } //error when the waveform is not possible to generate if (std::abs(wave_freq) > usrp->get_tx_rate()/2){ throw std::runtime_error("wave freq out of Nyquist zone"); } if (usrp->get_tx_rate()/std::abs(wave_freq) > wave_table_len/2){ throw std::runtime_error("wave freq too small for table"); } //pre-compute the waveform values const wave_table_class wave_table(wave_type, ampl); const size_t step = boost::math::iround(wave_freq/usrp->get_tx_rate() * wave_table_len); size_t index = 0; //create a transmit streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) uhd::stream_args_t stream_args("fc32", otw); for (size_t chan = 0; chan < usrp->get_tx_num_channels(); chan++) stream_args.channels.push_back(chan); //linear mapping uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate a buffer which we re-use for each channel if (spb == 0) spb = tx_stream->get_max_num_samps()*10; std::vector<std::complex<float> > buff(spb); std::vector<std::complex<float> *> buffs(usrp->get_tx_num_channels(), &buff.front()); //setup the metadata flags uhd::tx_metadata_t md; md.start_of_burst = true; md.end_of_burst = false; md.has_time_spec = true; md.time_spec = uhd::time_spec_t(0.1); std::cout << boost::format("Setting device timestamp to 0...") << std::endl; usrp->set_time_now(uhd::time_spec_t(0.0)); //Check Ref and LO Lock detect std::vector<std::string> sensor_names; sensor_names = usrp->get_tx_sensor_names(0); if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) { uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked",0); std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } sensor_names = usrp->get_mboard_sensor_names(0); if ((ref == "mimo") and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") != sensor_names.end())) { uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked",0); std::cout << boost::format("Checking TX: %s ...") % mimo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(mimo_locked.to_bool()); } if ((ref == "external") and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())) { uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked",0); std::cout << boost::format("Checking TX: %s ...") % ref_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(ref_locked.to_bool()); } std::signal(SIGINT, &sig_int_handler); std::cout << "Press Ctrl + C to stop streaming..." << std::endl; //send data until the signal handler gets called while(not stop_signal_called){ //fill the buffer with the waveform for (size_t n = 0; n < buff.size(); n++){ buff[n] = wave_table(index += step); } //send the entire contents of the buffer tx_stream->send(buffs, buff.size(), md); md.start_of_burst = false; md.has_time_spec = false; } //send a mini EOB packet md.end_of_burst = true; tx_stream->send("", 0, md); //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return 0; }
/*********************************************************************** * Main function **********************************************************************/ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args, wave_type, ant, subdev, ref, pps, otw, channel_list; uint64_t total_num_samps, spb; double rate, freq, gain, wave_freq, bw; float ampl; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args") ("spb", po::value<uint64_t>(&spb)->default_value(0), "samples per buffer, 0 for default") ("nsamps", po::value<uint64_t>(&total_num_samps)->default_value(0), "total number of samples to transmit") ("rate", po::value<double>(&rate), "rate of outgoing samples") ("freq", po::value<double>(&freq), "RF center frequency in Hz") ("ampl", po::value<float>(&l)->default_value(float(0.3)), "amplitude of the waveform [0 to 0.7]") ("gain", po::value<double>(&gain), "gain for the RF chain") ("ant", po::value<std::string>(&ant), "antenna selection") ("subdev", po::value<std::string>(&subdev), "subdevice specification") ("bw", po::value<double>(&bw), "analog frontend filter bandwidth in Hz") ("wave-type", po::value<std::string>(&wave_type)->default_value("CONST"), "waveform type (CONST, SQUARE, RAMP, SINE)") ("wave-freq", po::value<double>(&wave_freq)->default_value(0), "waveform frequency in Hz") ("ref", po::value<std::string>(&ref)->default_value("internal"), "clock reference (internal, external, mimo, gpsdo)") ("pps", po::value<std::string>(&pps), "PPS source (internal, external, mimo, gpsdo)") ("otw", po::value<std::string>(&otw)->default_value("sc16"), "specify the over-the-wire sample mode") ("channels", po::value<std::string>(&channel_list)->default_value("0"), "which channels to use (specify \"0\", \"1\", \"0,1\", etc)") ("int-n", "tune USRP with integer-N tuning") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); //print the help message if (vm.count("help")){ std::cout << boost::format("UHD TX Waveforms %s") % desc << std::endl; return ~0; } //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //detect which channels to use std::vector<std::string> channel_strings; std::vector<size_t> channel_nums; boost::split(channel_strings, channel_list, boost::is_any_of("\"',")); for(size_t ch = 0; ch < channel_strings.size(); ch++){ size_t chan = boost::lexical_cast<int>(channel_strings[ch]); if(chan >= usrp->get_tx_num_channels()) throw std::runtime_error("Invalid channel(s) specified."); else channel_nums.push_back(boost::lexical_cast<int>(channel_strings[ch])); } //Lock mboard clocks usrp->set_clock_source(ref); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_tx_subdev_spec(subdev); std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //set the sample rate if (not vm.count("rate")){ std::cerr << "Please specify the sample rate with --rate" << std::endl; return ~0; } std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_tx_rate(rate); std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl; //set the center frequency if (not vm.count("freq")){ std::cerr << "Please specify the center frequency with --freq" << std::endl; return ~0; } for(size_t ch = 0; ch < channel_nums.size(); ch++) { std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq/1e6) << std::endl; uhd::tune_request_t tune_request(freq); if(vm.count("int-n")) tune_request.args = uhd::device_addr_t("mode_n=integer"); usrp->set_tx_freq(tune_request, channel_nums[ch]); std::cout << boost::format("Actual TX Freq: %f MHz...") % (usrp->get_tx_freq(channel_nums[ch])/1e6) << std::endl << std::endl; //set the rf gain if (vm.count("gain")){ std::cout << boost::format("Setting TX Gain: %f dB...") % gain << std::endl; usrp->set_tx_gain(gain, channel_nums[ch]); std::cout << boost::format("Actual TX Gain: %f dB...") % usrp->get_tx_gain(channel_nums[ch]) << std::endl << std::endl; } //set the analog frontend filter bandwidth if (vm.count("bw")){ std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % bw << std::endl; usrp->set_tx_bandwidth(bw, channel_nums[ch]); std::cout << boost::format("Actual TX Bandwidth: %f MHz...") % usrp->get_tx_bandwidth(channel_nums[ch]) << std::endl << std::endl; } //set the antenna if (vm.count("ant")) usrp->set_tx_antenna(ant, channel_nums[ch]); } boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time //for the const wave, set the wave freq for small samples per period if (wave_freq == 0 and wave_type == "CONST"){ wave_freq = usrp->get_tx_rate()/2; } //error when the waveform is not possible to generate if (std::abs(wave_freq) > usrp->get_tx_rate()/2){ throw std::runtime_error("wave freq out of Nyquist zone"); } if (usrp->get_tx_rate()/std::abs(wave_freq) > wave_table_len/2){ throw std::runtime_error("wave freq too small for table"); } //pre-compute the waveform values const wave_table_class wave_table(wave_type, ampl); const size_t step = boost::math::iround(wave_freq/usrp->get_tx_rate() * wave_table_len); size_t index = 0; //create a transmit streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) uhd::stream_args_t stream_args("fc32", otw); stream_args.channels = channel_nums; uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate a buffer which we re-use for each channel if (spb == 0) spb = tx_stream->get_max_num_samps()*10; std::vector<std::complex<float> > buff(spb); std::vector<std::complex<float> *> buffs(channel_nums.size(), &buff.front()); std::cout << boost::format("Setting device timestamp to 0...") << std::endl; if (channel_nums.size() > 1) { // Sync times if (pps == "mimo") { UHD_ASSERT_THROW(usrp->get_num_mboards() == 2); //make mboard 1 a slave over the MIMO Cable usrp->set_time_source("mimo", 1); //set time on the master (mboard 0) usrp->set_time_now(uhd::time_spec_t(0.0), 0); //sleep a bit while the slave locks its time to the master boost::this_thread::sleep(boost::posix_time::milliseconds(100)); } else { if (pps == "internal" or pps == "external" or pps == "gpsdo") usrp->set_time_source(pps); usrp->set_time_unknown_pps(uhd::time_spec_t(0.0)); boost::this_thread::sleep(boost::posix_time::seconds(1)); //wait for pps sync pulse } } else { usrp->set_time_now(0.0); } //Check Ref and LO Lock detect std::vector<std::string> sensor_names; const size_t tx_sensor_chan = channel_list.empty() ? 0 : boost::lexical_cast<size_t>(channel_list[0]); sensor_names = usrp->get_tx_sensor_names(tx_sensor_chan); if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) { uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked", tx_sensor_chan); std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } const size_t mboard_sensor_idx = 0; sensor_names = usrp->get_mboard_sensor_names(mboard_sensor_idx); if ((ref == "mimo") and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") != sensor_names.end())) { uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked", mboard_sensor_idx); std::cout << boost::format("Checking TX: %s ...") % mimo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(mimo_locked.to_bool()); } if ((ref == "external") and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())) { uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked", mboard_sensor_idx); std::cout << boost::format("Checking TX: %s ...") % ref_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(ref_locked.to_bool()); } std::signal(SIGINT, &sig_int_handler); std::cout << "Press Ctrl + C to stop streaming..." << std::endl; // Set up metadata. We start streaming a bit in the future // to allow MIMO operation: uhd::tx_metadata_t md; md.start_of_burst = true; md.end_of_burst = false; md.has_time_spec = true; md.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.1); //send data until the signal handler gets called //or if we accumulate the number of samples specified (unless it's 0) uint64_t num_acc_samps = 0; while(true){ if (stop_signal_called) break; if (total_num_samps > 0 and num_acc_samps >= total_num_samps) break; //fill the buffer with the waveform for (size_t n = 0; n < buff.size(); n++){ buff[n] = wave_table(index += step); } //send the entire contents of the buffer num_acc_samps += tx_stream->send( buffs, buff.size(), md ); md.start_of_burst = false; md.has_time_spec = false; } //send a mini EOB packet md.end_of_burst = true; tx_stream->send("", 0, md); //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return EXIT_SUCCESS; }
double set_frequency(double target_freq, bool int_n_mode, bool flush = false) { static const double REF_DOUBLER_THRESH_FREQ = 12.5e6; static const double PFD_FREQ_MAX = 25.0e6; static const double BAND_SEL_FREQ_MAX = 100e3; static const double VCO_FREQ_MIN = 2.2e9; static const double VCO_FREQ_MAX = 4.4e9; //Default invalid value for actual_freq double actual_freq = 0; uhd::range_t rf_divider_range = _get_rfdiv_range(); uhd::range_t int_range = get_int_range(); double pfd_freq = 0; boost::uint16_t R = 0, BS = 0, N = 0, FRAC = 0, MOD = 0; boost::uint16_t RFdiv = static_cast<boost::uint16_t>(rf_divider_range.start()); bool D = false, T = false; //Reference doubler for 50% duty cycle D = (_reference_freq <= REF_DOUBLER_THRESH_FREQ); //increase RF divider until acceptable VCO frequency double vco_freq = target_freq; while (vco_freq < VCO_FREQ_MIN && RFdiv < static_cast<boost::uint16_t>(rf_divider_range.stop())) { vco_freq *= 2; RFdiv *= 2; } /* * The goal here is to loop though possible R dividers, * band select clock dividers, N (int) dividers, and FRAC * (frac) dividers. * * Calculate the N and F dividers for each set of values. * The loop exits when it meets all of the constraints. * The resulting loop values are loaded into the registers. * * from pg.21 * * f_pfd = f_ref*(1+D)/(R*(1+T)) * f_vco = (N + (FRAC/MOD))*f_pfd * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD * f_actual = f_vco/RFdiv) */ double feedback_freq = _fb_after_divider ? target_freq : vco_freq; for(R = 1; R <= 1023; R+=1){ //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) pfd_freq = _reference_freq*(D?2:1)/(R*(T?2:1)); //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) if (pfd_freq > PFD_FREQ_MAX) continue; //First, ignore fractional part of tuning N = boost::uint16_t(std::floor(feedback_freq/pfd_freq)); //keep N > minimum int divider requirement if (N < static_cast<boost::uint16_t>(int_range.start())) continue; for(BS=1; BS <= 255; BS+=1){ //keep the band select frequency at or below band_sel_freq_max //constraint on band select clock if (pfd_freq/BS > BAND_SEL_FREQ_MAX) continue; goto done_loop; } } done_loop: //Fractional-N calculation MOD = 4095; //max fractional accuracy FRAC = static_cast<boost::uint16_t>(boost::math::round((feedback_freq/pfd_freq - N)*MOD)); if (int_n_mode) { if (FRAC > (MOD / 2)) { //Round integer such that actual freq is closest to target N++; } FRAC = 0; } //Reference divide-by-2 for 50% duty cycle // if R even, move one divide by 2 to to regs.reference_divide_by_2 if(R % 2 == 0) { T = true; R /= 2; } //Typical phase resync time documented in data sheet pg.24 static const double PHASE_RESYNC_TIME = 400e-6; //If feedback after divider, then compensation for the divider is pulled into the INT value int rf_div_compensation = _fb_after_divider ? 1 : RFdiv; //Compute the actual frequency in terms of _reference_freq, N, FRAC, MOD, D, R and T. actual_freq = ( double((N + (double(FRAC)/double(MOD))) * (_reference_freq*(D?2:1)/(R*(T?2:1)))) ) / rf_div_compensation; _regs.frac_12_bit = FRAC; _regs.int_16_bit = N; _regs.mod_12_bit = MOD; _regs.clock_divider_12_bit = std::max<boost::uint16_t>(1, boost::uint16_t(std::ceil(PHASE_RESYNC_TIME*pfd_freq/MOD))); _regs.feedback_select = _fb_after_divider ? adf435x_regs_t::FEEDBACK_SELECT_DIVIDED : adf435x_regs_t::FEEDBACK_SELECT_FUNDAMENTAL; _regs.clock_div_mode = _fb_after_divider ? adf435x_regs_t::CLOCK_DIV_MODE_RESYNC_ENABLE : adf435x_regs_t::CLOCK_DIV_MODE_FAST_LOCK; _regs.r_counter_10_bit = R; _regs.reference_divide_by_2 = T ? adf435x_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED : adf435x_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; _regs.reference_doubler = D ? adf435x_regs_t::REFERENCE_DOUBLER_ENABLED : adf435x_regs_t::REFERENCE_DOUBLER_DISABLED; _regs.band_select_clock_div = boost::uint8_t(BS); _regs.rf_divider_select = static_cast<typename adf435x_regs_t::rf_divider_select_t>(_get_rfdiv_setting(RFdiv)); _regs.ldf = int_n_mode ? adf435x_regs_t::LDF_INT_N : adf435x_regs_t::LDF_FRAC_N; std::string tuning_str = (int_n_mode) ? "Integer-N" : "Fractional"; UHD_LOGV(often) << boost::format("ADF 435X Frequencies (MHz): REQUESTED=%0.9f, ACTUAL=%0.9f" ) % (target_freq/1e6) % (actual_freq/1e6) << std::endl << boost::format("ADF 435X Intermediates (MHz): Feedback=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f, REF=%0.2f" ) % (feedback_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) % (_reference_freq/1e6) << std::endl << boost::format("ADF 435X Tuning: %s") % tuning_str.c_str() << std::endl << boost::format("ADF 435X Settings: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d" ) % R % BS % N % FRAC % MOD % T % D % RFdiv << std::endl; UHD_ASSERT_THROW((_regs.frac_12_bit & ((boost::uint16_t)~0xFFF)) == 0); UHD_ASSERT_THROW((_regs.mod_12_bit & ((boost::uint16_t)~0xFFF)) == 0); UHD_ASSERT_THROW((_regs.clock_divider_12_bit & ((boost::uint16_t)~0xFFF)) == 0); UHD_ASSERT_THROW((_regs.r_counter_10_bit & ((boost::uint16_t)~0x3FF)) == 0); UHD_ASSERT_THROW(vco_freq >= VCO_FREQ_MIN and vco_freq <= VCO_FREQ_MAX); UHD_ASSERT_THROW(RFdiv >= static_cast<boost::uint16_t>(rf_divider_range.start())); UHD_ASSERT_THROW(RFdiv <= static_cast<boost::uint16_t>(rf_divider_range.stop())); UHD_ASSERT_THROW(_regs.int_16_bit >= static_cast<boost::uint16_t>(int_range.start())); UHD_ASSERT_THROW(_regs.int_16_bit <= static_cast<boost::uint16_t>(int_range.stop())); if (flush) commit(); return actual_freq; }
//! Return the index of a radio component, given a slot name. This means DSPs, radio_perifs size_t get_radio_index(const std::string &slot_name) { UHD_ASSERT_THROW(slot_name == "A" or slot_name == "B"); return slot_name == "A" ? 0 : 1; }
int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args, sync, subdev; double seconds_in_future; size_t total_num_samps; double rate; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args") ("secs", po::value<double>(&seconds_in_future)->default_value(1.5), "number of seconds in the future to receive") ("nsamps", po::value<size_t>(&total_num_samps)->default_value(10000), "total number of samples to receive") ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of incoming samples") ("sync", po::value<std::string>(&sync)->default_value("now"), "synchronization method: now, pps, mimo") ("subdev", po::value<std::string>(&subdev), "subdev spec (homogeneous across motherboards)") ("dilv", "specify to disable inner-loop verbose") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); //print the help message if (vm.count("help")){ std::cout << boost::format("UHD RX Multi Samples %s") % desc << std::endl; std::cout << " This is a demonstration of how to receive aligned data from multiple channels.\n" " This example can receive from multiple DSPs, multiple motherboards, or both.\n" " The MIMO cable or PPS can be used to synchronize the configuration. See --sync\n" "\n" " Specify --subdev to select multiple channels per motherboard.\n" " Ex: --subdev=\"0:A 0:B\" to get 2 channels on a Basic RX.\n" "\n" " Specify --args to select multiple motherboards in a configuration.\n" " Ex: --args=\"addr0=192.168.10.2, addr1=192.168.10.3\"\n" << std::endl; return ~0; } bool verbose = vm.count("dilv") == 0; //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_rx_subdev_spec(subdev); //sets across all mboards std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //set the rx sample rate (sets across all channels) std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_rx_rate(rate); std::cout << boost::format("Actual RX Rate: %f Msps...") % (usrp->get_rx_rate()/1e6) << std::endl << std::endl; std::cout << boost::format("Setting device timestamp to 0...") << std::endl; if (sync == "now"){ //This is not a true time lock, the devices will be off by a few RTT. //Rather, this is just to allow for demonstration of the code below. usrp->set_time_now(uhd::time_spec_t(0.0)); } else if (sync == "pps"){ usrp->set_time_source("external"); usrp->set_time_unknown_pps(uhd::time_spec_t(0.0)); boost::this_thread::sleep(boost::posix_time::seconds(1)); //wait for pps sync pulse } else if (sync == "mimo"){ UHD_ASSERT_THROW(usrp->get_num_mboards() == 2); //make mboard 1 a slave over the MIMO Cable usrp->set_clock_source("mimo", 1); usrp->set_time_source("mimo", 1); //set time on the master (mboard 0) usrp->set_time_now(uhd::time_spec_t(0.0), 0); //sleep a bit while the slave locks its time to the master boost::this_thread::sleep(boost::posix_time::milliseconds(100)); } //create a receive streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) uhd::stream_args_t stream_args("fc32"); //complex floats for (size_t chan = 0; chan < usrp->get_rx_num_channels(); chan++) stream_args.channels.push_back(chan); //linear mapping uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming std::cout << std::endl; std::cout << boost::format( "Begin streaming %u samples, %f seconds in the future..." ) % total_num_samps % seconds_in_future << std::endl; uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); stream_cmd.num_samps = total_num_samps; stream_cmd.stream_now = false; stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); usrp->issue_stream_cmd(stream_cmd); //tells all channels to stream //meta-data will be filled in by recv() uhd::rx_metadata_t md; //allocate buffers to receive with samples (one buffer per channel) const size_t samps_per_buff = rx_stream->get_max_num_samps(); std::vector<std::vector<std::complex<float> > > buffs( usrp->get_rx_num_channels(), std::vector<std::complex<float> >(samps_per_buff) ); //create a vector of pointers to point to each of the channel buffers std::vector<std::complex<float> *> buff_ptrs; for (size_t i = 0; i < buffs.size(); i++) buff_ptrs.push_back(&buffs[i].front()); //the first call to recv() will block this many seconds before receiving double timeout = seconds_in_future + 0.1; //timeout (delay before receive + padding) size_t num_acc_samps = 0; //number of accumulated samples while(num_acc_samps < total_num_samps){ //receive a single packet size_t num_rx_samps = rx_stream->recv( buff_ptrs, samps_per_buff, md, timeout ); //use a small timeout for subsequent packets timeout = 0.1; //handle the error code if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) break; if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){ throw std::runtime_error(str(boost::format( "Unexpected error code 0x%x" ) % md.error_code)); } if(verbose) std::cout << boost::format( "Received packet: %u samples, %u full secs, %f frac secs" ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; num_acc_samps += num_rx_samps; } if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout before all samples received..." << std::endl; //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return 0; }
int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); std::string args, tx_file, rx_file, type, ref, wire_format, cpu_format; size_t samples_per_buff; double rate, freq, tx_gain, rx_gain, rx_bw, delay, lo_off; rx_bw = RX_BW; rx_gain = RX_GAIN; wire_format = WIRE_FORMAT; cpu_format = CPU_FORMAT; rate = SAMP_RATE; args = ARGS; ref = REF_CLOCK; freq = CENT_FREQ; tx_gain = TX_GAIN; samples_per_buff = SAMPLES_PER_BUFFER; tx_file = TX_FILENAME; rx_file = RX_FILENAME; //------------------INIT TX------------------ //Set the scheduling priority on the current thread. Same as set_thread_priority but does not throw on failure. std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Make the usrp by calling the constructor with param the args usrp->set_clock_source(ref); //Set the clock source for the usrp device. This sets the source for a 10 MHz reference clock. Typical options for source: internal, external, MIMO. std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_tx_rate(rate); //Set the sample rate std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl << std::endl; std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq/1e6) << std::endl; //Set up tuning frequency uhd::tune_request_t tune_request; tune_request = uhd::tune_request_t(freq); //Generate the tune request usrp->set_tx_freq(tune_request); //Tune to CENT_FREQ std::cout << boost::format("Actual TX Freq: %f MHz...") % (usrp->get_tx_freq()/1e6) << std::endl << std::endl; //PRINT Actual CENT_FREQ std::cout << boost::format("Setting TX Gain: %f dB...") % tx_gain << std::endl; usrp->set_tx_gain(tx_gain); //Set the tx_gain std::cout << boost::format("Actual TX Gain: %f dB...") % usrp->get_tx_gain() << std::endl << std::endl; //------------------CHECK STUFF------------------ //Check Ref and LO Lock detect std::vector<std::string> sensor_names; sensor_names = usrp->get_tx_sensor_names(0); if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) { uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked",0); std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string() << std::endl; UHD_ASSERT_THROW(lo_locked.to_bool()); } //------------------INIT TX STREAM------------------ //create a transmit streamer uhd::stream_args_t stream_args(cpu_format, wire_format); //Call the constructor of the class stream_args_t and generate the stream_args object with inputs the cpu_format and wire_format (this is the format per sample) uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //Generate a tx_streamer object named tx_stream using the usrp->get_tx_stream(stream_args). Remember, usrp is already initialized //Setup tx_metadata uhd::tx_metadata_t tx_md; //TX metadata structure for describing received IF data. Includes time specification, and start and stop burst flags. The send routines will convert the metadata to IF data headers. tx_md.start_of_burst = false; //Set start of burst to true for the first packet in the chain. ? tx_md.end_of_burst = false; //------------------LOAD DATA AND TX------------------ std::vector<std::complex<float> > tx_buff(samples_per_buff); std::ifstream infile(tx_file.c_str(), std::ifstream::binary); if(!infile.good()){ std::cout << "IN File error\n"; return 0; } //loop until the entire file has been read int i = 0; for (int i = 0; i < samples_per_buff; ++i){ infile.read((char*)&tx_buff.at(i), tx_buff.size()*sizeof(std::complex<float>)); // std::cout << tx_buff.at(i) << ' '; } tx_stream->send(&tx_buff.front(), samples_per_buff, tx_md); infile.close(); //Close the file pointer //------------------INIT RX------------------ //IS THIS NECESSARY? //always select the subdevice first, the channel mapping affects the other settings //usrp->set_rx_subdev_spec(subdev); std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; usrp->set_rx_rate(rate); std::cout << boost::format("Actual RX Rate: %f Msps...") % (usrp->get_rx_rate()/1e6) << std::endl << std::endl; //set the center frequency std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6) << std::endl; usrp->set_rx_freq(tune_request); std::cout << boost::format("Actual RX Freq: %f MHz...") % (usrp->get_rx_freq()/1e6) << std::endl << std::endl; std::cout << boost::format("Setting RX Gain: %f dB...") % rx_gain << std::endl; usrp->set_rx_gain(rx_gain); std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl; boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow 1sec setup time //------------------CHECK STUFF------------------ //Always check for locked sensor check_locked_sensor(usrp->get_rx_sensor_names(0), "lo_locked", boost::bind(&uhd::usrp::multi_usrp::get_rx_sensor, usrp, _1, 0), 1); //------------------INIT RX STREAM--------------- //create a receive streamer with the same args as TX uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); uhd::rx_metadata_t rx_md; std::vector<std::complex<float> > rx_buff(samples_per_buff); std::ofstream outfile; outfile.open(rx_file.c_str(), std::ofstream::binary); if(!outfile.good()){ std::cout << "OUT File error\n"; return 0; } //If RX_CONT == 1 enable continuoys sampling else just sent some packets and done uhd::stream_cmd_t stream_cmd((RX_CONT == 1)? uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS: uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE ); stream_cmd.num_samps = samples_per_buff; //You might have a problem here... stream_cmd.stream_now = true; //Start streaming ASAP stream_cmd.time_spec = uhd::time_spec_t(); //Setup the time to the USRP time (Why??) rx_stream->issue_stream_cmd(stream_cmd); //Issue a stream command to the usrp device. This tells the usrp to send samples into the host. See the documentation for stream_cmd_t for more info. size_t num_rx_samps = rx_stream->recv(&rx_buff.front(), rx_buff.size(), rx_md, 10.0, false); // Receive buffers containing samples described by the metadata. std::cout << "Samples received in a single shot: " << num_rx_samps << std::endl; if (outfile.is_open()){ outfile.write((const char*)&rx_buff.front(), num_rx_samps*sizeof(std::complex<float>)-1); } return EXIT_SUCCESS; }