summaryrefslogtreecommitdiff
path: root/gr-uhd/apps/uhd_siggen_base.py
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-08-12 15:05:46 +0200
committerMichael Dickens <michael.dickens@ettus.com>2020-09-10 14:17:50 -0400
commit9e4836dc10b2a6ca537d8c290ac668d94692cbe4 (patch)
tree95957067b5f9e3a3d0489d4a486bdb2e515d7dea /gr-uhd/apps/uhd_siggen_base.py
parentcc4854828366b921f4efbe46e5524be7fe3a6cf8 (diff)
uhd: Update uhd_siggen_gui to allow setting absolute power
Note: This requires a USRP with power API enabled. Summary of changes: - uhd_app now provides the --power argument and applies it as a reference power level. It clashes with --gain. UHDApp now has two 'modes' for setting the power: Via gain (the previous, standard way) or by setting a power. UHDApp calls all the right APIs for each use case. - uhd_siggen_base is now aware of these settings and will make sure the output power is correct by combining the requested power and the requested amplitude (meaning, it sets a ref power that is at the correct level above the requested power level). - The GUI can now set either power or gain, depending on command line arguments. When changing the amplitude in power mode, the ref power is also changed so the output power (in dBm) stays the same when the amplitude changes. - siggen now checks for invalid amplitudes (must be in 0 <= amplitude <= 1). - --amplitude was moved from uhd_app.py to uhd_siggen_base.py, where it belongs. uhd_fft for example does not have that argument. - If --amplitude is set to 0.0, then it now fails in power mode. It's still possible in gain mode.
Diffstat (limited to 'gr-uhd/apps/uhd_siggen_base.py')
-rw-r--r--gr-uhd/apps/uhd_siggen_base.py74
1 files changed, 70 insertions, 4 deletions
diff --git a/gr-uhd/apps/uhd_siggen_base.py b/gr-uhd/apps/uhd_siggen_base.py
index 38d197e3ad..daf8184f56 100644
--- a/gr-uhd/apps/uhd_siggen_base.py
+++ b/gr-uhd/apps/uhd_siggen_base.py
@@ -22,6 +22,9 @@ from gnuradio import analog
from gnuradio import blocks
from gnuradio.gr.pubsub import pubsub
+# PyLint can't reliably detect C++ exports in modules, so let's disable that
+# pylint: disable=no-member
+
DESC_KEY = 'desc'
SAMP_RATE_KEY = 'samp_rate'
LINK_RATE_KEY = 'link_rate'
@@ -35,7 +38,6 @@ WAVEFORM_FREQ_KEY = 'waveform_freq'
WAVEFORM_OFFSET_KEY = 'waveform_offset'
WAVEFORM2_FREQ_KEY = 'waveform2_freq'
FREQ_RANGE_KEY = 'freq_range'
-GAIN_RANGE_KEY = 'gain_range'
TYPE_KEY = 'type'
WAVEFORMS = {
@@ -52,9 +54,25 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp):
GUI-unaware GNU Radio flowgraph. This may be used either with command
line applications or GUI applications.
"""
+ MIN_AMP_POWER_MODE = .001
+
def __init__(self, args):
gr.top_block.__init__(self)
pubsub.__init__(self)
+ if not 0.0 <= args.amplitude <= 1.0:
+ raise ValueError(
+ "Invalid value for amplitude: {}. Must be in [0.0, 1.0]"
+ .format(args.amplitude))
+ # If the power argument is given, we need to turn that into a power
+ # *reference* level. This is a bit of a hack because we're assuming
+ # knowledge of UHDApp (i.e. we're leaking abstractions). But it's simple
+ # and harmless enough.
+ if args.power:
+ if args.amplitude < self.MIN_AMP_POWER_MODE:
+ raise RuntimeError(
+ "[ERROR] Invalid amplitude: In power mode, amplitude must be "
+ "larger than {}!".format(self.MIN_AMP_POWER_MODE))
+ args.power -= 20 * math.log10(args.amplitude)
UHDApp.__init__(self, args=args, prefix="UHD-SIGGEN")
self.extra_sink = None
@@ -78,8 +96,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp):
self.publish(SAMP_RATE_KEY, lambda: self.usrp.get_samp_rate())
self.publish(DESC_KEY, lambda: self.usrp_description)
self.publish(FREQ_RANGE_KEY, lambda: self.usrp.get_freq_range(self.channels[0]))
- self.publish(GAIN_RANGE_KEY, lambda: self.usrp.get_gain_range(self.channels[0]))
- self.publish(GAIN_KEY, lambda: self.usrp.get_gain(self.channels[0]))
+ self.publish(GAIN_KEY, lambda: self.get_gain_or_power())
self[SAMP_RATE_KEY] = args.samp_rate
self[TX_FREQ_KEY] = args.freq
@@ -92,12 +109,13 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp):
#subscribe set methods
self.subscribe(SAMP_RATE_KEY, self.set_samp_rate)
- self.subscribe(GAIN_KEY, self.set_gain)
+ self.subscribe(GAIN_KEY, self.set_gain_or_power)
self.subscribe(TX_FREQ_KEY, self.set_freq)
self.subscribe(AMPLITUDE_KEY, self.set_amplitude)
self.subscribe(WAVEFORM_FREQ_KEY, self.set_waveform_freq)
self.subscribe(WAVEFORM2_FREQ_KEY, self.set_waveform2_freq)
self.subscribe(TYPE_KEY, self.set_waveform)
+ self.subscribe(RF_FREQ_KEY, self.update_gain_range)
#force update on pubsub keys
for key in (SAMP_RATE_KEY, GAIN_KEY, TX_FREQ_KEY,
@@ -234,8 +252,51 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp):
else:
return True # Waveform not yet set
self.vprint("Set amplitude to:", amplitude)
+ self.update_gain_range()
return True
+ def get_gain_or_power(self):
+ """
+ Depending on gain type, return either a power level or the current gain
+ """
+ if self.gain_type == self.GAIN_TYPE_GAIN:
+ return self.usrp.get_gain(self.channels[0])
+ return self.usrp.get_power_reference(self.channels[0]) \
+ + 20 * math.log10(self[AMPLITUDE_KEY])
+
+ def set_gain_or_power(self, gain_or_power):
+ """
+ Call this if a gain or power value changed, but you're not sure which it
+ is.
+
+ If it's a power, we subtract the signal offset to generate a reference
+ power.
+ """
+ if self.gain_type == self.GAIN_TYPE_POWER:
+ self.set_power_reference(
+ gain_or_power - 20 * math.log10(self[AMPLITUDE_KEY]))
+ else:
+ self.set_gain(gain_or_power)
+
+ def update_gain_range(self):
+ """
+ Update self.gain_range.
+ """
+ if self.gain_type == self.GAIN_TYPE_POWER:
+ if self[AMPLITUDE_KEY] < self.MIN_AMP_POWER_MODE:
+ raise RuntimeError(
+ "[ERROR] Invalid amplitude: In power mode, amplitude must be "
+ "larger than {}!".format(self.MIN_AMP_POWER_MODE))
+ power_range = self.usrp.get_power_range(self.channels[0])
+ ampl_offset = 20 * math.log10(self[AMPLITUDE_KEY])
+ self.gain_range = uhd.meta_range(
+ math.floor(power_range.start() + ampl_offset),
+ math.ceil(power_range.stop() + ampl_offset),
+ power_range.step()
+ )
+ self.vprint("Updated power range to {:.2f} ... {:.2f} dBm.".format(
+ self.gain_range.start(), self.gain_range.stop()))
+
def setup_argparser():
"""
@@ -246,6 +307,11 @@ def setup_argparser():
tx_or_rx="Tx",
)
group = parser.add_argument_group('Siggen Arguments')
+ group.add_argument("-m", "--amplitude", type=eng_arg.eng_float, default=0.15,
+ help="Set output amplitude to AMPL (0.0-1.0). Note that "
+ "if --power is given, UHD will attempt to match the "
+ "output power regardless of the amplitude.",
+ metavar="AMPL")
group.add_argument("-x", "--waveform-freq", type=eng_arg.eng_float, default=0.0,
help="Set baseband waveform frequency to FREQ")
group.add_argument("-y", "--waveform2-freq", type=eng_arg.eng_float, default=0.0,