diff options
Diffstat (limited to 'gr-uhd/apps/uhd_siggen_base.py')
-rw-r--r-- | gr-uhd/apps/uhd_siggen_base.py | 74 |
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, |