ESPARGOS / esp-sdr
git clone https://github.com/ESPARGOS/esp-sdr.git
ESP-SDR uses the undocumented raw I/Q capture functionality of ESP32 family chips to turn them into (low-duty-cycle) Software Defined Radios
+9
stars, 24h · #1,544
+~63
stars, 7 days · #1,966
+1.1k
stars, 30 days · #509
1.1k
★ total · +6% this week
150
forks · 6 open issues
Star history (as recorded here)
LanguageC
LicenseGPL-3.0
Created2026-09-28 (24d ago)
Last push5d ago
Watchers21
OwnerOrganization
GitHub topics
Links
- GitHub: github.com/ESPARGOS/esp-sdr
- Homepage: https://espargos.net/espsdr/
- Releases · Issues · Hacker News mentions
README excerpt
# ESP-SDR firmware ### Try it yourself: Project overview · Browser SDR viewer · Browser firmware installer ESP-SDR turns the Wi-Fi/Bluetooth radio of an ordinary ESP32 board into a receive-only software-defined radio. The firmware captures raw I/Q samples from the chip's own receiver and sends them to your computer over USB or UART. No extra SDR hardware is needed. The ESP32's receiver normally feeds its samples straight into the fixed-function Wi-Fi modem. With the help of LLMs, we found an undocumented debug path that lets the CPU read those samples instead. How it works explains the mechanism register by register. Parts of the firmware are AI-generated: we understand the capture mechanism well on the ESP32-C61 used in our ESPARGOS One array, but porting it to the whole ESP32 family by hand would have been too much work. ## Quick start 1. Flash the firmware from the browser installer. 2. Open the browser viewer and connect. For continuous streaming into Gqrx, GNU Radio and friends, use an ESP32-S31 with SoapyESPSDR, or an ESP32-S3 with esp-sdr-bridge. ## Supported chips | Chip | Status | Native USB | UART0 TX / RX | Sample rates (MS/s) | Notes | | --- | --- | --- | --- | --- | --- | | ESP32 | ✅ | — | GPIO1 / GPIO3 | 80, 40, 16 | | | ESP32-C2 | ✅ | — | GPIO20 / GPIO19 | 80, 40, 16 | 26 MHz crystal; rebuild for 40 MHz | | ESP32-C3 | ✅ | Serial/JTAG | GPIO21 / GPIO20 | 80, 40, 16 | | | ESP32-C5 | ✅ | Serial/JTAG | GPIO11 / GPIO12 | 80 … 4 | also receives 5 GHz | | ESP32-C6 | ✅ | Serial/JTAG | GPIO16 / GPIO17 | 80, 40, 16 | continuous capture¹ (256 bins) | | ESP32-C61 | ✅ | Serial/JTAG | GPIO11 / GPIO10 | 80 … 4 | continuous capture¹ (256 bins) | | ESP32-H2 | ✅ | Serial/JTAG | GPIO24 / GPIO23 | 32, 16, 10.667, 6.4 | Bluetooth radio, see esp32h2.md | | ESP32-H21 | 🚧 | | | | | | ESP32-H4 | 🚧 | | | | | | ESP32-P4 | ❌ | | | | no radio | | ESP32-S2 | ✅ | USB-OTG CDC | GPIO43 / GPIO44 | 80, 40, 16 | 4 MB flash | | ESP32-S3 | ✅ | Serial/JTAG | GPIO43 / GPIO44 | 80, 40, 16 | continuous capture¹ and I/Q over USB | | ESP32-S31 | ✅ | Serial/JTAG | GPIO58 / GPIO59 | 80 … 4 | continuous capture¹; streaming firmware | ✅ supported · 🚧 not yet supported · ❌ not possible ¹ **Continuous capture** means the chip records the signal without gaps while it computes spectra, over native USB only. It can't FFT all of it: only a small share of the signal, often a few percent or less, goes into a spectrum. The viewer shows that share as FFT coverage. This mode exists at 256 FFT bins on the C6 and C61, and at all sizes on the S3 and S31. All other spectra, including every spectrum over UART, come from separate snapshots with gaps in between; the viewer then says "Reception has gaps between snapshots". All chips accept tuning from 100 to 6000 MHz, but the PLL only locks in a limited range around 2.4 GHz (and 5 GHz on the C5). ESP32, C2, C3, S2 and S3 reach down to about 1.85 GHz using a 5/6 LO divider, the C6 to about 1.95 GHz; see rx-controls.md. Snapshots are bursts of up to