diff options
author | eb | 2006-09-27 05:14:03 +0000 |
---|---|---|
committer | eb | 2006-09-27 05:14:03 +0000 |
commit | f1c41f807cb29472d0924149e39d6ec8ad90e6a2 (patch) | |
tree | 47e42f8cdfc83aaa3b706e06862c3efa4ba16745 /gnuradio-examples/python | |
parent | 04bb51ec4f1539c51c861b7fcad2ca8047a872a3 (diff) | |
download | gnuradio-f1c41f807cb29472d0924149e39d6ec8ad90e6a2.tar.gz gnuradio-f1c41f807cb29472d0924149e39d6ec8ad90e6a2.tar.bz2 gnuradio-f1c41f807cb29472d0924149e39d6ec8ad90e6a2.zip |
Merged changes from eb/digital-wip into trunk.
This includes:
* renaming gnuradio-examples/python/gmsk2 to gnuradio-examples/python/digital
* refactoring the digital data tx and rx test code into benchmark_tx
and benchmark_rx. These accept a -m <modulation> argument.
<modulation> can currently be selected from gmsk, dbpsk, dqpsk
* Two new AGC blocks: gr_agc2: separate attack and delay rates;
gr_feedforward_agc: FIR-ish compressor. Normalizes to peak envelope.
* Working DBPSK mod/demod (works fine)
* Working DQPSK mod/demod (works, but still needs more work)
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3662 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gnuradio-examples/python')
32 files changed, 965 insertions, 1973 deletions
diff --git a/gnuradio-examples/python/Makefile.am b/gnuradio-examples/python/Makefile.am index f548eff34..49d2ba3a8 100644 --- a/gnuradio-examples/python/Makefile.am +++ b/gnuradio-examples/python/Makefile.am @@ -19,4 +19,4 @@ # Boston, MA 02110-1301, USA. # -SUBDIRS = audio channel-coding digital_voice gmsk2 mc4020 multi_usrp usrp +SUBDIRS = audio channel-coding digital_voice digital multi_usrp usrp diff --git a/gnuradio-examples/python/gmsk2/Makefile.am b/gnuradio-examples/python/digital/Makefile.am index 9c5c88dc7..ad2fa4d68 100644 --- a/gnuradio-examples/python/gmsk2/Makefile.am +++ b/gnuradio-examples/python/digital/Makefile.am @@ -21,17 +21,13 @@ EXTRA_DIST = \ README \ - benchmark_gmsk_rx.py \ - benchmark_gmsk_tx.py \ - benchmark_mpsk_rx.py \ - benchmark_mpsk_tx.py \ + benchmark_rx.py \ + benchmark_tx.py \ fusb_options.py \ gen_whitener.py \ - gmsk_test.py \ pick_bitrate.py \ receive_path.py \ - transmit_path.py - - - - + rx_voice.py \ + transmit_path.py \ + tunnel.py \ + tx_voice.py diff --git a/gnuradio-examples/python/gmsk2/README b/gnuradio-examples/python/digital/README index b3c343e4b..adc3fe078 100644 --- a/gnuradio-examples/python/gmsk2/README +++ b/gnuradio-examples/python/digital/README @@ -1,20 +1,16 @@ Quick overview of what's here: -* gmsk_test.py: stand-alone program that exercises the GMSK packet tx -and rx code. The two halves are connected with a simulated noisy -channel. It's easy to add extra instrumentation to log various internal -states. We used a variant of this code to get this working in the -first place. - -* benchmark_gmsk_tx.py: generates packets of the size you +* benchmark_tx.py: generates packets of the size you specify and sends them across the air using the USRP. Known to work -well using the USRP with the Flex 400 transceiver daughterboard. +well using the USRP with the RFX transceiver daughterboards. You can specify the bitrate to use with the -r <bitrate> command line parameter. The default is 500k. Some machines will do 1M or more. +You can select the modulation to use with the -m <modulation> command +line argument. The legal values for <modulation> are gmsk, dbpsk and dqpsk. -* benchmark_gmsk_rx.py: the receiver half of benchmark_gmsk_tx.py. -Command line arguments are pretty much the same as tx. Works well -with a USRP and Flex 400 transceiver daughterboard. Will also work +* benchmark_tx.py: the receiver half of benchmark_tx.py. +Command line arguments are pretty much the same as rx. Works well +with a USRP and RFX transceiver daughterboards. Will also work with TVRX daugherboard, but you'll need to fiddle with the gain. See below. Prints a summary of each packet received and keeps a running total of packets received, and how many of them were error free. @@ -24,8 +20,8 @@ get an output line. If the CRC32 of the payload was correct you get "ok = True", else "ok = False". The "pktno" is extracted from the received packet. If there are skipped numbers, you're missing some packets. Be sure you've got a suitable antenna connected to the TX/RX -port on each board. A "70 cm" / 420 MHz antenna for a ham -handi-talkie works great. These are available at ham radio supplies, +port on each board. For the RFX-400, "70 cm" / 420 MHz antennas for ham +handi-talkies work great. These are available at ham radio supplies, etc. The boards need to be at least 3m apart. You can also try experimenting with the rx gain (-g <gain> command line option). @@ -56,7 +52,7 @@ On machine A: $ su # ./tunnel.py --freq 423.0M --bitrate 500k # # in another window on A, also as root... - # ifconfig gr0 10.10.10.1 + # ifconfig gr0 192.168.200.1 On machine B: @@ -64,18 +60,18 @@ On machine B: $ su # ./tunnel.py --freq 423.0M --bitrate 500k # # in another window on B, also as root... - # ifconfig gr0 10.10.10.2 + # ifconfig gr0 192.168.200.2 Now, on machine A you shold be able to ping machine B: - $ ping 10.10.10.2 + $ ping 192.168.200.2 and you should see some output for each packet in the tunnel.py window if you used the -v option. Likewise, on machine B: - $ ping 10.10.10.1 + $ ping 192.168.200.1 This now uses a carrier sense MAC, so you should be able to ssh between the machines, web browse, etc. diff --git a/gnuradio-examples/python/digital/benchmark_rx.py b/gnuradio-examples/python/digital/benchmark_rx.py new file mode 100755 index 000000000..26ccdac47 --- /dev/null +++ b/gnuradio-examples/python/digital/benchmark_rx.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 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 2, 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, modulation_utils +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import struct +import sys + +# from current dir +from receive_path import receive_path +import fusb_options + +#import os +#print os.getpid() +#raw_input('Attach and press enter: ') + + +class my_graph(gr.flow_graph): + + def __init__(self, demod_class, rx_callback, options): + gr.flow_graph.__init__(self) + self.rxpath = receive_path(self, demod_class, rx_callback, options) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + (pktno,) = struct.unpack('!H', payload[0:2]) + n_rcvd += 1 + if ok: + n_right += 1 + + print "ok = %5s pktno = %4d n_rcvd = %4d n_right = %4d" % ( + ok, pktno, n_rcvd, n_right) + + + demods = modulation_utils.type_1_demods() + + # Create Options Parser: + parser = OptionParser (option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), + default='gmsk', + help="Select modulation from: %s [default=%%default]" + % (', '.join(demods.keys()),)) + + receive_path.add_options(parser, expert_grp) + + for mod in demods.values(): + mod.add_options(expert_grp) + + fusb_options.add_options(expert_grp) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help(sys.stderr) + sys.exit(1) + + if options.rx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) + + + # build the graph + fg = my_graph(demods[options.modulation], rx_callback, options) + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: Failed to enable realtime scheduling." + + fg.start() # start flow graph + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/digital/benchmark_tx.py b/gnuradio-examples/python/digital/benchmark_tx.py new file mode 100755 index 000000000..55f309322 --- /dev/null +++ b/gnuradio-examples/python/digital/benchmark_tx.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# Copyright 2005, 2006 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 2, 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, modulation_utils +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, time, struct, sys + +# from current dir +from transmit_path import transmit_path +import fusb_options + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + def __init__(self, modulator_class, options): + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, modulator_class, options) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + mods = modulation_utils.type_1_mods() + + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + default='gmsk', + help="Select modulation from: %s [default=%%default]" + % (', '.join(mods.keys()),)) + + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + + transmit_path.add_options(parser, expert_grp) + + for mod in mods.values(): + mod.add_options(expert_grp) + + fusb_options.add_options(expert_grp) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.tx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) + + # build the graph + fg = my_graph(mods[options.modulation], options) + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + fg.start() # start flow graph + + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + pkt_size = int(options.size) + + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/fusb_options.py b/gnuradio-examples/python/digital/fusb_options.py index cdb15d72b..cdb15d72b 100644 --- a/gnuradio-examples/python/gmsk2/fusb_options.py +++ b/gnuradio-examples/python/digital/fusb_options.py diff --git a/gnuradio-examples/python/gmsk2/gen_whitener.py b/gnuradio-examples/python/digital/gen_whitener.py index 93aea2b82..93aea2b82 100755 --- a/gnuradio-examples/python/gmsk2/gen_whitener.py +++ b/gnuradio-examples/python/digital/gen_whitener.py diff --git a/gnuradio-examples/python/digital/limbo/README b/gnuradio-examples/python/digital/limbo/README new file mode 100644 index 000000000..fe48f4358 --- /dev/null +++ b/gnuradio-examples/python/digital/limbo/README @@ -0,0 +1,12 @@ +Files in here are in various states of disrepair and/or have been +superceded by revised code in the directory above. + +They're here until we figure out what to do with them. + + +* gmsk_test.py: stand-alone program that exercises the GMSK packet tx +and rx code. The two halves are connected with a simulated noisy +channel. It's easy to add extra instrumentation to log various internal +states. We used a variant of this code to get this working in the +first place. + diff --git a/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py b/gnuradio-examples/python/digital/limbo/benchmark_gmsk_rx.py index f511e334c..0e072d0f6 100755 --- a/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py +++ b/gnuradio-examples/python/digital/limbo/benchmark_gmsk_rx.py @@ -97,7 +97,7 @@ def main(): demod_kwargs = { } # placeholder # build the graph - fg = my_graph(blks.gmsk2_demod, + fg = my_graph(blks.gmsk_demod, options.rx_subdev_spec, options.bitrate, options.decim, options.spb, rx_callback, options, demod_kwargs) diff --git a/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py b/gnuradio-examples/python/digital/limbo/benchmark_gmsk_tx.py index 36bced29b..ec78d24b9 100755 --- a/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py +++ b/gnuradio-examples/python/digital/limbo/benchmark_gmsk_tx.py @@ -39,16 +39,11 @@ import fusb_options #print os.getpid() #raw_input('Attach and press enter') - class my_graph(gr.flow_graph): - def __init__(self, mod_class, tx_subdev_spec, - bitrate, interp_rate, spb, gain, - options, mod_kwargs): + def __init__(self, options, mod_kwargs): gr.flow_graph.__init__(self) - self.txpath = transmit_path(self, mod_class, tx_subdev_spec, - bitrate, interp_rate, spb, gain, - options, mod_kwargs) + self.txpath = transmit_path(self, options, mod_kwargs) # ///////////////////////////////////////////////////////////////////////////// @@ -71,7 +66,7 @@ def main(): metavar="FREQ") parser.add_option("-r", "--bitrate", type="eng_float", default=None, help="specify bitrate. spb and interp will be derived.") - parser.add_option("-S", "--spb", type="int", default=None, + parser.add_option("-S", "--spb", type="int", default=2, help="set samples/baud [default=%default]") parser.add_option("-i", "--interp", type="intx", default=None, help="set fpga interpolation rate to INTERP [default=%default]") @@ -97,16 +92,21 @@ def main(): pkt_size = int(options.size) + # Add gmsk_mod modulator class to options list + options.modulation = getattr(blks, "gmsk_mod") + + # Add GMSK modulator's properties mod_kwargs = { + 'spb': options.spb, 'bt' : options.bt, + 'verbose' : False, + 'debug' : False, } - + # build the graph - fg = my_graph(blks.gmsk2_mod, options.tx_subdev_spec, - options.bitrate, options.interp, options.spb, options.gain, - options, mod_kwargs) + fg = my_graph(options, mod_kwargs) - print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "bitrate: %sbps" % (eng_notation.num_to_str(fg.txpath.bitrate()),) print "spb: %3d" % (fg.txpath.spb(),) print "interp: %3d" % (fg.txpath.interp(),) @@ -114,10 +114,14 @@ def main(): if not ok: print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),) raise SystemExit + else: + print "Transmitting on frequency %s" % (eng_notation.num_to_str(options.freq)) r = gr.enable_realtime_scheduling() if r != gr.RT_OK: print "Warning: failed to enable realtime scheduling" + else: + print "Started realtime scheduling" fg.start() # start flow graph diff --git a/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py b/gnuradio-examples/python/digital/limbo/benchmark_mpsk_rx.py index 9bb70106f..9bb70106f 100755 --- a/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py +++ b/gnuradio-examples/python/digital/limbo/benchmark_mpsk_rx.py diff --git a/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py b/gnuradio-examples/python/digital/limbo/benchmark_mpsk_tx.py index 2808f1d5c..ec08fb680 100755 --- a/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py +++ b/gnuradio-examples/python/digital/limbo/benchmark_mpsk_tx.py @@ -29,9 +29,6 @@ from optparse import OptionParser import random, time, struct, sys # from current dir -from bpsk import bpsk_mod -from dbpsk import dbpsk_mod -from dqpsk import dqpsk_mod from transmit_path import transmit_path import fusb_options @@ -42,13 +39,9 @@ import fusb_options class my_graph(gr.flow_graph): - def __init__(self, mod_class, tx_subdev_spec, - bitrate, interp_rate, spb, gain, - options, mod_kwargs): + def __init__(self, options, mod_kwargs): gr.flow_graph.__init__(self) - self.txpath = transmit_path(self, mod_class, tx_subdev_spec, - bitrate, interp_rate, spb, gain, - options, mod_kwargs) + self.txpath = transmit_path(self, options, mod_kwargs) # ///////////////////////////////////////////////////////////////////////////// @@ -71,22 +64,26 @@ def main(): metavar="FREQ") parser.add_option("-r", "--bitrate", type="eng_float", default=None, help="specify bitrate. spb and interp will be derived.") - parser.add_option("-S", "--spb", type="int", default=None, + parser.add_option("-S", "--spb", type="int", default=2, help="set samples/baud [default=%default]") parser.add_option("-i", "--interp", type="intx", default=None, help="set fpga interpolation rate to INTERP [default=%default]") parser.add_option("-s", "--size", type="eng_float", default=1500, help="set packet size [default=%default]") - parser.add_option("-m", "--modulation", type="string", default='dbpsk', - help="modulation type (bpsk, dbpsk, dqpsk) [default=%default]") - parser.add_option("", "--excess-bw", type="float", default=0.3, - help="set RRC excess bandwith factor [default=%default]") parser.add_option("-g", "--gain", type="eng_float", default=100.0, help="transmitter gain [default=%default]") parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, help="set megabytes to transmit [default=%default]") parser.add_option("","--discontinuous", action="store_true", default=False, help="enable discontinous transmission (bursts of 5 packets)") + + parser.add_option("-m", "--modulation", type="string", default='dbpsk', + help="modulation type (bpsk, dbpsk, dqpsk) [default=%default]") + parser.add_option("", "--excess-bw", type="float", default=0.3, + help="set RRC excess bandwith factor [default=%default]") + parser.add_option("", "--no-gray-code", action="store_false", default=True, + help="Don't use gray coding on modulated bits [default=%default]") + fusb_options.add_options(parser) (options, args) = parser.parse_args () @@ -99,23 +96,20 @@ def main(): pkt_size = int(options.size) + # Add PSK modulator class to options list + options.modulation = getattr(blks, options.modulation + "_mod") + + # Add PSK modulator's properties mod_kwargs = { + 'spb' : options.spb, 'excess_bw' : options.excess_bw, + 'gray_code' : options.no_gray_code, + 'verbose' : False, + 'debug' : False, } - - #FIXME: rework when static class defintions are ready for the modulation types - if(options.modulation=='bpsk'): - modulation=bpsk_mod - elif( options.modulation=='dbpsk'): - modulation=dbpsk_mod - else: - modulation=dqpsk_mod - + # build the graph - fg = my_graph(modulation, - options.tx_subdev_spec, options.bitrate, options.interp, - options.spb, options.gain, - options, mod_kwargs) + fg = my_graph(options, mod_kwargs) print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) print "spb: %3d" % (fg.txpath.spb(),) diff --git a/gnuradio-examples/python/gmsk2/gmsk_test.py b/gnuradio-examples/python/digital/limbo/gmsk_test.py index 7ae69a0a9..7ae69a0a9 100755 --- a/gnuradio-examples/python/gmsk2/gmsk_test.py +++ b/gnuradio-examples/python/digital/limbo/gmsk_test.py diff --git a/gnuradio-examples/python/gmsk2/mpsk_test.py b/gnuradio-examples/python/digital/limbo/mpsk_test.py index 1f257d9c5..1f257d9c5 100755 --- a/gnuradio-examples/python/gmsk2/mpsk_test.py +++ b/gnuradio-examples/python/digital/limbo/mpsk_test.py diff --git a/gnuradio-examples/python/gmsk2/qpsk_tester.py b/gnuradio-examples/python/digital/limbo/qpsk_tester.py index ea7bae2eb..ea7bae2eb 100644 --- a/gnuradio-examples/python/gmsk2/qpsk_tester.py +++ b/gnuradio-examples/python/digital/limbo/qpsk_tester.py diff --git a/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py b/gnuradio-examples/python/digital/limbo/qpsk_usrp_tester.py index bf7698a2b..bf7698a2b 100644 --- a/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py +++ b/gnuradio-examples/python/digital/limbo/qpsk_usrp_tester.py diff --git a/gnuradio-examples/python/gmsk2/pick_bitrate.py b/gnuradio-examples/python/digital/pick_bitrate.py index 35074f1dc..42aefa94e 100644 --- a/gnuradio-examples/python/gmsk2/pick_bitrate.py +++ b/gnuradio-examples/python/digital/pick_bitrate.py @@ -1,5 +1,5 @@ # -# Copyright 2005 Free Software Foundation, Inc. +# Copyright 2005,2006 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,36 +21,36 @@ _default_bitrate = 500e3 -_valid_spbs = (2,3,4,5,6,7) +_valid_samples_per_symbol = (2,3,4,5,6,7) def _gen_tx_info(converter_rate): results = [] - for spb in _valid_spbs: + for samples_per_symbol in _valid_samples_per_symbol: for interp in range(16, 512 + 1, 4): - bitrate = converter_rate / interp / spb - results.append((bitrate, spb, interp)) + bitrate = converter_rate / interp / samples_per_symbol + results.append((bitrate, samples_per_symbol, interp)) results.sort() return results def _gen_rx_info(converter_rate): results = [] - for spb in _valid_spbs: + for samples_per_symbol in _valid_samples_per_symbol: for decim in range(8, 256 + 1, 2): - bitrate = converter_rate / decim / spb - results.append((bitrate, spb, decim)) + bitrate = converter_rate / decim / samples_per_symbol + results.append((bitrate, samples_per_symbol, decim)) results.sort() return results -def _filter_info(info, samples_per_baud, xrate): - if samples_per_baud is not None: - info = [x for x in info if x[1] == samples_per_baud] +def _filter_info(info, samples_per_symbol, xrate): + if samples_per_symbol is not None: + info = [x for x in info if x[1] == samples_per_symbol] if xrate is not None: info = [x for x in info if x[2] == xrate] return info def _pick_best(target_bitrate, bits_per_symbol, info): """ - @returns tuple (bitrate, samples_per_baud, interp_rate_or_decim_rate) + @returns tuple (bitrate, samples_per_symbol, interp_rate_or_decim_rate) """ if len(info) == 0: raise RuntimeError, "info is zero length!" @@ -62,7 +62,7 @@ def _pick_best(target_bitrate, bits_per_symbol, info): target_symbolrate = target_bitrate / bits_per_symbol # Find the closest matching symbol rate. - # In the event of a tie, the one with the lowest samples_per_baud wins. + # In the event of a tie, the one with the lowest samples_per_symbol wins. # (We already sorted them, so the first one is the one we take) best = info[0] @@ -76,30 +76,30 @@ def _pick_best(target_bitrate, bits_per_symbol, info): # convert symbol rate back to bit rate return ((best[0] * bits_per_symbol),) + best[1:] -def _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, +def _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, xrate, converter_rate, gen_info): """ - @returns tuple (bitrate, samples_per_baud, interp_rate_or_decim_rate) + @returns tuple (bitrate, samples_per_symbol, interp_rate_or_decim_rate) """ if not isinstance(bits_per_symbol, int) or bits_per_symbol < 1: raise ValueError, "bits_per_symbol must be an int >= 1" - if samples_per_baud is not None and xrate is not None: # completely determined - return (float(converter_rate) / xrate / samples_per_baud, - samples_per_baud, xrate) + if samples_per_symbol is not None and xrate is not None: # completely determined + return (float(converter_rate) / xrate / samples_per_symbol, + samples_per_symbol, xrate) - if bitrate is None and samples_per_baud is None and xrate is None: + if bitrate is None and samples_per_symbol is None and xrate is None: bitrate = _default_bitrate # now we have a target bitrate and possibly an xrate or - # samples_per_baud constraint, but not both of them. + # samples_per_symbol constraint, but not both of them. return _pick_best(bitrate, bits_per_symbol, - _filter_info(gen_info(converter_rate), samples_per_baud, xrate)) + _filter_info(gen_info(converter_rate), samples_per_symbol, xrate)) # --------------------------------------------------------------------------------------- -def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_baud, +def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_symbol, interp_rate, converter_rate=128e6): """ Given the 4 input parameters, return at configuration that matches @@ -108,20 +108,20 @@ def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_baud, @type bitrate: number or None @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 @type bits_per_symbol: integer >= 1 - @param samples_per_baud: samples/baud (aka samples/symbol) - @type samples_per_baud: number or None + @param samples_per_symbol: samples/baud (aka samples/symbol) + @type samples_per_symbol: number or None @param interp_rate: USRP interpolation factor @type interp_rate: integer or None @param converter_rate: converter sample rate in Hz @type converter_rate: number - @returns tuple (bitrate, samples_per_baud, interp_rate) + @returns tuple (bitrate, samples_per_symbol, interp_rate) """ - return _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, interp_rate, converter_rate, _gen_tx_info) -def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_baud, +def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_symbol, decim_rate, converter_rate=64e6): """ Given the 4 input parameters, return at configuration that matches @@ -130,14 +130,14 @@ def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_baud, @type bitrate: number or None @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 @type bits_per_symbol: integer >= 1 - @param samples_per_baud: samples/baud (aka samples/symbol) - @type samples_per_baud: number or None + @param samples_per_symbol: samples/baud (aka samples/symbol) + @type samples_per_symbol: number or None @param decim_rate: USRP decimation factor @type decim_rate: integer or None @param converter_rate: converter sample rate in Hz @type converter_rate: number - @returns tuple (bitrate, samples_per_baud, decim_rate) + @returns tuple (bitrate, samples_per_symbol, decim_rate) """ - return _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, decim_rate, converter_rate, _gen_rx_info) diff --git a/gnuradio-examples/python/digital/receive_path.py b/gnuradio-examples/python/digital/receive_path.py new file mode 100644 index 000000000..9d55c88dd --- /dev/null +++ b/gnuradio-examples/python/digital/receive_path.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 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 2, 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, blks +from gnuradio import usrp +from gnuradio import eng_notation +import copy +import sys + +# from current dir +from pick_bitrate import pick_rx_bitrate + +# ///////////////////////////////////////////////////////////////////////////// +# receive path +# ///////////////////////////////////////////////////////////////////////////// + +class receive_path(gr.hier_block): + def __init__(self, fg, demod_class, rx_callback, options): + + options = copy.copy(options) # make a copy so we can destructively modify + + self._verbose = options.verbose + self._rx_freq = options.rx_freq # receiver's center frequency + self._rx_gain = options.rx_gain # receiver's gain + self._rx_subdev_spec = options.rx_subdev_spec # daughterboard to use + self._bitrate = options.bitrate # desired bit rate + self._decim = options.decim # Decimating rate for the USRP (prelim) + self._samples_per_symbol = options.samples_per_symbol # desired samples/symbol + self._fusb_block_size = options.fusb_block_size # usb info for USRP + self._fusb_nblocks = options.fusb_nblocks # usb info for USRP + + self._rx_callback = rx_callback # this callback is fired when there's a packet available + self._demod_class = demod_class # the demodulator_class we're using + + if self._rx_freq is None: + sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n") + raise SystemExit + + # Set up USRP source; also adjusts decim, samples_per_symbol, and bitrate + self._setup_usrp_source() + + # copy the final answers back into options for use by demodulator + options.samples_per_symbol = self._samples_per_symbol + options.bitrate = self._bitrate + options.decim = self._decim + + # Get demod_kwargs + demod_kwargs = self._demod_class.extract_kwargs_from_options(options) + + # Design filter to get actual channel we want + sw_decim = 1 + chan_coeffs = gr.firdes.low_pass (1.0, # gain + sw_decim * self._samples_per_symbol, # sampling rate + 1.0, # midpoint of trans. band + 0.1, # width of trans. band + gr.firdes.WIN_HANN) # filter type + + # Decimating channel filter + # complex in and out, float taps + self.chan_filt = gr.fft_filter_ccc(sw_decim, chan_coeffs) + #self.chan_filt = gr.fir_filter_ccf(sw_decim, chan_coeffs) + + # receiver + self.packet_receiver = \ + blks.demod_pkts(fg, + self._demod_class(fg, **demod_kwargs), + access_code=None, + callback=self._rx_callback, + threshold=-1) + + ok = self.set_freq(self._rx_freq) + if not ok: + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(self._rx_freq)) + raise ValueError, eng_notation.num_to_str(self._rx_freq) + + g = self.subdev.gain_range() + if options.show_rx_gain_range: + print "Rx Gain Range: minimum = %g, maximum = %g, step size = %g" \ + % (g[0], g[1], g[2]) + + self.set_gain(options.rx_gain) + + self.set_auto_tr(True) # enable Auto Transmit/Receive switching + + # Carrier Sensing Blocks + alpha = 0.001 + thresh = 30 # in dB, will have to adjust + self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha) + fg.connect(self.chan_filt, self.probe) + + # Display some information about the setup + if self._verbose: + self._print_verbage() + + fg.connect(self.u, self.chan_filt, self.packet_receiver) + gr.hier_block.__init__(self, fg, None, None) + + def _setup_usrp_source(self): + self.u = usrp.source_c (fusb_block_size=self._fusb_block_size, + fusb_nblocks=self._fusb_nblocks) + adc_rate = self.u.adc_rate() + + # derive values of bitrate, samples_per_symbol, and decim from desired info + (self._bitrate, self._samples_per_symbol, self._decim) = \ + pick_rx_bitrate(self._bitrate, self._demod_class.bits_per_symbol(), \ + self._samples_per_symbol, self._decim, adc_rate) + + self.u.set_decim_rate(self._decim) + + # determine the daughterboard subdevice we're using + if self._rx_subdev_spec is None: + self._rx_subdev_spec = usrp.pick_rx_subdevice(self.u) + self.subdev = usrp.selected_subdev(self.u, self._rx_subdev_spec) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, self._rx_subdev_spec)) + + 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. + """ + r = self.u.tune(0, self.subdev, target_freq) + if r: + return True + + return False + + def set_gain(self, gain): + """ + Sets the analog gain in the USRP + """ + if gain is None: + r = self.subdev.gain_range() + gain = (r[0] + r[1])/2 # set gain to midpoint + self.gain = gain + return self.subdev.set_gain(gain) + + def set_auto_tr(self, enable): + return self.subdev.set_auto_tr(enable) + + def bitrate(self): + return self._bitrate + + def samples_per_symbol(self): + return self._samples_per_symbol + + def decim(self): + return self._decim + + def carrier_sensed(self): + """ + Return True if we think carrier is present. + """ + #return self.probe.level() > X + return self.probe.unmuted() + + def carrier_threshold(self): + """ + Return current setting in dB. + """ + return self.probe.threshold() + + def set_carrier_threshold(self, threshold_in_db): + """ + Set carrier threshold. + + @param threshold_in_db: set detection threshold + @type threshold_in_db: float (dB) + """ + self.probe.set_threshold(threshold_in_db) + + + def add_options(normal, expert): + """ + Adds receiver-specific options to the Options Parser + """ + add_freq_option(normal) + if not normal.has_option("--bitrate"): + normal.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. samples-per-symbol and interp/decim will be derived.") + normal.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + normal.add_option("", "--rx-gain", type="eng_float", default=None, metavar="GAIN", + help="set receiver gain in dB [default=midpoint]. See also --show-rx-gain-range") + normal.add_option("", "--show-rx-gain-range", action="store_true", default=False, + help="print min and max Rx gain available on selected daughterboard") + normal.add_option("-v", "--verbose", action="store_true", default=False) + expert.add_option("-S", "--samples-per-symbol", type="int", default=None, + help="set samples/symbol [default=%default]") + expert.add_option("", "--rx-freq", type="eng_float", default=None, + help="set Rx frequency to FREQ [default=%default]", metavar="FREQ") + expert.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decimation rate to DECIM [default=%default]") + expert.add_option("", "--log", action="store_true", default=False, + help="Log all parts of flow graph to files (CAUTION: lots of data)") + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + + def _print_verbage(self): + """ + Prints information about the receive path + """ + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + print "Rx gain: %g" % (self.gain,) + print "modulation: %s" % (self._demod_class.__name__) + print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) + print "samples/symbol: %3d" % (self._samples_per_symbol) + print "decim: %3d" % (self._decim) + print "Rx Frequency: %s" % (eng_notation.num_to_str(self._rx_freq)) + # print "Rx Frequency: %f" % (self._rx_freq) + +def add_freq_option(parser): + """ + Hackery that has the -f / --freq option set both tx_freq and rx_freq + """ + def freq_callback(option, opt_str, value, parser): + parser.values.rx_freq = value + parser.values.tx_freq = value + + if not parser.has_option('--freq'): + parser.add_option('-f', '--freq', type="eng_float", + action="callback", callback=freq_callback, + help="set Tx and/or Rx frequency to FREQ [default=%default]", + metavar="FREQ") diff --git a/gnuradio-examples/python/gmsk2/rx_voice.py b/gnuradio-examples/python/digital/rx_voice.py index 605b46360..130486245 100755 --- a/gnuradio-examples/python/gmsk2/rx_voice.py +++ b/gnuradio-examples/python/digital/rx_voice.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005 Free Software Foundation, Inc. +# Copyright 2005,2006 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, blks +from gnuradio import gr, gru, modulation_utils from gnuradio import usrp from gnuradio import audio from gnuradio import eng_notation @@ -34,6 +34,7 @@ import struct # from current dir from receive_path import receive_path +import fusb_options #import os #print os.getpid() @@ -41,12 +42,12 @@ from receive_path import receive_path class audio_tx(gr.hier_block): - def __init__(self, fg): + def __init__(self, fg, audio_output_dev): self.packet_src = gr.message_source(33) voice_decoder = gsm_full_rate.decode_ps() s2f = gr.short_to_float () sink_scale = gr.multiply_const_ff(1.0/32767.) - audio_sink = audio.sink(8000) + audio_sink = audio.sink(8000, audio_output_dev) fg.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink) gr.hier_block.__init__(self, fg, self.packet_src, audio_sink) @@ -56,12 +57,10 @@ class audio_tx(gr.hier_block): class my_graph(gr.flow_graph): - def __init__(self, rx_subdev_spec, bitrate, decim_rate, spb, rx_callback, log): + def __init__(self, demod_class, rx_callback, options): gr.flow_graph.__init__(self) - self.rxpath = receive_path(self, rx_subdev_spec, bitrate, decim_rate, - spb, rx_callback, log) - - self.audio_tx = audio_tx(self) + self.rxpath = receive_path(self, demod_class, rx_callback, options) + self.audio_tx = audio_tx(self, options.audio_output) # ///////////////////////////////////////////////////////////////////////////// @@ -87,40 +86,45 @@ def main(): print "ok = %r n_rcvd = %4d n_right = %4d" % ( ok, n_rcvd, n_right) - parser = OptionParser (option_class=eng_option) - parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, - help="select USRP Rx side A or B") - parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, - help="set Rx frequency to FREQ [default=%default]", metavar="FREQ") - parser.add_option("-r", "--bitrate", type="eng_float", default=100e3, - help="specify bitrate. spb and interp will be derived.") - parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]") - parser.add_option("-d", "--decim", type="intx", default=None, - help="set fpga decim rate to DECIM [default=%default]") - parser.add_option("-g", "--gain", type="eng_float", default=27, - help="set rx gain") - parser.add_option("","--log", action="store_true", default=False, - help="enable diagnostic logging") + demods = modulation_utils.type_1_demods() + + # Create Options Parser: + parser = OptionParser (option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), + default='gmsk', + help="Select modulation from: %s [default=%%default]" + % (', '.join(demods.keys()),)) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + + receive_path.add_options(parser, expert_grp) + + for mod in demods.values(): + mod.add_options(expert_grp) + + fusb_options.add_options(expert_grp) + + parser.set_defaults(bitrate=50e3) # override default bitrate default (options, args) = parser.parse_args () if len(args) != 0: - parser.print_help() + parser.print_help(sys.stderr) sys.exit(1) - if options.freq < 1e6: - options.freq *= 1e6 + if options.rx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) - # build the graph - fg = my_graph(options.rx_subdev_spec, options.bitrate, - options.decim, options.spb, rx_callback, options.log) - print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),) - print "spb: %3d" % (fg.rxpath.spb(),) - print "decim: %3d" % (fg.rxpath.decim(),) + # build the graph + fg = my_graph(demods[options.modulation], rx_callback, options) - fg.rxpath.set_freq(options.freq) - fg.rxpath.set_gain(options.gain) - print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: Failed to enable realtime scheduling." fg.start() # start flow graph fg.wait() # wait for it to finish diff --git a/gnuradio-examples/python/digital/transmit_path.py b/gnuradio-examples/python/digital/transmit_path.py new file mode 100644 index 000000000..5c4017362 --- /dev/null +++ b/gnuradio-examples/python/digital/transmit_path.py @@ -0,0 +1,232 @@ +# +# Copyright 2005,2006 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 2, 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, blks +from gnuradio import usrp +from gnuradio import eng_notation + +import copy +import sys + +# from current dir +from pick_bitrate import pick_tx_bitrate + +# ///////////////////////////////////////////////////////////////////////////// +# transmit path +# ///////////////////////////////////////////////////////////////////////////// + +class transmit_path(gr.hier_block): + def __init__(self, fg, modulator_class, options): + ''' + See below for what options should hold + ''' + + options = copy.copy(options) # make a copy so we can destructively modify + + self._verbose = options.verbose + self._tx_freq = options.tx_freq # tranmitter's center frequency + self._tx_amplitude = options.tx_amplitude # digital amplitude sent to USRP + self._tx_subdev_spec = options.tx_subdev_spec # daughterboard to use + self._bitrate = options.bitrate # desired bit rate + self._interp = options.interp # interpolating rate for the USRP (prelim) + self._samples_per_symbol = options.samples_per_symbol # desired samples/baud + self._fusb_block_size = options.fusb_block_size # usb info for USRP + self._fusb_nblocks = options.fusb_nblocks # usb info for USRP + + self._modulator_class = modulator_class # the modulator_class we are using + + if self._tx_freq is None: + sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n") + raise SystemExit + + # Set up USRP sink; also adjusts interp, samples_per_symbol, and bitrate + self._setup_usrp_sink() + + # copy the final answers back into options for use by modulator + options.samples_per_symbol = self._samples_per_symbol + options.bitrate = self._bitrate + options.interp = self._interp + + # Get mod_kwargs + mod_kwargs = self._modulator_class.extract_kwargs_from_options(options) + + # Set center frequency of USRP + ok = self.set_freq(self._tx_freq) + if not ok: + print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(self._tx_freq),) + raise ValueError + + # transmitter + self.packet_transmitter = \ + blks.mod_pkts(fg, + self._modulator_class(fg, **mod_kwargs), + access_code=None, + msgq_limit=4, + pad_for_usrp=True) + + + # Set the USRP for maximum transmit gain + # (Note that on the RFX cards this is a nop.) + self.set_gain(self.subdev.gain_range()[0]) + + self.amp = gr.multiply_const_cc(1) + self.set_tx_amplitude(self._tx_amplitude) + + # enable Auto Transmit/Receive switching + self.set_auto_tr(True) + + # Display some information about the setup + if self._verbose: + self._print_verbage() + + # Create and setup transmit path flow graph + fg.connect(self.packet_transmitter, self.amp, self.u) + gr.hier_block.__init__(self, fg, None, None) + + def _setup_usrp_sink(self): + """ + Creates a USRP sink, determines the settings for best bitrate, + and attaches to the transmitter's subdevice. + """ + self.u = usrp.sink_c(fusb_block_size=self._fusb_block_size, + fusb_nblocks=self._fusb_nblocks) + dac_rate = self.u.dac_rate(); + + # derive values of bitrate, samples_per_symbol, and interp from desired info + (self._bitrate, self._samples_per_symbol, self._interp) = \ + pick_tx_bitrate(self._bitrate, self._modulator_class.bits_per_symbol(), + self._samples_per_symbol, self._interp, dac_rate) + + self.u.set_interp_rate(self._interp) + + # determine the daughterboard subdevice we're using + if self._tx_subdev_spec is None: + self._tx_subdev_spec = usrp.pick_tx_subdevice(self.u) + self.u.set_mux(usrp.determine_tx_mux_value(self.u, self._tx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, self._tx_subdev_spec) + + + 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. + """ + r = self.u.tune(self.subdev._which, self.subdev, target_freq) + if r: + return True + + return False + + def set_gain(self, gain): + """ + Sets the analog gain in the USRP + """ + self.gain = gain + self.subdev.set_gain(gain) + + def set_tx_amplitude(self, ampl): + """ + Sets the transmit amplitude sent to the USRP + @param: ampl 0 <= ampl < 32768. Try 8000 + """ + self._tx_amplitude = max(0.0, min(ampl, 32767.0)) + self.amp.set_k(self._tx_amplitude) + + def set_auto_tr(self, enable): + """ + Turns on auto transmit/receive of USRP daughterboard (if exits; else ignored) + """ + return self.subdev.set_auto_tr(enable) + + def send_pkt(self, payload='', eof=False): + """ + Calls the transmitter method to send a packet + """ + return self.packet_transmitter.send_pkt(payload, eof) + + def bitrate(self): + return self._bitrate + + def samples_per_symbol(self): + return self._samples_per_symbol + + def interp(self): + return self._interp + + def add_options(normal, expert): + """ + Adds transmitter-specific options to the Options Parser + """ + add_freq_option(normal) + if not normal.has_option('--bitrate'): + normal.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. samples-per-symbol and interp/decim will be derived.") + normal.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + normal.add_option("", "--tx-amplitude", type="eng_float", default=12000, metavar="AMPL", + help="set transmitter digital amplitude: 0 <= AMPL < 32768 [default=%default]") + normal.add_option("-v", "--verbose", action="store_true", default=False) + + expert.add_option("-S", "--samples-per-symbol", type="int", default=None, + help="set samples/symbol [default=%default]") + expert.add_option("", "--tx-freq", type="eng_float", default=None, + help="set transmit frequency to FREQ [default=%default]", metavar="FREQ") + expert.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + expert.add_option("", "--log", action="store_true", default=False, + help="Log all parts of flow graph to file (CAUTION: lots of data)") + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + def _print_verbage(self): + """ + Prints information about the transmit path + """ + print "Using TX d'board %s" % (self.subdev.side_and_name(),) + print "Tx amplitude %s" % (self._tx_amplitude) + print "modulation: %s" % (self._modulator_class.__name__) + print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) + print "samples/symbol: %3d" % (self._samples_per_symbol) + print "interp: %3d" % (self._interp) + print "Tx Frequency: %s" % (eng_notation.num_to_str(self._tx_freq)) + + +def add_freq_option(parser): + """ + Hackery that has the -f / --freq option set both tx_freq and rx_freq + """ + def freq_callback(option, opt_str, value, parser): + parser.values.rx_freq = value + parser.values.tx_freq = value + + if not parser.has_option('--freq'): + parser.add_option('-f', '--freq', type="eng_float", + action="callback", callback=freq_callback, + help="set Tx and/or Rx frequency to FREQ [default=%default]", + metavar="FREQ") diff --git a/gnuradio-examples/python/gmsk2/tunnel.py b/gnuradio-examples/python/digital/tunnel.py index faf16a634..56229f536 100755 --- a/gnuradio-examples/python/gmsk2/tunnel.py +++ b/gnuradio-examples/python/digital/tunnel.py @@ -33,7 +33,7 @@ # ///////////////////////////////////////////////////////////////////////////// -from gnuradio import gr, gru, blks +from gnuradio import gr, gru, modulation_utils from gnuradio import usrp from gnuradio import eng_notation from gnuradio.eng_option import eng_option @@ -89,17 +89,11 @@ def open_tun_interface(tun_device_filename): class my_graph(gr.flow_graph): def __init__(self, mod_class, demod_class, - tx_subdev_spec, rx_subdev_spec, - rx_callback, - options, kwargs): + rx_callback, options): gr.flow_graph.__init__(self) - self.txpath = transmit_path(self, mod_class, tx_subdev_spec, - options.bitrate, options.interp, options.spb, - options.tx_gain, options, kwargs) - self.rxpath = receive_path(self, demod_class, rx_subdev_spec, - options.bitrate, options.decim, options.spb, - rx_callback, options, {}) + self.txpath = transmit_path(self, mod_class, options) + self.rxpath = receive_path(self, demod_class, rx_callback, options) def send_pkt(self, payload='', eof=False): return self.txpath.send_pkt(payload, eof) @@ -180,46 +174,43 @@ class cs_mac(object): def main(): - parser = OptionParser (option_class=eng_option) - parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, - help="set Tx and Rx frequency to FREQ [default=%default]", - metavar="FREQ") - parser.add_option("-r", "--bitrate", type="eng_float", default=None, - help="specify bitrate. spb and interp will be derived.") - parser.add_option("-g", "--rx-gain", type="eng_float", default=27, - help="set rx gain") - parser.add_option("-p", "--tx-gain", type="eng_float", default=100, - help="set tx gain") - parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, - help="select USRP Tx side A or B") - parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, - help="select USRP Rx side A or B") - parser.add_option("-S", "--spb", type="int", default=None, - help="set samples/baud [default=%default]") - parser.add_option("-d", "--decim", type="intx", default=None, - help="set fpga decim rate to DECIM [default=%default]") - parser.add_option("-i", "--interp", type="intx", default=None, - help="set fpga interpolation rate to INTERP [default=%default]") - parser.add_option("-c", "--carrier-threshold", type="eng_float", default=30, - help="set carrier detect threshold (dB) [default=%default]") - parser.add_option("", "--bt", type="float", default=0.3, - help="set bandwidth-time product [default=%default]") - parser.add_option("","--tun-device-filename", default="/dev/net/tun", - help="path to tun device file [default=%default]") + mods = modulation_utils.type_1_mods() + demods = modulation_utils.type_1_demods() + + parser = OptionParser (option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + default='gmsk', + help="Select modulation from: %s [default=%%default]" + % (', '.join(mods.keys()),)) + parser.add_option("-v","--verbose", action="store_true", default=False) - fusb_options.add_options(parser) - (options, args) = parser.parse_args () + expert_grp.add_option("-c", "--carrier-threshold", type="eng_float", default=30, + help="set carrier detect threshold (dB) [default=%default]") + expert_grp.add_option("","--tun-device-filename", default="/dev/net/tun", + help="path to tun device file [default=%default]") + + transmit_path.add_options(parser, expert_grp) + receive_path.add_options(parser, expert_grp) + + for mod in mods.values(): + mod.add_options(expert_grp) + + for demod in demods.values(): + demod.add_options(expert_grp) + fusb_options.add_options(expert_grp) + + (options, args) = parser.parse_args () if len(args) != 0: - parser.print_help() + parser.print_help(sys.stderr) sys.exit(1) - if options.freq < 1e6: - options.freq *= 1e6 - - mod_kwargs = { - 'bt' : options.bt, - } + if options.rx_freq is None or options.tx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) # open the TUN/TAP interface (tun_fd, tun_ifname) = open_tun_interface(options.tun_device_filename) @@ -244,18 +235,18 @@ def main(): options.fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096) options.fusb_nblocks = gr.prefs().get_long('fusb', 'nblocks', 16) - print "fusb_block_size =", options.fusb_block_size - print "fusb_nblocks =", options.fusb_nblocks + #print "fusb_block_size =", options.fusb_block_size + #print "fusb_nblocks =", options.fusb_nblocks # instantiate the MAC mac = cs_mac(tun_fd, verbose=True) # build the graph (PHY) - fg = my_graph(blks.gmsk2_mod, blks.gmsk2_demod, - options.tx_subdev_spec, options.rx_subdev_spec, + fg = my_graph(mods[options.modulation], + demods[options.modulation], mac.phy_rx_callback, - options, mod_kwargs) + options) mac.set_flow_graph(fg) # give the MAC a handle for the PHY @@ -264,23 +255,12 @@ def main(): eng_notation.num_to_str(fg.txpath.bitrate()), eng_notation.num_to_str(fg.rxpath.bitrate())) - print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) - print "spb: %3d" % (fg.txpath.spb(),) - print "interp: %3d" % (fg.txpath.interp(),) - - ok = fg.txpath.set_freq(options.freq) - if not ok: - print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),) - raise SystemExit - - ok = fg.rxpath.set_freq(options.freq) - if not ok: - print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),) - raise SystemExit - - print "Tx gain: ", options.tx_gain - fg.rxpath.set_gain(options.rx_gain) - print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + print "modulation: %s" % (options.modulation,) + print "freq: %s" % (eng_notation.num_to_str(options.tx_freq)) + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "samples/symbol: %3d" % (fg.txpath.samples_per_symbol(),) + #print "interp: %3d" % (fg.txpath.interp(),) + #print "decim: %3d" % (fg.rxpath.decim(),) fg.rxpath.set_carrier_threshold(options.carrier_threshold) print "Carrier sense threshold:", options.carrier_threshold, "dB" @@ -289,7 +269,7 @@ def main(): print "Allocated virtual ethernet interface: %s" % (tun_ifname,) print "You must now use ifconfig to set its IP address. E.g.," print - print " $ sudo ifconfig %s 10.10.10.1" % (tun_ifname,) + print " $ sudo ifconfig %s 192.168.200.1" % (tun_ifname,) print print "Be sure to use a different address in the same subnet for each machine." print diff --git a/gnuradio-examples/python/gmsk2/tx_voice.py b/gnuradio-examples/python/digital/tx_voice.py index b1f6b0ab8..eba0c3c71 100755 --- a/gnuradio-examples/python/gmsk2/tx_voice.py +++ b/gnuradio-examples/python/digital/tx_voice.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005 Free Software Foundation, Inc. +# Copyright 2005,2006 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, blks +from gnuradio import gr, gru, modulation_utils from gnuradio import usrp from gnuradio import audio from gnuradio import eng_notation @@ -36,27 +36,35 @@ import sys # from current dir from transmit_path import transmit_path +import fusb_options #import os #print os.getpid() #raw_input('Attach and press enter') -class my_graph(gr.flow_graph): - - def __init__(self, tx_subdev_spec, bitrate, interp_rate, spb, bt): - gr.flow_graph.__init__(self) - self.txpath = transmit_path(self, tx_subdev_spec, bitrate, interp_rate, spb, bt) - - audio_input = "" +class audio_rx(gr.hier_block): + def __init__(self, fg, audio_input_dev): sample_rate = 8000 - src = audio.source(sample_rate, audio_input) + src = audio.source(sample_rate, audio_input_dev) src_scale = gr.multiply_const_ff(32767) f2s = gr.float_to_short() voice_coder = gsm_full_rate.encode_sp() self.packets_from_encoder = gr.msg_queue() packet_sink = gr.message_sink(33, self.packets_from_encoder, False) - self.connect(src, src_scale, f2s, voice_coder, packet_sink) + fg.connect(src, src_scale, f2s, voice_coder, packet_sink) + gr.hier_block.__init__(self, fg, src, packet_sink) + + def get_encoded_voice_packet(self): + return self.packets_from_encoder.delete_head() + + +class my_graph(gr.flow_graph): + + def __init__(self, modulator_class, options): + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, modulator_class, options) + self.audio_rx = audio_rx(self, options.audio_input) @@ -72,43 +80,47 @@ def main(): def rx_callback(ok, payload): print "ok = %r, payload = '%s'" % (ok, payload) - parser = OptionParser (option_class=eng_option) - parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, - help="select USRP Tx side A or B") - parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, - help="set Tx and Rx frequency to FREQ [default=%default]", metavar="FREQ") - parser.add_option("-r", "--bitrate", type="eng_float", default=100e3, - help="specify bitrate. spb and interp will be derived.") - parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]") - parser.add_option("-i", "--interp", type="intx", default=None, - help="set fpga interpolation rate to INTERP [default=%default]") - parser.add_option("-s", "--size", type="eng_float", default=1500, - help="set packet size [default=%default]") - parser.add_option("", "--bt", type="float", default=0.3, help="set bandwidth-time product [default=%default]") - parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, - help="set megabytes to transmit [default=%default]") - parser.add_option("","--discontinuous", action="store_true", default=False, - help="enable discontinous transmission (bursts of 5 packets)") + mods = modulation_utils.type_1_mods() + + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + + parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + default='gmsk', + help="Select modulation from: %s [default=%%default]" + % (', '.join(mods.keys()),)) + parser.add_option("-M", "--megabytes", type="eng_float", default=0, + help="set megabytes to transmit [default=inf]") + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + + transmit_path.add_options(parser, expert_grp) + + for mod in mods.values(): + mod.add_options(expert_grp) + + fusb_options.add_options(expert_grp) + + parser.set_defaults(bitrate=50e3) # override default bitrate default (options, args) = parser.parse_args () if len(args) != 0: parser.print_help() sys.exit(1) - if options.freq < 1e6: - options.freq *= 1e6 + if options.tx_freq is None: + sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") + parser.print_help(sys.stderr) + sys.exit(1) - pkt_size = int(options.size) # build the graph - fg = my_graph(options.tx_subdev_spec, options.bitrate, options.interp, - options.spb, options.bt) + fg = my_graph(mods[options.modulation], options) - print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) - print "spb: %3d" % (fg.txpath.spb(),) - print "interp: %3d" % (fg.txpath.interp(),) + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" - fg.txpath.set_freq(options.freq) fg.start() # start flow graph @@ -117,14 +129,12 @@ def main(): n = 0 pktno = 0 - while n < nbytes: - packet = fg.packets_from_encoder.delete_head() + while nbytes == 0 or n < nbytes: + packet = fg.audio_rx.get_encoded_voice_packet() s = packet.to_string() send_pkt(s) n += len(s) sys.stderr.write('.') - if options.discontinuous and pktno % 5 == 4: - time.sleep(1) pktno += 1 send_pkt(eof=True) diff --git a/gnuradio-examples/python/gmsk2/bpsk.py b/gnuradio-examples/python/gmsk2/bpsk.py deleted file mode 100644 index dcf8a10b6..000000000 --- a/gnuradio-examples/python/gmsk2/bpsk.py +++ /dev/null @@ -1,256 +0,0 @@ -# -# Copyright 2005,2006 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 2, 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. -# - -# See gnuradio-examples/python/gmsk2 for examples - -""" -BPSK modulation and demodulation. -""" - -from gnuradio import gr, gru -from math import pi, sqrt -import cmath -import Numeric -from pprint import pprint - -_use_gray_code = True - -def make_constellation(m): - return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] - -# Common definition of constellations for Tx and Rx -constellation = { - 2 : make_constellation(2), # BPSK - 4 : make_constellation(4), # QPSK - 8 : make_constellation(8) # 8PSK - } - -if 0: - print "const(2) =" - pprint(constellation[2]) - print "const(4) =" - pprint(constellation[4]) - print "const(8) =" - pprint(constellation[8]) - - -if _use_gray_code: - # ----------------------- - # Do Gray code - # ----------------------- - # binary to gray coding - binary_to_gray = { - 2 : (0, 1), - 4 : (0, 1, 3, 2), - 8 : (0, 1, 3, 2, 7, 6, 4, 5) - } - - # gray to binary - gray_to_binary = { - 2 : (0, 1), - 4 : (0, 1, 3, 2), - 8 : (0, 1, 3, 2, 6, 7, 5, 4) - } -else: - # ----------------------- - # Don't Gray code - # ----------------------- - # identity mapping - binary_to_gray = { - 2 : (0, 1), - 4 : (0, 1, 2, 3), - 8 : (0, 1, 2, 3, 4, 5, 6, 7) - } - - # identity mapping - gray_to_binary = { - 2 : (0, 1), - 4 : (0, 1, 2, 3), - 8 : (0, 1, 2, 3, 4, 5, 6, 7) - } - - -# ///////////////////////////////////////////////////////////////////////////// -# mPSK mod/demod with steams of bytes as data i/o -# ///////////////////////////////////////////////////////////////////////////// - - -class bpsk_mod(gr.hier_block): - - def __init__(self, fg, spb, excess_bw): - """ - Hierarchical block for RRC-filtered BPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - """ - if not isinstance(spb, int) or spb < 2: - raise TypeError, "sbp must be an integer >= 2" - self.spb = spb - - ntaps = 11 * spb - - bits_per_symbol = self.bits_per_baud() - arity = pow(2,bits_per_symbol) - print "bits_per_symbol =", bits_per_symbol - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) - - self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - spb, # gain (spb since we're interpolating by spb) - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) - - # Connect - fg.connect(self.bytes2chunks, self.chunks2symbols, self.rrc_filter) - - if 1: - fg.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self=None): # staticmethod that's also callable on an instance - return 1 - bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM - - -class bpsk_demod__coherent_detection_of_psk(gr.hier_block): - def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): - """ - Hierarchical block for RRC-filtered BPSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param costas_alpha: loop filter gain - @type costas_alphas: float - @param gain_mu: - @type gain_mu: float - """ - if spb < 2: - raise TypeError, "sbp must be >= 2" - self.spb = spb - - bits_per_symbol = self.bits_per_baud() - arity = pow(2,bits_per_symbol) - print "bits_per_symbol =", bits_per_symbol - - # Automatic gain control - self.preamp = gr.multiply_const_cc(10e-5) - self.agc = gr.agc_cc(1e-3, 1, 1) - - # Costas loop (carrier tracking) - # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? - costas_order = 2 - costas_alpha *= 15 # 2nd order loop needs more gain - beta = .25 * costas_alpha * costas_alpha - self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) - - # RRC data filter - ntaps = 11 * spb - self.rrc_taps = gr.firdes.root_raised_cosine( - 1.0, # gain - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) - - # symbol clock recovery - omega = spb - gain_omega = .25 * gain_mu * gain_mu - omega_rel_limit = 0.5 - mu = 0.05 - gain_mu = 0.1 - self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, - mu, gain_mu, omega_rel_limit) - - # find closest constellation point - #rot = .707 + .707j - rot = 1 - rotated_const = map(lambda pt: pt * rot, constellation[arity]) - print "rotated_const =", rotated_const - - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - self.gray_decoder = gr.map_bb(gray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) - - fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - self.slicer, self.gray_decoder, self.unpack) - - # Debug sinks - if 1: - fg.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) - fg.connect(self.costas_loop, - gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) - fg.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) - fg.connect(self.clock_recovery, - gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) - fg.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "slicer.dat")) - fg.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "unpack.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.preamp, self.unpack) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self=None): # staticmethod that's also callable on an instance - return 1 - bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM - - -bpsk_demod = bpsk_demod__coherent_detection_of_psk - diff --git a/gnuradio-examples/python/gmsk2/dbpsk.py b/gnuradio-examples/python/gmsk2/dbpsk.py deleted file mode 100644 index 7d2765df4..000000000 --- a/gnuradio-examples/python/gmsk2/dbpsk.py +++ /dev/null @@ -1,282 +0,0 @@ -# -# Copyright 2005,2006 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 2, 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. -# - -# See gnuradio-examples/python/gmsk2 for examples - -""" -differential BPSK modulation and demodulation. -""" - -from gnuradio import gr, gru -from math import pi, sqrt -import cmath -import Numeric -from pprint import pprint - -_use_gray_code = True - -def make_constellation(m): - return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] - -# Common definition of constellations for Tx and Rx -constellation = { - 2 : make_constellation(2), # BPSK - 4 : make_constellation(4), # QPSK - 8 : make_constellation(8) # 8PSK - } - -if 0: - print "const(2) =" - pprint(constellation[2]) - print "const(4) =" - pprint(constellation[4]) - print "const(8) =" - pprint(constellation[8]) - - -if _use_gray_code: - # ----------------------- - # Do Gray code - # ----------------------- - # binary to gray coding - binary_to_gray = { - 2 : (0, 1), - 4 : (0, 1, 3, 2), - 8 : (0, 1, 3, 2, 7, 6, 4, 5) - } - - # gray to binary - gray_to_binary = { - 2 : (0, 1), - 4 : (0, 1, 3, 2), - 8 : (0, 1, 3, 2, 6, 7, 5, 4) - } -else: - # ----------------------- - # Don't Gray code - # ----------------------- - # identity mapping - binary_to_gray = { - 2 : (0, 1), - 4 : (0, 1, 2, 3), - 8 : (0, 1, 2, 3, 4, 5, 6, 7) - } - - # identity mapping - gray_to_binary = { - 2 : (0, 1), - 4 : (0, 1, 2, 3), - 8 : (0, 1, 2, 3, 4, 5, 6, 7) - } - - -# ///////////////////////////////////////////////////////////////////////////// -# BPSK mod/demod with steams of bytes as data i/o -# ///////////////////////////////////////////////////////////////////////////// - - -class dbpsk_mod(gr.hier_block): - - def __init__(self, fg, spb, excess_bw): - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - """ - if not isinstance(spb, int) or spb < 2: - raise TypeError, "sbp must be an integer >= 2" - self.spb = spb - - ntaps = 11 * spb - - bits_per_symbol = self.bits_per_baud() - arity = pow(2,bits_per_symbol) - self.bits_per_symbol = bits_per_symbol - print "bits_per_symbol =", bits_per_symbol - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) - - if True: - self.gray_coder = gr.map_bb(binary_to_gray[arity]) - else: - self.gray_coder = None - - self.diffenc = gr.diff_encoder_bb(arity) - - self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - spb, # gain (spb since we're interpolating by spb) - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) - - # Connect - if self.gray_coder: - fg.connect(self.bytes2chunks, self.gray_coder) - t = self.gray_coder - else: - t = self.bytes2chunks - - fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) - - if 1: - fg.connect(self.gray_coder, - gr.file_sink(gr.sizeof_char, "graycoder.dat")) - fg.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "diffenc.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self=None): # staticmethod that's also callable on an instance - return 1 - bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM - - - -class dbpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): - def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): - """ - Hierarchical block for RRC-filtered BPSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param costas_alpha: loop filter gain - @type costas_alphas: float - @param gain_mu: - @type gain_mu: float - """ - if spb < 2: - raise TypeError, "sbp must be >= 2" - self.spb = spb - - bits_per_symbol = self.bits_per_baud() - arity = pow(2,bits_per_symbol) - print "bits_per_symbol =", bits_per_symbol - - # Automatic gain control - self.preamp = gr.multiply_const_cc(10e-5) - self.agc = gr.agc_cc(1e-3, 1, 1, 1000) - - # Costas loop (carrier tracking) - # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? - costas_order = 2 - costas_alpha *= 15 # 2nd order loop needs more gain - beta = .25 * costas_alpha * costas_alpha - self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) - - # RRC data filter - ntaps = 11 * spb - self.rrc_taps = gr.firdes.root_raised_cosine( - 1.0, # gain - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) - - # symbol clock recovery - omega = spb - gain_omega = .25 * gain_mu * gain_mu - omega_rel_limit = 0.5 - mu = 0.05 - gain_mu = 0.1 - self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, - mu, gain_mu, omega_rel_limit) - - # find closest constellation point - #rot = .707 + .707j - rot = 1 - rotated_const = map(lambda pt: pt * rot, constellation[arity]) - print "rotated_const =", rotated_const - - self.diffdec = gr.diff_phasor_cc() - #self.diffdec = gr.diff_decoder_bb(arity) - - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - self.gray_decoder = gr.map_bb(gray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) - - fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - self.diffdec, self.slicer, self.gray_decoder, self.unpack) - #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - # self.slicer, self.diffdec, self.gray_decoder, self.unpack) - - # Debug sinks - if 1: - fg.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) - fg.connect(self.costas_loop, - gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) - fg.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) - fg.connect(self.clock_recovery, - gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) - fg.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "slicer.dat")) - fg.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) - #fg.connect(self.diffdec, - # gr.file_sink(gr.sizeof_char, "diffdec.dat")) - fg.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "unpack.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.preamp, self.unpack) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self=None): # staticmethod that's also callable on an instance - return 1 - bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM - - -dbpsk_demod = dbpsk_demod__coherent_detection_of_differentially_encoded_psk - diff --git a/gnuradio-examples/python/gmsk2/dqpsk.py b/gnuradio-examples/python/gmsk2/dqpsk.py deleted file mode 100644 index a18f28b75..000000000 --- a/gnuradio-examples/python/gmsk2/dqpsk.py +++ /dev/null @@ -1,280 +0,0 @@ -# -# Copyright 2005,2006 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 2, 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. -# - -# See gnuradio-examples/python/gmsk2 for examples - -""" -differential QPSK modulation and demodulation. -""" - -from gnuradio import gr, gru -from math import pi, sqrt -import cmath -import Numeric -from pprint import pprint - -_use_gray_code = True - -def make_constellation(m): - return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] - -# Common definition of constellations for Tx and Rx -constellation = { - 2 : make_constellation(2), # BPSK - 4 : make_constellation(4), # QPSK - 8 : make_constellation(8) # 8PSK - } - -if 0: - print "const(2) =" - pprint(constellation[2]) - print "const(4) =" - pprint(constellation[4]) - print "const(8) =" - pprint(constellation[8]) - - -if _use_gray_code: - # ----------------------- - # Do Gray code - # ----------------------- - # binary to gray coding - binary_to_gray = { - 2 : (0, 1), - 4 : (0, 1, 3, 2), - 8 : (0, 1, 3, 2, 7, 6, 4, 5) - } - - # gray to binary - gray_to_binary = { - 2 : (0, 1), - 4 : (0, 1, 3, 2), - 8 : (0, 1, 3, 2, 6, 7, 5, 4) - } -else: - # ----------------------- - # Don't Gray code - # ----------------------- - # identity mapping - binary_to_gray = { - 2 : (0, 1), - 4 : (0, 1, 2, 3), - 8 : (0, 1, 2, 3, 4, 5, 6, 7) - } - - # identity mapping - gray_to_binary = { - 2 : (0, 1), - 4 : (0, 1, 2, 3), - 8 : (0, 1, 2, 3, 4, 5, 6, 7) - } - - -# ///////////////////////////////////////////////////////////////////////////// -# QPSK mod/demod with steams of bytes as data i/o -# ///////////////////////////////////////////////////////////////////////////// - - -class dqpsk_mod(gr.hier_block): - - def __init__(self, fg, spb, excess_bw): - """ - Hierarchical block for RRC-filtered QPSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - """ - if not isinstance(spb, int) or spb < 2: - raise TypeError, "sbp must be an integer >= 2" - self.spb = spb - - ntaps = 11 * spb - - bits_per_symbol = self.bits_per_baud() - arity = pow(2,bits_per_symbol) - print "bits_per_symbol =", bits_per_symbol - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) - - if True: - self.gray_coder = gr.map_bb(binary_to_gray[arity]) - else: - self.gray_coder = None - - self.diffenc = gr.diff_encoder_bb(arity) - - self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - spb, # gain (spb since we're interpolating by spb) - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) - - # Connect - if self.gray_coder: - fg.connect(self.bytes2chunks, self.gray_coder) - t = self.gray_coder - else: - t = self.bytes2chunks - - fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) - - if 1: - fg.connect(self.gray_coder, - gr.file_sink(gr.sizeof_char, "graycoder.dat")) - fg.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "diffenc.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self=None): # staticmethod that's also callable on an instance - return 2 - bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM - - - -class dqpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): - def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): - """ - Hierarchical block for RRC-filtered QPSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param costas_alpha: loop filter gain - @type costas_alphas: float - @param gain_mu: - @type gain_mu: float - """ - if spb < 2: - raise TypeError, "sbp must be >= 2" - self.spb = spb - - bits_per_symbol = self.bits_per_baud() - arity = pow(2,bits_per_symbol) - print "bits_per_symbol =", bits_per_symbol - - # Automatic gain control - self.preamp = gr.multiply_const_cc(10e-5) - self.agc = gr.agc_cc(1e-3, 1, 1) - - # Costas loop (carrier tracking) - # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? - costas_order = 4 - beta = .25 * costas_alpha * costas_alpha - self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) - - # RRC data filter - ntaps = 11 * spb - self.rrc_taps = gr.firdes.root_raised_cosine( - 1.0, # gain - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) - - # symbol clock recovery - omega = spb - gain_omega = .25 * gain_mu * gain_mu - omega_rel_limit = 0.5 - mu = 0.05 - gain_mu = 0.1 - self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, - mu, gain_mu, omega_rel_limit) - - # find closest constellation point - #rot = .707 + .707j - rot = 1 - rotated_const = map(lambda pt: pt * rot, constellation[arity]) - print "rotated_const =", rotated_const - - self.diffdec = gr.diff_phasor_cc() - #self.diffdec = gr.diff_decoder_bb(arity) - - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - self.gray_decoder = gr.map_bb(gray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) - - fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - self.diffdec, self.slicer, self.gray_decoder, self.unpack) - #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - # self.slicer, self.diffdec, self.gray_decoder, self.unpack) - - # Debug sinks - if 1: - fg.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) - fg.connect(self.costas_loop, - gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) - fg.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) - fg.connect(self.clock_recovery, - gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) - fg.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "slicer.dat")) - fg.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) - #fg.connect(self.diffdec, - # gr.file_sink(gr.sizeof_char, "diffdec.dat")) - fg.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "unpack.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.preamp, self.unpack) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self=None): # staticmethod that's also callable on an instance - return 2 - bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM - - -dqpsk_demod = dqpsk_demod__coherent_detection_of_differentially_encoded_psk - diff --git a/gnuradio-examples/python/gmsk2/qpsk.py b/gnuradio-examples/python/gmsk2/qpsk.py deleted file mode 100644 index 26d95ed71..000000000 --- a/gnuradio-examples/python/gmsk2/qpsk.py +++ /dev/null @@ -1,418 +0,0 @@ -# -# Copyright 2005,2006 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 2, 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. -# - -# See gnuradio-examples/python/gmsk2 for examples - -""" -PSK and differential PSK modulation and demodulation. -""" - -from gnuradio import gr, gru -from math import pi, sqrt -import cmath -import Numeric -from pprint import pprint - -_use_gray_code = True - -def make_constellation(m): - return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] - -# Common definition of constellations for Tx and Rx -constellation = { - 2 : make_constellation(2), # BPSK - 4 : make_constellation(4), # QPSK - 8 : make_constellation(8) # 8PSK - } - -if 0: - print "const(2) =" - pprint(constellation[2]) - print "const(4) =" - pprint(constellation[4]) - print "const(8) =" - pprint(constellation[8]) - - -if _use_gray_code: - # ----------------------- - # Do Gray code - # ----------------------- - # binary to gray coding - binary_to_gray = { - 2 : (0, 1), - 4 : (0, 1, 3, 2), - 8 : (0, 1, 3, 2, 7, 6, 4, 5) - } - - # gray to binary - gray_to_binary = { - 2 : (0, 1), - 4 : (0, 1, 3, 2), - 8 : (0, 1, 3, 2, 6, 7, 5, 4) - } -else: - # ----------------------- - # Don't Gray code - # ----------------------- - # identity mapping - binary_to_gray = { - 2 : (0, 1), - 4 : (0, 1, 2, 3), - 8 : (0, 1, 2, 3, 4, 5, 6, 7) - } - - # identity mapping - gray_to_binary = { - 2 : (0, 1), - 4 : (0, 1, 2, 3), - 8 : (0, 1, 2, 3, 4, 5, 6, 7) - } - - -# ///////////////////////////////////////////////////////////////////////////// -# mPSK mod/demod with steams of bytes as data i/o -# ///////////////////////////////////////////////////////////////////////////// - - -class mpsk_mod(gr.hier_block): - - def __init__(self, fg, spb, arity, excess_bw, diff=False): - """ - Hierarchical block for RRC-filtered PSK modulation. - - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: integer - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param arity: whick PSK: 2, 4, 8 - @type arity: int in {2, 4, 8} - @param diff: differential PSK if true - @type diff: bool - """ - if not isinstance(spb, int) or spb < 2: - raise TypeError, "sbp must be an integer >= 2" - self.spb = spb - - if not arity in (2, 4): - raise ValueError, "n must be 2, 4, or 8" - - ntaps = 11 * spb - - bits_per_symbol = int(gru.log2(arity)) - self.bits_per_symbol = bits_per_symbol - print "bits_per_symbol =", bits_per_symbol - - # turn bytes into k-bit vectors - self.bytes2chunks = \ - gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) - - if True or arity > 2: - self.gray_coder = gr.map_bb(binary_to_gray[arity]) - else: - self.gray_coder = None - - if diff: - self.diffenc = gr.diff_encoder_bb(arity) - else: - self.diffenc = None - - self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) - - # pulse shaping filter - self.rrc_taps = gr.firdes.root_raised_cosine( - spb, # gain (spb since we're interpolating by spb) - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) - - # Connect - if self.gray_coder: - fg.connect(self.bytes2chunks, self.gray_coder) - t = self.gray_coder - else: - t = self.bytes2chunks - - if diff: - fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) - else: - fg.connect(t, self.chunks2symbols, self.rrc_filter) - - if 1: - fg.connect(self.gray_coder, - gr.file_sink(gr.sizeof_char, "graycoder.dat")) - if diff: - fg.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "diffenc.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self): - return self.bits_per_symbol - - -class mpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): - def __init__(self, fg, spb, arity, excess_bw, diff=False, costas_alpha=0.005, gain_mu=0.05): - """ - Hierarchical block for RRC-filtered PSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param arity: whick PSK: 2, 4, 8 - @type arity: int in {2, 4, 8} - @param diff: differential PSK if true - @type diff: bool - @param costas_alpha: loop filter gain - @type costas_alphas: float - @param gain_mu: - @type gain_mu: float - """ - if spb < 2: - raise TypeError, "sbp must be >= 2" - self.spb = spb - - if not arity in (2, 4): - raise ValueError, "n must be 2 or 4" - - if not diff and arity==4: - raise NotImplementedError, "non-differential QPSK not supported yet" - - bits_per_symbol = int(gru.log2(arity)) - print "bits_per_symbol =", bits_per_symbol - - # Automatic gain control - self.agc = gr.agc_cc(1e-3, 1, 1) - - # Costas loop (carrier tracking) - # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? - if arity == 2: - costas_order = 2 - costas_alpha *= 15 # 2nd order loop needs more gain - else: - costas_order = 4 - beta = .25 * costas_alpha * costas_alpha - self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) - - # RRC data filter - ntaps = 11 * spb - self.rrc_taps = gr.firdes.root_raised_cosine( - 1.0, # gain - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) - - # symbol clock recovery - omega = spb - gain_omega = .25 * gain_mu * gain_mu - omega_rel_limit = 0.5 - mu = 0.05 - gain_mu = 0.1 - self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, - mu, gain_mu, omega_rel_limit) - - # find closest constellation point - #rot = .707 + .707j - rot = 1 - rotated_const = map(lambda pt: pt * rot, constellation[arity]) - print "rotated_const =", rotated_const - - if(diff): - self.diffdec = gr.diff_phasor_cc() - #self.diffdec = gr.diff_decoder_bb(arity) - - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - self.gray_decoder = gr.map_bb(gray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) - - if(diff): - fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - self.diffdec, self.slicer, self.gray_decoder, self.unpack) - else: - fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - self.slicer, self.gray_decoder, self.unpack) - - #fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - # self.slicer, self.diffdec, self.gray_decoder, self.unpack) - - # Debug sinks - if 1: - fg.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) - fg.connect(self.costas_loop, - gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) - fg.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) - fg.connect(self.clock_recovery, - gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) - fg.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "slicer.dat")) - if(diff): - fg.connect(self.diffdec, - gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) - #fg.connect(self.diffdec, - # gr.file_sink(gr.sizeof_char, "diffdec.dat")) - fg.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "unpack.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.agc, self.unpack) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self): - return self.bits_per_symbol - - -######################################################################### - -class mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk(gr.hier_block): - def __init__(self, fg, spb, arity, excess_bw, diff=False, costas_alpha=0.005, gain_mu=0.05): - """ - Hierarchical block for RRC-filtered PSK demodulation - - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (LSB) - - @param fg: flow graph - @type fg: flow graph - @param spb: samples per baud >= 2 - @type spb: float - @param excess_bw: Root-raised cosine filter excess bandwidth - @type excess_bw: float - @param arity: whick PSK: 2, 4, 8 - @type arity: int in {2, 4, 8} - @param diff: differential PSK if true - @type diff: bool - @param costas_alpha: loop filter gain - @type costas_alphas: float - @param gain_mu: - @type gain_mu: float - """ - if spb < 2: - raise TypeError, "sbp must be >= 2" - self.spb = spb - - if not arity in (2, 4): - raise ValueError, "n must be 2 or 4" - - bits_per_symbol = int(gru.log2(arity)) - print "bits_per_symbol =", bits_per_symbol - - # Automatic gain control - self.agc = gr.agc_cc(1e-3, 1, 1) - - # Costas loop (carrier tracking) - # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? - if arity == 2: - costas_order = 2 - costas_alpha *= 15 # 2nd order loop needs more gain - else: - costas_order = 4 - beta = .25 * costas_alpha * costas_alpha - self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) - - # RRC data filter - ntaps = 11 * spb - self.rrc_taps = gr.firdes.root_raised_cosine( - 1.0, # gain - spb, # sampling rate - 1.0, # symbol rate - excess_bw, # excess bandwidth (roll-off factor) - ntaps) - - self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) - - # symbol clock recovery - omega = spb - gain_omega = .25 * gain_mu * gain_mu - omega_rel_limit = 0.5 - mu = 0.05 - gain_mu = 0.1 - self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, - mu, gain_mu, omega_rel_limit) - - # find closest constellation point - #rot = .707 + .707j - rot = 1 - rotated_const = map(lambda pt: pt * rot, constellation[arity]) - print "rotated_const =", rotated_const - - self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) - self.gray_decoder = gr.map_bb(gray_to_binary[arity]) - - # unpack the k bit vector into a stream of bits - self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) - - fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, - self.slicer, self.gray_decoder, self.unpack) - - # Debug sinks - if 1: - fg.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) - fg.connect(self.costas_loop, - gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) - fg.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) - fg.connect(self.clock_recovery, - gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) - fg.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "slicer.dat")) - fg.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "unpack.dat")) - - # Initialize base class - gr.hier_block.__init__(self, fg, self.agc, self.unpack) - - def samples_per_baud(self): - return self.spb - - def bits_per_baud(self): - return self.bits_per_symbol - - -mpsk_demod = mpsk_demod__coherent_detection_of_differentially_encoded_psk -#mpsk_demod = mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk diff --git a/gnuradio-examples/python/gmsk2/receive_path.py b/gnuradio-examples/python/gmsk2/receive_path.py deleted file mode 100644 index c2eba7b76..000000000 --- a/gnuradio-examples/python/gmsk2/receive_path.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2005,2006 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 2, 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, blks -from gnuradio import usrp - -# from current dir -from pick_bitrate import pick_rx_bitrate - -# ///////////////////////////////////////////////////////////////////////////// -# receive path -# ///////////////////////////////////////////////////////////////////////////// - -class receive_path(gr.hier_block): - def __init__(self, fg, demod_class, rx_subdev_spec, - bitrate, decim, spb, - rx_callback, options, demod_kwargs): - - self.u = usrp.source_c (fusb_block_size=options.fusb_block_size, - fusb_nblocks=options.fusb_nblocks) - adc_rate = self.u.adc_rate() - - (self._bitrate, self._spb, self._decim) = \ - pick_rx_bitrate(bitrate, demod_class.bits_per_baud(), spb, decim, adc_rate) - - self.u.set_decim_rate(self._decim) - sw_decim = 1 - - if rx_subdev_spec is None: - rx_subdev_spec = usrp.pick_rx_subdevice(self.u) - self.subdev = usrp.selected_subdev(self.u, rx_subdev_spec) - print "Using RX d'board %s" % (self.subdev.side_and_name(),) - - self.u.set_mux(usrp.determine_rx_mux_value(self.u, rx_subdev_spec)) - - # Create filter to get actual channel we want - chan_coeffs = gr.firdes.low_pass (1.0, # gain - sw_decim * self._spb, # sampling rate - 1.0, # midpoint of trans. band - 0.1, # width of trans. band - gr.firdes.WIN_HANN) # filter type - - print "len(rx_chan_coeffs) =", len(chan_coeffs) - - # Decimating Channel filter - # complex in and out, float taps - self.chan_filt = gr.fft_filter_ccc(sw_decim, chan_coeffs) - #self.chan_filt = gr.fir_filter_ccf(sw_decim, chan_coeffs) - - # receiver - self.packet_receiver = \ - blks.demod_pkts(fg, - demod_class(fg, spb=self._spb, **demod_kwargs), - access_code=None, - callback=rx_callback, - threshold=-1) - - fg.connect(self.u, self.chan_filt, self.packet_receiver) - gr.hier_block.__init__(self, fg, None, None) - - g = self.subdev.gain_range() - #self.set_gain((g[0] + g[1])/2) # set gain to midpoint - self.set_gain(g[1]) # set gain to max - self.set_auto_tr(True) # enable Auto Transmit/Receive switching - - # Carrier Sensing Blocks - alpha = 0.001 - thresh = 30 # in dB, will have to adjust - self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha) - fg.connect(self.chan_filt, self.probe) - - 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. - """ - r = self.u.tune(0, self.subdev, target_freq) - if r: - return True - - return False - - def set_gain(self, gain): - if gain is None: - r = self.subdev.gain_range() - gain = (r[0] + r[1])/2 # set gain to midpoint - self.gain = gain - return self.subdev.set_gain(gain) - - def set_auto_tr(self, enable): - return self.subdev.set_auto_tr(enable) - - def bitrate(self): - return self._bitrate - - def spb(self): - return self._spb - - def decim(self): - return self._decim - - - def carrier_sensed(self): - """ - Return True if we think carrier is present. - """ - #return self.probe.level() > X - return self.probe.unmuted() - - def carrier_threshold(self): - """ - Return current setting in dB. - """ - return self.probe.threshold() - - def set_carrier_threshold(self, threshold_in_db): - """ - Set carrier threshold. - - @param threshold_in_db: set detection threshold - @type threshold_in_db: float (dB) - """ - self.probe.set_threshold(threshold_in_db) - diff --git a/gnuradio-examples/python/gmsk2/transmit_path.py b/gnuradio-examples/python/gmsk2/transmit_path.py deleted file mode 100644 index d360d1a5e..000000000 --- a/gnuradio-examples/python/gmsk2/transmit_path.py +++ /dev/null @@ -1,108 +0,0 @@ -# -# Copyright 2005,2006 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 2, 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, blks -from gnuradio import usrp - -# from current dir -from pick_bitrate import pick_tx_bitrate - -# ///////////////////////////////////////////////////////////////////////////// -# transmit path -# ///////////////////////////////////////////////////////////////////////////// - -class transmit_path(gr.hier_block): - def __init__(self, fg, mod_class, tx_subdev_spec, - bitrate, interp, spb, gain, - options, mod_kwargs): - - self.normal_gain = gain - - self.u = usrp.sink_c (fusb_block_size=options.fusb_block_size, - fusb_nblocks=options.fusb_nblocks) - dac_rate = self.u.dac_rate(); - - print mod_class - print mod_class.bits_per_baud() - (self._bitrate, self._spb, self._interp) = \ - pick_tx_bitrate(bitrate, mod_class.bits_per_baud(), spb, interp, dac_rate) - - self.u.set_interp_rate(self._interp) - - # determine the daughterboard subdevice we're using - if tx_subdev_spec is None: - tx_subdev_spec = usrp.pick_tx_subdevice(self.u) - self.u.set_mux(usrp.determine_tx_mux_value(self.u, tx_subdev_spec)) - self.subdev = usrp.selected_subdev(self.u, tx_subdev_spec) - print "Using TX d'board %s" % (self.subdev.side_and_name(),) - - # transmitter - self.packet_transmitter = \ - blks.mod_pkts(fg, - mod_class(fg, spb=self._spb, **mod_kwargs), - access_code=None, - msgq_limit=4, - pad_for_usrp=True) - - self.amp = gr.multiply_const_cc (self.normal_gain) - - fg.connect(self.packet_transmitter, self.amp, self.u) - gr.hier_block.__init__(self, fg, None, None) - - self.set_gain(self.subdev.gain_range()[1]) # set max Tx gain - self.set_auto_tr(True) # enable Auto Transmit/Receive switching - - 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. - """ - r = self.u.tune(self.subdev._which, self.subdev, target_freq) - if r: - return True - - return False - - def set_gain(self, gain): - self.gain = gain - self.subdev.set_gain(gain) - - def set_auto_tr(self, enable): - return self.subdev.set_auto_tr(enable) - - def send_pkt(self, payload='', eof=False): - return self.packet_transmitter.send_pkt(payload, eof) - - def bitrate(self): - return self._bitrate - - def spb(self): - return self._spb - - def interp(self): - return self._interp diff --git a/gnuradio-examples/python/mc4020/Makefile.am b/gnuradio-examples/python/mc4020/Makefile.am deleted file mode 100644 index 45f48b46b..000000000 --- a/gnuradio-examples/python/mc4020/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright 2004 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 2, 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. -# - -EXTRA_DIST = \ - fm_demod.py \ - mc4020_fft.py - - - - diff --git a/gnuradio-examples/python/mc4020/fm_demod.py b/gnuradio-examples/python/mc4020/fm_demod.py deleted file mode 100755 index e58407f73..000000000 --- a/gnuradio-examples/python/mc4020/fm_demod.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr -from gnuradio import audio -from gnuradio import mc4020 -import sys - -def high_speed_adc (fg, input_rate): - # return gr.file_source (gr.sizeof_short, "dummy.dat", False) - return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) - -# -# return a gr.flow_graph -# -def build_graph (freq1, freq2): - input_rate = 20e6 - cfir_decimation = 125 - audio_decimation = 5 - - quad_rate = input_rate / cfir_decimation - audio_rate = quad_rate / audio_decimation - - fg = gr.flow_graph () - - # use high speed ADC as input source - src = high_speed_adc (fg, input_rate) - - # compute FIR filter taps for channel selection - channel_coeffs = \ - gr.firdes.low_pass (1.0, # gain - input_rate, # sampling rate - 250e3, # low pass cutoff freq - 8*100e3, # width of trans. band - gr.firdes.WIN_HAMMING) - - # input: short; output: complex - chan_filter1 = \ - gr.freq_xlating_fir_filter_scf (cfir_decimation, - channel_coeffs, - freq1, # 1st station freq - input_rate) - - (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation) - - # sound card as final sink - audio_sink = audio.sink (int (audio_rate)) - - # now wire it all together - fg.connect (src, chan_filter1) - fg.connect (chan_filter1, head1) - fg.connect (tail1, (audio_sink, 0)) - - # two stations at once? - if freq2: - # Extract the second station and connect - # it to a second pipeline... - - # input: short; output: complex - chan_filter2 = \ - gr.freq_xlating_fir_filter_scf (cfir_decimation, - channel_coeffs, - freq2, # 2nd station freq - input_rate) - - (head2, tail2) = build_pipeline (fg, quad_rate, audio_decimation) - - fg.connect (src, chan_filter2) - fg.connect (chan_filter2, head2) - fg.connect (tail2, (audio_sink, 1)) - - return fg - -def build_pipeline (fg, quad_rate, audio_decimation): - '''Given a flow_graph, fg, construct a pipeline - for demodulating a broadcast FM signal. The - input is the downconverteed complex baseband - signal. The output is the demodulated audio. - - build_pipeline returns a two element tuple - containing the input and output endpoints. - ''' - fm_demod_gain = 2200.0/32768.0 - audio_rate = quad_rate / audio_decimation - volume = 1.0 - - # input: complex; output: float - fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) - - # compute FIR filter taps for audio filter - width_of_transition_band = audio_rate / 32 - audio_coeffs = gr.firdes.low_pass (1.0, # gain - quad_rate, # sampling rate - audio_rate/2 - width_of_transition_band, - width_of_transition_band, - gr.firdes.WIN_HAMMING) - - # input: float; output: float - audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) - - fg.connect (fm_demod, audio_filter) - return ((fm_demod, 0), (audio_filter, 0)) - - -def main (args): - nargs = len (args) - if nargs == 1: - freq1 = float (args[0]) * 1e6 - freq2 = None - elif nargs == 2: - freq1 = float (args[0]) * 1e6 - freq2 = float (args[1]) * 1e6 - else: - sys.stderr.write ('usage: fm_demod freq1 [freq2]\n') - sys.exit (1) - - # connect to RF front end - rf_front_end = gr.microtune_4937_eval_board () - if not rf_front_end.board_present_p (): - raise IOError, 'RF front end not found' - - # set front end gain - rf_front_end.set_AGC (300) - IF_freq = rf_front_end.get_output_freq () - IF_freq = 5.75e6 - - if not freq2: # one station - - rf_front_end.set_RF_freq (freq1) - fg = build_graph (IF_freq, None) - - else: # two stations - - if abs (freq1 - freq2) > 5.5e6: - raise IOError, 'freqs too far apart' - - target_freq = (freq1 + freq2) / 2 - actual_freq = rf_front_end.set_RF_freq (target_freq) - #actual_freq = target_freq - - fg = build_graph (IF_freq + freq1 - actual_freq, - IF_freq + freq2 - actual_freq) - - fg.start () # fork thread(s) and return - raw_input ('Press Enter to quit: ') - fg.stop () - -if __name__ == '__main__': - main (sys.argv[1:]) - - diff --git a/gnuradio-examples/python/mc4020/mc4020_fft.py b/gnuradio-examples/python/mc4020/mc4020_fft.py deleted file mode 100755 index d226b9ca8..000000000 --- a/gnuradio-examples/python/mc4020/mc4020_fft.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2004 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 2, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr -from gnuradio import mc4020 -from gnuradio.eng_option import eng_option -from gnuradio.wxgui import stdgui, fftsink -from optparse import OptionParser -import wx - -class app_flow_graph (stdgui.gui_flow_graph): - def __init__(self, frame, panel, vbox, argv): - stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) - - - parser = OptionParser (option_class=eng_option) - (options, args) = parser.parse_args () - - input_rate = 20e6 - src = mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) - cvt = gr.short_to_float () - block, fft_win = fftsink.make_fft_sink_f (self, panel, "Rx Data", 512, input_rate) - - self.connect (src, cvt) - self.connect (cvt, block) - vbox.Add (fft_win, 1, wx.EXPAND) - - -def main (): - app = stdgui.stdapp (app_flow_graph, "USRP FFT") - app.MainLoop () - -if __name__ == '__main__': - main () diff --git a/gnuradio-examples/python/usrp/usrp_siggen.py b/gnuradio-examples/python/usrp/usrp_siggen.py index 59e01e0a9..6a41f74b8 100755 --- a/gnuradio-examples/python/usrp/usrp_siggen.py +++ b/gnuradio-examples/python/usrp/usrp_siggen.py @@ -101,10 +101,10 @@ class my_graph(gr.flow_graph): """ r = self.u.tune(self.subdev._which, self.subdev, target_freq) if r: - print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq) - print "r.dxc_freq =", eng_notation.num_to_str(r.dxc_freq) - print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq) - print "r.inverted =", r.inverted + #print "r.baseband_freq =", eng_notation.num_to_str(r.baseband_freq) + #print "r.dxc_freq =", eng_notation.num_to_str(r.dxc_freq) + #print "r.residual_freq =", eng_notation.num_to_str(r.residual_freq) + #print "r.inverted =", r.inverted return True return False |