Rtlsdr

Elixir wrapper for librtlsdr - interface with RTL-SDR USB devices for software-defined radio applications.

Features

Prerequisites

You need librtlsdr installed on your system:

macOS

brew install librtlsdr

Ubuntu/Debian

sudo apt-get install librtlsdr-dev

Arch Linux

sudo pacman -S rtl-sdr

Installation

Add rtlsdr to your list of dependencies in mix.exs:

def deps do
  [
    {:rtlsdr, "~> 0.1.0"}
  ]
end

Then run:

mix deps.get
mix compile

Quick Start

# List available devices
Rtlsdr.list_devices()
#=> [%{index: 0, name: "Generic RTL2832U OEM", ...}]

# Start a device
{:ok, device} = Rtlsdr.Device.start_link(index: 0)

# Configure the device
:ok = Rtlsdr.Device.set_center_freq(device, 100_000_000)  # 100 MHz
:ok = Rtlsdr.Device.set_sample_rate(device, 2_048_000)    # 2.048 MS/s
:ok = Rtlsdr.Device.set_tuner_gain_mode(device, :manual)
:ok = Rtlsdr.Device.set_tuner_gain(device, 400)           # 40.0 dB

# Read samples synchronously
{:ok, samples} = Rtlsdr.Device.read_samples(device, 262144)

# Convert to IQ float pairs
iq_samples = Rtlsdr.samples_to_iq(samples)
#=> [{0.0, 0.0039...}, {0.125, -0.0078...}, ...]

# Or start streaming
:ok = Rtlsdr.Device.start_streaming(device, self())

receive do
  {:rtlsdr_samples, data} ->
    # Process your samples here
    IO.puts("Received #{byte_size(data)} bytes")
end

# Stop streaming
:ok = Rtlsdr.Device.stop_streaming(device)

# Close the device
:ok = Rtlsdr.Device.stop(device)

IQ Sample Format

Samples are returned as a binary containing interleaved 8-bit unsigned I/Q data: <<I0, Q0, I1, Q1, ...>>

Each I and Q value is in the range 0-255, with 127/128 being the center (zero) point.

To convert to normalized float values:

# To list of {I, Q} tuples (-1.0 to 1.0)
Rtlsdr.samples_to_iq(samples)

# To flat list of floats [I1, Q1, I2, Q2, ...]
Rtlsdr.samples_to_floats(samples)

Using the Streamer

For pub/sub style streaming with multiple consumers:

{:ok, streamer} = Rtlsdr.Streamer.start_link(
  device_index: 0,
  center_freq: 100_000_000,
  sample_rate: 2_048_000,
  tuner_gain: 400
)

# Subscribe to receive samples
Rtlsdr.Streamer.subscribe(streamer)

# Start streaming
Rtlsdr.Streamer.start_streaming(streamer)

# Receive samples
receive do
  {:rtlsdr_samples, data} -> process(data)
end

# Get statistics
{:ok, stats} = Rtlsdr.Streamer.stats(streamer)
#=> %{bytes_received: 1048576, samples_received: 4, ...}

Device Configuration

Frequency

# Set center frequency (in Hz)
Rtlsdr.Device.set_center_freq(device, 433_920_000)  # 433.92 MHz

# Get current frequency
{:ok, freq} = Rtlsdr.Device.get_center_freq(device)

Sample Rate

Valid range: 225,001 - 3,200,000 Hz

Rtlsdr.Device.set_sample_rate(device, 2_048_000)

# Common sample rates
Rtlsdr.common_sample_rates()
#=> [250000, 1024000, 1800000, 2048000, 2400000, 2560000, 2880000, 3200000]

Gain Control

# Get available gain values (in tenths of dB)
{:ok, gains} = Rtlsdr.Device.get_tuner_gains(device)
#=> [0, 9, 14, 27, 37, 77, 87, 125, 144, 157, 166, 197, ...]

# Set manual gain mode
Rtlsdr.Device.set_tuner_gain_mode(device, :manual)

# Set gain (in tenths of dB, so 400 = 40.0 dB)
Rtlsdr.Device.set_tuner_gain(device, 400)

# Or use automatic gain control
Rtlsdr.Device.set_tuner_gain_mode(device, :auto)
Rtlsdr.Device.set_agc_mode(device, true)

Frequency Correction

# Set PPM correction for crystal offset
Rtlsdr.Device.set_freq_correction(device, 56)  # 56 ppm

Direct Sampling (HF mode)

# 0 = disabled (normal tuner mode)
# 1 = I-ADC input enabled
# 2 = Q-ADC input enabled
Rtlsdr.Device.set_direct_sampling(device, 1)

Bias Tee

⚠️ Warning: Only enable if your setup requires bias tee power (e.g., for an LNA).

Rtlsdr.Device.set_bias_tee(device, true)

Supported Tuners

Tuner Frequency Range
R820T/R820T2 24 MHz - 1766 MHz
E4000 52 MHz - 2200 MHz (gap at 1100-1250 MHz)
FC0012 22 MHz - 948.6 MHz
FC0013 22 MHz - 1100 MHz
FC2580 146 MHz - 308 MHz

API Reference

Rtlsdr

Rtlsdr.Device

Rtlsdr.Streamer

License

MIT License - see LICENSE file for details.

Contributing

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