summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-sounder/README80
-rw-r--r--gr-sounder/src/fpga/tb/sounder_tb.sav8
-rw-r--r--gr-sounder/src/fpga/tb/sounder_tb.v4
-rw-r--r--gr-sounder/src/python/Makefile.am15
-rw-r--r--gr-sounder/src/python/sounder.py233
-rwxr-xr-xgr-sounder/src/python/sounder_loopback.sh4
-rwxr-xr-xgr-sounder/src/python/test_lp.sh4
-rwxr-xr-xgr-sounder/src/python/test_rx.sh4
-rwxr-xr-xgr-sounder/src/python/test_tx.sh3
-rwxr-xr-xgr-sounder/src/python/usrp_sounder.py198
10 files changed, 367 insertions, 186 deletions
diff --git a/gr-sounder/README b/gr-sounder/README
index ef495f1e8..3c5df21d4 100644
--- a/gr-sounder/README
+++ b/gr-sounder/README
@@ -1,10 +1,9 @@
This is a work-in-progress implementation of a m-sequence based channel
sounder for GNU Radio and the USRP.
-At present, only the transmitter is implemented. When completed, you
-will be able to place the sounder transmitter at one location, the
-sounder receiver at another location, then determine in real-time the
-channel impulse and frequency response between them.
+In typical use, the user would run the sounder as a transmitter on one
+USRP, and a receiver on another at a different location. The receiver
+will determine the impulse response of the RF channel in between.
The sounder uses a custom FPGA bitstream that is able to generate and
receive a sounder waveform across a full 32 MHz wide swath of RF spectrum;
@@ -17,45 +16,76 @@ out this response during calibration.
The sounder is based on sending a maximal-length PN code modulated as BPSK
with the supplied center frequency, with a chip-rate of 32 MHz. The
-receiver (partially implemented at this time but not working yet) correlates
-the received signal across all phases of the PN code and outputs an impulse
-response vector. As auto-correlation of an m-sequence is near zero for
-any relative phase shift, the actual measured energy at a particular
-phase shift is related to the impulse response for that time delay. This
-is the same principle used in spread-spectrum RAKE receivers such as are
+receiver correlates the received signal across all phases of the PN code
+and outputs an impulse response vector. As auto-correlation of an m-sequence
+is near zero for any relative phase shift, the actual measured energy at a
+particular phase shift is related to the impulse response for that time delay.
+This is the same principle used in spread-spectrum RAKE receivers such as are
used with GPS and CDMA.
-The transmitter and receiver are designed to work only with the board in
-side A. This may be a standalone LFTX/LFRX or an RFX daughterboard.
+The transmitter is designed to work only with the board in side A. The
+receiver may be in side A or side B. The boards may be standalone LFTX/LFRXs
+or RFX daughterboards.
To use, the following script is installed into $prefix/bin:
-usage: usrp_sounder.py [options]
+Usage: usrp_sounder.py [options]
-options:
+Options:
-h, --help show this help message and exit
+ -R RX_SUBDEV_SPEC, --rx-subdev-spec=RX_SUBDEV_SPEC
+ select USRP Rx side A or B
-f FREQ, --frequency=FREQ
set frequency to FREQ in Hz, default is 0.0
+ -d DEGREE, --degree=DEGREE
+ set sounding sequence degree (2-12), default is 12,
-t, --transmit enable sounding transmitter
-r, --receive enable sounding receiver
- -d DEGREE, --degree=DEGREE
- set souding sequence degree (len=2^degree-1), default
- is 16
- -n SAMPLES, --samples=SAMPLES
- number of samples to capture on receive, default is
- infinite
-l, --loopback enable digital loopback, default is disabled
+ -v, --verbose enable verbose output, default is disabled
+ -D, --debug enable debugging output, default is disabled
+ -F FILENAME, --filename=FILENAME
+ log received impulse responses to file
To use with an LFTX board, set the center frequency to 16M:
$ usrp_sounder.py -f 16M -t
-You can vary the m-sequence degree between 1 and 16, which will create
-sequence lengths between 1 (DC) and 65535 (1.023 us). This will affect
-how frequently the receiver can calculate impulse response vectors (to be
-documented as the receiver is completed.)
+The sounder receiver command line is:
+
+$ usrp_sounder.py -f 16M -r -F output.dat
+
+You can vary the m-sequence degree between 2 and 12, which will create
+sequence lengths between 3 and 4095 (128 us). This will affect
+how frequently the receiver can calculate impulse response vectors.
+
+The correlator uses an O(N^2) algorithm, by using an entire PN period
+of the received signal to correlate at each lag value. Thus, using a
+degree 12 PN code of length 4095, it takes 4095*4095/32e6 seconds to
+calculate a single impulse response vector, about a half a second. One
+can reduce this time by a factor of 4 for each decrement in PN code
+degree, but this also reduces the inherent processing gain by 6 dB as
+well.
+
+The impulse response vectors are written to a file in complex float
+format, and consist of the actual impulse response with a noise floor
+dependent on the PN code degree in use.
+
+There is a loopback test mode that causes the sounding waveform to be
+routed back to the receiver inside the USRP:
+
+$ usrp_sounder.py -r -t -l -F output.dat
+
+The resulting impulse response will be a spike followed by a near zero
+value for the rest of the period.
+
+Synchronization at the receiver is not yet implemented, so the actual
+impulse response may be time shifted an arbitrary value within the the
+impulse response vector. If one assumes the first to arrive signal is
+the strongest, then one can circularly rotate the vector until the peak
+is at time zero.
Johnathan Corgan
Corgan Enterprises LLC
jcorgan@corganenterprises.com
-4/25/07
+5/28/07
diff --git a/gr-sounder/src/fpga/tb/sounder_tb.sav b/gr-sounder/src/fpga/tb/sounder_tb.sav
index 74019f5ee..3a73a9445 100644
--- a/gr-sounder/src/fpga/tb/sounder_tb.sav
+++ b/gr-sounder/src/fpga/tb/sounder_tb.sav
@@ -1,4 +1,4 @@
-*-26.117517 250000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-24.753519 93900000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
@28
sounder_tb.uut.clk_i
sounder_tb.rst
@@ -23,7 +23,9 @@ sounder_tb.tx_dac_i[13:0]
-
@22
sounder_tb.fifo_strobe
+@8421
sounder_tb.fifo_i[15:0]
+@22
sounder_tb.fifo_q[15:0]
@200
-
@@ -32,3 +34,7 @@ sounder_tb.uut.transmitter.pn_code.pn_o
sounder_tb.uut.receiver.pn_ref
@200
-
+@28
+sounder_tb.tx_strobe
+@8420
+sounder_tb.uut.receiver.sum_i[31:0]
diff --git a/gr-sounder/src/fpga/tb/sounder_tb.v b/gr-sounder/src/fpga/tb/sounder_tb.v
index 045791e43..6a9eff0ea 100644
--- a/gr-sounder/src/fpga/tb/sounder_tb.v
+++ b/gr-sounder/src/fpga/tb/sounder_tb.v
@@ -197,14 +197,14 @@ module sounder_tb;
#20 enable_rx(1);
#20 enable_lp(1);
#20 set_reset(0);
- #((uut.len+1)*uut.len*20);
+ #((uut.len+1)*uut.len*20*2);
end
endtask // test_lp
// Execute tests
initial
begin
- #20 test_tx(12);
+ // #20 test_tx(12);
#20 test_lp(12);
#100 $finish;
end
diff --git a/gr-sounder/src/python/Makefile.am b/gr-sounder/src/python/Makefile.am
index 7ce181271..16f7ff035 100644
--- a/gr-sounder/src/python/Makefile.am
+++ b/gr-sounder/src/python/Makefile.am
@@ -21,12 +21,23 @@
include $(top_srcdir)/Makefile.common
+# Install this stuff so that it ends up as the gnuradio.sounder module
+# This usually ends up at:
+# ${prefix}/lib/python${python_version}/site-packages/gnuradio
+
+ourpythondir = $(grpythondir)
+ourlibdir = $(grpyexecdir)
+
EXTRA_DIST = \
- usrp_sounder.py \
+ usrp_sounder.py \
+ sounder_loopback.sh \
qa_nothing.py \
run_tests.in
bin_SCRIPTS = \
usrp_sounder.py
-MOSTLYCLEANFILES = *~ *.pyc *.pyo output.*
+ourpython_PYTHON = \
+ sounder.py
+
+MOSTLYCLEANFILES = *~ *.pyc *.pyo \ No newline at end of file
diff --git a/gr-sounder/src/python/sounder.py b/gr-sounder/src/python/sounder.py
new file mode 100644
index 000000000..b3c5423c4
--- /dev/null
+++ b/gr-sounder/src/python/sounder.py
@@ -0,0 +1,233 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 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, usrp
+from gnuradio import eng_notation
+
+n2s = eng_notation.num_to_str
+
+FR_MODE = usrp.FR_USER_0
+bmFR_MODE_RESET = 1 << 0 # bit 0: active high reset
+bmFR_MODE_TX = 1 << 1 # bit 1: enable transmitter
+bmFR_MODE_RX = 1 << 2 # bit 2: enable receiver
+bmFR_MODE_LP = 1 << 3 # bit 3: enable digital loopback
+
+FR_DEGREE = usrp.FR_USER_1
+
+def pick_subdevice(u):
+ """
+ The user didn't specify a subdevice on the command line.
+ If there's a daughterboard on A, select A.
+ If there's a daughterboard on B, select B.
+ Otherwise, select A.
+ """
+ if u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem
+ return (0, 0)
+ if u.db[1][0].dbid() >= 0:
+ return (1, 0)
+ return (0, 0)
+
+class sounder_tx:
+ def __init__(self, loopback=False,verbose=False):
+ self._loopback=loopback
+ self._verbose = verbose
+ self._u = usrp.sink_s(fpga_filename='usrp_sounder.rbf')
+ if not self._loopback:
+ self._subdev_spec = usrp.pick_tx_subdevice(self._u)
+ self._subdev = usrp.selected_subdev(self._u, self._subdev_spec)
+ if self._verbose:
+ print "Using", self._subdev.name(), "for sounder transmitter."
+ self._u.start()
+
+ def tune(self, frequency):
+ if self._verbose:
+ print "Setting transmitter frequency to", n2s(frequency)
+ result = self._u.tune(0, self._subdev, frequency)
+ if result == False:
+ raise RuntimeError("Failed to set transmitter frequency.")
+
+class sounder_rx:
+ def __init__(self,subdev_spec=None,length=1,msgq=None,loopback=False,verbose=False,debug=False):
+ self._subdev_spec = subdev_spec
+ self._length = length
+ self._msgq = msgq
+ self._loopback = loopback
+ self._verbose = verbose
+ self._debug = debug
+
+ self._fg = gr.flow_graph()
+ self._u = usrp.source_c(fpga_filename='usrp_sounder.rbf')
+ if not self._loopback:
+ if self._subdev_spec == None:
+ self._subdev_spec = pick_subdevice(self._u)
+ self._u.set_mux(usrp.determine_rx_mux_value(self._u, self._subdev_spec))
+ self._subdev = usrp.selected_subdev(self._u, self._subdev_spec)
+ if self._verbose:
+ print "Using", self._subdev.name(), "for sounder receiver."
+
+ self._vblen = gr.sizeof_gr_complex*self._length
+ if self._debug:
+ print "Generating impulse vectors of length", self._length, "byte length", self._vblen
+
+ self._s2v = gr.stream_to_vector(gr.sizeof_gr_complex, self._length)
+ self._sink = gr.message_sink(self._vblen, self._msgq, True)
+ self._fg.connect(self._u, self._s2v, self._sink)
+
+ def tune(self, frequency):
+ if self._verbose:
+ print "Setting receiver frequency to", n2s(frequency)
+ result = self._u.tune(0, self._subdev, frequency)
+ if result == False:
+ raise RuntimeError("Failed to set receiver frequency.")
+
+ def start(self):
+ if self._debug:
+ print "Starting receiver flow graph."
+ self._fg.start()
+
+ def wait(self):
+ if self._debug:
+ print "Waiting for threads..."
+ self._fg.wait()
+
+ def stop(self):
+ if self._debug:
+ print "Stopping receiver flow graph."
+ self._fg.stop()
+ self.wait()
+ if self._debug:
+ print "Receiver flow graph stopped."
+
+
+class sounder:
+ def __init__(self,transmit=False,receive=False,loopback=False,rx_subdev_spec=None,
+ frequency=0.0,degree=10,length=1,msgq=None,verbose=False,debug=False):
+ self._transmit = transmit
+ self._receive = receive
+ self._loopback = loopback
+ self._rx_subdev_spec = rx_subdev_spec
+ self._frequency = frequency
+ self._degree = degree
+ self._length = length
+ self._msgq = msgq
+ self._verbose = verbose
+ self._debug = debug
+ self._mode = 0
+ self._u = None
+ self._trans = None
+ self._rcvr = None
+ self._transmitting = False
+ self._receiving = False
+
+ if self._transmit:
+ self._trans = sounder_tx(loopback=self._loopback,verbose=self._verbose)
+ self._u = self._trans._u
+
+ if self._receive:
+ self._rcvr = sounder_rx(subdev_spec=self._rx_subdev_spec,length=self._length,
+ msgq=self._msgq,loopback=self._loopback,verbose=self._verbose,
+ debug=self._debug)
+ self._u = self._rcvr._u # either receiver or transmitter object will do
+
+ self.set_reset(True)
+ if self._loopback == False:
+ self.tune(self._frequency)
+ self.set_degree(self._degree)
+ self.set_loopback(self._loopback)
+ self.set_reset(False)
+
+ def tune(self, frequency):
+ self._frequency = frequency
+ if self._rcvr:
+ self._rcvr.tune(frequency)
+ if self._trans:
+ self._trans.tune(frequency)
+
+ def set_degree(self, degree):
+ if self._verbose:
+ print "Setting PN code degree to", degree
+ self._u._write_fpga_reg(FR_DEGREE, degree);
+
+ def _write_mode(self):
+ if self._debug:
+ print "Writing mode register with:", hex(self._mode)
+ self._u._write_fpga_reg(FR_MODE, self._mode)
+
+ def enable_tx(self, value):
+ if value:
+ if self._verbose:
+ print "Enabling transmitter."
+ self._mode |= bmFR_MODE_TX
+ self._transmitting = True
+ else:
+ if self._verbose:
+ print "Disabling transmitter."
+ self._mode &= ~bmFR_MODE_TX
+ self._write_mode()
+
+ def enable_rx(self, value):
+ if value:
+ self._mode |= bmFR_MODE_RX
+ self._write_mode()
+ self._rcvr.start()
+ self._receiving = True
+ else:
+ self._rcvr.stop()
+ self._mode &= ~bmFR_MODE_RX
+ self._write_mode()
+ self._receiving = False
+
+ def set_loopback(self, value):
+ if value:
+ if self._verbose:
+ print "Enabling digital loopback."
+ self._mode |= bmFR_MODE_LP
+ else:
+ if self._verbose:
+ print "Disabling digital loopback."
+ self._mode &= ~bmFR_MODE_LP
+ self._write_mode()
+
+ def set_reset(self, value):
+ if value:
+ if self._debug:
+ print "Asserting reset."
+ self._mode |= bmFR_MODE_RESET
+ else:
+ if self._debug:
+ print "De-asserting reset."
+ self._mode &= ~bmFR_MODE_RESET
+ self._write_mode()
+
+ def start(self):
+ if self._transmit:
+ self.enable_tx(True)
+ if self._receive:
+ self.enable_rx(True)
+
+ def __del__(self):
+ if self._transmitting:
+ self.enable_tx(False)
+
+ if self._receiving:
+ self.enable_rx(False)
+
diff --git a/gr-sounder/src/python/sounder_loopback.sh b/gr-sounder/src/python/sounder_loopback.sh
new file mode 100755
index 000000000..a97a8fdcf
--- /dev/null
+++ b/gr-sounder/src/python/sounder_loopback.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# Note this runs the installed script, not the one in the tree
+usrp_sounder.py -r -l -t -d12 -v -F loopback.dat -D
diff --git a/gr-sounder/src/python/test_lp.sh b/gr-sounder/src/python/test_lp.sh
deleted file mode 100755
index fbcc3f533..000000000
--- a/gr-sounder/src/python/test_lp.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-usrp_sounder.py -r -l -t -n5000 -d12
-hexdump output.dat >output.hex
diff --git a/gr-sounder/src/python/test_rx.sh b/gr-sounder/src/python/test_rx.sh
deleted file mode 100755
index 21998b4de..000000000
--- a/gr-sounder/src/python/test_rx.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-
-usrp_sounder.py -r -n5000 -d12
-hexdump output.dat >output.hex
diff --git a/gr-sounder/src/python/test_tx.sh b/gr-sounder/src/python/test_tx.sh
deleted file mode 100755
index f29ba1f34..000000000
--- a/gr-sounder/src/python/test_tx.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-usrp_sounder.py -t -f 16M -d12
diff --git a/gr-sounder/src/python/usrp_sounder.py b/gr-sounder/src/python/usrp_sounder.py
index 31e766ef5..4aada45d6 100755
--- a/gr-sounder/src/python/usrp_sounder.py
+++ b/gr-sounder/src/python/usrp_sounder.py
@@ -20,174 +20,82 @@
# Boston, MA 02110-1301, USA.
#
-from gnuradio import gr, usrp
+from gnuradio import gr
+from gnuradio.sounder import sounder
from gnuradio import eng_notation
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-import sys, time
+import sys
n2s = eng_notation.num_to_str
-FR_MODE = usrp.FR_USER_0
-bmFR_MODE_RESET = 1 << 0 # bit 0: active high reset
-bmFR_MODE_TX = 1 << 1 # bit 1: enable transmitter
-bmFR_MODE_RX = 1 << 2 # bit 2: enable receiver
-bmFR_MODE_LP = 1 << 3 # bit 3: enable digital loopback
-
-FR_DEGREE = usrp.FR_USER_1
-
-class sounder:
- def __init__(self, options):
- self._options = options
- self._mode = 0
-
- self._u = None
- self._trans = None
- self._rcvr = None
- self._transmitting = False
- self._receiving = False
-
- if options.transmit:
- print "Creating sounder transmitter."
- self._trans = usrp.sink_s(fpga_filename='usrp_sounder.rbf')
- self._trans_subdev_spec = usrp.pick_tx_subdevice(self._trans)
- self._trans_subdev = usrp.selected_subdev(self._trans, self._trans_subdev_spec)
- self._trans.start()
- self._u = self._trans
-
- if options.receive:
- print "Creating sounder receiver."
- self._fg = gr.flow_graph()
- self._rcvr = usrp.source_s(fpga_filename='usrp_sounder.rbf', decim_rate=128)
- self._rcvr_subdev_spec = usrp.pick_rx_subdevice(self._rcvr)
- self._rcvr_subdev = usrp.selected_subdev(self._rcvr, self._rcvr_subdev_spec)
- self._sink = gr.file_sink(gr.sizeof_short, "output.dat")
-
- if options.samples >= 0:
- self._head = gr.head(gr.sizeof_short, options.samples*gr.sizeof_short)
- self._fg.connect(self._rcvr, self._head, self._sink)
- else:
- self._fg.connect(self._rcvr, self._sink)
- self._u = self._rcvr # either receiver or transmitter object will do
-
- self.set_reset(True)
- self.set_freq(options.frequency)
- self.set_degree(options.degree)
- self.set_loopback(options.loopback)
- self.set_reset(False)
-
- def set_freq(self, frequency):
- print "Setting center frequency to", n2s(frequency)
- if self._rcvr:
- self._rcvr.tune(0, self._rcvr_subdev, frequency)
-
- if self._trans:
- self._trans.tune(0, self._trans_subdev, frequency)
-
- def set_degree(self, degree):
- print "Setting PN code degree to", degree
- self._u._write_fpga_reg(FR_DEGREE, degree);
-
- def _write_mode(self):
- print "Writing mode register with:", hex(self._mode)
- self._u._write_fpga_reg(FR_MODE, self._mode)
-
- def enable_tx(self, value):
- if value:
- print "Enabling transmitter."
- self._mode |= bmFR_MODE_TX
- self._transmitting = True
- else:
- print "Disabling transmitter."
- self._mode &= ~bmFR_MODE_TX
- self._write_mode()
-
- def enable_rx(self, value):
- if value:
- print "Starting receiver flow graph."
- self._mode |= bmFR_MODE_RX
- self._write_mode()
- self._fg.start()
- self._receiving = True
- if self._options.samples >= 0:
- self._fg.wait()
- else:
- print "Stopping receiver flow graph."
- if self._options.samples < 0:
- self._fg.stop()
- print "Waiting for threads..."
- self._fg.wait()
- print "Receiver flow graph stopped."
- self._mode &= ~bmFR_MODE_RX
- self._write_mode()
- self._receiving = False
-
- def set_loopback(self, value):
- if value:
- print "Enabling digital loopback."
- self._mode |= bmFR_MODE_LP
- else:
- print "Disabling digital loopback."
- self._mode &= ~bmFR_MODE_LP
- self._write_mode()
-
- def set_reset(self, value):
- if value:
- print "Asserting reset."
- self._mode |= bmFR_MODE_RESET
- else:
- print "De-asserting reset."
- self._mode &= ~bmFR_MODE_RESET
- self._write_mode()
-
- def __del__(self):
- if self._transmitting:
- self.enable_tx(False)
-
- if self._receiving:
- self.enable_rx(False)
-
-# ------------------------------------------------------------------------------
-
def main():
parser = OptionParser(option_class=eng_option)
+ parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0),
+ help="select USRP Rx side A or B")
parser.add_option("-f", "--frequency", type="eng_float", default=0.0,
help="set frequency to FREQ in Hz, default is %default", metavar="FREQ")
-
- parser.add_option("-d", "--degree", type="int", default=16,
- help="set souding sequence degree (len=2^degree-1), default is %default")
-
+ parser.add_option("-d", "--degree", type="int", default=12,
+ help="set sounding sequence degree (2-12), default is %default,")
parser.add_option("-t", "--transmit", action="store_true", default=False,
help="enable sounding transmitter")
-
parser.add_option("-r", "--receive", action="store_true", default=False,
help="enable sounding receiver")
-
- parser.add_option("-n", "--samples", type="int", default=-1,
- help="number of samples to capture on receive, default is infinite")
-
parser.add_option("-l", "--loopback", action="store_true", default=False,
help="enable digital loopback, default is disabled")
-
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="enable verbose output, default is disabled")
+ parser.add_option("-D", "--debug", action="store_true", default=False,
+ help="enable debugging output, default is disabled")
+ parser.add_option("-F", "--filename", default=None,
+ help="log received impulse responses to file")
+
(options, args) = parser.parse_args()
if len(args) != 0 or not (options.transmit | options.receive):
parser.print_help()
sys.exit(1)
- print "Using PN code degree of", options.degree, "length", 2**options.degree-1
- print "Sounding frequency range is", n2s(options.frequency-16e6), "to", n2s(options.frequency+16e6)
-
- s = sounder(options)
-
- if options.transmit:
- s.enable_tx(True)
+ if options.receive and (options.filename == None):
+ print "Must supply filename when receiving."
+ sys.exit(1)
+
+ if options.degree > 12 or options.degree < 2:
+ print "PN code degree must be between 2 and 12"
+ sys.exit(1)
+
+ length = int(2**options.degree-1)
+ if options.verbose:
+ print "Using PN code degree of", options.degree, "length", length
+ if options.loopback == False:
+ print "Sounding frequency range is", n2s(options.frequency-16e6), "to", n2s(options.frequency+16e6)
+ if options.filename != None:
+ print "Logging impulse records to file: ", options.filename
+
+ msgq = gr.msg_queue()
+ s = sounder(transmit=options.transmit,receive=options.receive,loopback=options.loopback,
+ rx_subdev_spec=options.rx_subdev_spec,frequency=options.frequency,degree=options.degree,
+ length=length,msgq=msgq,verbose=options.verbose,debug=options.debug)
+ s.start()
if options.receive:
- s.enable_rx(True)
-
- if options.samples < 0:
- raw_input("Press enter to exit.")
-
+ f = open(options.filename, "wb")
+ print "Enter CTRL-C to stop."
+ try:
+ while (1):
+ msg = msgq.delete_head()
+ if msg.type() == 1:
+ break
+ rec = msg.to_string()[:length*gr.sizeof_gr_complex]
+ if options.debug:
+ print "Received impulse vector of length", len(rec)
+ f.write(rec)
+
+ except KeyboardInterrupt:
+ pass
+ else:
+ if options.transmit:
+ raw_input("Press return to exit.")
+
if __name__ == "__main__":
main()