1 // 2 // Copyright 2020 Ettus Research, a National Instruments Brand 3 // 4 // SPDX-License-Identifier: GPL-3.0-or-later 5 // 6 7 #include <uhd/exception.hpp> 8 #include <uhd/rfnoc/defaults.hpp> 9 #include <uhd/rfnoc/moving_average_block_control.hpp> 10 #include <uhd/rfnoc/property.hpp> 11 #include <uhd/rfnoc/registry.hpp> 12 #include <string> 13 14 using namespace uhd::rfnoc; 15 16 const uint32_t moving_average_block_control::REG_SUM_LEN_ADDR = 0; 17 const uint32_t moving_average_block_control::REG_DIVISOR_ADDR = 4; 18 19 // User property names 20 const char* const PROP_KEY_SUM_LEN = "sum_len"; 21 const char* const PROP_KEY_DIVISOR = "divisor"; 22 23 class moving_average_block_control_impl : public moving_average_block_control 24 { 25 public: RFNOC_BLOCK_CONSTRUCTOR(moving_average_block_control)26 RFNOC_BLOCK_CONSTRUCTOR(moving_average_block_control), _sum_len(10), _divisor(10) 27 { 28 _register_props(); 29 this->regs().poke32(REG_SUM_LEN_ADDR, uint8_t(_sum_len)); 30 this->regs().poke32(REG_DIVISOR_ADDR, uint32_t(_divisor)); 31 } 32 set_sum_len(const uint8_t sum_len)33 void set_sum_len(const uint8_t sum_len) 34 { 35 set_property(PROP_KEY_SUM_LEN, static_cast<int>(sum_len), res_source_info::USER); 36 } 37 get_sum_len() const38 uint8_t get_sum_len() const 39 { 40 return _sum_len; 41 } 42 set_divisor(const uint32_t divisor)43 void set_divisor(const uint32_t divisor) 44 { 45 set_property(PROP_KEY_DIVISOR, static_cast<int>(divisor), res_source_info::USER); 46 } 47 get_divisor() const48 uint32_t get_divisor() const 49 { 50 return _divisor; 51 } 52 53 private: _register_props()54 void _register_props() 55 { 56 // Register user properties 57 register_property( 58 &_prop_sum_len, [this]() { _set_sum_len(_prop_sum_len.get()); }); 59 register_property( 60 &_prop_divisor, [this]() { _set_divisor(_prop_divisor.get()); }); 61 } 62 _set_sum_len(int sum_len)63 void _set_sum_len(int sum_len) 64 { 65 // The hardware implementation requires this value to be in the range [1, 255] 66 if ((sum_len < 1) || (sum_len > 255)) { 67 throw uhd::value_error( 68 "Attempting to set Moving Average Block sum length to invalid value!"); 69 } 70 // The hardware implementation causes this noc block to clear the fifo when a 71 // register write occurs to the sum length. This value should only be written if 72 // the value actually changes. 73 if (sum_len != _sum_len) { 74 _sum_len = sum_len; 75 this->regs().poke32(REG_SUM_LEN_ADDR, uint8_t(_sum_len)); 76 } 77 } 78 _set_divisor(int divisor)79 void _set_divisor(int divisor) 80 { 81 // The hardware implementation requires this value to be in the range [1, 2^24-1] 82 if ((divisor < 1) || (divisor > (1 << 24) - 1)) { 83 throw uhd::value_error( 84 "Attempting to set Moving Average Block divisor to invalid value!"); 85 } 86 _divisor = divisor; 87 this->regs().poke32(REG_DIVISOR_ADDR, uint32_t(_divisor)); 88 } 89 90 /************************************************************************** 91 * Attributes 92 *************************************************************************/ 93 property_t<int> _prop_sum_len = 94 property_t<int>{PROP_KEY_SUM_LEN, 10, {res_source_info::USER}}; 95 property_t<int> _prop_divisor = 96 property_t<int>{PROP_KEY_DIVISOR, 10, {res_source_info::USER}}; 97 98 uint8_t _sum_len; 99 uint32_t _divisor; 100 }; 101 102 UHD_RFNOC_BLOCK_REGISTER_DIRECT(moving_average_block_control, 103 MOVING_AVERAGE_BLOCK, 104 "MovingAverage", 105 CLOCK_KEY_GRAPH, 106 "bus_clk") 107