"# sdr-cuda"
A real-time radio signal detector and decoder running on Windows with an RTL-SDR dongle and NVIDIA GPU. Detects and decodes aircraft (ADS-B), ships (AIS), and astrophysical signals (solar bursts, Jupiter emissions, hydrogen line), with a live OpenStreetMap display and spectrum waterfall.
The program tunes a cheap RTL-SDR USB dongle (~$30) to a radio frequency and streams raw IQ samples to the GPU at 2.4 million samples per second. A 1-million point FFT runs on the GPU each frame, producing a high-resolution frequency spectrum. The spectrum is scanned for peaks, and domain-specific decoders determine whether a signal is an aircraft transponder, a ship transponder, a Doppler-shifted satellite, or a cosmic event. Results are displayed in a live ImGui window showing a spectrum plot, a scrolling waterfall, an OpenStreetMap overlay with entity markers, and a timestamped event log.
Every 100 frames the main loop pauses and runs a frequency sweep across several bands (ADS-B, AIS, NOAA satellite, hydrogen line), checking each for activity before returning to the main frequency.
- RTL-SDR V3 dongle (RTL2832U / R820T2)
- NVIDIA GPU (built for RTX 4090, sm_89 — change
CMAKE_CUDA_ARCHITECTURESfor other cards)
- Windows 10/11
- CUDA Toolkit 12.x or 13.x
- Visual Studio 2022 Build Tools (Desktop C++ workload)
- CMake 3.23+
- Zadig (one-time USB driver replacement for the dongle — zadig.akeo.ie)
rtlsdr.dll pthreadVC2.dll msvcr100.dll glew32.dll cudart64_*.dll
cd path\to\project
rmdir /s /q build
cmake -B build -S . -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DRTLSDR_ROOT="%CD%\rtl-sdr" -DGLEW_ROOT="%CD%\glew" -DCMAKE_CUDA_COMPILER="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v13.1/bin/nvcc.exe" -DCMAKE_CUDA_HOST_COMPILER="C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Tools/MSVC/14.44.35207/bin/Hostx64/x64/cl.exe"
cmake --build buildAdjust the MSVC version number in the host compiler path to match what is in your BuildTools\VC\Tools\MSVC\ folder.
Plug in the dongle, then:
copy rtl-sdr\rtlsdr.dll build\
copy rtl-sdr\pthreadVC2.dll build\
copy rtl-sdr\msvcr100.dll build\
copy glew\bin\Release\x64\glew32.dll build\
build\sdr_cuda_detector.exe [center_frequency_hz]Default frequency is 137.1 MHz (NOAA APT satellite downlink). Example for ADS-B:
build\sdr_cuda_detector.exe 1090000000Main entry point and processing loop. Opens the RTL-SDR device, allocates GPU buffers, and runs the main frame loop. Each frame: reads raw IQ samples, uploads to GPU, converts to complex float, runs a Welch-averaged FFT, finds peaks, and runs all detectors. Also handles retuning when the user presses arrow keys in the UI, and triggers the frequency sweep every 100 frames.
Multi-band frequency scanner. Defines SWEEP_PLAN — the list of bands to visit (ADS-B at 1090 MHz, AIS at 162 MHz, NOAA at 137.1 MHz, hydrogen line at 1420 MHz). For each entry it retunes the dongle, waits for the PLL to settle, reads samples, runs a GPU FFT, computes SNR against the median noise floor, and posts an event if a signal is detected. Mirrors the run_sweep() function in the Python script.
ADS-B / Mode-S decoder for aircraft at 1090 MHz. A CUDA kernel scans every sample in parallel for the Mode-S preamble pattern. Candidates are Manchester-decoded and CRC24-checked on the CPU. Valid DF17 Extended Squitter messages are parsed for aircraft callsign, altitude, velocity, and CPR position. Decoded aircraft are posted to the map as triangle markers labelled with their callsign.
AIS decoder for ships at 162 MHz. Runs an FM discriminator (phase difference demodulation) on the IQ samples, extracts bits with clock recovery, NRZI-decodes them, and extracts HDLC frames. Valid frames (CRC-16 checked) are parsed for MMSI, position, speed, and heading. Decoded vessels are posted to the map as diamond markers.
OpenStreetMap tile renderer and entity overlay. Downloads PNG tiles over HTTP (WinInet) on background threads, caches them to disk, and uploads them as OpenGL textures. Renders the tile grid and entity markers (aircraft, ships, anomalies, receiver) using the ImGui draw list. Supports mouse drag to pan and scroll wheel to zoom.
ImGui + OpenGL visualisation. Creates a Win32 window, initialises GLEW and OpenGL, and renders three panels each frame: a live spectrum line plot, a scrolling waterfall heatmap (written directly into a CUDA/GL interop texture by a GPU kernel — no CPU copy), and a bottom row with the map on the left and a timestamped detection event log on the right. Also handles keyboard input for manual retuning.
Python prototype of the same pipeline using pyrtlsdr, PyCUDA, scikit-cuda, and matplotlib. Slower than the CUDA version but adds Skyfield orbital prediction — it tracks NOAA satellite passes and only attempts decoding when a satellite is above the horizon. Useful for experimenting with detection parameters without recompiling.
All thresholds are linear power ratios (peak / noise floor):
| Signal | Threshold | Notes |
|---|---|---|
| General peaks | 6× | Doppler, anomaly markers |
| Solar burst | 10× | Wideband, any frequency |
| Jupiter emission | 6× | 10–40 MHz only |
| Hydrogen line | 3× | 1420 ±1 MHz, ±5 bin window |
| Sweep bands | 6× (3× H-line) | Per SWEEP_PLAN entry |
- The RTL-SDR dongle must have its Windows driver replaced with WinUSB using Zadig before first use.
- Below 24 MHz the dongle switches to direct sampling mode (Q-branch) automatically.
- The hydrogen line at 1420 MHz is at the edge of RTL-SDR sensitivity — a dedicated LNA and dish are needed for reliable detection.
- Map tiles are cached in
tile_cache\next to the exe and reused on subsequent runs. Delete this folder to force a fresh download. - CUDA architecture is set to sm_89 (RTX 4090). Change
CMAKE_CUDA_ARCHITECTURESin CMakeLists.txt for other GPUs (e.g. 86 for RTX 3090, 75 for RTX 2080).