Tagged: rtl2832u

RTLSDR-NEXT: A Ground-Up Rust Rewrite of the RTL-SDR Driver

Thank you to Matthew Delashaw, who has written in and shared a guest post with us. Matthew has rewritten the 2013 librtlsdr library from the ground up in Rust. His motivations for doing so and the results are explained in the post below:


I actually started down this path as an "interest". There was a Ham radio Technical Interest Group I was planning on attending a meeting. I had already wanted to convert my Raspberry Pi into a fallback radio receiver for potential internet outages and listening to storm chasers on SKYWARN. Now I have the "v4" dongle, and a full end-to-end SDR solution. !Spoilers, I'm releasing a native smart phone client soon.

The RTL2832U chipset has powered affordable software-defined radio for over a decade. The reference driver, librtlsdr, was written in C around 2013 and follows the same architectural pattern it always has: a blocking callback loop, manual buffer management, and a programming model that predates modern async runtimes by years.

rtlsdr-next is a ground-up Rust rewrite. It exposes SDR data as a native Tokio Stream, ships a zero-allocation DSP pipeline, and has first-class support for the RTL-SDR Blog V4 — a newer hardware variant the upstream driver handles correctly but never cleanly abstracted. The result is faster, safer, and substantially easier to build applications on top of.

1.49 GiB/s IQ conversion on Pi 5  ·  ~45ms frequency switching (was ~270ms with 20 I2C toggles)  ·  0 allocations in the streaming hot path


Why rewrite it at all?

The C driver works. Millions of people run it daily via OpenWebRX, GQRX, SDR++, and friends. But its architecture creates friction at every layer: the callback-based stream makes backpressure impossible to reason about, the I2C bus is hammered with redundant open/close cycles, and the conversion routine uses a 256-entry lookup table whose cache pressure eats into throughput on modern out-of-order cores.

More practically: trying to integrate librtlsdr into a modern async Rust application means spawning a dedicated thread, wrapping callbacks in channels, and handling all the lifetime gymnastics manually. For every project that does this, someone reinvents the same boilerplate. There are plenty of Rust "wrappers" out there That exemplifies this.


The stream architecture

The primary interface is a standard async stream. A SampleStream wraps a background USB reader thread that feeds raw IQ bytes into a tokio::mpsc channel. The F32Stream layer sits on top and handles conversion, decimation, DC removal, and AGC — all in a single pipeline with no intermediate heap allocations.

let mut stream = driver.stream_f32(8)   // ÷8 → 256 kSPS
    .with_dc_removal(0.01)
    .with_agc(1.0, 0.01, 0.01);

while let Some(Ok(iq)) = stream.next().await {
    // interleaved f32 I/Q, ready to demodulate
}

The blocking USB read thread never touches the async runtime. Sample delivery to async consumers happens entirely through the channel, and the PooledBuffer type ensures the backing buffers are returned to the pool via Drop — no explicit lifecycle management needed at the call site.

  • SampleStream — Blocking USB thread → tokio::mpsc channel. Pre-allocated buffer pool. Flush-on-tune via broadcast::Sender.
  • F32Stream — Convert → decimate (FIR) → DC remove → AGC. Processes split I/Q in-place. No per-block allocation.
  • PooledBuffer — Returns buffer to pool on Drop. try_send with blocking fallback thread — the pool never silently starves.
  • BoardOrchestratorV4Orchestrator / GenericOrchestrator produce a TuningPlan. Board logic never leaks into chip drivers.

The I2C repeater optimization

Every register write to the R828D tuner chip goes through an I2C bridge in the RTL2832U. The bridge must be explicitly opened and closed around each transaction. In a naive implementation — which is what the reference driver does — every call to set_frequency independently opens and closes the repeater for each register write.

A full frequency switch involves setting the PLL, MUX, filter coefficients, and various control registers. That adds up to roughly 20 open/close cycles, and each one costs ~13ms of USB round-trip time.

The fix: a single with_repeater(|| { ... }) closure that holds the bridge open for the entire mux + PLL sequence. One open, one close, all the work done in between.

// Before: ~20 repeater toggles ≈ 270ms
self.set_mux(hz)?;   // 10 writes, each with open/close
self.set_pll(hz)?;   // 10 writes, each with open/close

// After: 1 repeater toggle ≈ 45ms
self.with_repeater(|| {
    self.set_mux_raw(hz)?;
    self.set_pll_raw(hz)?;
    Ok(())
})?;

The distinction between write_reg_mask (opens and closes the repeater itself) and write_reg_mask_raw (no repeater toggle, must be inside a bracket) is enforced by convention throughout the codebase. Any raw variant called outside a bracket is a bug that surfaces immediately as a timeout rather than silently returning stale data.


Converter throughput

librtlsdr converts raw IQ bytes to float via a static 256-entry lookup table. It is a reasonable approach from an era when float math was expensive and cache was plentiful. On the Cortex-A76 inside the Pi 5, the situation is inverted: the NEON FPU is underutilized and random-access table reads create cache pressure that limits throughput.

The arithmetic equivalent — (x as f32 - 127.5) / 127.5 — is computed in two instructions per sample and is trivially auto-vectorized by LLVM. The compiler emits NEON FMLA instructions without any manual intrinsics.

Operation librtlsdr (C) rtlsdr-next (Rust)
Standard conversion (256KB) 172.32 µs · 1.42 GiB/s 164.35 µs · 1.49 GiB/s
V4 inverted conversion 256.07 µs · 976 MiB/s 170.81 µs · 1.43 GiB/s
FIR decimation ÷8 N/A 615 µs · 426 MSa/s

The V4 inversion case is a particularly notable optimization. librtlsdr implements it as a two-pass operation: first a full LUT conversion, then a second pass to negate every Q sample. The Rust implementation folds both into a single pass, processing I and Q pairs together and avoiding a complete re-read of the output buffer.


RTL-SDR Blog V4 specifics

The V4 is a substantial hardware revision. It ships with an R828D tuner (not R820T), adds an HF upconverter and a GPIO-switched triplexer, and has several initialization quirks that librtlsdr discovered through usbmon traces and EEPROM string detection.

The board logic is isolated entirely in V4Orchestrator. Given a target frequency, it returns a TuningPlan — the actual tuner frequency, whether spectral inversion is needed, which triplexer path to select, and whether the frequency falls inside a notch band. The R828D chip driver never touches a GPIO.

Notable quirks baked into the driver: the R828D responds at I2C address 0x74 rather than the R820T's 0x34; frequencies below 28.8 MHz are upconverted by adding the crystal frequency, and the resulting spectrum is inverted (Q = –Q). Every demodulator register write must be followed by a dummy read of page 0x0a register 0x01 — the hardware requires this as a flush sync, and omitting it causes subsequent control transfers to stall with a pipe error.


Built-in DSP pipeline

The dsp module ships a complete demodulation stack. The decimator uses a windowed-sinc FIR with NEON acceleration on aarch64, with a scalar fallback that LLVM auto-vectorizes on x86_64. The FM demodulator is a quadrature discriminator with configurable de-emphasis. AM uses a two-stage DC-subtraction envelope detector. SSB uses the phasing method with a 65-tap Hilbert transformer windowed with Blackman-Harris for high sideband rejection.

All demodulators maintain state across block boundaries — the history overlap buffer in the decimator ensures the FIR convolution is correct at every chunk edge, which is essential for continuous streaming.


Standalone servers

Two installable binaries ship alongside the library. rtl_tcp implements the standard RTL-TCP protocol and is compatible with OpenWebRX+, GQRX, and SDR++. websdr is a self-contained WebSocket SDR server with a full spectrum and waterfall UI embedded as a compiled-in HTML file — no separate web server needed. Both support TLS. The WebSDR binary accepts --cert and --key flags for wss:// connections, which are required by iOS App Transport Security when using a public domain.

  • OpenWebRX+ — confirmed working
  • GQRX — confirmed working
  • SDR++ — confirmed working
  • Corona SDR (iOS) — confirmed working

Getting started

cargo install rtlsdr-next

# Smoke test — run this first
RUST_LOG=info cargo run --release --example hw_probe

# Start an rtl_tcp server
rtl_tcp --address 0.0.0.0 --port 1234

# Start the WebSDR UI
websdr --address 0.0.0.0 --port 8080

On Linux, set up a udev rule for persistent USB access without sudo. On Windows, Zadig is required to swap the DVB-T driver to WinUSB — build works without it, but the USB runtime requires it at runtime.


Source on GitHub at github.com/mattdelashaw/rtlsdr-next. Licensed Apache 2.0. Benchmarks measured on Raspberry Pi 5 (aarch64) and AMD Ryzen 7600X (x86_64) with cargo build --release, no target-cpu=native.

Keep and eye out for the smart phone app release here: Spectral Bands

rtlsdr-next running with GQRX
rtlsdr-next running with GQRX

Adding ACARS Decoding to an ADS-B Flight Tracker

Over on his blog, cynicalGSD has written a detailed post about how he extended his home ADS-B flight tracking setup to also decode ACARS. His existing system runs an RTL-SDR dongle on a Raspberry Pi feeding a database and Flask web app. Adding ACARS required a second RTL-SDR and a separate VHF dipole antenna tuned for 129–131 MHz.

ACARS (Aircraft Communications Addressing and Reporting System) is a text-based datalink that has been in use since 1978, carrying short messages between aircraft and ground stations. It includes messages such as OOOI events (Out of gate, Off ground, On ground, Into gate), pilot weather reports, maintenance fault codes, and gate and fuel data. The key feature of their implementation is cross-referencing ACARS messages with existing ADS-B records via aircraft registration and ICAO hex address, enriching flight records with precise departure and arrival timestamps from the airline's own reporting system.

The full write-up covers the database schema, Python integration using acarsdec, gain tuning tips, and the Flask web interface. cynicalGSD mentions that the code is available for anyone interested, but we didn't see a link, so please comment on his post if you are interested.

Technical Summary of cynicalGSD's ACARS + ADS-B implementation.
Technical Summary of cynicalGSD's ACARS + ADS-B implementation.

GridDown: An Offline-First Situational Awareness Platform with RTL-SDR, SARSAT, Meshtastic

Thank you to Cameron from BlackAtlas LLC for submitting their project GridDown, which is an open source Android tablet-based situational awareness system designed to operate without an internet connection. At its core, it appears to be a tablet with custom software, and then you can add sensors such as an RTL-SDR for ADS-B+Remote ID, a SARSAT receiver, and a Meshtastic ESP32-S3+SX1262 device. A demonstration of the UI can be found at https://griddown.blackatlas.tech.

Cameron writes:

[GridDown is] an offline-first situational awareness platform built for emergency preparedness, field response, and tactical operations in infrastructure-degraded environments — designed to work when cell towers are down, internet is unavailable, and operators are fully off-grid.

The platform is a Progressive Web App (~120,000 lines of vanilla JavaScript, no frameworks) that runs on Samsung Galaxy tablets, laptops/PCs, and works completely offline after initial setup. It's built by BlackAtlas LLC and is available for trial at https://griddown.blackatlas.tech.

The system has many facets to it, including:

  • Encrypted voice and text messaging via an ESP32-S3 with SX1262 LoRa transceiver
  • Passive RF sensing with the ESP32-S3 and SX1262.
  • Three passive drone detection methods: WiFi fingerprinting, FAA Remote ID reception, and 900 MHz control/telemetry link detection
  • Automatic gunshot detection via a ES7210 quad-channel I2S microphone on the ESP32-S3.
  • Automatic RF jamming detection
  • SARSAT beacon receiver
  • SSTV Encode/Decode
  • Meshtastic integration
  • APRS via Bluetooth TNC
  • ADS-B reception
  • RadioCode gamma spectrometer integration
  • Offline maps

ADS-B detection is handled by a Raspberry Pi 5 running an RTL-SDR Blog V4 dongle. Cameron writes:

The Pi connects to the tablet's built-in WiFi hotspot (no internet required — the hotspot functions as a local network only), and a Node.js bridge reads aircraft data from readsb and subscribes to the Remote ID receiver's MQTT output, then serves a unified WebSocket and REST API to the tablet. GridDown renders aircraft and drone tracks as heading-rotated silhouette icons on its offline map with altitude labels, age-based alpha fade, and emergency squawk alerting (7500/7600/7700). A 10,000 mAh USB-C PD battery provides approximately 5 hours of field runtime for the Pi.

The full setup script, hub bridge, and hotspot connection scripts ship with the project.

The software is dual-licensed, with it being open source GPL v3 (note that the GitHub link appears to be broken - we have asked for clarification) for non-commercial use, or a commercial licence for hardware bundles and business deployments. 

Alternatively, BlackAtlas LLC is selling ready-to-use kits, with the core tablet coming in at $799. Other bundles include the Tablet + SARSAT receiver for $1,299, the Tablet + Meshtastic bundle for $1,299, and the Tablet + ADS-B/Remote ID bundle for $1,999.

The GridDown Web Interface
The GridDown Web Interface

Ground Station: An Open Source SDR Orchestration Platform for Satellite Tracking and Decoding

Over on GitHub, we've seen the release of a new program simply called "Ground Station", described as a full-featured, open-source software solution for satellite tracking and radio communication.

The software presents as a web-based UI that allows users to manage satellite passes, view SDR waterfall data, decode basic signals such as GMSK telemetry, view telemetry packets, synchronize TLEs, manage multiple SDR devices, browse downloaded weather imagery, monitor DSP performance, and interface with antenna rotators.

Unlike tools such as SatDump, which focus primarily on signal processing and decoding, Ground Station acts as a higher-level orchestration platform. It automates the full workflow, handling pass prediction, SDR control, recording, and decoding, and integrates with SatDump for more complex protocols like weather satellite image decoding.

While SatDump does include some tracking and automation features, Ground Station takes this further with support for multiple SDRs, coordination across multiple stations, and a centralized management interface. It also includes an interesting AI-based speech-to-text feature for transcribing amateur satellite voice communications.

This could be a great tool to use alongside our Discovery Dish and Discovery Drive antenna rotator!

Ground Station: The Overview Page
Ground Station: The Overview Page

Automatic Signal Recognition with AI Machine Learning and RTL-SDR

Thank you to Trevor Unland for submitting his AI machine learning project called "RTL-ML" which automatically recognizes and classifies eight different signal types on low-power ARM processors running an RTL-SDR.

Trevor's blog post explains the machine learning architecture in detail, the accuracy he obtained, and how to try it yourself. If you try it for yourself, you can either run the pre-trained model or train your own model if you have sufficient training data.

The code is entirely open source on GitHub, and the training set data has been shared on HuggingFace

RTL-ML is an open-source Python toolkit for automatic radio signal classification using machine learning. It runs on ARM single-board computers like the Raspberry Pi 5 or Indiedroid Nova paired with an RTL-SDR Blog V4, achieving 87.5% accuracy across 8 real-world signal types including ADS-B aircraft transponders, NOAA weather satellites, ISM sensors, FM broadcast, NOAA weather radio, pagers, and APRS.

The project provides a complete pipeline from signal capture to trained classifier. Unlike academic approaches that rely on synthetic data or expensive GPU hardware, RTL-ML uses real signals captured from actual antennas and runs entirely on edge hardware with no cloud dependency. The Random Forest model is 186KB and processes signals in around 120ms on a Pi 5.

The GitHub repository includes the full capture and training scripts, a pre-trained model, 8 validated spectrograms, and documentation for adding new signal types. It works out of the box on both Raspberry Pi 5 and Indiedroid Nova with identical code and accuracy.

RTL-ML Setup: RTL-SDR Blog V4, Dipole Antenna and Indiedroid Nova ARM Computer.
RTL-ML Setup: RTL-SDR Blog V4, Dipole Antenna and Indiedroid Nova ARM Computer.

You might also be interested in some similar projects we've posted about in the past, such as this Shazam-style signal classifier, which used audio data from sigidwiki.com, and an Android app doing the same thing (which unfortunately now appears to have been removed from Google Play). There is also this deep learning based signal classifier model.

Discovery Drive Campaign Now Live!

We're extremely pleased to announce that our campaign for our Discovery Drive automatic antenna rotator is now live on Crowd Supply! Pricing is reduced during the campaign period, so check it out soon!

Discovery Drive is an automatic antenna rotator designed for use with our Discovery Dish product, as well as similarly sized antennas such as Wi-Fi grid and Yagi antennas.

A motorized rotator, such as Discovery Drive, enables precise tracking of fast-moving polar orbiting satellites using a satellite dish or directional antenna. Examples of polar orbiting weather satellites include METEOR-M2, METOP, and FENGYUN. Depending on your location, you may also have access to other interesting satellites that dump data over specific regions.

In addition to public weather data, operators and enthusiasts might be interested in using Discovery Drive to track CubeSats, and amateur radio operators may wish to track amateur radio satellites.

Amateur radio astronomy hobbyists can map the galaxy in the hydrogen line spectrum using Stellarium, or custom software to aim a Discovery Dish with H-Line feed, allowing you to scan multiple parts of the sky in one night.

Discovery Drive - A Motorized Antenna Rotator Engineered for Discovery Dish

JoesScanner: A Modern Frontend for Trunking Recorder to Listen, Browse, and Download Calls

Thank you to Joe for submitting news about the release of his project called "JoesScanner". JoesScanner is an app for Windows, Android, and iOS that provides a modern frontend for Trunking Recorder, for listening to, browsing, and downloading trunked radio calls.

A trunked radio call uses dynamically assigned frequencies from a shared pool, so tracking a conversation requires trunking software (e.g., Unitrunker, SDRTrunk, DSDPlus) and typically two RTL-SDRs, one for the control channel and one for the voice channel.

Trunking Recorder is a Windows application for recording/importing audio from trunked radio systems monitored by Unitrunker, SDRTrunk, ProScan, or DSDPlus. While Trunking Recorder already has a web-based browser front-end viewer, Joe was not happy with it and decided to build his own.

Joe writes:

Joe’s Scanner is a Windows, Android, and iOS app that connects to a Trunking Recorder (TR) backend and provides a modern front end for listening, browsing, and downloading calls.
The idea is to make TR based setups easier for end users, especially on mobile, while staying lightweight and ad free.

Key features:

- Connects to any Trunking Recorder server over HTTP or HTTPS, with or without username/password
- iOS background audio support
- History browsing with downloadable calls
- If the TR installation provides transcriptions, the app can enable address detection and what3words detection
- Free to use with no ads, and no data harvesting or resale

Background:

I built it because I run my own TR servers and was not happy with the existing client options, so I created what I wanted for my customers.

I am also making it available for anyone to use with their own TR servers for free.

Server owners can optionally apply to have their server listed in the in app directory to simplify setup for their users:
https://joesscanner.com/support/joes-scanner/joes-scanner-server-addition/

Microsoft Store: https://apps.microsoft.com/detail/9n5hbztcnt4t?hl=en-US&gl=US

Google Play: https://play.google.com/store/apps/details?id=app.joesscanner.com

Apple App Store: https://apps.apple.com/us/app/joes-scanner/id6758413482

Joe notes that the code is all open source and is available on GitHub.

JoesScanner - Mobile Interface
JoesScanner - Mobile Interface

CoronaSDR for iOS – A Free Native RTL_TCP Client

Thank you to Silviu YO6SAY for writing in and sharing with us news about the release of his iOS App called "CoronaSDR" which is a native client for receiving from rtl_tcp servers. rtl_tcp is a server program for RTL-SDRs that streams raw IQ data over a network connection.

Unlike Android, iOS does not allow third-party USB devices like the RTL-SDR to run on its devices. But you can set up an rtl_tcp server on a networked PC or Raspberry Pi in your home, and connect to the data stream with an iOS app like CoronaSDR.

Silviu writes:

CoronaSDR is a free, native iOS app that connects to an rtl_tcp server on your local network (no cloud, no subscription).

Current features
• Live spectrum + waterfall (Metal / GPU-accelerated)
• Demod modes: AM / NFM / WFM / USB / LSB / CW
• RF controls: gain, PPM, direct sampling, offset tuning, bias-tee
• Stations with tags + CSV/TSV import/export
• List/range scanning with squelch hold/skip
• Background audio + lock screen controls

Known limitations (early build)
• Built solo so far — no external testers yet
• Most real-world testing to date has been NFM and WFM
• Other modes are implemented, but I’d consider them early until more field feedback comes in

Tested with an RTL-SDR Blog V4 (R828D) on a Raspberry Pi running rtl_tcp.

I’d really appreciate detailed feedback (device + iOS version, tuner type, rtl_tcp command, mode/frequency, and steps to reproduce any issues).
 
CoronaSDR - RTL_TCP Client for iOS Devices.
CoronaSDR - RTL_TCP Client for iOS Devices.