diff options
-rw-r--r-- | host/docs/devices.dox | 1 | ||||
-rw-r--r-- | host/docs/power.dox | 154 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/radio_control.hpp | 99 | ||||
-rw-r--r-- | host/include/uhd/usrp/multi_usrp.hpp | 106 | ||||
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp | 6 | ||||
-rw-r--r-- | host/lib/rfnoc/radio_control_impl.cpp | 36 | ||||
-rw-r--r-- | host/lib/usrp/multi_usrp.cpp | 56 | ||||
-rw-r--r-- | host/lib/usrp/multi_usrp_python.hpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/multi_usrp_rfnoc.cpp | 36 |
9 files changed, 500 insertions, 0 deletions
diff --git a/host/docs/devices.dox b/host/docs/devices.dox index 5deb39f3c..dbe860382 100644 --- a/host/docs/devices.dox +++ b/host/docs/devices.dox @@ -14,6 +14,7 @@ \li \subpage page_dpdk \li \subpage page_configfiles \li \subpage page_compat +\li \subpage page_power ## USRP N-Series Devices diff --git a/host/docs/power.dox b/host/docs/power.dox new file mode 100644 index 000000000..816c74824 --- /dev/null +++ b/host/docs/power.dox @@ -0,0 +1,154 @@ +/*! \page page_power Power Level Controls + +\tableofcontents + +\section power_overview + +Starting with UHD 4, UHD comes with reference power level APIs. These allow to +not just set a relative gain level, but configure a USRP to transmit a certain +power, or to estimate received power levels. + +The actual transmitted or received power also depends on the transmitted signal +itself. The absolute power setting is thus a *reference power level*. +The reference power level maps a digital signal level (in dBFS) to an absolute, +analog power level (in dBm). The power level setting is the analog power level +that corresponds to a 0 dBFS digital signal. + +Note that most USRPs do not support setting reference power levels. Refer to the +individual device manual pages for more information. + +\section power_ref_levels RX and TX reference power levels + +<b>RX reference power level:</b> + +The RX reference power level is defined as such: When a signal with this power +level is applied to the RF input, the digital signal will be at a 0 dBFS power +level. + +If a tone with this power level is applied to the RF input, it will be +full-scale in the digital representation. + +Example: The reference power level is set to -4 dBm by calling +~~~{.cpp} +U->set_rx_power_reference(-4.0, 0); +~~~ + +Then, a signal is captured. It turns out the signal is a sine wave with +an amplitude of 0.5, which means its power is 6 dB lower than a signal +with an amplitude of 1.0 (or -6 dBFS). Based on the reference power level, we +can thus infer that the tone injected into the RF port is: + + (-4 dBm - 6 dB) = -10 dBm + +<b>TX reference power level:</b> + +The TX reference power level is defined as such: When a 0 dBFS signal is +transmitted, it will leave the RF output at the selected reference power level. +In other contexts, this value is sometimes referred to as "peak power level", +because it's the maximum power that can be transmitted. + +If a fullscale tone is transmitted, the transmitted analog tone will have the +reference power level. + +Example: The reference power level is set to -4 dBm by calling +~~~{.cpp} +U->set_tx_power_reference(-4.0, 0); +~~~ + +Then, we generate a tone that is a sine wave with amplitude 0.5 and +transmit it using this device and channel. With this amplitude, the +signal is 6 dB lower in power than a sine wave with amplitude 1.0. +Based on the reference power level, we can thus infer that the tone +leaving the RF port has the following absolute power: + + (-4 dBm - 6 dB) = -10 dBm + +\section power_amp_rate Amplitude Ranges and Clipping + +In practice, it is never possible to cleanly transmit or receive a signal at +0 dBFS, so the reference levels need to be appropriately normalized. Because +all USRPs have a different amplitude range they can transmit/receive before +clipping or distortion occurs, the APIs are designed to be agnostic of the +hardware. The derivation of the actual analog power is thus the responsibility +of the application (i.e., the code that also calls `recv()` and `send()`), which has +access to the sample values. UHD itself doesn't inspect the sample values for +performance reasons, and thus can only manage reference levels. + +\section power_tune_owner Retaining gain or power levels across frequency + +When tuning a USRP (i.e., changing its frequency) it may be necessary to also +adjust gain stages. Due to physical limitations, the same output power is not +always available (or possible) at different frequencies. This means that the +output power may vary when retuning. The relative gain range is usually the same +across frequencies, though. + +UHD will try to maintain the relative gain setting, or the power level setting. +The choice is determined by which API was called last. If the gain level was set +last (i.e., by either calling `set_tx_gain()` or `set_rx_gain()`), then the gain +level will be kept constant after retuning, but the power level will likely have +changed. If the power reference level was set last (by either calling +`set_rx_power_reference()` or `set_tx_power_reference()`), then UHD will attempt +to maintain a constant power reference level, which means UHD will likely have +to modify the relative gain values. To get the exact power level after a retune, +read back the current power reference level (`get_rx_power_reference()` or +`get_tx_power_reference()`). + +The following example shows how the APIs behave for reception. For transmission, +the behaviour is the same (just replace 'rx' with 'tx' in the API calls). Note +that the determination of relative gain or power is retained over retunes is +independent for TX and RX. + +~~~{.cpp} +// usrp is a multi_usrp object, f0 and f1 are valid frequencies +usrp->set_rx_frequency(f0); +usrp->set_rx_gain(10); +// This should print '10', or the closest coerced value: +std::cout << usrp->get_rx_gain() << std::endl; +// This can print anything, depending on device and calibration data: +std::cout << usrp->get_rx_power_reference() << std::endl; +usrp->set_rx_frequency(f1); +// This should still print '10', or the closest coerced value: +std::cout << usrp->get_rx_gain() << std::endl; +// This can print anything, and possibly not the same value as before +std::cout << usrp->get_rx_power_reference() << std::endl; +usrp->set_rx_power_reference(-20); +// This should print -20, assuming the device can transmit at that power: +std::cout << usrp->get_rx_power_reference() << std::endl; +// This will print the current gain value, whatever that is +std::cout << usrp->get_rx_gain() << std::endl; +usrp->set_rx_frequency(f0); +// This should still print -20, or the closest coerced value +std::cout << usrp->get_rx_power_reference() << std::endl; +// This will print the current gain value, possibly not the same as before +std::cout << usrp->get_rx_gain() << std::endl; +~~~ + +\section power_implementation Device Implementations of Power Level APIs + +Under the hood, this API call will affect any gain stage that it needs to +affect. It is possible to read back the current gain settings by calling +`get_tx_gain()` or `get_rx_gain()`. However, changing the gain settings by calling +`set_tx_gain()` or `set_rx_gain()` will cause the power level to change. + +The specific implementation of this API is very device-specific. Refer to the +individual USRP manual pages for more details. + +\section power_storage Calibration Table Storage + +UHD needs to store calibration tables to be able to map reference power levels +to settings for the individual gain stages of each USRP and/or daughterboard. +These tables can be stored in three different ways: + +- Hard-coded as part of UHD. If a gain table is hard-coded as part of UHD, it + means that the gain table is considered an average table for a given device. + Its accuracy may vary a lot, as it is not calibrated to a specific device + and/or environment. +- In the device EEPROM. By storing calibration data in an EEPROM on the device, + it is possible to use the same calibration data even when using different host + computers. Calibration data in EEPROMs can also be updated to account for + different environments, aging of components, or anything else. +- On a file. Calibration data in a file is the most flexible, it can be replaced + easily. It is however local to the computer that stores the calibration data. + +*/ +// vim:ft=doxygen: diff --git a/host/include/uhd/rfnoc/radio_control.hpp b/host/include/uhd/rfnoc/radio_control.hpp index 9d343cdac..96c3e1bbe 100644 --- a/host/include/uhd/rfnoc/radio_control.hpp +++ b/host/include/uhd/rfnoc/radio_control.hpp @@ -189,6 +189,56 @@ public: virtual double set_tx_gain( const double gain, const std::string& name, const size_t chan) = 0; + /*! Return true if this channel has a reference power API enabled + * + * Many devices either don't have a built-in reference power API, or they + * require calibration data for it to work. This means that it is not clear, + * even when the device type is known, if a device supports setting a power + * reference level. Use this method to query the availability of + * set_tx_power_reference() and get_tx_power_reference(), which will throw + * a uhd::not_implemented_error or uhd::runtime_error if they cannot be used. + * + * See \ref page_power for more information, or query the specific device's + * manual page to see if a power API is available, and how to enable it. + * + * \param chan The channel for which this feature is queried + * + * \returns true if this channel has a TX power API available + */ + virtual bool has_tx_power_reference(const size_t chan = 0) = 0; + + /*! Set the reference TX power level for a given channel + * + * Note: This functionality is not supported for most devices, and will + * cause a uhd::not_implemented_error exception to be thrown on devices that + * do not have this functionality. + * + * For more information on how to use this API, see \ref page_power. + * + * \param power_dbm The reference power level in dBm + * \param chan The channel for which this setting applies + * + * \throws uhd::not_implemented_error if this functionality does not exist + * for this device + */ + virtual void set_tx_power_reference( + const double power_dbm, const size_t chan = 0) = 0; + + /*! Return the actual reference TX power level. + * + * Note: This functionality is not supported for most devices, and will + * cause a uhd::not_implemented_error exception to be thrown on devices that + * do not have this functionality. + * + * For more information on how to use this API, see \ref page_power. + * + * \param chan The channel for which this setting is queried + * \throws uhd::not_implemented_error if this functionality does not exist + * for this device + */ + virtual double get_tx_power_reference(const size_t chan = 0) = 0; + + /*! Return a list of valid RX gain names */ virtual std::vector<std::string> get_rx_gain_names(const size_t chan) const = 0; @@ -239,6 +289,55 @@ public: */ virtual void set_rx_agc(const bool enable, const size_t chan) = 0; + /*! Return true if this channel has a reference power API enabled + * + * Many devices either don't have a built-in reference power API, or they + * require calibration data for it to work. This means that it is not clear, + * even when the device type is known, if a device supports setting a power + * reference level. Use this method to query the availability of + * set_rx_power_reference() and get_rx_power_reference(), which will throw + * a uhd::not_implemented_error or uhd::runtime_error if they cannot be used. + * + * See \ref page_power for more information, or query the specific device's + * manual page to see if a power API is available, and how to enable it. + * + * \param chan The channel for which this feature is queried + * + * \returns true if this channel has an RX power API available + */ + virtual bool has_rx_power_reference(const size_t chan = 0) = 0; + + /*! Set the reference RX power level for a given channel + * + * Note: This functionality is not supported for most devices, and will + * cause a uhd::not_implemented_error exception to be thrown on devices that + * do not have this functionality. + * + * For more information on how to use this API, see \ref page_power. + * + * \param power_dbm The reference power level in dBm + * \param chan The channel for which this setting applies + * + * \throws uhd::not_implemented_error if this functionality does not exist + * for this device + */ + virtual void set_rx_power_reference( + const double power_dbm, const size_t chan = 0) = 0; + + /*! Return the actual reference RX power level. + * + * Note: This functionality is not supported for most devices, and will + * cause a uhd::not_implemented_error exception to be thrown on devices that + * do not have this functionality. + * + * For more information on how to use this API, see \ref page_power. + * + * \param chan The channel for which this setting is queried + * \throws uhd::not_implemented_error if this functionality does not exist + * for this device + */ + virtual double get_rx_power_reference(const size_t chan = 0) = 0; + /*! Return a list of TX gain profiles for this radio */ virtual std::vector<std::string> get_tx_gain_profile_names( diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 53e63361f..e177e7cf7 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -22,6 +22,7 @@ #define UHD_USRP_MULTI_USRP_FILTER_API #define UHD_USRP_MULTI_USRP_LO_CONFIG_API #define UHD_USRP_MULTI_USRP_TX_LO_CONFIG_API +#define UHD_USRP_MULTI_USRP_POWER_LEVEL #include <uhd/config.hpp> #include <uhd/device.hpp> @@ -1176,6 +1177,59 @@ public: virtual void set_rx_iq_balance( const std::complex<double>& correction, size_t chan = ALL_CHANS) = 0; + + /************************************************************************** + * Power level controls + *************************************************************************/ + /*! Return true if this channel has a reference power API enabled + * + * Many devices either don't have a built-in reference power API, or they + * require calibration data for it to work. This means that it is not clear, + * even when the device type is known, if a device supports setting a power + * reference level. Use this method to query the availability of + * set_rx_power_reference() and get_rx_power_reference(), which will throw + * a uhd::not_implemented_error or uhd::runtime_error if they cannot be used. + * + * See \ref page_power for more information, or query the specific device's + * manual page to see if a power API is available, and how to enable it. + * + * \param chan The channel for which this feature is queried + * + * \returns true if this channel has an RX power API available + */ + virtual bool has_rx_power_reference(const size_t chan = 0) = 0; + + /*! Set the reference RX power level for a given channel + * + * Note: This functionality is not supported for most devices, and will + * cause a uhd::not_implemented_error exception to be thrown on devices that + * do not have this functionality. + * + * For more information on how to use this API, see \ref page_power. + * + * \param power_dbm The reference power level in dBm + * \param chan The channel for which this setting applies + * + * \throws uhd::not_implemented_error if this functionality does not exist + * for this device + */ + virtual void set_rx_power_reference( + const double power_dbm, const size_t chan = 0) = 0; + + /*! Return the actual reference RX power level. + * + * Note: This functionality is not supported for most devices, and will + * cause a uhd::not_implemented_error exception to be thrown on devices that + * do not have this functionality. + * + * For more information on how to use this API, see \ref page_power. + * + * \param chan The channel for which this setting is queried + * \throws uhd::not_implemented_error if this functionality does not exist + * for this device + */ + virtual double get_rx_power_reference(const size_t chan = 0) = 0; + /******************************************************************* * TX methods ******************************************************************/ @@ -1372,6 +1426,58 @@ public: */ virtual std::vector<std::string> get_tx_gain_names(size_t chan = 0) = 0; + /************************************************************************** + * Power level controls + *************************************************************************/ + /*! Return true if this channel has a reference power API enabled + * + * Many devices either don't have a built-in reference power API, or they + * require calibration data for it to work. This means that it is not clear, + * even when the device type is known, if a device supports setting a power + * reference level. Use this method to query the availability of + * set_tx_power_reference() and get_tx_power_reference(), which will throw + * a uhd::not_implemented_error or uhd::runtime_error if they cannot be used. + * + * See \ref page_power for more information, or query the specific device's + * manual page to see if a power API is available, and how to enable it. + * + * \param chan The channel for which this feature is queried + * + * \returns true if this channel has a TX power API available + */ + virtual bool has_tx_power_reference(const size_t chan = 0) = 0; + + /*! Set the reference TX power level for a given channel + * + * Note: This functionality is not supported for most devices, and will + * cause a uhd::not_implemented_error exception to be thrown on devices that + * do not have this functionality. + * + * For more information on how to use this API, see \ref page_power. + * + * \param power_dbm The reference power level in dBm + * \param chan The channel for which this setting applies + * + * \throws uhd::not_implemented_error if this functionality does not exist + * for this device + */ + virtual void set_tx_power_reference( + const double power_dbm, const size_t chan = 0) = 0; + + /*! Return the actual reference TX power level. + * + * Note: This functionality is not supported for most devices, and will + * cause a uhd::not_implemented_error exception to be thrown on devices that + * do not have this functionality. + * + * For more information on how to use this API, see \ref page_power. + * + * \param chan The channel for which this setting is queried + * \throws uhd::not_implemented_error if this functionality does not exist + * for this device + */ + virtual double get_tx_power_reference(const size_t chan = 0) = 0; + /*! * Select the TX antenna on the frontend. * \param ant the antenna name diff --git a/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp b/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp index c3a6bd507..4916ecf6f 100644 --- a/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp +++ b/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp @@ -72,6 +72,8 @@ public: virtual double set_rx_bandwidth(const double bandwidth, const size_t chan); virtual void set_tx_gain_profile(const std::string& profile, const size_t chan); virtual void set_rx_gain_profile(const std::string& profile, const size_t chan); + virtual void set_rx_power_reference(const double power_dbm, const size_t chan); + virtual void set_tx_power_reference(const double power_dbm, const size_t chan); // Getters virtual std::string get_tx_antenna(const size_t chan) const; @@ -100,6 +102,10 @@ public: virtual double get_rx_bandwidth(const size_t); virtual meta_range_t get_tx_bandwidth_range(size_t chan) const; virtual meta_range_t get_rx_bandwidth_range(size_t chan) const; + virtual bool has_rx_power_reference(const size_t chan); + virtual bool has_tx_power_reference(const size_t chan); + virtual double get_rx_power_reference(const size_t chan); + virtual double get_tx_power_reference(const size_t chan); /************************************************************************** * LO Controls diff --git a/host/lib/rfnoc/radio_control_impl.cpp b/host/lib/rfnoc/radio_control_impl.cpp index 4f1246e5c..e34a9b430 100644 --- a/host/lib/rfnoc/radio_control_impl.cpp +++ b/host/lib/rfnoc/radio_control_impl.cpp @@ -404,6 +404,28 @@ double radio_control_impl::set_rx_gain( return set_rx_gain(gain, chan); } +bool radio_control_impl::has_rx_power_reference(const size_t) +{ + return false; +} + +bool radio_control_impl::has_tx_power_reference(const size_t) +{ + return false; +} + +void radio_control_impl::set_rx_power_reference(const double, const size_t) +{ + throw uhd::not_implemented_error( + "set_rx_power_reference() is not supported on this radio!"); +} + +void radio_control_impl::set_tx_power_reference(const double, const size_t) +{ + throw uhd::not_implemented_error( + "set_tx_power_reference() is not supported on this radio!"); +} + void radio_control_impl::set_rx_agc(const bool, const size_t) { throw uhd::not_implemented_error("set_rx_agc() is not supported on this radio!"); @@ -575,6 +597,20 @@ uhd::meta_range_t radio_control_impl::get_rx_bandwidth_range(size_t chan) const return result; } +double radio_control_impl::get_rx_power_reference(const size_t) +{ + throw uhd::not_implemented_error( + "get_rx_power_reference() is not supported on this radio!"); + return 0.0; +} + +double radio_control_impl::get_tx_power_reference(const size_t) +{ + throw uhd::not_implemented_error( + "get_tx_power_reference() is not supported on this radio!"); + return 0.0; +} + /****************************************************************************** * LO Default API *****************************************************************************/ diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index c91f596cd..0392d4df9 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -1718,6 +1718,34 @@ public: return rx_gain_group(chan)->get_names(); } + /************************************************************************** + * RX Power control + *************************************************************************/ + bool has_rx_power_reference(const size_t chan) + { + return _tree->exists(rx_rf_fe_root(chan) / "ref_power/value"); + } + + void set_rx_power_reference(const double power_dbm, const size_t chan = 0) + { + const auto power_ref_path = rx_rf_fe_root(chan) / "ref_power/value"; + if (!_tree->exists(power_ref_path)) { + throw uhd::not_implemented_error( + "set_rx_power_reference() not available for this device and channel"); + } + _tree->access<double>(power_ref_path).set(power_dbm); + } + + double get_rx_power_reference(const size_t chan = 0) + { + const auto power_ref_path = rx_rf_fe_root(chan) / "ref_power/value"; + if (!_tree->exists(power_ref_path)) { + throw uhd::not_implemented_error( + "get_rx_power_reference() not available for this device and channel"); + } + return _tree->access<double>(power_ref_path).get(); + } + void set_rx_antenna(const std::string& ant, size_t chan) { _tree->access<std::string>(rx_rf_fe_root(chan) / "antenna" / "value").set(ant); @@ -2194,6 +2222,34 @@ public: return tx_gain_group(chan)->get_names(); } + /************************************************************************** + * TX Power Controls + *************************************************************************/ + bool has_tx_power_reference(const size_t chan) + { + return _tree->exists(tx_rf_fe_root(chan) / "ref_power/value"); + } + + void set_tx_power_reference(const double power_dbm, const size_t chan = 0) + { + const auto power_ref_path = tx_rf_fe_root(chan) / "ref_power/value"; + if (!_tree->exists(power_ref_path)) { + throw uhd::not_implemented_error( + "set_tx_power_reference() not available for this device and channel"); + } + _tree->access<double>(power_ref_path).set(power_dbm); + } + + double get_tx_power_reference(const size_t chan = 0) + { + const auto power_ref_path = tx_rf_fe_root(chan) / "ref_power/value"; + if (!_tree->exists(power_ref_path)) { + throw uhd::not_implemented_error( + "get_tx_power_reference() not available for this device and channel"); + } + return _tree->access<double>(power_ref_path).get(); + } + void set_tx_antenna(const std::string& ant, size_t chan) { _tree->access<std::string>(tx_rf_fe_root(chan) / "antenna" / "value").set(ant); diff --git a/host/lib/usrp/multi_usrp_python.hpp b/host/lib/usrp/multi_usrp_python.hpp index f4e0a73e1..62f34ffa2 100644 --- a/host/lib/usrp/multi_usrp_python.hpp +++ b/host/lib/usrp/multi_usrp_python.hpp @@ -19,6 +19,7 @@ void export_multi_usrp(py::module& m) const auto ALL_CHANS = multi_usrp::ALL_CHANS; const auto ALL_LOS = multi_usrp::ALL_LOS; + // clang-format off py::class_<multi_usrp, multi_usrp::sptr>(m, "multi_usrp") // Factory @@ -125,6 +126,8 @@ void export_multi_usrp(py::module& m) .def("get_rx_gain_profile" , &multi_usrp::get_rx_gain_profile, py::arg("chan") = 0) .def("set_rx_gain_profile" , &multi_usrp::set_rx_gain_profile, py::arg("profile"), py::arg("chan") = 0) .def("get_rx_gain_profile_names", &multi_usrp::get_rx_gain_profile_names, py::arg("chan") = 0) + .def("set_rx_power_reference" , &multi_usrp::set_rx_power_reference, py::arg("power_dbm"), py::arg("chan") = 0) + .def("get_rx_power_reference" , &multi_usrp::get_rx_power_reference, py::arg("chan") = 0) // TX methods .def("set_tx_subdev_spec" , &multi_usrp::set_tx_subdev_spec, py::arg("spec"), py::arg("mboard") = ALL_MBOARDS) @@ -163,6 +166,8 @@ void export_multi_usrp(py::module& m) .def("get_tx_gain_profile" , &multi_usrp::get_tx_gain_profile, py::arg("chan") = 0) .def("set_tx_gain_profile" , &multi_usrp::set_tx_gain_profile, py::arg("profile"), py::arg("chan") = 0) .def("get_tx_gain_profile_names", &multi_usrp::get_tx_gain_profile_names, py::arg("chan") = 0) + .def("set_tx_power_reference" , &multi_usrp::set_tx_power_reference, py::arg("power_dbm"), py::arg("chan") = 0) + .def("get_tx_power_reference" , &multi_usrp::get_tx_power_reference, py::arg("chan") = 0) // GPIO methods .def("get_gpio_banks" , &multi_usrp::get_gpio_banks) @@ -182,6 +187,7 @@ void export_multi_usrp(py::module& m) .def("set_tx_filter" , &multi_usrp::set_tx_filter) // clang-format off ; + // clang-format on } #endif /* INCLUDED_UHD_USRP_MULTI_USRP_PYTHON_HPP */ diff --git a/host/lib/usrp/multi_usrp_rfnoc.cpp b/host/lib/usrp/multi_usrp_rfnoc.cpp index 14b5fd50b..a62fe3f8e 100644 --- a/host/lib/usrp/multi_usrp_rfnoc.cpp +++ b/host/lib/usrp/multi_usrp_rfnoc.cpp @@ -1396,6 +1396,24 @@ public: return rx_chain.radio->get_rx_gain_names(rx_chain.block_chan); } + bool has_rx_power_reference(const size_t chan) + { + auto& rx_chain = _get_rx_chan(chan); + return rx_chain.radio->has_rx_power_reference(rx_chain.block_chan); + } + + void set_rx_power_reference(const double power_dbm, const size_t chan) + { + auto& rx_chain = _get_rx_chan(chan); + rx_chain.radio->set_rx_power_reference(power_dbm, rx_chain.block_chan); + } + + double get_rx_power_reference(const size_t chan) + { + auto& rx_chain = _get_rx_chan(chan); + return rx_chain.radio->get_rx_power_reference(rx_chain.block_chan); + } + void set_rx_antenna(const std::string& ant, size_t chan) { auto& rx_chain = _get_rx_chan(chan); @@ -1836,6 +1854,24 @@ public: return tx_chain.radio->get_tx_gain_names(tx_chain.block_chan); } + bool has_tx_power_reference(const size_t chan) + { + auto& tx_chain = _get_tx_chan(chan); + return tx_chain.radio->has_rx_power_reference(tx_chain.block_chan); + } + + void set_tx_power_reference(const double power_dbm, const size_t chan) + { + auto& tx_chain = _get_tx_chan(chan); + tx_chain.radio->set_tx_power_reference(power_dbm, tx_chain.block_chan); + } + + double get_tx_power_reference(const size_t chan) + { + auto& tx_chain = _get_tx_chan(chan); + return tx_chain.radio->get_tx_power_reference(tx_chain.block_chan); + } + void set_tx_antenna(const std::string& ant, size_t chan) { auto tx_chain = _get_tx_chan(chan); |