From SpenchWiki
Jump to: navigation, search

OP25 is an open-source implementation of the APCO Project 25 digital radio standard.

There have been a number of changes in its dependencies that cause recent versions not to work. The important ones are:

  1. Removal of Legacy USRP code from GNU Radio (replaced by UHD)
  2. IT++ BCH routine no longer behaves as expected, so the error checking on the frame header never succeeds
  3. GNU Radio (and GRUEL) have changed and certain files are no longer found by the build system (e.g. gruel_common.i)

Here are some notes on getting it working.

Note: if you already have OP25 installed, fear not! I have published detailed instructions on how you can easily have multiple side-by-side installations of the same GNU Radio module, such as OP25.


This section applies to version 306 of the SVN source.

Apply the patch in the root of your source directory:

patch -p0 < r307.diff

Then go through the build process from the top (i.e. you must start with bootstrap!).

Once OP25 is installed, you can test the decoder in GNU Radio Companion by opening the OP25.grc file. Make sure you:

  1. download, compile and install gr-baz for its OP25 extensions
  2. enable the appropriate source block for your setup (e.g. USRP, RTL2832U dongle or file source), and disable the rest!

Note: If you wish to run any of the OP25 applications from the python directory (e.g. usrp_p25_rx.py), you must symlink (or copy) from gr-baz the Legacy USRP shim (usrp.py) into the GNU Radio Python directory. This will enable all applications that use the Legacy USRP Source Python interface to talk to all USRP models supported by UHD! For example:

sudo ln -s ~/src/gr-baz/python/usrp.py /usr/local/lib/python2.7/dist-packages/gnuradio/usrp.py

DES-OFB & More

A while ago I modified version 219 of the SVN source to support DES-OFB decryption, among other things. This went unmaintained and was never merged. Therefore proceed at your own risk. Perhaps a kind soul will consider merging into the latest source?

This version has several features:

  • DES-OFB decryption (entered as 64-bit hex key, uses Phil Karn's DES source)
  • Dumps voice frames, encryption state and more to console
  • Error correction on Low Speed Data Word
  • Hamming error detection at frame level
  • Decodes additional information from LDU1 and LDU2
  • Uses Pavel's imbe_vocoder, which at the time produced better audio than the internal software_imbe_decoder

It should also be noted that the code is hacking ugly (e.g. decryption done inside software_imbe_decoder.cc and decrypted frames are sent from there to imbe_vocoder).


  1. Check out version 219of the SVN source:
    svn co http://op25.osmocom.org/svn/trunk@219 op25
  2. Apply the patch in the source directory
    patch -p0 < r219.des-ofb.diff
  3. Configure, compile and install imbe_vocoder
  4. In imbe_vocoder/src/lib/.libs, add some symlinks to provide libraries to the linker (you'll need to re-do this if you ever make clean):
    ln -s _op25_imbe.so libop25_imbe.so
    ln -s ../_op25_imbe.la _op25_imbe.la
  5. Modify your environment so the linker/loader can find the imbe_vocoder:
    LD_LIBRARY_PATH=<OP25 build directory>/imbe_vocoder/src/lib/.libs:/usr/local/lib:$LD_LIBRARY_PATH
  6. Symlink (or copy) <build directory>/imbe_vocoder/src/lib/_op25_imbe.so and <build directory>/imbe_vocoder/src/lib/_op25_imbe.la to GNU Radio's Python installation directory, for example:
  7. Configure, compile and install decoder

Then you can test the decoder in GNU Radio Companion (as above) with OP25.grc from gr-baz, or you can run audio_p25_rx.py as follows:

./audio_p25_rx.py -f <freq>M -R <side> -O -o <output WAV file>.wav -k <DES key, 16 hex chars>

Sample Output

When executing OP25.grc you should see something like:

Generating: "/home/balint/Documents/mint/op25_grc.py"

Executing: "/home/balint/Documents/mint/op25_grc.py"

linux; GNU C++ version 4.6.3; Boost_104900; UHD_003.005.000-11-g79a26e96

Imported legacy fsk4
Using Volk machine: avx_64_mmx_orc
Using software IMBE decoder
Project 25 IMBE Encoder/Decoder Fixed-Point implementation
Developed by Pavel Yazev E-mail: pyazev@gmail.com
Version 1.0 (c) Copyright 2009
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; see the file ``LICENSE'' for details.
ioctl(d_tap, TUNSETIFF, &ifr): Operation not permitted
Using legacy decoder_ff
DES key: <hidden to protect the innocent/guilty>
Using legacy fsk4.demod_ff
>>> gr_fir_ccc: using SSE
>>> gr_fir_fff: using SSE
LDU1 MFID: 0x00 Emergency: 0 Reserved: 0x4000 TGID: 0x0001 Source: 0x129712

0EAF 00C3 0483 00CD 0747 01AF 0234 00E6

03C0 0F4B 00D4 0233 0297 053D 03B5 002C

058A 0D00 0765 0F9D 0182 028D 00DB 00C3

064B 0053 0C97 0315 0614 0666 00CB 00E9

0585 02FC 0113 02A1 051E 0536 001B 0098

065A 0DCF 08A3 0F17 0124 035F 06CB 00EC

0182 03C3 0190 03C3 0519 0120 03D1 0075

0E4D 061A 038A 04AD 0418 0499 069F 003E

054D 0DA7 0932 0718 0518 030A 02E6 0086

LDU2: MI=100EE08234BADF8200
LDU2 AlgID: 0x81 KID: 0x3780 IV: 0x82DFBA3482E00E10

0FA1 0E5F 025B 0E4A 053A 066D 0381 00F5

0FB8 0816 0C5A 030C 05A8 04B7 0387 0046

0524 02DD 0A38 0CB8 0420 0033 0227 0070

0D4D 0A64 032D 0DDF 0070 07B9 0084 00C9

0AA7 0A90 0E6E 065C 07B4 043F 0535 003B

085C 0E70 0E14 08E9 02C8 0526 04A7 0036

075E 0FB7 04A0 0B52 0420 077A 027B 003A

0F15 0504 0C5B 0D8F 0433 065E 0270 0035

053C 0876 0F97 0891 0576 05AE 07C3 007E

LDU2: New IV
DES: 1616 bits used from 25 iterations
LDU1 MFID: 0x00 Emergency: 0 Reserved: 0x4000 TGID: 0x0001 Source: 0x129712

05CB 0931 0585 0FB5 0001 02F5 0354 0005

060C 091B 0BA8 05B1 0000 0489 0506 00FA

048B 07A9 0628 087C 0001 02C9 074F 00CB

0451 015C 045B 07E4 0003 0567 01D3 00C8

0212 0696 0F1B 0C86 0002 00BB 06D0 0040

05CD 05FB 0419 0ADF 0001 008E 07D1 0084

018A 0A3B 07B4 0BE8 0024 042B 07DE 0044

038E 06D0 04AA 025C 0004 0386 0597 0074

050A 03C9 07F0 0027 0002 05BF 0673 00D5

Side note!

If we take the Source ID in the above sample - 0x129712 - and convert to decimal, we get 1218322.

We can then take this ID and look it up on the ACMA database here, and we can see who that ID and radio belongs to!