aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/x300
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/x300')
-rw-r--r--host/lib/usrp/x300/x300_device_args.hpp7
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp62
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());
////////////////////////////////////////////////////////////////////