diff options
Diffstat (limited to 'host/lib/usrp/x300')
22 files changed, 3328 insertions, 2957 deletions
diff --git a/host/lib/usrp/x300/x300_adc_ctrl.cpp b/host/lib/usrp/x300/x300_adc_ctrl.cpp index b8101753f..26c1d85ff 100644 --- a/host/lib/usrp/x300/x300_adc_ctrl.cpp +++ b/host/lib/usrp/x300/x300_adc_ctrl.cpp @@ -7,14 +7,15 @@ #include "x300_adc_ctrl.hpp" #include "ads62p48_regs.hpp" +#include <uhd/exception.hpp> #include <uhd/types/ranges.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/safe_call.hpp> -#include <uhd/exception.hpp> using namespace uhd; -x300_adc_ctrl::~x300_adc_ctrl(void){ +x300_adc_ctrl::~x300_adc_ctrl(void) +{ /* NOP */ } @@ -24,26 +25,26 @@ x300_adc_ctrl::~x300_adc_ctrl(void){ class x300_adc_ctrl_impl : public x300_adc_ctrl { public: - x300_adc_ctrl_impl(uhd::spi_iface::sptr iface, const size_t slaveno): - _iface(iface), _slaveno(slaveno) + x300_adc_ctrl_impl(uhd::spi_iface::sptr iface, const size_t slaveno) + : _iface(iface), _slaveno(slaveno) { init(); } void init() { - //power-up adc - _ads62p48_regs.reset = 1; - this->send_ads62p48_reg(0x00); //issue a reset to the ADC - _ads62p48_regs.reset = 0; + // power-up adc + _ads62p48_regs.reset = 1; + this->send_ads62p48_reg(0x00); // issue a reset to the ADC + _ads62p48_regs.reset = 0; _ads62p48_regs.enable_low_speed_mode = 0; - _ads62p48_regs.ref = ads62p48_regs_t::REF_INTERNAL; - _ads62p48_regs.standby = ads62p48_regs_t::STANDBY_NORMAL; - _ads62p48_regs.power_down = ads62p48_regs_t::POWER_DOWN_NORMAL; - _ads62p48_regs.lvds_cmos = ads62p48_regs_t::LVDS_CMOS_DDR_LVDS; - _ads62p48_regs.channel_control = ads62p48_regs_t::CHANNEL_CONTROL_INDEPENDENT; - _ads62p48_regs.data_format = ads62p48_regs_t::DATA_FORMAT_2S_COMPLIMENT; + _ads62p48_regs.ref = ads62p48_regs_t::REF_INTERNAL; + _ads62p48_regs.standby = ads62p48_regs_t::STANDBY_NORMAL; + _ads62p48_regs.power_down = ads62p48_regs_t::POWER_DOWN_NORMAL; + _ads62p48_regs.lvds_cmos = ads62p48_regs_t::LVDS_CMOS_DDR_LVDS; + _ads62p48_regs.channel_control = ads62p48_regs_t::CHANNEL_CONTROL_INDEPENDENT; + _ads62p48_regs.data_format = ads62p48_regs_t::DATA_FORMAT_2S_COMPLIMENT; _ads62p48_regs.clk_out_pos_edge = ads62p48_regs_t::CLK_OUT_POS_EDGE_MINUS4_26; _ads62p48_regs.clk_out_neg_edge = ads62p48_regs_t::CLK_OUT_NEG_EDGE_MINUS4_26; @@ -67,7 +68,6 @@ public: this->send_ads62p48_reg(0x6a); this->send_ads62p48_reg(0x75); this->send_ads62p48_reg(0x76); - } void reset() @@ -75,31 +75,42 @@ public: init(); } - double set_gain(const double &gain) + double set_gain(const double& gain) { const meta_range_t gain_range = meta_range_t(0, 6.0, 0.5); - const int gain_bits = int((gain_range.clip(gain)*2.0) + 0.5); - _ads62p48_regs.gain_chA = gain_bits; - _ads62p48_regs.gain_chB = gain_bits; + const int gain_bits = int((gain_range.clip(gain) * 2.0) + 0.5); + _ads62p48_regs.gain_chA = gain_bits; + _ads62p48_regs.gain_chB = gain_bits; this->send_ads62p48_reg(0x55); this->send_ads62p48_reg(0x68); - return gain_bits/2; + return gain_bits / 2; } - void set_test_word(const std::string &patterna, const std::string &patternb, const uint32_t num) + void set_test_word( + const std::string& patterna, const std::string& patternb, const uint32_t num) { - _ads62p48_regs.custom_pattern_low = num & 0xff; + _ads62p48_regs.custom_pattern_low = num & 0xff; _ads62p48_regs.custom_pattern_high = num >> 8; - if (patterna == "ones") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ONES; - if (patterna == "zeros") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ZEROS; - if (patterna == "custom") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_CUSTOM; - if (patterna == "ramp") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_RAMP; - if (patterna == "normal") _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_NORMAL; - if (patternb == "ones") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ONES; - if (patternb == "zeros") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ZEROS; - if (patternb == "custom") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_CUSTOM; - if (patterna == "ramp") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_RAMP; - if (patterna == "normal") _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_NORMAL; + if (patterna == "ones") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ONES; + if (patterna == "zeros") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_ZEROS; + if (patterna == "custom") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_CUSTOM; + if (patterna == "ramp") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_RAMP; + if (patterna == "normal") + _ads62p48_regs.test_patterns_chA = ads62p48_regs_t::TEST_PATTERNS_CHA_NORMAL; + if (patternb == "ones") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ONES; + if (patternb == "zeros") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_ZEROS; + if (patternb == "custom") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_CUSTOM; + if (patterna == "ramp") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_RAMP; + if (patterna == "normal") + _ads62p48_regs.test_patterns_chB = ads62p48_regs_t::TEST_PATTERNS_CHB_NORMAL; this->send_ads62p48_reg(0x51); this->send_ads62p48_reg(0x52); this->send_ads62p48_reg(0x62); @@ -109,10 +120,7 @@ public: ~x300_adc_ctrl_impl(void) { _ads62p48_regs.power_down = ads62p48_regs_t::POWER_DOWN_GLOBAL; - UHD_SAFE_CALL - ( - this->send_ads62p48_reg(0x40); - ) + UHD_SAFE_CALL(this->send_ads62p48_reg(0x40);) } private: diff --git a/host/lib/usrp/x300/x300_adc_ctrl.hpp b/host/lib/usrp/x300/x300_adc_ctrl.hpp index eb29dd28f..106d79eed 100644 --- a/host/lib/usrp/x300/x300_adc_ctrl.hpp +++ b/host/lib/usrp/x300/x300_adc_ctrl.hpp @@ -27,9 +27,10 @@ public: */ static sptr make(uhd::spi_iface::sptr iface, const size_t slaveno); - virtual double set_gain(const double &) = 0; + virtual double set_gain(const double&) = 0; - virtual void set_test_word(const std::string &patterna, const std::string &patternb, const uint32_t = 0) = 0; + virtual void set_test_word( + const std::string& patterna, const std::string& patternb, const uint32_t = 0) = 0; virtual void reset(void) = 0; }; diff --git a/host/lib/usrp/x300/x300_clock_ctrl.cpp b/host/lib/usrp/x300/x300_clock_ctrl.cpp index 93e02ca7d..a867a9138 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.cpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.cpp @@ -5,32 +5,43 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "lmk04816_regs.hpp" #include "x300_clock_ctrl.hpp" +#include "lmk04816_regs.hpp" #include "x300_defaults.hpp" -#include <uhd/utils/safe_call.hpp> #include <uhd/utils/math.hpp> +#include <uhd/utils/safe_call.hpp> #include <stdint.h> #include <boost/format.hpp> #include <boost/math/special_functions/round.hpp> -#include <stdexcept> #include <cmath> #include <cstdlib> +#include <stdexcept> -static const double X300_REF_CLK_OUT_RATE = 10e6; +static const double X300_REF_CLK_OUT_RATE = 10e6; static const uint16_t X300_MAX_CLKOUT_DIV = 1045; -constexpr double MIN_VCO_FREQ = 2370e6; -constexpr double MAX_VCO_FREQ = 2600e6; -constexpr double VCXO_FREQ = 96.0e6; // VCXO runs at 96MHz -constexpr int VCXO_PLL2_N = 2; // Assume that the PLL2 N predivider is set to /2. - -struct x300_clk_delays { - x300_clk_delays() : - fpga_dly_ns(0.0),adc_dly_ns(0.0),dac_dly_ns(0.0),db_rx_dly_ns(0.0),db_tx_dly_ns(0.0) - {} - x300_clk_delays(double fpga, double adc, double dac, double db_rx, double db_tx) : - fpga_dly_ns(fpga),adc_dly_ns(adc),dac_dly_ns(dac),db_rx_dly_ns(db_rx),db_tx_dly_ns(db_tx) - {} +constexpr double MIN_VCO_FREQ = 2370e6; +constexpr double MAX_VCO_FREQ = 2600e6; +constexpr double VCXO_FREQ = 96.0e6; // VCXO runs at 96MHz +constexpr int VCXO_PLL2_N = 2; // Assume that the PLL2 N predivider is set to /2. + +struct x300_clk_delays +{ + x300_clk_delays() + : fpga_dly_ns(0.0) + , adc_dly_ns(0.0) + , dac_dly_ns(0.0) + , db_rx_dly_ns(0.0) + , db_tx_dly_ns(0.0) + { + } + x300_clk_delays(double fpga, double adc, double dac, double db_rx, double db_tx) + : fpga_dly_ns(fpga) + , adc_dly_ns(adc) + , dac_dly_ns(dac) + , db_rx_dly_ns(db_rx) + , db_tx_dly_ns(db_tx) + { + } double fpga_dly_ns; double adc_dly_ns; @@ -51,14 +62,14 @@ static const x300_clk_delays X300_REV7_CLK_DELAYS = x300_clk_delays( using namespace uhd; using namespace uhd::math::fp_compare; -x300_clock_ctrl::~x300_clock_ctrl(void){ +x300_clock_ctrl::~x300_clock_ctrl(void) +{ /* NOP */ } -class x300_clock_ctrl_impl : public x300_clock_ctrl { - +class x300_clock_ctrl_impl : public x300_clock_ctrl +{ public: - ~x300_clock_ctrl_impl(void) {} x300_clock_ctrl_impl(uhd::spi_iface::sptr spiface, @@ -66,18 +77,19 @@ public: const size_t hw_rev, const double master_clock_rate, const double dboard_clock_rate, - const double system_ref_rate): - _spiface(spiface), - _slaveno(static_cast<int>(slaveno)), - _hw_rev(hw_rev), - _master_clock_rate(master_clock_rate), - _dboard_clock_rate(dboard_clock_rate), - _system_ref_rate(system_ref_rate) + const double system_ref_rate) + : _spiface(spiface) + , _slaveno(static_cast<int>(slaveno)) + , _hw_rev(hw_rev) + , _master_clock_rate(master_clock_rate) + , _dboard_clock_rate(dboard_clock_rate) + , _system_ref_rate(system_ref_rate) { init(); } - void reset_clocks() { + void reset_clocks() + { _lmk04816_regs.RESET = lmk04816_regs_t::RESET_RESET; this->write_regs(0); _lmk04816_regs.RESET = lmk04816_regs_t::RESET_NO_RESET; @@ -90,52 +102,56 @@ public: sync_clocks(); } - void sync_clocks(void) { - //soft sync: - //put the sync IO into output mode - FPGA must be input - //write low, then write high - this triggers a soft sync + void sync_clocks(void) + { + // soft sync: + // put the sync IO into output mode - FPGA must be input + // write low, then write high - this triggers a soft sync _lmk04816_regs.SYNC_POL_INV = lmk04816_regs_t::SYNC_POL_INV_SYNC_LOW; this->write_regs(11); _lmk04816_regs.SYNC_POL_INV = lmk04816_regs_t::SYNC_POL_INV_SYNC_HIGH; this->write_regs(11); } - double get_master_clock_rate(void) { + double get_master_clock_rate(void) + { return _master_clock_rate; } - double get_sysref_clock_rate(void) { + double get_sysref_clock_rate(void) + { return _system_ref_rate; } - double get_refout_clock_rate(void) { - //We support only one reference output rate + double get_refout_clock_rate(void) + { + // We support only one reference output rate return X300_REF_CLK_OUT_RATE; } - void set_dboard_rate(const x300_clock_which_t which, double rate) { - uint16_t div = uint16_t(_vco_freq / rate); - uint16_t *reg = NULL; - uint8_t addr = 0xFF; + void set_dboard_rate(const x300_clock_which_t which, double rate) + { + uint16_t div = uint16_t(_vco_freq / rate); + uint16_t* reg = NULL; + uint8_t addr = 0xFF; // Make sure requested rate is an even divisor of the VCO frequency if (not math::frequencies_are_equal(_vco_freq / div, rate)) throw uhd::value_error("invalid dboard rate requested"); - switch (which) - { - case X300_CLOCK_WHICH_DB0_RX: - case X300_CLOCK_WHICH_DB1_RX: - reg = &_lmk04816_regs.CLKout2_3_DIV; - addr = 1; - break; - case X300_CLOCK_WHICH_DB0_TX: - case X300_CLOCK_WHICH_DB1_TX: - reg = &_lmk04816_regs.CLKout4_5_DIV; - addr = 2; - break; - default: - UHD_THROW_INVALID_CODE_PATH(); + switch (which) { + case X300_CLOCK_WHICH_DB0_RX: + case X300_CLOCK_WHICH_DB1_RX: + reg = &_lmk04816_regs.CLKout2_3_DIV; + addr = 1; + break; + case X300_CLOCK_WHICH_DB0_TX: + case X300_CLOCK_WHICH_DB1_TX: + reg = &_lmk04816_regs.CLKout4_5_DIV; + addr = 2; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } if (*reg == div) @@ -143,13 +159,15 @@ public: // Since the clock rate on one daughter board cannot be changed without // affecting the other daughter board, don't allow it. - throw uhd::not_implemented_error("x3xx set dboard clock rate does not support changing the clock rate"); + throw uhd::not_implemented_error( + "x3xx set dboard clock rate does not support changing the clock rate"); // This is open source code and users may need to enable this function // to support other daughterboards. If so, comment out the line above // that throws the error and allow the program to reach the code below. - // The LMK04816 datasheet says the register must be written twice if SYNC is enabled + // The LMK04816 datasheet says the register must be written twice if SYNC is + // enabled *reg = div; write_regs(addr); write_regs(addr); @@ -159,18 +177,17 @@ public: double get_dboard_rate(const x300_clock_which_t which) { double rate = 0.0; - switch (which) - { - case X300_CLOCK_WHICH_DB0_RX: - case X300_CLOCK_WHICH_DB1_RX: - rate = _vco_freq / _lmk04816_regs.CLKout2_3_DIV; - break; - case X300_CLOCK_WHICH_DB0_TX: - case X300_CLOCK_WHICH_DB1_TX: - rate = _vco_freq / _lmk04816_regs.CLKout4_5_DIV; - break; - default: - UHD_THROW_INVALID_CODE_PATH(); + switch (which) { + case X300_CLOCK_WHICH_DB0_RX: + case X300_CLOCK_WHICH_DB1_RX: + rate = _vco_freq / _lmk04816_regs.CLKout2_3_DIV; + break; + case X300_CLOCK_WHICH_DB0_TX: + case X300_CLOCK_WHICH_DB1_TX: + rate = _vco_freq / _lmk04816_regs.CLKout4_5_DIV; + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } return rate; } @@ -178,49 +195,63 @@ public: std::vector<double> get_dboard_rates(const x300_clock_which_t) { std::vector<double> rates; - for (size_t div = size_t(_vco_freq / _master_clock_rate); div <= X300_MAX_CLKOUT_DIV; div++) + for (size_t div = size_t(_vco_freq / _master_clock_rate); + div <= X300_MAX_CLKOUT_DIV; + div++) rates.push_back(_vco_freq / div); return rates; } void enable_dboard_clock(const x300_clock_which_t which, const bool enable) { - switch (which) - { - case X300_CLOCK_WHICH_DB0_RX: - if (enable != (_lmk04816_regs.CLKout2_TYPE == lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP)) - { - _lmk04816_regs.CLKout2_TYPE = enable ? lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP : lmk04816_regs_t::CLKOUT2_TYPE_P_DOWN; - write_regs(6); - } - break; - case X300_CLOCK_WHICH_DB1_RX: - if (enable != (_lmk04816_regs.CLKout3_TYPE == lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP)) - { - _lmk04816_regs.CLKout3_TYPE = enable ? lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP : lmk04816_regs_t::CLKOUT3_TYPE_P_DOWN; - write_regs(6); - } - break; - case X300_CLOCK_WHICH_DB0_TX: - if (enable != (_lmk04816_regs.CLKout5_TYPE == lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP)) - { - _lmk04816_regs.CLKout5_TYPE = enable ? lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP : lmk04816_regs_t::CLKOUT5_TYPE_P_DOWN; - write_regs(7); - } - break; - case X300_CLOCK_WHICH_DB1_TX: - if (enable != (_lmk04816_regs.CLKout4_TYPE == lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP)) - { - _lmk04816_regs.CLKout4_TYPE = enable ? lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP : lmk04816_regs_t::CLKOUT4_TYPE_P_DOWN; - write_regs(7); - } - break; - default: - UHD_THROW_INVALID_CODE_PATH(); + switch (which) { + case X300_CLOCK_WHICH_DB0_RX: + if (enable + != (_lmk04816_regs.CLKout2_TYPE + == lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP)) { + _lmk04816_regs.CLKout2_TYPE = + enable ? lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP + : lmk04816_regs_t::CLKOUT2_TYPE_P_DOWN; + write_regs(6); + } + break; + case X300_CLOCK_WHICH_DB1_RX: + if (enable + != (_lmk04816_regs.CLKout3_TYPE + == lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP)) { + _lmk04816_regs.CLKout3_TYPE = + enable ? lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP + : lmk04816_regs_t::CLKOUT3_TYPE_P_DOWN; + write_regs(6); + } + break; + case X300_CLOCK_WHICH_DB0_TX: + if (enable + != (_lmk04816_regs.CLKout5_TYPE + == lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP)) { + _lmk04816_regs.CLKout5_TYPE = + enable ? lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP + : lmk04816_regs_t::CLKOUT5_TYPE_P_DOWN; + write_regs(7); + } + break; + case X300_CLOCK_WHICH_DB1_TX: + if (enable + != (_lmk04816_regs.CLKout4_TYPE + == lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP)) { + _lmk04816_regs.CLKout4_TYPE = + enable ? lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP + : lmk04816_regs_t::CLKOUT4_TYPE_P_DOWN; + write_regs(7); + } + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } } - void set_ref_out(const bool enable) { + void set_ref_out(const bool enable) + { // TODO Implement divider configuration to allow for configurable output // rates if (enable) @@ -230,44 +261,48 @@ public: this->write_regs(8); } - void write_regs(uint8_t addr) { + void write_regs(uint8_t addr) + { uint32_t data = _lmk04816_regs.get_reg(addr); - _spiface->write_spi(_slaveno, spi_config_t::EDGE_RISE, data,32); + _spiface->write_spi(_slaveno, spi_config_t::EDGE_RISE, data, 32); } - double set_clock_delay(const x300_clock_which_t which, const double delay_ns, const bool resync = true) { - //All dividers have are delayed by 5 taps by default. The delay - //set by this function is relative to the 5 tap delay - static const uint16_t DDLY_MIN_TAPS = 5; - static const uint16_t DDLY_MAX_TAPS = 522; //Extended mode + double set_clock_delay( + const x300_clock_which_t which, const double delay_ns, const bool resync = true) + { + // All dividers have are delayed by 5 taps by default. The delay + // set by this function is relative to the 5 tap delay + static const uint16_t DDLY_MIN_TAPS = 5; + static const uint16_t DDLY_MAX_TAPS = 522; // Extended mode - //The resolution and range of the analog delay is fixed + // The resolution and range of the analog delay is fixed static const double ADLY_RES_NS = 0.025; static const double ADLY_MIN_NS = 0.500; static const double ADLY_MAX_NS = 0.975; - //Each digital tap delays the clock by one VCO period - double vco_period_ns = 1.0e9/_vco_freq; - double half_vco_period_ns = vco_period_ns/2.0; + // Each digital tap delays the clock by one VCO period + double vco_period_ns = 1.0e9 / _vco_freq; + double half_vco_period_ns = vco_period_ns / 2.0; - //Implement as much of the requested delay using digital taps. Whatever is leftover - //will be made up using the analog delay element and the half-cycle digital tap. - //A caveat here is that the analog delay starts at ADLY_MIN_NS, so we need to back off - //by that much when coming up with the digital taps so that the difference can be made - //up using the analog delay. + // Implement as much of the requested delay using digital taps. Whatever is + // leftover will be made up using the analog delay element and the half-cycle + // digital tap. A caveat here is that the analog delay starts at ADLY_MIN_NS, so + // we need to back off by that much when coming up with the digital taps so that + // the difference can be made up using the analog delay. uint16_t ddly_taps = 0; if (delay_ns < ADLY_MIN_NS) { - ddly_taps = static_cast<uint16_t>(std::floor((delay_ns)/vco_period_ns)); + ddly_taps = static_cast<uint16_t>(std::floor((delay_ns) / vco_period_ns)); } else { - ddly_taps = static_cast<uint16_t>(std::floor((delay_ns-ADLY_MIN_NS)/vco_period_ns)); + ddly_taps = static_cast<uint16_t>( + std::floor((delay_ns - ADLY_MIN_NS) / vco_period_ns)); } double leftover_delay = delay_ns - (vco_period_ns * ddly_taps); - //Compute settings - uint16_t ddly_value = ddly_taps + DDLY_MIN_TAPS; - bool adly_en = false; - uint8_t adly_value = 0; - uint8_t half_shift_en = 0; + // Compute settings + uint16_t ddly_value = ddly_taps + DDLY_MIN_TAPS; + bool adly_en = false; + uint8_t adly_value = 0; + uint8_t half_shift_en = 0; if (ddly_value > DDLY_MAX_TAPS) { throw uhd::value_error("set_clock_delay: Requested delay is out of range."); @@ -275,172 +310,203 @@ public: double coerced_delay = (vco_period_ns * ddly_taps); if (leftover_delay > ADLY_MAX_NS) { - //The VCO is running too slowly for us to compensate the digital delay difference using - //analog delay. Do the best we can. - adly_en = true; - adly_value = static_cast<uint8_t>(boost::math::round((ADLY_MAX_NS-ADLY_MIN_NS)/ADLY_RES_NS)); + // The VCO is running too slowly for us to compensate the digital delay + // difference using analog delay. Do the best we can. + adly_en = true; + adly_value = static_cast<uint8_t>( + boost::math::round((ADLY_MAX_NS - ADLY_MIN_NS) / ADLY_RES_NS)); coerced_delay += ADLY_MAX_NS; } else if (leftover_delay >= ADLY_MIN_NS && leftover_delay <= ADLY_MAX_NS) { - //The leftover delay can be compensated by the analog delay up to the analog delay resolution - adly_en = true; - adly_value = static_cast<uint8_t>(boost::math::round((leftover_delay-ADLY_MIN_NS)/ADLY_RES_NS)); - coerced_delay += ADLY_MIN_NS+(ADLY_RES_NS*adly_value); - } else if (leftover_delay >= (ADLY_MIN_NS - half_vco_period_ns) && leftover_delay < ADLY_MIN_NS) { - //The leftover delay if less than the minimum supported analog delay but if we move the digital - //delay back by half a VCO cycle then it will be in the range of the analog delay. So do that! - adly_en = true; - adly_value = static_cast<uint8_t>(boost::math::round((leftover_delay+half_vco_period_ns-ADLY_MIN_NS)/ADLY_RES_NS)); + // The leftover delay can be compensated by the analog delay up to the analog + // delay resolution + adly_en = true; + adly_value = static_cast<uint8_t>( + boost::math::round((leftover_delay - ADLY_MIN_NS) / ADLY_RES_NS)); + coerced_delay += ADLY_MIN_NS + (ADLY_RES_NS * adly_value); + } else if (leftover_delay >= (ADLY_MIN_NS - half_vco_period_ns) + && leftover_delay < ADLY_MIN_NS) { + // The leftover delay if less than the minimum supported analog delay but if + // we move the digital delay back by half a VCO cycle then it will be in the + // range of the analog delay. So do that! + adly_en = true; + adly_value = static_cast<uint8_t>(boost::math::round( + (leftover_delay + half_vco_period_ns - ADLY_MIN_NS) / ADLY_RES_NS)); half_shift_en = 1; - coerced_delay += ADLY_MIN_NS+(ADLY_RES_NS*adly_value)-half_vco_period_ns; + coerced_delay += + ADLY_MIN_NS + (ADLY_RES_NS * adly_value) - half_vco_period_ns; } else { - //Even after moving the digital delay back by half a cycle, we cannot make up the difference - //so give up on compensating for the difference from the digital delay tap. - //If control reaches here then the value of leftover_delay is possible very small and will still - //be close to what the client requested. + // Even after moving the digital delay back by half a cycle, we cannot make up + // the difference so give up on compensating for the difference from the + // digital delay tap. If control reaches here then the value of leftover_delay + // is possible very small and will still be close to what the client + // requested. } - UHD_LOG_DEBUG("X300", boost::format("x300_clock_ctrl::set_clock_delay: Which=%d, Requested=%f, Digital Taps=%d, Half Shift=%d, Analog Delay=%d (%s), Coerced Delay=%fns" - ) % which % delay_ns % ddly_value % (half_shift_en?"ON":"OFF") % ((int)adly_value) % (adly_en?"ON":"OFF") % coerced_delay) - - //Apply settings - switch (which) - { - case X300_CLOCK_WHICH_FPGA: - _lmk04816_regs.CLKout0_1_DDLY = ddly_value; - _lmk04816_regs.CLKout0_1_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout0_ADLY_SEL = lmk04816_regs_t::CLKOUT0_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout1_ADLY_SEL = lmk04816_regs_t::CLKOUT1_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout0_1_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout0_ADLY_SEL = lmk04816_regs_t::CLKOUT0_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout1_ADLY_SEL = lmk04816_regs_t::CLKOUT1_ADLY_SEL_D_PD; - } - write_regs(0); - write_regs(6); - _delays.fpga_dly_ns = coerced_delay; - break; - case X300_CLOCK_WHICH_DB0_RX: - case X300_CLOCK_WHICH_DB1_RX: - _lmk04816_regs.CLKout2_3_DDLY = ddly_value; - _lmk04816_regs.CLKout2_3_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout2_ADLY_SEL = lmk04816_regs_t::CLKOUT2_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout3_ADLY_SEL = lmk04816_regs_t::CLKOUT3_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout2_3_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout2_ADLY_SEL = lmk04816_regs_t::CLKOUT2_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout3_ADLY_SEL = lmk04816_regs_t::CLKOUT3_ADLY_SEL_D_PD; - } - write_regs(1); - write_regs(6); - _delays.db_rx_dly_ns = coerced_delay; - break; - case X300_CLOCK_WHICH_DB0_TX: - case X300_CLOCK_WHICH_DB1_TX: - _lmk04816_regs.CLKout4_5_DDLY = ddly_value; - _lmk04816_regs.CLKout4_5_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout4_ADLY_SEL = lmk04816_regs_t::CLKOUT4_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout5_ADLY_SEL = lmk04816_regs_t::CLKOUT5_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout4_5_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout4_ADLY_SEL = lmk04816_regs_t::CLKOUT4_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout5_ADLY_SEL = lmk04816_regs_t::CLKOUT5_ADLY_SEL_D_PD; - } - write_regs(2); - write_regs(7); - _delays.db_tx_dly_ns = coerced_delay; - break; - case X300_CLOCK_WHICH_DAC0: - case X300_CLOCK_WHICH_DAC1: - _lmk04816_regs.CLKout6_7_DDLY = ddly_value; - _lmk04816_regs.CLKout6_7_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout6_ADLY_SEL = lmk04816_regs_t::CLKOUT6_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout7_ADLY_SEL = lmk04816_regs_t::CLKOUT7_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout6_7_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout6_ADLY_SEL = lmk04816_regs_t::CLKOUT6_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout7_ADLY_SEL = lmk04816_regs_t::CLKOUT7_ADLY_SEL_D_PD; - } - write_regs(3); - write_regs(7); - _delays.dac_dly_ns = coerced_delay; - break; - case X300_CLOCK_WHICH_ADC0: - case X300_CLOCK_WHICH_ADC1: - _lmk04816_regs.CLKout8_9_DDLY = ddly_value; - _lmk04816_regs.CLKout8_9_HS = half_shift_en; - if (adly_en) { - _lmk04816_regs.CLKout8_ADLY_SEL = lmk04816_regs_t::CLKOUT8_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout9_ADLY_SEL = lmk04816_regs_t::CLKOUT9_ADLY_SEL_D_BOTH; - _lmk04816_regs.CLKout8_9_ADLY = adly_value; - } else { - _lmk04816_regs.CLKout8_ADLY_SEL = lmk04816_regs_t::CLKOUT8_ADLY_SEL_D_PD; - _lmk04816_regs.CLKout9_ADLY_SEL = lmk04816_regs_t::CLKOUT9_ADLY_SEL_D_PD; - } - write_regs(4); - write_regs(8); - _delays.adc_dly_ns = coerced_delay; - break; - default: - throw uhd::value_error("set_clock_delay: Requested source is invalid."); + UHD_LOG_DEBUG("X300", + boost::format( + "x300_clock_ctrl::set_clock_delay: Which=%d, Requested=%f, Digital " + "Taps=%d, Half Shift=%d, Analog Delay=%d (%s), Coerced Delay=%fns") + % which % delay_ns % ddly_value % (half_shift_en ? "ON" : "OFF") + % ((int)adly_value) % (adly_en ? "ON" : "OFF") % coerced_delay) + + // Apply settings + switch (which) { + case X300_CLOCK_WHICH_FPGA: + _lmk04816_regs.CLKout0_1_DDLY = ddly_value; + _lmk04816_regs.CLKout0_1_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout0_ADLY_SEL = + lmk04816_regs_t::CLKOUT0_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout1_ADLY_SEL = + lmk04816_regs_t::CLKOUT1_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout0_1_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout0_ADLY_SEL = + lmk04816_regs_t::CLKOUT0_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout1_ADLY_SEL = + lmk04816_regs_t::CLKOUT1_ADLY_SEL_D_PD; + } + write_regs(0); + write_regs(6); + _delays.fpga_dly_ns = coerced_delay; + break; + case X300_CLOCK_WHICH_DB0_RX: + case X300_CLOCK_WHICH_DB1_RX: + _lmk04816_regs.CLKout2_3_DDLY = ddly_value; + _lmk04816_regs.CLKout2_3_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout2_ADLY_SEL = + lmk04816_regs_t::CLKOUT2_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout3_ADLY_SEL = + lmk04816_regs_t::CLKOUT3_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout2_3_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout2_ADLY_SEL = + lmk04816_regs_t::CLKOUT2_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout3_ADLY_SEL = + lmk04816_regs_t::CLKOUT3_ADLY_SEL_D_PD; + } + write_regs(1); + write_regs(6); + _delays.db_rx_dly_ns = coerced_delay; + break; + case X300_CLOCK_WHICH_DB0_TX: + case X300_CLOCK_WHICH_DB1_TX: + _lmk04816_regs.CLKout4_5_DDLY = ddly_value; + _lmk04816_regs.CLKout4_5_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout4_ADLY_SEL = + lmk04816_regs_t::CLKOUT4_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout5_ADLY_SEL = + lmk04816_regs_t::CLKOUT5_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout4_5_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout4_ADLY_SEL = + lmk04816_regs_t::CLKOUT4_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout5_ADLY_SEL = + lmk04816_regs_t::CLKOUT5_ADLY_SEL_D_PD; + } + write_regs(2); + write_regs(7); + _delays.db_tx_dly_ns = coerced_delay; + break; + case X300_CLOCK_WHICH_DAC0: + case X300_CLOCK_WHICH_DAC1: + _lmk04816_regs.CLKout6_7_DDLY = ddly_value; + _lmk04816_regs.CLKout6_7_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout6_ADLY_SEL = + lmk04816_regs_t::CLKOUT6_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout7_ADLY_SEL = + lmk04816_regs_t::CLKOUT7_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout6_7_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout6_ADLY_SEL = + lmk04816_regs_t::CLKOUT6_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout7_ADLY_SEL = + lmk04816_regs_t::CLKOUT7_ADLY_SEL_D_PD; + } + write_regs(3); + write_regs(7); + _delays.dac_dly_ns = coerced_delay; + break; + case X300_CLOCK_WHICH_ADC0: + case X300_CLOCK_WHICH_ADC1: + _lmk04816_regs.CLKout8_9_DDLY = ddly_value; + _lmk04816_regs.CLKout8_9_HS = half_shift_en; + if (adly_en) { + _lmk04816_regs.CLKout8_ADLY_SEL = + lmk04816_regs_t::CLKOUT8_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout9_ADLY_SEL = + lmk04816_regs_t::CLKOUT9_ADLY_SEL_D_BOTH; + _lmk04816_regs.CLKout8_9_ADLY = adly_value; + } else { + _lmk04816_regs.CLKout8_ADLY_SEL = + lmk04816_regs_t::CLKOUT8_ADLY_SEL_D_PD; + _lmk04816_regs.CLKout9_ADLY_SEL = + lmk04816_regs_t::CLKOUT9_ADLY_SEL_D_PD; + } + write_regs(4); + write_regs(8); + _delays.adc_dly_ns = coerced_delay; + break; + default: + throw uhd::value_error("set_clock_delay: Requested source is invalid."); } - //Delays are applied only on a sync event - if (resync) sync_clocks(); + // Delays are applied only on a sync event + if (resync) + sync_clocks(); return coerced_delay; } - double get_clock_delay(const x300_clock_which_t which) { - switch (which) - { - case X300_CLOCK_WHICH_FPGA: - return _delays.fpga_dly_ns; - case X300_CLOCK_WHICH_DB0_RX: - case X300_CLOCK_WHICH_DB1_RX: - return _delays.db_rx_dly_ns; - case X300_CLOCK_WHICH_DB0_TX: - case X300_CLOCK_WHICH_DB1_TX: - return _delays.db_tx_dly_ns; - case X300_CLOCK_WHICH_DAC0: - case X300_CLOCK_WHICH_DAC1: - return _delays.dac_dly_ns; - case X300_CLOCK_WHICH_ADC0: - case X300_CLOCK_WHICH_ADC1: - return _delays.adc_dly_ns; - default: - throw uhd::value_error("get_clock_delay: Requested source is invalid."); + double get_clock_delay(const x300_clock_which_t which) + { + switch (which) { + case X300_CLOCK_WHICH_FPGA: + return _delays.fpga_dly_ns; + case X300_CLOCK_WHICH_DB0_RX: + case X300_CLOCK_WHICH_DB1_RX: + return _delays.db_rx_dly_ns; + case X300_CLOCK_WHICH_DB0_TX: + case X300_CLOCK_WHICH_DB1_TX: + return _delays.db_tx_dly_ns; + case X300_CLOCK_WHICH_DAC0: + case X300_CLOCK_WHICH_DAC1: + return _delays.dac_dly_ns; + case X300_CLOCK_WHICH_ADC0: + case X300_CLOCK_WHICH_ADC1: + return _delays.adc_dly_ns; + default: + throw uhd::value_error("get_clock_delay: Requested source is invalid."); } } private: - double autoset_pll2_config(const double output_freq) { // VCXO runs at 96MHz, assume PLL2 reference doubler is enabled const double ref = VCXO_FREQ * 2; const int lowest_vcodiv = static_cast<int>(std::ceil(MIN_VCO_FREQ / output_freq)); - const int highest_vcodiv = static_cast<int>(std::floor(MAX_VCO_FREQ / output_freq)); + const int highest_vcodiv = + static_cast<int>(std::floor(MAX_VCO_FREQ / output_freq)); // Find the PLL2 configuration with the lowest frequency error, favoring // higher phase comparison frequencies. - double best_error = 1e10; - double best_mcr = 0.0; + double best_error = 1e10; + double best_mcr = 0.0; double best_vco_freq = _vco_freq; - int best_N = _lmk04816_regs.PLL2_N_30; - int best_R = _lmk04816_regs.PLL2_R_28; + int best_N = _lmk04816_regs.PLL2_N_30; + int best_R = _lmk04816_regs.PLL2_R_28; for (int vcodiv = lowest_vcodiv; vcodiv <= highest_vcodiv; vcodiv++) { const double try_vco_freq = vcodiv * output_freq; // Start at R=2: with a min value of 2 for R, we don't have to worry // about exceeding the maximum phase comparison frequency for PLL2. - for (int r = 2; r <= 50; r++) - { + for (int r = 2; r <= 50; r++) { // Note: We could accomplish somewhat higher resolution if we change // the N predivider to odd values as well, and we may be able to get // better spur performance by balancing the predivider and the @@ -449,56 +515,60 @@ private: boost::math::round((r * try_vco_freq) / (VCXO_PLL2_N * ref))); const double actual_mcr = (ref * VCXO_PLL2_N * n) / (vcodiv * r); - const double error = std::abs(actual_mcr - output_freq); + const double error = std::abs(actual_mcr - output_freq); if (error < best_error) { - best_error = error; - best_mcr = actual_mcr; + best_error = error; + best_mcr = actual_mcr; best_vco_freq = try_vco_freq; - best_N = n; - best_R = r; + best_N = n; + best_R = r; } } } UHD_ASSERT_THROW(best_mcr > 0.0); - _vco_freq = best_vco_freq; + _vco_freq = best_vco_freq; _lmk04816_regs.PLL2_N_30 = best_N; _lmk04816_regs.PLL2_R_28 = best_R; _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; if (fp_compare_epsilon<double>(best_error) > 0.0) { UHD_LOGGER_WARNING("X300") - << boost::format("Attempted master clock rate %0.2f MHz, got %0.2f MHz") - % (output_freq / 1e6) % (best_mcr / 1e6); + << boost::format("Attempted master clock rate %0.2f MHz, got %0.2f MHz") + % (output_freq / 1e6) % (best_mcr / 1e6); } - UHD_LOGGER_TRACE("X300") << boost::format( - "Using automatic LMK04816 PLL2 config: N=%d, R=%d, VCO=%0.2f MHz, MCR=%0.2f MHz") - % _lmk04816_regs.PLL2_N_30 % _lmk04816_regs.PLL2_R_28 - % (_vco_freq / 1e6) % (best_mcr / 1e6); + UHD_LOGGER_TRACE("X300") + << boost::format("Using automatic LMK04816 PLL2 config: N=%d, R=%d, " + "VCO=%0.2f MHz, MCR=%0.2f MHz") + % _lmk04816_regs.PLL2_N_30 % _lmk04816_regs.PLL2_R_28 + % (_vco_freq / 1e6) % (best_mcr / 1e6); return best_mcr; } - void init() { + void init() + { /* The X3xx has two primary rates. The first is the * _system_ref_rate, which is sourced from the "clock_source"/"value" field - * of the property tree, and whose value can be 10e6, 11.52e6, 23.04e6, or 30.72e6. - * The _system_ref_rate is the input to the clocking system, and - * what comes out is a disciplined master clock running at the - * _master_clock_rate. As such, only certain combinations of - * system reference rates and master clock rates are supported. - * Additionally, a subset of these will operate in "zero delay" mode. */ - - enum opmode_t { INVALID, - m10M_200M_NOZDEL, // used for debug purposes only - m10M_200M_ZDEL, // Normal mode - m11_52M_184_32M_ZDEL, // LTE with 11.52 MHz ref - m23_04M_184_32M_ZDEL, // LTE with 23.04 MHz ref - m30_72M_184_32M_ZDEL, // LTE with external ref, aka CPRI Mode - m10M_184_32M_NOZDEL, // LTE with 10 MHz ref - m10M_120M_ZDEL, // NI USRP 120 MHz Clocking - m10M_AUTO_NOZDEL }; // automatic for arbitrary clock from 10MHz ref + * of the property tree, and whose value can be 10e6, 11.52e6, 23.04e6, + * or 30.72e6. The _system_ref_rate is the input to the clocking system, and what + * comes out is a disciplined master clock running at the _master_clock_rate. As + * such, only certain combinations of system reference rates and master clock + * rates are supported. Additionally, a subset of these will operate in "zero + * delay" mode. */ + + enum opmode_t { + INVALID, + m10M_200M_NOZDEL, // used for debug purposes only + m10M_200M_ZDEL, // Normal mode + m11_52M_184_32M_ZDEL, // LTE with 11.52 MHz ref + m23_04M_184_32M_ZDEL, // LTE with 23.04 MHz ref + m30_72M_184_32M_ZDEL, // LTE with external ref, aka CPRI Mode + m10M_184_32M_NOZDEL, // LTE with 10 MHz ref + m10M_120M_ZDEL, // NI USRP 120 MHz Clocking + m10M_AUTO_NOZDEL + }; // automatic for arbitrary clock from 10MHz ref /* The default clocking mode is 10MHz reference generating a 200 MHz master * clock, in zero-delay mode. */ @@ -515,61 +585,61 @@ private: } 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 if ( - fp_compare_epsilon<double>(_master_clock_rate) >= uhd::usrp::x300::MIN_TICK_RATE - && fp_compare_epsilon<double>(_master_clock_rate) <= uhd::usrp::x300::MAX_TICK_RATE - ) { + } else if (fp_compare_epsilon<double>(_master_clock_rate) + >= uhd::usrp::x300::MIN_TICK_RATE + && fp_compare_epsilon<double>(_master_clock_rate) + <= uhd::usrp::x300::MAX_TICK_RATE) { /* 10MHz reference, attempt to automatically configure PLL * for arbitrary master clock rate, Zero Delay */ - UHD_LOGGER_WARNING("X300") - << "Using automatic master clock PLL config. This is an experimental feature."; + UHD_LOGGER_WARNING("X300") << "Using automatic master clock PLL config. " + "This is an experimental feature."; clocking_mode = m10M_AUTO_NOZDEL; } 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) - )); + 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 (math::frequencies_are_equal(_system_ref_rate, 11.52e6)) { if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 11.52MHz reference, 184.32 MHz master clock out, Zero Delay */ clocking_mode = m11_52M_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) - )); + 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 if (math::frequencies_are_equal(_system_ref_rate, 23.04e6)) { if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 11.52MHz reference, 184.32 MHz master clock out, Zero Delay */ clocking_mode = m23_04M_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) - )); + 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 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) - )); + 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) - )); + 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))); } UHD_ASSERT_THROW(clocking_mode != INVALID); @@ -583,29 +653,29 @@ private: * architecture. Please refer to the datasheet for more information. */ switch (clocking_mode) { case m10M_200M_NOZDEL: - _vco_freq = 2400e6; + _vco_freq = 2400e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT; // PLL1 - 2 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 48; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 48; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 48 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 25; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 4; + _lmk04816_regs.PLL2_N_30 = 25; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 4; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; break; case m10M_200M_ZDEL: - _vco_freq = 2400e6; + _vco_freq = 2400e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 2 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 5; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 5; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_1600UA; // PLL2 - 96 MHz compare frequency @@ -613,26 +683,28 @@ private: _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_5; _lmk04816_regs.PLL2_R_28 = 2; - if(_hw_rev <= 4) - _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_1600UA; + if (_hw_rev <= 4) + _lmk04816_regs.PLL2_CP_GAIN_26 = + lmk04816_regs_t::PLL2_CP_GAIN_26_1600UA; else - _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_400UA; + _lmk04816_regs.PLL2_CP_GAIN_26 = + lmk04816_regs_t::PLL2_CP_GAIN_26_400UA; break; case m10M_184_32M_NOZDEL: - _vco_freq = 2580.48e6; + _vco_freq = 2580.48e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT; // PLL1 - 2 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 48; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 48; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 7.68 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 168; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 25; + _lmk04816_regs.PLL2_N_30 = 168; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 25; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; _lmk04816_regs.PLL2_R3_LF = lmk04816_regs_t::PLL2_R3_LF_4KILO_OHM; @@ -644,18 +716,18 @@ private: break; case m11_52M_184_32M_ZDEL: - _vco_freq = 2580.48e6; + _vco_freq = 2580.48e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 1.92 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 6; - _lmk04816_regs.PLL1_R_27 = 6; + _lmk04816_regs.PLL1_N_28 = 6; + _lmk04816_regs.PLL1_R_27 = 6; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 7.68 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 168; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 25; + _lmk04816_regs.PLL2_N_30 = 168; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 25; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; _lmk04816_regs.PLL2_R3_LF = lmk04816_regs_t::PLL2_R3_LF_1KILO_OHM; @@ -667,18 +739,18 @@ private: break; case m23_04M_184_32M_ZDEL: - _vco_freq = 2580.48e6; + _vco_freq = 2580.48e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 1.92 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 12; - _lmk04816_regs.PLL1_R_27 = 12; + _lmk04816_regs.PLL1_N_28 = 12; + _lmk04816_regs.PLL1_R_27 = 12; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 7.68 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 168; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 25; + _lmk04816_regs.PLL2_N_30 = 168; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 25; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; _lmk04816_regs.PLL2_R3_LF = lmk04816_regs_t::PLL2_R3_LF_1KILO_OHM; @@ -690,18 +762,18 @@ private: break; case m30_72M_184_32M_ZDEL: - _vco_freq = 2580.48e6; + _vco_freq = 2580.48e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 2.048 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 15; - _lmk04816_regs.PLL1_R_27 = 15; + _lmk04816_regs.PLL1_N_28 = 15; + _lmk04816_regs.PLL1_R_27 = 15; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 7.68 MHz compare frequency - _lmk04816_regs.PLL2_N_30 = 168; - _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; - _lmk04816_regs.PLL2_R_28 = 25; + _lmk04816_regs.PLL2_N_30 = 168; + _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_2A; + _lmk04816_regs.PLL2_R_28 = 25; _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_3200UA; _lmk04816_regs.PLL2_R3_LF = lmk04816_regs_t::PLL2_R3_LF_1KILO_OHM; @@ -713,12 +785,12 @@ private: break; case m10M_120M_ZDEL: - _vco_freq = 2400e6; + _vco_freq = 2400e6; _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT_ZER_DELAY; // PLL1 - 2 MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 5; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 5; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - 96 MHz compare frequency @@ -726,10 +798,12 @@ private: _lmk04816_regs.PLL2_P_30 = lmk04816_regs_t::PLL2_P_30_DIV_5; _lmk04816_regs.PLL2_R_28 = 2; - if(_hw_rev <= 4) - _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_1600UA; + if (_hw_rev <= 4) + _lmk04816_regs.PLL2_CP_GAIN_26 = + lmk04816_regs_t::PLL2_CP_GAIN_26_1600UA; else - _lmk04816_regs.PLL2_CP_GAIN_26 = lmk04816_regs_t::PLL2_CP_GAIN_26_400UA; + _lmk04816_regs.PLL2_CP_GAIN_26 = + lmk04816_regs_t::PLL2_CP_GAIN_26_400UA; break; @@ -737,8 +811,8 @@ private: _lmk04816_regs.MODE = lmk04816_regs_t::MODE_DUAL_INT; // PLL1 - 2MHz compare frequency - _lmk04816_regs.PLL1_N_28 = 48; - _lmk04816_regs.PLL1_R_27 = 5; + _lmk04816_regs.PLL1_N_28 = 48; + _lmk04816_regs.PLL1_R_27 = 5; _lmk04816_regs.PLL1_CP_GAIN_27 = lmk04816_regs_t::PLL1_CP_GAIN_27_100UA; // PLL2 - this call will set _vco_freq and PLL2 P/N/R registers. @@ -751,11 +825,11 @@ private: break; }; - uint16_t master_clock_div = static_cast<uint16_t>( - std::ceil(_vco_freq / _master_clock_rate)); + uint16_t master_clock_div = + static_cast<uint16_t>(std::ceil(_vco_freq / _master_clock_rate)); - uint16_t dboard_div = static_cast<uint16_t>( - std::ceil(_vco_freq / _dboard_clock_rate)); + uint16_t dboard_div = + static_cast<uint16_t>(std::ceil(_vco_freq / _dboard_clock_rate)); /* Reset the LMK clock controller. */ _lmk04816_regs.RESET = lmk04816_regs_t::RESET_RESET; @@ -770,13 +844,13 @@ private: this->write_regs(0); // Register 1 - _lmk04816_regs.CLKout2_3_PD = lmk04816_regs_t::CLKOUT2_3_PD_POWER_UP; + _lmk04816_regs.CLKout2_3_PD = lmk04816_regs_t::CLKOUT2_3_PD_POWER_UP; _lmk04816_regs.CLKout2_3_DIV = dboard_div; // Register 2 - _lmk04816_regs.CLKout4_5_PD = lmk04816_regs_t::CLKOUT4_5_PD_POWER_UP; + _lmk04816_regs.CLKout4_5_PD = lmk04816_regs_t::CLKOUT4_5_PD_POWER_UP; _lmk04816_regs.CLKout4_5_DIV = dboard_div; // Register 3 - _lmk04816_regs.CLKout6_7_DIV = master_clock_div; + _lmk04816_regs.CLKout6_7_DIV = master_clock_div; _lmk04816_regs.CLKout6_7_OSCin_Sel = lmk04816_regs_t::CLKOUT6_7_OSCIN_SEL_VCO; // Register 4 _lmk04816_regs.CLKout8_9_DIV = master_clock_div; @@ -786,39 +860,55 @@ private: static_cast<uint16_t>(std::ceil(_vco_freq / _system_ref_rate)); // Register 6 - _lmk04816_regs.CLKout0_TYPE = lmk04816_regs_t::CLKOUT0_TYPE_LVDS; //FPGA - _lmk04816_regs.CLKout1_TYPE = lmk04816_regs_t::CLKOUT1_TYPE_P_DOWN; //CPRI feedback clock, use LVDS - _lmk04816_regs.CLKout2_TYPE = lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP; //DB_0_RX - _lmk04816_regs.CLKout3_TYPE = lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP; //DB_1_RX + _lmk04816_regs.CLKout0_TYPE = lmk04816_regs_t::CLKOUT0_TYPE_LVDS; // FPGA + _lmk04816_regs.CLKout1_TYPE = + lmk04816_regs_t::CLKOUT1_TYPE_P_DOWN; // CPRI feedback clock, use LVDS + _lmk04816_regs.CLKout2_TYPE = + lmk04816_regs_t::CLKOUT2_TYPE_LVPECL_700MVPP; // DB_0_RX + _lmk04816_regs.CLKout3_TYPE = + lmk04816_regs_t::CLKOUT3_TYPE_LVPECL_700MVPP; // DB_1_RX // Register 7 - _lmk04816_regs.CLKout4_TYPE = lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP; //DB_1_TX - _lmk04816_regs.CLKout5_TYPE = lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP; //DB_0_TX - _lmk04816_regs.CLKout6_TYPE = lmk04816_regs_t::CLKOUT6_TYPE_LVPECL_700MVPP; //DB0_DAC - _lmk04816_regs.CLKout7_TYPE = lmk04816_regs_t::CLKOUT7_TYPE_LVPECL_700MVPP; //DB1_DAC - _lmk04816_regs.CLKout8_TYPE = lmk04816_regs_t::CLKOUT8_TYPE_LVPECL_700MVPP; //DB0_ADC + _lmk04816_regs.CLKout4_TYPE = + lmk04816_regs_t::CLKOUT4_TYPE_LVPECL_700MVPP; // DB_1_TX + _lmk04816_regs.CLKout5_TYPE = + lmk04816_regs_t::CLKOUT5_TYPE_LVPECL_700MVPP; // DB_0_TX + _lmk04816_regs.CLKout6_TYPE = + lmk04816_regs_t::CLKOUT6_TYPE_LVPECL_700MVPP; // DB0_DAC + _lmk04816_regs.CLKout7_TYPE = + lmk04816_regs_t::CLKOUT7_TYPE_LVPECL_700MVPP; // DB1_DAC + _lmk04816_regs.CLKout8_TYPE = + lmk04816_regs_t::CLKOUT8_TYPE_LVPECL_700MVPP; // DB0_ADC // Register 8 - _lmk04816_regs.CLKout9_TYPE = lmk04816_regs_t::CLKOUT9_TYPE_LVPECL_700MVPP; //DB1_ADC - _lmk04816_regs.CLKout10_TYPE = lmk04816_regs_t::CLKOUT10_TYPE_LVDS; //REF_CLKOUT - _lmk04816_regs.CLKout11_TYPE = lmk04816_regs_t::CLKOUT11_TYPE_P_DOWN; //Debug header, use LVPECL + _lmk04816_regs.CLKout9_TYPE = + lmk04816_regs_t::CLKOUT9_TYPE_LVPECL_700MVPP; // DB1_ADC + _lmk04816_regs.CLKout10_TYPE = lmk04816_regs_t::CLKOUT10_TYPE_LVDS; // REF_CLKOUT + _lmk04816_regs.CLKout11_TYPE = + lmk04816_regs_t::CLKOUT11_TYPE_P_DOWN; // Debug header, use LVPECL // Register 10 - _lmk04816_regs.EN_OSCout0 = lmk04816_regs_t::EN_OSCOUT0_DISABLED; //Debug header - _lmk04816_regs.FEEDBACK_MUX = 5; //use output 10 (REF OUT) for feedback + _lmk04816_regs.EN_OSCout0 = lmk04816_regs_t::EN_OSCOUT0_DISABLED; // Debug header + _lmk04816_regs.FEEDBACK_MUX = 5; // use output 10 (REF OUT) for feedback _lmk04816_regs.EN_FEEDBACK_MUX = lmk04816_regs_t::EN_FEEDBACK_MUX_ENABLED; // Register 11 // MODE set in individual cases above _lmk04816_regs.SYNC_QUAL = lmk04816_regs_t::SYNC_QUAL_FB_MUX; - _lmk04816_regs.EN_SYNC = lmk04816_regs_t::EN_SYNC_ENABLE; - _lmk04816_regs.NO_SYNC_CLKout0_1 = lmk04816_regs_t::NO_SYNC_CLKOUT0_1_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout2_3 = lmk04816_regs_t::NO_SYNC_CLKOUT2_3_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout4_5 = lmk04816_regs_t::NO_SYNC_CLKOUT4_5_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout6_7 = lmk04816_regs_t::NO_SYNC_CLKOUT6_7_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout8_9 = lmk04816_regs_t::NO_SYNC_CLKOUT8_9_CLOCK_XY_SYNC; - _lmk04816_regs.NO_SYNC_CLKout10_11 = lmk04816_regs_t::NO_SYNC_CLKOUT10_11_CLOCK_XY_SYNC; + _lmk04816_regs.EN_SYNC = lmk04816_regs_t::EN_SYNC_ENABLE; + _lmk04816_regs.NO_SYNC_CLKout0_1 = + lmk04816_regs_t::NO_SYNC_CLKOUT0_1_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout2_3 = + lmk04816_regs_t::NO_SYNC_CLKOUT2_3_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout4_5 = + lmk04816_regs_t::NO_SYNC_CLKOUT4_5_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout6_7 = + lmk04816_regs_t::NO_SYNC_CLKOUT6_7_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout8_9 = + lmk04816_regs_t::NO_SYNC_CLKOUT8_9_CLOCK_XY_SYNC; + _lmk04816_regs.NO_SYNC_CLKout10_11 = + lmk04816_regs_t::NO_SYNC_CLKOUT10_11_CLOCK_XY_SYNC; _lmk04816_regs.SYNC_TYPE = lmk04816_regs_t::SYNC_TYPE_INPUT; // Register 12 @@ -826,14 +916,18 @@ private: /* Input Clock Configurations */ // Register 13 - _lmk04816_regs.EN_CLKin0 = lmk04816_regs_t::EN_CLKIN0_NO_VALID_USE; // This is not connected - _lmk04816_regs.EN_CLKin2 = lmk04816_regs_t::EN_CLKIN2_NO_VALID_USE; // Used only for CPRI + _lmk04816_regs.EN_CLKin0 = + lmk04816_regs_t::EN_CLKIN0_NO_VALID_USE; // This is not connected + _lmk04816_regs.EN_CLKin2 = + lmk04816_regs_t::EN_CLKIN2_NO_VALID_USE; // Used only for CPRI _lmk04816_regs.Status_CLKin1_MUX = lmk04816_regs_t::STATUS_CLKIN1_MUX_UWIRE_RB; _lmk04816_regs.CLKin_Select_MODE = lmk04816_regs_t::CLKIN_SELECT_MODE_CLKIN1_MAN; - _lmk04816_regs.HOLDOVER_MUX = lmk04816_regs_t::HOLDOVER_MUX_PLL1_R; + _lmk04816_regs.HOLDOVER_MUX = lmk04816_regs_t::HOLDOVER_MUX_PLL1_R; // Register 14 - _lmk04816_regs.Status_CLKin1_TYPE = lmk04816_regs_t::STATUS_CLKIN1_TYPE_OUT_PUSH_PULL; - _lmk04816_regs.Status_CLKin0_TYPE = lmk04816_regs_t::STATUS_CLKIN0_TYPE_OUT_PUSH_PULL; + _lmk04816_regs.Status_CLKin1_TYPE = + lmk04816_regs_t::STATUS_CLKIN1_TYPE_OUT_PUSH_PULL; + _lmk04816_regs.Status_CLKin0_TYPE = + lmk04816_regs_t::STATUS_CLKIN0_TYPE_OUT_PUSH_PULL; // Register 26 // PLL2_CP_GAIN_26 set above in individual cases @@ -848,7 +942,8 @@ private: // PLL1_N_28 and PLL2_R_28 are set in the individual cases above // Register 29 - _lmk04816_regs.PLL2_N_CAL_29 = _lmk04816_regs.PLL2_N_30; // N_CAL should always match N + _lmk04816_regs.PLL2_N_CAL_29 = + _lmk04816_regs.PLL2_N_30; // N_CAL should always match N _lmk04816_regs.OSCin_FREQ_29 = lmk04816_regs_t::OSCIN_FREQ_29_63_TO_127MHZ; // Register 30 @@ -861,12 +956,18 @@ private: _delays = X300_REV0_6_CLK_DELAYS; } - //Apply delay values - set_clock_delay(X300_CLOCK_WHICH_FPGA, _delays.fpga_dly_ns, false); - set_clock_delay(X300_CLOCK_WHICH_DB0_RX, _delays.db_rx_dly_ns, false); //Sets both Ch0 and Ch1 - set_clock_delay(X300_CLOCK_WHICH_DB0_TX, _delays.db_tx_dly_ns, false); //Sets both Ch0 and Ch1 - set_clock_delay(X300_CLOCK_WHICH_ADC0, _delays.adc_dly_ns, false); //Sets both Ch0 and Ch1 - set_clock_delay(X300_CLOCK_WHICH_DAC0, _delays.dac_dly_ns, false); //Sets both Ch0 and Ch1 + // Apply delay values + set_clock_delay(X300_CLOCK_WHICH_FPGA, _delays.fpga_dly_ns, false); + set_clock_delay(X300_CLOCK_WHICH_DB0_RX, + _delays.db_rx_dly_ns, + false); // Sets both Ch0 and Ch1 + set_clock_delay(X300_CLOCK_WHICH_DB0_TX, + _delays.db_tx_dly_ns, + false); // Sets both Ch0 and Ch1 + set_clock_delay( + X300_CLOCK_WHICH_ADC0, _delays.adc_dly_ns, false); // Sets both Ch0 and Ch1 + set_clock_delay( + X300_CLOCK_WHICH_DAC0, _delays.dac_dly_ns, false); // Sets both Ch0 and Ch1 /* Write the configuration values into the LMK */ for (uint8_t i = 1; i <= 16; ++i) { @@ -879,24 +980,25 @@ private: this->sync_clocks(); } - const spi_iface::sptr _spiface; - const int _slaveno; - const size_t _hw_rev; + const spi_iface::sptr _spiface; + const int _slaveno; + const size_t _hw_rev; // This is technically constant, but it can be coerced during initialization - double _master_clock_rate; - const double _dboard_clock_rate; - const double _system_ref_rate; - lmk04816_regs_t _lmk04816_regs; - double _vco_freq; - x300_clk_delays _delays; + double _master_clock_rate; + const double _dboard_clock_rate; + const double _system_ref_rate; + lmk04816_regs_t _lmk04816_regs; + double _vco_freq; + x300_clk_delays _delays; }; x300_clock_ctrl::sptr x300_clock_ctrl::make(uhd::spi_iface::sptr spiface, - const size_t slaveno, - const size_t hw_rev, - const double master_clock_rate, - const double dboard_clock_rate, - const double system_ref_rate) { - return sptr(new x300_clock_ctrl_impl(spiface, slaveno, hw_rev, - master_clock_rate, dboard_clock_rate, system_ref_rate)); + const size_t slaveno, + const size_t hw_rev, + const double master_clock_rate, + const double dboard_clock_rate, + const double system_ref_rate) +{ + return sptr(new x300_clock_ctrl_impl( + spiface, slaveno, hw_rev, master_clock_rate, dboard_clock_rate, system_ref_rate)); } diff --git a/host/lib/usrp/x300/x300_clock_ctrl.hpp b/host/lib/usrp/x300/x300_clock_ctrl.hpp index 3ab8b45f9..609464ca0 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.hpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.hpp @@ -13,8 +13,7 @@ #include <boost/utility.hpp> -enum x300_clock_which_t -{ +enum x300_clock_which_t { X300_CLOCK_WHICH_ADC0, X300_CLOCK_WHICH_ADC1, X300_CLOCK_WHICH_DAC0, @@ -29,17 +28,16 @@ enum x300_clock_which_t class x300_clock_ctrl : boost::noncopyable { public: - typedef boost::shared_ptr<x300_clock_ctrl> sptr; virtual ~x300_clock_ctrl(void) = 0; static sptr make(uhd::spi_iface::sptr spiface, - const size_t slaveno, - const size_t hw_rev, - const double master_clock_rate, - const double dboard_clock_rate, - const double system_ref_rate); + const size_t slaveno, + const size_t hw_rev, + const double master_clock_rate, + const double dboard_clock_rate, + const double system_ref_rate); /*! Get the master clock rate of the device. * \return the clock frequency in Hz @@ -78,7 +76,8 @@ public: * \param enable true=enable, false=disable * \return a list of clock rates in Hz */ - virtual void enable_dboard_clock(const x300_clock_which_t which, const bool enable) = 0; + virtual void enable_dboard_clock( + const x300_clock_which_t which, const bool enable) = 0; /*! Turn the reference output on/off * \param true = on, false = off @@ -92,7 +91,9 @@ public: * \return the actual delay value set * \throw exception when which invalid or delay_ns out of range */ - virtual double set_clock_delay(const x300_clock_which_t which, const double delay_ns, const bool resync = true) = 0; + virtual double set_clock_delay(const x300_clock_which_t which, + const double delay_ns, + const bool resync = true) = 0; /*! Get the clock delay for the given clock divider. * \param which which clock diff --git a/host/lib/usrp/x300/x300_dac_ctrl.cpp b/host/lib/usrp/x300/x300_dac_ctrl.cpp index a9df96002..f951a44a2 100644 --- a/host/lib/usrp/x300/x300_dac_ctrl.cpp +++ b/host/lib/usrp/x300/x300_dac_ctrl.cpp @@ -7,11 +7,11 @@ #include "x300_dac_ctrl.hpp" #include "x300_regs.hpp" -#include <uhdlib/utils/system_time.hpp> +#include <uhd/exception.hpp> #include <uhd/types/time_spec.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/safe_call.hpp> -#include <uhd/exception.hpp> +#include <uhdlib/utils/system_time.hpp> #include <boost/format.hpp> #include <chrono> #include <thread> @@ -22,10 +22,12 @@ using namespace uhd; #define write_ad9146_reg(addr, data) \ _iface->write_spi(_slaveno, spi_config_t::EDGE_RISE, ((addr) << 8) | (data), 16) -#define read_ad9146_reg(addr) \ - (_iface->read_spi(_slaveno, spi_config_t::EDGE_RISE, ((addr) << 8) | (1 << 15), 16) & 0xff) +#define read_ad9146_reg(addr) \ + (_iface->read_spi(_slaveno, spi_config_t::EDGE_RISE, ((addr) << 8) | (1 << 15), 16) \ + & 0xff) -x300_dac_ctrl::~x300_dac_ctrl(void){ +x300_dac_ctrl::~x300_dac_ctrl(void) +{ /* NOP */ } @@ -35,38 +37,41 @@ x300_dac_ctrl::~x300_dac_ctrl(void){ class x300_dac_ctrl_impl : public x300_dac_ctrl { public: - x300_dac_ctrl_impl(uhd::spi_iface::sptr iface, const size_t slaveno, const double refclk): - _iface(iface), _slaveno(static_cast<int>(slaveno)), _refclk(refclk) + x300_dac_ctrl_impl( + uhd::spi_iface::sptr iface, const size_t slaveno, const double refclk) + : _iface(iface), _slaveno(static_cast<int>(slaveno)), _refclk(refclk) { - //Power up all DAC subsystems - write_ad9146_reg(0x01, 0x10); //Up: I DAC, Q DAC, Receiver, Voltage Ref, Clocks - write_ad9146_reg(0x02, 0x00); //No extended delays. Up: Voltage Ref, PLL, DAC, FIFO, Filters + // Power up all DAC subsystems + write_ad9146_reg(0x01, 0x10); // Up: I DAC, Q DAC, Receiver, Voltage Ref, Clocks + write_ad9146_reg( + 0x02, 0x00); // No extended delays. Up: Voltage Ref, PLL, DAC, FIFO, Filters reset(); } ~x300_dac_ctrl_impl(void) { - UHD_SAFE_CALL - ( - //Power down all DAC subsystems - write_ad9146_reg(0x01, 0xEF); //Down: I DAC, Q DAC, Receiver, Voltage Ref, Clocks - write_ad9146_reg(0x02, 0x1F); //No extended delays. Down: Voltage Ref, PLL, DAC, FIFO, Filters + UHD_SAFE_CALL( + // Power down all DAC subsystems + write_ad9146_reg( + 0x01, 0xEF); // Down: I DAC, Q DAC, Receiver, Voltage Ref, Clocks + write_ad9146_reg(0x02, + 0x1F); // No extended delays. Down: Voltage Ref, PLL, DAC, FIFO, Filters ) } void reset() { - //ADI recommendations: + // ADI recommendations: //- soft reset the chip before configuration //- put the chip in sleep mode during configuration and wake it up when done //- configure synchronization settings when sleeping _soft_reset(); _sleep_mode(true); _init(); - //We run backend sync regardless of whether we need to sync multiple DACs - //because we use the internal DAC FIFO to meet system synchronous timing - //and we need to guarantee that the FIFO is not empty. + // We run backend sync regardless of whether we need to sync multiple DACs + // because we use the internal DAC FIFO to meet system synchronous timing + // and we need to guarantee that the FIFO is not empty. _backend_sync(); _sleep_mode(false); } @@ -78,20 +83,20 @@ public: _check_pll(); _check_dac_sync(); return; - } catch (...) {} + } catch (...) { + } std::string err_str; // Try 3 times to sync before giving up - for (size_t retries = 0; retries < 3; retries++) - { + for (size_t retries = 0; retries < 3; retries++) { try { _sleep_mode(true); _init(); _backend_sync(); _sleep_mode(false); return; - } catch (const uhd::runtime_error &e) { + } catch (const uhd::runtime_error& e) { err_str = e.what(); } } @@ -114,23 +119,23 @@ public: // void _init() { - write_ad9146_reg(0x1e, 0x01); //Datasheet: "Set 1 for proper operation" - write_ad9146_reg(0x06, 0xFF); //Clear all event flags + write_ad9146_reg(0x1e, 0x01); // Datasheet: "Set 1 for proper operation" + write_ad9146_reg(0x06, 0xFF); // Clear all event flags // Calculate N0 to be VCO friendly. // Aim for VCO between 1 and 2GHz, assert otherwise. const int N1 = 4; int N0_val, N0; - for (N0_val = 0; N0_val < 3; N0_val++) - { - N0 = (1 << N0_val); //1, 2, 4 - if ((_refclk * N0 * N1) >= 1e9) break; + for (N0_val = 0; N0_val < 3; N0_val++) { + N0 = (1 << N0_val); // 1, 2, 4 + if ((_refclk * N0 * N1) >= 1e9) + break; } UHD_ASSERT_THROW((_refclk * N0 * N1) >= 1e9); UHD_ASSERT_THROW((_refclk * N0 * N1) <= 2e9); // Start PLL - write_ad9146_reg(0x06, 0xC0); //Clear PLL event flags + write_ad9146_reg(0x06, 0xC0); // Clear PLL event flags write_ad9146_reg(0x0C, 0xD1); // Narrow PLL loop filter, Midrange charge pump. write_ad9146_reg(0x0D, 0xD1 | (N0_val << 2)); // N1=4, N2=16, N0 as calculated write_ad9146_reg(0x0A, 0xCF); // Auto init VCO band training as per datasheet @@ -149,7 +154,7 @@ public: // - First transaction goes into low bits // - Second transaction goes into high bits // therefore, we want Q to go first (bit 6 == 1) - write_ad9146_reg(0x03, (1 << 6)); //2s comp, i first, byte mode + write_ad9146_reg(0x03, (1 << 6)); // 2s comp, i first, byte mode // Configure interpolation filters write_ad9146_reg(0x1C, 0x00); // Configure HB1 @@ -165,31 +170,33 @@ public: // void _backend_sync(void) { - write_ad9146_reg(0x10, 0x40); // Disable SYNC mode to reset state machines. + write_ad9146_reg(0x10, 0x40); // Disable SYNC mode to reset state machines. - //SYNC Settings: + // SYNC Settings: //- SYNC = Enabled //- Data Rate Mode: Synchronize at the rate at which data is consumed and not at // the granularity of the FIFO //- Falling edge sync: For the X300, DACCLK is generated using RefClk. Within the // DAC, the RefClk is sampled by DACCLK to sync interpolation // stages across multiple DACs. To ensure that we capture the - // RefClk when it is not transitioning, we sample on the falling - // edge of DACCLK + // RefClk when it is not transitioning, we sample on the + // falling edge of DACCLK //- Averaging = MAX - write_ad9146_reg(0x10, 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. + write_ad9146_reg( + 0x10, 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. - //Wait for backend SYNC state machine to lock before proceeding. This guarantees that the - //inputs and output of the FIFO have synchronized clocks + // Wait for backend SYNC state machine to lock before proceeding. This guarantees + // that the inputs and output of the FIFO have synchronized clocks _check_dac_sync(); - //FIFO write pointer offset - //One of ADI's requirements to use data-rate synchronization in PLL mode is to meet - //setup and hold times for RefClk -> DCI clock which we *do not* currently meet in - //the FPGA. The DCI clock reaches a full RefClk cycle later which results in the - //FIFO popping before the first push. This results in a steady-state FIFO fullness - //of pointer - 1. To reach the optimal FIFO fullness of 4 we set the pointer to 5. - //FIXME: At some point we should meet timing on this interface + // FIFO write pointer offset + // One of ADI's requirements to use data-rate synchronization in PLL mode is to + // meet setup and hold times for RefClk -> DCI clock which we *do not* currently + // meet in the FPGA. The DCI clock reaches a full RefClk cycle later which results + // in the FIFO popping before the first push. This results in a steady-state FIFO + // fullness of pointer - 1. To reach the optimal FIFO fullness of 4 we set the + // pointer to 5. + // FIXME: At some point we should meet timing on this interface write_ad9146_reg(0x17, 0x05); // We are requesting a soft FIFO align just to put the FIFO @@ -204,22 +211,23 @@ public: // void _check_pll() { - //Clear PLL event flags + // Clear PLL event flags write_ad9146_reg(0x06, 0xC0); // Verify PLL is Locked. 1 sec timeout. // NOTE: Data sheet inconsistent about which pins give PLL lock status. FIXME! const time_spec_t exit_time = uhd::get_system_time() + time_spec_t(1.0); - while (true) - { + while (true) { const size_t reg_e = read_ad9146_reg(0x0E); // PLL Status (Expect bit 7 = 1) - const size_t reg_6 = read_ad9146_reg(0x06); // Event Flags (Expect bit 7 = 0 and bit 6 = 1) + const size_t reg_6 = + read_ad9146_reg(0x06); // Event Flags (Expect bit 7 = 0 and bit 6 = 1) if ((((reg_e >> 7) & 0x1) == 0x1) && (((reg_6 >> 6) & 0x3) == 0x1)) break; if (exit_time < uhd::get_system_time()) - throw uhd::runtime_error("x300_dac_ctrl: timeout waiting for DAC PLL to lock"); - if (reg_6 & (1 << 7)) // Lock lost? - write_ad9146_reg(0x06, 0xC0); // Clear PLL event flags + throw uhd::runtime_error( + "x300_dac_ctrl: timeout waiting for DAC PLL to lock"); + if (reg_6 & (1 << 7)) // Lock lost? + write_ad9146_reg(0x06, 0xC0); // Clear PLL event flags std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } @@ -234,21 +242,25 @@ public: write_ad9146_reg(0x12, 0x00); const time_spec_t exit_time = uhd::get_system_time() + time_spec_t(1.0); - while (true) - { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // wait for sync to complete - const size_t reg_12 = read_ad9146_reg(0x12); // Sync Status (Expect bit 7 = 0, bit 6 = 1) - const size_t reg_6 = read_ad9146_reg(0x06); // Event Flags (Expect bit 5 = 0 and bit 4 = 1) + while (true) { + std::this_thread::sleep_for( + std::chrono::milliseconds(1)); // wait for sync to complete + const size_t reg_12 = + read_ad9146_reg(0x12); // Sync Status (Expect bit 7 = 0, bit 6 = 1) + const size_t reg_6 = + read_ad9146_reg(0x06); // Event Flags (Expect bit 5 = 0 and bit 4 = 1) if ((((reg_12 >> 6) & 0x3) == 0x1) && (((reg_6 >> 4) & 0x3) == 0x1)) break; if (exit_time < uhd::get_system_time()) - throw uhd::runtime_error("x300_dac_ctrl: timeout waiting for backend synchronization"); + throw uhd::runtime_error( + "x300_dac_ctrl: timeout waiting for backend synchronization"); if (reg_6 & (1 << 5)) - write_ad9146_reg(0x06, 0x30); // Clear Sync event flags + write_ad9146_reg(0x06, 0x30); // Clear Sync event flags #ifdef X300_DAC_RETRY_BACKEND_SYNC - if (reg_12 & (1 << 7)) { // Sync acquired and lost? - write_ad9146_reg(0x10, 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. - write_ad9146_reg(0x12, 0x00); // Clear Sync event flags + if (reg_12 & (1 << 7)) { // Sync acquired and lost? + write_ad9146_reg(0x10, + 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. + write_ad9146_reg(0x12, 0x00); // Clear Sync event flags } #endif } @@ -262,7 +274,11 @@ public: // Register 0x19 has a thermometer indicator of the FIFO depth const size_t reg_19 = read_ad9146_reg(0x19); if ((reg_19 & 0xFF) != 0xF) { - std::string msg((boost::format("x300_dac_ctrl: front-end sync failed. unexpected FIFO depth [0x%x]") % (reg_19 & 0xFF)).str()); + std::string msg( + (boost::format( + "x300_dac_ctrl: front-end sync failed. unexpected FIFO depth [0x%x]") + % (reg_19 & 0xFF)) + .str()); if (failure_is_fatal) { throw uhd::runtime_error(msg); } else { @@ -273,10 +289,10 @@ public: void _sleep_mode(bool sleep) { - uint8_t sleep_val = sleep ? (1<<7) : 0x00; - //Set sleep word and default fullscale value - write_ad9146_reg(0x41, sleep_val | 0x01); //I DAC - write_ad9146_reg(0x45, sleep_val | 0x01); //Q DAC + uint8_t sleep_val = sleep ? (1 << 7) : 0x00; + // Set sleep word and default fullscale value + write_ad9146_reg(0x41, sleep_val | 0x01); // I DAC + write_ad9146_reg(0x45, sleep_val | 0x01); // Q DAC } void _soft_reset() @@ -294,7 +310,8 @@ private: /*********************************************************************** * Public make function for the DAC control **********************************************************************/ -x300_dac_ctrl::sptr x300_dac_ctrl::make(uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate) +x300_dac_ctrl::sptr x300_dac_ctrl::make( + uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate) { return sptr(new x300_dac_ctrl_impl(iface, slaveno, clock_rate)); } diff --git a/host/lib/usrp/x300/x300_dac_ctrl.hpp b/host/lib/usrp/x300/x300_dac_ctrl.hpp index 0ef99011b..74dba0cb4 100644 --- a/host/lib/usrp/x300/x300_dac_ctrl.hpp +++ b/host/lib/usrp/x300/x300_dac_ctrl.hpp @@ -25,7 +25,8 @@ public: * \param spiface the interface to spi * \return a new codec control object */ - static sptr make(uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate); + static sptr make( + uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate); // ! Reset the DAC virtual void reset(void) = 0; diff --git a/host/lib/usrp/x300/x300_dboard_iface.cpp b/host/lib/usrp/x300/x300_dboard_iface.cpp index 6986ee8ab..36e430985 100644 --- a/host/lib/usrp/x300/x300_dboard_iface.cpp +++ b/host/lib/usrp/x300/x300_dboard_iface.cpp @@ -18,14 +18,13 @@ using namespace boost::assign; /*********************************************************************** * Structors **********************************************************************/ -x300_dboard_iface::x300_dboard_iface(const x300_dboard_iface_config_t &config): - _config(config) +x300_dboard_iface::x300_dboard_iface(const x300_dboard_iface_config_t& config) + : _config(config) { - //reset the aux dacs + // reset the aux dacs _dac_regs[UNIT_RX] = ad5623_regs_t(); _dac_regs[UNIT_TX] = ad5623_regs_t(); - for(unit_t unit: _dac_regs.keys()) - { + for (unit_t unit : _dac_regs.keys()) { _dac_regs[unit].data = 1; _dac_regs[unit].addr = ad5623_regs_t::ADDR_ALL; _dac_regs[unit].cmd = ad5623_regs_t::CMD_RESET; @@ -41,11 +40,8 @@ x300_dboard_iface::x300_dboard_iface(const x300_dboard_iface_config_t &config): x300_dboard_iface::~x300_dboard_iface(void) { - UHD_SAFE_CALL - ( - this->set_clock_enabled(UNIT_RX, false); - this->set_clock_enabled(UNIT_TX, false); - ) + UHD_SAFE_CALL(this->set_clock_enabled(UNIT_RX, false); + this->set_clock_enabled(UNIT_TX, false);) } /*********************************************************************** @@ -53,14 +49,14 @@ x300_dboard_iface::~x300_dboard_iface(void) **********************************************************************/ void x300_dboard_iface::set_clock_rate(unit_t unit, double rate) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); // Just return if the requested rate is already set if (std::abs(_clock_rates[unit] - rate) < std::numeric_limits<double>::epsilon()) return; - switch(unit) - { + switch (unit) { case UNIT_RX: _config.clock->set_dboard_rate(_config.which_rx_clk, rate); break; @@ -70,20 +66,21 @@ void x300_dboard_iface::set_clock_rate(unit_t unit, double rate) default: UHD_THROW_INVALID_CODE_PATH(); } - _clock_rates[unit] = rate; //set to shadow + _clock_rates[unit] = rate; // set to shadow } double x300_dboard_iface::get_clock_rate(unit_t unit) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - return _clock_rates[unit]; //get from shadow + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + return _clock_rates[unit]; // get from shadow } std::vector<double> x300_dboard_iface::get_clock_rates(unit_t unit) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - switch(unit) - { + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + switch (unit) { case UNIT_RX: return _config.clock->get_dboard_rates(_config.which_rx_clk); case UNIT_TX: @@ -95,9 +92,9 @@ std::vector<double> x300_dboard_iface::get_clock_rates(unit_t unit) void x300_dboard_iface::set_clock_enabled(unit_t unit, bool enb) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); - switch(unit) - { + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); + switch (unit) { case UNIT_RX: return _config.clock->enable_dboard_clock(_config.which_rx_clk, enb); case UNIT_TX: @@ -109,7 +106,8 @@ void x300_dboard_iface::set_clock_enabled(unit_t unit, bool enb) double x300_dboard_iface::get_codec_rate(unit_t unit) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); return _config.clock->get_master_clock_rate(); } @@ -126,7 +124,8 @@ uint32_t x300_dboard_iface::get_pin_ctrl(unit_t unit) return _config.gpio->get_pin_ctrl(unit); } -void x300_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask) +void x300_dboard_iface::set_atr_reg( + unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask) { _config.gpio->set_atr_reg(unit, reg, value, mask); } @@ -165,34 +164,33 @@ uint32_t x300_dboard_iface::read_gpio(unit_t unit) * SPI **********************************************************************/ void x300_dboard_iface::write_spi( - unit_t unit, - const spi_config_t &config, - uint32_t data, - size_t num_bits -){ + unit_t unit, const spi_config_t& config, uint32_t data, size_t num_bits) +{ uint32_t slave = 0; - if (unit == UNIT_TX) slave |= _config.tx_spi_slaveno; - if (unit == UNIT_RX) slave |= _config.rx_spi_slaveno; + if (unit == UNIT_TX) + slave |= _config.tx_spi_slaveno; + if (unit == UNIT_RX) + slave |= _config.rx_spi_slaveno; _config.spi->write_spi(int(slave), config, data, num_bits); } uint32_t x300_dboard_iface::read_write_spi( - unit_t unit, - const spi_config_t &config, - uint32_t data, - size_t num_bits -){ - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + unit_t unit, const spi_config_t& config, uint32_t data, size_t num_bits) +{ + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); return _config.spi->read_spi( - (unit==dboard_iface::UNIT_TX)?_config.tx_spi_slaveno:_config.rx_spi_slaveno, - config, data, num_bits); + (unit == dboard_iface::UNIT_TX) ? _config.tx_spi_slaveno : _config.rx_spi_slaveno, + config, + data, + num_bits); } /*********************************************************************** * I2C **********************************************************************/ -void x300_dboard_iface::write_i2c(uint16_t addr, const byte_vector_t &bytes) +void x300_dboard_iface::write_i2c(uint16_t addr, const byte_vector_t& bytes) { return _config.i2c->write_i2c(addr, bytes); } @@ -207,76 +205,67 @@ byte_vector_t x300_dboard_iface::read_i2c(uint16_t addr, size_t num_bytes) **********************************************************************/ void x300_dboard_iface::_write_aux_dac(unit_t unit) { - static const uhd::dict<unit_t, int> unit_to_spi_dac = map_list_of - (UNIT_RX, DB_RX_LSDAC_SEN) - (UNIT_TX, DB_TX_LSDAC_SEN) - ; - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + static const uhd::dict<unit_t, int> unit_to_spi_dac = + map_list_of(UNIT_RX, DB_RX_LSDAC_SEN)(UNIT_TX, DB_TX_LSDAC_SEN); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); _config.spi->write_spi( - unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, - _dac_regs[unit].get_reg(), 24 - ); + unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, _dac_regs[unit].get_reg(), 24); } void x300_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, double value) { - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); - _dac_regs[unit].data = boost::math::iround(4095*value/3.3); - _dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N; + _dac_regs[unit].data = boost::math::iround(4095 * value / 3.3); + _dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N; typedef uhd::dict<aux_dac_t, ad5623_regs_t::addr_t> aux_dac_to_addr; - static const uhd::dict<unit_t, aux_dac_to_addr> unit_to_which_to_addr = map_list_of - (UNIT_RX, map_list_of - (AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A) - (AUX_DAC_B, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A) - ) - (UNIT_TX, map_list_of - (AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A) - (AUX_DAC_B, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B) - (AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A) - ) - ; + static const uhd::dict<unit_t, aux_dac_to_addr> unit_to_which_to_addr = + map_list_of(UNIT_RX, + map_list_of(AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A)(AUX_DAC_B, + ad5623_regs_t::ADDR_DAC_B)(AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B)( + AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A))(UNIT_TX, + map_list_of(AUX_DAC_A, ad5623_regs_t::ADDR_DAC_A)(AUX_DAC_B, + ad5623_regs_t::ADDR_DAC_B)(AUX_DAC_C, ad5623_regs_t::ADDR_DAC_B)( + AUX_DAC_D, ad5623_regs_t::ADDR_DAC_A)); _dac_regs[unit].addr = unit_to_which_to_addr[unit][which]; this->_write_aux_dac(unit); } double x300_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which) { - static const uhd::dict<unit_t, int> unit_to_spi_adc = map_list_of - (UNIT_RX, DB_RX_LSADC_SEN) - (UNIT_TX, DB_TX_LSADC_SEN) - ; + static const uhd::dict<unit_t, int> unit_to_spi_adc = + map_list_of(UNIT_RX, DB_RX_LSADC_SEN)(UNIT_TX, DB_TX_LSADC_SEN); - if (unit == UNIT_BOTH) throw uhd::runtime_error("UNIT_BOTH not supported."); + if (unit == UNIT_BOTH) + throw uhd::runtime_error("UNIT_BOTH not supported."); - //setup spi config args + // setup spi config args spi_config_t config; config.mosi_edge = spi_config_t::EDGE_FALL; config.miso_edge = spi_config_t::EDGE_RISE; - //setup the spi registers + // setup the spi registers ad7922_regs_t ad7922_regs; - switch(which){ - case AUX_ADC_A: ad7922_regs.mod = 0; break; - case AUX_ADC_B: ad7922_regs.mod = 1; break; - } ad7922_regs.chn = ad7922_regs.mod; //normal mode: mod == chn + switch (which) { + case AUX_ADC_A: + ad7922_regs.mod = 0; + break; + case AUX_ADC_B: + ad7922_regs.mod = 1; + break; + } + ad7922_regs.chn = ad7922_regs.mod; // normal mode: mod == chn - //write and read spi - _config.spi->write_spi( - unit_to_spi_adc[unit], config, - ad7922_regs.get_reg(), 16 - ); - ad7922_regs.set_reg(uint16_t(_config.spi->read_spi( - unit_to_spi_adc[unit], config, - ad7922_regs.get_reg(), 16 - ))); - - //convert to voltage and return - return 3.3*ad7922_regs.result/4095; + // write and read spi + _config.spi->write_spi(unit_to_spi_adc[unit], config, ad7922_regs.get_reg(), 16); + ad7922_regs.set_reg(uint16_t( + _config.spi->read_spi(unit_to_spi_adc[unit], config, ad7922_regs.get_reg(), 16))); + + // convert to voltage and return + return 3.3 * ad7922_regs.result / 4095; } uhd::time_spec_t x300_dboard_iface::get_command_time() @@ -290,15 +279,13 @@ void x300_dboard_iface::set_command_time(const uhd::time_spec_t& t) } void x300_dboard_iface::add_rx_fe( - const std::string& fe_name, - rx_frontend_core_3000::sptr fe_core) + const std::string& fe_name, rx_frontend_core_3000::sptr fe_core) { _rx_fes[fe_name] = fe_core; } void x300_dboard_iface::set_fe_connection( - unit_t unit, const std::string& fe_name, - const fe_connection_t& fe_conn) + unit_t unit, const std::string& fe_name, const fe_connection_t& fe_conn) { if (unit == UNIT_RX) { if (_rx_fes.has_key(fe_name)) { diff --git a/host/lib/usrp/x300/x300_dboard_iface.hpp b/host/lib/usrp/x300/x300_dboard_iface.hpp index f41bb3d42..713c90748 100644 --- a/host/lib/usrp/x300/x300_dboard_iface.hpp +++ b/host/lib/usrp/x300/x300_dboard_iface.hpp @@ -8,41 +8,41 @@ #ifndef INCLUDED_X300_DBOARD_IFACE_HPP #define INCLUDED_X300_DBOARD_IFACE_HPP +#include "ad5623_regs.hpp" //aux dac +#include "ad7922_regs.hpp" //aux adc #include "x300_clock_ctrl.hpp" -#include <uhdlib/usrp/cores/spi_core_3000.hpp> -#include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/usrp/dboard_iface.hpp> #include <uhdlib/usrp/cores/gpio_atr_3000.hpp> +#include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> #include <uhdlib/usrp/cores/rx_frontend_core_3000.hpp> -#include "ad7922_regs.hpp" //aux adc -#include "ad5623_regs.hpp" //aux dac -#include <uhd/usrp/dboard_iface.hpp> -#include <uhd/types/dict.hpp> +#include <uhdlib/usrp/cores/spi_core_3000.hpp> struct x300_dboard_iface_config_t { uhd::usrp::gpio_atr::db_gpio_atr_3000::sptr gpio; - spi_core_3000::sptr spi; - size_t rx_spi_slaveno; - size_t tx_spi_slaveno; - uhd::i2c_iface::sptr i2c; - x300_clock_ctrl::sptr clock; - x300_clock_which_t which_rx_clk; - x300_clock_which_t which_tx_clk; - uint8_t dboard_slot; - uhd::timed_wb_iface::sptr cmd_time_ctrl; + spi_core_3000::sptr spi; + size_t rx_spi_slaveno; + size_t tx_spi_slaveno; + uhd::i2c_iface::sptr i2c; + x300_clock_ctrl::sptr clock; + x300_clock_which_t which_rx_clk; + x300_clock_which_t which_tx_clk; + uint8_t dboard_slot; + uhd::timed_wb_iface::sptr cmd_time_ctrl; }; class x300_dboard_iface : public uhd::usrp::dboard_iface { public: - x300_dboard_iface(const x300_dboard_iface_config_t &config); + x300_dboard_iface(const x300_dboard_iface_config_t& config); ~x300_dboard_iface(void); inline special_props_t get_special_props(void) { special_props_t props; props.soft_clock_divider = false; - props.mangle_i2c_addrs = (_config.dboard_slot == 1); + props.mangle_i2c_addrs = (_config.dboard_slot == 1); return props; } @@ -51,7 +51,8 @@ public: void set_pin_ctrl(unit_t unit, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_pin_ctrl(unit_t unit); - void set_atr_reg(unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask = 0xffffffff); + void set_atr_reg( + unit_t unit, atr_reg_t reg, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_atr_reg(unit_t unit, atr_reg_t reg); void set_gpio_ddr(unit_t unit, uint32_t value, uint32_t mask = 0xffffffff); uint32_t get_gpio_ddr(unit_t unit); @@ -62,7 +63,7 @@ public: void set_command_time(const uhd::time_spec_t& t); uhd::time_spec_t get_command_time(void); - void write_i2c(uint16_t, const uhd::byte_vector_t &); + void write_i2c(uint16_t, const uhd::byte_vector_t&); uhd::byte_vector_t read_i2c(uint16_t, size_t); void set_clock_rate(unit_t, double); @@ -72,21 +73,12 @@ public: double get_codec_rate(unit_t); void write_spi( - unit_t unit, - const uhd::spi_config_t &config, - uint32_t data, - size_t num_bits - ); + unit_t unit, const uhd::spi_config_t& config, uint32_t data, size_t num_bits); uint32_t read_write_spi( - unit_t unit, - const uhd::spi_config_t &config, - uint32_t data, - size_t num_bits - ); + unit_t unit, const uhd::spi_config_t& config, uint32_t data, size_t num_bits); void set_fe_connection( - unit_t unit, const std::string& name, - const uhd::usrp::fe_connection_t& fe_conn); + unit_t unit, const std::string& name, const uhd::usrp::fe_connection_t& fe_conn); // X300 can set the FE connection on the RX side bool has_set_fe_connection(const unit_t unit) override @@ -94,9 +86,7 @@ public: return unit == UNIT_RX; } - void add_rx_fe( - const std::string& fe_name, - rx_frontend_core_3000::sptr fe_core); + void add_rx_fe(const std::string& fe_name, rx_frontend_core_3000::sptr fe_core); private: const x300_dboard_iface_config_t _config; @@ -107,5 +97,4 @@ private: }; - #endif /* INCLUDED_X300_DBOARD_IFACE_HPP */ diff --git a/host/lib/usrp/x300/x300_defaults.hpp b/host/lib/usrp/x300/x300_defaults.hpp index aa8d1b688..2e242f24f 100644 --- a/host/lib/usrp/x300/x300_defaults.hpp +++ b/host/lib/usrp/x300/x300_defaults.hpp @@ -7,103 +7,100 @@ #ifndef INCLUDED_X300_DEFAULTS_HPP #define INCLUDED_X300_DEFAULTS_HPP -#include <uhd/transport/udp_simple.hpp> //mtu #include "../device3/device3_impl.hpp" +#include <uhd/transport/udp_simple.hpp> //mtu #include <string> - -namespace uhd { -namespace usrp { -namespace x300 { +namespace uhd { namespace usrp { namespace x300 { static constexpr size_t NIUSRPRIO_DEFAULT_RPC_PORT = 5444; static constexpr uint32_t RADIO_DEST_PREFIX_TX = 0; -static constexpr size_t XB_DST_E0 = 0; -static constexpr size_t XB_DST_E1 = 1; -static constexpr size_t XB_DST_PCI = 2; -static constexpr size_t XB_DST_R0 = 3; // Radio 0 -> Slot A -static constexpr size_t XB_DST_R1 = 4; // Radio 1 -> Slot B -static constexpr size_t XB_DST_CE0 = 5; +static constexpr size_t XB_DST_E0 = 0; +static constexpr size_t XB_DST_E1 = 1; +static constexpr size_t XB_DST_PCI = 2; +static constexpr size_t XB_DST_R0 = 3; // Radio 0 -> Slot A +static constexpr size_t XB_DST_R1 = 4; // Radio 1 -> Slot B +static constexpr size_t XB_DST_CE0 = 5; -static constexpr size_t SRC_ADDR0 = 0; -static constexpr size_t SRC_ADDR1 = 1; -static constexpr size_t DST_ADDR = 2; +static constexpr size_t SRC_ADDR0 = 0; +static constexpr size_t SRC_ADDR1 = 1; +static constexpr size_t DST_ADDR = 2; -static constexpr double DEFAULT_TICK_RATE = 200e6; // Hz -static constexpr double MAX_TICK_RATE = 200e6; // Hz -static constexpr double MIN_TICK_RATE = 184.32e6; // Hz -static constexpr double BUS_CLOCK_RATE = 187.5e6; // Hz +static constexpr double DEFAULT_TICK_RATE = 200e6; // Hz +static constexpr double MAX_TICK_RATE = 200e6; // Hz +static constexpr double MIN_TICK_RATE = 184.32e6; // Hz +static constexpr double BUS_CLOCK_RATE = 187.5e6; // Hz -static const std::string FW_FILE_NAME = "usrp_x300_fw.bin"; +static const std::string FW_FILE_NAME = "usrp_x300_fw.bin"; // Clock & Time-related defaults static const std::string DEFAULT_CLOCK_SOURCE = "internal"; static const std::string DEFAULT_TIME_SOURCE = "internal"; -static const bool DEFAULT_TIME_OUTPUT = true; +static const bool DEFAULT_TIME_OUTPUT = true; static const std::vector<std::string> CLOCK_SOURCE_OPTIONS{ - "internal", - "external", - "gpsdo" -}; + "internal", "external", "gpsdo"}; static const std::vector<std::string> TIME_SOURCE_OPTIONS{ - "internal", - "external", - "gpsdo" -}; + "internal", "external", "gpsdo"}; static const std::vector<double> EXTERNAL_FREQ_OPTIONS{10e6, 30.72e6, 200e6}; -static constexpr size_t RX_SW_BUFF_SIZE_ETH = 0x2000000;//32MiB For an ~8k frame size any size >32MiB is just wasted buffer space -static constexpr size_t RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib - -//The FIFO closest to the DMA controller is 1023 elements deep for RX and 1029 elements deep for TX -//where an element is 8 bytes. The buffers (number of frames * frame size) must be aligned to the -//memory page size. For the control, we are getting lucky because 64 frames * 256 bytes each aligns -//with the typical page size of 4096 bytes. Since most page sizes are 4096 bytes or some multiple of -//that, keep the number of frames * frame size aligned to it. -static constexpr size_t PCIE_RX_DATA_FRAME_SIZE = 4096; //bytes -static constexpr size_t PCIE_RX_DATA_NUM_FRAMES = 4096; -static constexpr size_t PCIE_TX_DATA_FRAME_SIZE = 4096; //bytes -static constexpr size_t PCIE_TX_DATA_NUM_FRAMES = 4096; -static constexpr size_t PCIE_MSG_FRAME_SIZE = 256; //bytes -static constexpr size_t PCIE_MSG_NUM_FRAMES = 64; -static constexpr size_t PCIE_MAX_CHANNELS = 6; -static constexpr size_t PCIE_MAX_MUXED_CTRL_XPORTS = 32; -static constexpr size_t PCIE_MAX_MUXED_ASYNC_XPORTS = 4; - -static const size_t DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes -static const size_t XGE_DATA_FRAME_SEND_SIZE = 4000; // Reduced to make sure flow control packets are not blocked for too long at high rates -static const size_t XGE_DATA_FRAME_RECV_SIZE = 8000; -static const size_t GE_DATA_FRAME_SEND_SIZE = 1472; -static const size_t GE_DATA_FRAME_RECV_SIZE = 1472; - -static const size_t ETH_MSG_FRAME_SIZE = uhd::transport::udp_simple::mtu; //bytes +static constexpr size_t RX_SW_BUFF_SIZE_ETH = + 0x2000000; // 32MiB For an ~8k frame size any size >32MiB is just wasted buffer + // space +static constexpr size_t RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; // 1Mib + +// The FIFO closest to the DMA controller is 1023 elements deep for RX and 1029 elements +// deep for TX where an element is 8 bytes. The buffers (number of frames * frame size) +// must be aligned to the memory page size. For the control, we are getting lucky because +// 64 frames * 256 bytes each aligns with the typical page size of 4096 bytes. Since most +// page sizes are 4096 bytes or some multiple of that, keep the number of frames * frame +// size aligned to it. +static constexpr size_t PCIE_RX_DATA_FRAME_SIZE = 4096; // bytes +static constexpr size_t PCIE_RX_DATA_NUM_FRAMES = 4096; +static constexpr size_t PCIE_TX_DATA_FRAME_SIZE = 4096; // bytes +static constexpr size_t PCIE_TX_DATA_NUM_FRAMES = 4096; +static constexpr size_t PCIE_MSG_FRAME_SIZE = 256; // bytes +static constexpr size_t PCIE_MSG_NUM_FRAMES = 64; +static constexpr size_t PCIE_MAX_CHANNELS = 6; +static constexpr size_t PCIE_MAX_MUXED_CTRL_XPORTS = 32; +static constexpr size_t PCIE_MAX_MUXED_ASYNC_XPORTS = 4; + +static const size_t DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes +static const size_t XGE_DATA_FRAME_SEND_SIZE = + 4000; // Reduced to make sure flow control packets are not blocked for too long at + // high rates +static const size_t XGE_DATA_FRAME_RECV_SIZE = 8000; +static const size_t GE_DATA_FRAME_SEND_SIZE = 1472; +static const size_t GE_DATA_FRAME_RECV_SIZE = 1472; + +static const size_t ETH_MSG_FRAME_SIZE = uhd::transport::udp_simple::mtu; // bytes // MTU throttling for ethernet/TX (see above): static constexpr size_t ETH_DATA_FRAME_MAX_TX_SIZE = 8000; -static constexpr double RECV_OFFLOAD_BUFFER_TIMEOUT = 0.1; //seconds -static constexpr double THREAD_BUFFER_TIMEOUT = 0.1; // Time in seconds +static constexpr double RECV_OFFLOAD_BUFFER_TIMEOUT = 0.1; // seconds +static constexpr double THREAD_BUFFER_TIMEOUT = 0.1; // Time in seconds -static constexpr size_t ETH_MSG_NUM_FRAMES = 64; -static constexpr size_t ETH_DATA_NUM_FRAMES = 32; -static constexpr double DEFAULT_SYSREF_RATE = 10e6; +static constexpr size_t ETH_MSG_NUM_FRAMES = 64; +static constexpr size_t ETH_DATA_NUM_FRAMES = 32; +static constexpr double DEFAULT_SYSREF_RATE = 10e6; // Limit the number of initialization threads -static const size_t MAX_INIT_THREADS = 10; - -static const size_t MAX_RATE_PCIE = 800000000; // bytes/s -static const size_t MAX_RATE_10GIGE = (size_t)( // bytes/s - 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data - ( float(DATA_FRAME_MAX_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) / - float(DATA_FRAME_MAX_SIZE + 8 /* UDP header */ + 20 /* Ethernet header length */ ))); -static const size_t MAX_RATE_1GIGE = (size_t)( // bytes/s - 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data - ( float(GE_DATA_FRAME_RECV_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) / - float(GE_DATA_FRAME_RECV_SIZE + 8 /* UDP header */ + 20 /* Ethernet header length */ ))); +static const size_t MAX_INIT_THREADS = 10; + +static const size_t MAX_RATE_PCIE = 800000000; // bytes/s +static const size_t MAX_RATE_10GIGE = (size_t)( // bytes/s + 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data + (float(DATA_FRAME_MAX_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) + / float(DATA_FRAME_MAX_SIZE + + 8 /* UDP header */ + 20 /* Ethernet header length */))); +static const size_t MAX_RATE_1GIGE = (size_t)( // bytes/s + 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data + (float(GE_DATA_FRAME_RECV_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) + / float(GE_DATA_FRAME_RECV_SIZE + + 8 /* UDP header */ + 20 /* Ethernet header length */))); }}} /* namespace uhd::usrp::x300 */ #endif /* INCLUDED_X300_DEFAULTS_HPP */ - diff --git a/host/lib/usrp/x300/x300_device_args.hpp b/host/lib/usrp/x300/x300_device_args.hpp index db1a01212..bdb3762af 100644 --- a/host/lib/usrp/x300/x300_device_args.hpp +++ b/host/lib/usrp/x300/x300_device_args.hpp @@ -7,8 +7,8 @@ #ifndef INCLUDED_X300_DEV_ARGS_HPP #define INCLUDED_X300_DEV_ARGS_HPP -#include "x300_impl.hpp" #include "x300_defaults.hpp" +#include "x300_impl.hpp" #include <uhdlib/usrp/constrained_device_args.hpp> namespace uhd { namespace usrp { namespace x300 { @@ -16,97 +16,116 @@ namespace uhd { namespace usrp { namespace x300 { class x300_device_args_t : public constrained_device_args_t { public: - x300_device_args_t(): - _master_clock_rate("master_clock_rate", DEFAULT_TICK_RATE), - _dboard_clock_rate("dboard_clock_rate", -1), - _system_ref_rate("system_ref_rate", DEFAULT_SYSREF_RATE), - _clock_source("clock_source", DEFAULT_CLOCK_SOURCE), - _time_source("time_source", DEFAULT_TIME_SOURCE), - _first_addr("addr", ""), - _second_addr("second_addr", ""), - _resource("resource", ""), - _self_cal_adc_delay("self_cal_adc_delay", false), - _ext_adc_self_test("ext_adc_self_test", false), - _ext_adc_self_test_duration("ext_adc_self_test", 30.0), - _recover_mb_eeprom("recover_mb_eeprom", false), - _ignore_cal_file("ignore_cal_file", false), - _niusrprio_rpc_port("niusrprio_rpc_port", NIUSRPRIO_DEFAULT_RPC_PORT), - _has_fw_file("fw", false), - _fw_file("fw", ""), - _blank_eeprom("blank_eeprom", false), - _enable_tx_dual_eth("enable_tx_dual_eth", false) + x300_device_args_t() + : _master_clock_rate("master_clock_rate", DEFAULT_TICK_RATE) + , _dboard_clock_rate("dboard_clock_rate", -1) + , _system_ref_rate("system_ref_rate", DEFAULT_SYSREF_RATE) + , _clock_source("clock_source", DEFAULT_CLOCK_SOURCE) + , _time_source("time_source", DEFAULT_TIME_SOURCE) + , _first_addr("addr", "") + , _second_addr("second_addr", "") + , _resource("resource", "") + , _self_cal_adc_delay("self_cal_adc_delay", false) + , _ext_adc_self_test("ext_adc_self_test", false) + , _ext_adc_self_test_duration("ext_adc_self_test", 30.0) + , _recover_mb_eeprom("recover_mb_eeprom", false) + , _ignore_cal_file("ignore_cal_file", false) + , _niusrprio_rpc_port("niusrprio_rpc_port", NIUSRPRIO_DEFAULT_RPC_PORT) + , _has_fw_file("fw", false) + , _fw_file("fw", "") + , _blank_eeprom("blank_eeprom", false) + , _enable_tx_dual_eth("enable_tx_dual_eth", false) { // nop } - double get_master_clock_rate() const { + double get_master_clock_rate() const + { return _master_clock_rate.get(); } - double get_dboard_clock_rate() const { + double get_dboard_clock_rate() const + { return _dboard_clock_rate.get(); } - double get_system_ref_rate() const { + double get_system_ref_rate() const + { return _system_ref_rate.get(); } - std::string get_clock_source() const { + std::string get_clock_source() const + { return _clock_source.get(); } - std::string get_time_source() const { + std::string get_time_source() const + { return _time_source.get(); } - std::string get_first_addr() const { + std::string get_first_addr() const + { return _first_addr.get(); } - std::string get_second_addr() const { + std::string get_second_addr() const + { return _second_addr.get(); } - bool get_self_cal_adc_delay() const { + bool get_self_cal_adc_delay() const + { return _self_cal_adc_delay.get(); } - bool get_ext_adc_self_test() const { + bool get_ext_adc_self_test() const + { return _ext_adc_self_test.get(); } - double get_ext_adc_self_test_duration() const { + double get_ext_adc_self_test_duration() const + { return _ext_adc_self_test_duration.get(); } - bool get_recover_mb_eeprom() const { + bool get_recover_mb_eeprom() const + { return _recover_mb_eeprom.get(); } - bool get_ignore_cal_file() const { + bool get_ignore_cal_file() const + { return _ignore_cal_file.get(); } // must be a number in the string // default NIUSRPRIO_DEFAULT_RPC_PORT - std::string get_niusrprio_rpc_port() const { + std::string get_niusrprio_rpc_port() const + { return std::to_string(_niusrprio_rpc_port.get()); } - std::string get_resource() const { + std::string get_resource() const + { return _resource.get(); } // must be valid file, key == fw, default x300::FW_FILE_NAME - std::string get_fw_file() const { + std::string get_fw_file() const + { return _fw_file.get(); } // true if the key is set - bool has_fw_file() const { + bool has_fw_file() const + { return _has_fw_file.get(); } - bool get_blank_eeprom() const { + bool get_blank_eeprom() const + { return _blank_eeprom.get(); } - bool get_enable_tx_dual_eth() const { + bool get_enable_tx_dual_eth() const + { return _enable_tx_dual_eth.get(); } - inline virtual std::string to_string() const { - return _master_clock_rate.to_string() + ", " + - ""; + inline virtual std::string to_string() const + { + return _master_clock_rate.to_string() + ", " + ""; } private: - virtual void _parse(const device_addr_t& dev_args) { - //Extract parameters from dev_args + virtual void _parse(const device_addr_t& dev_args) + { + // Extract parameters from dev_args #define PARSE_DEFAULT(arg) parse_arg_default(dev_args, arg); PARSE_DEFAULT(_master_clock_rate) if (dev_args.has_key(_master_clock_rate.key())) { @@ -118,14 +137,12 @@ private: // Some daughterboards may require other rates, but this default // works best for all newer daughterboards (i.e. CBX, WBX, SBX, // UBX, and TwinRX). - if (_master_clock_rate.get() >= MIN_TICK_RATE && - _master_clock_rate.get() <= MAX_TICK_RATE) { + if (_master_clock_rate.get() >= MIN_TICK_RATE + && _master_clock_rate.get() <= MAX_TICK_RATE) { _dboard_clock_rate.set(_master_clock_rate.get() / 4); } else { - throw uhd::value_error( - "Can't infer daughterboard clock rate. Specify " - "dboard_clk_rate in the device args." - ); + throw uhd::value_error("Can't infer daughterboard clock rate. Specify " + "dboard_clk_rate in the device args."); } } PARSE_DEFAULT(_system_ref_rate) @@ -152,11 +169,11 @@ private: PARSE_DEFAULT(_fw_file); } PARSE_DEFAULT(_blank_eeprom) - if (dev_args.has_key("enable_tx_dual_eth")){ + if (dev_args.has_key("enable_tx_dual_eth")) { _enable_tx_dual_eth.set(true); } - //Sanity check params + // Sanity check params _enforce_range(_master_clock_rate, MIN_TICK_RATE, MAX_TICK_RATE); _enforce_discrete(_system_ref_rate, EXTERNAL_FREQ_OPTIONS); _enforce_discrete(_clock_source, CLOCK_SOURCE_OPTIONS); @@ -164,26 +181,26 @@ private: // TODO: If _fw_file is set, make sure it's actually a file } - constrained_device_args_t::num_arg<double> _master_clock_rate; - constrained_device_args_t::num_arg<double> _dboard_clock_rate; - constrained_device_args_t::num_arg<double> _system_ref_rate; - constrained_device_args_t::str_arg<false> _clock_source; - constrained_device_args_t::str_arg<false> _time_source; - constrained_device_args_t::str_arg<false> _first_addr; - constrained_device_args_t::str_arg<false> _second_addr; - constrained_device_args_t::str_arg<true> _resource; - constrained_device_args_t::bool_arg _self_cal_adc_delay; - constrained_device_args_t::bool_arg _ext_adc_self_test; - constrained_device_args_t::num_arg<double> _ext_adc_self_test_duration; - constrained_device_args_t::bool_arg _recover_mb_eeprom; - constrained_device_args_t::bool_arg _ignore_cal_file; - constrained_device_args_t::num_arg<size_t> _niusrprio_rpc_port; - constrained_device_args_t::bool_arg _has_fw_file; - constrained_device_args_t::str_arg<true> _fw_file; - constrained_device_args_t::bool_arg _blank_eeprom; - constrained_device_args_t::bool_arg _enable_tx_dual_eth; + constrained_device_args_t::num_arg<double> _master_clock_rate; + constrained_device_args_t::num_arg<double> _dboard_clock_rate; + constrained_device_args_t::num_arg<double> _system_ref_rate; + constrained_device_args_t::str_arg<false> _clock_source; + constrained_device_args_t::str_arg<false> _time_source; + constrained_device_args_t::str_arg<false> _first_addr; + constrained_device_args_t::str_arg<false> _second_addr; + constrained_device_args_t::str_arg<true> _resource; + constrained_device_args_t::bool_arg _self_cal_adc_delay; + constrained_device_args_t::bool_arg _ext_adc_self_test; + constrained_device_args_t::num_arg<double> _ext_adc_self_test_duration; + constrained_device_args_t::bool_arg _recover_mb_eeprom; + constrained_device_args_t::bool_arg _ignore_cal_file; + constrained_device_args_t::num_arg<size_t> _niusrprio_rpc_port; + constrained_device_args_t::bool_arg _has_fw_file; + constrained_device_args_t::str_arg<true> _fw_file; + constrained_device_args_t::bool_arg _blank_eeprom; + constrained_device_args_t::bool_arg _enable_tx_dual_eth; }; -}}} //namespace +}}} // namespace uhd::usrp::x300 -#endif //INCLUDED_X300_DEV_ARGS_HPP +#endif // INCLUDED_X300_DEV_ARGS_HPP diff --git a/host/lib/usrp/x300/x300_fw_ctrl.cpp b/host/lib/usrp/x300/x300_fw_ctrl.cpp index 21c64b509..cbe48bfe8 100644 --- a/host/lib/usrp/x300/x300_fw_ctrl.cpp +++ b/host/lib/usrp/x300/x300_fw_ctrl.cpp @@ -5,18 +5,18 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include <uhd/types/wb_iface.hpp> #include "x300_fw_common.h" +#include "x300_regs.hpp" +#include <uhd/exception.hpp> +#include <uhd/transport/nirio/niriok_proxy.h> +#include <uhd/transport/nirio/status.h> #include <uhd/transport/udp_simple.hpp> +#include <uhd/types/wb_iface.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/utils/log.hpp> -#include <uhd/exception.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/format.hpp> #include <boost/thread/mutex.hpp> -#include <uhd/transport/nirio/status.h> -#include <uhd/transport/nirio/niriok_proxy.h> -#include "x300_regs.hpp" -#include <boost/date_time/posix_time/posix_time.hpp> #include <chrono> #include <thread> @@ -26,7 +26,7 @@ using namespace uhd::niusrprio; class x300_ctrl_iface : public wb_iface { public: - enum {num_retries = 3}; + enum { num_retries = 3 }; x300_ctrl_iface(bool enable_errors = true) : errors(enable_errors) { @@ -41,39 +41,37 @@ public: void poke32(const wb_addr_type addr, const uint32_t data) { - for (size_t i = 1; i <= num_retries; i++) - { + for (size_t i = 1; i <= num_retries; i++) { boost::mutex::scoped_lock lock(reg_access); - try - { + try { return this->__poke32(addr, data); - } - catch(const uhd::io_error &ex) - { - std::string error_msg = str(boost::format( - "%s: x300 fw communication failure #%u\n%s") % __loc_info() % i % ex.what()); - if (errors) UHD_LOGGER_ERROR("X300") << error_msg ; - if (i == num_retries) throw uhd::io_error(error_msg); + } catch (const uhd::io_error& ex) { + std::string error_msg = + str(boost::format("%s: x300 fw communication failure #%u\n%s") + % __loc_info() % i % ex.what()); + if (errors) + UHD_LOGGER_ERROR("X300") << error_msg; + if (i == num_retries) + throw uhd::io_error(error_msg); } } } uint32_t peek32(const wb_addr_type addr) { - for (size_t i = 1; i <= num_retries; i++) - { + for (size_t i = 1; i <= num_retries; i++) { boost::mutex::scoped_lock lock(reg_access); - try - { + try { uint32_t data = this->__peek32(addr); return data; - } - catch(const uhd::io_error &ex) - { - std::string error_msg = str(boost::format( - "%s: x300 fw communication failure #%u\n%s") % __loc_info() % i % ex.what()); - if (errors) UHD_LOGGER_ERROR("X300") << error_msg ; - if (i == num_retries) throw uhd::io_error(error_msg); + } catch (const uhd::io_error& ex) { + std::string error_msg = + str(boost::format("%s: x300 fw communication failure #%u\n%s") + % __loc_info() % i % ex.what()); + if (errors) + UHD_LOGGER_ERROR("X300") << error_msg; + if (i == num_retries) + throw uhd::io_error(error_msg); } } return 0; @@ -83,9 +81,9 @@ protected: bool errors; virtual void __poke32(const wb_addr_type addr, const uint32_t data) = 0; - virtual uint32_t __peek32(const wb_addr_type addr) = 0; - virtual void __flush() = 0; - virtual std::string __loc_info() = 0; + virtual uint32_t __peek32(const wb_addr_type addr) = 0; + virtual void __flush() = 0; + virtual std::string __loc_info() = 0; boost::mutex reg_access; }; @@ -97,39 +95,40 @@ protected: class x300_ctrl_iface_enet : public x300_ctrl_iface { public: - x300_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true): - x300_ctrl_iface(enable_errors), udp(udp), seq(0) + x300_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true) + : x300_ctrl_iface(enable_errors), udp(udp), seq(0) { - try - { + try { this->peek32(0); + } catch (...) { } - catch(...){} } protected: virtual void __poke32(const wb_addr_type addr, const uint32_t data) { - //load request struct + // load request struct x300_fw_comms_t request = x300_fw_comms_t(); - request.flags = uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK | X300_FW_COMMS_FLAGS_POKE32); + request.flags = + uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK | X300_FW_COMMS_FLAGS_POKE32); request.sequence = uhd::htonx<uint32_t>(seq++); - request.addr = uhd::htonx(addr); - request.data = uhd::htonx(data); + request.addr = uhd::htonx(addr); + request.data = uhd::htonx(data); - //send request + // send request __flush(); udp->send(boost::asio::buffer(&request, sizeof(request))); - //recv reply + // recv reply x300_fw_comms_t reply = x300_fw_comms_t(); const size_t nbytes = udp->recv(boost::asio::buffer(&reply, sizeof(reply)), 1.0); - if (nbytes == 0) throw uhd::io_error("x300 fw poke32 - reply timed out"); + if (nbytes == 0) + throw uhd::io_error("x300 fw poke32 - reply timed out"); - //sanity checks + // sanity checks const size_t flags = uhd::ntohx<uint32_t>(reply.flags); UHD_ASSERT_THROW(nbytes == sizeof(reply)); - UHD_ASSERT_THROW(not (flags & X300_FW_COMMS_FLAGS_ERROR)); + UHD_ASSERT_THROW(not(flags & X300_FW_COMMS_FLAGS_ERROR)); UHD_ASSERT_THROW(flags & X300_FW_COMMS_FLAGS_POKE32); UHD_ASSERT_THROW(flags & X300_FW_COMMS_FLAGS_ACK); UHD_ASSERT_THROW(reply.sequence == request.sequence); @@ -139,39 +138,42 @@ protected: virtual uint32_t __peek32(const wb_addr_type addr) { - //load request struct + // load request struct x300_fw_comms_t request = x300_fw_comms_t(); - request.flags = uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK | X300_FW_COMMS_FLAGS_PEEK32); + request.flags = + uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK | X300_FW_COMMS_FLAGS_PEEK32); request.sequence = uhd::htonx<uint32_t>(seq++); - request.addr = uhd::htonx(addr); - request.data = 0; + request.addr = uhd::htonx(addr); + request.data = 0; - //send request + // send request __flush(); udp->send(boost::asio::buffer(&request, sizeof(request))); - //recv reply + // recv reply x300_fw_comms_t reply = x300_fw_comms_t(); const size_t nbytes = udp->recv(boost::asio::buffer(&reply, sizeof(reply)), 1.0); - if (nbytes == 0) throw uhd::io_error("x300 fw peek32 - reply timed out"); + if (nbytes == 0) + throw uhd::io_error("x300 fw peek32 - reply timed out"); - //sanity checks + // sanity checks const size_t flags = uhd::ntohx<uint32_t>(reply.flags); UHD_ASSERT_THROW(nbytes == sizeof(reply)); - UHD_ASSERT_THROW(not (flags & X300_FW_COMMS_FLAGS_ERROR)); + UHD_ASSERT_THROW(not(flags & X300_FW_COMMS_FLAGS_ERROR)); UHD_ASSERT_THROW(flags & X300_FW_COMMS_FLAGS_PEEK32); UHD_ASSERT_THROW(flags & X300_FW_COMMS_FLAGS_ACK); UHD_ASSERT_THROW(reply.sequence == request.sequence); UHD_ASSERT_THROW(reply.addr == request.addr); - //return result! + // return result! return uhd::ntohx<uint32_t>(reply.data); } virtual void __flush(void) { char buff[X300_FW_COMMS_MTU] = {}; - while (udp->recv(boost::asio::buffer(buff), 0.0)){} //flush + while (udp->recv(boost::asio::buffer(buff), 0.0)) { + } // flush } virtual std::string __loc_info(void) @@ -191,61 +193,66 @@ private: class x300_ctrl_iface_pcie : public x300_ctrl_iface { public: - x300_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy, bool enable_errors = true): - x300_ctrl_iface(enable_errors), _drv_proxy(drv_proxy) + x300_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy, bool enable_errors = true) + : x300_ctrl_iface(enable_errors), _drv_proxy(drv_proxy) { nirio_status status = 0; - nirio_status_chain(_drv_proxy->set_attribute(RIO_ADDRESS_SPACE, BUS_INTERFACE), status); + nirio_status_chain( + _drv_proxy->set_attribute(RIO_ADDRESS_SPACE, BUS_INTERFACE), status); - //Verify that the Ettus FPGA loaded in the device. This may not be true if the - //user is switching to UHD after using LabVIEW FPGA. + // Verify that the Ettus FPGA loaded in the device. This may not be true if the + // user is switching to UHD after using LabVIEW FPGA. uint32_t pcie_fpga_signature = 0; _drv_proxy->peek(FPGA_PCIE_SIG_REG, pcie_fpga_signature); if (pcie_fpga_signature != FPGA_X3xx_SIG_VALUE) - throw uhd::io_error("cannot create x300_ctrl_iface_pcie. incorrect/no fpga image"); + throw uhd::io_error( + "cannot create x300_ctrl_iface_pcie. incorrect/no fpga image"); - //Also, poll on the ZPU_STATUS bit to ensure all the state machines in the FPGA are - //ready to accept register transaction requests. + // Also, poll on the ZPU_STATUS bit to ensure all the state machines in the FPGA + // are ready to accept register transaction requests. uint32_t reg_data = 0xffffffff; - boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); + boost::posix_time::ptime start_time = + boost::posix_time::microsec_clock::local_time(); boost::posix_time::time_duration elapsed; do { - std::this_thread::sleep_for(std::chrono::microseconds(500)); //Avoid flooding the bus + std::this_thread::sleep_for( + std::chrono::microseconds(500)); // Avoid flooding the bus elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_drv_proxy->peek(PCIE_ZPU_STATUS_REG(0), reg_data), status); - } while ( - nirio_status_not_fatal(status) && - (reg_data & PCIE_ZPU_STATUS_SUSPENDED) && - elapsed.total_milliseconds() < INIT_TIMEOUT_IN_MS); + nirio_status_chain( + _drv_proxy->peek(PCIE_ZPU_STATUS_REG(0), reg_data), status); + } while (nirio_status_not_fatal(status) && (reg_data & PCIE_ZPU_STATUS_SUSPENDED) + && elapsed.total_milliseconds() < INIT_TIMEOUT_IN_MS); nirio_status_to_exception(status, "Could not initialize x300_ctrl_iface_pcie."); - try - { + try { this->peek32(0); + } catch (...) { } - catch(...){} } protected: virtual void __poke32(const wb_addr_type addr, const uint32_t data) { nirio_status status = 0; - uint32_t reg_data = 0xffffffff; - boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); + uint32_t reg_data = 0xffffffff; + boost::posix_time::ptime start_time = + boost::posix_time::microsec_clock::local_time(); boost::posix_time::time_duration elapsed; nirio_status_chain(_drv_proxy->poke(PCIE_ZPU_DATA_REG(addr), data), status); if (nirio_status_not_fatal(status)) { do { - std::this_thread::sleep_for(std::chrono::microseconds(50)); //Avoid flooding the bus + std::this_thread::sleep_for( + std::chrono::microseconds(50)); // Avoid flooding the bus elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_drv_proxy->peek(PCIE_ZPU_STATUS_REG(addr), reg_data), status); + nirio_status_chain( + _drv_proxy->peek(PCIE_ZPU_STATUS_REG(addr), reg_data), status); } while ( - nirio_status_not_fatal(status) && - ((reg_data & (PCIE_ZPU_STATUS_BUSY | PCIE_ZPU_STATUS_SUSPENDED)) != 0) && - elapsed.total_milliseconds() < READ_TIMEOUT_IN_MS); + nirio_status_not_fatal(status) + && ((reg_data & (PCIE_ZPU_STATUS_BUSY | PCIE_ZPU_STATUS_SUSPENDED)) != 0) + && elapsed.total_milliseconds() < READ_TIMEOUT_IN_MS); } if (nirio_status_fatal(status)) @@ -257,20 +264,24 @@ protected: virtual uint32_t __peek32(const wb_addr_type addr) { nirio_status status = 0; - uint32_t reg_data = 0xffffffff; - boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); + uint32_t reg_data = 0xffffffff; + boost::posix_time::ptime start_time = + boost::posix_time::microsec_clock::local_time(); boost::posix_time::time_duration elapsed; - nirio_status_chain(_drv_proxy->poke(PCIE_ZPU_READ_REG(addr), PCIE_ZPU_READ_START), status); + nirio_status_chain( + _drv_proxy->poke(PCIE_ZPU_READ_REG(addr), PCIE_ZPU_READ_START), status); if (nirio_status_not_fatal(status)) { do { - std::this_thread::sleep_for(std::chrono::microseconds(50)); //Avoid flooding the bus + std::this_thread::sleep_for( + std::chrono::microseconds(50)); // Avoid flooding the bus elapsed = boost::posix_time::microsec_clock::local_time() - start_time; - nirio_status_chain(_drv_proxy->peek(PCIE_ZPU_STATUS_REG(addr), reg_data), status); + nirio_status_chain( + _drv_proxy->peek(PCIE_ZPU_STATUS_REG(addr), reg_data), status); } while ( - nirio_status_not_fatal(status) && - ((reg_data & (PCIE_ZPU_STATUS_BUSY | PCIE_ZPU_STATUS_SUSPENDED)) != 0) && - elapsed.total_milliseconds() < READ_TIMEOUT_IN_MS); + nirio_status_not_fatal(status) + && ((reg_data & (PCIE_ZPU_STATUS_BUSY | PCIE_ZPU_STATUS_SUSPENDED)) != 0) + && elapsed.total_milliseconds() < READ_TIMEOUT_IN_MS); } nirio_status_chain(_drv_proxy->peek(PCIE_ZPU_DATA_REG(addr), reg_data), status); @@ -298,12 +309,14 @@ private: static const uint32_t INIT_TIMEOUT_IN_MS = 5000; }; -wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true) +wb_iface::sptr x300_make_ctrl_iface_enet( + uhd::transport::udp_simple::sptr udp, bool enable_errors = true) { return wb_iface::sptr(new x300_ctrl_iface_enet(udp, enable_errors)); } -wb_iface::sptr x300_make_ctrl_iface_pcie(niriok_proxy::sptr drv_proxy, bool enable_errors = true) +wb_iface::sptr x300_make_ctrl_iface_pcie( + niriok_proxy::sptr drv_proxy, bool enable_errors = true) { return wb_iface::sptr(new x300_ctrl_iface_pcie(drv_proxy, enable_errors)); } diff --git a/host/lib/usrp/x300/x300_fw_uart.cpp b/host/lib/usrp/x300/x300_fw_uart.cpp index 912d977ed..0dde87da5 100644 --- a/host/lib/usrp/x300/x300_fw_uart.cpp +++ b/host/lib/usrp/x300/x300_fw_uart.cpp @@ -6,11 +6,11 @@ // #include "x300_impl.hpp" -#include <uhd/types/wb_iface.hpp> #include "x300_regs.hpp" -#include <uhd/utils/log.hpp> -#include <uhd/types/serial.hpp> #include <uhd/exception.hpp> +#include <uhd/types/serial.hpp> +#include <uhd/types/wb_iface.hpp> +#include <uhd/utils/log.hpp> #include <boost/format.hpp> #include <chrono> @@ -18,44 +18,42 @@ using namespace uhd; struct x300_uart_iface : uart_iface { - x300_uart_iface(wb_iface::sptr iface): - _iface(iface), - rxoffset(0), - txword32(0), - _last_device_rxoffset(0) + x300_uart_iface(wb_iface::sptr iface) + : _iface(iface), rxoffset(0), txword32(0), _last_device_rxoffset(0) { - txoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX)); + txoffset = + _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX)); rxpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_ADDR)); txpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_ADDR)); - poolsize = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_WORDS32)); + poolsize = + _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_WORDS32)); _rxcache.resize(poolsize); - //this->write_uart("HELLO UART\n"); - //this->read_uart(0.1); + // this->write_uart("HELLO UART\n"); + // this->read_uart(0.1); } void putchar(const char ch) { - const int shift = ((txoffset%4) * 8); - if (shift == 0) txword32 = 0; + const int shift = ((txoffset % 4) * 8); + if (shift == 0) + txword32 = 0; txword32 |= uint32_t(ch) << shift; // Write out full 32 bit words or whatever we have if end of string - if (txoffset % 4 == 3 or ch == '\n') - { - _iface->poke32(SR_ADDR(txpool, txoffset/4), txword32); + if (txoffset % 4 == 3 or ch == '\n') { + _iface->poke32(SR_ADDR(txpool, txoffset / 4), txword32); } - txoffset = (txoffset + 1) % (poolsize*4); - if (ch == '\n') - { + txoffset = (txoffset + 1) % (poolsize * 4); + if (ch == '\n') { // Tell the X300 to write the string - _iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX), txoffset); + _iface->poke32( + SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX), txoffset); } } - void write_uart(const std::string &buff) + void write_uart(const std::string& buff) { boost::mutex::scoped_lock lock(_write_mutex); - for(const char ch: buff) - { + for (const char ch : buff) { this->putchar(ch); } } @@ -65,60 +63,57 @@ struct x300_uart_iface : uart_iface if (rxoffset == _last_device_rxoffset) return -1; - int ret = static_cast<int>(_rxcache[((rxoffset)/4) % poolsize] >> ((rxoffset%4)*8) & 0xFF); + int ret = static_cast<int>( + _rxcache[((rxoffset) / 4) % poolsize] >> ((rxoffset % 4) * 8) & 0xFF); rxoffset++; return ret; } void update_cache(void) { - uint32_t device_rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); + uint32_t device_rxoffset = + _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); uint32_t delta = device_rxoffset - rxoffset; - while (delta) - { - if (delta >= poolsize*4) - { + while (delta) { + if (delta >= poolsize * 4) { // all the data is new - reload the entire cache - for (uint32_t i = 0; i < poolsize; i++) - { + for (uint32_t i = 0; i < poolsize; i++) { _rxcache[i] = _iface->peek32(SR_ADDR(rxpool, i)); } // set the head to the same character as the current device // offset (tail) one loop earlier - rxoffset = device_rxoffset - (poolsize*4); + rxoffset = device_rxoffset - (poolsize * 4); // set the tail to the current device offset _last_device_rxoffset = device_rxoffset; // the string at the head is a partial, so skip it - for (int c = getchar(); c != '\n' and c != -1; c = getchar()) {} + for (int c = getchar(); c != '\n' and c != -1; c = getchar()) { + } // clear the partial string in the buffer, if any _rxbuff.clear(); - } - else if (rxoffset == _last_device_rxoffset) - { + } else if (rxoffset == _last_device_rxoffset) { // new data was added - refresh the portion of the cache that was updated - for (uint32_t i = (_last_device_rxoffset/4) % poolsize; - i != ((device_rxoffset/4)+1) % poolsize; - i = (i+1) % poolsize) - { + for (uint32_t i = (_last_device_rxoffset / 4) % poolsize; + i != ((device_rxoffset / 4) + 1) % poolsize; + i = (i + 1) % poolsize) { _rxcache[i] = _iface->peek32(SR_ADDR(rxpool, i)); } // set the tail to the current device offset _last_device_rxoffset = device_rxoffset; - } - else - { - // there is new data, but we aren't done with what we have - check back later + } else { + // there is new data, but we aren't done with what we have - check back + // later break; } // check again to see if anything changed while we were updating the cache - device_rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); + device_rxoffset = + _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)); delta = device_rxoffset - rxoffset; } } @@ -126,26 +121,22 @@ struct x300_uart_iface : uart_iface std::string read_uart(double timeout) { boost::mutex::scoped_lock lock(_read_mutex); - const auto exit_time = - std::chrono::steady_clock::now() - + std::chrono::microseconds(int64_t(timeout*1e6)); + const auto exit_time = std::chrono::steady_clock::now() + + std::chrono::microseconds(int64_t(timeout * 1e6)); std::string buff; - while (true) - { + while (true) { // Update cache this->update_cache(); // Get available characters - for (int ch = this->getchar(); ch != -1; ch = this->getchar()) - { + for (int ch = this->getchar(); ch != -1; ch = this->getchar()) { // store character to buffer _rxbuff.append(1, ch); // newline found - return string - if (ch == '\n') - { + if (ch == '\n') { buff.swap(_rxbuff); return buff; } diff --git a/host/lib/usrp/x300/x300_image_loader.cpp b/host/lib/usrp/x300/x300_image_loader.cpp index 4e2c9e580..5cb1f1b85 100644 --- a/host/lib/usrp/x300/x300_image_loader.cpp +++ b/host/lib/usrp/x300/x300_image_loader.cpp @@ -5,28 +5,25 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include <fstream> -#include <vector> - -#include <boost/algorithm/string.hpp> -#include <boost/filesystem.hpp> -#include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/xml_parser.hpp> - +#include "cdecode.h" +#include "x300_fw_common.h" +#include "x300_impl.hpp" #include <uhd/config.hpp> #include <uhd/device.hpp> -#include <uhd/image_loader.hpp> #include <uhd/exception.hpp> -#include <uhd/transport/udp_simple.hpp> +#include <uhd/image_loader.hpp> #include <uhd/transport/nirio/niusrprio_session.h> #include <uhd/transport/nirio/status.h> +#include <uhd/transport/udp_simple.hpp> #include <uhd/utils/byteswap.hpp> #include <uhd/utils/paths.hpp> #include <uhd/utils/static.hpp> - -#include "x300_impl.hpp" -#include "x300_fw_common.h" -#include "cdecode.h" +#include <boost/algorithm/string.hpp> +#include <boost/filesystem.hpp> +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/xml_parser.hpp> +#include <fstream> +#include <vector> namespace fs = boost::filesystem; @@ -50,65 +47,81 @@ using namespace uhd::transport; /* * Bitstream header pattern */ -static const uint8_t X300_FPGA_BIT_HEADER[] = -{ - 0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, - 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00 -}; +static const uint8_t X300_FPGA_BIT_HEADER[] = {0x00, + 0x09, + 0x0f, + 0xf0, + 0x0f, + 0xf0, + 0x0f, + 0xf0, + 0x0f, + 0xf0, + 0x00, + 0x00, + 0x01, + 0x61, + 0x00}; /* * Packet structure */ -typedef struct { +typedef struct +{ uint32_t flags; uint32_t sector; uint32_t index; uint32_t size; union { - uint8_t data8[X300_PACKET_SIZE_BYTES]; - uint16_t data16[X300_PACKET_SIZE_BYTES/2]; + uint8_t data8[X300_PACKET_SIZE_BYTES]; + uint16_t data16[X300_PACKET_SIZE_BYTES / 2]; }; } x300_fpga_update_data_t; /* * X-Series burn session */ -typedef struct { - bool found; - bool ethernet; - bool configure; // Reload FPGA after burning to flash (Ethernet only) - bool verify; // Device will verify the download along the way (Ethernet only) - bool download; // Host will read the FPGA image on the device to a file - bool lvbitx; - uhd::device_addr_t dev_addr; - std::string ip_addr; - std::string fpga_type; - std::string resource; - std::string filepath; - std::string outpath; - std::string rpc_port; - udp_simple::sptr write_xport; - udp_simple::sptr read_xport; - size_t size; - uint8_t data_in[udp_simple::mtu]; - std::vector<char> bitstream; // .bin image extracted from .lvbitx file +typedef struct +{ + bool found; + bool ethernet; + bool configure; // Reload FPGA after burning to flash (Ethernet only) + bool verify; // Device will verify the download along the way (Ethernet only) + bool download; // Host will read the FPGA image on the device to a file + bool lvbitx; + uhd::device_addr_t dev_addr; + std::string ip_addr; + std::string fpga_type; + std::string resource; + std::string filepath; + std::string outpath; + std::string rpc_port; + udp_simple::sptr write_xport; + udp_simple::sptr read_xport; + size_t size; + uint8_t data_in[udp_simple::mtu]; + std::vector<char> bitstream; // .bin image extracted from .lvbitx file } x300_session_t; /* * Extract the .bin image from the given LVBITX file. */ -static void extract_from_lvbitx(x300_session_t &session){ - boost::property_tree::ptree pt; - boost::property_tree::xml_parser::read_xml(session.filepath.c_str(), pt, - boost::property_tree::xml_parser::no_comments | - boost::property_tree::xml_parser::trim_whitespace); +static void extract_from_lvbitx(x300_session_t& session) +{ + boost::property_tree::ptree pt; + boost::property_tree::xml_parser::read_xml(session.filepath.c_str(), + pt, + boost::property_tree::xml_parser::no_comments + | boost::property_tree::xml_parser::trim_whitespace); const std::string encoded_bitstream(pt.get<std::string>("Bitfile.Bitstream")); std::vector<char> decoded_bitstream(encoded_bitstream.size()); base64_decodestate decode_state; base64_init_decodestate(&decode_state); const size_t decoded_size = base64_decode_block(encoded_bitstream.c_str(), - encoded_bitstream.size(), &decoded_bitstream.front(), &decode_state); + encoded_bitstream.size(), + &decoded_bitstream.front(), + &decode_state); decoded_bitstream.resize(decoded_size); session.bitstream.swap(decoded_bitstream); @@ -118,118 +131,122 @@ static void extract_from_lvbitx(x300_session_t &session){ /* * Validate X300 image and extract if LVBITX. */ -static void x300_validate_image(x300_session_t &session){ - if(not fs::exists(session.filepath)){ - throw uhd::runtime_error(str(boost::format("Could not find image at path \"%s\".") - % session.filepath)); +static void x300_validate_image(x300_session_t& session) +{ + if (not fs::exists(session.filepath)) { + throw uhd::runtime_error(str( + boost::format("Could not find image at path \"%s\".") % session.filepath)); } std::string extension = fs::extension(session.filepath); - session.lvbitx = (extension == ".lvbitx"); + session.lvbitx = (extension == ".lvbitx"); - if(session.lvbitx){ + if (session.lvbitx) { extract_from_lvbitx(session); - if(session.size > X300_FPGA_BIN_SIZE_BYTES){ - throw uhd::runtime_error(str(boost::format("The specified FPGA image is too large: %d vs. %d") - % session.size % X300_FPGA_BIN_SIZE_BYTES)); + if (session.size > X300_FPGA_BIN_SIZE_BYTES) { + throw uhd::runtime_error( + str(boost::format("The specified FPGA image is too large: %d vs. %d") + % session.size % X300_FPGA_BIN_SIZE_BYTES)); } /* * PCIe burning just takes a filepath, even for a .lvbitx file, * so just extract it to validate the size. */ - if(!session.ethernet) session.bitstream.clear(); - } - else if(extension == ".bin" or extension == ".bit"){ + if (!session.ethernet) + session.bitstream.clear(); + } else if (extension == ".bin" or extension == ".bit") { uint32_t max_size = (extension == ".bin") ? X300_FPGA_BIN_SIZE_BYTES - : X300_FPGA_BIT_SIZE_BYTES; + : X300_FPGA_BIT_SIZE_BYTES; session.size = fs::file_size(session.filepath); - if(session.size > max_size){ - throw uhd::runtime_error(str(boost::format("The specified FPGA image is too large: %d vs. %d") - % session.size % max_size)); + if (session.size > max_size) { + throw uhd::runtime_error( + str(boost::format("The specified FPGA image is too large: %d vs. %d") + % session.size % max_size)); return; } - } - else{ - throw uhd::runtime_error(str(boost::format("Invalid extension \"%s\". Extension must be .bin, .bit, or .lvbitx.") - % extension)); + } else { + throw uhd::runtime_error( + str(boost::format( + "Invalid extension \"%s\". Extension must be .bin, .bit, or .lvbitx.") + % extension)); } } -static void x300_setup_session(x300_session_t &session, - const device_addr_t &args, - const std::string &filepath, - const std::string &outpath){ +static void x300_setup_session(x300_session_t& session, + const device_addr_t& args, + const std::string& filepath, + const std::string& outpath) +{ device_addrs_t devs = x300_find(args); - if(devs.size() == 0){ + if (devs.size() == 0) { session.found = false; return; - } - else if(devs.size() > 1){ - std::string err_msg = "Could not resolve given args to a single X-Series device.\n" - "Applicable devices:\n"; - - for(const uhd::device_addr_t &dev: devs){ - std::string identifier = dev.has_key("addr") ? "addr" - : "resource"; - - err_msg += str(boost::format(" * %s (%s=%s)\n") - % dev.get("product", "X3XX") - % identifier - % dev.get(identifier)); + } else if (devs.size() > 1) { + std::string err_msg = + "Could not resolve given args to a single X-Series device.\n" + "Applicable devices:\n"; + + for (const uhd::device_addr_t& dev : devs) { + std::string identifier = dev.has_key("addr") ? "addr" : "resource"; + + err_msg += str(boost::format(" * %s (%s=%s)\n") % dev.get("product", "X3XX") + % identifier % dev.get(identifier)); } - err_msg += "\nSpecify one of these devices with the given args to load an image onto it."; + err_msg += "\nSpecify one of these devices with the given args to load an image " + "onto it."; throw uhd::runtime_error(err_msg); } - session.found = true; + session.found = true; session.dev_addr = devs[0]; session.ethernet = session.dev_addr.has_key("addr"); - if(session.ethernet){ - session.ip_addr = session.dev_addr["addr"]; - session.configure = args.has_key("configure"); - session.write_xport = udp_simple::make_connected(session.ip_addr, - BOOST_STRINGIZE(X300_FPGA_PROG_UDP_PORT)); - session.read_xport = udp_simple::make_connected(session.ip_addr, - BOOST_STRINGIZE(X300_FPGA_READ_UDP_PORT)); - session.verify = args.has_key("verify"); + if (session.ethernet) { + session.ip_addr = session.dev_addr["addr"]; + session.configure = args.has_key("configure"); + session.write_xport = udp_simple::make_connected( + session.ip_addr, BOOST_STRINGIZE(X300_FPGA_PROG_UDP_PORT)); + session.read_xport = udp_simple::make_connected( + session.ip_addr, BOOST_STRINGIZE(X300_FPGA_READ_UDP_PORT)); + session.verify = args.has_key("verify"); session.download = args.has_key("download"); - } - else{ + } else { session.resource = session.dev_addr["resource"]; session.rpc_port = args.get("rpc-port", "5444"); } /* - * The user can specify an FPGA type (1G, HGS, XGS), rather than a filename. If the user - * does not specify one, this will default to the type currently on the device. If this - * cannot be determined, then the user is forced to specify a filename. + * The user can specify an FPGA type (1G, HGS, XGS), rather than a filename. If the + * user does not specify one, this will default to the type currently on the device. + * If this cannot be determined, then the user is forced to specify a filename. */ session.fpga_type = args.get("fpga", session.dev_addr.get("fpga", "")); - if(filepath == ""){ - if(!session.dev_addr.has_key("product") or session.fpga_type == ""){ - throw uhd::runtime_error("Found a device but could not auto-generate an image filename."); - } - else session.filepath = find_image_path(str(boost::format("usrp_%s_fpga_%s.bit") - % (to_lower_copy(session.dev_addr["product"])) - % session.fpga_type)); - } - else session.filepath = filepath; + if (filepath == "") { + if (!session.dev_addr.has_key("product") or session.fpga_type == "") { + throw uhd::runtime_error( + "Found a device but could not auto-generate an image filename."); + } else + session.filepath = find_image_path( + str(boost::format("usrp_%s_fpga_%s.bit") + % (to_lower_copy(session.dev_addr["product"])) % session.fpga_type)); + } else + session.filepath = filepath; /* * The user can specify an output image path, or UHD will use the * system temporary path by default */ - if(outpath == ""){ - if(!session.dev_addr.has_key("product") or session.fpga_type == ""){ - throw uhd::runtime_error("Found a device but could not auto-generate an image filename."); + if (outpath == "") { + if (!session.dev_addr.has_key("product") or session.fpga_type == "") { + throw uhd::runtime_error( + "Found a device but could not auto-generate an image filename."); } - std::string filename = str(boost::format("usrp_%s_fpga_%s") - % (to_lower_copy(session.dev_addr["product"])) - % session.fpga_type); + std::string filename = + str(boost::format("usrp_%s_fpga_%s") + % (to_lower_copy(session.dev_addr["product"])) % session.fpga_type); session.outpath = get_tmp_path() + "/" + filename; } else { @@ -244,172 +261,180 @@ static void x300_setup_session(x300_session_t &session, * Ethernet communication functions */ static UHD_INLINE size_t x300_send_and_recv(udp_simple::sptr xport, - uint32_t pkt_code, - x300_fpga_update_data_t *pkt_out, - uint8_t* data){ + uint32_t pkt_code, + x300_fpga_update_data_t* pkt_out, + uint8_t* data) +{ pkt_out->flags = uhd::htonx<uint32_t>(pkt_code); xport->send(boost::asio::buffer(pkt_out, sizeof(*pkt_out))); return xport->recv(boost::asio::buffer(data, udp_simple::mtu), UDP_TIMEOUT); } -static UHD_INLINE bool x300_recv_ok(const x300_fpga_update_data_t *pkt_in, - size_t len){ - return (len > 0 and - ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR) != X300_FPGA_PROG_FLAGS_ERROR)); +static UHD_INLINE bool x300_recv_ok(const x300_fpga_update_data_t* pkt_in, size_t len) +{ + return (len > 0 + and ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR) + != X300_FPGA_PROG_FLAGS_ERROR)); } // Image data needs to be bitswapped -static UHD_INLINE void x300_bitswap(uint8_t *num){ +static UHD_INLINE void x300_bitswap(uint8_t* num) +{ *num = ((*num & 0xF0) >> 4) | ((*num & 0x0F) << 4); *num = ((*num & 0xCC) >> 2) | ((*num & 0x33) << 2); *num = ((*num & 0xAA) >> 1) | ((*num & 0x55) << 1); } -static void x300_ethernet_load(x300_session_t &session){ - +static void x300_ethernet_load(x300_session_t& session) +{ // UDP receive buffer x300_fpga_update_data_t pkt_out; - const x300_fpga_update_data_t *pkt_in = reinterpret_cast<const x300_fpga_update_data_t*>(session.data_in); + const x300_fpga_update_data_t* pkt_in = + reinterpret_cast<const x300_fpga_update_data_t*>(session.data_in); // Initialize write session uint32_t flags = X300_FPGA_PROG_FLAGS_ACK | X300_FPGA_PROG_FLAGS_INIT; - size_t len = x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); - if(x300_recv_ok(pkt_in, len)){ + size_t len = + x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); + if (x300_recv_ok(pkt_in, len)) { std::cout << "-- Initializing FPGA loading..." << std::flush; - } - else if(len == 0){ + } else if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else{ + } else { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error during initialization."); } std::cout << "successful." << std::endl; - if(session.verify){ - std::cout << "-- NOTE: Device is verifying the image it is receiving, increasing the loading time." << std::endl; + if (session.verify) { + std::cout << "-- NOTE: Device is verifying the image it is receiving, increasing " + "the loading time." + << std::endl; } size_t current_pos = 0; - size_t sectors = (session.size / X300_FLASH_SECTOR_SIZE); + size_t sectors = (session.size / X300_FLASH_SECTOR_SIZE); std::ifstream image(session.filepath.c_str(), std::ios::binary); // Each sector - for(size_t i = 0; i < session.size; i += X300_FLASH_SECTOR_SIZE){ - + for (size_t i = 0; i < session.size; i += X300_FLASH_SECTOR_SIZE) { // Print progress percentage at beginning of each sector std::cout << boost::format("\r-- Loading %s FPGA image: %d%% (%d/%d sectors)") - % session.fpga_type - % (int(double(i) / double(session.size) * 100.0)) - % (i / X300_FLASH_SECTOR_SIZE) - % sectors - << std::flush; + % session.fpga_type + % (int(double(i) / double(session.size) * 100.0)) + % (i / X300_FLASH_SECTOR_SIZE) % sectors + << std::flush; // Each packet - for(size_t j = i; (j < session.size and j < (i+X300_FLASH_SECTOR_SIZE)); j += X300_PACKET_SIZE_BYTES){ + for (size_t j = i; (j < session.size and j < (i + X300_FLASH_SECTOR_SIZE)); + j += X300_PACKET_SIZE_BYTES) { flags = X300_FPGA_PROG_FLAGS_ACK; - if(j == i) flags |= X300_FPGA_PROG_FLAGS_ERASE; // Erase at beginning of sector - if(session.verify) flags |= X300_FPGA_PROG_FLAGS_VERIFY; + if (j == i) + flags |= X300_FPGA_PROG_FLAGS_ERASE; // Erase at beginning of sector + if (session.verify) + flags |= X300_FPGA_PROG_FLAGS_VERIFY; // Set burn location - pkt_out.sector = htonx<uint32_t>(X300_FPGA_SECTOR_START + (i/X300_FLASH_SECTOR_SIZE)); - pkt_out.index = htonx<uint32_t>((j % X300_FLASH_SECTOR_SIZE) / 2); - pkt_out.size = htonx<uint32_t>(X300_PACKET_SIZE_BYTES / 2); + pkt_out.sector = + htonx<uint32_t>(X300_FPGA_SECTOR_START + (i / X300_FLASH_SECTOR_SIZE)); + pkt_out.index = htonx<uint32_t>((j % X300_FLASH_SECTOR_SIZE) / 2); + pkt_out.size = htonx<uint32_t>(X300_PACKET_SIZE_BYTES / 2); // Read next piece of image memset(pkt_out.data8, 0, X300_PACKET_SIZE_BYTES); - if(session.lvbitx){ - memcpy(pkt_out.data8, &session.bitstream[current_pos], X300_PACKET_SIZE_BYTES); + if (session.lvbitx) { + memcpy(pkt_out.data8, + &session.bitstream[current_pos], + X300_PACKET_SIZE_BYTES); current_pos += X300_PACKET_SIZE_BYTES; - } - else{ + } else { image.read((char*)pkt_out.data8, X300_PACKET_SIZE_BYTES); } // Data must be bitswapped and byteswapped - for(size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++){ + for (size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++) { x300_bitswap(&pkt_out.data8[k]); } - for(size_t k = 0; k < (X300_PACKET_SIZE_BYTES/2); k++){ + for (size_t k = 0; k < (X300_PACKET_SIZE_BYTES / 2); k++) { pkt_out.data16[k] = htonx<uint16_t>(pkt_out.data16[k]); } - len = x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); - if(len == 0){ - if(!session.lvbitx) image.close(); + len = + x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); + if (len == 0) { + if (!session.lvbitx) + image.close(); throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)){ - if(!session.lvbitx) image.close(); + } else if ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)) { + if (!session.lvbitx) + image.close(); throw uhd::runtime_error("Device reported an error."); } } } - if(!session.lvbitx){ + if (!session.lvbitx) { image.close(); } std::cout << boost::format("\r-- Loading %s FPGA image: 100%% (%d/%d sectors)") - % session.fpga_type - % sectors - % sectors - << std::endl; + % session.fpga_type % sectors % sectors + << std::endl; // Cleanup - if(!session.lvbitx) image.close(); - flags = (X300_FPGA_PROG_FLAGS_CLEANUP | X300_FPGA_PROG_FLAGS_ACK); + if (!session.lvbitx) + image.close(); + flags = (X300_FPGA_PROG_FLAGS_CLEANUP | X300_FPGA_PROG_FLAGS_ACK); pkt_out.sector = pkt_out.index = pkt_out.size = 0; memset(pkt_out.data8, 0, X300_PACKET_SIZE_BYTES); std::cout << "-- Finalizing image load..." << std::flush; len = x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); - if(len == 0){ + if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error during cleanup."); - } - else std::cout << "successful." << std::endl; + } else + std::cout << "successful." << std::endl; // Save new FPGA image (if option set) - if(session.configure){ + if (session.configure) { flags = (X300_FPGA_PROG_CONFIGURE | X300_FPGA_PROG_FLAGS_ACK); x300_send_and_recv(session.write_xport, flags, &pkt_out, session.data_in); std::cout << "-- Saving image onto device..." << std::flush; - if(len == 0){ + if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_PROG_FLAGS_ERROR)) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error while saving the image."); - } - else std::cout << "successful." << std::endl; + } else + std::cout << "successful." << std::endl; } - std::cout << str(boost::format("Power-cycle the USRP %s to use the new image.") % session.dev_addr.get("product", "")) << std::endl; + std::cout << str(boost::format("Power-cycle the USRP %s to use the new image.") + % session.dev_addr.get("product", "")) + << std::endl; } -static void x300_ethernet_read(x300_session_t &session){ - +static void x300_ethernet_read(x300_session_t& session) +{ // UDP receive buffer x300_fpga_update_data_t pkt_out; memset(pkt_out.data8, 0, X300_PACKET_SIZE_BYTES); - x300_fpga_update_data_t *pkt_in = reinterpret_cast<x300_fpga_update_data_t*>(session.data_in); + x300_fpga_update_data_t* pkt_in = + reinterpret_cast<x300_fpga_update_data_t*>(session.data_in); // Initialize read session uint32_t flags = X300_FPGA_READ_FLAGS_ACK | X300_FPGA_READ_FLAGS_INIT; size_t len = x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); - if(x300_recv_ok(pkt_in, len)){ + if (x300_recv_ok(pkt_in, len)) { std::cout << "-- Initializing FPGA reading..." << std::flush; - } - else if(len == 0){ + } else if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else{ + } else { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error during initialization."); } @@ -426,83 +451,79 @@ static void x300_ethernet_read(x300_session_t &session){ pkt_out.size = htonx<uint32_t>(X300_PACKET_SIZE_BYTES / 2); len = x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); - if(len == 0){ + if (len == 0) { throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)) { throw uhd::runtime_error("Device reported an error."); } // Data must be bitswapped and byteswapped - for(size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++){ + for (size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++) { x300_bitswap(&pkt_in->data8[k]); } - for(size_t k = 0; k < (X300_PACKET_SIZE_BYTES/2); k++){ + for (size_t k = 0; k < (X300_PACKET_SIZE_BYTES / 2); k++) { pkt_in->data16[k] = htonx<uint16_t>(pkt_in->data16[k]); } // Assume the largest size first size_t image_size = X300_FPGA_BIT_SIZE_BYTES; - size_t sectors = (image_size / X300_FLASH_SECTOR_SIZE); + size_t sectors = (image_size / X300_FLASH_SECTOR_SIZE); std::string extension(".bit"); // Check for the beginning header sequence to determine // the total amount of data (.bit vs .bin) on the flash // The .bit file format includes header information not part of a .bin - for (size_t i = 0; i < sizeof(X300_FPGA_BIT_HEADER); i++) - { - if (pkt_in->data8[i] != X300_FPGA_BIT_HEADER[i]) - { - std::cout << "-- No *.bit header detected, FPGA image is a raw stream (*.bin)!" << std::endl; + for (size_t i = 0; i < sizeof(X300_FPGA_BIT_HEADER); i++) { + if (pkt_in->data8[i] != X300_FPGA_BIT_HEADER[i]) { + std::cout + << "-- No *.bit header detected, FPGA image is a raw stream (*.bin)!" + << std::endl; image_size = X300_FPGA_BIN_SIZE_BYTES; - sectors = (image_size / X300_FLASH_SECTOR_SIZE); - extension = std::string(".bin"); + sectors = (image_size / X300_FLASH_SECTOR_SIZE); + extension = std::string(".bin"); break; } } session.outpath += extension; std::ofstream image(session.outpath.c_str(), std::ios::binary); - std::cout << boost::format("-- Output FPGA file: %s\n") - % session.outpath; + std::cout << boost::format("-- Output FPGA file: %s\n") % session.outpath; // Write the first packet image.write((char*)pkt_in->data8, X300_PACKET_SIZE_BYTES); // Each sector size_t pkt_count = X300_PACKET_SIZE_BYTES; - for(size_t i = 0; i < image_size; i += X300_FLASH_SECTOR_SIZE){ - + for (size_t i = 0; i < image_size; i += X300_FLASH_SECTOR_SIZE) { // Once we determine the image size, print the progress percentage std::cout << boost::format("\r-- Reading %s FPGA image: %d%% (%d/%d sectors)") - % session.fpga_type - % (int(double(i) / double(image_size) * 100.0)) - % (i / X300_FLASH_SECTOR_SIZE) - % sectors + % session.fpga_type + % (int(double(i) / double(image_size) * 100.0)) + % (i / X300_FLASH_SECTOR_SIZE) % sectors << std::flush; // Each packet - while (pkt_count < image_size and pkt_count < (i + X300_FLASH_SECTOR_SIZE)) - { + while (pkt_count < image_size and pkt_count < (i + X300_FLASH_SECTOR_SIZE)) { // Set burn location - pkt_out.sector = htonx<uint32_t>(X300_FPGA_SECTOR_START + (i/X300_FLASH_SECTOR_SIZE)); - pkt_out.index = htonx<uint32_t>((pkt_count % X300_FLASH_SECTOR_SIZE) / 2); + pkt_out.sector = + htonx<uint32_t>(X300_FPGA_SECTOR_START + (i / X300_FLASH_SECTOR_SIZE)); + pkt_out.index = htonx<uint32_t>((pkt_count % X300_FLASH_SECTOR_SIZE) / 2); - len = x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); - if(len == 0){ + len = + x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); + if (len == 0) { image.close(); throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)) { image.close(); throw uhd::runtime_error("Device reported an error."); } // Data must be bitswapped and byteswapped - for(size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++){ + for (size_t k = 0; k < X300_PACKET_SIZE_BYTES; k++) { x300_bitswap(&pkt_in->data8[k]); } - for(size_t k = 0; k < (X300_PACKET_SIZE_BYTES/2); k++){ + for (size_t k = 0; k < (X300_PACKET_SIZE_BYTES / 2); k++) { pkt_in->data16[k] = htonx<uint16_t>(pkt_in->data16[k]); } @@ -510,8 +531,7 @@ static void x300_ethernet_read(x300_session_t &session){ // If this is the last packet, get rid of the extra zero padding // due to packet size size_t nbytes = X300_PACKET_SIZE_BYTES; - if (pkt_count > (image_size - X300_PACKET_SIZE_BYTES)) - { + if (pkt_count > (image_size - X300_PACKET_SIZE_BYTES)) { nbytes = (image_size - pkt_count); } @@ -526,85 +546,94 @@ static void x300_ethernet_read(x300_session_t &session){ } std::cout << boost::format("\r-- Reading %s FPGA image: 100%% (%d/%d sectors)") - % session.fpga_type - % sectors - % sectors + % session.fpga_type % sectors % sectors << std::endl; // Cleanup image.close(); - flags = (X300_FPGA_READ_FLAGS_CLEANUP | X300_FPGA_READ_FLAGS_ACK); + flags = (X300_FPGA_READ_FLAGS_CLEANUP | X300_FPGA_READ_FLAGS_ACK); pkt_out.sector = pkt_out.index = pkt_out.size = 0; memset(pkt_out.data8, 0, X300_PACKET_SIZE_BYTES); std::cout << "-- Finalizing image read for verification..." << std::flush; len = x300_send_and_recv(session.read_xport, flags, &pkt_out, session.data_in); - if(len == 0){ + if (len == 0) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Timed out waiting for reply from device."); - } - else if((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)){ + } else if ((ntohl(pkt_in->flags) & X300_FPGA_READ_FLAGS_ERROR)) { std::cout << "failed." << std::endl; throw uhd::runtime_error("Device reported an error during cleanup."); - } - else std::cout << "successful image read." << std::endl; + } else + std::cout << "successful image read." << std::endl; } -static void x300_pcie_load(x300_session_t &session){ - - std::cout << boost::format("\r-- Loading %s FPGA image (this will take 5-10 minutes)...") - % session.fpga_type - << std::flush; +static void x300_pcie_load(x300_session_t& session) +{ + std::cout << boost::format( + "\r-- Loading %s FPGA image (this will take 5-10 minutes)...") + % session.fpga_type + << std::flush; nirio_status status = NiRio_Status_Success; niusrprio::niusrprio_session fpga_session(session.resource, session.rpc_port); - nirio_status_chain(fpga_session.download_bitstream_to_flash(session.filepath), status); + nirio_status_chain( + fpga_session.download_bitstream_to_flash(session.filepath), status); - if(nirio_status_fatal(status)){ + if (nirio_status_fatal(status)) { std::cout << "failed." << std::endl; - niusrprio::nirio_status_to_exception(status, "NI-RIO reported the following error:"); - } - else std::cout << "successful." << std::endl; - std::cout << str(boost::format("Power-cycle the USRP %s to use the new image.") % session.dev_addr.get("product", "")) << std::endl; + niusrprio::nirio_status_to_exception( + status, "NI-RIO reported the following error:"); + } else + std::cout << "successful." << std::endl; + std::cout << str(boost::format("Power-cycle the USRP %s to use the new image.") + % session.dev_addr.get("product", "")) + << std::endl; } -static bool x300_image_loader(const image_loader::image_loader_args_t &image_loader_args){ +static bool x300_image_loader(const image_loader::image_loader_args_t& image_loader_args) +{ // See if any X3x0 with the given args is found device_addrs_t devs = x300_find(image_loader_args.args); - if (devs.size() == 0) return false; + if (devs.size() == 0) + return false; x300_session_t session; x300_setup_session(session, - image_loader_args.args, - image_loader_args.fpga_path, - image_loader_args.out_path); + image_loader_args.args, + image_loader_args.fpga_path, + image_loader_args.out_path); - if(!session.found) return false; + if (!session.found) + return false; std::cout << boost::format("Unit: USRP %s (%s, %s)\nFPGA Image: %s\n") - % session.dev_addr["product"] - % session.dev_addr["serial"] - % session.dev_addr[session.ethernet ? "addr" : "resource"] - % session.filepath; + % session.dev_addr["product"] % session.dev_addr["serial"] + % session.dev_addr[session.ethernet ? "addr" : "resource"] + % session.filepath; // Download the FPGA image to a file - if(image_loader_args.download) { + if (image_loader_args.download) { std::cout << "Attempting to download the FPGA image ..." << std::endl; x300_ethernet_read(session); } - if (not image_loader_args.load_fpga) return true; + if (not image_loader_args.load_fpga) + return true; - if (session.ethernet) x300_ethernet_load(session); - else x300_pcie_load(session); + if (session.ethernet) + x300_ethernet_load(session); + else + x300_pcie_load(session); return true; } -UHD_STATIC_BLOCK(register_x300_image_loader){ - std::string recovery_instructions = "Aborting. Your USRP X-Series device will likely be unusable. Visit\n" - "http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_load_fpga_imgs_jtag\n" - "for details on restoring your device."; +UHD_STATIC_BLOCK(register_x300_image_loader) +{ + std::string recovery_instructions = + "Aborting. Your USRP X-Series device will likely be unusable. Visit\n" + "http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_load_fpga_imgs_jtag\n" + "for details on restoring your device."; image_loader::register_image_loader("x300", x300_image_loader, recovery_instructions); } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 7d2ce6b28..ed6678761 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -7,29 +7,28 @@ #include "x300_impl.hpp" #include "x300_lvbitx.hpp" -#include "x310_lvbitx.hpp" #include "x300_mb_eeprom_iface.hpp" -#include <uhdlib/usrp/common/apply_corrections.hpp> -#include <uhd/utils/static.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/paths.hpp> -#include <uhd/utils/safe_call.hpp> -#include <uhd/usrp/subdev_spec.hpp> +#include "x310_lvbitx.hpp" #include <uhd/transport/if_addrs.hpp> -#include <uhd/transport/udp_zero_copy.hpp> +#include <uhd/transport/nirio/niusrprio_session.h> +#include <uhd/transport/nirio_zero_copy.hpp> #include <uhd/transport/udp_constants.hpp> +#include <uhd/transport/udp_zero_copy.hpp> #include <uhd/transport/zero_copy_recv_offload.hpp> -#include <uhd/transport/nirio_zero_copy.hpp> -#include <uhd/transport/nirio/niusrprio_session.h> -#include <uhd/utils/platform.hpp> #include <uhd/types/sid.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/utils/log.hpp> #include <uhd/utils/math.hpp> - +#include <uhd/utils/paths.hpp> +#include <uhd/utils/platform.hpp> +#include <uhd/utils/safe_call.hpp> +#include <uhd/utils/static.hpp> +#include <uhdlib/usrp/common/apply_corrections.hpp> #include <boost/algorithm/string.hpp> #include <boost/asio.hpp> #include <boost/make_shared.hpp> -#include <fstream> #include <chrono> +#include <fstream> #include <thread> using namespace uhd; @@ -45,27 +44,28 @@ namespace asio = boost::asio; /****************************************************************************** * Helpers *****************************************************************************/ -static std::string get_fpga_option(wb_iface::sptr zpu_ctrl) { - //Possible options: - //1G = {0:1G, 1:1G} w/ DRAM, HG = {0:1G, 1:10G} w/ DRAM, XG = {0:10G, 1:10G} w/ DRAM - //HA = {0:1G, 1:Aurora} w/ DRAM, XA = {0:10G, 1:Aurora} w/ DRAM +static std::string get_fpga_option(wb_iface::sptr zpu_ctrl) +{ + // Possible options: + // 1G = {0:1G, 1:1G} w/ DRAM, HG = {0:1G, 1:10G} w/ DRAM, XG = {0:10G, 1:10G} w/ + // DRAM HA = {0:1G, 1:Aurora} w/ DRAM, XA = {0:10G, 1:Aurora} w/ DRAM std::string option; uint32_t sfp0_type = zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_SFP0_TYPE)); uint32_t sfp1_type = zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_SFP1_TYPE)); - if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_1G_ETH) { + if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_1G_ETH) { option = "1G"; - } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_10G_ETH) { + } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_10G_ETH) { option = "HG"; - } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_10G_ETH) { + } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_10G_ETH) { option = "XG"; - } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_AURORA) { + } else if (sfp0_type == RB_SFP_1G_ETH and sfp1_type == RB_SFP_AURORA) { option = "HA"; - } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_AURORA) { + } else if (sfp0_type == RB_SFP_10G_ETH and sfp1_type == RB_SFP_AURORA) { option = "XA"; } else { - option = "HG"; //Default + option = "HG"; // Default } return option; } @@ -73,153 +73,150 @@ static std::string get_fpga_option(wb_iface::sptr zpu_ctrl) { namespace { - /*! Return the correct motherboard type for a given product ID - * - * Note: In previous versions, we had two different mappings for PCIe and - * Ethernet in case the PIDs would conflict, but they never did and it was - * thus consolidated into one. - */ - x300_impl::x300_mboard_t map_pid_to_mb_type(const uint32_t pid) - { - switch (pid) { - case X300_USRP_PCIE_SSID_ADC_33: - case X300_USRP_PCIE_SSID_ADC_18: - return x300_impl::USRP_X300_MB; - case X310_USRP_PCIE_SSID_ADC_33: - case X310_2940R_40MHz_PCIE_SSID_ADC_33: - case X310_2940R_120MHz_PCIE_SSID_ADC_33: - case X310_2942R_40MHz_PCIE_SSID_ADC_33: - case X310_2942R_120MHz_PCIE_SSID_ADC_33: - case X310_2943R_40MHz_PCIE_SSID_ADC_33: - case X310_2943R_120MHz_PCIE_SSID_ADC_33: - case X310_2944R_40MHz_PCIE_SSID_ADC_33: - case X310_2950R_40MHz_PCIE_SSID_ADC_33: - case X310_2950R_120MHz_PCIE_SSID_ADC_33: - case X310_2952R_40MHz_PCIE_SSID_ADC_33: - case X310_2952R_120MHz_PCIE_SSID_ADC_33: - case X310_2953R_40MHz_PCIE_SSID_ADC_33: - case X310_2953R_120MHz_PCIE_SSID_ADC_33: - case X310_2954R_40MHz_PCIE_SSID_ADC_33: - case X310_USRP_PCIE_SSID_ADC_18: - case X310_2940R_40MHz_PCIE_SSID_ADC_18: - case X310_2940R_120MHz_PCIE_SSID_ADC_18: - case X310_2942R_40MHz_PCIE_SSID_ADC_18: - case X310_2942R_120MHz_PCIE_SSID_ADC_18: - case X310_2943R_40MHz_PCIE_SSID_ADC_18: - case X310_2943R_120MHz_PCIE_SSID_ADC_18: - case X310_2944R_40MHz_PCIE_SSID_ADC_18: - case X310_2945R_PCIE_SSID_ADC_18: - case X310_2950R_40MHz_PCIE_SSID_ADC_18: - case X310_2950R_120MHz_PCIE_SSID_ADC_18: - case X310_2952R_40MHz_PCIE_SSID_ADC_18: - case X310_2952R_120MHz_PCIE_SSID_ADC_18: - case X310_2953R_40MHz_PCIE_SSID_ADC_18: - case X310_2953R_120MHz_PCIE_SSID_ADC_18: - case X310_2954R_40MHz_PCIE_SSID_ADC_18: - case X310_2955R_PCIE_SSID_ADC_18: - return x300_impl::USRP_X310_MB; - case X310_2974_PCIE_SSID_ADC_18: - return x300_impl::USRP_X310_MB_NI_2974; - default: - return x300_impl::UNKNOWN; - } - UHD_THROW_INVALID_CODE_PATH(); +/*! Return the correct motherboard type for a given product ID + * + * Note: In previous versions, we had two different mappings for PCIe and + * Ethernet in case the PIDs would conflict, but they never did and it was + * thus consolidated into one. + */ +x300_impl::x300_mboard_t map_pid_to_mb_type(const uint32_t pid) +{ + switch (pid) { + case X300_USRP_PCIE_SSID_ADC_33: + case X300_USRP_PCIE_SSID_ADC_18: + return x300_impl::USRP_X300_MB; + case X310_USRP_PCIE_SSID_ADC_33: + case X310_2940R_40MHz_PCIE_SSID_ADC_33: + case X310_2940R_120MHz_PCIE_SSID_ADC_33: + case X310_2942R_40MHz_PCIE_SSID_ADC_33: + case X310_2942R_120MHz_PCIE_SSID_ADC_33: + case X310_2943R_40MHz_PCIE_SSID_ADC_33: + case X310_2943R_120MHz_PCIE_SSID_ADC_33: + case X310_2944R_40MHz_PCIE_SSID_ADC_33: + case X310_2950R_40MHz_PCIE_SSID_ADC_33: + case X310_2950R_120MHz_PCIE_SSID_ADC_33: + case X310_2952R_40MHz_PCIE_SSID_ADC_33: + case X310_2952R_120MHz_PCIE_SSID_ADC_33: + case X310_2953R_40MHz_PCIE_SSID_ADC_33: + case X310_2953R_120MHz_PCIE_SSID_ADC_33: + case X310_2954R_40MHz_PCIE_SSID_ADC_33: + case X310_USRP_PCIE_SSID_ADC_18: + case X310_2940R_40MHz_PCIE_SSID_ADC_18: + case X310_2940R_120MHz_PCIE_SSID_ADC_18: + case X310_2942R_40MHz_PCIE_SSID_ADC_18: + case X310_2942R_120MHz_PCIE_SSID_ADC_18: + case X310_2943R_40MHz_PCIE_SSID_ADC_18: + case X310_2943R_120MHz_PCIE_SSID_ADC_18: + case X310_2944R_40MHz_PCIE_SSID_ADC_18: + case X310_2945R_PCIE_SSID_ADC_18: + case X310_2950R_40MHz_PCIE_SSID_ADC_18: + case X310_2950R_120MHz_PCIE_SSID_ADC_18: + case X310_2952R_40MHz_PCIE_SSID_ADC_18: + case X310_2952R_120MHz_PCIE_SSID_ADC_18: + case X310_2953R_40MHz_PCIE_SSID_ADC_18: + case X310_2953R_120MHz_PCIE_SSID_ADC_18: + case X310_2954R_40MHz_PCIE_SSID_ADC_18: + case X310_2955R_PCIE_SSID_ADC_18: + return x300_impl::USRP_X310_MB; + case X310_2974_PCIE_SSID_ADC_18: + return x300_impl::USRP_X310_MB_NI_2974; + default: + return x300_impl::UNKNOWN; } + UHD_THROW_INVALID_CODE_PATH(); +} - /*! Map the motherboard type to a product name - */ - std::string map_mb_type_to_product_name( - const x300_impl::x300_mboard_t mb_type, - const std::string& default_name="") - { - switch (mb_type) { - case x300_impl::USRP_X300_MB: - return "X300"; - case x300_impl::USRP_X310_MB: - return "X310"; - case x300_impl::USRP_X310_MB_NI_2974: - return "NI-2974"; - default: - return default_name; - } +/*! Map the motherboard type to a product name + */ +std::string map_mb_type_to_product_name( + const x300_impl::x300_mboard_t mb_type, const std::string& default_name = "") +{ + switch (mb_type) { + case x300_impl::USRP_X300_MB: + return "X300"; + case x300_impl::USRP_X310_MB: + return "X310"; + case x300_impl::USRP_X310_MB_NI_2974: + return "NI-2974"; + default: + return default_name; } +} -} /* namespace anon */ +} // namespace /*********************************************************************** * Discovery over the udp and pcie transport **********************************************************************/ //@TODO: Refactor the find functions to collapse common code for ethernet and PCIe -static device_addrs_t x300_find_with_addr(const device_addr_t &hint) +static device_addrs_t x300_find_with_addr(const device_addr_t& hint) { - udp_simple::sptr comm = udp_simple::make_broadcast( - hint["addr"], BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)); + udp_simple::sptr comm = + udp_simple::make_broadcast(hint["addr"], BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)); - //load request struct + // load request struct x300_fw_comms_t request = x300_fw_comms_t(); - request.flags = uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK); - request.sequence = uhd::htonx<uint32_t>(std::rand()); + request.flags = uhd::htonx<uint32_t>(X300_FW_COMMS_FLAGS_ACK); + request.sequence = uhd::htonx<uint32_t>(std::rand()); - //send request + // send request comm->send(asio::buffer(&request, sizeof(request))); - //loop for replies until timeout + // loop for replies until timeout device_addrs_t addrs; - while (true) - { + while (true) { char buff[X300_FW_COMMS_MTU] = {}; - const size_t nbytes = comm->recv(asio::buffer(buff), 0.050); - if (nbytes == 0) break; - const x300_fw_comms_t *reply = (const x300_fw_comms_t *)buff; - if (request.flags != reply->flags) continue; - if (request.sequence != reply->sequence) continue; + const size_t nbytes = comm->recv(asio::buffer(buff), 0.050); + if (nbytes == 0) + break; + const x300_fw_comms_t* reply = (const x300_fw_comms_t*)buff; + if (request.flags != reply->flags) + continue; + if (request.sequence != reply->sequence) + continue; device_addr_t new_addr; new_addr["type"] = "x300"; new_addr["addr"] = comm->get_recv_addr(); - //Attempt to read the name from the EEPROM and perform filtering. - //This operation can throw due to compatibility mismatch. - try - { + // Attempt to read the name from the EEPROM and perform filtering. + // This operation can throw due to compatibility mismatch. + try { wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_enet( - udp_simple::make_connected(new_addr["addr"], - BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), + udp_simple::make_connected( + new_addr["addr"], BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), false /* Suppress timeout errors */ ); new_addr["fpga"] = get_fpga_option(zpu_ctrl); - i2c_core_100_wb32::sptr zpu_i2c = i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); - x300_mb_eeprom_iface::sptr eeprom_iface = x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); - const mboard_eeprom_t mb_eeprom = - x300_impl::get_mb_eeprom(eeprom_iface); - if (mb_eeprom.size() == 0 or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) - { + i2c_core_100_wb32::sptr zpu_i2c = + i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); + x300_mb_eeprom_iface::sptr eeprom_iface = + x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); + const mboard_eeprom_t mb_eeprom = x300_impl::get_mb_eeprom(eeprom_iface); + if (mb_eeprom.size() == 0 + or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) { // Skip device claimed by another process continue; } - new_addr["name"] = mb_eeprom["name"]; - new_addr["serial"] = mb_eeprom["serial"]; + new_addr["name"] = mb_eeprom["name"]; + new_addr["serial"] = mb_eeprom["serial"]; const std::string product_name = map_mb_type_to_product_name( x300_impl::get_mb_type_from_eeprom(mb_eeprom)); if (!product_name.empty()) { new_addr["product"] = product_name; } - } - catch(const std::exception &) - { - //set these values as empty string so the device may still be found - //and the filter's below can still operate on the discovered device - new_addr["name"] = ""; + } catch (const std::exception&) { + // set these values as empty string so the device may still be found + // and the filter's below can still operate on the discovered device + new_addr["name"] = ""; new_addr["serial"] = ""; } - //filter the discovered device below by matching optional keys - if ( - (not hint.has_key("name") or hint["name"] == new_addr["name"]) and - (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) and - (not hint.has_key("product") or hint["product"] == new_addr["product"]) - ){ + // filter the discovered device below by matching optional keys + if ((not hint.has_key("name") or hint["name"] == new_addr["name"]) + and (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) + and (not hint.has_key("product") or hint["product"] == new_addr["product"])) { addrs.push_back(new_addr); } } @@ -228,13 +225,13 @@ static device_addrs_t x300_find_with_addr(const device_addr_t &hint) } -//We need a zpu xport registry to ensure synchronization between the static finder method -//and the instances of the x300_impl class. -typedef uhd::dict< std::string, boost::weak_ptr<wb_iface> > pcie_zpu_iface_registry_t; +// We need a zpu xport registry to ensure synchronization between the static finder method +// and the instances of the x300_impl class. +typedef uhd::dict<std::string, boost::weak_ptr<wb_iface>> pcie_zpu_iface_registry_t; UHD_SINGLETON_FCN(pcie_zpu_iface_registry_t, get_pcie_zpu_iface_registry) static boost::mutex pcie_zpu_iface_registry_mutex; -static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_query) +static device_addrs_t x300_find_pcie(const device_addr_t& hint, bool explicit_query) { std::string rpc_port_name(std::to_string(NIUSRPRIO_DEFAULT_RPC_PORT)); if (hint.has_key("niusrpriorpc_port")) { @@ -244,12 +241,13 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu device_addrs_t addrs; niusrprio_session::device_info_vtr dev_info_vtr; nirio_status status = niusrprio_session::enumerate(rpc_port_name, dev_info_vtr); - if (explicit_query) nirio_status_to_exception(status, "x300_find_pcie: Error enumerating NI-RIO devices."); + if (explicit_query) + nirio_status_to_exception( + status, "x300_find_pcie: Error enumerating NI-RIO devices."); - for(niusrprio_session::device_info &dev_info: dev_info_vtr) - { + for (niusrprio_session::device_info& dev_info : dev_info_vtr) { device_addr_t new_addr; - new_addr["type"] = "x300"; + new_addr["type"] = "x300"; new_addr["resource"] = dev_info.resource_name; std::string resource_d(dev_info.resource_name); boost::to_upper(resource_d); @@ -262,157 +260,154 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu new_addr["product"] = product_name; } - niriok_proxy::sptr kernel_proxy = niriok_proxy::make_and_open(dev_info.interface_path); + 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. - //This operation can throw due to compatibility mismatch. - try - { - //This block could throw an exception if the user is switching to using UHD - //after LabVIEW FPGA. In that case, skip reading the name and serial and pick - //a default FPGA flavor. During make, a new image will be loaded and everything - //will be OK + // Attempt to read the name from the EEPROM and perform filtering. + // This operation can throw due to compatibility mismatch. + try { + // This block could throw an exception if the user is switching to using UHD + // after LabVIEW FPGA. In that case, skip reading the name and serial and pick + // a default FPGA flavor. During make, a new image will be loaded and + // everything will be OK wb_iface::sptr zpu_ctrl; - //Hold on to the registry mutex as long as zpu_ctrl is alive - //to prevent any use by different threads while enumerating + // Hold on to the registry mutex as long as zpu_ctrl is alive + // to prevent any use by different threads while enumerating boost::mutex::scoped_lock lock(pcie_zpu_iface_registry_mutex); if (get_pcie_zpu_iface_registry().has_key(resource_d)) { zpu_ctrl = get_pcie_zpu_iface_registry()[resource_d].lock(); - if (!zpu_ctrl) - { + if (!zpu_ctrl) { get_pcie_zpu_iface_registry().pop(resource_d); } } // if the registry didn't have a key OR that key was an orphaned weak_ptr - if (!zpu_ctrl) - { - zpu_ctrl = x300_make_ctrl_iface_pcie(kernel_proxy, false /* suppress timeout errors */); - //We don't put this zpu_ctrl in the registry because we need - //a persistent niriok_proxy associated with the object + if (!zpu_ctrl) { + zpu_ctrl = x300_make_ctrl_iface_pcie( + kernel_proxy, false /* suppress timeout errors */); + // We don't put this zpu_ctrl in the registry because we need + // a persistent niriok_proxy associated with the object } - //Attempt to autodetect the FPGA type + // Attempt to autodetect the FPGA type if (not hint.has_key("fpga")) { new_addr["fpga"] = get_fpga_option(zpu_ctrl); } - i2c_core_100_wb32::sptr zpu_i2c = i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); - x300_mb_eeprom_iface::sptr eeprom_iface = x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); - const mboard_eeprom_t mb_eeprom = - x300_impl::get_mb_eeprom(eeprom_iface); - if (mb_eeprom.size() == 0 or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) - { + i2c_core_100_wb32::sptr zpu_i2c = + i2c_core_100_wb32::make(zpu_ctrl, I2C1_BASE); + x300_mb_eeprom_iface::sptr eeprom_iface = + x300_mb_eeprom_iface::make(zpu_ctrl, zpu_i2c); + const mboard_eeprom_t mb_eeprom = x300_impl::get_mb_eeprom(eeprom_iface); + if (mb_eeprom.size() == 0 + or x300_impl::claim_status(zpu_ctrl) == x300_impl::CLAIMED_BY_OTHER) { // Skip device claimed by another process continue; } - new_addr["name"] = mb_eeprom["name"]; + new_addr["name"] = mb_eeprom["name"]; new_addr["serial"] = mb_eeprom["serial"]; - } - catch(const std::exception &) - { - //set these values as empty string so the device may still be found - //and the filter's below can still operate on the discovered device + } catch (const std::exception&) { + // set these values as empty string so the device may still be found + // and the filter's below can still operate on the discovered device if (not hint.has_key("fpga")) { new_addr["fpga"] = "HG"; } - new_addr["name"] = ""; + new_addr["name"] = ""; new_addr["serial"] = ""; } - //filter the discovered device below by matching optional keys + // filter the discovered device below by matching optional keys std::string resource_i = hint.has_key("resource") ? hint["resource"] : ""; boost::to_upper(resource_i); - if ( - (not hint.has_key("resource") or resource_i == resource_d) and - (not hint.has_key("name") or hint["name"] == new_addr["name"]) and - (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) and - (not hint.has_key("product") or hint["product"] == new_addr["product"]) - ){ + if ((not hint.has_key("resource") or resource_i == resource_d) + and (not hint.has_key("name") or hint["name"] == new_addr["name"]) + and (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]) + and (not hint.has_key("product") or hint["product"] == new_addr["product"])) { addrs.push_back(new_addr); } } return addrs; } -device_addrs_t x300_find(const device_addr_t &hint_) +device_addrs_t x300_find(const device_addr_t& hint_) { - //handle the multi-device discovery + // handle the multi-device discovery device_addrs_t hints = separate_device_addr(hint_); - if (hints.size() > 1) - { + if (hints.size() > 1) { device_addrs_t found_devices; std::string error_msg; - for(const device_addr_t &hint_i: hints) - { + for (const device_addr_t& hint_i : hints) { device_addrs_t found_devices_i = x300_find(hint_i); - if (found_devices_i.size() != 1) error_msg += str(boost::format( - "Could not resolve device hint \"%s\" to a single device." - ) % hint_i.to_string()); - else found_devices.push_back(found_devices_i[0]); + if (found_devices_i.size() != 1) + error_msg += + str(boost::format( + "Could not resolve device hint \"%s\" to a single device.") + % hint_i.to_string()); + else + found_devices.push_back(found_devices_i[0]); } - if (found_devices.empty()) return device_addrs_t(); - if (not error_msg.empty()) throw uhd::value_error(error_msg); + if (found_devices.empty()) + return device_addrs_t(); + if (not error_msg.empty()) + throw uhd::value_error(error_msg); return device_addrs_t(1, combine_device_addrs(found_devices)); } - //initialize the hint for a single device case + // initialize the hint for a single device case UHD_ASSERT_THROW(hints.size() <= 1); - hints.resize(1); //in case it was empty + hints.resize(1); // in case it was empty device_addr_t hint = hints[0]; device_addrs_t addrs; - if (hint.has_key("type") and hint["type"] != "x300") return addrs; + if (hint.has_key("type") and hint["type"] != "x300") + return addrs; - //use the address given - if (hint.has_key("addr")) - { + // use the address given + if (hint.has_key("addr")) { device_addrs_t reply_addrs; - try - { + try { reply_addrs = x300_find_with_addr(hint); - } - catch(const std::exception &ex) - { - UHD_LOGGER_ERROR("X300") << "X300 Network discovery error " << ex.what() ; - } - catch(...) - { - UHD_LOGGER_ERROR("X300") << "X300 Network discovery unknown error " ; + } catch (const std::exception& ex) { + UHD_LOGGER_ERROR("X300") << "X300 Network discovery error " << ex.what(); + } catch (...) { + UHD_LOGGER_ERROR("X300") << "X300 Network discovery unknown error "; } return reply_addrs; } - if (!hint.has_key("resource")) - { - //otherwise, no address was specified, send a broadcast on each interface - for(const if_addrs_t &if_addrs: get_if_addrs()) - { - //avoid the loopback device - if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue; + if (!hint.has_key("resource")) { + // otherwise, no address was specified, send a broadcast on each interface + for (const if_addrs_t& if_addrs : get_if_addrs()) { + // avoid the loopback device + if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) + continue; - //create a new hint with this broadcast address + // create a new hint with this broadcast address device_addr_t new_hint = hint; - new_hint["addr"] = if_addrs.bcast; + new_hint["addr"] = if_addrs.bcast; - //call discover with the new hint and append results + // call discover with the new hint and append results device_addrs_t new_addrs = x300_find(new_hint); - //if we are looking for a serial, only add the one device with a matching serial + // if we are looking for a serial, only add the one device with a matching + // serial if (hint.has_key("serial")) { - bool found_serial = false; //signal to break out of the interface loop - for (device_addrs_t::iterator new_addr_it=new_addrs.begin(); new_addr_it != new_addrs.end(); new_addr_it++) { + bool found_serial = false; // signal to break out of the interface loop + for (device_addrs_t::iterator new_addr_it = new_addrs.begin(); + new_addr_it != new_addrs.end(); + new_addr_it++) { if ((*new_addr_it)["serial"] == hint["serial"]) { addrs.insert(addrs.begin(), *new_addr_it); found_serial = true; break; } } - if (found_serial) break; + if (found_serial) + break; } else { // Otherwise, add all devices we find addrs.insert(addrs.begin(), new_addrs.begin(), new_addrs.end()); @@ -421,7 +416,8 @@ device_addrs_t x300_find(const device_addr_t &hint_) } device_addrs_t pcie_addrs = x300_find_pcie(hint, hint.has_key("resource")); - if (not pcie_addrs.empty()) addrs.insert(addrs.end(), pcie_addrs.begin(), pcie_addrs.end()); + if (not pcie_addrs.empty()) + addrs.insert(addrs.end(), pcie_addrs.begin(), pcie_addrs.end()); return addrs; } @@ -429,7 +425,7 @@ device_addrs_t x300_find(const device_addr_t &hint_) /*********************************************************************** * Make **********************************************************************/ -static device::sptr x300_make(const device_addr_t &device_addr) +static device::sptr x300_make(const device_addr_t& device_addr) { return device::sptr(new x300_impl(device_addr)); } @@ -439,33 +435,33 @@ UHD_STATIC_BLOCK(register_x300_device) device::register_device(&x300_find, &x300_make, device::USRP); } -static void x300_load_fw(wb_iface::sptr fw_reg_ctrl, const std::string &file_name) +static void x300_load_fw(wb_iface::sptr fw_reg_ctrl, const std::string& file_name) { UHD_LOGGER_INFO("X300") << "Loading firmware " << file_name; - //load file into memory + // load file into memory std::ifstream fw_file(file_name.c_str()); - uint32_t fw_file_buff[X300_FW_NUM_BYTES/sizeof(uint32_t)]; - fw_file.read((char *)fw_file_buff, sizeof(fw_file_buff)); + uint32_t fw_file_buff[X300_FW_NUM_BYTES / sizeof(uint32_t)]; + fw_file.read((char*)fw_file_buff, sizeof(fw_file_buff)); fw_file.close(); - //Poke the fw words into the WB boot loader + // Poke the fw words into the WB boot loader fw_reg_ctrl->poke32(SR_ADDR(BOOT_LDR_BASE, BL_ADDRESS), 0); - for (size_t i = 0; i < X300_FW_NUM_BYTES; i+=sizeof(uint32_t)) - { - //@TODO: FIXME: Since x300_ctrl_iface acks each write and traps exceptions, the first try for the last word - // written will print an error because it triggers a FW reload and fails to reply. - fw_reg_ctrl->poke32(SR_ADDR(BOOT_LDR_BASE, BL_DATA), uhd::byteswap(fw_file_buff[i/sizeof(uint32_t)])); + for (size_t i = 0; i < X300_FW_NUM_BYTES; i += sizeof(uint32_t)) { + //@TODO: FIXME: Since x300_ctrl_iface acks each write and traps exceptions, the + // first try for the last word + // written will print an error because it triggers a FW reload and + // fails to reply. + fw_reg_ctrl->poke32(SR_ADDR(BOOT_LDR_BASE, BL_DATA), + uhd::byteswap(fw_file_buff[i / sizeof(uint32_t)])); } - //Wait for fimrware to reboot. 3s is an upper bound + // Wait for fimrware to reboot. 3s is an upper bound std::this_thread::sleep_for(std::chrono::milliseconds(3000)); - UHD_LOGGER_INFO("X300") << "Firmware loaded!" ; + UHD_LOGGER_INFO("X300") << "Firmware loaded!"; } -x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) - : device3_impl() - , _sid_framer(0) +x300_impl::x300_impl(const uhd::device_addr_t& dev_addr) : device3_impl(), _sid_framer(0) { UHD_LOGGER_INFO("X300") << "X300 initialization sequence..."; _tree->create<std::string>("/name").set("X-Series Device"); @@ -475,8 +471,7 @@ x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) // Serialize the initialization process if (dev_addr.has_key("serialize_init") or device_args.size() == 1) { - for (size_t i = 0; i < device_args.size(); i++) - { + for (size_t i = 0; i < device_args.size(); i++) { this->setup_mb(i, device_args[i]); } return; @@ -486,26 +481,22 @@ x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) // Initialize groups of USRPs in parallel size_t total_usrps = device_args.size(); size_t num_usrps = 0; - while (num_usrps < total_usrps) - { + while (num_usrps < total_usrps) { size_t init_usrps = std::min(total_usrps - num_usrps, x300::MAX_INIT_THREADS); boost::thread_group setup_threads; - for (size_t i = 0; i < init_usrps; i++) - { + for (size_t i = 0; i < init_usrps; i++) { const size_t index = num_usrps + i; - setup_threads.create_thread([this, index, device_args](){ + setup_threads.create_thread([this, index, device_args]() { this->setup_mb(index, device_args[index]); }); } setup_threads.join_all(); num_usrps += init_usrps; } - } void x300_impl::mboard_members_t::discover_eth( - const mboard_eeprom_t mb_eeprom, - const std::vector<std::string> &ip_addrs) + const mboard_eeprom_t mb_eeprom, const std::vector<std::string>& ip_addrs) { // Clear any previous addresses added eth_conns.clear(); @@ -517,16 +508,19 @@ void x300_impl::mboard_members_t::discover_eth( const std::string key = "ip-addr" + boost::to_string(i); // Show a warning if there exists duplicate addresses in the mboard eeprom - if (std::find(mb_eeprom_addrs.begin(), mb_eeprom_addrs.end(), mb_eeprom[key]) != mb_eeprom_addrs.end()) { - UHD_LOGGER_WARNING("X300") << str(boost::format( - "Duplicate IP address %s found in mboard EEPROM. " - "Device may not function properly. View and reprogram the values " - "using the usrp_burn_mb_eeprom utility.") % mb_eeprom[key]); + if (std::find(mb_eeprom_addrs.begin(), mb_eeprom_addrs.end(), mb_eeprom[key]) + != mb_eeprom_addrs.end()) { + UHD_LOGGER_WARNING("X300") << str( + boost::format( + "Duplicate IP address %s found in mboard EEPROM. " + "Device may not function properly. View and reprogram the values " + "using the usrp_burn_mb_eeprom utility.") + % mb_eeprom[key]); } mb_eeprom_addrs.push_back(mb_eeprom[key]); } - for(const std::string& addr: ip_addrs) { + for (const std::string& addr : ip_addrs) { x300_eth_conn_t conn_iface; conn_iface.addr = addr; conn_iface.type = X300_IFACE_NONE; @@ -537,10 +531,12 @@ void x300_impl::mboard_members_t::discover_eth( if (addr == mb_eeprom_addrs[i]) { // Choose the interface based on the index parity if (i % 2 == 0) { - conn_iface.type = X300_IFACE_ETH0; - conn_iface.link_rate = loaded_fpga_image == "HG" ? x300::MAX_RATE_1GIGE : x300::MAX_RATE_10GIGE; + conn_iface.type = X300_IFACE_ETH0; + conn_iface.link_rate = loaded_fpga_image == "HG" + ? x300::MAX_RATE_1GIGE + : x300::MAX_RATE_10GIGE; } else { - conn_iface.type = X300_IFACE_ETH1; + conn_iface.type = X300_IFACE_ETH1; conn_iface.link_rate = x300::MAX_RATE_10GIGE; } break; @@ -550,45 +546,49 @@ void x300_impl::mboard_members_t::discover_eth( // Check default IP addresses if we couldn't // determine the IP from the mboard eeprom if (conn_iface.type == X300_IFACE_NONE) { - UHD_LOGGER_WARNING("X300") << str(boost::format( - "Address %s not found in mboard EEPROM. Address may be wrong or " - "the EEPROM may be corrupt. Attempting to continue with default " - "IP addresses.") % conn_iface.addr - ); - - if (addr == boost::asio::ip::address_v4( - uint32_t(X300_DEFAULT_IP_ETH0_1G)).to_string()) { - conn_iface.type = X300_IFACE_ETH0; + UHD_LOGGER_WARNING("X300") << str( + boost::format( + "Address %s not found in mboard EEPROM. Address may be wrong or " + "the EEPROM may be corrupt. Attempting to continue with default " + "IP addresses.") + % conn_iface.addr); + + if (addr + == boost::asio::ip::address_v4(uint32_t(X300_DEFAULT_IP_ETH0_1G)) + .to_string()) { + conn_iface.type = X300_IFACE_ETH0; conn_iface.link_rate = x300::MAX_RATE_1GIGE; - } else if (addr == boost::asio::ip::address_v4( - uint32_t(X300_DEFAULT_IP_ETH1_1G)).to_string()) { - conn_iface.type = X300_IFACE_ETH1; + } else if (addr + == boost::asio::ip::address_v4(uint32_t(X300_DEFAULT_IP_ETH1_1G)) + .to_string()) { + conn_iface.type = X300_IFACE_ETH1; conn_iface.link_rate = x300::MAX_RATE_1GIGE; - } else if (addr == boost::asio::ip::address_v4( - uint32_t(X300_DEFAULT_IP_ETH0_10G)).to_string()) { - conn_iface.type = X300_IFACE_ETH0; + } else if (addr + == boost::asio::ip::address_v4(uint32_t(X300_DEFAULT_IP_ETH0_10G)) + .to_string()) { + conn_iface.type = X300_IFACE_ETH0; conn_iface.link_rate = x300::MAX_RATE_10GIGE; - } else if (addr == boost::asio::ip::address_v4( - uint32_t(X300_DEFAULT_IP_ETH1_10G)).to_string()) { - conn_iface.type = X300_IFACE_ETH1; + } else if (addr + == boost::asio::ip::address_v4(uint32_t(X300_DEFAULT_IP_ETH1_10G)) + .to_string()) { + conn_iface.type = X300_IFACE_ETH1; conn_iface.link_rate = x300::MAX_RATE_10GIGE; } else { - throw uhd::assertion_error(str(boost::format( - "X300 Initialization Error: Failed to match address %s with " - "any addresses for the device. Please check the address.") - % conn_iface.addr - )); + throw uhd::assertion_error( + str(boost::format( + "X300 Initialization Error: Failed to match address %s with " + "any addresses for the device. Please check the address.") + % conn_iface.addr)); } } // Save to a vector of connections if (conn_iface.type != X300_IFACE_NONE) { // Check the address before we add it - try - { + try { wb_iface::sptr zpu_ctrl = x300_make_ctrl_iface_enet( - udp_simple::make_connected(conn_iface.addr, - BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), + udp_simple::make_connected( + conn_iface.addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT)), false /* Suppress timeout errors */ ); @@ -597,42 +597,40 @@ void x300_impl::mboard_members_t::discover_eth( } // If the address does not work, throw an error - catch(std::exception &) - { - throw uhd::io_error(str(boost::format( - "X300 Initialization Error: Invalid address %s") - % conn_iface.addr)); + catch (std::exception&) { + throw uhd::io_error( + str(boost::format("X300 Initialization Error: Invalid address %s") + % conn_iface.addr)); } eth_conns.push_back(conn_iface); } } if (eth_conns.size() == 0) - throw uhd::assertion_error("X300 Initialization Error: No ethernet interfaces specified."); + throw uhd::assertion_error( + "X300 Initialization Error: No ethernet interfaces specified."); } -void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) +void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t& dev_addr) { - const fs_path mb_path = fs_path("/mboards") / mb_i; - mboard_members_t &mb = _mb[mb_i]; + const fs_path mb_path = fs_path("/mboards") / mb_i; + mboard_members_t& mb = _mb[mb_i]; mb.initialization_done = false; const std::string thread_id( - boost::lexical_cast<std::string>(boost::this_thread::get_id()) - ); + boost::lexical_cast<std::string>(boost::this_thread::get_id())); const std::string thread_msg( - "Thread ID " + thread_id + " for motherboard " - + std::to_string(mb_i) - ); + "Thread ID " + thread_id + " for motherboard " + std::to_string(mb_i)); mb.args.parse(dev_addr); std::vector<std::string> eth_addrs; // Not choosing eth0 based on resource might cause user issues - std::string eth0_addr = dev_addr.has_key("resource") ? dev_addr["resource"] : dev_addr["addr"]; + std::string eth0_addr = dev_addr.has_key("resource") ? dev_addr["resource"] + : dev_addr["addr"]; eth_addrs.push_back(eth0_addr); - mb.next_src_addr = 0; //Host source address for blocks + mb.next_src_addr = 0; // Host source address for blocks mb.next_tx_src_addr = 0; mb.next_rx_src_addr = 0; if (not mb.args.get_second_addr().empty()) { @@ -649,19 +647,18 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) init.addr = eth_addrs[0]; mb.eth_conns.push_back(init); - mb.xport_path = dev_addr.has_key("resource") ? "nirio" : "eth"; + mb.xport_path = dev_addr.has_key("resource") ? "nirio" : "eth"; mb.if_pkt_is_big_endian = mb.xport_path != "nirio"; - if (mb.xport_path == "nirio") - { + if (mb.xport_path == "nirio") { nirio_status status = 0; const std::string rpc_port_name = mb.args.get_niusrprio_rpc_port(); UHD_LOGGER_INFO("X300") << boost::format("Connecting to niusrpriorpc at localhost:%s...") - % rpc_port_name; + % rpc_port_name; - //Instantiate the correct lvbitx object + // Instantiate the correct lvbitx object nifpga_lvbitx::sptr lvbitx; switch (get_mb_type_from_pcie(mb.args.get_resource(), rpc_port_name)) { case USRP_X300_MB: @@ -672,85 +669,95 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) lvbitx.reset(new x310_lvbitx(dev_addr["fpga"])); break; default: - nirio_status_to_exception(status, "Motherboard detection error. Please ensure that you \ + nirio_status_to_exception( + status, "Motherboard detection error. Please ensure that you \ have a valid USRP X3x0, NI USRP-294xR, NI USRP-295xR or NI USRP-2974 device and that all the device \ drivers have loaded successfully."); } - //Load the lvbitx onto the device - UHD_LOGGER_INFO("X300") << boost::format("Using LVBITX bitfile %s...") % lvbitx->get_bitfile_path(); - mb.rio_fpga_interface.reset(new niusrprio_session(dev_addr["resource"], rpc_port_name)); - nirio_status_chain(mb.rio_fpga_interface->open(lvbitx, dev_addr.has_key("download-fpga")), status); + // Load the lvbitx onto the device + UHD_LOGGER_INFO("X300") + << boost::format("Using LVBITX bitfile %s...") % lvbitx->get_bitfile_path(); + mb.rio_fpga_interface.reset( + new niusrprio_session(dev_addr["resource"], rpc_port_name)); + nirio_status_chain( + mb.rio_fpga_interface->open(lvbitx, dev_addr.has_key("download-fpga")), + status); nirio_status_to_exception(status, "x300_impl: Could not initialize RIO session."); - //Tell the quirks object which FIFOs carry TX stream data - const uint32_t tx_data_fifos[2] = {x300::RADIO_DEST_PREFIX_TX, x300::RADIO_DEST_PREFIX_TX + 3}; - mb.rio_fpga_interface->get_kernel_proxy()->get_rio_quirks().register_tx_streams(tx_data_fifos, 2); + // Tell the quirks object which FIFOs carry TX stream data + const uint32_t tx_data_fifos[2] = { + x300::RADIO_DEST_PREFIX_TX, x300::RADIO_DEST_PREFIX_TX + 3}; + mb.rio_fpga_interface->get_kernel_proxy()->get_rio_quirks().register_tx_streams( + tx_data_fifos, 2); _tree->create<size_t>(mb_path / "mtu/recv").set(x300::PCIE_RX_DATA_FRAME_SIZE); _tree->create<size_t>(mb_path / "mtu/send").set(x300::PCIE_TX_DATA_FRAME_SIZE); _tree->create<double>(mb_path / "link_max_rate").set(x300::MAX_RATE_PCIE); } - for(const std::string &key: dev_addr.keys()) - { - if (key.find("recv") != std::string::npos) mb.recv_args[key] = dev_addr[key]; - if (key.find("send") != std::string::npos) mb.send_args[key] = dev_addr[key]; + for (const std::string& key : dev_addr.keys()) { + if (key.find("recv") != std::string::npos) + mb.recv_args[key] = dev_addr[key]; + if (key.find("send") != std::string::npos) + mb.send_args[key] = dev_addr[key]; } - //create basic communication + // create basic communication UHD_LOGGER_DEBUG("X300") << "Setting up basic communication..."; if (mb.xport_path == "nirio") { boost::mutex::scoped_lock lock(pcie_zpu_iface_registry_mutex); if (get_pcie_zpu_iface_registry().has_key(mb.get_pri_eth().addr)) { - throw uhd::assertion_error("Someone else has a ZPU transport to the device open. Internal error!"); + throw uhd::assertion_error( + "Someone else has a ZPU transport to the device open. Internal error!"); } else { - mb.zpu_ctrl = x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy()); - get_pcie_zpu_iface_registry()[mb.get_pri_eth().addr] = boost::weak_ptr<wb_iface>(mb.zpu_ctrl); + mb.zpu_ctrl = + x300_make_ctrl_iface_pcie(mb.rio_fpga_interface->get_kernel_proxy()); + get_pcie_zpu_iface_registry()[mb.get_pri_eth().addr] = + boost::weak_ptr<wb_iface>(mb.zpu_ctrl); } } else { mb.zpu_ctrl = x300_make_ctrl_iface_enet(udp_simple::make_connected( - mb.get_pri_eth().addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT))); + mb.get_pri_eth().addr, BOOST_STRINGIZE(X300_FW_COMMS_UDP_PORT))); } // Claim device if (not try_to_claim(mb.zpu_ctrl)) { throw uhd::runtime_error("Failed to claim device"); } - mb.claimer_task = uhd::task::make([this, mb](){ - this->claimer_loop(mb.zpu_ctrl); - }, "x300_claimer"); + mb.claimer_task = uhd::task::make( + [this, mb]() { this->claimer_loop(mb.zpu_ctrl); }, "x300_claimer"); - //extract the FW path for the X300 - //and live load fw over ethernet link + // extract the FW path for the X300 + // and live load fw over ethernet link if (mb.args.has_fw_file()) { - const std::string x300_fw_image = - find_image_path(mb.args.get_fw_file()); + const std::string x300_fw_image = find_image_path(mb.args.get_fw_file()); x300_load_fw(mb.zpu_ctrl, x300_fw_image); } - //check compat numbers - //check fpga compat before fw compat because the fw is a subset of the fpga image + // check compat numbers + // check fpga compat before fw compat because the fw is a subset of the fpga image this->check_fpga_compat(mb_path, mb); this->check_fw_compat(mb_path, mb); mb.fw_regmap = boost::make_shared<fw_regmap_t>(); mb.fw_regmap->initialize(*mb.zpu_ctrl.get(), true); - //store which FPGA image is loaded + // store which FPGA image is loaded mb.loaded_fpga_image = get_fpga_option(mb.zpu_ctrl); - //low speed perif access - mb.zpu_spi = spi_core_3000::make(mb.zpu_ctrl, SR_ADDR(SET0_BASE, ZPU_SR_SPI), - SR_ADDR(SET0_BASE, ZPU_RB_SPI)); + // low speed perif access + mb.zpu_spi = spi_core_3000::make( + mb.zpu_ctrl, SR_ADDR(SET0_BASE, ZPU_SR_SPI), SR_ADDR(SET0_BASE, ZPU_RB_SPI)); mb.zpu_i2c = i2c_core_100_wb32::make(mb.zpu_ctrl, I2C1_BASE); - mb.zpu_i2c->set_clock_rate(x300::BUS_CLOCK_RATE/2); + mb.zpu_i2c->set_clock_rate(x300::BUS_CLOCK_RATE / 2); //////////////////////////////////////////////////////////////////// // print network routes mapping //////////////////////////////////////////////////////////////////// /* - const uint32_t routes_addr = mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_ROUTE_MAP_ADDR)); - const uint32_t routes_len = mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_ROUTE_MAP_LEN)); + const uint32_t routes_addr = mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, + X300_FW_SHMEM_ROUTE_MAP_ADDR)); const uint32_t routes_len = + mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_ROUTE_MAP_LEN)); UHD_VAR(routes_len); for (size_t i = 0; i < routes_len; i+=1) { @@ -778,29 +785,28 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) } const mboard_eeprom_t mb_eeprom = get_mb_eeprom(eeprom16); - _tree->create<mboard_eeprom_t>(mb_path / "eeprom") + _tree + ->create<mboard_eeprom_t>(mb_path / "eeprom") // Initialize the property with a current copy of the EEPROM contents .set(mb_eeprom) // Whenever this property is written, update the chip - .add_coerced_subscriber( - [this, eeprom16](const mboard_eeprom_t &mb_eeprom){ - this->set_mb_eeprom(eeprom16, mb_eeprom); - } - ) - ; + .add_coerced_subscriber([this, eeprom16](const mboard_eeprom_t& mb_eeprom) { + this->set_mb_eeprom(eeprom16, mb_eeprom); + }); if (mb.args.get_recover_mb_eeprom()) { - UHD_LOGGER_WARNING("X300") << "UHD is operating in EEPROM Recovery Mode which disables hardware version " - "checks.\nOperating in this mode may cause hardware damage and unstable " - "radio performance!"; + UHD_LOGGER_WARNING("X300") + << "UHD is operating in EEPROM Recovery Mode which disables hardware version " + "checks.\nOperating in this mode may cause hardware damage and unstable " + "radio performance!"; return; } //////////////////////////////////////////////////////////////////// // parse the product number //////////////////////////////////////////////////////////////////// - const std::string product_name = map_mb_type_to_product_name( - get_mb_type_from_eeprom(mb_eeprom), "X300?"); + const std::string product_name = + map_mb_type_to_product_name(get_mb_type_from_eeprom(mb_eeprom), "X300?"); if (product_name == "X300?") { if (not mb.args.get_recover_mb_eeprom()) { throw uhd::runtime_error( @@ -818,7 +824,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //////////////////////////////////////////////////////////////////// // discover ethernet interfaces, frame sizes, and link rates //////////////////////////////////////////////////////////////////// - if (mb.xport_path == "eth" ) { + if (mb.xport_path == "eth") { double link_max_rate = 0.0; // Discover ethernet interfaces @@ -836,101 +842,104 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) * multiple transmission units - this is why the limits passed into the * 'determine_max_frame_size' function are actually frame sizes. */ frame_size_t req_max_frame_size; - req_max_frame_size.recv_frame_size = (mb.recv_args.has_key("recv_frame_size")) \ - ? boost::lexical_cast<size_t>(mb.recv_args["recv_frame_size"]) \ - : x300::DATA_FRAME_MAX_SIZE; - req_max_frame_size.send_frame_size = (mb.send_args.has_key("send_frame_size")) \ - ? boost::lexical_cast<size_t>(mb.send_args["send_frame_size"]) \ - : x300::DATA_FRAME_MAX_SIZE; - - #if defined UHD_PLATFORM_LINUX - const std::string mtu_tool("ip link"); - #elif defined UHD_PLATFORM_WIN32 - const std::string mtu_tool("netsh"); - #else - const std::string mtu_tool("ifconfig"); - #endif + req_max_frame_size.recv_frame_size = + (mb.recv_args.has_key("recv_frame_size")) + ? boost::lexical_cast<size_t>(mb.recv_args["recv_frame_size"]) + : x300::DATA_FRAME_MAX_SIZE; + req_max_frame_size.send_frame_size = + (mb.send_args.has_key("send_frame_size")) + ? boost::lexical_cast<size_t>(mb.send_args["send_frame_size"]) + : x300::DATA_FRAME_MAX_SIZE; + +#if defined UHD_PLATFORM_LINUX + const std::string mtu_tool("ip link"); +#elif defined UHD_PLATFORM_WIN32 + const std::string mtu_tool("netsh"); +#else + const std::string mtu_tool("ifconfig"); +#endif // Detect the frame size on the path to the USRP try { - frame_size_t pri_frame_sizes = determine_max_frame_size( - eth_addrs.at(0), req_max_frame_size - ); + frame_size_t pri_frame_sizes = + determine_max_frame_size(eth_addrs.at(0), req_max_frame_size); _max_frame_sizes = pri_frame_sizes; if (eth_addrs.size() > 1) { - frame_size_t sec_frame_sizes = determine_max_frame_size( - eth_addrs.at(1), req_max_frame_size - ); + frame_size_t sec_frame_sizes = + determine_max_frame_size(eth_addrs.at(1), req_max_frame_size); // Choose the minimum of the max frame sizes // to ensure we don't exceed any one of the links' MTU _max_frame_sizes.recv_frame_size = std::min( - pri_frame_sizes.recv_frame_size, - sec_frame_sizes.recv_frame_size - ); + pri_frame_sizes.recv_frame_size, sec_frame_sizes.recv_frame_size); _max_frame_sizes.send_frame_size = std::min( - pri_frame_sizes.send_frame_size, - sec_frame_sizes.send_frame_size - ); + pri_frame_sizes.send_frame_size, sec_frame_sizes.send_frame_size); } - } catch(std::exception &e) { - UHD_LOGGER_ERROR("X300") << e.what() ; + } catch (std::exception& e) { + UHD_LOGGER_ERROR("X300") << e.what(); } if ((mb.recv_args.has_key("recv_frame_size")) - && (req_max_frame_size.recv_frame_size > _max_frame_sizes.recv_frame_size)) { + && (req_max_frame_size.recv_frame_size > _max_frame_sizes.recv_frame_size)) { UHD_LOGGER_WARNING("X300") - << boost::format("You requested a receive frame size of (%lu) but your NIC's max frame size is (%lu).") - % req_max_frame_size.recv_frame_size - % _max_frame_sizes.recv_frame_size - << boost::format("Please verify your NIC's MTU setting using '%s' or set the recv_frame_size argument appropriately.") - % mtu_tool - << "UHD will use the auto-detected max frame size for this connection." - ; + << boost::format("You requested a receive frame size of (%lu) but your " + "NIC's max frame size is (%lu).") + % req_max_frame_size.recv_frame_size + % _max_frame_sizes.recv_frame_size + << boost::format("Please verify your NIC's MTU setting using '%s' or set " + "the recv_frame_size argument appropriately.") + % mtu_tool + << "UHD will use the auto-detected max frame size for this connection."; } if ((mb.send_args.has_key("send_frame_size")) - && (req_max_frame_size.send_frame_size > _max_frame_sizes.send_frame_size)) { + && (req_max_frame_size.send_frame_size > _max_frame_sizes.send_frame_size)) { UHD_LOGGER_WARNING("X300") - << boost::format("You requested a send frame size of (%lu) but your NIC's max frame size is (%lu).") - % req_max_frame_size.send_frame_size - % _max_frame_sizes.send_frame_size - << boost::format("Please verify your NIC's MTU setting using '%s' or set the send_frame_size argument appropriately.") - % mtu_tool - << "UHD will use the auto-detected max frame size for this connection." - ; + << boost::format("You requested a send frame size of (%lu) but your " + "NIC's max frame size is (%lu).") + % req_max_frame_size.send_frame_size + % _max_frame_sizes.send_frame_size + << boost::format("Please verify your NIC's MTU setting using '%s' or set " + "the send_frame_size argument appropriately.") + % mtu_tool + << "UHD will use the auto-detected max frame size for this connection."; } // Check frame sizes - for (auto conn : mb.eth_conns) - { + for (auto conn : mb.eth_conns) { link_max_rate += conn.link_rate; - size_t rec_send_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_SEND_SIZE : x300::XGE_DATA_FRAME_SEND_SIZE; - size_t rec_recv_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_RECV_SIZE : x300::XGE_DATA_FRAME_RECV_SIZE; + size_t rec_send_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_SEND_SIZE + : x300::XGE_DATA_FRAME_SEND_SIZE; + size_t rec_recv_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_RECV_SIZE + : x300::XGE_DATA_FRAME_RECV_SIZE; - if (_max_frame_sizes.send_frame_size < rec_send_frame_size) - { + if (_max_frame_sizes.send_frame_size < rec_send_frame_size) { UHD_LOGGER_WARNING("X300") - << boost::format("For the %s connection, UHD recommends a send frame size of at least %lu for best\nperformance, but your configuration will only allow %lu.") - % conn.addr - % rec_send_frame_size - % _max_frame_sizes.send_frame_size - << "This may negatively impact your maximum achievable sample rate.\nCheck the MTU on the interface and/or the send_frame_size argument." - ; + << boost::format("For the %s connection, UHD recommends a send frame " + "size of at least %lu for best\nperformance, but " + "your configuration will only allow %lu.") + % conn.addr % rec_send_frame_size + % _max_frame_sizes.send_frame_size + << "This may negatively impact your maximum achievable sample " + "rate.\nCheck the MTU on the interface and/or the send_frame_size " + "argument."; } - if (_max_frame_sizes.recv_frame_size < rec_recv_frame_size) - { + if (_max_frame_sizes.recv_frame_size < rec_recv_frame_size) { UHD_LOGGER_WARNING("X300") - << boost::format("For the %s connection, UHD recommends a receive frame size of at least %lu for best\nperformance, but your configuration will only allow %lu.") - % conn.addr - % rec_recv_frame_size - % _max_frame_sizes.recv_frame_size - << "This may negatively impact your maximum achievable sample rate.\nCheck the MTU on the interface and/or the recv_frame_size argument." - ; + << boost::format("For the %s connection, UHD recommends a receive " + "frame size of at least %lu for best\nperformance, " + "but your configuration will only allow %lu.") + % conn.addr % rec_recv_frame_size + % _max_frame_sizes.recv_frame_size + << "This may negatively impact your maximum achievable sample " + "rate.\nCheck the MTU on the interface and/or the recv_frame_size " + "argument."; } } @@ -943,40 +952,48 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) // read hardware revision and compatibility number //////////////////////////////////////////////////////////////////// mb.hw_rev = 0; - if(mb_eeprom.has_key("revision") and not mb_eeprom["revision"].empty()) { + if (mb_eeprom.has_key("revision") and not mb_eeprom["revision"].empty()) { try { mb.hw_rev = boost::lexical_cast<size_t>(mb_eeprom["revision"]); - } catch(...) { - throw uhd::runtime_error("Revision in EEPROM is invalid! Please reprogram your EEPROM."); + } catch (...) { + throw uhd::runtime_error( + "Revision in EEPROM is invalid! Please reprogram your EEPROM."); } } else { throw uhd::runtime_error("No revision detected. MB EEPROM must be reprogrammed!"); } size_t hw_rev_compat = 0; - if (mb.hw_rev >= 7) { //Revision compat was added with revision 7 - if (mb_eeprom.has_key("revision_compat") and not mb_eeprom["revision_compat"].empty()) { + if (mb.hw_rev >= 7) { // Revision compat was added with revision 7 + if (mb_eeprom.has_key("revision_compat") + and not mb_eeprom["revision_compat"].empty()) { try { hw_rev_compat = boost::lexical_cast<size_t>(mb_eeprom["revision_compat"]); - } catch(...) { - throw uhd::runtime_error("Revision compat in EEPROM is invalid! Please reprogram your EEPROM."); + } catch (...) { + throw uhd::runtime_error("Revision compat in EEPROM is invalid! Please " + "reprogram your EEPROM."); } } else { - throw uhd::runtime_error("No revision compat detected. MB EEPROM must be reprogrammed!"); + throw uhd::runtime_error( + "No revision compat detected. MB EEPROM must be reprogrammed!"); } } else { - //For older HW just assume that revision_compat = revision + // For older HW just assume that revision_compat = revision hw_rev_compat = mb.hw_rev; } if (hw_rev_compat > X300_REVISION_COMPAT) { - throw uhd::runtime_error(str(boost::format( - "Hardware is too new for this software. Please upgrade to a driver that supports hardware revision %d.") - % mb.hw_rev)); - } else if (mb.hw_rev < X300_REVISION_MIN) { //Compare min against the revision (and not compat) to give us more leeway for partial support for a compat - throw uhd::runtime_error(str(boost::format( - "Software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.") - % mb.hw_rev)); + throw uhd::runtime_error( + str(boost::format("Hardware is too new for this software. Please upgrade to " + "a driver that supports hardware revision %d.") + % mb.hw_rev)); + } else if (mb.hw_rev < X300_REVISION_MIN) { // Compare min against the revision (and + // not compat) to give us more leeway for + // partial support for a compat + throw uhd::runtime_error( + str(boost::format("Software is too new for this hardware. Please downgrade " + "to a driver that supports hardware revision %d.") + % mb.hw_rev)); } //////////////////////////////////////////////////////////////////// @@ -984,63 +1001,55 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //////////////////////////////////////////////////////////////////// UHD_LOGGER_DEBUG("X300") << "Setting up RF frontend clocking..."; - //Initialize clock control registers. NOTE: This does not configure the LMK yet. + // 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(), - mb.args.get_system_ref_rate() - ); + mb.args.get_system_ref_rate()); mb.fw_regmap->ref_freq_reg.write( - fw_regmap_t::ref_freq_reg_t::REF_FREQ, - uint32_t(mb.args.get_system_ref_rate()) - ); + fw_regmap_t::ref_freq_reg_t::REF_FREQ, uint32_t(mb.args.get_system_ref_rate())); - //Initialize clock source to use internal reference and generate - //a valid radio clock. This may change after configuration is done. - //This will configure the LMK and wait for lock + // Initialize clock source to use internal reference and generate + // a valid radio clock. This may change after configuration is done. + // This will configure the LMK and wait for lock update_clock_source(mb, mb.args.get_clock_source()); //////////////////////////////////////////////////////////////////// // create clock properties //////////////////////////////////////////////////////////////////// - _tree->create<double>(mb_path / "master_clock_rate") - .set_publisher([mb](){ return mb.clock->get_master_clock_rate(); }) - ; + _tree->create<double>(mb_path / "master_clock_rate").set_publisher([mb]() { + return mb.clock->get_master_clock_rate(); + }); - UHD_LOGGER_INFO("X300") - << "Radio 1x clock: " << (mb.clock->get_master_clock_rate()/1e6) - << " MHz"; + UHD_LOGGER_INFO("X300") << "Radio 1x clock: " + << (mb.clock->get_master_clock_rate() / 1e6) << " MHz"; //////////////////////////////////////////////////////////////////// // Create the GPSDO control //////////////////////////////////////////////////////////////////// static const uint32_t dont_look_for_gpsdo = 0x1234abcdul; - //otherwise if not disabled, look for the internal GPSDO - if (mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_GPSDO_STATUS)) != dont_look_for_gpsdo) - { + // otherwise if not disabled, look for the internal GPSDO + if (mb.zpu_ctrl->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_GPSDO_STATUS)) + != dont_look_for_gpsdo) { UHD_LOG_DEBUG("X300", "Detecting internal GPSDO...."); try { // gps_ctrl will print its own log statements if a GPSDO was found mb.gps = gps_ctrl::make(x300_make_uart_iface(mb.zpu_ctrl)); - } - catch(std::exception &e) { + } catch (std::exception& e) { UHD_LOGGER_ERROR("X300") << "An error occurred making GPSDO control: " << e.what(); } if (mb.gps and mb.gps->gps_detected()) { - for(const std::string& name : mb.gps->get_sensors()) { + for (const std::string& name : mb.gps->get_sensors()) { _tree->create<sensor_value_t>(mb_path / "sensors" / name) - .set_publisher([&mb, name](){ - return mb.gps->get_sensor(name); - }) - ; + .set_publisher([&mb, name]() { return mb.gps->get_sensor(name); }); } - } - else { - mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_GPSDO_STATUS), dont_look_for_gpsdo); + } else { + mb.zpu_ctrl->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_GPSDO_STATUS), + dont_look_for_gpsdo); } } @@ -1049,97 +1058,88 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) //////////////////////////////////////////////////////////////////// _tree->create<std::string>(mb_path / "time_source" / "value") .set(mb.args.get_time_source()) - .add_coerced_subscriber([this, &mb](const std::string& time_source){ + .add_coerced_subscriber([this, &mb](const std::string& time_source) { this->update_time_source(mb, time_source); - }) - ; - static const std::vector<std::string> time_sources = - {"internal", "external", "gpsdo"}; + }); + static const std::vector<std::string> time_sources = { + "internal", "external", "gpsdo"}; _tree->create<std::vector<std::string>>(mb_path / "time_source" / "options") .set(time_sources); - //setup the time output, default to ON + // setup the time output, default to ON _tree->create<bool>(mb_path / "time_source" / "output") - .add_coerced_subscriber([this, &mb](const bool time_output){ + .add_coerced_subscriber([this, &mb](const bool time_output) { this->set_time_source_out(mb, time_output); }) - .set(true) - ; + .set(true); //////////////////////////////////////////////////////////////////// // setup clock sources and properties //////////////////////////////////////////////////////////////////// _tree->create<std::string>(mb_path / "clock_source" / "value") .set(mb.args.get_clock_source()) - .add_coerced_subscriber([this, &mb](const std::string& clock_source){ + .add_coerced_subscriber([this, &mb](const std::string& clock_source) { this->update_clock_source(mb, clock_source); - }) - ; - static const std::vector<std::string> clock_source_options = - {"internal", "external", "gpsdo"}; + }); + static const std::vector<std::string> clock_source_options = { + "internal", "external", "gpsdo"}; _tree->create<std::vector<std::string>>(mb_path / "clock_source" / "options") .set(clock_source_options); - //setup external reference options. default to 10 MHz input reference + // setup external reference options. default to 10 MHz input reference _tree->create<std::string>(mb_path / "clock_source" / "external"); - _tree->create<std::vector<double>>(mb_path / "clock_source" / "external" / "freq" / "options") + _tree + ->create<std::vector<double>>( + mb_path / "clock_source" / "external" / "freq" / "options") .set(x300::EXTERNAL_FREQ_OPTIONS); _tree->create<double>(mb_path / "clock_source" / "external" / "value") .set(mb.clock->get_sysref_clock_rate()); // FIXME the external clock source settings need to be more robust - //setup the clock output, default to ON + // setup the clock output, default to ON _tree->create<bool>(mb_path / "clock_source" / "output") - .add_coerced_subscriber([&mb](const bool clock_output){ - mb.clock->set_ref_out(clock_output); - }) - ; + .add_coerced_subscriber( + [&mb](const bool clock_output) { mb.clock->set_ref_out(clock_output); }); // Initialize tick rate (must be done before setting time) // Note: The master tick rate can't be changed at runtime! const double master_clock_rate = mb.clock->get_master_clock_rate(); _tree->create<double>(mb_path / "tick_rate") - .set_coercer([master_clock_rate](const double rate){ + .set_coercer([master_clock_rate](const double rate) { // The contract of multi_usrp::set_master_clock_rate() is to coerce // and not throw, so we'll follow that behaviour here. if (!uhd::math::frequencies_are_equal(rate, master_clock_rate)) { - UHD_LOGGER_WARNING("X300") << - "Cannot update master clock rate! X300 Series does not " - "allow changing the clock rate during runtime." - ; + UHD_LOGGER_WARNING("X300") + << "Cannot update master clock rate! X300 Series does not " + "allow changing the clock rate during runtime."; } return master_clock_rate; }) - .add_coerced_subscriber([this](const double rate){ - this->update_tx_streamers(rate); - }) - .add_coerced_subscriber([this](const double rate){ - this->update_rx_streamers(rate); - }) - .set(master_clock_rate) - ; + .add_coerced_subscriber( + [this](const double rate) { this->update_tx_streamers(rate); }) + .add_coerced_subscriber( + [this](const double rate) { this->update_rx_streamers(rate); }) + .set(master_clock_rate); //////////////////////////////////////////////////////////////////// // and do the misc mboard sensors //////////////////////////////////////////////////////////////////// _tree->create<sensor_value_t>(mb_path / "sensors" / "ref_locked") - .set_publisher([this, &mb](){ return this->get_ref_locked(mb); }); + .set_publisher([this, &mb]() { return this->get_ref_locked(mb); }); //////////////// RFNOC ///////////////// const size_t n_rfnoc_blocks = mb.zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_NUM_CE)); - enumerate_rfnoc_blocks( - mb_i, + enumerate_rfnoc_blocks(mb_i, n_rfnoc_blocks, x300::XB_DST_PCI + 1, /* base port */ uhd::sid_t(x300::SRC_ADDR0, 0, x300::DST_ADDR + mb_i, 0), - dev_addr - ); + dev_addr); //////////////// RFNOC ///////////////// // If we have a radio, we must configure its codec control: const std::string radio_blockid_hint = str(boost::format("%d/Radio") % mb_i); std::vector<rfnoc::block_id_t> radio_ids = - find_blocks<rfnoc::x300_radio_ctrl_impl>(radio_blockid_hint); + find_blocks<rfnoc::x300_radio_ctrl_impl>(radio_blockid_hint); if (not radio_ids.empty()) { if (radio_ids.size() > 2) { UHD_LOGGER_WARNING("X300") @@ -1147,33 +1147,31 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) radio_ids.resize(2); } - for(const rfnoc::block_id_t &id: radio_ids) { - rfnoc::x300_radio_ctrl_impl::sptr radio(get_block_ctrl<rfnoc::x300_radio_ctrl_impl>(id)); + for (const rfnoc::block_id_t& id : radio_ids) { + rfnoc::x300_radio_ctrl_impl::sptr radio( + get_block_ctrl<rfnoc::x300_radio_ctrl_impl>(id)); mb.radios.push_back(radio); - radio->setup_radio( - mb.zpu_i2c, - mb.clock, - mb.args.get_ignore_cal_file(), - mb.args.get_self_cal_adc_delay() - ); + radio->setup_radio(mb.zpu_i2c, + mb.clock, + mb.args.get_ignore_cal_file(), + mb.args.get_self_cal_adc_delay()); } //////////////////////////////////////////////////////////////////// // ADC test and cal //////////////////////////////////////////////////////////////////// if (mb.args.get_self_cal_adc_delay()) { - rfnoc::x300_radio_ctrl_impl::self_cal_adc_xfer_delay( - mb.radios, mb.clock, - [this, &mb](const double timeout){ - return this->wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout); + rfnoc::x300_radio_ctrl_impl::self_cal_adc_xfer_delay(mb.radios, + mb.clock, + [this, &mb](const double timeout) { + return this->wait_for_clk_locked( + mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout); }, true /* Apply ADC delay */); } if (mb.args.get_ext_adc_self_test()) { rfnoc::x300_radio_ctrl_impl::extended_adc_test( - mb.radios, - mb.args.get_ext_adc_self_test_duration() - ); + mb.radios, mb.args.get_ext_adc_self_test_duration()); } else { for (size_t i = 0; i < mb.radios.size(); i++) { mb.radios.at(i)->self_test_adc(); @@ -1188,8 +1186,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) } } else { - UHD_LOGGER_INFO("X300") - << "No Radio Block found. Assuming radio-less operation."; + UHD_LOGGER_INFO("X300") << "No Radio Block found. Assuming radio-less operation."; } /* end of radio block(s) initialization */ mb.initialization_done = true; @@ -1197,30 +1194,27 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) x300_impl::~x300_impl(void) { - try - { - for(mboard_members_t &mb: _mb) - { - //kill the claimer task and unclaim the device + try { + for (mboard_members_t& mb : _mb) { + // kill the claimer task and unclaim the device mb.claimer_task.reset(); - { //Critical section + { // Critical section boost::mutex::scoped_lock lock(pcie_zpu_iface_registry_mutex); release(mb.zpu_ctrl); - //If the process is killed, the entire registry will disappear so we - //don't need to worry about unclean shutdowns here. + // If the process is killed, the entire registry will disappear so we + // don't need to worry about unclean shutdowns here. if (get_pcie_zpu_iface_registry().has_key(mb.get_pri_eth().addr)) { get_pcie_zpu_iface_registry().pop(mb.get_pri_eth().addr); } } } - } - catch(...) - { + } catch (...) { UHD_SAFE_CALL(throw;) } } -uint32_t x300_impl::mboard_members_t::allocate_pcie_dma_chan(const uhd::sid_t &tx_sid, const xport_type_t xport_type) +uint32_t x300_impl::mboard_members_t::allocate_pcie_dma_chan( + const uhd::sid_t& tx_sid, const xport_type_t xport_type) { static const uint32_t CTRL_CHANNEL = 0; static const uint32_t ASYNC_MSG_CHANNEL = 1; @@ -1236,28 +1230,29 @@ uint32_t x300_impl::mboard_members_t::allocate_pcie_dma_chan(const uhd::sid_t &t if (_dma_chan_pool.count(raw_sid) == 0) { size_t channel = _dma_chan_pool.size() + FIRST_DATA_CHANNEL; if (channel > x300::PCIE_MAX_CHANNELS) { - throw uhd::runtime_error("Trying to allocate more DMA channels than are available"); + throw uhd::runtime_error( + "Trying to allocate more DMA channels than are available"); } _dma_chan_pool[raw_sid] = channel; UHD_LOGGER_DEBUG("X300") - << "Assigning PCIe DMA channel " << _dma_chan_pool[raw_sid] - << " to SID " << tx_sid.to_pp_string_hex(); + << "Assigning PCIe DMA channel " << _dma_chan_pool[raw_sid] << " to SID " + << tx_sid.to_pp_string_hex(); } return _dma_chan_pool[raw_sid]; } } -static uint32_t extract_sid_from_pkt(void* pkt, size_t) { +static uint32_t extract_sid_from_pkt(void* pkt, size_t) +{ return uhd::sid_t(uhd::wtohx(static_cast<const uint32_t*>(pkt)[1])).get_dst(); } -static uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport -( +static uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport( uhd::niusrprio::niusrprio_session::sptr rio_fpga_interface, uint32_t dma_channel_num, - size_t max_muxed_ports -) { + size_t max_muxed_ports) +{ zero_copy_xport_params buff_args; buff_args.send_frame_size = x300::PCIE_MSG_FRAME_SIZE; buff_args.recv_frame_size = x300::PCIE_MSG_FRAME_SIZE; @@ -1265,77 +1260,70 @@ static uhd::transport::muxed_zero_copy_if::sptr make_muxed_pcie_msg_xport buff_args.num_recv_frames = x300::PCIE_MSG_NUM_FRAMES * max_muxed_ports; zero_copy_if::sptr base_xport = nirio_zero_copy::make( - rio_fpga_interface, dma_channel_num, - buff_args, uhd::device_addr_t()); + rio_fpga_interface, dma_channel_num, buff_args, uhd::device_addr_t()); return muxed_zero_copy_if::make(base_xport, extract_sid_from_pkt, max_muxed_ports); } -uhd::both_xports_t x300_impl::make_transport( - const uhd::sid_t &address, +uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, const xport_type_t xport_type, - const uhd::device_addr_t& args -) { - const size_t mb_index = address.get_dst_addr() - x300::DST_ADDR; - mboard_members_t &mb = _mb[mb_index]; - const uhd::device_addr_t& xport_args = (xport_type == CTRL) ? uhd::device_addr_t() : args; + const uhd::device_addr_t& args) +{ + const size_t mb_index = address.get_dst_addr() - x300::DST_ADDR; + mboard_members_t& mb = _mb[mb_index]; + const uhd::device_addr_t& xport_args = (xport_type == CTRL) ? uhd::device_addr_t() + : args; zero_copy_xport_params default_buff_args; both_xports_t xports; xports.endianness = mb.if_pkt_is_big_endian ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (mb.xport_path == "nirio") { - xports.send_sid = this->allocate_sid(mb, address, x300::SRC_ADDR0, x300::XB_DST_PCI); + xports.send_sid = + this->allocate_sid(mb, address, x300::SRC_ADDR0, x300::XB_DST_PCI); xports.recv_sid = xports.send_sid.reversed(); uint32_t dma_channel_num = mb.allocate_pcie_dma_chan(xports.send_sid, xport_type); if (xport_type == CTRL) { - //Transport for control stream + // Transport for control stream if (not mb.ctrl_dma_xport) { - //One underlying DMA channel will handle - //all control traffic - mb.ctrl_dma_xport = make_muxed_pcie_msg_xport( - mb.rio_fpga_interface, + // One underlying DMA channel will handle + // all control traffic + mb.ctrl_dma_xport = make_muxed_pcie_msg_xport(mb.rio_fpga_interface, dma_channel_num, x300::PCIE_MAX_MUXED_CTRL_XPORTS); } - //Create a virtual control transport + // Create a virtual control transport xports.recv = mb.ctrl_dma_xport->make_stream(xports.recv_sid.get_dst()); } else if (xport_type == ASYNC_MSG) { - //Transport for async message stream + // Transport for async message stream if (not mb.async_msg_dma_xport) { - //One underlying DMA channel will handle - //all async message traffic - mb.async_msg_dma_xport = make_muxed_pcie_msg_xport( - mb.rio_fpga_interface, + // One underlying DMA channel will handle + // all async message traffic + mb.async_msg_dma_xport = make_muxed_pcie_msg_xport(mb.rio_fpga_interface, dma_channel_num, x300::PCIE_MAX_MUXED_ASYNC_XPORTS); } - //Create a virtual async message transport + // Create a virtual async message transport xports.recv = mb.async_msg_dma_xport->make_stream(xports.recv_sid.get_dst()); } else { - //Transport for data stream - default_buff_args.send_frame_size = - (xport_type == TX_DATA) - ? x300::PCIE_TX_DATA_FRAME_SIZE - : x300::PCIE_MSG_FRAME_SIZE; - - default_buff_args.recv_frame_size = - (xport_type == RX_DATA) - ? x300::PCIE_RX_DATA_FRAME_SIZE - : x300::PCIE_MSG_FRAME_SIZE; - - default_buff_args.num_send_frames = - (xport_type == TX_DATA) - ? x300::PCIE_TX_DATA_NUM_FRAMES - : x300::PCIE_MSG_NUM_FRAMES; + // Transport for data stream + default_buff_args.send_frame_size = (xport_type == TX_DATA) + ? x300::PCIE_TX_DATA_FRAME_SIZE + : x300::PCIE_MSG_FRAME_SIZE; - default_buff_args.num_recv_frames = - (xport_type == RX_DATA) - ? x300::PCIE_RX_DATA_NUM_FRAMES - : x300::PCIE_MSG_NUM_FRAMES; + default_buff_args.recv_frame_size = (xport_type == RX_DATA) + ? x300::PCIE_RX_DATA_FRAME_SIZE + : x300::PCIE_MSG_FRAME_SIZE; + + default_buff_args.num_send_frames = (xport_type == TX_DATA) + ? x300::PCIE_TX_DATA_NUM_FRAMES + : x300::PCIE_MSG_NUM_FRAMES; + + default_buff_args.num_recv_frames = (xport_type == RX_DATA) + ? x300::PCIE_RX_DATA_NUM_FRAMES + : x300::PCIE_MSG_NUM_FRAMES; xports.recv = nirio_zero_copy::make( - mb.rio_fpga_interface, dma_channel_num, - default_buff_args, xport_args); + mb.rio_fpga_interface, dma_channel_num, default_buff_args, xport_args); } xports.send = xports.recv; @@ -1344,23 +1332,27 @@ uhd::both_xports_t x300_impl::make_transport( // - Upper 16 bits: Destination address (e.g. 0.0) // - Lower 16 bits: DMA channel uint32_t router_config_word = (xports.recv_sid.get_dst() << 16) | dma_channel_num; - mb.rio_fpga_interface->get_kernel_proxy()->poke(PCIE_ROUTER_REG(0), router_config_word); + mb.rio_fpga_interface->get_kernel_proxy()->poke( + PCIE_ROUTER_REG(0), router_config_word); - //For the nirio transport, buffer size is depends on the frame size and num frames - xports.recv_buff_size = xports.recv->get_num_recv_frames() * xports.recv->get_recv_frame_size(); - xports.send_buff_size = xports.send->get_num_send_frames() * xports.send->get_send_frame_size(); + // For the nirio transport, buffer size is depends on the frame size and num + // frames + xports.recv_buff_size = + xports.recv->get_num_recv_frames() * xports.recv->get_recv_frame_size(); + xports.send_buff_size = + xports.send->get_num_send_frames() * xports.send->get_send_frame_size(); } else if (mb.xport_path == "eth") { // Decide on the IP/Interface pair based on the endpoint index - size_t &next_src_addr = - xport_type == TX_DATA ? mb.next_tx_src_addr : - xport_type == RX_DATA ? mb.next_rx_src_addr : - mb.next_src_addr; - x300_eth_conn_t conn = mb.eth_conns[next_src_addr]; - const uint32_t xbar_src_addr = - next_src_addr==0 ? x300::SRC_ADDR0 : x300::SRC_ADDR1; - const uint32_t xbar_src_dst = - conn.type==X300_IFACE_ETH0 ? x300::XB_DST_E0 : x300::XB_DST_E1; + size_t& next_src_addr = xport_type == TX_DATA + ? mb.next_tx_src_addr + : xport_type == RX_DATA ? mb.next_rx_src_addr + : mb.next_src_addr; + x300_eth_conn_t conn = mb.eth_conns[next_src_addr]; + const uint32_t xbar_src_addr = next_src_addr == 0 ? x300::SRC_ADDR0 + : x300::SRC_ADDR1; + const uint32_t xbar_src_dst = conn.type == X300_IFACE_ETH0 ? x300::XB_DST_E0 + : x300::XB_DST_E1; // Do not increment src addr for tx_data by default, using dual ethernet // with the DMA FIFO causes sequence errors to DMA FIFO bandwidth @@ -1373,119 +1365,125 @@ uhd::both_xports_t x300_impl::make_transport( xports.recv_sid = xports.send_sid.reversed(); // Set size and number of frames - size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size; - size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size; - default_buff_args.send_frame_size = std::min(system_max_send_frame_size, x300::ETH_MSG_FRAME_SIZE); - default_buff_args.recv_frame_size = std::min(system_max_recv_frame_size, x300::ETH_MSG_FRAME_SIZE); + size_t system_max_send_frame_size = (size_t)_max_frame_sizes.send_frame_size; + size_t system_max_recv_frame_size = (size_t)_max_frame_sizes.recv_frame_size; + default_buff_args.send_frame_size = + std::min(system_max_send_frame_size, x300::ETH_MSG_FRAME_SIZE); + default_buff_args.recv_frame_size = + std::min(system_max_recv_frame_size, x300::ETH_MSG_FRAME_SIZE); default_buff_args.send_buff_size = conn.link_rate / 50; // 20ms - default_buff_args.recv_buff_size = std::max(conn.link_rate / 50, x300::ETH_MSG_NUM_FRAMES * x300::ETH_MSG_FRAME_SIZE); // enough to hold greater of 20ms or number of msg frames - if (xport_type == TX_DATA) - { - size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_SEND_SIZE : x300::XGE_DATA_FRAME_SEND_SIZE; - default_buff_args.send_frame_size = args.cast<size_t>("send_frame_size", std::min(default_frame_size, system_max_send_frame_size)); - if (default_buff_args.send_frame_size > system_max_send_frame_size) - { + default_buff_args.recv_buff_size = std::max(conn.link_rate / 50, + x300::ETH_MSG_NUM_FRAMES + * x300::ETH_MSG_FRAME_SIZE); // enough to hold greater of 20ms or number + // of msg frames + if (xport_type == TX_DATA) { + size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_SEND_SIZE + : x300::XGE_DATA_FRAME_SEND_SIZE; + default_buff_args.send_frame_size = args.cast<size_t>("send_frame_size", + std::min(default_frame_size, system_max_send_frame_size)); + if (default_buff_args.send_frame_size > system_max_send_frame_size) { UHD_LOGGER_WARNING("X300") - << boost::format("Requested send_frame_size of %d exceeds the maximum allowed on the %s connection. Using %d.") - % default_buff_args.send_frame_size - % conn.addr - % system_max_send_frame_size - ; + << boost::format("Requested send_frame_size of %d exceeds the " + "maximum allowed on the %s connection. Using %d.") + % default_buff_args.send_frame_size % conn.addr + % system_max_send_frame_size; default_buff_args.send_frame_size = system_max_send_frame_size; } - } - else if (xport_type == RX_DATA) - { - size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_RECV_SIZE : x300::XGE_DATA_FRAME_RECV_SIZE; - default_buff_args.recv_frame_size = args.cast<size_t>("recv_frame_size", std::min(default_frame_size, system_max_recv_frame_size)); - if (default_buff_args.recv_frame_size > system_max_recv_frame_size) - { + } else if (xport_type == RX_DATA) { + size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_RECV_SIZE + : x300::XGE_DATA_FRAME_RECV_SIZE; + default_buff_args.recv_frame_size = args.cast<size_t>("recv_frame_size", + std::min(default_frame_size, system_max_recv_frame_size)); + if (default_buff_args.recv_frame_size > system_max_recv_frame_size) { UHD_LOGGER_WARNING("X300") - << boost::format("Requested recv_frame_size of %d exceeds the maximum allowed on the %s connection. Using %d.") - % default_buff_args.recv_frame_size - % conn.addr - % system_max_recv_frame_size - ; + << boost::format("Requested recv_frame_size of %d exceeds the " + "maximum allowed on the %s connection. Using %d.") + % default_buff_args.recv_frame_size % conn.addr + % system_max_recv_frame_size; default_buff_args.recv_frame_size = system_max_recv_frame_size; } - default_buff_args.num_recv_frames = 2; // set some buffers so the offload thread actually offloads the socket I/O + default_buff_args.num_recv_frames = + 2; // set some buffers so the offload thread actually offloads the socket + // I/O } - //make a new transport - fpga has no idea how to talk to us on this yet + // make a new transport - fpga has no idea how to talk to us on this yet udp_zero_copy::buff_params buff_params; - xports.recv = udp_zero_copy::make( - conn.addr, - BOOST_STRINGIZE(X300_VITA_UDP_PORT), - default_buff_args, - buff_params, - xport_args); + xports.recv = udp_zero_copy::make(conn.addr, + BOOST_STRINGIZE(X300_VITA_UDP_PORT), + default_buff_args, + buff_params, + xport_args); // Create a threaded transport for the receive chain only // Note that this shouldn't affect PCIe if (xport_type == RX_DATA) { xports.recv = zero_copy_recv_offload::make( - xports.recv, - x300::RECV_OFFLOAD_BUFFER_TIMEOUT - ); + xports.recv, x300::RECV_OFFLOAD_BUFFER_TIMEOUT); } xports.send = xports.recv; - //For the UDP transport the buffer size is the size of the socket buffer - //in the kernel + // For the UDP transport the buffer size is the size of the socket buffer + // in the kernel xports.recv_buff_size = buff_params.recv_buff_size; xports.send_buff_size = buff_params.send_buff_size; - //clear the ethernet dispatcher's udp port - //NOT clearing this, the dispatcher is now intelligent + // clear the ethernet dispatcher's udp port + // NOT clearing this, the dispatcher is now intelligent //_zpu_ctrl->poke32(SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT0+8+3)), 0); - //send a mini packet with SID into the ZPU - //ZPU will reprogram the ethernet framer - UHD_LOGGER_DEBUG("X300") << "programming packet for new xport on " - << conn.addr << " sid " << xports.send_sid ; - //YES, get a __send__ buffer from the __recv__ socket + // send a mini packet with SID into the ZPU + // ZPU will reprogram the ethernet framer + UHD_LOGGER_DEBUG("X300") << "programming packet for new xport on " << conn.addr + << " sid " << xports.send_sid; + // YES, get a __send__ buffer from the __recv__ socket //-- this is the only way to program the framer for recv: managed_send_buffer::sptr buff = xports.recv->get_send_buff(); - buff->cast<uint32_t *>()[0] = 0; //eth dispatch looks for != 0 - buff->cast<uint32_t *>()[1] = uhd::htonx(xports.send_sid.get()); + buff->cast<uint32_t*>()[0] = 0; // eth dispatch looks for != 0 + buff->cast<uint32_t*>()[1] = uhd::htonx(xports.send_sid.get()); buff->commit(8); buff.reset(); - //reprogram the ethernet dispatcher's udp port (should be safe to always set) - UHD_LOGGER_TRACE("X300") - << "reprogram the ethernet dispatcher's udp port" ; - mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT0+8+3)), X300_VITA_UDP_PORT); - mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT1+8+3)), X300_VITA_UDP_PORT); + // reprogram the ethernet dispatcher's udp port (should be safe to always set) + UHD_LOGGER_TRACE("X300") << "reprogram the ethernet dispatcher's udp port"; + mb.zpu_ctrl->poke32( + SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT0 + 8 + 3)), X300_VITA_UDP_PORT); + mb.zpu_ctrl->poke32( + SR_ADDR(SET0_BASE, (ZPU_SR_ETHINT1 + 8 + 3)), X300_VITA_UDP_PORT); - //Do a peek to an arbitrary address to guarantee that the - //ethernet framer has been programmed before we return. + // Do a peek to an arbitrary address to guarantee that the + // ethernet framer has been programmed before we return. mb.zpu_ctrl->peek32(0); } return xports; } -uhd::sid_t x300_impl::allocate_sid( - mboard_members_t &mb, - const uhd::sid_t &address, - const uint32_t src_addr, - const uint32_t src_dst -) { +uhd::sid_t x300_impl::allocate_sid(mboard_members_t& mb, + const uhd::sid_t& address, + const uint32_t src_addr, + const uint32_t src_dst) +{ uhd::sid_t sid = address; sid.set_src_addr(src_addr); - sid.set_src_endpoint(_sid_framer++); //increment for next setup + sid.set_src_endpoint(_sid_framer++); // increment for next setup // TODO Move all of this setup_mb() // Program the X300 to recognise it's own local address. mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_XB_LOCAL), address.get_dst_addr()); - // Program CAM entry for outgoing packets matching a X300 resource (for example a Radio) - // This type of packet matches the XB_LOCAL address and is looked up in the upper half of the CAM - mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 256 + address.get_dst_endpoint()), address.get_dst_xbarport()); + // Program CAM entry for outgoing packets matching a X300 resource (for example a + // Radio) This type of packet matches the XB_LOCAL address and is looked up in the + // upper half of the CAM + mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 256 + address.get_dst_endpoint()), + address.get_dst_xbarport()); // Program CAM entry for returning packets to us (for example GR host via Eth0) - // This type of packet does not match the XB_LOCAL address and is looked up in the lower half of the CAM + // This type of packet does not match the XB_LOCAL address and is looked up in the + // lower half of the CAM mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, 0 + src_addr), src_dst); - UHD_LOGGER_TRACE("X300") << "done router config for sid " << sid ; + UHD_LOGGER_TRACE("X300") << "done router config for sid " << sid; return sid; } @@ -1493,95 +1491,123 @@ uhd::sid_t x300_impl::allocate_sid( /*********************************************************************** * clock and time control logic **********************************************************************/ -void x300_impl::set_time_source_out(mboard_members_t &mb, const bool enb) +void x300_impl::set_time_source_out(mboard_members_t& mb, const bool enb) { - mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_OUT_EN, enb?1:0); + mb.fw_regmap->clock_ctrl_reg.write( + fw_regmap_t::clk_ctrl_reg_t::PPS_OUT_EN, enb ? 1 : 0); } -void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source) +void x300_impl::update_clock_source(mboard_members_t& mb, const std::string& source) { - //Optimize for the case when the current source is internal and we are trying - //to set it to internal. This is the only case where we are guaranteed that - //the clock has not gone away so we can skip setting the MUX and reseting the LMK. - const bool reconfigure_clks = (mb.current_refclk_src != "internal") or (source != "internal"); + // Optimize for the case when the current source is internal and we are trying + // to set it to internal. This is the only case where we are guaranteed that + // the clock has not gone away so we can skip setting the MUX and reseting the LMK. + const bool reconfigure_clks = (mb.current_refclk_src != "internal") + or (source != "internal"); if (reconfigure_clks) { - //Update the clock MUX on the motherboard to select the requested source + // Update the clock MUX on the motherboard to select the requested source if (source == "internal") { - mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); + mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, + fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 1); } else if (source == "external") { - mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); + mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, + fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 0); } else if (source == "gpsdo") { - mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); + mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::CLK_SOURCE, + fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); mb.fw_regmap->clock_ctrl_reg.set(fw_regmap_t::clk_ctrl_reg_t::TCXO_EN, 0); } else { throw uhd::key_error("update_clock_source: unknown source: " + source); } mb.fw_regmap->clock_ctrl_reg.flush(); - //Reset the LMK to make sure it re-locks to the new reference + // Reset the LMK to make sure it re-locks to the new reference mb.clock->reset_clocks(); } - //Wait for the LMK to lock (always, as a sanity check that the clock is useable) - //* Currently the LMK can take as long as 30 seconds to lock to a reference but we don't + // Wait for the LMK to lock (always, as a sanity check that the clock is useable) + //* Currently the LMK can take as long as 30 seconds to lock to a reference but we + // don't //* want to wait that long during initialization. - //TODO: Need to verify timeout and settings to make sure lock can be achieved in < 1.0 seconds + // TODO: Need to verify timeout and settings to make sure lock can be achieved in + // < 1.0 seconds double timeout = mb.initialization_done ? 30.0 : 1.0; - //The programming code in x300_clock_ctrl is not compatible with revs <= 4 and may - //lead to locking issues. So, disable the ref-locked check for older (unsupported) boards. + // The programming code in x300_clock_ctrl is not compatible with revs <= 4 and may + // lead to locking issues. So, disable the ref-locked check for older (unsupported) + // boards. if (mb.hw_rev > 4) { - if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout)) { - //failed to lock on reference + if (not wait_for_clk_locked( + mb, fw_regmap_t::clk_status_reg_t::LMK_LOCK, timeout)) { + // failed to lock on reference if (mb.initialization_done) { - throw uhd::runtime_error((boost::format("Reference Clock PLL failed to lock to %s source.") % source).str()); + throw uhd::runtime_error( + (boost::format("Reference Clock PLL failed to lock to %s source.") + % source) + .str()); } else { - //TODO: Re-enable this warning when we figure out a reliable lock time - //UHD_LOGGER_WARNING("X300") << "Reference clock failed to lock to " + source + " during device initialization. " << - // "Check for the lock before operation or ignore this warning if using another clock source." ; + // TODO: Re-enable this warning when we figure out a reliable lock time + // UHD_LOGGER_WARNING("X300") << "Reference clock failed to lock to " + + // source + " during device initialization. " << + // "Check for the lock before operation or ignore this warning if using + // another clock source." ; } } } if (reconfigure_clks) { - //Reset the radio clock PLL in the FPGA - mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), ZPU_SR_SW_RST_RADIO_CLK_PLL); + // Reset the radio clock PLL in the FPGA + mb.zpu_ctrl->poke32( + SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), ZPU_SR_SW_RST_RADIO_CLK_PLL); mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), 0); - //Wait for radio clock PLL to lock - if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK, 0.01)) { - throw uhd::runtime_error((boost::format("Reference Clock PLL in FPGA failed to lock to %s source.") % source).str()); + // Wait for radio clock PLL to lock + if (not wait_for_clk_locked( + mb, fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK, 0.01)) { + throw uhd::runtime_error( + (boost::format("Reference Clock PLL in FPGA failed to lock to %s source.") + % source) + .str()); } - //Reset the IDELAYCTRL used to calibrate the data interface delays - mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), ZPU_SR_SW_RST_ADC_IDELAYCTRL); + // Reset the IDELAYCTRL used to calibrate the data interface delays + mb.zpu_ctrl->poke32( + SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), ZPU_SR_SW_RST_ADC_IDELAYCTRL); mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_SW_RST), 0); - //Wait for the ADC IDELAYCTRL to be ready - if (not wait_for_clk_locked(mb, fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK, 0.01)) { - throw uhd::runtime_error((boost::format("ADC Calibration Clock in FPGA failed to lock to %s source.") % source).str()); + // Wait for the ADC IDELAYCTRL to be ready + if (not wait_for_clk_locked( + mb, fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK, 0.01)) { + throw uhd::runtime_error( + (boost::format( + "ADC Calibration Clock in FPGA failed to lock to %s source.") + % source) + .str()); } // Reset ADCs and DACs - for(rfnoc::x300_radio_ctrl_impl::sptr r: mb.radios) { + for (rfnoc::x300_radio_ctrl_impl::sptr r : mb.radios) { r->reset_codec(); } } - //Update cache value + // Update cache value mb.current_refclk_src = source; } -void x300_impl::update_time_source(mboard_members_t &mb, const std::string &source) +void x300_impl::update_time_source(mboard_members_t& mb, const std::string& source) { if (source == "internal") { - mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); + mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, + fw_regmap_t::clk_ctrl_reg_t::SRC_INTERNAL); } else if (source == "external") { - mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); + mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, + fw_regmap_t::clk_ctrl_reg_t::SRC_EXTERNAL); } else if (source == "gpsdo") { - mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); + mb.fw_regmap->clock_ctrl_reg.write(fw_regmap_t::clk_ctrl_reg_t::PPS_SELECT, + fw_regmap_t::clk_ctrl_reg_t::SRC_GPSDO); } else { throw uhd::key_error("update_time_source: unknown source: " + source); } @@ -1589,15 +1615,17 @@ void x300_impl::update_time_source(mboard_members_t &mb, const std::string &sour /* TODO - Implement intelligent PPS detection //check for valid pps if (!is_pps_present(mb)) { - throw uhd::runtime_error((boost::format("The %d PPS was not detected. Please check the PPS source and try again.") % source).str()); + throw uhd::runtime_error((boost::format("The %d PPS was not detected. Please + check the PPS source and try again.") % source).str()); } */ } -void x300_impl::sync_times(mboard_members_t &mb, const uhd::time_spec_t& t) +void x300_impl::sync_times(mboard_members_t& mb, const uhd::time_spec_t& t) { - std::vector<rfnoc::block_id_t> radio_ids = find_blocks<rfnoc::x300_radio_ctrl_impl>("Radio"); - for(const rfnoc::block_id_t &id: radio_ids) { + std::vector<rfnoc::block_id_t> radio_ids = + find_blocks<rfnoc::x300_radio_ctrl_impl>("Radio"); + for (const rfnoc::block_id_t& id : radio_ids) { get_block_ctrl<rfnoc::x300_radio_ctrl_impl>(id)->set_time_sync(t); } @@ -1608,9 +1636,8 @@ void x300_impl::sync_times(mboard_members_t &mb, const uhd::time_spec_t& t) bool x300_impl::wait_for_clk_locked(mboard_members_t& mb, uint32_t which, double timeout) { - const auto timeout_time = - std::chrono::steady_clock::now() - + std::chrono::milliseconds(int64_t(timeout * 1000)); + const auto timeout_time = std::chrono::steady_clock::now() + + std::chrono::milliseconds(int64_t(timeout * 1000)); do { if (mb.fw_regmap->clock_status_reg.read(which) == 1) { return true; @@ -1618,16 +1645,21 @@ bool x300_impl::wait_for_clk_locked(mboard_members_t& mb, uint32_t which, double std::this_thread::sleep_for(std::chrono::milliseconds(1)); } while (std::chrono::steady_clock::now() < timeout_time); - //Check one last time - return (mb.fw_regmap->clock_status_reg.read(which)==1); + // Check one last time + return (mb.fw_regmap->clock_status_reg.read(which) == 1); } sensor_value_t x300_impl::get_ref_locked(mboard_members_t& mb) { mb.fw_regmap->clock_status_reg.refresh(); - const bool lock = (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::LMK_LOCK)==1) && - (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK)==1) && - (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK)==1); + const bool lock = + (mb.fw_regmap->clock_status_reg.get(fw_regmap_t::clk_status_reg_t::LMK_LOCK) == 1) + && (mb.fw_regmap->clock_status_reg.get( + fw_regmap_t::clk_status_reg_t::RADIO_CLK_LOCK) + == 1) + && (mb.fw_regmap->clock_status_reg.get( + fw_regmap_t::clk_status_reg_t::IDELAYCTRL_LOCK) + == 1); return sensor_value_t("Ref", lock, "locked", "unlocked"); } @@ -1635,11 +1667,13 @@ bool x300_impl::is_pps_present(mboard_members_t& mb) { // The ZPU_RB_CLK_STATUS_PPS_DETECT bit toggles with each rising edge of the PPS. // We monitor it for up to 1.5 seconds looking for it to toggle. - uint32_t pps_detect = mb.fw_regmap->clock_status_reg.read(fw_regmap_t::clk_status_reg_t::PPS_DETECT); - for (int i = 0; i < 15; i++) - { + uint32_t pps_detect = + mb.fw_regmap->clock_status_reg.read(fw_regmap_t::clk_status_reg_t::PPS_DETECT); + for (int i = 0; i < 15; i++) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); - if (pps_detect != mb.fw_regmap->clock_status_reg.read(fw_regmap_t::clk_status_reg_t::PPS_DETECT)) + if (pps_detect + != mb.fw_regmap->clock_status_reg.read( + fw_regmap_t::clk_status_reg_t::PPS_DETECT)) return true; } return false; @@ -1658,22 +1692,18 @@ void x300_impl::claimer_loop(wb_iface::sptr iface) x300_impl::claim_status_t x300_impl::claim_status(wb_iface::sptr iface) { claim_status_t claim_status = CLAIMED_BY_OTHER; // Default to most restrictive - auto timeout_time = - std::chrono::steady_clock::now() - + std::chrono::seconds(1); - while (std::chrono::steady_clock::now() < timeout_time) - { - //If timed out, then device is definitely unclaimed - if (iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_STATUS)) == 0) - { + auto timeout_time = std::chrono::steady_clock::now() + std::chrono::seconds(1); + while (std::chrono::steady_clock::now() < timeout_time) { + // If timed out, then device is definitely unclaimed + if (iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_STATUS)) == 0) { claim_status = UNCLAIMED; break; } - //otherwise check claim src to determine if another thread with the same src has claimed the device + // otherwise check claim src to determine if another thread with the same src has + // claimed the device uint32_t hash = iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC)); - if (hash == 0) - { + if (hash == 0) { // A non-zero claim status and an empty hash means the claim might // be in the process of being released. This is possible because // older firmware takes a long time to update the status. Wait and @@ -1696,20 +1726,17 @@ void x300_impl::claim(wb_iface::sptr iface) bool x300_impl::try_to_claim(wb_iface::sptr iface, long timeout_ms) { const auto timeout_time = - std::chrono::steady_clock::now() - + std::chrono::milliseconds(timeout_ms); - while (1) - { + std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout_ms); + while (1) { claim_status_t status = claim_status(iface); - if (status == UNCLAIMED) - { + if (status == UNCLAIMED) { claim(iface); - // It takes the claimer 10ms to update status, so wait 20ms before verifying claim + // It takes the claimer 10ms to update status, so wait 20ms before verifying + // claim std::this_thread::sleep_for(std::chrono::milliseconds(20)); continue; } - if (status == CLAIMED_BY_US) - { + if (status == CLAIMED_BY_US) { break; } if (std::chrono::steady_clock::now() > timeout_time) { @@ -1730,57 +1757,62 @@ void x300_impl::release(wb_iface::sptr iface) /*********************************************************************** * Frame size detection **********************************************************************/ -x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &addr, - const frame_size_t &user_frame_size) +x300_impl::frame_size_t x300_impl::determine_max_frame_size( + const std::string& addr, const frame_size_t& user_frame_size) { - udp_simple::sptr udp = udp_simple::make_connected(addr, - BOOST_STRINGIZE(X300_MTU_DETECT_UDP_PORT)); + udp_simple::sptr udp = + udp_simple::make_connected(addr, BOOST_STRINGIZE(X300_MTU_DETECT_UDP_PORT)); - std::vector<uint8_t> buffer(std::max(user_frame_size.recv_frame_size, user_frame_size.send_frame_size)); - x300_mtu_t *request = reinterpret_cast<x300_mtu_t *>(&buffer.front()); - static const double echo_timeout = 0.020; //20 ms + std::vector<uint8_t> buffer( + std::max(user_frame_size.recv_frame_size, user_frame_size.send_frame_size)); + x300_mtu_t* request = reinterpret_cast<x300_mtu_t*>(&buffer.front()); + static const double echo_timeout = 0.020; // 20 ms - //test holler - check if its supported in this fw version + // test holler - check if its supported in this fw version request->flags = uhd::htonx<uint32_t>(X300_MTU_DETECT_ECHO_REQUEST); - request->size = uhd::htonx<uint32_t>(sizeof(x300_mtu_t)); + request->size = uhd::htonx<uint32_t>(sizeof(x300_mtu_t)); udp->send(boost::asio::buffer(buffer, sizeof(x300_mtu_t))); udp->recv(boost::asio::buffer(buffer), echo_timeout); if (!(uhd::ntohx<uint32_t>(request->flags) & X300_MTU_DETECT_ECHO_REPLY)) throw uhd::not_implemented_error("Holler protocol not implemented"); - //Reducing range of (min,max) by setting max value to 10gig max_frame_size as larger sizes are not supported + // Reducing range of (min,max) by setting max value to 10gig max_frame_size as larger + // sizes are not supported size_t min_recv_frame_size = sizeof(x300_mtu_t); - size_t max_recv_frame_size = std::min(user_frame_size.recv_frame_size, x300::DATA_FRAME_MAX_SIZE) & size_t(~3); + size_t max_recv_frame_size = + std::min(user_frame_size.recv_frame_size, x300::DATA_FRAME_MAX_SIZE) & size_t(~3); size_t min_send_frame_size = sizeof(x300_mtu_t); - size_t max_send_frame_size = std::min(user_frame_size.send_frame_size, x300::DATA_FRAME_MAX_SIZE) & size_t(~3); + size_t max_send_frame_size = + std::min(user_frame_size.send_frame_size, x300::DATA_FRAME_MAX_SIZE) & size_t(~3); UHD_LOGGER_DEBUG("X300") << "Determining maximum frame size... "; - while (min_recv_frame_size < max_recv_frame_size) - { - size_t test_frame_size = (max_recv_frame_size/2 + min_recv_frame_size/2 + 3) & ~3; + while (min_recv_frame_size < max_recv_frame_size) { + size_t test_frame_size = (max_recv_frame_size / 2 + min_recv_frame_size / 2 + 3) + & ~3; - request->flags = uhd::htonx<uint32_t>(X300_MTU_DETECT_ECHO_REQUEST); - request->size = uhd::htonx<uint32_t>(test_frame_size); - udp->send(boost::asio::buffer(buffer, sizeof(x300_mtu_t))); + request->flags = uhd::htonx<uint32_t>(X300_MTU_DETECT_ECHO_REQUEST); + request->size = uhd::htonx<uint32_t>(test_frame_size); + udp->send(boost::asio::buffer(buffer, sizeof(x300_mtu_t))); - size_t len = udp->recv(boost::asio::buffer(buffer), echo_timeout); + size_t len = udp->recv(boost::asio::buffer(buffer), echo_timeout); - if (len >= test_frame_size) - min_recv_frame_size = test_frame_size; - else - max_recv_frame_size = test_frame_size - 4; + if (len >= test_frame_size) + min_recv_frame_size = test_frame_size; + else + max_recv_frame_size = test_frame_size - 4; } - if(min_recv_frame_size < IP_PROTOCOL_MIN_MTU_SIZE-IP_PROTOCOL_UDP_PLUS_IP_HEADER) { - throw uhd::runtime_error("System receive MTU size is less than the minimum required by the IP protocol."); + if (min_recv_frame_size < IP_PROTOCOL_MIN_MTU_SIZE - IP_PROTOCOL_UDP_PLUS_IP_HEADER) { + throw uhd::runtime_error("System receive MTU size is less than the minimum " + "required by the IP protocol."); } - while (min_send_frame_size < max_send_frame_size) - { - size_t test_frame_size = (max_send_frame_size/2 + min_send_frame_size/2 + 3) & ~3; + while (min_send_frame_size < max_send_frame_size) { + size_t test_frame_size = (max_send_frame_size / 2 + min_send_frame_size / 2 + 3) + & ~3; request->flags = uhd::htonx<uint32_t>(X300_MTU_DETECT_ECHO_REQUEST); - request->size = uhd::htonx<uint32_t>(sizeof(x300_mtu_t)); + request->size = uhd::htonx<uint32_t>(sizeof(x300_mtu_t)); udp->send(boost::asio::buffer(buffer, test_frame_size)); size_t len = udp->recv(boost::asio::buffer(buffer), echo_timeout); @@ -1793,8 +1825,9 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &a max_send_frame_size = test_frame_size - 4; } - if(min_send_frame_size < IP_PROTOCOL_MIN_MTU_SIZE-IP_PROTOCOL_UDP_PLUS_IP_HEADER) { - throw uhd::runtime_error("System send MTU size is less than the minimum required by the IP protocol."); + if (min_send_frame_size < IP_PROTOCOL_MIN_MTU_SIZE - IP_PROTOCOL_UDP_PLUS_IP_HEADER) { + throw uhd::runtime_error( + "System send MTU size is less than the minimum required by the IP protocol."); } frame_size_t frame_size; @@ -1803,8 +1836,8 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &a // of the recv and send frame sizes. frame_size.recv_frame_size = std::min(min_recv_frame_size, min_send_frame_size); frame_size.send_frame_size = std::min(min_recv_frame_size, min_send_frame_size); - UHD_LOGGER_INFO("X300") - << "Maximum frame size: " << frame_size.send_frame_size << " bytes."; + UHD_LOGGER_INFO("X300") << "Maximum frame size: " << frame_size.send_frame_size + << " bytes."; return frame_size; } @@ -1812,10 +1845,8 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &a * compat checks **********************************************************************/ -void x300_impl::check_fw_compat( - const fs_path &mb_path, - const mboard_members_t &members -) { +void x300_impl::check_fw_compat(const fs_path& mb_path, const mboard_members_t& members) +{ auto iface = members.zpu_ctrl; const uint32_t compat_num = iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_COMPAT_NUM)); @@ -1826,78 +1857,75 @@ void x300_impl::check_fw_compat( const std::string image_loader_path = (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); const std::string image_loader_cmd = - str(boost::format("\"%s\" --args=\"type=x300,%s=%s\"") - % image_loader_path - % (members.xport_path == "eth" ? "addr" - : "resource") - % members.get_pri_eth().addr); - - throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number %d, but got %d:\n" - "The FPGA/firmware image on your device is not compatible with this host code build.\n" - "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 image loader utility. " - "Use this command:\n\n%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_FW_COMPAT_MAJOR) % compat_major - % print_utility_error("uhd_images_downloader.py") - % image_loader_cmd)); + str(boost::format("\"%s\" --args=\"type=x300,%s=%s\"") % image_loader_path + % (members.xport_path == "eth" ? "addr" : "resource") + % members.get_pri_eth().addr); + + throw uhd::runtime_error( + str(boost::format( + "Expected firmware compatibility number %d, but got %d:\n" + "The FPGA/firmware image on your device is not compatible with this " + "host code build.\n" + "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 image loader utility. " + "Use this command:\n\n%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_FW_COMPAT_MAJOR) % compat_major + % print_utility_error("uhd_images_downloader.py") % image_loader_cmd)); } _tree->create<std::string>(mb_path / "fw_version") .set(str(boost::format("%u.%u") % compat_major % compat_minor)); } -void x300_impl::check_fpga_compat(const fs_path &mb_path, const mboard_members_t &members) +void x300_impl::check_fpga_compat(const fs_path& mb_path, const mboard_members_t& members) { uint32_t compat_num = members.zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_COMPAT_NUM)); uint32_t compat_major = (compat_num >> 16); uint32_t compat_minor = (compat_num & 0xffff); - if (compat_major != X300_FPGA_COMPAT_MAJOR) - { - std::string image_loader_path = (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); - std::string image_loader_cmd = str(boost::format("\"%s\" --args=\"type=x300,%s=%s\"") - % image_loader_path - % (members.xport_path == "eth" ? "addr" - : "resource") - % members.get_pri_eth().addr); - - throw uhd::runtime_error(str(boost::format( - "Expected FPGA compatibility number %d, but got %d:\n" - "The FPGA image on your device is not compatible with this host code build.\n" - "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 image loader utility. Use this command:\n\n%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_utility_error("uhd_images_downloader.py") - % image_loader_cmd)); + if (compat_major != X300_FPGA_COMPAT_MAJOR) { + std::string image_loader_path = + (fs::path(uhd::get_pkg_path()) / "bin" / "uhd_image_loader").string(); + std::string image_loader_cmd = + str(boost::format("\"%s\" --args=\"type=x300,%s=%s\"") % image_loader_path + % (members.xport_path == "eth" ? "addr" : "resource") + % members.get_pri_eth().addr); + + throw uhd::runtime_error( + str(boost::format( + "Expected FPGA compatibility number %d, but got %d:\n" + "The FPGA image on your device is not compatible with this host code " + "build.\n" + "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 image loader utility. Use this " + "command:\n\n%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_utility_error("uhd_images_downloader.py") % image_loader_cmd)); } - _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u") - % compat_major % compat_minor)); - - const uint32_t git_hash = members.zpu_ctrl->peek32(SR_ADDR(SET0_BASE, - ZPU_RB_GIT_HASH)); - const std::string git_hash_str = str( - boost::format("%07x%s") - % (git_hash & 0x0FFFFFFF) - % ((git_hash & 0xF0000000) ? "-dirty" : "") - ); + _tree->create<std::string>(mb_path / "fpga_version") + .set(str(boost::format("%u.%u") % compat_major % compat_minor)); + + const uint32_t git_hash = + members.zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_GIT_HASH)); + const std::string git_hash_str = str(boost::format("%07x%s") % (git_hash & 0x0FFFFFFF) + % ((git_hash & 0xF0000000) ? "-dirty" : "")); _tree->create<std::string>(mb_path / "fpga_version_hash").set(git_hash_str); UHD_LOG_DEBUG("X300", "Using FPGA version: " << compat_major << "." << compat_minor - << " git hash: " << git_hash_str); + << " git hash: " << git_hash_str); } x300_impl::x300_mboard_t x300_impl::get_mb_type_from_pcie( - const std::string& resource, const std::string& rpc_port) + const std::string& resource, const std::string& rpc_port) { - //Detect the PCIe product ID to distinguish between X300 and X310 + // Detect the PCIe product ID to distinguish between X300 and X310 nirio_status status = NiRio_Status_Success; uint32_t pid; niriok_proxy::sptr discovery_proxy = @@ -1911,20 +1939,18 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_pcie( } } - UHD_LOGGER_WARNING("X300") << - "NI-RIO Error -- unable to determine motherboard type!"; + UHD_LOGGER_WARNING("X300") << "NI-RIO Error -- unable to determine motherboard type!"; return UNKNOWN; } x300_impl::x300_mboard_t x300_impl::get_mb_type_from_eeprom( - const uhd::usrp::mboard_eeprom_t& mb_eeprom) + const uhd::usrp::mboard_eeprom_t& mb_eeprom) { - if (not mb_eeprom["product"].empty()) - { + if (not mb_eeprom["product"].empty()) { uint16_t product_num = 0; try { product_num = boost::lexical_cast<uint16_t>(mb_eeprom["product"]); - } catch (const boost::bad_lexical_cast &) { + } catch (const boost::bad_lexical_cast&) { product_num = 0; } diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 9de68a697..c58440d54 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -8,36 +8,34 @@ #ifndef INCLUDED_X300_IMPL_HPP #define INCLUDED_X300_IMPL_HPP -#include "x300_radio_ctrl_impl.hpp" +#include "../device3/device3_impl.hpp" #include "x300_clock_ctrl.hpp" -#include "x300_fw_common.h" -#include "x300_regs.hpp" #include "x300_defaults.hpp" #include "x300_device_args.hpp" - -#include "../device3/device3_impl.hpp" +#include "x300_fw_common.h" +#include "x300_radio_ctrl_impl.hpp" +#include "x300_regs.hpp" #include <uhd/property_tree.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> -#include <uhd/usrp/subdev_spec.hpp> -#include <uhd/types/sensors.hpp> -#include <uhd/transport/udp_simple.hpp> //mtu -#include <uhd/usrp/gps_ctrl.hpp> +#include <uhd/transport/muxed_zero_copy_if.hpp> #include <uhd/transport/nirio/niusrprio_session.h> +#include <uhd/transport/udp_simple.hpp> //mtu #include <uhd/transport/vrt_if_packet.hpp> -#include <uhd/transport/muxed_zero_copy_if.hpp> +#include <uhd/types/sensors.hpp> +#include <uhd/usrp/gps_ctrl.hpp> +#include <uhd/usrp/mboard_eeprom.hpp> +#include <uhd/usrp/subdev_spec.hpp> ///////////// RFNOC ///////////////////// #include <uhd/rfnoc/block_ctrl.hpp> ///////////// RFNOC ///////////////////// -#include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> #include <uhdlib/usrp/common/recv_packet_demuxer_3000.hpp> +#include <uhdlib/usrp/cores/i2c_core_100_wb32.hpp> #include <boost/dynamic_bitset.hpp> #include <boost/weak_ptr.hpp> #include <atomic> // Ethernet ports -enum x300_eth_iface_t -{ +enum x300_eth_iface_t { X300_IFACE_NONE = 0, X300_IFACE_ETH0 = 1, X300_IFACE_ETH1 = 2, @@ -53,47 +51,46 @@ struct x300_eth_conn_t uhd::uart_iface::sptr x300_make_uart_iface(uhd::wb_iface::sptr iface); -uhd::wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors = true); -uhd::wb_iface::sptr x300_make_ctrl_iface_pcie(uhd::niusrprio::niriok_proxy::sptr drv_proxy, bool enable_errors = true); +uhd::wb_iface::sptr x300_make_ctrl_iface_enet( + uhd::transport::udp_simple::sptr udp, bool enable_errors = true); +uhd::wb_iface::sptr x300_make_ctrl_iface_pcie( + uhd::niusrprio::niriok_proxy::sptr drv_proxy, bool enable_errors = true); -uhd::device_addrs_t x300_find(const uhd::device_addr_t &hint_); +uhd::device_addrs_t x300_find(const uhd::device_addr_t& hint_); class x300_impl : public uhd::usrp::device3_impl { public: - - x300_impl(const uhd::device_addr_t &); - void setup_mb(const size_t which, const uhd::device_addr_t &); + x300_impl(const uhd::device_addr_t&); + void setup_mb(const size_t which, const uhd::device_addr_t&); ~x300_impl(void); // device claim functions - enum claim_status_t {UNCLAIMED, CLAIMED_BY_US, CLAIMED_BY_OTHER}; + enum claim_status_t { UNCLAIMED, CLAIMED_BY_US, CLAIMED_BY_OTHER }; static claim_status_t claim_status(uhd::wb_iface::sptr iface); static void claim(uhd::wb_iface::sptr iface); static bool try_to_claim(uhd::wb_iface::sptr iface, long timeout = 2000); static void release(uhd::wb_iface::sptr iface); - enum x300_mboard_t { - USRP_X300_MB, USRP_X310_MB, USRP_X310_MB_NI_2974, UNKNOWN - }; - static x300_mboard_t get_mb_type_from_pcie(const std::string& resource, const std::string& rpc_port); - static x300_mboard_t get_mb_type_from_eeprom(const uhd::usrp::mboard_eeprom_t& mb_eeprom); + enum x300_mboard_t { USRP_X300_MB, USRP_X310_MB, USRP_X310_MB_NI_2974, UNKNOWN }; + static x300_mboard_t get_mb_type_from_pcie( + const std::string& resource, const std::string& rpc_port); + static x300_mboard_t get_mb_type_from_eeprom( + const uhd::usrp::mboard_eeprom_t& mb_eeprom); //! Read out the on-board EEPROM, convert to dict, and return static uhd::usrp::mboard_eeprom_t get_mb_eeprom(uhd::i2c_iface::sptr i2c); protected: - void subdev_to_blockid( - const uhd::usrp::subdev_spec_pair_t &spec, const size_t mb_i, - uhd::rfnoc::block_id_t &block_id, uhd::device_addr_t &block_args - ); + void subdev_to_blockid(const uhd::usrp::subdev_spec_pair_t& spec, + const size_t mb_i, + uhd::rfnoc::block_id_t& block_id, + uhd::device_addr_t& block_args); uhd::usrp::subdev_spec_pair_t blockid_to_subdev( - const uhd::rfnoc::block_id_t &blockid, const uhd::device_addr_t &block_args - ); + const uhd::rfnoc::block_id_t& blockid, const uhd::device_addr_t& block_args); private: - - //vector of member objects per motherboard + // vector of member objects per motherboard struct mboard_members_t { uhd::usrp::x300::x300_device_args_t args; @@ -109,7 +106,7 @@ private: // Discover the ethernet connections per motherboard void discover_eth(const uhd::usrp::mboard_eeprom_t mb_eeprom, - const std::vector<std::string> &ip_addrs); + const std::vector<std::string>& ip_addrs); // Get the primary ethernet connection inline const x300_eth_conn_t& get_pri_eth() const @@ -120,20 +117,20 @@ private: uhd::device_addr_t send_args; uhd::device_addr_t recv_args; bool if_pkt_is_big_endian; - uhd::niusrprio::niusrprio_session::sptr rio_fpga_interface; + uhd::niusrprio::niusrprio_session::sptr rio_fpga_interface; - //perifs in the zpu + // perifs in the zpu uhd::wb_iface::sptr zpu_ctrl; spi_core_3000::sptr zpu_spi; i2c_core_100_wb32::sptr zpu_i2c; - //other perifs on mboard + // other perifs on mboard x300_clock_ctrl::sptr clock; uhd::gps_ctrl::sptr gps; uhd::usrp::x300::fw_regmap_t::sptr fw_regmap; - //which FPGA image is loaded + // which FPGA image is loaded std::string loaded_fpga_image; size_t hw_rev; @@ -154,25 +151,23 @@ private: * * Note the SID is always the transmit SID (i.e. from host to device). */ - uint32_t allocate_pcie_dma_chan(const uhd::sid_t &tx_sid, const xport_type_t xport_type); + uint32_t allocate_pcie_dma_chan( + const uhd::sid_t& tx_sid, const xport_type_t xport_type); }; std::vector<mboard_members_t> _mb; - //task for periodically reclaiming the device from others + // task for periodically reclaiming the device from others void claimer_loop(uhd::wb_iface::sptr); std::atomic<size_t> _sid_framer; - uhd::sid_t allocate_sid( - mboard_members_t &mb, - const uhd::sid_t &address, + uhd::sid_t allocate_sid(mboard_members_t& mb, + const uhd::sid_t& address, const uint32_t src_addr, const uint32_t src_dst); - uhd::both_xports_t make_transport( - const uhd::sid_t &address, + uhd::both_xports_t make_transport(const uhd::sid_t& address, const xport_type_t xport_type, - const uhd::device_addr_t& args - ); + const uhd::device_addr_t& args); struct frame_size_t { @@ -186,24 +181,25 @@ private: * to the device and see which packet sizes actually work. This way, we can take * switches etc. into account which might live between the device and the host. */ - frame_size_t determine_max_frame_size(const std::string &addr, const frame_size_t &user_mtu); + frame_size_t determine_max_frame_size( + const std::string& addr, const frame_size_t& user_mtu); //////////////////////////////////////////////////////////////////// // - //Caching for transport interface re-use -- like sharing a DMA. - //The cache is optionally used by make_transport by use-case. - //The cache maps an ID string to a transport-ish object. - //The ID string identifies a purpose for the transport. + // Caching for transport interface re-use -- like sharing a DMA. + // The cache is optionally used by make_transport by use-case. + // The cache maps an ID string to a transport-ish object. + // The ID string identifies a purpose for the transport. // - //For recv, there is a demux cache, which maps a ID string - //to a recv demux object. When a demux is used, the underlying transport - //must never be used outside of the demux. Use demux->make_proxy(sid). + // For recv, there is a demux cache, which maps a ID string + // to a recv demux object. When a demux is used, the underlying transport + // must never be used outside of the demux. Use demux->make_proxy(sid). // uhd::dict<std::string, uhd::usrp::recv_packet_demuxer_3000::sptr> _demux_cache; // - //For send, there is a shared send xport, which maps an ID string - //to a transport capable of sending buffers. Send transports - //can be shared amongst multiple callers, unlike recv. + // For send, there is a shared send xport, which maps an ID string + // to a transport capable of sending buffers. Send transports + // can be shared amongst multiple callers, unlike recv. // uhd::dict<std::string, uhd::transport::zero_copy_if::sptr> _send_cache; // @@ -214,10 +210,10 @@ private: bool _ignore_cal_file; void update_clock_control(mboard_members_t&); - void initialize_clock_control(mboard_members_t &mb); + void initialize_clock_control(mboard_members_t& mb); void set_time_source_out(mboard_members_t&, const bool); - void update_clock_source(mboard_members_t&, const std::string &); - void update_time_source(mboard_members_t&, const std::string &); + void update_clock_source(mboard_members_t&, const std::string&); + void update_time_source(mboard_members_t&, const std::string&); void sync_times(mboard_members_t&, const uhd::time_spec_t&); uhd::sensor_value_t get_ref_locked(mboard_members_t& mb); @@ -225,13 +221,10 @@ private: bool is_pps_present(mboard_members_t& mb); //! Write the contents of an EEPROM dict to the on-board EEPROM - void set_mb_eeprom( - uhd::i2c_iface::sptr i2c, - const uhd::usrp::mboard_eeprom_t & - ); + void set_mb_eeprom(uhd::i2c_iface::sptr i2c, const uhd::usrp::mboard_eeprom_t&); - void check_fw_compat(const uhd::fs_path &mb_path, const mboard_members_t &members); - void check_fpga_compat(const uhd::fs_path &mb_path, const mboard_members_t &members); + void check_fw_compat(const uhd::fs_path& mb_path, const mboard_members_t& members); + void check_fpga_compat(const uhd::fs_path& mb_path, const mboard_members_t& members); /// More IO stuff uhd::device_addr_t get_tx_hints(size_t mb_index); diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index d833b3715..07e93173a 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -5,8 +5,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later // -#include "x300_regs.hpp" #include "x300_impl.hpp" +#include "x300_regs.hpp" using namespace uhd; using namespace uhd::usrp; @@ -35,7 +35,7 @@ void x300_impl::post_streamer_hooks(direction_t dir) // Loop through all tx streamers. Find all radios connected to one // streamer. Sync those. - for(const boost::weak_ptr<uhd::tx_streamer> &streamer_w: _tx_streamers.vals()) { + for (const boost::weak_ptr<uhd::tx_streamer>& streamer_w : _tx_streamers.vals()) { const boost::shared_ptr<device3_send_packet_streamer> streamer = boost::dynamic_pointer_cast<device3_send_packet_streamer>(streamer_w.lock()); if (not streamer) { @@ -43,13 +43,15 @@ void x300_impl::post_streamer_hooks(direction_t dir) } std::vector<rfnoc::x300_radio_ctrl_impl::sptr> radio_ctrl_blks = - streamer->get_terminator()->find_downstream_node<rfnoc::x300_radio_ctrl_impl>(); + streamer->get_terminator() + ->find_downstream_node<rfnoc::x300_radio_ctrl_impl>(); try { - //UHD_LOGGER_INFO("X300") << "[X300] syncing " << radio_ctrl_blks.size() << " radios " ; + // UHD_LOGGER_INFO("X300") << "[X300] syncing " << radio_ctrl_blks.size() << " + // radios " ; rfnoc::x300_radio_ctrl_impl::synchronize_dacs(radio_ctrl_blks); - } - catch(const uhd::io_error &ex) { - throw uhd::io_error(str(boost::format("Failed to sync DACs! %s ") % ex.what())); + } catch (const uhd::io_error& ex) { + throw uhd::io_error( + str(boost::format("Failed to sync DACs! %s ") % ex.what())); } } } diff --git a/host/lib/usrp/x300/x300_mb_eeprom.cpp b/host/lib/usrp/x300/x300_mb_eeprom.cpp index b3ebf6101..663f4c9db 100644 --- a/host/lib/usrp/x300/x300_mb_eeprom.cpp +++ b/host/lib/usrp/x300/x300_mb_eeprom.cpp @@ -5,38 +5,38 @@ // #include "x300_impl.hpp" -#include <uhdlib/utils/eeprom_utils.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> #include <uhd/types/serial.hpp> +#include <uhd/usrp/mboard_eeprom.hpp> +#include <uhdlib/utils/eeprom_utils.hpp> namespace { - const uint8_t X300_EEPROM_ADDR = 0x50; - - struct x300_eeprom_map - { - //identifying numbers - unsigned char revision[2]; - unsigned char product[2]; - unsigned char revision_compat[2]; - uint8_t _pad0[2]; - - //all the mac addrs - uint8_t mac_addr0[6]; - uint8_t _pad1[2]; - uint8_t mac_addr1[6]; - uint8_t _pad2[2]; - - //all the IP addrs - uint32_t gateway; - uint32_t subnet[4]; - uint32_t ip_addr[4]; - uint8_t _pad3[16]; - - //names and serials - unsigned char name[NAME_MAX_LEN]; - unsigned char serial[SERIAL_LEN]; - }; -} +const uint8_t X300_EEPROM_ADDR = 0x50; + +struct x300_eeprom_map +{ + // identifying numbers + unsigned char revision[2]; + unsigned char product[2]; + unsigned char revision_compat[2]; + uint8_t _pad0[2]; + + // all the mac addrs + uint8_t mac_addr0[6]; + uint8_t _pad1[2]; + uint8_t mac_addr1[6]; + uint8_t _pad2[2]; + + // all the IP addrs + uint32_t gateway; + uint32_t subnet[4]; + uint32_t ip_addr[4]; + uint8_t _pad3[16]; + + // names and serials + unsigned char name[NAME_MAX_LEN]; + unsigned char serial[SERIAL_LEN]; +}; +} // namespace using namespace uhd; using uhd::usrp::mboard_eeprom_t; @@ -51,170 +51,150 @@ mboard_eeprom_t x300_impl::get_mb_eeprom(uhd::i2c_iface::sptr iface) return mb_eeprom; } - //extract the revision number + // extract the revision number mb_eeprom["revision"] = uint16_bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, revision), - bytes.begin() + (offsetof(x300_eeprom_map, revision)+2)) - ); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, revision), + bytes.begin() + (offsetof(x300_eeprom_map, revision) + 2))); - //extract the revision compat number + // extract the revision compat number mb_eeprom["revision_compat"] = uint16_bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, revision_compat), - bytes.begin() + (offsetof(x300_eeprom_map, revision_compat)+2)) - ); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, revision_compat), + bytes.begin() + (offsetof(x300_eeprom_map, revision_compat) + 2))); - //extract the product code + // extract the product code mb_eeprom["product"] = uint16_bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, product), - bytes.begin() + (offsetof(x300_eeprom_map, product)+2)) - ); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, product), + bytes.begin() + (offsetof(x300_eeprom_map, product) + 2))); - //extract the mac addresses + // extract the mac addresses mb_eeprom["mac-addr0"] = mac_addr_t::from_bytes( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, mac_addr0), - bytes.begin() + (offsetof(x300_eeprom_map, mac_addr0)+6)) - ).to_string(); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, mac_addr0), + bytes.begin() + (offsetof(x300_eeprom_map, mac_addr0) + 6))) + .to_string(); mb_eeprom["mac-addr1"] = mac_addr_t::from_bytes( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, mac_addr1), - bytes.begin() + (offsetof(x300_eeprom_map, mac_addr1)+6)) - ).to_string(); + byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, mac_addr1), + bytes.begin() + (offsetof(x300_eeprom_map, mac_addr1) + 6))) + .to_string(); - //extract the ip addresses + // extract the ip addresses boost::asio::ip::address_v4::bytes_type ip_addr_bytes; - byte_copy( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, gateway), - bytes.begin() + (offsetof(x300_eeprom_map, gateway)+4)), - ip_addr_bytes - ); + byte_copy(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, gateway), + bytes.begin() + (offsetof(x300_eeprom_map, gateway) + 4)), + ip_addr_bytes); mb_eeprom["gateway"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); - for (size_t i = 0; i < 4; i++) - { - const std::string n(1, char(i)+'0'); + for (size_t i = 0; i < 4; i++) { + const std::string n(1, char(i) + '0'); byte_copy( - byte_vector_t( - bytes.begin() + (offsetof(x300_eeprom_map, ip_addr)+(i*4)), - bytes.begin() + (offsetof(x300_eeprom_map, ip_addr)+(i*4)+4)), - ip_addr_bytes - ); - mb_eeprom["ip-addr"+n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); + byte_vector_t(bytes.begin() + (offsetof(x300_eeprom_map, ip_addr) + (i * 4)), + bytes.begin() + (offsetof(x300_eeprom_map, ip_addr) + (i * 4) + 4)), + ip_addr_bytes); + mb_eeprom["ip-addr" + n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); byte_copy( - byte_vector_t( - bytes.begin() + (offsetof(x300_eeprom_map, subnet)+(i*4)), - bytes.begin() + (offsetof(x300_eeprom_map, subnet)+(i*4)+4)), - ip_addr_bytes - ); - mb_eeprom["subnet"+n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); + byte_vector_t(bytes.begin() + (offsetof(x300_eeprom_map, subnet) + (i * 4)), + bytes.begin() + (offsetof(x300_eeprom_map, subnet) + (i * 4) + 4)), + ip_addr_bytes); + mb_eeprom["subnet" + n] = boost::asio::ip::address_v4(ip_addr_bytes).to_string(); } - //extract the serial - mb_eeprom["serial"] = bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, serial), - bytes.begin() + (offsetof(x300_eeprom_map, serial)+SERIAL_LEN)) - ); + // extract the serial + mb_eeprom["serial"] = + bytes_to_string(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, serial), + bytes.begin() + (offsetof(x300_eeprom_map, serial) + SERIAL_LEN))); - //extract the name - mb_eeprom["name"] = bytes_to_string( - byte_vector_t( - bytes.begin() + offsetof(x300_eeprom_map, name), - bytes.begin() + (offsetof(x300_eeprom_map, name)+NAME_MAX_LEN)) - ); + // extract the name + mb_eeprom["name"] = + bytes_to_string(byte_vector_t(bytes.begin() + offsetof(x300_eeprom_map, name), + bytes.begin() + (offsetof(x300_eeprom_map, name) + NAME_MAX_LEN))); return mb_eeprom; } -void x300_impl::set_mb_eeprom( - i2c_iface::sptr iface, - const mboard_eeprom_t &mb_eeprom -) { +void x300_impl::set_mb_eeprom(i2c_iface::sptr iface, const mboard_eeprom_t& mb_eeprom) +{ const mboard_eeprom_t curr_eeprom = get_mb_eeprom(iface); // Check for duplicate MAC and IP addresses - const std::vector<std::string> mac_keys{ - "mac-addr0", - "mac-addr1" - }; + const std::vector<std::string> mac_keys{"mac-addr0", "mac-addr1"}; const std::vector<std::string> ip_keys{ - "ip-addr0", - "ip-addr1", - "ip-addr2", - "ip-addr3" - }; + "ip-addr0", "ip-addr1", "ip-addr2", "ip-addr3"}; - //make sure there are no duplicate values + // make sure there are no duplicate values if (check_for_duplicates<uhd::mac_addr_t>( - "X300", mb_eeprom, curr_eeprom,"MAC address", mac_keys) or - check_for_duplicates<boost::asio::ip::address_v4>( - "X300", mb_eeprom, curr_eeprom, "IP address", ip_keys)) - { + "X300", mb_eeprom, curr_eeprom, "MAC address", mac_keys) + or check_for_duplicates<boost::asio::ip::address_v4>( + "X300", mb_eeprom, curr_eeprom, "IP address", ip_keys)) { throw uhd::value_error( "Duplicate values not permitted - write to EEPROM aborted"); } - //parse the revision number - if (mb_eeprom.has_key("revision")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, revision), - string_to_uint16_bytes(mb_eeprom["revision"]) - ); - - //parse the revision compat number - if (mb_eeprom.has_key("revision_compat")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, revision_compat), - string_to_uint16_bytes(mb_eeprom["revision_compat"]) - ); - - //parse the product code - if (mb_eeprom.has_key("product")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, product), - string_to_uint16_bytes(mb_eeprom["product"]) - ); - - //store the mac addresses - if (mb_eeprom.has_key("mac-addr0")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, mac_addr0), - mac_addr_t::from_string(mb_eeprom["mac-addr0"]).to_bytes() - ); - if (mb_eeprom.has_key("mac-addr1")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, mac_addr1), - mac_addr_t::from_string(mb_eeprom["mac-addr1"]).to_bytes() - ); - - //store the ip addresses + // parse the revision number + if (mb_eeprom.has_key("revision")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, revision), + string_to_uint16_bytes(mb_eeprom["revision"])); + + // parse the revision compat number + if (mb_eeprom.has_key("revision_compat")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, revision_compat), + string_to_uint16_bytes(mb_eeprom["revision_compat"])); + + // parse the product code + if (mb_eeprom.has_key("product")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, product), + string_to_uint16_bytes(mb_eeprom["product"])); + + // store the mac addresses + if (mb_eeprom.has_key("mac-addr0")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, mac_addr0), + mac_addr_t::from_string(mb_eeprom["mac-addr0"]).to_bytes()); + if (mb_eeprom.has_key("mac-addr1")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, mac_addr1), + mac_addr_t::from_string(mb_eeprom["mac-addr1"]).to_bytes()); + + // store the ip addresses byte_vector_t ip_addr_bytes(4); - if (mb_eeprom.has_key("gateway")){ - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, gateway), ip_addr_bytes); + if (mb_eeprom.has_key("gateway")) { + byte_copy( + boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(), + ip_addr_bytes); + iface->write_eeprom( + X300_EEPROM_ADDR, offsetof(x300_eeprom_map, gateway), ip_addr_bytes); } - for (size_t i = 0; i < 4; i++) - { - const std::string n(1, char(i)+'0'); - if (mb_eeprom.has_key("ip-addr"+n)){ - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr"+n]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, ip_addr)+(i*4), ip_addr_bytes); + for (size_t i = 0; i < 4; i++) { + const std::string n(1, char(i) + '0'); + if (mb_eeprom.has_key("ip-addr" + n)) { + byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr" + n]) + .to_bytes(), + ip_addr_bytes); + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, ip_addr) + (i * 4), + ip_addr_bytes); } - if (mb_eeprom.has_key("subnet"+n)){ - byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet"+n]).to_bytes(), ip_addr_bytes); - iface->write_eeprom(X300_EEPROM_ADDR, offsetof(x300_eeprom_map, subnet)+(i*4), ip_addr_bytes); + if (mb_eeprom.has_key("subnet" + n)) { + byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet" + n]) + .to_bytes(), + ip_addr_bytes); + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, subnet) + (i * 4), + ip_addr_bytes); } } - //store the serial - if (mb_eeprom.has_key("serial")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, serial), - string_to_bytes(mb_eeprom["serial"], SERIAL_LEN) - ); - - //store the name - if (mb_eeprom.has_key("name")) iface->write_eeprom( - X300_EEPROM_ADDR, offsetof(x300_eeprom_map, name), - string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN) - ); + // store the serial + if (mb_eeprom.has_key("serial")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, serial), + string_to_bytes(mb_eeprom["serial"], SERIAL_LEN)); + + // store the name + if (mb_eeprom.has_key("name")) + iface->write_eeprom(X300_EEPROM_ADDR, + offsetof(x300_eeprom_map, name), + string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN)); } diff --git a/host/lib/usrp/x300/x300_mb_eeprom_iface.cpp b/host/lib/usrp/x300/x300_mb_eeprom_iface.cpp index 630e8ce2b..12022ec24 100644 --- a/host/lib/usrp/x300/x300_mb_eeprom_iface.cpp +++ b/host/lib/usrp/x300/x300_mb_eeprom_iface.cpp @@ -19,12 +19,12 @@ #include "x300_mb_eeprom_iface.hpp" #include "x300_fw_common.h" -#include "x300_regs.hpp" #include "x300_impl.hpp" +#include "x300_regs.hpp" #include <uhd/exception.hpp> -#include <uhd/utils/platform.hpp> -#include <uhd/utils/log.hpp> #include <uhd/utils/byteswap.hpp> +#include <uhd/utils/log.hpp> +#include <uhd/utils/platform.hpp> #include <boost/thread.hpp> using namespace uhd; @@ -34,7 +34,6 @@ static const uint32_t X300_FW_SHMEM_IDENT_MIN_VERSION = 0x50001; class x300_mb_eeprom_iface_impl : public x300_mb_eeprom_iface { public: - x300_mb_eeprom_iface_impl(wb_iface::sptr wb, i2c_iface::sptr i2c) : _wb(wb), _i2c(i2c) { _compat_num = _wb->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_COMPAT_NUM)); @@ -50,14 +49,10 @@ public: * \param addr the address * \param buf the vector of bytes */ - void write_i2c( - uint16_t addr, - const byte_vector_t &buf - ) + void write_i2c(uint16_t addr, const byte_vector_t& buf) { UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR); - if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US) - { + if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US) { throw uhd::io_error("Attempted to write MB EEPROM without claim to device."); } _i2c->write_i2c(addr, buf); @@ -69,24 +64,18 @@ public: * \param num_bytes number of bytes to read * \return a vector of bytes */ - byte_vector_t read_i2c( - uint16_t addr, - size_t num_bytes - ) + byte_vector_t read_i2c(uint16_t addr, size_t num_bytes) { UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR); byte_vector_t bytes; - if (_compat_num > X300_FW_SHMEM_IDENT_MIN_VERSION) - { + if (_compat_num > X300_FW_SHMEM_IDENT_MIN_VERSION) { bytes = read_eeprom(addr, 0, num_bytes); } else { x300_impl::claim_status_t status = x300_impl::claim_status(_wb); // Claim device before driving the I2C bus - if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb)) - { + if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb)) { bytes = _i2c->read_i2c(addr, num_bytes); - if (status != x300_impl::CLAIMED_BY_US) - { + if (status != x300_impl::CLAIMED_BY_US) { // We didn't originally have the claim, so give it up x300_impl::release(_wb); } @@ -101,15 +90,10 @@ public: * \param offset byte offset * \param buf the vector of bytes */ - void write_eeprom( - uint16_t addr, - uint16_t offset, - const byte_vector_t &buf - ) + void write_eeprom(uint16_t addr, uint16_t offset, const byte_vector_t& buf) { UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR); - if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US) - { + if (x300_impl::claim_status(_wb) != x300_impl::CLAIMED_BY_US) { throw uhd::io_error("Attempted to write MB EEPROM without claim to device."); } _i2c->write_eeprom(addr, offset, buf); @@ -122,37 +106,31 @@ public: * \param num_bytes number of bytes to read * \return a vector of bytes */ - byte_vector_t read_eeprom( - uint16_t addr, - uint16_t offset, - size_t num_bytes - ) + byte_vector_t read_eeprom(uint16_t addr, uint16_t offset, size_t num_bytes) { UHD_ASSERT_THROW(addr == MBOARD_EEPROM_ADDR); byte_vector_t bytes; x300_impl::claim_status_t status = x300_impl::claim_status(_wb); - if (_compat_num >= X300_FW_SHMEM_IDENT_MIN_VERSION) - { + if (_compat_num >= X300_FW_SHMEM_IDENT_MIN_VERSION) { // Get MB EEPROM data from firmware memory - if (num_bytes == 0) return bytes; + if (num_bytes == 0) + return bytes; size_t bytes_read = 0; - for (size_t word = offset / 4; bytes_read < num_bytes; word++) - { - uint32_t value = byteswap(_wb->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_IDENT + word))); - for (size_t byte = offset % 4; byte < 4 and bytes_read < num_bytes; byte++) - { + for (size_t word = offset / 4; bytes_read < num_bytes; word++) { + uint32_t value = + byteswap(_wb->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_IDENT + word))); + for (size_t byte = offset % 4; byte < 4 and bytes_read < num_bytes; + byte++) { bytes.push_back(uint8_t((value >> (byte * 8)) & 0xff)); bytes_read++; } } } else { // Claim device before driving the I2C bus - if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb)) - { + if (status == x300_impl::CLAIMED_BY_US or x300_impl::try_to_claim(_wb)) { bytes = _i2c->read_eeprom(addr, offset, num_bytes); - if (status != x300_impl::CLAIMED_BY_US) - { + if (status != x300_impl::CLAIMED_BY_US) { // We didn't originally have the claim, so give it up x300_impl::release(_wb); } @@ -173,8 +151,8 @@ x300_mb_eeprom_iface::~x300_mb_eeprom_iface(void) /* NOP */ } -x300_mb_eeprom_iface::sptr x300_mb_eeprom_iface::make(wb_iface::sptr wb, i2c_iface::sptr i2c) +x300_mb_eeprom_iface::sptr x300_mb_eeprom_iface::make( + wb_iface::sptr wb, i2c_iface::sptr i2c) { return boost::make_shared<x300_mb_eeprom_iface_impl>(wb, i2c->eeprom16()); } - diff --git a/host/lib/usrp/x300/x300_mb_eeprom_iface.hpp b/host/lib/usrp/x300/x300_mb_eeprom_iface.hpp index dfc1eea6d..d323d6359 100644 --- a/host/lib/usrp/x300/x300_mb_eeprom_iface.hpp +++ b/host/lib/usrp/x300/x300_mb_eeprom_iface.hpp @@ -10,9 +10,9 @@ #include <uhd/config.hpp> #include <uhd/types/serial.hpp> -#include <boost/utility.hpp> -#include <boost/shared_ptr.hpp> #include <uhd/types/wb_iface.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> class x300_mb_eeprom_iface : public uhd::i2c_iface { diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp index d0aadc55a..9057180e4 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp @@ -6,19 +6,19 @@ #include "x300_radio_ctrl_impl.hpp" #include "x300_dboard_iface.hpp" -#include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/usrp/dboard_iface.hpp> #include <uhd/rfnoc/node_ctrl_base.hpp> #include <uhd/transport/chdr.hpp> +#include <uhd/usrp/dboard_eeprom.hpp> +#include <uhd/usrp/dboard_iface.hpp> +#include <uhd/utils/log.hpp> #include <uhd/utils/math.hpp> #include <uhd/utils/safe_call.hpp> #include <uhdlib/rfnoc/wb_iface_adapter.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> #include <uhdlib/usrp/common/apply_corrections.hpp> +#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> #include <boost/algorithm/string.hpp> -#include <boost/make_shared.hpp> #include <boost/date_time/posix_time/posix_time_io.hpp> +#include <boost/make_shared.hpp> #include <chrono> #include <thread> @@ -33,26 +33,26 @@ static const size_t IO_MASTER_RADIO = 0; * Structors ***************************************************************************/ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl) - , _ignore_cal_file(false) +, _ignore_cal_file(false) { - UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::ctor() " ; + UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::ctor() "; //////////////////////////////////////////////////////////////////// // Set up basic info //////////////////////////////////////////////////////////////////// - _radio_type = (get_block_id().get_block_count() == 0) ? PRIMARY : SECONDARY; - _radio_slot = (get_block_id().get_block_count() == 0) ? "A" : "B"; + _radio_type = (get_block_id().get_block_count() == 0) ? PRIMARY : SECONDARY; + _radio_slot = (get_block_id().get_block_count() == 0) ? "A" : "B"; _radio_clk_rate = _tree->access<double>("master_clock_rate").get(); //////////////////////////////////////////////////////////////////// // Set up peripherals //////////////////////////////////////////////////////////////////// wb_iface::sptr ctrl = _get_ctrl(IO_MASTER_RADIO); - _regs = boost::make_shared<radio_regmap_t>(_radio_type==PRIMARY?0:1); + _regs = boost::make_shared<radio_regmap_t>(_radio_type == PRIMARY ? 0 : 1); _regs->initialize(*ctrl, true); - //Only Radio0 has the ADC/DAC reset bits. Those bits are reserved for Radio1 - if (_radio_type==PRIMARY) { + // Only Radio0 has the ADC/DAC reset bits. Those bits are reserved for Radio1 + if (_radio_type == PRIMARY) { _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); _regs->misc_outs_reg.flush(); @@ -67,84 +67,100 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl) //////////////////////////////////////////////////////////////// _spi = spi_core_3000::make(ctrl, regs::sr_addr(radio_ctrl_impl::regs::SPI), - regs::rb_addr(radio_ctrl_impl::regs::RB_SPI) - ); + regs::rb_addr(radio_ctrl_impl::regs::RB_SPI)); _adc = x300_adc_ctrl::make(_spi, DB_ADC_SEN); _dac = x300_dac_ctrl::make(_spi, DB_DAC_SEN, _radio_clk_rate); - if (_radio_type==PRIMARY) { - _fp_gpio = gpio_atr::gpio_atr_3000::make(ctrl, - regs::sr_addr(regs::FP_GPIO), - regs::rb_addr(regs::RB_FP_GPIO) - ); - for(const gpio_atr::gpio_attr_map_t::value_type attr: gpio_atr::gpio_attr_map) { - switch (attr.first){ + if (_radio_type == PRIMARY) { + _fp_gpio = gpio_atr::gpio_atr_3000::make( + ctrl, regs::sr_addr(regs::FP_GPIO), regs::rb_addr(regs::RB_FP_GPIO)); + for (const gpio_atr::gpio_attr_map_t::value_type attr : gpio_atr::gpio_attr_map) { + switch (attr.first) { case usrp::gpio_atr::GPIO_SRC: - _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this](const std::vector<std::string>&){ - throw uhd::runtime_error("This device does not support setting the GPIO_SRC attribute."); - }); + _tree + ->create<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber([this](const std::vector<std::string>&) { + throw uhd::runtime_error("This device does not support " + "setting the GPIO_SRC attribute."); + }); break; case usrp::gpio_atr::GPIO_CTRL: case usrp::gpio_atr::GPIO_DDR: - _tree->create<std::vector<std::string>>(fs_path("gpio") / "FP0" / attr.second) - .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) - .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){ - uint32_t val = 0; - for(size_t i = 0 ; i < str_val.size() ; i++){ - val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i; - } - _fp_gpio->set_gpio_attr(attr.first, val); - }); + _tree + ->create<std::vector<std::string>>( + fs_path("gpio") / "FP0" / attr.second) + .set(std::vector<std::string>( + 32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) + .add_coerced_subscriber( + [this, attr](const std::vector<std::string> str_val) { + uint32_t val = 0; + for (size_t i = 0; i < str_val.size(); i++) { + val += usrp::gpio_atr::gpio_attr_value_pair + .at(attr.second) + .at(str_val[i]) + << i; + } + _fp_gpio->set_gpio_attr(attr.first, val); + }); break; case usrp::gpio_atr::GPIO_READBACK: _tree->create<uint32_t>(fs_path("gpio") / "FP0" / "READBACK") - .set_publisher([this](){ - return _fp_gpio->read_gpio(); - }); + .set_publisher([this]() { return _fp_gpio->read_gpio(); }); break; default: _tree->create<uint32_t>(fs_path("gpio") / "FP0" / attr.second) - .set(0) - .add_coerced_subscriber([this, attr](const uint32_t val){ - _fp_gpio->set_gpio_attr(attr.first, val); - }); + .set(0) + .add_coerced_subscriber([this, attr](const uint32_t val) { + _fp_gpio->set_gpio_attr(attr.first, val); + }); } - } } //////////////////////////////////////////////////////////////// // create legacy codec control objects //////////////////////////////////////////////////////////////// - _tree->create<int>("rx_codecs" / _radio_slot / "gains"); //phony property so this dir exists - _tree->create<int>("tx_codecs" / _radio_slot / "gains"); //phony property so this dir exists + _tree->create<int>( + "rx_codecs" / _radio_slot / "gains"); // phony property so this dir exists + _tree->create<int>( + "tx_codecs" / _radio_slot / "gains"); // phony property so this dir exists _tree->create<std::string>("rx_codecs" / _radio_slot / "name").set("ads62p48"); _tree->create<std::string>("tx_codecs" / _radio_slot / "name").set("ad9146"); - _tree->create<meta_range_t>("rx_codecs" / _radio_slot / "gains" / "digital" / "range").set(meta_range_t(0, 6.0, 0.5)); + _tree->create<meta_range_t>("rx_codecs" / _radio_slot / "gains" / "digital" / "range") + .set(meta_range_t(0, 6.0, 0.5)); _tree->create<double>("rx_codecs" / _radio_slot / "gains" / "digital" / "value") - .add_coerced_subscriber(boost::bind(&x300_adc_ctrl::set_gain, _adc, _1)).set(0) - ; + .add_coerced_subscriber(boost::bind(&x300_adc_ctrl::set_gain, _adc, _1)) + .set(0); //////////////////////////////////////////////////////////////// // create front-end objects //////////////////////////////////////////////////////////////// for (size_t i = 0; i < _get_num_radios(); i++) { - _leds[i] = gpio_atr::gpio_atr_3000::make_write_only(_get_ctrl(i), regs::sr_addr(regs::LEDS)); - _leds[i]->set_atr_mode(usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); + _leds[i] = gpio_atr::gpio_atr_3000::make_write_only( + _get_ctrl(i), regs::sr_addr(regs::LEDS)); + _leds[i]->set_atr_mode( + usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); - _rx_fe_map[i].core = rx_frontend_core_3000::make(_get_ctrl(i), regs::sr_addr(x300_regs::RX_FE_BASE)); + _rx_fe_map[i].core = rx_frontend_core_3000::make( + _get_ctrl(i), regs::sr_addr(x300_regs::RX_FE_BASE)); _rx_fe_map[i].core->set_adc_rate(_radio_clk_rate); _rx_fe_map[i].core->set_dc_offset(rx_frontend_core_3000::DEFAULT_DC_OFFSET_VALUE); - _rx_fe_map[i].core->set_dc_offset_auto(rx_frontend_core_3000::DEFAULT_DC_OFFSET_ENABLE); - _rx_fe_map[i].core->populate_subtree(_tree->subtree(_root_path / "rx_fe_corrections" / i)); + _rx_fe_map[i].core->set_dc_offset_auto( + rx_frontend_core_3000::DEFAULT_DC_OFFSET_ENABLE); + _rx_fe_map[i].core->populate_subtree( + _tree->subtree(_root_path / "rx_fe_corrections" / i)); - _tx_fe_map[i].core = tx_frontend_core_200::make(_get_ctrl(i), regs::sr_addr(x300_regs::TX_FE_BASE)); + _tx_fe_map[i].core = tx_frontend_core_200::make( + _get_ctrl(i), regs::sr_addr(x300_regs::TX_FE_BASE)); _tx_fe_map[i].core->set_dc_offset(tx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE); - _tx_fe_map[i].core->set_iq_balance(tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); - _tx_fe_map[i].core->populate_subtree(_tree->subtree(_root_path / "tx_fe_corrections" / i)); + _tx_fe_map[i].core->set_iq_balance( + tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); + _tx_fe_map[i].core->populate_subtree( + _tree->subtree(_root_path / "tx_fe_corrections" / i)); //////////////////////////////////////////////////////////////// // Bind the daughterboard command time to the motherboard level property @@ -152,16 +168,19 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl) if (_tree->exists(fs_path("time") / "cmd")) { _tree->access<time_spec_t>(fs_path("time") / "cmd") - .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_fe_cmd_time, this, _1, i)); + .add_coerced_subscriber( + boost::bind(&x300_radio_ctrl_impl::set_fe_cmd_time, this, _1, i)); } } //////////////////////////////////////////////////////////////// // Update default SPP (overwrites the default value from the XML file) //////////////////////////////////////////////////////////////// - const size_t max_bytes_header = uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); - const size_t default_spp = (_tree->access<size_t>("mtu/recv").get() - max_bytes_header) - / (2 * sizeof(int16_t)); + const size_t max_bytes_header = + uhd::transport::vrt::chdr::max_if_hdr_words64 * sizeof(uint64_t); + const size_t default_spp = + (_tree->access<size_t>("mtu/recv").get() - max_bytes_header) + / (2 * sizeof(int16_t)); _tree->access<int>(get_arg_path("spp") / "value").set(default_spp); } @@ -173,21 +192,19 @@ x300_radio_ctrl_impl::~x300_radio_ctrl_impl() _tree->remove(fs_path("tx_codecs" / _radio_slot)); _tree->remove(_root_path / "rx_fe_corrections"); _tree->remove(_root_path / "tx_fe_corrections"); - if (_radio_type==PRIMARY) { - for(const gpio_atr::gpio_attr_map_t::value_type attr: gpio_atr::gpio_attr_map) { + if (_radio_type == PRIMARY) { + for (const gpio_atr::gpio_attr_map_t::value_type attr : + gpio_atr::gpio_attr_map) { _tree->remove(fs_path("gpio") / "FP0" / attr.second); } } // Reset peripherals - if (_radio_type==PRIMARY) { + if (_radio_type == PRIMARY) { _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); - } - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 0); - _regs->misc_outs_reg.flush(); - ) - + } _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_ENABLED, 0); + _regs->misc_outs_reg.flush();) } /**************************************************************************** @@ -197,102 +214,129 @@ double x300_radio_ctrl_impl::set_rate(double rate) { const double actual_rate = get_rate(); if (not uhd::math::frequencies_are_equal(rate, actual_rate)) { - UHD_LOGGER_WARNING("X300 RADIO") << "Requesting invalid sampling rate from device: " << rate/1e6 << " MHz. Actual rate is: " << actual_rate/1e6 << " MHz." ; + UHD_LOGGER_WARNING("X300 RADIO") + << "Requesting invalid sampling rate from device: " << rate / 1e6 + << " MHz. Actual rate is: " << actual_rate / 1e6 << " MHz."; } // On X3x0, tick rate can't actually be changed at runtime return actual_rate; } -void x300_radio_ctrl_impl::set_fe_cmd_time(const time_spec_t &time, const size_t chan) +void x300_radio_ctrl_impl::set_fe_cmd_time(const time_spec_t& time, const size_t chan) { - if (_tree->exists(fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd"))) { - _tree->access<time_spec_t>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd") - ).set(time); + if (_tree->exists(fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd"))) { + _tree + ->access<time_spec_t>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd")) + .set(time); } } -void x300_radio_ctrl_impl::set_tx_antenna(const std::string &ant, const size_t chan) +void x300_radio_ctrl_impl::set_tx_antenna(const std::string& ant, const size_t chan) { - _tree->access<std::string>( - fs_path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value") - ).set(ant); + _tree + ->access<std::string>( + fs_path("dboards" / _radio_slot / "tx_frontends" + / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value")) + .set(ant); } std::string x300_radio_ctrl_impl::get_tx_antenna(const size_t chan) { - return _tree->access<std::string>( - fs_path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value") - ).get(); + return _tree + ->access<std::string>( + fs_path("dboards" / _radio_slot / "tx_frontends" + / _tx_fe_map.at(chan).db_fe_name / "antenna" / "value")) + .get(); } -void x300_radio_ctrl_impl::set_rx_antenna(const std::string &ant, const size_t chan) +void x300_radio_ctrl_impl::set_rx_antenna(const std::string& ant, const size_t chan) { - _tree->access<std::string>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value") - ).set(ant); + _tree + ->access<std::string>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value")) + .set(ant); } std::string x300_radio_ctrl_impl::get_rx_antenna(const size_t chan) { - return _tree->access<std::string>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value") - ).get(); + return _tree + ->access<std::string>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "antenna" / "value")) + .get(); } double x300_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "freq" / "value") - ).set(freq).get(); + return _tree + ->access<double>(fs_path("dboards" / _radio_slot / "tx_frontends" + / _tx_fe_map.at(chan).db_fe_name / "freq" / "value")) + .set(freq) + .get(); } double x300_radio_ctrl_impl::get_tx_frequency(const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "freq" / "value") - ).get(); + return _tree + ->access<double>(fs_path("dboards" / _radio_slot / "tx_frontends" + / _tx_fe_map.at(chan).db_fe_name / "freq" / "value")) + .get(); } double x300_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "freq" / "value") - ).set(freq).get(); + return _tree + ->access<double>(fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "freq" / "value")) + .set(freq) + .get(); } double x300_radio_ctrl_impl::get_rx_frequency(const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "freq" / "value") - ).get(); + return _tree + ->access<double>(fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "freq" / "value")) + .get(); } double x300_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value") - ).set(bandwidth).get(); + return _tree + ->access<double>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value")) + .set(bandwidth) + .get(); } double x300_radio_ctrl_impl::get_rx_bandwidth(const size_t chan) { - return _tree->access<double>( - fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value") - ).get(); + return _tree + ->access<double>( + fs_path("dboards" / _radio_slot / "rx_frontends" + / _rx_fe_map.at(chan).db_fe_name / "bandwidth" / "value")) + .get(); } double x300_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) { - //TODO: This is extremely hacky! - fs_path path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name / "gains"); + // TODO: This is extremely hacky! + fs_path path("dboards" / _radio_slot / "tx_frontends" / _tx_fe_map.at(chan).db_fe_name + / "gains"); std::vector<std::string> gain_stages = _tree->list(path); if (gain_stages.size() == 1) { - const double actual_gain = _tree->access<double>(path / gain_stages[0] / "value").set(gain).get(); + const double actual_gain = + _tree->access<double>(path / gain_stages[0] / "value").set(gain).get(); radio_ctrl_impl::set_tx_gain(actual_gain, chan); return gain; } else { - UHD_LOGGER_WARNING("X300 RADIO") << "set_tx_gain: could not apply gain for this daughterboard."; + UHD_LOGGER_WARNING("X300 RADIO") + << "set_tx_gain: could not apply gain for this daughterboard."; radio_ctrl_impl::set_tx_gain(0.0, chan); return 0.0; } @@ -300,15 +344,18 @@ double x300_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) double x300_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) { - //TODO: This is extremely hacky! - fs_path path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "gains"); + // TODO: This is extremely hacky! + fs_path path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name + / "gains"); std::vector<std::string> gain_stages = _tree->list(path); if (gain_stages.size() == 1) { - const double actual_gain = _tree->access<double>(path / gain_stages[0] / "value").set(gain).get(); + const double actual_gain = + _tree->access<double>(path / gain_stages[0] / "value").set(gain).get(); radio_ctrl_impl::set_rx_gain(actual_gain, chan); return gain; } else { - UHD_LOGGER_WARNING("X300 RADIO") << "set_rx_gain: could not apply gain for this daughterboard."; + UHD_LOGGER_WARNING("X300 RADIO") + << "set_rx_gain: could not apply gain for this daughterboard."; radio_ctrl_impl::set_tx_gain(0.0, chan); return 0.0; } @@ -317,79 +364,105 @@ double x300_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_names(const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); std::vector<std::string> lo_names; if (_tree->exists(rx_fe_fe_root / "los")) { - for(const std::string &name: _tree->list(rx_fe_fe_root / "los")) { + for (const std::string& name : _tree->list(rx_fe_fe_root / "los")) { lo_names.push_back(name); } } return lo_names; } -std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_sources(const std::string &name, const size_t chan) +std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_sources( + const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { - //Special value ALL_LOS support atomically sets the source for all LOs - return _tree->access< std::vector<std::string> >(rx_fe_fe_root / "los" / ALL_LOS / "source" / "options").get(); + // Special value ALL_LOS support atomically sets the source for all LOs + return _tree + ->access<std::vector<std::string>>( + rx_fe_fe_root / "los" / ALL_LOS / "source" / "options") + .get(); } else { return std::vector<std::string>(); } } else { if (_tree->exists(rx_fe_fe_root / "los")) { - return _tree->access< std::vector<std::string> >(rx_fe_fe_root / "los" / name / "source" / "options").get(); + return _tree + ->access<std::vector<std::string>>( + rx_fe_fe_root / "los" / name / "source" / "options") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } } } else { // If the daughterboard doesn't expose it's LO(s) then it can only be internal - return std::vector<std::string> (1, "internal"); + return std::vector<std::string>(1, "internal"); } } -void x300_radio_ctrl_impl::set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan) +void x300_radio_ctrl_impl::set_rx_lo_source( + const std::string& src, const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { - //Special value ALL_LOS support atomically sets the source for all LOs - _tree->access<std::string>(rx_fe_fe_root / "los" / ALL_LOS / "source" / "value").set(src); + // Special value ALL_LOS support atomically sets the source for all LOs + _tree + ->access<std::string>( + rx_fe_fe_root / "los" / ALL_LOS / "source" / "value") + .set(src); } else { - for(const std::string &n: _tree->list(rx_fe_fe_root / "los")) { + for (const std::string& n : _tree->list(rx_fe_fe_root / "los")) { this->set_rx_lo_source(src, n, chan); } } } else { if (_tree->exists(rx_fe_fe_root / "los")) { - _tree->access<std::string>(rx_fe_fe_root / "los" / name / "source" / "value").set(src); + _tree + ->access<std::string>( + rx_fe_fe_root / "los" / name / "source" / "value") + .set(src); } else { throw uhd::runtime_error("Could not find LO stage " + name); } } } else { - throw uhd::runtime_error("This device does not support manual configuration of LOs"); + throw uhd::runtime_error( + "This device does not support manual configuration of LOs"); } } -const std::string x300_radio_ctrl_impl::get_rx_lo_source(const std::string &name, const size_t chan) +const std::string x300_radio_ctrl_impl::get_rx_lo_source( + const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - //Special value ALL_LOS support atomically sets the source for all LOs - return _tree->access<std::string>(rx_fe_fe_root / "los" / ALL_LOS / "source" / "value").get(); + // Special value ALL_LOS support atomically sets the source for all LOs + return _tree + ->access<std::string>( + rx_fe_fe_root / "los" / ALL_LOS / "source" / "value") + .get(); } else { if (_tree->exists(rx_fe_fe_root / "los")) { - return _tree->access<std::string>(rx_fe_fe_root / "los" / name / "source" / "value").get(); + return _tree + ->access<std::string>( + rx_fe_fe_root / "los" / name / "source" / "value") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } @@ -400,17 +473,20 @@ const std::string x300_radio_ctrl_impl::get_rx_lo_source(const std::string &name } } -void x300_radio_ctrl_impl::set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan) +void x300_radio_ctrl_impl::set_rx_lo_export_enabled( + bool enabled, const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) { - //Special value ALL_LOS support atomically sets the source for all LOs - _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export").set(enabled); + // Special value ALL_LOS support atomically sets the source for all LOs + _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export") + .set(enabled); } else { - for(const std::string &n: _tree->list(rx_fe_fe_root / "los")) { + for (const std::string& n : _tree->list(rx_fe_fe_root / "los")) { this->set_rx_lo_export_enabled(enabled, n, chan); } } @@ -422,17 +498,20 @@ void x300_radio_ctrl_impl::set_rx_lo_export_enabled(bool enabled, const std::str } } } else { - throw uhd::runtime_error("This device does not support manual configuration of LOs"); + throw uhd::runtime_error( + "This device does not support manual configuration of LOs"); } } -bool x300_radio_ctrl_impl::get_rx_lo_export_enabled(const std::string &name, const size_t chan) +bool x300_radio_ctrl_impl::get_rx_lo_export_enabled( + const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - //Special value ALL_LOS support atomically sets the source for all LOs + // Special value ALL_LOS support atomically sets the source for all LOs return _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export").get(); } else { if (_tree->exists(rx_fe_fe_root / "los")) { @@ -447,56 +526,73 @@ bool x300_radio_ctrl_impl::get_rx_lo_export_enabled(const std::string &name, con } } -double x300_radio_ctrl_impl::set_rx_lo_freq(double freq, const std::string &name, const size_t chan) +double x300_radio_ctrl_impl::set_rx_lo_freq( + double freq, const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - throw uhd::runtime_error("LO frequency must be set for each stage individually"); + throw uhd::runtime_error( + "LO frequency must be set for each stage individually"); } else { if (_tree->exists(rx_fe_fe_root / "los")) { - _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value").set(freq); - return _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value").get(); + _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") + .set(freq); + return _tree + ->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } } } else { - throw uhd::runtime_error("This device does not support manual configuration of LOs"); + throw uhd::runtime_error( + "This device does not support manual configuration of LOs"); } } -double x300_radio_ctrl_impl::get_rx_lo_freq(const std::string &name, const size_t chan) +double x300_radio_ctrl_impl::get_rx_lo_freq(const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - throw uhd::runtime_error("LO frequency must be retrieved for each stage individually"); + throw uhd::runtime_error( + "LO frequency must be retrieved for each stage individually"); } else { if (_tree->exists(rx_fe_fe_root / "los")) { - return _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value").get(); + return _tree + ->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } } } else { // Return actual RF frequency if the daughterboard doesn't expose it's LO(s) - return _tree->access<double>(rx_fe_fe_root / "freq" /" value").get(); + return _tree->access<double>(rx_fe_fe_root / "freq" / " value").get(); } } -freq_range_t x300_radio_ctrl_impl::get_rx_lo_freq_range(const std::string &name, const size_t chan) +freq_range_t x300_radio_ctrl_impl::get_rx_lo_freq_range( + const std::string& name, const size_t chan) { - fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); + fs_path rx_fe_fe_root = fs_path( + "dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name); if (_tree->exists(rx_fe_fe_root / "los")) { if (name == ALL_LOS) { - throw uhd::runtime_error("LO frequency range must be retrieved for each stage individually"); + throw uhd::runtime_error( + "LO frequency range must be retrieved for each stage individually"); } else { if (_tree->exists(rx_fe_fe_root / "los")) { - return _tree->access<freq_range_t>(rx_fe_fe_root / "los" / name / "freq" / "range").get(); + return _tree + ->access<freq_range_t>( + rx_fe_fe_root / "los" / name / "freq" / "range") + .get(); } else { throw uhd::runtime_error("Could not find LO stage " + name); } @@ -508,21 +604,19 @@ freq_range_t x300_radio_ctrl_impl::get_rx_lo_freq_range(const std::string &name, } template <typename map_type> -static size_t _get_chan_from_map(std::map<size_t, map_type> map, const std::string &fe) +static size_t _get_chan_from_map(std::map<size_t, map_type> map, const std::string& fe) { for (auto it = map.begin(); it != map.end(); ++it) { if (it->second.db_fe_name == fe) { return it->first; } - } - throw uhd::runtime_error(str( - boost::format("Invalid daughterboard frontend name: %s") - % fe - )); + throw uhd::runtime_error( + str(boost::format("Invalid daughterboard frontend name: %s") % fe)); } -size_t x300_radio_ctrl_impl::get_chan_from_dboard_fe(const std::string &fe, const uhd::direction_t direction) +size_t x300_radio_ctrl_impl::get_chan_from_dboard_fe( + const std::string& fe, const uhd::direction_t direction) { switch (direction) { case uhd::TX_DIRECTION: @@ -534,7 +628,8 @@ size_t x300_radio_ctrl_impl::get_chan_from_dboard_fe(const std::string &fe, cons } } -std::string x300_radio_ctrl_impl::get_dboard_fe_from_chan(const size_t chan, const uhd::direction_t direction) +std::string x300_radio_ctrl_impl::get_dboard_fe_from_chan( + const size_t chan, const uhd::direction_t direction) { switch (direction) { case uhd::TX_DIRECTION: @@ -565,61 +660,83 @@ double x300_radio_ctrl_impl::get_output_samp_rate(size_t chan) std::vector<std::string> x300_radio_ctrl_impl::get_gpio_banks() const { std::vector<std::string> banks{"RX", "TX"}; - // These pairs are the same, but RXA/TXA are from pre-rfnoc era and are kept for backward compat: - banks.push_back("RX"+_radio_slot); - banks.push_back("TX"+_radio_slot); + // These pairs are the same, but RXA/TXA are from pre-rfnoc era and are kept for + // backward compat: + banks.push_back("RX" + _radio_slot); + banks.push_back("TX" + _radio_slot); if (_fp_gpio) { banks.push_back("FP0"); } return banks; } -void x300_radio_ctrl_impl::set_gpio_attr( - const std::string &bank, - const std::string &attr, - const uint32_t value, - const uint32_t mask -) { +void x300_radio_ctrl_impl::set_gpio_attr(const std::string& bank, + const std::string& attr, + const uint32_t value, + const uint32_t mask) +{ if (bank == "FP0" and _fp_gpio) { - const uint32_t current = _tree->access<uint32_t>(fs_path("gpio") / bank / attr).get(); + const uint32_t current = + _tree->access<uint32_t>(fs_path("gpio") / bank / attr).get(); const uint32_t new_value = (current & ~mask) | (value & mask); _tree->access<uint32_t>(fs_path("gpio") / bank / attr).set(new_value); return; } - if (bank.size() > 2 and bank[1] == 'X') - { - const std::string name = bank.substr(2); - const dboard_iface::unit_t unit = (bank[0] == 'R')? dboard_iface::UNIT_RX : dboard_iface::UNIT_TX; - dboard_iface::sptr iface = _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); - if (attr == "CTRL") iface->set_pin_ctrl(unit, uint16_t(value), uint16_t(mask)); - if (attr == "DDR") iface->set_gpio_ddr(unit, uint16_t(value), uint16_t(mask)); - if (attr == "OUT") iface->set_gpio_out(unit, uint16_t(value), uint16_t(mask)); - if (attr == "ATR_0X") iface->set_atr_reg(unit, gpio_atr::ATR_REG_IDLE, uint16_t(value), uint16_t(mask)); - if (attr == "ATR_RX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY, uint16_t(value), uint16_t(mask)); - if (attr == "ATR_TX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY, uint16_t(value), uint16_t(mask)); - if (attr == "ATR_XX") iface->set_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX, uint16_t(value), uint16_t(mask)); + if (bank.size() > 2 and bank[1] == 'X') { + const std::string name = bank.substr(2); + const dboard_iface::unit_t unit = (bank[0] == 'R') ? dboard_iface::UNIT_RX + : dboard_iface::UNIT_TX; + dboard_iface::sptr iface = + _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); + if (attr == "CTRL") + iface->set_pin_ctrl(unit, uint16_t(value), uint16_t(mask)); + if (attr == "DDR") + iface->set_gpio_ddr(unit, uint16_t(value), uint16_t(mask)); + if (attr == "OUT") + iface->set_gpio_out(unit, uint16_t(value), uint16_t(mask)); + if (attr == "ATR_0X") + iface->set_atr_reg( + unit, gpio_atr::ATR_REG_IDLE, uint16_t(value), uint16_t(mask)); + if (attr == "ATR_RX") + iface->set_atr_reg( + unit, gpio_atr::ATR_REG_RX_ONLY, uint16_t(value), uint16_t(mask)); + if (attr == "ATR_TX") + iface->set_atr_reg( + unit, gpio_atr::ATR_REG_TX_ONLY, uint16_t(value), uint16_t(mask)); + if (attr == "ATR_XX") + iface->set_atr_reg( + unit, gpio_atr::ATR_REG_FULL_DUPLEX, uint16_t(value), uint16_t(mask)); } } uint32_t x300_radio_ctrl_impl::get_gpio_attr( - const std::string &bank, - const std::string &attr -) { + const std::string& bank, const std::string& attr) +{ if (bank == "FP0" and _fp_gpio) { return uint32_t(_tree->access<uint64_t>(fs_path("gpio") / bank / attr).get()); } if (bank.size() > 2 and bank[1] == 'X') { - const std::string name = bank.substr(2); - const dboard_iface::unit_t unit = (bank[0] == 'R')? dboard_iface::UNIT_RX : dboard_iface::UNIT_TX; - dboard_iface::sptr iface = _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); - if (attr == "CTRL") return iface->get_pin_ctrl(unit); - if (attr == "DDR") return iface->get_gpio_ddr(unit); - if (attr == "OUT") return iface->get_gpio_out(unit); - if (attr == "ATR_0X") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_IDLE); - if (attr == "ATR_RX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY); - if (attr == "ATR_TX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY); - if (attr == "ATR_XX") return iface->get_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX); - if (attr == "READBACK") return iface->read_gpio(unit); + const std::string name = bank.substr(2); + const dboard_iface::unit_t unit = (bank[0] == 'R') ? dboard_iface::UNIT_RX + : dboard_iface::UNIT_TX; + dboard_iface::sptr iface = + _tree->access<dboard_iface::sptr>(fs_path("dboards") / name / "iface").get(); + if (attr == "CTRL") + return iface->get_pin_ctrl(unit); + if (attr == "DDR") + return iface->get_gpio_ddr(unit); + if (attr == "OUT") + return iface->get_gpio_out(unit); + if (attr == "ATR_0X") + return iface->get_atr_reg(unit, gpio_atr::ATR_REG_IDLE); + if (attr == "ATR_RX") + return iface->get_atr_reg(unit, gpio_atr::ATR_REG_RX_ONLY); + if (attr == "ATR_TX") + return iface->get_atr_reg(unit, gpio_atr::ATR_REG_TX_ONLY); + if (attr == "ATR_XX") + return iface->get_atr_reg(unit, gpio_atr::ATR_REG_FULL_DUPLEX); + if (attr == "READBACK") + return iface->read_gpio(unit); } return 0; } @@ -627,11 +744,10 @@ uint32_t x300_radio_ctrl_impl::get_gpio_attr( /**************************************************************************** * Radio control and setup ***************************************************************************/ -void x300_radio_ctrl_impl::setup_radio( - uhd::i2c_iface::sptr zpu_i2c, - x300_clock_ctrl::sptr clock, - bool ignore_cal_file, - bool verbose) +void x300_radio_ctrl_impl::setup_radio(uhd::i2c_iface::sptr zpu_i2c, + x300_clock_ctrl::sptr clock, + bool ignore_cal_file, + bool verbose) { _self_cal_adc_capture_delay(verbose); _ignore_cal_file = ignore_cal_file; @@ -644,57 +760,56 @@ void x300_radio_ctrl_impl::setup_radio( static const size_t TX_EEPROM_ADDR = 0x4; static const size_t GDB_EEPROM_ADDR = 0x1; const static std::vector<size_t> EEPROM_ADDRS{ - RX_EEPROM_ADDR, - TX_EEPROM_ADDR, - GDB_EEPROM_ADDR - }; + RX_EEPROM_ADDR, TX_EEPROM_ADDR, GDB_EEPROM_ADDR}; const static std::vector<std::string> EEPROM_PATHS{ - "rx_eeprom", - "tx_eeprom", - "gdb_eeprom" - }; + "rx_eeprom", "tx_eeprom", "gdb_eeprom"}; const size_t DB_OFFSET = (_radio_slot == "A") ? 0x0 : 0x2; - const fs_path db_path = ("dboards" / _radio_slot); + const fs_path db_path = ("dboards" / _radio_slot); for (size_t i = 0; i < EEPROM_ADDRS.size(); i++) { const size_t addr = EEPROM_ADDRS[i] + DB_OFFSET; - //Load EEPROM + // Load EEPROM _db_eeproms[addr].load(*zpu_i2c, BASE_ADDR | addr); - //Add to tree + // Add to tree _tree->create<dboard_eeprom_t>(db_path / EEPROM_PATHS[i]) .set(_db_eeproms[addr]) .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::_set_db_eeprom, - this, zpu_i2c, (BASE_ADDR | addr), _1)); + this, + zpu_i2c, + (BASE_ADDR | addr), + _1)); } - //create a new dboard interface + // create a new dboard interface x300_dboard_iface_config_t db_config; db_config.gpio = gpio_atr::db_gpio_atr_3000::make(_get_ctrl(IO_MASTER_RADIO), radio_ctrl_impl::regs::sr_addr(radio_ctrl_impl::regs::GPIO), - radio_ctrl_impl::regs::rb_addr(radio_ctrl_impl::regs::RB_DB_GPIO) - ); - db_config.spi = _spi; + radio_ctrl_impl::regs::rb_addr(radio_ctrl_impl::regs::RB_DB_GPIO)); + db_config.spi = _spi; db_config.rx_spi_slaveno = DB_RX_SEN; db_config.tx_spi_slaveno = DB_TX_SEN; - db_config.i2c = zpu_i2c; - db_config.clock = clock; - db_config.which_rx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_RX : X300_CLOCK_WHICH_DB1_RX; - db_config.which_tx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_TX : X300_CLOCK_WHICH_DB1_TX; - db_config.dboard_slot = (_radio_slot == "A")? 0 : 1; + db_config.i2c = zpu_i2c; + db_config.clock = clock; + db_config.which_rx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_RX + : X300_CLOCK_WHICH_DB1_RX; + db_config.which_tx_clk = (_radio_slot == "A") ? X300_CLOCK_WHICH_DB0_TX + : X300_CLOCK_WHICH_DB1_TX; + db_config.dboard_slot = (_radio_slot == "A") ? 0 : 1; db_config.cmd_time_ctrl = _get_ctrl(IO_MASTER_RADIO); - //create a new dboard manager - boost::shared_ptr<x300_dboard_iface> db_iface = boost::make_shared<x300_dboard_iface>(db_config); - _db_manager = dboard_manager::make( - _db_eeproms[RX_EEPROM_ADDR + DB_OFFSET], + // create a new dboard manager + boost::shared_ptr<x300_dboard_iface> db_iface = + boost::make_shared<x300_dboard_iface>(db_config); + _db_manager = dboard_manager::make(_db_eeproms[RX_EEPROM_ADDR + DB_OFFSET], _db_eeproms[TX_EEPROM_ADDR + DB_OFFSET], _db_eeproms[GDB_EEPROM_ADDR + DB_OFFSET], - db_iface, _tree->subtree(db_path), + db_iface, + _tree->subtree(db_path), true // defer daughterboard intitialization ); size_t rx_chan = 0, tx_chan = 0; - for(const std::string& fe: _db_manager->get_rx_frontends()) { + for (const std::string& fe : _db_manager->get_rx_frontends()) { if (rx_chan >= _get_num_radios()) { break; } @@ -702,12 +817,14 @@ void x300_radio_ctrl_impl::setup_radio( db_iface->add_rx_fe(fe, _rx_fe_map[rx_chan].core); const fs_path fe_path(db_path / "rx_frontends" / fe); const std::string conn = _tree->access<std::string>(fe_path / "connection").get(); - const double if_freq = (_tree->exists(fe_path / "if_freq/value")) ? - _tree->access<double>(fe_path / "if_freq/value").get() : 0.0; + const double if_freq = + (_tree->exists(fe_path / "if_freq/value")) + ? _tree->access<double>(fe_path / "if_freq/value").get() + : 0.0; _rx_fe_map[rx_chan].core->set_fe_connection(usrp::fe_connection_t(conn, if_freq)); rx_chan++; } - for(const std::string& fe: _db_manager->get_tx_frontends()) { + for (const std::string& fe : _db_manager->get_tx_frontends()) { if (tx_chan >= _get_num_radios()) { break; } @@ -722,40 +839,63 @@ void x300_radio_ctrl_impl::setup_radio( // Initialize the daughterboards now that frontend cores and connections exist _db_manager->initialize_dboards(); - //now that dboard is created -- register into rx antenna event + // now that dboard is created -- register into rx antenna event if (not _rx_fe_map.empty()) { for (size_t i = 0; i < _get_num_radios(); i++) { - if (_tree->exists(db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name / "antenna" / "value")) { - // We need a desired subscriber for antenna/value because the experts don't coerce that property. - _tree->access<std::string>(db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name / "antenna" / "value") - .add_desired_subscriber(boost::bind(&x300_radio_ctrl_impl::_update_atr_leds, this, _1, i)); - _update_atr_leds(_tree->access<std::string> - (db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name / "antenna" / "value").get(), i); + if (_tree->exists(db_path / "rx_frontends" / _rx_fe_map[i].db_fe_name + / "antenna" / "value")) { + // We need a desired subscriber for antenna/value because the experts + // don't coerce that property. + _tree + ->access<std::string>(db_path / "rx_frontends" + / _rx_fe_map[i].db_fe_name / "antenna" + / "value") + .add_desired_subscriber(boost::bind( + &x300_radio_ctrl_impl::_update_atr_leds, this, _1, i)); + _update_atr_leds(_tree + ->access<std::string>(db_path / "rx_frontends" + / _rx_fe_map[i].db_fe_name + / "antenna" / "value") + .get(), + i); } else { - _update_atr_leds("", i); //init anyway, even if never called + _update_atr_leds("", i); // init anyway, even if never called } } } - //bind frontend corrections to the dboard freq props + // bind frontend corrections to the dboard freq props const fs_path db_tx_fe_path = db_path / "tx_frontends"; if (not _tx_fe_map.empty()) { for (size_t i = 0; i < _get_num_radios(); i++) { - if (_tree->exists(db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { - _tree->access<double>(db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") - .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, this, db_path, - _root_path / "tx_fe_corrections" / _tx_fe_map[i].db_fe_name, _1)); + if (_tree->exists( + db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { + _tree + ->access<double>( + db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") + .add_coerced_subscriber( + boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, + this, + db_path, + _root_path / "tx_fe_corrections" / _tx_fe_map[i].db_fe_name, + _1)); } } } const fs_path db_rx_fe_path = db_path / "rx_frontends"; if (not _rx_fe_map.empty()) { for (size_t i = 0; i < _get_num_radios(); i++) { - if (_tree->exists(db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { - _tree->access<double>(db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") - .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, this, db_path, - _root_path / "rx_fe_corrections" / _tx_fe_map[i].db_fe_name, - _1)); + if (_tree->exists( + db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { + _tree + ->access<double>( + db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") + .add_coerced_subscriber( + boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, + this, + db_path, + _root_path / "rx_fe_corrections" / _tx_fe_map[i].db_fe_name, + _1)); } } } @@ -764,7 +904,7 @@ void x300_radio_ctrl_impl::setup_radio( // Set tick rate //////////////////////////////////////////////////////////////// const double tick_rate = get_output_samp_rate(0); - if (_radio_type==PRIMARY) { + if (_radio_type == PRIMARY) { // Slot A is the highlander timekeeper _tree->access<double>("tick_rate").set(tick_rate); } @@ -772,20 +912,16 @@ void x300_radio_ctrl_impl::setup_radio( } void x300_radio_ctrl_impl::set_rx_fe_corrections( - const fs_path &db_path, - const fs_path &rx_fe_corr_path, - const double lo_freq -) { + const fs_path& db_path, const fs_path& rx_fe_corr_path, const double lo_freq) +{ if (not _ignore_cal_file) { apply_rx_fe_corrections(_tree, db_path, rx_fe_corr_path, lo_freq); } } void x300_radio_ctrl_impl::set_tx_fe_corrections( - const fs_path &db_path, - const fs_path &tx_fe_corr_path, - const double lo_freq -) { + const fs_path& db_path, const fs_path& tx_fe_corr_path, const double lo_freq) +{ if (not _ignore_cal_file) { apply_tx_fe_corrections(_tree, db_path, tx_fe_corr_path, lo_freq); } @@ -793,7 +929,7 @@ void x300_radio_ctrl_impl::set_tx_fe_corrections( void x300_radio_ctrl_impl::reset_codec() { - if (_radio_type==PRIMARY) { //ADC/DAC reset lines only exist in Radio0 + if (_radio_type == PRIMARY) { // ADC/DAC reset lines only exist in Radio0 _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::ADC_RESET, 1); _regs->misc_outs_reg.set(radio_regmap_t::misc_outs_reg_t::DAC_RESET_N, 0); _regs->misc_outs_reg.flush(); @@ -809,29 +945,34 @@ void x300_radio_ctrl_impl::reset_codec() void x300_radio_ctrl_impl::self_test_adc(uint32_t ramp_time_ms) { - //Bypass all front-end corrections + // Bypass all front-end corrections for (size_t i = 0; i < _get_num_radios(); i++) { _rx_fe_map[i].core->bypass_all(true); } - //Test basic patterns - _adc->set_test_word("ones", "ones"); _check_adc(0xfffcfffc); - _adc->set_test_word("zeros", "zeros"); _check_adc(0x00000000); - _adc->set_test_word("ones", "zeros"); _check_adc(0xfffc0000); - _adc->set_test_word("zeros", "ones"); _check_adc(0x0000fffc); + // Test basic patterns + _adc->set_test_word("ones", "ones"); + _check_adc(0xfffcfffc); + _adc->set_test_word("zeros", "zeros"); + _check_adc(0x00000000); + _adc->set_test_word("ones", "zeros"); + _check_adc(0xfffc0000); + _adc->set_test_word("zeros", "ones"); + _check_adc(0x0000fffc); for (size_t k = 0; k < 14; k++) { _adc->set_test_word("zeros", "custom", 1 << k); - _check_adc(1 << (k+2)); + _check_adc(1 << (k + 2)); } for (size_t k = 0; k < 14; k++) { _adc->set_test_word("custom", "zeros", 1 << k); - _check_adc(1 << (k+18)); + _check_adc(1 << (k + 18)); } - //Turn on ramp pattern test + // Turn on ramp pattern test _adc->set_test_word("ramp", "ramp"); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - //Sleep added for SPI transactions to finish and ramp to start before checker is enabled. + // Sleep added for SPI transactions to finish and ramp to start before checker is + // enabled. std::this_thread::sleep_for(std::chrono::microseconds(1000)); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); @@ -855,37 +996,46 @@ void x300_radio_ctrl_impl::self_test_adc(uint32_t ramp_time_ms) else q_status = "Not Locked!"; - //Return to normal mode + // Return to normal mode _adc->set_test_word("normal", "normal"); if ((i_status != "Good") or (q_status != "Good")) { throw uhd::runtime_error( - (boost::format("ADC self-test failed for %s. Ramp checker status: {ADC_A=%s, ADC_B=%s}")%unique_id()%i_status%q_status).str()); + (boost::format( + "ADC self-test failed for %s. Ramp checker status: {ADC_A=%s, ADC_B=%s}") + % unique_id() % i_status % q_status) + .str()); } - //Restore front-end corrections + // Restore front-end corrections for (size_t i = 0; i < _get_num_radios(); i++) { _rx_fe_map[i].core->bypass_all(false); } } -void x300_radio_ctrl_impl::extended_adc_test(const std::vector<x300_radio_ctrl_impl::sptr>& radios, double duration_s) +void x300_radio_ctrl_impl::extended_adc_test( + const std::vector<x300_radio_ctrl_impl::sptr>& radios, double duration_s) { static const size_t SECS_PER_ITER = 5; - UHD_LOGGER_INFO("X300 RADIO") << boost::format("Running Extended ADC Self-Test (Duration=%.0fs, %ds/iteration)...") - % duration_s % SECS_PER_ITER; + UHD_LOGGER_INFO("X300 RADIO") + << boost::format( + "Running Extended ADC Self-Test (Duration=%.0fs, %ds/iteration)...") + % duration_s % SECS_PER_ITER; - size_t num_iters = static_cast<size_t>(ceil(duration_s/SECS_PER_ITER)); + size_t num_iters = static_cast<size_t>(ceil(duration_s / SECS_PER_ITER)); size_t num_failures = 0; for (size_t iter = 0; iter < num_iters; iter++) { - //Run self-test - UHD_LOGGER_INFO("X300 RADIO") << boost::format("Extended ADC Self-Test Iteration %06d... ") % (iter+1); + // Run self-test + UHD_LOGGER_INFO("X300 RADIO") + << boost::format("Extended ADC Self-Test Iteration %06d... ") % (iter + 1); try { for (size_t i = 0; i < radios.size(); i++) { - radios[i]->self_test_adc((SECS_PER_ITER*1000)/radios.size()); + radios[i]->self_test_adc((SECS_PER_ITER * 1000) / radios.size()); } - UHD_LOGGER_INFO("X300 RADIO") << boost::format("Extended ADC Self-Test Iteration %06d passed ") % (iter+1); - } catch(std::exception &e) { + UHD_LOGGER_INFO("X300 RADIO") + << boost::format("Extended ADC Self-Test Iteration %06d passed ") + % (iter + 1); + } catch (std::exception& e) { num_failures++; UHD_LOGGER_ERROR("X300 RADIO") << e.what(); } @@ -894,75 +1044,82 @@ void x300_radio_ctrl_impl::extended_adc_test(const std::vector<x300_radio_ctrl_i UHD_LOGGER_INFO("X300 RADIO") << "Extended ADC Self-Test PASSED"; } else { throw uhd::runtime_error( - (boost::format("Extended ADC Self-Test FAILED!!! (%d/%d failures)\n") % num_failures % num_iters).str()); + (boost::format("Extended ADC Self-Test FAILED!!! (%d/%d failures)\n") + % num_failures % num_iters) + .str()); } } -void x300_radio_ctrl_impl::synchronize_dacs(const std::vector<x300_radio_ctrl_impl::sptr>& radios) +void x300_radio_ctrl_impl::synchronize_dacs( + const std::vector<x300_radio_ctrl_impl::sptr>& radios) { - if (radios.size() < 2) return; //Nothing to synchronize + if (radios.size() < 2) + return; // Nothing to synchronize //**PRECONDITION** - //This function assumes that all the VITA times in "radios" are synchronized - //to a common reference. Currently, this function is called in get_tx_stream - //which also has the same precondition. + // This function assumes that all the VITA times in "radios" are synchronized + // to a common reference. Currently, this function is called in get_tx_stream + // which also has the same precondition. - //Get a rough estimate of the cumulative command latency + // Get a rough estimate of the cumulative command latency boost::posix_time::ptime t_start = boost::posix_time::microsec_clock::local_time(); for (size_t i = 0; i < radios.size(); i++) { - radios[i]->user_reg_read64(regs::RB_TIME_NOW); //Discard value. We are just timing the call + radios[i]->user_reg_read64( + regs::RB_TIME_NOW); // Discard value. We are just timing the call } boost::posix_time::time_duration t_elapsed = boost::posix_time::microsec_clock::local_time() - t_start; - //Add 100% of headroom + uncertainty to the command time - uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 16000 /*Scheduler latency*/; + // Add 100% of headroom + uncertainty to the command time + uint64_t t_sync_us = + (t_elapsed.total_microseconds() * 2) + 16000 /*Scheduler latency*/; std::string err_str; - //Try to sync 3 times before giving up - for (size_t attempt = 0; attempt < 3; attempt++) - { - try - { - //Reinitialize and resync all DACs + // Try to sync 3 times before giving up + for (size_t attempt = 0; attempt < 3; attempt++) { + try { + // Reinitialize and resync all DACs for (size_t i = 0; i < radios.size(); i++) { radios[i]->_dac->sync(); } - //Set tick rate and make sure FRAMEP/N is 0 + // Set tick rate and make sure FRAMEP/N is 0 for (size_t i = 0; i < radios.size(); i++) { - radios[i]->set_command_tick_rate(radios[i]->_radio_clk_rate, IO_MASTER_RADIO); - radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); + radios[i]->set_command_tick_rate( + radios[i]->_radio_clk_rate, IO_MASTER_RADIO); + radios[i]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); } - //Pick radios[0] as the time reference. - uhd::time_spec_t sync_time = - radios[0]->_time64->get_time_now() + uhd::time_spec_t(((double)t_sync_us)/1e6); + // Pick radios[0] as the time reference. + uhd::time_spec_t sync_time = radios[0]->_time64->get_time_now() + + uhd::time_spec_t(((double)t_sync_us) / 1e6); - //Send the sync command + // Send the sync command for (size_t i = 0; i < radios.size(); i++) { radios[i]->set_command_time(sync_time, IO_MASTER_RADIO); - //Arm FRAMEP/N sync pulse by asserting a rising edge - radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1); + // Arm FRAMEP/N sync pulse by asserting a rising edge + radios[i]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 1); } - //Reset FRAMEP/N to 0 after 2 clock cycles + // Reset FRAMEP/N to 0 after 2 clock cycles for (size_t i = 0; i < radios.size(); i++) { - radios[i]->set_command_time(sync_time + (2.0 / radios[i]->_radio_clk_rate), IO_MASTER_RADIO); - radios[i]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); + radios[i]->set_command_time( + sync_time + (2.0 / radios[i]->_radio_clk_rate), IO_MASTER_RADIO); + radios[i]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::DAC_SYNC, 0); radios[i]->set_command_time(uhd::time_spec_t(0.0), IO_MASTER_RADIO); } - //Wait and check status + // Wait and check status std::this_thread::sleep_for(std::chrono::microseconds(t_sync_us)); for (size_t i = 0; i < radios.size(); i++) { radios[i]->_dac->verify_sync(); } return; - } - catch (const uhd::runtime_error &e) - { + } catch (const uhd::runtime_error& e) { err_str = e.what(); UHD_LOGGER_TRACE("X300 RADIO") << "Retrying DAC synchronization: " << err_str; } @@ -978,144 +1135,165 @@ double x300_radio_ctrl_impl::self_cal_adc_xfer_delay( { UHD_LOGGER_INFO("X300 RADIO") << "Running ADC transfer delay self-cal: "; - //Effective resolution of the self-cal. + // Effective resolution of the self-cal. static const size_t NUM_DELAY_STEPS = 100; - double master_clk_period = (1.0e9 / clock->get_master_clock_rate()); //in ns - double delay_start = 0.0; - double delay_range = 2 * master_clk_period; - double delay_incr = delay_range / NUM_DELAY_STEPS; + double master_clk_period = (1.0e9 / clock->get_master_clock_rate()); // in ns + double delay_start = 0.0; + double delay_range = 2 * master_clk_period; + double delay_incr = delay_range / NUM_DELAY_STEPS; double cached_clk_delay = clock->get_clock_delay(X300_CLOCK_WHICH_ADC0); - double fpga_clk_delay = clock->get_clock_delay(X300_CLOCK_WHICH_FPGA); + double fpga_clk_delay = clock->get_clock_delay(X300_CLOCK_WHICH_FPGA); - //Iterate through several values of delays and measure ADC data integrity - std::vector< std::pair<double,bool> > results; + // Iterate through several values of delays and measure ADC data integrity + std::vector<std::pair<double, bool>> results; for (size_t i = 0; i < NUM_DELAY_STEPS; i++) { - //Delay the ADC clock (will set both Ch0 and Ch1 delays) - double delay = clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, delay_incr*i + delay_start); + // Delay the ADC clock (will set both Ch0 and Ch1 delays) + double delay = + clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, delay_incr * i + delay_start); wait_for_clk_locked(0.1); uint32_t err_code = 0; for (size_t r = 0; r < radios.size(); r++) { - //Test each channel (I and Q) individually so as to not accidentally trigger - //on the data from the other channel if there is a swap + // Test each channel (I and Q) individually so as to not accidentally trigger + // on the data from the other channel if there is a swap // -- Test I Channel -- - //Put ADC in ramp test mode. Tie the other channel to all ones. + // Put ADC in ramp test mode. Tie the other channel to all ones. radios[r]->_adc->set_test_word("ramp", "ones"); - //Turn on the pattern checker in the FPGA. It will lock when it sees a zero - //and count deviations from the expected value - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //50ms @ 200MHz = 10 million samples + // Turn on the pattern checker in the FPGA. It will lock when it sees a zero + // and count deviations from the expected value + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); + // 50ms @ 200MHz = 10 million samples std::this_thread::sleep_for(std::chrono::milliseconds(50)); - if (radios[r]->_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_LOCKED)) { - err_code += radios[r]->_regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_ERROR); + if (radios[r]->_regs->misc_ins_reg.read( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_LOCKED)) { + err_code += radios[r]->_regs->misc_ins_reg.get( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_I_ERROR); } else { - err_code += 100; //Increment error code by 100 to indicate no lock + err_code += 100; // Increment error code by 100 to indicate no lock } // -- Test Q Channel -- - //Put ADC in ramp test mode. Tie the other channel to all ones. + // Put ADC in ramp test mode. Tie the other channel to all ones. radios[r]->_adc->set_test_word("ones", "ramp"); - //Turn on the pattern checker in the FPGA. It will lock when it sees a zero - //and count deviations from the expected value - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //50ms @ 200MHz = 10 million samples + // Turn on the pattern checker in the FPGA. It will lock when it sees a zero + // and count deviations from the expected value + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); + // 50ms @ 200MHz = 10 million samples std::this_thread::sleep_for(std::chrono::milliseconds(50)); - if (radios[r]->_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_LOCKED)) { - err_code += radios[r]->_regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_ERROR); + if (radios[r]->_regs->misc_ins_reg.read( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_LOCKED)) { + err_code += radios[r]->_regs->misc_ins_reg.get( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER1_Q_ERROR); } else { - err_code += 100; //Increment error code by 100 to indicate no lock + err_code += 100; // Increment error code by 100 to indicate no lock } } - //UHD_LOGGER_INFO("X300 RADIO") << (boost::format("XferDelay=%fns, Error=%d") % delay % err_code); - results.push_back(std::pair<double,bool>(delay, err_code==0)); + // UHD_LOGGER_INFO("X300 RADIO") << (boost::format("XferDelay=%fns, Error=%d") % + // delay % err_code); + results.push_back(std::pair<double, bool>(delay, err_code == 0)); } - //Calculate the valid window + // Calculate the valid window int win_start_idx = -1, win_stop_idx = -1, cur_start_idx = -1, cur_stop_idx = -1; for (size_t i = 0; i < results.size(); i++) { - std::pair<double,bool>& item = results[i]; - if (item.second) { //If data is stable - if (cur_start_idx == -1) { //This is the first window + std::pair<double, bool>& item = results[i]; + if (item.second) { // If data is stable + if (cur_start_idx == -1) { // This is the first window cur_start_idx = i; - cur_stop_idx = i; - } else { //We are extending the window + cur_stop_idx = i; + } else { // We are extending the window cur_stop_idx = i; } } else { - if (cur_start_idx == -1) { //We haven't yet seen valid data - //Do nothing - } else if (win_start_idx == -1) { //We passed the first valid window + if (cur_start_idx == -1) { // We haven't yet seen valid data + // Do nothing + } else if (win_start_idx == -1) { // We passed the first valid window win_start_idx = cur_start_idx; - win_stop_idx = cur_stop_idx; - } else { //Update cached window if current window is larger - double cur_win_len = results[cur_stop_idx].first - results[cur_start_idx].first; - double cached_win_len = results[win_stop_idx].first - results[win_start_idx].first; + win_stop_idx = cur_stop_idx; + } else { // Update cached window if current window is larger + double cur_win_len = + results[cur_stop_idx].first - results[cur_start_idx].first; + double cached_win_len = + results[win_stop_idx].first - results[win_start_idx].first; if (cur_win_len > cached_win_len) { win_start_idx = cur_start_idx; - win_stop_idx = cur_stop_idx; + win_stop_idx = cur_stop_idx; } } - //Reset current window + // Reset current window cur_start_idx = -1; - cur_stop_idx = -1; + cur_stop_idx = -1; } } if (win_start_idx == -1) { - throw uhd::runtime_error("self_cal_adc_xfer_delay: Self calibration failed. Convergence error."); + throw uhd::runtime_error( + "self_cal_adc_xfer_delay: Self calibration failed. Convergence error."); } - double win_center = (results[win_stop_idx].first + results[win_start_idx].first) / 2.0; + double win_center = + (results[win_stop_idx].first + results[win_start_idx].first) / 2.0; double win_length = results[win_stop_idx].first - results[win_start_idx].first; - if (win_length < master_clk_period/4) { - throw uhd::runtime_error("self_cal_adc_xfer_delay: Self calibration failed. Valid window too narrow."); + if (win_length < master_clk_period / 4) { + throw uhd::runtime_error( + "self_cal_adc_xfer_delay: Self calibration failed. Valid window too narrow."); } - //Cycle slip the relative delay by a clock cycle to prevent sample misalignment - //fpga_clk_delay > 0 and 0 < win_center < 2*(1/MCR) so one cycle slip is all we need - bool cycle_slip = (win_center-fpga_clk_delay >= master_clk_period); + // Cycle slip the relative delay by a clock cycle to prevent sample misalignment + // fpga_clk_delay > 0 and 0 < win_center < 2*(1/MCR) so one cycle slip is all we need + bool cycle_slip = (win_center - fpga_clk_delay >= master_clk_period); if (cycle_slip) { win_center -= master_clk_period; } if (apply_delay) { - //Apply delay - win_center = clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, win_center); //Sets ADC0 and ADC1 + // Apply delay + win_center = clock->set_clock_delay( + X300_CLOCK_WHICH_ADC0, win_center); // Sets ADC0 and ADC1 wait_for_clk_locked(0.1); - //Validate + // Validate for (size_t r = 0; r < radios.size(); r++) { radios[r]->self_test_adc(2000); } } else { - //Restore delay - clock->set_clock_delay(X300_CLOCK_WHICH_ADC0, cached_clk_delay); //Sets ADC0 and ADC1 + // Restore delay + clock->set_clock_delay( + X300_CLOCK_WHICH_ADC0, cached_clk_delay); // Sets ADC0 and ADC1 } - //Teardown + // Teardown for (size_t r = 0; r < radios.size(); r++) { radios[r]->_adc->set_test_word("normal", "normal"); - radios[r]->_regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + radios[r]->_regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); } - UHD_LOGGER_INFO("X300 RADIO") << (boost::format("ADC transfer delay self-cal done (FPGA->ADC=%.3fns%s, Window=%.3fns)") % - (win_center-fpga_clk_delay) % (cycle_slip?" +cyc":"") % win_length); + UHD_LOGGER_INFO("X300 RADIO") + << (boost::format( + "ADC transfer delay self-cal done (FPGA->ADC=%.3fns%s, Window=%.3fns)") + % (win_center - fpga_clk_delay) % (cycle_slip ? " +cyc" : "") + % win_length); return win_center; } /**************************************************************************** * Helpers ***************************************************************************/ -void x300_radio_ctrl_impl::_update_atr_leds(const std::string &rx_ant, const size_t chan) +void x300_radio_ctrl_impl::_update_atr_leds(const std::string& rx_ant, const size_t chan) { // The "RX1" port is used by TwinRX and the "TX/RX" port is used by all // other full-duplex dboards. We need to handle both here. const bool is_txrx = (rx_ant == "TX/RX" or rx_ant == "RX1"); - const int TXRX_RX = (1 << 0); - const int TXRX_TX = (1 << 1); - const int RX2_RX = (1 << 2); + const int TXRX_RX = (1 << 0); + const int TXRX_TX = (1 << 1); + const int RX2_RX = (1 << 2); _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_IDLE, 0); _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY, is_txrx ? TXRX_RX : RX2_RX); _leds.at(chan)->set_atr_reg(gpio_atr::ATR_REG_TX_ONLY, TXRX_TX); @@ -1124,76 +1302,91 @@ void x300_radio_ctrl_impl::_update_atr_leds(const std::string &rx_ant, const siz void x300_radio_ctrl_impl::_self_cal_adc_capture_delay(bool print_status) { - if (print_status) UHD_LOGGER_INFO("X300 RADIO") << "Running ADC capture delay self-cal..."; + if (print_status) + UHD_LOGGER_INFO("X300 RADIO") << "Running ADC capture delay self-cal..."; - static const uint32_t NUM_DELAY_STEPS = 32; //The IDELAYE2 element has 32 steps - static const uint32_t NUM_RETRIES = 2; //Retry self-cal if it fails in warmup situations - static const int32_t MIN_WINDOW_LEN = 4; + static const uint32_t NUM_DELAY_STEPS = 32; // The IDELAYE2 element has 32 steps + static const uint32_t NUM_RETRIES = + 2; // Retry self-cal if it fails in warmup situations + static const int32_t MIN_WINDOW_LEN = 4; int32_t win_start = -1, win_stop = -1; uint32_t iter = 0; while (iter++ < NUM_RETRIES) { for (uint32_t dly_tap = 0; dly_tap < NUM_DELAY_STEPS; dly_tap++) { - //Apply delay - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, dly_tap); - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0); + // Apply delay + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, dly_tap); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0); uint32_t err_code = 0; // -- Test I Channel -- - //Put ADC in ramp test mode. Tie the other channel to all ones. + // Put ADC in ramp test mode. Tie the other channel to all ones. _adc->set_test_word("ramp", "ones"); - //Turn on the pattern checker in the FPGA. It will lock when it sees a zero - //and count deviations from the expected value - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //5ms @ 200MHz = 1 million samples + // Turn on the pattern checker in the FPGA. It will lock when it sees a zero + // and count deviations from the expected value + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); + // 5ms @ 200MHz = 1 million samples std::this_thread::sleep_for(std::chrono::milliseconds(5)); - if (_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_LOCKED)) { - err_code += _regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_ERROR); + if (_regs->misc_ins_reg.read( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_LOCKED)) { + err_code += _regs->misc_ins_reg.get( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_ERROR); } else { - err_code += 100; //Increment error code by 100 to indicate no lock + err_code += 100; // Increment error code by 100 to indicate no lock } // -- Test Q Channel -- - //Put ADC in ramp test mode. Tie the other channel to all ones. + // Put ADC in ramp test mode. Tie the other channel to all ones. _adc->set_test_word("ones", "ramp"); - //Turn on the pattern checker in the FPGA. It will lock when it sees a zero - //and count deviations from the expected value - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //5ms @ 200MHz = 1 million samples + // Turn on the pattern checker in the FPGA. It will lock when it sees a zero + // and count deviations from the expected value + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); + // 5ms @ 200MHz = 1 million samples std::this_thread::sleep_for(std::chrono::milliseconds(5)); - if (_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_LOCKED)) { - err_code += _regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_ERROR); + if (_regs->misc_ins_reg.read( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_LOCKED)) { + err_code += _regs->misc_ins_reg.get( + radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_ERROR); } else { - err_code += 100; //Increment error code by 100 to indicate no lock + err_code += 100; // Increment error code by 100 to indicate no lock } if (err_code == 0) { - if (win_start == -1) { //This is the first window + if (win_start == -1) { // This is the first window win_start = dly_tap; - win_stop = dly_tap; - } else { //We are extending the window + win_stop = dly_tap; + } else { // We are extending the window win_stop = dly_tap; } } else { - if (win_start != -1) { //A valid window turned invalid + if (win_start != -1) { // A valid window turned invalid if (win_stop - win_start >= MIN_WINDOW_LEN) { - break; //Valid window found + break; // Valid window found } else { - win_start = -1; //Reset window + win_start = -1; // Reset window } } } - //UHD_LOGGER_INFO("X300 RADIO") << (boost::format("CapTap=%d, Error=%d") % dly_tap % err_code); + // UHD_LOGGER_INFO("X300 RADIO") << (boost::format("CapTap=%d, Error=%d") % + // dly_tap % err_code); } - //Retry the self-cal if it fails - if ((win_start == -1 || (win_stop - win_start) < MIN_WINDOW_LEN) && iter < NUM_RETRIES /*not last iteration*/) { + // Retry the self-cal if it fails + if ((win_start == -1 || (win_stop - win_start) < MIN_WINDOW_LEN) + && iter < NUM_RETRIES /*not last iteration*/) { win_start = -1; - win_stop = -1; + win_stop = -1; std::this_thread::sleep_for(std::chrono::milliseconds(2000)); } else { break; @@ -1203,46 +1396,55 @@ void x300_radio_ctrl_impl::_self_cal_adc_capture_delay(bool print_status) _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); if (win_start == -1) { - throw uhd::runtime_error("self_cal_adc_capture_delay: Self calibration failed. Convergence error."); + throw uhd::runtime_error( + "self_cal_adc_capture_delay: Self calibration failed. Convergence error."); } - if (win_stop-win_start < MIN_WINDOW_LEN) { - throw uhd::runtime_error("self_cal_adc_capture_delay: Self calibration failed. Valid window too narrow."); + if (win_stop - win_start < MIN_WINDOW_LEN) { + throw uhd::runtime_error("self_cal_adc_capture_delay: Self calibration failed. " + "Valid window too narrow."); } uint32_t ideal_tap = (win_stop + win_start) / 2; - _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, ideal_tap); + _regs->misc_outs_reg.write( + radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_VAL, ideal_tap); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 1); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_DATA_DLY_STB, 0); if (print_status) { - double tap_delay = (1.0e12 / _radio_clk_rate) / (2*32); //in ps - UHD_LOGGER_INFO("X300 RADIO") << boost::format("ADC capture delay self-cal done (Tap=%d, Window=%d, TapDelay=%.3fps, Iter=%d)") % ideal_tap % (win_stop-win_start) % tap_delay % iter; + double tap_delay = (1.0e12 / _radio_clk_rate) / (2 * 32); // in ps + UHD_LOGGER_INFO("X300 RADIO") + << boost::format("ADC capture delay self-cal done (Tap=%d, Window=%d, " + "TapDelay=%.3fps, Iter=%d)") + % ideal_tap % (win_stop - win_start) % tap_delay % iter; } } void x300_radio_ctrl_impl::_check_adc(const uint32_t val) { - //Wait for previous control transaction to flush + // Wait for previous control transaction to flush user_reg_read64(regs::RB_TEST); - //Wait for ADC test pattern to propagate + // Wait for ADC test pattern to propagate std::this_thread::sleep_for(std::chrono::microseconds(5)); - //Read value of RX readback register and verify - uint32_t adc_rb = static_cast<uint32_t>(user_reg_read64(regs::RB_TEST)>>32); - adc_rb ^= 0xfffc0000; //adapt for I inversion in FPGA + // Read value of RX readback register and verify + uint32_t adc_rb = static_cast<uint32_t>(user_reg_read64(regs::RB_TEST) >> 32); + adc_rb ^= 0xfffc0000; // adapt for I inversion in FPGA if (val != adc_rb) { throw uhd::runtime_error( - (boost::format("ADC self-test failed for %s. (Exp=0x%x, Got=0x%x)")%unique_id()%val%adc_rb).str()); + (boost::format("ADC self-test failed for %s. (Exp=0x%x, Got=0x%x)") + % unique_id() % val % adc_rb) + .str()); } } -void x300_radio_ctrl_impl::_set_db_eeprom(i2c_iface::sptr i2c, const size_t addr, const uhd::usrp::dboard_eeprom_t &db_eeprom) +void x300_radio_ctrl_impl::_set_db_eeprom( + i2c_iface::sptr i2c, const size_t addr, const uhd::usrp::dboard_eeprom_t& db_eeprom) { db_eeprom.store(*i2c, addr); _db_eeproms[addr] = db_eeprom; } -void x300_radio_ctrl_impl::_set_command_time(const time_spec_t &spec, const size_t port) +void x300_radio_ctrl_impl::_set_command_time(const time_spec_t& spec, const size_t port) { set_fe_cmd_time(spec, port); } @@ -1251,15 +1453,16 @@ void x300_radio_ctrl_impl::_set_command_time(const time_spec_t &spec, const size ***************************************************************************/ bool x300_radio_ctrl_impl::check_radio_config() { - UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::check_radio_config() " ; + UHD_RFNOC_BLOCK_TRACE() << "x300_radio_ctrl_impl::check_radio_config() "; const fs_path rx_fe_path = fs_path("dboards" / _radio_slot / "rx_frontends"); for (size_t chan = 0; chan < _num_rx_channels; chan++) { if (_tree->exists(rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "enabled")) { const bool chan_active = _is_streamer_active(uhd::RX_DIRECTION, chan); if (chan_active) { - _tree->access<bool>(rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "enabled") - .set(chan_active) - ; + _tree + ->access<bool>( + rx_fe_path / _rx_fe_map.at(chan).db_fe_name / "enabled") + .set(chan_active); } } } @@ -1269,9 +1472,10 @@ bool x300_radio_ctrl_impl::check_radio_config() if (_tree->exists(tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "enabled")) { const bool chan_active = _is_streamer_active(uhd::TX_DIRECTION, chan); if (chan_active) { - _tree->access<bool>(tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "enabled") - .set(chan_active) - ; + _tree + ->access<bool>( + tx_fe_path / _tx_fe_map.at(chan).db_fe_name / "enabled") + .set(chan_active); } } } diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp index 7b02f2cf1..7cc0ea18d 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp @@ -8,8 +8,8 @@ #ifndef INCLUDED_LIBUHD_RFNOC_X300_RADIO_CTRL_IMPL_HPP #define INCLUDED_LIBUHD_RFNOC_X300_RADIO_CTRL_IMPL_HPP -#include "x300_clock_ctrl.hpp" #include "x300_adc_ctrl.hpp" +#include "x300_clock_ctrl.hpp" #include "x300_dac_ctrl.hpp" #include "x300_regs.hpp" #include <uhd/usrp/dboard_eeprom.hpp> @@ -17,11 +17,10 @@ #include <uhd/usrp/gpio_defs.hpp> #include <uhdlib/rfnoc/radio_ctrl_impl.hpp> #include <uhdlib/usrp/cores/rx_frontend_core_3000.hpp> -#include <uhdlib/usrp/cores/tx_frontend_core_200.hpp> #include <uhdlib/usrp/cores/spi_core_3000.hpp> +#include <uhdlib/usrp/cores/tx_frontend_core_200.hpp> -namespace uhd { - namespace rfnoc { +namespace uhd { namespace rfnoc { /*! \brief Provide access to an X300 radio. */ @@ -41,8 +40,8 @@ public: ***********************************************************************/ double set_rate(double rate); - void set_tx_antenna(const std::string &ant, const size_t chan); - void set_rx_antenna(const std::string &ant, const size_t chan); + void set_tx_antenna(const std::string& ant, const size_t chan); + void set_rx_antenna(const std::string& ant, const size_t chan); std::string get_tx_antenna(const size_t chan); std::string get_rx_antenna(const size_t chan); @@ -57,24 +56,30 @@ public: double set_rx_gain(const double gain, const size_t chan); std::vector<std::string> get_rx_lo_names(const size_t chan); - std::vector<std::string> get_rx_lo_sources(const std::string &name, const size_t chan); - freq_range_t get_rx_lo_freq_range(const std::string &name, const size_t chan); + std::vector<std::string> get_rx_lo_sources( + const std::string& name, const size_t chan); + freq_range_t get_rx_lo_freq_range(const std::string& name, const size_t chan); - void set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan); - const std::string get_rx_lo_source(const std::string &name, const size_t chan); + void set_rx_lo_source( + const std::string& src, const std::string& name, const size_t chan); + const std::string get_rx_lo_source(const std::string& name, const size_t chan); - void set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan); - bool get_rx_lo_export_enabled(const std::string &name, const size_t chan); + void set_rx_lo_export_enabled( + bool enabled, const std::string& name, const size_t chan); + bool get_rx_lo_export_enabled(const std::string& name, const size_t chan); - double set_rx_lo_freq(double freq, const std::string &name, const size_t chan); - double get_rx_lo_freq(const std::string &name, const size_t chan); + double set_rx_lo_freq(double freq, const std::string& name, const size_t chan); + double get_rx_lo_freq(const std::string& name, const size_t chan); - size_t get_chan_from_dboard_fe(const std::string &fe, const direction_t dir); + size_t get_chan_from_dboard_fe(const std::string& fe, const direction_t dir); std::string get_dboard_fe_from_chan(const size_t chan, const direction_t dir); std::vector<std::string> get_gpio_banks() const; - void set_gpio_attr(const std::string &bank, const std::string &attr, const uint32_t value, const uint32_t mask); - uint32_t get_gpio_attr(const std::string &bank, const std::string &attr); + void set_gpio_attr(const std::string& bank, + const std::string& attr, + const uint32_t value, + const uint32_t mask); + uint32_t get_gpio_attr(const std::string& bank, const std::string& attr); double get_output_samp_rate(size_t port); @@ -83,23 +88,19 @@ public: ***********************************************************************/ /*! Set up the radio. No API calls may be made before this one. */ - void setup_radio( - uhd::i2c_iface::sptr zpu_i2c, + void setup_radio(uhd::i2c_iface::sptr zpu_i2c, x300_clock_ctrl::sptr clock, bool ignore_cal_file, - bool verbose - ); + bool verbose); void reset_codec(); - void self_test_adc( - uint32_t ramp_time_ms = 100); + void self_test_adc(uint32_t ramp_time_ms = 100); static void extended_adc_test( const std::vector<x300_radio_ctrl_impl::sptr>&, double duration_s); - static void synchronize_dacs( - const std::vector<x300_radio_ctrl_impl::sptr>& radios); + static void synchronize_dacs(const std::vector<x300_radio_ctrl_impl::sptr>& radios); static double self_cal_adc_xfer_delay( const std::vector<x300_radio_ctrl_impl::sptr>& radios, @@ -111,21 +112,25 @@ protected: virtual bool check_radio_config(); private: - class radio_regmap_t : public uhd::soft_regmap_t { + class radio_regmap_t : public uhd::soft_regmap_t + { public: typedef boost::shared_ptr<radio_regmap_t> sptr; - class misc_outs_reg_t : public uhd::soft_reg32_wo_t { + class misc_outs_reg_t : public uhd::soft_reg32_wo_t + { public: - UHD_DEFINE_SOFT_REG_FIELD(DAC_ENABLED, /*width*/ 1, /*shift*/ 0); //[0] - UHD_DEFINE_SOFT_REG_FIELD(DAC_RESET_N, /*width*/ 1, /*shift*/ 1); //[1] - UHD_DEFINE_SOFT_REG_FIELD(ADC_RESET, /*width*/ 1, /*shift*/ 2); //[2] - UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_STB, /*width*/ 1, /*shift*/ 3); //[3] - UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_VAL, /*width*/ 5, /*shift*/ 4); //[8:4] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER_ENABLED, /*width*/ 1, /*shift*/ 9); //[9] - UHD_DEFINE_SOFT_REG_FIELD(DAC_SYNC, /*width*/ 1, /*shift*/ 10); //[10] - - misc_outs_reg_t(): uhd::soft_reg32_wo_t(regs::sr_addr(regs::MISC_OUTS)) { - //Initial values + UHD_DEFINE_SOFT_REG_FIELD(DAC_ENABLED, /*width*/ 1, /*shift*/ 0); //[0] + UHD_DEFINE_SOFT_REG_FIELD(DAC_RESET_N, /*width*/ 1, /*shift*/ 1); //[1] + UHD_DEFINE_SOFT_REG_FIELD(ADC_RESET, /*width*/ 1, /*shift*/ 2); //[2] + UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_STB, /*width*/ 1, /*shift*/ 3); //[3] + UHD_DEFINE_SOFT_REG_FIELD(ADC_DATA_DLY_VAL, /*width*/ 5, /*shift*/ 4); //[8:4] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER_ENABLED, /*width*/ 1, /*shift*/ 9); //[9] + UHD_DEFINE_SOFT_REG_FIELD(DAC_SYNC, /*width*/ 1, /*shift*/ 10); //[10] + + misc_outs_reg_t() : uhd::soft_reg32_wo_t(regs::sr_addr(regs::MISC_OUTS)) + { + // Initial values set(DAC_ENABLED, 0); set(DAC_RESET_N, 0); set(ADC_RESET, 0); @@ -136,77 +141,96 @@ private: } } misc_outs_reg; - class misc_ins_reg_t : public uhd::soft_reg64_ro_t { + class misc_ins_reg_t : public uhd::soft_reg64_ro_t + { public: - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_Q_LOCKED, /*width*/ 1, /*shift*/ 32); //[0] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_I_LOCKED, /*width*/ 1, /*shift*/ 33); //[1] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_LOCKED, /*width*/ 1, /*shift*/ 34); //[2] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_LOCKED, /*width*/ 1, /*shift*/ 35); //[3] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_Q_ERROR, /*width*/ 1, /*shift*/ 36); //[4] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER0_I_ERROR, /*width*/ 1, /*shift*/ 37); //[5] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_Q_ERROR, /*width*/ 1, /*shift*/ 38); //[6] - UHD_DEFINE_SOFT_REG_FIELD(ADC_CHECKER1_I_ERROR, /*width*/ 1, /*shift*/ 39); //[7] - - misc_ins_reg_t(): uhd::soft_reg64_ro_t(regs::rb_addr(regs::RB_MISC_IO)) { } + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER0_Q_LOCKED, /*width*/ 1, /*shift*/ 32); //[0] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER0_I_LOCKED, /*width*/ 1, /*shift*/ 33); //[1] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER1_Q_LOCKED, /*width*/ 1, /*shift*/ 34); //[2] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER1_I_LOCKED, /*width*/ 1, /*shift*/ 35); //[3] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER0_Q_ERROR, /*width*/ 1, /*shift*/ 36); //[4] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER0_I_ERROR, /*width*/ 1, /*shift*/ 37); //[5] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER1_Q_ERROR, /*width*/ 1, /*shift*/ 38); //[6] + UHD_DEFINE_SOFT_REG_FIELD( + ADC_CHECKER1_I_ERROR, /*width*/ 1, /*shift*/ 39); //[7] + + misc_ins_reg_t() : uhd::soft_reg64_ro_t(regs::rb_addr(regs::RB_MISC_IO)) {} } misc_ins_reg; - radio_regmap_t(int radio_num) : soft_regmap_t("radio" + std::to_string(radio_num) + "_regmap") { + radio_regmap_t(int radio_num) + : soft_regmap_t("radio" + std::to_string(radio_num) + "_regmap") + { add_to_map(misc_outs_reg, "misc_outs_reg", PRIVATE); add_to_map(misc_ins_reg, "misc_ins_reg", PRIVATE); } }; - struct x300_regs { - static const uint32_t TX_FE_BASE = 224; - static const uint32_t RX_FE_BASE = 232; + struct x300_regs + { + static const uint32_t TX_FE_BASE = 224; + static const uint32_t RX_FE_BASE = 232; }; - void _update_atr_leds(const std::string &rx_ant, const size_t chan); + void _update_atr_leds(const std::string& rx_ant, const size_t chan); void _self_cal_adc_capture_delay(bool print_status); void _check_adc(const uint32_t val); - void _set_db_eeprom(uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t &); + void _set_db_eeprom( + uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t&); - void set_rx_fe_corrections(const uhd::fs_path &db_path, const uhd::fs_path &rx_fe_corr_path, const double lo_freq); - void set_tx_fe_corrections(const uhd::fs_path &db_path, const uhd::fs_path &tx_fe_corr_path, const double lo_freq); + void set_rx_fe_corrections(const uhd::fs_path& db_path, + const uhd::fs_path& rx_fe_corr_path, + const double lo_freq); + void set_tx_fe_corrections(const uhd::fs_path& db_path, + const uhd::fs_path& tx_fe_corr_path, + const double lo_freq); - void _set_command_time(const uhd::time_spec_t &spec, const size_t port); - void set_fe_cmd_time(const time_spec_t &time, const size_t chan); + void _set_command_time(const uhd::time_spec_t& spec, const size_t port); + void set_fe_cmd_time(const time_spec_t& time, const size_t chan); private: // members enum radio_connection_t { PRIMARY, SECONDARY }; - radio_connection_t _radio_type; - std::string _radio_slot; + radio_connection_t _radio_type; + std::string _radio_slot; //! Radio clock rate is the rate at which the ADC and DAC are running at. // Not necessarily this block's sampling rate (tick rate). - double _radio_clk_rate; + double _radio_clk_rate; - radio_regmap_t::sptr _regs; - std::map<size_t, usrp::gpio_atr::gpio_atr_3000::sptr> _leds; - spi_core_3000::sptr _spi; - x300_adc_ctrl::sptr _adc; - x300_dac_ctrl::sptr _dac; - usrp::gpio_atr::gpio_atr_3000::sptr _fp_gpio; + radio_regmap_t::sptr _regs; + std::map<size_t, usrp::gpio_atr::gpio_atr_3000::sptr> _leds; + spi_core_3000::sptr _spi; + x300_adc_ctrl::sptr _adc; + x300_dac_ctrl::sptr _dac; + usrp::gpio_atr::gpio_atr_3000::sptr _fp_gpio; std::map<size_t, usrp::dboard_eeprom_t> _db_eeproms; - usrp::dboard_manager::sptr _db_manager; + usrp::dboard_manager::sptr _db_manager; - struct rx_fe_perif { - std::string name; - std::string db_fe_name; + struct rx_fe_perif + { + std::string name; + std::string db_fe_name; rx_frontend_core_3000::sptr core; }; - struct tx_fe_perif { - std::string name; - std::string db_fe_name; - tx_frontend_core_200::sptr core; + struct tx_fe_perif + { + std::string name; + std::string db_fe_name; + tx_frontend_core_200::sptr core; }; - std::map<size_t, rx_fe_perif> _rx_fe_map; - std::map<size_t, tx_fe_perif> _tx_fe_map; + std::map<size_t, rx_fe_perif> _rx_fe_map; + std::map<size_t, tx_fe_perif> _tx_fe_map; bool _ignore_cal_file; diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index 5fdc89979..d2677c05e 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -9,22 +9,22 @@ #define INCLUDED_X300_REGS_HPP #include <uhd/config.hpp> -#include <stdint.h> #include <uhd/utils/soft_register.hpp> +#include <stdint.h> -static const int BL_ADDRESS = 0; -static const int BL_DATA = 1; +static const int BL_ADDRESS = 0; +static const int BL_DATA = 1; -//wishbone settings map - relevant to host code -#define SET0_BASE 0xa000 -#define SETXB_BASE 0xb000 +// wishbone settings map - relevant to host code +#define SET0_BASE 0xa000 +#define SETXB_BASE 0xb000 #define BOOT_LDR_BASE 0xfa00 -#define I2C0_BASE 0xfe00 -#define I2C1_BASE 0xff00 +#define I2C0_BASE 0xfe00 +#define I2C1_BASE 0xff00 #define SR_ADDR(base, offset) ((base) + (offset)*4) -//I2C1 device addresses -#define MBOARD_EEPROM_ADDR 0x50 +// I2C1 device addresses +#define MBOARD_EEPROM_ADDR 0x50 static const int ZPU_SR_LEDS = 00; static const int ZPU_SR_SW_RST = 01; @@ -37,11 +37,11 @@ static const int ZPU_SR_ETHINT1 = 56; static const int ZPU_SR_DRAM_FIFO0 = 72; static const int ZPU_SR_DRAM_FIFO1 = 80; -//reset bits -#define ZPU_SR_SW_RST_ETH_PHY (1<<0) -#define ZPU_SR_SW_RST_RADIO_RST (1<<1) -#define ZPU_SR_SW_RST_RADIO_CLK_PLL (1<<2) -#define ZPU_SR_SW_RST_ADC_IDELAYCTRL (1<<3) +// reset bits +#define ZPU_SR_SW_RST_ETH_PHY (1 << 0) +#define ZPU_SR_SW_RST_RADIO_RST (1 << 1) +#define ZPU_SR_SW_RST_RADIO_CLK_PLL (1 << 2) +#define ZPU_SR_SW_RST_ADC_IDELAYCTRL (1 << 3) static const int ZPU_RB_SPI = 2; static const int ZPU_RB_CLK_STATUS = 3; @@ -55,23 +55,23 @@ static const uint32_t RB_SFP_1G_ETH = 0; static const uint32_t RB_SFP_10G_ETH = 1; static const uint32_t RB_SFP_AURORA = 2; -//spi slaves on radio -#define DB_DAC_SEN (1 << 7) -#define DB_ADC_SEN (1 << 6) +// spi slaves on radio +#define DB_DAC_SEN (1 << 7) +#define DB_ADC_SEN (1 << 6) #define DB_RX_LSADC_SEN (1 << 5) #define DB_RX_LSDAC_SEN (1 << 4) #define DB_TX_LSADC_SEN (1 << 3) #define DB_TX_LSDAC_SEN (1 << 2) -#define DB_RX_SEN (1 << 1) -#define DB_TX_SEN (1 << 0) +#define DB_RX_SEN (1 << 1) +#define DB_TX_SEN (1 << 0) //------------------------------------------------------------------- // PCIe Registers //------------------------------------------------------------------- -static const uint32_t X300_PCIE_VID = 0x1093; -static const uint32_t X300_PCIE_PID = 0xC4C4; -//Rev 0-6 motherboard/PCIe IDs (ADC driven at 3.3V) +static const uint32_t X300_PCIE_VID = 0x1093; +static const uint32_t X300_PCIE_PID = 0xC4C4; +// Rev 0-6 motherboard/PCIe IDs (ADC driven at 3.3V) static const uint32_t X300_USRP_PCIE_SSID_ADC_33 = 0x7736; static const uint32_t X310_USRP_PCIE_SSID_ADC_33 = 0x76CA; static const uint32_t X310_2940R_40MHz_PCIE_SSID_ADC_33 = 0x772B; @@ -88,7 +88,7 @@ static const uint32_t X310_2952R_120MHz_PCIE_SSID_ADC_33 = 0x77FF; static const uint32_t X310_2953R_40MHz_PCIE_SSID_ADC_33 = 0x7731; static const uint32_t X310_2953R_120MHz_PCIE_SSID_ADC_33 = 0x7800; static const uint32_t X310_2954R_40MHz_PCIE_SSID_ADC_33 = 0x7732; -//Rev 7+ motherboard/PCIe IDs (ADCs driven at 1.8V) +// Rev 7+ motherboard/PCIe IDs (ADCs driven at 1.8V) static const uint32_t X300_USRP_PCIE_SSID_ADC_18 = 0x7861; static const uint32_t X310_USRP_PCIE_SSID_ADC_18 = 0x7862; static const uint32_t X310_2940R_40MHz_PCIE_SSID_ADC_18 = 0x7853; @@ -109,10 +109,10 @@ static const uint32_t X310_2954R_40MHz_PCIE_SSID_ADC_18 = 0x785A; static const uint32_t X310_2955R_PCIE_SSID_ADC_18 = 0x78F0; static const uint32_t X310_2974_PCIE_SSID_ADC_18 = 0x799B; -static const uint32_t FPGA_X3xx_SIG_VALUE = 0x58333030; +static const uint32_t FPGA_X3xx_SIG_VALUE = 0x58333030; -static const uint32_t PCIE_FPGA_ADDR_BASE = 0xC0000; -#define PCIE_FPGA_REG(X) (PCIE_FPGA_ADDR_BASE + (X)) +static const uint32_t PCIE_FPGA_ADDR_BASE = 0xC0000; +#define PCIE_FPGA_REG(X) (PCIE_FPGA_ADDR_BASE + (X)) static const uint32_t FPGA_PCIE_SIG_REG = PCIE_FPGA_REG(0x0000); static const uint32_t FPGA_CNTR_LO_REG = PCIE_FPGA_REG(0x0004); @@ -124,38 +124,40 @@ static const uint32_t FPGA_USR_SIG_REG_SIZE = 16; static const uint32_t FPGA_STATUS_DMA_ACTIVE_MASK = 0x3F3F0000; -static const uint32_t PCIE_TX_DMA_REG_BASE = PCIE_FPGA_REG(0x0200); -static const uint32_t PCIE_RX_DMA_REG_BASE = PCIE_FPGA_REG(0x0400); - -static const uint32_t DMA_REG_GRP_SIZE = 16; -static const uint32_t DMA_CTRL_STATUS_REG = 0x0; -static const uint32_t DMA_FRAME_SIZE_REG = 0x4; -static const uint32_t DMA_SAMPLE_COUNT_REG = 0x8; -static const uint32_t DMA_PKT_COUNT_REG = 0xC; - -#define PCIE_TX_DMA_REG(REG, CHAN) (PCIE_TX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) -#define PCIE_RX_DMA_REG(REG, CHAN) (PCIE_RX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) - -static const uint32_t DMA_CTRL_DISABLED = 0x00000000; -static const uint32_t DMA_CTRL_ENABLED = 0x00000002; -static const uint32_t DMA_CTRL_CLEAR_STB = 0x00000001; -static const uint32_t DMA_CTRL_SW_BUF_U64 = (3 << 4); -static const uint32_t DMA_CTRL_SW_BUF_U32 = (2 << 4); -static const uint32_t DMA_CTRL_SW_BUF_U16 = (1 << 4); -static const uint32_t DMA_CTRL_SW_BUF_U8 = (0 << 4); -static const uint32_t DMA_STATUS_ERROR = 0x00000001; -static const uint32_t DMA_STATUS_BUSY = 0x00000002; - -static const uint32_t PCIE_ROUTER_REG_BASE = PCIE_FPGA_REG(0x0500); -#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + (X)) - -static const uint32_t PCIE_ZPU_DATA_BASE = 0x30000; -static const uint32_t PCIE_ZPU_READ_BASE = 0x20000; //Trig and Status share the same base -static const uint32_t PCIE_ZPU_STATUS_BASE = 0x20000; - -#define PCIE_ZPU_DATA_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + (X)) -#define PCIE_ZPU_READ_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + (X)) -#define PCIE_ZPU_STATUS_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + (X)) +static const uint32_t PCIE_TX_DMA_REG_BASE = PCIE_FPGA_REG(0x0200); +static const uint32_t PCIE_RX_DMA_REG_BASE = PCIE_FPGA_REG(0x0400); + +static const uint32_t DMA_REG_GRP_SIZE = 16; +static const uint32_t DMA_CTRL_STATUS_REG = 0x0; +static const uint32_t DMA_FRAME_SIZE_REG = 0x4; +static const uint32_t DMA_SAMPLE_COUNT_REG = 0x8; +static const uint32_t DMA_PKT_COUNT_REG = 0xC; + +#define PCIE_TX_DMA_REG(REG, CHAN) \ + (PCIE_TX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) +#define PCIE_RX_DMA_REG(REG, CHAN) \ + (PCIE_RX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) + +static const uint32_t DMA_CTRL_DISABLED = 0x00000000; +static const uint32_t DMA_CTRL_ENABLED = 0x00000002; +static const uint32_t DMA_CTRL_CLEAR_STB = 0x00000001; +static const uint32_t DMA_CTRL_SW_BUF_U64 = (3 << 4); +static const uint32_t DMA_CTRL_SW_BUF_U32 = (2 << 4); +static const uint32_t DMA_CTRL_SW_BUF_U16 = (1 << 4); +static const uint32_t DMA_CTRL_SW_BUF_U8 = (0 << 4); +static const uint32_t DMA_STATUS_ERROR = 0x00000001; +static const uint32_t DMA_STATUS_BUSY = 0x00000002; + +static const uint32_t PCIE_ROUTER_REG_BASE = PCIE_FPGA_REG(0x0500); +#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + (X)) + +static const uint32_t PCIE_ZPU_DATA_BASE = 0x30000; +static const uint32_t PCIE_ZPU_READ_BASE = 0x20000; // Trig and Status share the same base +static const uint32_t PCIE_ZPU_STATUS_BASE = 0x20000; + +#define PCIE_ZPU_DATA_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + (X)) +#define PCIE_ZPU_READ_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + (X)) +#define PCIE_ZPU_STATUS_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + (X)) static const uint32_t PCIE_ZPU_READ_START = 0x0; static const uint32_t PCIE_ZPU_READ_CLOBBER = 0x80000000; @@ -166,63 +168,72 @@ static const uint32_t PCIE_ZPU_STATUS_SUSPENDED = 0x80000000; // Register Maps //------------------------------------------------------------------- namespace uhd { namespace usrp { namespace x300 { - class fw_regmap_t : public uhd::soft_regmap_t { +class fw_regmap_t : public uhd::soft_regmap_t +{ +public: + typedef boost::shared_ptr<fw_regmap_t> sptr; + + class clk_ctrl_reg_t : public uhd::soft_reg32_wo_t + { public: - typedef boost::shared_ptr<fw_regmap_t> sptr; - - class clk_ctrl_reg_t : public uhd::soft_reg32_wo_t { - public: - UHD_DEFINE_SOFT_REG_FIELD(CLK_SOURCE, /*width*/ 2, /*shift*/ 0); //[1:0] - UHD_DEFINE_SOFT_REG_FIELD(PPS_SELECT, /*width*/ 2, /*shift*/ 2); //[3:2] - UHD_DEFINE_SOFT_REG_FIELD(PPS_OUT_EN, /*width*/ 1, /*shift*/ 4); //[4] - UHD_DEFINE_SOFT_REG_FIELD(TCXO_EN, /*width*/ 1, /*shift*/ 5); //[5] - UHD_DEFINE_SOFT_REG_FIELD(GPSDO_PWR_EN, /*width*/ 1, /*shift*/ 6); //[6] - UHD_DEFINE_SOFT_REG_FIELD(TIME_SYNC, /*width*/ 1, /*shift*/ 7); //[7] - - static const uint32_t SRC_EXTERNAL = 0x0; - static const uint32_t SRC_INTERNAL = 0x2; - static const uint32_t SRC_GPSDO = 0x3; - - clk_ctrl_reg_t(): uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL)) { - //Initial values - set(CLK_SOURCE, SRC_INTERNAL); - set(PPS_SELECT, SRC_INTERNAL); - set(PPS_OUT_EN, 0); - set(TCXO_EN, 1); - set(GPSDO_PWR_EN, 1); //GPSDO power always ON - set(TIME_SYNC, 0); - } - } clock_ctrl_reg; - - class clk_status_reg_t : public uhd::soft_reg32_ro_t { - public: - UHD_DEFINE_SOFT_REG_FIELD(LMK_STATUS, /*width*/ 2, /*shift*/ 0); //[1:0] - UHD_DEFINE_SOFT_REG_FIELD(LMK_LOCK, /*width*/ 1, /*shift*/ 2); //[2] - UHD_DEFINE_SOFT_REG_FIELD(LMK_HOLDOVER, /*width*/ 1, /*shift*/ 3); //[3] - UHD_DEFINE_SOFT_REG_FIELD(PPS_DETECT, /*width*/ 1, /*shift*/ 4); //[4] - UHD_DEFINE_SOFT_REG_FIELD(RADIO_CLK_LOCK, /*width*/ 1, /*shift*/ 5); //[5] - UHD_DEFINE_SOFT_REG_FIELD(IDELAYCTRL_LOCK, /*width*/ 1, /*shift*/ 6); //[6] - - clk_status_reg_t(): uhd::soft_reg32_ro_t(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) {} - } clock_status_reg; - - class ref_freq_reg_t : public uhd::soft_reg32_wo_t { - public: - UHD_DEFINE_SOFT_REG_FIELD(REF_FREQ, /*width*/ 32, /*shift*/ 0); - - ref_freq_reg_t(): uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_REF_FREQ)) { - //Initial values - set(REF_FREQ, 10000000); - } - } ref_freq_reg; - - fw_regmap_t() : soft_regmap_t("fw_regmap") { - add_to_map(clock_ctrl_reg, "clock_ctrl_reg", PUBLIC); - add_to_map(clock_status_reg, "clock_status_reg", PUBLIC); - add_to_map(ref_freq_reg, "ref_freq_reg", PUBLIC); + UHD_DEFINE_SOFT_REG_FIELD(CLK_SOURCE, /*width*/ 2, /*shift*/ 0); //[1:0] + UHD_DEFINE_SOFT_REG_FIELD(PPS_SELECT, /*width*/ 2, /*shift*/ 2); //[3:2] + UHD_DEFINE_SOFT_REG_FIELD(PPS_OUT_EN, /*width*/ 1, /*shift*/ 4); //[4] + UHD_DEFINE_SOFT_REG_FIELD(TCXO_EN, /*width*/ 1, /*shift*/ 5); //[5] + UHD_DEFINE_SOFT_REG_FIELD(GPSDO_PWR_EN, /*width*/ 1, /*shift*/ 6); //[6] + UHD_DEFINE_SOFT_REG_FIELD(TIME_SYNC, /*width*/ 1, /*shift*/ 7); //[7] + + static const uint32_t SRC_EXTERNAL = 0x0; + static const uint32_t SRC_INTERNAL = 0x2; + static const uint32_t SRC_GPSDO = 0x3; + + clk_ctrl_reg_t() : uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL)) + { + // Initial values + set(CLK_SOURCE, SRC_INTERNAL); + set(PPS_SELECT, SRC_INTERNAL); + set(PPS_OUT_EN, 0); + set(TCXO_EN, 1); + set(GPSDO_PWR_EN, 1); // GPSDO power always ON + set(TIME_SYNC, 0); } - }; + } clock_ctrl_reg; + + class clk_status_reg_t : public uhd::soft_reg32_ro_t + { + public: + UHD_DEFINE_SOFT_REG_FIELD(LMK_STATUS, /*width*/ 2, /*shift*/ 0); //[1:0] + UHD_DEFINE_SOFT_REG_FIELD(LMK_LOCK, /*width*/ 1, /*shift*/ 2); //[2] + UHD_DEFINE_SOFT_REG_FIELD(LMK_HOLDOVER, /*width*/ 1, /*shift*/ 3); //[3] + UHD_DEFINE_SOFT_REG_FIELD(PPS_DETECT, /*width*/ 1, /*shift*/ 4); //[4] + UHD_DEFINE_SOFT_REG_FIELD(RADIO_CLK_LOCK, /*width*/ 1, /*shift*/ 5); //[5] + UHD_DEFINE_SOFT_REG_FIELD(IDELAYCTRL_LOCK, /*width*/ 1, /*shift*/ 6); //[6] + + clk_status_reg_t() : uhd::soft_reg32_ro_t(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) + { + } + } clock_status_reg; + + class ref_freq_reg_t : public uhd::soft_reg32_wo_t + { + public: + UHD_DEFINE_SOFT_REG_FIELD(REF_FREQ, /*width*/ 32, /*shift*/ 0); + + ref_freq_reg_t() : uhd::soft_reg32_wo_t(SR_ADDR(SET0_BASE, ZPU_SR_REF_FREQ)) + { + // Initial values + set(REF_FREQ, 10000000); + } + } ref_freq_reg; + + fw_regmap_t() : soft_regmap_t("fw_regmap") + { + add_to_map(clock_ctrl_reg, "clock_ctrl_reg", PUBLIC); + add_to_map(clock_status_reg, "clock_status_reg", PUBLIC); + add_to_map(ref_freq_reg, "ref_freq_reg", PUBLIC); + } +}; -}}} +}}} // namespace uhd::usrp::x300 #endif /* INCLUDED_X300_REGS_HPP */ |