aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_constants.hpp11
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_cpld.cpp82
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp74
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.hpp16
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_init.cpp12
5 files changed, 103 insertions, 92 deletions
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_constants.hpp b/host/lib/usrp/dboard/rhodium/rhodium_constants.hpp
index dd703a612..d21804f50 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_constants.hpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_constants.hpp
@@ -56,7 +56,18 @@ static const std::vector<std::string> RHODIUM_TX_ANTENNAS = {
static constexpr char SPUR_DODGING_ARG_NAME[] = "spur_dodging";
static constexpr char SPUR_DODGING_THRESHOLD_ARG_NAME[] = "spur_dodging_threshold";
+static constexpr uint32_t RHODIUM_GPIO_MASK = 0x1F;
static constexpr uint32_t SW10_GPIO_MASK = 0x3;
+static constexpr uint32_t LED_GPIO_MASK = 0x1C;
+
+static constexpr uint32_t SW10_FROMTXLOWBAND = 0x0;
+static constexpr uint32_t SW10_FROMTXHIGHBAND = 0x1;
+static constexpr uint32_t SW10_ISOLATION = 0x2;
+static constexpr uint32_t SW10_TORX = 0x3;
+
+static constexpr uint32_t LED_RX = 0x04;
+static constexpr uint32_t LED_RX2 = 0x08;
+static constexpr uint32_t LED_TX = 0x10;
//! Main LO
static constexpr char RHODIUM_LO1[] = "lo1";
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_cpld.cpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_cpld.cpp
index 68efe0f83..846a4eac6 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_cpld.cpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_cpld.cpp
@@ -223,9 +223,6 @@ void rhodium_radio_ctrl_impl::_update_tx_freq_switches(
tx_sw5,
tx_hb_lb_sel
);
-
- // If TX lowband/highband changes, SW10 needs to be updated
- _update_tx_output_switches(get_tx_antenna(0));
}
void rhodium_radio_ctrl_impl::_update_rx_input_switches(
@@ -234,9 +231,6 @@ void rhodium_radio_ctrl_impl::_update_rx_input_switches(
UHD_LOG_TRACE(unique_id(),
"Update all RX input related switches. input=" << input
);
- const sw10_t sw10 = (input == "TX/RX") ?
- SW10_TORX :
- SW10_ISOLATION;
const rhodium_cpld_ctrl::cal_iso_sw_t cal_iso = (input == "CAL") ?
rhodium_cpld_ctrl::CAL_ISO_CALLOOPBACK :
rhodium_cpld_ctrl::CAL_ISO_ISOLATION;
@@ -261,42 +255,9 @@ void rhodium_radio_ctrl_impl::_update_rx_input_switches(
UHD_LOG_TRACE(unique_id(),
"Selected switch values:"
- " sw10=" << sw10 <<
" sw1=" << sw1 <<
" cal_iso=" << cal_iso
);
-
- // the TX path may be using TX/RX already, in which case only override sw10 if
- // we are attempting to use TX/RX
- if (get_tx_antenna(0) == "TX/RX")
- {
- if (input == "TX/RX")
- {
- UHD_LOG_TRACE(unique_id(),
- "Overriding TX antenna to TERM"
- );
- // TODO: setting antenna here could cause race conditions
- set_tx_antenna("TERM", 0);
-
- UHD_LOG_TRACE(unique_id(),
- "Setting switch values: sw10=" << sw10
- );
- _gpio->set_gpio_out(sw10, SW10_GPIO_MASK);
- }
- else {
- // skip setting sw10, allowing TX to continue using TX/RX
- UHD_LOG_TRACE(unique_id(),
- "sw10 setting was not applied because TX antenna is set to TX/RX"
- );
- }
- }
- else {
- // TX/RX is not in use, fire away
- UHD_LOG_TRACE(unique_id(),
- "Setting switch values: sw10=" << sw10
- );
- _gpio->set_gpio_out(sw10, SW10_GPIO_MASK);
- }
_cpld->set_rx_input_switches(sw1, cal_iso);
}
@@ -306,69 +267,32 @@ void rhodium_radio_ctrl_impl::_update_tx_output_switches(
UHD_LOG_TRACE(unique_id(),
"Update all TX output related switches. output=" << output
);
- sw10_t sw10;
rhodium_cpld_ctrl::tx_sw1_t sw1;
if (output == "TX/RX")
{
- //Both sw1 and sw10 need to select low/high band
- if (_map_freq_to_tx_band(get_tx_frequency(0)) == tx_band::TX_BAND_0)
+ //SW1 needs to select low/high band
+ if (_is_tx_lowband(get_tx_frequency(0)))
{
sw1 = rhodium_cpld_ctrl::TX_SW1_TOLOWBAND;
- sw10 = SW10_FROMTXLOWBAND;
}
else {
sw1 = rhodium_cpld_ctrl::TX_SW1_TOSWITCH2;
- sw10 = SW10_FROMTXHIGHBAND;
}
}
else if (output == "CAL") {
sw1 = rhodium_cpld_ctrl::TX_SW1_TOCALLOOPBACK;
- sw10 = SW10_ISOLATION;
}
else if (output == "TERM") {
sw1 = rhodium_cpld_ctrl::TX_SW1_ISOLATION;
- sw10 = SW10_ISOLATION;
}
else {
throw uhd::runtime_error("Invalid antenna in _update_tx_output_switches: " + output);
}
UHD_LOG_TRACE(unique_id(),
- "Selected switch values: sw1=" << sw1 << " sw10=" << sw10
+ "Selected switch values: sw1=" << sw1
);
- // If RX is on TX/RX, only set sw10 if TX is requesting TX/RX
- // and override the RX antenna value
- if (get_rx_antenna(0) == "TX/RX")
- {
- if (output == "TX/RX")
- {
- UHD_LOG_TRACE(unique_id(),
- "Overriding RX antenna to TERM"
- );
- // TODO: setting antenna here could cause race conditions
- set_rx_antenna("TERM", 0);
-
- UHD_LOG_TRACE(unique_id(),
- "Setting switch values: sw10=" << sw10
- );
- _gpio->set_gpio_out(sw10, SW10_GPIO_MASK);
- }
- else {
- // skip setting sw10, allowing RX to continue using TX/RX
- UHD_LOG_TRACE(unique_id(),
- "sw10 setting was not applied because RX antenna is set to TX/RX"
- );
- }
- }
- // If RX is on any other setting, set sw10 normally
- else {
- UHD_LOG_TRACE(unique_id(),
- "Setting switch values: sw10=" << sw10
- );
- _gpio->set_gpio_out(sw10, SW10_GPIO_MASK);
- }
-
_cpld->set_tx_output_switches(sw1);
}
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp
index 01f467476..3de3f36f1 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.cpp
@@ -93,8 +93,10 @@ void rhodium_radio_ctrl_impl::set_tx_antenna(
));
}
- radio_ctrl_impl::set_tx_antenna(ant, chan);
_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(
@@ -112,8 +114,10 @@ void rhodium_radio_ctrl_impl::set_rx_antenna(
));
}
- radio_ctrl_impl::set_rx_antenna(ant, chan);
_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)
@@ -180,6 +184,9 @@ double rhodium_radio_ctrl_impl::set_tx_frequency(
set_tx_gain(get_tx_gain(chan), 0);
radio_ctrl_impl::set_tx_frequency(coerced_freq, chan);
_update_tx_freq_switches(coerced_freq);
+ // if TX lowband/highband changed and antenna is TX/RX,
+ // the ATR needs to be updated
+ _update_atr(get_tx_antenna(0), TX_DIRECTION);
return coerced_freq;
}
@@ -296,6 +303,69 @@ double rhodium_radio_ctrl_impl::set_rx_gain(
return index;
}
+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);
+ }
+}
+
uhd::gain_range_t rhodium_radio_ctrl_impl::_get_gain_range(direction_t dir)
{
if (dir == RX_DIRECTION) {
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.hpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.hpp
index af6322655..ac2311a24 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.hpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_impl.hpp
@@ -56,13 +56,6 @@ public:
TX_BAND_7
};
- enum sw10_t {
- SW10_FROMTXLOWBAND = 0,
- SW10_FROMTXHIGHBAND = 1,
- SW10_ISOLATION = 2,
- SW10_TORX = 3
- };
-
/************************************************************************
* Structors
***********************************************************************/
@@ -217,6 +210,11 @@ private:
const direction_t dir
);
+ //! Configure ATR registers and update the cached antenna value from the
+ // new antenna value.
+ // ATR registers control SW10 and the frontend LEDs.
+ void _update_atr(const std::string& ant, const direction_t dir);
+
//! Map a frequency in Hz to an rx_band value. Will return
// rx_band::INVALID_BAND if the frequency is out of range.
static rx_band _map_freq_to_rx_band(const double freq);
@@ -285,8 +283,8 @@ private:
/**************************************************************************
* Private attributes
*************************************************************************/
- //! Locks access to setter APIs
- std::mutex _set_lock;
+ //! Locks access to the antenna cached values
+ std::mutex _ant_mutex;
//! Letter representation of the radio we're currently running
std::string _radio_slot;
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_init.cpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_init.cpp
index 600758efa..28e5eb3a6 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_init.cpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_ctrl_init.cpp
@@ -191,14 +191,22 @@ void rhodium_radio_ctrl_impl::_init_peripherals()
regs::rb_addr(regs::RB_DB_GPIO)
);
_gpio->set_atr_mode(
- usrp::gpio_atr::MODE_GPIO, // Disable ATR mode
- usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL
+ usrp::gpio_atr::MODE_ATR, // Enable ATR mode for Rhodium bits
+ RHODIUM_GPIO_MASK
+ );
+ _gpio->set_atr_mode(
+ usrp::gpio_atr::MODE_GPIO, // Disable ATR mode for unused bits
+ ~RHODIUM_GPIO_MASK
);
_gpio->set_gpio_ddr(
usrp::gpio_atr::DDR_OUTPUT, // Make all GPIOs outputs
usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL
);
+ UHD_LOG_TRACE(unique_id(), "Set initial ATR values...");
+ _update_atr(RHODIUM_DEFAULT_TX_ANTENNA, TX_DIRECTION);
+ _update_atr(RHODIUM_DEFAULT_RX_ANTENNA, RX_DIRECTION);
+
// Updating the TX frequency path may include an update to SW10, which is
// GPIO controlled, so this must follow CPLD and GPIO initialization
UHD_LOG_TRACE(unique_id(), "Writing initial switch values...");