3DS-SDR turns a New Nintendo 3DS into a handheld analog SDR scanner and spectrum display using an RTL-SDR receiver connected over the network with rtl_tcp.
The RTL-SDR is the RF front end. The 3DS handles the scanner logic, FM demodulation/DSP, audio, squelch, memories, spectrum scope, waterfall, controls, and UI locally.
Current public beta: v0.1.0-beta
Based on internal development build v21.13d.
Scanner hotfix: the current source tree contains the hardware-tested scanner synchronization fixes. NFM scanning is deliberately conservative and may be slower than a dedicated scanner, prioritizing correct frequency association and reliable holds.
Menu update: the current source also includes the dev11-based hierarchical firmware menu with Memories, Banks, Scan Settings, VFO, Display, and System pages.
This entire project was vibe-coded with ChatGPT.
3DS-SDR is experimental software and should be used at your own risk. Bugs and incomplete edge cases are still present, and some features may not yet be fully mature or thoroughly validated. Because development has been highly iterative and AI-assisted, behavior can change quickly between builds and regressions are possible even when a feature appears to be working.
I am publishing the source openly so others can inspect it, test it, point out mistakes, improve the DSP, and contribute fixes.
RTL-SDR
|
v
rtl_tcp host (OpenWrt / Linux / PC)
|
| 240 ksps unsigned 8-bit I/Q over TCP
v
Wi-Fi / LAN
|
v
New Nintendo 3DS
|- scanner / VFO
|- NFM + WBFM demodulation
|- audio DSP
|- squelch
|- spectrum scope + waterfall
|- memory banks
`- dual-screen UI + controls
The default rtl_tcp port is 1234. On startup the 3DS presents a server-IP editor and does not connect until you confirm the address. The last confirmed server IP is remembered.
- Conventional analog scanner with banks and channel memories
- Hierarchical firmware-style menu for Memories, Banks, Scan Settings, VFO, Display, and System
- VFO mode
- NFM voice receive
- WBFM broadcast receive
- 256-bin spectrum scope
- Full-screen rolling waterfall using the same FFT/smoothing data as the scope
- Persistent RADIO / SCOPE / WATERFALL view selection; idle scanning keeps radio status visible and the selected visualization appears on RECEIVE or HOLD
- Squelch with global and per-channel settings
- DELAY, CARRIER, and TIME scanner resume modes
- Explicit SCAN / HOLD / HOLD RX operating states
- Temporary channel avoid and monitor controls
- Channel/bank editing and persistent configuration
- Duplicate-memory cleanup
- Master PLAY/STOP that pauses DSP/scanning while keeping
rtl_tcpdrained live - Startup
rtl_tcpserver selection with remembered IPv4 address - Battery indicator
- IQ/audio FIFO, application LOAD, and allocator-memory diagnostics
- Automatic
rtl_tcpreconnect/recovery
- New Nintendo 3DS / New Nintendo 3DS XL / New Nintendo 2DS XL
- Homebrew-capable system capable of launching
.3dsxapplications
- RTL-SDR compatible with
rtl_tcp - A host that can run
rtl_tcp(for example OpenWrt, Linux, or a PC) - The 3DS and
rtl_tcpserver must be mutually reachable over IP
This project was developed with an RTL-SDR attached to an Archer C7 running OpenWrt, but the 3DS client only depends on the standard rtl_tcp protocol.
A typical server command is:
rtl_tcp -a 0.0.0.0 -p 1234The 3DS sends the sample-rate, frequency, and tuner commands after connecting.
Security note: rtl_tcp does not provide authentication or encryption. Run it only on a trusted LAN or behind an appropriate private network/VPN; do not expose it directly to the public Internet.
The current source tree includes the tested scanner-hotfix changes plus the newer dev11-based hierarchical menu described in the changelog.
Binary note: until the release binary is refreshed, the prebuilt below is the previous user-compiled scanner-hotfix build and may not yet contain the new menu.
A user-compiled, hardware-tested scanner-hotfix binary is included here:
SHA-256:
db3148f1166a4c0c3d9c4426096b06653eafa5fde4eea9120a0cd7640399b130
The scanner-hotfix source intentionally uses a conservative 250 ms NFM retune quarantine, so scanning is slower but avoids assigning delayed IQ from the previous frequency to the newly displayed memory.
Copy 3ds-sdr.3dsx to your SD card, for example:
sdmc:/3ds/3ds-sdr/3ds-sdr.3dsx
You can also build the current source yourself with devkitPro/devkitARM and libctru.
With a working devkitPro 3DS environment:
make clean
makeSuccessful compilation creates:
3ds-sdr.3dsx
3ds-sdr.elf
The application stores its runtime configuration in:
sdmc:/3ds/3ds-sdr/scanner-v21.cfg
sdmc:/3ds/3ds-sdr/server.cfg
server.cfg stores only the last confirmed rtl_tcp server address. Scanner configuration remains separate for compatibility with existing installations.
- Start
rtl_tcpon the SDR host. - Launch 3DS-SDR.
- The remembered server IP is preloaded (first-run fallback:
10.0.0.15). - Adjust the IPv4 address with the D-pad if necessary.
- Press A to connect.
No rtl_tcp connection is initiated until the server address is confirmed.
| Control | Action |
|---|---|
| A | SCAN / HOLD |
| B | Master PLAY / STOP |
| X | Normal → Scope → Waterfall → Normal |
| Y | Menu |
| D-pad Up/Down | Previous / next bank |
| D-pad Left/Right | Previous / next channel |
| R | Temporary avoid |
| L (hold) | Temporary monitor |
| ZL / ZR | Squelch down / up |
| SELECT | Unbound (available for system screenshot hotkeys) |
| START | Exit |
Press Y to open the hierarchical menu. Use Up/Down to select, A to open/activate, B to go back, and Y to close. The Memories browser also uses Left/Right to change banks, X to listen/hold on the selected memory, and R for temporary avoid. Diagnostics are under System.
D-pad Left/Right tunes by the selected step. D-pad Up/Down changes the step size.
The current NFM path uses:
240 ksps complex IQ
-> 63-tap complex channel LPF
-> 5:1 decimation to 48 ksps
-> phase-difference FM discriminator
-> 2nd-order ~300 Hz voice HPF
-> 75 us de-emphasis
-> ~4.2 kHz voice LPF
-> ~+4.1 dB makeup gain
-> soft limiter
-> 48 kHz audio
NFM is usable and intelligible but remains an area of active tuning. Reports comparing the same transmission against a conventional receiver are welcome.
The scope and waterfall share the same 256-point FFT and smoothed magnitude data. Switching display modes does not change receiver bandwidth or create a second DSP path.
The scanner supports enabled/disabled banks, enabled/disabled channels, temporary avoids, per-channel mode, and optional per-channel squelch overrides. Scan eligibility requires:
bank enabled
AND channel enabled
AND not temporarily avoided
Duplicate cleanup compares frequency + mode, preserves the first memory, removes later duplicates, compacts the bank, clamps affected indices, and saves the configuration.
- Receive-only. The 3DS does not transmit RF.
- Analog NFM/WBFM only; no digital voice decoding or trunk tracking.
rtl_tcpis required; the RTL-SDR is not connected directly to the 3DS.- NFM audio is still being refined and may not yet match a dedicated handheld receiver in clarity.
- Battery level exposed by the 3DS API is coarse rather than a precise percentage.
- This is an independent homebrew project and is not affiliated with Nintendo, Realtek, or the
rtl-sdrproject.
3DS-SDR is a receive-only general-purpose radio tool. Radio-monitoring laws and restrictions vary by jurisdiction and by service. You are responsible for using the software and connected receiver lawfully. Do not rely on this project for safety-critical or emergency communications.
Bug reports, RF/DSP measurements, reproducible audio comparisons, UI feedback, and small focused patches are welcome. See CONTRIBUTING.md.
When reporting an RF/audio issue, it is especially useful to include:
- mode (NFM/WBFM)
- frequency/service type
- approximate signal level shown by 3DS-SDR
- whether a conventional receiver heard the same transmission cleanly
- steps to reproduce
- build/version
3DS-SDR is released under the MIT License.
The project uses devkitPro/libctru when built; those projects retain their own licenses and are not bundled in this source repository.
See CHANGELOG.md.




0 comments
log in to comment.