summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-uhd/docs/uhd.dox1
-rw-r--r--gr-uhd/grc/gen_uhd_usrp_blocks.py72
-rw-r--r--gr-uhd/include/gnuradio/uhd/usrp_block.h60
-rw-r--r--gr-uhd/lib/usrp_block_impl.cc21
-rw-r--r--gr-uhd/lib/usrp_block_impl.h1
-rw-r--r--gr-uhd/lib/usrp_sink_impl.cc60
-rw-r--r--gr-uhd/lib/usrp_sink_impl.h4
-rw-r--r--gr-uhd/lib/usrp_source_impl.cc59
-rw-r--r--gr-uhd/lib/usrp_source_impl.h4
-rw-r--r--gr-uhd/python/uhd/bindings/docstrings/usrp_block_pydoc_template.h12
-rw-r--r--gr-uhd/python/uhd/bindings/usrp_block_python.cc25
11 files changed, 298 insertions, 21 deletions
diff --git a/gr-uhd/docs/uhd.dox b/gr-uhd/docs/uhd.dox
index 8c28e37e7f..68b605c105 100644
--- a/gr-uhd/docs/uhd.dox
+++ b/gr-uhd/docs/uhd.dox
@@ -88,6 +88,7 @@ Command name | Value Type | Description
-------------|--------------|-------------------------------------------------------------
`chan` | int | Specifies a channel. If this is not given, either all channels are chosen, or channel 0, depending on the action. A value of -1 forces 'all channels', where possible.
`gain` | double | Sets the Tx or Rx gain (in dB). Defaults to all channels.
+`power_dbm` | double | Sets the Tx or Rx power reference level (in dBm). Defaults to all channels. Works for certain devices only, and only if calibration data is available.
`freq` | double | Sets the Tx or Rx frequency. Defaults to all channels. If specified without `lo_offset`, it will set the LO offset to zero.
`lo_offset` | double | Sets an LO offset. Defaults to all channels. Note this does not affect the effective center frequency.
`tune` | tune_request | Like freq, but sets a full tune request (i.e. center frequency and DSP offset). Defaults to all channels.
diff --git a/gr-uhd/grc/gen_uhd_usrp_blocks.py b/gr-uhd/grc/gen_uhd_usrp_blocks.py
index 51aa22fc92..523e4bb0aa 100644
--- a/gr-uhd/grc/gen_uhd_usrp_blocks.py
+++ b/gr-uhd/grc/gen_uhd_usrp_blocks.py
@@ -148,7 +148,6 @@ templates:
${'%'} endif
% endif
)
-
% for m in range(max_mboards):
${'%'} if context.get('num_mboards')() > ${m}:
########################################################################
@@ -166,9 +165,7 @@ templates:
########################################################################
${'%'} endif
% endfor # for m in range(max_mboards)
-
self.${'$'}{id}.set_samp_rate(${'$'}{samp_rate})
-
${'%'} if sync == 'sync':
self.${'$'}{id}.set_time_unknown_pps(uhd.time_spec(0))
${'%'} elif sync == 'pc_clock':
@@ -180,14 +177,12 @@ templates:
% for n in range(max_nchan):
${'%'} if context.get('nchan')() > ${n}:
self.${'$'}{id}.set_center_freq(${'$'}{${'center_freq' + str(n)}}, ${n})
-
${'%'} if context.get('ant${n}')():
self.${'$'}{id}.set_antenna(${'$'}{${'ant' + str(n)}}, ${n})
${'%'} endif
${'%'} if context.get('bw${n}')():
self.${'$'}{id}.set_bandwidth(${'$'}{${'bw' + str(n)}}, ${n})
${'%'} endif
-
% if sourk == 'source':
${'%'} if context.get('rx_agc${n}')() == 'Enabled':
self.${'$'}{id}.set_rx_agc(True, ${n})
@@ -195,8 +190,10 @@ templates:
self.${'$'}{id}.set_rx_agc(False, ${n})
${'%'} endif
${'%'} if context.get('rx_agc${n}')() != 'Enabled':
- ${'%'} if bool(eval(context.get('norm_gain' + '${n}')())):
+ ${'%'} if context.get('gain_type' + '${n}')() == 'normalized':
self.${'$'}{id}.set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} elif context.get('gain_type' + '${n}')() == 'power':
+ self.${'$'}{id}.set_power_reference(${'$'}{${'gain' + str(n)}}, ${n})
${'%'} else:
self.${'$'}{id}.set_gain(${'$'}{${'gain' + str(n)}}, ${n})
${'%'} endif
@@ -208,8 +205,10 @@ templates:
self.${'$'}{id}.set_auto_iq_balance(${'$'}{${'iq_imbal_enb' + str(n)}}, ${n})
${'%'} endif
% else:
- ${'%'} if bool(eval(context.get('norm_gain' + '${n}')())):
+ ${'%'} if context.get('gain_type' + '${n}')() == 'normalized':
self.${'$'}{id}.set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} elif context.get('gain_type' + '${n}')() == 'power':
+ self.${'$'}{id}.set_power_reference(${'$'}{${'gain' + str(n)}}, ${n})
${'%'} else:
self.${'$'}{id}.set_gain(${'$'}{${'gain' + str(n)}}, ${n})
${'%'} endif
@@ -230,10 +229,23 @@ templates:
- ${'$'}{'set_rx_agc(False, ${n})' if context.get('rx_agc${n}')() == 'Disabled' else ''}
- |
${'%'} if context.get('rx_agc${n}')() != 'Enabled':
- self.${'$'}{id}.set_${'$'}{'normalized_' if bool(eval(context.get('norm_gain${n}')())) else ''}gain(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} if context.get('gain_type' + '${n}')() == 'normalized':
+ self.${'$'}{id}.set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} elif context.get('gain_type' + '${n}')() == 'power':
+ self.${'$'}{id}.set_power_reference(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} else:
+ self.${'$'}{id}.set_gain(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} endif
${'%'} endif
% else:
- - self.${'$'}{id}.set_${'$'}{'normalized_' if bool(eval(context.get('norm_gain${n}')())) else ''}gain(${'$'}{${'gain' + str(n)}}, ${n})
+ - |
+ ${'%'} if context.get('gain_type' + '${n}')() == 'normalized':
+ self.${'$'}{id}.set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} elif context.get('gain_type' + '${n}')() == 'power':
+ self.${'$'}{id}.set_power_reference(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} else:
+ self.${'$'}{id}.set_gain(${'$'}{${'gain' + str(n)}}, ${n})
+ ${'%'} endif
% endif
- ${'$'}{'set_lo_source(' + lo_source${n} + ', uhd.ALL_LOS, ${n})' if show_lo_controls else ''}
- ${'$'}{'set_lo_export_enabled(' + lo_export${n} + ', uhd.ALL_LOS, ${n})' if show_lo_controls else ''}
@@ -271,15 +283,19 @@ cpp_templates:
this->${'$'}{id}->set_rx_agc(False, ${n});
${'%'} endif
${'%'} if context.get('rx_agc${n}')() != 'Enabled':
- ${'%'} if bool(eval(context.get('norm_gain' + '${n}')())):
+ ${'%'} if context.get('gain_type' + '${n}')() == 'normalized':
this->${'$'}{id}->set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n});
+ ${'%'} elif context.get('gain_type' + '${n}')() == 'power':
+ this->${'$'}{id}->set_power_reference(${'$'}{${'gain' + str(n)}}, ${n});
${'%'} else:
this->${'$'}{id}->set_gain(${'$'}{${'gain' + str(n)}}, ${n});
${'%'} endif
${'%'} endif
% else:
- ${'%'} if bool(eval(context.get('norm_gain' + '${n}')())):
+ ${'%'} if context.get('gain_type' + '${n}')() == 'normalized':
this->${'$'}{id}->set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n});
+ ${'%'} elif context.get('gain_type' + '${n}')() == 'power':
+ this->${'$'}{id}->set_power_reference(${'$'}{${'gain' + str(n)}}, ${n});
${'%'} else:
this->${'$'}{id}->set_gain(${'$'}{${'gain' + str(n)}}, ${n});
${'%'} endif
@@ -315,10 +331,25 @@ cpp_templates:
% if sourk == 'source':
- ${'$'}{'set_rx_agc(True, ${n})' if context.get('rx_agc${n}')() == 'Enabled' else ''}
- ${'$'}{'set_rx_agc(False, ${n})' if context.get('rx_agc${n}')() == 'Disabled' else ''}
- - ${'$'}{'set_gain(${'$'}{${'gain' + str(n)}}, ${n})' if not bool(eval(context.get('norm_gain${n}')())) and context.get('rx_agc${n}')() != 'Enabled' else ''}
- - ${'$'}{'set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n})' if bool(eval(context.get('norm_gain${n}')())) and context.get('rx_agc${n}')() != 'Enabled' else ''}
+ - |
+ ${'%'} if context.get('rx_agc${n}')() != 'Enabled':
+ ${'%'} if context.get('gain_type' + '${n}')() == 'normalized':
+ this->${'$'}{id}->set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n});
+ ${'%'} elif context.get('gain_type' + '${n}')() == 'power':
+ this->${'$'}{id}->set_power_reference(${'$'}{${'gain' + str(n)}}, ${n});
+ ${'%'} else:
+ this->${'$'}{id}->set_gain(${'$'}{${'gain' + str(n)}}, ${n});
+ ${'%'} endif
+ ${'%'} endif
% else:
- - this->${'$'}{id}->set_${'$'}{'normalized_' if bool(eval(context.get('norm_gain${n}')())) else ''}gain(${'$'}{${'gain' + str(n)}}, ${n});
+ - |
+ ${'%'} if context.get('gain_type' + '${n}')() == 'normalized':
+ this->${'$'}{id}->set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n});
+ ${'%'} elif context.get('gain_type' + '${n}')() == 'power':
+ this->${'$'}{id}->set_power_reference(${'$'}{${'gain' + str(n)}}, ${n});
+ ${'%'} else:
+ this->${'$'}{id}->set_gain(${'$'}{${'gain' + str(n)}}, ${n});
+ ${'%'} endif
% endif
- ${'$'}{'set_lo_source(' + lo_source${n} + ', ::uhd::usrp::multi_usrp::ALL_LOS, ${n})' if show_lo_controls else ''}
- ${'$'}{'set_lo_export_enabled(' + lo_export${n} + ', ::uhd::usrp::multi_usrp::ALL_LOS, ${n})' if show_lo_controls else ''}
@@ -432,17 +463,16 @@ PARAMS_TMPL = """
% else:
hide: ${'$'}{ 'none' if nchan > ${n} else 'all' }
% endif
-- id: norm_gain${n}
+- id: gain_type${n}
label: 'Ch${n}: Gain Type'
category: RF Options
- dtype: string
- default: 'False'
- options: ['False', 'True']
- option_labels: [Absolute (dB), Normalized]
+ dtype: enum
+ options: [default, normalized, power]
+ option_labels: [Absolute (dB), Normalized, Absolute Power (dBm)]
% if sourk == 'source':
- hide: ${'$'}{ 'all' if nchan <= ${n} or rx_agc${n} == 'Enabled' else ('none' if bool(eval('norm_gain' + str(${n}))) else 'part')}
+ hide: ${'$'}{ 'all' if nchan <= ${n} or rx_agc${n} == 'Enabled' else ('none' if (eval('gain_type' + str(${n})) == 'default') else 'part')}
% else:
- hide: ${'$'}{ 'all' if nchan <= ${n} else ('none' if bool(eval('norm_gain' + str(${n}))) else 'part')}
+ hide: ${'$'}{ 'all' if nchan <= ${n} else ('none' if (eval('gain_type' + str(${n})) == 'default') else 'part')}
% endif
- id: ant${n}
label: 'Ch${n}: Antenna'
diff --git a/gr-uhd/include/gnuradio/uhd/usrp_block.h b/gr-uhd/include/gnuradio/uhd/usrp_block.h
index 63f859cb9b..aaad1211fb 100644
--- a/gr-uhd/include/gnuradio/uhd/usrp_block.h
+++ b/gr-uhd/include/gnuradio/uhd/usrp_block.h
@@ -20,6 +20,7 @@ namespace uhd {
GR_UHD_API const pmt::pmt_t cmd_chan_key();
GR_UHD_API const pmt::pmt_t cmd_gain_key();
+GR_UHD_API const pmt::pmt_t cmd_power_key();
GR_UHD_API const pmt::pmt_t cmd_freq_key();
GR_UHD_API const pmt::pmt_t cmd_lo_offset_key();
GR_UHD_API const pmt::pmt_t cmd_tune_key();
@@ -229,6 +230,65 @@ public:
virtual ::uhd::gain_range_t get_gain_range(const std::string& name,
size_t chan = 0) = 0;
+ /*! Query if this device is capable of absolute power levels
+ *
+ * If true, the set_power_reference() and get_power_reference() APIs can be
+ * used as well.
+ * Note that if the underlying UHD version doesn't support power APIs, a
+ * warning will be printed, and the return value is always false.
+ *
+ * \param chan the channel index 0 to N-1
+ * \returns true if there is a power reference API available for this channel
+ */
+ virtual bool has_power_reference(size_t chan = 0) = 0;
+
+ /*! Set the absolute power reference level for this channel
+ *
+ * Note that this API is available for certain devices only, and only if
+ * calibration data is available. Refer to the UHD manual for greater
+ * detail: https://files.ettus.com/manual/page_power.html
+ *
+ * In a nutshell, using the power reference will configure the device such
+ * that a full-scale signal (0 dBFS) corresponds to a signal at the
+ * antenna connector of \p power_dbm.
+ * After calling this function, the device will attempt to keep the power
+ * level constant after retuning, which means the gain level may be changed
+ * after a re-tune.
+ *
+ * The device may coerce the available power level (for example, if the
+ * requested power level is not achievable by the device). The coerced
+ * value may be read by calling get_power_reference().
+ *
+ * \param power_dbm The power reference level in dBm
+ * \param chan the channel index 0 to N-1
+ * \throws std::runtime_error if the underlying UHD version does not support
+ * the power API.
+ */
+ virtual void set_power_reference(double power_dbm, size_t chan = 0) = 0;
+
+ /*! Return the absolute power reference level for this channel
+ *
+ * Note that this API is only available for certain devices, and assuming
+ * the existence of calibration data. Refer to the UHD manual for greater
+ * detail: https://files.ettus.com/manual/page_compat.html
+ *
+ * See also set_power_reference().
+ *
+ * \param chan the channel index 0 to N-1
+ * \throws std::runtime_error if the underlying UHD version does not support
+ * the power API.
+ */
+ virtual double get_power_reference(size_t chan = 0) = 0;
+
+ /*! Return the available power range
+ *
+ * \param chan the channel index 0 to N-1
+ * \return the power range in dBm
+ * \throws std::runtime_error if the underlying UHD version does not support
+ * the power API.
+ */
+ virtual ::uhd::meta_range_t get_power_range(size_t chan = 0) = 0;
+
/*!
* Set the antenna to use for a given channel.
*
diff --git a/gr-uhd/lib/usrp_block_impl.cc b/gr-uhd/lib/usrp_block_impl.cc
index 7e6a140780..214593e21a 100644
--- a/gr-uhd/lib/usrp_block_impl.cc
+++ b/gr-uhd/lib/usrp_block_impl.cc
@@ -36,6 +36,11 @@ const pmt::pmt_t gr::uhd::cmd_gain_key()
static const pmt::pmt_t val = pmt::mp("gain");
return val;
}
+const pmt::pmt_t gr::uhd::cmd_power_key()
+{
+ static const pmt::pmt_t val = pmt::mp("power_dbm");
+ return val;
+}
const pmt::pmt_t gr::uhd::cmd_freq_key()
{
static const pmt::pmt_t val = pmt::mp("freq");
@@ -134,6 +139,7 @@ usrp_block_impl::usrp_block_impl(const ::uhd::device_addr_t& device_addr,
// Register default command handlers:
REGISTER_CMD_HANDLER(cmd_freq_key(), _cmd_handler_freq);
REGISTER_CMD_HANDLER(cmd_gain_key(), _cmd_handler_gain);
+ REGISTER_CMD_HANDLER(cmd_power_key(), _cmd_handler_power);
REGISTER_CMD_HANDLER(cmd_lo_offset_key(), _cmd_handler_looffset);
REGISTER_CMD_HANDLER(cmd_tune_key(), _cmd_handler_tune);
REGISTER_CMD_HANDLER(cmd_lo_freq_key(), _cmd_handler_lofreq);
@@ -649,6 +655,21 @@ void usrp_block_impl::_cmd_handler_gain(const pmt::pmt_t& gain_,
set_gain(gain, chan);
}
+void usrp_block_impl::_cmd_handler_power(const pmt::pmt_t& power_dbm_,
+ int chan,
+ const pmt::pmt_t& msg)
+{
+ double power_dbm = pmt::to_double(power_dbm_);
+ if (chan == -1) {
+ for (size_t i = 0; i < _nchan; i++) {
+ set_power_reference(power_dbm, i);
+ }
+ return;
+ }
+
+ set_power_reference(power_dbm, chan);
+}
+
void usrp_block_impl::_cmd_handler_antenna(const pmt::pmt_t& ant,
int chan,
const pmt::pmt_t& msg)
diff --git a/gr-uhd/lib/usrp_block_impl.h b/gr-uhd/lib/usrp_block_impl.h
index a81bd8a137..9f459ec7b4 100644
--- a/gr-uhd/lib/usrp_block_impl.h
+++ b/gr-uhd/lib/usrp_block_impl.h
@@ -118,6 +118,7 @@ protected:
void
_cmd_handler_looffset(const pmt::pmt_t& lo_offset, int chan, const pmt::pmt_t& msg);
void _cmd_handler_gain(const pmt::pmt_t& gain, int chan, const pmt::pmt_t& msg);
+ void _cmd_handler_power(const pmt::pmt_t& power_dbm, int chan, const pmt::pmt_t& msg);
void _cmd_handler_antenna(const pmt::pmt_t& ant, int chan, const pmt::pmt_t& msg);
void _cmd_handler_rate(const pmt::pmt_t& rate, int chan, const pmt::pmt_t& msg);
void _cmd_handler_tune(const pmt::pmt_t& tune, int chan, const pmt::pmt_t& msg);
diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc
index da240d09f6..729db6a3d7 100644
--- a/gr-uhd/lib/usrp_sink_impl.cc
+++ b/gr-uhd/lib/usrp_sink_impl.cc
@@ -187,6 +187,66 @@ std::vector<std::string> usrp_sink_impl::get_gain_names(size_t chan)
return _dev->get_tx_gain_range(name, chan);
}
+bool usrp_sink_impl::has_power_reference(size_t chan)
+{
+#ifdef UHD_USRP_MULTI_USRP_POWER_LEVEL
+ if (chan >= _stream_args.channels.size()) {
+ throw std::out_of_range("Invalid channel: " + std::to_string(chan));
+ }
+ const size_t dev_chan = _stream_args.channels[chan];
+ return _dev->has_tx_power_reference(dev_chan);
+#else
+ GR_LOG_WARN(d_logger,
+ "UHD version 4.0 or greater required for power reference API. ");
+ return false;
+#endif
+}
+
+void usrp_sink_impl::set_power_reference(double power_dbm, size_t chan)
+{
+#ifdef UHD_USRP_MULTI_USRP_POWER_LEVEL
+ if (chan >= _stream_args.channels.size()) {
+ throw std::out_of_range("Invalid channel: " + std::to_string(chan));
+ }
+ const size_t dev_chan = _stream_args.channels[chan];
+ _dev->set_tx_power_reference(power_dbm, dev_chan);
+#else
+ GR_LOG_ERROR(d_logger,
+ "UHD version 4.0 or greater required for power reference API.");
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+double usrp_sink_impl::get_power_reference(size_t chan)
+{
+#ifdef UHD_USRP_MULTI_USRP_POWER_LEVEL
+ if (chan >= _stream_args.channels.size()) {
+ throw std::out_of_range("Invalid channel: " + std::to_string(chan));
+ }
+ const size_t dev_chan = _stream_args.channels[chan];
+ return _dev->get_tx_power_reference(dev_chan);
+#else
+ GR_LOG_ERROR(d_logger,
+ "UHD version 4.0 or greater required for power reference API.");
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+::uhd::meta_range_t usrp_sink_impl::get_power_range(size_t chan)
+{
+#ifdef UHD_USRP_MULTI_USRP_POWER_LEVEL
+ if (chan >= _stream_args.channels.size()) {
+ throw std::out_of_range("Invalid channel: " + std::to_string(chan));
+ }
+ const size_t dev_chan = _stream_args.channels[chan];
+ return _dev->get_tx_power_range(dev_chan);
+#else
+ GR_LOG_ERROR(d_logger,
+ "UHD version 4.0 or greater required for power reference API.");
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
void usrp_sink_impl::set_antenna(const std::string& ant, size_t chan)
{
chan = _stream_args.channels[chan];
diff --git a/gr-uhd/lib/usrp_sink_impl.h b/gr-uhd/lib/usrp_sink_impl.h
index 153a3d3b01..a6d927045c 100644
--- a/gr-uhd/lib/usrp_sink_impl.h
+++ b/gr-uhd/lib/usrp_sink_impl.h
@@ -66,6 +66,9 @@ public:
std::vector<std::string> get_gain_names(size_t chan);
::uhd::gain_range_t get_gain_range(size_t chan);
::uhd::gain_range_t get_gain_range(const std::string& name, size_t chan);
+ bool has_power_reference(size_t chan);
+ double get_power_reference(size_t chan);
+ ::uhd::meta_range_t get_power_range(size_t chan);
std::string get_antenna(size_t chan);
std::vector<std::string> get_antennas(size_t chan);
::uhd::sensor_value_t get_sensor(const std::string& name, size_t chan);
@@ -86,6 +89,7 @@ public:
void set_gain(double gain, size_t chan);
void set_gain(double gain, const std::string& name, size_t chan);
void set_normalized_gain(double gain, size_t chan);
+ void set_power_reference(double power_dbm, size_t chan);
void set_antenna(const std::string& ant, size_t chan);
void set_bandwidth(double bandwidth, size_t chan);
double get_bandwidth(size_t chan);
diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc
index 38ec5ecc46..eed04e9787 100644
--- a/gr-uhd/lib/usrp_source_impl.cc
+++ b/gr-uhd/lib/usrp_source_impl.cc
@@ -203,6 +203,65 @@ std::vector<std::string> usrp_source_impl::get_gain_names(size_t chan)
return _dev->get_rx_gain_range(name, chan);
}
+bool usrp_source_impl::has_power_reference(size_t chan)
+{
+#ifdef UHD_USRP_MULTI_USRP_POWER_LEVEL
+ if (chan >= _stream_args.channels.size()) {
+ throw std::out_of_range("Invalid channel: " + std::to_string(chan));
+ }
+ const size_t dev_chan = _stream_args.channels[chan];
+ return _dev->has_rx_power_reference(dev_chan);
+#else
+ GR_LOG_WARN(d_logger, "UHD version 4.0 or greater required for power reference API.");
+ return false;
+#endif
+}
+
+void usrp_source_impl::set_power_reference(double power_dbm, size_t chan)
+{
+#ifdef UHD_USRP_MULTI_USRP_POWER_LEVEL
+ if (chan >= _stream_args.channels.size()) {
+ throw std::out_of_range("Invalid channel: " + std::to_string(chan));
+ }
+ const size_t dev_chan = _stream_args.channels[chan];
+ _dev->set_rx_power_reference(power_dbm, dev_chan);
+#else
+ GR_LOG_ERROR(d_logger,
+ "UHD version 4.0 or greater required for power reference API.");
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+double usrp_source_impl::get_power_reference(size_t chan)
+{
+#ifdef UHD_USRP_MULTI_USRP_POWER_LEVEL
+ if (chan >= _stream_args.channels.size()) {
+ throw std::out_of_range("Invalid channel: " + std::to_string(chan));
+ }
+ const size_t dev_chan = _stream_args.channels[chan];
+ return _dev->get_rx_power_reference(dev_chan);
+#else
+ GR_LOG_ERROR(d_logger,
+ "UHD version 4.0 or greater required for power reference API.");
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+::uhd::meta_range_t usrp_source_impl::get_power_range(size_t chan)
+{
+#ifdef UHD_USRP_MULTI_USRP_POWER_LEVEL
+ if (chan >= _stream_args.channels.size()) {
+ throw std::out_of_range("Invalid channel: " + std::to_string(chan));
+ }
+ const size_t dev_chan = _stream_args.channels[chan];
+ return _dev->get_rx_power_range(dev_chan);
+#else
+ GR_LOG_ERROR(d_logger,
+ "UHD version 4.0 or greater required for power reference API.");
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
void usrp_source_impl::set_antenna(const std::string& ant, size_t chan)
{
chan = _stream_args.channels[chan];
diff --git a/gr-uhd/lib/usrp_source_impl.h b/gr-uhd/lib/usrp_source_impl.h
index 371e7295a7..a5235b50b9 100644
--- a/gr-uhd/lib/usrp_source_impl.h
+++ b/gr-uhd/lib/usrp_source_impl.h
@@ -51,6 +51,9 @@ public:
std::vector<std::string> get_gain_names(size_t chan);
::uhd::gain_range_t get_gain_range(size_t chan);
::uhd::gain_range_t get_gain_range(const std::string& name, size_t chan);
+ bool has_power_reference(size_t chan);
+ double get_power_reference(size_t chan);
+ ::uhd::meta_range_t get_power_range(size_t chan);
std::string get_antenna(size_t chan);
std::vector<std::string> get_antennas(size_t chan);
::uhd::sensor_value_t get_sensor(const std::string& name, size_t chan);
@@ -72,6 +75,7 @@ public:
void set_gain(double gain, const std::string& name, size_t chan);
void set_rx_agc(const bool enable, size_t chan);
void set_normalized_gain(double gain, size_t chan);
+ void set_power_reference(double power_dbm, size_t chan);
void set_antenna(const std::string& ant, size_t chan);
void set_bandwidth(double bandwidth, size_t chan);
double get_bandwidth(size_t chan);
diff --git a/gr-uhd/python/uhd/bindings/docstrings/usrp_block_pydoc_template.h b/gr-uhd/python/uhd/bindings/docstrings/usrp_block_pydoc_template.h
index ed951cc3a3..2b36909541 100644
--- a/gr-uhd/python/uhd/bindings/docstrings/usrp_block_pydoc_template.h
+++ b/gr-uhd/python/uhd/bindings/docstrings/usrp_block_pydoc_template.h
@@ -75,6 +75,18 @@ static const char* __doc_gr_uhd_usrp_block_get_gain_range_0 = R"doc()doc";
static const char* __doc_gr_uhd_usrp_block_get_gain_range_1 = R"doc()doc";
+static const char* __doc_gr_uhd_usrp_block_has_power_reference = R"doc()doc";
+
+
+static const char* __doc_gr_uhd_usrp_block_set_power_reference = R"doc()doc";
+
+
+static const char* __doc_gr_uhd_usrp_block_get_power_reference = R"doc()doc";
+
+
+static const char* __doc_gr_uhd_usrp_block_get_power_range = R"doc()doc";
+
+
static const char* __doc_gr_uhd_usrp_block_set_antenna = R"doc()doc";
diff --git a/gr-uhd/python/uhd/bindings/usrp_block_python.cc b/gr-uhd/python/uhd/bindings/usrp_block_python.cc
index 876dfb52d0..67f0d4dab4 100644
--- a/gr-uhd/python/uhd/bindings/usrp_block_python.cc
+++ b/gr-uhd/python/uhd/bindings/usrp_block_python.cc
@@ -151,6 +151,31 @@ void bind_usrp_block(py::module& m)
D(usrp_block, get_gain_range, 1))
+ .def("has_power_reference",
+ &usrp_block::has_power_reference,
+ py::arg("chan") = 0,
+ D(usrp_block, has_power_reference))
+
+
+ .def("set_power_reference",
+ &usrp_block::set_power_reference,
+ py::arg("power_dbm"),
+ py::arg("chan") = 0,
+ D(usrp_block, set_power_reference))
+
+
+ .def("get_power_reference",
+ &usrp_block::get_power_reference,
+ py::arg("chan") = 0,
+ D(usrp_block, get_power_reference))
+
+
+ .def("get_power_range",
+ &usrp_block::get_power_range,
+ py::arg("chan") = 0,
+ D(usrp_block, get_power_range))
+
+
.def("set_antenna",
&usrp_block::set_antenna,
py::arg("ant"),