GNURadio and USRP Experiments

Packet Radio | Radio Data System

Amateur Packet Radio Receive and Transmit (1200 and 9600 baud G3RUH)

This experiment is aimed at better understanding the protocols used in Amateur Packet Radio.

04-Nov-2006 - I've finally reviewed all the material and converted the old code to make it more user friendly as well as to make use of the great blocks GNURADIO offers. I am talking about the Mueller and Muller clock recovery and sampler. Now both 1200 and 9600 python code works, both for transmit and receive. I have isolated the framer functionality in a block, gr_framer, that takes care of HDLC and G3RUH scrambling/descrambling. This block uses the message queue model to return the packets back to the python code. Full option parser support has been added to the python code, so that usrp parameters and message to transmit can be passed to the programs via command line. Here there is a description od the python programs:

1200rx.py

usage: 1200rx.py [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 (default=A)
-f FREQ, --freq=FREQ set frequency to FREQ
-g GAIN, --gain=GAIN set gain in dB (default is midpoint)
-d, --do-logging enable logging on datafiles
-s, --use-datafile use usrp.dat (256kbps) as input

This program receives packets and show them on terminal in this form:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
CRC C75F C75F

===== Sat Nov 4 11:21:50 2006
fm IZ2EEQ-7 to SXQT16-0 via RELAY-0,WIDE7-7 UIv pid=F0
'+4il .K\>
=====

XXXXXXXXXXX
CRC 34EC 34EC

===== Sat Nov 4 11:27:42 2006
fm IK1ZNW-6 to I2ODL-6 via IK2NHL-4 I45^ pid=F0
PC19^0^IK5PWJ-6^0^5452^1^IZ5FSA-6^0^5452^0^IK2XDE-6^0^5432^0^IK5ZUK-6^0^5452^1^I5UXJ-2^0^5451^1^IR1BI-6^0^5451^1^IR8AW-6^0^5452^H2^
=====

he Xs are returned by the framer and indicate a candidate packet whose CRC check failed. When CRC check for a packet is ok, the framer prints the CRC value to standard output and returns the packet to python, whose function printpacket prints it in a readable format. The program is downloadable here, and it needs gr_framer and ax25.py.

1200tx.py

usage: 1200tx.py [options]

options:
-h, --help show this help message and exit
-f FREQ, --freq=FREQ set frequency to FREQ
-m MESSAGE, --message=MESSAGE
message to send
-c CALL, --mycall=CALL
source callsign
-t CALL, --tocall=CALL
recipient callsign
-v CALL, --via=CALL digipeater callsign
-d, --do-logging enable logging on datafiles
-s, --use-datafile use usrp.dat (256kbps) as output

This program transmit a message from a source callsign to a dest callsign via a digipeater. It is made to work with a basic TX board (the only tx board I have), therefore it uses the repetition of spectrum of a sampled signal to go to VHF. I guess the code can be easily adapted for more serious transmit boards. The program is downloadable here, and it needs gr_framer and ax25.py.

9600rx.py

usage: 1200rx.py [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 (default=A)
-f FREQ, --freq=FREQ set frequency to FREQ
-g GAIN, --gain=GAIN set gain in dB (default is midpoint)
-d, --do-logging enable logging on datafiles
-s, --use-datafile use usrp.dat (256kbps) as input

This program receives packets and show them on terminal in this form:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
CRC C75F C75F

===== Sat Nov 4 11:21:50 2006
fm IZ2EEQ-7 to SXQT16-0 via RELAY-0,WIDE7-7 UIv pid=F0
'+4il .K\>
=====

XXXXXXXXXXX
CRC 34EC 34EC

===== Sat Nov 4 11:27:42 2006
fm IK1ZNW-6 to I2ODL-6 via IK2NHL-4 I45^ pid=F0
PC19^0^IK5PWJ-6^0^5452^1^IZ5FSA-6^0^5452^0^IK2XDE-6^0^5432^0^IK5ZUK-6^0^5452^1^I5UXJ-2^0^5451^1^IR1BI-6^0^5451^1^IR8AW-6^0^5452^H2^
=====

he Xs are returned by the framer and indicate a candidate packet whose CRC check failed. When CRC check for a packet is ok, the framer prints the CRC value to standard output and returns the packet to python, whose function printpacket prints it in a readable format. The program is downloadable here, and it needs gr_framer and ax25.py.

9600tx.py

usage: 9600tx.py [options]

options:
-h, --help show this help message and exit
-f FREQ, --freq=FREQ set frequency to FREQ
-m MESSAGE, --message=MESSAGE
message to send
-c CALL, --mycall=CALL
source callsign
-t CALL, --tocall=CALL
recipient callsign
-v CALL, --via=CALL digipeater callsign
-d, --do-logging enable logging on datafiles
-s, --use-datafile use usrp.dat (256kbps) as output

This program transmit a message from a source callsign to a dest callsign via a digipeater. It is made to work with a basic TX board (the only tx board I have), therefore it uses the repetition of spectrum of a sampled signal to go to VHF. I guess the code can be easily adapted for more serious transmit boards. The program is downloadable here, and it needs gr_framer and ax25.py.

Notes about block compile and install

In order to make it work, compile and install of gr-packetradio is needed. This is done according to the standard rules for compiling and installing a GNURadio block:

  1. ./bootstrap
  2. ./configure --prefix=your_gnuradio_installation_prefix --enable-maintainer-mode
  3. make
  4. make install

Graphical RDS (Radio Data System) decoder

This work is based on the rds block published on the discuss-gnuradio list at the beginning of 2006 from Ronnie Gaensli, and later adapted by Ryan Shoff.

Here there is a list of the main changes from the original version posted:

biphase_decoder:

  1. loss of sync implemented
  2. samples consumption fixed when aligning clock and signal

data_decoder:

  1. sync is now based on syndrome calculation
  2. loss of sync implemented
  3. group decoding for all of the 30 possible group types (work in progress)
  4. message model implemented to send decoded information to graphical frontend

The solution is made up of a custom block, gr-rds, contained in the gr-rds-new.tgz archive, and some python files, stored in rds.tgz.

After compiling and installing the block, you will need to run rds_scope.py to use the software. It makes use of rds_rx.py where the rds receiver chain is implemented, and rdspanel.py where the wxwidgets panel.

As soon as valid RDS info is received, the appropriate fields on the interface will change accordingly - some fields, as name of the station, program type and so on will show the appropriate strings, while the "flag" fields will light red if the corresponding function is active according to decoded RDS. The whole thing is reset upon frequency change.

The gr-rds block outputs useful interesting information on the standard input, and the verbosity level can be increased by changing the defines inside the source files.

This experiment is still work in progress as not all the group types are currently managed.