summaryrefslogtreecommitdiff
path: root/gr-digital/examples/narrowband
diff options
context:
space:
mode:
Diffstat (limited to 'gr-digital/examples/narrowband')
-rw-r--r--gr-digital/examples/narrowband/README153
-rwxr-xr-xgr-digital/examples/narrowband/benchmark_rx.py6
-rwxr-xr-xgr-digital/examples/narrowband/benchmark_tx.py6
-rwxr-xr-xgr-digital/examples/narrowband/digital_bert_rx.py2
-rwxr-xr-xgr-digital/examples/narrowband/digital_bert_tx.py2
-rwxr-xr-xgr-digital/examples/narrowband/rx_voice.py2
-rwxr-xr-xgr-digital/examples/narrowband/tunnel.py8
-rw-r--r--gr-digital/examples/narrowband/uhd_interface.py38
8 files changed, 191 insertions, 26 deletions
diff --git a/gr-digital/examples/narrowband/README b/gr-digital/examples/narrowband/README
new file mode 100644
index 000000000..1c50ad69b
--- /dev/null
+++ b/gr-digital/examples/narrowband/README
@@ -0,0 +1,153 @@
+Quick overview of what's here:
+
+* 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 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_rx.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.
+There are two levels of error reporting going on. If the access code
+(PN code) and header of a packet were properly detected, then you'll
+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. 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).
+
+Generally speaking, I start the rx first on one machine, and then fire
+up the tx on the other machine. The tx also supports a discontinous
+transmission mode where it sends bursts of 5 packets and then waits 1
+second. This is useful for ensuring that all the receiver control
+loops lock up fast enough.
+
+* tunnel.py: This program provides a framework for building your own
+MACs. It creates a "TAP" interface in the kernel, typically gr0,
+and sends and receives ethernet frames through it. See
+/usr/src/linux/Documentation/networking/tuntap.txt and/or Google for
+"universal tun tap". The Linux 2.6 kernel includes the tun module, you
+don't have to build it. You may have to "modprobe tun" if it's not
+loaded by default. If /dev/net/tun doesn't exist, try "modprobe tun".
+
+To run this program you'll need to be root or running with the
+appropriate capability to open the tun interface. You'll need to fire
+up two copies on different machines. Once each is running you'll need
+to ifconfig the gr0 interface to set the IP address.
+
+This will allow two machines to talk, but anything beyond the two
+machines depends on your networking setup. Left as an exercise...
+
+On machine A:
+
+ $ su
+ # ./tunnel.py --freq 423.0M --bitrate 500k
+ # # in another window on A, also as root...
+ # ifconfig gr0 192.168.200.1
+
+
+On machine B:
+
+ $ su
+ # ./tunnel.py --freq 423.0M --bitrate 500k
+ # # in another window on B, also as root...
+ # ifconfig gr0 192.168.200.2
+
+Now, on machine A you shold be able to ping machine B:
+
+ $ 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 192.168.200.1
+
+This now uses a carrier sense MAC, so you should be able to ssh
+between the machines, web browse, etc.
+
+* run_length.py: This program takes a single argument '-f FILE' and
+outputs the number of runs of similar bits within the file. It is
+useful as a diagnostic tool when experimenting with line coding or
+whitening algorithms.
+
+
+
+**********************************************************************
+**********************************************************************
+
+
+BERT testing example scripts
+
+benchmark_tx.py
+
+This sets up a BPSK transmitter that is modulated with a pseudorandom
+sequence of bits. The PN code is generated by sending an all 1s
+sequence through a 7-bit scrambler. The transmitter performs the BPSK
+modulation, then passes the complex baseband waveform through a
+root-raised-cosine filter and onto the USRP.
+
+The --sps parameter controls how many baseband samples per symbol
+are created and passed through the RRC filter, prior to going to the
+USRP over the USB for interpolation to the final DAC rate.
+
+The baseband bit rate is controlled by -r or --rate. This value, when
+multiplied by the --sps parameter, must result in valid interpolation
+rate for the USRP. For example, if the baseband rate is 250k bits/sec,
+and the samples per symbol is 4, then the final rate is 1M samples/sec,
+which results in an interpolation rate of 128. The valid interpolation
+rates for the USRP are multiples of 4 between 16 and 512.
+
+Finally, the RRC excess bandwidth may be specified by --excess-bw.
+(See ./benchmark_tx.py -h for additional parameters.)
+
+
+benchmark_rx.py
+
+This sets up a BPSK receiver to demodulate the received waveform. It
+accepts a similar set of parameters as the transmitter, except that one
+specifies the USRP decimation rate desired. The resulting sample stream
+rate must be an integral number of baseband symbols. For example, the
+parameters corresponding to the above transmitter would be to use a
+decimation rate of 8 (32 sps), 16 (16 sps), 32 (8 sps), 64, (4 sps), or
+128 (2 sps). The lower the USRP decimation, the more CPU is required to
+demodulate the signal, so not all valid decimation rates will work.
+
+The baseband signal from the USRP is first passed through an AGC to
+establish an average power of 1.0. It is then passed through a matched
+filter (another RRC), a Costas phase-locked loop, and a Mueller and
+Muller bit timing recovery loop. The resulting constellation has an SNR
+estimation probe attached, and is then sliced into a bit stream.
+
+The recovered bits are then passed through a 7-bit descrambler. If
+there are no channel errors, the all 1s sequence is recovered. In the
+event of a channel error, there will be a 0 in the bit stream for each
+feedback tap in the descrambler. In this case, the CCSDS descrambler is
+using 3 feedback taps.
+
+Finally, the signal is passed into a bit density measurement probe. The
+channel BER is measured by dividing the 0s density by three. This
+measurement is inaccurate at high BER rates (>10%) as the error 0s
+begin to overlap.
+
+The benchmark script will, once per second, output the Costas loop
+frequency offset, the recovered timing error, the estimated SNR, and the
+average BER.
+
+NOTE: The particular SNR estimator used is inaccurate below about 7dB,
+and will report erroneously high values even for random noise.
+
+There are a variety of Costas and M&M loop parameters one can adjust.
+See ./benchmark_rx.py -h for the full set.
+
+
diff --git a/gr-digital/examples/narrowband/benchmark_rx.py b/gr-digital/examples/narrowband/benchmark_rx.py
index 65aac3638..32c3222ae 100755
--- a/gr-digital/examples/narrowband/benchmark_rx.py
+++ b/gr-digital/examples/narrowband/benchmark_rx.py
@@ -44,7 +44,11 @@ class my_top_block(gr.top_block):
gr.top_block.__init__(self)
if(options.rx_freq is not None):
- self.source = uhd_receiver(options.address, options.bitrate,
+ # Work-around to get the modulation's bits_per_symbol
+ args = demodulator.extract_kwargs_from_options(options)
+ symbol_rate = options.bitrate / demodulator(**args).bits_per_symbol()
+
+ self.source = uhd_receiver(options.args, symbol_rate,
options.samples_per_symbol,
options.rx_freq, options.rx_gain,
options.antenna, options.verbose)
diff --git a/gr-digital/examples/narrowband/benchmark_tx.py b/gr-digital/examples/narrowband/benchmark_tx.py
index 1fd881981..25ed355da 100755
--- a/gr-digital/examples/narrowband/benchmark_tx.py
+++ b/gr-digital/examples/narrowband/benchmark_tx.py
@@ -43,7 +43,11 @@ class my_top_block(gr.top_block):
gr.top_block.__init__(self)
if(options.tx_freq is not None):
- self.sink = uhd_transmitter(options.address, options.bitrate,
+ # Work-around to get the modulation's bits_per_symbol
+ args = modulator.extract_kwargs_from_options(options)
+ symbol_rate = options.bitrate / modulator(**args).bits_per_symbol()
+
+ self.sink = uhd_transmitter(options.args, symbol_rate,
options.samples_per_symbol,
options.tx_freq, options.tx_gain,
options.antenna, options.verbose)
diff --git a/gr-digital/examples/narrowband/digital_bert_rx.py b/gr-digital/examples/narrowband/digital_bert_rx.py
index 9878f55e1..28331310d 100755
--- a/gr-digital/examples/narrowband/digital_bert_rx.py
+++ b/gr-digital/examples/narrowband/digital_bert_rx.py
@@ -113,7 +113,7 @@ class rx_psk_block(gr.top_block):
self._demodulator = self._demodulator_class(**demod_kwargs)
if(options.rx_freq is not None):
- self._source = uhd_receiver(options.address, options.bitrate,
+ self._source = uhd_receiver(options.args, options.bitrate,
options.samples_per_symbol,
options.rx_freq, options.rx_gain,
options.antenna, options.verbose)
diff --git a/gr-digital/examples/narrowband/digital_bert_tx.py b/gr-digital/examples/narrowband/digital_bert_tx.py
index 96cb338fe..46f4f9097 100755
--- a/gr-digital/examples/narrowband/digital_bert_tx.py
+++ b/gr-digital/examples/narrowband/digital_bert_tx.py
@@ -67,7 +67,7 @@ class tx_psk_block(gr.top_block):
self._modulator = self._modulator_class(**mod_kwargs)
if(options.tx_freq is not None):
- self._sink = uhd_transmitter(options.address, options.bitrate,
+ self._sink = uhd_transmitter(options.args, options.bitrate,
options.samples_per_symbol,
options.tx_freq, options.tx_gain,
options.antenna, options.verbose)
diff --git a/gr-digital/examples/narrowband/rx_voice.py b/gr-digital/examples/narrowband/rx_voice.py
index 42d7b893b..100caff8e 100755
--- a/gr-digital/examples/narrowband/rx_voice.py
+++ b/gr-digital/examples/narrowband/rx_voice.py
@@ -66,7 +66,7 @@ class my_top_block(gr.top_block):
self.audio_tx = audio_tx(options.audio_output)
if(options.rx_freq is not None):
- self.source = uhd_receiver(options.address, options.bitrate,
+ self.source = uhd_receiver(options.args, options.bitrate,
options.samples_per_symbol,
options.rx_freq, options.rx_gain,
options.antenna, options.verbose)
diff --git a/gr-digital/examples/narrowband/tunnel.py b/gr-digital/examples/narrowband/tunnel.py
index 7f40bb1c3..7414a7227 100755
--- a/gr-digital/examples/narrowband/tunnel.py
+++ b/gr-digital/examples/narrowband/tunnel.py
@@ -92,12 +92,16 @@ class my_top_block(gr.top_block):
gr.top_block.__init__(self)
- self.source = uhd_receiver(options.address, options.bitrate,
+ # Get the modulation's bits_per_symbol
+ args = mod_class.extract_kwargs_from_options(options)
+ symbol_rate = options.bitrate / mod_class(**args).bits_per_symbol()
+
+ self.source = uhd_receiver(options.args, symbol_rate,
options.samples_per_symbol,
options.rx_freq, options.rx_gain,
options.antenna, options.verbose)
- self.sink = uhd_transmitter(options.address, options.bitrate,
+ self.sink = uhd_transmitter(options.args, symbol_rate,
options.samples_per_symbol,
options.tx_freq, options.tx_gain,
options.antenna, options.verbose)
diff --git a/gr-digital/examples/narrowband/uhd_interface.py b/gr-digital/examples/narrowband/uhd_interface.py
index 8420f3eec..a0be516ec 100644
--- a/gr-digital/examples/narrowband/uhd_interface.py
+++ b/gr-digital/examples/narrowband/uhd_interface.py
@@ -42,36 +42,36 @@ def add_freq_option(parser):
metavar="FREQ")
class uhd_interface:
- def __init__(self, istx, address, bitrate, sps, freq=None,
+ def __init__(self, istx, args, sym_rate, sps, freq=None,
gain=None, antenna=None):
if(istx):
- self.u = uhd.usrp_sink(device_addr=address,
+ self.u = uhd.usrp_sink(device_addr=args,
io_type=uhd.io_type.COMPLEX_FLOAT32,
num_channels=1)
else:
- self.u = uhd.usrp_source(device_addr=address,
+ self.u = uhd.usrp_source(device_addr=args,
io_type=uhd.io_type.COMPLEX_FLOAT32,
num_channels=1)
- self._addr = address
+ self._args = args
self._ant = antenna
self._gain = self.set_gain(gain)
self._freq = self.set_freq(freq)
- self._rate, self._sps = self.set_sample_rate(bitrate, sps)
+ self._rate, self._sps = self.set_sample_rate(sym_rate, sps)
if(antenna):
self.u.set_antenna(antenna, 0)
- def set_sample_rate(self, bitrate, req_sps):
+ def set_sample_rate(self, sym_rate, req_sps):
start_sps = req_sps
while(True):
- asked_samp_rate = bitrate * req_sps
+ asked_samp_rate = sym_rate * req_sps
self.u.set_samp_rate(asked_samp_rate)
actual_samp_rate = self.u.get_samp_rate()
- sps = actual_samp_rate/bitrate
+ sps = actual_samp_rate/sym_rate
if(sps < 2):
req_sps +=1
else:
@@ -79,7 +79,7 @@ class uhd_interface:
break
if(sps != req_sps):
- print "\nBit Rate: %f" % (bitrate)
+ print "\nSymbol Rate: %f" % (sym_rate)
print "Requested sps: %f" % (start_sps)
print "Given sample rate: %f" % (actual_samp_rate)
print "Actual sps for rate: %f" % (actual_sps)
@@ -124,14 +124,14 @@ class uhd_interface:
#-------------------------------------------------------------------#
class uhd_transmitter(uhd_interface, gr.hier_block2):
- def __init__(self, address, bitrate, sps, freq=None, gain=None,
+ def __init__(self, args, sym_rate, sps, freq=None, gain=None,
antenna=None, verbose=False):
gr.hier_block2.__init__(self, "uhd_transmitter",
gr.io_signature(1,1,gr.sizeof_gr_complex),
gr.io_signature(0,0,0))
# Set up the UHD interface as a transmitter
- uhd_interface.__init__(self, True, address, bitrate, sps,
+ uhd_interface.__init__(self, True, args, sym_rate, sps,
freq, gain, antenna)
self.connect(self, self.u)
@@ -141,8 +141,8 @@ class uhd_transmitter(uhd_interface, gr.hier_block2):
def add_options(parser):
add_freq_option(parser)
- parser.add_option("-a", "--address", type="string", default="addr=192.168.10.2",
- help="Address of UHD device, [default=%default]")
+ parser.add_option("-a", "--args", type="string", default="",
+ help="UHD device address args [default=%default]")
parser.add_option("-A", "--antenna", type="string", default=None,
help="select Rx Antenna where appropriate")
parser.add_option("", "--tx-freq", type="eng_float", default=None,
@@ -160,7 +160,7 @@ class uhd_transmitter(uhd_interface, gr.hier_block2):
Prints information about the UHD transmitter
"""
print "\nUHD Transmitter:"
- print "Address: %s" % (self._addr)
+ print "Args: %s" % (self._args)
print "Freq: %sHz" % (eng_notation.num_to_str(self._freq))
print "Gain: %f dB" % (self._gain)
print "Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate))
@@ -174,14 +174,14 @@ class uhd_transmitter(uhd_interface, gr.hier_block2):
class uhd_receiver(uhd_interface, gr.hier_block2):
- def __init__(self, address, bitrate, sps, freq=None, gain=None,
+ def __init__(self, args, sym_rate, sps, freq=None, gain=None,
antenna=None, verbose=False):
gr.hier_block2.__init__(self, "uhd_receiver",
gr.io_signature(0,0,0),
gr.io_signature(1,1,gr.sizeof_gr_complex))
# Set up the UHD interface as a receiver
- uhd_interface.__init__(self, False, address, bitrate, sps,
+ uhd_interface.__init__(self, False, args, sym_rate, sps,
freq, gain, antenna)
self.connect(self.u, self)
@@ -191,8 +191,8 @@ class uhd_receiver(uhd_interface, gr.hier_block2):
def add_options(parser):
add_freq_option(parser)
- parser.add_option("-a", "--address", type="string", default="addr=192.168.10.2",
- help="Address of UHD device, [default=%default]")
+ parser.add_option("-a", "--args", type="string", default="",
+ help="UHD device address args [default=%default]")
parser.add_option("-A", "--antenna", type="string", default=None,
help="select Rx Antenna where appropriate")
parser.add_option("", "--rx-freq", type="eng_float", default=None,
@@ -211,7 +211,7 @@ class uhd_receiver(uhd_interface, gr.hier_block2):
Prints information about the UHD transmitter
"""
print "\nUHD Receiver:"
- print "Address: %s" % (self._addr)
+ print "UHD Args: %s" % (self._args)
print "Freq: %sHz" % (eng_notation.num_to_str(self._freq))
print "Gain: %f dB" % (self._gain)
print "Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate))