diff options
Diffstat (limited to 'host/examples/tx_waveforms.cpp')
-rw-r--r-- | host/examples/tx_waveforms.cpp | 89 |
1 files changed, 59 insertions, 30 deletions
diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index e9cf210bb..9886000b1 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -20,19 +20,41 @@ #include <uhd/usrp/simple_usrp.hpp> #include <boost/program_options.hpp> #include <boost/thread/thread_time.hpp> //system time +#include <boost/math/special_functions/round.hpp> #include <boost/format.hpp> +#include <boost/function.hpp> #include <iostream> #include <complex> #include <cmath> namespace po = boost::program_options; +/*********************************************************************** + * Waveform generators + **********************************************************************/ +float gen_const(float){ + return 1; +} + +float gen_square(float x){ + return float((std::fmod(x, 1) < float(0.5))? 0 : 1); +} + +float gen_ramp(float x){ + return std::fmod(x, 1)*2 - 1; +} + +float gen_sine(float x){ + static const float two_pi = 2*std::acos(float(-1)); + return std::sin(x*two_pi); +} + int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args, wave_type; - size_t total_duration, amspb; + size_t total_duration, spb; double rate, freq, wave_freq; float ampl, gain; @@ -42,7 +64,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "simple uhd device address args") ("duration", po::value<size_t>(&total_duration)->default_value(3), "number of seconds to transmit") - ("amspb", po::value<size_t>(&amspb)->default_value(10000), "approximate mimimum samples per buffer") + ("spb", po::value<size_t>(&spb)->default_value(10000), "samples per buffer") ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of outgoing samples") ("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz") ("ampl", po::value<float>(&l)->default_value(float(0.3)), "amplitude of the waveform") @@ -88,33 +110,24 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //error when the waveform is not possible to generate - if (std::abs(wave_freq)/sdev->get_tx_rate() < 0.5/amspb){ - throw std::runtime_error("wave freq/tx rate too small"); - } if (std::abs(wave_freq) > sdev->get_tx_rate()/2){ throw std::runtime_error("wave freq out of Nyquist zone"); } - //fill a buffer with one period worth of samples - std::vector<float> period(size_t(sdev->get_tx_rate()/std::abs(wave_freq))); - std::cout << boost::format("Samples per waveform period: %d") % period.size() << std::endl; - for (size_t n = 0; n < period.size(); n++){ - if (wave_type == "CONST") period[n] = ampl; - else if (wave_type == "SQUARE") period[n] = (n > period.size()/2)? ampl : 0; - else if (wave_type == "RAMP") period[n] = float((n/double(period.size()-1)) * 2*ampl - ampl); - else if (wave_type == "SINE") period[n] = ampl*float(std::sin(2*M_PI*n/double(period.size()))); - else throw std::runtime_error("unknown waveform type: " + wave_type); - } - - //allocate data to send (fill with several periods worth of IQ samples) - const size_t periods_per_buff = std::max<size_t>(1, amspb/period.size()); - std::vector<std::complex<float> > buff(period.size()*periods_per_buff); - std::cout << boost::format("Samples per send buffer: %d") % buff.size() << std::endl; - const size_t i_ahead = (wave_freq > 0)? period.size()/4 : 0; - const size_t q_ahead = (wave_freq < 0)? period.size()/4 : 0; - for (size_t n = 0; n < buff.size(); n++) buff[n] = std::complex<float>( - period[(n+i_ahead)%period.size()], period[(n+q_ahead)%period.size()] //I,Q - ); + //store the generator function for the selected waveform + boost::function<float(float)> wave_gen; + if (wave_type == "CONST") wave_gen = &gen_const; + else if (wave_type == "SQUARE") wave_gen = &gen_square; + else if (wave_type == "RAMP") wave_gen = &gen_ramp; + else if (wave_type == "SINE") wave_gen = &gen_sine; + else throw std::runtime_error("unknown waveform type: " + wave_type); + + //allocate the buffer and precalculate values + std::vector<std::complex<float> > buff(spb); + const float cps = float(wave_freq/sdev->get_tx_rate()); + const float i_off = (wave_freq > 0)? float(0.25) : 0; + const float q_off = (wave_freq < 0)? float(0.25) : 0; + float theta = 0; //setup the metadata flags uhd::tx_metadata_t md; @@ -123,11 +136,27 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //send the data in multiple packets boost::system_time end_time(boost::get_system_time() + boost::posix_time::seconds(total_duration)); - while(end_time > boost::get_system_time()) dev->send( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF - ); + while(end_time > boost::get_system_time()){ + + //fill the buffer with the waveform + for (size_t n = 0; n < buff.size(); n++){ + buff[n] = std::complex<float>( + ampl*wave_gen(i_off + theta), + ampl*wave_gen(q_off + theta) + ); + theta += cps; + } + + //bring the theta back into range [0, 1) + theta = std::fmod(theta, 1); + + //send the entire contents of the buffer + dev->send( + &buff.front(), buff.size(), md, + uhd::io_type_t::COMPLEX_FLOAT32, + uhd::device::SEND_MODE_FULL_BUFF + ); + } //send a mini EOB packet md.start_of_burst = false; |