Skip to content

nandortoth/rtlsdr-manager

RTL-SDR Manager Library for .NET

NuGet Version NuGet Downloads License .NET Version

A modern, high-performance .NET library for managing RTL-SDR devices with support for async operations, multiple tuner types, and advanced features like KerberosSDR.

✨ Features

  • πŸš€ Async/Await Support - Non-blocking sample reading with concurrent queue buffering
  • πŸŽ›οΈ Multiple Tuner Support - E4000, R820T/R828D, FC0012, FC0013, FC2580
  • πŸ”§ Advanced Configuration - Gain control, frequency correction, direct sampling, bias tee
  • πŸ“‘ KerberosSDR Ready - Frequency dithering and GPIO control for coherent SDR arrays
  • πŸ”’ Type-Safe API - Strongly-typed frequency values with unit conversions
  • πŸ’Ύ Cross-Platform - Works on Windows, Linux, and macOS
  • ⚑ High Performance - LibraryImport P/Invoke for optimal native interop
  • πŸ›‘οΈ Production Ready - Proper exception handling, disposal patterns, and null safety
  • πŸ”‡ Console Output Control - Scoped suppression of native library diagnostic messages

πŸ“¦ Installation

Via NuGet Package Manager

# .NET CLI
dotnet add package RtlSdrManager

# Package Manager Console (Visual Studio)
Install-Package RtlSdrManager

# PackageReference (in .csproj)
<PackageReference Include="RtlSdrManager" Version="0.5.2" />

Prerequisites

You must have the librtlsdr native library installed on your system:

Windows:

# Using Chocolatey
choco install rtl-sdr

# Or download from: https://github.com/osmocom/rtl-sdr/releases

Linux (Ubuntu/Debian):

sudo apt-get install librtlsdr-dev

macOS:

brew install librtlsdr

πŸš€ Quick Start

Basic Usage

using RtlSdrManager;
using RtlSdrManager.Modes;

// Get the singleton device manager
var manager = RtlSdrDeviceManager.Instance;

// Check available devices
Console.WriteLine($"Found {manager.CountDevices} RTL-SDR device(s)");

// Open the first device with a friendly name
manager.OpenManagedDevice(0, "my-rtl-sdr");

// Configure the device
var device = manager["my-rtl-sdr"];
device.CenterFrequency = Frequency.FromMHz(1090);  // ADS-B frequency
device.SampleRate = Frequency.FromMHz(2);
device.TunerGainMode = TunerGainModes.AGC;
device.AGCMode = AGCModes.Enabled;
device.ResetDeviceBuffer();

Console.WriteLine($"Tuner: {device.TunerType}");
Console.WriteLine($"Center Frequency: {device.CenterFrequency.MHz} MHz");

Console Output Suppression

By default, the library shows diagnostic messages from librtlsdr (like "Found Rafael Micro R820T tuner" and "[R82XX] PLL not locked!"). You can suppress these messages globally:

// Enable suppression globally (default is false - messages shown)
RtlSdrDeviceManager.SuppressLibraryConsoleOutput = true;

// Open a device - suppressed only during operation
manager.OpenManagedDevice(0, "my-rtl-sdr");  // librtlsdr messages hidden
var device = manager["my-rtl-sdr"];
device.SampleRate = Frequency.FromMHz(2.4);  // librtlsdr messages hidden

// Disable suppression - show messages again
RtlSdrDeviceManager.SuppressLibraryConsoleOutput = false;
device.CenterFrequency = Frequency.FromMHz(1090);  // Will show librtlsdr output

Note: Suppression uses scoped suppression (v0.5.2+) with reference-counted global singleton pattern:

  • Stdout/stderr redirected to /dev/null (Unix/macOS) or NUL (Windows) only during device operations
  • Console restored between operations, allowing console applications (Spectre.Console, etc.) to work properly
  • Prevents file descriptor corruption when multiple devices are opened simultaneously

Synchronous Sample Reading

// Read samples synchronously (blocking)
var samples = device.ReadSamples(256 * 1024);

foreach (var sample in samples)
{
    // Process I/Q samples
    Console.WriteLine($"I: {sample.I}, Q: {sample.Q}");
}

Asynchronous Sample Reading

// Configure async buffer
device.MaxAsyncBufferSize = 512 * 1024;
device.DropSamplesOnFullBuffer = true;

// Start async reading in background
device.StartReadSamplesAsync();

// Option 1: Event-based (recommended for real-time processing)
device.SamplesAvailable += (sender, args) =>
{
    var samples = device.GetSamplesFromAsyncBuffer(args.SampleCount);
    // Process samples in real-time
};

// Option 2: Manual polling (for custom processing logic)
while (running)
{
    if (device.AsyncBuffer.TryDequeue(out var data))
    {
        // Process data
        Console.WriteLine($"Received {data.Samples.Length} samples");
    }
    else
    {
        await Task.Delay(100);
    }
}

// Stop reading when done
device.StopReadSamplesAsync();

// Clean up
manager.CloseManagedDevice("my-rtl-sdr");

Manual Gain Control

// Switch to manual gain mode
device.TunerGainMode = TunerGainModes.Manual;

// Get supported gain values
var gains = device.SupportedTunerGains;
Console.WriteLine($"Supported gains: {string.Join(", ", gains)} dB");

// Set specific gain
device.TunerGain = 42.1; // dB

// Or use convenience methods
device.SetMaximumTunerGain();
device.SetMinimumTunerGain();

Frequency Operations

// Create frequencies with different units
var freq1 = Frequency.FromHz(1090_000_000);
var freq2 = Frequency.FromKHz(1090_000);
var freq3 = Frequency.FromMHz(1090);
var freq4 = Frequency.FromGHz(1.09);

// Convert between units
Console.WriteLine($"{freq1.Hz} Hz");
Console.WriteLine($"{freq1.KHz} KHz");
Console.WriteLine($"{freq1.MHz} MHz");
Console.WriteLine($"{freq1.GHz} GHz");

// Arithmetic operations
var shifted = freq1 + Frequency.FromKHz(100); // Add 100 KHz offset
var doubled = freq1 * 2;

// Comparison
if (freq1 > Frequency.FromMHz(100))
{
    Console.WriteLine("Above 100 MHz");
}

Advanced Features

Bias Tee (for powering external LNAs)

// Enable bias tee on GPIO 0 (most common)
device.SetBiasTee(BiasTeeModes.Enabled);

// For R820T tuners, specify GPIO pin
device.SetBiasTeeGPIO(gpio: 0, BiasTeeModes.Enabled);

Direct Sampling (HF reception)

// Enable direct sampling on I-ADC
device.DirectSamplingMode = DirectSamplingModes.I_ADC;

// Or on Q-ADC
device.DirectSamplingMode = DirectSamplingModes.Q_ADC;

// Disable
device.DirectSamplingMode = DirectSamplingModes.Disabled;

Frequency Correction (PPM)

// Set frequency correction in PPM
device.FrequencyCorrection = 10; // +10 PPM

KerberosSDR Support

// Enable KerberosSDR mode (required for these features)
device.KerberosSDRMode = KerberosSDRModes.Enabled;

// Enable frequency dithering (for R820T only)
device.FrequencyDitheringMode = FrequencyDitheringModes.Enabled;

// Control GPIO pins directly
device.SetGPIO(gpio: 1, GPIOModes.Enabled);

πŸ“š Documentation

For more detailed information and advanced usage scenarios:

Sample Applications

Check out the samples/ directory for complete working examples:

  • Demo1 - Event-based async sample reading
  • Demo2 - Manual polling from async buffer
  • Demo3 - Synchronous sample reading
  • Demo4 - Device information and configuration

πŸ”§ Building from Source

Requirements

  • .NET 9.0 SDK or later
  • librtlsdr native library

Build Commands

# Clone the repository
git clone https://github.com/nandortoth/rtlsdr-manager.git
cd rtlsdr-manager

# Build the entire solution
dotnet build

# Run tests (if available)
dotnet test

# Create NuGet packages
dotnet pack --configuration Release

# Or use the convenience script
./build.sh

Build Output

The build process creates:

  • NuGet packages β†’ artifacts/packages/
  • Library binaries β†’ artifacts/binaries/RtlSdrManager/
  • Sample binaries β†’ artifacts/binaries/Samples/

Running Samples

# Using the convenience script
./runsample.sh

# Or manually
dotnet run --project samples/RtlSdrManager.Samples

πŸ—οΈ Architecture

RtlSdrManager/
β”œβ”€β”€ src/
β”‚   └── RtlSdrManager/           # Main library
β”‚       β”œβ”€β”€ Exceptions/          # Custom exception types
β”‚       β”œβ”€β”€ Hardware/            # Hardware type definitions
β”‚       β”œβ”€β”€ Interop/             # P/Invoke wrappers
β”‚       └── Modes/               # Enumeration types
β”œβ”€β”€ samples/
β”‚   └── RtlSdrManager.Samples/   # Example applications
└── docs/                        # Documentation

🀝 Contributing

Contributions are welcome! Please feel free to submit issues, fork the repository, and create pull requests.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please ensure your code:

  • Follows the EditorConfig style guidelines
  • Builds without warnings
  • Includes XML documentation for public APIs
  • Includes unit tests for new features (when applicable)

πŸ“‹ System Requirements

  • .NET Runtime: 9.0 or later
  • Operating System: Windows, Linux, macOS
  • Hardware: RTL-SDR compatible device (RTL2832U-based)
  • Native Library: librtlsdr installed on the system

πŸ“ Supported Devices

This library supports RTL-SDR devices with the following tuners:

Tuner Frequency Range Notes
Elonics E4000 52-1100 MHz, 1250-2200 MHz No longer manufactured
Rafael Micro R820T 24-1766 MHz Most common, excellent performance
Rafael Micro R828D 24-1766 MHz Similar to R820T
Fitipower FC0012 22-948.6 MHz Basic performance
Fitipower FC0013 22-1100 MHz Basic performance
FCI FC2580 146-308 MHz, 438-924 MHz Good performance

πŸ“œ License

This project is licensed under the GNU General Public License v3.0 or later - see the LICENSE.md file for details.

RTL-SDR Manager Library for .NET
Copyright (C) 2018-2025 Nandor Toth

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

πŸ”— Links

πŸ™ Acknowledgments

πŸ“Š Project Status

  • βœ… Stable - Production ready
  • βœ… Actively Maintained - Regular updates and bug fixes
  • βœ… .NET 9.0 - Modern .NET with latest features
  • βœ… Cross-Platform - Windows, Linux, macOS support

Made with ❀️ by Nandor Toth

Packages

No packages published

Contributors 2

  •  
  •