diff options
author | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-03-13 10:53:43 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-04-07 14:20:14 -0500 |
commit | 11d70898d15fe9c42e191c166581d83c62354ca1 (patch) | |
tree | ca47e66c07e628e8f8b517a763b190807573853a /host/lib | |
parent | 76aaf0f55788a4d2c7adeea65a9205340421ca49 (diff) | |
download | uhd-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.txt | 1 | ||||
-rw-r--r-- | host/lib/rfnoc/fir_filter_block_control.cpp | 101 |
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") |