aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/x300/x300_radio_control.cpp66
1 files changed, 53 insertions, 13 deletions
diff --git a/host/lib/usrp/x300/x300_radio_control.cpp b/host/lib/usrp/x300/x300_radio_control.cpp
index 3bbadf7d6..6a851bc8f 100644
--- a/host/lib/usrp/x300/x300_radio_control.cpp
+++ b/host/lib/usrp/x300/x300_radio_control.cpp
@@ -94,6 +94,14 @@ static constexpr uint32_t SR_LEDS = PERIPH_BASE + 176 * PERIPH_REG_OFFSET;
static constexpr uint32_t SR_FP_GPIO = PERIPH_BASE + 184 * PERIPH_REG_OFFSET;
static constexpr uint32_t SR_DB_GPIO = PERIPH_BASE + 192 * PERIPH_REG_OFFSET;
+// LED bit positions
+// Green LED on TX/RX port (left SMA)
+static constexpr int SR_LED_TXRX_RX = (1 << 0);
+// Red LED on TX/RX port (left SMA)
+static constexpr int SR_LED_TXRX_TX = (1 << 1);
+// Green LED on RX2 port (right SMA)
+static constexpr int SR_LED_RX2_RX = (1 << 2);
+
static constexpr uint32_t RB_MISC_IO = PERIPH_BASE + 16 * PERIPH_REG_OFFSET;
static constexpr uint32_t RB_SPI = PERIPH_BASE + 17 * PERIPH_REG_OFFSET;
// static constexpr uint32_t RB_LEDS = PERIPH_BASE + 18 * PERIPH_REG_OFFSET;
@@ -178,6 +186,17 @@ public:
x300_regs::SR_LEDS, x300_regs::PERIPH_REG_OFFSET));
_leds->set_atr_mode(
usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL);
+ // Set LEDs to default setting: RX2 LED on RX, TX/RX red LED on TX. The
+ // actual setting depends on the antenna choice and is handled in
+ // _update_atr_leds().
+ _leds->set_atr_reg(gpio_atr::ATR_REG_IDLE, 0);
+ _leds->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY, x300_regs::SR_LED_RX2_RX);
+ _leds->set_atr_reg(gpio_atr::ATR_REG_TX_ONLY, x300_regs::SR_LED_TXRX_TX);
+ // We choose to light both LEDs on full duplex, regardless of the
+ // antenna selection, because the single multi-color LED on the TX/RX
+ // side does not provide useful visual feedback by itself.
+ _leds->set_atr_reg(gpio_atr::ATR_REG_FULL_DUPLEX,
+ x300_regs::SR_LED_RX2_RX | x300_regs::SR_LED_TXRX_TX);
// We always want to initialize at least one frontend core for both TX and RX
// RX periphs
for (size_t i = 0; i < std::max<size_t>(get_num_output_ports(), 1); i++) {
@@ -1768,21 +1787,36 @@ private:
_db_eeproms[addr] = db_eeprom;
}
+ // A note on updating the LED ATR register: There is a single ATR register
+ // for the radio block, despite there being 2 channels. For most (1-channel)
+ // daughterboards, the rules are simple: When transmitting, the red LED turns
+ // on. When receiving, either the green LED under the RX2 or on the TX/RX
+ // port turn, depending on if the user has selected a TX/RX antenna or not.
+ // For TwinRX, we have additional rules. The board has two channels, but
+ // either of them can used with any SMA port. We therefore have to check
+ // which channels are active (0, 1, or both) and on the active channels,
+ // which set of antenna ports is used (RX1 aka TX/RX, RX2). All active RX
+ // ports shall then be added the the RX ATR register.
void _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");
- // Green LED on TX/RX port (left SMA)
- constexpr int TXRX_RX = (1 << 0);
- // Red LED on TX/RX port (left SMA)
- constexpr int TXRX_TX = (1 << 1);
- // Green LED on RX2 port (right SMA)
- constexpr int RX2_RX = (1 << 2);
- _leds->set_atr_reg(gpio_atr::ATR_REG_IDLE, 0);
- _leds->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY, is_txrx ? TXRX_RX : RX2_RX);
- _leds->set_atr_reg(gpio_atr::ATR_REG_TX_ONLY, TXRX_TX);
- _leds->set_atr_reg(gpio_atr::ATR_REG_FULL_DUPLEX, RX2_RX | TXRX_TX);
+ uint32_t rx_led_atr_state = 0;
+ if (_twinrx) {
+ for (size_t chan = 0; chan < get_num_output_ports(); chan++) {
+ const auto fe_enable_path = get_db_path("rx", chan) / "enabled";
+ if (get_tree()->access<bool>(fe_enable_path).get()) {
+ if (get_rx_antenna(chan) == "RX1") {
+ rx_led_atr_state |= x300_regs::SR_LED_TXRX_RX;
+ }
+ if (get_rx_antenna(chan) == "RX2") {
+ rx_led_atr_state |= x300_regs::SR_LED_RX2_RX;
+ }
+ }
+ }
+ } else {
+ rx_led_atr_state = rx_ant == "TX/RX" ? x300_regs::SR_LED_TXRX_RX
+ : x300_regs::SR_LED_RX2_RX;
+ }
+ _leds->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY, rx_led_atr_state);
}
void _set_rx_fe(const std::string& fe, const size_t chan)
@@ -1888,6 +1922,12 @@ private:
"Enabling RX chan " << chan << ": " << (chan_active ? "Yes" : "No"));
get_tree()->access<bool>(fe_enable_path).set(chan_active);
}
+ // Modifying the number of active channels can affect how the
+ // front-panel LEDs get configured for TwinRX boards. Worst case,
+ // this is a no-op since we call it with the same argument as it was
+ // called before. Note this must be called after the 'enable'
+ // property is set.
+ _update_atr_leds(get_rx_antenna(chan), chan);
}
return true;