diff options
Diffstat (limited to 'host/lib/usrp')
-rw-r--r-- | host/lib/usrp/b100/b100_impl.cpp | 10 | ||||
-rw-r--r-- | host/lib/usrp/b100/b100_impl.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 47 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.hpp | 61 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_io_impl.cpp | 156 | ||||
-rw-r--r-- | host/lib/usrp/e100/e100_impl.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_impl.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_network.cpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/multi_usrp.cpp | 3 | ||||
-rw-r--r-- | host/lib/usrp/usrp1/usrp1_impl.cpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_iface.cpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 18 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_io_impl.cpp | 52 |
13 files changed, 258 insertions, 113 deletions
diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 24a87a3c8..c4279913c 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -23,7 +23,7 @@ #include <uhd/utils/cast.hpp> #include <uhd/exception.hpp> #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp> #include <uhd/utils/safe_call.hpp> #include <boost/format.hpp> #include <boost/assign/list_of.hpp> @@ -82,7 +82,7 @@ static device_addrs_t b100_find(const device_addr_t &hint) b100_fw_image = find_image_path(hint.get("fw", B100_FW_FILE_NAME)); } catch(...){ - UHD_MSG(warning) << boost::format("Could not locate B100 firmware. %s\n") % print_images_error(); + UHD_MSG(warning) << boost::format("Could not locate B100 firmware. %s\n") % print_utility_error("uhd_images_downloader.py"); return b100_addrs; } UHD_LOG << "the firmware image: " << b100_fw_image << std::endl; @@ -532,10 +532,10 @@ void b100_impl::check_fw_compat(void){ ); if (fw_compat_num != B100_FW_COMPAT_NUM){ throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number 0x%x, but got 0x%x:\n" + "Expected firmware compatibility number %d, but got %d:\n" "The firmware build is not compatible with the host code build.\n" "%s" - ) % B100_FW_COMPAT_NUM % fw_compat_num % print_images_error())); + ) % int(B100_FW_COMPAT_NUM) % fw_compat_num % print_utility_error("uhd_images_downloader.py"))); } _tree->create<std::string>("/mboards/0/fw_version").set(str(boost::format("%u.0") % fw_compat_num)); } @@ -552,7 +552,7 @@ void b100_impl::check_fpga_compat(void){ "Expected FPGA compatibility number %d, but got %d:\n" "The FPGA build is not compatible with the host code build." "%s" - ) % int(B100_FPGA_COMPAT_NUM) % fpga_major % print_images_error())); + ) % int(B100_FPGA_COMPAT_NUM) % fpga_major % print_utility_error("uhd_images_downloader.py"))); } _tree->create<std::string>("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); } diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 59ea2202e..dbca543be 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -46,7 +46,7 @@ static const double B100_LINK_RATE_BPS = 256e6/5; //pratical link rate (< 480 Mbps) static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.ihx"; static const std::string B100_FPGA_FILE_NAME = "usrp_b100_fpga.bin"; -static const boost::uint16_t B100_FW_COMPAT_NUM = 0x04; +static const boost::uint16_t B100_FW_COMPAT_NUM = 4; static const boost::uint16_t B100_FPGA_COMPAT_NUM = 11; static const boost::uint32_t B100_RX_SID_BASE = 30; static const boost::uint32_t B100_TX_ASYNC_SID = 10; diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 01c0f5cbf..b2f0d8d3e 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -22,7 +22,7 @@ #include <uhd/utils/cast.hpp> #include <uhd/exception.hpp> #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp> #include <uhd/utils/safe_call.hpp> #include <uhd/usrp/dboard_eeprom.hpp> #include <boost/format.hpp> @@ -115,7 +115,7 @@ static device_addrs_t b200_find(const device_addr_t &hint) UHD_MSG(warning) << boost::format( "Could not locate B200 firmware.\n" "Please install the images package. %s\n" - ) % print_images_error(); + ) % print_utility_error("uhd_images_downloader.py"); return b200_addrs; } UHD_LOG << "the firmware image: " << b200_fw_image << std::endl; @@ -416,6 +416,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr) .publish(boost::bind(&b200_impl::get_tick_rate, this)) .subscribe(boost::bind(&b200_impl::update_tick_rate, this, _1)); _tree->create<time_spec_t>(mb_path / "time" / "cmd"); + _tree->create<bool>(mb_path / "auto_tick_rate").set(false); //////////////////////////////////////////////////////////////////// // and do the misc mboard sensors @@ -516,6 +517,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) _tree->access<double>(mb_path / "rx_dsps" / str(boost::format("%u") % i)/ "rate/value").set(B200_DEFAULT_RATE); _tree->access<double>(mb_path / "tx_dsps" / str(boost::format("%u") % i) / "rate/value").set(B200_DEFAULT_RATE); } + // We can automatically choose a master clock rate, but not if the user specifies one + _tree->access<bool>(mb_path / "auto_tick_rate").set(not device_addr.has_key("master_clock_rate")); + if (not device_addr.has_key("master_clock_rate")) { + UHD_MSG(status) << "Setting master clock rate selection to 'automatic'." << std::endl; + } //GPS installed: use external ref, time, and init time spec if (_gps and _gps->gps_detected()) @@ -579,7 +585,7 @@ void b200_impl::setup_radio(const size_t dspno) _tree->create<meta_range_t>(rx_dsp_path / "rate" / "range") .publish(boost::bind(&rx_dsp_core_3000::get_host_rates, perif.ddc)); _tree->create<double>(rx_dsp_path / "rate" / "value") - .coerce(boost::bind(&rx_dsp_core_3000::set_host_rate, perif.ddc, _1)) + .coerce(boost::bind(&b200_impl::coerce_rx_samp_rate, this, perif.ddc, dspno, _1)) .subscribe(boost::bind(&b200_impl::update_rx_samp_rate, this, dspno, _1)) .set(0.0); // Can only set this after tick rate is initialized. _tree->create<double>(rx_dsp_path / "freq" / "value") @@ -603,7 +609,7 @@ void b200_impl::setup_radio(const size_t dspno) _tree->create<meta_range_t>(tx_dsp_path / "rate" / "range") .publish(boost::bind(&tx_dsp_core_3000::get_host_rates, perif.duc)); _tree->create<double>(tx_dsp_path / "rate" / "value") - .coerce(boost::bind(&tx_dsp_core_3000::set_host_rate, perif.duc, _1)) + .coerce(boost::bind(&b200_impl::coerce_tx_samp_rate, this, perif.duc, dspno, _1)) .subscribe(boost::bind(&b200_impl::update_tx_samp_rate, this, dspno, _1)) .set(0.0); // Can only set this after tick rate is initialized. _tree->create<double>(tx_dsp_path / "freq" / "value") @@ -719,7 +725,7 @@ void b200_impl::codec_loopback_self_test(wb_iface::sptr iface) /*********************************************************************** * Sample and tick rate comprehension below **********************************************************************/ -void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, const char* direction /*= NULL*/) +void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, const std::string &direction /*= ""*/) { const size_t max_chans = 2; if (chan_count > max_chans) @@ -727,7 +733,7 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co throw uhd::value_error(boost::str( boost::format("cannot not setup %d %s channels (maximum is %d)") % chan_count - % (direction ? direction : "data") + % (direction.empty() ? "data" : direction) % max_chans )); } @@ -741,20 +747,26 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co % (tick_rate/1e6) % (max_tick_rate/1e6) % chan_count - % (direction ? direction : "data") + % (direction.empty() ? "data" : direction) )); } } } -double b200_impl::set_tick_rate(const double rate) +double b200_impl::set_tick_rate(const double new_tick_rate) { - UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz\n") % (rate/1e6)); + UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz... ") % (new_tick_rate/1e6)) << std::flush; + check_tick_rate_with_current_streamers(new_tick_rate); // Defined in b200_io_impl.cpp - check_tick_rate_with_current_streamers(rate); // Defined in b200_io_impl.cpp + // Make sure the clock rate is actually changed before doing + // the full Monty of setting regs and loopback tests etc. + if (std::abs(new_tick_rate - _tick_rate) < 1.0) { + UHD_MSG(status) << "OK" << std::endl; + return _tick_rate; + } - _tick_rate = _codec_ctrl->set_clock_rate(rate); - UHD_MSG(status) << (boost::format("Actually got clock rate %.6f MHz\n") % (_tick_rate/1e6)); + _tick_rate = _codec_ctrl->set_clock_rate(new_tick_rate); + UHD_MSG(status) << std::endl << (boost::format("Actually got clock rate %.6f MHz.") % (_tick_rate/1e6)) << std::endl; //reset after clock rate change this->reset_codec_dcm(); @@ -779,11 +791,11 @@ void b200_impl::check_fw_compat(void) if (compat_major != B200_FW_COMPAT_NUM_MAJOR){ throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number 0x%x, but got 0x%x.%x:\n" + "Expected firmware compatibility number %d.%d, but got %d.%d:\n" "The firmware build is not compatible with the host code build.\n" "%s" - ) % int(B200_FW_COMPAT_NUM_MAJOR) % compat_major % compat_minor - % print_images_error())); + ) % int(B200_FW_COMPAT_NUM_MAJOR) % int(B200_FW_COMPAT_NUM_MINOR) + % compat_major % compat_minor % print_utility_error("uhd_images_downloader.py"))); } _tree->create<std::string>("/mboards/0/fw_version").set(str(boost::format("%u.%u") % compat_major % compat_minor)); @@ -800,11 +812,10 @@ void b200_impl::check_fpga_compat(void) if (compat_major != B200_FPGA_COMPAT_NUM){ throw uhd::runtime_error(str(boost::format( - "Expected FPGA compatibility number 0x%x, but got 0x%x.%x:\n" + "Expected FPGA compatibility number %d, but got %d:\n" "The FPGA build is not compatible with the host code build.\n" "%s" - ) % int(B200_FPGA_COMPAT_NUM) % compat_major % compat_minor - % print_images_error())); + ) % int(B200_FPGA_COMPAT_NUM) % compat_major % print_utility_error("uhd_images_downloader.py"))); } _tree->create<std::string>("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % compat_major % compat_minor)); diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 8f03d81ad..71592f60b 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -45,9 +45,9 @@ #include <uhd/transport/bounded_buffer.hpp> #include <boost/weak_ptr.hpp> #include "recv_packet_demuxer_3000.hpp" -static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 0x07; -static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0x00; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x04; +static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 7; +static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 4; static const double B200_BUS_CLOCK_RATE = 100e6; static const double B200_DEFAULT_TICK_RATE = 32e6; static const double B200_DEFAULT_FREQ = 100e6; // Hz @@ -98,7 +98,13 @@ public: uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); bool recv_async_msg(uhd::async_metadata_t &, double); - void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction = NULL); + + //! Check that the combination of stream args and tick rate are valid. + // + // Basically figures out the arguments for enforce_tick_rate_limits() + // and calls said method. If arguments are invalid, throws a + // uhd::value_error. + void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction = ""); private: //controllers @@ -190,11 +196,56 @@ private: double _tick_rate; double get_tick_rate(void){return _tick_rate;} double set_tick_rate(const double rate); + + /*! \brief Choose a tick rate (master clock rate) that works well for the given sampling rate. + * + * This function will try and choose a master clock rate automatically. + * See the function definition for details on the algorithm. + * + * The chosen tick rate is the largest multiple of two that is smaler + * than the max tick rate. + * The base rate is either given explicitly, or is the lcm() of the tx + * and rx sampling rates. In that case, it reads the rates directly + * from the property tree. It also tries to guess the number of channels + * (for the max possible tick rate) by checking the available streamers. + * This value, too, can explicitly be given. + * + * \param rate If this is given, it will be used as a minimum rate, or + * argument to lcm(). + * \param tree_dsp_path The sampling rate from this property tree path + * will be ignored. + * \param num_chans If given, specifies the number of channels. + */ + void set_auto_tick_rate( + const double rate=0, + const uhd::fs_path &tree_dsp_path="", + size_t num_chans=0 + ); + void update_tick_rate(const double); - void enforce_tick_rate_limits(size_t chan_count, double tick_rate, const char* direction = NULL); + + /*! Check if \p tick_rate works with \p chan_count channels. + * + * Throws a uhd::value_error if not. + */ + void enforce_tick_rate_limits(size_t chan_count, double tick_rate, const std::string &direction = ""); void check_tick_rate_with_current_streamers(double rate); + /*! Return the max number of channels on active rx_streamer or tx_streamer objects associated with this device. + * + * \param direction Set to "TX" to only check tx_streamers, "RX" to only check + * rx_streamers. Any other value will check if \e any active + * streamers are available. + * \return Return the number of tx streamers (direction=="TX"), the number of rx + * streamers (direction=="RX") or the total number of streamers. + */ + size_t max_chan_count(const std::string &direction=""); + + //! Coercer, attached to the "rate/value" property on the rx dsps. + double coerce_rx_samp_rate(rx_dsp_core_3000::sptr, size_t, const double); void update_rx_samp_rate(const size_t, const double); + //! Coercer, attached to the "rate/value" property on the tx dsps. + double coerce_tx_samp_rate(tx_dsp_core_3000::sptr, size_t, const double); void update_tx_samp_rate(const size_t, const double); }; diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index 262c95f0d..60b925517 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2012-2013 Ettus Research LLC +// Copyright 2012-2014 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 @@ -21,8 +21,10 @@ #include "../../transport/super_recv_packet_handler.hpp" #include "../../transport/super_send_packet_handler.hpp" #include "async_packet_handler.hpp" +#include <uhd/utils/math.hpp> #include <boost/bind.hpp> #include <boost/make_shared.hpp> +#include <boost/math/common_factor.hpp> #include <set> using namespace uhd; @@ -34,30 +36,32 @@ using namespace uhd::transport; **********************************************************************/ void b200_impl::check_tick_rate_with_current_streamers(double rate) { - size_t max_tx_chan_count = 0, max_rx_chan_count = 0; + // Defined in b200_impl.cpp + enforce_tick_rate_limits(max_chan_count("RX"), rate, "RX"); + enforce_tick_rate_limits(max_chan_count("TX"), rate, "TX"); +} + +// direction can either be "TX", "RX", or empty (default) +size_t b200_impl::max_chan_count(const std::string &direction /* = "" */) +{ + size_t max_count = 0; BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) { - { + if ((direction == "RX" or direction.empty()) and not perif.rx_streamer.expired()) { boost::shared_ptr<sph::recv_packet_streamer> rx_streamer = boost::dynamic_pointer_cast<sph::recv_packet_streamer>(perif.rx_streamer.lock()); - if (rx_streamer) - max_rx_chan_count = std::max(max_rx_chan_count, rx_streamer->get_num_channels()); + max_count = std::max(max_count, rx_streamer->get_num_channels()); } - - { + if ((direction == "TX" or direction.empty()) and not perif.tx_streamer.expired()) { boost::shared_ptr<sph::send_packet_streamer> tx_streamer = boost::dynamic_pointer_cast<sph::send_packet_streamer>(perif.tx_streamer.lock()); - if (tx_streamer) - max_tx_chan_count = std::max(max_tx_chan_count, tx_streamer->get_num_channels()); + max_count = std::max(max_count, tx_streamer->get_num_channels()); } } - - // Defined in b200_impl.cpp - enforce_tick_rate_limits(max_rx_chan_count, rate, "RX"); - enforce_tick_rate_limits(max_tx_chan_count, rate, "TX"); + return max_count; } -void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction /*= NULL*/) +void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction /*= ""*/) { std::set<size_t> chans_set; for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) @@ -69,26 +73,120 @@ void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_ enforce_tick_rate_limits(chans_set.size(), tick_rate, direction); // Defined in b200_impl.cpp } -void b200_impl::update_tick_rate(const double rate) +void b200_impl::set_auto_tick_rate( + const double rate, + const fs_path &tree_dsp_path, + size_t num_chans +) { + if (num_chans == 0) { // Divine them + num_chans = std::max(size_t(1), max_chan_count()); + } + + // See also the doxygen documentation for these steps in b200_impl.hpp + // Step 1: Obtain LCM and max rate from all relevant dsps + boost::uint32_t lcm_rate = (rate == 0) ? 1 : static_cast<boost::uint32_t>(floor(rate + 0.5)); + for (int i = 0; i < 2; i++) { // Loop through rx and tx + std::string dir = (i == 0) ? "tx" : "rx"; + // We have no way of knowing which DSPs are used, so we check them all. + BOOST_FOREACH(const std::string &dsp_no, _tree->list(str(boost::format("/mboards/0/%s_dsps") % dir))) { + fs_path dsp_path = str(boost::format("/mboards/0/%s_dsps/%s") % dir % dsp_no); + if (dsp_path == tree_dsp_path) { + continue; + } + double this_dsp_rate = _tree->access<double>(dsp_path / "rate/value").get(); + // If this_dsp_rate == B200_DEFAULT_RATE, we assume the user did not actually set + // the sampling rate. If the user *did* set the rate to + // B200_DEFAULT_RATE on all DSPs, then this will still work (see below). + // If the user set one DSP to B200_DEFAULT_RATE and the other to + // a different rate, this also works if the rates are integer multiples + // of one another. Only for certain configurations of B200_DEFAULT_RATE + // and another rate that is not an integer multiple, this will be problematic. + // Since this case is less common than the case where a rate is left unset, + // we don't handle that but rather explain that corner case in the documentation. + if (this_dsp_rate == B200_DEFAULT_RATE) { + continue; + } + lcm_rate = boost::math::lcm<boost::uint32_t>( + lcm_rate, + static_cast<boost::uint32_t>(floor(this_dsp_rate + 0.5)) + ); + } + } + if (lcm_rate == 1) { + lcm_rate = static_cast<boost::uint32_t>(B200_DEFAULT_RATE); + } + + // Step 2: Determine whether if we can use lcm_rate (preferred), + // or have to give up because too large: + const double max_tick_rate = + ((num_chans <= 1) ? ad9361_device_t::AD9361_RECOMMENDED_MAX_CLOCK_RATE : ad9361_device_t::AD9361_MAX_CLOCK_RATE/2); + double base_rate = static_cast<double>(lcm_rate); + if (base_rate > max_tick_rate) { + UHD_MSG(warning) + << "Cannot automatically determine an appropriate tick rate for these sampling rates." << std::endl + << "Consider using different sampling rates, or manually specify a suitable master clock rate." << std::endl; + return; // Let the others handle this + } + + // Step 3: Choose the new rate + // Rules for choosing the tick rate: + // Choose a rate that is a power of 2 larger than the sampling rate, + // but at least 4. Cannot exceed the max tick rate, of course, but must + // be larger than the minimum tick rate. + // An equation that does all that is: + // + // f_auto = r * 2^floor(log2(f_max/r)) + // + // where r is the base rate and f_max is the maximum tick rate. The case + // where floor() yields 1 must be caught. + const double min_tick_rate = _codec_ctrl->get_clock_rate_range().start(); + // We use shifts here instead of 2^x because exp2() is not available in all compilers, + // also this guarantees no rounding issues. The type cast to int32_t serves as floor(): + boost::int32_t multiplier = (1 << boost::int32_t(uhd::math::log2(max_tick_rate / base_rate))); + if (multiplier == 2 and base_rate >= min_tick_rate) { + // Don't bother (see above) + multiplier = 1; + } + double new_rate = base_rate * multiplier; + UHD_ASSERT_THROW(new_rate >= min_tick_rate); + UHD_ASSERT_THROW(new_rate <= max_tick_rate); + + if (_tree->access<double>("/mboards/0/tick_rate").get() != new_rate) { + _tree->access<double>("/mboards/0/tick_rate").set(new_rate); + } +} + +void b200_impl::update_tick_rate(const double new_tick_rate) { - check_tick_rate_with_current_streamers(rate); + check_tick_rate_with_current_streamers(new_tick_rate); BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) { boost::shared_ptr<sph::recv_packet_streamer> my_streamer = boost::dynamic_pointer_cast<sph::recv_packet_streamer>(perif.rx_streamer.lock()); - if (my_streamer) my_streamer->set_tick_rate(rate); - perif.framer->set_tick_rate(_tick_rate); + if (my_streamer) my_streamer->set_tick_rate(new_tick_rate); + perif.framer->set_tick_rate(new_tick_rate); } BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) { boost::shared_ptr<sph::send_packet_streamer> my_streamer = boost::dynamic_pointer_cast<sph::send_packet_streamer>(perif.tx_streamer.lock()); - if (my_streamer) my_streamer->set_tick_rate(rate); - perif.deframer->set_tick_rate(_tick_rate); + if (my_streamer) my_streamer->set_tick_rate(new_tick_rate); + perif.deframer->set_tick_rate(new_tick_rate); } } + +double b200_impl::coerce_rx_samp_rate(rx_dsp_core_3000::sptr ddc, size_t dspno, const double rx_rate) +{ + // Have to set tick rate first, or the ddc will change the requested rate based on default tick rate + if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { + const std::string dsp_path = (boost::format("/mboards/0/rx_dsps/%s") % dspno).str(); + set_auto_tick_rate(rx_rate, dsp_path); + } + return ddc->set_host_rate(rx_rate); +} + void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate) { boost::shared_ptr<sph::recv_packet_streamer> my_streamer = @@ -99,6 +197,16 @@ void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate) my_streamer->set_scale_factor(adj); } +double b200_impl::coerce_tx_samp_rate(tx_dsp_core_3000::sptr duc, size_t dspno, const double tx_rate) +{ + // Have to set tick rate first, or the duc will change the requested rate based on default tick rate + if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { + const std::string dsp_path = (boost::format("/mboards/0/tx_dsps/%s") % dspno).str(); + set_auto_tick_rate(tx_rate, dsp_path); + } + return duc->set_host_rate(tx_rate); +} + void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate) { boost::shared_ptr<sph::send_packet_streamer> my_streamer = @@ -264,6 +372,9 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_) if (args.otw_format.empty()) args.otw_format = "sc16"; args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; + if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { + set_auto_tick_rate(0, "", args.channels.size()); + } check_streamer_args(args, this->get_tick_rate(), "RX"); boost::shared_ptr<sph::recv_packet_streamer> my_streamer; @@ -371,7 +482,10 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t &args_) if (args.otw_format.empty()) args.otw_format = "sc16"; args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; - check_streamer_args(args, this->get_tick_rate(), "TX"); + if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) { + set_auto_tick_rate(0, "", args.channels.size()); + } + check_streamer_args(args, this->get_tick_rate(), "RX"); boost::shared_ptr<sph::send_packet_streamer> my_streamer; for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 8b4f2316c..ac419e0e0 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -21,7 +21,7 @@ #include <uhd/utils/msg.hpp> #include <uhd/exception.hpp> #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp> #include <boost/bind.hpp> #include <boost/format.hpp> #include <boost/filesystem.hpp> @@ -132,7 +132,7 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ e100_fpga_image = find_image_path(device_addr.get("fpga", default_fpga_file_name)); } catch(...){ - UHD_MSG(error) << boost::format("Could not find FPGA image. %s\n") % print_images_error(); + UHD_MSG(error) << boost::format("Could not find FPGA image. %s\n") % print_utility_error("uhd_images_downloader.py"); throw; } e100_load_fpga(e100_fpga_image); diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index e42ac390e..8807a56e4 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -28,7 +28,7 @@ #include <uhd/utils/msg.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp> #include <uhd/usrp/dboard_eeprom.hpp> #include <uhd/transport/if_addrs.hpp> #include <uhd/transport/udp_zero_copy.hpp> @@ -397,7 +397,7 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr) "%s" ) % fpga::COMPAT_MAJOR % _get_version(FPGA_MAJOR) % _get_version(FPGA_MINOR) - % print_images_error())); + % print_utility_error("uhd_images_downloader.py"))); } //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 883ff0c4f..59e1eec86 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -33,7 +33,7 @@ #include <uhd/utils/msg.hpp> #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp> #include <boost/asio.hpp> #include <boost/thread.hpp> diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 0c128dd22..7f27bdc64 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -431,6 +431,9 @@ public: ******************************************************************/ void set_master_clock_rate(double rate, size_t mboard){ if (mboard != ALL_MBOARDS){ + if (_tree->exists(mb_root(mboard) / "auto_tick_rate")) { + _tree->access<bool>(mb_root(mboard) / "auto_tick_rate").set(false); + } _tree->access<double>(mb_root(mboard) / "tick_rate").set(rate); return; } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 709092e42..dbd5408e8 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -23,7 +23,7 @@ #include <uhd/utils/cast.hpp> #include <uhd/exception.hpp> #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp> #include <boost/format.hpp> #include <boost/assign/list_of.hpp> #include <boost/filesystem.hpp> @@ -85,7 +85,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) usrp1_fw_image = find_image_path(hint.get("fw", "usrp1_fw.ihx")); } catch(...){ - UHD_MSG(warning) << boost::format("Could not locate USRP1 firmware. %s") % print_images_error(); + UHD_MSG(warning) << boost::format("Could not locate USRP1 firmware. %s") % print_utility_error("uhd_images_downloader.py"); } UHD_LOG << "USRP1 firmware image: " << usrp1_fw_image << std::endl; diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index b2085807f..65cf90a17 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -23,7 +23,7 @@ #include <uhd/utils/msg.hpp> #include <uhd/utils/paths.hpp> #include <uhd/utils/tasks.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp> #include <uhd/utils/safe_call.hpp> #include <uhd/types/dict.hpp> #include <boost/thread.hpp> @@ -375,7 +375,7 @@ public: fpga_image_path = uhd::find_image_path(fpga_image); } catch(const std::exception &){ - return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_images_error()); + return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_utility_error("uhd_images_downloader.py")); } //escape char for multi-line cmd + newline + indent? @@ -389,13 +389,13 @@ public: if (this->get_rev() == USRP2_REV3 or this->get_rev() == USRP2_REV4){ const std::string card_burner = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp2_card_burner.py").string(); const std::string card_burner_cmd = str(boost::format("\"%s%s\" %s--fpga=\"%s\" %s--fw=\"%s\"") % sudo % card_burner % ml % fpga_image_path % ml % fw_image_path); - return str(boost::format("%s\n%s") % print_images_error() % card_burner_cmd); + return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % card_burner_cmd); } else{ const std::string addr = _ctrl_transport->get_recv_addr(); const std::string net_burner_path = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp_n2xx_simple_net_burner").string(); const std::string net_burner_cmd = str(boost::format("\"%s\" %s--addr=\"%s\"") % net_burner_path % ml % addr); - return str(boost::format("%s\n%s") % print_images_error() % net_burner_cmd); + return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % net_burner_cmd); } } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index a879ae02d..c7980c997 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -24,7 +24,7 @@ #include "apply_corrections.hpp" #include <uhd/utils/static.hpp> #include <uhd/utils/msg.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp> #include <uhd/utils/safe_call.hpp> #include <uhd/usrp/subdev_spec.hpp> #include <uhd/transport/if_addrs.hpp> @@ -171,7 +171,7 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu default: continue; } - + niriok_proxy::sptr kernel_proxy = niriok_proxy::make_and_open(dev_info.interface_path); //Attempt to read the name from the EEPROM and perform filtering. @@ -1434,8 +1434,8 @@ bool x300_impl::wait_for_ref_locked(wb_iface::sptr ctrl, double timeout) boost::this_thread::sleep(boost::posix_time::milliseconds(1)); } while (boost::get_system_time() < timeout_time); - //failed to lock on reference - return false; + //Check one last time + return get_ref_locked(ctrl).to_bool(); } sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl) @@ -1670,11 +1670,11 @@ void x300_impl::check_fw_compat(const fs_path &mb_path, wb_iface::sptr iface) if (compat_major != X300_FW_COMPAT_MAJOR) { throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number 0x%x, but got 0x%x.%x:\n" + "Expected firmware compatibility number %d.%d, but got %d.%d:\n" "The firmware build is not compatible with the host code build.\n" "%s" - ) % int(X300_FW_COMPAT_MAJOR) % compat_major % compat_minor - % print_images_error())); + ) % int(X300_FW_COMPAT_MAJOR) % int(X300_FW_COMPAT_MINOR) + % compat_major % compat_minor % print_utility_error("uhd_images_downloader.py"))); } _tree->create<std::string>(mb_path / "fw_version").set(str(boost::format("%u.%u") % compat_major % compat_minor)); @@ -1694,11 +1694,11 @@ void x300_impl::check_fpga_compat(const fs_path &mb_path, wb_iface::sptr iface) "Download the appropriate FPGA images for this version of UHD.\n" "%s\n\n" "Then burn a new image to the on-board flash storage of your\n" - "USRP X3xx device using the burner utility. \n\n" + "USRP X3xx device using the burner utility. %s\n\n" "For more information, refer to the UHD manual:\n\n" " http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_flash" ) % int(X300_FPGA_COMPAT_MAJOR) % compat_major - % print_images_error())); + % print_utility_error("uhd_images_downloader.py") % print_utility_error("usrp_x3xx_fpga_burner"))); } _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u") % compat_major % compat_minor)); diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index 334ae8168..e3515af0c 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -23,6 +23,7 @@ #include <uhd/transport/nirio_zero_copy.hpp> #include "async_packet_handler.hpp" #include <uhd/transport/bounded_buffer.hpp> +#include <uhd/transport/chdr.hpp> #include <boost/bind.hpp> #include <uhd/utils/tasks.hpp> #include <uhd/utils/log.hpp> @@ -124,41 +125,6 @@ void x300_impl::update_subdev_spec(const std::string &tx_rx, const size_t mb_i, /*********************************************************************** - * VITA stuff - **********************************************************************/ -static void x300_if_hdr_unpack_be( - const boost::uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_unpack_be(packet_buff, if_packet_info); -} - -static void x300_if_hdr_pack_be( - boost::uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_pack_be(packet_buff, if_packet_info); -} - -static void x300_if_hdr_unpack_le( - const boost::uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_unpack_le(packet_buff, if_packet_info); -} - -static void x300_if_hdr_pack_le( - boost::uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_pack_le(packet_buff, if_packet_info); -} - -/*********************************************************************** * RX flow control handler **********************************************************************/ static size_t get_rx_flow_control_window(size_t frame_size, size_t sw_buff_size, const device_addr_t& rx_args) @@ -209,9 +175,9 @@ static void handle_rx_flowctrl(const boost::uint32_t sid, zero_copy_if::sptr xpo //load header if (big_endian) - x300_if_hdr_pack_be(pkt, packet_info); + vrt::chdr::if_hdr_pack_be(pkt, packet_info); else - x300_if_hdr_pack_le(pkt, packet_info); + vrt::chdr::if_hdr_pack_le(pkt, packet_info); //load payload pkt[packet_info.num_header_words32+0] = uhd::htonx<boost::uint32_t>(0); @@ -276,12 +242,12 @@ static void handle_tx_async_msgs(boost::shared_ptr<x300_tx_fc_guts_t> guts, zero { if (big_endian) { - x300_if_hdr_unpack_be(packet_buff, if_packet_info); + vrt::chdr::if_hdr_unpack_be(packet_buff, if_packet_info); endian_conv = uhd::ntohx; } else { - x300_if_hdr_unpack_le(packet_buff, if_packet_info); + vrt::chdr::if_hdr_unpack_le(packet_buff, if_packet_info); endian_conv = uhd::wtohx; } } @@ -430,10 +396,10 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_) //init some streamer stuff std::string conv_endianness; if (mb.if_pkt_is_big_endian) { - my_streamer->set_vrt_unpacker(&x300_if_hdr_unpack_be); + my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_be); conv_endianness = "be"; } else { - my_streamer->set_vrt_unpacker(&x300_if_hdr_unpack_le); + my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_le); conv_endianness = "le"; } @@ -594,10 +560,10 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_) std::string conv_endianness; if (mb.if_pkt_is_big_endian) { - my_streamer->set_vrt_packer(&x300_if_hdr_pack_be); + my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_be); conv_endianness = "be"; } else { - my_streamer->set_vrt_packer(&x300_if_hdr_pack_le); + my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_le); conv_endianness = "le"; } |