From 11d70898d15fe9c42e191c166581d83c62354ca1 Mon Sep 17 00:00:00 2001 From: Aaron Rossetto Date: Fri, 13 Mar 2020 10:53:43 -0500 Subject: rfnoc: Add FIR filter RFNoC block controller --- host/lib/rfnoc/CMakeLists.txt | 1 + host/lib/rfnoc/fir_filter_block_control.cpp | 101 ++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 host/lib/rfnoc/fir_filter_block_control.cpp (limited to 'host/lib/rfnoc') 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 +#include +#include +#include +#include + +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::max(); + _program_coefficients(); + } + + size_t get_max_num_coefficients() const + { + return _max_num_coeffs; + } + + void set_coefficients(const std::vector& 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 get_coefficients() const + { + return _coeffs; + } + +private: + void _program_coefficients() + { + // Write coefficients [0..num_coeffs-2].. + std::vector coeffs_addr(_max_num_coeffs - 1, REG_FIR_LOAD_COEFF_ADDR); + std::vector 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(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 _coeffs; + + /************************************************************************** + * Attributes + *************************************************************************/ + property_t _prop_type_in = property_t{ + PROP_KEY_TYPE, IO_TYPE_SC16, {res_source_info::INPUT_EDGE}}; + property_t _prop_type_out = property_t{ + 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") -- cgit v1.2.3