summaryrefslogtreecommitdiff
path: root/gr-uhd/apps/uhd_siggen_base.py
diff options
context:
space:
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,