aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2022-01-12 14:47:54 +0100
committerAaron Rossetto <aaron.rossetto@ni.com>2022-02-04 13:16:00 -0600
commit42ff4fb7f5a3e37714f025473f95089bf1ff8c98 (patch)
tree6d70a54cd704c95149f4b2c03bf32505fe26014a /host
parent3e496cbda1d809d2ca15f69cfa231424bf47179f (diff)
downloaduhd-42ff4fb7f5a3e37714f025473f95089bf1ff8c98.tar.gz
uhd-42ff4fb7f5a3e37714f025473f95089bf1ff8c98.tar.bz2
uhd-42ff4fb7f5a3e37714f025473f95089bf1ff8c98.zip
uhd: Harmonize fuzzy frequency comparisons
Throughout UHD, we often do floating-point comparisons for frequency ranges that require resilience to floating point rounding errors. Most of the time the checks look like this: ```cpp if (fp_compare_epsilon<double>(freq) > boundary) { // ... } ``` The exception is the N320 daughterboard control, which uses a custom epsilon: ```cpp if (fp_compare_epsilon<double>(freq, RHODIUM_FREQ_COMPARE_EPSILON) > boundary) { // ... } ``` This was, for the most part, not by design, but because authors simply didn't think about which epsilon value was appropriate for the frequency comparison. This was complicated by the fact that fp_compare_epsilon previously had some issues. This patch introduces FREQ_COMPARE_EPSILON, which is a sensible default value for fp_compare_epsilon when doing frequency comparisons (note that fp_compare_delta already had such a value). Also, it introduces freq_compare_epsilon(x), which is a shorthand for fp_compare_epsilon<double>(x, FREQ_COMPARE_EPSILON). We then replace all occurrences of fp_compare_epsilon<double> which are specific to frequency checks with freq_compare_epsilon.
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/utils/math.hpp26
-rw-r--r--host/lib/usrp/dboard/e3xx/e3xx_bands.cpp36
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_bands.cpp30
-rw-r--r--host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp4
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_bands.cpp4
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_constants.hpp2
-rw-r--r--host/lib/usrp/dboard/rhodium/rhodium_cpld_ctrl.cpp4
-rw-r--r--host/lib/usrp/x300/x300_clock_ctrl.cpp6
-rw-r--r--host/tests/fp_compare_epsilon_test.cpp10
9 files changed, 79 insertions, 43 deletions
diff --git a/host/include/uhd/utils/math.hpp b/host/include/uhd/utils/math.hpp
index 6ee46e98a..c44aa4db9 100644
--- a/host/include/uhd/utils/math.hpp
+++ b/host/include/uhd/utils/math.hpp
@@ -51,6 +51,16 @@ static const double PI = 3.14159265358979323846;
static const float SINGLE_PRECISION_EPSILON = 1.19e-7f;
static const double DOUBLE_PRECISION_EPSILON = 2.22e-16;
+//! Epsilon value for when using fp_compare_epsilon to compare frequencies
+//
+// Note that this is a UHD/USRP-specific constant. In UHD, frequencies are on
+// the order of 1e9 (GHz) or below. We will declare frequencies as equal if they
+// are within a millihertz. For the purpose of
+// comparing frequencies, we "lose" 9 decimal places for the integer
+// component of the frequency, so we choose this epsilon value for floating
+// point comparison of frequencies.
+static constexpr double FREQ_COMPARE_EPSILON = 1e-12;
+
namespace fp_compare {
/*!
@@ -142,6 +152,22 @@ UHD_INLINE bool operator>(double lhs, fp_compare_epsilon<float_t> rhs);
template <typename float_t>
UHD_INLINE bool operator>=(double lhs, fp_compare_epsilon<float_t> rhs);
+//! An alias for fp_compare_epsilon, but with defaults for frequencies
+class freq_compare_epsilon : public fp_compare_epsilon<double>
+{
+public:
+ UHD_INLINE freq_compare_epsilon(double value)
+ : fp_compare_epsilon<double>(value, FREQ_COMPARE_EPSILON)
+ {
+ }
+
+ UHD_INLINE freq_compare_epsilon(const freq_compare_epsilon& copy)
+ : fp_compare_epsilon<double>(copy)
+ {
+ }
+};
+
+
} // namespace fp_compare
diff --git a/host/lib/usrp/dboard/e3xx/e3xx_bands.cpp b/host/lib/usrp/dboard/e3xx/e3xx_bands.cpp
index e28acf3b9..e9226216b 100644
--- a/host/lib/usrp/dboard/e3xx/e3xx_bands.cpp
+++ b/host/lib/usrp/dboard/e3xx/e3xx_bands.cpp
@@ -146,21 +146,21 @@ e3xx_radio_control_impl::rx_band e3xx_radio_control_impl::map_freq_to_rx_band(
{
e3xx_radio_control_impl::rx_band band;
- if (fp_compare_epsilon<double>(freq) < AD9361_RX_MIN_FREQ) {
+ if (freq_compare_epsilon(freq) < AD9361_RX_MIN_FREQ) {
band = rx_band::INVALID_BAND;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND3_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_RX_LB_BAND3_MIN_FREQ) {
band = rx_band::LB_B2;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND4_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_RX_LB_BAND4_MIN_FREQ) {
band = rx_band::LB_B3;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND5_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_RX_LB_BAND5_MIN_FREQ) {
band = rx_band::LB_B4;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND6_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_RX_LB_BAND6_MIN_FREQ) {
band = rx_band::LB_B5;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND7_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_RX_LB_BAND7_MIN_FREQ) {
band = rx_band::LB_B6;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_HB_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_RX_HB_MIN_FREQ) {
band = rx_band::LB_B7;
- } else if (fp_compare_epsilon<double>(freq) <= AD9361_RX_MAX_FREQ) {
+ } else if (freq_compare_epsilon(freq) <= AD9361_RX_MAX_FREQ) {
band = rx_band::HB;
} else {
band = rx_band::INVALID_BAND;
@@ -174,25 +174,25 @@ e3xx_radio_control_impl::tx_band e3xx_radio_control_impl::map_freq_to_tx_band(
{
e3xx_radio_control_impl::tx_band band;
- if (fp_compare_epsilon<double>(freq) < AD9361_TX_MIN_FREQ) {
+ if (freq_compare_epsilon(freq) < AD9361_TX_MIN_FREQ) {
band = tx_band::INVALID_BAND;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_160_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_TX_LB_160_MIN_FREQ) {
band = tx_band::LB_80;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_225_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_TX_LB_225_MIN_FREQ) {
band = tx_band::LB_160;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_400_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_TX_LB_400_MIN_FREQ) {
band = tx_band::LB_225;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_575_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_TX_LB_575_MIN_FREQ) {
band = tx_band::LB_400;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_1000_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_TX_LB_1000_MIN_FREQ) {
band = tx_band::LB_575;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_1700_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_TX_LB_1700_MIN_FREQ) {
band = tx_band::LB_1000;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_2750_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_TX_LB_2750_MIN_FREQ) {
band = tx_band::LB_1700;
- } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_HB_MIN_FREQ) {
+ } else if (freq_compare_epsilon(freq) < E3XX_TX_HB_MIN_FREQ) {
band = tx_band::LB_2750;
- } else if (fp_compare_epsilon<double>(freq) <= AD9361_TX_MAX_FREQ) {
+ } else if (freq_compare_epsilon(freq) <= AD9361_TX_MAX_FREQ) {
band = tx_band::HB;
} else {
band = tx_band::INVALID_BAND;
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_bands.cpp b/host/lib/usrp/dboard/magnesium/magnesium_bands.cpp
index ef72aee95..b54bf9a62 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_bands.cpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_bands.cpp
@@ -98,23 +98,23 @@ magnesium_radio_control_impl::rx_band magnesium_radio_control_impl::_map_freq_to
{
magnesium_radio_control_impl::rx_band band;
- if (fp_compare_epsilon<double>(freq) < MAGNESIUM_MIN_FREQ) {
+ if (freq_compare_epsilon(freq) < MAGNESIUM_MIN_FREQ) {
band = rx_band::INVALID_BAND;
- } else if (fp_compare_epsilon<double>(freq) < MAGNESIUM_LOWBAND_FREQ) {
+ } else if (freq_compare_epsilon(freq) < MAGNESIUM_LOWBAND_FREQ) {
band = rx_band::LOWBAND;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(1)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(1)) {
band = rx_band::BAND0;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(2)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(2)) {
band = rx_band::BAND1;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(3)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(3)) {
band = rx_band::BAND2;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(4)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(4)) {
band = rx_band::BAND3;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(5)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(5)) {
band = rx_band::BAND4;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(6)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(6)) {
band = rx_band::BAND5;
- } else if (fp_compare_epsilon<double>(freq) <= MAGNESIUM_MAX_FREQ) {
+ } else if (freq_compare_epsilon(freq) <= MAGNESIUM_MAX_FREQ) {
band = rx_band::BAND6;
} else {
band = rx_band::INVALID_BAND;
@@ -128,17 +128,17 @@ magnesium_radio_control_impl::tx_band magnesium_radio_control_impl::_map_freq_to
{
magnesium_radio_control_impl::tx_band band;
- if (fp_compare_epsilon<double>(freq) < MAGNESIUM_MIN_FREQ) {
+ if (freq_compare_epsilon(freq) < MAGNESIUM_MIN_FREQ) {
band = tx_band::INVALID_BAND;
- } else if (fp_compare_epsilon<double>(freq) < MAGNESIUM_LOWBAND_FREQ) {
+ } else if (freq_compare_epsilon(freq) < MAGNESIUM_LOWBAND_FREQ) {
band = tx_band::LOWBAND;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(1)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(1)) {
band = tx_band::BAND0;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(2)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(2)) {
band = tx_band::BAND1;
- } else if (fp_compare_epsilon<double>(freq) < band_map.at(3)) {
+ } else if (freq_compare_epsilon(freq) < band_map.at(3)) {
band = tx_band::BAND2;
- } else if (fp_compare_epsilon<double>(freq) <= MAGNESIUM_MAX_FREQ) {
+ } else if (freq_compare_epsilon(freq) <= MAGNESIUM_MAX_FREQ) {
band = tx_band::BAND3;
} else {
band = tx_band::INVALID_BAND;
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp
index 441e7b427..637d85d49 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp
@@ -299,8 +299,8 @@ void magnesium_radio_control_impl::_update_freq(
: ad9371_freq;
RFNOC_LOG_TRACE("RF freq = " << rf_freq);
- UHD_ASSERT_THROW(fp_compare_epsilon<double>(rf_freq) >= 0);
- UHD_ASSERT_THROW(fp_compare_epsilon<double>(std::abs(rf_freq - _desired_rf_freq[dir]))
+ UHD_ASSERT_THROW(freq_compare_epsilon(rf_freq) >= 0);
+ UHD_ASSERT_THROW(freq_compare_epsilon(std::abs(rf_freq - _desired_rf_freq[dir]))
<= _master_clock_rate / 2);
if (dir == RX_DIRECTION) {
radio_control_impl::set_rx_frequency(rf_freq, chan);
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_bands.cpp b/host/lib/usrp/dboard/rhodium/rhodium_bands.cpp
index 73f1bbe0c..6c16a7d7f 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_bands.cpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_bands.cpp
@@ -69,7 +69,7 @@ constexpr double RHODIUM_TX_BAND7_MIN_FREQ = 4100e6;
rhodium_radio_control_impl::rx_band rhodium_radio_control_impl::_map_freq_to_rx_band(
const double freq)
{
- auto freq_compare = fp_compare_epsilon<double>(freq, RHODIUM_FREQ_COMPARE_EPSILON);
+ const auto freq_compare = freq_compare_epsilon(freq);
if (freq_compare < RHODIUM_RX_BAND0_MIN_FREQ) {
return rx_band::RX_BAND_INVALID;
@@ -97,7 +97,7 @@ rhodium_radio_control_impl::rx_band rhodium_radio_control_impl::_map_freq_to_rx_
rhodium_radio_control_impl::tx_band rhodium_radio_control_impl::_map_freq_to_tx_band(
const double freq)
{
- auto freq_compare = fp_compare_epsilon<double>(freq, RHODIUM_FREQ_COMPARE_EPSILON);
+ const auto freq_compare = freq_compare_epsilon(freq);
if (freq_compare < RHODIUM_TX_BAND0_MIN_FREQ) {
return tx_band::TX_BAND_INVALID;
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_constants.hpp b/host/lib/usrp/dboard/rhodium/rhodium_constants.hpp
index cc6a70dc3..7043c50af 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_constants.hpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_constants.hpp
@@ -12,8 +12,6 @@
#include <string>
#include <vector>
-static constexpr double RHODIUM_FREQ_COMPARE_EPSILON = 1e-5;
-
static constexpr size_t NUM_RHODIUM_RADIO_RATES = 3;
static constexpr std::array<double, NUM_RHODIUM_RADIO_RATES> RHODIUM_RADIO_RATES = {
diff --git a/host/lib/usrp/dboard/rhodium/rhodium_cpld_ctrl.cpp b/host/lib/usrp/dboard/rhodium/rhodium_cpld_ctrl.cpp
index b95f03983..099b5d132 100644
--- a/host/lib/usrp/dboard/rhodium/rhodium_cpld_ctrl.cpp
+++ b/host/lib/usrp/dboard/rhodium/rhodium_cpld_ctrl.cpp
@@ -263,7 +263,7 @@ void rhodium_cpld_ctrl::set_rx_lo_path(const double freq, const bool defer_commi
UHD_LOG_TRACE("RH_CPLD", "Configuring RX LO filter and settings. freq=" << freq);
std::lock_guard<std::mutex> l(_set_mutex);
- auto freq_compare = fp_compare_epsilon<double>(freq, RHODIUM_FREQ_COMPARE_EPSILON);
+ const auto freq_compare = freq_compare_epsilon(freq);
if (freq_compare < RX_DEMOD_ADJ_1500OHM_THRESHOLD) {
_regs.rx_demod_adj =
@@ -296,7 +296,7 @@ void rhodium_cpld_ctrl::set_tx_lo_path(const double freq, const bool defer_commi
UHD_LOG_TRACE("RH_CPLD", "Configuring TX LO filter and settings. freq=" << freq);
std::lock_guard<std::mutex> l(_set_mutex);
- auto freq_compare = fp_compare_epsilon<double>(freq, RHODIUM_FREQ_COMPARE_EPSILON);
+ const auto freq_compare = freq_compare_epsilon(freq);
if (freq_compare < RHODIUM_LO_0_9_GHZ_LPF_THRESHOLD_FREQ) {
_regs.tx_lo_filter_sel =
diff --git a/host/lib/usrp/x300/x300_clock_ctrl.cpp b/host/lib/usrp/x300/x300_clock_ctrl.cpp
index e80335d9b..fc0094866 100644
--- a/host/lib/usrp/x300/x300_clock_ctrl.cpp
+++ b/host/lib/usrp/x300/x300_clock_ctrl.cpp
@@ -585,9 +585,11 @@ private:
} else if (math::frequencies_are_equal(_master_clock_rate, 120e6)) {
/* 10MHz reference, 120 MHz master clock rate, Zero Delay */
clocking_mode = m10M_120M_ZDEL;
- } else if (fp_compare_epsilon<double>(_master_clock_rate)
+ } else if (fp_compare_delta<double>(
+ _master_clock_rate, math::FREQ_COMPARISON_DELTA_HZ)
>= uhd::usrp::x300::MIN_TICK_RATE
- && fp_compare_epsilon<double>(_master_clock_rate)
+ && fp_compare_delta<double>(
+ _master_clock_rate, math::FREQ_COMPARISON_DELTA_HZ)
<= uhd::usrp::x300::MAX_TICK_RATE) {
/* 10MHz reference, attempt to automatically configure PLL
* for arbitrary master clock rate, Zero Delay */
diff --git a/host/tests/fp_compare_epsilon_test.cpp b/host/tests/fp_compare_epsilon_test.cpp
index 3aa973d3e..56cdd03e8 100644
--- a/host/tests/fp_compare_epsilon_test.cpp
+++ b/host/tests/fp_compare_epsilon_test.cpp
@@ -258,3 +258,13 @@ BOOST_AUTO_TEST_CASE(double_greaterthanequals_operators)
BOOST_CHECK(charlie >= alpha);
BOOST_CHECK(double(alpha._value + 3.0008) >= alpha);
}
+
+BOOST_AUTO_TEST_CASE(frequency_comparison)
+{
+ // Delta comparison
+ BOOST_CHECK(uhd::math::frequencies_are_equal(
+ 1e9, 1e9 + uhd::math::FREQ_COMPARISON_DELTA_HZ / 10));
+ // Epsilon comparison below 1 mHz
+ BOOST_CHECK(
+ freq_compare_epsilon(1e9) == (1e9 + uhd::math::FREQ_COMPARE_EPSILON / 10));
+}