diff options
author | Martin Braun <martin.braun@ettus.com> | 2016-07-13 12:57:17 -0700 |
---|---|---|
committer | Johnathan Corgan <johnathan@corganlabs.com> | 2016-08-01 14:26:09 -0700 |
commit | 0759cc9ce9be7e27b7abcdf4c1974b06ed2951fb (patch) | |
tree | 4aeb49727a4e7b758b7bd441fc9ba00149c2b68f /gr-uhd | |
parent | 9e7989cecfce54079e3a9af2714d5bb82563d0b1 (diff) |
uhd: Updates to UHDApp and siggen apps
- Added time source option
- Fixed bug where sources where not applied to all motherboards
- Various formatting cleanups (better Pylint score)
- Catch case where lo_locked sensor detection fails
Diffstat (limited to 'gr-uhd')
-rw-r--r-- | gr-uhd/apps/uhd_app.py | 35 | ||||
-rw-r--r-- | gr-uhd/apps/uhd_siggen_base.py | 94 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_siggen_gui | 33 |
3 files changed, 97 insertions, 65 deletions
diff --git a/gr-uhd/apps/uhd_app.py b/gr-uhd/apps/uhd_app.py index ff4412a140..652a9fbab6 100644 --- a/gr-uhd/apps/uhd_app.py +++ b/gr-uhd/apps/uhd_app.py @@ -42,12 +42,25 @@ LONG_TPL = """{prefix} Motherboard: {mb_id} ({mb_serial}) """ class UHDApp(object): + " Base class for simple UHD-based applications " def __init__(self, prefix=None, args=None): self.prefix = prefix self.args = args self.verbose = args.verbose or 0 if self.args.sync == 'auto' and len(self.args.channels) > 1: self.args.sync = 'pps' + self.antenna = None + self.gain_range = None + self.samp_rate = None + self.has_lo_sensor = None + self.async_msgq = None + self.async_src = None + self.async_rcv = None + self.tr = None + self.gain = None + self.freq = None + self.channels = None + self.cpu_format = None def vprint(self, *args): """ @@ -78,7 +91,7 @@ class UHDApp(object): if info_pp['mb_serial'] == "": info_pp['mb_serial'] = "no serial" info_pp['db_subdev'] = usrp_info["{xx}_subdev_name".format(xx=tx_or_rx)] - info_pp['db_serial'] = ", " + usrp_info["{xx}_serial".format(xx=tx_or_rx)] + info_pp['db_serial'] = ", " + usrp_info["{xx}_serial".format(xx=tx_or_rx)] if info_pp['db_serial'] == "": info_pp['db_serial'] = "no serial" info_pp['subdev'] = self.usrp.get_subdev_spec(mboard) @@ -112,12 +125,12 @@ class UHDApp(object): """ Call this when USRP async metadata needs printing. """ - md = self.async_src.msg_to_async_metadata_t(msg) + metadata = self.async_src.msg_to_async_metadata_t(msg) print("[{prefix}] Channel: {chan} Time: {t} Event: {e}".format( prefix=self.prefix, - chan=md.channel, - t=md.time_spec.get_real_secs(), - e=md.event_code, + chan=metadata.channel, + t=metadata.time_spec.get_real_secs(), + e=metadata.event_code, )) def setup_usrp(self, ctor, args, cpu_format='fc32'): @@ -141,9 +154,13 @@ class UHDApp(object): if args.spec: for mb_idx in xrange(self.usrp.get_num_mboards()): self.usrp.set_subdev_spec(args.spec, mb_idx) - # Set the clock source: + # Set the clock and/or time source: if args.clock_source is not None: - self.usrp.set_clock_source(args.clock_source) + for mb_idx in xrange(self.usrp.get_num_mboards()): + self.usrp.set_clock_source(args.clock_source, mb_idx) + if args.time_source is not None: + for mb_idx in xrange(self.usrp.get_num_mboards()): + self.usrp.set_time_source(args.time_source, mb_idx) # Sampling rate: self.usrp.set_samp_rate(args.samp_rate) self.samp_rate = self.usrp.get_samp_rate() @@ -153,7 +170,7 @@ class UHDApp(object): if self.antenna is not None: for i, chan in enumerate(self.channels): if not self.antenna[i] in self.usrp.get_antennas(chan): - self.vprint("[ERROR] {} is not a valid antenna name for this USRP device!".format(ant)) + self.vprint("[ERROR] {} is not a valid antenna name for this USRP device!".format(self.antenna[i])) exit(1) self.usrp.set_antenna(self.antenna[i], chan) self.vprint("[{prefix}] Channel {chan}: Using antenna {ant}.".format( @@ -310,5 +327,7 @@ class UHDApp(object): default='auto', help="Set to 'pps' to sync devices to PPS") group.add_argument("--clock-source", help="Set the clock source; typically 'internal', 'external' or 'gpsdo'") + group.add_argument("--time-source", + help="Set the time source") return parser diff --git a/gr-uhd/apps/uhd_siggen_base.py b/gr-uhd/apps/uhd_siggen_base.py index 31415dac41..cc699dd145 100644 --- a/gr-uhd/apps/uhd_siggen_base.py +++ b/gr-uhd/apps/uhd_siggen_base.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # # Copyright 2008,2009,2011,2012,2015 Free Software Foundation, Inc. # @@ -23,6 +23,17 @@ Provide a base flow graph for USRP signal generators. """ +from __future__ import print_function +import math +try: + from uhd_app import UHDApp +except ImportError: + from gnuradio.uhd.uhd_app import UHDApp +from gnuradio import gr, uhd, eng_notation, eng_arg +from gnuradio import analog +from gnuradio import blocks +from gnuradio.gr.pubsub import pubsub + DESC_KEY = 'desc' SAMP_RATE_KEY = 'samp_rate' LINK_RATE_KEY = 'link_rate' @@ -39,26 +50,9 @@ FREQ_RANGE_KEY = 'freq_range' GAIN_RANGE_KEY = 'gain_range' TYPE_KEY = 'type' -# FIXME figure out if this can be deleted -#def setter(ps, key, val): ps[key] = val - -import sys -import math -import argparse -try: - from uhd_app import UHDApp -except ImportError: - from gnuradio.uhd.uhd_app import UHDApp -from gnuradio import gr, gru, uhd, eng_notation, eng_arg -from gnuradio import analog -from gnuradio import blocks -from gnuradio.gr.pubsub import pubsub -from gnuradio.eng_option import eng_option -from optparse import OptionParser - n2s = eng_notation.num_to_str -waveforms = { +WAVEFORMS = { analog.GR_CONST_WAVE : "Constant", analog.GR_SIN_WAVE : "Complex Sinusoid", analog.GR_GAUSSIAN : "Gaussian Noise", @@ -78,6 +72,11 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): UHDApp.__init__(self, args=args, prefix="UHD-SIGGEN") self.extra_sink = None + # Allocate some attributes + self._src1 = None + self._src2 = None + self._src = None + # Initialize device: self.setup_usrp( ctor=uhd.usrp_sink, @@ -121,13 +120,13 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self[key] = self[key] self[TYPE_KEY] = args.type #set type last - def set_samp_rate(self, sr): + def set_samp_rate(self, samp_rate): """ When sampling rate is updated, also update the signal sources. """ - self.vprint("Setting sampling rate to: {rate} Msps".format(rate=sr/1e6)) - self.usrp.set_samp_rate(sr) - sr = self.usrp.get_samp_rate() + self.vprint("Setting sampling rate to: {rate} Msps".format(rate=samp_rate/1e6)) + self.usrp.set_samp_rate(samp_rate) + samp_rate = self.usrp.get_samp_rate() if self[TYPE_KEY] in (analog.GR_SIN_WAVE, analog.GR_CONST_WAVE): self._src.set_sampling_freq(self[SAMP_RATE_KEY]) elif self[TYPE_KEY] == "2tone": @@ -138,10 +137,11 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self._src2.set_sampling_freq(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) else: return True # Waveform not yet set - self.vprint("Set sample rate to: {rate} Msps".format(rate=sr/1e6)) + self.vprint("Set sample rate to: {rate} Msps".format(rate=samp_rate/1e6)) return True def set_waveform_freq(self, freq): + " Change the frequency 1 of the generated waveform " if self[TYPE_KEY] == analog.GR_SIN_WAVE: self._src.set_frequency(freq) elif self[TYPE_KEY] == "2tone": @@ -152,6 +152,10 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): return True def set_waveform2_freq(self, freq): + """ + Change the frequency 2 of the generated waveform. This only + applies to 2-tone and sweep. + """ if freq is None: self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY] return @@ -161,19 +165,22 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self._src1.set_frequency(freq) return True - def set_waveform(self, type): + def set_waveform(self, waveform_type): + """ + Select the generated waveform + """ self.vprint("Selecting waveform...") self.lock() self.disconnect_all() - if type == analog.GR_SIN_WAVE or type == analog.GR_CONST_WAVE: + if waveform_type == analog.GR_SIN_WAVE or waveform_type == analog.GR_CONST_WAVE: self._src = analog.sig_source_c(self[SAMP_RATE_KEY], # Sample rate - type, # Waveform type + waveform_type, # Waveform waveform_type self[WAVEFORM_FREQ_KEY], # Waveform frequency self[AMPLITUDE_KEY], # Waveform amplitude self[WAVEFORM_OFFSET_KEY]) # Waveform offset - elif type == analog.GR_GAUSSIAN or type == analog.GR_UNIFORM: - self._src = analog.noise_source_c(type, self[AMPLITUDE_KEY]) - elif type == "2tone": + elif waveform_type == analog.GR_GAUSSIAN or waveform_type == analog.GR_UNIFORM: + self._src = analog.noise_source_c(waveform_type, self[AMPLITUDE_KEY]) + elif waveform_type == "2tone": self._src1 = analog.sig_source_c(self[SAMP_RATE_KEY], analog.GR_SIN_WAVE, self[WAVEFORM_FREQ_KEY], @@ -187,9 +194,9 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self[AMPLITUDE_KEY]/2.0, 0) self._src = blocks.add_cc() - self.connect(self._src1,(self._src,0)) - self.connect(self._src2,(self._src,1)) - elif type == "sweep": + self.connect(self._src1, (self._src, 0)) + self.connect(self._src2, (self._src, 1)) + elif waveform_type == "sweep": # rf freq is center frequency # waveform_freq is total swept width # waveform2_freq is sweep rate @@ -205,21 +212,21 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self._src = blocks.multiply_const_cc(self[AMPLITUDE_KEY]) self.connect(self._src1, self._src2, self._src) else: - raise RuntimeError("[UHD-SIGGEN] Unknown waveform type") - for c in xrange(len(self.channels)): - self.connect(self._src, (self.usrp, c)) + raise RuntimeError("[UHD-SIGGEN] Unknown waveform waveform_type") + for chan in xrange(len(self.channels)): + self.connect(self._src, (self.usrp, chan)) if self.extra_sink is not None: self.connect(self._src, self.extra_sink) self.unlock() - self.vprint("Set baseband modulation to:", waveforms[type]) - if type == analog.GR_SIN_WAVE: + self.vprint("Set baseband modulation to:", WAVEFORMS[waveform_type]) + if waveform_type == analog.GR_SIN_WAVE: self.vprint("Modulation frequency: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) self.vprint("Initial phase:", self[WAVEFORM_OFFSET_KEY]) - elif type == "2tone": + elif waveform_type == "2tone": self.vprint("Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) self.vprint("Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)) - elif type == "sweep": - self.vprint("Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0))) + elif waveform_type == "sweep": + self.vprint("Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0), n2s(self[WAVEFORM_FREQ_KEY]/2.0))) self.vprint("Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)) self.vprint("TX amplitude:", self[AMPLITUDE_KEY]) @@ -274,6 +281,7 @@ def setup_argparser(): return parser def main(): + " Go, go, go! " if gr.enable_realtime_scheduling() != gr.RT_OK: print("Note: failed to enable realtime scheduling, continuing") # Grab command line args and create top block @@ -281,8 +289,8 @@ def main(): parser = setup_argparser() args = parser.parse_args() tb = USRPSiggen(args) - except RuntimeError as e: - print(e) + except RuntimeError as ex: + print(ex) exit(1) tb.start() raw_input('[UHD-SIGGEN] Press Enter to quit:\n') diff --git a/gr-uhd/apps/uhd_siggen_gui b/gr-uhd/apps/uhd_siggen_gui index ab04ccc8e2..c5528f3777 100755 --- a/gr-uhd/apps/uhd_siggen_gui +++ b/gr-uhd/apps/uhd_siggen_gui @@ -1,6 +1,6 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python # -# Copyright 2015 Free Software Foundation, Inc. +# Copyright 2015-2016 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -32,13 +32,14 @@ Signal Generator App # Generated: Sun Jun 28 17:21:28 2015 ################################################## +from __future__ import print_function import sip import sys import threading import time from distutils.version import StrictVersion from PyQt4 import Qt -from PyQt4.QtCore import QObject, pyqtSlot +from PyQt4.QtCore import pyqtSlot from gnuradio import analog from gnuradio import eng_notation from gnuradio import gr @@ -69,9 +70,9 @@ class uhd_siggen_gui(Qt.QWidget): Qt.QWidget.__init__(self) self.setWindowTitle("UHD Signal Generator") try: - self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) + self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) except: - pass + pass self.top_scroll_layout = Qt.QVBoxLayout() self.setLayout(self.top_scroll_layout) self.top_scroll = Qt.QScrollArea() @@ -90,8 +91,8 @@ class uhd_siggen_gui(Qt.QWidget): # Widgets + Controls ################################################## ### Waveform Selector - self._waveform_options = uhd_siggen.waveforms.keys() - self._waveform_labels = uhd_siggen.waveforms.values() + self._waveform_options = uhd_siggen.WAVEFORMS.keys() + self._waveform_labels = uhd_siggen.WAVEFORMS.values() self._waveform_group_box = Qt.QGroupBox("Waveform") self._waveform_box = Qt.QHBoxLayout() class variable_chooser_button_group(Qt.QButtonGroup): @@ -259,11 +260,12 @@ class uhd_siggen_gui(Qt.QWidget): self._lo_locked_probe_0_tool_bar.addWidget(self._lo_locked_probe_0_label) self.top_grid_layout.addWidget(self._lo_locked_probe_0_tool_bar, 8,0,1,1) def _chan0_lo_locked_probe(): + " Monitor lock status of LO on channel 0 " while True: - val = all([self.usrp.get_sensor('lo_locked', c).to_bool() for c in range(len(self._sg.channels))]) try: + val = all([self.usrp.get_sensor('lo_locked', c).to_bool() for c in range(len(self._sg.channels))]) self.set_chan0_lo_locked(val) - except AttributeError: + except: pass time.sleep(.1) _chan0_lo_locked_thread = threading.Thread(target=_chan0_lo_locked_probe) @@ -366,8 +368,8 @@ class uhd_siggen_gui(Qt.QWidget): self.freq_fine + self.freq_coarse, self.lo_offset ) - for idx, c in enumerate(self._sg.channels): - tune_res = self.usrp.set_center_freq(tune_req, c) + for idx, chan in enumerate(self._sg.channels): + tune_res = self.usrp.set_center_freq(tune_req, chan) if idx == 0: self.set_label_dsp_freq(tune_res.actual_dsp_freq) self.set_label_rf_freq(tune_res.actual_rf_freq) @@ -446,7 +448,7 @@ def main(): """ Go, go, go! """ parser = setup_parser() args = parser.parse_args() - if(StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0")): + if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"): Qt.QApplication.setGraphicsSystem(gr.prefs().get_string('qtgui', 'style', 'raster')) qapp = Qt.QApplication(sys.argv) siggen_gui = uhd_siggen_gui(args) @@ -457,14 +459,17 @@ def main(): qapp.exec_() siggen_gui = None #to clean up Qt widgets -if __name__ == '__main__': +def x11_init_threads(): + " If on X11, init threads " import ctypes - import sys if sys.platform.startswith('linux'): try: x11 = ctypes.cdll.LoadLibrary('libX11.so') x11.XInitThreads() except: print("Warning: failed to XInitThreads()") + +if __name__ == '__main__': + x11_init_threads() main() |