diff options
author | Mark Meserve <mark.meserve@ni.com> | 2018-11-19 13:50:18 -0600 |
---|---|---|
committer | Brent Stapleton <bstapleton@g.hmc.edu> | 2018-11-29 11:13:56 -0800 |
commit | c26de63a6481970cbc4c84b110df72e29c46ee3d (patch) | |
tree | bb0ae0db8ed1384154b46ff2372cb001bfff8f9f /host/lib | |
parent | 2e85508a8719e2c1be548b70cf797365ce69a1f9 (diff) | |
download | uhd-c26de63a6481970cbc4c84b110df72e29c46ee3d.tar.gz uhd-c26de63a6481970cbc4c84b110df72e29c46ee3d.tar.bz2 uhd-c26de63a6481970cbc4c84b110df72e29c46ee3d.zip |
rh: add support for atr frontend control
Diffstat (limited to 'host/lib')
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..."); |