- Rust 78.2%
- Svelte 16.4%
- TypeScript 4.3%
- CSS 0.8%
- Shell 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [tokio](https://tokio.rs) ([source](https://github.com/tokio-rs/tokio)) | dependencies | patch | `1.54.0` → `1.54.1` | --- ### Release Notes <details> <summary>tokio-rs/tokio (tokio)</summary> ### [`v1.54.1`](https://github.com/tokio-rs/tokio/releases/tag/tokio-1.54.1): Tokio v1.54.1 [Compare Source](https://github.com/tokio-rs/tokio/compare/tokio-1.54.0...tokio-1.54.1) ##### 1.54.1 (October 21st, 2026) ##### Fixed - time: revert "remove the runtime handle from timers" ([#​8692]) [#​8692]: https://github.com/tokio-rs/tokio/pull/8692 </details> --- ### Configuration 📅 **Schedule**: (in timezone America/Los_Angeles) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNzYuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjE3Ni4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: #24 |
||
| crates | ||
| docs | ||
| scripts | ||
| web | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
| renovate.json | ||
Trunk8
A trunking-first SDR scanner you run headless and control from a browser. It aims to decode every trunking protocol SDRTrunk does (P25 Phase 1/2, DMR Tier III / Capacity Plus / Connect Plus / Capacity Max / Hytera XPT, NXDN, MPT 1327, LTR, LTR-Net, Passport), with HackRF and PlutoSDR as first-class hardware.
Status: M2 (P25 Phase 1 trunking) working. Add a system by its control channel and Trunk8 detects the site, follows grants onto voice channels on any tuner that covers them, decodes IMBE voice, records calls and streams them to the browser. Conventional analog channels (NBFM/AM with CTCSS/DCS) work too. Validated against real off-air C4FM and CQPSK (simulcast) recordings; not yet tested on live hardware. See docs/PLAN.md for the roadmap and docs/ui-sketch.html for where the UI is headed.
Build
Requires Rust 1.90+ and Node 22+. SoapySDR is optional at runtime; it's used for devices without a native driver (Airspy, SDRplay, LimeSDR) and for a PlutoSDR on the network.
(cd web && npm ci && npm run build) # the UI is embedded into the binary
cargo build --release # digital voice calls are logged, but silent
cargo build --release --features vocoder # also decode P25 voice (see below)
About --features vocoder: digital voice decoding uses the blip25-vocoder crate,
whose synthesis core was reverse-engineered from the reference vocoder. Its full-rate (IMBE,
P25 Phase 1) half covers expired patents; its half-rate (AMBE+2) half reads on US 8,359,197,
in force until 2028-05-20. It is off by default; decide whether it is acceptable where you
build and run Trunk8.
Run
./target/release/trunk8 # every attached SDR, or a synthetic signal if none
./target/release/trunk8 --list-devices
./target/release/trunk8 -s 'driver=hackrf#center=852e6,rate=16e6,gain=30'
./target/release/trunk8 -s 'driver=pluto#center=852e6,rate=4e6'
./target/release/trunk8 -s 'driver=soapy,soapy_driver=plutosdr,hostname=192.168.2.1#rate=4e6'
./target/release/trunk8 -s 'file:capture.sigmf-meta'
./target/release/trunk8 -s 'file:capture.iq?format=cs8¢er=852e6&rate=8e6'
./target/release/trunk8 -s synthetic
Then open http://127.0.0.1:8088. There is no authentication yet, so the server only
listens on localhost by default; change it with --listen at your own risk.
Channels and the call log are stored in SQLite under --data-dir (default
~/.local/share/trunk8), with one Ogg Opus file per call. Calls older than
--retention-days (default 30) are deleted.
Tuners
Tuners opened without an explicit #center= are automatic: when idle, Trunk8 retunes
them to cover channels and systems that no tuner covers, and to pick up voice channels a
system recently missed. Set a center (on the command line or in the UI) to pin a tuner.
Test recordings
scripts/fetch-testdata.sh downloads real P25 recordings used by the decoder tests (they're
skipped when absent). To try trunking without hardware, replay the control channel on one
"tuner" and the voice channel it grants on another:
./target/release/trunk8 -s 'file:testdata/p25p1-cqpsk-cc.wav?center=851262500' \
-s 'file:testdata/p25p1-cqpsk-vc.wav?center=851387500'
Then add a system with control channel 851.2625 MHz; about 20 seconds into the recording a call to talkgroup 20182 is granted on 851.3875 MHz and followed onto the second source.
Hardware notes
- HackRF One: 2–20 MS/s, 8-bit. It has a DC spike at the center, so keep signals of interest off the exact center frequency.
- PlutoSDR: about 4 MS/s is gap-free over USB. A stock unit tunes 325 MHz–3.8 GHz; VHF needs the AD9364 firmware setting (70 MHz–6 GHz).
Develop
cargo run -- -s synthetic # backend on :8088
(cd web && npm run dev) # UI with hot reload on :5173, proxied to the backend
cargo test && cargo clippy --all-targets
(cd web && npm run check)
| Path | What it is |
|---|---|
crates/t8-hw |
Source trait; seify (HackRF, Pluto, RTL-SDR, Soapy), file replay and synthetic sources; tuner thread with sample fan-out |
crates/t8-dsp |
Protocol-agnostic DSP: polyphase channelizer, resampler, filters, FM/AM demodulators, squelch, spectrum |
crates/t8-core |
Engine: places channels on tuners, tuner scheduler, conventional channel pipelines, P25 systems (control channel + traffic workers), call events and audio |
crates/t8-p25 |
P25 Phase 1: C4FM/CQPSK demodulator, framing, NID BCH, trellis, TSBK and LDU/link control decoding |
crates/t8-vocoder |
IMBE decoding (opt-in, see above) |
crates/trunk8 |
The trunk8 binary: axum REST + WebSocket API, Opus encoding, SQLite store, call recorder, embedded UI |
web/ |
SvelteKit UI |