gr-gpio
Description
gr-gpio is an extension to the normal USRP firmware, implemented as an alternative FPGA bitstream, using the existing USRP host code. With the gr-gpio component you can transmit and receive a digital stream to and from the USRP which is aligned with the existing analog stream. Digital data is sent to or received from the daughterboard GPIO pins and sacrifice one bit each from the I and the Q analog streams to transport the digital bits.
Receiving Streaming Digital Samples
Digital streams are sampled from GPIO 14 and GPIO 15 from the selected daughterboard and replace the LSB of the I and Q analog streams, respectively. In the host, on can then use usrp.source_s() to obtain the combined streams and separate them with logical bit operations. The GPIO pins are sampled at the decimated RF rate; that is, the GPIO data replaces the LSBs at the output of the digital downconverter. As a result of pipeline delays in the analog processing stream, there will be a fixed but decimation rate dependent delta between the analog and digital streams.
Transmitting Streaming Digital Samples
In the host, one uses usrp.sink_s() and encodes the desired digital data into the LSBs of the I and Q sample data. These are then routed to GPIO 14 and GPIO 15 of the selected daughterboard. The data is output on the GPIO pins at the same rate as the sample data arriving over the USB. Due to pipeline delays in the analog processing stream, there will be a fixed but interpolation rate dependent delta between the analog and digital streams.
Note: The headers on the daughterboards have a line of ground pins next to the gpio pins. Also, it is not safe for some daughterboards to connect all pins on the RX header to all pins of the TX header using a flat cable for a loopback test. Only connect GPIO pins 14 and 15 (and the corresponding ground pins).
Installing gr-gpio
gr-gpio is available as part of the standard GNU Radio build and has no additional external dependencies. Without additional configuration, the gr-gpio component:
- Adds usrp_gpio.rbf into $prefix/share/usrp/rev2 and $prefix/share/usrp/rev4
- Creates $prefix/lib/pythonX.X/site-packages/gnuradio/gpio directory
- Adds gpio_rx_sfile.py, gpio_usrp_fft.py, and gpio_usrp_siggen.py to $prefix/bin
The USRP host code is not changed.
Using gr-gpio
To receive streaming digital samples, one first creates a USRP source block using the gr-gpio FPGA bitstream:
from gnuradio import gpio u = usrp.source_s(fpga_filename=gpio.fpga_filename, ...) # In addition to any other parameters
Create and configure daughterboard object as normally done.
Note: when using the BasicRX or LFRX daughterboards, one must ensure the receive MUX is set to enable complex sampling, in order to have both I and Q sample streams sent to the host. That is, instead of using usrp.determine_rx_mux_value(), one must set the mux value manually.
If using the daughterboard in RXA use:
u.set_mux(0x10)
If using the daughterboard in RXB use:
u.set_mux(0x32)
Since the USRP source is instantiated with usrp.source_s() it will produce a datastream of interleaved shorts:
{I0 analog 15 bits, I0 digital 1 bit}{Q0 analog 15 bits, Q0 digital 1 bit}
{I1 analog 15 bits, I1 digital 1 bit}{Q1 analog 15 bits, Q1 digital 1 bit}
...
{Ix analog 15 bits, Ix digital 1 bit}{Qx analog 15 bits, Qx digital 1 bit}
To make packing and unpacking the analog and digital sample streams easier a new gnuradio block has been added:
gpio.and_const_ss
This block does a logical AND operation between the 16 bit samples flowing in and the 16 bit constant you give when instantiating gpio.and_const_ss.
To extract the digital values create and insert into the flowgraph:
dig_strip = gpio.and_const_ss(0x0001)
To extract the analog stream use:
ana_strip = gpio.and_const_ss(0xFFFE)
After the ana_strip block the stream becomes:
{I0 analog 15 bits, zero 1 bit} {Q0 analog 15 bits, zero 1 bit}
{I1 analog 15 bits, zero 1 bit} {Q1 analog 15 bits, zero 1 bit}
...
{Ix analog 15 bits, zero 1 bit} {Qx analog 15 bits, zero 1 bit}
To mimic the output produced by usrp.source_c(), one may at this point use the gr.interleaved_short_to_complex() block to convert the stream into a series of complex values.
After the dig_strip the stream becomes:
{zero 15 bits, I0 digital 1 bit} {zero 15 bits, Q0 digital 1 bit}
{zero 15 bits, I1 digital 1 bit} {zero 15 bits, Q1 digital 1 bit}
...
{zero 15 bits, Ix digital 1 bit} {zero 15 bits, Qx digital 1 bit}
To separate these into their own stream of samples. in may at this point use the gr.deinterleave() block.
To transmit streaming digital samples, one first creates a USRP sink block using the gr-gpio FPGA bitstream:
from gnuradio import gpio u = usrp.sink_s(fpga_filename=gpio.fpga_filename, ...) # In addition to any other parameters
This block expects 16-bit interleaved short input samples, with the LSB of I and Q encoded with the values that will be driven onto GPIO pins 14 and 15:
{I0 analog 15 bits, I0 digital 1 bit}{Q0 analog 15 bits, Q0 digital 1 bit}
{I1 analog 15 bits, I1 digital 1 bit}{Q1 analog 15 bits, Q1 digital 1 bit}
...
{Ix analog 15 bits, Ix digital 1 bit}{Qx analog 15 bits, Qx digital 1 bit}
Example Applications with gr-gpio
gr-gpio installs the following scripts in $prefix/bin:
- gpio_rx_sfile.py - record analog and digital streams to files
$ gpio_rx_sfile.py --help
usage: gpio_rx_sfile.py: [options] analog_filename digital_filename
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 (default=A)
-d DECIM, --decim=DECIM
set fgpa decimation rate to DECIM [default=16]
-f FREQ, --freq=FREQ set frequency to FREQ
-g GAIN, --gain=GAIN set gain in dB (default is midpoint)
-N NSAMPLES, --nsamples=NSAMPLES
number of samples to collect [default=+inf]
-F, --force-complex-RXA
enable basicRX hack to force complex mode on basicRX
and LFRX. Only works on side A. Only use with --gain 0
- gpio_usrp_siggen.py - generate streaming digital test pattern with analog data
$gpio_usrp_siggen.py --help
usage: gpio_usrp_siggen.py [options]
options:
-h, --help show this help message and exit
-T TX_SUBDEV_SPEC, --tx-subdev-spec=TX_SUBDEV_SPEC
select USRP Tx side A or B
-f RF_FREQ, --rf-freq=RF_FREQ
set RF center frequency to FREQ
-i INTERP, --interp=INTERP
set fgpa interpolation rate to INTERP [default=512]
--sine generate a complex sinusoid [default]
--gaussian generate Gaussian random output
--uniform generate Uniform random output
-w WAVEFORM_FREQ, --waveform-freq=WAVEFORM_FREQ
set waveform frequency to FREQ [default=100000.0]
-a AMPL, --amplitude=AMPL
set waveform amplitude to AMPLITUDE [default=16000.0]
-g GAIN, --gain=GAIN set output gain to GAIN [default=none]
-o OFFSET, --offset=OFFSET
set waveform offset to OFFSET [default=0]
--digital generate (only) a digital wave on lsb (will be output
on gpio pins with special usrp firmware)
- gpio_usrp_fft.py - display analog or digital streams as FFT, scope, or waterfall
$ gpio_usrp_fft.py --help
usage: gpio_usrp_fft.py [options]
options:
-h, --help show this help message and exit
-w NUM, --which=NUM select which USRP (0, 1, ...) default is 0
-A ANTENNA, --antenna=ANTENNA
select Rx Antenna (only on RFX-series boards)
-d DECIM, --decim=DECIM
set fgpa decimation rate to DECIM [default=32]
-f FREQ, --freq=FREQ set frequency to FREQ
-g GAIN, --gain=GAIN set gain in dB (default is midpoint)
-W, --waterfall Enable waterfall display
-8, --width-8 Enable 8-bit samples across USB
-S, --oscilloscope Enable oscilloscope display (default)
-F, --fft Enable FFT display
-n FRAME_DECIM, --frame-decim=FRAME_DECIM
set oscope frame decimation factor to n [default=1]
-v V_SCALE, --v-scale=V_SCALE
set oscope initial V/div to SCALE [default=1]
-t T_SCALE, --t-scale=T_SCALE
set oscope initial s/div to SCALE [default=10us]
--digital show (only) the digital wave on lsb (will be input
from gpio pins with special usrp firmware)
--analog show (only) the analog wave on msbs (will be input
from analog inputs)
--file=FILE input from file FILE in stead of USRP (will be input
from raw file in interleaved short format)
Loopback Testing
To perform a digital loopback test using BasicRX and BasicTX boards installed in side A, connect GPIO pin 14 on the BasicTX to GPIO pin 14 on the BasicRX. Do the same for GPIO pin 15.
In one console:
$ gpio_usrp_fft.py --digital -R A -d 128 -S
This will create an oscilloscope which only shows the lsb of RXA (hardcoded).
In another console:
$ gpio_usrp_siggen.py --digital -i 512
This will send a digital test pattern (which only uses lsb) to TXA (hardcoded).
