Hello, I'm trying to make a uhd program that is basically the rfnoc version of the non-RFNOC Tx_waveforms example in uhd/host/examples.
What I am trying to do is transmit samples (from a wave table for example), using the rfnoc radio block. Note that I am cross compiling for an E310 usrp. Also note that the other two RX rfnoc examples do run for me on the E310. I have pasted the code below. This compiles with no problems, however, when run on the E310, it hangs indefinitely at usrp->get_txstream In this case the usrp object is a device3 object. Also note that I am using the uhd development branch with uhd version 4.0.0.rfnoc-devel-409 Thanks, Jack #include <fcntl.h> #include <sys/ioctl.h> #include <linux/types.h> #include <linux/spi/spidev.h> #include "wavetable.hpp" #include <uhd/utils/thread_priority.hpp> #include <uhd/utils/safe_main.hpp> #include <uhd/utils/static.hpp> #include <uhd/usrp/multi_usrp.hpp> #include <uhd/device3.hpp> #include <uhd/rfnoc/radio_ctrl.hpp> #include <uhd/rfnoc/source_block_ctrl_base.hpp> #include <uhd/exception.hpp> #include <boost/program_options.hpp> #include <boost/math/special_functions/round.hpp> #include <boost/foreach.hpp> #include <boost/format.hpp> #include <boost/thread.hpp> #include <boost/lexical_cast.hpp> #include <boost/algorithm/string.hpp> #include <stdint.h> #include <iostream> #include <csignal> //#include "../lib/usrp/common/ad9361_ctrl.hpp" namespace po = boost::program_options; /*********************************************************************** * Signal handlers **********************************************************************/ static bool stop_signal_called = false; void sig_int_handler(int){stop_signal_called = true;} /*********************************************************************** * 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") ("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::device3::sptr usrp = uhd::device3::make(args); //detect which channels to use std::vector<std::string> channel_strings; std::vector<size_t> channel_nums; std::vector<uhd::rfnoc::radio_ctrl::sptr> radios; std::vector<uhd::rfnoc::block_id_t> radio_ids; 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]); channel_nums.push_back(boost::lexical_cast<int>(channel_strings[ch])); uhd::rfnoc::block_id_t radio_ctrl_id(0, "Radio", boost::lexical_cast<int>(channel_strings[ch])); uhd::rfnoc::radio_ctrl::sptr radio_ctrl = usrp->get_block_ctrl< uhd::rfnoc::radio_ctrl >(radio_ctrl_id); radios.push_back(radio_ctrl); radio_ids.push_back(radio_ctrl_id); } //set the sample rate if (not vm.count("rate")){ std::cerr << "Please specify the sample rate with --rate" << std::endl; return ~0; } for(size_t r = 0; r<radios.size();r++){ std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl; radios[r]->set_rate(rate); std::cout << boost::format("Actual TX Rate: %f Msps...") % (radios[r]->get_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 r = 0; r < radios.size(); r++) { 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"); radios[r]->set_tx_frequency(freq, channel_nums[r]); std::cout << boost::format("Actual TX Freq: %f MHz...") % (radios[r]->get_tx_frequency(channel_nums[r])/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; radios[r]->set_tx_gain(gain, channel_nums[r]); //std::cout << boost::format("Actual TX Gain: %f dB...") % radios[r]->get_tx_gain(radios[r]) << std::endl << std::endl; } //set the antenna if (vm.count("ant")) radios[r]->set_tx_antenna(ant, channel_nums[r]); } 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 = radios[0]->get_tx_frequency(channel_nums[0])/2; } //error when the waveform is not possible to generate if (std::abs(wave_freq) > radios[0]->get_tx_frequency(channel_nums[0])/2){ throw std::runtime_error("wave freq out of Nyquist zone"); } if (radios[0]->get_tx_frequency(channel_nums[0])/std::abs(wave_freq) > wave_table_len/2){ throw std::runtime_error("wave freq too small for table"); } std::vector<size_t> spp; for (size_t r = 0; r < radios.size(); r++){ spp.push_back(radios[r]->get_arg<int>("spp")); } //pre-compute the waveform values const wave_table_class wave_table(wave_type, ampl); const size_t step = boost::math::iround(wave_freq/radios[0]->get_tx_frequency(channel_nums[0]) * wave_table_len); size_t index = 0; uhd::rfnoc::graph::sptr tx_graph = usrp->create_graph("tx_waveforms"); usrp->clear(); //create a transmit streamer for each device //linearly map channels (index0 = channel0, index1 = channel1, ...) std::vector<uhd::tx_streamer::sptr> tx_streams; uhd::device_addr_t streamer_args(""); std::cout << "block id" << radio_ids[0] << std::endl; std::cout << "block id" << channel_nums[0] << std::endl; streamer_args["block_id"] = radio_ids[0].to_string(); streamer_args["block_port"] = str(boost::format("%d") % channel_nums[0]); //create a tx streamer std::cout << "Samples per packet: " << spp[0] << std::endl; uhd::stream_args_t stream_args("fc32", "sc16"); // We should read the wire format from the blocks stream_args.channels = channel_nums; stream_args.args = streamer_args; stream_args.args["spp"] = boost::lexical_cast<std::string>(spp[0]); std::cout << "Using streamer args: " << stream_args.args.to_string() << std::endl; printf("Getting tx stream\n"); uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); /////****** THIS IS WHERE IT HANGS!!! **************//////// tx_streams.push_back(tx_stream); printf("Got tx stream\n"); std::cout << "Done" << std::endl; //allocate a buffer which we re-use for each channel if (spb == 0) spb = tx_streams[0]->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 << "Buffer allocated" << std::endl; //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]); 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 = false; int freq_iter=0; //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; printf("Before wave table\n"); //fill the buffer with the waveform for (size_t n = 0; n < buff.size(); n++){ buff[n] = wave_table(index += step); } while(true){ if (stop_signal_called) break; if (total_num_samps > 0 and num_acc_samps >= total_num_samps) break; //send the entire contents of the buffer for ( int s; s < tx_streams.size(); s++){ num_acc_samps += tx_streams[s]->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; for ( int s; s < tx_streams.size(); s++){ tx_streams[s]->send("", 0, md); } //finished std::cout << std::endl << "Done!" << std::endl << std::endl; return EXIT_SUCCESS; }
_______________________________________________ USRP-users mailing list USRP-users@lists.ettus.com http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com