1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
//
// Copyright 2014-2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include <uhd/convert.hpp>
#include <uhd/rfnoc/window_block_ctrl.hpp>
#include <uhd/utils/log.hpp>
using namespace uhd::rfnoc;
class window_block_ctrl_impl : public window_block_ctrl
{
public:
UHD_RFNOC_BLOCK_CONSTRUCTOR(window_block_ctrl),
_item_type("sc16"), // We only support sc16 in this block
_bpi(uhd::convert::get_bytes_per_item("sc16"))
{
_max_len = uint32_t(user_reg_read64(RB_MAX_WINDOW_LEN));
UHD_LOGGER_DEBUG(unique_id())
<< "window_block::window_block() max_len ==" << _max_len << std::endl;
UHD_ASSERT_THROW(_max_len);
// TODO we need a coercer to check that spp on the prop tree doesn't get set to
// anything invalid
_set_default_window(std::min<size_t>(get_arg<int>("spp"), _max_len));
}
//! Set window coefficients and length
void set_window(const std::vector<int>& coeffs)
{
UHD_LOGGER_TRACE(unique_id()) << "window_block::set_window()" << std::endl;
if (coeffs.size() > _max_len) {
throw uhd::value_error(
str(boost::format("window_block::set_window(): Too many window "
"coefficients! Provided %d, window allows up to %d.\n")
% coeffs.size() % _max_len));
}
size_t window_len = coeffs.size();
// Window block can take complex coefficients in sc16 format, but typical usage is
// to have real(coeffs) == imag(coeffs)
std::vector<uint32_t> coeffs_;
for (size_t i = 0; i < window_len - 1; i++) {
if (coeffs[i] > 32767 || coeffs[i] < -32768) {
throw uhd::value_error(
str(boost::format(
"window_block::set_window(): Coefficient %d "
"(index %d) outside coefficient range [-32768,32767].\n")
% coeffs[i] % i));
}
coeffs_.push_back(coeffs[i]);
}
// Write coefficients via the load bus
for (size_t i = 0; i < window_len - 1; i++) {
sr_write(AXIS_WINDOW_LOAD, coeffs_[i]);
}
// Assert tlast when sending the final coefficient (sorry, no joke here)
sr_write(AXIS_WINDOW_LOAD_TLAST, coeffs_.back());
// Set the window length
sr_write(SR_WINDOW_LEN, window_len);
// This block requires spp to match the window length:
set_arg<int>("spp", int(window_len));
}
//! Returns the maximum window length of this block.
size_t get_max_len() const
{
return _max_len;
}
size_t get_window_len() const
{
return size_t(get_arg<int>("spp"));
}
private:
const std::string _item_type;
const size_t _bpi;
size_t _max_len;
//! Default is a rectangular window
void _set_default_window(size_t window_len)
{
std::vector<int> default_coeffs(window_len, (1 << 15) - 1);
set_window(default_coeffs);
}
};
UHD_RFNOC_BLOCK_REGISTER(window_block_ctrl, "Window");
|