diff options
author | mattprost <matt.prost@ni.com> | 2021-12-16 13:48:26 -0600 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2022-04-07 13:28:02 -0700 |
commit | b8acf58798018f5fb4d84d470badadce5dd3a08d (patch) | |
tree | 137db7eeff0d3bbc202b228fd4bee4f143b1b467 /mpm | |
parent | a8ad4917d331258e163e1786c0325a4b7e7d2e3e (diff) | |
download | uhd-b8acf58798018f5fb4d84d470badadce5dd3a08d.tar.gz uhd-b8acf58798018f5fb4d84d470badadce5dd3a08d.tar.bz2 uhd-b8acf58798018f5fb4d84d470badadce5dd3a08d.zip |
n310: Add Filter API to n310
Add the Filter API to n3xx specifically for the AD937x device. The TX
filter is limited to 32 taps, and the RX filter is limited to 48 taps.
This feature requires MPM version 4.2 or later on the device.
Co-authored-by: bpadalino <bpadalino@gmail.com>
Signed-off-by: mattprost <matt.prost@ni.com>
Diffstat (limited to 'mpm')
-rw-r--r-- | mpm/include/mpm/ad937x/ad937x_ctrl.hpp | 2 | ||||
-rw-r--r-- | mpm/lib/mykonos/ad937x_ctrl.cpp | 9 | ||||
-rw-r--r-- | mpm/lib/mykonos/ad937x_device.cpp | 71 | ||||
-rw-r--r-- | mpm/lib/mykonos/ad937x_device.hpp | 7 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/magnesium.py | 9 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/rpc_server.py | 2 |
6 files changed, 81 insertions, 19 deletions
diff --git a/mpm/include/mpm/ad937x/ad937x_ctrl.hpp b/mpm/include/mpm/ad937x/ad937x_ctrl.hpp index 936655405..57840b9f3 100644 --- a/mpm/include/mpm/ad937x/ad937x_ctrl.hpp +++ b/mpm/include/mpm/ad937x/ad937x_ctrl.hpp @@ -259,7 +259,7 @@ public: const std::string& which, const int8_t gain, const std::vector<int16_t>& fir) = 0; //! get the FIR filter for the frontend which - virtual std::vector<int16_t> get_fir(const std::string& which, int8_t& gain) = 0; + virtual std::pair<int8_t, std::vector<int16_t>> get_fir(const std::string& which) = 0; // TODO: update docstring with temperature unit and calibration information //! get the device temperature diff --git a/mpm/lib/mykonos/ad937x_ctrl.cpp b/mpm/lib/mykonos/ad937x_ctrl.cpp index 7cd5c1d98..2a4bfbc87 100644 --- a/mpm/lib/mykonos/ad937x_ctrl.cpp +++ b/mpm/lib/mykonos/ad937x_ctrl.cpp @@ -430,7 +430,6 @@ public: virtual void set_fir( const std::string& which, const int8_t gain, const std::vector<int16_t>& fir) { - const auto dir = _get_direction_from_antenna(which); const auto lengths = _get_valid_fir_lengths(which); if (std::find(lengths.begin(), lengths.end(), fir.size()) == lengths.end()) { @@ -438,15 +437,13 @@ public: } std::lock_guard<std::mutex> lock(*spi_mutex); - device.set_fir(dir, gain, fir); + device.set_fir(which, gain, fir); } - virtual std::vector<int16_t> get_fir(const std::string& which, int8_t& gain) + virtual std::pair<int8_t, std::vector<int16_t>> get_fir(const std::string& which) { - auto dir = _get_direction_from_antenna(which); - std::lock_guard<std::mutex> lock(*spi_mutex); - return device.get_fir(dir, gain); + return device.get_fir(which); } virtual int16_t get_temperature() diff --git a/mpm/lib/mykonos/ad937x_device.cpp b/mpm/lib/mykonos/ad937x_device.cpp index fba065983..1a1905004 100644 --- a/mpm/lib/mykonos/ad937x_device.cpp +++ b/mpm/lib/mykonos/ad937x_device.cpp @@ -10,6 +10,7 @@ #include "adi/mykonos_gpio.h" #include "config/ad937x_config_t.hpp" #include "config/ad937x_default_config.hpp" +#include "mpm/ad937x/ad937x_ctrl.hpp" #include <uhd/utils/algorithm.hpp> #include <boost/format.hpp> #include <cmath> @@ -20,6 +21,7 @@ using namespace mpm::ad937x::device; using namespace mpm::ad937x::gpio; +using namespace mpm::chips; using namespace uhd; const double ad937x_device::MIN_FREQ = 300e6; @@ -59,6 +61,20 @@ static constexpr double AD9371_TX_DAC_FILT_MAX_CORNER = 187.0e6; // Hz static const uint32_t PLL_LOCK_TIMEOUT_MS = 200; +const std::map<std::string, mykonosfirName_t> ad937x_device::_tx_filter_map{ + {"TX1_FIR", TX1_FIR}, + {"TX2_FIR", TX2_FIR}, + {"TX1TX2_FIR", TX1TX2_FIR}, +}; + +const std::map<std::string, mykonosfirName_t> ad937x_device::_rx_filter_map{ + {"RX1_FIR", RX1_FIR}, + {"RX2_FIR", RX2_FIR}, + {"RX1RX2_FIR", RX1RX2_FIR}, + {"OBSRX_A_FIR", OBSRX_A_FIR}, + {"OBSRX_B_FIR", OBSRX_B_FIR}, +}; + // Amount of time to average samples for RX DC offset // A larger averaging window will result in: // Longer latency to correct DC offset changes @@ -667,6 +683,28 @@ void ad937x_device::set_agc_mode(const direction_t direction, const gain_mode_t } void ad937x_device::set_fir( + const std::string& name, int8_t gain, const std::vector<int16_t>& fir) +{ + mykonosfirName_t filter_name; + if (_rx_filter_map.count(name) == 1) { + filter_name = _rx_filter_map.at(name); + mykonos_config.rx_fir_config.set_fir(gain, fir); + } else if (_tx_filter_map.count(name) == 1) { + filter_name = _tx_filter_map.at(name); + mykonos_config.tx_fir_config.set_fir(gain, fir); + } else { + throw mpm::runtime_error("set_fir invalid name: " + name); + } + mykonosFir_t filter{.gain_dB = gain, + .numFirCoefs = static_cast<uint8_t>(fir.size()), + .coefs = const_cast<int16_t*>(fir.data())}; + const auto state = _move_to_config_state(); + CALL_API(MYKONOS_programFir(mykonos_config.device, filter_name, &filter)); + _restore_from_config_state(state); +} + + +void ad937x_device::set_fir( const direction_t direction, int8_t gain, const std::vector<int16_t>& fir) { switch (direction) { @@ -679,8 +717,13 @@ void ad937x_device::set_fir( default: MPM_THROW_INVALID_CODE_PATH(); } - - // TODO: reload this on device + mykonosfirName_t filter_name = (direction == TX_DIRECTION) ? TX1TX2_FIR : RX1RX2_FIR; + mykonosFir_t filter{.gain_dB = gain, + .numFirCoefs = static_cast<uint8_t>(fir.size()), + .coefs = const_cast<int16_t*>(fir.data())}; + const auto state = _move_to_config_state(); + CALL_API(MYKONOS_programFir(mykonos_config.device, filter_name, &filter)); + _restore_from_config_state(state); } void ad937x_device::set_gain_pin_step_sizes(const direction_t direction, @@ -795,16 +838,24 @@ double ad937x_device::get_gain(const direction_t direction, const chain_t chain) } } -std::vector<int16_t> ad937x_device::get_fir(const direction_t direction, int8_t& gain) +std::pair<int8_t, std::vector<int16_t>> ad937x_device::get_fir(const std::string& name) { - switch (direction) { - case TX_DIRECTION: - return mykonos_config.tx_fir_config.get_fir(gain); - case RX_DIRECTION: - return mykonos_config.rx_fir_config.get_fir(gain); - default: - MPM_THROW_INVALID_CODE_PATH(); + mykonosfirName_t filter_name; + if (_rx_filter_map.count(name) == 1) { + filter_name = _rx_filter_map.at(name); + } else if (_tx_filter_map.count(name) == 1) { + filter_name = _tx_filter_map.at(name); + } else { + throw mpm::runtime_error("get_fir invalid name: " + name); } + mykonosFir_t fir; + std::vector<int16_t> rv(96, 0); + fir.coefs = rv.data(); + const auto state = _move_to_config_state(); + CALL_API(MYKONOS_readFir(mykonos_config.device, filter_name, &fir)); + _restore_from_config_state(state); + rv.resize(fir.numFirCoefs); + return std::pair<int8_t, std::vector<int16_t>>(fir.gain_dB, rv); } int16_t ad937x_device::get_temperature() diff --git a/mpm/lib/mykonos/ad937x_device.hpp b/mpm/lib/mykonos/ad937x_device.hpp index 8ee77db54..4b4503eb3 100644 --- a/mpm/lib/mykonos/ad937x_device.hpp +++ b/mpm/lib/mykonos/ad937x_device.hpp @@ -20,6 +20,7 @@ #include <boost/filesystem.hpp> #include <boost/noncopyable.hpp> #include <functional> +#include <map> #include <memory> class ad937x_device : public boost::noncopyable @@ -82,9 +83,10 @@ public: bool get_pll_lock_status(const uint8_t pll, const bool wait_for_lock = false); + void set_fir(const std::string& name, int8_t gain, const std::vector<int16_t>& fir); void set_fir( const uhd::direction_t direction, int8_t gain, const std::vector<int16_t>& fir); - std::vector<int16_t> get_fir(const uhd::direction_t direction, int8_t& gain); + std::pair<int8_t, std::vector<int16_t>> get_fir(const std::string& name); int16_t get_temperature(); @@ -136,4 +138,7 @@ private: static double _convert_rx_gain_from_mykonos(const uint8_t gain); static uint16_t _convert_tx_gain_to_mykonos(const double gain); static double _convert_tx_gain_from_mykonos(const uint16_t gain); + + const static std::map<std::string, mykonosfirName_t> _tx_filter_map; + const static std::map<std::string, mykonosfirName_t> _rx_filter_map; }; diff --git a/mpm/python/usrp_mpm/dboard_manager/magnesium.py b/mpm/python/usrp_mpm/dboard_manager/magnesium.py index d5cc525dc..1ffbc6f16 100644 --- a/mpm/python/usrp_mpm/dboard_manager/magnesium.py +++ b/mpm/python/usrp_mpm/dboard_manager/magnesium.py @@ -493,6 +493,15 @@ class Magnesium(BfrfsEEPROM, DboardManagerBase): self._reinit(self.master_clock_rate) return bw + def set_fir(self, name, gain, coeffs): + self.log.debug("ad9371 set_fir name: {} gain: {} coeffs: {}".format(name, gain, coeffs)) + self.mykonos.set_fir(name, gain, coeffs) + return + + def get_fir(self, name): + self.log.debug("ad9371 get_fir name: {}".format(name)) + return self.mykonos.get_fir(name) + ########################################################################## # Debug ########################################################################## diff --git a/mpm/python/usrp_mpm/rpc_server.py b/mpm/python/usrp_mpm/rpc_server.py index 78b76ab19..c0779ab77 100644 --- a/mpm/python/usrp_mpm/rpc_server.py +++ b/mpm/python/usrp_mpm/rpc_server.py @@ -32,7 +32,7 @@ from usrp_mpm.sys_utils import net TIMEOUT_INTERVAL = 5.0 # Seconds before claim expires (default value) TOKEN_LEN = 16 # Length of the token string # Compatibility number for MPM -MPM_COMPAT_NUM = (4, 1) +MPM_COMPAT_NUM = (4, 2) def no_claim(func): " Decorator for functions that require no token check " |