ZigRadio Reference Manual

Generated from ZigRadio v0.8.0.

Example

Coming soon...

Building

Coming soon...

Running

Coming soon...

Blocks

Sources

AirspyHFSource

Source a complex-valued signal from an Airspy HF+. This source requires the libairspyhf library.

radio.blocks.AirspyHFSource.init(frequency: f64, rate: f64, options: Options)
Arguments
  • frequency (f64): Tuning frequency in Hz

  • rate (f64): Sample rate in Hz (e.g. 192 kHz, 256 kHz, 384 kHz, 768 kHz)

  • options (Options): Additional options:

    • hf_agc (bool, default true)
    • hf_agc_threshold (enum { Low, High}, default .Low)
    • hf_att (u8, default 0 dB, for manual attenuation when HF AGC is disabled, range of 0 to 48 dB, 6 dB step)
    • hf_lna (bool, default false)
    • debug (bool, default false)
Type Signature
  • ❑➔ out Complex(f32)
Example
var src = radio.blocks.AirspyHFSource.init(7.150e6, 192e3, .{ .hf_lna = true });
try top.connect(&src.block, &snk.block);

ApplicationSource

Source a signal from a host application.

Provides an interface for applications to push samples into the flowgraph.

radio.blocks.ApplicationSource(comptime T: type).init(rate: f64)
Comptime Arguments
  • T (type): Complex(f32), f32, u1, etc.
Arguments
  • rate (f64): Sample rate in Hz
Type Signature
  • ❑➔ out T
Example
var src = radio.blocks.ApplicationSource(std.math.Complex(f32)).init(1e6);
try top.connect(&src.block, &snk.block);
...
try src.push(std.math.Complex(f32).init(2, 3));

IQStreamSource

Source a complex-valued signal from a binary stream, using the specified sample format.

radio.blocks.IQStreamSource.init(reader: std.io.AnyReader, format: SampleFormat, rate: f64, options: Options)
Arguments
  • reader (std.io.AnyReader): Reader

  • format (SampleFormat): Choice of s8, u8, u16le, u16be, s16le, s16be, u32le, u32be, s32le, s32be, f32le, f32be, f64le, f64be

  • rate (f64): Sample rate in Hz

  • options (Options): Additional options

Type Signature
  • ❑➔ out Complex(f32)
Example
var input_file = try std.fs.cwd().openFile("samples.iq", .{});
defer input_file.close();
...
var src = radio.blocks.IQStreamSource.init(input_file.reader().any(), .s16le, 1e6, .{});
try top.connect(&src.block, &snk.block);

RealStreamSource

Source a real-valued signal from a binary stream, using the specified sample format.

radio.blocks.RealStreamSource.init(reader: std.io.AnyReader, format: SampleFormat, rate: f64, options: Options)
Arguments
  • reader (std.io.AnyReader): Reader

  • format (SampleFormat): Choice of s8, u8, u16le, u16be, s16le, s16be, u32le, u32be, s32le, s32be, f32le, f32be, f64le, f64be

  • rate (f64): Sample rate in Hz

  • options (Options): Additional options

Type Signature
  • ❑➔ out f32
Example
var input_file = try std.fs.cwd().openFile("samples.real", .{});
defer input_file.close();
...
var src = radio.blocks.RealStreamSource.init(input_file.reader().any(), .s16le, 1e6, .{});
try top.connect(&src.block, &snk.block);

RtlSdrSource

Source a complex-valued signal from an RTL-SDR dongle. This source requires the librtlsdr library.

radio.blocks.RtlSdrSource.init(frequency: f64, rate: f64, options: Options)
Arguments
  • frequency (f64): Tuning frequency in Hz

  • rate (f64): Sample rate in Hz

  • options (Options): Additional options: struct (bias_tee, direct_sampling, bandwidth, rf_gain, freq_correction, device_index, debug)

    • biastee (bool, default false)
    • direct_sampling (?DirectSamplingMode, default null, choice of .I, .Q)
    • bandwidth (?f32, default null for sample rate)
    • rf_gain (?f32, number in dB for manual gain, default null for auto-gain)
    • freq_correction (isize, in PPM, default 0)
    • device_index (isize, default 0)
    • debug (bool, default false)
Type Signature
  • ❑➔ out Complex(f32)
Example
var src = radio.blocks.RtlSdrSource.init(162.400e6, 1e6, .{ .autogain = true });
try top.connect(&src.block, &snk.block);

SignalSource

Sources a real-valued signal with configurable waveform, frequency, amplitude, and phase.

radio.blocks.SignalSource.init(waveform: WaveformFunction, frequency: f32, rate: f64, options: Options)
Arguments
  • waveform (WaveformFunction): Choice of .Cosine, .Sine, .Square, .Triangle, .Sawtooth, .Constant

  • frequency (f32): Frequency in Hz

  • rate (f64): Sample rate in Hz

  • options (Options): Additional options:

    • amplitude (f32, default 1.0)
    • offset (f32, default 0.0)
    • phase (f32, in radians, default 0.0)
Type Signature
  • ❑➔ out f32
Example
var src = radio.blocks.SignalSource.init(.Sine, 1000, 48000, .{ .amplitude = 0.5 });
try top.connect(&src.block, &snk.block);

ZeroSource

Source a zero-valued signal of the specified type.

radio.blocks.ZeroSource(comptime T: type).init(rate: f64)
Comptime Arguments
  • T (type): Complex(f32), f32, u1, etc.
Arguments
  • rate (f64): Sample rate in Hz
Type Signature
  • ❑➔ out T
Example
var src = radio.blocks.ZeroSource(std.math.Complex(f32)).init(1e6);
try top.connect(&src.block, &snk.block);

Sinks

ApplicationSink

Sink a signal to a host application.

Provides an interface for applications to consume samples from the flowgraph.

radio.blocks.ApplicationSink(comptime T: type).init()
Comptime Arguments
  • T (type): Complex(f32), f32, u1, etc.
Type Signature
  • in T ➔❑
Example
var snk = radio.blocks.ApplicationSink(std.math.Complex(f32)).init();
try top.connect(&src.block, &snk.block);
...
const sample = snk.pop();

BenchmarkSink

Benchmark throughput.

Consumes samples and periodically reports the sample rate and byte rate.

radio.blocks.BenchmarkSink(comptime T: type).init(options: Options)
Comptime Arguments
  • T (type): Complex(f32), f32, u1, etc.
Arguments
  • options (Options): Additional options:
    • title ([]const u8, default "BenchmarkSink")
    • report_period_ms (usize, reporting period in milliseconds, default 3000)
Type Signature
  • in T ➔❑
Example
var snk = radio.blocks.BenchmarkSink(std.math.Complex(f32)).init(.{});
try top.connect(&src.block, &snk.block);

IQStreamSink

Sink a complex-valued signal to a binary stream, using the specified sample format.

radio.blocks.IQStreamSink.init(writer: std.io.AnyWriter, format: SampleFormat, options: Options)
Arguments
  • writer (std.io.AnyWriter): Writer

  • format (SampleFormat): Choice of s8, u8, u16le, u16be, s16le, s16be, u32le, u32be, s32le, s32be, f32le, f32be, f64le, f64be

  • options (Options): Additional options

Type Signature
  • in Complex(f32) ➔❑
Example
var output_file = try std.fs.cwd().createFile("samples.iq", .{});
defer output_file.close();
...
var snk = radio.blocks.IQStreamSink.init(output_file.writer().any(), .s16le, .{});
try top.connect(&src.block, &snk.block);

JSONStreamSink

Sink a signal to a binary stream, serialized with JSON. Samples are serialized individually and newline delimited.

radio.blocks.JSONStreamSink(comptime T: type).init(writer: std.io.AnyWriter, options: Options)
Comptime Arguments
  • T (type): Any type serializable by std.json.stringify()
Arguments
  • writer (std.io.AnyWriter): Writer

  • options (Options): Additional options

Type Signature
  • in T ➔❑
Example
var output_file = try std.fs.cwd().createFile("samples.json", .{});
defer output_file.close();
...
var snk = radio.blocks.JSONStreamSink(Foo).init(output_file.writer().any(), .{});
try top.connect(&src.block, &snk.block);

PrintSink

Sink a signal to standard out.

radio.blocks.PrintSink(comptime T: type).init()
Comptime Arguments
  • T (type): Any type formattable by std.debug.print()
Type Signature
  • in T ➔❑
Example
var snk = radio.blocks.PrintSink(f32).init();
try top.connect(&src.block, &snk.block);

PulseAudioSink

Sink a mono or stereo real-valued signal to the PulseAudio sound server. This sink requires the libpulse-simple library.

radio.blocks.PulseAudioSink.init()
Type Signature
  • in1 f32, in2 f32 ➔❑
Example
var snk = radio.blocks.PulseAudioSink(2).init();
try top.connectPort(&src_left.block, "out", &snk.block, "in1");
try top.connectPort(&src_right.block, "out", &snk.block, "in2");

RealStreamSink

Sink a real-valued signal to a binary stream, using the specified sample format.

radio.blocks.RealStreamSink.init(writer: std.io.AnyWriter, format: SampleFormat, options: Options)
Arguments
  • writer (std.io.AnyWriter): Writer

  • format (SampleFormat): Choice of s8, u8, u16le, u16be, s16le, s16be, u32le, u32be, s32le, s32be, f32le, f32be, f64le, f64be

  • options (Options): Additional options

Type Signature
  • in f32 ➔❑
Example
var output_file = try std.fs.cwd().createFile("samples.real", .{});
defer output_file.close();
...
var snk = radio.blocks.RealStreamSink.init(output_file.writer().any(), .u16be, .{});
try top.connect(&src.block, &snk.block);

Filtering

BandpassFilterBlock

Filter a complex or real valued signal with a real-valued FIR band-pass filter generated by the window design method.

$$ y[n] = (x * h_{bpf})[n] $$

radio.blocks.BandpassFilterBlock(comptime T: type, comptime N: comptime_int).init(cutoffs: struct{f32,f32}, options: Options)
Comptime Arguments
  • T (type): Complex(f32), f32

  • N (comptime_int): Number of taps

Arguments
  • cutoffs (struct{f32,f32}): Lower and upper cutoff frequencies in Hz

  • options (Options): Additional options:

    • nyquist (?f32, alternate Nyquist frequency in Hz)
    • window (WindowFunction, window function, default Hamming)
Type Signature
  • in T ➔❑➔ out T
Example
var filter = radio.blocks.BandpassFilterBlock(std.math.Complex(f32), 129).init(.{ 10e3, 20e3 }, .{});

BandstopFilterBlock

Filter a complex or real valued signal with a real-valued FIR band-stop filter generated by the window design method.

$$ y[n] = (x * h_{bsf})[n] $$

radio.blocks.BandstopFilterBlock(comptime T: type, comptime N: comptime_int).init(cutoffs: struct{f32,f32}, options: Options)
Comptime Arguments
  • T (type): Complex(f32), f32

  • N (comptime_int): Number of taps

Arguments
  • cutoffs (struct{f32,f32}): Lower and upper cutoff frequencies in Hz

  • options (Options): Additional options:

    • nyquist (?f32, alternate Nyquist frequency in Hz)
    • window (WindowFunction, window function, default Hamming)
Type Signature
  • in T ➔❑➔ out T
Example
var filter = radio.blocks.BandstopFilterBlock(std.math.Complex(f32), 129).init(.{ 10e3, 20e3 }, .{});

ComplexBandpassFilterBlock

Filter a complex-valued signal with a complex-valued FIR band-pass filter generated by the window design method. This filter is asymmetric in the frequency domain.

$$ y[n] = (x * h_{bpf})[n] $$

radio.blocks.ComplexBandpassFilterBlock(comptime N: comptime_int).init(cutoffs: struct{f32,f32}, options: Options)
Comptime Arguments
  • N (comptime_int): Number of taps
Arguments
  • cutoffs (struct{f32,f32}): Lower and upper cutoff frequencies in Hz

  • options (Options): Additional options:

    • nyquist (?f32, alternate Nyquist frequency in Hz)
    • window (WindowFunction, window function, default Hamming)
Type Signature
  • in Complex(f32) ➔❑➔ out Complex(f32)
Example
var filter = radio.blocks.ComplexBandpassFilterBlock(129).init(.{ 10e3, 20e3 }, .{});

ComplexBandstopFilterBlock

Filter a complex-valued signal with a complex-valued FIR band-stop filter generated by the window design method. This filter is asymmetric in the frequency domain.

$$ y[n] = (x * h_{bsf})[n] $$

radio.blocks.ComplexBandstopFilterBlock(comptime N: comptime_int).init(cutoffs: struct{f32,f32}, options: Options)
Comptime Arguments
  • N (comptime_int): Number of taps
Arguments
  • cutoffs (struct{f32,f32}): Lower and upper cutoff frequencies in Hz

  • options (Options): Additional options:

    • nyquist (?f32, alternate Nyquist frequency in Hz)
    • window (WindowFunction, window function, default Hamming)
Type Signature
  • in Complex(f32) ➔❑➔ out Complex(f32)
Example
var filter = radio.blocks.ComplexBandstopFilterBlock(129).init(.{ 10e3, 20e3 }, .{});

FIRFilterBlock

Filter a complex or real valued signal with an FIR filter.

$$ y[n] = (x * h)[n] $$

$$ y[n] = b_0 x[n] + b_1 x[n-1] + ... + b_N x[n-N] $$

radio.blocks.FIRFilterBlock(comptime T: type, comptime U: type, comptime N: comptime_int).init(taps: [N]U)
Comptime Arguments
  • T (type): Complex(f32), f32

  • U (type): Tap data type (e.g. Complex(f32), f32)

  • N (comptime_int): Number of taps

Arguments
  • taps ([N]U): Taps
Type Signature
  • in T ➔❑➔ out T
Example
var filter = radio.blocks.FIRFilterBlock(std.math.Complex(f32), f32, 64).init(taps);

FMDeemphasisFilterBlock

Filter a complex or real valued signal with an FM De-emphasis filter, a single-pole low-pass IIR filter.

$$ y[n] = (x * h_{fmdeemph})[n] $$

radio.blocks.FMDeemphasisFilterBlock.init(tau: De-emphasis)
Arguments
  • tau (De-emphasis): time constant
Type Signature
  • in f32 ➔❑➔ out f32
Example
var deemphasis = radio.blocks.FMDeemphasisFilterBlock.init(75e-6);

HighpassFilterBlock

Filter a complex or real valued signal with a real-valued FIR high-pass filter generated by the window design method.

$$ y[n] = (x * h_{hpf})[n] $$

radio.blocks.HighpassFilterBlock(comptime T: type, comptime N: comptime_int).init(cutoff: f32, options: Options)
Comptime Arguments
  • T (type): Complex(f32), f32

  • N (comptime_int): Number of taps (filter length)

Arguments
  • cutoff (f32): Cutoff frequency in Hz

  • options (Options): Additional options:

    • nyquist (?f32, alternate Nyquist frequency in Hz)
    • window (WindowFunction, window function, default Hamming)
Type Signature
  • in T ➔❑➔ out T
Example
var filter = radio.blocks.HighpassFilterBlock(std.math.Complex(f32), 129).init(100, .{});

IIRFilterBlock

Filter a complex or real valued signal with an IIR filter.

$$ y[n] = (x * h)[n] $$

$$ \begin{align} y[n] = &\frac{1}{a_0}(b_0 x[n] + b_1 x[n-1] + ... + b_N x[n-N] \\ - &a_1 y[n-1] - a_2 y[n-2] - ... - a_M x[n-M])\end{align} $$

radio.blocks.IIRFilterBlock(comptime T: type, comptime N: comptime_int, comptime M: comptime_int).init(b_taps: [N]f32, a_taps: [M]f32)
Comptime Arguments
  • T (type): Complex(f32), f32

  • N (comptime_int): Number of feedforward taps

  • M (comptime_int): Number of feedback taps

Arguments
  • b_taps ([N]f32): Feedforward taps

  • a_taps ([M]f32): Feedback taps

Type Signature
  • in T ➔❑➔ out T
Example
var filter = radio.blocks.IIRFilterBlock(std.math.Complex(f32), 3, 3).init(b_taps, a_taps);

LowpassFilterBlock

Filter a complex or real valued signal with a real-valued FIR low-pass filter generated by the window design method.

$$ y[n] = (x * h_{lpf})[n] $$

radio.blocks.LowpassFilterBlock(comptime T: type, comptime N: comptime_int).init(cutoff: f32, options: Options)
Comptime Arguments
  • T (type): Complex(f32), f32

  • N (comptime_int): Number of taps (filter length)

Arguments
  • cutoff (f32): Cutoff frequency in Hz

  • options (Options): Additional options:

    • nyquist (?f32, alternate Nyquist frequency in Hz)
    • window (WindowFunction, window function, default Hamming)
Type Signature
  • in T ➔❑➔ out T
Example
var filter = radio.blocks.LowpassFilterBlock(std.math.Complex(f32), 128).init(10e3, .{});

RectangularMatchedFilterBlock

Correlate a real-valued signal with a rectangular matched filter.

radio.blocks.RectangularMatchedFilterBlock.init(baudrate: Baudrate)
Arguments
  • baudrate (Baudrate):
Type Signature
  • in f32 ➔❑➔ out f32
Example
var matched_filter = radio.blocks.RectangularMatchedFilterBlock.init(2400);

SinglepoleHighpassFilterBlock

Filter a complex or real valued signal with a single-pole high-pass IIR filter.

$$ H(s) = \frac{\tau s}{\tau s + 1} $$

$$ H(z) = \frac{2\tau f_s}{1 + 2\tau f_s} \frac{1 - z^{-1}}{1 + (\frac{1 - 2\tau f_s}{1 + 2\tau f_s}) z^{-1}} $$

$$ y[n] = \frac{2\tau f_s}{1 + 2\tau f_s} \; x[n] + \frac{2\tau f_s}{1 + 2\tau f_s} \; x[n-1] - \frac{1 - 2\tau f_s}{1 + 2\tau f_s} \; y[n-1] $$

radio.blocks.SinglepoleHighpassFilterBlock(comptime T: type).init(cutoff: f32)
Comptime Arguments
  • T (type): Complex(f32), f32
Arguments
  • cutoff (f32): Cutoff frequency in Hz
Type Signature
  • in T ➔❑➔ out T
Example
var filter = radio.blocks.SinglepoleHighpassFilterBlock(f32).init(100);

SinglepoleLowpassFilterBlock

Filter a complex or real valued signal with a single-pole low-pass IIR filter.

$$ H(s) = \frac{1}{\tau s + 1} $$

$$ H(z) = \frac{1}{1 + 2\tau f_s} \frac{1 + z^{-1}}{1 + (\frac{1 - 2\tau f_s}{1 + 2\tau f_s}) z^{-1}} $$

$$ y[n] = \frac{1}{1 + 2\tau f_s} \; x[n] + \frac{1}{1 + 2\tau f_s} \; x[n-1] - \frac{1 - 2\tau f_s}{1 + 2\tau f_s} \; y[n-1] $$

radio.blocks.SinglepoleLowpassFilterBlock(comptime T: type).init(cutoff: f32)
Comptime Arguments
  • T (type): Complex(f32), f32
Arguments
  • cutoff (f32): Cutoff frequency in Hz
Type Signature
  • in T ➔❑➔ out T
Example
var filter = radio.blocks.SinglepoleLowpassFilterBlock(f32).init(1e3);

Math Operations

AddBlock

Add two signals.

$$ y[n] = x_{1}[n] + x_{2}[n] $$

radio.blocks.AddBlock(comptime T: type).init()
Comptime Arguments
  • T (type): Complex(f32), f32, etc.
Type Signature
  • in1 T, in2 T ➔❑➔ out T
Example
var summer = radio.blocks.AddBlock(std.math.Complex(f32)).init();
try top.connectPort(&src1.block, "out1", &summer.block, "in1");
try top.connectPort(&src2.block, "out1", &summer.block, "in2");
try top.connect(&summer.block, &sink.block);

ComplexMagnitudeBlock

Compute the magnitude of a complex-valued signal.

$$ y[n] = |x[n]| $$

$$ y[n] = \sqrt{\text{Re}(x[n])^2 + \text{Im}(x[n])^2} $$

radio.blocks.ComplexMagnitudeBlock.init()
Type Signature
  • in Complex(f32) ➔❑➔ out f32
Example
var mag = radio.blocks.ComplexMagnitudeBlock.init();

MultiplyBlock

Multiply two signals.

$$ y[n] = x_{1}[n] \; x_{2}[n] $$

radio.blocks.MultiplyBlock(comptime T: type).init()
Comptime Arguments
  • T (type): Complex(f32), f32, etc.
Type Signature
  • in1 T, in2 T ➔❑➔ out T
Example
var multiplier = radio.blocks.MultiplyBlock(std.math.Complex(f32)).init();
try top.connectPort(&src1.block, "out1", &multiplier.block, "in1");
try top.connectPort(&src2.block, "out1", &multiplier.block, "in2");
try top.connect(&multiplier.block, &snk.block);

MultiplyConjugateBlock

Multiply a complex-valued signal by the complex conjugate of another complex-valued signal.

$$ y[n] = x_{1}[n] \; x_{2}^*[n] $$

radio.blocks.MultiplyConjugateBlock.init()
Type Signature
  • in1 Complex(f32), in2 Complex(f32) ➔❑➔ out Complex(f32)
Example
var mixer = radio.blocks.MultiplyConjugateBlock.init();
try top.connectPort(&src1.block, "out1", &mixer.block, "in1");
try top.connectPort(&src2.block, "out1", &mixer.block, "in2");
try top.connect(&mixer.block, &snk.block);

SubtractBlock

Subtract two signals.

$$ y[n] = x_{1}[n] - x_{2}[n] $$

radio.blocks.SubtractBlock(comptime T: type).init()
Comptime Arguments
  • T (type): Complex(f32), f32, etc.
Type Signature
  • in1 T, in2 T ➔❑➔ out T
Example
var subtractor = radio.blocks.SubtractBlock(std.math.Complex(f32)).init();
try top.connectPort(&src1.block, "out1", &subtractor.block, "in1");
try top.connectPort(&src1.block, "out1", &subtractor.block, "in2");
try top.connect(&subtractor.block, &snk.block);

Level Control

AGCBlock

Apply automatic gain to a real or complex valued signal to maintain an average target power.

$$ y[n] = \text{AGC}(x[n], \text{mode}, \text{target}, \text{threshold}) $$

Implementation note: this is a feedforward AGC. The power_tau time constant controls the moving average of the power estimator. The gain_tau time constant controls the speed of the gain adjustment. The gain has symmetric attack and decay dynamics.

radio.blocks.AGCBlock(comptime T: type).init(mode: Mode, options: Options)
Comptime Arguments
  • T (type): Complex(f32), f32
Arguments
  • mode (Mode): AGC mode, either preset of .Slow, .Medium, .Fast or a custom time constant

  • options (Options): Additional options:

    • target_dbfs (f32, target level in dBFS, default -20)
    • threshold_dbfs (f32, threshold level in dBFS, default -75)
    • power_tau (f32, power estimator time constant, default 1.0)
Type Signature
  • in T ➔❑➔ out T
Example
var agc = radio.blocks.AGCBlock(std.math.Complex(f32)).init(.{ .preset = .Fast }, .{ .target_dbfs = -30, .threshold_dbfs = -75 });

Sample Rate Manipulation

DownsamplerBlock

Downsample a complex or real valued signal. This block reduces the sample rate for downstream blocks in the flow graph by a factor of M.

$$ y[n] = x[nM] $$

Note: this block performs no anti-alias filtering.

radio.blocks.DownsamplerBlock(comptime T: type).init(factor: usize)
Comptime Arguments
  • T (type): Complex(f32), f32, etc.
Arguments
  • factor (usize): Downsampling factor
Type Signature
  • in T ➔❑➔ out T
Example
var downsampler = radio.blocks.DownsamplerBlock(std.math.Complex(f32)).init(4);

Spectrum Manipulation

TunerBlock

Frequency translate, low-pass filter, and downsample a complex-valued signal.

$$ y[n] = (\text{FrequencyTranslate}(x[n], f_{offset}) * h_{lpf})[nM] $$

This block is convenient for translating signals to baseband.

radio.blocks.TunerBlock.init(offset: f32, bandwidth: f32, factor: usize)
Arguments
  • offset (f32): Translation offset in Hz

  • bandwidth (f32): Signal bandwidth in Hz

  • factor (usize): Downsampling factor M

Type Signature
  • in1 Complex(f32) ➔❑➔ out1 Complex(f32)
Example
var tuner = radio.blocks.TunerBlock.init(50e3, 10e3, 5);
try top.connect(&src.block, &tuner.block);
try top.connect(&tuner.block, &snk.block);

FrequencyTranslatorBlock

Frequency translate a complex-valued signal by mixing it with \( e^{j \omega_0 n} \), where \( \omega_0 = 2 \pi f_o / f_s \).

$$ y[n] = x[n] \; e^{j\omega_0 n} $$

radio.blocks.FrequencyTranslatorBlock.init(offset: Translation)
Arguments
  • offset (Translation): offset in Hz
Type Signature
  • in Complex(f32) ➔❑➔ out Complex(f32)
Example
var translator = radio.blocks.FrequencyTranslatorBlock.init(-50e3);

Carrier and Clock Recovery

ComplexPLLBlock

Generate a phase-locked complex sinusoid to a complex-valued reference signal.

$$ y[n] = \text{PLL}(x[n], f_{BW}, f_{min}, f_{max}, M) $$

radio.blocks.ComplexPLLBlock.init(loop_bandwidth: f32, frequency_range: struct{f32,f32}, options: Options)
Arguments
  • loop_bandwidth (f32): Loop bandwidth in Hz

  • frequency_range (struct{f32,f32}): Minimum and maximum frequency range in Hz

  • options (Options): Additional options:

    • multiplier (f32, frequency multiplier, default 1.0)
Type Signature
  • in Complex(f32) ➔❑➔ out Complex(f32), err f32
Example
var pll = radio.blocks.ComplexPLLBlock.init(500, .{ 8e3, 12e3 }, .{});
try top.connect(&src.block, &pll.block);
try top.connectPort(&pll.block, "out1", &snk.block);
try top.connectPort(&pll.block, "out2", &err_snk.block);

Digital

DifferentialDecoderBlock

Decode a differentially encoded bit stream.

radio.blocks.DifferentialDecoderBlock.init()
Type Signature
  • in u1 ➔❑➔ out u1
Example
var diffdecoder = radio.blocks.DifferentialDecoderBlock(false).init();

SlicerBlock

Slice a signal into symbols using the specified slicer.

radio.blocks.SlicerBlock.init()
Type Signature
  • in T ➔❑➔ out U
Example
var slicer = radio.blocks.SlicerBlock(radio.blocks.BinarySlicer).init();

Type Conversion

ComplexToImagBlock

Decompose the imaginary part of a complex-valued signal.

$$ y[n] = \text{Im}(x[n]) $$

radio.blocks.ComplexToImagBlock.init()
Type Signature
  • in Complex(f32) ➔❑➔ out f32
Example
var complextoimag = radio.blocks.ComplexToImagBlock.init();

ComplexToRealBlock

Decompose the real part of a complex-valued signal.

$$ y[n] = \text{Re}(x[n]) $$

radio.blocks.ComplexToRealBlock.init()
Type Signature
  • in Complex(f32) ➔❑➔ out f32
Example
var complextoreal = radio.blocks.ComplexToRealBlock.init();

RealToComplexBlock

Compose a complex-valued signal from a real-valued signal and a zero-valued imaginary part.

$$ y[n] = x[n] + 0 \, j $$

radio.blocks.RealToComplexBlock.init()
Type Signature
  • in f32 ➔❑➔ out Complex(f32)
Example
var realtocomplex = radio.blocks.RealToComplexBlock.init();

Miscellaneous

DelayBlock

Delay a signal by a fixed number of samples.

$$ y[n] = x[n - D] $$

radio.blocks.DelayBlock(comptime T: type).init(delay: usize)
Comptime Arguments
  • T (type): Complex(f32), f32, etc.
Arguments
  • delay (usize): Number of samples to delay
Type Signature
  • in T ➔❑➔ out T
Example
var delay = radio.blocks.DelayBlock(std.math.Complex(f32)).init(7);

Demodulation

AMEnvelopeDemodulatorBlock

Demodulate a baseband, double-sideband amplitude modulated

$$ y[n] = \text{AMDemodulate}(x[n], \text{bandwidth}) $$

complex-valued signal with an envelope detector.

radio.blocks.AMEnvelopeDemodulatorBlock.init(options: Options)
Arguments
  • options (Options): Additional options:
    • bandwidth (f32, bandwidth in Hz, default 5e3)
Type Signature
  • in1 Complex(f32) ➔❑➔ out1 f32
Example
var demod = radio.blocks.AMEnvelopeDemodulatorBlock.init(.{});
try top.connect(&src.block, &demod.block);
try top.connect(&demod.block, &snk.block);

AMSynchronousDemodulatorBlock

Demodulate a baseband, double-sideband amplitude modulated complex-valued signal with a synchronous detector.

$$ y[n] = \text{AMDemodulate}(x[n], \text{bandwidth}) $$

radio.blocks.AMSynchronousDemodulatorBlock.init(options: Options)
Arguments
  • options (Options): Additional options:
    • bandwidth (f32, bandwidth in Hz, default 5e3)
Type Signature
  • in1 Complex(f32) ➔❑➔ out1 f32
Example
var demod = radio.blocks.AMSynchronousDemodulatorBlock.init(.{});
try top.connect(&src.block, &demod.block);
try top.connect(&demod.block, &snk.block);

NBFMDemodulatorBlock

Demodulate a baseband, narrowband FM modulated complex-valued signal.

$$ y[n] = \text{NBFMDemodulate}(x[n], \text{deviation}, \text{bandwidth}) $$

radio.blocks.NBFMDemodulatorBlock.init(options: Options)
Arguments
  • options (Options): Additional options:
    • bandwidth (f32, bandwidth in Hz, default 5e3)
    • deviation (f32, deviation in Hz, default 4e3)
Type Signature
  • in1 Complex(f32) ➔❑➔ out1 f32
Example
var demod = radio.blocks.NBFMDemodulatorBlock.init(.{});
try top.connect(&src.block, &demod.block);
try top.connect(&demod.block, &snk.block);

WBFMMonoDemodulatorBlock

Demodulate a baseband, broadcast radio wideband FM modulated complex-valued signal into the real-valued mono channel (L+R) signal.

$$ y[n] = \text{WBFMMonoDemodulate}(x[n], \text{deviation}, \text{bandwidth}, \tau) $$

radio.blocks.WBFMMonoDemodulatorBlock.init(options: Options)
Arguments
  • options (Options): Additional options:
    • deviation (f32, deviation in Hz, default 75e3)
    • af_bandwidth (f32, audio bandwidth in Hz, default 15e3)
    • af_deemphasis_tau (f32, audio de-emphasis time constant, default 75e-6)
Type Signature
  • in1 Complex(f32) ➔❑➔ out1 f32
Example
var demod = radio.blocks.WBFMMonoDemodulatorBlock.init(.{});
try top.connect(&src.block, &demod.block);
try top.connect(&demod.block, &snk.block);

WBFMStereoDemodulatorBlock

Demodulate a baseband, broadcast radio wideband FM modulated complex-valued signal into the real-valued stereo channel (L and R) signals.

$$ y_{left}[n], y_{right}[n] = \text{WBFMStereoDemodulate}(x[n], \text{deviation}, \text{bandwidth}, \tau) $$

radio.blocks.WBFMStereoDemodulatorBlock.init(options: Options)
Arguments
  • options (Options): Additional options:
    • deviation (f32, deviation in Hz, default 75e3)
    • af_bandwidth (f32, audio bandwidth in Hz, default 15e3)
    • af_deemphasis_tau (f32, audio de-emphasis time constant, default 75e-6)
Type Signature
  • in1 Complex(f32) ➔❑➔ out1 f32, out2 f32
Example
var demod = radio.blocks.WBFMStereoDemodulatorBlock.init(.{});
try top.connect(&src.block, &demod.block);
try top.connectPort(&demod.block, "out1", &left_snk.block, "in1");
try top.connectPort(&demod.block, "out2", &right_snk.block, "in1");

FrequencyDiscriminatorBlock

Compute the instantaneous frequency of a complex-valued input signal. This is a method of frequency demodulation.

$$ y[n] = \frac{\text{arg}(x[n] \; x^*[n-1])}{2 \pi k} $$

radio.blocks.FrequencyDiscriminatorBlock.init(deviation: f32)
Arguments
  • deviation (f32): Frequency deviation in Hz
Type Signature
  • in Complex(f32) ➔❑➔ out f32
Example
var demod = radio.blocks.FrequencyDiscriminatorBlock.init(5e3);