diff options
Diffstat (limited to 'host')
-rw-r--r-- | host/examples/tx_waveforms.cpp | 112 | ||||
-rw-r--r-- | host/include/uhd/usrp/dboard_iface.hpp | 8 | ||||
-rw-r--r-- | host/include/uhd/usrp/simple_usrp.hpp | 9 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_basic_and_lf.cpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/simple_usrp.cpp | 16 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dboard_iface.cpp | 20 |
6 files changed, 100 insertions, 73 deletions
diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index b9b24f516..9886000b1 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -22,19 +22,40 @@ #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, mspb; - double rate, freq, wave_freq, aepb; + size_t total_duration, spb; + double rate, freq, wave_freq; float ampl, gain; //setup the program options @@ -43,8 +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") - ("mspb", po::value<size_t>(&mspb)->default_value(10000), "mimimum samples per buffer") - ("aepb", po::value<double>(&aepb)->default_value(1e-5), "allowed error 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") @@ -90,57 +110,25 @@ 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/mspb){ - 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"); } - //how many periods should we have per buffer to mimimize error - double samps_per_period = sdev->get_tx_rate()/std::abs(wave_freq); - std::cout << boost::format("Samples per waveform period: %d") % samps_per_period << std::endl; - size_t periods_per_buff = std::max<size_t>(1, mspb/samps_per_period); - while (true){ - double num_samps_per_buff = periods_per_buff*samps_per_period; - double sample_error = num_samps_per_buff - boost::math::round(num_samps_per_buff); - if (std::abs(sample_error) <= aepb) break; - periods_per_buff++; - } - - //allocate data to send (fill with several periods worth of IQ samples) - std::vector<std::complex<float> > buff(samps_per_period*periods_per_buff); - const double i_ahead = (wave_freq > 0)? samps_per_period/4 : 0; - const double q_ahead = (wave_freq < 0)? samps_per_period/4 : 0; - std::cout << boost::format("Samples per send buffer: %d") % buff.size() << std::endl; - if (wave_type == "CONST"){ - for (size_t n = 0; n < buff.size(); n++){ - buff[n] = std::complex<float>(ampl, ampl); - } - } - else if (wave_type == "SQUARE"){ - for (size_t n = 0; n < buff.size(); n++){ - float I = (std::fmod(n+i_ahead, samps_per_period) > samps_per_period/2)? ampl : 0; - float Q = (std::fmod(n+q_ahead, samps_per_period) > samps_per_period/2)? ampl : 0; - buff[n] = std::complex<float>(I, Q); - } - } - else if (wave_type == "RAMP"){ - for (size_t n = 0; n < buff.size(); n++){ - float I = float(std::fmod(n+i_ahead, samps_per_period)/samps_per_period * 2*ampl - ampl); - float Q = float(std::fmod(n+q_ahead, samps_per_period)/samps_per_period * 2*ampl - ampl); - buff[n] = std::complex<float>(I, Q); - } - } - else if (wave_type == "SINE"){ - for (size_t n = 0; n < buff.size(); n++){ - float I = float(ampl*std::sin(2*M_PI*(n+i_ahead)/samps_per_period)); - float Q = float(ampl*std::sin(2*M_PI*(n+q_ahead)/samps_per_period)); - buff[n] = std::complex<float>(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; md.start_of_burst = true; //always SOB (good for continuous streaming) @@ -148,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; diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp index e776ecc42..c7db244f2 100644 --- a/host/include/uhd/usrp/dboard_iface.hpp +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -148,6 +148,14 @@ public: virtual void write_gpio(unit_t unit, boost::uint16_t value) = 0; /*! + * Setup the GPIO debug mux. + * + * \param unit which unit rx or tx + * \param which which debug: 0, 1 + */ + virtual void set_gpio_debug(unit_t unit, int which) = 0; + + /*! * Read daughterboard GPIO pin values. * * \param unit which unit rx or tx diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index c2c7505af..08b9c01ea 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -25,6 +25,7 @@ #include <uhd/types/clock_config.hpp> #include <uhd/types/tune_result.hpp> #include <uhd/usrp/subdev_spec.hpp> +#include <uhd/usrp/dboard_iface.hpp> #include <boost/shared_ptr.hpp> #include <boost/utility.hpp> #include <vector> @@ -136,6 +137,8 @@ public: */ virtual float read_rssi(void) = 0; + virtual dboard_iface::sptr get_rx_dboard_iface(void) = 0; + /******************************************************************* * TX methods ******************************************************************/ @@ -160,11 +163,7 @@ public: virtual bool get_tx_lo_locked(void) = 0; - /******************************************************************* - * Interface access methods - ******************************************************************/ - virtual wax::obj get_rx_dboard_iface(void) = 0; - virtual wax::obj get_tx_dboard_iface(void) = 0; + virtual dboard_iface::sptr get_tx_dboard_iface(void) = 0; }; }} diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index f8236d598..0b6e4a75a 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -170,8 +170,8 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_ANTENNA: - UHD_ASSERT_THROW(val.as<std::string>() == std::string("")); - return; + if (val.as<std::string>().empty()) return; + throw std::runtime_error("no selectable antennas on this board"); case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it @@ -259,8 +259,8 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_ANTENNA: - UHD_ASSERT_THROW(val.as<std::string>() == std::string("")); - return; + if (val.as<std::string>().empty()) return; + throw std::runtime_error("no selectable antennas on this board"); case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index 5b4a58805..e573d0fc0 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -168,6 +168,10 @@ public: return _rx_subdev()[SUBDEV_PROP_RSSI].as<float>(); } + dboard_iface::sptr get_rx_dboard_iface(void){ + return _rx_dboard()[DBOARD_PROP_DBOARD_IFACE].as<dboard_iface::sptr>(); + } + /******************************************************************* * TX methods ******************************************************************/ @@ -232,16 +236,8 @@ public: return _tx_subdev()[SUBDEV_PROP_LO_LOCKED].as<bool>(); } - /******************************************************************* - * Interface access methods - ******************************************************************/ - - wax::obj get_rx_dboard_iface(void) { - return _rx_dboard(); - } - - wax::obj get_tx_dboard_iface(void) { - return _tx_dboard(); + dboard_iface::sptr get_tx_dboard_iface(void){ + return _tx_dboard()[DBOARD_PROP_DBOARD_IFACE].as<dboard_iface::sptr>(); } private: diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index cff13292b..c79044bce 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -51,6 +51,7 @@ public: void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); void set_gpio_ddr(unit_t, boost::uint16_t); void write_gpio(unit_t, boost::uint16_t); + void set_gpio_debug(unit_t, int); boost::uint16_t read_gpio(unit_t); void write_i2c(boost::uint8_t, const byte_vector_t &); @@ -219,6 +220,25 @@ void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t _iface->poke16(unit_to_atr_to_addr[unit][atr], value); } +void usrp2_dboard_iface::set_gpio_debug(unit_t unit, int which){ + this->set_gpio_ddr(unit, 0xffff); //all outputs + + //calculate the new selection mux setting + boost::uint32_t new_sels = 0x0; + int sel = (which == 0)? + U2_FLAG_GPIO_SEL_DEBUG_0: + U2_FLAG_GPIO_SEL_DEBUG_1; + for(size_t i = 0; i < 16; i++){ + new_sels |= sel << (i*2); + } + + //write the selection mux value to register + switch(unit){ + case UNIT_RX: _iface->poke32(_iface->regs.gpio_rx_sel, new_sels); return; + case UNIT_TX: _iface->poke32(_iface->regs.gpio_tx_sel, new_sels); return; + } +} + /*********************************************************************** * SPI **********************************************************************/ |