From 2a575bf9b5a4942f60e979161764b9e942699e1e Mon Sep 17 00:00:00 2001 From: Lars Amsel Date: Fri, 4 Jun 2021 08:27:50 +0200 Subject: uhd: Add support for the USRP X410 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lars Amsel Co-authored-by: Michael Auchter Co-authored-by: Martin Braun Co-authored-by: Paul Butler Co-authored-by: Cristina Fuentes Co-authored-by: Humberto Jimenez Co-authored-by: Virendra Kakade Co-authored-by: Lane Kolbly Co-authored-by: Max Köhler Co-authored-by: Andrew Lynch Co-authored-by: Grant Meyerhoff Co-authored-by: Ciro Nishiguchi Co-authored-by: Thomas Vogel --- .../include/uhdlib/usrp/dboard/zbx/zbx_dboard.hpp | 416 +++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 host/lib/include/uhdlib/usrp/dboard/zbx/zbx_dboard.hpp (limited to 'host/lib/include/uhdlib/usrp/dboard/zbx/zbx_dboard.hpp') diff --git a/host/lib/include/uhdlib/usrp/dboard/zbx/zbx_dboard.hpp b/host/lib/include/uhdlib/usrp/dboard/zbx/zbx_dboard.hpp new file mode 100644 index 000000000..619c4a05f --- /dev/null +++ b/host/lib/include/uhdlib/usrp/dboard/zbx/zbx_dboard.hpp @@ -0,0 +1,416 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#pragma once + +#include "zbx_constants.hpp" +#include "zbx_cpld_ctrl.hpp" +#include "zbx_expert.hpp" +#include "zbx_lo_ctrl.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd::rfnoc; + +namespace uhd { namespace usrp { namespace zbx { + +const static uint16_t ZBX_PID = 0x4002; + +/*! Provide access to a ZBX radio. + */ +class zbx_dboard_impl : public uhd::usrp::x400::x400_dboard_iface +{ +public: + using sptr = std::shared_ptr; + using time_accessor_fn_type = std::function; + + /************************************************************************ + * Structors + ***********************************************************************/ + zbx_dboard_impl(register_iface& reg_iface, + const size_t reg_base_address, + time_accessor_fn_type&& time_accessor, + const size_t db_idx, + const std::string& radio_slot, + const std::string& rpc_prefix, + const std::string& unique_id, + uhd::usrp::x400_rpc_iface::sptr mb_rpcc, + uhd::usrp::zbx_rpc_iface::sptr rpcc, + uhd::rfnoc::x400::rfdc_control::sptr rfdcc, + uhd::property_tree::sptr tree); + virtual ~zbx_dboard_impl(); + + size_t get_chan_from_dboard_fe( + const std::string& fe, const uhd::direction_t) const override; + std::string get_dboard_fe_from_chan( + const size_t chan, const uhd::direction_t) const override; + + /************************************************************************ + * node_t && noc_block_base API calls + ***********************************************************************/ + void deinit(); + + void set_command_time(uhd::time_spec_t time, const size_t chan) override; + + /************************************************************************ + * API calls + ***********************************************************************/ + + bool is_adc_self_cal_supported() override + { + return true; + } + + uhd::usrp::x400::adc_self_cal_params_t get_adc_self_cal_params(const double tone_freq) override + { + // This is chosen such that the IF2 frequency is 1.06G + const double rx_freq = 4.7e9 - 5.12e6; + const double if2_freq = 1.06e9; + const double offset = tone_freq - if2_freq; + + // Minus because this zone is inverted + const double tx_freq = rx_freq - offset; + return { + 10.0, // min_gain + 50.0, // max_gain + rx_freq, // rx_freq + tx_freq, // tx_freq + }; + } + + rf_control::gain_profile_iface::sptr get_tx_gain_profile_api() override + { + return _tx_gain_profile_api; + } + rf_control::gain_profile_iface::sptr get_rx_gain_profile_api() override + { + return _rx_gain_profile_api; + } + + void set_tx_antenna(const std::string& ant, const size_t chan) override; + void set_rx_antenna(const std::string& ant, const size_t chan) override; + std::vector get_tx_antennas(const size_t /*chan*/) const override + { + return TX_ANTENNAS; + } + std::vector get_rx_antennas(const size_t /*chan*/) const override + { + return RX_ANTENNAS; + } + + double set_tx_frequency(const double freq, const size_t chan) override; + double set_rx_frequency(const double freq, const size_t chan) override; + uhd::freq_range_t get_tx_frequency_range(const size_t /*chan*/) const override + { + return ZBX_FREQ_RANGE; + } + uhd::freq_range_t get_rx_frequency_range(const size_t /*chan*/) const override + { + return ZBX_FREQ_RANGE; + } + + double set_tx_bandwidth(const double bandwidth, const size_t chan) override; + double set_rx_bandwidth(const double bandwidth, const size_t chan) override; + uhd::meta_range_t get_tx_bandwidth_range(size_t chan) const override + { + return _tree + ->access( + _get_frontend_path(TX_DIRECTION, chan) / "bandwidth" / "range") + .get(); + } + uhd::meta_range_t get_rx_bandwidth_range(size_t chan) const override + { + return _tree + ->access( + _get_frontend_path(RX_DIRECTION, chan) / "bandwidth" / "range") + .get(); + } + + double set_tx_gain(const double gain, const size_t chan) override; + double set_tx_gain( + const double gain, const std::string& name, const size_t chan) override; + double set_rx_gain(const double gain, const size_t chan) override; + double set_rx_gain( + const double gain, const std::string& name, const size_t chan) override; + double get_rx_gain(const size_t chan) override; + double get_tx_gain(const size_t chan) override; + double get_rx_gain(const std::string& name, const size_t chan) override; + double get_tx_gain(const std::string& name, const size_t chan) override; + + uhd::gain_range_t get_tx_gain_range(const size_t /*chan*/) const override + { + return ZBX_TX_GAIN_RANGE; + } + uhd::gain_range_t get_rx_gain_range(const size_t /*chan*/) const override + { + // FIXME This should return a ZBX_RX_LOW_FREQ_GAIN_RANGE when freq is + // low, but this function is const + return ZBX_RX_GAIN_RANGE; + } + + // LO Property Getters + std::vector get_tx_lo_names(const size_t /*chan*/) const + { + return ZBX_LOS; + } + std::vector get_rx_lo_names(const size_t /*chan*/) const + { + return ZBX_LOS; + } + std::vector get_tx_lo_sources( + const std::string& /*name*/, const size_t /*chan*/) const + { + return std::vector{"internal", "external"}; + } + std::vector get_rx_lo_sources( + const std::string& /*name*/, const size_t /*chan*/) const + { + return std::vector{"internal", "external"}; + } + + // LO Frequency Control + double set_tx_lo_freq( + const double freq, const std::string& name, const size_t chan) override; + double set_rx_lo_freq( + const double freq, const std::string& name, const size_t chan) override; + double get_tx_lo_freq(const std::string& name, const size_t chan) override; + double get_rx_lo_freq(const std::string& name, size_t chan) override; + + // LO Source Control + void set_tx_lo_source( + const std::string& src, const std::string& name, const size_t chan) override; + void set_rx_lo_source( + const std::string& src, const std::string& name, const size_t chan) override; + const std::string get_tx_lo_source( + const std::string& name, const size_t chan) override; + const std::string get_rx_lo_source( + const std::string& name, const size_t chan) override; + + uhd::freq_range_t get_rx_lo_freq_range( + const std::string& name, const size_t chan) const override + { + return _get_lo_freq_range(name, chan); + } + + // TODO: Why is this not const? + uhd::freq_range_t get_tx_lo_freq_range( + const std::string& name, const size_t chan) override + { + return _get_lo_freq_range(name, chan); + } + + void set_rx_lo_export_enabled( + const bool enabled, const std::string& name, const size_t chan) override; + bool get_rx_lo_export_enabled( + const std::string& name, const size_t chan) override; + void set_tx_lo_export_enabled( + const bool enabled, const std::string& name, const size_t chan) override; + bool get_tx_lo_export_enabled(const std::string& name, const size_t chan) override; + + + /****************************************************************************** + * EEPROM API + *****************************************************************************/ + eeprom_map_t get_db_eeprom() override; + + /************************************************************************** + * Radio Identification API Calls + *************************************************************************/ + + std::string get_tx_antenna(size_t chan) const override; + std::string get_rx_antenna(size_t chan) const override; + double get_tx_frequency(size_t chan) override; + double get_rx_frequency(size_t chan) override; + double get_rx_bandwidth(size_t chan) override; + double get_tx_bandwidth(size_t chan) override; + void set_tx_tune_args(const uhd::device_addr_t&, const size_t) override; + void set_rx_tune_args(const uhd::device_addr_t&, const size_t) override; + std::vector get_tx_gain_names(size_t) const override; + std::vector get_rx_gain_names(size_t) const override; + + uhd::gain_range_t get_tx_gain_range( + const std::string& name, const size_t chan) const override; + + uhd::gain_range_t get_rx_gain_range( + const std::string& name, const size_t chan) const override; + + void set_rx_agc(const bool, const size_t) override; + + std::vector& get_pwr_mgr(uhd::direction_t trx) override; + +private: + uhd::property_tree::sptr get_tree() + { + return _tree; + } + + // Expert map, keyed by the pair of tx/rx and channel + uhd::experts::expert_container::sptr _expert_container; + + /************************************************************************** + * Helpers + *************************************************************************/ + //! Initialize DB-CPLD + void _init_cpld(); + + //! Initialize all the peripherals connected to this block + void _init_peripherals(); + + //! Init a subtree for the RF frontends + void _init_frontend_subtree(uhd::property_tree::sptr subtree, + const uhd::direction_t trx, + const size_t chan_idx, + const fs_path fe_path); + //! Initializing the expert properties + void _init_frequency_prop_tree(uhd::property_tree::sptr subtree, + uhd::experts::expert_container::sptr expert, + const fs_path fe_path); + void _init_gain_prop_tree(uhd::property_tree::sptr subtree, + uhd::experts::expert_container::sptr, + const uhd::direction_t trx, + const size_t chan_idx, + const fs_path fe_path); + void _init_antenna_prop_tree(uhd::property_tree::sptr subtree, + uhd::experts::expert_container::sptr, + const uhd::direction_t trx, + const size_t chan_idx, + const fs_path fe_path); + void _init_programming_prop_tree(uhd::property_tree::sptr subtree, + uhd::experts::expert_container::sptr, + const fs_path fe_path); + void _init_lo_prop_tree(uhd::property_tree::sptr subtree, + uhd::experts::expert_container::sptr, + const uhd::direction_t trx, + const size_t chan_idx, + const fs_path fe_path); + //! Init all experts, bind to properties created above + void _init_experts(uhd::property_tree::sptr subtree, + uhd::experts::expert_container::sptr, + const uhd::direction_t trx, + const size_t chan_idx, + const fs_path fe_path); + + uhd::usrp::pwr_cal_mgr::sptr _init_power_cal(uhd::property_tree::sptr subtree, + const uhd::direction_t trx, + const size_t chan_idx, + const fs_path fe_path); + + //! Initialize property tree + void _init_prop_tree(); + //! Init RPC interaction + void _init_mpm(); + + //! Set up sensor property nodes + void _init_mpm_sensors(const direction_t dir, const size_t chan_idx); + + //! Get subtree path for a given direction/channel + fs_path _get_frontend_path(const direction_t dir, const size_t chan_idx) const; + + // Get all los "lock status", per enabled && locked individual LOs + bool _get_all_los_locked(const direction_t dir, const size_t chan); + + const std::string _unique_id; + std::string get_unique_id() const; + + freq_range_t _get_lo_freq_range(const std::string& name, const size_t chan) const; + + /************************************************************************** + * Private attributes + *************************************************************************/ + + static constexpr size_t _num_rx_chans = 2; + static constexpr size_t _num_tx_chans = 2; + + //! Interface to the registers + uhd::rfnoc::register_iface& _regs; + const size_t _reg_base_address; + + //! Interface to get the command time + time_accessor_fn_type _time_accessor; + + //! Letter representation of the radio we're currently running + const std::string _radio_slot; + + //! Index of this daughterboard + const size_t _db_idx; + + // infos about the daughtherboard + std::vector> _all_dboard_info; + + //! Prepended for all dboard RPC calls + const std::string _rpc_prefix; + + //! Reference to the MB controller + uhd::rfnoc::mpmd_mb_controller::sptr _mb_control; + + //! Reference to wb_iface adapters + std::vector _wb_ifaces; + + //! Reference to the RPC client + uhd::usrp::x400_rpc_iface::sptr _mb_rpcc; + uhd::usrp::zbx_rpc_iface::sptr _rpcc; + + //! Reference to the RFDC controller + uhd::rfnoc::x400::rfdc_control::sptr _rfdcc; + + //! Reference to the CPLD controls + std::shared_ptr _cpld; + + //! Reference to all LO controls + std::map> _lo_ctrl_map; + + //! Reference to the TX Cal data + std::shared_ptr _tx_dsa_cal; + + //! Reference to the RX Cal data + std::shared_ptr _rx_dsa_cal; + + //! Reference to this block's subtree + // + // It is mutable because _tree->access<>(..).get() is not const, but we + // need to do just that in some const contexts + mutable uhd::property_tree::sptr _tree; + + std::vector _rx_pwr_mgr; + std::vector _tx_pwr_mgr; + + rf_control::gain_profile_iface::sptr _tx_gain_profile_api; + rf_control::gain_profile_iface::sptr _rx_gain_profile_api; + + //! Store the current RX gain profile + std::vector _rx_gain_profile = { + ZBX_GAIN_PROFILE_DEFAULT, ZBX_GAIN_PROFILE_DEFAULT}; + //! Store the current TX gain profile + std::vector _tx_gain_profile = { + ZBX_GAIN_PROFILE_DEFAULT, ZBX_GAIN_PROFILE_DEFAULT}; + + //! The sampling rate of the RFdc, typically something close to 3 GHz + const double _rfdc_rate; + + //! The PLL reference rate, typically something in the 50 - 64 MHz range + const double _prc_rate; +}; + +}}} // namespace uhd::usrp::zbx -- cgit v1.2.3