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;  }  | 
