aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorAaron Rossetto <aaron.rossetto@ni.com>2020-03-13 10:53:43 -0500
committerAaron Rossetto <aaron.rossetto@ni.com>2020-04-07 14:20:14 -0500
commit11d70898d15fe9c42e191c166581d83c62354ca1 (patch)
treeca47e66c07e628e8f8b517a763b190807573853a /host/lib
parent76aaf0f55788a4d2c7adeea65a9205340421ca49 (diff)
downloaduhd-11d70898d15fe9c42e191c166581d83c62354ca1.tar.gz
uhd-11d70898d15fe9c42e191c166581d83c62354ca1.tar.bz2
uhd-11d70898d15fe9c42e191c166581d83c62354ca1.zip
rfnoc: Add FIR filter RFNoC block controller
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/rfnoc/CMakeLists.txt1
-rw-r--r--host/lib/rfnoc/fir_filter_block_control.cpp101
2 files changed, 102 insertions, 0 deletions
diff --git a/host/lib/rfnoc/CMakeLists.txt b/host/lib/rfnoc/CMakeLists.txt
index ea774b2c8..4edfe4009 100644
--- a/host/lib/rfnoc/CMakeLists.txt
+++ b/host/lib/rfnoc/CMakeLists.txt
@@ -45,6 +45,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/duc_block_control.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dmafifo_block_control.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fft_block_control.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/fir_filter_block_control.cpp
${CMAKE_CURRENT_SOURCE_DIR}/null_block_control.cpp
${CMAKE_CURRENT_SOURCE_DIR}/radio_control_impl.cpp
)
diff --git a/host/lib/rfnoc/fir_filter_block_control.cpp b/host/lib/rfnoc/fir_filter_block_control.cpp
new file mode 100644
index 000000000..38a0e4b9c
--- /dev/null
+++ b/host/lib/rfnoc/fir_filter_block_control.cpp
@@ -0,0 +1,101 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/exception.hpp>
+#include <uhd/rfnoc/defaults.hpp>
+#include <uhd/rfnoc/fir_filter_block_control.hpp>
+#include <uhd/rfnoc/property.hpp>
+#include <uhd/rfnoc/registry.hpp>
+
+using namespace uhd::rfnoc;
+
+const uint32_t fir_filter_block_control::REG_FIR_MAX_NUM_COEFFS_ADDR = 0;
+const uint32_t fir_filter_block_control::REG_FIR_LOAD_COEFF_ADDR = 4;
+const uint32_t fir_filter_block_control::REG_FIR_LOAD_COEFF_LAST_ADDR = 8;
+
+class fir_filter_block_control_impl : public fir_filter_block_control
+{
+public:
+ RFNOC_BLOCK_CONSTRUCTOR(fir_filter_block_control)
+ , _max_num_coeffs(this->regs().peek32(REG_FIR_MAX_NUM_COEFFS_ADDR)),
+ _coeffs(_max_num_coeffs, int16_t(0))
+ {
+ // register edge properties
+ register_property(&_prop_type_in);
+ register_property(&_prop_type_out);
+
+ // add resolvers for type (keeps it constant)
+ add_property_resolver({&_prop_type_in}, {&_prop_type_in}, [this]() {
+ _prop_type_in.set(IO_TYPE_SC16);
+ });
+ add_property_resolver({&_prop_type_out}, {&_prop_type_out}, [this]() {
+ _prop_type_out.set(IO_TYPE_SC16);
+ });
+
+ // initialize hardware with an impulse response
+ _coeffs[0] = std::numeric_limits<int16_t>::max();
+ _program_coefficients();
+ }
+
+ size_t get_max_num_coefficients() const
+ {
+ return _max_num_coeffs;
+ }
+
+ void set_coefficients(const std::vector<int16_t>& coeffs)
+ {
+ if (coeffs.size() > _max_num_coeffs) {
+ std::string error_msg =
+ "Too many filter coefficients specified (max " +
+ std::to_string(_max_num_coeffs) + ")";
+ throw uhd::value_error(error_msg);
+ }
+
+ // save the new coefficients...
+ _coeffs = coeffs;
+ // ...and expand it to the number supported by the hardware,
+ // padding with zeroes
+ _coeffs.resize(_max_num_coeffs, 0);
+ _program_coefficients();
+ }
+
+ std::vector<int16_t> get_coefficients() const
+ {
+ return _coeffs;
+ }
+
+private:
+ void _program_coefficients()
+ {
+ // Write coefficients [0..num_coeffs-2]..
+ std::vector<uint32_t> coeffs_addr(_max_num_coeffs - 1, REG_FIR_LOAD_COEFF_ADDR);
+ std::vector<uint32_t> coeffs_minus_last(_max_num_coeffs - 1);
+ std::transform(_coeffs.begin(), _coeffs.end() - 1, coeffs_minus_last.begin(),
+ [this](int16_t value) -> uint32_t { return static_cast<uint32_t>(value); });
+
+ this->regs().multi_poke32(coeffs_addr, coeffs_minus_last);
+ // ...and the final coefficients (num_coeffs-1)
+ this->regs().poke32(
+ REG_FIR_LOAD_COEFF_LAST_ADDR, _coeffs.at(_max_num_coeffs - 1));
+ }
+
+ //! Number of coefficients supported by the FIR filter
+ const size_t _max_num_coeffs;
+
+ //! Current FIR filter coefficients
+ std::vector<int16_t> _coeffs;
+
+ /**************************************************************************
+ * Attributes
+ *************************************************************************/
+ property_t<std::string> _prop_type_in = property_t<std::string>{
+ PROP_KEY_TYPE, IO_TYPE_SC16, {res_source_info::INPUT_EDGE}};
+ property_t<std::string> _prop_type_out = property_t<std::string>{
+ PROP_KEY_TYPE, IO_TYPE_SC16, {res_source_info::OUTPUT_EDGE}};
+};
+
+UHD_RFNOC_BLOCK_REGISTER_DIRECT(
+ fir_filter_block_control, FIR_FILTER_BLOCK, "FIR", CLOCK_KEY_GRAPH, "bus_clk")