diff options
-rw-r--r-- | gr-uhd/apps/msgq_runner.py | 1 | ||||
-rw-r--r-- | gr-uhd/apps/uhd_app.py | 77 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_fft | 156 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_rx_cfile | 76 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_rx_nogui | 36 | ||||
-rw-r--r-- | gr-uhd/apps/uhd_siggen_base.py | 66 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_siggen_gui | 84 | ||||
-rwxr-xr-x | gr-uhd/examples/python/freq_hopping.py | 72 | ||||
-rw-r--r-- | gr-uhd/grc/gen_uhd_usrp_blocks.py | 6 | ||||
-rw-r--r-- | gr-uhd/python/uhd/__init__.py | 47 | ||||
-rw-r--r-- | gr-uhd/python/uhd/qa_uhd.py | 1 |
11 files changed, 384 insertions, 238 deletions
diff --git a/gr-uhd/apps/msgq_runner.py b/gr-uhd/apps/msgq_runner.py index 31bebcf0df..1fe86f1ad1 100644 --- a/gr-uhd/apps/msgq_runner.py +++ b/gr-uhd/apps/msgq_runner.py @@ -32,6 +32,7 @@ To determine if the runner has exited, call exited() on the object. from gnuradio import gr import threading + class msgq_runner(threading.Thread): def __init__(self, msgq, callback, exit_on_error=False): diff --git a/gr-uhd/apps/uhd_app.py b/gr-uhd/apps/uhd_app.py index 65b35ac736..55c2a71d2f 100644 --- a/gr-uhd/apps/uhd_app.py +++ b/gr-uhd/apps/uhd_app.py @@ -18,7 +18,7 @@ from gnuradio import eng_arg from gnuradio import uhd from gnuradio import gr -COMMAND_DELAY = .2 # Seconds +COMMAND_DELAY = .2 # Seconds COMPACT_TPL = "{mb_id} ({mb_serial}), {db_subdev} ({subdev}, {ant}{db_serial})" LONG_TPL = """{prefix} Motherboard: {mb_id} ({mb_serial}) @@ -30,11 +30,13 @@ LONG_TPL = """{prefix} Motherboard: {mb_id} ({mb_serial}) # PyLint can't reliably detect C++ exports in modules, so let's disable that # pylint: disable=no-member + class UHDApp: GAIN_TYPE_GAIN = 'dB' GAIN_TYPE_POWER = 'power_dbm' " Base class for simple UHD-based applications " + def __init__(self, prefix=None, args=None): self.prefix = prefix self.args = args @@ -42,7 +44,7 @@ class UHDApp: if self.args.sync == 'auto' and len(self.args.channels) > 1: self.args.sync = 'pps' self.antenna = None - self.gain_range = None # Can also be power range + self.gain_range = None # Can also be power range self.samp_rate = None self.has_lo_sensor = None self.async_msgq = None @@ -87,8 +89,10 @@ class UHDApp: info_pp['mb_serial'] = usrp_info['mboard_serial'] 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_subdev'] = usrp_info["{xx}_subdev_name".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) @@ -173,11 +177,13 @@ class UHDApp: self.samp_rate = self.usrp.get_samp_rate() self.vprint("Using sampling rate: {rate}".format(rate=self.samp_rate)) # Set the antenna: - self.antenna = self.normalize_sel("channels", "antenna", len(args.channels), args.antenna) + self.antenna = self.normalize_sel( + "channels", "antenna", len(args.channels), args.antenna) if self.antenna is not None: for i, chan in enumerate(self.channels): if not self.antenna[i] in self.usrp.get_antennas(i): - print("[ERROR] {} is not a valid antenna name for this USRP device!".format(self.antenna[i])) + print("[ERROR] {} is not a valid antenna name for this USRP device!".format( + self.antenna[i])) sys.exit(1) self.usrp.set_antenna(self.antenna[i], i) self.vprint("[{prefix}] Channel {chan}: Using antenna {ant}.".format( @@ -207,14 +213,16 @@ class UHDApp: self.has_lo_sensor = 'lo_locked' in self.usrp.get_sensor_names() # Set LO export and LO source operation if (args.lo_export is not None) and (args.lo_source is not None): - self.lo_source = self.normalize_sel("channels", "lo-source", len(self.channels), args.lo_source) - self.lo_export = self.normalize_sel("channels", "lo-export", len(self.channels), args.lo_export) + self.lo_source = self.normalize_sel( + "channels", "lo-source", len(self.channels), args.lo_source) + self.lo_export = self.normalize_sel( + "channels", "lo-export", len(self.channels), args.lo_export) self.lo_source_channel = None for chan, lo_source, lo_export in zip(self.channels, self.lo_source, self.lo_export): if (lo_source == "None") or (lo_export == "None"): continue if lo_export == "True": - #If channel is LO source set frequency and store response + # If channel is LO source set frequency and store response self.usrp.set_lo_export_enabled(True, uhd.ALL_LOS, chan) if lo_source == "internal": self.lo_source_channel = chan @@ -225,7 +233,7 @@ class UHDApp: if getattr(args, 'lo_offset', None) is not None: treq = uhd.tune_request( target_freq=args.freq, - rf_freq=args.freq+args.lo_offset, + rf_freq=args.freq + args.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL, dsp_freq=tune_resp.actual_dsp_freq, dsp_freq_policy=uhd.tune_request.POLICY_MANUAL) @@ -251,7 +259,8 @@ class UHDApp: self.usrp.set_command_time(cmd_time, mb_idx) command_time_set = True except RuntimeError: - sys.stderr.write('[{prefix}] [WARNING] Failed to set command times.\n'.format(prefix=self.prefix)) + sys.stderr.write('[{prefix}] [WARNING] Failed to set command times.\n'.format( + prefix=self.prefix)) for i, chan in enumerate(self.channels): self.tr = self.usrp.set_center_freq(treq, i) if self.tr is None: @@ -268,7 +277,8 @@ class UHDApp: if args.show_async_msg: self.async_msgq = gr.msg_queue(0) self.async_src = uhd.amsg_source("", self.async_msgq) - self.async_rcv = uhd.msgq_runner(self.async_msgq, self.async_callback) + self.async_rcv = uhd.msgq_runner( + self.async_msgq, self.async_callback) def set_gain(self, gain): """ @@ -278,7 +288,8 @@ class UHDApp: """ if gain is None: if self.args.verbose: - self.vprint("Defaulting to mid-point gains:".format(prefix=self.prefix)) + self.vprint( + "Defaulting to mid-point gains:".format(prefix=self.prefix)) for i, chan in enumerate(self.channels): self.usrp.set_normalized_gain(.5, i) if self.args.verbose: @@ -304,7 +315,8 @@ class UHDApp: """ Safely tune all channels to freq. """ - self.vprint("Tuning all channels to {freq} MHz.".format(freq=freq / 1e6)) + self.vprint( + "Tuning all channels to {freq} MHz.".format(freq=freq / 1e6)) # Set frequency (tune request takes lo_offset): if hasattr(self.args, 'lo_offset') and self.args.lo_offset is not None: treq = uhd.tune_request(freq, self.args.lo_offset) @@ -316,7 +328,7 @@ class UHDApp: if getattr(self.args, 'lo_offset', None) is not None: treq = uhd.tune_request( target_freq=freq, - rf_freq=freq+self.args.lo_offset, + rf_freq=freq + self.args.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL, dsp_freq=tune_resp.actual_dsp_freq, dsp_freq_policy=uhd.tune_request.POLICY_MANUAL) @@ -340,7 +352,8 @@ class UHDApp: self.usrp.set_command_time(cmd_time, mb_idx) command_time_set = True except RuntimeError: - sys.stderr.write('[{prefix}] [WARNING] Failed to set command times.\n'.format(prefix=self.prefix)) + sys.stderr.write('[{prefix}] [WARNING] Failed to set command times.\n'.format( + prefix=self.prefix)) for i, chan in enumerate(self.channels): self.tr = self.usrp.set_center_freq(treq, i) if self.tr is None: @@ -354,16 +367,17 @@ class UHDApp: self.vprint("Syncing channels...".format(prefix=self.prefix)) time.sleep(COMMAND_DELAY) self.freq = self.usrp.get_center_freq(0) - self.vprint("First channel has freq: {freq} MHz.".format(freq=self.freq / 1e6)) + self.vprint("First channel has freq: {freq} MHz.".format( + freq=self.freq / 1e6)) @staticmethod def setup_argparser( - parser=None, - description='USRP App', - allow_mimo=True, - tx_or_rx="", - skip_freq=False, - ): + parser=None, + description='USRP App', + allow_mimo=True, + tx_or_rx="", + skip_freq=False, + ): """ Create or amend an argument parser with typical USRP options. """ @@ -374,19 +388,22 @@ class UHDApp: try: return [int(x.strip()) for x in string.split(",")] except ValueError: - raise argparse.ArgumentTypeError("Not a comma-separated list: {string}".format(string=string)) + raise argparse.ArgumentTypeError( + "Not a comma-separated list: {string}".format(string=string)) if parser is None: parser = argparse.ArgumentParser( description=description, ) tx_or_rx = tx_or_rx.strip() + " " group = parser.add_argument_group('USRP Arguments') - group.add_argument("-a", "--args", default="", help="UHD device address args") + group.add_argument("-a", "--args", default="", + help="UHD device address args") group.add_argument( "--spec", help="Subdevice(s) of UHD device where appropriate. " "Use a comma-separated list to set different boards to different specs.") - group.add_argument("-A", "--antenna", help="Select {xx}antenna(s) where appropriate".format(xx=tx_or_rx)) + group.add_argument( + "-A", "--antenna", help="Select {xx}antenna(s) where appropriate".format(xx=tx_or_rx)) group.add_argument("-s", "--samp-rate", type=eng_arg.eng_float, default=1e6, help="Sample rate") group.add_argument("-g", "--gain", type=eng_arg.eng_float, default=None, @@ -403,7 +420,7 @@ class UHDApp: group.add_argument("--lo-offset", type=eng_arg.eng_float, default=0.0, help="Set daughterboard LO offset to OFFSET [default=hw default]") if allow_mimo: - group.add_argument("-c", "--channels", default=[0,], type=cslist, + group.add_argument("-c", "--channels", default=[0, ], type=cslist, help="Select {xx} Channels".format(xx=tx_or_rx)) group.add_argument( "--lo-export", @@ -415,8 +432,10 @@ class UHDApp: "for each channel with a comma-separated list. None skips this channel.") group.add_argument("--otw-format", choices=['sc16', 'sc12', 'sc8'], default='sc16', help="Choose over-the-wire data format") - group.add_argument("--stream-args", default="", help="Set additional stream arguments") - group.add_argument("-v", "--verbose", action="count", help="Use verbose console output") + group.add_argument("--stream-args", default="", + help="Set additional stream arguments") + group.add_argument("-v", "--verbose", action="count", + help="Use verbose console output") group.add_argument("--show-async-msg", action="store_true", help="Show asynchronous message notifications from UHD") group.add_argument("--sync", choices=('default', 'pps', 'auto'), diff --git a/gr-uhd/apps/uhd_fft b/gr-uhd/apps/uhd_fft index 05f2ee3008..fc5e9276c2 100755 --- a/gr-uhd/apps/uhd_fft +++ b/gr-uhd/apps/uhd_fft @@ -42,7 +42,7 @@ import time import math import signal from PyQt5 import Qt -import sip # Needs to be imported after PyQt5, could fail otherwise +import sip # Needs to be imported after PyQt5, could fail otherwise from gnuradio import eng_notation from gnuradio import eng_arg from gnuradio import gr @@ -60,10 +60,12 @@ except ImportError: # pylint: disable=c-extension-no-member # pylint: disable=no-member + class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): """ Simple UHD Spectrum Analyzer / Scope App. """ + def __init__(self, args): UHDApp.__init__(self, args=args, prefix="UHD FFT") gr.top_block.__init__(self, "UHD FFT") @@ -137,13 +139,15 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self._ant_options = self.usrp.get_antennas(0) for c in range(len(self.channels)): self.usrp.set_bandwidth(self.samp_rate + abs(self.lo_offset), c) - self.usrp_device_info = self.get_usrp_info_string(compact=True, tx_or_rx='rx') + self.usrp_device_info = self.get_usrp_info_string( + compact=True, tx_or_rx='rx') ### Now set up the GUI widgets: ##################################### # Sampling rate: self._samp_rate__tool_bar = Qt.QToolBar(self) self._samp_rate__tool_bar.addWidget(Qt.QLabel("Sampling Rate: ")) - self._samp_rate__line_edit = Qt.QLineEdit(eng_notation.num_to_str(self.samp_rate)) + self._samp_rate__line_edit = Qt.QLineEdit( + eng_notation.num_to_str(self.samp_rate)) self._samp_rate__tool_bar.addWidget(self._samp_rate__line_edit) self._samp_rate__line_edit.returnPressed.connect( lambda: self.set_samp_rate(eng_notation.str_to_num( @@ -190,28 +194,32 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): for label in self._ant_labels: self._ant_combo_box.addItem(label) self._ant_callback = \ - lambda i: Qt.QMetaObject.invokeMethod( - self._ant_combo_box, - "setCurrentIndex", - Qt.Q_ARG("int", self._ant_options.index(i))) + lambda i: Qt.QMetaObject.invokeMethod( + self._ant_combo_box, + "setCurrentIndex", + Qt.Q_ARG("int", self._ant_options.index(i))) self._ant_callback(self.antenna) - self._ant_combo_box.currentIndexChanged.connect(lambda i: self.set_ant(self._ant_options[i])) + self._ant_combo_box.currentIndexChanged.connect( + lambda i: self.set_ant(self._ant_options[i])) self.top_grid_layout.addWidget(self._ant_tool_bar, 4, 2, 1, 2) # Device + UHD info: self._usrp_device_info_tool_bar = Qt.QToolBar(self) self._usrp_device_info_formatter = lambda x: x - self._usrp_device_info_tool_bar.addWidget(Qt.QLabel("Device Information: ")) + self._usrp_device_info_tool_bar.addWidget( + Qt.QLabel("Device Information: ")) self._usrp_device_info_label = Qt.QLabel( str(self._usrp_device_info_formatter(self.usrp_device_info))) self._usrp_device_info_tool_bar.addWidget(self._usrp_device_info_label) - self.top_grid_layout.addWidget(self._usrp_device_info_tool_bar, 1, 2, 1, 2) + self.top_grid_layout.addWidget( + self._usrp_device_info_tool_bar, 1, 2, 1, 2) self._uhd_version_info_tool_bar = Qt.QToolBar(self) self._uhd_version_info_formatter = lambda x: x self._uhd_version_info_tool_bar.addWidget(Qt.QLabel("UHD Version: ")) self._uhd_version_info_label = Qt.QLabel( str(self._uhd_version_info_formatter(self.uhd_version_info))) self._uhd_version_info_tool_bar.addWidget(self._uhd_version_info_label) - self.top_grid_layout.addWidget(self._uhd_version_info_tool_bar, 1, 0, 1, 2) + self.top_grid_layout.addWidget( + self._uhd_version_info_tool_bar, 1, 0, 1, 2) ### Plot GUIs ####################################################### widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "green", "cyan", "magenta", "black", "yellow", @@ -221,48 +229,53 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] self.display = Qt.QTabWidget() self.display_widget_0 = Qt.QWidget() - self.display_layout_0 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.display_widget_0) + self.display_layout_0 = Qt.QBoxLayout( + Qt.QBoxLayout.TopToBottom, self.display_widget_0) self.display_grid_layout_0 = Qt.QGridLayout() self.display_layout_0.addLayout(self.display_grid_layout_0) self.display.addTab(self.display_widget_0, "Spectrum") self.display_widget_1 = Qt.QWidget() - self.display_layout_1 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.display_widget_1) + self.display_layout_1 = Qt.QBoxLayout( + Qt.QBoxLayout.TopToBottom, self.display_widget_1) self.display_grid_layout_1 = Qt.QGridLayout() self.display_layout_1.addLayout(self.display_grid_layout_1) self.display.addTab(self.display_widget_1, "Waterfall") self.display_widget_2 = Qt.QWidget() - self.display_layout_2 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.display_widget_2) + self.display_layout_2 = Qt.QBoxLayout( + Qt.QBoxLayout.TopToBottom, self.display_widget_2) self.display_grid_layout_2 = Qt.QGridLayout() self.display_layout_2.addLayout(self.display_grid_layout_2) self.display.addTab(self.display_widget_2, "Scope") self.top_grid_layout.addWidget(self.display, 0, 0, 1, 4) self.qtgui_waterfall_sink_x_0 = qtgui.waterfall_sink_c( - self.fft_size, #size - fft.window.WIN_BLACKMAN_hARRIS, #wintype - self.freq, #fc - self.samp_rate, #bw - "", #name - len(self.channels), #number of inputs - None # parent + self.fft_size, # size + fft.window.WIN_BLACKMAN_hARRIS, # wintype + self.freq, # fc + self.samp_rate, # bw + "", # name + len(self.channels), # number of inputs + None # parent ) self.qtgui_waterfall_sink_x_0.set_update_time(self.update_rate) self.qtgui_waterfall_sink_x_0.enable_grid(False) self.qtgui_waterfall_sink_x_0.disable_legend() - alpha = 10.**(len(self.channels)-1) + alpha = 10.**(len(self.channels) - 1) for i in range(len(self.channels)): - self.qtgui_waterfall_sink_x_0.set_line_label(i, "Channel {0}".format(i)) + self.qtgui_waterfall_sink_x_0.set_line_label( + i, "Channel {0}".format(i)) self.qtgui_waterfall_sink_x_0.set_color_map(i, 0) self.qtgui_waterfall_sink_x_0.set_line_alpha(i, alpha) self.qtgui_waterfall_sink_x_0.set_intensity_range(-90, 10) self._qtgui_waterfall_sink_x_0_win = sip.wrapinstance( self.qtgui_waterfall_sink_x_0.qwidget(), Qt.QWidget) - self.display_grid_layout_1.addWidget(self._qtgui_waterfall_sink_x_0_win, 0, 0, 1, 4) + self.display_grid_layout_1.addWidget( + self._qtgui_waterfall_sink_x_0_win, 0, 0, 1, 4) self.qtgui_time_sink_x_0 = qtgui.time_sink_c( - 1024, #size - self.samp_rate, #samp_rate - "", #name - len(self.channels), #number of inputs - None # parent + 1024, # size + self.samp_rate, # samp_rate + "", # name + len(self.channels), # number of inputs + None # parent ) self.qtgui_time_sink_x_0.set_update_time(self.update_rate) self.qtgui_time_sink_x_0.set_y_axis(-1, 1) @@ -274,11 +287,13 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self.qtgui_time_sink_x_0.enable_grid(False) self.qtgui_time_sink_x_0.enable_control_panel(True) self.qtgui_time_sink_x_0.disable_legend() - for i in range(2*len(self.channels)): + for i in range(2 * len(self.channels)): if i % 2 == 0: - self.qtgui_time_sink_x_0.set_line_label(i, "Re{{Channel {0}}}".format(i//2)) + self.qtgui_time_sink_x_0.set_line_label( + i, "Re{{Channel {0}}}".format(i // 2)) else: - self.qtgui_time_sink_x_0.set_line_label(i, "Im{{Channel {0}}}".format(i//2)) + self.qtgui_time_sink_x_0.set_line_label( + i, "Im{{Channel {0}}}".format(i // 2)) self.qtgui_time_sink_x_0.set_line_width(i, widths[i]) self.qtgui_time_sink_x_0.set_line_color(i, colors[i]) self.qtgui_time_sink_x_0.set_line_style(i, styles[i]) @@ -286,15 +301,16 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_0_win = sip.wrapinstance( self.qtgui_time_sink_x_0.qwidget(), Qt.QWidget) - self.display_grid_layout_2.addWidget(self._qtgui_time_sink_x_0_win, 0, 0, 1, 4) + self.display_grid_layout_2.addWidget( + self._qtgui_time_sink_x_0_win, 0, 0, 1, 4) self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( - self.fft_size, #size - fft.window.WIN_BLACKMAN_hARRIS, #wintype - self.freq, #fc - self.samp_rate, #bw - "", #name - len(self.channels), #number of inputs - None #parent + self.fft_size, # size + fft.window.WIN_BLACKMAN_hARRIS, # wintype + self.freq, # fc + self.samp_rate, # bw + "", # name + len(self.channels), # number of inputs + None # parent ) self.qtgui_freq_sink_x_0.set_update_time(self.update_rate) self.qtgui_freq_sink_x_0.set_y_axis(-100, 10) @@ -302,7 +318,8 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self.qtgui_freq_sink_x_0.set_y_label("Relative Gain", "dB") else: self.qtgui_freq_sink_x_0.set_y_label("Received Power", "dBm") - self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") + self.qtgui_freq_sink_x_0.set_trigger_mode( + qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0.enable_autoscale(True) self.qtgui_freq_sink_x_0.enable_grid(True) self.qtgui_freq_sink_x_0.set_fft_average(self.fft_average) @@ -318,12 +335,14 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_win = sip.wrapinstance( self.qtgui_freq_sink_x_0.qwidget(), Qt.QWidget) - self.display_grid_layout_0.addWidget(self._qtgui_freq_sink_x_0_win, 0, 0, 1, 4) + self.display_grid_layout_0.addWidget( + self._qtgui_freq_sink_x_0_win, 0, 0, 1, 4) + def _freeze_scaling(widget, sleep_time): time.sleep(sleep_time) widget.enable_autoscale(False) _freeze_fft_thread = threading.Thread( - target=lambda: _freeze_scaling(self.qtgui_freq_sink_x_0, .5/self.fft_average)) + target=lambda: _freeze_scaling(self.qtgui_freq_sink_x_0, .5 / self.fft_average)) _freeze_fft_thread.daemon = True _freeze_fft_thread.start() _freeze_scope_thread = threading.Thread( @@ -338,11 +357,11 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self.display_layout_phase.addLayout(self.display_grid_layout_phase) self.display.addTab(self.display_widget_phase, "Rel. Phase") self.qtgui_phase_plot = qtgui.time_sink_f( - 1024, #size - self.samp_rate, #samp_rate - "", #name + 1024, # size + self.samp_rate, # samp_rate + "", # name len(self.channels) - 1, - None # parent + None # parent ) self.qtgui_phase_plot.set_update_time(self.update_rate) self.qtgui_phase_plot.set_y_axis(-3.5, 3.5) @@ -356,7 +375,7 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self.qtgui_phase_plot.disable_legend() for i in range(len(self.channels) - 1): self.qtgui_phase_plot.set_line_label( - i, "Phase Delta Channels {0}/{1}".format(i, i+1)) + i, "Phase Delta Channels {0}/{1}".format(i, i + 1)) self.qtgui_phase_plot.set_line_width(i, widths[i]) self.qtgui_phase_plot.set_line_color(i, colors[i]) self.qtgui_phase_plot.set_line_style(i, styles[i]) @@ -364,14 +383,17 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self.qtgui_phase_plot.set_line_alpha(i, alphas[i]) self._qtgui_phase_plot_win = sip.wrapinstance( self.qtgui_phase_plot.qwidget(), Qt.QWidget) - self.display_grid_layout_phase.addWidget(self._qtgui_phase_plot_win, 0, 0, 1, 4) + self.display_grid_layout_phase.addWidget( + self._qtgui_phase_plot_win, 0, 0, 1, 4) ### Other widgets ################################################### self._lo_locked_probe_tool_bar = Qt.QToolBar(self) - self._lo_locked_probe_formatter = lambda x: {True: 'Yes', False: 'No'}[x] + self._lo_locked_probe_formatter = lambda x: { + True: 'Yes', False: 'No'}[x] if self.has_lo_sensor: self._lo_locked_probe_tool_bar.addWidget(Qt.QLabel("LO locked: ")) self._lo_locked_probe_label = Qt.QLabel( str(self._lo_locked_probe_formatter(self.lo_locked_probe))) + def _chan0_lo_locked_probe(): while self.has_lo_sensor: self.chan0_lo_locked = self.usrp.get_sensor('lo_locked') @@ -382,14 +404,18 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): except AttributeError: pass time.sleep(1.0 / (10)) - _chan0_lo_locked_thread = threading.Thread(target=_chan0_lo_locked_probe) + _chan0_lo_locked_thread = threading.Thread( + target=_chan0_lo_locked_probe) _chan0_lo_locked_thread.daemon = True _chan0_lo_locked_thread.start() else: - self._lo_locked_probe_tool_bar.addWidget(Qt.QLabel("No LO lock sensor available.")) + self._lo_locked_probe_tool_bar.addWidget( + Qt.QLabel("No LO lock sensor available.")) self._lo_locked_probe_label = Qt.QLabel("") self._lo_locked_probe_tool_bar.addWidget(self._lo_locked_probe_label) - self.top_grid_layout.addWidget(self._lo_locked_probe_tool_bar, 4, 0, 1, 2) + self.top_grid_layout.addWidget( + self._lo_locked_probe_tool_bar, 4, 0, 1, 2) + def _current_freq_probe(): while True: val = self.usrp.get_center_freq(0) @@ -437,19 +463,21 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): else: self.connect((self.usrp, idx), (self.qtgui_freq_sink_x_0, idx)) self.connect((self.usrp, idx), (self.qtgui_time_sink_x_0, idx)) - self.connect((self.usrp, idx), (self.qtgui_waterfall_sink_x_0, idx)) + self.connect((self.usrp, idx), + (self.qtgui_waterfall_sink_x_0, idx)) if args.phase_relations and len(self.channels) > 1: for idx in range(len(self.channels[:-1])): self.connect_phase_plot( (self.usrp, idx), - (self.usrp, idx+1), + (self.usrp, idx + 1), (self.qtgui_phase_plot, idx) ) def connect_phase_plot(self, src_port1, src_port2, dst_port): " Calculate relative phase between two src ports and send it dst_port " multiplier = blocks.multiply_cc() - self.connect(src_port1, (multiplier, 0), blocks.complex_to_arg(), dst_port) + self.connect(src_port1, (multiplier, 0), + blocks.complex_to_arg(), dst_port) self.connect(src_port2, blocks.conjugate_cc(), (multiplier, 1)) # This is a Qt name: @@ -484,9 +512,11 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): self._freq_line_edit, "setText", Qt.Q_ARG("QString", eng_notation.num_to_str(self.freq)) ) - self.qtgui_waterfall_sink_x_0.set_frequency_range(self.freq, self.samp_rate) + self.qtgui_waterfall_sink_x_0.set_frequency_range( + self.freq, self.samp_rate) if tune_source != 'freqsink_msg': - self.qtgui_freq_sink_x_0.set_frequency_range(self.freq, self.samp_rate) + self.qtgui_freq_sink_x_0.set_frequency_range( + self.freq, self.samp_rate) if self.gain_type == self.GAIN_TYPE_POWER: self.gain = self.get_gain_or_power() self._gain__win.d_widget.setValue(self.gain) @@ -501,7 +531,8 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): ) self.qtgui_freq_sink_x_0.set_frequency_range(self.freq, self.samp_rate) self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate) - self.qtgui_waterfall_sink_x_0.set_frequency_range(self.freq, self.samp_rate) + self.qtgui_waterfall_sink_x_0.set_frequency_range( + self.freq, self.samp_rate) self.usrp.set_samp_rate(self.samp_rate) for c in range(len(self.channels)): self.usrp.set_bandwidth(self.samp_rate + abs(self.lo_offset), c) @@ -541,7 +572,7 @@ class uhd_fft(UHDApp, gr.top_block, Qt.QWidget): Return the input to the power scaler as a function of the current power reference level. """ - return 10**(self.gain/20) + return 10**(self.gain / 20) def setup_argparser(): @@ -560,7 +591,8 @@ def setup_argparser(): group.add_argument("--avg-alpha", type=float, default=None, help="Specify FFT average alpha (overrides --fft-average)") group.add_argument("--update-rate", dest="update_rate", - type=eng_arg.eng_float, default=eng_notation.num_to_str(.1), + type=eng_arg.eng_float, default=eng_notation.num_to_str( + .1), help="Set GUI widget update period in seconds") group.add_argument("--phase-relations", action="store_true", help="Plot relative phases between multiple channels") @@ -578,6 +610,7 @@ def main(): top_block.show() # Make sure SIGINT/SIGTERM handling is enabled # pylint: disable=unused-argument + def sig_handler(sig=None, frame=None): top_block.stop() top_block.wait() @@ -589,5 +622,6 @@ def main(): timer.timeout.connect(lambda: None) qapp.exec_() + if __name__ == '__main__': main() diff --git a/gr-uhd/apps/uhd_rx_cfile b/gr-uhd/apps/uhd_rx_cfile index 2ed83c47f0..b6dbb15ccd 100755 --- a/gr-uhd/apps/uhd_rx_cfile +++ b/gr-uhd/apps/uhd_rx_cfile @@ -27,26 +27,31 @@ from optparse import OptionParser n2s = eng_notation.num_to_str COMMAND_DELAY = .2 + class rx_cfile_block(gr.top_block): """ Simple flowgraph that streams from USRP source to file. """ + def __init__(self, options, filename): gr.top_block.__init__(self) # Dissect the channel list: try: - self.channels = [int(x.strip()) for x in options.channels.split(",")] + self.channels = [int(x.strip()) + for x in options.channels.split(",")] except ValueError: - sys.stderr.write("[UHD_RX] [ERROR] Invalid channel list: {}".format(options.channels)) + sys.stderr.write( + "[UHD_RX] [ERROR] Invalid channel list: {}".format(options.channels)) exit(1) # Create file names: if len(self.channels) == 1: - self.filenames = [filename,] + self.filenames = [filename, ] else: base, ext = os.path.splitext(filename) self.filenames = [] for i in range(len(self.channels)): - self.filenames.append("{base}.{num}{ext}".format(base=base, num=i, ext=ext)) + self.filenames.append( + "{base}.{num}{ext}".format(base=base, num=i, ext=ext)) # Check CPU format: self.cpu_format = 'fc32' self.item_size = gr.sizeof_gr_complex @@ -78,7 +83,7 @@ class rx_cfile_block(gr.top_block): )) exit(1) if len(self.antenna) == 1 and len(self.channels) > 1: - self.antenna = [self.antenna[0],] * len(self.channels) + self.antenna = [self.antenna[0], ] * len(self.channels) for i, chan in enumerate(self.channels): self._u.set_antenna(self.antenna[i], chan) if options.verbose: @@ -93,7 +98,8 @@ class rx_cfile_block(gr.top_block): print("[UHD_RX] Defaulting to mid-point gains:") for chan in self.channels: self._u.set_normalized_gain(.5, chan) - print("[UHD_RX] Channel {chan} gain: {g} dB".format(chan=chan, g=self._u.get_gain(chan))) + print("[UHD_RX] Channel {chan} gain: {g} dB".format( + chan=chan, g=self._u.get_gain(chan))) else: for chan in self.channels: if options.normalized_gain: @@ -117,11 +123,13 @@ class rx_cfile_block(gr.top_block): self._u.set_command_time(cmd_time, mb_idx) command_time_set = True except RuntimeError: - sys.stderr.write('[UHD_RX] [WARNING] Failed to set command times.\n') + sys.stderr.write( + '[UHD_RX] [WARNING] Failed to set command times.\n') for chan in self.channels: tr = self._u.set_center_freq(treq, chan) if tr == None: - sys.stderr.write('[UHD_RX] [ERROR] Failed to set center frequency on channel {chan}\n'.format(chan=chan)) + sys.stderr.write( + '[UHD_RX] [ERROR] Failed to set center frequency on channel {chan}\n'.format(chan=chan)) exit(1) if command_time_set: for mb_idx in range(self._u.get_num_mboards()): @@ -135,16 +143,18 @@ class rx_cfile_block(gr.top_block): if options.metafile: # store additional metadata extras = pmt.make_dict() - extras = pmt.dict_add(extras, pmt.intern("rx_gain"), pmt.from_double(gain)) + extras = pmt.dict_add(extras, pmt.intern( + "rx_gain"), pmt.from_double(gain)) extras_str = pmt.serialize_str(extras) self._sink.append(blocks.file_meta_sink( - self.item_size, self.filenames[i], - samp_rate, 1, - self.meta_file_type, True, - 1000000, extras_str, False + self.item_size, self.filenames[i], + samp_rate, 1, + self.meta_file_type, True, + 1000000, extras_str, False )) else: - self._sink.append(blocks.file_sink(self.item_size, self.filenames[i])) + self._sink.append(blocks.file_sink( + self.item_size, self.filenames[i])) # Create head block if needed and wire it up: if options.nsamples is None: self.connect((self._u, i), self._sink[i]) @@ -167,40 +177,51 @@ class rx_cfile_block(gr.top_block): rx_serial = info["rx_serial"] rx_antenna = info["rx_antenna"] rx_subdev_spec = info["rx_subdev_spec"] - print("[UHD_RX] Motherboard: %s (%s)" % (mboard_id, mboard_serial)) + print("[UHD_RX] Motherboard: %s (%s)" % + (mboard_id, mboard_serial)) if "B200" in mboard_id or "B210" in mboard_id or "E310" in mboard_id: - print("[UHD_RX] Daughterboard: %s (%s, %s)" % (mboard_id, rx_antenna, rx_subdev_spec)) + print("[UHD_RX] Daughterboard: %s (%s, %s)" % + (mboard_id, rx_antenna, rx_subdev_spec)) else: - print("[UHD_RX] Daughterboard: %s (%s, %s, %s)" % (rx_id, rx_serial, rx_antenna, rx_subdev_spec)) + print("[UHD_RX] Daughterboard: %s (%s, %s, %s)" % + (rx_id, rx_serial, rx_antenna, rx_subdev_spec)) except KeyError: print("[UHD_RX] Args: ", options.args) print("[UHD_RX] Receiving on {} channels.".format(len(self.channels))) print("[UHD_RX] Rx gain: {gain}".format(gain=gain)) print("[UHD_RX] Rx frequency: {freq}".format(freq=freq)) - print("[UHD_RX] Rx baseband frequency: {actual}".format(actual=n2s(tr.actual_rf_freq))) - print("[UHD_RX] Rx DDC frequency: {dsp}".format(dsp=n2s(tr.actual_dsp_freq))) - print("[UHD_RX] Rx Sample Rate: {rate}".format(rate=n2s(samp_rate))) + print("[UHD_RX] Rx baseband frequency: {actual}".format( + actual=n2s(tr.actual_rf_freq))) + print("[UHD_RX] Rx DDC frequency: {dsp}".format( + dsp=n2s(tr.actual_dsp_freq))) + print("[UHD_RX] Rx Sample Rate: {rate}".format( + rate=n2s(samp_rate))) if options.nsamples is None: print("[UHD_RX] Receiving samples until Ctrl-C") else: - print("[UHD_RX] Receiving {n} samples.".format(n=n2s(options.nsamples))) + print("[UHD_RX] Receiving {n} samples.".format( + n=n2s(options.nsamples))) if options.output_shorts: print("[UHD_RX] Writing 16-bit complex shorts") else: print("[UHD_RX] Writing 32-bit complex floats") - print("[UHD_RX] Output file(s): {files}".format(files=", ".join(self.filenames))) + print("[UHD_RX] Output file(s): {files}".format( + files=", ".join(self.filenames))) # Direct asynchronous notifications to callback function: if options.show_async_msg: self.async_msgq = gr.msg_queue(0) self.async_src = uhd.amsg_source("", self.async_msgq) - self.async_rcv = uhd.msgq_runner(self.async_msgq, self.async_callback) + self.async_rcv = uhd.msgq_runner( + self.async_msgq, self.async_callback) def async_callback(self, msg): md = self.async_src.msg_to_async_metadata_t(msg) - print("[UHD_RX] Channel: %i Time: %f Event: %i" % (md.channel, md.time_spec.get_real_secs(), md.event_code)) + print("[UHD_RX] Channel: %i Time: %f Event: %i" % + (md.channel, md.time_spec.get_real_secs(), md.event_code)) + def get_options(): - usage="%prog: [options] output_filename" + usage = "%prog: [options] output_filename" parser = OptionParser(option_class=eng_option, usage=usage) parser.add_option("-a", "--args", type="string", default="", help="UHD device address args , [default=%default]") @@ -220,9 +241,9 @@ def get_options(): help="Set gain in dB (default is midpoint)") parser.add_option("--normalized-gain", action="store_true", help="Specify gain as normalized value (in [0, 1])") - parser.add_option( "-m","--metafile", action="store_true", default=False, + parser.add_option("-m", "--metafile", action="store_true", default=False, help="output metadata to file [default=%default]") - parser.add_option( "-s","--output-shorts", action="store_true", default=False, + parser.add_option("-s", "--output-shorts", action="store_true", default=False, help="Output interleaved shorts instead of complex floats") parser.add_option("-N", "--nsamples", type="eng_float", default=None, help="Number of samples to collect [default=+inf]") @@ -246,6 +267,7 @@ def get_options(): exit(1) return (options, args[0]) + if __name__ == '__main__': (options, filename) = get_options() tb = rx_cfile_block(options, filename) diff --git a/gr-uhd/apps/uhd_rx_nogui b/gr-uhd/apps/uhd_rx_nogui index 06bce7ea7f..e091df1327 100755 --- a/gr-uhd/apps/uhd_rx_nogui +++ b/gr-uhd/apps/uhd_rx_nogui @@ -60,10 +60,11 @@ from gnuradio.eng_option import eng_option # (device_rate, channel_rate, audio_rate, channel_pass, channel_stop, demod) DEMOD_PARAMS = { - 'AM' : (256000, 16000, 16000, 5000, 8000, analog.demod_10k0a3e_cf), - 'FM' : (256000, 32000, 8000, 8000, 9000, analog.demod_20k0f3e_cf), - 'WFM' : (320000, 320000, 32000, 80000, 115000, analog.demod_200kf3e_cf) - } + 'AM': (256000, 16000, 16000, 5000, 8000, analog.demod_10k0a3e_cf), + 'FM': (256000, 32000, 8000, 8000, 9000, analog.demod_20k0f3e_cf), + 'WFM': (320000, 320000, 32000, 80000, 115000, analog.demod_200kf3e_cf) +} + class uhd_src(gr.hier_block2): """ @@ -74,14 +75,16 @@ class uhd_src(gr.hier_block2): Calibration value is the offset from the tuned frequency to the actual frequency. """ + def __init__(self, args, spec, antenna, samp_rate, gain=None, calibration=0.0): gr.hier_block2.__init__( self, "uhd_src", gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._src = \ - uhd.usrp_source(device_addr=args, stream_args=uhd.stream_args('fc32')) + uhd.usrp_source(device_addr=args, + stream_args=uhd.stream_args('fc32')) # Set the subdevice spec if spec: @@ -102,7 +105,7 @@ class uhd_src(gr.hier_block2): # If no gain specified, set to midrange gain_range = self._src.get_gain_range() if gain is None: - gain = (gain_range.start()+gain_range.stop())/2.0 + gain = (gain_range.start() + gain_range.stop()) / 2.0 print("Using gain: ", gain) self._src.set_gain(gain) @@ -117,6 +120,7 @@ class uhd_src(gr.hier_block2): """ Set sampling rate """ return self._samp_rate + class app_top_block(gr.top_block): def __init__(self, options): gr.top_block.__init__(self) @@ -139,24 +143,24 @@ class app_top_block(gr.top_block): chan_taps = filter.optfir.low_pass(1.0, # Filter gain if_rate, # Sample rate - channel_pass, # One sided modulation bandwidth - channel_stop, # One sided channel bandwidth + channel_pass, # One sided modulation bandwidth + channel_stop, # One sided channel bandwidth 0.1, # Passband ripple 60) # Stopband attenuation chan = filter.freq_xlating_fir_filter_ccf( - channel_decim, # Decimation rate + channel_decim, # Decimation rate chan_taps, # Filter taps 0.0, # Offset frequency if_rate) # Sample rate rfsql = analog.pwr_squelch_cc( options.rf_squelch, # Power threshold - 125.0/channel_rate, # Time constant - int(channel_rate/20), # 50ms rise/fall + 125.0 / channel_rate, # Time constant + int(channel_rate / 20), # 50ms rise/fall False) # Zero, not gate output - agc = analog.agc_cc(1.0/channel_rate, # Time constant + agc = analog.agc_cc(1.0 / channel_rate, # Time constant 1.0, # Reference power 1.0) # Gain @@ -170,7 +174,7 @@ class app_top_block(gr.top_block): tail = demod if options.ctcss != None and options.ctcss > 60.0: ctcss = analog.ctcss_squelch_ff(audio_rate, # Sample rate - options.ctcss) # Squelch tone + options.ctcss) # Squelch tone self.connect(demod, ctcss) tail = ctcss @@ -191,7 +195,8 @@ class app_top_block(gr.top_block): if self.options.show_async_msg: self.async_msgq = gr.msg_queue(0) self.async_src = uhd.amsg_source("", self.async_msgq) - self.async_rcv = uhd.msgq_runner(self.async_msgq, self.async_callback) + self.async_rcv = uhd.msgq_runner( + self.async_msgq, self.async_callback) def async_callback(self, msg): """ Callback for processing async messages """ @@ -252,5 +257,6 @@ def main(): except KeyboardInterrupt: pass + if __name__ == "__main__": main() diff --git a/gr-uhd/apps/uhd_siggen_base.py b/gr-uhd/apps/uhd_siggen_base.py index daf8184f56..8d1b37012c 100644 --- a/gr-uhd/apps/uhd_siggen_base.py +++ b/gr-uhd/apps/uhd_siggen_base.py @@ -41,14 +41,15 @@ FREQ_RANGE_KEY = 'freq_range' TYPE_KEY = 'type' WAVEFORMS = { - analog.GR_CONST_WAVE : "Constant", - analog.GR_SIN_WAVE : "Complex Sinusoid", - analog.GR_GAUSSIAN : "Gaussian Noise", - analog.GR_UNIFORM : "Uniform Noise", - "2tone" : "Two Tone", - "sweep" : "Sweep", + analog.GR_CONST_WAVE: "Constant", + analog.GR_SIN_WAVE: "Complex Sinusoid", + analog.GR_GAUSSIAN: "Gaussian Noise", + analog.GR_UNIFORM: "Uniform Noise", + "2tone": "Two Tone", + "sweep": "Sweep", } + class USRPSiggen(gr.top_block, pubsub, UHDApp): """ GUI-unaware GNU Radio flowgraph. This may be used either with command @@ -87,15 +88,18 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): args=args, ) print("[UHD-SIGGEN] UHD Signal Generator") - print("[UHD-SIGGEN] UHD Version: {ver}".format(ver=uhd.get_version_string())) + print( + "[UHD-SIGGEN] UHD Version: {ver}".format(ver=uhd.get_version_string())) print("[UHD-SIGGEN] Using USRP configuration:") print(self.get_usrp_info_string(tx_or_rx="tx")) - self.usrp_description = self.get_usrp_info_string(tx_or_rx="tx", compact=True) + self.usrp_description = self.get_usrp_info_string( + tx_or_rx="tx", compact=True) - ### Set subscribers and publishers: + # Set subscribers and publishers: 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(FREQ_RANGE_KEY, + lambda: self.usrp.get_freq_range(self.channels[0])) self.publish(GAIN_KEY, lambda: self.get_gain_or_power()) self[SAMP_RATE_KEY] = args.samp_rate @@ -107,7 +111,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self[DSP_FREQ_KEY] = 0 self[RF_FREQ_KEY] = 0 - #subscribe set methods + # subscribe set methods self.subscribe(SAMP_RATE_KEY, self.set_samp_rate) self.subscribe(GAIN_KEY, self.set_gain_or_power) self.subscribe(TX_FREQ_KEY, self.set_freq) @@ -117,18 +121,19 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self.subscribe(TYPE_KEY, self.set_waveform) self.subscribe(RF_FREQ_KEY, self.update_gain_range) - #force update on pubsub keys + # force update on pubsub keys for key in (SAMP_RATE_KEY, GAIN_KEY, TX_FREQ_KEY, AMPLITUDE_KEY, WAVEFORM_FREQ_KEY, WAVEFORM_OFFSET_KEY, WAVEFORM2_FREQ_KEY): self[key] = self[key] - self[TYPE_KEY] = args.type #set type last + self[TYPE_KEY] = args.type # set type last 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=samp_rate / 1e6)) + 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): @@ -138,10 +143,12 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self._src2.set_sampling_freq(self[SAMP_RATE_KEY]) elif self[TYPE_KEY] == "sweep": self._src1.set_sampling_freq(self[SAMP_RATE_KEY]) - self._src2.set_sampling_freq(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) + 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=samp_rate / 1e6)) + return True # Waveform not yet set + self.vprint("Set sample rate to: {rate} Msps".format( + rate=samp_rate / 1e6)) return True def set_waveform_freq(self, freq): @@ -151,7 +158,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): elif self[TYPE_KEY] == "2tone": self._src1.set_frequency(freq) elif self[TYPE_KEY] == 'sweep': - #there is no set sensitivity, redo fg + # there is no set sensitivity, redo fg self[TYPE_KEY] = self[TYPE_KEY] return True @@ -178,11 +185,14 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): if waveform_type in (analog.GR_SIN_WAVE, analog.GR_CONST_WAVE): self._src = analog.sig_source_c(self[SAMP_RATE_KEY], # Sample rate waveform_type, # Waveform waveform_type - self[WAVEFORM_FREQ_KEY], # Waveform frequency - self[AMPLITUDE_KEY], # Waveform amplitude - self[WAVEFORM_OFFSET_KEY]) # Waveform offset + # Waveform frequency + self[WAVEFORM_FREQ_KEY], + # Waveform amplitude + self[AMPLITUDE_KEY], + self[WAVEFORM_OFFSET_KEY]) # Waveform offset elif waveform_type in (analog.GR_GAUSSIAN, analog.GR_UNIFORM): - self._src = analog.noise_source_c(waveform_type, self[AMPLITUDE_KEY]) + 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, @@ -211,7 +221,8 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self[WAVEFORM2_FREQ_KEY], 1.0, -0.5) - self._src2 = analog.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) + self._src2 = analog.frequency_modulator_fc( + self[WAVEFORM_FREQ_KEY] * 2 * math.pi / self[SAMP_RATE_KEY]) self._src = blocks.multiply_const_cc(self[AMPLITUDE_KEY]) self.connect(self._src1, self._src2, self._src) else: @@ -224,7 +235,8 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self.vprint("Set baseband modulation to:", WAVEFORMS[waveform_type]) n2s = eng_notation.num_to_str if waveform_type == analog.GR_SIN_WAVE: - self.vprint("Modulation frequency: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) + self.vprint("Modulation frequency: %sHz" % + (n2s(self[WAVEFORM_FREQ_KEY]),)) self.vprint("Initial phase:", self[WAVEFORM_OFFSET_KEY]) elif waveform_type == "2tone": self.vprint("Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) @@ -250,7 +262,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): elif self[TYPE_KEY] == "sweep": self._src.set_k(amplitude) else: - return True # Waveform not yet set + return True # Waveform not yet set self.vprint("Set amplitude to:", amplitude) self.update_gain_range() return True @@ -262,7 +274,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): 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]) + + 20 * math.log10(self[AMPLITUDE_KEY]) def set_gain_or_power(self, gain_or_power): """ @@ -333,6 +345,7 @@ def setup_argparser(): help="Generate a swept sine wave") return parser + def main(): " Go, go, go! " if gr.enable_realtime_scheduling() != gr.RT_OK: @@ -350,5 +363,6 @@ def main(): tb.stop() tb.wait() + if __name__ == "__main__": main() diff --git a/gr-uhd/apps/uhd_siggen_gui b/gr-uhd/apps/uhd_siggen_gui index 191837ff27..0d9cb56c28 100755 --- a/gr-uhd/apps/uhd_siggen_gui +++ b/gr-uhd/apps/uhd_siggen_gui @@ -39,7 +39,7 @@ import time import math from PyQt5 import Qt from PyQt5.QtCore import pyqtSlot -import sip # Needs to be imported after PyQt5, could fail otherwise +import sip # Needs to be imported after PyQt5, could fail otherwise from gnuradio import analog from gnuradio import eng_notation from gnuradio import qtgui @@ -59,6 +59,7 @@ class uhd_siggen_gui(Qt.QWidget): """ Signal Generator Flowgraph """ + def __init__(self, args): ################################################## # Set up the siggen app @@ -94,14 +95,16 @@ class uhd_siggen_gui(Qt.QWidget): ################################################## # Widgets + Controls ################################################## - ### Waveform Selector + # Waveform Selector self._waveform_options = list(uhd_siggen.WAVEFORMS.keys()) self._waveform_labels = list(uhd_siggen.WAVEFORMS.values()) self._waveform_group_box = Qt.QGroupBox("Waveform") self._waveform_box = Qt.QHBoxLayout() + class variable_chooser_button_group(Qt.QButtonGroup): def __init__(self, parent=None): Qt.QButtonGroup.__init__(self, parent) + @pyqtSlot(int) def updateButtonChecked(self, button_id): self.button(button_id).setChecked(True) @@ -121,14 +124,14 @@ class uhd_siggen_gui(Qt.QWidget): lambda i: self.set_waveform(self._waveform_options[i]) ) self.top_grid_layout.addWidget(self._waveform_group_box, 0, 0, 1, 5) - ### Center Frequency Sliders + # Center Frequency Sliders self.freq_coarse = self._sg.usrp.get_center_freq(self._sg.channels[0]) self._freq_coarse_range = Range( self.usrp.get_freq_range(self._sg.channels[0]).start(), self.usrp.get_freq_range(self._sg.channels[0]).stop(), - 1e3, # Step + 1e3, # Step self.freq_coarse, - 200, # Min Width + 200, # Min Width ) self._freq_coarse_win = RangeWidget( self._freq_coarse_range, @@ -154,8 +157,8 @@ class uhd_siggen_gui(Qt.QWidget): self.top_grid_layout.addWidget(self._freq_fine_win, 2, 0, 1, 5) self.lo_offset = self._sg.args.lo_offset self._lo_offset_range = Range( - -self._sg[uhd_siggen.SAMP_RATE_KEY]/2, - self._sg[uhd_siggen.SAMP_RATE_KEY]/2, + -self._sg[uhd_siggen.SAMP_RATE_KEY] / 2, + self._sg[uhd_siggen.SAMP_RATE_KEY] / 2, 1e3, self.lo_offset, 200 @@ -168,11 +171,11 @@ class uhd_siggen_gui(Qt.QWidget): float ) self.top_grid_layout.addWidget(self._lo_offset_win, 3, 0, 1, 5) - ### Signal frequencies + # Signal frequencies self._freq1_enable_on = (analog.GR_SIN_WAVE, "2tone", "sweep") self._freq1_offset_range = Range( - -self._sg[uhd_siggen.SAMP_RATE_KEY]/2, - self._sg[uhd_siggen.SAMP_RATE_KEY]/2, + -self._sg[uhd_siggen.SAMP_RATE_KEY] / 2, + self._sg[uhd_siggen.SAMP_RATE_KEY] / 2, 100, self._sg.args.waveform_freq, 200 @@ -184,12 +187,13 @@ class uhd_siggen_gui(Qt.QWidget): "counter_slider", float ) - self._freq1_offset_win.setEnabled(self._sg[uhd_siggen.TYPE_KEY] in self._freq1_enable_on) + self._freq1_offset_win.setEnabled( + self._sg[uhd_siggen.TYPE_KEY] in self._freq1_enable_on) self.top_grid_layout.addWidget(self._freq1_offset_win, 4, 0, 1, 3) self._freq2_enable_on = ("2tone", "sweep") self._freq2_offset_range = Range( - -self._sg[uhd_siggen.SAMP_RATE_KEY]/2, - self._sg[uhd_siggen.SAMP_RATE_KEY]/2, + -self._sg[uhd_siggen.SAMP_RATE_KEY] / 2, + self._sg[uhd_siggen.SAMP_RATE_KEY] / 2, 100, self._sg.args.waveform2_freq, 200 @@ -201,9 +205,10 @@ class uhd_siggen_gui(Qt.QWidget): "counter_slider", float ) - self._freq2_offset_win.setEnabled(self._sg[uhd_siggen.TYPE_KEY] in self._freq2_enable_on) + self._freq2_offset_win.setEnabled( + self._sg[uhd_siggen.TYPE_KEY] in self._freq2_enable_on) self.top_grid_layout.addWidget(self._freq2_offset_win, 4, 3, 1, 2) - ### Amplitude + # Amplitude min_ampl = \ self._sg.MIN_AMP_POWER_MODE \ if self._sg.gain_type == self._sg.GAIN_TYPE_POWER else 0 @@ -235,7 +240,7 @@ class uhd_siggen_gui(Qt.QWidget): float ) self.top_grid_layout.addWidget(self._gain_win, 6, 0, 1, 5) - ### Samp rate, LO sync, Antenna Select + # Samp rate, LO sync, Antenna Select self.samp_rate = self._sg[uhd_siggen.SAMP_RATE_KEY] self._samp_rate_tool_bar = Qt.QToolBar(self) self._samp_rate_tool_bar.addWidget(Qt.QLabel("Sampling Rate: ")) @@ -248,7 +253,8 @@ class uhd_siggen_gui(Qt.QWidget): ) self.top_grid_layout.addWidget(self._samp_rate_tool_bar, 7, 0, 1, 2) _sync_phases_push_button = Qt.QPushButton("Sync LOs") - _sync_phases_push_button.pressed.connect(lambda: self.set_sync_phases(True)) + _sync_phases_push_button.pressed.connect( + lambda: self.set_sync_phases(True)) _sync_phases_push_button.setEnabled(bool(len(self._sg.channels) > 1)) self.top_grid_layout.addWidget(_sync_phases_push_button, 7, 2, 1, 1) # Antenna Select @@ -272,8 +278,11 @@ class uhd_siggen_gui(Qt.QWidget): self._lo_locked_probe_0_formatter = lambda x: x self._lo_locked_probe_0_tool_bar.addWidget(Qt.QLabel("LO locked: ")) self._lo_locked_probe_0_label = Qt.QLabel(str(False)) - 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) + 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: @@ -285,7 +294,8 @@ class uhd_siggen_gui(Qt.QWidget): except: self.set_chan0_lo_locked("Lock Detect Failed!") time.sleep(.1) - _chan0_lo_locked_thread = threading.Thread(target=_chan0_lo_locked_probe) + _chan0_lo_locked_thread = threading.Thread( + target=_chan0_lo_locked_probe) _chan0_lo_locked_thread.daemon = True _chan0_lo_locked_thread.start() self.label_rf_freq = self._sg.tr.actual_rf_freq @@ -295,7 +305,8 @@ class uhd_siggen_gui(Qt.QWidget): self._label_rf_freq_label = \ Qt.QLabel(str(self._label_rf_freq_formatter(self.label_rf_freq))) self._label_rf_freq_tool_bar.addWidget(self._label_rf_freq_label) - self.top_grid_layout.addWidget(self._label_rf_freq_tool_bar, 8, 1, 1, 1) + self.top_grid_layout.addWidget( + self._label_rf_freq_tool_bar, 8, 1, 1, 1) self.label_dsp_freq = self._sg.tr.actual_dsp_freq self._label_dsp_freq_tool_bar = Qt.QToolBar(self) self._label_dsp_freq_formatter = lambda x: x @@ -303,22 +314,24 @@ class uhd_siggen_gui(Qt.QWidget): self._label_dsp_freq_label = \ Qt.QLabel(str(self._label_dsp_freq_formatter(self.label_dsp_freq))) self._label_dsp_freq_tool_bar.addWidget(self._label_dsp_freq_label) - self.top_grid_layout.addWidget(self._label_dsp_freq_tool_bar, 8, 2, 1, 1) + self.top_grid_layout.addWidget( + self._label_dsp_freq_tool_bar, 8, 2, 1, 1) ################################################## # Freq Sink ################################################## if self._sg.args.show_freq_sink: self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( - 1024, #size - fft.window.WIN_BLACKMAN_hARRIS, #wintype - self.freq_coarse + self.freq_fine, #fc - self.samp_rate, #bw - "", #name - 1 #number of inputs + 1024, # size + fft.window.WIN_BLACKMAN_hARRIS, # wintype + self.freq_coarse + self.freq_fine, # fc + self.samp_rate, # bw + "", # name + 1 # number of inputs ) self.qtgui_freq_sink_x_0.set_update_time(0.10) self.qtgui_freq_sink_x_0.set_y_axis(-100, 10) - self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") + self.qtgui_freq_sink_x_0.set_trigger_mode( + qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0.enable_autoscale(False) self.qtgui_freq_sink_x_0.enable_grid(False) self.qtgui_freq_sink_x_0.set_fft_average(1.0) @@ -327,8 +340,10 @@ class uhd_siggen_gui(Qt.QWidget): self.qtgui_freq_sink_x_0.set_line_width(0, 1) self.qtgui_freq_sink_x_0.set_line_color(0, "blue") self.qtgui_freq_sink_x_0.set_line_alpha(0, 1.0) - self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.qwidget(), Qt.QWidget) - self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win, 9, 0, 2, 5) + self._qtgui_freq_sink_x_0_win = sip.wrapinstance( + self.qtgui_freq_sink_x_0.qwidget(), Qt.QWidget) + self.top_grid_layout.addWidget( + self._qtgui_freq_sink_x_0_win, 9, 0, 2, 5) # Reconnect: self._sg.extra_sink = self.qtgui_freq_sink_x_0 self._sg[uhd_siggen.TYPE_KEY] = self._sg[uhd_siggen.TYPE_KEY] @@ -435,7 +450,8 @@ class uhd_siggen_gui(Qt.QWidget): def set_sync_phases(self, sync): """ Execute when the sync-phases button is pushed """ if sync: - self._sg.vprint("Attempting to sync LO phases. This does not work with all boards.") + self._sg.vprint( + "Attempting to sync LO phases. This does not work with all boards.") self._sg.set_freq(self.freq_coarse + self.freq_fine, False) def set_ant(self, ant): @@ -484,6 +500,7 @@ class uhd_siggen_gui(Qt.QWidget): Qt.Q_ARG("QString", str(chan0_lo_locked)) ) + def setup_parser(): """ Argument parser for siggen_gui @@ -496,6 +513,7 @@ def setup_parser(): ) return parser + def main(): """ Go, go, go! """ parser = setup_parser() @@ -504,6 +522,7 @@ def main(): siggen_gui = uhd_siggen_gui(args) siggen_gui.show() # pylint: disable=unused-argument + def sig_handler(sig=None, frame=None): siggen_gui.stop() Qt.QApplication.quit() @@ -514,5 +533,6 @@ def main(): timer.timeout.connect(lambda: None) qapp.exec_() + if __name__ == '__main__': main() diff --git a/gr-uhd/examples/python/freq_hopping.py b/gr-uhd/examples/python/freq_hopping.py index 8fd65aade8..871181e045 100755 --- a/gr-uhd/examples/python/freq_hopping.py +++ b/gr-uhd/examples/python/freq_hopping.py @@ -19,6 +19,7 @@ from gnuradio import gr from gnuradio import blocks from gnuradio import uhd + def setup_parser(): """ Setup the parser for the frequency hopper. """ parser = argparse.ArgumentParser( @@ -77,31 +78,34 @@ def setup_parser(): class FrequencyHopperSrc(gr.hier_block2): """ Provides tags for frequency hopping """ + def __init__( - self, - n_bursts, n_channels, - freq_delta, base_freq, dsp_tuning, - burst_length, base_time, hop_time, - post_tuning=False, - tx_gain=0, - verbose=False - ): + self, + n_bursts, n_channels, + freq_delta, base_freq, dsp_tuning, + burst_length, base_time, hop_time, + post_tuning=False, + tx_gain=0, + verbose=False + ): gr.hier_block2.__init__( self, "FrequencyHopperSrc", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex), ) n_samples_total = n_bursts * burst_length - lowest_frequency = base_freq - numpy.floor(n_channels/2) * freq_delta - self.hop_sequence = [lowest_frequency + n * freq_delta for n in range(n_channels)] + lowest_frequency = base_freq - numpy.floor(n_channels / 2) * freq_delta + self.hop_sequence = [lowest_frequency + n * + freq_delta for n in range(n_channels)] numpy.random.shuffle(self.hop_sequence) # Repeat that: - self.hop_sequence = [self.hop_sequence[x % n_channels] for x in range(n_bursts)] + self.hop_sequence = [self.hop_sequence[x % n_channels] + for x in range(n_bursts)] if verbose: print("Hop Frequencies | Hop Pattern") print("=================|================================") for f in self.hop_sequence: - print("{:6.3f} MHz | ".format(f/1e6), end='') + print("{:6.3f} MHz | ".format(f / 1e6), end='') if n_channels < 50: print(" " * int((f - base_freq) / freq_delta) + "#") else: @@ -113,25 +117,28 @@ class FrequencyHopperSrc(gr.hier_block2): gain_tag.offset = 0 gain_tag.key = pmt.string_to_symbol('tx_command') gain_tag.value = pmt.to_pmt({'gain': tx_gain}) - tag_list = [gain_tag,] + tag_list = [gain_tag, ] for i in range(len(self.hop_sequence)): time = pmt.cons( - pmt.from_uint64(int(base_time + i * hop_time+0.01)), - pmt.from_double((base_time + i * hop_time+0.01) % 1), + pmt.from_uint64(int(base_time + i * hop_time + 0.01)), + pmt.from_double((base_time + i * hop_time + 0.01) % 1), ) tune_tag = gr.tag_t() tune_tag.offset = i * burst_length # TODO dsp_tuning should also be able to do post_tuning if i > 0 and post_tuning and not dsp_tuning: - tune_tag.offset -= 1 # Move it to last sample of previous burst + tune_tag.offset -= 1 # Move it to last sample of previous burst if dsp_tuning: tune_tag.key = pmt.string_to_symbol('tx_command') - tune_tag.value = pmt.to_pmt({'lo_freq': base_freq, 'dsp_freq': base_freq - self.hop_sequence[i]}) - tune_tag.value = pmt.dict_add(tune_tag.value, pmt.intern("time"),time) + tune_tag.value = pmt.to_pmt( + {'lo_freq': base_freq, 'dsp_freq': base_freq - self.hop_sequence[i]}) + tune_tag.value = pmt.dict_add( + tune_tag.value, pmt.intern("time"), time) else: tune_tag.key = pmt.string_to_symbol('tx_command') tune_tag.value = pmt.to_pmt({'freq': self.hop_sequence[i]}) - tune_tag.value = pmt.dict_add(tune_tag.value, pmt.intern('time'), time) + tune_tag.value = pmt.dict_add( + tune_tag.value, pmt.intern('time'), time) tag_list.append(tune_tag) length_tag = gr.tag_t() length_tag.offset = i * burst_length @@ -142,11 +149,12 @@ class FrequencyHopperSrc(gr.hier_block2): time_tag.offset = i * burst_length time_tag.key = pmt.string_to_symbol('tx_time') time_tag.value = pmt.make_tuple( - pmt.car(time), - pmt.cdr(time) + pmt.car(time), + pmt.cdr(time) ) tag_list.append(time_tag) - tag_source = blocks.vector_source_c((1.0,) * n_samples_total, repeat=False, tags=tag_list) + tag_source = blocks.vector_source_c( + (1.0,) * n_samples_total, repeat=False, tags=tag_list) mult = blocks.multiply_cc() self.connect(self, mult, self) self.connect(tag_source, (mult, 1)) @@ -154,10 +162,12 @@ class FrequencyHopperSrc(gr.hier_block2): class FlowGraph(gr.top_block): """ Flow graph that does the frequency hopping. """ + def __init__(self, args): gr.top_block.__init__(self) if args.input_file is not None: - src = blocks.file_source(gr.sizeof_gr_complex, args.input_file, repeat=True) + src = blocks.file_source( + gr.sizeof_gr_complex, args.input_file, repeat=True) else: src = blocks.vector_source_c((.5,) * int(1e6) * 2, repeat=True) # Setup USRP @@ -189,6 +199,7 @@ class FlowGraph(gr.top_block): ) self.connect(src, hopper_block, self.usrp) + def print_hopper_stats(args): """ Nothing to do with Grace Hopper """ print(""" @@ -205,14 +216,16 @@ Transmit Gain | {gain} dB ===================+========================= """.format( hop_time=args.hop_time, - hop_duration=1000.0/args.rate*args.samp_per_burst, + hop_duration=1000.0 / args.rate * args.samp_per_burst, gain=args.gain if args.gain else "(midpoint)", - lowest_freq=args.freq/1e6, - highest_freq=(args.freq + (args.num_channels-1) * args.freq_delta)/1e6, - freq_delta=args.freq_delta/1e6, + lowest_freq=args.freq / 1e6, + highest_freq=(args.freq + (args.num_channels - 1) * + args.freq_delta) / 1e6, + freq_delta=args.freq_delta / 1e6, num_channels=args.num_channels, - rate=args.rate/1e6, - )) + rate=args.rate / 1e6, + )) + def main(): """ Go, go, go! """ @@ -227,6 +240,7 @@ def main(): top_block.usrp.set_time_now(uhd.time_spec(0.0)) top_block.run() + if __name__ == '__main__': try: main() diff --git a/gr-uhd/grc/gen_uhd_usrp_blocks.py b/gr-uhd/grc/gen_uhd_usrp_blocks.py index 8c31038d07..371fe937cc 100644 --- a/gr-uhd/grc/gen_uhd_usrp_blocks.py +++ b/gr-uhd/grc/gen_uhd_usrp_blocks.py @@ -594,14 +594,16 @@ ${'$'}{len_tag_name}, ${'%'} endif """ + def parse_tmpl(_tmpl, **kwargs): """ Render _tmpl using the kwargs. """ from mako.template import Template block_template = Template(_tmpl) return str(block_template.render(**kwargs)) + MAX_NUM_MBOARDS = 8 -MAX_NUM_CHANNELS = MAX_NUM_MBOARDS*4 +MAX_NUM_CHANNELS = MAX_NUM_MBOARDS * 4 if __name__ == '__main__': for file in sys.argv[1:]: @@ -612,7 +614,7 @@ if __name__ == '__main__': sourk = 'sink' direction = 'in' else: - raise Exception('is % a source or sink?'%file) + raise Exception('is % a source or sink?' % file) params = ''.join([ parse_tmpl(PARAMS_TMPL, n=n, sourk=sourk) for n in range(MAX_NUM_CHANNELS) diff --git a/gr-uhd/python/uhd/__init__.py b/gr-uhd/python/uhd/__init__.py index 7c0f23dde1..1ffa94e821 100644 --- a/gr-uhd/python/uhd/__init__.py +++ b/gr-uhd/python/uhd/__init__.py @@ -16,6 +16,8 @@ line. ######################################################################## # Prepare uhd swig module to make it more pythonic ######################################################################## + + def _prepare_uhd_python(): try: from . import uhd_python @@ -25,45 +27,56 @@ def _prepare_uhd_python(): __path__.append(os.path.join(dirname, "bindings")) from . import uhd_python - #some useful typedefs for the user + # some useful typedefs for the user setattr(uhd_python, 'freq_range_t', uhd_python.meta_range_t) setattr(uhd_python, 'gain_range_t', uhd_python.meta_range_t) - #Make the python tune request object inherit from float - #so that it can be passed in GRC as a frequency parameter. - #The type checking in GRC will accept the tune request. - #Also use kwargs to construct individual struct elements. + # Make the python tune request object inherit from float + # so that it can be passed in GRC as a frequency parameter. + # The type checking in GRC will accept the tune request. + # Also use kwargs to construct individual struct elements. class tune_request_t(uhd_python.tune_request_t): # def __new__(self, *args, **kwargs): return float.__new__(self) def __float__(self): return self.target_freq + def __init__(self, *args, **kwargs): super().__init__(*args) - for key, val in list(kwargs.items()): setattr(self, key, val) + for key, val in list(kwargs.items()): + setattr(self, key, val) setattr(uhd_python, 'tune_request_t', tune_request_t) - #handle general things on all uhd_python attributes - #Install the __str__ and __repr__ handlers if applicable - #Create aliases for uhd swig attributes to avoid the "_t" + # handle general things on all uhd_python attributes + # Install the __str__ and __repr__ handlers if applicable + # Create aliases for uhd swig attributes to avoid the "_t" for attr in dir(uhd_python): myobj = getattr(uhd_python, attr) - if hasattr(myobj, 'to_string'): myobj.__repr__ = lambda o: o.to_string().strip() - if hasattr(myobj, 'to_pp_string'): myobj.__str__ = lambda o: o.to_pp_string().strip() - if hasattr(myobj, 'to_bool'): myobj.__nonzero__ = lambda o: o.to_bool() - if hasattr(myobj, 'to_int'): myobj.__int__ = lambda o: o.to_int() - if hasattr(myobj, 'to_real'): myobj.__float__ = lambda o: o.to_real() - if attr.endswith('_t'): setattr(uhd_python, attr[:-2], myobj) + if hasattr(myobj, 'to_string'): + myobj.__repr__ = lambda o: o.to_string().strip() + if hasattr(myobj, 'to_pp_string'): + myobj.__str__ = lambda o: o.to_pp_string().strip() + if hasattr(myobj, 'to_bool'): + myobj.__nonzero__ = lambda o: o.to_bool() + if hasattr(myobj, 'to_int'): + myobj.__int__ = lambda o: o.to_int() + if hasattr(myobj, 'to_real'): + myobj.__float__ = lambda o: o.to_real() + if attr.endswith('_t'): + setattr(uhd_python, attr[:-2], myobj) - #make a new find devices that casts everything with the pythonized device_addr_t which has __str__ + # make a new find devices that casts everything with the pythonized device_addr_t which has __str__ def find_devices(*args, **kwargs): def to_pythonized_dev_addr(dev_addr): new_dev_addr = uhd_python.device_addr_t() - for key in list(dev_addr.keys()): new_dev_addr[key] = dev_addr.get(key) + for key in list(dev_addr.keys()): + new_dev_addr[key] = dev_addr.get(key) return new_dev_addr return __builtins__['map'](to_pythonized_dev_addr, uhd_python.find_devices_raw(*args, **kwargs)) setattr(uhd_python, 'find_devices', find_devices) + ######################################################################## # Initialize this module with the contents of uhd pybind ######################################################################## _prepare_uhd_python() + from .uhd_python import * diff --git a/gr-uhd/python/uhd/qa_uhd.py b/gr-uhd/python/uhd/qa_uhd.py index 65b50d794b..c8fb65c144 100644 --- a/gr-uhd/python/uhd/qa_uhd.py +++ b/gr-uhd/python/uhd/qa_uhd.py @@ -12,6 +12,7 @@ gr-uhd sanity checking from gnuradio import gr, gr_unittest, uhd + class test_uhd(gr_unittest.TestCase): def setUp(self): |