diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2013-12-15 00:30:11 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2013-12-15 00:30:11 +0100 |
commit | ae587d9d1678d50c98497efeaeecda28f2703229 (patch) | |
tree | 1ebbf6c22a285b472d27ace9b6862b34de863a1f /python/crc-dwap.py | |
parent | 3b9870cebf16a50ade6d7591e089c8ccbe614024 (diff) | |
download | dabmod-ae587d9d1678d50c98497efeaeecda28f2703229.tar.gz dabmod-ae587d9d1678d50c98497efeaeecda28f2703229.tar.bz2 dabmod-ae587d9d1678d50c98497efeaeecda28f2703229.zip |
autotools: AM_INIT_AUTOMAKE with subdir-objects
Make the autotools non-recursive to suppress error, and make it
future-proof.
Diffstat (limited to 'python/crc-dwap.py')
-rwxr-xr-x | python/crc-dwap.py | 547 |
1 files changed, 547 insertions, 0 deletions
diff --git a/python/crc-dwap.py b/python/crc-dwap.py new file mode 100755 index 0000000..7fec510 --- /dev/null +++ b/python/crc-dwap.py @@ -0,0 +1,547 @@ +#!/usr/bin/env python + +# Copyright (C) 2006, 2007, 2008, 2009,-2010 Her Majesty the Queen in +# Right of Canada (Communications Research Center Canada) + +# This file is part of CRC-DADMOD. +# +# CRC-DADMOD 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 of the +# License, or (at your option) any later version. +# +# CRC-DADMOD 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 CRC-DADMOD. If not, see <http://www.gnu.org/licenses/>. + + +from wxPython.wx import * +from optparse import OptionParser +from gnuradio import gr +from gnuradio import usrp +from gnuradio.wxgui import fftsink, scopesink +from gnuradio.eng_notation import num_to_str +from gnuradio.eng_option import * + +ID_ABOUT = wxNewId() +ID_EXIT = wxNewId() +ID_GAIN_SLIDER0 = wxNewId() +ID_FREQ_SLIDER0 = wxNewId() +ID_GAIN_SLIDER1 = wxNewId() +ID_FREQ_SLIDER1 = wxNewId() +ID_START = wxNewId() +ID_STOP = wxNewId() + +def gcd(a, b) : + if b == 0 : + return a + return gcd(b, a % b) + + +def appendFrequency(option, opt, value, parser): + if parser.values.frequency is None : + parser.values.frequency = [ value ] + else : + parser.values.frequency.append(value) + +def listUsrp(option, opt, value, parser): + id = 0 + while (true) : + try: + version = usrp._look_for_usrp(id) + print "USRP #%i" % id + print " Rev: %i" % version + dst = usrp.sink_c(id) + src = usrp.source_c(id) + print " Tx" + for db in dst.db: + if (db[0].dbid() != -1): + print " %s" % db[0].side_and_name() + (min, max, offset) = db[0].freq_range() + print " Frequency" + print " Min: %sHz" % num_to_str(min) + print " Max: %sHz" % num_to_str(max) + print " Offset: %sHz" % num_to_str(offset) + (min, max, offset) = db[0].gain_range() + print " Gain" + print " Min: %sdB" % num_to_str(min) + print " Max: %sdB" % num_to_str(max) + print " Offset: %sdB" % num_to_str(offset) + print " Rx" + for db in src.db: + if (db[0].dbid() != -1): + print " %s" % db[0].side_and_name() + (min, max, offset) = db[0].freq_range() + print " Frequency" + print " Min: %sHz" % num_to_str(min) + print " Max: %sHz" % num_to_str(max) + print " Offset: %sHz" % num_to_str(offset) + (min, max, offset) = db[0].gain_range() + print " Gain" + print " Min: %sdB" % num_to_str(min) + print " Max: %sdB" % num_to_str(max) + print " Offset: %sdB" % num_to_str(offset) + except RuntimeError: + break + id += 1 + + raise SystemExit + +class MyFrame(wxFrame): + def __init__(self, parent, ID, title): + wxFrame.__init__(self, parent, ID, title, + wxDefaultPosition) + + self.pga = 0 + self.pgaMin = -20 + self.pgaMax = 0 + self.pgaStep = 0.25 + +# Parsing options + parser = OptionParser(option_class=eng_option, + usage="usage: %prog [options] filename1" \ + " [-f frequency2 filename2 [...]]") + parser.add_option("-a", "--agc", action="store_true", + help="enable agc") + parser.add_option("-c", "--clockrate", type="eng_float", default=128e6, + help="set USRP clock rate (128e6)") + parser.add_option("--copy", action="store_true", + help="enable real to imag data copy when in real mode") + parser.add_option("-e", "--encoding", type="choice", choices=["s", "f"], + default="f", help="choose data encoding: [s]igned or [f]loat.") + parser.add_option("-f", "--frequency", type="eng_float", + action="callback", callback=appendFrequency, + help="set output frequency (222.064e6)") + parser.add_option("-g", "--gain", type="float", + help="set output pga gain") + parser.add_option("-l", "--list", action="callback", callback=listUsrp, + help="list USRPs and daugtherboards") + parser.add_option("-m", "--mode", type="eng_float", default=2, + help="mode: 1: real, 2: complex (2)") + parser.add_option("-o", "--osc", action="store_true", + help="enable oscilloscope") + parser.add_option("-r", "--samplingrate", type="eng_float", + default=3.2e6, + help="set input sampling rate (3200000)") + parser.add_option("-s", "--spectrum", action="store_true", + help="enable spectrum analyzer") +# parser.add_option("-t", "--tx", type="choice", choices=["A", "B"], +# default="A", help="choose USRP tx A|B output (A)") + parser.add_option("-u", "--usrp", action="store_true", + help="enable USRP output") + + (options, args) = parser.parse_args() + if len(args) == 0 : + options.filename = [ "/dev/stdin" ] + else : + options.filename = args +# Setting default frequency + if options.frequency is None : + options.frequency = [ 222.064e6 ] + if len(options.filename) != len(options.frequency) : + parser.error("Nb input file != nb frequency!") + +# Status bar +# self.CreateStatusBar(3, 0) +# msg = "PGA: %.2f dB" % (self.pga * self.pgaStep) +# self.SetStatusText(msg, 1) +# msg = "Freq: %.3f mHz" % (options.frequency[0] / 1000000.0) +# self.SetStatusText(msg, 2) + +# Menu bar + menu = wxMenu() + menu.Append(ID_ABOUT, "&About", + "More information about this program") + menu.AppendSeparator() + menu.Append(ID_EXIT, "E&xit", "Terminate the program") + menuBar = wxMenuBar() + menuBar.Append(menu, "&File") + self.SetMenuBar(menuBar) + + +# Main windows + mainSizer = wxFlexGridSizer(0, 1) + sliderSizer = wxFlexGridSizer(0, 2) + buttonSizer = wxBoxSizer(wxHORIZONTAL) + + if options.usrp : + # TX d'board 0 + gainLabel = wxStaticText(self, -1, "PGA 0") + gainSlider = wxSlider(self, ID_GAIN_SLIDER0, self.pga, + self.pgaMin / self.pgaStep, self.pgaMax / self.pgaStep, + style = wxSL_HORIZONTAL | wxSL_AUTOTICKS) + gainSlider.SetSize((400, -1)) + sliderSizer.Add(gainLabel, 0, + wxALIGN_CENTER_VERTICAL | wxFIXED_MINSIZE, 0) + sliderSizer.Add(gainSlider, 0, + wxALIGN_CENTER_VERTICAL | wxFIXED_MINSIZE, 0) + + freqLabel = wxStaticText(self, -1, "Frequency 0") + freqSlider = wxSlider(self, ID_FREQ_SLIDER0, + options.frequency[0] / 16000, 0, 20e3, + style = wxSL_HORIZONTAL | wxSL_AUTOTICKS) + freqSlider.SetSize((400, -1)) + sliderSizer.Add(freqLabel, 0, + wxALIGN_CENTER_VERTICAL | wxFIXED_MINSIZE, 0) + sliderSizer.Add(freqSlider, 0, + wxALIGN_CENTER_VERTICAL | wxFIXED_MINSIZE, 0) + + if len(options.frequency) > 1 : + # TX d'board 1 + gainLabel = wxStaticText(self, -1, "PGA 1") + gainSlider = wxSlider(self, ID_GAIN_SLIDER1, self.pga, + self.pgaMin / self.pgaStep, self.pgaMax / self.pgaStep, + style = wxSL_HORIZONTAL | wxSL_AUTOTICKS) + gainSlider.SetSize((400, -1)) + sliderSizer.Add(gainLabel, 0, + wxALIGN_CENTER_VERTICAL | wxFIXED_MINSIZE, 0) + sliderSizer.Add(gainSlider, 0, + wxALIGN_CENTER_VERTICAL | wxFIXED_MINSIZE, 0) + + freqLabel = wxStaticText(self, -1, "Frequency 1") + freqSlider = wxSlider(self, ID_FREQ_SLIDER1, + options.frequency[1] / 16000, 0, 20e3, + style = wxSL_HORIZONTAL | wxSL_AUTOTICKS) + freqSlider.SetSize((400, -1)) + sliderSizer.Add(freqLabel, 0, + wxALIGN_CENTER_VERTICAL | wxFIXED_MINSIZE, 0) + sliderSizer.Add(freqSlider, 0, + wxALIGN_CENTER_VERTICAL | wxFIXED_MINSIZE, 0) + + mainSizer.Add(sliderSizer, 1, wxEXPAND, 0) + + start = wxButton(self, ID_START, "Start") + stop = wxButton(self, ID_STOP, "Stop") + buttonSizer.Add(start, 1, wxALIGN_CENTER, 0) + buttonSizer.Add(stop, 1, wxALIGN_CENTER, 0) + mainSizer.Add(buttonSizer, 1, wxEXPAND, 0) + +# GnuRadio + self.fg = gr.flow_graph() + if options.mode == 1 : + print "Source: real" + if (options.encoding == "s") : + print "Source encoding: short" + src = gr.file_source(gr.sizeof_short, options.filename[0], 1) + if (options.copy) : + print "Imag: copy" + imag = src + else : + print "Imag: null" + imag = gr.null_source(gr.sizeof_short) + interleaver = gr.interleave(gr.sizeof_short) + self.fg.connect(src, (interleaver, 0)) + self.fg.connect(imag, (interleaver, 1)) + tail = interleaver + elif (options.encoding == "f") : + print "Source encoding: float" + src = gr.file_source(gr.sizeof_gr_complex, + options.filename[0], 1) + tail = src + elif (options.mode == 2) : + print "Source: complex" + if len(options.frequency) == 1 : + if (options.encoding == "s") : + print "Source encoding: short" + src = gr.file_source(gr.sizeof_short, + options.filename[0], 1) + elif (options.encoding == "f") : + print "Source encoding: float" + src = gr.file_source(gr.sizeof_gr_complex, + options.filename[0], 1) + else : + parser.error("Invalid encoding type for complex data!") + tail = src + + elif (len(options.frequency) == 2) : + src0 = gr.file_source(gr.sizeof_gr_complex, + options.filename[0], 1) + src1 = gr.file_source(gr.sizeof_gr_complex, + options.filename[1], 1) + interleaver = gr.interleave(gr.sizeof_gr_complex) + self.fg.connect(src0, (interleaver, 0)) + self.fg.connect(src1, (interleaver, 1)) + tail = interleaver + else : + parser.error( + "Invalid number of source (> 2) with complex input!") + else : + parser.error("Invalid mode!") + +# Interpolation + dac_freq = options.clockrate + interp = int(dac_freq / options.samplingrate) + if interp == 0 : + parser.error("Invalid sampling rate!") + if options.mode == 2 : + print "Input sampling rate: %s complex samples/s" % \ + num_to_str(options.samplingrate) + else : + print "Input sampling rate: %s samples/s" % \ + num_to_str(options.samplingrate) + print "Interpolation rate: int(%s / %s) = %sx" % \ + (num_to_str(dac_freq), num_to_str(options.samplingrate), interp) + if interp > 512 : + factor = gcd(dac_freq / 512, options.samplingrate) + num = int((dac_freq / 512) / factor) + den = int(options.samplingrate / factor) + print "Resampling by %i / %i" % (num, den) + resampler = blks.rational_resampler_ccc(self.fg, num, den) + self.fg.connect(tail, resampler) + tail = resampler + interp = 512 + options.samplingrate = dac_freq / 512 + +# AGC + if options.agc : + agc = gr.agc_cc() + self.fg.connect(tail, agc) + tail = agc + +# USRP + if options.usrp : + nchan = len(options.frequency) + if len(options.frequency) == 1 : + if options.mode == 1 : + mux = 0x00000098 + elif options.mode == 2 : + mux = 0x00000098 + else : + parser.error("Unsupported mode for USRP mux!") + elif len(options.frequency) == 2 : + if options.mode == 1 : + mux = 0x0000ba98 + elif options.mode == 2 : + mux = 0x0000ba98 + else : + parser.error("Unsupported mode for USRP mux!") + else : + parser.error("Invalid number of frequency [0..2]!") +# if options.tx == "A" : +# mux = 0x00000098 +# else : +# mux = 0x00009800 + print "Nb channels: ", nchan + print "Mux: 0x%x" % mux + if options.encoding == 's' : + dst = usrp.sink_s(0, interp, nchan, mux) + elif options.encoding == 'f' : + dst = usrp.sink_c(0, interp, nchan, mux) + else : + parser.error("Unsupported data encoding for USRP!") + + dst.set_verbose(1) + + for i in range(len(options.frequency)) : + if options.gain is None : + print "Setting gain to %f" % dst.pga_max() + dst.set_pga(i << 1, dst.pga_max()) + else : + print "Setting gain to %f" % options.gain + dst.set_pga(i << 1, options.gain) + + tune = false + for dboard in dst.db: + if (dboard[0].dbid() != -1): + device = dboard[0] + print "Tuning TX d'board %s to %sHz" % \ + (device.side_and_name(), + num_to_str(options.frequency[i])) + device.lo_offset = 38e6 + (min, max, offset) = device.freq_range() + print " Frequency" + print " Min: %sHz" % num_to_str(min) + print " Max: %sHz" % num_to_str(max) + print " Offset: %sHz" % num_to_str(offset) +#device.set_gain(device.gain_range()[1]) + device.set_enable(True) + tune = \ + dst.tune(device._which, device, + options.frequency[i] * 128e6 / dac_freq) + if tune: + print " Baseband frequency: %sHz" % \ + num_to_str(tune.baseband_freq) + print " DXC frequency: %sHz" % \ + num_to_str(tune.dxc_freq) + print " Residual Freqency: %sHz" % \ + num_to_str(tune.residual_freq) + print " Inverted: ", \ + tune.inverted + mux = usrp.determine_tx_mux_value(dst, + (device._which, 0)) + dst.set_mux(mux) + break + else: + print " Failed!" + if not tune: + print " Failed!" + raise SystemExit + +# int nunderruns () + + print "USRP" + print " Rx halfband: ", dst.has_rx_halfband() + print " Tx halfband: ", dst.has_tx_halfband() + print " Nb DDC: ", dst.nddc() + print " Nb DUC: ", dst.nduc() +#dst._write_9862(0, 14, 224) + + print " DAC frequency: %s samples/s" % num_to_str(dst.dac_freq()) + print " Fpga decimation rate: %s -> %s samples/s" % \ + (num_to_str(dst.interp_rate()), + num_to_str(dac_freq / dst.interp_rate())) + print " Nb channels:", + if hasattr(dst, "nchannels()") : + print dst.nchannels() + else: + print "N/A" + print " Mux:", + if hasattr(dst, "mux()") : + print "0x%x" % dst.mux() + else : + print "N/A" + print " FPGA master clock frequency:", + if hasattr(dst, "fpga_master_clock_freq()") : + print "%sHz" % num_to_str(dst.fpga_master_clock_freq()) + else : + print "N/A" + print " Converter rate:", + if hasattr(dst, "converter_rate()") : + print "%s" % num_to_str(dst.converter_rate()) + else : + print "N/A" + print " DAC rate:", + if hasattr(dst, "dac_rate()") : + print "%s sample/s" % num_to_str(dst.dac_rate()) + else : + print "N/A" + print " Interp rate: %sx" % num_to_str(dst.interp_rate()) + print " DUC frequency 0: %sHz" % num_to_str(dst.tx_freq(0)) + print " DUC frequency 1: %sHz" % num_to_str(dst.tx_freq(1)) + print " Programmable Gain Amplifier 0: %s dB" % \ + num_to_str(dst.pga(0)) + print " Programmable Gain Amplifier 1: %s dB" % \ + num_to_str(dst.pga(2)) + + else : + dst = gr.null_sink(gr.sizeof_gr_complex) + +# AGC + if options.agc : + agc = gr.agc_cc() + self.fg.connect(tail, agc) + tail = agc + + self.fg.connect(tail, dst) + +# oscilloscope + if options.osc : + oscPanel = wxPanel(self, -1) + if (options.encoding == "s") : + converter = gr.interleaved_short_to_complex() + self.fg.connect(tail, converter) + signal = converter + elif (options.encoding == "f") : + signal = tail + else : + parser.error("Unsupported data encoding for oscilloscope!") + +#block = scope_sink_f(fg, parent, title=label, sample_rate=input_rate) +#return (block, block.win) + + oscWin = scopesink.scope_sink_c(self.fg, oscPanel, "Signal", + options.samplingrate) + self.fg.connect(signal, oscWin) + mainSizer.Add(oscPanel, 1, wxEXPAND) + +# spectrometer + if options.spectrum : + ymin = 0 + ymax = 160 + fftPanel = wxPanel(self, -1) + if (options.encoding == "s") : + converter = gr.interleaved_short_to_complex() + self.fg.connect(tail, converter) + signal = converter + elif (options.encoding == "f") : + signal = tail + else : + parser.error("Unsupported data encoding for oscilloscope!") + + fftWin = fftsink.fft_sink_c(self.fg, fftPanel, + title="Spectrum", + fft_size=2048, + sample_rate=options.samplingrate, + y_per_div=(ymax - ymin) / 8, + ref_level=ymax, + fft_rate=50, + average=True + ) + self.fg.connect(signal, fftWin) + mainSizer.Add(fftPanel, 1, wxEXPAND) + +# Events + EVT_MENU(self, ID_ABOUT, self.OnAbout) + EVT_MENU(self, ID_EXIT, self.TimeToQuit) + EVT_SLIDER(self, ID_GAIN_SLIDER0, self.slideEvent) + EVT_SLIDER(self, ID_FREQ_SLIDER0, self.slideEvent) + EVT_SLIDER(self, ID_GAIN_SLIDER1, self.slideEvent) + EVT_SLIDER(self, ID_FREQ_SLIDER1, self.slideEvent) + EVT_BUTTON(self, ID_START, self.onClick) + EVT_BUTTON(self, ID_STOP, self.onClick) + +#Layout sizers + self.SetSizer(mainSizer) + self.SetAutoLayout(1) + mainSizer.Fit(self) + + self.fg.start() + + def OnAbout(self, event): + dlg = wxMessageDialog(self, "This sample program shows off\n" + "frames, menus, statusbars, and this\n" + "message dialog.", + "About Me", wxOK | wxICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + + + def TimeToQuit(self, event): + self.Close(true) + + def slideEvent(self, evt): + value = evt.GetInt() + id = evt.GetId() + if id == ID_GAIN_SLIDER: + msg = "PGA: %.2f dB" % (value * self.pgaStep) + self.SetStatusText(msg, 1) + elif id == ID_FREQ_SLIDER: + msg = "Freq: %.3f mHz" % (value * 16.0 / 1000) + self.SetStatusText(msg, 2) + else: + print "Slider event not yet coded!" + self.Close(True) + + def onClick(self, event): + id = event.GetId() + if id == ID_START: + self.fg.start() + elif id == ID_STOP: + self.fg.stop() + else: + print "Click event not yet coded!" + self.Close(True) + +class MyApp(wxApp): + def OnInit(self): + frame = MyFrame(NULL, -1, "Digital WAve Player") + frame.Show(true) + self.SetTopWindow(frame) + return true + +app = MyApp(0) +app.MainLoop() |