README.md
August 28, 2026 · View on GitHub
A handheld SDR scanner running on the ESP32-P4 with an RTL-SDR Blog V3 or V4 plugged into its USB host port.
It's currently in a very early devlopment stage and will be broken up into a few different releases. Right now I will release a headless firmware and a GUI version. The GUI started on esp-brookesia but I've since swapped it for my own handheld-radio LCD shell. I will try my best to get these to be cross compatible with different boards and configurations, so please submit an issue if you have trouble.
Designed to work with my other project CartoTUI - a terminal ascii map.
<°)))><
- P25 | Project 25 Phase 1 (C4FM) trunked/conventional digital voice. On-device IMBE voice decode using OP25's fixed-point vocoder; live NAC / TG / SRC, BCH health, and display.
- FM Monitor | wideband broadcast FM, narrowband FM voice (LISTEN), band
SCAN, and POCSAG pager decode | sharing one integer
rtl_fm-style front end. - ADS-B | 1090 MHz aircraft tracking.
- LoRa Mesh | on-board SX1262 + LoRaMesher gateway with a live node/link view, VERY WIP.
><> Downloads
| Board | Flash | Build | Firmware | Flipper App |
|---|---|---|---|---|
| ESP32-P4-NANO | 16MB | Headless (P25 / ADS-B / FM / POCSAG), serial console + host control panel | v0.1.1 | n/a |
| ESP32-P4-NANO Flipper Build | 16MB | Flipper controlled via BT/UART (P25 / ADS-B / FM / POCSAG) | v0.4.0 | v2.1 |
| ESP32-P4-WIFI6-Touch-LCD-4B (Smart 86 Box) | 32MB | GUI, touch LCD (P25 / ADS-B / FM / scanner) | v0.2.0 | n/a |
| ESP32-P4-WIFI6 | 32MB | Headless P25, serial console/host control panel *and SubGHZ recording soon. | v0.3.0 | n/a |
| ESP32-P4-WIFI6-Touch-LCD-4.3 | 32MB | Delayed due to hardware issues* | n/a | n/a |
| LilyGo T-Display P4 | 16MB | Coming Soon! | n/a | n/a |
Notes: Waveshare LCD 4.3 is a very misleading build. The schematics seem to point towards the ultimate configuration, however I must not be great at understanding them. The way power is routed is awful. If you power the board via the provided battery port, 5V is routed away from everything. This includes ALL GPIO, and the USB 2.0 HS port/UART. This seems to be the case for many of the LCD lines from Waveshare (86 Box was the same), but with that board you are able to remove/bridge a MOSFET to route the 5V out permanently through USB 2.0 HS. This then lets you power the 86 Box via GPIO with a boost convertor. (assets folder holds detailed screenshots of this method).
This is not the case with the LCD 4.3 variant. Removing the same MOSFET does let you provide 5V out through USB HS 2.0, however, due to the insane design of the rest of the power path, powering via GPIO does NOT route 5V there. I have no idea why it's this complicated and unfortunately didn't check if 5V worked prior to the MOSFET removal/GPIO powering, but I am betting it wont. This basically leaves you with powering via the UART USB-C port and a power bank, which sucks. I have the furthest build with this board, full support with remote subghz recording and storage. Plus tons of new features. I will release it, but will no longer support it going forward as I will be moving on to the Lilygo T-Display P4. - 8/28/2026
All builds are on the releases page.
}<((((()°> Hardware notes
You need one of the boards listed above and the accompanying firmware. Other ESP32-P4 boards probably work but I haven't tried them and will continue to add to the roster. RTL-SDR V3/V4 are the target dongles; older V3 sticks work but you'd lose the triplexer routing (Not crazy important in my tests). In my opinion, I wouldn't try sourcing the V4's as they're a dead end in terms of support.
Pin mapping for the audio: I²S MCLK=13 BCK=12 WS=10 DOUT=9 DIN=11, codec PA enable on GPIO 53, I²C SDA=7 SCL=8, USB VBUS enable on 46 for nano board. Smart 86 Box requires soldering. Will type out a tutorial soon. Not a hard thing to do at all though.
- Optional SX1262 LoRa module for the mesh app WIP.
><)))O> Build & flash
Requires ESP-IDF v5.4.3 (configured with Python 3.12). From the project dir:
idf.py set-target esp32p4
idf.py build
idf.py -p /dev/ttyACM0 flash monitor
A convenience wrapper (idf12.sh / idf12.ps1) that sources the IDF environment
is included one level up in the original tree; plain idf.py works the same.
The
managed_components/tree is committed because the Waveshare BSP is patched in-place. After switching host OS, runidf.py fullcleanonce (thebuild/cache stores absolute paths).
Architecture & specs
- SoC/board | ESP32-P4 (dual-core RISC-V) on the Waveshare ESP32-P4-NANO or Smart 86 Box. 16 MB flash, PSRAM at 200 MHz, 720x720 MIPI-DSI capacitive touch LCD.
- Sample rates | RTL-SDR over USB host runs at 240 kSPS for P25, 256 kSPS for FM/POCSAG, and 2 MSPS for ADS-B. Audio out is 16 kHz mono.
- Integer DSP | the FM front end is a fixed-point
rtl_fm-derived pipeline and P25 voice uses OP25's integerimbe_vocoder. Demod runs real-time with no IQ drops, and one P25 LDU decodes well under real-time. - USB streaming | self-resubmitting USB transfers fill a PSRAM IQ ring.
- Audio | 16 kHz output ring with a prebuffer sized above one decode burst.
- LCD shell | a custom LVGL UI.
3D Print Sneak Peaks
Credits & licenses
This project is released under the GNU GPL v3 (see LICENSE), as required by
its GPL dependencies. It bundles and builds on:
- rtl-sdr / librtlsdr | Osmocom (GPL-2.0+)
- xtrsdr - For the amazing work with getting it lean enough for the ESP32.
- OP25
imbe_vocoder| Pavel Yazev (GPL-3.0+) - mbelib | ISC (kept as a fallback decoder)
- DSD / dsd-fme | P25 framing (GPL)
- LoRaMesher | mesh networking
- esp-brookesia | UI launcher
- Espressif ESP-IDF and the Waveshare ESP32-P4 BSP
Original copyright/license headers in third-party sources are preserved verbatim.
Legal note: the IMBE/AMBE voice codecs are covered by patents held by DVSI. This firmware is provided for educational and experimental use; you are responsible for compliance with applicable laws and licenses in your region.