diff options
-rw-r--r-- | gr-uhd/docs/uhd.dox | 1 | ||||
-rw-r--r-- | gr-uhd/grc/gen_uhd_usrp_blocks.py | 72 | ||||
-rw-r--r-- | gr-uhd/include/gnuradio/uhd/usrp_block.h | 60 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_block_impl.cc | 21 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_block_impl.h | 1 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_sink_impl.cc | 60 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_sink_impl.h | 4 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_source_impl.cc | 59 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_source_impl.h | 4 | ||||
-rw-r--r-- | gr-uhd/python/uhd/bindings/docstrings/usrp_block_pydoc_template.h | 12 | ||||
-rw-r--r-- | gr-uhd/python/uhd/bindings/usrp_block_python.cc | 25 |
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"), |