diff options
Diffstat (limited to 'host/lib/usrp/x300')
-rw-r--r-- | host/lib/usrp/x300/x300_device_args.hpp | 7 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 62 |
2 files changed, 64 insertions, 5 deletions
diff --git a/host/lib/usrp/x300/x300_device_args.hpp b/host/lib/usrp/x300/x300_device_args.hpp index 6c6680c4f..7e17c36ce 100644 --- a/host/lib/usrp/x300/x300_device_args.hpp +++ b/host/lib/usrp/x300/x300_device_args.hpp @@ -197,12 +197,11 @@ private: if (dev_args.has_key(_dboard_clock_rate.key())) { _dboard_clock_rate.parse(dev_args[_dboard_clock_rate.key()]); } else { - // Some daughterboards may require other rates, but this default - // works best for all newer daughterboards (i.e. CBX, WBX, SBX, - // UBX, and TwinRX). + // This default clock rate works best for most daughterboards (i.e. DBSRX2, + // WBX, SBX, CBX, and TwinRX). if (_master_clock_rate.get() >= MIN_TICK_RATE && _master_clock_rate.get() <= MAX_TICK_RATE) { - _dboard_clock_rate.set(_master_clock_rate.get() / 4); + _dboard_clock_rate.set(_master_clock_rate.get() / 2); } else { throw uhd::value_error("Can't infer daughterboard clock rate. Specify " "dboard_clk_rate in the device args."); diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index a414fd0f1..fa8425fac 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -7,6 +7,7 @@ // #include "x300_impl.hpp" +#include "../dboard/db_ubx.hpp" #include "x300_claim.hpp" #include "x300_eth_mgr.hpp" #include "x300_mb_controller.hpp" @@ -15,6 +16,8 @@ #include "x300_mboard_type.hpp" #include "x300_pcie_mgr.hpp" #include <uhd/transport/if_addrs.hpp> +#include <uhd/usrp/dboard_eeprom.hpp> +#include <uhd/usrp/dboard_id.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/paths.hpp> #include <uhd/utils/safe_call.hpp> @@ -141,6 +144,31 @@ device_addrs_t x300_find(const device_addr_t& hint_) } /*********************************************************************** + * Daughterboard detection before initialization in software + **********************************************************************/ +static std::vector<dboard_id_t> get_dboard_ids(uhd::i2c_iface& zpu_i2c) +{ + std::vector<dboard_id_t> dboard_ids; + // Read dboard ids from the EEPROM + constexpr size_t BASE_ADDR = 0x50; + constexpr size_t RX_EEPROM_ADDR = 0x5; + constexpr size_t TX_EEPROM_ADDR = 0x4; + static const std::vector<size_t> DB_OFFSETS{0x0, 0x2}; + static const std::vector<size_t> EEPROM_ADDRS{RX_EEPROM_ADDR, TX_EEPROM_ADDR}; + for (size_t eeprom_addr : EEPROM_ADDRS) { + for (size_t db_offset : DB_OFFSETS) { + const size_t addr = eeprom_addr + db_offset; + // Load EEPROM + std::unordered_map<size_t, usrp::dboard_eeprom_t> db_eeproms; + db_eeproms[addr].load(zpu_i2c, BASE_ADDR | addr); + uint16_t dboard_id = db_eeproms[addr].id.to_uint16(); + dboard_ids.push_back(static_cast<dboard_id_t>(dboard_id)); + } + } + return dboard_ids; +} + +/*********************************************************************** * Make **********************************************************************/ static device::sptr x300_make(const device_addr_t& device_addr) @@ -331,13 +359,45 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t& dev_addr) // create clock control objects //////////////////////////////////////////////////////////////////// UHD_LOGGER_DEBUG("X300") << "Setting up RF frontend clocking..."; + + // The default daughterboard clock rate may have to be overridden. This is due to the + // limitation on X300 devices where both daughterboards must use the same clock rate. + // The daughterboards that require specific clock rates are UBX and TwinRX. TwinRX + // requires a clock rate of 100 MHz for the best RF performance. UBX daughterboards + // require a clock rate of no more than the max pfd frequency to maintain phase + // synchronization. If there is no UBX, the default daughterboard clock rate is half + // of the master clock rate for X300. + const double x300_dboard_clock_rate = [this, dev_addr, mb]() -> double { + // Do not override use-specified dboard clock rates + if (dev_addr.has_key("dboard_clock_rate")) { + return mb.args.get_dboard_clock_rate(); + } + const double mcr = mb.args.get_master_clock_rate(); + double dboard_clock_rate = mb.args.get_dboard_clock_rate(); + // Check for UBX daughterboards + std::vector<dboard_id_t> dboard_ids = get_dboard_ids(*mb.zpu_i2c); + for (dboard_id_t dboard_id : dboard_ids) { + if (std::find( + dboard::ubx::ubx_ids.begin(), dboard::ubx::ubx_ids.end(), dboard_id) + != dboard::ubx::ubx_ids.end()) { + double ubx_clock_rate = mcr; + for (int i = 2; ubx_clock_rate > dboard::ubx::get_max_pfd_freq(dboard_id); + i++) { + ubx_clock_rate = mcr / i; + } + dboard_clock_rate = std::min(dboard_clock_rate, ubx_clock_rate); + } + } + return dboard_clock_rate; + }(); + // Initialize clock control registers. // NOTE: This does not configure the LMK yet. mb.clock = x300_clock_ctrl::make(mb.zpu_spi, 1 /*slaveno*/, mb.hw_rev, mb.args.get_master_clock_rate(), - mb.args.get_dboard_clock_rate(), + x300_dboard_clock_rate, mb.args.get_system_ref_rate()); //////////////////////////////////////////////////////////////////// |