diff options
Diffstat (limited to 'host/lib/usrp/x300/x300_radio_ctrl_impl.cpp')
-rw-r--r-- | host/lib/usrp/x300/x300_radio_ctrl_impl.cpp | 1092 |
1 files changed, 648 insertions, 444 deletions
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); } } } |