diff options
-rw-r--r-- | host/docs/dboards.rst | 1 | ||||
-rw-r--r-- | host/examples/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/examples/tx_bursts.cpp | 162 | ||||
-rw-r--r-- | host/examples/tx_timed_samples.cpp | 2 | ||||
-rw-r--r-- | host/examples/tx_waveforms.cpp | 72 | ||||
-rw-r--r-- | host/include/uhd/utils/log.hpp | 6 | ||||
-rw-r--r-- | host/include/uhd/utils/msg.hpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_wbx_common.cpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_wbx_simple.cpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/clock_ctrl.cpp | 22 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/codec_ctrl.cpp | 24 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/codec_impl.cpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_clk_regs.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.hpp | 2 | ||||
-rw-r--r-- | host/lib/utils/log.cpp | 42 | ||||
-rw-r--r-- | host/lib/utils/msg.cpp | 21 |
18 files changed, 307 insertions, 70 deletions
diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 959a1b300..593dd3a42 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -265,6 +265,7 @@ The TVRX2 board has 2 real-mode subdevices. It is operated at a low IF. Receive Subdevices: + * **Subdevice RX1:** real signal on antenna J100 * **Subdevice RX2:** real signal on antenna J140 diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index 1bb037d16..fe9e6409e 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -26,6 +26,7 @@ SET(example_sources rx_timed_samples.cpp test_async_messages.cpp test_pps_input.cpp + tx_bursts.cpp tx_samples_from_file.cpp tx_timed_samples.cpp tx_waveforms.cpp diff --git a/host/examples/tx_bursts.cpp b/host/examples/tx_bursts.cpp new file mode 100644 index 000000000..a66fb85b6 --- /dev/null +++ b/host/examples/tx_bursts.cpp @@ -0,0 +1,162 @@ +// +// Copyright 2010-2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/utils/thread_priority.hpp> +#include <uhd/utils/safe_main.hpp> +#include <uhd/usrp/multi_usrp.hpp> +#include <boost/program_options.hpp> +#include <boost/thread/thread.hpp> +#include <boost/format.hpp> +#include <csignal> +#include <iostream> +#include <complex> + +namespace po = boost::program_options; + +static bool stop_signal_called = false; +void sig_int_handler(int){stop_signal_called = true;} + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + uhd::set_thread_priority_safe(); + + //variables to be set by po + std::string args; + double seconds_in_future; + size_t total_num_samps; + double rate; + float ampl; + double freq; + double rep_rate; + double gain; + + //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") + ("secs", po::value<double>(&seconds_in_future)->default_value(1.5), "delay before first burst") + ("repeat", "repeat burst") + ("rep-delay", po::value<double>(&rep_rate)->default_value(0.5), "delay between bursts") + ("nsamps", po::value<size_t>(&total_num_samps)->default_value(10000), "total number of samples to transmit") + ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of outgoing samples") + ("ampl", po::value<float>(&l)->default_value(float(0.3)), "amplitude of each sample") + ("freq", po::value<double>(&freq)->default_value(0), "center frequency") + ("gain", po::value<double>(&gain)->default_value(0), "gain") + ("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 TX Timed Samples %s") % desc << std::endl; + return ~0; + } + + bool verbose = vm.count("dilv") == 0; + bool repeat = vm.count("repeat") != 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; + + //set the tx sample rate + 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; + + std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq/1e6) << std::endl; + for(size_t i=0; i < usrp->get_tx_num_channels(); i++) usrp->set_tx_freq(freq, i); + std::cout << boost::format("Actual TX Freq: %f MHz...") % (usrp->get_tx_freq()/1e6) << std::endl << std::endl; + + std::cout << boost::format("Setting TX Gain: %f...") % (gain) << std::endl; + for(size_t i=0; i < usrp->get_tx_num_channels(); i++) usrp->set_tx_gain(gain, i); + std::cout << boost::format("Actual TX Gain: %f...") % (usrp->get_tx_gain()) << std::endl << std::endl; + + std::cout << boost::format("Setting device timestamp to 0...") << std::endl; + usrp->set_time_now(uhd::time_spec_t(0.0)); + + //allocate buffer with data to send + size_t spb = usrp->get_device()->get_max_send_samps_per_packet(); + + std::vector<std::complex<float> *> buffs; + for(size_t i=0; i < usrp->get_num_mboards(); i++) { + buffs.push_back(new std::complex<float>[spb]); + for(size_t n=0; n < spb; n++) + buffs.back()[n] = std::complex<float>(ampl, ampl); + } + + std::signal(SIGINT, &sig_int_handler); + if(repeat) std::cout << "Press Ctrl + C to quit..." << std::endl; + + double time_to_send = seconds_in_future; + + do { + //setup metadata for the first packet + 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(time_to_send); + + //the first call to send() will block this many seconds before sending: + double timeout = std::max(rep_rate, seconds_in_future) + 0.1; //timeout (delay before transmit + padding) + + size_t num_acc_samps = 0; //number of accumulated samples + while(num_acc_samps < total_num_samps){ + size_t samps_to_send = std::min(total_num_samps - num_acc_samps, spb); + + //ensure the the last packet has EOB set + md.end_of_burst = samps_to_send < spb; + + //send a single packet + size_t num_tx_samps = usrp->get_device()->send( + buffs, samps_to_send, md, + uhd::io_type_t::COMPLEX_FLOAT32, + uhd::device::SEND_MODE_ONE_PACKET, timeout + ); + + //do not use time spec for subsequent packets + md.has_time_spec = false; + md.start_of_burst = false; + + if (num_tx_samps < samps_to_send) std::cerr << "Send timeout..." << std::endl; + if(verbose) std::cout << boost::format("Sent packet: %u samples") % num_tx_samps << std::endl; + + num_acc_samps += num_tx_samps; + } + + time_to_send += rep_rate; + + std::cout << std::endl << "Waiting for async burst ACK... " << std::flush; + uhd::async_metadata_t async_md; + bool got_async_burst_ack = false; + //loop through all messages for the ACK packet (may have underflow messages in queue) + while (not got_async_burst_ack and usrp->get_device()->recv_async_msg(async_md, seconds_in_future)){ + got_async_burst_ack = (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK); + } + std::cout << (got_async_burst_ack? "success" : "fail") << std::endl; + } while (not stop_signal_called and repeat); + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index d33dc13c3..79aa6738c 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -91,7 +91,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ size_t samps_to_send = std::min(total_num_samps - num_acc_samps, buff.size()); //ensure the the last packet has EOB set - md.end_of_burst = samps_to_send <= buff.size(); + md.end_of_burst = samps_to_send < buff.size(); //send a single packet size_t num_tx_samps = usrp->get_device()->send( diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 5b3a1b70c..f150f520a 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -21,6 +21,7 @@ #include <uhd/usrp/multi_usrp.hpp> #include <boost/program_options.hpp> #include <boost/math/special_functions/round.hpp> +#include <boost/foreach.hpp> #include <boost/format.hpp> #include <boost/function.hpp> #include <iostream> @@ -119,26 +120,32 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ 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; + 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); } - //set the antenna - if (vm.count("ant")) usrp->set_tx_antenna(ant); + std::cout << boost::format("Setting device timestamp to 0...") << std::endl; + usrp->set_time_now(uhd::time_spec_t(0.0)); //for the const wave, set the wave freq for small samples per period if (wave_freq == 0 and wave_type == "CONST"){ @@ -162,29 +169,35 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ 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/usrp->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; + std::vector<std::complex<float> *> buffs; + for(size_t i=0; i < usrp->get_num_mboards(); i++) + buffs.push_back(new std::complex<float>[spb]); + //setup the metadata flags uhd::tx_metadata_t md; - md.start_of_burst = false; //never SOB when continuous + md.start_of_burst = false; //no for continuous streaming md.end_of_burst = false; + md.has_time_spec = true; + md.time_spec = uhd::time_spec_t(0.1); 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] = std::complex<float>( - ampl*wave_gen(i_off + theta), - ampl*wave_gen(q_off + theta) - ); + for (size_t n = 0; n < spb; n++){ + BOOST_FOREACH(std::complex<float> *buff, buffs) { + buff[n] = std::complex<float>( + ampl*wave_gen(i_off + theta), + ampl*wave_gen(q_off + theta) + ); + } theta += cps; } @@ -193,14 +206,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //send the entire contents of the buffer usrp->get_device()->send( - &buff.front(), buff.size(), md, + buffs, spb, md, uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::SEND_MODE_FULL_BUFF ); + + md.has_time_spec = false; } //send a mini EOB packet - md.start_of_burst = false; md.end_of_burst = true; usrp->get_device()->send("", 0, md, uhd::io_type_t::COMPLEX_FLOAT32, @@ -210,5 +224,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //finished std::cout << std::endl << "Done!" << std::endl << std::endl; + BOOST_FOREACH(std::complex<float> *buff, buffs){ + delete buff; + } + return 0; } diff --git a/host/include/uhd/utils/log.hpp b/host/include/uhd/utils/log.hpp index bc8f41fb4..1f515c15e 100644 --- a/host/include/uhd/utils/log.hpp +++ b/host/include/uhd/utils/log.hpp @@ -19,6 +19,7 @@ #define INCLUDED_UHD_UTILS_LOG_HPP #include <uhd/config.hpp> +#include <uhd/utils/pimpl.hpp> #include <boost/current_function.hpp> #include <ostream> #include <string> @@ -77,7 +78,8 @@ namespace uhd{ namespace _log{ }; //! Internal logging object (called by UHD_LOG macros) - struct UHD_API log{ + class UHD_API log{ + public: log( const verbosity_t verbosity, const std::string &file, @@ -86,6 +88,8 @@ namespace uhd{ namespace _log{ ); ~log(void); std::ostream &operator()(void); + private: + UHD_PIMPL_DECL(impl) _impl; }; }} //namespace uhd::_log diff --git a/host/include/uhd/utils/msg.hpp b/host/include/uhd/utils/msg.hpp index 050504e57..71d2cb35e 100644 --- a/host/include/uhd/utils/msg.hpp +++ b/host/include/uhd/utils/msg.hpp @@ -19,6 +19,7 @@ #define INCLUDED_UHD_UTILS_MSG_HPP #include <uhd/config.hpp> +#include <uhd/utils/pimpl.hpp> #include <ostream> #include <string> @@ -52,10 +53,13 @@ namespace uhd{ namespace msg{ UHD_API void register_handler(const handler_t &handler); //! Internal message object (called by UHD_MSG macro) - struct UHD_API _msg{ + class UHD_API _msg{ + public: _msg(const type_t type); ~_msg(void); std::ostream &operator()(void); + private: + UHD_PIMPL_DECL(impl) _impl; }; }} //namespace uhd::msg diff --git a/host/lib/usrp/dboard/db_wbx_common.cpp b/host/lib/usrp/dboard/db_wbx_common.cpp index 131729f42..f35677692 100644 --- a/host/lib/usrp/dboard/db_wbx_common.cpp +++ b/host/lib/usrp/dboard/db_wbx_common.cpp @@ -95,7 +95,7 @@ wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4350_CE|RXBB_PDB|ADF4350_PDBRF|RX_ATTN_MASK); //setup ATR for the mixer enables - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, TX_MIXER_DIS, TX_MIXER_DIS | TX_MIXER_ENB); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, TX_MIXER_ENB, TX_MIXER_DIS | TX_MIXER_ENB); this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, TX_MIXER_DIS, TX_MIXER_DIS | TX_MIXER_ENB); this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, TX_MIXER_ENB, TX_MIXER_DIS | TX_MIXER_ENB); this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, TX_MIXER_ENB, TX_MIXER_DIS | TX_MIXER_ENB); diff --git a/host/lib/usrp/dboard/db_wbx_simple.cpp b/host/lib/usrp/dboard/db_wbx_simple.cpp index c9ae7f23a..d6cc959c7 100644 --- a/host/lib/usrp/dboard/db_wbx_simple.cpp +++ b/host/lib/usrp/dboard/db_wbx_simple.cpp @@ -91,7 +91,7 @@ wbx_simple::wbx_simple(ctor_args_t args) : wbx_base(args){ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, ANTSW_IO, ANTSW_IO); //setup ATR for the antenna switches (constant) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, ANT_XX, ANTSW_IO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, ANT_RX, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, ANT_RX, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, ANT_TX, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, ANT_TX, ANTSW_IO); diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 7572ed6b1..f1fdfb7cf 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -136,11 +136,23 @@ public: //uses output clock 7 (cmos) void enable_rx_dboard_clock(bool enb){ - _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; - _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; - _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; - this->write_reg(clk_regs.output(clk_regs.rx_db)); - this->update_regs(); + switch(_iface->get_rev()) { + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_LVDS; + _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; + this->write_reg(clk_regs.output(clk_regs.rx_db)); + this->update_regs(); + break; + default: + _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; + _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA; + this->write_reg(clk_regs.output(clk_regs.rx_db)); + this->update_regs(); + break; + } } void set_rate_rx_dboard_clock(double rate){ diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index b32a9f256..047195390 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -75,6 +75,22 @@ public: this->set_rx_analog_gain(1); break; + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: + _ads62p44_regs.reset = 1; + this->send_ads62p44_reg(0x00); //issue a reset to the ADC + //everything else should be pretty much default, i think + //_ads62p44_regs.decimation = DECIMATION_DECIMATE_1; + _ads62p44_regs.override = 1; + this->send_ads62p44_reg(0x14); + _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_NORMAL; + _ads62p44_regs.output_interface = ads62p44_regs_t::OUTPUT_INTERFACE_LVDS; + _ads62p44_regs.lvds_current = ads62p44_regs_t::LVDS_CURRENT_2_5MA; + this->send_ads62p44_reg(0x11); + this->send_ads62p44_reg(0x14); + this->set_rx_analog_gain(1); + break; + case usrp2_iface::USRP_NXXX: break; } } @@ -93,6 +109,8 @@ public: case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: //send a global power-down to the ADC here... it will get lifted on reset _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_GLOBAL_PD; this->send_ads62p44_reg(0x14); @@ -126,6 +144,8 @@ public: switch(_iface->get_rev()){ case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: _ads62p44_regs.fine_gain = int(gain/0.5); this->send_ads62p44_reg(0x17); break; @@ -138,6 +158,8 @@ public: switch(_iface->get_rev()){ case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: _ads62p44_regs.gain_correction = int(gain / 0.05); this->send_ads62p44_reg(0x1A); break; @@ -150,6 +172,8 @@ public: switch(_iface->get_rev()){ case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: _ads62p44_regs.coarse_gain = ads62p44_regs_t::COARSE_GAIN_3_5DB;//gain ? ads62p44_regs_t::COARSE_GAIN_3_5DB : ads62p44_regs_t::COARSE_GAIN_0DB; this->send_ads62p44_reg(0x14); break; diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp index 50320773f..26da42759 100644 --- a/host/lib/usrp/usrp2/codec_impl.cpp +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -67,6 +67,8 @@ void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ switch(_iface->get_rev()){ case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: val = _iface->get_cname() + " adc - ads62p44"; break; diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 027cb5f78..bf1fd5cce 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -231,6 +231,8 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_iface->get_rev()){ case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x12); break; case clock_config_t::REF_SMA : _iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); break; @@ -262,6 +264,8 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_iface->get_rev()){ case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: _clock_ctrl->set_mimo_clock_delay(mimo_clock_delay_usrp_n2xx); break; diff --git a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp index 6c46d0a35..8b185eac0 100644 --- a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp @@ -43,6 +43,8 @@ public: break; case usrp2_iface::USRP_N200: case usrp2_iface::USRP_N210: + case usrp2_iface::USRP_N200_R4: + case usrp2_iface::USRP_N210_R4: exp = 6; adc = 2; serdes = 4; diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 5e197d1f9..bf7fe803f 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -363,6 +363,8 @@ public: case 0x0400: return USRP2_REV4; case 0x0A00: return USRP_N200; case 0x0A01: return USRP_N210; + case 0x0A10: return USRP_N200_R4; + case 0x0A11: return USRP_N210_R4; } return USRP_NXXX; //unknown type } @@ -373,6 +375,8 @@ public: case USRP2_REV4: return "USRP2-REV4"; case USRP_N200: return "USRP-N200"; case USRP_N210: return "USRP-N210"; + case USRP_N200_R4: return "USRP-N200-REV4"; + case USRP_N210_R4: return "USRP-N210-REV4"; case USRP_NXXX: return "USRP-N???"; } UHD_THROW_INVALID_CODE_PATH(); diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index f2b8a1e29..16b640a70 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -56,7 +56,9 @@ public: USRP2_REV3 = 3, USRP2_REV4 = 4, USRP_N200 = 200, + USRP_N200_R4 = 201, USRP_N210 = 210, + USRP_N210_R4 = 211, USRP_NXXX = 0 }; diff --git a/host/lib/utils/log.cpp b/host/lib/utils/log.cpp index 7d11877a1..31d11796e 100644 --- a/host/lib/utils/log.cpp +++ b/host/lib/utils/log.cpp @@ -90,9 +90,7 @@ static fs::path get_temp_path(void){ **********************************************************************/ class log_resource_type{ public: - boost::mutex mutex; - std::ostringstream ss; - uhd::_log::verbosity_t verbosity, level; + uhd::_log::verbosity_t level; log_resource_type(void){ @@ -113,19 +111,20 @@ public: } ~log_resource_type(void){ + boost::mutex::scoped_lock lock(_mutex); _file_stream.close(); if (_file_lock != NULL) delete _file_lock; } - void log_to_file(void){ - if (verbosity < level) return; + void log_to_file(const std::string &log_msg){ + boost::mutex::scoped_lock lock(_mutex); if (_file_lock == NULL){ const std::string log_path = (get_temp_path() / "uhd.log").string(); _file_stream.open(log_path.c_str(), std::fstream::out | std::fstream::app); _file_lock = new ip::file_lock(log_path.c_str()); } _file_lock->lock(); - _file_stream << ss.str() << std::flush; + _file_stream << log_msg << std::flush; _file_lock->unlock(); } @@ -149,6 +148,7 @@ private: //file stream and lock: std::ofstream _file_stream; ip::file_lock *_file_lock; + boost::mutex _mutex; }; UHD_SINGLETON_FCN(log_resource_type, log_rs); @@ -167,20 +167,25 @@ static std::string get_rel_file_path(const fs::path &file){ return rel_path.string(); } +struct uhd::_log::log::impl{ + std::ostringstream ss; + verbosity_t verbosity; +}; + uhd::_log::log::log( const verbosity_t verbosity, const std::string &file, const unsigned int line, const std::string &function ){ - log_rs().mutex.lock(); - log_rs().verbosity = verbosity; + _impl = UHD_PIMPL_MAKE(impl, ()); + _impl->verbosity = verbosity; const std::string time = pt::to_simple_string(pt::microsec_clock::local_time()); const std::string header1 = str(boost::format("-- %s - level %d") % time % int(verbosity)); const std::string header2 = str(boost::format("-- %s") % function).substr(0, 80); const std::string header3 = str(boost::format("-- %s:%u") % get_rel_file_path(file) % line); const std::string border = std::string(std::max(std::max(header1.size(), header2.size()), header3.size()), '-'); - log_rs().ss + _impl->ss << std::endl << border << std::endl << header1 << std::endl @@ -191,35 +196,26 @@ uhd::_log::log::log( } uhd::_log::log::~log(void){ - log_rs().ss << std::endl; + if (_impl->verbosity < log_rs().level) return; + _impl->ss << std::endl; try{ - log_rs().log_to_file(); + log_rs().log_to_file(_impl->ss.str()); } catch(const std::exception &e){ /*! * Critical behavior below. * The following steps must happen in order to avoid a lock-up condition. * This is because the message facility will call into the logging facility. - * Therefore we must disable the logger (level = never) and unlock the mutex. - * - * 1) Set logging level to never. - * 2) Unlock the mutex. - * 3) Send the error message. - * 4) Return. + * Therefore we must disable the logger (level = never) before messaging. */ log_rs().level = never; - log_rs().ss.str(""); //clear for next call - log_rs().mutex.unlock(); UHD_MSG(error) << "Logging failed: " << e.what() << std::endl << "Logging has been disabled for this process" << std::endl ; - return; } - log_rs().ss.str(""); //clear for next call - log_rs().mutex.unlock(); } std::ostream & uhd::_log::log::operator()(void){ - return log_rs().ss; + return _impl->ss; } diff --git a/host/lib/utils/msg.cpp b/host/lib/utils/msg.cpp index 0fd62bfc1..de98ada64 100644 --- a/host/lib/utils/msg.cpp +++ b/host/lib/utils/msg.cpp @@ -65,8 +65,6 @@ static void msg_to_cerr(const std::string &title, const std::string &msg){ **********************************************************************/ struct msg_resource_type{ boost::mutex mutex; - std::ostringstream ss; - uhd::msg::type_t type; uhd::msg::handler_t handler; }; @@ -76,9 +74,8 @@ UHD_SINGLETON_FCN(msg_resource_type, msg_rs); * Setup the message handlers **********************************************************************/ void uhd::msg::register_handler(const handler_t &handler){ - msg_rs().mutex.lock(); + boost::mutex::scoped_lock lock(msg_rs().mutex); msg_rs().handler = handler; - msg_rs().mutex.unlock(); } static void default_msg_handler(uhd::msg::type_t type, const std::string &msg){ @@ -111,17 +108,21 @@ UHD_STATIC_BLOCK(msg_register_default_handler){ /*********************************************************************** * The message object implementation **********************************************************************/ +struct uhd::msg::_msg::impl{ + std::ostringstream ss; + type_t type; +}; + uhd::msg::_msg::_msg(const type_t type){ - msg_rs().mutex.lock(); - msg_rs().type = type; + _impl = UHD_PIMPL_MAKE(impl, ()); + _impl->type = type; } uhd::msg::_msg::~_msg(void){ - msg_rs().handler(msg_rs().type, msg_rs().ss.str()); - msg_rs().ss.str(""); //clear for next call - msg_rs().mutex.unlock(); + boost::mutex::scoped_lock lock(msg_rs().mutex); + msg_rs().handler(_impl->type, _impl->ss.str()); } std::ostream & uhd::msg::_msg::operator()(void){ - return msg_rs().ss; + return _impl->ss; } |