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