Crate rustradio

source ·
Expand description

This create provides a framework for running SDR (software defined radio) applications.

It’s heavily inspired by GNURadio, except of course written in Rust.

It currently has very few blocks, and is missing tags, and PDU messages.

In addition to the example applications in this crate, there’s also a sparslog project using this framework, that decodes IKEA Sparsnäs electricity meter RF signals.

Architecture overview

A RustRadio application consists of blocks that are connected by unidirectional streams. Each block has zero or more input streams, and zero or more output streams.

The signal flows through the blocks from “sources” (blocks without any input streams) to “sinks” (blocks without any output streams.

These blocks and streams are called a “graph”, like the mathematical concept of graphs that have nodes and edges.

A block does something to its input(s), and passes the result to its output(s).

A typical graph will be something like:

  [ Raw radio source ]
           ↓
      [ Filtering ]
           ↓
      [ Resampling ]
           ↓
     [ Demodulation ]
           ↓
     [ Symbol Sync ]
           ↓
[ Packet assembly and save ]

Or concretely, for sparslog:

     [ RtlSdrSource ]
           ↓
  [ RtlSdrDecode to convert from ]
  [ own format to complex I/Q    ]
           ↓
     [ FftFilter ]
           ↓
      [ RationalResampler ]
           ↓
      [ QuadratureDemod ]
           ↓
  [ AddConst for frequency offset ]
           ↓
   [ ZeroCrossing symbol sync ]
           ↓
     [ Custom Sparsnäs decoder ]
     [ block in the binary,    ]
     [ not in the framework    ]

Examples

Here’s a simple example that creates a couple of blocks, connects them with streams, and runs the graph.

use rustradio::graph::Graph;
use rustradio::blocks::{AddConst, VectorSource, DebugSink};
use rustradio::stream::StreamType;
use rustradio::Complex;
let mut g = Graph::new();
let src = g.add(Box::new(VectorSource::new(
    vec![
        Complex::new(10.0, 0.0),
        Complex::new(-20.0, 0.0),
        Complex::new(100.0, -100.0),
    ],
    false,
)));
let add = g.add(Box::new(AddConst::new(Complex::new(1.1, 2.0))));
let sink = g.add(Box::new(DebugSink::<Complex>::new()));
g.connect(StreamType::new_complex(), src, 0, add, 0);
g.connect(StreamType::new_complex(), add, 0, sink, 0);
g.run()?;

Modules

  • Add a constant value to every sample.
  • Blocks for the Au file format.
  • Turn positive Float values into binary 1u8, and negative into 0u8.
  • RustRadio Block implementation
  • Convenient mod collecting all standard library blocks for import.
  • Convert Complex numbers to square of their magnitude.
  • Generate the same value, forever.
  • Blocks for converting from one type to another.
  • Print values to stdout, for debugging.
  • Delay stream. Good for syncing up streams.
  • FFT filter. Like a FIR filter, but more efficient when there are many taps.
  • Send stream to raw file.
  • Read stream from raw file.
  • Finite impulse response filter.
  • Graphs contain blocks connected by streams, and run them.
  • Multiply stream by a constant value.
  • Discard anything written to this block.
  • Quadrature demod, the core of an FM demodulator.
  • Resample by a fractional amount.
  • Decode RTL-SDR’s byte based format into Complex I/Q.
  • Infinite Impulse Response (IIR) filter.
  • Streams connecting blocks.
  • Clock recovery implementations
  • TCP source.
  • Generate values from a fixed vector.

Macros

Structs

Traits

  • A trait all sample types must implement.

Type Aliases

  • Complex (I/Q) data.
  • Float type used. Usually f32, but not guaranteed.