diff options
author | Tom Rondeau | 2011-10-07 17:00:12 -0400 |
---|---|---|
committer | Tom Rondeau | 2011-10-07 17:00:37 -0400 |
commit | c4f3e0a671f3d756b96fa4671726348499712af3 (patch) | |
tree | 22838588d4f4ec7398e9c1b5c60bcfd90eaea286 | |
parent | a74499854ddddc8d5090f0cd0c34c8222a496a7a (diff) | |
download | gnuradio-c4f3e0a671f3d756b96fa4671726348499712af3.tar.gz gnuradio-c4f3e0a671f3d756b96fa4671726348499712af3.tar.bz2 gnuradio-c4f3e0a671f3d756b96fa4671726348499712af3.zip |
uhd: added UHD versions of siggen and siggen_gui.
-rw-r--r-- | gr-uhd/apps/Makefile.am | 7 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_siggen.py | 350 | ||||
-rwxr-xr-x | gr-uhd/apps/uhd_siggen_gui.py | 318 |
3 files changed, 672 insertions, 3 deletions
diff --git a/gr-uhd/apps/Makefile.am b/gr-uhd/apps/Makefile.am index a9e28b9cd..c1ee0ff05 100644 --- a/gr-uhd/apps/Makefile.am +++ b/gr-uhd/apps/Makefile.am @@ -29,6 +29,7 @@ SUBDIRS = hf_explorer hf_radio ourpythondir = $(grpythondir) bin_SCRIPTS = \ - uhd_fft.py \ - uhd_rx_cfile.py - + uhd_fft.py \ + uhd_rx_cfile.py \ + uhd_siggen.py \ + uhd_siggen_gui.py diff --git a/gr-uhd/apps/uhd_siggen.py b/gr-uhd/apps/uhd_siggen.py new file mode 100755 index 000000000..921ba44b5 --- /dev/null +++ b/gr-uhd/apps/uhd_siggen.py @@ -0,0 +1,350 @@ +#!/usr/bin/env python +# +# Copyright 2008,2009,2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +DESC_KEY = 'desc' +SAMP_RATE_KEY = 'samp_rate' +LINK_RATE_KEY = 'link_rate' +GAIN_KEY = 'gain' +TX_FREQ_KEY = 'tx_freq' +DSP_FREQ_KEY = 'dsp_freq' +RF_FREQ_KEY = 'rf_freq' +AMPLITUDE_KEY = 'amplitude' +AMPL_RANGE_KEY = 'ampl_range' +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' + +def setter(ps, key, val): ps[key] = val + +from gnuradio import gr, uhd, eng_notation +from gnuradio.gr.pubsub import pubsub +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math + +n2s = eng_notation.num_to_str + +waveforms = { gr.GR_SIN_WAVE : "Complex Sinusoid", + gr.GR_CONST_WAVE : "Constant", + gr.GR_GAUSSIAN : "Gaussian Noise", + gr.GR_UNIFORM : "Uniform Noise", + "2tone" : "Two Tone", + "sweep" : "Sweep" } + +# +# GUI-unaware GNU Radio flowgraph. This may be used either with command +# line applications or GUI applications. +# +class top_block(gr.top_block, pubsub): + def __init__(self, options, args): + gr.top_block.__init__(self) + pubsub.__init__(self) + self._verbose = options.verbose + + #initialize values from options + self._setup_usrpx(options) + self[SAMP_RATE_KEY] = options.samp_rate + self[TX_FREQ_KEY] = options.tx_freq + self[AMPLITUDE_KEY] = options.amplitude + self[WAVEFORM_FREQ_KEY] = options.waveform_freq + self[WAVEFORM_OFFSET_KEY] = options.offset + self[WAVEFORM2_FREQ_KEY] = options.waveform2_freq + self[DSP_FREQ_KEY] = 0 + self[RF_FREQ_KEY] = 0 + + #subscribe set methods + self.subscribe(SAMP_RATE_KEY, self.set_samp_rate) + self.subscribe(GAIN_KEY, self.set_gain) + 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) + + #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] = options.type #set type last + + def _setup_usrpx(self, options): + self._u = uhd.usrp_sink(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + self._u.set_samp_rate(options.samp_rate) + if(options.antenna): + self._u.set_antenna(options.antenna) + + self.publish(DESC_KEY, lambda: str(self._u)) + self.publish(FREQ_RANGE_KEY, self._u.get_freq_range) + self.publish(GAIN_RANGE_KEY, self._u.get_gain_range) + self.publish(GAIN_KEY, self._u.get_gain) + if self._verbose: + print str(self._u) + + def _set_tx_amplitude(self, ampl): + """ + Sets the transmit amplitude sent to the USRP + @param ampl the amplitude or None for automatic + """ + ampl_range = self[AMPL_RANGE_KEY] + if ampl is None: + ampl = (ampl_range[1] - ampl_range[0])*0.15 + ampl_range[0] + self[AMPLITUDE_KEY] = max(ampl_range[0], min(ampl, ampl_range[1])) + + def set_samp_rate(self, sr): + self._u.set_samp_rate(sr) + sr = self._u.get_samp_rate() + + if self[TYPE_KEY] in (gr.GR_SIN_WAVE, gr.GR_CONST_WAVE): + self._src.set_sampling_freq(self[SAMP_RATE_KEY]) + elif self[TYPE_KEY] == "2tone": + self._src1.set_sampling_freq(self[SAMP_RATE_KEY]) + 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]) + else: + return True # Waveform not yet set + + if self._verbose: + print "Set sample rate to:", sr + + return True + + def set_gain(self, gain): + if gain is None: + g = self[GAIN_RANGE_KEY] + gain = float(g[0]+g[1])/2 + if self._verbose: + print "Using auto-calculated mid-point TX gain" + self[GAIN_KEY] = gain + return + self._u.set_gain(gain) + if self._verbose: + print "Set TX gain to:", gain + + def set_freq(self, target_freq): + + if target_freq is None: + f = self[FREQ_RANGE_KEY] + target_freq = float(f[0]+f[1])/2.0 + if self._verbose: + print "Using auto-calculated mid-point frequency" + self[TX_FREQ_KEY] = target_freq + return + + tr = self._u.set_center_freq(target_freq) + fs = "%sHz" % (n2s(target_freq),) + if tr is not None: + self._freq = target_freq + self[DSP_FREQ_KEY] = tr.actual_dsp_freq + self[RF_FREQ_KEY] = tr.actual_rf_freq + if self._verbose: + print "Set center frequency to", self._u.get_center_freq() + print "Tx RF frequency: %sHz" % (n2s(tr.actual_rf_freq),) + print "Tx DSP frequency: %sHz" % (n2s(tr.actual_dsp_freq),) + elif self._verbose: + print "Failed to set freq." + return tr + + def set_waveform_freq(self, freq): + if self[TYPE_KEY] == gr.GR_SIN_WAVE: + self._src.set_frequency(freq) + elif self[TYPE_KEY] == "2tone": + self._src1.set_frequency(freq) + elif self[TYPE_KEY] == 'sweep': + #there is no set sensitivity, redo fg + self[TYPE_KEY] = self[TYPE_KEY] + return True + + def set_waveform2_freq(self, freq): + if freq is None: + self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY] + return + if self[TYPE_KEY] == "2tone": + self._src2.set_frequency(freq) + elif self[TYPE_KEY] == "sweep": + self._src1.set_frequency(freq) + return True + + def set_waveform(self, type): + self.lock() + self.disconnect_all() + if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE: + self._src = gr.sig_source_c(self[SAMP_RATE_KEY], # Sample rate + type, # Waveform type + self[WAVEFORM_FREQ_KEY], # Waveform frequency + self[AMPLITUDE_KEY], # Waveform amplitude + self[WAVEFORM_OFFSET_KEY]) # Waveform offset + elif type == gr.GR_GAUSSIAN or type == gr.GR_UNIFORM: + self._src = gr.noise_source_c(type, self[AMPLITUDE_KEY]) + elif type == "2tone": + self._src1 = gr.sig_source_c(self[SAMP_RATE_KEY], + gr.GR_SIN_WAVE, + self[WAVEFORM_FREQ_KEY], + self[AMPLITUDE_KEY]/2.0, + 0) + if(self[WAVEFORM2_FREQ_KEY] is None): + self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY] + + self._src2 = gr.sig_source_c(self[SAMP_RATE_KEY], + gr.GR_SIN_WAVE, + self[WAVEFORM2_FREQ_KEY], + self[AMPLITUDE_KEY]/2.0, + 0) + self._src = gr.add_cc() + self.connect(self._src1,(self._src,0)) + self.connect(self._src2,(self._src,1)) + elif type == "sweep": + # rf freq is center frequency + # waveform_freq is total swept width + # waveform2_freq is sweep rate + # will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2) + if self[WAVEFORM2_FREQ_KEY] is None: + self[WAVEFORM2_FREQ_KEY] = 0.1 + + self._src1 = gr.sig_source_f(self[SAMP_RATE_KEY], + gr.GR_TRI_WAVE, + self[WAVEFORM2_FREQ_KEY], + 1.0, + -0.5) + self._src2 = gr.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) + self._src = gr.multiply_const_cc(self[AMPLITUDE_KEY]) + self.connect(self._src1,self._src2,self._src) + else: + raise RuntimeError("Unknown waveform type") + + self.connect(self._src, self._u) + self.unlock() + + if self._verbose: + print "Set baseband modulation to:", waveforms[type] + if type == gr.GR_SIN_WAVE: + print "Modulation frequency: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),) + print "Initial phase:", self[WAVEFORM_OFFSET_KEY] + elif type == "2tone": + print "Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),) + print "Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),) + elif type == "sweep": + print "Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0)) + print "Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),) + print "TX amplitude:", self[AMPLITUDE_KEY] + + + def set_amplitude(self, amplitude): + if amplitude < 0.0 or amplitude > 1.0: + if self._verbose: + print "Amplitude out of range:", amplitude + return False + + if self[TYPE_KEY] in (gr.GR_SIN_WAVE, gr.GR_CONST_WAVE, gr.GR_GAUSSIAN, gr.GR_UNIFORM): + self._src.set_amplitude(amplitude) + elif self[TYPE_KEY] == "2tone": + self._src1.set_amplitude(amplitude/2.0) + self._src2.set_amplitude(amplitude/2.0) + elif self[TYPE_KEY] == "sweep": + self._src.set_k(amplitude) + else: + return True # Waveform not yet set + + if self._verbose: + print "Set amplitude to:", amplitude + return True + +def get_options(): + usage="%prog: [options]" + + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate (bandwidth) [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-f", "--tx-freq", type="eng_float", default=None, + help="Set carrier frequency to FREQ [default=mid-point]", + metavar="FREQ") + parser.add_option("-x", "--waveform-freq", type="eng_float", default=0, + help="Set baseband waveform frequency to FREQ [default=%default]") + parser.add_option("-y", "--waveform2-freq", type="eng_float", default=None, + help="Set 2nd waveform frequency to FREQ [default=%default]") + parser.add_option("--sine", dest="type", action="store_const", const=gr.GR_SIN_WAVE, + help="Generate a carrier modulated by a complex sine wave", + default=gr.GR_SIN_WAVE) + parser.add_option("--const", dest="type", action="store_const", const=gr.GR_CONST_WAVE, + help="Generate a constant carrier") + parser.add_option("--offset", type="eng_float", default=0, + help="Set waveform phase offset to OFFSET [default=%default]") + parser.add_option("--gaussian", dest="type", action="store_const", const=gr.GR_GAUSSIAN, + help="Generate Gaussian random output") + parser.add_option("--uniform", dest="type", action="store_const", const=gr.GR_UNIFORM, + help="Generate Uniform random output") + parser.add_option("--2tone", dest="type", action="store_const", const="2tone", + help="Generate Two Tone signal for IMD testing") + parser.add_option("--sweep", dest="type", action="store_const", const="sweep", + help="Generate a swept sine wave") + parser.add_option("", "--amplitude", type="eng_float", default=0.15, + help="Set output amplitude to AMPL (0.0-1.0) [default=%default]", + metavar="AMPL") + parser.add_option("-v", "--verbose", action="store_true", default=False, + help="Use verbose console output [default=%default]") + + (options, args) = parser.parse_args() + + return (options, args) + +# If this script is executed, the following runs. If it is imported, +# the below does not run. +def main(): + if gr.enable_realtime_scheduling() != gr.RT_OK: + print "Note: failed to enable realtime scheduling, continuing" + + # Grab command line options and create top block + try: + (options, args) = get_options() + tb = top_block(options, args) + + except RuntimeError, e: + print e + sys.exit(1) + + tb.start() + raw_input('Press Enter to quit: ') + tb.stop() + tb.wait() + +# Make sure to create the top block (tb) within a function: +# That code in main will allow tb to go out of scope on return, +# which will call the decontructor on usrp and stop transmit. +# Whats odd is that grc works fine with tb in the __main__, +# perhaps its because the try/except clauses around tb. +if __name__ == "__main__": + main() diff --git a/gr-uhd/apps/uhd_siggen_gui.py b/gr-uhd/apps/uhd_siggen_gui.py new file mode 100755 index 000000000..2ef6ea40f --- /dev/null +++ b/gr-uhd/apps/uhd_siggen_gui.py @@ -0,0 +1,318 @@ +#!/usr/bin/env python +# +# Copyright 2009,2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import wx +from gnuradio import gr +from gnuradio.gr.pubsub import pubsub +from gnuradio.wxgui import gui, forms +import uhd_siggen +import sys, math + +class app_gui(pubsub): + def __init__(self, frame, panel, vbox, top_block, options, args): + pubsub.__init__(self) + self.frame = frame # Use for top-level application window frame + self.panel = panel # Use as parent class for created windows + self.vbox = vbox # Use as sizer for created windows + self.tb = top_block # GUI-unaware flowgraph class + self.options = options # Supplied command-line options + self.args = args # Supplied command-line arguments + self.build_gui() + + # Event response handlers + def evt_set_status_msg(self, msg): + self.frame.SetStatusText(msg, 0) + + # GUI construction + def build_gui(self): + self.vbox.AddSpacer(5) + self.vbox.AddStretchSpacer() + ################################################## + # Baseband controls + ################################################## + bb_vbox = forms.static_box_sizer(parent=self.panel, label="Baseband Modulation", orient=wx.VERTICAL, bold=True) + self.vbox.Add(bb_vbox, 0, wx.EXPAND) + sine_bb_hbox = wx.BoxSizer(wx.HORIZONTAL) + sweep_bb_hbox = wx.BoxSizer(wx.HORIZONTAL) + tone_bb_hbox = wx.BoxSizer(wx.HORIZONTAL) + self.vbox.AddSpacer(10) + self.vbox.AddStretchSpacer() + #callback to show/hide forms + def set_type(type): + sine_bb_hbox.ShowItems(type == gr.GR_SIN_WAVE) + sweep_bb_hbox.ShowItems(type == 'sweep') + tone_bb_hbox.ShowItems(type == '2tone') + self.vbox.Layout() + self.tb.subscribe(uhd_siggen.TYPE_KEY, set_type) + #create sine forms + sine_bb_hbox.AddSpacer(10) + forms.text_box( + parent=self.panel, sizer=sine_bb_hbox, + label='Frequency (Hz)', + ps=self.tb, + key=uhd_siggen.WAVEFORM_FREQ_KEY, + converter=forms.float_converter(), + ) + sine_bb_hbox.AddStretchSpacer() + #create sweep forms + sweep_bb_hbox.AddSpacer(10) + forms.text_box( + parent=self.panel, sizer=sweep_bb_hbox, + label='Sweep Width (Hz)', + ps=self.tb, + key=uhd_siggen.WAVEFORM_FREQ_KEY, + converter=forms.float_converter(), + ) + sweep_bb_hbox.AddStretchSpacer() + forms.text_box( + parent=self.panel, sizer=sweep_bb_hbox, + label='Sweep Rate (Hz)', + ps=self.tb, + key=uhd_siggen.WAVEFORM2_FREQ_KEY, + converter=forms.float_converter(), + ) + sweep_bb_hbox.AddStretchSpacer() + #create 2tone forms + tone_bb_hbox.AddSpacer(10) + forms.text_box( + parent=self.panel, sizer=tone_bb_hbox, + label='Tone 1 (Hz)', + ps=self.tb, + key=uhd_siggen.WAVEFORM_FREQ_KEY, + converter=forms.float_converter(), + ) + tone_bb_hbox.AddStretchSpacer() + forms.text_box( + parent=self.panel, sizer=tone_bb_hbox, + label='Tone 2 (Hz)', + ps=self.tb, + key=uhd_siggen.WAVEFORM2_FREQ_KEY, + converter=forms.float_converter(), + ) + tone_bb_hbox.AddStretchSpacer() + forms.radio_buttons( + parent=self.panel, sizer=bb_vbox, + choices=uhd_siggen.waveforms.keys(), + labels=uhd_siggen.waveforms.values(), + ps=self.tb, + key=uhd_siggen.TYPE_KEY, + style=wx.NO_BORDER | wx.RA_HORIZONTAL, + ) + bb_vbox.AddSpacer(10) + bb_vbox.Add(sine_bb_hbox, 0, wx.EXPAND) + bb_vbox.Add(sweep_bb_hbox, 0, wx.EXPAND) + bb_vbox.Add(tone_bb_hbox, 0, wx.EXPAND) + set_type(self.tb[uhd_siggen.TYPE_KEY]) + + ################################################## + # Frequency controls + ################################################## + fc_vbox = forms.static_box_sizer(parent=self.panel, + label="Center Frequency", + orient=wx.VERTICAL, + bold=True) + fc_vbox.AddSpacer(5) + # First row of frequency controls (center frequency) + freq_hbox = wx.BoxSizer(wx.HORIZONTAL) + fc_vbox.Add(freq_hbox, 0, wx.EXPAND) + fc_vbox.AddSpacer(10) + # Second row of frequency controls (results) + tr_hbox = wx.BoxSizer(wx.HORIZONTAL) + fc_vbox.Add(tr_hbox, 0, wx.EXPAND) + fc_vbox.AddSpacer(5) + # Add frequency controls to top window sizer + self.vbox.Add(fc_vbox, 0, wx.EXPAND) + self.vbox.AddSpacer(10) + self.vbox.AddStretchSpacer() + freq_hbox.AddSpacer(5) + forms.text_box( + parent=self.panel, sizer=freq_hbox, + proportion=1, + converter=forms.float_converter(), + ps=self.tb, + key=uhd_siggen.TX_FREQ_KEY, + ) + freq_hbox.AddSpacer(10) + + forms.slider( + parent=self.panel, sizer=freq_hbox, + proportion=2, + ps=self.tb, + key=uhd_siggen.TX_FREQ_KEY, + minimum=self.tb[uhd_siggen.FREQ_RANGE_KEY].start(), + maximum=self.tb[uhd_siggen.FREQ_RANGE_KEY].stop(), + num_steps=100, + ) + freq_hbox.AddSpacer(5) + tr_hbox.AddSpacer(5) + forms.static_text( + parent=self.panel, sizer=tr_hbox, + label='RF Frequency', + ps=self.tb, + key=uhd_siggen.RF_FREQ_KEY, + converter=forms.float_converter(), + proportion=1, + ) + tr_hbox.AddSpacer(10) + forms.static_text( + parent=self.panel, sizer=tr_hbox, + label='DSP Frequency', + ps=self.tb, + key=uhd_siggen.DSP_FREQ_KEY, + converter=forms.float_converter(), + proportion=1, + ) + tr_hbox.AddSpacer(5) + + ################################################## + # Amplitude controls + ################################################## + amp_hbox = forms.static_box_sizer(parent=self.panel, + label="Amplitude", + orient=wx.VERTICAL, + bold=True) + amp_hbox.AddSpacer(5) + # First row of amp controls (ampl) + lvl_hbox = wx.BoxSizer(wx.HORIZONTAL) + amp_hbox.Add(lvl_hbox, 0, wx.EXPAND) + amp_hbox.AddSpacer(10) + # Second row of amp controls (tx gain) + gain_hbox = wx.BoxSizer(wx.HORIZONTAL) + amp_hbox.Add(gain_hbox, 0, wx.EXPAND) + amp_hbox.AddSpacer(5) + self.vbox.Add(amp_hbox, 0, wx.EXPAND) + self.vbox.AddSpacer(10) + self.vbox.AddStretchSpacer() + lvl_hbox.AddSpacer(5) + forms.text_box( + parent=self.panel, sizer=lvl_hbox, + proportion=1, + converter=forms.float_converter(), + ps=self.tb, + key=uhd_siggen.AMPLITUDE_KEY, + label="Level (0.0-1.0)", + ) + lvl_hbox.AddSpacer(10) + forms.log_slider( + parent=self.panel, sizer=lvl_hbox, + proportion=2, + ps=self.tb, + key=uhd_siggen.AMPLITUDE_KEY, + min_exp=-6, + max_exp=0, + base=10, + num_steps=100, + ) + lvl_hbox.AddSpacer(5) + if self.tb[uhd_siggen.GAIN_RANGE_KEY].start() < self.tb[uhd_siggen.GAIN_RANGE_KEY].stop(): + gain_hbox.AddSpacer(5) + forms.text_box( + parent=self.panel, sizer=gain_hbox, + proportion=1, + converter=forms.float_converter(), + ps=self.tb, + key=uhd_siggen.GAIN_KEY, + label="TX Gain (dB)", + ) + gain_hbox.AddSpacer(10) + forms.slider( + parent=self.panel, sizer=gain_hbox, + proportion=2, + ps=self.tb, + key=uhd_siggen.GAIN_KEY, + minimum=self.tb[uhd_siggen.GAIN_RANGE_KEY].start(), + maximum=self.tb[uhd_siggen.GAIN_RANGE_KEY].stop(), + step_size=self.tb[uhd_siggen.GAIN_RANGE_KEY].step(), + ) + gain_hbox.AddSpacer(5) + + ################################################## + # Sample Rate controls + ################################################## + sam_hbox = forms.static_box_sizer(parent=self.panel, + label="Sample Rate", + orient=wx.HORIZONTAL, + bold=True) + self.vbox.Add(sam_hbox, 0, wx.EXPAND) + self.vbox.AddSpacer(10) + self.vbox.AddStretchSpacer() + sam_hbox.AddStretchSpacer(20) + forms.static_text( + parent=self.panel, sizer=sam_hbox, + label='Sample Rate (sps)', + ps=self.tb, + key=uhd_siggen.SAMP_RATE_KEY, + converter=forms.float_converter(), + ) + sam_hbox.AddStretchSpacer(20) + + ################################################## + # UHD status + ################################################## + u2_hbox = forms.static_box_sizer(parent=self.panel, + label="UHD Status", + orient=wx.HORIZONTAL, + bold=True) + self.vbox.Add(u2_hbox, 0, wx.EXPAND) + self.vbox.AddSpacer(10) + self.vbox.AddStretchSpacer() + u2_hbox.AddSpacer(10) + forms.static_text( + parent=self.panel, sizer=u2_hbox, + ps=self.tb, + key=uhd_siggen.DESC_KEY, + converter=forms.str_converter(), + ) + self.vbox.AddSpacer(5) + self.vbox.AddStretchSpacer() + +def main(): + try: + # Get command line parameters + (options, args) = uhd_siggen.get_options() + + # Create the top block using these + tb = uhd_siggen.top_block(options, args) + + # Create the GUI application + app = gui.app(top_block=tb, # Constructed top block + gui=app_gui, # User interface class + options=options, # Command line options + args=args, # Command line args + title="UHD Signal Generator", # Top window title + nstatus=1, # Number of status lines + start=True, # Whether to start flowgraph + realtime=True) # Whether to set realtime priority + + # And run it + app.MainLoop() + + except RuntimeError, e: + print e + sys.exit(1) + +# Make sure to create the top block (tb) within a function: That code +# in main will allow tb to go out of scope on return, which will call +# the decontructor on uhd device and stop transmit. Whats odd is that +# grc works fine with tb in the __main__, perhaps its because the +# try/except clauses around tb. +if __name__ == "__main__": main() |