diff options
author | Tom Rondeau | 2011-10-04 14:12:05 -0400 |
---|---|---|
committer | Tom Rondeau | 2011-10-04 14:12:05 -0400 |
commit | f3f2885ac08704910592b9091b6817aa71599003 (patch) | |
tree | 7ddeedce193c53506ec778709ef70942f5c68888 /gr-shd | |
parent | cb23b7a23ca8a1b1331e3d70e97425b1d52b2222 (diff) | |
parent | f2a11d98f65f245410190ee2f7cabff12e58a696 (diff) | |
download | gnuradio-f3f2885ac08704910592b9091b6817aa71599003.tar.gz gnuradio-f3f2885ac08704910592b9091b6817aa71599003.tar.bz2 gnuradio-f3f2885ac08704910592b9091b6817aa71599003.zip |
Merge branch 'shd'
Diffstat (limited to 'gr-shd')
32 files changed, 2826 insertions, 0 deletions
diff --git a/gr-shd/.gitignore b/gr-shd/.gitignore new file mode 100644 index 000000000..a37fc0c1a --- /dev/null +++ b/gr-shd/.gitignore @@ -0,0 +1,3 @@ +/Makefile +/Makefile.in +/*.pc diff --git a/gr-shd/Makefile.am b/gr-shd/Makefile.am new file mode 100644 index 000000000..2331831e0 --- /dev/null +++ b/gr-shd/Makefile.am @@ -0,0 +1,31 @@ +# +# Copyright 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. +# + +include $(top_srcdir)/Makefile.common + +SUBDIRS = include lib apps + +if PYTHON +SUBDIRS += swig grc +endif + +pkgconfigdir = $(libdir)/pkgconfig +dist_pkgconfig_DATA = gnuradio-shd.pc diff --git a/gr-shd/apps/.gitignore b/gr-shd/apps/.gitignore new file mode 100644 index 000000000..22a4e7292 --- /dev/null +++ b/gr-shd/apps/.gitignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in + diff --git a/gr-shd/apps/Makefile.am b/gr-shd/apps/Makefile.am new file mode 100644 index 000000000..16837f575 --- /dev/null +++ b/gr-shd/apps/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 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. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST += \ + $(bin_SCRIPTS) + +ourpythondir = $(grpythondir) + +bin_SCRIPTS = \ + shd_fft.py \ + shd_rx_cfile.py + diff --git a/gr-shd/apps/shd_fft.py b/gr-shd/apps/shd_fft.py new file mode 100755 index 000000000..81e84d383 --- /dev/null +++ b/gr-shd/apps/shd_fft.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +from gnuradio import gr, gru +from gnuradio import shd +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2 +from gnuradio.wxgui import scopesink2, form, slider +from optparse import OptionParser +import wx +import sys +import numpy + +class app_top_block(stdgui2.std_top_block): + def __init__(self, frame, panel, vbox, argv): + stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="type=xmini", + help="Address of SHD 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("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + 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, + help="Enable oscilloscope display") + parser.add_option("", "--avg-alpha", type="eng_float", default=1e-1, + help="Set fftsink averaging factor, default=[%default]") + parser.add_option("", "--ref-scale", type="eng_float", default=1.0, + help="Set dBFS=0dB input value, default=[%default]") + parser.add_option("--fft-size", type="int", default=1024, + help="Set number of FFT bins [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.src = shd.smini_source(device_addr=options.address, + io_type=shd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self.src.set_samp_rate(options.samp_rate) + input_rate = self.src.get_samp_rate() + + if options.waterfall: + self.scope = \ + waterfallsink2.waterfall_sink_c (panel, fft_size=1024, + sample_rate=input_rate) + self.frame.SetMinSize((800, 420)) + elif options.oscilloscope: + self.scope = scopesink2.scope_sink_c(panel, sample_rate=input_rate) + self.frame.SetMinSize((800, 600)) + else: + self.scope = fftsink2.fft_sink_c (panel, + fft_size=options.fft_size, + sample_rate=input_rate, + ref_scale=options.ref_scale, + ref_level=20.0, + y_divs = 12, + avg_alpha=options.avg_alpha) + self.frame.SetMinSize((800, 420)) + + self.connect(self.src, self.scope) + + 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(options.antenna): + self.src.set_antenna(options.antenna, 0) + + if self.show_debug_info: + self.myform['samprate'].set_value(self.src.get_samp_rate()) + self.myform['fs@gbe'].set_value(input_rate) + self.myform['baseband'].set_value(0) + self.myform['ddc'].set_value(0) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + print "Center Freq: ", self.src.get_center_freq() + print "Freq Range: ", self.src.get_freq_range() + print "Gain: ", self.src.get_gain() + print "Gain Names: ", self.src.get_gain_names() + print "Gain Range: ", self.src.get_gain_range() + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + def _build_gui(self, vbox): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + vbox.Add(self.scope.win, 10, wx.EXPAND) + + # add control area at the bottom + self.myform = myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,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((5,0), 0, 0) + g = self.src.get_gain_range() + + # some configurations don't have gain control + if g.stop() > g.start(): + myform['gain'] = form.slider_field(parent=self.panel, + sizer=hbox, label="Gain", + weight=3, + min=int(g.start()), + max=int(g.stop()), + callback=self.set_gain) + + hbox.Add((5,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_samp_rate(kv): + return self.set_samp_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((5,0), 0) + myform['samprate'] = form.float_field( + parent=panel, sizer=hbox, label="Sample Rate", + callback=myform.check_input_and_call(_form_set_samp_rate, + self._set_status_msg)) + + hbox.Add((5,0), 1) + myform['fs@gbe'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@GbE") + + hbox.Add((5,0), 1) + myform['baseband'] = form.static_float_field( + parent=panel, sizer=hbox, label="Analog BB") + + hbox.Add((5,0), 1) + myform['ddc'] = form.static_float_field( + parent=panel, sizer=hbox, label="DDC") + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + r = self.src.set_center_freq(target_freq, 0) + + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r.actual_rf_freq) + self.myform['ddc'].set_value(r.actual_dsp_freq) + if not self.options.oscilloscope: + self.scope.set_baseband_freq(target_freq) + return True + + return False + + 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) + + def set_samp_rate(self, samp_rate): + ok = self.src.set_samp_rate(samp_rate) + input_rate = self.src.get_samp_rate() + self.scope.set_sample_rate(input_rate) + if self.show_debug_info: # update displayed values + self.myform['samprate'].set_value(self.src.get_samp_rate()) + self.myform['fs@gbe'].set_value(input_rate) + + # shd set_samp_rate never fails; always falls back to closest requested. + return True + + def _setup_events(self): + if not self.options.waterfall and not self.options.oscilloscope: + self.scope.win.Bind(wx.EVT_LEFT_DCLICK, self.evt_left_dclick) + + def evt_left_dclick(self, event): + (ux, uy) = self.scope.win.GetXY(event) + if event.CmdDown(): + # Re-center on maximum power + points = self.scope.win._points + if self.scope.win.peak_hold: + if self.scope.win.peak_vals is not None: + ind = numpy.argmax(self.scope.win.peak_vals) + else: + ind = int(points.shape()[0]/2) + else: + ind = numpy.argmax(points[:,1]) + (freq, pwr) = points[ind] + target_freq = freq/self.scope.win._scale_factor + print ind, freq, pwr + self.set_freq(target_freq) + else: + # Re-center on clicked frequency + target_freq = ux/self.scope.win._scale_factor + self.set_freq(target_freq) + + +def main (): + app = stdgui2.stdapp(app_top_block, "SHD FFT", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gr-shd/apps/shd_rx_cfile.py b/gr-shd/apps/shd_rx_cfile.py new file mode 100755 index 000000000..007bc809f --- /dev/null +++ b/gr-shd/apps/shd_rx_cfile.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +""" +Read samples from a SHD device and write to file formatted as binary +outputs single precision complex float values or complex short values +(interleaved 16 bit signed short integers). +""" + +from gnuradio import gr, eng_notation +from gnuradio import shd +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +n2s = eng_notation.num_to_str + +class rx_cfile_block(gr.top_block): + + def __init__(self, options, filename): + gr.top_block.__init__(self) + + # Create a SHD device source + if options.output_shorts: + self._src = shd.smini_source(device_addr=options.address, + io_type=shd.io_type.COMPLEX_INT16, + num_channels=1) + self._sink = gr.file_sink(gr.sizeof_short*2, filename) + else: + self._src = shd.smini_source(device_addr=options.address, + io_type=shd.io_type.COMPLEX_FLOAT32, + num_channels=1) + self._sink = gr.file_sink(gr.sizeof_gr_complex, filename) + + # Set receiver sample rate + self._src.set_samp_rate(options.samp_rate) + + # Set receive daughterboard gain + if options.gain is None: + g = self._src.get_gain_range() + options.gain = float(g.start()+g.stop())/2 + print "Using mid-point gain of", \ + options.gain, "(", g.start(), "-", g.stop(), ")" + self._src.set_gain(options.gain) + + # Set the antenna + if(options.antenna): + self._src.set_antenna(options.antenna, 0) + + # Set frequency (tune request takes lo_offset) + if(options.lo_offset is not None): + treq = shd.tune_request(options.freq, options.lo_offset) + else: + treq = shd.tune_request(options.freq) + tr = self._src.set_center_freq(treq) + if tr == None: + sys.stderr.write('Failed to set center frequency\n') + raise SystemExit, 1 + + # Create head block if needed and wire it up + if options.nsamples is None: + self.connect(self._src, self._sink) + else: + if options.output_shorts: + self._head = gr.head(gr.sizeof_short*2, + int(options.nsamples)) + else: + self._head = gr.head(gr.sizeof_gr_complex, + int(options.nsamples)) + + self.connect(self._src, self._head, self._sink) + + input_rate = self._src.get_samp_rate() + + if options.verbose: + print "Address:", options.address + print "Rx gain:", options.gain + print "Rx baseband frequency:", n2s(tr.actual_rf_freq) + print "Rx DDC frequency:", n2s(tr.actual_dsp_freq) + print "Rx Sample Rate:", n2s(input_rate) + if options.nsamples is None: + print "Receiving samples until Ctrl-C" + else: + print "Receving", n2s(options.nsamples), "samples" + if options.output_shorts: + print "Writing 16-bit complex shorts" + else: + print "Writing 32-bit complex floats" + print "Output filename:", filename + +def get_options(): + usage="%prog: [options] output_filename" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-a", "--address", type="string", default="type=xmini", + help="Address of SHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("", "--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") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + 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]") + parser.add_option("-v", "--verbose", action="store_true", default=False, + help="verbose output") + parser.add_option("", "--lo-offset", type="eng_float", default=None, + help="set daughterboard LO offset to OFFSET [default=hw default]") + + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + + if options.freq is None: + parser.print_help() + sys.stderr.write('You must specify the frequency with -f FREQ\n'); + raise SystemExit, 1 + + return (options, args[0]) + + +if __name__ == '__main__': + (options, filename) = get_options() + tb = rx_cfile_block(options, filename) + + try: + tb.run() + except KeyboardInterrupt: + pass diff --git a/gr-shd/apps/shd_siggen.py b/gr-shd/apps/shd_siggen.py new file mode 100755 index 000000000..112eeea15 --- /dev/null +++ b/gr-shd/apps/shd_siggen.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +""" +Read samples from a SHD device and write to file formatted as binary +outputs single precision complex float values or complex short values +(interleaved 16 bit signed short integers). +""" + +from gnuradio import gr, eng_notation +from gnuradio import shd +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +n2s = eng_notation.num_to_str + +class shd_siggen(gr.top_block): + + def __init__(self, options): + gr.top_block.__init__(self) + + self._src = gr.sig_source_c(options.samp_rate, gr.GR_SIN_WAVE, + 200, 1) + + self._snk = shd.smini_sink(device_addr=options.address, + io_type=shd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + # Set receiver sample rate + self._snk.set_samp_rate(options.samp_rate) + + # Set receive daughterboard gain + if options.gain is None: + g = self._snk.get_gain_range() + options.gain = float(g.start()+g.stop())/2 + print "Using mid-point gain of", \ + options.gain, "(", g.start(), "-", g.stop(), ")" + self._snk.set_gain(options.gain) + + # Set the antenna + if(options.antenna): + self._snk.set_antenna(options.antenna, 0) + + # Set frequency (tune request takes lo_offset) + if(options.lo_offset is not None): + treq = shd.tune_request(options.freq, options.lo_offset) + else: + treq = shd.tune_request(options.freq) + tr = self._snk.set_center_freq(treq) + if tr == None: + sys.stderr.write('Failed to set center frequency\n') + raise SystemExit, 1 + + # Create head block if needed and wire it up + self.connect(self._src, self._snk) + input_rate = self._snk.get_samp_rate() + + if options.verbose: + print "Address:", options.address + print "Rx gain:", options.gain + print "Rx baseband frequency:", n2s(tr.actual_rf_freq) + print "Rx DDC frequency:", n2s(tr.actual_dsp_freq) + print "Rx Sample Rate:", n2s(input_rate) + +def get_options(): + usage="%prog: [options]" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-a", "--address", type="string", default="type=xmini", + help="Address of SHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("", "--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") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-v", "--verbose", action="store_true", default=False, + help="verbose output") + parser.add_option("", "--lo-offset", type="eng_float", default=None, + help="set daughterboard LO offset to OFFSET [default=hw default]") + + (options, args) = parser.parse_args () + + if options.freq is None: + parser.print_help() + sys.stderr.write('You must specify the frequency with -f FREQ\n'); + raise SystemExit, 1 + + return (options) + + +if __name__ == '__main__': + options = get_options() + tb = shd_siggen(options) + + try: + tb.run() + except KeyboardInterrupt: + pass diff --git a/gr-shd/gnuradio-shd.pc.in b/gr-shd/gnuradio-shd.pc.in new file mode 100644 index 000000000..cff0dcf00 --- /dev/null +++ b/gr-shd/gnuradio-shd.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gnuradio-shd +Description: GNU Radio blocks for the Symplex Hardware Driver (SHD) +Requires: gnuradio-core +Version: @LIBVER@ +Libs: -L${libdir} -lgnuradio-shd +Cflags: -I${includedir} diff --git a/gr-shd/grc/.gitignore b/gr-shd/grc/.gitignore new file mode 100644 index 000000000..2c261c55b --- /dev/null +++ b/gr-shd/grc/.gitignore @@ -0,0 +1,3 @@ +/shd_smini*.xml +/Makefile +/Makefile.in diff --git a/gr-shd/grc/Makefile.am b/gr-shd/grc/Makefile.am new file mode 100644 index 000000000..c44ad1b4e --- /dev/null +++ b/gr-shd/grc/Makefile.am @@ -0,0 +1,43 @@ +# +# Copyright 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. +# + +include $(top_srcdir)/Makefile.common + +grcblocksdir = $(grc_blocksdir) + +generated_shd_smini_blocks = \ + shd_smini_source.xml \ + shd_smini_sink.xml + +BUILT_SOURCES += $(generated_shd_smini_blocks) + +dist_grcblocks_DATA = \ + shd_block_tree.xml \ + $(BUILT_SOURCES) + +######################################################################## +# Rules for generating the source and sink xml wrappers +######################################################################## +EXTRA_DIST += $(srcdir)/gen_shd_smini_blocks.py + +$(generated_shd_smini_blocks): $(srcdir)/gen_shd_smini_blocks.py + @echo "generating $@..." + $(PYTHON) $< $@ diff --git a/gr-shd/grc/gen_shd_smini_blocks.py b/gr-shd/grc/gen_shd_smini_blocks.py new file mode 100644 index 000000000..652b6cf51 --- /dev/null +++ b/gr-shd/grc/gen_shd_smini_blocks.py @@ -0,0 +1,297 @@ +""" +Copyright 2011 Free Software Foundation, Inc. + +This file is part of GNU Radio + +GNU Radio Companion 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 2 +of the License, or (at your option) any later version. + +GNU Radio Companion 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +MAIN_TMPL = """\ +<?xml version="1.0"?> +<block> + <name>SHD: SMINI $sourk.title()</name> + <key>shd_smini_$(sourk)</key> + <import>from gnuradio import shd</import> + <make>shd.smini_$(sourk)( + device_addr=\$dev_addr, + io_type=shd.io_type.\$type.type, + num_channels=\$nchan, +) +\#if \$clock_rate() +self.\$(id).set_clock_rate(\$clock_rate, shd.ALL_MBOARDS) +\#end if +#for $m in range($max_mboards) +######################################################################## +\#if \$num_mboards() > $m and \$ref_source$(m)() == 'external' +self.\$(id).set_clock_config(shd.clock_config.external(), $m) +\#end if +######################################################################## +\#if \$num_mboards() > $m and \$ref_source$(m)() == 'internal' +self.\$(id).set_clock_config(shd.clock_config.internal(), $m) +\#end if +######################################################################## +\#if \$num_mboards() > $m and \$ref_source$(m)() == 'mimo' +_config = shd.clock_config() +_config.ref_source = shd.clock_config.REF_MIMO +_config.pps_source = shd.clock_config.PPS_MIMO +self.\$(id).set_clock_config(_config, $m) +\#end if +######################################################################## +\#if \$num_mboards() > $m and \$sd_spec$(m)() +self.\$(id).set_subdev_spec(\$sd_spec$(m), $m) +\#end if +######################################################################## +#end for +\#if \$sync() +self.\$(id).set_time_unknown_pps(shd.time_spec()) +\#end if +self.\$(id).set_samp_rate(\$samp_rate) +#for $n in range($max_nchan) +\#if \$nchan() > $n +self.\$(id).set_center_freq(\$center_freq$(n), $n) +self.\$(id).set_gain(\$gain$(n), $n) +\#end if +#end for +</make> + <callback>set_samp_rate(\$samp_rate)</callback> + #for $n in range($max_nchan) + <callback>set_center_freq(\$center_freq$(n), $n)</callback> + <callback>set_gain(\$gain$(n), $n)</callback> + #end for + <param> + <name>$(direction.title())put Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>type:COMPLEX_FLOAT32</opt> + <opt>vlen:1</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>type:COMPLEX_INT16</opt> + <opt>vlen:2</opt> + </option> + </param> + <param> + <name>Device Addr</name> + <key>dev_addr</key> + <value></value> + <type>string</type> + <hide> + \#if \$dev_addr() + none + \#else + part + \#end if + </hide> + </param> + <param> + <name>Sync</name> + <key>sync</key> + <value></value> + <type>enum</type> + <hide>\#if \$sync() then 'none' else 'part'#</hide> + <option> + <name>unknown PPS</name> + <key>sync</key> + </option> + <option> + <name>don't sync</name> + <key></key> + </option> + </param> + <param> + <name>Clock Rate (Hz)</name> + <key>clock_rate</key> + <value>0.0</value> + <type>real</type> + <hide>\#if \$clock_rate() then 'none' else 'part'#</hide> + <option> + <name>Default</name> + <key>0.0</key> + </option> + </param> + <param> + <name>Num Mboards</name> + <key>num_mboards</key> + <value>1</value> + <type>int</type> + <hide>part</hide> + #for $m in range(1, $max_mboards+1) + <option> + <name>$(m)</name> + <key>$m</key> + </option> + #end for + </param> + #for $m in range($max_mboards) + <param> + <name>Mb$(m): Ref Source</name> + <key>ref_source$(m)</key> + <value></value> + <type>enum</type> + <hide> + \#if not \$num_mboards() > $m + all + \#elif \$ref_source$(m)() + none + \#else + part + \#end if + </hide> + <option><name>Default</name><key></key></option> + <option><name>Internal</name><key>internal</key></option> + <option><name>External</name><key>external</key></option> + <option><name>MIMO Cable</name><key>mimo</key></option> + </param> + <param> + <name>Mb$(m): Subdev Spec</name> + <key>sd_spec$(m)</key> + <value></value> + <type>string</type> + <hide> + \#if not \$num_mboards() > $m + all + \#elif \$sd_spec$(m)() + none + \#else + part + \#end if + </hide> + </param> + #end for + <param> + <name>Num Channels</name> + <key>nchan</key> + <value>1</value> + <type>int</type> + #for $n in range(1, $max_nchan+1) + <option> + <name>$(n)</name> + <key>$n</key> + </option> + #end for + </param> + <param> + <name>Samp Rate (Sps)</name> + <key>samp_rate</key> + <value>samp_rate</value> + <type>real</type> + </param> + $params + <check>$max_nchan >= \$nchan</check> + <check>\$nchan > 0</check> + <check>$max_mboards >= \$num_mboards</check> + <check>\$num_mboards > 0</check> + <check>\$nchan >= \$num_mboards</check> + <$sourk> + <name>$direction</name> + <type>\$type</type> + <vlen>\$type.vlen</vlen> + <nports>\$nchan</nports> + </$sourk> + <doc> +The SHD SMINI $sourk.title() Block: + +Device Address: +The device address is a delimited string used to locate SHD devices on your system. \\ +If left blank, the first SHD device found will be used. \\ +Use the device address to specify a specific device or list of devices. +SMINI1 Example: serial=12345678 +SMINI2 Example: type=xmini + +Num Motherboards: +Selects the number of SMINI motherboards in this device configuration. + +Reference Source: +Where the motherboard should sync its time and clock references. +If source and sink blocks reference the same device, +it is only necessary to set the reference source on one of the blocks. + +Subdevice specification: +Each motherboard should have its own subdevice specification \\ +and all subdevice specifications should be the same length. \\ +Select the subdevice or subdevices for each channel using a markup string. \\ +The markup string consists of a list of dboard_slot:subdev_name pairs (one pair per channel). \\ +If left blank, the SHD will try to select the first subdevice on your system. \\ +See the application notes for further details. +Single channel example: :AB +Dual channel example: :A :B + +Num Channels: +Selects the total number of channels in this multi-SMINI configuration. +Ex: 4 motherboards with 2 channels per board = 8 channels total + +Sample rate: +The sample rate is the number of samples per second input by this block. \\ +The SHD device driver will try its best to match the requested sample rate. \\ +If the requested rate is not possible, the SHD block will print an error at runtime. + +Center frequency: +The center frequency is the overall frequency of the RF chain. \\ +For greater control of how the SHD tunes elements in the RF chain, \\ +pass a tune_request object rather than a simple target frequency. +Tuning with an LO offset example: shd.tune_request(freq, lo_off) + + </doc> +</block> +""" + +PARAMS_TMPL = """ + <param> + <name>Ch$(n): Center Freq (Hz)</name> + <key>center_freq$(n)</key> + <value>0</value> + <type>real</type> + <hide>\#if \$nchan() > $n then 'none' else 'all'#</hide> + </param> + <param> + <name>Ch$(n): Gain (dB)</name> + <key>gain$(n)</key> + <value>0</value> + <type>real</type> + <hide>\#if \$nchan() > $n then 'none' else 'all'#</hide> + </param> +""" + +def parse_tmpl(_tmpl, **kwargs): + from Cheetah import Template + return str(Template.Template(_tmpl, kwargs)) + +max_num_mboards = 8 +max_num_channels = max_num_mboards*4 + +if __name__ == '__main__': + import sys + for file in sys.argv[1:]: + if 'source' in file: + sourk = 'source' + direction = 'out' + elif 'sink' in file: + sourk = 'sink' + direction = 'in' + else: raise Exception, 'is %s a source or sink?'%file + + params = ''.join([parse_tmpl(PARAMS_TMPL, n=n) for n in range(max_num_channels)]) + open(file, 'w').write(parse_tmpl(MAIN_TMPL, + max_nchan=max_num_channels, + max_mboards=max_num_mboards, + params=params, + sourk=sourk, + direction=direction, + )) diff --git a/gr-shd/grc/shd_block_tree.xml b/gr-shd/grc/shd_block_tree.xml new file mode 100644 index 000000000..5d9786f67 --- /dev/null +++ b/gr-shd/grc/shd_block_tree.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Block Tree for shd blocks. +################################################### + --> +<cat> + <name></name> <!-- Blank for Root Name --> + <cat> + <name>SHD</name> + <block>shd_smini_source</block> + <block>shd_smini_sink</block> + </cat> +</cat> diff --git a/gr-shd/include/.gitignore b/gr-shd/include/.gitignore new file mode 100644 index 000000000..b336cc7ce --- /dev/null +++ b/gr-shd/include/.gitignore @@ -0,0 +1,2 @@ +/Makefile +/Makefile.in diff --git a/gr-shd/include/Makefile.am b/gr-shd/include/Makefile.am new file mode 100644 index 000000000..2cb1597df --- /dev/null +++ b/gr-shd/include/Makefile.am @@ -0,0 +1,27 @@ +# +# Copyright 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. +# + +include $(top_srcdir)/Makefile.common + +grinclude_HEADERS = \ + gr_shd_api.h \ + gr_shd_smini_source.h \ + gr_shd_smini_sink.h
\ No newline at end of file diff --git a/gr-shd/include/gr_shd_api.h b/gr-shd/include/gr_shd_api.h new file mode 100644 index 000000000..e6773c3f3 --- /dev/null +++ b/gr-shd/include/gr_shd_api.h @@ -0,0 +1,33 @@ +/* + * Copyright 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. + */ + +#ifndef INCLUDED_GR_SHD_API_H +#define INCLUDED_GR_SHD_API_H + +#include <shd/config.hpp> + +#ifdef gnuradio_shd_EXPORTS +# define GR_SHD_API SHD_EXPORT +#else +# define GR_SHD_API SHD_IMPORT +#endif + +#endif /* INCLUDED_GR_SHD_API_H */ diff --git a/gr-shd/include/gr_shd_smini_sink.h b/gr-shd/include/gr_shd_smini_sink.h new file mode 100644 index 000000000..938958687 --- /dev/null +++ b/gr-shd/include/gr_shd_smini_sink.h @@ -0,0 +1,282 @@ +/* + * Copyright 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. + */ + +#ifndef INCLUDED_GR_SHD_SMINI_SINK_H +#define INCLUDED_GR_SHD_SMINI_SINK_H + +#include <gr_shd_api.h> +#include <gr_sync_block.h> +#include <shd/xmini/multi_xmini.hpp> + +class shd_smini_sink; + +GR_SHD_API boost::shared_ptr<shd_smini_sink> shd_make_smini_sink( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels +); + +class GR_SHD_API shd_smini_sink : virtual public gr_sync_block +{ + public: + + /*! + * Set the subdevice specification. + * \param spec the subdev spec markup string + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) = 0; + + /*! + * Set the sample rate for the smini device. + * \param rate a new rate in Sps + */ + virtual void set_samp_rate(double rate) = 0; + + /*! + * Get the sample rate for the smini device. + * This is the actual sample rate and may differ from the rate set. + * \return the actual rate in Sps + */ + virtual double get_samp_rate(void) = 0; + + /*! + * Tune the smini device to the desired center frequency. + * \param tune_request the tune request instructions + * \param chan the channel index 0 to N-1 + * \return a tune result with the actual frequencies + */ + virtual shd::tune_result_t set_center_freq( + const shd::tune_request_t tune_request, size_t chan = 0 + ) = 0; + + /*! + * Tune the smini device to the desired center frequency. + * This is a wrapper around set center freq so that in this case, + * the user can pass a single frequency in the call through swig. + * \param freq the desired frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result with the actual frequencies + */ + shd::tune_result_t set_center_freq(double freq, size_t chan = 0){ + return set_center_freq(shd::tune_request_t(freq), chan); + } + + /*! + * Get the center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ + virtual double get_center_freq(size_t chan = 0) = 0; + + /*! + * Get the tunable frequency range. + * \param chan the channel index 0 to N-1 + * \return the frequency range in Hz + */ + virtual shd::freq_range_t get_freq_range(size_t chan = 0) = 0; + + /*! + * Set the gain for the dboard. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ + virtual void set_gain(double gain, size_t chan = 0) = 0; + + /*! + * Set the named gain on the dboard. + * \param gain the gain in dB + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + */ + virtual void set_gain(double gain, const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting. + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double get_gain(size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting of named stage. + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double get_gain(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting of named stage. + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0; + + /*! + * Get the settable gain range. + * \param chan the channel index 0 to N-1 + * \return the gain range in dB + */ + virtual shd::gain_range_t get_gain_range(size_t chan = 0) = 0; + + /*! + * Get the settable gain range. + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + * \return the gain range in dB + */ + virtual shd::gain_range_t get_gain_range(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Set the antenna to use. + * \param ant the antenna string + * \param chan the channel index 0 to N-1 + */ + virtual void set_antenna(const std::string &ant, + size_t chan = 0) = 0; + + /*! + * Get the antenna in use. + * \param chan the channel index 0 to N-1 + * \return the antenna string + */ + virtual std::string get_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible antennas. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna strings + */ + virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0; + + /*! + * Set the subdevice bandpass filter. + * \param chan the channel index 0 to N-1 + * \param bandwidth the filter bandwidth in Hz + */ + virtual void set_bandwidth(double bandwidth, size_t chan = 0) = 0; + + /*! + * Get a daughterboard sensor value. + * \param name the name of the sensor + * \param chan the channel index 0 to N-1 + * \return a sensor value object + */ + virtual shd::sensor_value_t get_dboard_sensor(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get a list of possible daughterboard sensor names. + * \param chan the channel index 0 to N-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_dboard_sensor_names(size_t chan = 0) = 0; + + /*! + * Get a motherboard sensor value. + * \param name the name of the sensor + * \param mboard the motherboard index 0 to M-1 + * \return a sensor value object + */ + virtual shd::sensor_value_t get_mboard_sensor(const std::string &name, + size_t mboard = 0) = 0; + + /*! + * Get a list of possible motherboard sensor names. + * \param mboard the motherboard index 0 to M-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0; + + /*! + * Set the clock configuration. + * \param clock_config the new configuration + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_clock_config(const shd::clock_config_t &clock_config, + size_t mboard = 0) = 0; + + /*! + * Get the master clock rate. + * \param mboard the motherboard index 0 to M-1 + * \return the clock rate in Hz + */ + virtual double get_clock_rate(size_t mboard = 0) = 0; + + /*! + * Set the master clock rate. + * \param rate the new rate in Hz + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_clock_rate(double rate, size_t mboard = 0) = 0; + + /*! + * Get the current time registers. + * \param mboard the motherboard index 0 to M-1 + * \return the current smini time + */ + virtual shd::time_spec_t get_time_now(size_t mboard = 0) = 0; + + /*! + * Get the time when the last pps pulse occured. + * \param mboard the motherboard index 0 to M-1 + * \return the current smini time + */ + virtual shd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0; + + /*! + * Sets the time registers immediately. + * \param time_spec the new time + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_time_now(const shd::time_spec_t &time_spec, + size_t mboard = 0) = 0; + + /*! + * Set the time registers at the next pps. + * \param time_spec the new time + */ + virtual void set_time_next_pps(const shd::time_spec_t &time_spec) = 0; + + /*! + * Sync the time registers with an unknown pps edge. + * \param time_spec the new time + */ + virtual void set_time_unknown_pps(const shd::time_spec_t &time_spec) = 0; + + /*! + * Get access to the underlying shd dboard iface object. + * \return the dboard_iface object + */ + virtual shd::xmini::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0; + + /*! + * Get access to the underlying shd device object. + * \return the multi smini device object + */ + virtual shd::xmini::multi_xmini::sptr get_device(void) = 0; +}; + +#endif /* INCLUDED_GR_SHD_SMINI_SINK_H */ diff --git a/gr-shd/include/gr_shd_smini_source.h b/gr-shd/include/gr_shd_smini_source.h new file mode 100644 index 000000000..3e3dbf427 --- /dev/null +++ b/gr-shd/include/gr_shd_smini_source.h @@ -0,0 +1,286 @@ +/* + * Copyright 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. + */ + +#ifndef INCLUDED_GR_SHD_SMINI_SOURCE_H +#define INCLUDED_GR_SHD_SMINI_SOURCE_H + +#include <gr_shd_api.h> +#include <gr_sync_block.h> +#include <shd/xmini/multi_xmini.hpp> + +class shd_smini_source; + +GR_SHD_API boost::shared_ptr<shd_smini_source> shd_make_smini_source( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels +); + +class GR_SHD_API shd_smini_source : virtual public gr_sync_block +{ + public: + + /*! + * Set the subdevice specification. + * \param spec the subdev spec markup string + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_subdev_spec(const std::string &spec, + size_t mboard = 0) = 0; + + /*! + * Set the sample rate for the smini device. + * \param rate a new rate in Sps + */ + virtual void set_samp_rate(double rate) = 0; + + /*! + * Get the sample rate for the smini device. + * This is the actual sample rate and may differ from the rate set. + * \return the actual rate in Sps + */ + virtual double get_samp_rate(void) = 0; + + /*! + * Tune the smini device to the desired center frequency. + * \param tune_request the tune request instructions + * \param chan the channel index 0 to N-1 + * \return a tune result with the actual frequencies + */ + virtual shd::tune_result_t set_center_freq( + const shd::tune_request_t tune_request, + size_t chan = 0 + ) = 0; + + /*! + * Tune the smini device to the desired center frequency. + * This is a wrapper around set center freq so that in this case, + * the user can pass a single frequency in the call through swig. + * \param freq the desired frequency in Hz + * \param chan the channel index 0 to N-1 + * \return a tune result with the actual frequencies + */ + shd::tune_result_t set_center_freq(double freq, size_t chan = 0){ + return set_center_freq(shd::tune_request_t(freq), chan); + } + + /*! + * Get the center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ + virtual double get_center_freq(size_t chan = 0) = 0; + + /*! + * Get the tunable frequency range. + * \param chan the channel index 0 to N-1 + * \return the frequency range in Hz + */ + virtual shd::freq_range_t get_freq_range(size_t chan = 0) = 0; + + /*! + * Set the gain for the dboard. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + */ + virtual void set_gain(double gain, size_t chan = 0) = 0; + + /*! + * Set the named gain on the dboard. + * \param gain the gain in dB + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + */ + virtual void set_gain(double gain, const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting. + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double get_gain(size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting of named stage. + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double get_gain(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get the actual dboard gain setting of named stage. + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0; + + /*! + * Get the settable gain range. + * \param chan the channel index 0 to N-1 + * \return the gain range in dB + */ + virtual shd::gain_range_t get_gain_range(size_t chan = 0) = 0; + + /*! + * Get the settable gain range. + * \param name the name of the gain stage + * \param chan the channel index 0 to N-1 + * \return the gain range in dB + */ + virtual shd::gain_range_t get_gain_range(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Set the antenna to use. + * \param ant the antenna string + * \param chan the channel index 0 to N-1 + */ + virtual void set_antenna(const std::string &ant, + size_t chan = 0) = 0; + + /*! + * Get the antenna in use. + * \param chan the channel index 0 to N-1 + * \return the antenna string + */ + virtual std::string get_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible antennas. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna strings + */ + virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0; + + /*! + * Set the subdevice bandpass filter. + * \param bandwidth the filter bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ + virtual void set_bandwidth(double bandwidth, + size_t chan = 0) = 0; + + /*! + * Get a daughterboard sensor value. + * \param name the name of the sensor + * \param chan the channel index 0 to N-1 + * \return a sensor value object + */ + virtual shd::sensor_value_t get_dboard_sensor(const std::string &name, + size_t chan = 0) = 0; + + /*! + * Get a list of possible daughterboard sensor names. + * \param chan the channel index 0 to N-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_dboard_sensor_names(size_t chan = 0) = 0; + + /*! + * Get a motherboard sensor value. + * \param name the name of the sensor + * \param mboard the motherboard index 0 to M-1 + * \return a sensor value object + */ + virtual shd::sensor_value_t get_mboard_sensor(const std::string &name, + size_t mboard = 0) = 0; + + /*! + * Get a list of possible motherboard sensor names. + * \param mboard the motherboard index 0 to M-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0; + + /*! + * Set the clock configuration. + * \param clock_config the new configuration + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_clock_config(const shd::clock_config_t &clock_config, + size_t mboard = 0) = 0; + + /*! + * Get the master clock rate. + * \param mboard the motherboard index 0 to M-1 + * \return the clock rate in Hz + */ + virtual double get_clock_rate(size_t mboard = 0) = 0; + + /*! + * Set the master clock rate. + * \param rate the new rate in Hz + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_clock_rate(double rate, + size_t mboard = 0) = 0; + + /*! + * Get the current time registers. + * \param mboard the motherboard index 0 to M-1 + * \return the current smini time + */ + virtual shd::time_spec_t get_time_now(size_t mboard = 0) = 0; + + /*! + * Get the time when the last pps pulse occured. + * \param mboard the motherboard index 0 to M-1 + * \return the current smini time + */ + virtual shd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0; + + /*! + * Sets the time registers immediately. + * \param time_spec the new time + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_time_now(const shd::time_spec_t &time_spec, + size_t mboard = 0) = 0; + + /*! + * Set the time registers at the next pps. + * \param time_spec the new time + */ + virtual void set_time_next_pps(const shd::time_spec_t &time_spec) = 0; + + /*! + * Sync the time registers with an unknown pps edge. + * \param time_spec the new time + */ + virtual void set_time_unknown_pps(const shd::time_spec_t &time_spec) = 0; + + /*! + * Get access to the underlying shd dboard iface object. + * \return the dboard_iface object + */ + virtual shd::xmini::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0; + + /*! + * Get access to the underlying shd device object. + * \return the multi smini device object + */ + virtual shd::xmini::multi_xmini::sptr get_device(void) = 0; +}; + +#endif /* INCLUDED_GR_SHD_SMINI_SOURCE_H */ diff --git a/gr-shd/lib/.gitignore b/gr-shd/lib/.gitignore new file mode 100644 index 000000000..b336cc7ce --- /dev/null +++ b/gr-shd/lib/.gitignore @@ -0,0 +1,2 @@ +/Makefile +/Makefile.in diff --git a/gr-shd/lib/Makefile.am b/gr-shd/lib/Makefile.am new file mode 100644 index 000000000..7a887aebf --- /dev/null +++ b/gr-shd/lib/Makefile.am @@ -0,0 +1,42 @@ +# +# Copyright 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. +# + +include $(top_srcdir)/Makefile.common + +AM_CPPFLAGS = \ + $(STD_DEFINES_AND_INCLUDES) \ + $(WITH_INCLUDES) \ + $(SHD_CPPFLAGS) \ + -Dgnuradio_shd_EXPORTS + +lib_LTLIBRARIES = libgnuradio-shd.la + +libgnuradio_shd_la_SOURCES = \ + gr_shd_smini_source.cc \ + gr_shd_smini_sink.cc + +libgnuradio_shd_la_LIBADD = \ + $(GNURADIO_CORE_LA) \ + $(SHD_LIBS) + +libgnuradio_shd_la_LDFLAGS = $(NO_UNDEFINED) $(LTVERSIONFLAGS) + +noinst_HEADERS = diff --git a/gr-shd/lib/gr_shd_smini_sink.cc b/gr-shd/lib/gr_shd_smini_sink.cc new file mode 100644 index 000000000..c9fb222d0 --- /dev/null +++ b/gr-shd/lib/gr_shd_smini_sink.cc @@ -0,0 +1,276 @@ +/* + * Copyright 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. + */ + +#include <gr_shd_smini_sink.h> +#include <gr_io_signature.h> +#include <stdexcept> + +/********************************************************************* + * SHD Multi SMINI Sink Impl + ********************************************************************/ +class shd_smini_sink_impl : public shd_smini_sink +{ +public: + shd_smini_sink_impl(const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels): + gr_sync_block("gr shd smini sink", + gr_make_io_signature(num_channels, num_channels, io_type.size), + gr_make_io_signature(0, 0, 0)), + _type(io_type), + _nchan(num_channels), + _has_time_spec(_nchan > 1) + { + _dev = shd::xmini::multi_xmini::make(device_addr); + } + + void set_subdev_spec(const std::string &spec, + size_t mboard) + { + return _dev->set_tx_subdev_spec(spec, mboard); + } + + void set_samp_rate(double rate){ + _dev->set_tx_rate(rate); + _sample_rate = this->get_samp_rate(); + } + + double get_samp_rate(void){ + return _dev->get_tx_rate(); + } + + shd::tune_result_t set_center_freq( + const shd::tune_request_t tune_request, size_t chan) + { + return _dev->set_tx_freq(tune_request, chan); + } + + double get_center_freq(size_t chan) + { + return _dev->get_tx_freq(chan); + } + + shd::freq_range_t get_freq_range(size_t chan) + { + return _dev->get_tx_freq_range(chan); + } + + void set_gain(double gain, size_t chan) + { + return _dev->set_tx_gain(gain, chan); + } + + void set_gain(double gain, const std::string &name, + size_t chan) + { + return _dev->set_tx_gain(gain, name, chan); + } + + double get_gain(size_t chan){ + return _dev->get_tx_gain(chan); + } + + double get_gain(const std::string &name, size_t chan) + { + return _dev->get_tx_gain(name, chan); + } + + std::vector<std::string> get_gain_names(size_t chan) + { + return _dev->get_tx_gain_names(chan); + } + + shd::gain_range_t get_gain_range(size_t chan) + { + return _dev->get_tx_gain_range(chan); + } + + shd::gain_range_t get_gain_range(const std::string &name, + size_t chan) + { + return _dev->get_tx_gain_range(name, chan); + } + + void set_antenna(const std::string &ant, size_t chan) + { + return _dev->set_tx_antenna(ant, chan); + } + + std::string get_antenna(size_t chan) + { + return _dev->get_tx_antenna(chan); + } + + std::vector<std::string> get_antennas(size_t chan) + { + return _dev->get_tx_antennas(chan); + } + + void set_bandwidth(double bandwidth, size_t chan) + { + return _dev->set_tx_bandwidth(bandwidth, chan); + } + + shd::sensor_value_t get_dboard_sensor(const std::string &name, + size_t chan) + { + return _dev->get_tx_sensor(name, chan); + } + + std::vector<std::string> get_dboard_sensor_names(size_t chan) + { + return _dev->get_tx_sensor_names(chan); + } + + shd::sensor_value_t get_mboard_sensor(const std::string &name, + size_t mboard) + { + return _dev->get_mboard_sensor(name, mboard); + } + + std::vector<std::string> get_mboard_sensor_names(size_t mboard) + { + return _dev->get_mboard_sensor_names(mboard); + } + + void set_clock_config(const shd::clock_config_t &clock_config, + size_t mboard) + { + return _dev->set_clock_config(clock_config, mboard); + } + + double get_clock_rate(size_t mboard) + { + return _dev->get_master_clock_rate(mboard); + } + + void set_clock_rate(double rate, size_t mboard) + { + return _dev->set_master_clock_rate(rate, mboard); + } + + shd::time_spec_t get_time_now(size_t mboard = 0) + { + return _dev->get_time_now(mboard); + } + + shd::time_spec_t get_time_last_pps(size_t mboard) + { + return _dev->get_time_last_pps(mboard); + } + + void set_time_now(const shd::time_spec_t &time_spec, + size_t mboard) + { + return _dev->set_time_now(time_spec, mboard); + } + + void set_time_next_pps(const shd::time_spec_t &time_spec) + { + return _dev->set_time_next_pps(time_spec); + } + + void set_time_unknown_pps(const shd::time_spec_t &time_spec) + { + return _dev->set_time_unknown_pps(time_spec); + } + + shd::xmini::dboard_iface::sptr get_dboard_iface(size_t chan) + { + return _dev->get_tx_dboard_iface(chan); + } + + shd::xmini::multi_xmini::sptr get_device(void) + { + return _dev; + } + + /******************************************************************* + * Work + ******************************************************************/ + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + //send a mid-burst packet with time spec + _metadata.start_of_burst = false; + _metadata.end_of_burst = false; + _metadata.has_time_spec = _has_time_spec; + + size_t num_sent = _dev->get_device()->send( + input_items, noutput_items, _metadata, + _type, shd::device::SEND_MODE_FULL_BUFF, 1.0); + + //increment the timespec by the number of samples sent + _metadata.time_spec += shd::time_spec_t(0, num_sent, _sample_rate); + return num_sent; + } + + //Send an empty start-of-burst packet to begin streaming. + //Set at a time in the near future to avoid late packets. + bool start(void) + { + _metadata.start_of_burst = true; + _metadata.end_of_burst = false; + _metadata.has_time_spec = _has_time_spec; + _metadata.time_spec = get_time_now() + shd::time_spec_t(0.01); + + _dev->get_device()->send( + gr_vector_const_void_star(_nchan), 0, _metadata, + _type, shd::device::SEND_MODE_ONE_PACKET, 1.0); + return true; + } + + //Send an empty end-of-burst packet to end streaming. + //Ending the burst avoids an underflow error on stop. + bool stop(void) + { + _metadata.start_of_burst = false; + _metadata.end_of_burst = true; + _metadata.has_time_spec = false; + + _dev->get_device()->send( + gr_vector_const_void_star(_nchan), 0, _metadata, + _type, shd::device::SEND_MODE_ONE_PACKET, 1.0); + return true; + } + +protected: + shd::xmini::multi_xmini::sptr _dev; + const shd::io_type_t _type; + size_t _nchan; + bool _has_time_spec; + shd::tx_metadata_t _metadata; + double _sample_rate; +}; + +/********************************************************************* + * Make SHD Multi SMINI Sink + ********************************************************************/ + +boost::shared_ptr<shd_smini_sink> shd_make_smini_sink( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels) +{ + return boost::shared_ptr<shd_smini_sink>( + new shd_smini_sink_impl(device_addr, io_type, num_channels)); +} diff --git a/gr-shd/lib/gr_shd_smini_source.cc b/gr-shd/lib/gr_shd_smini_source.cc new file mode 100644 index 000000000..caf98f311 --- /dev/null +++ b/gr-shd/lib/gr_shd_smini_source.cc @@ -0,0 +1,299 @@ +/* + * Copyright 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. + */ + +#include <gr_shd_smini_source.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> +#include <boost/format.hpp> + +/********************************************************************* + * SHD Multi S-MINI Source Impl + ********************************************************************/ +class shd_smini_source_impl : public shd_smini_source +{ +public: + shd_smini_source_impl( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels + ): + gr_sync_block( + "gr shd smini source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(num_channels, num_channels, io_type.size) + ), + _type(io_type), + _nchan(num_channels), + _stream_now(_nchan == 1), + _tmp_buffs(_nchan) + { + _dev = shd::xmini::multi_xmini::make(device_addr); + } + + void set_subdev_spec(const std::string &spec, size_t mboard) + { + return _dev->set_rx_subdev_spec(spec, mboard); + } + + void set_samp_rate(double rate) + { + _dev->set_rx_rate(rate); + } + + double get_samp_rate(void) + { + return _dev->get_rx_rate(); + } + + shd::tune_result_t set_center_freq( + const shd::tune_request_t tune_request, size_t chan) + { + return _dev->set_rx_freq(tune_request, chan); + } + + double get_center_freq(size_t chan) + { + return _dev->get_rx_freq(chan); + } + + shd::freq_range_t get_freq_range(size_t chan) + { + return _dev->get_rx_freq_range(chan); + } + + void set_gain(double gain, size_t chan) + { + return _dev->set_rx_gain(gain, chan); + } + + void set_gain(double gain, const std::string &name, + size_t chan) + { + return _dev->set_rx_gain(gain, name, chan); + } + + double get_gain(size_t chan) + { + return _dev->get_rx_gain(chan); + } + + double get_gain(const std::string &name, size_t chan) + { + return _dev->get_rx_gain(name, chan); + } + + std::vector<std::string> get_gain_names(size_t chan) + { + return _dev->get_rx_gain_names(chan); + } + + shd::gain_range_t get_gain_range(size_t chan) + { + return _dev->get_rx_gain_range(chan); + } + + shd::gain_range_t get_gain_range(const std::string &name, + size_t chan) + { + return _dev->get_rx_gain_range(name, chan); + } + + void set_antenna(const std::string &ant, size_t chan) + { + return _dev->set_rx_antenna(ant, chan); + } + + std::string get_antenna(size_t chan) + { + return _dev->get_rx_antenna(chan); + } + + std::vector<std::string> get_antennas(size_t chan) + { + return _dev->get_rx_antennas(chan); + } + + void set_bandwidth(double bandwidth, size_t chan) + { + return _dev->set_rx_bandwidth(bandwidth, chan); + } + + shd::sensor_value_t get_dboard_sensor(const std::string &name, + size_t chan) + { + return _dev->get_rx_sensor(name, chan); + } + + std::vector<std::string> get_dboard_sensor_names(size_t chan) + { + return _dev->get_rx_sensor_names(chan); + } + + shd::sensor_value_t get_mboard_sensor(const std::string &name, + size_t mboard) + { + return _dev->get_mboard_sensor(name, mboard); + } + + std::vector<std::string> get_mboard_sensor_names(size_t mboard) + { + return _dev->get_mboard_sensor_names(mboard); + } + + void set_clock_config(const shd::clock_config_t &clock_config, + size_t mboard) + { + return _dev->set_clock_config(clock_config, mboard); + } + + double get_clock_rate(size_t mboard) + { + return _dev->get_master_clock_rate(mboard); + } + + void set_clock_rate(double rate, size_t mboard) + { + return _dev->set_master_clock_rate(rate, mboard); + } + + shd::time_spec_t get_time_now(size_t mboard = 0) + { + return _dev->get_time_now(mboard); + } + + shd::time_spec_t get_time_last_pps(size_t mboard) + { + return _dev->get_time_last_pps(mboard); + } + + void set_time_now(const shd::time_spec_t &time_spec, + size_t mboard) + { + return _dev->set_time_now(time_spec, mboard); + } + + void set_time_next_pps(const shd::time_spec_t &time_spec) + { + return _dev->set_time_next_pps(time_spec); + } + + void set_time_unknown_pps(const shd::time_spec_t &time_spec) + { + return _dev->set_time_unknown_pps(time_spec); + } + + shd::xmini::dboard_iface::sptr get_dboard_iface(size_t chan) + { + return _dev->get_rx_dboard_iface(chan); + } + + shd::xmini::multi_xmini::sptr get_device(void) + { + return _dev; + } + + /******************************************************************* + * Work + ******************************************************************/ + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + //In order to allow for low-latency: + //We receive all available packets without timeout. + //This call can timeout under regular operation... + size_t num_samps = _dev->get_device()->recv( + output_items, noutput_items, _metadata, + _type, shd::device::RECV_MODE_FULL_BUFF, 0.0); + + //If receive resulted in a timeout condition: + //We now receive a single packet with a large timeout. + if(_metadata.error_code == shd::rx_metadata_t::ERROR_CODE_TIMEOUT) { + num_samps = _dev->get_device()->recv( + output_items, noutput_items, _metadata, + _type, shd::device::RECV_MODE_ONE_PACKET, 1.0); + } + + //handle possible errors conditions + switch(_metadata.error_code) { + case shd::rx_metadata_t::ERROR_CODE_NONE: + //TODO insert tag for time stamp + break; + + case shd::rx_metadata_t::ERROR_CODE_TIMEOUT: + //Assume that the user called stop() on the flow graph. + //However, a timeout can occur under error conditions. + return WORK_DONE; + + case shd::rx_metadata_t::ERROR_CODE_OVERFLOW: + //ignore overflows and try work again + //TODO insert tag for overflow + return work(noutput_items, input_items, output_items); + + default: + std::cout << boost::format("SHD source block got error code 0x%x" + ) % _metadata.error_code << std::endl; + return num_samps; + } + + return num_samps; + } + + bool start(void) + { + //setup a stream command that starts streaming slightly in the future + static const double reasonable_delay = 0.1; //order of magnitude over RTT + shd::stream_cmd_t stream_cmd(shd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + stream_cmd.stream_now = _stream_now; + stream_cmd.time_spec = get_time_now() + shd::time_spec_t(reasonable_delay); + _dev->issue_stream_cmd(stream_cmd); + return true; + } + + bool stop(void) + { + _dev->issue_stream_cmd(shd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); + return true; + } + +private: + shd::xmini::multi_xmini::sptr _dev; + const shd::io_type_t _type; + size_t _nchan; + bool _stream_now; + gr_vector_void_star _tmp_buffs; + shd::rx_metadata_t _metadata; +}; + + +/********************************************************************* + * Make SHD Multi SMINI Source + ********************************************************************/ + +boost::shared_ptr<shd_smini_source> shd_make_smini_source( + const shd::device_addr_t &device_addr, + const shd::io_type_t &io_type, + size_t num_channels) +{ + return boost::shared_ptr<shd_smini_source>( + new shd_smini_source_impl(device_addr, io_type, num_channels)); +} diff --git a/gr-shd/swig/.gitignore b/gr-shd/swig/.gitignore new file mode 100644 index 000000000..23ae38f9b --- /dev/null +++ b/gr-shd/swig/.gitignore @@ -0,0 +1,8 @@ +/shd_swig.cc +/shd_swig.py +/Makefile +/Makefile.in +/guile +/python +/run_guile_tests +/run_tests diff --git a/gr-shd/swig/Makefile.am b/gr-shd/swig/Makefile.am new file mode 100644 index 000000000..3e155ba41 --- /dev/null +++ b/gr-shd/swig/Makefile.am @@ -0,0 +1,82 @@ +# +# Copyright 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. +# + +include $(top_srcdir)/Makefile.common +include $(top_srcdir)/Makefile.swig + +TESTS = +EXTRA_DIST += run_tests.in run_guile_tests.in $(nobase_guile_DATA) +DISTCLEANFILES += run_tests run_guile_tests + +noinst_PYTHON = qa_shd.py +noinst_GUILE = shd.test + +AM_CPPFLAGS = \ + $(STD_DEFINES_AND_INCLUDES) \ + $(PYTHON_CPPFLAGS) \ + $(SHD_CPPFLAGS) \ + $(WITH_INCLUDES) + +shd_swig_swig_args = $(SHD_CPPFLAGS) + +if GUILE +nobase_guile_DATA = \ + gnuradio/shd.scm +endif + +# ---------------------------------------------------------------- +# The SWIG library + +TOP_SWIG_IFILES = \ + shd_swig.i + +# Install so that they end up available as: +# import gnuradio.shd +# This ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio/shd +shd_swig_pythondir_category = \ + gnuradio/shd + +# additional libraries for linking with the SWIG-generated library +shd_swig_la_swig_libadd = \ + $(top_builddir)/gr-shd/lib/libgnuradio-shd.la + +# additional Python files to be installed along with the SWIG-generated one +shd_swig_python = \ + __init__.py + +# additional SWIG files to be installed +shd_swig_swiginclude_headers = + +shd_swig_swig_args = $(SHD_CPPFLAGS) + +## If SHD was installed, defined GR_HAVE_SHD for swigging headers +if GR_DEFINE_HAVE_SHD + shd_swig_swig_args += -DGR_HAVE_SHD +endif + +if PYTHON +TESTS += run_tests +endif + +if GUILE +TESTS += run_guile_tests +endif diff --git a/gr-shd/swig/Makefile.swig.gen b/gr-shd/swig/Makefile.swig.gen new file mode 100644 index 000000000..ebe843bbe --- /dev/null +++ b/gr-shd/swig/Makefile.swig.gen @@ -0,0 +1,145 @@ +# -*- Makefile -*- +# +# Copyright 2009 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. +# + +# Makefile.swig.gen for shd_swig.i + +## Default install locations for these files: +## +## Default location for the Python directory is: +## ${prefix}/lib/python${python_version}/site-packages/[category]/shd_swig +## Default location for the Python exec directory is: +## ${exec_prefix}/lib/python${python_version}/site-packages/[category]/shd_swig +## +## The following can be overloaded to change the install location, but +## this has to be done in the including Makefile.am -before- +## Makefile.swig is included. + +shd_swig_pythondir_category ?= gnuradio/shd_swig +shd_swig_pylibdir_category ?= $(shd_swig_pythondir_category) +shd_swig_pythondir = $(pythondir)/$(shd_swig_pythondir_category) +shd_swig_pylibdir = $(pyexecdir)/$(shd_swig_pylibdir_category) + +# The .so libraries for the guile modules get installed whereever guile +# is installed, usually /usr/lib/guile/gnuradio/ +# FIXME: determince whether these should be installed with gnuradio. +shd_swig_scmlibdir = $(libdir) + +# The scm files for the guile modules get installed where ever guile +# is installed, usually /usr/share/guile/site/shd_swig +# FIXME: determince whether these should be installed with gnuradio. +shd_swig_scmdir = $(guiledir) + +## SWIG headers are always installed into the same directory. + +shd_swig_swigincludedir = $(swigincludedir) + +## This is a template file for a "generated" Makefile addition (in +## this case, "Makefile.swig.gen"). By including the top-level +## Makefile.swig, this file will be used to generate the SWIG +## dependencies. Assign the variable TOP_SWIG_FILES to be the list of +## SWIG .i files to generated wrappings for; there can be more than 1 +## so long as the names are unique (no sorting is done on the +## TOP_SWIG_FILES list). This file explicitly assumes that a SWIG .i +## file will generate .cc, .py, and possibly .h files -- meaning that +## all of these files will have the same base name (that provided for +## the SWIG .i file). +## +## This code is setup to ensure parallel MAKE ("-j" or "-jN") does the +## right thing. For more info, see < +## http://sources.redhat.com/automake/automake.html#Multiple-Outputs > + +## Other cleaned files: dependency files generated by SWIG or this Makefile + +MOSTLYCLEANFILES += $(DEPDIR)/*.S* + +## Various SWIG variables. These can be overloaded in the including +## Makefile.am by setting the variable value there, then including +## Makefile.swig . + +shd_swig_swiginclude_HEADERS = \ + shd_swig.i \ + $(shd_swig_swiginclude_headers) + +if PYTHON +shd_swig_pylib_LTLIBRARIES = \ + _shd_swig.la + +_shd_swig_la_SOURCES = \ + python/shd_swig.cc \ + $(shd_swig_la_swig_sources) + +shd_swig_python_PYTHON = \ + shd_swig.py \ + $(shd_swig_python) + +_shd_swig_la_LIBADD = \ + $(STD_SWIG_LA_LIB_ADD) \ + $(shd_swig_la_swig_libadd) + +_shd_swig_la_LDFLAGS = \ + $(STD_SWIG_LA_LD_FLAGS) \ + $(shd_swig_la_swig_ldflags) + +_shd_swig_la_CXXFLAGS = \ + $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ + $(shd_swig_la_swig_cxxflags) + +python/shd_swig.cc: shd_swig.py +shd_swig.py: shd_swig.i + +# Include the python dependencies for this file +-include python/shd_swig.d + +endif # end of if python + +if GUILE + +shd_swig_scmlib_LTLIBRARIES = \ + libguile-gnuradio-shd_swig.la +libguile_gnuradio_shd_swig_la_SOURCES = \ + guile/shd_swig.cc \ + $(shd_swig_la_swig_sources) +nobase_shd_swig_scm_DATA = \ + gnuradio/shd_swig.scm \ + gnuradio/shd_swig-primitive.scm +libguile_gnuradio_shd_swig_la_LIBADD = \ + $(STD_SWIG_LA_LIB_ADD) \ + $(shd_swig_la_swig_libadd) +libguile_gnuradio_shd_swig_la_LDFLAGS = \ + $(STD_SWIG_LA_LD_FLAGS) \ + $(shd_swig_la_swig_ldflags) +libguile_gnuradio_shd_swig_la_CXXFLAGS = \ + $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ + $(shd_swig_la_swig_cxxflags) + +guile/shd_swig.cc: gnuradio/shd_swig.scm +gnuradio/shd_swig.scm: shd_swig.i +gnuradio/shd_swig-primitive.scm: gnuradio/shd_swig.scm + +# Include the guile dependencies for this file +-include guile/shd_swig.d + +endif # end of GUILE + + diff --git a/gr-shd/swig/__init__.py b/gr-shd/swig/__init__.py new file mode 100644 index 000000000..17589625c --- /dev/null +++ b/gr-shd/swig/__init__.py @@ -0,0 +1,88 @@ +# +# Copyright 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. +# + +######################################################################## +# Prepare shd swig module to make it more pythonic +######################################################################## +def _prepare_shd_swig(): + import shd_swig + + #some useful typedefs for the user + setattr(shd_swig, 'freq_range_t', shd_swig.meta_range_t) + setattr(shd_swig, 'gain_range_t', shd_swig.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. + class tune_request_t(shd_swig.tune_request_t, float): + def __new__(self, *args): return float.__new__(self) + def __float__(self): return self.target_freq + setattr(shd_swig, 'tune_request_t', tune_request_t) + + #Make the python tune request object inherit from string + #so that it can be passed in GRC as a string parameter. + #The type checking in GRC will accept the device address. + #Define the set/get item special methods for dict access. + class device_addr_t(shd_swig.device_addr_t, str): + def __new__(self, *args): return str.__new__(self) + def __getitem__(self, key): return self.get(key) + def __setitem__(self, key, val): self.set(key, val) + setattr(shd_swig, 'device_addr_t', device_addr_t) + + #handle general things on all shd_swig attributes + #Install the __str__ and __repr__ handlers if applicable + #Create aliases for shd swig attributes to avoid the "_t" + for attr in dir(shd_swig): + myobj = getattr(shd_swig, 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(shd_swig, attr[:-2], myobj) + + #Cast constructor args (FIXME swig handle overloads?) + for attr in ('smini_source', 'smini_sink'): + def constructor_factory(old_constructor): + def constructor_interceptor(*args, **kwargs): + args = list(args) + kwargs = dict(kwargs) + for index, key, cast in ( + (0, 'device_addr', device_addr), + (1, 'io_type', io_type), + ): + if len(args) > index: args[index] = cast(args[index]) + if kwargs.has_key(key): kwargs[key] = cast(kwargs[key]) + return old_constructor(*args, **kwargs) + return constructor_interceptor + setattr(shd_swig, attr, constructor_factory(getattr(shd_swig, attr))) + + #Aliases for deprecated constructors + setattr(shd_swig, 'single_smini_source', shd_swig.smini_source) + setattr(shd_swig, 'single_smini_sink', shd_swig.smini_sink) + setattr(shd_swig, 'multi_smini_source', shd_swig.smini_source) + setattr(shd_swig, 'multi_smini_sink', shd_swig.smini_sink) + +######################################################################## +# Initialize this module with the contents of shd swig +######################################################################## +_prepare_shd_swig() +from shd_swig import * diff --git a/gr-shd/swig/gnuradio/.gitignore b/gr-shd/swig/gnuradio/.gitignore new file mode 100644 index 000000000..adf5c3727 --- /dev/null +++ b/gr-shd/swig/gnuradio/.gitignore @@ -0,0 +1,2 @@ +shd_swig-primitive.scm +shd_swig.scm diff --git a/gr-shd/swig/gnuradio/shd.scm b/gr-shd/swig/gnuradio/shd.scm new file mode 100644 index 000000000..91af98dd8 --- /dev/null +++ b/gr-shd/swig/gnuradio/shd.scm @@ -0,0 +1,27 @@ +;;; +;;; Copyright 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 this program. If not, see <http://www.gnu.org/licenses/>. +;;; + +;;; Semi bogus module that just reexports the shd_swig module + +(define-module (gnuradio shd) + #:use-module (gnuradio export-safely) + #:use-module (gnuradio shd_swig) + #:duplicates (merge-generics replace check)) + +(re-export-all '(gnuradio shd_swig)) diff --git a/gr-shd/swig/qa_shd.py b/gr-shd/swig/qa_shd.py new file mode 100755 index 000000000..538de918c --- /dev/null +++ b/gr-shd/swig/qa_shd.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright 2005,2008,2010 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, gr_unittest +import shd_swig + +class test_shd(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000_nop (self): + """Just see if we can import the module... + They may not have a SHD device connected, etc. Don't try to run anything""" + pass + +if __name__ == '__main__': + gr_unittest.run(test_shd, "test_shd.xml") diff --git a/gr-shd/swig/run_guile_tests.in b/gr-shd/swig/run_guile_tests.in new file mode 100644 index 000000000..5d08b0dd5 --- /dev/null +++ b/gr-shd/swig/run_guile_tests.in @@ -0,0 +1,14 @@ +#!/bin/sh + +. @top_builddir@/setup_guile_test_env + +# 1st argument is absolute path to hand coded guile source directory +# 2nd argument is absolute path to component C++ shared library build directory +# 3nd argument is absolute path to component SWIG build directory + +add_local_paths \ + @srcdir@ \ + @abs_builddir@ \ + @abs_builddir@ + +@GUILE@ -e main -c '(use-modules (gnuradio test-suite guile-test))' -t @srcdir@ diff --git a/gr-shd/swig/run_tests.in b/gr-shd/swig/run_tests.in new file mode 100644 index 000000000..580296374 --- /dev/null +++ b/gr-shd/swig/run_tests.in @@ -0,0 +1,10 @@ +#!/bin/sh + +# 1st parameter is absolute path to component source directory +# 2nd parameter is absolute path to component build directory +# 3rd parameter is path to Python QA directory + +@top_builddir@/run_tests.sh \ + @abs_top_srcdir@/gr-shd \ + @abs_top_builddir@/gr-shd \ + @srcdir@ diff --git a/gr-shd/swig/shd.test b/gr-shd/swig/shd.test new file mode 100644 index 000000000..7b118a081 --- /dev/null +++ b/gr-shd/swig/shd.test @@ -0,0 +1,37 @@ +;;; -*- Scheme -*- +;;; +;;; Copyright 2010 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 this program. If not, see <http://www.gnu.org/licenses/>. +;;; + +;;; If you're using Emacs's Scheme mode: +;;; (put 'with-test-prefix 'scheme-indent-function 1) + +;;; See the comments in gnuradio/test-suite/lib.scm for info on writing tests. +;;; See also the very end of the file, where the test-equal, test-eqv +;;; and test-eq macros are defined. + +(define-module (test-module) + #:use-module (oop goops) + #:use-module (gnuradio core) + #:use-module (gnuradio test-suite lib) + #:duplicates (merge-generics replace check)) + +;;; Just see if we can import the module... +;;; They may not have a SHD device attached, powered up etc. + +(use-modules (gnuradio shd)) diff --git a/gr-shd/swig/shd_swig.i b/gr-shd/swig/shd_swig.i new file mode 100644 index 000000000..217b2f1af --- /dev/null +++ b/gr-shd/swig/shd_swig.i @@ -0,0 +1,135 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +// Defined during configure; avoids trying to locate +// header files if SHD was not installed. +#ifdef GR_HAVE_SHD + +#define GR_SHD_API + +//////////////////////////////////////////////////////////////////////// +// Language independent exception handler +//////////////////////////////////////////////////////////////////////// +%include exception.i + +%exception { + try { + $action + } + catch(std::exception &e) { + SWIG_exception(SWIG_RuntimeError, e.what()); + } + catch(...) { + SWIG_exception(SWIG_RuntimeError, "Unknown exception"); + } + +} + +//////////////////////////////////////////////////////////////////////// +// standard includes +//////////////////////////////////////////////////////////////////////// +%include "gnuradio.i" + +//////////////////////////////////////////////////////////////////////// +// block headers +//////////////////////////////////////////////////////////////////////// +%{ +#include <gr_shd_smini_source.h> +#include <gr_shd_smini_sink.h> +%} + +//////////////////////////////////////////////////////////////////////// +// used types +//////////////////////////////////////////////////////////////////////// +%template(string_vector_t) std::vector<std::string>; + +%include <shd/config.hpp> + +%include <shd/utils/pimpl.hpp> + +%ignore shd::dict::operator[]; //ignore warnings about %extend +%include <shd/types/dict.hpp> +%template(string_string_dict_t) shd::dict<std::string, std::string>; //define after dict + +%include <shd/types/device_addr.hpp> + +%include <shd/types/io_type.hpp> + +%template(range_vector_t) std::vector<shd::range_t>; //define before range +%include <shd/types/ranges.hpp> + +%include <shd/types/tune_request.hpp> + +%include <shd/types/tune_result.hpp> + +%include <shd/types/io_type.hpp> + +%include <shd/types/time_spec.hpp> + +%include <shd/types/clock_config.hpp> + +%include <shd/types/metadata.hpp> + +%ignore shd::device::register_device; //causes compile to choke in MSVC +%include <shd/device.hpp> +%template(device_addr_vector_t) std::vector<shd::device_addr_t>; + +%include <shd/types/sensors.hpp> + +//////////////////////////////////////////////////////////////////////// +// swig dboard_iface for python access +//////////////////////////////////////////////////////////////////////// +%include stdint.i +%include <shd/types/serial.hpp> +%template(byte_vector_t) std::vector<uint8_t>; +%include <shd/xmini/dboard_iface.hpp> + +%template(dboard_iface_sptr) boost::shared_ptr<shd::xmini::dboard_iface>; + +//////////////////////////////////////////////////////////////////////// +// block magic +//////////////////////////////////////////////////////////////////////// +GR_SWIG_BLOCK_MAGIC(shd,smini_source) +%include <gr_shd_smini_source.h> + +GR_SWIG_BLOCK_MAGIC(shd,smini_sink) +%include <gr_shd_smini_sink.h> + +//////////////////////////////////////////////////////////////////////// +// helpful constants +//////////////////////////////////////////////////////////////////////// +%{ +static const size_t ALL_MBOARDS = shd::xmini::multi_xmini::ALL_MBOARDS; +%} +static const size_t ALL_MBOARDS; + +#if SWIGGUILE +%scheme %{ +(load-extension-global "libguile-gnuradio-shd_swig" "scm_init_gnuradio_shd_swig_module") +%} + +%goops %{ +(use-modules (gnuradio gnuradio_core_runtime)) +%} +#endif /* SWIGGUILE */ + +#endif /* GR_HAVE_SHD */ |