aboutsummaryrefslogtreecommitdiffstats
path: root/host/include
diff options
context:
space:
mode:
Diffstat (limited to 'host/include')
-rw-r--r--host/include/uhd/cal/CMakeLists.txt5
-rw-r--r--host/include/uhd/cal/pwr_cal.fbs46
-rw-r--r--host/include/uhd/cal/pwr_cal.hpp151
-rw-r--r--host/include/uhd/cal/pwr_cal_generated.h340
4 files changed, 541 insertions, 1 deletions
diff --git a/host/include/uhd/cal/CMakeLists.txt b/host/include/uhd/cal/CMakeLists.txt
index 8d8dfa11e..38b4885ef 100644
--- a/host/include/uhd/cal/CMakeLists.txt
+++ b/host/include/uhd/cal/CMakeLists.txt
@@ -5,16 +5,19 @@
#
UHD_INSTALL(FILES
- database.hpp
container.hpp
+ database.hpp
iq_cal.hpp
+ pwr_cal.hpp
iq_cal_generated.h
+ pwr_cal_generated.h
DESTINATION ${INCLUDE_DIR}/uhd/cal
COMPONENT headers
)
UHD_INSTALL(FILES
iq_cal.fbs
+ pwr_cal.fbs
DESTINATION ${PKG_DATA_DIR}/cal
COMPONENT headers
)
diff --git a/host/include/uhd/cal/pwr_cal.fbs b/host/include/uhd/cal/pwr_cal.fbs
new file mode 100644
index 000000000..7cf66feee
--- /dev/null
+++ b/host/include/uhd/cal/pwr_cal.fbs
@@ -0,0 +1,46 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+// Calibration Table for power calibration coefficents.
+// See also pwr_cal.hpp
+
+include "cal_metadata.fbs";
+
+namespace uhd.usrp.cal;
+
+// Maps a gain value (dB) to a power value (dBm)
+struct PowerMap
+{
+ gain: double (key);
+ power_dbm: double;
+}
+
+// For a given frequency, stores all gain -> power measurements, as well as a
+// max and min power level the device can reasonably produce.
+table FreqPowerMap
+{
+ freq: ulong (key);
+ powers: [PowerMap];
+ min_power: double; // Minimum power achievable at this frequency
+ max_power: double; // Maximum power achievable at this frequency
+}
+
+// Given a temperature, store a gain table
+table TempFreqMap
+{
+ temperature: int (key); // Temperature in C
+ freqs: [FreqPowerMap];
+}
+
+table PowerCal
+{
+ metadata: Metadata;
+ temp_freq_map: [TempFreqMap];
+ ref_gain: int = -1;
+}
+
+root_type PowerCal;
+file_identifier "dB/m"; // dB per dBm
diff --git a/host/include/uhd/cal/pwr_cal.hpp b/host/include/uhd/cal/pwr_cal.hpp
new file mode 100644
index 000000000..b30c6dfc2
--- /dev/null
+++ b/host/include/uhd/cal/pwr_cal.hpp
@@ -0,0 +1,151 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#pragma once
+
+#include <uhd/cal/container.hpp>
+#include <uhd/config.hpp>
+#include <uhd/types/ranges.hpp>
+#include <boost/optional.hpp>
+#include <map>
+
+namespace uhd { namespace usrp { namespace cal {
+
+/*! Class that stores power levels (in dBm) at various gains, frequencies, and
+ * temperatures.
+ *
+ * This container class is suitable for all cases where devices want to store a
+ * gain-to-power mapping from a single, overall gain value.
+ *
+ * The underlying data structure stores the power level for every gain/frequency
+ * point that is part of this data set. It can also do a reverse look-up of gain
+ * values for a given power value.
+ *
+ * The interpolation algorithms assume a monotonic gain/power profile, i.e.,
+ * f(gain) = power is monotonically increasing. If the power is not monotonically
+ * increasing, the interpolation algorithms still work, but get_gain() might
+ * produce a greater than necessary interpolation error. For that case, this
+ * class provides get_gain_coerced(), which helps with both coercion of the
+ * interpolated gain into a gain value that can be used at the call site, as
+ * well as minimizing the effect on the application using this container.
+ *
+ * All interpolation algorithms first interpolate temperature by finding the
+ * nearest available temperature data. For example, if the data set includes
+ * calibration data for 40C and 50C, and the actual temperature is measured at
+ * 48C, then the data set for 50C is used, and the data set for 40C is not
+ * considered at all.
+ * Within a data set, frequency and gain are interpolated in two dimensions (the
+ * same is true for frequency and power for get_gain() and get_gain_coerced())
+ * using a bilinear interpolation.
+ */
+class UHD_API pwr_cal : public container
+{
+public:
+ using sptr = std::shared_ptr<pwr_cal>;
+
+ /*! Add or update a power level data point
+ *
+ * Note: Power measurements can only be written atomically. It is not
+ * possible to add individual gain/power points using this method.
+ *
+ * \param gain_power_map A mapping gain -> power (dB -> dBm) for all
+ * measured gain points for this frequency.
+ * \param max_power The maximum available power for this frequency.
+ * \param min_power The minimum available power for this frequency.
+ * \param freq The frequency at which this power level was measured
+ * \param temperature The temperature at which this power level was measured,
+ * in Celsius. This parameter is optional, the return
+ * value for get_temperature() is used if no temperature
+ * is provided here.
+ */
+ virtual void add_power_table(const std::map<double, double>& gain_power_map,
+ const double max_power,
+ const double min_power,
+ const double freq,
+ const boost::optional<int> temperature = boost::none) = 0;
+
+ /*! Clear all stored values
+ *
+ * Note: All of the getters will throw a uhd::assertion_error if called after
+ * clearing the data.
+ */
+ virtual void clear() = 0;
+
+ /*! Set the current default temperature
+ *
+ * Some of the API calls have a optional temperature argument. However, in
+ * practice, it is often useful to set an ambient temperature once, or only
+ * when it has changed, and then use a default temperature instead of
+ * providing the temperature on every call. This sets the default
+ * temperature.
+ */
+ virtual void set_temperature(const int temperature) = 0;
+
+ //! Return the current default temperature
+ virtual int get_temperature() const = 0;
+
+ /*! Set the reference gain point, i.e., the gain value where by definition
+ * the difference between linearized power and measured power is zero.
+ *
+ * Currently unused.
+ */
+ virtual void set_ref_gain(const double gain) = 0;
+
+ /*! Return the current reference gain point.
+ *
+ * Currently unused.
+ */
+ virtual double get_ref_gain() const = 0;
+
+ /*! Return the min and max power available for this frequency
+ */
+ virtual uhd::meta_range_t get_power_limits(const double freq,
+ const boost::optional<int> temperature = boost::none) const = 0;
+
+ /*! Returns the power at a gain value.
+ *
+ * This will interpolate from the given data set to obtain a power value if
+ * gain and frequency are not exactly within the given data set.
+ *
+ * \param gain The gain at which we are checking the power
+ * \param freq The frequency at which we are checking the power
+ * \param temperature The temperature at which we are checking the power. If
+ * none is given, uses the current default temperature
+ * (see set_temperature()).
+ */
+ virtual double get_power(const double gain,
+ const double freq,
+ const boost::optional<int> temperature = boost::none) const = 0;
+
+ /*! Look up a gain value from a power value.
+ *
+ * This is the reverse function to get_power(). Like get_power(), it will
+ * interpolate in two dimensions (linearly) if the requested power value is
+ * not part of the measurement data.
+ *
+ * Note: \p power_dbm is coerced into the available power range using
+ * get_power_limits().
+ *
+ * \param power_dbm The power (in dBm) at which we are getting the gain value for
+ * \param freq The frequency at which we are finding the gain
+ * \param temperature The temperature at which we are finding the gain. If
+ * none is given, uses the current default temperature
+ * (see set_temperature()).
+ */
+ virtual double get_gain(const double power_dbm,
+ const double freq,
+ const boost::optional<int> temperature = boost::none) const = 0;
+
+ //! Factory for new cal data sets
+ static sptr make(
+ const std::string& name, const std::string& serial, const uint64_t timestamp);
+
+ //! Default factory
+ static sptr make();
+};
+
+}}} // namespace uhd::usrp::cal
+
diff --git a/host/include/uhd/cal/pwr_cal_generated.h b/host/include/uhd/cal/pwr_cal_generated.h
new file mode 100644
index 000000000..f7ea8d8a7
--- /dev/null
+++ b/host/include/uhd/cal/pwr_cal_generated.h
@@ -0,0 +1,340 @@
+// automatically generated by the FlatBuffers compiler, do not modify
+
+
+#ifndef FLATBUFFERS_GENERATED_PWRCAL_UHD_USRP_CAL_H_
+#define FLATBUFFERS_GENERATED_PWRCAL_UHD_USRP_CAL_H_
+
+#include "flatbuffers/flatbuffers.h"
+
+#include "cal_metadata_generated.h"
+
+namespace uhd {
+namespace usrp {
+namespace cal {
+
+struct PowerMap;
+
+struct FreqPowerMap;
+struct FreqPowerMapBuilder;
+
+struct TempFreqMap;
+struct TempFreqMapBuilder;
+
+struct PowerCal;
+struct PowerCalBuilder;
+
+FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) PowerMap FLATBUFFERS_FINAL_CLASS {
+ private:
+ double gain_;
+ double power_dbm_;
+
+ public:
+ PowerMap() {
+ memset(static_cast<void *>(this), 0, sizeof(PowerMap));
+ }
+ PowerMap(double _gain, double _power_dbm)
+ : gain_(flatbuffers::EndianScalar(_gain)),
+ power_dbm_(flatbuffers::EndianScalar(_power_dbm)) {
+ }
+ double gain() const {
+ return flatbuffers::EndianScalar(gain_);
+ }
+ bool KeyCompareLessThan(const PowerMap *o) const {
+ return gain() < o->gain();
+ }
+ int KeyCompareWithValue(double val) const {
+ return static_cast<int>(gain() > val) - static_cast<int>(gain() < val);
+ }
+ double power_dbm() const {
+ return flatbuffers::EndianScalar(power_dbm_);
+ }
+};
+FLATBUFFERS_STRUCT_END(PowerMap, 16);
+
+struct FreqPowerMap FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef FreqPowerMapBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_FREQ = 4,
+ VT_POWERS = 6,
+ VT_MIN_POWER = 8,
+ VT_MAX_POWER = 10
+ };
+ uint64_t freq() const {
+ return GetField<uint64_t>(VT_FREQ, 0);
+ }
+ bool KeyCompareLessThan(const FreqPowerMap *o) const {
+ return freq() < o->freq();
+ }
+ int KeyCompareWithValue(uint64_t val) const {
+ return static_cast<int>(freq() > val) - static_cast<int>(freq() < val);
+ }
+ const flatbuffers::Vector<const uhd::usrp::cal::PowerMap *> *powers() const {
+ return GetPointer<const flatbuffers::Vector<const uhd::usrp::cal::PowerMap *> *>(VT_POWERS);
+ }
+ double min_power() const {
+ return GetField<double>(VT_MIN_POWER, 0.0);
+ }
+ double max_power() const {
+ return GetField<double>(VT_MAX_POWER, 0.0);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField<uint64_t>(verifier, VT_FREQ) &&
+ VerifyOffset(verifier, VT_POWERS) &&
+ verifier.VerifyVector(powers()) &&
+ VerifyField<double>(verifier, VT_MIN_POWER) &&
+ VerifyField<double>(verifier, VT_MAX_POWER) &&
+ verifier.EndTable();
+ }
+};
+
+struct FreqPowerMapBuilder {
+ typedef FreqPowerMap Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_freq(uint64_t freq) {
+ fbb_.AddElement<uint64_t>(FreqPowerMap::VT_FREQ, freq, 0);
+ }
+ void add_powers(flatbuffers::Offset<flatbuffers::Vector<const uhd::usrp::cal::PowerMap *>> powers) {
+ fbb_.AddOffset(FreqPowerMap::VT_POWERS, powers);
+ }
+ void add_min_power(double min_power) {
+ fbb_.AddElement<double>(FreqPowerMap::VT_MIN_POWER, min_power, 0.0);
+ }
+ void add_max_power(double max_power) {
+ fbb_.AddElement<double>(FreqPowerMap::VT_MAX_POWER, max_power, 0.0);
+ }
+ explicit FreqPowerMapBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ FreqPowerMapBuilder &operator=(const FreqPowerMapBuilder &);
+ flatbuffers::Offset<FreqPowerMap> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<FreqPowerMap>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<FreqPowerMap> CreateFreqPowerMap(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ uint64_t freq = 0,
+ flatbuffers::Offset<flatbuffers::Vector<const uhd::usrp::cal::PowerMap *>> powers = 0,
+ double min_power = 0.0,
+ double max_power = 0.0) {
+ FreqPowerMapBuilder builder_(_fbb);
+ builder_.add_max_power(max_power);
+ builder_.add_min_power(min_power);
+ builder_.add_freq(freq);
+ builder_.add_powers(powers);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<FreqPowerMap> CreateFreqPowerMapDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ uint64_t freq = 0,
+ std::vector<uhd::usrp::cal::PowerMap> *powers = nullptr,
+ double min_power = 0.0,
+ double max_power = 0.0) {
+ auto powers__ = powers ? _fbb.CreateVectorOfSortedStructs<uhd::usrp::cal::PowerMap>(powers) : 0;
+ return uhd::usrp::cal::CreateFreqPowerMap(
+ _fbb,
+ freq,
+ powers__,
+ min_power,
+ max_power);
+}
+
+struct TempFreqMap FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef TempFreqMapBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_TEMPERATURE = 4,
+ VT_FREQS = 6
+ };
+ int32_t temperature() const {
+ return GetField<int32_t>(VT_TEMPERATURE, 0);
+ }
+ bool KeyCompareLessThan(const TempFreqMap *o) const {
+ return temperature() < o->temperature();
+ }
+ int KeyCompareWithValue(int32_t val) const {
+ return static_cast<int>(temperature() > val) - static_cast<int>(temperature() < val);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<uhd::usrp::cal::FreqPowerMap>> *freqs() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<uhd::usrp::cal::FreqPowerMap>> *>(VT_FREQS);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int32_t>(verifier, VT_TEMPERATURE) &&
+ VerifyOffset(verifier, VT_FREQS) &&
+ verifier.VerifyVector(freqs()) &&
+ verifier.VerifyVectorOfTables(freqs()) &&
+ verifier.EndTable();
+ }
+};
+
+struct TempFreqMapBuilder {
+ typedef TempFreqMap Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_temperature(int32_t temperature) {
+ fbb_.AddElement<int32_t>(TempFreqMap::VT_TEMPERATURE, temperature, 0);
+ }
+ void add_freqs(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<uhd::usrp::cal::FreqPowerMap>>> freqs) {
+ fbb_.AddOffset(TempFreqMap::VT_FREQS, freqs);
+ }
+ explicit TempFreqMapBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ TempFreqMapBuilder &operator=(const TempFreqMapBuilder &);
+ flatbuffers::Offset<TempFreqMap> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<TempFreqMap>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<TempFreqMap> CreateTempFreqMap(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t temperature = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<uhd::usrp::cal::FreqPowerMap>>> freqs = 0) {
+ TempFreqMapBuilder builder_(_fbb);
+ builder_.add_freqs(freqs);
+ builder_.add_temperature(temperature);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<TempFreqMap> CreateTempFreqMapDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t temperature = 0,
+ std::vector<flatbuffers::Offset<uhd::usrp::cal::FreqPowerMap>> *freqs = nullptr) {
+ auto freqs__ = freqs ? _fbb.CreateVectorOfSortedTables<uhd::usrp::cal::FreqPowerMap>(freqs) : 0;
+ return uhd::usrp::cal::CreateTempFreqMap(
+ _fbb,
+ temperature,
+ freqs__);
+}
+
+struct PowerCal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef PowerCalBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_METADATA = 4,
+ VT_TEMP_FREQ_MAP = 6,
+ VT_REF_GAIN = 8
+ };
+ const Metadata *metadata() const {
+ return GetPointer<const Metadata *>(VT_METADATA);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<uhd::usrp::cal::TempFreqMap>> *temp_freq_map() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<uhd::usrp::cal::TempFreqMap>> *>(VT_TEMP_FREQ_MAP);
+ }
+ int32_t ref_gain() const {
+ return GetField<int32_t>(VT_REF_GAIN, -1);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffset(verifier, VT_METADATA) &&
+ verifier.VerifyTable(metadata()) &&
+ VerifyOffset(verifier, VT_TEMP_FREQ_MAP) &&
+ verifier.VerifyVector(temp_freq_map()) &&
+ verifier.VerifyVectorOfTables(temp_freq_map()) &&
+ VerifyField<int32_t>(verifier, VT_REF_GAIN) &&
+ verifier.EndTable();
+ }
+};
+
+struct PowerCalBuilder {
+ typedef PowerCal Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_metadata(flatbuffers::Offset<Metadata> metadata) {
+ fbb_.AddOffset(PowerCal::VT_METADATA, metadata);
+ }
+ void add_temp_freq_map(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<uhd::usrp::cal::TempFreqMap>>> temp_freq_map) {
+ fbb_.AddOffset(PowerCal::VT_TEMP_FREQ_MAP, temp_freq_map);
+ }
+ void add_ref_gain(int32_t ref_gain) {
+ fbb_.AddElement<int32_t>(PowerCal::VT_REF_GAIN, ref_gain, -1);
+ }
+ explicit PowerCalBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ PowerCalBuilder &operator=(const PowerCalBuilder &);
+ flatbuffers::Offset<PowerCal> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<PowerCal>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<PowerCal> CreatePowerCal(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<Metadata> metadata = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<uhd::usrp::cal::TempFreqMap>>> temp_freq_map = 0,
+ int32_t ref_gain = -1) {
+ PowerCalBuilder builder_(_fbb);
+ builder_.add_ref_gain(ref_gain);
+ builder_.add_temp_freq_map(temp_freq_map);
+ builder_.add_metadata(metadata);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<PowerCal> CreatePowerCalDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<Metadata> metadata = 0,
+ std::vector<flatbuffers::Offset<uhd::usrp::cal::TempFreqMap>> *temp_freq_map = nullptr,
+ int32_t ref_gain = -1) {
+ auto temp_freq_map__ = temp_freq_map ? _fbb.CreateVectorOfSortedTables<uhd::usrp::cal::TempFreqMap>(temp_freq_map) : 0;
+ return uhd::usrp::cal::CreatePowerCal(
+ _fbb,
+ metadata,
+ temp_freq_map__,
+ ref_gain);
+}
+
+inline const uhd::usrp::cal::PowerCal *GetPowerCal(const void *buf) {
+ return flatbuffers::GetRoot<uhd::usrp::cal::PowerCal>(buf);
+}
+
+inline const uhd::usrp::cal::PowerCal *GetSizePrefixedPowerCal(const void *buf) {
+ return flatbuffers::GetSizePrefixedRoot<uhd::usrp::cal::PowerCal>(buf);
+}
+
+inline const char *PowerCalIdentifier() {
+ return "dB/m";
+}
+
+inline bool PowerCalBufferHasIdentifier(const void *buf) {
+ return flatbuffers::BufferHasIdentifier(
+ buf, PowerCalIdentifier());
+}
+
+inline bool VerifyPowerCalBuffer(
+ flatbuffers::Verifier &verifier) {
+ return verifier.VerifyBuffer<uhd::usrp::cal::PowerCal>(PowerCalIdentifier());
+}
+
+inline bool VerifySizePrefixedPowerCalBuffer(
+ flatbuffers::Verifier &verifier) {
+ return verifier.VerifySizePrefixedBuffer<uhd::usrp::cal::PowerCal>(PowerCalIdentifier());
+}
+
+inline void FinishPowerCalBuffer(
+ flatbuffers::FlatBufferBuilder &fbb,
+ flatbuffers::Offset<uhd::usrp::cal::PowerCal> root) {
+ fbb.Finish(root, PowerCalIdentifier());
+}
+
+inline void FinishSizePrefixedPowerCalBuffer(
+ flatbuffers::FlatBufferBuilder &fbb,
+ flatbuffers::Offset<uhd::usrp::cal::PowerCal> root) {
+ fbb.FinishSizePrefixed(root, PowerCalIdentifier());
+}
+
+} // namespace cal
+} // namespace usrp
+} // namespace uhd
+
+#endif // FLATBUFFERS_GENERATED_PWRCAL_UHD_USRP_CAL_H_