aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/dboard/rhodium/rhodium_radio_control.hpp
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-07-03 20:15:35 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 12:16:25 -0800
commitc256b9df6502536c2e451e690f1ad5962c664d1a (patch)
treea83ad13e6f5978bbe14bb3ecf8294ba1e3d28db4 /host/lib/usrp/dboard/rhodium/rhodium_radio_control.hpp
parent9a8435ed998fc5c65257f4c55768750b227ab19e (diff)
downloaduhd-c256b9df6502536c2e451e690f1ad5962c664d1a.tar.gz
uhd-c256b9df6502536c2e451e690f1ad5962c664d1a.tar.bz2
uhd-c256b9df6502536c2e451e690f1ad5962c664d1a.zip
x300/mpmd: Port all RFNoC devices to the new RFNoC framework
Co-Authored-By: Alex Williams <alex.williams@ni.com> Co-Authored-By: Sugandha Gupta <sugandha.gupta@ettus.com> Co-Authored-By: Brent Stapleton <brent.stapleton@ettus.com> Co-Authored-By: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Diffstat (limited to 'host/lib/usrp/dboard/rhodium/rhodium_radio_control.hpp')
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_radio_control.hpp480
1 files changed, 480 insertions, 0 deletions
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_radio_control.hpp b/host/lib/usrp/dboard/rhodium/rhodium_radio_control.hpp
new file mode 100644
index 000000000..a70db79cc
--- /dev/null
+++ b/host/lib/usrp/dboard/rhodium/rhodium_radio_control.hpp
@@ -0,0 +1,480 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef INCLUDED_LIBUHD_RFNOC_RHODIUM_RADIO_CTRL_IMPL_HPP
+#define INCLUDED_LIBUHD_RFNOC_RHODIUM_RADIO_CTRL_IMPL_HPP
+
+#include "rhodium_constants.hpp"
+#include "rhodium_cpld_ctrl.hpp"
+#include "rhodium_cpld_regs.hpp"
+#include <uhd/types/serial.hpp>
+#include <uhd/usrp/gpio_defs.hpp>
+#include <uhdlib/rfnoc/radio_control_impl.hpp>
+#include <uhdlib/rfnoc/rpc_block_ctrl.hpp>
+#include <uhdlib/usrp/common/lmx2592.hpp>
+#include <uhdlib/usrp/common/mpmd_mb_controller.hpp>
+#include <uhdlib/usrp/cores/gpio_atr_3000.hpp>
+#include <uhdlib/usrp/cores/rx_frontend_core_3000.hpp>
+#include <uhdlib/usrp/cores/tx_frontend_core_200.hpp>
+#include <mutex>
+
+namespace uhd { namespace rfnoc {
+
+/*! \brief Provide access to an Rhodium radio.
+ */
+class rhodium_radio_control_impl : public radio_control_impl
+{
+public:
+ typedef boost::shared_ptr<rhodium_radio_control_impl> sptr;
+
+ //! Frequency bands for RX. Bands are a function of the analog filter banks
+ enum class rx_band {
+ RX_BAND_INVALID,
+ RX_BAND_0,
+ RX_BAND_1,
+ RX_BAND_2,
+ RX_BAND_3,
+ RX_BAND_4,
+ RX_BAND_5,
+ RX_BAND_6,
+ RX_BAND_7
+ };
+
+ //! Frequency bands for TX. Bands are a function of the analog filter banks
+ enum class tx_band {
+ TX_BAND_INVALID,
+ TX_BAND_0,
+ TX_BAND_1,
+ TX_BAND_2,
+ TX_BAND_3,
+ TX_BAND_4,
+ TX_BAND_5,
+ TX_BAND_6,
+ TX_BAND_7
+ };
+
+ /************************************************************************
+ * Structors
+ ***********************************************************************/
+ rhodium_radio_control_impl(make_args_ptr make_args);
+ virtual ~rhodium_radio_control_impl();
+
+ /************************************************************************
+ * RF API calls
+ ***********************************************************************/
+ // Note: We use the cached values in radio_ctrl_impl, so most getters are
+ // not reimplemented here
+ double set_rate(double rate);
+
+ // Setters
+ void set_tx_antenna(const std::string &ant, const size_t chan);
+ void set_rx_antenna(const std::string &ant, const size_t chan);
+ double set_tx_frequency(const double freq, const size_t chan);
+ double set_rx_frequency(const double freq, const size_t chan);
+ void set_tx_tune_args(const uhd::device_addr_t&, const size_t chan);
+ void set_rx_tune_args(const uhd::device_addr_t&, const size_t chan);
+ double set_tx_gain(const double gain, const size_t chan);
+ double set_rx_gain(const double gain, const size_t chan);
+
+ // Getters
+ std::vector<std::string> get_tx_antennas(const size_t) const;
+ std::vector<std::string> get_rx_antennas(const size_t) const;
+ uhd::freq_range_t get_tx_frequency_range(const size_t) const;
+ uhd::freq_range_t get_rx_frequency_range(const size_t) const;
+ uhd::gain_range_t get_tx_gain_range(const size_t) const;
+ uhd::gain_range_t get_rx_gain_range(const size_t) const;
+ uhd::meta_range_t get_tx_bandwidth_range(size_t) const;
+ uhd::meta_range_t get_rx_bandwidth_range(size_t) const;
+
+ /**************************************************************************
+ * LO Controls
+ *************************************************************************/
+ std::vector<std::string> get_rx_lo_names(const size_t chan) const;
+ std::vector<std::string> get_rx_lo_sources(
+ const std::string& name, const size_t chan) const;
+ freq_range_t get_rx_lo_freq_range(const std::string& name, const size_t chan) const;
+ void set_rx_lo_source(
+ const std::string& src, const std::string& name, const size_t chan);
+ const std::string get_rx_lo_source(const std::string& name, const size_t chan);
+ double set_rx_lo_freq(double freq, const std::string& name, const size_t chan);
+ double get_rx_lo_freq(const std::string& name, const size_t chan);
+ std::vector<std::string> get_tx_lo_names(const size_t chan) const;
+ std::vector<std::string> get_tx_lo_sources(
+ const std::string& name, const size_t chan) const;
+ freq_range_t get_tx_lo_freq_range(const std::string& name, const size_t chan);
+ void set_tx_lo_source(
+ const std::string& src, const std::string& name, const size_t chan);
+ const std::string get_tx_lo_source(const std::string& name, const size_t chan);
+ double set_tx_lo_freq(const double freq, const std::string& name, const size_t chan);
+ double get_tx_lo_freq(const std::string& name, const size_t chan);
+ // LO Export Control
+ void set_tx_lo_export_enabled(
+ const bool enabled, const std::string& name, const size_t chan);
+ void set_rx_lo_export_enabled(
+ const bool enabled, const std::string& name, const size_t chan);
+ bool get_tx_lo_export_enabled(const std::string& name, const size_t chan);
+ bool get_rx_lo_export_enabled(const std::string& name, const size_t chan);
+
+ /**************************************************************************
+ * GPIO Controls
+ *************************************************************************/
+ std::vector<std::string> get_gpio_banks() const;
+ void set_gpio_attr(
+ const std::string& bank, const std::string& attr, const uint32_t value);
+ uint32_t get_gpio_attr(const std::string& bank, const std::string& attr);
+
+ /**************************************************************************
+ * EEPROM API
+ *************************************************************************/
+ void set_db_eeprom(const uhd::eeprom_map_t& db_eeprom);
+ uhd::eeprom_map_t get_db_eeprom();
+
+ /**************************************************************************
+ * Sensor API
+ *************************************************************************/
+ std::vector<std::string> get_rx_sensor_names(size_t chan) const;
+ uhd::sensor_value_t get_rx_sensor(const std::string& name, size_t chan);
+ std::vector<std::string> get_tx_sensor_names(size_t chan) const;
+ uhd::sensor_value_t get_tx_sensor(const std::string& name, size_t chan);
+
+ /**************************************************************************
+ * Radio Identification API Calls
+ *************************************************************************/
+ std::string get_slot_name() const
+ {
+ return _radio_slot;
+ }
+ size_t get_chan_from_dboard_fe(
+ const std::string& fe, const uhd::direction_t direction) const;
+ std::string get_dboard_fe_from_chan(
+ const size_t chan, const uhd::direction_t direction) const;
+ std::string get_fe_name(const size_t chan, const uhd::direction_t direction) const;
+
+ /**************************************************************************
+ * node_t API Calls
+ *************************************************************************/
+ void set_command_time(uhd::time_spec_t time, const size_t chan);
+
+ /************************************************************************
+ * ??? calls
+ ***********************************************************************/
+ // LO Distribution Control
+ void set_tx_lo_output_enabled(const bool enabled, const std::string& port_name, const size_t chan);
+ void set_rx_lo_output_enabled(const bool enabled, const std::string& port_name, const size_t chan);
+ bool get_tx_lo_output_enabled(const std::string& port_name, const size_t chan);
+ bool get_rx_lo_output_enabled(const std::string& port_name, const size_t chan);
+
+ // LO Gain Control
+
+ //! Set the external gain for a TX LO
+ // Out of range values will be coerced
+ double set_tx_lo_gain(const double gain, const std::string &name, const size_t chan);
+
+ //! Set the external gain for an RX LO
+ // Out of range values will be coerced
+ double set_rx_lo_gain(const double gain, const std::string &name, const size_t chan);
+
+ double get_tx_lo_gain(const std::string &name, const size_t chan);
+ double get_rx_lo_gain(const std::string &name, const size_t chan);
+
+ // LO Output Power Control
+
+ //! Set the output power setting of a TX LO
+ // Out of range values will be coerced
+ double set_tx_lo_power(const double power, const std::string &name, const size_t chan);
+
+ //! Set the output power setting of a RX LO
+ // Out of range values will be coerced
+ double set_rx_lo_power(const double power, const std::string &name, const size_t chan);
+
+ double get_tx_lo_power(const std::string &name, const size_t chan);
+ double get_rx_lo_power(const std::string &name, const size_t chan);
+
+
+private:
+ /**************************************************************************
+ * noc_block_base API
+ *************************************************************************/
+ //! Safely shut down all peripherals
+ //
+ // Reminder: After this is called, no peeks and pokes are allowed!
+ void deinit()
+ {
+ RFNOC_LOG_TRACE("deinit()");
+ // Remove access to all peripherals
+ _wb_iface.reset();
+ _spi.reset();
+ _tx_lo.reset();
+ _rx_lo.reset();
+ _cpld.reset();
+ _gpio.reset();
+ _fp_gpio.reset();
+ _rx_fe_core.reset();
+ _tx_fe_core.reset();
+ }
+
+ /**************************************************************************
+ * Helpers
+ *************************************************************************/
+ //! Initialize all the peripherals connected to this block
+ void _init_peripherals();
+
+ //! Sync up with MPM
+ void _init_mpm();
+
+ //! Set state of this class to sensible defaults
+ void _init_defaults();
+
+ //! Init a subtree for the RF frontends
+ void _init_frontend_subtree(uhd::property_tree::sptr subtree);
+
+ //! Initialize property tree
+ void _init_prop_tree();
+
+ //! Discover and initialize any mpm sensors
+ void _init_mpm_sensors(const direction_t dir, const size_t chan_idx);
+
+ //! Get the frequency range for an LO
+ freq_range_t _get_lo_freq_range(const std::string &name) const;
+
+ //! Get the current lowband intermediate frequency
+ double _get_lowband_lo_freq() const;
+
+ //! Configure LO1's export
+ void _set_lo1_export_enabled(
+ const bool enabled,
+ const direction_t dir
+ );
+
+ //! Validate that port_name is valid, and that LO distribution functions
+ // can be called in this instance
+ void _validate_output_port(
+ const std::string& port_name,
+ const std::string& function_name
+ );
+
+ //! Configure LO Distribution board's termination switches
+ void _set_lo_output_enabled(
+ const bool enabled,
+ const std::string& port_name,
+ const direction_t dir
+ );
+
+ bool _get_lo_output_enabled(
+ const std::string& port_name,
+ const direction_t dir
+ );
+
+ //! Configure LO1's output power
+ // Out of range values will be coerced to [0-63]
+ double _set_lo1_power(
+ const double power,
+ const direction_t dir
+ );
+
+ //! Flash all front end LEDs at 1 Hz for the specified amount of time
+ void _identify_with_leds(double identify_duration);
+
+ //! 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);
+
+ //! Configure DSP core corrections based on current frequency
+ void _update_corrections(const double freq, const direction_t dir, const bool enable);
+
+ //! 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);
+ //! Map a frequency in Hz to an tx_band value. Will return
+ // tx_band::INVALID_BAND if the frequency is out of range.
+ static tx_band _map_freq_to_tx_band(const double freq);
+
+ //! Return if the given rx frequency is in lowband
+ // NOTE: Returns false if frequency is out of Rh's rx frequency range
+ static bool _is_rx_lowband(const double freq);
+ //! Return if the given tx frequency is in lowband
+ // NOTE: Returns false if frequency is out of Rh's tx frequency range
+ static bool _is_tx_lowband(const double freq);
+
+ //! Return the gain range of the LMX LO
+ static uhd::gain_range_t _get_lo_gain_range();
+ //! Return the power setting range of the LMX LO
+ static uhd::gain_range_t _get_lo_power_range();
+
+ //! Lookup the LO DSA setting from LO frequency
+ int _get_lo_dsa_setting(const double freq, const direction_t dir);
+
+ //! Lookup the LO output power setting from LO frequency
+ unsigned int _get_lo_power_setting(const double freq);
+
+ bool _get_spur_dodging_enabled(const uhd::direction_t dir) const;
+ double _get_spur_dodging_threshold(const uhd::direction_t dir) const;
+ bool _get_highband_spur_reduction_enabled(const uhd::direction_t dir) const;
+ bool _get_timed_command_enabled() const;
+
+ /**************************************************************************
+ * Sensors
+ *************************************************************************/
+ //! Return LO lock status. Factors in current band (low/high) and
+ // direction (TX/RX)
+ bool get_lo_lock_status(const direction_t dir) const;
+
+ /**************************************************************************
+ * Frontend Controls
+ *************************************************************************/
+
+ void _set_tx_fe_connection(const std::string &conn);
+ void _set_rx_fe_connection(const std::string &conn);
+ std::string _get_tx_fe_connection() const;
+ std::string _get_rx_fe_connection() const;
+
+ /**************************************************************************
+ * CPLD Controls (implemented in rhodium_radio_ctrl_cpld.cpp)
+ *************************************************************************/
+ void _update_rx_freq_switches(
+ const double freq
+ );
+
+ void _update_tx_freq_switches(
+ const double freq
+ );
+
+ void _update_rx_input_switches(
+ const std::string &input
+ );
+
+ void _update_tx_output_switches(
+ const std::string &output
+ );
+
+ /**************************************************************************
+ * Private attributes
+ *************************************************************************/
+ //! Locks access to the antenna cached values
+ std::mutex _ant_mutex;
+
+ //! Letter representation of the radio we're currently running
+ std::string _radio_slot;
+
+ //! Prepended for all dboard RPC calls
+ std::string _rpc_prefix;
+
+ //! Daughterboard info from MPM
+ std::map<std::string, std::string> _dboard_info;
+
+ //! Reference to the MB controller
+ mpmd_mb_controller::sptr _n320_mb_control;
+
+ //! Reference to the MB timekeeper
+ uhd::rfnoc::mpmd_mb_controller::mpmd_timekeeper::sptr _n3xx_timekeeper;
+
+ //! Reference to the RPC client
+ uhd::rpc_client::sptr _rpcc;
+
+ //! Reference to wb_iface compat adapter. This will call into this->regs()
+ uhd::timed_wb_iface::sptr _wb_iface;
+
+ //! Reference to the SPI core
+ uhd::spi_iface::sptr _spi;
+
+ //! Reference to the TX LO
+ lmx2592_iface::sptr _tx_lo;
+
+ //! Reference to the RX LO
+ lmx2592_iface::sptr _rx_lo;
+
+ //! Reference to the CPLD controls. Even if there's multiple radios,
+ // there's only one CPLD control.
+ std::shared_ptr<rhodium_cpld_ctrl> _cpld;
+
+ //! ATR controls. These control the external DSA and the AD9371 gain
+ // up/down bits. They do *not* control the ATR state of the CPLD, the
+ // tx/rx run states are hooked up directly to the CPLD.
+ //
+ // Every radio channel gets its own ATR state register.
+ usrp::gpio_atr::gpio_atr_3000::sptr _gpio;
+
+ //! Front panel GPIO controller. Note that only one radio block per
+ // module can be the FP-GPIO master.
+ usrp::gpio_atr::gpio_atr_3000::sptr _fp_gpio;
+
+ //! One DSP core per channel
+ rx_frontend_core_3000::sptr _rx_fe_core;
+ tx_frontend_core_200::sptr _tx_fe_core;
+
+ //! Sampling rate, and also ref clock frequency for the lowband LOs.
+ double _master_clock_rate = 1.0;
+ //! Saved frontend connection for DSP core
+ std::string _rx_fe_connection;
+ std::string _tx_fe_connection;
+ //! Desired RF frequency
+ std::map<direction_t, double> _desired_rf_freq = {
+ {RX_DIRECTION, 2.44e9}, {TX_DIRECTION, 2.44e9}};
+ //! Frequency at which gain setting was last applied. The CPLD requires a new gain
+ // control write when switching between lowband and highband frequencies, so save
+ // the frequency when sending a gain control command.
+ double _tx_frequency_at_last_gain_write = 0.0;
+ double _rx_frequency_at_last_gain_write = 0.0;
+ //! LO gain
+ double _lo_rx_gain = 0.0;
+ double _lo_tx_gain = 0.0;
+ //! LO output power
+ double _lo_rx_power = 0.0;
+ double _lo_tx_power = 0.0;
+ //! Gain profile
+ std::map<direction_t, std::string> _gain_profile = {
+ {RX_DIRECTION, "default"}, {TX_DIRECTION, "default"}};
+
+ //! LO source
+ std::string _rx_lo_source = "internal";
+ std::string _tx_lo_source = "internal";
+
+ //! LO export enabled
+ bool _rx_lo_exported = false;
+ bool _tx_lo_exported = false;
+
+ //! LO state frequency
+ double _rx_lo_freq = 0.0;
+ double _tx_lo_freq = 0.0;
+
+ //! LO Distribution board
+ bool _lo_dist_present = false;
+
+ //! LO Distribution board output status
+ bool _lo_dist_rx_out_enabled[4] = { false, false, false, false };
+ bool _lo_dist_tx_out_enabled[4] = { false, false, false, false };
+
+ std::unordered_map<uhd::direction_t, uhd::device_addr_t, std::hash<size_t>>
+ _tune_args{{uhd::RX_DIRECTION, uhd::device_addr_t()},
+ {uhd::TX_DIRECTION, uhd::device_addr_t()}};
+
+ //! Cache the contents of the DB EEPROM
+ uhd::eeprom_map_t _db_eeprom;
+
+ //! Cached list of RX sensor names
+ std::vector<std::string> _rx_sensor_names{"lo_locked"};
+ //! Cached list of TX sensor names
+ std::vector<std::string> _tx_sensor_names{"lo_locked"};
+
+ property_t<std::string> _spur_dodging_mode{SPUR_DODGING_PROP_NAME,
+ RHODIUM_DEFAULT_SPUR_DOGING_MODE,
+ {res_source_info::USER}};
+ property_t<double> _spur_dodging_threshold{SPUR_DODGING_THRESHOLD_PROP_NAME,
+ RHODIUM_DEFAULT_SPUR_DOGING_THRESHOLD,
+ {res_source_info::USER}};
+ property_t<std::string> _highband_spur_reduction_mode{
+ HIGHBAND_SPUR_REDUCTION_PROP_NAME,
+ RHODIUM_DEFAULT_HB_SPUR_REDUCTION_MODE,
+ {res_source_info::USER}};
+
+}; /* class rhodium_radio_control_impl */
+
+}} /* namespace uhd::rfnoc */
+
+#endif /* INCLUDED_LIBUHD_RFNOC_RHODIUM_RADIO_CTRL_IMPL_HPP */
+