aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri Stolnikov <horiz0n@gmx.net>2013-05-09 13:48:16 +0200
committerDimitri Stolnikov <horiz0n@gmx.net>2013-05-09 13:48:16 +0200
commit3393647bec42b37a5f05ac67d171da9ac8e837d4 (patch)
tree62757d8af9403b54a66dbab03be3ce4823f85ba7
parent7c22e6975ccb1f2a4b5072e49fad1a928f0ceeee (diff)
apps: add named gain controls to fft and siggen apps
usage examples: osmocom_fft -a hackrf -v osmocom_fft -a rtl=0 -v osmocom_fft -a uhd -v osmocom_siggen -a hackrf -f 100e6 --sweep -x 2e6 -y 10 -v osmocom_siggen -a uhd,subdev=A:0 -f 100e6 --sweep -x 2e6 -y 10 -s 4e6 -v
-rw-r--r--apps/CMakeLists.txt2
-rwxr-xr-xapps/osmocom_fft452
-rwxr-xr-xapps/osmocom_siggen352
-rw-r--r--apps/osmocom_siggen_base.py136
-rwxr-xr-xapps/osmocom_siggen_gui374
-rwxr-xr-xapps/osmocom_siggen_nogui51
6 files changed, 781 insertions, 586 deletions
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 88e5d4a..9f1a958 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -29,6 +29,6 @@ GR_PYTHON_INSTALL(
PROGRAMS
osmocom_fft
osmocom_siggen
- osmocom_siggen_gui
+ osmocom_siggen_nogui
DESTINATION ${GR_RUNTIME_DIR}
)
diff --git a/apps/osmocom_fft b/apps/osmocom_fft
index 5449354..85406b1 100755
--- a/apps/osmocom_fft
+++ b/apps/osmocom_fft
@@ -20,9 +20,20 @@
# Boston, MA 02110-1301, USA.
#
+SAMP_RANGE_KEY = 'samp_range'
+SAMP_RATE_KEY = 'samp_rate'
+GAIN_KEY = lambda x: 'gain:'+x
+BWIDTH_KEY = 'bwidth'
+CENTER_FREQ_KEY = 'center_freq'
+FREQ_CORR_KEY = 'freq_corr'
+FREQ_RANGE_KEY = 'freq_range'
+GAIN_RANGE_KEY = lambda x: 'gain_range:'+x
+BWIDTH_RANGE_KEY = 'bwidth_range'
+
import osmosdr
from gnuradio import gr, gru
from gnuradio import eng_notation
+from gnuradio.gr.pubsub import pubsub
from gnuradio.eng_option import eng_option
from optparse import OptionParser
@@ -38,24 +49,27 @@ except ImportError:
sys.stderr.write("Error importing GNU Radio's wxgui. Please make sure gr-wxgui is installed.\n")
sys.exit(1)
-class app_top_block(stdgui2.std_top_block):
+class app_top_block(stdgui2.std_top_block, pubsub):
def __init__(self, frame, panel, vbox, argv):
stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)
+ pubsub.__init__(self)
self.frame = frame
self.panel = panel
parser = OptionParser(option_class=eng_option)
parser.add_option("-a", "--args", type="string", default="",
- help="device args, [default=%default]")
+ help="Device args, [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("-f", "--freq", type="eng_float", default=None,
- help="set frequency to FREQ", metavar="FREQ")
+ help="Select RX antenna where appropriate")
+ parser.add_option("-s", "--samp-rate", type="eng_float", default=None,
+ help="Set sample rate (bandwidth), minimum by default")
+ parser.add_option("-f", "--center-freq", type="eng_float", default=None,
+ help="Set frequency to FREQ", metavar="FREQ")
+ parser.add_option("-c", "--freq-corr", type="eng_float", default=0,
+ help="Set frequency correction (ppm)")
parser.add_option("-g", "--gain", type="eng_float", default=None,
- help="set gain in dB (default is midpoint)")
+ help="Set gain in dB (default is midpoint)")
parser.add_option("-W", "--waterfall", action="store_true", default=False,
help="Enable waterfall display")
parser.add_option("-S", "--oscilloscope", action="store_true", default=False,
@@ -70,30 +84,83 @@ class app_top_block(stdgui2.std_top_block):
help="Set number of FFT bins [default=%default]")
parser.add_option("", "--fft-rate", type="int", default=30,
help="Set FFT update rate, [default=%default]")
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="Use verbose console output [default=%default]")
(options, args) = parser.parse_args()
if len(args) != 0:
parser.print_help()
sys.exit(1)
self.options = options
- self.show_debug_info = True
+
+ self._verbose = options.verbose
self.src = osmosdr.source_c(options.args)
# Set the antenna
if(options.antenna):
- self.src.set_antenna(options.antenna, 0)
+ self.src.set_antenna(options.antenna)
+
+ if options.samp_rate is None:
+ options.samp_rate = self.src.get_sample_rates().start()
+
+ if options.gain is None:
+ # if no gain was specified, use the mid-point in dB
+ r = self.src.get_gain_range()
+ options.gain = float(r.start()+r.stop())/2
+
+ if options.center_freq is None:
+ # if no freq was specified, use the mid-point in Hz
+ r = self.src.get_freq_range()
+ options.center_freq = float(r.start()+r.stop())/2
+
+ input_rate = self.src.set_sample_rate(options.samp_rate)
+
+ self.src.set_gain(options.gain)
+
+ #print self.src.get_sample_rates().to_pp_string()
+
+ self.publish(SAMP_RANGE_KEY, self.src.get_sample_rates)
+ self.publish(FREQ_RANGE_KEY, self.src.get_freq_range)
+
+ for name in self.get_gain_names():
+ self.publish(GAIN_RANGE_KEY(name), (lambda self=self,name=name: self.src.get_gain_range(name)))
+
+ self.publish(BWIDTH_RANGE_KEY, self.src.get_bandwidth_range)
- self.src.set_sample_rate(options.samp_rate)
- input_rate = self.src.get_sample_rate()
+ for name in self.get_gain_names():
+ self.publish(GAIN_KEY(name), (lambda self=self,name=name: self.src.get_gain(name)))
+
+ self.publish(BWIDTH_KEY, self.src.get_bandwidth)
+
+ #initialize values from options
+ self[SAMP_RANGE_KEY] = self.src.get_sample_rates()
+ self[SAMP_RATE_KEY] = options.samp_rate
+ self[CENTER_FREQ_KEY] = options.center_freq
+ self[FREQ_CORR_KEY] = options.freq_corr
+
+ #subscribe set methods
+ self.subscribe(SAMP_RATE_KEY, self.set_sample_rate)
+
+ for name in self.get_gain_names():
+ self.subscribe(GAIN_KEY(name), (lambda gain,self=self,name=name: self.set_named_gain(gain, name)))
+
+ self.subscribe(BWIDTH_KEY, self.set_bandwidth)
+ self.subscribe(CENTER_FREQ_KEY, self.set_freq)
+ self.subscribe(FREQ_CORR_KEY, self.set_freq_corr)
+
+ #force update on pubsub keys
+ for key in (SAMP_RATE_KEY, BWIDTH_KEY, CENTER_FREQ_KEY, FREQ_CORR_KEY):
+ print key, "=", self[key]
+ #self[key] = self[key]
if options.waterfall:
self.scope = \
- waterfallsink2.waterfall_sink_c (panel, fft_size=1024,
+ waterfallsink2.waterfallsrc_c (panel, fft_size=options.fft_size,
sample_rate=input_rate)
self.frame.SetMinSize((800, 420))
elif options.oscilloscope:
- self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate)
+ self.scope = scopesink2.scopesrc_c(panel, sample_rate=input_rate)
self.frame.SetMinSize((800, 600))
else:
self.scope = fftsink2.fft_sink_c (panel,
@@ -107,7 +174,7 @@ class app_top_block(stdgui2.std_top_block):
fft_rate=options.fft_rate)
def fftsink_callback(x, y):
self.set_freq(x)
-
+
self.scope.set_callback(fftsink_callback)
self.frame.SetMinSize((800, 420))
@@ -116,25 +183,8 @@ class app_top_block(stdgui2.std_top_block):
self._build_gui(vbox)
self._setup_events()
-
# set initial values
-
- if options.gain is None:
- # if no gain was specified, use the mid-point in dB
- g = self.src.get_gain_range()
- options.gain = float(g.start()+g.stop())/2
-
- if options.freq is None:
- # if no freq was specified, use the mid-point
- r = self.src.get_freq_range()
- options.freq = float(r.start()+r.stop())/2
-
- self.set_gain(options.gain)
-
- if self.show_debug_info:
- self.myform['samprate'].set_value(self.src.get_sample_rate())
-
- if not(self.set_freq(options.freq)):
+ if not(self.set_freq(options.center_freq)):
self._set_status_msg("Failed to set initial frequency")
def _set_status_msg(self, msg):
@@ -142,99 +192,271 @@ class app_top_block(stdgui2.std_top_block):
def _build_gui(self, vbox):
- def _form_set_freq(kv):
- return self.set_freq(kv['freq'])
-
- vbox.Add(self.scope.win, 10, wx.EXPAND)
+ vbox.Add(self.scope.win, 0, wx.EXPAND)
+ vbox.AddSpacer(3)
# add control area at the bottom
self.myform = myform = form.form()
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- hbox.Add((4,0), 0, 0)
- myform['freq'] = form.float_field(
- parent=self.panel, sizer=hbox, label="Center freq", weight=1,
- callback=myform.check_input_and_call(_form_set_freq,
- self._set_status_msg))
-
- hbox.Add((4,0), 0, 0)
- g = self.src.get_gain_range()
-
- # some configurations don't have gain control
- if g.stop() <= g.start():
- glow = 0.0
- ghigh = 1.0
-
- else:
- glow = g.start()
- ghigh = g.stop()
-
- myform['gain'] = form.slider_field(parent=self.panel,
- sizer=hbox, label="Gain",
- weight=3,
- min=int(glow), max=int(ghigh),
- callback=self.set_gain)
- hbox.Add((4,0), 0, 0)
- vbox.Add(hbox, 0, wx.EXPAND)
-
- self._build_subpanel(vbox)
-
- def _build_subpanel(self, vbox_arg):
- # build a secondary information panel (sometimes hidden)
- # FIXME figure out how to have this be a subpanel that is always
- # created, but has its visibility controlled by foo.Show(True/False)
-
- def _form_set_sample_rate(kv):
- return self.set_sample_rate(kv['samprate'])
-
- if not(self.show_debug_info):
- return
-
- panel = self.panel
- vbox = vbox_arg
- myform = self.myform
-
- hbox = wx.BoxSizer(wx.HORIZONTAL)
-
- hbox.Add((4,0), 0)
- myform['samprate'] = form.float_field(
- parent=panel, sizer=hbox, label="Sample Rate",
- callback=myform.check_input_and_call(_form_set_sample_rate,
- self._set_status_msg))
+ ##################################################
+ # Frequency controls
+ ##################################################
+ fc_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Center Frequency",
+ orient=wx.VERTICAL,
+ bold=True)
+ fc_vbox.AddSpacer(3)
+ # First row of frequency controls (center frequency)
+ freq_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ fc_vbox.Add(freq_hbox, 0, wx.EXPAND)
+ fc_vbox.AddSpacer(5)
+ # Second row of frequency controls (freq. correction)
+ corr_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ fc_vbox.Add(corr_hbox, 0, wx.EXPAND)
+ fc_vbox.AddSpacer(3)
+
+ # Add frequency controls to top window sizer
+ vbox.Add(fc_vbox, 0, wx.EXPAND)
vbox.AddSpacer(5)
-
- vbox.Add(hbox, 0, wx.EXPAND)
+ vbox.AddStretchSpacer()
+
+ freq_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=freq_hbox,
+ label='Center Frequency (Hz)',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=CENTER_FREQ_KEY,
+ )
+ freq_hbox.AddSpacer(5)
+
+ forms.slider(
+ parent=self.panel, sizer=freq_hbox,
+ proportion=3,
+ ps=self,
+ key=CENTER_FREQ_KEY,
+ minimum=self[FREQ_RANGE_KEY].start(),
+ maximum=self[FREQ_RANGE_KEY].stop(),
+ num_steps=101,
+ )
+ freq_hbox.AddSpacer(3)
+
+ corr_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=corr_hbox,
+ label='Freq. Correction (ppm)',
+ proportion=1,
+ converter=forms.int_converter(),
+ ps=self,
+ key=FREQ_CORR_KEY,
+ )
+ corr_hbox.AddSpacer(5)
+
+ forms.slider(
+ parent=self.panel, sizer=corr_hbox,
+ proportion=3,
+ ps=self,
+ key=FREQ_CORR_KEY,
+ minimum=-100,
+ maximum=+100,
+ num_steps=201,
+ step_size=1,
+ )
+ corr_hbox.AddSpacer(3)
+
+ ##################################################
+ # Gain controls
+ ##################################################
+ gc_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Gain Settings",
+ orient=wx.VERTICAL,
+ bold=True)
+ gc_vbox.AddSpacer(3)
+
+ # Add gain controls to top window sizer
+ vbox.Add(gc_vbox, 0, wx.EXPAND)
vbox.AddSpacer(5)
+ vbox.AddStretchSpacer()
+
+ for gain_name in self.get_gain_names():
+ range = self[GAIN_RANGE_KEY(gain_name)]
+ gain = self[GAIN_KEY(gain_name)]
+
+ #print gain_name, gain, range.to_pp_string()
+ if range.start() < range.stop():
+ gain_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ gc_vbox.Add(gain_hbox, 0, wx.EXPAND)
+ gc_vbox.AddSpacer(3)
+
+ gain_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=gain_hbox,
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=GAIN_KEY(gain_name),
+ label=gain_name + " Gain (dB)",
+ )
+ gain_hbox.AddSpacer(5)
+ forms.slider(
+ parent=self.panel, sizer=gain_hbox,
+ proportion=3,
+ ps=self,
+ key=GAIN_KEY(gain_name),
+ minimum=range.start(),
+ maximum=range.stop(),
+ step_size=range.step(),
+ )
+ gain_hbox.AddSpacer(3)
+
+ ##################################################
+ # Bandwidth controls
+ ##################################################
+ try:
+
+ bw_range = self[BWIDTH_RANGE_KEY]
+ #print bw_range.to_pp_string()
+ #if bw_range.start() < bw_range.stop():
+ if 0:
+ bwidth_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Bandwidth",
+ orient=wx.VERTICAL,
+ bold=True)
+ bwidth_vbox.AddSpacer(3)
+ bwidth_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ bwidth_vbox.Add(bwidth_hbox, 0, wx.EXPAND)
+ bwidth_vbox.AddSpacer(3)
+
+ vbox.Add(bwidth_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(5)
+ vbox.AddStretchSpacer()
+
+ bwidth_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=bwidth_hbox,
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=BWIDTH_KEY,
+ label="Bandwidth (Hz)",
+ )
+ bwidth_hbox.AddSpacer(5)
+ forms.slider(
+ parent=self.panel, sizer=bwidth_hbox,
+ proportion=3,
+ ps=self,
+ key=BWIDTH_KEY,
+ minimum=bw_range.start(),
+ maximum=bw_range.stop(),
+ step_size=bw_range.step(),
+ )
+ bwidth_hbox.AddSpacer(3)
+
+ except RuntimeError:
+ pass
+
+
+ ##################################################
+ # Sample rate controls
+ ##################################################
+ sr_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Sample Rate",
+ orient=wx.VERTICAL,
+ bold=True)
+ sr_vbox.AddSpacer(3)
+ # First row of sample rate controls
+ sr_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ sr_vbox.Add(sr_hbox, 0, wx.EXPAND)
+ sr_vbox.AddSpacer(5)
+
+ # Add frequency controls to top window sizer
+ vbox.Add(sr_vbox, 0, wx.EXPAND)
+ vbox.AddSpacer(5)
+ vbox.AddStretchSpacer()
+
+ sr_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=sr_hbox,
+ label='Sample Rate (Hz)',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self,
+ key=SAMP_RATE_KEY,
+ )
+ sr_hbox.AddSpacer(5)
+
+ #forms.slider(
+ # parent=self.panel, sizer=sr_hbox,
+ # proportion=3,
+ # ps=self,
+ # key=SAMP_RATE_KEY,
+ # minimum=self[SAMP_RANGE_KEY].start(),
+ # maximum=self[SAMP_RANGE_KEY].stop(),
+ # step_size=self[SAMP_RANGE_KEY].step(),
+ #)
+ #sr_hbox.AddSpacer(3)
- def set_freq(self, target_freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @rypte: bool
- """
- actual_freq = self.src.set_center_freq(target_freq, 0)
- self.myform['freq'].set_value(actual_freq)
+ def set_sample_rate(self, samp_rate):
+ samp_rate = self.src.set_sample_rate(samp_rate)
+ self.scope.set_sample_rate(samp_rate)
+ if self._verbose:
+ print "Set sample rate to:", samp_rate
+ return samp_rate
+
+ def get_gain_names(self):
+ return self.src.get_gain_names()
+
+ def set_named_gain(self, gain, name):
+ if gain is None:
+ g = self[GAIN_RANGE_KEY(name)]
+ gain = float(g.start()+g.stop())/2
+ if self._verbose:
+ print "Using auto-calculated mid-point gain"
+ self[GAIN_KEY(name)] = gain
+ return
- if not self.options.oscilloscope:
- self.scope.set_baseband_freq(actual_freq)
+ gain = self.src.set_gain(gain, name)
+ if self._verbose:
+ print "Set " + name + " gain to:", gain
+
+ def set_bandwidth(self, bw):
+ bw = self.src.set_bandwidth(bw)
+ if self._verbose:
+ print "Set bandwidth to:", bw
+
+ def set_freq(self, freq):
+ if freq is None:
+ f = self[FREQ_RANGE_KEY]
+ freq = float(f.start()+f.stop())/2.0
+ if self._verbose:
+ print "Using auto-calculated mid-point frequency"
+ self[CENTER_FREQ_KEY] = freq
+ return
- return True
+ freq = self.src.set_center_freq(freq)
- def set_gain(self, gain):
- if self.myform.has_key('gain'):
- self.myform['gain'].set_value(gain) # update displayed value
- self.src.set_gain(gain, 0)
+ if not self.options.oscilloscope:
+ self.scope.set_baseband_freq(freq)
+
+ if freq is not None:
+ if self._verbose:
+ print "Set center frequency to", freq
+ elif self._verbose:
+ print "Failed to set freq."
+ return freq
+
+ def set_freq_corr(self, ppm):
+ if ppm is None:
+ ppm = 0.0
+ if self._verbose:
+ print "Using frequency corrrection of", ppm
+ self[FREQ_CORR_KEY] = ppm
+ return
- def set_sample_rate(self, samp_rate):
- ok = self.src.set_sample_rate(samp_rate)
- input_rate = self.src.get_sample_rate()
- self.scope.set_sample_rate(input_rate)
- if self.show_debug_info: # update displayed values
- self.myform['samprate'].set_value(self.src.get_sample_rate())
-
- # set_sample_rate never fails; always falls back to closest requested.
- return True
+ ppm = self.src.set_freq_corr(ppm)
+ if self._verbose:
+ print "Set frequency correction to:", ppm
def _setup_events(self):
if not self.options.waterfall and not self.options.oscilloscope:
diff --git a/apps/osmocom_siggen b/apps/osmocom_siggen
index 0283fcf..3724c5b 100755
--- a/apps/osmocom_siggen
+++ b/apps/osmocom_siggen
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2008,2009,2011,2012 Free Software Foundation, Inc.
+# Copyright 2009,2011,2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,31 +21,347 @@
#
from gnuradio import gr
+from gnuradio.gr.pubsub import pubsub
from osmosdr import osmocom_siggen_base as osmocom_siggen
-import sys
+import sys, math
-def main():
- if gr.enable_realtime_scheduling() != gr.RT_OK:
- print "Note: failed to enable realtime scheduling, continuing"
+try:
+ from gnuradio.wxgui import gui, forms
+ import wx
+except ImportError:
+ sys.stderr.write("Error importing GNU Radio's wxgui. Please make sure gr-wxgui is installed.\n")
+ sys.exit(1)
+
+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(3)
+ 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(5)
+ 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(osmocom_siggen.TYPE_KEY, set_type)
+ #create sine forms
+ sine_bb_hbox.AddSpacer(5)
+ forms.text_box(
+ parent=self.panel, sizer=sine_bb_hbox,
+ label='Frequency (Hz)',
+ ps=self.tb,
+ key=osmocom_siggen.WAVEFORM_FREQ_KEY,
+ converter=forms.float_converter(),
+ )
+ sine_bb_hbox.AddStretchSpacer()
+ #create sweep forms
+ sweep_bb_hbox.AddSpacer(5)
+ forms.text_box(
+ parent=self.panel, sizer=sweep_bb_hbox,
+ label='Sweep Width (Hz)',
+ ps=self.tb,
+ key=osmocom_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=osmocom_siggen.WAVEFORM2_FREQ_KEY,
+ converter=forms.float_converter(),
+ )
+ sweep_bb_hbox.AddStretchSpacer()
+ #create 2tone forms
+ tone_bb_hbox.AddSpacer(5)
+ forms.text_box(
+ parent=self.panel, sizer=tone_bb_hbox,
+ label='Tone 1 (Hz)',
+ ps=self.tb,
+ key=osmocom_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=osmocom_siggen.WAVEFORM2_FREQ_KEY,
+ converter=forms.float_converter(),
+ )
+ tone_bb_hbox.AddStretchSpacer()
+ forms.radio_buttons(
+ parent=self.panel, sizer=bb_vbox,
+ choices=osmocom_siggen.waveforms.keys(),
+ labels=osmocom_siggen.waveforms.values(),
+ ps=self.tb,
+ key=osmocom_siggen.TYPE_KEY,
+ style=wx.NO_BORDER | wx.RA_HORIZONTAL,
+ )
+ bb_vbox.AddSpacer(5)
+ 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[osmocom_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(3)
+
+ # First row of frequency controls (center frequency)
+ freq_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ fc_vbox.Add(freq_hbox, 0, wx.EXPAND)
+ fc_vbox.AddSpacer(5)
+
+ # Second row of frequency controls (freq. correction)
+ corr_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ fc_vbox.Add(corr_hbox, 0, wx.EXPAND)
+ fc_vbox.AddSpacer(3)
+
+ # Add frequency controls to top window sizer
+ self.vbox.Add(fc_vbox, 0, wx.EXPAND)
+ self.vbox.AddSpacer(5)
+ self.vbox.AddStretchSpacer()
+
+ freq_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=freq_hbox,
+ label='Center Frequency (Hz)',
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self.tb,
+ key=osmocom_siggen.TX_FREQ_KEY,
+ )
+ freq_hbox.AddSpacer(5)
+
+ forms.slider(
+ parent=self.panel, sizer=freq_hbox,
+ proportion=2,
+ ps=self.tb,
+ key=osmocom_siggen.TX_FREQ_KEY,
+ minimum=self.tb[osmocom_siggen.FREQ_RANGE_KEY].start(),
+ maximum=self.tb[osmocom_siggen.FREQ_RANGE_KEY].stop(),
+ num_steps=101,
+ )
+ freq_hbox.AddSpacer(3)
+
+ corr_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=corr_hbox,
+ label='Freq. Correction (ppm)',
+ proportion=1,
+ converter=forms.int_converter(),
+ ps=self.tb,
+ key=osmocom_siggen.FREQ_CORR_KEY,
+ )
+ corr_hbox.AddSpacer(5)
+
+ forms.slider(
+ parent=self.panel, sizer=corr_hbox,
+ proportion=2,
+ ps=self.tb,
+ key=osmocom_siggen.FREQ_CORR_KEY,
+ minimum=-100,
+ maximum=+100,
+ num_steps=201,
+ step_size=1,
+ )
+ corr_hbox.AddSpacer(3)
+
+ ##################################################
+ # Amplitude controls
+ ##################################################
+ amp_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Amplitude",
+ orient=wx.VERTICAL,
+ bold=True)
+ amp_vbox.AddSpacer(3)
+
+ # First row of amp controls (ampl)
+ lvl_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ amp_vbox.Add(lvl_hbox, 0, wx.EXPAND)
+ amp_vbox.AddSpacer(5)
+
+ self.vbox.Add(amp_vbox, 0, wx.EXPAND)
+ self.vbox.AddSpacer(5)
+ self.vbox.AddStretchSpacer()
- # Grab command line options and create top block
+ lvl_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=lvl_hbox,
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self.tb,
+ key=osmocom_siggen.AMPLITUDE_KEY,
+ label="Level (0.1-1.0)",
+ )
+ lvl_hbox.AddSpacer(5)
+ forms.log_slider(
+ parent=self.panel, sizer=lvl_hbox,
+ proportion=2,
+ ps=self.tb,
+ key=osmocom_siggen.AMPLITUDE_KEY,
+ min_exp=-1,
+ max_exp=0,
+ base=10,
+ num_steps=100,
+ )
+ lvl_hbox.AddSpacer(3)
+
+ for gain_name in self.tb.get_gain_names():
+ range = self.tb[osmocom_siggen.GAIN_RANGE_KEY(gain_name)]
+ gain = self.tb[osmocom_siggen.GAIN_KEY(gain_name)]
+
+ #print gain_name, gain, range.to_pp_string()
+ if range.start() < range.stop():
+ gain_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ amp_vbox.Add(gain_hbox, 0, wx.EXPAND)
+ amp_vbox.AddSpacer(3)
+
+ gain_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=gain_hbox,
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self.tb,
+ key=osmocom_siggen.GAIN_KEY(gain_name),
+ label=gain_name + " Gain (dB)",
+ )
+ gain_hbox.AddSpacer(5)
+ forms.slider(
+ parent=self.panel, sizer=gain_hbox,
+ proportion=2,
+ ps=self.tb,
+ key=osmocom_siggen.GAIN_KEY(gain_name),
+ minimum=range.start(),
+ maximum=range.stop(),
+ step_size=range.step(),
+ )
+ gain_hbox.AddSpacer(3)
+
+ ##################################################
+ # Bandwidth controls
+ ##################################################
+ try:
+
+ bw_range = self.tb[osmocom_siggen.BWIDTH_RANGE_KEY]
+ #print bw_range.to_pp_string()
+ #if bw_range.start() < bw_range.stop():
+ if 0:
+ bwidth_vbox = forms.static_box_sizer(parent=self.panel,
+ label="Bandwidth",
+ orient=wx.VERTICAL,
+ bold=True)
+ bwidth_vbox.AddSpacer(3)
+ bwidth_hbox = wx.BoxSizer(wx.HORIZONTAL)
+ bwidth_vbox.Add(bwidth_hbox, 0, wx.EXPAND)
+ bwidth_vbox.AddSpacer(3)
+
+ self.vbox.Add(bwidth_vbox, 0, wx.EXPAND)
+ self.vbox.AddSpacer(5)
+ self.vbox.AddStretchSpacer()
+
+ bwidth_hbox.AddSpacer(3)
+ forms.text_box(
+ parent=self.panel, sizer=bwidth_hbox,
+ proportion=1,
+ converter=forms.float_converter(),
+ ps=self.tb,
+ key=osmocom_siggen.BWIDTH_KEY,
+ label="Bandwidth (Hz)",
+ )
+ bwidth_hbox.AddSpacer(5)
+ forms.slider(
+ parent=self.panel, sizer=bwidth_hbox,
+ proportion=2,
+ ps=self.tb,
+ key=osmocom_siggen.BWIDTH_KEY,
+ minimum=bw_range.start(),
+ maximum=bw_range.stop(),
+ step_size=bw_range.step(),
+ )
+ bwidth_hbox.AddSpacer(3)
+
+ except RuntimeError:
+ pass
+
+ ##################################################
+ # 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(5)
+ self.vbox.AddStretchSpacer()
+ sam_hbox.AddStretchSpacer(20)
+ forms.static_text(
+ parent=self.panel, sizer=sam_hbox,
+ label='Sample Rate (sps)',
+ ps=self.tb,
+ key=osmocom_siggen.SAMP_RATE_KEY,
+ converter=forms.float_converter(),
+ )
+ sam_hbox.AddStretchSpacer(20)
+
+def main():
try:
+ # Get command line parameters
(options, args) = osmocom_siggen.get_options()
+
+ # Create the top block using these
tb = osmocom_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="OSMOCOM 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)
- 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()
+# 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 radio 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()
diff --git a/apps/osmocom_siggen_base.py b/apps/osmocom_siggen_base.py
index 3b5d1d7..6a12015 100644
--- a/apps/osmocom_siggen_base.py
+++ b/apps/osmocom_siggen_base.py
@@ -21,9 +21,7 @@
#
SAMP_RATE_KEY = 'samp_rate'
-LINK_RATE_KEY = 'link_rate'
-GAIN_KEY = 'gain'
-IF_GAIN_KEY = 'if_gain'
+GAIN_KEY = lambda x: 'gain:'+x
BWIDTH_KEY = 'bwidth'
TX_FREQ_KEY = 'tx_freq'
FREQ_CORR_KEY = 'freq_corr'
@@ -33,8 +31,7 @@ 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'
-IF_GAIN_RANGE_KEY = 'if_gain_range'
+GAIN_RANGE_KEY = lambda x: 'gain_range:'+x
BWIDTH_RANGE_KEY = 'bwidth_range'
TYPE_KEY = 'type'
@@ -50,12 +47,12 @@ import math
n2s = eng_notation.num_to_str
-waveforms = { gr.GR_SIN_WAVE : "Complex Sinusoid",
+waveforms = { gr.GR_SIN_WAVE : "Sinusoid",
gr.GR_CONST_WAVE : "Constant",
gr.GR_GAUSSIAN : "Gaussian Noise",
gr.GR_UNIFORM : "Uniform Noise",
- "2tone" : "Two Tone",
- "sweep" : "Sweep" }
+ "2tone" : "Two Tone (IMD)",
+ "sweep" : "Freq. Sweep" }
#
# GUI-unaware GNU Radio flowgraph. This may be used either with command
@@ -79,8 +76,10 @@ class top_block(gr.top_block, pubsub):
#subscribe set methods
self.subscribe(SAMP_RATE_KEY, self.set_samp_rate)
- self.subscribe(GAIN_KEY, self.set_gain)
- self.subscribe(IF_GAIN_KEY, self.set_if_gain)
+
+ for name in self.get_gain_names():
+ self.subscribe(GAIN_KEY(name), (lambda gain,self=self,name=name: self.set_named_gain(gain, name)))
+
self.subscribe(BWIDTH_KEY, self.set_bandwidth)
self.subscribe(TX_FREQ_KEY, self.set_freq)
self.subscribe(FREQ_CORR_KEY, self.set_freq_corr)
@@ -90,58 +89,50 @@ class top_block(gr.top_block, pubsub):
self.subscribe(TYPE_KEY, self.set_waveform)
#force update on pubsub keys
- for key in (SAMP_RATE_KEY, GAIN_KEY, IF_GAIN_KEY, BWIDTH_KEY,
+ for key in (SAMP_RATE_KEY, GAIN_KEY, BWIDTH_KEY,
TX_FREQ_KEY, FREQ_CORR_KEY, AMPLITUDE_KEY,
WAVEFORM_FREQ_KEY, WAVEFORM_OFFSET_KEY, WAVEFORM2_FREQ_KEY):
-# print "key: ", key, "=", self[key]
+ #print key, "=", self[key]
self[key] = self[key]
self[TYPE_KEY] = options.type #set type last
def _setup_osmosdr(self, options):
self._sink = osmosdr.sink_c(options.args)
- self._sink.set_sample_rate(options.samp_rate)
+
+ if options.samp_rate is None:
+ options.samp_rate = self._sink.get_sample_rates().start()
+
+ self.set_samp_rate(options.samp_rate)
# Set the gain from options
if(options.gain):
- self._sink.set_gain(options.gain)
+ gain = self._sink.set_gain(options.gain)
+ if self._verbose:
+ print "Set gain to:", gain
# Set the antenna
if(options.antenna):
- self._sink.set_antenna(options.antenna, 0)
+ ant = self._sink.set_antenna(options.antenna, 0)
+ if self._verbose:
+ print "Set antenna to:", ant
self.publish(FREQ_RANGE_KEY, self._sink.get_freq_range)
- self.publish(GAIN_RANGE_KEY, self._get_rf_gain_range)
- self.publish(IF_GAIN_RANGE_KEY, self._get_if_gain_range)
- self.publish(BWIDTH_RANGE_KEY, self._sink.get_bandwidth_range)
- self.publish(GAIN_KEY, self._get_rf_gain)
- self.publish(IF_GAIN_KEY, self._get_if_gain)
- self.publish(BWIDTH_KEY, self._sink.get_bandwidth)
- def _get_rf_gain_range(self):
- return self._sink.get_gain_range("RF")
+ for name in self.get_gain_names():
+ self.publish(GAIN_RANGE_KEY(name), (lambda self=self,name=name: self._sink.get_gain_range(name)))
- def _get_if_gain_range(self):
- return self._sink.get_gain_range("IF")
+ self.publish(BWIDTH_RANGE_KEY, self._sink.get_bandwidth_range)
- def _get_rf_gain(self):
- return self._sink.get_gain("RF")
+ for name in self.get_gain_names():
+ self.publish(GAIN_KEY(name), (lambda self=self,name=name: self._sink.get_gain(name)))
- def _get_if_gain(self):
- return self._sink.get_gain("IF")
+ self.publish(BWIDTH_KEY, self._sink.get_bandwidth)
- def _set_tx_amplitude(self, ampl):
- """
- Sets the transmit amplitude
- @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.3 + ampl_range[0]
- self[AMPLITUDE_KEY] = max(ampl_range[0], min(ampl, ampl_range[1]))
+ def get_gain_names(self):
+ return self._sink.get_gain_names()
def set_samp_rate(self, sr):
- self._sink.set_sample_rate(sr)
- sr = self._sink.get_sample_rate()
+ sr = self._sink.set_sample_rate(sr)
if self[TYPE_KEY] in (gr.GR_SIN_WAVE, gr.GR_CONST_WAVE):
self._src.set_sampling_freq(self[SAMP_RATE_KEY])
@@ -159,64 +150,53 @@ class top_block(gr.top_block, pubsub):
return True
- def set_gain(self, gain):
+ def set_named_gain(self, gain, name):
if gain is None:
- g = self[GAIN_RANGE_KEY]
+ g = self[GAIN_RANGE_KEY(name)]
gain = float(g.start()+g.stop())/2
if self._verbose:
- print "Using auto-calculated mid-point RF gain"
- self[GAIN_KEY] = gain
+ print "Using auto-calculated mid-point gain"
+ self[GAIN_KEY(name)] = gain
return
- gain = self._sink.set_gain(gain, "RF")
- if self._verbose:
- print "Set RF gain to:", gain
- def set_if_gain(self, gain):
- if gain is None:
- g = self[IF_GAIN_RANGE_KEY]
- gain = float(g.start()+g.stop())/2
- if self._verbose:
- print "Using auto-calculated mid-point IF gain"
- self[IF_GAIN_KEY] = gain
- return
- gain = self._sink.set_gain(gain, "IF")
+ gain = self._sink.set_gain(gain, name)
if self._verbose:
- print "Set IF gain to:", gain
+ print "Set " + name + " gain to:", gain
def set_bandwidth(self, bw):
bw = self._sink.set_bandwidth(bw)
if self._verbose:
print "Set bandwidth to:", bw
- def set_freq(self, target_freq):
-
- if target_freq is None:
+ def set_freq(self, freq):
+ if freq is None:
f = self[FREQ_RANGE_KEY]
- target_freq = float(f.start()+f.stop())/2.0
+ freq = float(f.start()+f.stop())/2.0
if self._verbose:
print "Using auto-calculated mid-point frequency"
- self[TX_FREQ_KEY] = target_freq
+ self[TX_FREQ_KEY] = freq
return
- tr = self._sink.set_center_freq(target_freq)
- if tr is not None:
- self._freq = tr
+ freq = self._sink.set_center_freq(freq)
+ if freq is not None:
+ self._freq = freq
if self._verbose:
- print "Set center frequency to", tr
+ print "Set center frequency to", freq
elif self._verbose:
print "Failed to set freq."
- return tr
+ return freq
def set_freq_corr(self, ppm):
if ppm is None:
+ ppm = 0.0
if self._verbose:
- print "Setting freq corrrection to 0"
- self[FREQ_CORR_KEY] = 0
+ print "Using frequency corrrection of", ppm
+ self[FREQ_CORR_KEY] = ppm
return
ppm = self._sink.set_freq_corr(ppm)
if self._verbose:
- print "Set freq correction to:", ppm
+ print "Set frequency correction to:", ppm
def set_waveform_freq(self, freq):
if self[TYPE_KEY] == gr.GR_SIN_WAVE:
@@ -242,11 +222,11 @@ class top_block(gr.top_block, pubsub):
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
+ 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":
@@ -330,8 +310,8 @@ def get_options():
help="Device args, [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("-s", "--samp-rate", type="eng_float", default=None,
+ help="Set sample rate (bandwidth), minimum by 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,
@@ -359,7 +339,7 @@ def get_options():
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.3,
- help="Set output amplitude to AMPL (0.0-1.0) [default=%default]",
+ help="Set output amplitude to AMPL (0.1-1.0) [default=%default]",
metavar="AMPL")
parser.add_option("-v", "--verbose", action="store_true", default=False,
help="Use verbose console output [default=%default]")
diff --git a/apps/osmocom_siggen_gui b/apps/osmocom_siggen_gui
deleted file mode 100755
index 86003c4..0000000
--- a/apps/osmocom_siggen_gui
+++ /dev/null
@@ -1,374 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2009,2011,2012 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.
-#
-
-from gnuradio import gr
-from gnuradio.gr.pubsub import pubsub
-from osmosdr import osmocom_siggen_base as osmocom_siggen
-import sys, math
-
-try:
- from gnuradio.wxgui import gui, forms
- import wx
-except ImportError:
- sys.stderr.write("Error importing GNU Radio's wxgui. Please make sure gr-wxgui is installed.\n")
- sys.exit(1)
-
-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(3)
- 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(5)
- 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(osmocom_siggen.TYPE_KEY, set_type)
- #create sine forms
- sine_bb_hbox.AddSpacer(5)
- forms.text_box(
- parent=self.panel, sizer=sine_bb_hbox,
- label='Frequency (Hz)',
- ps=self.tb,
- key=osmocom_siggen.WAVEFORM_FREQ_KEY,
- converter=forms.float_converter(),
- )
- sine_bb_hbox.AddStretchSpacer()
- #create sweep forms
- sweep_bb_hbox.AddSpacer(5)
- forms.text_box(
- parent=self.panel, sizer=sweep_bb_hbox,
- label='Sweep Width (Hz)',
- ps=self.tb,
- key=osmocom_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=osmocom_siggen.WAVEFORM2_FREQ_KEY,
- converter=forms.float_converter(),
- )
- sweep_bb_hbox.AddStretchSpacer()
- #create 2tone forms
- tone_bb_hbox.AddSpacer(5)
- forms.text_box(
- parent=self.panel, sizer=tone_bb_hbox,
- label='Tone 1 (Hz)',
- ps=self.tb,
- key=osmocom_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=osmocom_siggen.WAVEFORM2_FREQ_KEY,
- converter=forms.float_converter(),
- )
- tone_bb_hbox.AddStretchSpacer()
- forms.radio_buttons(
- parent=self.panel, sizer=bb_vbox,
- choices=osmocom_siggen.waveforms.keys(),
- labels=osmocom_siggen.waveforms.values(),
- ps=self.tb,
- key=osmocom_siggen.TYPE_KEY,
- style=wx.NO_BORDER | wx.RA_HORIZONTAL,
- )
- bb_vbox.AddSpacer(5)
- 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[osmocom_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(3)
- # First row of frequency controls (center frequency)
- freq_hbox = wx.BoxSizer(wx.HORIZONTAL)
- fc_vbox.Add(freq_hbox, 0, wx.EXPAND)
- fc_vbox.AddSpacer(5)
- # Second row of frequency controls (freq. correction)
- corr_hbox = wx.BoxSizer(wx.HORIZONTAL)
- fc_vbox.Add(corr_hbox, 0, wx.EXPAND)
- fc_vbox.AddSpacer(3)
- # Add frequency controls to top window sizer
- self.vbox.Add(fc_vbox, 0, wx.EXPAND)
- self.vbox.AddSpacer(5)
- self.vbox.AddStretchSpacer()
-
- freq_hbox.AddSpacer(3)
- forms.text_box(
- parent=self.panel, sizer=freq_hbox,
- label='Center Frequency (Hz)',
- proportion=1,
- converter=forms.float_converter(),
- ps=self.tb,
- key=osmocom_siggen.TX_FREQ_KEY,
- )
- freq_hbox.AddSpacer(5)
-
- forms.slider(
- parent=self.panel, sizer=freq_hbox,
- proportion=2,
- ps=self.tb,
- key=osmocom_siggen.TX_FREQ_KEY,
- minimum=self.tb[osmocom_siggen.FREQ_RANGE_KEY].start(),
- maximum=self.tb[osmocom_siggen.FREQ_RANGE_KEY].stop(),
- num_steps=100,
- )
- freq_hbox.AddSpacer(3)
-
- corr_hbox.AddSpacer(3)
- forms.text_box(
- parent=self.panel, sizer=corr_hbox,
- label='Frequency Correction (ppm)',
- proportion=1,
- converter=forms.int_converter(),
- ps=self.tb,
- key=osmocom_siggen.FREQ_CORR_KEY,
- )
- corr_hbox.AddSpacer(5)
-
- forms.slider(
- parent=self.panel, sizer=corr_hbox,
- proportion=2,
- ps=self.tb,
- key=osmocom_siggen.FREQ_CORR_KEY,
- minimum=-100,
- maximum=+100,
- num_steps=201,
- )
- corr_hbox.AddSpacer(3)
-
- ##################################################
- # Amplitude controls
- ##################################################
- amp_vbox = forms.static_box_sizer(parent=self.panel,
- label="Amplitude",
- orient=wx.VERTICAL,
- bold=True)
- amp_vbox.AddSpacer(3)
- # First row of amp controls (ampl)
- lvl_hbox = wx.BoxSizer(wx.HORIZONTAL)
- amp_vbox.Add(lvl_hbox, 0, wx.EXPAND)
- amp_vbox.AddSpacer(5)
- # Second row of amp controls (tx gain)
- gain_hbox = wx.BoxSizer(wx.HORIZONTAL)
- amp_vbox.Add(gain_hbox, 0, wx.EXPAND)
- amp_vbox.AddSpacer(3)
- if_gain_hbox = wx.BoxSizer(wx.HORIZONTAL)
- amp_vbox.Add(if_gain_hbox, 0, wx.EXPAND)
- amp_vbox.AddSpacer(3)
-
- self.vbox.Add(amp_vbox, 0, wx.EXPAND)
- self.vbox.AddSpacer(5)
- self.vbox.AddStretchSpacer()
-
- lvl_hbox.AddSpacer(3)
- forms.text_box(
- parent=self.panel, sizer=lvl_hbox,
- proportion=1,
- converter=forms.float_converter(),
- ps=self.tb,
- key=osmocom_siggen.AMPLITUDE_KEY,
- label="Level (0.0-1.0)",
- )
- lvl_hbox.AddSpacer(5)
- forms.log_slider(
- parent=self.panel, sizer=lvl_hbox,
- proportion=2,
- ps=self.tb,
- key=osmocom_siggen.AMPLITUDE_KEY,
- min_exp=-6,
- max_exp=0,
- base=10,
- num_steps=100,
- )
- lvl_hbox.AddSpacer(3)
-
- if self.tb[osmocom_siggen.GAIN_RANGE_KEY].start() < self.tb[osmocom_siggen.GAIN_RANGE_KEY].stop():
- gain_hbox.AddSpacer(3)
- forms.text_box(
- parent=self.panel, sizer=gain_hbox,
- proportion=1,
- converter=forms.float_converter(),
- ps=self.tb,
- key=osmocom_siggen.GAIN_KEY,
- label="RF Gain (dB)",
- )
- gain_hbox.AddSpacer(5)
- forms.slider(
- parent=self.panel, sizer=gain_hbox,
- proportion=2,
- ps=self.tb,
- key=osmocom_siggen.GAIN_KEY,
- minimum=self.tb[osmocom_siggen.GAIN_RANGE_KEY].start(),
- maximum=self.tb[osmocom_siggen.GAIN_RANGE_KEY].stop(),
- step_size=self.tb[osmocom_siggen.GAIN_RANGE_KEY].step(),
- )
- gain_hbox.AddSpacer(3)
-
- if self.tb[osmocom_siggen.IF_GAIN_RANGE_KEY].start() < self.tb[osmocom_siggen.IF_GAIN_RANGE_KEY].stop():
- if_gain_hbox.AddSpacer(3)
- forms.text_box(
- parent=self.panel, sizer=if_gain_hbox,
- proportion=1,
- converter=forms.float_converter(),
- ps=self.tb,
- key=osmocom_siggen.IF_GAIN_KEY,
- label="IF Gain (dB)",
- )
- if_gain_hbox.AddSpacer(5)
- forms.slider(
- parent=self.panel, sizer=if_gain_hbox,
- proportion=2,
- ps=self.tb,
- key=osmocom_siggen.IF_GAIN_KEY,
- minimum=self.tb[osmocom_siggen.IF_GAIN_RANGE_KEY].start(),
- maximum=self.tb[osmocom_siggen.IF_GAIN_RANGE_KEY].stop(),
- step_size=self.tb[osmocom_siggen.IF_GAIN_RANGE_KEY].step(),
- )
- if_gain_hbox.AddSpacer(3)
-
- ##################################################
- # Bandiwdth controls
- ##################################################
- bwidth_vbox = forms.static_box_sizer(parent=self.panel,
- label="Bandwidth",
- orient=wx.VERTICAL,
- bold=True)
- bwidth_vbox.AddSpacer(3)
- bwidth_hbox = wx.BoxSizer(wx.HORIZONTAL)
- bwidth_vbox.Add(bwidth_hbox, 0, wx.EXPAND)
- bwidth_vbox.AddSpacer(3)
-
- self.vbox.Add(bwidth_vbox, 0, wx.EXPAND)
- self.vbox.AddSpacer(5)
- self.vbox.AddStretchSpacer()
-
- if self.tb[osmocom_siggen.BWIDTH_RANGE_KEY].start() < self.tb[osmocom_siggen.BWIDTH_RANGE_KEY].stop():
- bwidth_hbox.AddSpacer(3)
- forms.text_box(
- parent=self.panel, sizer=bwidth_hbox,
- proportion=1,
- converter=forms.float_converter(),
- ps=self.tb,
- key=osmocom_siggen.BWIDTH_KEY,
- label="Bandwidth (Hz)",
- )
- bwidth_hbox.AddSpacer(5)
- forms.slider(
- parent=self.panel, sizer=bwidth_hbox,
- proportion=2,
- ps=self.tb,
- key=osmocom_siggen.BWIDTH_KEY,
- minimum=self.tb[osmocom_siggen.BWIDTH_RANGE_KEY].start(),
- maximum=self.tb[osmocom_siggen.BWIDTH_RANGE_KEY].stop(),
- step_size=self.tb[osmocom_siggen.BWIDTH_RANGE_KEY].step(),
- )
- bwidth_hbox.AddSpacer(3)
-
- ##################################################
- # 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(5)
- self.vbox.AddStretchSpacer()
- sam_hbox.AddStretchSpacer(20)
- forms.static_text(
- parent=self.panel, sizer=sam_hbox,
- label='Sample Rate (sps)',
- ps=self.tb,
- key=osmocom_siggen.SAMP_RATE_KEY,
- converter=forms.float_converter(),
- )
- sam_hbox.AddStretchSpacer(20)
-
-def main():
- try:
- # Get command line parameters
- (options, args) = osmocom_siggen.get_options()
-
- # Create the top block using these
- tb = osmocom_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="OSMOCOM 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 radio 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()
diff --git a/apps/osmocom_siggen_nogui b/apps/osmocom_siggen_nogui
new file mode 100755
index 0000000..0283fcf
--- /dev/null
+++ b/apps/osmocom_siggen_nogui
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,2009,2011,2012 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.
+#
+
+from gnuradio import gr
+from osmosdr import osmocom_siggen_base as osmocom_siggen
+import sys
+
+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) = osmocom_siggen.get_options()
+ tb = osmocom_siggen.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()