diff options
Diffstat (limited to 'gr-uhd/examples')
-rw-r--r-- | gr-uhd/examples/.gitignore | 5 | ||||
-rw-r--r-- | gr-uhd/examples/Makefile.am | 31 | ||||
-rwxr-xr-x | gr-uhd/examples/fm_tx4.py | 205 | ||||
-rwxr-xr-x | gr-uhd/examples/max_power.py | 142 | ||||
-rw-r--r-- | gr-uhd/examples/multi-antenna/.gitignore | 11 | ||||
-rw-r--r-- | gr-uhd/examples/multi-antenna/Makefile.am | 29 | ||||
-rwxr-xr-x | gr-uhd/examples/multi-antenna/multi_fft.py | 152 | ||||
-rwxr-xr-x | gr-uhd/examples/multi-antenna/multi_file.py | 134 | ||||
-rwxr-xr-x | gr-uhd/examples/multi-antenna/multi_scope.py | 139 | ||||
-rwxr-xr-x | gr-uhd/examples/usrp_am_mw_rcv.py | 316 |
10 files changed, 1164 insertions, 0 deletions
diff --git a/gr-uhd/examples/.gitignore b/gr-uhd/examples/.gitignore new file mode 100644 index 000000000..ad8a13c08 --- /dev/null +++ b/gr-uhd/examples/.gitignore @@ -0,0 +1,5 @@ +/Makefile +/Makefile.in +*.dat +*.32f +*.32fc diff --git a/gr-uhd/examples/Makefile.am b/gr-uhd/examples/Makefile.am new file mode 100644 index 000000000..de4a453ff --- /dev/null +++ b/gr-uhd/examples/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 = multi-antenna + +ourdatadir = $(exampledir)/uhd + +dist_ourdata_SCRIPTS = \ + fm_tx4.py \ + max_power.py \ + usrp_am_mw_rcv.py diff --git a/gr-uhd/examples/fm_tx4.py b/gr-uhd/examples/fm_tx4.py new file mode 100755 index 000000000..9b39752c1 --- /dev/null +++ b/gr-uhd/examples/fm_tx4.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# +# Copyright 2005-2007,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. +# + +""" +Transmit N simultaneous narrow band FM signals. + +They will be centered at the frequency specified on the command line, +and will spaced at 25kHz steps from there. + +The program opens N files with names audio-N.dat where N is in [0,7]. +These files should contain floating point audio samples in the range [-1,1] +sampled at 32kS/sec. You can create files like this using +audio_to_file.py +""" + +from gnuradio import gr, eng_notation +from gnuradio import uhd +from gnuradio import blks2 +from gnuradio.eng_option import eng_option +from optparse import OptionParser +from usrpm import usrp_dbid +import math +import sys + +from gnuradio.wxgui import stdgui2, fftsink2 +import wx + + +######################################################## +# instantiate one transmit chain for each call + +class pipeline(gr.hier_block2): + def __init__(self, filename, lo_freq, audio_rate, if_rate): + + gr.hier_block2.__init__(self, "pipeline", + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) + + try: + src = gr.file_source (gr.sizeof_float, filename, True) + except RuntimeError: + sys.stderr.write(("\nError: Could not open file '%s'\n\n" % \ + filename)) + sys.exit(1) + + print audio_rate, if_rate + fmtx = blks2.nbfm_tx (audio_rate, if_rate, max_dev=5e3, tau=75e-6) + + # Local oscillator + lo = gr.sig_source_c (if_rate, # sample rate + gr.GR_SIN_WAVE, # waveform type + lo_freq, #frequency + 1.0, # amplitude + 0) # DC Offset + mixer = gr.multiply_cc () + + self.connect (src, fmtx, (mixer, 0)) + self.connect (lo, (mixer, 1)) + self.connect (mixer, self) + +class fm_tx_block(stdgui2.std_top_block): + def __init__(self, frame, panel, vbox, argv): + MAX_CHANNELS = 7 + stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=400e3, + 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("-n", "--nchannels", type="int", default=4, + help="number of Tx channels [1,4]") + #parser.add_option("","--debug", action="store_true", default=False, + # help="Launch Tx debugger") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.nchannels < 1 or options.nchannels > MAX_CHANNELS: + sys.stderr.write ("fm_tx4: nchannels out of range. Must be in [1,%d]\n" % MAX_CHANNELS) + sys.exit(1) + + if options.freq is None: + sys.stderr.write("fm_tx4: must specify frequency with -f FREQ\n") + parser.print_help() + sys.exit(1) + + # ---------------------------------------------------------------- + # Set up constants and parameters + + self.u = uhd.usrp_sink(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + self.usrp_rate = options.samp_rate + self.u.set_samp_rate(self.usrp_rate) + self.usrp_rate = self.u.get_samp_rate() + + self.sw_interp = 10 + self.audio_rate = self.usrp_rate / self.sw_interp # 32 kS/s + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.get_gain_range() + options.gain = float(g.start()+g.stop())/2 + + self.set_gain(options.gain) + self.set_freq(options.freq) + + if(options.antenna): + self.u.set_antenna(options.antenna, 0) + + self.sum = gr.add_cc () + + # Instantiate N NBFM channels + step = 25e3 + offset = (0 * step, 1 * step, -1 * step, + 2 * step, -2 * step, 3 * step, -3 * step) + + for i in range (options.nchannels): + t = pipeline("audio-%d.dat" % (i % 4), offset[i], + self.audio_rate, self.usrp_rate) + self.connect(t, (self.sum, i)) + + self.gain = gr.multiply_const_cc (1.0 / options.nchannels) + + # connect it all + self.connect (self.sum, self.gain) + self.connect (self.gain, self.u) + + # plot an FFT to verify we are sending what we want + if 1: + post_mod = fftsink2.fft_sink_c(panel, title="Post Modulation", + fft_size=512, + sample_rate=self.usrp_rate, + y_per_div=20, + ref_level=40) + self.connect (self.gain, post_mod) + vbox.Add (post_mod.win, 1, wx.EXPAND) + + + #if options.debug: + # self.debugger = tx_debug_gui.tx_debug_gui(self.subdev) + # self.debugger.Show(True) + + + 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 up converter. Finally, we feed + any residual_freq to the s/w freq translater. + """ + + r = self.u.set_center_freq(target_freq, 0) + if r: + print "Frequency =", eng_notation.num_to_str(self.u.get_center_freq()) + return True + + return False + + def set_gain(self, gain): + self.u.set_gain(gain, 0) + + +def main (): + app = stdgui2.stdapp(fm_tx_block, "Multichannel FM Tx", nstatus=1) + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gr-uhd/examples/max_power.py b/gr-uhd/examples/max_power.py new file mode 100755 index 000000000..44d3beeee --- /dev/null +++ b/gr-uhd/examples/max_power.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,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. +# + +""" +Setup USRP for maximum power consumption. +""" + + +from gnuradio import gr +from gnuradio import uhd +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +from gnuradio import eng_notation + +n2s = eng_notation.num_to_str + +# Set this to a huge number; UHD will adjust to the +# maximum the USRP xxxx device can handle +MAX_RATE = 1000e6 + +class build_block(gr.top_block): + def __init__(self, address, tx_enable, rx_enable): + gr.top_block.__init__(self) + + d = uhd.device_find(uhd.device_addr(address)) + uhd_type = d[0].get('type') + + print "\nFound '%s' at address '%s'" % \ + (uhd_type, address) + + # Test the type of USRP; if it's a USRP (v1), it has + # 2 channels; otherwise, it has 1 channel + if uhd_type == "usrp": + tx_nchan = 2 + rx_nchan = 2 + else: + tx_nchan = 1 + rx_nchan = 1 + + if tx_enable: + print "\nTRANSMIT CHAIN" + self.u_tx = uhd.usrp_sink(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=tx_nchan) + self.u_tx.set_samp_rate(MAX_RATE) + + self.tx_src0 = gr.sig_source_c(self.u_tx.get_samp_rate(), + gr.GR_CONST_WAVE, + 0, 1.0, 0) + + # Get dboard gain range and select maximum + tx_gain_range = self.u_tx.get_gain_range() + tx_gain = tx_gain_range.stop() + + # Get dboard freq range and select midpoint + tx_freq_range = self.u_tx.get_freq_range() + tx_freq_mid = (tx_freq_range.start() + tx_freq_range.stop())/2.0 + + for i in xrange(tx_nchan): + self.u_tx.set_center_freq (tx_freq_mid + i*1e6, i) + self.u_tx.set_gain(tx_gain, i) + + print "\nTx Sample Rate: %ssps" % (n2s(self.u_tx.get_samp_rate())) + for i in xrange(tx_nchan): + print "Tx Channel %d: " % (i) + print "\tFrequency = %sHz" % \ + (n2s(self.u_tx.get_center_freq(i))) + print "\tGain = %f dB" % (self.u_tx.get_gain(i)) + print "" + + self.connect (self.tx_src0, self.u_tx) + + if rx_enable: + print "\nRECEIVE CHAIN" + self.u_rx = uhd.usrp_source(device_addr=address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=rx_nchan) + self.rx_dst0 = gr.null_sink (gr.sizeof_gr_complex) + + self.u_rx.set_samp_rate(MAX_RATE) + + # Get dboard gain range and select maximum + rx_gain_range = self.u_rx.get_gain_range() + rx_gain = rx_gain_range.stop() + + # Get dboard freq range and select midpoint + rx_freq_range = self.u_rx.get_freq_range() + rx_freq_mid = (rx_freq_range.start() + rx_freq_range.stop())/2.0 + + for i in xrange(tx_nchan): + self.u_rx.set_center_freq (rx_freq_mid + i*1e6, i) + self.u_rx.set_gain(rx_gain, i) + + print "\nRx Sample Rate: %ssps" % (n2s(self.u_rx.get_samp_rate())) + for i in xrange(rx_nchan): + print "Rx Channel %d: " % (i) + print "\tFrequency = %sHz" % \ + (n2s(self.u_rx.get_center_freq(i))) + print "\tGain = %f dB" % (self.u_rx.get_gain(i)) + print "" + + self.connect (self.u_rx, self.rx_dst0) + +def main (): + parser = OptionParser (option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-t", action="store_true", dest="tx_enable", + default=False, help="enable Tx path") + parser.add_option("-r", action="store_true", dest="rx_enable", + default=False, help="enable Rx path") + (options, args) = parser.parse_args () + + tb = build_block (options.address, options.tx_enable, options.rx_enable) + + tb.start () + raw_input ('Press Enter to quit: ') + tb.stop () + +if __name__ == '__main__': + main () diff --git a/gr-uhd/examples/multi-antenna/.gitignore b/gr-uhd/examples/multi-antenna/.gitignore new file mode 100644 index 000000000..ff40c06f3 --- /dev/null +++ b/gr-uhd/examples/multi-antenna/.gitignore @@ -0,0 +1,11 @@ +/Makefile +/Makefile.in +/.la +/.lo +/.deps +/.libs +/*.la +/*.lo +/*.pyc +/*.pyo +/*.dat diff --git a/gr-uhd/examples/multi-antenna/Makefile.am b/gr-uhd/examples/multi-antenna/Makefile.am new file mode 100644 index 000000000..0cb944589 --- /dev/null +++ b/gr-uhd/examples/multi-antenna/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2006,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. +# + +include $(top_srcdir)/Makefile.common + +ourdatadir = $(exampledir)/multi-antenna + +dist_ourdata_SCRIPTS = \ + multi_fft.py \ + multi_file.py \ + multi_scope.py diff --git a/gr-uhd/examples/multi-antenna/multi_fft.py b/gr-uhd/examples/multi-antenna/multi_fft.py new file mode 100755 index 000000000..d4c878c84 --- /dev/null +++ b/gr-uhd/examples/multi-antenna/multi_fft.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. +# + +from gnuradio import gr, eng_notation +from gnuradio import uhd +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2 +from gnuradio.wxgui import scopesink2, form, slider +import wx +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + +class my_graph(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="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate (bandwidth) [default=%default]") + parser.add_option("-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("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + parser.add_option("-N", "--nchans", type="int", default=1, + help="set number of channels (default=%default)") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + self.nchans = options.nchans + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=self.nchans) + self.u.set_samp_rate(options.samp_rate) + input_rate = self.u.get_samp_rate() + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.u.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.u.get_freq_range() + options.freq = float(r.start()+r.stop())/2 + + self.set_gain(options.gain) + self.set_freq(options.freq) + + #if self.u.nddcs() < nchan: + # sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + # nchan, self.u.nddcs())) + # raise SystemExit + + #if (len (self.subdev) < 4 or + # self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX or + # self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX): + # sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + # sys.exit(1) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, di) + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + for i in range(self.nchans): + scope = fftsink2.fft_sink_c(panel, sample_rate=input_rate/sw_decim, + title="Input %d" % (i,), + ref_level=80, y_per_div=20) + vbox.Add(scope.win, 10, wx.EXPAND) + + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + self.connect((di, i), chan_filt, scope) + else: + self.connect((di, i), scope) + + def set_gain(self, gain): + for i in range(self.nchans): + self.u.set_gain(gain, i) + + + def set_freq(self, target_freq): + for i in range(self.nchans): + r = self.u.set_center_freq(target_freq, 0) + + if r: + return True + else: + print "set_freq: failed to set subdev[%d] freq to %f" % \ + (i, target_freq) + return False + +def main (): + app = stdgui2.stdapp(my_graph, "Multi Scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gr-uhd/examples/multi-antenna/multi_file.py b/gr-uhd/examples/multi-antenna/multi_file.py new file mode 100755 index 000000000..87d9085e3 --- /dev/null +++ b/gr-uhd/examples/multi-antenna/multi_file.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from usrpm import usrp_dbid +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + + +class my_graph(gr.top_block): + + def __init__(self): + gr.top_block.__init__(self) + + parser = OptionParser (option_class=eng_option) + #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ [default=%default])", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=20, + help="set gain in dB [default=%default]") + parser.add_option("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + parser.add_option("-o", "--output", type="string", default=None, + help="set output basename") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + if options.output is None: + parser.print_help() + sys.stderr.write("You must provide an output filename base with -o OUTPUT\n") + raise SystemExit + else: + basename = options.output + + nchan = 4 + nsecs = 4.0 + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") + if self.u.nddcs() < nchan: + sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + nchan, self.u.nddcs())) + raise SystemExit + + if not self.u.set_nchannels(nchan): + sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) + raise SystemExit + + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) + sink_data_rate = input_rate/sw_decim + print "Scope data rate = %s" % (eng_notation.num_to_str(sink_data_rate),) + + self.subdev = self.u.db(0) + self.u.db(1) + + if (len(self.subdev) < 4 or + self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX or + self.u.db(1, 0).dbid() != usrp_dbid.BASIC_RX): + sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + sys.exit(1) + + self.u.set_mux(gru.hexint(0xf3f2f1f0)) + + # collect 1 second worth of data + limit = int(nsecs * input_rate * nchan) + print "limit = ", limit + head = gr.head(gr.sizeof_gr_complex, limit) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, head, di) + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + for i in range(nchan): + + sink = gr.file_sink(gr.sizeof_gr_complex, + basename + ("-%s-%d.dat" % (eng_notation.num_to_str(sink_data_rate), i))) + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + self.connect((di, i), chan_filt, sink) + else: + self.connect((di, i), sink) + + + self.set_gain(options.gain) + self.set_freq(options.freq) + + def set_gain(self, gain): + for i in range(len(self.subdev)): + self.subdev[i].set_gain(gain) + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + +def main (): + my_graph().run() + +if __name__ == '__main__': + main () diff --git a/gr-uhd/examples/multi-antenna/multi_scope.py b/gr-uhd/examples/multi-antenna/multi_scope.py new file mode 100755 index 000000000..d1e28ad18 --- /dev/null +++ b/gr-uhd/examples/multi-antenna/multi_scope.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui2, fftsink2, waterfallsink2, scopesink2, form, slider +import wx +from usrpm import usrp_dbid +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + + +class my_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("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ [default=%default])", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=20, + help="set gain in dB [default=%default]") + parser.add_option("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + nchan = 4 + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") + if self.u.nddcs() < nchan: + sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + nchan, self.u.nddcs())) + raise SystemExit + + if not self.u.set_nchannels(nchan): + sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) + raise SystemExit + + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) + print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),) + + self.subdev = self.u.db(0) + self.u.db(1) + + if (len(self.subdev) < 4 or + self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX or + self.u.db(0, 0).dbid() != usrp_dbid.BASIC_RX): + sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + sys.exit(1) + + self.u.set_mux(gru.hexint(0xf3f2f1f0)) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, di) + + # our destination (8 float inputs) + self.scope = scopesink2.scope_sink_f(panel, sample_rate=input_rate/sw_decim, + num_inputs=2*nchan) + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + # bust the deinterleaved complex channels into floats + for i in range(nchan): + + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + c2f = gr.complex_to_float() + self.connect((di, i), chan_filt, c2f) + else: + c2f = gr.complex_to_float() + self.connect((di, i), c2f) + + self.connect((c2f, 0), (self.scope, 2*i + 0)) + self.connect((c2f, 1), (self.scope, 2*i + 1)) + + + self._build_gui(vbox) + + self.set_gain(options.gain) + self.set_freq(options.freq) + + def set_gain(self, gain): + for i in range(len(self.subdev)): + self.subdev[i].set_gain(gain) + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + + def _build_gui(self, vbox): + vbox.Add(self.scope.win, 10, wx.EXPAND) + + + +def main (): + app = stdgui2.stdapp(my_top_block, "Multi Scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gr-uhd/examples/usrp_am_mw_rcv.py b/gr-uhd/examples/usrp_am_mw_rcv.py new file mode 100755 index 000000000..b9132e45a --- /dev/null +++ b/gr-uhd/examples/usrp_am_mw_rcv.py @@ -0,0 +1,316 @@ +#!/usr/bin/env python +# +# Copyright 2005-2007,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, eng_notation, optfir +from gnuradio import audio +from gnuradio import uhd +from gnuradio import blks2 +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import slider, powermate +from gnuradio.wxgui import stdgui2, fftsink2, form +from optparse import OptionParser +from usrpm import usrp_dbid +import sys +import math +import wx + +class wfm_rx_block (stdgui2.std_top_block): + def __init__(self, frame, panel, vbox, argv): + stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv) + + parser=OptionParser(option_class=eng_option) + parser.add_option("-a", "--address", type="string", + default="addr=192.168.10.2", + help="Address of UHD device, [default=%default]") + parser.add_option("-A", "--antenna", type="string", default=None, + help="select Rx Antenna where appropriate") + parser.add_option("-s", "--samp-rate", type="eng_float", default=1e6, + help="set sample rate (bandwidth) [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=1008.0e3, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-I", "--use-if-freq", action="store_true", default=False, + help="use intermediate freq (compensates DC problems in quadrature boards)" ) + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is maximum)") + parser.add_option("-V", "--volume", type="eng_float", default=None, + help="set volume (default is midpoint)") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.frame = frame + self.panel = panel + self.use_IF=options.use_if_freq + if self.use_IF: + self.IF_freq=64000.0 + else: + self.IF_freq=0.0 + + self.vol = 0 + self.state = "FREQ" + self.freq = 0 + + # build graph + + #TODO: add an AGC after the channel filter and before the AM_demod + + self.u = uhd.usrp_source(device_addr=options.address, + io_type=uhd.io_type.COMPLEX_FLOAT32, + num_channels=1) + + usrp_rate = 256e3 + self.u.set_samp_rate(usrp_rate) + usrp_rate = self.u.get_samp_rate() + + chanfilt_decim = 4 + demod_rate = usrp_rate / chanfilt_decim # 64 kHz + audio_decimation = 2 + audio_rate = demod_rate / audio_decimation # 32 kHz + + chan_filt_coeffs = gr.firdes.low_pass_2 (1, # gain + usrp_rate, # sampling rate + 8e3, # passband cutoff + 4e3, # transition bw + 60) # stopband attenuation + + #print len(chan_filt_coeffs) + self.chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + + if self.use_IF: + # Turn If to baseband and filter. + self.chan_filt = gr.freq_xlating_fir_filter_ccf (chanfilt_decim, + chan_filt_coeffs, + self.IF_freq, + usrp_rate) + else: + self.chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + self.am_demod = gr.complex_to_mag() + + self.volume_control = gr.multiply_const_ff(self.vol) + + audio_filt_coeffs = gr.firdes.low_pass_2 (1, # gain + demod_rate, # sampling rate + 8e3, # passband cutoff + 2e3, # transition bw + 60) # stopband attenuation + + self.audio_filt=gr.fir_filter_fff(audio_decimation,audio_filt_coeffs) + # sound card as final sink + self.audio_sink = audio.sink (int (audio_rate), + options.audio_output, + False) # ok_to_block + + # now wire it all together + self.connect (self.u, self.chan_filt, self.am_demod, + self.audio_filt, self.volume_control, + self.audio_sink) + + self._build_gui(vbox, usrp_rate, demod_rate, audio_rate) + + if options.gain is None: + g = self.u.get_gain_range() + if True: + # if no gain was specified, use the mid gain + options.gain = (g.start() + g.stop())/2.0 + + if options.volume is None: + v = self.volume_range() + options.volume = float(v[0]*3+v[1])/4.0 + + if abs(options.freq) < 1e3: + options.freq *= 1e3 + + # set initial values + + self.set_gain(options.gain) + self.set_vol(options.volume) + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + if(options.antenna): + self.u.set_antenna(options.antenna, 0) + + def _set_status_msg(self, msg, which=0): + self.frame.GetStatusBar().SetStatusText(msg, which) + + + def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + + if 1: + self.src_fft = fftsink2.fft_sink_c(self.panel, title="Data from USRP", + fft_size=512, sample_rate=usrp_rate, + ref_scale=32768.0, ref_level=0.0, y_divs=12) + self.connect (self.u, self.src_fft) + vbox.Add (self.src_fft.win, 4, wx.EXPAND) + + if 0: + self.post_filt_fft = fftsink2.fft_sink_c(self.panel, title="Post Channel filter", + fft_size=512, sample_rate=demod_rate) + self.connect (self.chan_filt, self.post_filt_fft) + vbox.Add (self.post_filt_fft.win, 4, wx.EXPAND) + + if 0: + post_demod_fft = fftsink2.fft_sink_f(self.panel, title="Post Demod", + fft_size=1024, sample_rate=demod_rate, + y_per_div=10, ref_level=0) + self.connect (self.am_demod, post_demod_fft) + vbox.Add (post_demod_fft.win, 4, wx.EXPAND) + + if 1: + audio_fft = fftsink2.fft_sink_f(self.panel, title="Audio", + fft_size=512, sample_rate=audio_rate, + y_per_div=10, ref_level=20) + self.connect (self.audio_filt, audio_fft) + vbox.Add (audio_fft.win, 4, wx.EXPAND) + + + # control area form at bottom + self.myform = myform = form.form() + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0) + myform['freq_slider'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3, + range=(520.0e3, 1611.0e3, 1.0e3), + callback=self.set_freq) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + + myform['volume'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume", + weight=3, range=self.volume_range(), + callback=self.set_vol) + hbox.Add((5,0), 1) + + g = self.u.get_gain_range() + myform['gain'] = \ + form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, range=(g.start(), g.stop(), g.step()), + callback=self.set_gain) + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + try: + self.knob = powermate.powermate(self.frame) + self.rot = 0 + powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate) + powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button) + except: + print "FYI: No Powermate or Contour Knob found" + + + def on_rotate (self, event): + self.rot += event.delta + if (self.state == "FREQ"): + if self.rot >= 3: + self.set_freq(self.freq + .1e6) + self.rot -= 3 + elif self.rot <=-3: + self.set_freq(self.freq - .1e6) + self.rot += 3 + else: + step = self.volume_range()[2] + if self.rot >= 3: + self.set_vol(self.vol + step) + self.rot -= 3 + elif self.rot <=-3: + self.set_vol(self.vol - step) + self.rot += 3 + + def on_button (self, event): + if event.value == 0: # button up + return + self.rot = 0 + if self.state == "FREQ": + self.state = "VOL" + else: + self.state = "FREQ" + self.update_status_bar () + + + def set_vol (self, vol): + g = self.volume_range() + self.vol = max(g[0], min(g[1], vol)) + self.volume_control.set_k(10**(self.vol/10)) + self.myform['volume'].set_value(self.vol) + self.update_status_bar () + + 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.u.set_center_freq(target_freq + self.IF_freq, 0) + + if r: + self.freq = target_freq + self.myform['freq'].set_value(target_freq) # update displayed value + self.myform['freq_slider'].set_value(target_freq) # update displayed value + self.update_status_bar() + self._set_status_msg("OK", 0) + return True + + self._set_status_msg("Failed", 0) + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.u.set_gain(gain) + + def update_status_bar (self): + msg = "Volume:%r Setting:%s" % (self.vol, self.state) + self._set_status_msg(msg, 1) + try: + self.src_fft.set_baseband_freq(self.freq) + except: + None + + def volume_range(self): + return (-40.0, 0.0, 0.5) + + +if __name__ == '__main__': + app = stdgui2.stdapp (wfm_rx_block, "USRP Broadcast AM MW RX") + app.MainLoop () |