aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.cpp2
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.cpp12
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_ad9371_iface.hpp5
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_constants.hpp3
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp139
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_control.hpp21
-rw-r--r--host/lib/usrp/multi_usrp_rfnoc.cpp38
-rw-r--r--host/python/pyuhd.cpp1
-rw-r--r--mpm/include/mpm/ad937x/ad937x_ctrl.hpp2
-rw-r--r--mpm/lib/mykonos/ad937x_ctrl.cpp9
-rw-r--r--mpm/lib/mykonos/ad937x_device.cpp71
-rw-r--r--mpm/lib/mykonos/ad937x_device.hpp7
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/magnesium.py9
-rw-r--r--mpm/python/usrp_mpm/rpc_server.py2
14 files changed, 284 insertions, 37 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>
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 "