Find any trunked system's control channel with rtl_power — no database needed
Drive into a county you've never scanned and the question is the same every time: which of the thirty carriers in the 800 MHz band is the control channel? You could look it up. Or you could notice that voice channels come and go with each call, while the control channel is a 9600-baud data stream that transmits 24 hours a day. Measure the band three times and keep the carriers that were there all three times.
Sweep it
rtl_power -f 851M:869M:12.5k -g 30 -i 5 -e 60 sweep.csv
That is twelve passes over a minute, one row per pass per 2.4 MHz slice, with a dB value per 12.5 kHz bin. Pull out the bins that are at least 12 dB over the band's median in every pass:
python3 - <<'EOF'
import csv, statistics
hist = {}
for row in csv.reader(open("sweep.csv")):
lo, step = float(row[2]), float(row[4])
vals = [float(v) for v in row[6:]]
med = statistics.median(vals)
for i, v in enumerate(vals):
f = round((lo + i * step) / 1e6, 4)
hist.setdefault(f, []).append(v - med)
steady = {f: min(v) for f, v in hist.items() if len(v) >= 3 and min(v) >= 12}
for f, m in sorted(steady.items(), key=lambda x: -x[1])[:10]:
print(f"{f:.4f} MHz +{m:.0f} dB in every pass")
EOF
On a Saturday afternoon in Pinellas that prints eight or nine frequencies. The strongest few are control channels; the rest are busy voice channels of the same systems (a countywide system keeps several up almost continuously) and the odd paging transmitter.
Confirm with the decoder
Point dsd-fme at each candidate for ten seconds:
rtl_tcp -a 127.0.0.1 -p 23471 -b 32 -n 64 &
dsd-fme -ft -i rtltcp:127.0.0.1:23471:856.9625M:40:0:12:0:2 -o udp:127.0.0.1:23456
A control channel prints Sync: +P25p1 … TSBK lines several times a second — those are the grants, idents and site data. A voice channel prints HDU / LDU1 frames and then Base Frequency Not Found as dsd-fme waits for a channel map that never comes. P25 phase 2 (+P25p2) is always a voice channel; the control channel of a phase 2 system is still phase 1.
If the sync is there but the audio is garbage, try the QPSK demodulator (-ft -mq): countywide simulcast systems transmit LSM, which the default C4FM demod can't follow. More on that.
What the bridge does with this
Exactly the above, continuously. The listening dongle's sweep always includes 851–869 MHz; the hunt reads that sweep's per-bin history instead of starting a second rtl_power (two processes on one dongle leaves it wedged — we learned that the hard way), ranks the steady carriers, folds a site's several carriers into one entry, and tries them strongest-first, C4FM then QPSK. The whole thing takes 15–30 seconds from cold. The journal line looks like:
bridge: control-channel hunt: 800 MHz (sweep, 3 passes): 18 steady — 856.9625 (+38 dB), 857.9625 (+34 dB), …
bridge: systems ranked: 856.9625 (+38 dB) Pinellas County (Countywide Simulcast); 857.9625 (+34 dB) SLERS (P25); …
Names come from a RadioReference export when you've loaded one; without it the system is named by its NAC ("unlisted P25 system (NAC 800)") and everything still works — you just don't get agency names on the talkgroups.
Rather not build it?
Spotter $64 · Full Spectrum $499: the builds on this blog, programmed and tested, set up for where you drive, with free updates for life. The guides stay here, free, if you change your mind.
Shop Join the free Android beta
Open firmware and bridge on GitHub · receive only · every command on this blog is copied from a Pi we run