GopherTrunk v0.2.3 — social announcement drafts
Copy-paste drafts for posting the v0.2.3 release. Two versions below: a longer one for Reddit and a tighter one for Discord.
Release: https://github.com/MattCheramie/GopherTrunk/releases/tag/v0.2.3
Title: GopherTrunk v0.2.3 — POCSAG paging, remote rtl_tcp, one dongle covers many DMR repeaters, Hamlib rigctld, new web viz panels
Body:
GopherTrunk v0.2.3 is out. GopherTrunk is a pure-Go digital-trunking
radio scanner for RTL-SDR / HackRF / Airspy / Airspy HF+ — P25 (Phase 1 +
2), DMR (with AMBE+2 voice), NXDN, Motorola Type II, EDACS, LTR, MPT 1327,
dPMR, D-STAR, YSF. No CGO, no librtlsdr / libhackrf / libairspy /
libusb at build or runtime, single ~10 MB static binary for Linux, macOS,
and Windows, with a headless daemon, a Bubbletea TUI cockpit, and a
browser-based web operator console.
This is a big one. v0.2.2 was the operational-recovery release; v0.2.3 is
the scope-expansion release. New mode (POCSAG paging), new dongle
topology (one wideband SDR covers a whole repeater cluster, plus remote
rtl_tcp sources mounted as virtual tuners), new amateur-radio integration
(Hamlib rigctld TCP server), and four new web panels that turn the
console from “trunking dashboard” into a full SDR observation surface.
What’s new since v0.2.2:
- POCSAG paging decoder. New protocol end-to-end: BCH(31,21) FEC
(corrects up to 2 bit errors per codeword), sync-codeword locker with
polarity-inverse fallback, batch carve-up, full-RIC reconstruction from
the 18-bit address-codeword field + slot index, and both message
encodings (CCIR 584 extended BCD numeric + 7-bit LSB-first ASCII
alphanumeric). Pages publish on a new
events.KindPagerMessagebus event, persist to apager_logSQLite table, are queryable viaGET /api/v1/pager/messages?limit=N, and render live in a new/pagersweb panel (received time, RIC, function code, encoding, body, bit-error count). DSP wiring (FM demod → bit slicer →Syncer.Push) lands next. role: widebandSDR devices — one dongle, many DMR Tier II repeaters and DMR Tier III control channels. A single SDR pinned to a centre frequency now decodes every conventional DMR repeater AND a DMR Tier III control channel inside its IQ bandwidth (e.g. several 12.5 kHz carriers within a 2.4 MHz IQ window around 453 MHz), no extra hardware needed. Add arole: widebandentry tosdr.deviceswith acenter_freq_hzand achannels: [...]list binding each frequency to atrunking.systemsentry; T2 and T3 can mix on the same dongle. Fans the IQ out via the newinternal/dsp/tunerpackage (DDC-per- channel or shared polyphase channelizer, picked by channel count).- Remote
rtl_tcpSDRs. A newrtltcpdriver mounts any number of remotertl_tcpservers as virtual tuners alongside locally-attached USB dongles. Speaks the well-known librtlsdr wire protocol (12-byteRTL0header, u8 IQ stream, 5-byte command packets) used by SDR++, Gqrx, and OpenWebRX, so any host runningrtl_tcpcan publish its dongle to the daemon. Pool roles, broker fan-out, baseband recording, and the live spectrum panel all work against remote sources just like local ones. Plaintext on the wire — restrict to trusted networks or wrap with SSH/WireGuard/Tailscale. - Hamlib
rigctldTCP server. Opt-in (api.rigctld: "127.0.0.1:4532") endpoint speaking the standard rigctld wire protocol so external amateur-radio tooling (Cloudlog, GridTracker, PSTRotator, satellite trackers,rigctl(1)) can read and set the control SDR’s frequency without learning the GopherTrunk REST API. Implements the ~10 commands real clients send; unknown commands returnRPRT -1per Hamlib’s convention. RX-only —set_ptt 1is rejected. Tuning routes through the iqtap broker so external retunes stay coherent with the spectrum panel’s frequency axis. - Bookmarks / frequency manager. UI-managed conventional channel
list (marine VHF, NOAA weather, FRS/GMRS, repeater outputs, public-
safety conventional fall-backs) backed by a
bookmarksSQLite table. Each row carries name, frequency, mode, optional CTCSS / DCS, freeform notes, and an operator-defined group tag. REST endpoints under/api/v1/bookmarks; web panel at/bookmarks. Mutations publishbookmark.{created,updated,deleted}events so subscribers refresh without polling. - Live spectrum panel with click-to-tune + bookmark markers. New
FFT producer feeds a
/spectrumweb panel rendering a real-time waterfall over the SDR’s IQ bandwidth. Clicking anywhere on the canvas posts the bin’s centre frequency toPOST /api/v1/spectrum/devices/{serial}/tuneand the SDR retunes immediately. Bookmarks render as small cyan ticks across the top of the waterfall wherever a bookmark frequency falls inside the visible band. Tune goes through the iqtap broker so the frequency stays coherent across the spectrum, constellation, rigctld, and CC decoder views, and survivespool.Reacquire. - Constellation viewer. New web panel at
/constellationthat renders a live 2D scatter of decimated IQ samples (2 ksps default). Brighter dots = newer samples; reference rings at |z|=0.5 and |z|=1.0; per-frame dBFS energy banner. Identifies signal shape visually — PSK clusters, FSK arcs, AM rotation, noise circles, DC bias, frequency-offset spirals — without launching a separate SDR receiver alongside GopherTrunk. - CC Activity panel. New web panel at
/ccthat filters the events stream down to control-channel chatter: voice grants, affiliations, registrations, patches / dynamic regroups, talker aliases, CC lock / loss, call start/end. Kind + system substring filters narrow the view; pause freezes the display without disconnecting the bus. - IQ tap broker — multi-consumer SDR fan-out. New broker package lets multiple consumers (decoder + spectrum + constellation + rigctld) share the same SDR’s IQ stream without disturbing decode. The foundation under all four of the new web panels and the wideband multi-channel work.
gophertrunk sdr doctor— per-dongle driver-binding report. Many Windows 11 users reported RTL-SDRs not being recognized despite appearing in Device Manager. Windows has no equivalent ofUSBDEVFS_DISCONNECT(you can’t programmatically rebind a USB function driver), so the fix is diagnostic rather than mechanical: a newsdr doctorsubcommand walks the OS USB tree, reads the bound function driver via SetupAPI on Windows or the interface-0 sysfs symlink on Linux, and prints a row per dongle with an actionable next step (run Zadig; pick Interface 0 not the composite parent; re-target WinUSB instead of libusbK; blacklistdvb_usb_rtl28xxu). Read-only — safe to run as a regular user alongside a live daemon.- Voice-call watchdog now gates on decoder progress (#356). Voice
chains used to keep a call alive forever via an unconditional 1 s
heartbeat. The four chains (P25 Phase 1, P25 Phase 2, DMR, NBFM) now
gate
Engine.Touchon actual decoder progress — an LDU / superframe / voice subframe / PCM batch — so the 30 s inactivity watchdog can fire and release the bound voice SDR when transmission stops. Before this fix a stalled decoder (simulcast garbage, vocoder hang) refreshedLastHeardAtevery tick regardless, leaving the active call permanently locked on a single talkgroup and every subsequent grant logging “no voice device available for grant”. - Airspy R2 Windows open path fixed (#270). Defer
SET_SAMPLE_TYPEfromOpen()toStreamIQ(), matching libairspy’s open ordering (GET_SAMPLERATESIN first, no vendor OUT during open). Airspy R2 was failing to open on Windows withwinusb: WinUsb_ControlTransfer OUT: usb: device disconnectedeven thoughsdr listdetected the device. The Windows USB backend also stops foldingERROR_GEN_FAILUREintoErrDeviceGone— that conflation printed “usb: device disconnected” for what is actually a firmware NAK / stalled pipe / wrong-driver-bound condition.
Downloads (Linux / macOS / Windows, x64 + ARM64): https://github.com/MattCheramie/GopherTrunk/releases/tag/v0.2.3
Project & docs: https://gophertrunk.org
Heads-up: the v0.x line is still flagged prerelease — actively developed, and feedback / captures / bug reports are very welcome.
Discord
GopherTrunk v0.2.3 is out
Pure-Go digital-trunking scanner for RTL-SDR / HackRF / Airspy — P25, DMR, NXDN, analog trunked, single static binary, zero CGO.
Scope-expansion release: new mode, new dongle topologies, new viz panels.
What’s new since v0.2.2:
- POCSAG paging decoder — BCH(31,21) FEC, full-RIC reconstruction,
numeric + alphanumeric messages, SQLite log,
/pagersweb panel. role: widebandSDR — one dongle covers many DMR Tier II repeaters AND a Tier III control channel inside its IQ bandwidth. T2 and T3 mix on the same dongle; channelization via DDC-per-channel or shared polyphase channelizer.- Remote
rtl_tcpSDRs — mount any number ofrtl_tcpservers as virtual tuners alongside local USB dongles; speaks the librtlsdr wire protocol used by SDR++, Gqrx, OpenWebRX. - Hamlib
rigctldTCP server — Cloudlog / GridTracker / PSTRotator / satellite trackers /rigctl(1)can drive the control SDR over the standard amateur-radio control protocol. RX-only. - Bookmarks / frequency manager — UI-managed conventional channel list backed by SQLite. Marine VHF, NOAA, FRS/GMRS, repeaters; CTCSS / DCS / mode / group tags; live bus events on mutation.
- Live spectrum panel — real-time waterfall over the SDR’s IQ bandwidth. Click-to-tune posts the bin frequency to a new tune endpoint; bookmark frequencies render as cyan ticks.
- Constellation viewer — live 2D IQ scatter at
/constellation, identifies signal shape visually (PSK clusters, FSK arcs, noise circles, frequency offsets). - CC Activity panel — filtered events stream at
/ccfor control-channel chatter only (grants, affiliations, patches, talker aliases). - IQ tap broker — multi-consumer SDR fan-out so the decoder, spectrum, constellation, and rigctld can share one dongle’s IQ.
gophertrunk sdr doctor— Windows / Linux per-dongle driver- binding report with actionable next steps.- Voice-call watchdog gates on decoder progress (#356) — stalled decoders can no longer keep a call alive forever; the 30 s inactivity watchdog actually fires now.
- Airspy R2 Windows open path fixed (#270) — defer SET_SAMPLE_TYPE to StreamIQ, matching libairspy’s open ordering.
Download: https://github.com/MattCheramie/GopherTrunk/releases/tag/v0.2.3 Docs: https://gophertrunk.org