


ESP32-S3 board as a 13 cm transceiver: rtl_tcp receiver for SDR++ and FM/SSB voice transmitter
An update to my earlier post about receiving 2.4 GHz with an ESP32-S3: it **transmits** now, too, and the whole thing is a proper release.
**Receive.**
`espdr-rx` turns the board into an rtl_tcp server (1.84 to 2.79 GHz, 250 or 333 ksps, no FPGA); SDR++ and GNU Radio use it as an RTL-SDR.
**Transmit.**
`espdr-tx` sends narrowband FM or SSB voice in 2320 to 2450 MHz from a WAV file, a pipe or a sound card. The chip has no I/Q input, so the trick is polar modulation: the Wi-Fi PHY's test-tone carrier is steered in frequency (the RF PLL's sigma-delta word, 40 000 updates per second) and in amplitude (a gain code,
0.28 dB steps over 18 dB), computed on the PC from the analytic signal of the audio. Screenshot: SDR++ with a HackRF on a second computer receiving the SSB
voice from the ESP32-S3 (that is the
*only*
transmitter).
Measured with a PlutoSDR: with the SSB carrier fully suppressed the unwanted sideband is 61 to 63 dB and the third-order intermodulation 33 dB below the wanted tones. Speech is understood
in FM and SSB, from a file and live from a microphone, for 20 to 30 s at a time without an underrun.
**Honest limits:**
one board, one host (Linux), tested with a PlutoSDR and a HackRF. The power is not calibrated (an estimate: microwatts at the antenna of a dev board), harmonics and
spurious emissions are not measured, the frequency is as good as the board's crystal (mine is +5.4 ppm off; `--ppm` corrects it). It sends only in the 13 cm band and needs an amateur
licence, which the tool asks you to confirm. Much of the code and the documentation was written with Claude as the coding assistant; every number in the docs was measured.
It stands on eSpDR by **h0m3us3r**, who found how to read the chip's undocumented I/Q dump path (thank you!).
Repo and release (the wheel contains the firmware, `pipx install` is enough): https://github.com/jochenhammes/esp32-sdr-trx - https://github.com/jochenhammes/esp32-sdr-trx/releases/tag/v1.0.0-rc2.
How it works and all measurements: `docs/internals.md` and `docs/research/TX-RESEARCH.md`. Reports from other boards are very welcome.