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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
//
// Copyright 2020 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include <uhd/cal/pwr_cal.hpp>
#include <uhd/exception.hpp>
#include <boost/test/unit_test.hpp>
#include <iostream>
using namespace uhd::usrp::cal;
BOOST_AUTO_TEST_CASE(test_pwr_cal_api)
{
const std::string name = "Mock Gain/Power Data";
const std::string serial = "ABC1234";
const uint64_t timestamp = 0x12340000;
auto gain_power_data = pwr_cal::make(name, serial, timestamp);
BOOST_CHECK_EQUAL(gain_power_data->get_name(), name);
BOOST_CHECK_EQUAL(gain_power_data->get_serial(), serial);
BOOST_CHECK_EQUAL(gain_power_data->get_timestamp(), timestamp);
constexpr int NEW_TEMP = 25;
gain_power_data->set_temperature(NEW_TEMP);
BOOST_CHECK_EQUAL(gain_power_data->get_temperature(), NEW_TEMP);
// Write a table...
gain_power_data->add_power_table({{0.0, -30.0}, {10.0, -20.0}}, -40.0, -10.0, 1e9);
// ...read it back...
BOOST_CHECK_EQUAL(gain_power_data->get_power(0.0, 1e9), -30.0);
BOOST_CHECK_EQUAL(gain_power_data->get_power(10.0, 1e9), -20.0);
// ...and make sure any other index will do the same
BOOST_CHECK_EQUAL(gain_power_data->get_power(47.2, 23e6), -20.0);
// Let's say power goes down 10 dB per octave
gain_power_data->add_power_table({{0.0, -40.0}, {10.0, -30.0}}, -40.0, -10.0, 2e9);
// Do uninterpolated readbacks again
BOOST_CHECK_EQUAL(gain_power_data->get_power(10.0, 1e9), -20.0);
BOOST_CHECK_EQUAL(gain_power_data->get_power(47.2, 23e6), -20.0);
// Now interpolate
BOOST_CHECK_CLOSE(gain_power_data->get_power(5.0, 1.5e9), -30.0, 1e-6);
// Some ref gain checks
BOOST_CHECK_EQUAL(gain_power_data->get_ref_gain(), 0.0);
gain_power_data->set_ref_gain(5.0);
BOOST_CHECK_EQUAL(gain_power_data->get_ref_gain(), 5.0);
// Clear, make sure the container doesn't work anymore, and add the value
// back for future tests
gain_power_data->clear();
BOOST_REQUIRE_THROW(gain_power_data->get_power(47.2, 23e6), uhd::exception);
gain_power_data->add_power_table({{10.0, -20.0}}, -20.0, -20.0, 1e9);
constexpr int ROOM_TEMP = 20;
gain_power_data->set_temperature(ROOM_TEMP);
BOOST_CHECK_EQUAL(gain_power_data->get_temperature(), ROOM_TEMP);
// Shouldn't change anything yet
BOOST_CHECK_EQUAL(gain_power_data->get_power(10.0, 1e9), -20.0);
// Power shall go down 5 dB at this new temperature (whoa)
gain_power_data->add_power_table({{10.0, -25.0}}, -20.0, -20.0, 1e9);
BOOST_CHECK_EQUAL(gain_power_data->get_power(10.0, 1e9), -25.0);
// And if we have to interpolate, temp compensation uses NN:
BOOST_CHECK_EQUAL(gain_power_data->get_power(10.0, 1e9, 21), -25.0);
// Now clear, then add a more useful data set. We can stay at ROOM_TEMP.
gain_power_data->clear();
constexpr double power_offset = -20.0; // 0 dB shall map to -20 dBm
constexpr double lin_error = 0.1; // The linearization error shall increase by 0.1
// dB per dB gain
constexpr double ref_freq = 1e9;
std::map<double, double> test_gain_power;
constexpr double max_gain = 10.0;
for (double gain = 0.0; gain <= max_gain; gain += 1.0) {
test_gain_power[gain] = gain + power_offset + lin_error * gain;
}
const double min_power = test_gain_power.cbegin()->second;
const double max_power = test_gain_power.crbegin()->second;
gain_power_data->add_power_table(test_gain_power, min_power, max_power, ref_freq);
// Quick check
BOOST_CHECK_EQUAL(gain_power_data->get_power(0.0, ref_freq), power_offset);
const std::pair<double, double> expected_limits{min_power, max_power};
const auto limits = gain_power_data->get_power_limits(ref_freq);
BOOST_CHECK_EQUAL(limits.start(), min_power);
BOOST_CHECK_EQUAL(limits.stop(), max_power);
BOOST_CHECK_CLOSE(gain_power_data->get_gain(-20.0, ref_freq), 0.0, 1e-6);
BOOST_CHECK_CLOSE(
gain_power_data->get_gain(test_gain_power.crbegin()->second, ref_freq),
test_gain_power.crbegin()->first,
1e-6);
BOOST_CHECK_CLOSE(gain_power_data->get_gain(-19.0, ref_freq), 1/1.1, 1e-6);
}
BOOST_AUTO_TEST_CASE(test_pwr_cal_api_irreg)
{
const std::string name = "Mock Gain/Power Data";
const std::string serial = "ABC1234";
const uint64_t timestamp = 0x12340000;
auto gain_power_data = pwr_cal::make(name, serial, timestamp);
constexpr int ROOM_TEMP = 20;
gain_power_data->set_temperature(ROOM_TEMP);
constexpr double MIN_POWER = -40;
constexpr double MAX_POWER = -10;
// Write a table...
gain_power_data->add_power_table(
{{0.0, -30.0}, {10.0, -20.0}}, MIN_POWER, MAX_POWER, 1e9);
// Let's say power goes down 10 dB per octave
gain_power_data->add_power_table(
{{0.0, -40.0}, {10.0, -30.0}}, MIN_POWER, MAX_POWER, 2e9);
// Interpolated readback:
BOOST_CHECK_CLOSE(gain_power_data->get_power(5.0, 1.5e9), -30.0, 1e-6);
BOOST_CHECK_CLOSE(gain_power_data->get_gain(-30.0, 1.5e9), 5.0, 0.1);
}
BOOST_AUTO_TEST_CASE(test_pwr_cal_serdes)
{
const std::string name = "Mock Gain/Power Data";
const std::string serial = "ABC1234";
const uint64_t timestamp = 0x12340000;
auto gain_power_data_blueprint = pwr_cal::make(name, serial, timestamp);
constexpr double power_offset = -20.0;
constexpr double lin_error = 0.1;
constexpr double ref_freq = 1e9;
std::map<double, double> test_gain_power;
for (double gain = 0.0; gain < 10.0; gain += 1.0) {
test_gain_power[gain] = gain + power_offset + lin_error * gain;
}
const double min_power = test_gain_power[0.0];
const double max_power = test_gain_power[9.0];
gain_power_data_blueprint->add_power_table(
test_gain_power, min_power, max_power, ref_freq);
const auto serialized = gain_power_data_blueprint->serialize();
auto pwr_cal_data = container::make<pwr_cal>(serialized);
BOOST_CHECK_EQUAL(pwr_cal_data->get_name(), name);
BOOST_CHECK_EQUAL(pwr_cal_data->get_serial(), serial);
BOOST_CHECK_EQUAL(pwr_cal_data->get_timestamp(), timestamp);
for (auto& gp : test_gain_power) {
BOOST_CHECK_EQUAL(
pwr_cal_data->get_power(gp.first, ref_freq),
gp.second);
}
}
BOOST_AUTO_TEST_CASE(test_pwr_cal_des_fail)
{
std::vector<uint8_t> not_actual_data(42, 23);
BOOST_REQUIRE_THROW(container::make<pwr_cal>(not_actual_data), uhd::runtime_error);
}
|