aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard/rhodium/rhodium_radio_control_cpld.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/dboard/rhodium/rhodium_radio_control_cpld.cpp')
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_radio_control_cpld.cpp252
1 files changed, 252 insertions, 0 deletions
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_control_cpld.cpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_control_cpld.cpp
new file mode 100644
index 000000000..f4f17e8ab
--- /dev/null
+++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_control_cpld.cpp
@@ -0,0 +1,252 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include "rhodium_constants.hpp"
+#include "rhodium_cpld_ctrl.hpp"
+#include "rhodium_radio_control.hpp"
+#include <uhd/utils/log.hpp>
+
+using namespace uhd;
+using namespace uhd::usrp;
+using namespace uhd::rfnoc;
+
+namespace {
+
+const char* rx_band_to_log(rhodium_radio_control_impl::rx_band rx_band)
+{
+ switch (rx_band) {
+ case rhodium_radio_control_impl::rx_band::RX_BAND_0:
+ return "0";
+ case rhodium_radio_control_impl::rx_band::RX_BAND_1:
+ return "1";
+ case rhodium_radio_control_impl::rx_band::RX_BAND_2:
+ return "2";
+ case rhodium_radio_control_impl::rx_band::RX_BAND_3:
+ return "3";
+ case rhodium_radio_control_impl::rx_band::RX_BAND_4:
+ return "4";
+ case rhodium_radio_control_impl::rx_band::RX_BAND_5:
+ return "5";
+ case rhodium_radio_control_impl::rx_band::RX_BAND_6:
+ return "6";
+ case rhodium_radio_control_impl::rx_band::RX_BAND_7:
+ return "7";
+ case rhodium_radio_control_impl::rx_band::RX_BAND_INVALID:
+ return "INVALID";
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
+ }
+}
+
+const char* tx_band_to_log(rhodium_radio_control_impl::tx_band tx_band)
+{
+ switch (tx_band) {
+ case rhodium_radio_control_impl::tx_band::TX_BAND_0:
+ return "0";
+ case rhodium_radio_control_impl::tx_band::TX_BAND_1:
+ return "1";
+ case rhodium_radio_control_impl::tx_band::TX_BAND_2:
+ return "2";
+ case rhodium_radio_control_impl::tx_band::TX_BAND_3:
+ return "3";
+ case rhodium_radio_control_impl::tx_band::TX_BAND_4:
+ return "4";
+ case rhodium_radio_control_impl::tx_band::TX_BAND_5:
+ return "5";
+ case rhodium_radio_control_impl::tx_band::TX_BAND_6:
+ return "6";
+ case rhodium_radio_control_impl::tx_band::TX_BAND_7:
+ return "7";
+ case rhodium_radio_control_impl::tx_band::TX_BAND_INVALID:
+ return "INVALID";
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
+ }
+}
+} // namespace
+
+void rhodium_radio_control_impl::_update_rx_freq_switches(const double freq)
+{
+ RFNOC_LOG_TRACE("Update all RX freq related switches. f=" << freq << " Hz");
+ const auto band = _map_freq_to_rx_band(freq);
+ RFNOC_LOG_TRACE("Selected band " << rx_band_to_log(band));
+
+ // select values for lowband/highband switches
+ const bool is_lowband = (band == rx_band::RX_BAND_0);
+ auto rx_sw2_sw7 = is_lowband ? rhodium_cpld_ctrl::RX_SW2_SW7_LOWBANDFILTERBANK
+ : rhodium_cpld_ctrl::RX_SW2_SW7_HIGHBANDFILTERBANK;
+ auto rx_hb_lb_sel = is_lowband ? rhodium_cpld_ctrl::RX_HB_LB_SEL_LOWBAND
+ : rhodium_cpld_ctrl::RX_HB_LB_SEL_HIGHBAND;
+
+ // select values for filter bank switches
+ rhodium_cpld_ctrl::rx_sw3_t rx_sw3;
+ rhodium_cpld_ctrl::rx_sw4_sw5_t rx_sw4_sw5;
+ rhodium_cpld_ctrl::rx_sw6_t rx_sw6;
+ switch (band) {
+ case rx_band::RX_BAND_0:
+ // Low band doesn't use the filter banks, use configuration for band 1
+ case rx_band::RX_BAND_1:
+ rx_sw3 = rhodium_cpld_ctrl::RX_SW3_TOSWITCH4;
+ rx_sw4_sw5 = rhodium_cpld_ctrl::RX_SW4_SW5_FILTER0450X0760MHZ;
+ rx_sw6 = rhodium_cpld_ctrl::RX_SW6_FROMSWITCH5;
+ break;
+ case rx_band::RX_BAND_2:
+ rx_sw3 = rhodium_cpld_ctrl::RX_SW3_TOSWITCH4;
+ rx_sw4_sw5 = rhodium_cpld_ctrl::RX_SW4_SW5_FILTER0760X1100MHZ;
+ rx_sw6 = rhodium_cpld_ctrl::RX_SW6_FROMSWITCH5;
+ break;
+ case rx_band::RX_BAND_3:
+ rx_sw3 = rhodium_cpld_ctrl::RX_SW3_TOSWITCH4;
+ rx_sw4_sw5 = rhodium_cpld_ctrl::RX_SW4_SW5_FILTER1100X1410MHZ;
+ rx_sw6 = rhodium_cpld_ctrl::RX_SW6_FROMSWITCH5;
+ break;
+ case rx_band::RX_BAND_4:
+ rx_sw3 = rhodium_cpld_ctrl::RX_SW3_TOSWITCH4;
+ rx_sw4_sw5 = rhodium_cpld_ctrl::RX_SW4_SW5_FILTER1410X2050MHZ;
+ rx_sw6 = rhodium_cpld_ctrl::RX_SW6_FROMSWITCH5;
+ break;
+ case rx_band::RX_BAND_5:
+ rx_sw3 = rhodium_cpld_ctrl::RX_SW3_TOFILTER2050X3000MHZ;
+ rx_sw4_sw5 = rhodium_cpld_ctrl::RX_SW4_SW5_FILTER0450X0760MHZ;
+ rx_sw6 = rhodium_cpld_ctrl::RX_SW6_FROMFILTER2050X3000MHZ;
+ break;
+ case rx_band::RX_BAND_6:
+ rx_sw3 = rhodium_cpld_ctrl::RX_SW3_TOFILTER3000X4500MHZ;
+ rx_sw4_sw5 = rhodium_cpld_ctrl::RX_SW4_SW5_FILTER0450X0760MHZ;
+ rx_sw6 = rhodium_cpld_ctrl::RX_SW6_FROMFILTER3000X4500MHZ;
+ break;
+ case rx_band::RX_BAND_7:
+ rx_sw3 = rhodium_cpld_ctrl::RX_SW3_TOFILTER4500X6000MHZ;
+ rx_sw4_sw5 = rhodium_cpld_ctrl::RX_SW4_SW5_FILTER0450X0760MHZ;
+ rx_sw6 = rhodium_cpld_ctrl::RX_SW6_FROMFILTER4500X6000MHZ;
+ break;
+ case rx_band::RX_BAND_INVALID:
+ throw uhd::runtime_error(
+ str(boost::format("Cannot map RX frequency to band: %f") % freq));
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
+ }
+
+ // commit settings to cpld
+ _cpld->set_rx_switches(rx_sw2_sw7, rx_sw3, rx_sw4_sw5, rx_sw6, rx_hb_lb_sel);
+}
+
+void rhodium_radio_control_impl::_update_tx_freq_switches(const double freq)
+{
+ RFNOC_LOG_TRACE("Update all TX freq related switches. f=" << freq << " Hz");
+ const auto band = _map_freq_to_tx_band(freq);
+ RFNOC_LOG_TRACE("Selected band " << tx_band_to_log(band));
+
+ // select values for lowband/highband switches
+ const bool is_lowband = (band == tx_band::TX_BAND_0);
+ auto tx_hb_lb_sel = is_lowband ? rhodium_cpld_ctrl::TX_HB_LB_SEL_LOWBAND
+ : rhodium_cpld_ctrl::TX_HB_LB_SEL_HIGHBAND;
+
+ // select values for filter bank switches
+ rhodium_cpld_ctrl::tx_sw2_t tx_sw2;
+ rhodium_cpld_ctrl::tx_sw3_sw4_t tx_sw3_sw4;
+ rhodium_cpld_ctrl::tx_sw5_t tx_sw5;
+ switch (band) {
+ case tx_band::TX_BAND_0:
+ // Low band doesn't use the filter banks, use configuration for band 1
+ case tx_band::TX_BAND_1:
+ tx_sw2 = rhodium_cpld_ctrl::TX_SW2_FROMSWITCH3;
+ tx_sw3_sw4 = rhodium_cpld_ctrl::TX_SW3_SW4_FROMTXFILTERLP0650MHZ;
+ tx_sw5 = rhodium_cpld_ctrl::TX_SW5_TOSWITCH4;
+ break;
+ case tx_band::TX_BAND_2:
+ tx_sw2 = rhodium_cpld_ctrl::TX_SW2_FROMSWITCH3;
+ tx_sw3_sw4 = rhodium_cpld_ctrl::TX_SW3_SW4_FROMTXFILTERLP1000MHZ;
+ tx_sw5 = rhodium_cpld_ctrl::TX_SW5_TOSWITCH4;
+ break;
+ case tx_band::TX_BAND_3:
+ tx_sw2 = rhodium_cpld_ctrl::TX_SW2_FROMSWITCH3;
+ tx_sw3_sw4 = rhodium_cpld_ctrl::TX_SW3_SW4_FROMTXFILTERLP1350MHZ;
+ tx_sw5 = rhodium_cpld_ctrl::TX_SW5_TOSWITCH4;
+ break;
+ case tx_band::TX_BAND_4:
+ tx_sw2 = rhodium_cpld_ctrl::TX_SW2_FROMSWITCH3;
+ tx_sw3_sw4 = rhodium_cpld_ctrl::TX_SW3_SW4_FROMTXFILTERLP1900MHZ;
+ tx_sw5 = rhodium_cpld_ctrl::TX_SW5_TOSWITCH4;
+ break;
+ case tx_band::TX_BAND_5:
+ tx_sw2 = rhodium_cpld_ctrl::TX_SW2_FROMTXFILTERLP3000MHZ;
+ tx_sw3_sw4 = rhodium_cpld_ctrl::TX_SW3_SW4_FROMTXFILTERLP0650MHZ;
+ tx_sw5 = rhodium_cpld_ctrl::TX_SW5_TOTXFILTERLP3000MHZ;
+ break;
+ case tx_band::TX_BAND_6:
+ tx_sw2 = rhodium_cpld_ctrl::TX_SW2_FROMTXFILTERLP4100MHZ;
+ tx_sw3_sw4 = rhodium_cpld_ctrl::TX_SW3_SW4_FROMTXFILTERLP0650MHZ;
+ tx_sw5 = rhodium_cpld_ctrl::TX_SW5_TOTXFILTERLP4100MHZ;
+ break;
+ case tx_band::TX_BAND_7:
+ tx_sw2 = rhodium_cpld_ctrl::TX_SW2_FROMTXFILTERLP6000MHZ;
+ tx_sw3_sw4 = rhodium_cpld_ctrl::TX_SW3_SW4_FROMTXFILTERLP0650MHZ;
+ tx_sw5 = rhodium_cpld_ctrl::TX_SW5_TOTXFILTERLP6000MHZ;
+ break;
+ case tx_band::TX_BAND_INVALID:
+ throw uhd::runtime_error(
+ str(boost::format("Cannot map TX frequency to band: %f") % freq));
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
+ }
+
+ // commit settings to cpld
+ _cpld->set_tx_switches(tx_sw2, tx_sw3_sw4, tx_sw5, tx_hb_lb_sel);
+}
+
+void rhodium_radio_control_impl::_update_rx_input_switches(const std::string& input)
+{
+ RFNOC_LOG_TRACE("Update all RX input related switches. input=" << input);
+ const rhodium_cpld_ctrl::cal_iso_sw_t cal_iso =
+ (input == "CAL") ? rhodium_cpld_ctrl::CAL_ISO_CALLOOPBACK
+ : rhodium_cpld_ctrl::CAL_ISO_ISOLATION;
+ const rhodium_cpld_ctrl::rx_sw1_t sw1 = [input] {
+ if (input == "TX/RX") {
+ return rhodium_cpld_ctrl::RX_SW1_FROMTXRXINPUT;
+ } else if (input == "RX2") {
+ return rhodium_cpld_ctrl::RX_SW1_FROMRX2INPUT;
+ } else if (input == "CAL") {
+ return rhodium_cpld_ctrl::RX_SW1_FROMCALLOOPBACK;
+ } else if (input == "TERM") {
+ return rhodium_cpld_ctrl::RX_SW1_ISOLATION;
+ } else {
+ throw uhd::runtime_error(
+ "Invalid antenna in _update_rx_input_switches: " + input);
+ }
+ }();
+
+ RFNOC_LOG_TRACE("Selected switch values:"
+ " sw1="
+ << sw1 << " cal_iso=" << cal_iso);
+ _cpld->set_rx_input_switches(sw1, cal_iso);
+}
+
+void rhodium_radio_control_impl::_update_tx_output_switches(const std::string& output)
+{
+ RFNOC_LOG_TRACE("Update all TX output related switches. output=" << output);
+ rhodium_cpld_ctrl::tx_sw1_t sw1;
+
+ if (output == "TX/RX") {
+ // SW1 needs to select low/high band
+ if (_is_tx_lowband(get_tx_frequency(0))) {
+ sw1 = rhodium_cpld_ctrl::TX_SW1_TOLOWBAND;
+ } else {
+ sw1 = rhodium_cpld_ctrl::TX_SW1_TOSWITCH2;
+ }
+ } else if (output == "CAL") {
+ sw1 = rhodium_cpld_ctrl::TX_SW1_TOCALLOOPBACK;
+ } else if (output == "TERM") {
+ sw1 = rhodium_cpld_ctrl::TX_SW1_ISOLATION;
+ } else {
+ throw uhd::runtime_error(
+ "Invalid antenna in _update_tx_output_switches: " + output);
+ }
+
+ RFNOC_LOG_TRACE("Selected switch values: sw1=" << sw1);
+ _cpld->set_tx_output_switches(sw1);
+}