OP25 For Dummies – Or how to build a police scanner for $30 (Part 1)

OP25 is a program that decodes P25 Phase 1 and Phase 2 digital radio.  Some municipal areas are upgrading to P25 Phase 2 so almost gone are the days that you can track them with a police scanner since P25 is a Trunked Radio system and not just a lone frequency to monitor.   The only things that do Phase 2 are hardware scanners and hardware radios and OP25 for software radios.  Bear in mind Phase 2 could be encrypted and nothing you can do will decode it.

OP25 is HARD.  I’m a geek and I messed with it on and off for a year or more and it whipped me more than once.  Now that I have it working I find that it is REMARKABLY easy and I’m mad at all the geeks out there who never made a simple tutorial.  There are tutorials out there, some good but everybody leaves out the good stuff or the stuff they took for granted.

I’m kind of working on the assumption that you have Linux installed and have your SDR device working.  In a pinch I guess the first thing you could do is to install gqrx which would pull in all the necessary RTL stuff you need.  Follow the directions here if you need to.  Yeah that’s a weird way of doing it but it’ll work and probably the easiest thing to do for a newbie.

Installing OP25 is a SNAP.  Download from the repository using this command. I’m doing this on Ubuntu 18.04

“NOTE:  I’m told that on newer installations that it may be required to install an older version of cmake if compilation errors occur.  There are instructions in the comments below by Scott B that detail the procedure to overcome the compilation error.  Thanks Scott!”

git clone https://github.com/boatbod/op25.git

It will make a folder called op25

cd op25


It will instruct you to install GNUPLOT following the build and install process

sudo apt-get install gnuplot-x11

Wait a bit for it to install.  It should take care of everything.

Now it is installed but there are three obstacles to overcome.

  • How to launch the program with what command to use
  • How to set up the file trunk.tsv
  • How to set up the file yourcity.tsv

That’s basically it.  Now my assumption here is that you are using a generic RTL-SDR device.  I’m using a V3.

These will set you back about $30 or so.  But you only need one of these to track a trunked radio system.

So plug in your RTL-SDR device and let’s get ready to do this thing.

I’m going to demonstrate using my home town of New Bern NC.  Lets find the trunked system to follow.



Go to this page  to list the frequencies.

This page will not always be spot on.  The actual control channel at the moment (they change it sometimes) is 857.2625.

To find the control channel if you don’t know which one it is just open a program like GQRX and look and listen for the control channel.  It will sound like digital noise.  And the signal will be a constant spike.  As you can see I found my Control Channel at 857.2625 as stated above.


Now go back to your system and get in the correct directory. Check your path for accuracy.

cd /home/john/op25/op25/gr-op25_repeater/apps


./rx.py --args 'rtl' -N 'LNA:47' -S 2400000 -f 857.2625e6 -o 25000 -q -2

If you get a bunch of errors remove the last part of the command (-q -2)  It works as above on my V3 SDR but not on my NESDR Smart. You may also have to adjust the -2 number depending on your individual SDR.  Have fun with that.  To further illustrate my SDR v3 works at -2, my NESDR Smart works with the -q -2 removed (0), and my Adalm-Pluto works at -q 5 (positive 5).  You just have to play around until you get your signal centered on the plot.

As per the pic below ………If where it says 857.262500/812.262500 is all zeros then you need to keep adjusting the -q number.  On that screen you can start GNUPLOT by pressing the number 1 key.  Keep messing with the q number until the signal is centered on the plot.

Something like the box above should pop up.  There won’t be any sound but take note of the NAC.  In my case it is 0xfc  We’re going to need that.  Copy your NAC for your frequency.  YOU WILL ONLY GET THE CORRECT NAC IF YOU ARE TUNED TO THE CONTROL CHANNEL YOU WANT TO MONITOR.

Now you should still be in the apps directory.  Double click on the file named trunk.tsv and open it with LibreOffice.  Make sure the file looks like this and has these settings. (I’ve already modified my file, so ignore the difference.)

Now take note of the way I changed the file.  I made the SysName = NewBern, then put my control channel frequency in, put the NAC I copied earlier in, and then told it the tag file was named newbern.tsv  Under modulation there are only two types, CQPSK or C4FM.  If one doesn’t work, try the other.  Save this and exit.  Save it as the “Use Text CSV Format”

Now open the file tompkins.tsv  It looks like this.  Make sure the settings are the same as depicted above.

Delete all the filled in fields in here and go back to the radio reference.com page where all the New Bern frequencies were.


Now go to the tompkins.tsv file that you cleared and type in column A the numbers in the DEC column (i.e. 100, 101, 102, etc.)  Then in column B insert in the tag (i.e. Law Dispatch, Public Works, etc.).

Sorry mine are not in order.  Sue me.

Do a “Save As” and name the file newbern.tsv (remember that field in the other file you named newbern.tsv).  Make sure this file is also saved in the same format as above and also in the apps directory where the tompkins.tsv file was.

Okay open your terminal.  cd to the apps directory  /op25/op25/gr-op25_repeater/apps and do this command:

./rx.py --args 'rtl' -N 'LNA:47' -S 2400000 -f 857.2625e6 -o 25000 -q -2 -T trunk.tsv -V -2 -U 2> stderr.2

Again you may have to remove the -q -2 or adjust it depending on your SDR

When OP25 launches hit the number “1” on your keyboard to open GNUPLOT

And now when there is a transmission on the Control Channel, OP25 will track it to the correct frequency and even display the talk group that is currently active.

Now lets make a little script file so we aren’t forever typing long commands.


cd op25

sudo nano op25.sh

Paste in the following data in the file (MAKE SURE YOUR PATH IS CORRECT AND DON’T FORGET ABOUT THE -q -2 part if you have problems):

#! /bin/sh

cd /home/john/op25/op25/gr-op25_repeater/apps

./rx.py –args ‘rtl’ -N ‘LNA:47’ -S 2400000 -f 857.2625e6 -o 25000 -q -2 -T trunk.tsv -V -2 -U 2> stderr.2

Hit CTL + the X key then Y to save the file.  Now make it executable.

sudo chmod +x op25.sh

Now to launch the file simply be in the directory that script file is in and type:


It will cd to to the right directory and run the command to start OP25.

In the comments below Mr. Alex Bowman found an easier way to launch the program.  Create an alias in Linux so that you just type “op25” (without the quotes) into the terminal from any directory.

sudo nano .bashrc

Then paste in the following lines.

#OP25 alias
alias op25=’bash /home/john/op25/op25.sh’

Be sure your path is right about.  Note my path of /home/john.  Yours is different unless your name is John, of course.

Now hit Ctl key plus X, then hit Y to save.  Restart the terminal and you should now be able to launch OP25 just by typing OP25.  It works like a champ.  I tried it.

That’s it.  I hope I made this easier for someone.

Here’s OP25 in action:

And lastly here is a video of me using OP25 to track 2 Control Channels simultaneously.  You’ll hear the transmissions echo in the video.  That is my screencast software recording both from the microphone and speakers and not the way OP25 sounds.

On a final note just for fun I installed OP25 on a Raspberry Pi 3 B+.  It works like a champ.  I installed GQRX first which pulled in most everything OP25 needs and plus I use GQRX a lot anyway.  OP25 takes a while to build on a Pi but it does build.  If you look at the pic below the CPU usage is 40% however to get this picture I was running a VNC server as well so some of that usage is almost certainly the VNC session.

This is a living document (for a while).  If you find something I should add feel free to go to my contact page and email me.

89 thoughts on “OP25 For Dummies – Or how to build a police scanner for $30 (Part 1)

  1. Pingback: Tutorial on Setting up OP25 for P25 Phase 2 Digital Voice Decoding - rtl-sdr.com

  2. Gene

    Thank you. Runs great on a Tinkerboard. Monitoring Louisville Metrosafe. Used the standard RTL install procedures then I used sudo apt-get install gqrx-sdr and then sudo apt-get install libvolk1-bin and ran volk_profile. Then I followed all of your steps. And just for info the -n option in OP25 somewhere near the beginning of the will block the encrypted squeals that can cause loved ones to vote you off the island.
    I’m not sure why but this system has a better sound than others that I use and like.
    Thanks again, have finally found a use for this SBC that I had written off months ago. As an additional note my V3 is running off a powered USB adapter, not the Tinkerboard usb power.

    1. Tyler Ryno

      Ok, So far this is working out amazingly. but could i use this for Conventinal Scanning if my First Responders are using Analog and P25 convintional

    2. David

      What OS are you running on your Tinkerhoard? I run op25 latest build on a pi b+ and now and then the system just locks up on me.

  3. Pingback: OP25 on a Raspberry Pi (part 3) | John’s Tech Blog

  4. Brian

    Thanks for great tutorials. Not only got op25 phase 2 running on my laptop under Ubuntu, but also got it working on my Raspberry Pi 3 perfectly!

    I have a question, I am using the -n switch to silence the encrypted stuff (works fine), but is there a way to block them completely? I find sometimes the encrypted “silenced” talkgroups, over ride the non-encrypted ones and I miss some of the information. I listen to the fire departments in my area, but the police who are encrypted are on the same control channel and I will sometimes miss the dispatch of a fire call because a “silenced” talkgroup is active. Is there a way around this by chance?

    Thanks again for taking the time to put this information together in a easy to understand format!!

    1. John Hagensieker Post author

      In your .tsv file you can set Priority but you’d have to know which talk groups the encrypted stuff is generally on. Set a low priority for it.

      1. Brian

        ah, OK. I’ll give that a go then. I am getting a pretty good idea of which talk groups are the busiest and those will be my priority first.

        Thanks for the reply!

    2. Matt R.

      The “blacklist” field in trunk.tsv tells op25 to skip a talkgroup completely and keep listening for other talkgroups; I have been putting the encrypted talkgroups on the local system in that field and it seems to work OK. See my reply further below for the details.

      (Even with a talkgroup in the blacklist, if somebody transmits on that talkgroup, you will still see the talkgroup near the top of the screen, where op25 lists the last 5 frequencies it heard things on – you just won’t hear the audio for that talkgroup.)

      I hope this helps!

  5. PiScanner

    I see all the comments about getting this going on RasPi 3 B+, but not the details on it. So could you please post the RasPi 3 B+ portion of the tutorial. A couple SDR dongles and a PI 3+ would still be cheaper than a $600 P25-PII scanner, or a $3K P25 PII radio and hoping you can keep it unaffiliated and unstunned.

  6. David Dobson

    First time link user (ubuntu18-04) how and where can I check my build to ensure all is their and what not and something to compare to

  7. Gared

    I am linux stupid, but this tutorial helped me out a lot thank you. I am having trouble with setting up the whitelist I can’t seem to find it ( if you have it and I skipped it i’m sorry my brain is still fried from the commands )

    Do you have to setup a new line with the nac and the whitelist every time? Or just in the whitelist box you can have many many entries?

  8. Ashleigh

    Thanks for the tutorial. It saved me days of work. I had this working great for a few weeks but then i got a software update thru ubuntu yesterday and now its broken. I run op25.sh and it stops at setting gain LNA to 47

    Any ideas how to fix it?

    1. Ken F Simpson

      @ashleigh The issue I kept having is it needed a 0 in the offset column, that and double check to make sure its not saved as trunk.tsv.csv it should be trunk.tsv ,

  9. Matt R.

    Thanks for the write-up! I got an RTL-SDR a few years ago, when P25 decoding was not as far along as it is now. I started playing with it again recently and now I have a scanner – thanks!

    Some notes on how I set it up:

    I found I could copy the text of the tables on Radio-Reference and paste it into LibreOffice. LibreOffice treats the paste like importing a text file, and breaks it up into columns and rows pretty much how you would expect. You can then cut it down to just the talkgroup ID (first column) and whatever you want to use for the description (second column), for the .tsv file that describes the system you want to listen to.

    I used the “Description” field from Radio-Reference as the description in my .tsv file. The “Tag” field there is pretty generic; the “Alpha Tag” is a little better, but still kind of cryptic – especially on a system like the one near me, which has 800+ talkgroups. (On the other hand, “Alpha Tag” probably matches what the “official” system users actually see on the front of their radios.)

    When you are first listening, you might want to have a text file or a piece of paper handy. You will probably hear some encrypted talkgroups; note their talkgroup IDs. Then, add those channels into the “blacklist” field in trunk.tsv – you can put more than one talkgroup in that cell, separating them with commas. If you wanted to ignore talkgroups 1001, 2002, and 3003, that cell would look like this:


    Save trunk.tsv and restart the scanner program and op25 will then skip those talkgroups. (There is an -n option to rx.py to ignore encrypted channels, but if you use that, op25 will still stop on an encrypted talkgroup for as long as someone is transmitting on that talkgroup. Putting the talkgroup in the blacklist makes op25 skip it immediately and keep checking for other transmissions.)


  10. Scott Gayden

    Thank you so much for putting this information out there. I’m almost completely new to Linux and was able to follow along very easily. I was able to successfully get OP-25 running on Ubuntu 18.04 LTS with a RTL-SDR v3 dongle. Thank you again for this excellent writeup.

  11. marklt1

    Is there an way to get OP25 to work with multiple RTL-SDR dongles? The reason I ask that is that I monitor the Ohio MARCS P25 system where the frequencies can span 6 Mhz. I would like to constantly monitor the control channel with a single dongle and let the others take care of bouncing around.
    The way it works today is that it will jump from the control channel to a listening channel to listen to a specific talk group. I generally hear one side of the conversation since the control channel cannot tell me then next channel for the reply in time.
    Another user will reply to a call for that talk group but will appear on a different channel. I will miss that since the control channel isn’t constantly monitored. Three dongles would suffice in this situation.
    I’ve been looking for many months but haven’t had much luck. The only think close would be trunk recorder, which is a path really don’t want to take due to its intense use of resources.

    1. LK

      Did it stop working for you on 2019.01.18? I just tried listening and I get errors in the stderr file. I went to make sure I was on the correct freq and it looks like the radioreference.com site updated on the 18th as well, which seems to be a huge coincidence.

  12. Cam

    John, greetings from the Triangle. Your tutorials – especially this one on OP25 – were a great comfort during the recent storms. I recently bought an ADALM-PLUTO, and I’m finding a strange behavior – I can be zeroed right on the control channel, but the actual communication channels always seem to be too offset for me to recover audio. Have you seen such similar behavior on the Pluto?

    1. John Hagensieker Post author

      I have to set my Pluto at q 5 and then if it gets hot in the room have to set it to q 6. It’s kind of drifty but playing around with it a bit you should find the magic range.

  13. Nick

    Thanks for this tutorial. I can now listen to my county’s Phase II TDMA with a nesdr smart on MATE 1.20.1. I had to lose the “2> stderr.2” from the launch script in order to get it to work for me.

    I was also able to copy and paste the data from Radio Reference like Matt R. above.

    1. John Hagensieker Post author

      Outstanding write up. Thanks for sharing it here. It will only serve to help others get OP25 up and running with a Pi. I recently added a couple other blogs where I was playing around with DSDPlus and came to the conclusion that while DSDPlus is better eye candy, the superior decoder by a longshot is OP25. The fact you can run it on a Raspberry Pi is icing on the cake.

    2. Ethan

      Can someone please tell me how to get Alhambra PD to work? The only 2 freuencies I need are 471.1375 and 471.1000 but I think it’s conventional phase I. Please help

  14. Kirk Wolff

    Hello, I am using ubuntu 18.04 and i have been having trouble getting the line:

    git clone https://github.com/boatbod/op25.git

    to facilitate. I have tried sudo apt-get install, etc, but no good. Previously i was using Ubuntu 16.04 and it ran flawlessly. Any Ideas ??

    Oh, just love your blog. Simple is better and as a Robotics Engineer, I have found many mistakes by backing off original thoughts and Keeping It Simple !!


    1. John Hagensieker Post author

      Did you install git? sudo apt-get install git

      You can also go to that GitHub page and download the zip file and unzip it where you want it.

  15. Fred Albertson

    Hi John, You are a masterful teacher. Thanks for assisting a WIN 10 guy with a functional installation on Ubuntu. With your assistance, I’ve got OP25 working in Virtualbox with the exception of the audio – the next project…

  16. Alexander Bowman

    I’ve got this working on my raspberry pi 3.

    Something cool that might benefit others is, if you’re lazy like me, set an alias for op25.sh

    In Terminal:

    sudo nano .bashrc

    ##OP25 alias

    alias op25=’bash /home/pi/op25/op25.sh’

    Close terminal and open it back up. You can now run your command by typing op25 as soon as the terminal opens, without changing directories.

    1. Alexander Bowman

      CTRL+X, Y, Enter

      after typing:
      alias op25=’bash /home/pi/op25/op25.sh’

      for some reason the CTRL+X, Y, Enter was missed when I tried to post comment.

      1. John Hagensieker Post author

        Next time I launch OP25 on one of my Linux computers I’ll give that a try and then add it to the tutorial. Thanks!

        1. Alex Bowman

          I also added another alias that starts my services, but I’ll post that on Part 2 as the alias covers other items than covered here, Works well if you have to log in VNC to run your commands.

  17. Andrew Dixon

    Hi John .. your article is exactly what I was looking for… the only issue is really my lack of knowledge with Ubuntu .. I get to the point in the install that I send the rx.py line then I get errors and go no further…I get messages say things like source failure etc …and I deleted the last two commands but no joy
    Here is a screen capture


    I using windows 10 and a RTL 2832 type unit wchich works under SDRSharp.

    Would really appreciate a little help if you can spare the time


    1. John Hagensieker Post author

      Are you using a Virtual Machine of Ubuntu under Windows? I looked at your pic and I don’t think you are seeing your USB SDR device. If you are using Virtualbox you need to enable the USB device that is plugged in.

      1. Andrew Dixon

        Its looking like I have some Ubuntu issue… took suggestion an installed GQRX.. no errors during install but get
        XDG_RUNTIME_DIR not set, defaulting to ‘/tmp/runtime-useradd’ error
        and a
        QXcdConnection: could not connect to display error
        so cant even run GQRX

        Searching ….

  18. John G.

    I have OP25 running on a Pi3, can see the control channel processing TGIDs, decoding voice, and showing TG alias, but it only lasts for a few moments. The program will still be displaying the stream of calls, but stops decoding voice. I am just a few hundred yards from the prime site, so signal strength is not an issue.

    I am really impressed with the audio decoding in OP25 but I cannot get it to last more than a few minutes, if that. Any suggestions?

  19. John Grembowski

    Yes sir. I am using a 2.1a brick. I have messed with sampling rates and LNA and nothing keeps it going for more than 30 secs or so. I’m watching it change frequencies and display TGs as it should, but audio just stops dr oding.

  20. robbo

    not a good start

    lenovo@lenovo:~$ git clone https://github.com/boatbod/op25.git

    Command ‘git’ not found, but can be installed with:

    sudo apt install git

    lenovo@lenovo:~$ sudo apt install git clone https://github.com/boatbod/op25.git
    [sudo] password for lenovo:
    Reading package lists… Done
    Building dependency tree
    Reading state information… Done
    E: Unable to locate package clone
    E: Unable to locate package https://github.com/boatbod
    E: Couldn’t find any package by glob ‘https://github.com/boatbod’
    E: Couldn’t find any package by regex ‘https://github.com/boatbod’

      1. kent

        up and going at step ; ./rx.py –args ‘rtl’ -N ‘LNA:47’ -S 2400000 -f 168.0934e6 -o 25000 -q -2 -T trunk.tsv -V -2 -U 2> stderr.2

        seeing 4 or so voice frequencies updating but no audio coming through?

        alsa plugin in audio settings is up, but i cannot hear anything

        could it be the frequency drift on my sdr, it states a control channel for me as 168.100 on the website but im tuned to 168.0934 to get a good RX , could that throw out is tuning correctly to the frequency when it changes to grab the audio?

  21. Pingback: Setting up OP25 Scanner Trunking on an Ubuntu Virtual Machine | RadioHobbyist.org


    I am confused about control freq and talk groups for LARGE systems. My county, Shelby County Alabama is a part of the Alabama First Responders Network. Shelby County Has 5 different control frequencies, see https://www.radioreference.com/apps/db/?sid=7258&siteSort=county#sites .

    Within the Shelby County designation, there are 40-50 talk groups. I obviously do not need to tune to ALL of these TG’s. Is each TG associated with a specific control channel or ALL control channels? My question is, how do I know which talk group is linked to which control channel, or does it matter?

  23. Rob Hammerstein

    What if you are trying to set up for a certain county in Zone 3 of the NC VIPER System? Anybody tried this before? I see the site frequencies for each site but nothing for the county in particular.

  24. Marek

    So I am tuned to STARCOM21 773.84375c but only want to monitor two TG, 2609 and 2676. Do I have to put all of the other TGs in the blacklist even if i’m using the TGID Tags File with only two TG like we have here in the instructions?

    I had this running in one shot, awesome instructions!!!

  25. Zach

    It’s working! Only issue is that I wanted to only listen to certain talk groups, but I think I’m picking up pretty much my entire state because our Simulcast system works that way. How might I listen only to a few talk groups rather than all of them?

  26. bob salter

    Running RTL-SDR v3 and just no luck getting nac – have played w/ sample rate, offset, gain, Q and it just never dislays… No problem using unitrunker so I know I have the right control frequency. rtl_test gives correct output, gqrx works; just can’t get the ./rx.py –args ‘rtl’ -N ‘LNA:47’ -S 2400000 -f489.0750e6 -o 25000 -q –2 to produce any lines. Using ubuntu 1804 – have tried multiple dongles, even (2) machines..

  27. bob salter

    should have mentioned – trying to follow marin emergency radio authority. no problem w/ unitrunker 2 and dsdplus on a windows machine using 2 dongles

  28. Bob S

    Trying tune MERA (Marin County) and get a GNU constellation plot that looks like a semicircle from +5 to +5 using control frequency 489.075. I know that is good because it works with Unitrunker. Also know that my system is set up properly because I am able to set up my command line and trunking tsv and to decode Golden Gate Bridge District at 771.331250. Does OP25 not work for Motorola Type II Smartzone?

  29. LordDonkey

    If you add -l http: to the end you can enable the web interface, which in my opinion looks better. Radio Reference is a huge help for finding control channel frequencies, NAC, and talk group IDs.

  30. William Higinbotham

    Update from last comment: If your having a problem with Make giving an error during build. Please make note of this page. My observation appears to correct this. But I am still in the process of getting this up and running. https://osmocom.org/issues/3776. Please note this has to do with recent OP25-Master.zip download Modified 16 June 2019 06∶04∶52 PM EDT

  31. John

    I followed all the build steps with a Pi3B and have properly tuned in a known Phase 1 control channel with about 20 dB S/N. I get an “Allocating 15 zero copy buffers” instantly upon running :
    ./rx.py –args ‘rtl’ -N ‘LNA:47’ -S 2400000 -f 850.600e6 -o 25000 -q 5
    #5 graph confirms the control channel is tuned
    #2 shows clusters in the NW and SW corner with the eastern half a continous arc rather than clusters.

    gr-osmosdr 0.1.4 (0.1.4) gnuradio 3.7.11
    built-in source types: file osmosdr fcd rtl rtl_tcp uhd miri hackrf bladerf rfspace airspy airspyhf soapy redpitaya freesrp
    Using device #0 Generic RTL2832U SN: 712733086766700
    Found Rafael Micro R820T tuner
    [R82XX] PLL not locked!
    gain: name: LNA range: start 0 stop 0 step 0
    setting gain LNA to 47
    supported sample rates 250000-2560000 step 24000
    [R82XX] PLL not locked!
    Using two-stage decimator for speed=2400000, decim=25/4 if1=96000 if2=24000
    Project 25 IMBE Encoder/Decoder Fixed-Point implementation
    Developed by Pavel Yazev E-mail:
    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.
    p25_frame_assembler_impl: do_imbe[0], do_output[0], do_audio_output[0], do_phase2_tdma[0], do_nocrypt[0]

    I will try lowering the bandwidth from 2.4 Megs to 1 or 2 Megs
    Anything else I can try?

  32. LordDonkey

    Here’s a way to automatically name your stderr.2 log so they aren’t overwritten each time OP25 is run. Simply it just creates a variable called “today” with todays date and time and appends it to the log file name. This would be saved as a .sh and ran

    #! /bin/sh
    cd /home/michael/op25//op25/gr-op25_repeater/apps
    today=`date ‘+%F_%I:%M:%S-%p’`;
    ./rx.py –args ‘rtl’ -N ‘LNA:47’ -o 25000 -q -2 -T trunk.tsv -V -2 -U 2> “$today”__log.2 -l http: -n -d -300 -v 8 -t

  33. Jon

    Got this up and running. Is there any way to modify one of the files to output the frequency and talkgroup info to a simple 16×2 LCD panel? Would like to free up a display and make the whole setup portable with the LCD as the display.

  34. Doug Turpin

    Thanks so much for this awesome guide. Most of the local PD and Fire in Southwestern Va are analog but the State Police are on P25 Phase 1. I had been trying to get this to work for a while until I stumbled across this post. I had no issues getting up and running once I was here.

  35. simplio

    I did your initial instructions on the install then rebooted and cd into /op25/op25/gr-op25_repeater/apps

    then tried your args to see if it runs. then it returns with

    Traceback (most recent call last):
    File “./rx.py”, line 52, in
    import op25
    ImportError: No module named op25

    Is not working please help me.

  36. DB

    Using an NESDR, I can launch the first part to get the NAC
    but when I try to launch with the trunk file, I get this error. anyone else see this?

    ./rx.py –args ‘rtl’ -N ‘LNA:47’ -S 2400000 -f 859.7625e6 -T trunk.tsv -V -2 -U
    linux; GNU C++ version 7.3.0; Boost_106501; UHD_003.010.003.000-0-unknown

    gr-osmosdr v0.1.x-xxx-xunknown (0.1.5git) gnuradio 3.7.11
    built-in source types: file osmosdr fcd rtl rtl_tcp uhd plutosdr miri hackrf bladerf rfspace airspy airspyhf soapy redpitaya freesrp
    Using device #0 Realtek RTL2838UHIDIR SN: 00000001
    Found Rafael Micro R820T tuner
    [R82XX] PLL not locked!
    gain: name: LNA range: start 0 stop 0 step 0
    setting gain LNA to 47
    supported sample rates 250000-2560000 step 24000
    [R82XX] PLL not locked!
    [R82XX] PLL not locked!
    Using two-stage decimator for speed=2400000, decim=25/4 if1=96000 if2=24000
    Project 25 IMBE Encoder/Decoder Fixed-Point implementation
    Developed by Pavel Yazev E-mail:
    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.
    op25_audio::open_socket(): enabled udp host(, wireshark(23456), audio(23456)
    p25_frame_assembler_impl: do_imbe[1], do_output[0], do_audio_output[1], do_phase2_tdma[1], do_nocrypt[0]
    Traceback (most recent call last):
    File “./rx.py”, line 921, in
    rx = rx_main()
    File “./rx.py”, line 835, in __init__
    self.tb = p25_rx_block(self.options)
    File “./rx.py”, line 196, in __init__
    File “./rx.py”, line 762, in open_usrp
    File “./rx.py”, line 690, in __set_rx_from_osmosdr
    self.__build_graph(self.src, capture_rate)
    File “./rx.py”, line 323, in __build_graph
    self.trunk_rx = trunking.rx_ctl(frequency_set = self.change_freq, debug = self.options.verbosity, conf_file = self.options.trunk_conf_file, logfile_workers=logfile_workers, meta_update = self.meta_update)
    File “/home/db/op25/op25/gr-op25_repeater/apps/trunking.py”, line 659, in __init__
    File “/home/db/op25/op25/gr-op25_repeater/apps/trunking.py”, line 741, in build_config_tsv
    nac = int(fields[‘nac’], 0)
    KeyError: ‘nac’

    1. DB

      Here is my trunk file seutp —
      Sysname Control Channel List Offset NAC Modulation TGID Tags File Whitelist Blacklist Center Frequency
      Troop L 859.7625 0 0x3a1 CQPSK tompkins.tsv 859.7625

  37. Pingback: OP25 For P25 Phase 2 Digital Voice Decoding | VA3DBJ.ca

  38. Jason

    This is badass! I used VirtualBox on a Windows 10 box for the Ubuntu install. Took a couple extra steps to get it working but man, this is amazing! Thank you so much for the detailed instructions.

  39. Jeremy

    Thanks for the tutorial. Got it up and running on Linux Mint after my county switched to a P25 system from analog. I see a new scanner purchase in the not too distant future, but I couldn’t beat the cost of the RTL-SDR to find out what is or is not encrypted before spending a minimum of $350 on a new one.

  40. Jeff B

    Have changed the -q -2 to everything between (-5 thru +6) and can’t get NAC ??? I get the wave and spike that is right on the freq. I’ve set 853.0625 some of the setting produce the rolling oooooooo

    GQRX work fine and I can hear control channel. Using NooElec NESDR Nano 2+ Tiny Black RTL-SDR USB Set (RTL2832U + R820T2)

    Anyone know what else I can try to get the NAC I need to continue or can I get the NAC elsewhere. ?

  41. Jimmie Nichols

    I got this working by following your Awesome instructions! Thank you so much. I’m having trouble with the bash script for starting tho. I’ll come BK tommorow and be more specific.

  42. Scott B

    Hey John,

    I know this is an older blog post but I wanted to focus your attention on a bug myself and many others have run across during the installation of OP25. I’m familiar and comfortable with Linux, but what follows is absolutely a layman’s interpretation of a complex issue regarding the compiling of OP25 via cmake and the included install.sh executable.

    Later versions of cmake are encountering errors during the compile process. Specifically, this error:

    make[2]: *** No rule to make target ‘op25/gr-op25_repeater/swig/op25_repeater_swig.py’, needed by ‘op25/gr-op25_repeater/swig/op25_repeater_swig.pyc’. Stop.
    make[1]: *** [CMakeFiles/Makefile2:954: op25/gr-op25_repeater/swig/CMakeFiles/pygen_op25_gr_op25_repeater_swig_a9103.dir/all] Error 2
    make: *** [Makefile:130: all] Error 2

    After compiling, either via install.sh or following OP25’s included compile instructions, running rx.py returns this error:

    Traceback (most recent call last):
    File “./rx.py”, line 52, in
    import op25
    ImportError: No module named op25

    The fix for me and, from what I can tell, a few others, was to revert cmake to 3.10.3. I won’t try to explain the root of the problem; suffice it to say, commits later than 3.10.3 introduce and fail to correct an issue that impacts swig dependency parsing. It’s documented by both the devs for cmake and OP25.

    Again, the fix for me was to uninstall cmake 3.13.x and build cmake 3.10.3 from source (only way I could get it to compile OP25 correctly – pointing cmake at the earlier version without “installing” it on the system wouldn’t fix the error). This page goes into the problem in more detail: https://github.com/boatbod/op25/issues/25

    As this blog/tutorial is still called a “living” document, you might want to consider adding a note in the installation procedures indicating users can encounter this problem.

    For reference:

  43. Graham Norbury (boatbod)

    The latest versions of both osmocom and boatbod versions of OP25 have an (experimental) “-X” command line option to automatically adjust tuning. Older rtl dongles needing significant ppm correction will probably still have to be set up somewhere close for tracking to be effective, but modern dongles should be largely plug an play.

  44. Shane Irving

    Is there any chance we could get a live CD or VM as I’ve followed all of the instructions and it simply does not work on Ubuntu 18.04.4 LTS

    Even reading from a file does not work Errors like this….
    user@user-virtual-machine:~/op25/op25/gr-op25_repeater/apps$ sudo ./rx.py –args ‘file’ -O pulse
    linux; GNU C++ version 7.3.0; Boost_106501; UHD_003.010.003.000-0-unknown

    gr-osmosdr 0.1.4 (0.1.4) gnuradio 3.7.11
    built-in source types: file osmosdr fcd rtl rtl_tcp uhd miri hackrf bladerf rfspace airspy airspyhf soapy redpitaya freesrp

    FATAL: No file name specified.

    Trying to fill up 1 missing channel(s) with null source(s).
    This is being done to prevent the application from crashing
    due to gnuradio bug #528.

    Traceback (most recent call last):
    File “./rx.py”, line 986, in
    rx = rx_main()
    File “./rx.py”, line 899, in __init__
    self.tb = p25_rx_block(self.options)
    File “./rx.py”, line 150, in __init__
    sys.stderr.write(‘RTL Gain of %d set to: %.1f\n’ % (gain, self.src.get_gain(‘LNA’)))
    UnboundLocalError: local variable ‘gain’ referenced before assignment
    user@user-virtual-machine:~/op25/op25/gr-op25_repeater/apps$ sudo ./rx.py –args ‘file’ -i ‘cow’ -O pulse
    Traceback (most recent call last):
    File “./rx.py”, line 986, in
    rx = rx_main()
    File “./rx.py”, line 899, in __init__
    self.tb = p25_rx_block(self.options)
    File “./rx.py”, line 207, in __init__
    File “/usr/lib/python2.7/dist-packages/gnuradio/gr/hier_block2.py”, line 92, in __getattr__
    return getattr(self._impl, name)
    AttributeError: ‘top_block_sptr’ object has no attribute ‘open_file’

    Windows programs like DSD+ work fine, Linux based apps always seem broken and require a 300 IQ just to get things working 🙁


Leave a Reply to Marek Cancel reply

Your email address will not be published. Required fields are marked *