aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp')
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp677
1 files changed, 0 insertions, 677 deletions
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp
deleted file mode 100644
index d6dbbc594..000000000
--- a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp
+++ /dev/null
@@ -1,677 +0,0 @@
-//
-// Copyright 2018 Ettus Research, a National Instruments Company
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-#include "rhodium_radio_ctrl_impl.hpp"
-#include "rhodium_constants.hpp"
-#include <uhdlib/utils/narrow.hpp>
-#include <uhdlib/usrp/common/apply_corrections.hpp>
-#include <uhd/utils/log.hpp>
-#include <uhd/rfnoc/node_ctrl_base.hpp>
-#include <uhd/transport/chdr.hpp>
-#include <uhd/utils/algorithm.hpp>
-#include <uhd/utils/math.hpp>
-#include <uhd/types/direction.hpp>
-#include <uhd/types/eeprom.hpp>
-#include <uhd/exception.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/format.hpp>
-#include <sstream>
-#include <cmath>
-#include <cstdlib>
-
-using namespace uhd;
-using namespace uhd::usrp;
-using namespace uhd::rfnoc;
-using namespace uhd::math::fp_compare;
-
-namespace {
- constexpr char RX_FE_CONNECTION_LOWBAND[] = "QI";
- constexpr char RX_FE_CONNECTION_HIGHBAND[] = "IQ";
- constexpr char TX_FE_CONNECTION_LOWBAND[] = "QI";
- constexpr char TX_FE_CONNECTION_HIGHBAND[] = "IQ";
-
- constexpr double DEFAULT_IDENTIFY_DURATION = 5.0; // seconds
-
- constexpr uint64_t SET_RATE_RPC_TIMEOUT_MS = 10000;
-
- const fs_path TX_FE_PATH = fs_path("tx_frontends") / 0 / "tune_args";
- const fs_path RX_FE_PATH = fs_path("rx_frontends") / 0 / "tune_args";
-
- device_addr_t _get_tune_args(uhd::property_tree::sptr tree, std::string _radio_slot, uhd::direction_t dir)
- {
- const auto subtree = tree->subtree(fs_path("dboards") / _radio_slot);
- const auto tune_arg_path = (dir == RX_DIRECTION) ? RX_FE_PATH : TX_FE_PATH;
- return subtree->access<device_addr_t>(tune_arg_path).get();
- }
-}
-
-
-/******************************************************************************
- * Structors
- *****************************************************************************/
-UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(rhodium_radio_ctrl)
-{
- UHD_LOG_TRACE(unique_id(), "Entering rhodium_radio_ctrl_impl ctor...");
- const char radio_slot_name[] = {'A', 'B'};
- _radio_slot = radio_slot_name[get_block_id().get_block_count()];
- _rpc_prefix =
- (_radio_slot == "A") ? "db_0_" : "db_1_";
- UHD_LOG_TRACE(unique_id(), "Radio slot: " << _radio_slot);
-}
-
-rhodium_radio_ctrl_impl::~rhodium_radio_ctrl_impl()
-{
- UHD_LOG_TRACE(unique_id(), "rhodium_radio_ctrl_impl::dtor() ");
-}
-
-
-/******************************************************************************
- * API Calls
- *****************************************************************************/
-double rhodium_radio_ctrl_impl::set_rate(double requested_rate)
-{
- meta_range_t rates;
- for (const double rate : RHODIUM_RADIO_RATES) {
- rates.push_back(range_t(rate));
- }
-
- const double rate = rates.clip(requested_rate);
- if (!math::frequencies_are_equal(requested_rate, rate)) {
- UHD_LOG_WARNING(unique_id(),
- "Coercing requested sample rate from " << (requested_rate / 1e6) << " MHz to " <<
- (rate / 1e6) << " MHz, the closest possible rate.");
- }
-
- const double current_rate = get_rate();
- if (math::frequencies_are_equal(current_rate, rate)) {
- UHD_LOG_DEBUG(
- unique_id(), "Rate is already at " << (rate / 1e6) << " MHz. Skipping set_rate()");
- return current_rate;
- }
-
- // The master clock rate is always set by requesting db0's clock rate.
- UHD_LOG_TRACE(unique_id(), "Updating master clock rate to " << rate);
- auto new_rate = _rpcc->request_with_token<double>(
- SET_RATE_RPC_TIMEOUT_MS, "db_0_set_master_clock_rate", rate);
- // The lowband LO frequency will change with the master clock rate, so
- // update the tuning of the device.
- set_tx_frequency(get_tx_frequency(0), 0);
- set_rx_frequency(get_rx_frequency(0), 0);
-
- radio_ctrl_impl::set_rate(new_rate);
- return new_rate;
-}
-
-void rhodium_radio_ctrl_impl::set_tx_antenna(
- const std::string &ant,
- const size_t chan
-) {
- UHD_LOG_TRACE(unique_id(), "set_tx_antenna(ant=" << ant << ", chan=" << chan << ")");
- UHD_ASSERT_THROW(chan == 0);
-
- if (!uhd::has(RHODIUM_TX_ANTENNAS, ant)) {
- throw uhd::value_error(str(
- boost::format("[%s] Requesting invalid TX antenna value: %s")
- % unique_id()
- % ant
- ));
- }
-
- _update_tx_output_switches(ant);
- // _update_atr will set the cached antenna value, so no need to do
- // it here. See comments in _update_antenna for more info.
- _update_atr(ant, TX_DIRECTION);
-}
-
-void rhodium_radio_ctrl_impl::set_rx_antenna(
- const std::string &ant,
- const size_t chan
-) {
- UHD_LOG_TRACE(unique_id(), "Setting RX antenna to " << ant);
- UHD_ASSERT_THROW(chan == 0);
-
- if (!uhd::has(RHODIUM_RX_ANTENNAS, ant)) {
- throw uhd::value_error(str(
- boost::format("[%s] Requesting invalid RX antenna value: %s")
- % unique_id()
- % ant
- ));
- }
-
- _update_rx_input_switches(ant);
- // _update_atr will set the cached antenna value, so no need to do
- // it here. See comments in _update_antenna for more info.
- _update_atr(ant, RX_DIRECTION);
-}
-
-void rhodium_radio_ctrl_impl::_set_tx_fe_connection(const std::string &conn)
-{
- UHD_LOG_TRACE(unique_id(), "set_tx_fe_connection(conn=" << conn << ")");
-
- if (conn != _tx_fe_connection)
- {
- _tx_fe_core->set_mux(conn);
- _tx_fe_connection = conn;
- }
-}
-
-void rhodium_radio_ctrl_impl::_set_rx_fe_connection(const std::string &conn)
-{
- UHD_LOG_TRACE(unique_id(), "set_rx_fe_connection(conn=" << conn << ")");
-
- if (conn != _rx_fe_connection)
- {
- _rx_fe_core->set_fe_connection(conn);
- _rx_fe_connection = conn;
- }
-}
-
-std::string rhodium_radio_ctrl_impl::_get_tx_fe_connection() const
-{
- UHD_LOG_TRACE(unique_id(), "get_tx_fe_connection()");
-
- return _tx_fe_connection;
-}
-
-std::string rhodium_radio_ctrl_impl::_get_rx_fe_connection() const
-{
- UHD_LOG_TRACE(unique_id(), "get_rx_fe_connection()");
-
- return _rx_fe_connection;
-}
-
-double rhodium_radio_ctrl_impl::set_tx_frequency(
- const double freq,
- const size_t chan
-) {
- UHD_LOG_TRACE(unique_id(), "set_tx_frequency(f=" << freq << ", chan=" << chan << ")");
- UHD_ASSERT_THROW(chan == 0);
-
- const auto old_freq = get_tx_frequency(0);
- double coerced_target_freq = uhd::clip(freq, RHODIUM_MIN_FREQ, RHODIUM_MAX_FREQ);
-
- if (freq != coerced_target_freq) {
- UHD_LOG_DEBUG(unique_id(), "Requested frequency is outside supported range. Coercing to " << coerced_target_freq);
- }
-
- const bool is_highband = !_is_tx_lowband(coerced_target_freq);
-
- const double target_lo_freq = is_highband ?
- coerced_target_freq : _get_lowband_lo_freq() - coerced_target_freq;
- const double actual_lo_freq =
- set_tx_lo_freq(target_lo_freq, RHODIUM_LO1, chan);
- const double coerced_freq = is_highband ?
- actual_lo_freq : _get_lowband_lo_freq() - actual_lo_freq;
- const auto conn = is_highband ?
- TX_FE_CONNECTION_HIGHBAND : TX_FE_CONNECTION_LOWBAND;
-
- // update the cached frequency value now so calls to set gain and update
- // switches will read the new frequency
- radio_ctrl_impl::set_tx_frequency(coerced_freq, chan);
-
- _set_tx_fe_connection(conn);
- set_tx_gain(get_tx_gain(chan), 0);
-
- if (_get_highband_spur_reduction_enabled(TX_DIRECTION)) {
- if (_get_timed_command_enabled() and _is_tx_lowband(old_freq) != not is_highband) {
- UHD_LOG_WARNING(unique_id(),
- "Timed tuning commands that transition between lowband and highband, 450 "
- "MHz, do not function correctly when highband_spur_reduction is enabled! "
- "Disable highband_spur_reduction or avoid using timed tuning commands.");
- }
- UHD_LOG_TRACE(
- unique_id(), "TX Lowband LO is " << (is_highband ? "disabled" : "enabled"));
- _rpcc->notify_with_token(_rpc_prefix + "enable_tx_lowband_lo", (!is_highband));
- }
- _update_tx_freq_switches(coerced_freq);
- const bool enable_corrections = is_highband
- and (get_tx_lo_source(RHODIUM_LO1, 0) == "internal");
- _update_corrections(actual_lo_freq, TX_DIRECTION, enable_corrections);
- // if TX lowband/highband changed and antenna is TX/RX,
- // the ATR and SW1 need to be updated
- _update_tx_output_switches(get_tx_antenna(0));
- _update_atr(get_tx_antenna(0), TX_DIRECTION);
-
- return coerced_freq;
-}
-
-double rhodium_radio_ctrl_impl::set_rx_frequency(
- const double freq,
- const size_t chan
-) {
- UHD_LOG_TRACE(unique_id(), "set_rx_frequency(f=" << freq << ", chan=" << chan << ")");
- UHD_ASSERT_THROW(chan == 0);
-
- const auto old_freq = get_rx_frequency(0);
- double coerced_target_freq = uhd::clip(freq, RHODIUM_MIN_FREQ, RHODIUM_MAX_FREQ);
-
- if (freq != coerced_target_freq) {
- UHD_LOG_DEBUG(unique_id(), "Requested frequency is outside supported range. Coercing to " << coerced_target_freq);
- }
-
- const bool is_highband = !_is_rx_lowband(coerced_target_freq);
-
- const double target_lo_freq = is_highband ?
- coerced_target_freq : _get_lowband_lo_freq() - coerced_target_freq;
- const double actual_lo_freq =
- set_rx_lo_freq(target_lo_freq, RHODIUM_LO1, chan);
- const double coerced_freq = is_highband ?
- actual_lo_freq : _get_lowband_lo_freq() - actual_lo_freq;
- const auto conn = is_highband ?
- RX_FE_CONNECTION_HIGHBAND : RX_FE_CONNECTION_LOWBAND;
-
- // update the cached frequency value now so calls to set gain and update
- // switches will read the new frequency
- radio_ctrl_impl::set_rx_frequency(coerced_freq, chan);
-
- _set_rx_fe_connection(conn);
- set_rx_gain(get_rx_gain(chan), 0);
-
- if (_get_highband_spur_reduction_enabled(RX_DIRECTION)) {
- if (_get_timed_command_enabled() and _is_rx_lowband(old_freq) != not is_highband) {
- UHD_LOG_WARNING(unique_id(),
- "Timed tuning commands that transition between lowband and highband, 450 "
- "MHz, do not function correctly when highband_spur_reduction is enabled! "
- "Disable highband_spur_reduction or avoid using timed tuning commands.");
- }
- UHD_LOG_TRACE(
- unique_id(), "RX Lowband LO is " << (is_highband ? "disabled" : "enabled"));
- _rpcc->notify_with_token(_rpc_prefix + "enable_rx_lowband_lo", (!is_highband));
- }
- _update_rx_freq_switches(coerced_freq);
- const bool enable_corrections = is_highband
- and (get_rx_lo_source(RHODIUM_LO1, 0) == "internal");
- _update_corrections(actual_lo_freq, RX_DIRECTION, enable_corrections);
-
- return coerced_freq;
-}
-
-double rhodium_radio_ctrl_impl::set_rx_bandwidth(
- const double bandwidth,
- const size_t chan
-) {
- UHD_LOG_TRACE(unique_id(), "set_rx_bandwidth(bandwidth=" << bandwidth << ", chan=" << chan << ")");
- UHD_ASSERT_THROW(chan == 0);
-
- return get_rx_bandwidth(chan);
-}
-
-double rhodium_radio_ctrl_impl::set_tx_bandwidth(
- const double bandwidth,
- const size_t chan
-) {
- UHD_LOG_TRACE(unique_id(), "set_tx_bandwidth(bandwidth=" << bandwidth << ", chan=" << chan << ")");
- UHD_ASSERT_THROW(chan == 0);
-
- return get_tx_bandwidth(chan);
-}
-
-double rhodium_radio_ctrl_impl::set_tx_gain(
- const double gain,
- const size_t chan
-) {
- UHD_LOG_TRACE(unique_id(), "set_tx_gain(gain=" << gain << ", chan=" << chan << ")");
- UHD_ASSERT_THROW(chan == 0);
-
- auto freq = this->get_tx_frequency(chan);
- auto index = _get_gain_range(TX_DIRECTION).clip(gain);
-
- auto old_band = _is_tx_lowband(_tx_frequency_at_last_gain_write) ?
- rhodium_cpld_ctrl::gain_band_t::LOW :
- rhodium_cpld_ctrl::gain_band_t::HIGH;
- auto new_band = _is_tx_lowband(freq) ?
- rhodium_cpld_ctrl::gain_band_t::LOW :
- rhodium_cpld_ctrl::gain_band_t::HIGH;
-
- // The CPLD requires a rewrite of the gain control command on a change of lowband or highband
- if (get_tx_gain(chan) != index or old_band != new_band) {
- UHD_LOG_TRACE(unique_id(), "Writing new TX gain index: " << index);
- _cpld->set_gain_index(index, new_band, TX_DIRECTION);
- _tx_frequency_at_last_gain_write = freq;
- radio_ctrl_impl::set_tx_gain(index, chan);
- } else {
- UHD_LOG_TRACE(unique_id(), "No change in index or band, skipped writing TX gain index: " << index);
- }
-
- return index;
-}
-
-double rhodium_radio_ctrl_impl::set_rx_gain(
- const double gain,
- const size_t chan
-) {
- UHD_LOG_TRACE(unique_id(), "set_rx_gain(gain=" << gain << ", chan=" << chan << ")");
- UHD_ASSERT_THROW(chan == 0);
-
- auto freq = this->get_rx_frequency(chan);
- auto index = _get_gain_range(RX_DIRECTION).clip(gain);
-
- auto old_band = _is_rx_lowband(_rx_frequency_at_last_gain_write) ?
- rhodium_cpld_ctrl::gain_band_t::LOW :
- rhodium_cpld_ctrl::gain_band_t::HIGH;
- auto new_band = _is_rx_lowband(freq) ?
- rhodium_cpld_ctrl::gain_band_t::LOW :
- rhodium_cpld_ctrl::gain_band_t::HIGH;
-
- // The CPLD requires a rewrite of the gain control command on a change of lowband or highband
- if (get_rx_gain(chan) != index or old_band != new_band) {
- UHD_LOG_TRACE(unique_id(), "Writing new RX gain index: " << index);
- _cpld->set_gain_index(index, new_band, RX_DIRECTION);
- _rx_frequency_at_last_gain_write = freq;
- radio_ctrl_impl::set_rx_gain(index, chan);
- } else {
- UHD_LOG_TRACE(unique_id(), "No change in index or band, skipped writing RX gain index: " << index);
- }
-
- return index;
-}
-
-void rhodium_radio_ctrl_impl::_identify_with_leds(
- double identify_duration
-) {
- auto duration_ms = static_cast<uint64_t>(identify_duration * 1000);
- auto end_time =
- std::chrono::steady_clock::now() + std::chrono::milliseconds(duration_ms);
- bool led_state = true;
- {
- std::lock_guard<std::mutex> lock(_ant_mutex);
- while (std::chrono::steady_clock::now() < end_time) {
- auto atr = led_state ? (LED_RX | LED_RX2 | LED_TX) : 0;
- _gpio->set_atr_reg(gpio_atr::ATR_REG_IDLE, atr, RHODIUM_GPIO_MASK);
- led_state = !led_state;
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
- }
- }
- _update_atr(get_tx_antenna(0), TX_DIRECTION);
- _update_atr(get_rx_antenna(0), RX_DIRECTION);
-}
-
-void rhodium_radio_ctrl_impl::_update_atr(
- const std::string& ant,
- const direction_t dir
-) {
- // This function updates sw10 based on the value of both antennas, so we
- // use a mutex to prevent other calls in this class instance from running
- // at the same time.
- std::lock_guard<std::mutex> lock(_ant_mutex);
-
- UHD_LOG_TRACE(unique_id(),
- "Updating ATRs for " << ((dir == RX_DIRECTION) ? "RX" : "TX") << " to " << ant);
-
- const auto rx_ant = (dir == RX_DIRECTION) ? ant : get_rx_antenna(0);
- const auto tx_ant = (dir == TX_DIRECTION) ? ant : get_tx_antenna(0);
- const auto sw10_tx = _is_tx_lowband(get_tx_frequency(0)) ?
- SW10_FROMTXLOWBAND : SW10_FROMTXHIGHBAND;
-
-
- const uint32_t atr_idle = SW10_ISOLATION;
-
- const uint32_t atr_rx = [rx_ant]{
- if (rx_ant == "TX/RX") {
- return SW10_TORX | LED_RX;
- } else if (rx_ant == "RX2") {
- return SW10_ISOLATION | LED_RX2;
- } else {
- return SW10_ISOLATION;
- }
- }();
-
- const uint32_t atr_tx = (tx_ant == "TX/RX") ?
- (sw10_tx | LED_TX) : SW10_ISOLATION;
-
- const uint32_t atr_dx = [tx_ant, rx_ant, sw10_tx] {
- uint32_t sw10_return;
- if (tx_ant == "TX/RX") {
- // if both channels are set to TX/RX, TX will override
- sw10_return = sw10_tx | LED_TX;
- } else if (rx_ant == "TX/RX") {
- sw10_return = SW10_TORX | LED_RX;
- } else {
- sw10_return = SW10_ISOLATION;
- }
- sw10_return |= (rx_ant == "RX2") ? LED_RX2 : 0;
- return sw10_return;
- }();
-
- _gpio->set_atr_reg(gpio_atr::ATR_REG_IDLE, atr_idle, RHODIUM_GPIO_MASK);
- _gpio->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY, atr_rx, RHODIUM_GPIO_MASK);
- _gpio->set_atr_reg(gpio_atr::ATR_REG_TX_ONLY, atr_tx, RHODIUM_GPIO_MASK);
- _gpio->set_atr_reg(gpio_atr::ATR_REG_FULL_DUPLEX, atr_dx, RHODIUM_GPIO_MASK);
-
- UHD_LOG_TRACE(unique_id(),
- str(boost::format("Wrote ATR registers i:0x%02X, r:0x%02X, t:0x%02X, d:0x%02X")
- % atr_idle % atr_rx % atr_tx % atr_dx));
-
- if (dir == RX_DIRECTION) {
- radio_ctrl_impl::set_rx_antenna(ant, 0);
- } else {
- radio_ctrl_impl::set_tx_antenna(ant, 0);
- }
-}
-
-void rhodium_radio_ctrl_impl::_update_corrections(
- const double freq,
- const direction_t dir,
- const bool enable)
-{
- const std::string fe_path_part = dir == RX_DIRECTION ? "rx_fe_corrections"
- : "tx_fe_corrections";
- const fs_path fe_corr_path = _root_path / fe_path_part / 0;
- const fs_path dboard_path = fs_path("dboards") / _radio_slot;
-
- if (enable)
- {
- UHD_LOG_DEBUG(unique_id(),
- "Loading any available frontend corrections for "
- << ((dir == RX_DIRECTION) ? "RX" : "TX") << " at " << freq);
- if (dir == RX_DIRECTION) {
- apply_rx_fe_corrections(_tree, dboard_path, fe_corr_path, freq);
- } else {
- apply_tx_fe_corrections(_tree, dboard_path, fe_corr_path, freq);
- }
- } else {
- UHD_LOG_DEBUG(unique_id(),
- "Disabling frontend corrections for "
- << ((dir == RX_DIRECTION) ? "RX" : "TX"));
- if (dir == RX_DIRECTION) {
- _rx_fe_core->set_iq_balance(rx_frontend_core_3000::DEFAULT_IQ_BALANCE_VALUE);
- } else {
- _tx_fe_core->set_dc_offset(tx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE);
- _tx_fe_core->set_iq_balance(tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE);
- }
- }
-
-}
-
-uhd::gain_range_t rhodium_radio_ctrl_impl::_get_gain_range(direction_t dir)
-{
- if (dir == RX_DIRECTION) {
- return gain_range_t(RX_MIN_GAIN, RX_MAX_GAIN, RX_GAIN_STEP);
- } else if (dir == TX_DIRECTION) {
- return gain_range_t(TX_MIN_GAIN, TX_MAX_GAIN, TX_GAIN_STEP);
- } else {
- UHD_THROW_INVALID_CODE_PATH();
- }
-}
-
-bool rhodium_radio_ctrl_impl::_get_spur_dodging_enabled(uhd::direction_t dir) const
-{
- UHD_ASSERT_THROW(_tree->exists(get_arg_path(SPUR_DODGING_ARG_NAME) / "value"));
- auto block_value = _tree->access<std::string>(get_arg_path(SPUR_DODGING_ARG_NAME) / "value").get();
- auto dict = _get_tune_args(_tree, _radio_slot, dir);
-
- // get the current tune_arg for spur_dodging
- // if the tune_arg doesn't exist, use the radio block argument instead
- std::string spur_dodging_arg = dict.cast<std::string>(
- SPUR_DODGING_ARG_NAME,
- block_value);
-
- if (spur_dodging_arg == "enabled")
- {
- UHD_LOG_TRACE(unique_id(), "_get_spur_dodging_enabled returning enabled");
- return true;
- }
- else if (spur_dodging_arg == "disabled") {
- UHD_LOG_TRACE(unique_id(), "_get_spur_dodging_enabled returning disabled");
- return false;
- }
- else {
- throw uhd::value_error(
- str(boost::format("Invalid spur_dodging argument: %s Valid options are [enabled, disabled]")
- % spur_dodging_arg));
- }
-}
-
-double rhodium_radio_ctrl_impl::_get_spur_dodging_threshold(uhd::direction_t dir) const
-{
- UHD_ASSERT_THROW(_tree->exists(get_arg_path(SPUR_DODGING_THRESHOLD_ARG_NAME) / "value"));
- auto block_value = _tree->access<double>(get_arg_path(SPUR_DODGING_THRESHOLD_ARG_NAME) / "value").get();
- auto dict = _get_tune_args(_tree, _radio_slot, dir);
-
- // get the current tune_arg for spur_dodging_threshold
- // if the tune_arg doesn't exist, use the radio block argument instead
- auto threshold = dict.cast<double>(SPUR_DODGING_THRESHOLD_ARG_NAME, block_value);
-
- UHD_LOG_TRACE(unique_id(), "_get_spur_dodging_threshold returning " << threshold);
-
- return threshold;
-}
-
-bool rhodium_radio_ctrl_impl::_get_highband_spur_reduction_enabled(uhd::direction_t dir) const
-{
- UHD_ASSERT_THROW(
- _tree->exists(get_arg_path(HIGHBAND_SPUR_REDUCTION_ARG_NAME) / "value"));
- auto block_value = _tree
- ->access<std::string>(
- get_arg_path(HIGHBAND_SPUR_REDUCTION_ARG_NAME) / "value")
- .get();
- auto dict = _get_tune_args(_tree, _radio_slot, dir);
-
- // get the current tune_arg for highband_spur_reduction
- // if the tune_arg doesn't exist, use the radio block argument instead
- std::string highband_spur_reduction_arg =
- dict.cast<std::string>(HIGHBAND_SPUR_REDUCTION_ARG_NAME, block_value);
-
- if (highband_spur_reduction_arg == "enabled") {
- UHD_LOG_TRACE(unique_id(), __func__ << " returning enabled");
- return true;
- } else if (highband_spur_reduction_arg == "disabled") {
- UHD_LOG_TRACE(unique_id(), __func__ << " returning disabled");
- return false;
- } else {
- throw uhd::value_error(
- str(boost::format("Invalid highband_spur_reduction argument: %s Valid "
- "options are [enabled, disabled]")
- % highband_spur_reduction_arg));
- }
-}
-
-bool rhodium_radio_ctrl_impl::_get_timed_command_enabled() const
-{
- auto& prop = _tree->access<time_spec_t>(fs_path("time") / "cmd");
- // if timed commands are never set, the property will be empty
- // if timed commands were set but cleared, time_spec will be set to 0.0
- return !prop.empty() and prop.get() != time_spec_t(0.0);
-}
-
-size_t rhodium_radio_ctrl_impl::get_chan_from_dboard_fe(
- const std::string &fe, const direction_t /* dir */
-) {
- UHD_ASSERT_THROW(boost::lexical_cast<size_t>(fe) == 0);
- return 0;
-}
-
-std::string rhodium_radio_ctrl_impl::get_dboard_fe_from_chan(
- const size_t chan,
- const direction_t /* dir */
-) {
- UHD_ASSERT_THROW(chan == 0);
- return "0";
-}
-
-void rhodium_radio_ctrl_impl::set_rpc_client(
- uhd::rpc_client::sptr rpcc,
- const uhd::device_addr_t &block_args
-) {
- _rpcc = rpcc;
- _block_args = block_args;
-
- // Get and verify the MCR before _init_peripherals, which will use this value
- // Note: MCR gets set during the init() call (prior to this), which takes
- // in arguments from the device args. So if block_args contains a
- // master_clock_rate key, then it should better be whatever the device is
- // configured to do.
- _master_clock_rate = _rpcc->request_with_token<double>(_rpc_prefix + "get_master_clock_rate");
- if (block_args.cast<double>("master_clock_rate", _master_clock_rate)
- != _master_clock_rate) {
- throw uhd::runtime_error(str(
- boost::format("Master clock rate mismatch. Device returns %f MHz, "
- "but should have been %f MHz.")
- % (_master_clock_rate / 1e6)
- % (block_args.cast<double>(
- "master_clock_rate", _master_clock_rate) / 1e6)
- ));
- }
- UHD_LOG_DEBUG(unique_id(),
- "Master Clock Rate is: " << (_master_clock_rate / 1e6) << " MHz.");
- radio_ctrl_impl::set_rate(_master_clock_rate);
-
- UHD_LOG_TRACE(unique_id(), "Checking for existence of Rhodium DB in slot " << _radio_slot);
- const auto all_dboard_info = _rpcc->request<std::vector<std::map<std::string, std::string>>>("get_dboard_info");
-
- // There is a bug that if only one DB is plugged into slot B the vector
- // will only have 1 element but not be correlated to slot B at all.
- // For now, we assume a 1 element array means the DB is in slot A.
- if (all_dboard_info.size() <= get_block_id().get_block_count())
- {
- UHD_LOG_DEBUG(unique_id(), "No DB detected in slot " << _radio_slot);
- // Name and master clock rate are needed for RFNoC init, so set the
- // name now and let this function continue to set the MCR
- _tree->subtree(fs_path("dboards") / _radio_slot / "tx_frontends" / "0")
- ->create<std::string>("name").set("Unknown");
- _tree->subtree(fs_path("dboards") / _radio_slot / "rx_frontends" / "0")
- ->create<std::string>("name").set("Unknown");
- }
- else {
- _dboard_info = all_dboard_info.at(get_block_id().get_block_count());
- UHD_LOG_DEBUG(unique_id(),
- "Rhodium DB detected in slot " << _radio_slot <<
- ". Serial: " << _dboard_info.at("serial"));
- _init_defaults();
- _init_peripherals();
- _init_prop_tree();
-
- if (block_args.has_key("identify")) {
- const std::string identify_val = block_args.get("identify");
- double identify_duration = 0.0;
- try {
- identify_duration = std::stod(identify_val);
- if (!std::isnormal(identify_duration)) {
- identify_duration = DEFAULT_IDENTIFY_DURATION;
- }
- } catch (std::invalid_argument) {
- identify_duration = DEFAULT_IDENTIFY_DURATION;
- }
-
- UHD_LOG_INFO(unique_id(),
- "Running LED identification process for " << identify_duration
- << " seconds.");
- _identify_with_leds(identify_duration);
- }
- }
-}
-
-bool rhodium_radio_ctrl_impl::get_lo_lock_status(
- const direction_t dir
-) const
-{
- return
- ((dir == RX_DIRECTION) or _tx_lo->get_lock_status()) and
- ((dir == TX_DIRECTION) or _rx_lo->get_lock_status());
-}
-
-UHD_RFNOC_BLOCK_REGISTER(rhodium_radio_ctrl, "RhodiumRadio");