Thursday, July 6, 2017

Listening to local 700 MHz Simulcast public safety cheaply

March of last year I blogged about a method I have been using since 2013 to listen the Brown County Sustained Interoperable Radio for Emergency Notification (SIREN) 700 MHz APCO-25 Simulcast system.

The method I mentioned involved using a commercial radio specifically programed not to affiliate with the system.  At the time there were no scanners capable of dealing with LSM (linear simulcast modulation).  Well there are a couple now; the Uniden BCD436 does handle simulcast pretty well, and the newest is the Unication G4/G5 receiver.  The problem is both will set you back well over what most people are willing to pay.

A lot of people are listening to the Police these days on smartphones using various apps, which unknown to many of them is a volunteer effort of a local guy feeding broadcastify over the internet.  I don't like that way, as it eats the phone battery and data plan.  Nor I am overly fond of reliance on someone else to receive the info.  I am the type who likes a scanner on basically all the time in the background at home.  This sounds better, doesn't rely on the internet and gives you the control to stop the scan on an interesting talkgroup. Software Defined Radio is the future of radio anyway so might as well try and learn something I figure.

Today I will detail a software defined radio, that you can build for about $60, that will let you listen.  It uses the RLT-SDR hardware, a Raspberry Pi computer, and runs the OP25 trunking software ontop of GNU Radio.

Unless you live in complete darkness, you should know that RTL is a chipset originally designed for a USB digital TV tuner dongle.  Since the TV frequency band is basically 30 MHz to 2 GHz, the hardware is capable of pretty much anything in that range.  The folks behind osmocom.org are to thank for creating a replacement driver that enables all kinds of cool, and really cheap SDR projects, like the one I am about to explain.  (Did I mention I think someone like the ARRL should give folks like this an award?)


Needed Hardware:
-Raspberry Pi3 single board computer
-SD card (8 GB is fine)
-A RTL-SDR dongle (mine is version 3), and a SMA rubber duck antenna
-Amplified speaker (bluetooth?)
And just to get things setup:
-USB keyboard and USB mouse
-HDMI monitor or adapter to achieve the same (I have a nifty Radio Shack HDMI to VGA adapter that I got dirt cheap when they were going belly-up)

What finally pushed me to try this on the Raspberry Pi was a post from John, N8UR that is some of the best info I have found on how to use/configure OP25.  I applauded his write up and mentioned if it could run on an ARM computer, I'd be playing with it tomorrow.  Shortly their after it was confirmed by the code maintainer that it will run on a Raspberry Pi, so I sought out to figure it out.

Installing:

You'll want to download the Desktop version of Raspbian, and get that on a SD card.  We need the GUI to set things up/verify the signal, but after that, it can be turned off and this thing can run headless.  Perform the normal setup things with raspi-config (set keyboard to US, enable SSH, etc)

The OP25 author released these helpful tips to getting a good start:
First, the testing has been done on the PI 3 "B" with the default install of Raspbian. Load average was around 1.5 or 1.6, with the RPI GUI running and 'top' running in another window...
You'll need to edit the /etc/apt/sources.list file; the file contains the needed "deb-src" line in it, but it's commented out. To fix, edit the file and remove the '#' so the 'deb-src' appears in column one of the file. Save the file, then proceed with the install as follows, first installing the OP25 prerequisites:
sudo apt-get update
sudo apt-get build-dep gnuradio
sudo apt-get install gnuradio gnuradio-dev gr-osmosdr librtlsdr-dev libuhd-dev libhackrf-dev libitpp-dev libpcap-dev git

Then install OP25

cd ~
git clone https://git.osmocom.org/op25
cd op25
git checkout max

mkdir build
cd build
cmake ../
make
sudo make install
sudo ldconfig


The previous generation OP25 application (scope.py) is being deprecated soon; instead we now use the new rx.py. This app is discussed in the README file that's in the OP25 repo that you checked out:

/op25/op25/gr_op25_repeater/apps/README
(Optionally to speed up the compiling add -j4 to the make command it will use all four cores on a Pi3 and save a ton of time. )
You'll also likely want to have some other tools:
sudo apt-get install ftp gnuplot xrdp

You'll note this new max branch has a different GUI.  The previous version used the wxwidgets GUI library, and that was a common compatibility/code maintenance issue.  This new version has a lighter weight approach using gnuplot for the GUI.  Keep in mind that like any cool Linux development like this is in a constant state of flux, so the steps I detailed today, may very well change tomorrow.  I am sure I'll be blogging again about this.

Now on to the things that I had to figure out.

Configuring/Running:

The first thing you want to do is fire up the new rx.py script tuned to the data control channel of the Brown County System (772.63125)

Everything cool happens in this directory, so change there:

/op25/op25/gr-op25_repeater/apps/

I assume you read the README file mentioned before, which really tells you everything.

Here is my shell script to start the thing.  The first line is the finished product.  It starts the thing with no GUI.  The second line (uncomment it) I used for trouble shooting.  It fires up the gnuplot constellation (more on that shortly).   I tried other sampling rates, but ultimately found the  command line sample  rate to –S 1000000 lowered the processor cycles consumed by the higher SDR sampling rate, which is important when dealing with the Pi.

An observation I had was with OP25 was sometimes it misses very short or very quick response transmissions. It seemed like it just couldn't switch fast enough back and forth between the control channel and any given voice trunk on the system. I tried various sample rates thinking this would lessen the processor load and help this.  Then I read that RTL devices aren't known for their speedy tuning abilities.  Then I learned about the -o (tuning offset) option.  Adding an offset of -o 12.5e3 improved the missing audio problem for me.

Before you start the thing, there are two files you need to create;  trunk.tsv and brown.tsv.  However you can start it without the -T trunk.tsv option just to see if its decoding the control channel.  If everything is working, you'll see a terminal output with an increasing tsbks (trunking signaling blocks), and active voice channels.  If you don't even see that, you should look at the gnusplots and stderr error log for clues as to why its not decoding.




 The gnuplots are live (animated), though what I show here are obviously still screenshots.





Using the constellation plot as a guide you may need to re-arrange the antenna and play with the various command line options until you get a good 4-point constellation. What you want to do is to get rid of the cluster of symbols at the center of the plot so all the symbols move outward into four discrete groups.   If you live near one of the towers you may need to back off the gain to achieve this.  Another common thing to know is if you are tuned on center.  You might want to calibrate your RTL stick using SDRSharp or some other method.  Else just look for -1200 type errors, and add a -q -1 or -q -2 to your rx.py command line for compensation.

The bottom line is: Look in the stderr file for anything untoward.


On To Trunking:
Once you can decode the data control channel properly its time to configure the trunking.  This is commonly done in a file called trunk.tsv.






Make sure that all of the fields in your trunk.tsv are quoted and tab spaced.  Note the Brown System NAC is 0x4a1.

As you can see trunk.tsv references brown.tsv which is where the talk groups are defined.




brown.tsv provides a table of talkgroup numbers and names for the Brown SIREN site.  You are basically defining what you want it displayed as when its active.  Once again there must be a tab space between the talkgroup decimal ID and name.



Starting The Audio:

After rx.py starts, you can start the audio listener.  Do that in a separate terminal window, or start it as a background process.  There is more than one way to listen/ get audio to speakers.  The -w option in rx.py is the output data to wireshark option.  This includes audio as UDP.

Using that, a simplistic way to redirect the audio portion to your sound system is to use netcat.




The first line tells the Raspberry Pi to set its audio output to the 1/8" jack, instead of HDMI which may have been automatically setup when you hooked up a monitor.  Netcat redirects to aplay, which is pretty self explanatory.

When its up and running the terminal does show you what talkgroup you are hearing.



This should be everything you need to know.  It has a learning curve, but anything cool usually does.  If someone finds a nice case (a 6x4x2 project enclosure) and an amplified speaker with its own volume knob then we have the final touches.  I'd look forward to reading others performance feedback on other single board computers, and SDRs.  The Pi3 is pretty much the bare minimum, so I'd recommend heatsinks for your Pi.  I haven't yet read of anyone who has got it going on Asus Tinker Board, but would be interested in hearing from anyone on that.





{edit 8/13/17}
A friend reports that they tried the NooElectric SDR and have had better results.  They have done some extensive testing and report no chopped audio, and with few if any chirps on the beginning or end of transmissions.

One note; the NooElec dongles do not seem to exhibit any significant DC spike so the -o 12.5e3 offset on your rx.py command line offset is unnecessary. We have tested two of them and they work just fine with -q 0 specified.  Below are a couple of links to find them on the internet. 



And here is what my friend did to complete the project.  He installed it inside of an old Motorola Alert Monitor.  He drives the speaker with a 5v 3w amplifier. 

The small oled 128x32 display on front shows ip and disk usage on bootup. ( Use the available adafruit libraries and examples to add the necessary pieces to the OP25 terminal.py script.)


While receiving it shows talkgroup, frequency, and talkgroup description. The original volume knob controls volume, and turns system on/off.


Like I mentioned above, any cool Linux development like this is in a constant state of flux, so the steps I detailed today, may very well change tomorrow.  Thanks to these folks to keep sharing pointers like I did:

{2018 Update} I recommend reviewing KN4FMV's op25 for dummies:
https://www.hagensieker.com/wordpress/2018/07/17/op25-for-dummies/

{2019 Update} KN4KNG's blog:
https://abowman.org/2019/01/27/op25-on-rpi3-part-1/