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);
}
|