diff options
-rw-r--r-- | host/examples/init_usrp/.gitignore | 1 | ||||
-rw-r--r-- | host/examples/init_usrp/CMakeLists.txt | 8 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 1 | ||||
-rw-r--r-- | host/lib/usrp/common/ad9361_ctrl.cpp | 9 | ||||
-rw-r--r-- | host/lib/usrp/common/ad9361_ctrl.hpp | 3 | ||||
-rw-r--r-- | host/lib/usrp/common/ad9361_driver/ad9361_device.cpp | 23 | ||||
-rw-r--r-- | host/lib/usrp/common/ad9361_driver/ad9361_device.h | 14 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_impl.cpp | 1 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_network.cpp | 3 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_remote_codec_ctrl.cpp | 14 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_remote_codec_ctrl.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_clock_ctrl.cpp | 44 |
12 files changed, 99 insertions, 24 deletions
diff --git a/host/examples/init_usrp/.gitignore b/host/examples/init_usrp/.gitignore new file mode 100644 index 000000000..567609b12 --- /dev/null +++ b/host/examples/init_usrp/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/host/examples/init_usrp/CMakeLists.txt b/host/examples/init_usrp/CMakeLists.txt index 3560dbd45..8705b4a8d 100644 --- a/host/examples/init_usrp/CMakeLists.txt +++ b/host/examples/init_usrp/CMakeLists.txt @@ -55,6 +55,14 @@ link_directories(${Boost_LIBRARY_DIRS}) ### Make the executable ####################################################### add_executable(init_usrp init_usrp.cpp) +SET(CMAKE_BUILD_TYPE "Release") +MESSAGE(STATUS "******************************************************************************") +MESSAGE(STATUS "* NOTE: When building your own app, you probably need all kinds of different ") +MESSAGE(STATUS "* compiler flags. This is just an example, so it's unlikely these settings ") +MESSAGE(STATUS "* exactly matchh what you require. Make sure to double-check compiler and ") +MESSAGE(STATUS "* linker flags to make sure your specific requirements are included. ") +MESSAGE(STATUS "******************************************************************************") + # Shared library case: All we need to do is link against the library, and # anything else we need (in this case, some Boost libraries): if(NOT UHD_USE_STATIC_LIBS) diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index feb5a2d04..768fde313 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -743,6 +743,7 @@ void b200_impl::setup_radio(const size_t dspno) _tree->create<meta_range_t>(rf_fe_path / "bandwidth" / "range") .publish(boost::bind(&ad9361_ctrl::get_bw_filter_range, key)); _tree->create<double>(rf_fe_path / "freq" / "value") + .publish(boost::bind(&ad9361_ctrl::get_freq, _codec_ctrl, key)) .coerce(boost::bind(&ad9361_ctrl::tune, _codec_ctrl, key, _1)) .subscribe(boost::bind(&b200_impl::update_bandsel, this, key, _1)) .set(B200_DEFAULT_FREQ); diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp index f3ab36247..2d9f297b3 100644 --- a/host/lib/usrp/common/ad9361_ctrl.cpp +++ b/host/lib/usrp/common/ad9361_ctrl.cpp @@ -169,6 +169,15 @@ public: return _device.tune(direction, value); } + //! get the current frequency for the given frontend + double get_freq(const std::string &which) + { + boost::lock_guard<boost::mutex> lock(_mutex); + + ad9361_device_t::direction_t direction = _get_direction_from_antenna(which); + return _device.get_freq(direction); + } + //! turn on/off data port loopback void data_port_loopback(const bool on) { diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp index a6d65ad11..ac0404b24 100644 --- a/host/lib/usrp/common/ad9361_ctrl.hpp +++ b/host/lib/usrp/common/ad9361_ctrl.hpp @@ -122,6 +122,9 @@ public: //! enable or disable the quadrature calibration virtual void set_iq_balance_auto(const std::string &which, const bool on) = 0; + //! get the current frequency for the given frontend + virtual double get_freq(const std::string &which) = 0; + //! turn on/off Catalina's data port loopback virtual void data_port_loopback(const bool on) = 0; diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index 8737837b3..85e81cf97 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -1140,7 +1140,7 @@ double ad9361_device_t::_tune_bbvco(const double rate) const double vcomin = 672e6; double vcorate; int vcodiv; - + /* Iterate over VCO dividers until appropriate divider is found. */ int i = 1; for (; i <= 6; i++) { @@ -1337,7 +1337,7 @@ double ad9361_device_t::_setup_rates(const double rate) /* If we make it into this function, then we are tuning to a new rate. * Store the new rate. */ _req_clock_rate = rate; - UHD_LOG << boost::format("[ad9361_device_t::_setup_rates] rate=%d\n") % rate; + UHD_LOG << boost::format("[ad9361_device_t::_setup_rates] rate=%.6d\n") % rate; /* Set the decimation and interpolation values in the RX and TX chains. * This also switches filters in / out. Note that all transmitters and @@ -1734,7 +1734,9 @@ double ad9361_device_t::set_clock_rate(const double req_rate) * starts up. This prevents that, and any bugs in user code that request * the same rate over and over. */ if (freq_is_nearly_equal(req_rate, _req_clock_rate)) { - return _baseband_bw; // IJB. Should this not return req_rate? + // We return _baseband_bw, because that's closest to the + // actual value we're currently running. + return _baseband_bw; } /* We must be in the SLEEP / WAIT state to do this. If we aren't already @@ -1966,10 +1968,21 @@ double ad9361_device_t::tune(direction_t direction, const double value) return tune_freq; } +/* Get the current RX or TX frequency. */ +double ad9361_device_t::get_freq(direction_t direction) +{ + boost::lock_guard<boost::recursive_mutex> lock(_mutex); + + if (direction == RX) + return _rx_freq; + else + return _tx_freq; +} + /* Set the gain of RX1, RX2, TX1, or TX2. * - * Note that the 'value' passed to this function is the gain index - * for RX. Also note that the RX chains are done in terms of gain, and + * Note that the 'value' passed to this function is the gain index + * for RX. Also note that the RX chains are done in terms of gain, and * the TX chains are done in terms of attenuation. */ double ad9361_device_t::set_gain(direction_t direction, chain_t chain, const double value) { diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index 0c7a7e4f7..1c5c97829 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -81,6 +81,9 @@ public: * After tuning, it runs any appropriate calibrations. */ double tune(direction_t direction, const double value); + /* Get the current RX or TX frequency. */ + double get_freq(direction_t direction); + /* Set the gain of RX1, RX2, TX1, or TX2. * * Note that the 'value' passed to this function is the actual gain value, @@ -213,10 +216,17 @@ private: //Members //Intermediate state double _rx_freq, _tx_freq, _req_rx_freq, _req_tx_freq; double _last_calibration_freq; - double _baseband_bw, _bbpll_freq, _adcclock_freq; double _rx_analog_bw, _tx_analog_bw, _rx_bb_lp_bw, _tx_bb_lp_bw; double _rx_tia_lp_bw, _tx_sec_lp_bw; - double _req_clock_rate, _req_coreclk; + //! Current baseband sampling rate (this is the actual rate the device is + // is running at) + double _baseband_bw; + double _bbpll_freq, _adcclock_freq; + //! This was the last clock rate value that was requested. + // It is cached so we don't need to re-set the clock rate + // if another call to set_clock_rate() actually has the same value. + double _req_clock_rate; + double _req_coreclk; boost::uint16_t _rx_bbf_tunediv; boost::uint8_t _curr_gain_table; double _rx1_gain, _rx2_gain, _tx1_gain, _tx2_gain; diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index c7c007a20..231816fe8 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -1068,6 +1068,7 @@ void e300_impl::_setup_radio(const size_t dspno) _tree->create<meta_range_t>(rf_fe_path / "bandwidth" / "range") .publish(boost::bind(&ad9361_ctrl::get_bw_filter_range, key)); _tree->create<double>(rf_fe_path / "freq" / "value") + .publish(boost::bind(&ad9361_ctrl::get_freq, _codec_ctrl, key)) .coerce(boost::bind(&ad9361_ctrl::tune, _codec_ctrl, key, _1)) .subscribe(boost::bind(&e300_impl::_update_fe_lo_freq, this, key, _1)) .set(e300::DEFAULT_FE_FREQ); diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 2a63abc25..d68dc4541 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -220,6 +220,9 @@ static void e300_codec_ctrl_tunnel( case codec_xact_t::ACTION_TUNE: out->freq = _codec_ctrl->tune(which_str, in->freq); break; + case codec_xact_t::ACTION_GET_FREQ: + out->freq = _codec_ctrl->get_freq(which_str); + break; case codec_xact_t::ACTION_SET_LOOPBACK: _codec_ctrl->data_port_loopback( uhd::ntohx<boost::uint32_t>(in->bits) & 1); diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp index d3efdb812..9708634dd 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp @@ -96,6 +96,20 @@ public: return _retval.freq; } + double get_freq(const std::string &which) + { + _clear(); + _args.action = uhd::htonx<boost::uint32_t>(transaction_t::ACTION_GET_FREQ); + if (which == "TX1") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_TX1); + else if (which == "TX2") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_TX2); + else if (which == "RX1") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_RX1); + else if (which == "RX2") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_RX2); + else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); + + _transact(); + return _retval.freq; + } + void data_port_loopback(const bool on) { _clear(); diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp index 065c5e7a0..43723e0d5 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp @@ -56,7 +56,7 @@ public: static const boost::uint32_t ACTION_SET_AGC = 19; static const boost::uint32_t ACTION_SET_AGC_MODE = 20; static const boost::uint32_t ACTION_SET_BW = 21; - + static const boost::uint32_t ACTION_GET_FREQ = 22; //Values for "which" static const boost::uint32_t CHAIN_NONE = 0; diff --git a/host/lib/usrp/x300/x300_clock_ctrl.cpp b/host/lib/usrp/x300/x300_clock_ctrl.cpp index 04a9e4bec..e182f649b 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.cpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2013-2014 Ettus Research LLC +// Copyright 2013-2015 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 @@ -18,6 +18,7 @@ #include "lmk04816_regs.hpp" #include "x300_clock_ctrl.hpp" #include <uhd/utils/safe_call.hpp> +#include <uhd/utils/math.hpp> #include <boost/cstdint.hpp> #include <boost/format.hpp> #include <stdexcept> @@ -96,7 +97,7 @@ public: boost::uint8_t addr = 0xFF; // Make sure requested rate is an even divisor of the VCO frequency - if (not doubles_are_equal(_vco_freq / div, rate)) + if (not math::frequencies_are_equal(_vco_freq / div, rate)) throw uhd::value_error("invalid dboard rate requested"); switch (which) @@ -236,27 +237,42 @@ private: * clock, in zero-delay mode. */ opmode_t clocking_mode = INVALID; - if(doubles_are_equal(_system_ref_rate, 10e6)) { - if(doubles_are_equal(_master_clock_rate, 184.32e6)) { + if (math::frequencies_are_equal(_system_ref_rate, 10e6)) { + if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 10MHz reference, 184.32 MHz master clock out, NOT Zero Delay. */ clocking_mode = m10M_184_32M_NOZDEL; - } else if(doubles_are_equal(_master_clock_rate, 200e6)) { + } else if (math::frequencies_are_equal(_master_clock_rate, 200e6)) { /* 10MHz reference, 200 MHz master clock out, Zero Delay */ clocking_mode = m10M_200M_ZDEL; - } else if(doubles_are_equal(_master_clock_rate, 120e6)) { + } else if (math::frequencies_are_equal(_master_clock_rate, 120e6)) { /* 10MHz reference, 120 MHz master clock rate, Zero Delay */ clocking_mode = m10M_120M_ZDEL; + } else { + throw uhd::runtime_error(str( + boost::format("Invalid master clock rate: %.2f MHz.\n" + "Valid master clock rates when using a %f MHz reference clock are:\n" + "120 MHz, 184.32 MHz and 200 MHz.") + % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6) + )); } - } else if(doubles_are_equal(_system_ref_rate, 30.72e6)) { - if(doubles_are_equal(_master_clock_rate, 184.32e6)) { + } else if (math::frequencies_are_equal(_system_ref_rate, 30.72e6)) { + if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 30.72MHz reference, 184.32 MHz master clock out, Zero Delay */ clocking_mode = m30_72M_184_32M_ZDEL; + } else { + throw uhd::runtime_error(str( + boost::format("Invalid master clock rate: %.2f MHz.\n" + "Valid master clock rate when using a %.2f MHz reference clock is: 184.32 MHz.") + % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6) + )); } + } else { + throw uhd::runtime_error(str( + boost::format("Invalid system reference rate: %.2f MHz.\nValid reference frequencies are: 10 MHz, 30.72 MHz.") + % (_system_ref_rate / 1e6) + )); } - - if(clocking_mode == INVALID) { - throw uhd::runtime_error(str(boost::format("A master clock rate of %f cannot be derived from a system reference rate of %f") % _master_clock_rate % _system_ref_rate)); - } + UHD_ASSERT_THROW(clocking_mode != INVALID); // For 200 MHz output, the VCO is run at 2400 MHz // For the LTE/CPRI rate of 184.32 MHz, the VCO runs at 2580.48 MHz @@ -501,10 +517,6 @@ private: this->sync_clocks(); } - UHD_INLINE bool doubles_are_equal(double a, double b) { - return (std::fabs(a - b) < std::numeric_limits<double>::epsilon()); - } - const spi_iface::sptr _spiface; const size_t _slaveno; const size_t _hw_rev; |