diff options
Diffstat (limited to 'host')
| -rw-r--r-- | host/lib/usrp/common/ad9361_driver/ad9361_device.cpp | 2 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp | 12 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp | 5 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_constants.hpp | 3 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp | 139 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/magnesium/magnesium_radio_control.hpp | 21 | ||||
| -rw-r--r-- | host/lib/usrp/multi_usrp_rfnoc.cpp | 38 | ||||
| -rw-r--r-- | host/python/pyuhd.cpp | 1 | 
8 files changed, 203 insertions, 18 deletions
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index 6d687f80e..e53903c49 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -2946,7 +2946,7 @@ filter_info_base::sptr ad9361_device_t::_get_filter_fir(      max_num_taps = _get_num_fir_taps(direction);      filter_info_base::sptr fir( -        new digital_filter_fir<int16_t>(filter_info_base::DIGITAL_FIR_I16, +        std::make_shared<digital_filter_fir<int16_t>>(filter_info_base::DIGITAL_FIR_I16,              (enable == 0) ? true : false,              5,              rate, diff --git a/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp b/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp index 3bb0aeea6..e5bb87216 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp @@ -135,3 +135,15 @@ std::string magnesium_ad9371_iface::get_lo_source(const uhd::direction_t dir)      UHD_LOG_TRACE(_log_prefix, _rpc_prefix << "get_lo_source returned " << retval);      return retval;  } + +void magnesium_ad9371_iface::set_fir( +    const std::string& name, const int8_t gain, const std::vector<int16_t>& coeffs) +{ +    request<void>("set_fir", name, gain, coeffs); +} + +std::pair<int8_t, std::vector<int16_t>> magnesium_ad9371_iface::get_fir( +    const std::string& name) +{ +    return request<std::pair<int8_t, std::vector<int16_t>>>("get_fir", name); +} diff --git a/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp b/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp index 83381f114..0c1012fd5 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp @@ -37,6 +37,11 @@ public:      std::string get_lo_source(const uhd::direction_t dir); +    void set_fir( +        const std::string& name, const int8_t gain, const std::vector<int16_t>& coeffs); + +    std::pair<int8_t, std::vector<int16_t>> get_fir(const std::string& name); +  private:      /*! Shorthand to perform an RPC request. Saves some typing.       */ diff --git a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp index 8de62743d..9eaea8027 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_constants.hpp @@ -22,6 +22,9 @@ static constexpr double AD9371_TX_MAX_BANDWIDTH = 100.0e6; // HZ  static constexpr double AD9371_MIN_FREQ = 300.0e6; // Hz  static constexpr double AD9371_MAX_FREQ = 6.0e9; // Hz +static constexpr size_t AD9371_RX_MAX_FIR_TAPS = 48; // Coefficients +static constexpr size_t AD9371_TX_MAX_FIR_TAPS = 32; // Coefficients +  static constexpr double ADF4351_MIN_FREQ = 35.0e6;  static constexpr double ADF4351_MAX_FREQ = 4.4e9; diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp index 8e2463721..249833ddf 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp @@ -1175,6 +1175,145 @@ sensor_value_t magnesium_radio_control_impl::get_tx_sensor(  }  /************************************************************************** + * Filter API + *************************************************************************/ +std::vector<std::string> magnesium_radio_control_impl::get_rx_filter_names( +    const size_t chan) const +{ +    UHD_ASSERT_THROW(chan < TOTAL_RADIO_PORTS); +    if (chan % 2 == 0) { +        return {"RX1_FIR", "RX1RX2_FIR"}; +    } else { +        return {"RX2_FIR", "RX1RX2_FIR"}; +    } +} + +uhd::filter_info_base::sptr magnesium_radio_control_impl::get_rx_filter( +    const std::string& name, const size_t) +{ +    if (_mpm_compat_num[0] < 4 || (_mpm_compat_num[0] == 4 && _mpm_compat_num[1] < 2)) { +        RFNOC_LOG_WARNING("Getting rx filter not supported. Please upgrade MPM to a " +                          "minimum version of 4.2."); +        return std::make_shared<uhd::digital_filter_fir<int16_t>>( +            uhd::filter_info_base::filter_type::DIGITAL_FIR_I16, +            false, +            0, +            1.0, +            1, +            1, +            32767, +            AD9371_RX_MAX_FIR_TAPS, +            std::vector<int16_t>(AD9371_RX_MAX_FIR_TAPS, 0)); +    } + +    const auto rv     = _ad9371->get_fir(name); +    const auto coeffs = rv.second; +    // TODO: Put gain in the digital_filter_fir +    return std::make_shared<uhd::digital_filter_fir<int16_t>>( +        uhd::filter_info_base::filter_type::DIGITAL_FIR_I16, +        false, +        0, +        1.0, +        1, +        1, +        32767, +        AD9371_RX_MAX_FIR_TAPS, +        coeffs); +} + +void magnesium_radio_control_impl::set_rx_filter( +    const std::string& name, uhd::filter_info_base::sptr filter, const size_t) +{ +    std::lock_guard<std::recursive_mutex> l(_set_lock); + +    if (_mpm_compat_num[0] < 4 || (_mpm_compat_num[0] == 4 && _mpm_compat_num[1] < 2)) { +        RFNOC_LOG_WARNING("Setting rx filter not supported. Please upgrade MPM to a " +                          "minimum version of 4.2."); +        return; +    } + +    auto fir = std::dynamic_pointer_cast<uhd::digital_filter_fir<int16_t>>(filter); +    if (fir == nullptr) { +        throw uhd::runtime_error("Invalid Filter Type for RX Filter"); +    } +    if (fir->get_taps().size() != AD9371_RX_MAX_FIR_TAPS) { +        throw uhd::runtime_error("AD937x RX Filter Taps must be " +                                 + std::to_string(AD9371_RX_MAX_FIR_TAPS) +                                 + " taps long!"); +    } +    // TODO: Use gain in the digital_filter_fir +    _ad9371->set_fir(name, 6, fir->get_taps()); +} + +std::vector<std::string> magnesium_radio_control_impl::get_tx_filter_names( +    const size_t chan) const +{ +    UHD_ASSERT_THROW(chan < TOTAL_RADIO_PORTS); +    if (chan % 2 == 0) { +        return {"TX1_FIR", "TX1TX2_FIR"}; +    } else { +        return {"TX2_FIR", "TX1TX2_FIR"}; +    } +} + +uhd::filter_info_base::sptr magnesium_radio_control_impl::get_tx_filter( +    const std::string& name, const size_t) +{ +    if (_mpm_compat_num[0] < 4 || (_mpm_compat_num[0] == 4 && _mpm_compat_num[1] < 2)) { +        RFNOC_LOG_WARNING("Getting tx filter not supported. Please upgrade MPM to a " +                          "minimum version of 4.2."); +        return std::make_shared<uhd::digital_filter_fir<int16_t>>( +            uhd::filter_info_base::filter_type::DIGITAL_FIR_I16, +            false, +            0, +            1.0, +            1, +            1, +            32767, +            AD9371_TX_MAX_FIR_TAPS, +            std::vector<int16_t>(AD9371_TX_MAX_FIR_TAPS, 0)); +    } + +    const auto rv   = _ad9371->get_fir(name); +    const auto taps = rv.second; +    // TODO: Use gain in the digital_filter_fir +    return std::make_shared<uhd::digital_filter_fir<int16_t>>( +        uhd::filter_info_base::filter_type::DIGITAL_FIR_I16, +        false, +        0, +        1.0, +        1, +        1, +        32767, +        AD9371_TX_MAX_FIR_TAPS, +        taps); +} + +void magnesium_radio_control_impl::set_tx_filter( +    const std::string& name, uhd::filter_info_base::sptr filter, const size_t) +{ +    std::lock_guard<std::recursive_mutex> l(_set_lock); + +    if (_mpm_compat_num[0] < 4 || (_mpm_compat_num[0] == 4 && _mpm_compat_num[1] < 2)) { +        RFNOC_LOG_WARNING("Setting tx filter not supported. Please upgrade MPM to a " +                          "minimum version of 4.2."); +        return; +    } + +    auto fir = std::dynamic_pointer_cast<uhd::digital_filter_fir<int16_t>>(filter); +    if (fir == nullptr) { +        throw uhd::runtime_error("Invalid Filter Type for TX Filter"); +    } +    if (fir->get_taps().size() != AD9371_TX_MAX_FIR_TAPS) { +        throw uhd::runtime_error("AD937x TX Filter Taps must be " +                                 + std::to_string(AD9371_TX_MAX_FIR_TAPS) +                                 + " taps long!"); +    } +    // TODO: Use gain in the digital_filter_fir +    _ad9371->set_fir(name, 6, fir->get_taps()); +} + +/**************************************************************************   * Radio Identification API Calls   *************************************************************************/  size_t magnesium_radio_control_impl::get_chan_from_dboard_fe( diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.hpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.hpp index 5ac1ca245..814fbecf1 100644 --- a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.hpp +++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.hpp @@ -14,6 +14,7 @@  #include "magnesium_ad9371_iface.hpp"  #include "magnesium_cpld_ctrl.hpp"  #include "magnesium_cpld_regs.hpp" +#include <uhd/rfnoc/filter_node.hpp>  #include <uhd/types/eeprom.hpp>  #include <uhd/types/serial.hpp>  #include <uhd/usrp/dboard_manager.hpp> @@ -31,7 +32,8 @@ namespace uhd { namespace rfnoc {   *   * This daughterboard is used on the USRP N310 and N300.   */ -class magnesium_radio_control_impl : public radio_control_impl +class magnesium_radio_control_impl : public radio_control_impl, +                                     public uhd::rfnoc::detail::filter_node  {  public:      //! Frequency bands for RX. Bands are a function of the analog filter banks @@ -173,6 +175,23 @@ public:      std::string get_fe_name(          const size_t chan, const uhd::direction_t direction) const override; +    /************************************************************************** +     * Filter API +     *************************************************************************/ +    std::vector<std::string> get_rx_filter_names(const size_t chan) const override; +    uhd::filter_info_base::sptr get_rx_filter( +        const std::string& name, const size_t chan) override; +    void set_rx_filter(const std::string& name, +        uhd::filter_info_base::sptr filter, +        const size_t chan) override; + +    std::vector<std::string> get_tx_filter_names(const size_t chan) const override; +    uhd::filter_info_base::sptr get_tx_filter( +        const std::string& name, const size_t chan) override; +    void set_tx_filter(const std::string& name, +        uhd::filter_info_base::sptr filter, +        const size_t chan) override; +  private:      /**************************************************************************       * Helpers diff --git a/host/lib/usrp/multi_usrp_rfnoc.cpp b/host/lib/usrp/multi_usrp_rfnoc.cpp index 00e386b71..270e86ca4 100644 --- a/host/lib/usrp/multi_usrp_rfnoc.cpp +++ b/host/lib/usrp/multi_usrp_rfnoc.cpp @@ -17,6 +17,7 @@  #include <uhd/usrp/multi_usrp.hpp>  #include <uhd/utils/graph_utils.hpp>  #include <uhd/utils/math.hpp> +#include <uhd/utils/string.hpp>  #include <uhdlib/rfnoc/rfnoc_device.hpp>  #include <uhdlib/rfnoc/rfnoc_rx_streamer.hpp>  #include <uhdlib/rfnoc/rfnoc_tx_streamer.hpp> @@ -2229,11 +2230,13 @@ public:          const std::string& name, const size_t chan) override      {          try { +            // Get the blockid and filtername separated from the name string +            const auto names        = string::split(name, ":"); +            const auto& blockid     = names.first; +            const auto& filter_name = names.second;              // The block_id_t constructor is pretty smart; let it handle the parsing. -            block_id_t block_id(name); -            auto rx_chan = _get_rx_chan(chan); -            // The filter name is the `name` after the BLOCK_ID and a `:` -            std::string filter_name = name.substr(block_id.to_string().size() + 1); +            block_id_t block_id(blockid); +            const auto rx_chan = _get_rx_chan(chan);              // Try to dynamic cast either the radio or the DDC to a filter_node, and call              // its filter function              auto block_ctrl = [rx_chan, block_id, chan]() -> noc_block_base::sptr { @@ -2270,11 +2273,12 @@ public:      {          MUX_RX_API_CALL(set_rx_filter, name, filter);          try { +            const auto names        = string::split(name, ":"); +            const auto& blockid     = names.first; +            const auto& filter_name = names.second;              // The block_id_t constructor is pretty smart; let it handle the parsing. -            block_id_t block_id(name); -            auto rx_chan = _get_rx_chan(chan); -            // The filter name is the `name` after the BLOCK_ID and a `:` -            std::string filter_name = name.substr(block_id.to_string().size() + 1); +            block_id_t block_id(blockid); +            const auto rx_chan = _get_rx_chan(chan);              // Try to dynamic cast either the radio or the DDC to a filter_node, and call              // its filter function              auto block_ctrl = [rx_chan, block_id, chan]() -> noc_block_base::sptr { @@ -2352,11 +2356,12 @@ public:          const std::string& name, const size_t chan) override      {          try { +            const auto names        = string::split(name, ":"); +            const auto& blockid     = names.first; +            const auto& filter_name = names.second;              // The block_id_t constructor is pretty smart; let it handle the parsing. -            block_id_t block_id(name); -            auto tx_chan = _get_tx_chan(chan); -            // The filter name is the `name` after the BLOCK_ID and a `:` -            std::string filter_name = name.substr(block_id.to_string().size() + 1); +            block_id_t block_id(blockid); +            const auto tx_chan = _get_tx_chan(chan);              // Try to dynamic cast either the radio or the DUC to a filter_node, and call              // its filter function              auto block_ctrl = [tx_chan, block_id, chan]() -> noc_block_base::sptr { @@ -2393,11 +2398,12 @@ public:      {          MUX_TX_API_CALL(set_tx_filter, name, filter);          try { +            const auto names        = string::split(name, ":"); +            const auto& blockid     = names.first; +            const auto& filter_name = names.second;              // The block_id_t constructor is pretty smart; let it handle the parsing. -            block_id_t block_id(name); -            auto tx_chan = _get_tx_chan(chan); -            // The filter name is the `name` after the BLOCK_ID and a `:` -            std::string filter_name = name.substr(block_id.to_string().size() + 1); +            block_id_t block_id(blockid); +            const auto tx_chan = _get_tx_chan(chan);              // Try to dynamic cast either the radio or the DUC to a filter_node, and call              // its filter function              auto block_ctrl = [tx_chan, block_id, chan]() -> noc_block_base::sptr { diff --git a/host/python/pyuhd.cpp b/host/python/pyuhd.cpp index ca06f2d97..7022a5287 100644 --- a/host/python/pyuhd.cpp +++ b/host/python/pyuhd.cpp @@ -7,6 +7,7 @@  #include <pybind11/complex.h>  #include <pybind11/pybind11.h> +#include <pybind11/stl.h>  #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION  #include <numpy/arrayobject.h>  | 
