Generated from LuaRadio v0.11.0
.
local radio = require('radio')
-- RTL-SDR Source, frequency 88.5 MHz - 250 kHz, sample rate 1102500 Hz
local source = radio.RtlSdrSource(88.5e6 - 250e3, 1102500)
-- Tuner block, translate -250 kHz, filter 200 kHz, decimate by 5
local tuner = radio.TunerBlock(-250e3, 200e3, 5)
-- Wideband FM Stereo Demodulator block
local demodulator = radio.WBFMStereoDemodulator()
-- Left and right AF downsampler blocks
local l_downsampler = radio.DownsamplerBlock(5)
local r_downsampler = radio.DownsamplerBlock(5)
-- Audio sink, 2 channels for left and right audio
local sink = radio.PulseAudioSink(2)
-- Top-level block
local top = radio.CompositeBlock()
-- Connect blocks in top block
top:connect(source, tuner, demodulator)
top:connect(demodulator, 'left', l_downsampler, 'in')
top:connect(demodulator, 'right', r_downsampler, 'in')
top:connect(l_downsampler, 'out', sink, 'in1')
top:connect(r_downsampler, 'out', sink, 'in2')
-- Run top block
top:run()
$ luaradio example.lua
LuaRadio scripts can be run with the luaradio
runner, or directly with
luajit
, if the radio
package is installed in your Lua path.
luaradio
runnerThe luaradio
runner is a simple wrapper script for running LuaRadio scripts.
It can also print version information, dump relevant platform information, and
adjust the runtime debug verbosity of scripts. The runner modifies the Lua path
to support importing the radio
package locally, so it can be used to run
LuaRadio scripts directly from the repository without installation.
$ ./luaradio
Usage: luaradio [options] <script> [args]
Options:
-h, --help Print help and exit
--version Print version and exit
--platform Dump platform and exit
-v, --verbose Enable debug verbosity
$
To run a script, use luaradio
as you would use luajit
:
$ luaradio script.lua
To run a script with debug verbosity:
$ luaradio -v script.lua
LuaRadio interprets several environment variables to adjust runtime settings.
These environment variables are treated as flags that can be enabled with value
1
(or values y
, yes
, true
).
LUARADIO_DEBUG
- Enable debug verbosityLUARADIO_DISABLE_LIQUID
- Disable liquid-dsp libraryLUARADIO_DISABLE_VOLK
- Disable volk libraryLUARADIO_DISABLE_FFTW3F
- Disable fftw3f libraryFor example, to enable debug verbosity:
$ LUARADIO_DEBUG=1 luaradio script.lua
To disable use of the VOLK library:
$ LUARADIO_DISABLE_VOLK=1 luaradio script.lua
To run a script with no external libraries for acceleration:
$ LUARADIO_DISABLE_LIQUID=1 LUARADIO_DISABLE_VOLK=1 LUARADIO_DISABLE_FFTW3F=1 luaradio script.lua
radio.CompositeBlock()
Create a block to hold a flow graph composition, for either top-level or
hierarchical purposes. Top-level blocks may be run with the run()
method.
CompositeBlock:connect(...)
Connect blocks.
This method can be used in three ways:
Linear block connections. Connect the first output to the first input of each adjacent block. This usage is convenient for connecting blocks that only have one input port and output port (which is most blocks).
top:connect(b1, b2, b3)
Explicit block connections. Connect a particular output of the first block to a particular input of the second block. The output and input ports are specified by name. This invocation is used to connect a block to another block with multiple input ports.
top:connect(b1, 'out', b2, 'in2')
Alias port connections. Alias a composite block’s input or output port to a concrete block’s input or output port. This invocation is used for connecting the boundary inputs and outputs of a hierarchical block.
function MyHierarchicalBlock:instantiate()
local b1, b2, b3 = ...
...
self:connect(b1, b2, b3)
self:connect(self, 'in', b1, 'in')
self:connect(self, 'out', b3, 'out')
end
...
: Blocks [and ports] to connectCompositeBlock:run()
Run a top-level block. This is equivalent to calling start()
followed by
wait()
on the top-level block.
-- Run a top-level block
top:run()
CompositeBlock:start()
Start a top-level block.
-- Start a top-level block
top:start()
CompositeBlock:status()
Get the status of a top-level block.
running
(bool). (table)if top:status().running then
print('Still running...')
end
CompositeBlock:stop()
Stop a top-level block and wait until it has finished.
-- Start a top-level block
top:start()
-- Stop a top-level block
top:stop()
CompositeBlock:wait()
Wait for a top-level block to finish, either by natural termination or by
SIGINT
.
-- Start a top-level block
top:start()
-- Wait for the top-level block to finish
local success = top:wait()
Source a complex-valued signal from an Airspy HF+. This source requires the libairspyhf library.
radio.AirspyHFSource(frequency, rate[, options={}])
frequency
(number): Tuning frequency in Hzrate
(number): Sample rate in Hz (192 kHz, 256 kHz, 384 kHz, 768 kHz)options
(table): Additional options, specifying:
hf_agc
(bool, default true)hf_agc_threshold
(string, default “low”, choice of “low” or “high”)hf_att
(int, 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)out
ComplexFloat32-- Source samples from 91.1 MHz sampled at 768 kHz
local src = radio.AirspyHFSource(91.1e6, 768e3)
-- Source samples from 7.150 MHz sampled at 192 kHz, with HF AGC
-- enabled (default) and HF LNA enabled
local src = radio.AirspyHFSource(7.150e6, 192e3, {hf_lna = true})
-- Source samples from 14.175 MHz sampled at 192 kHz, with HF AGC disabled
-- and 24 dB HF attenuation
local src = radio.AirspyHFSource(14.175e6, 192e3, {hf_agc = false, hf_att = 24})
Source a complex-valued signal from an Airspy. This source requires the libairspy library. The Airspy R2 and Airspy Mini dongles are supported.
radio.AirspySource(frequency, rate[, options={}])
frequency
(number): Tuning frequency in Hzrate
(number): Sample rate in Hz (3 MHz or 6 MHz for Airspy Mini,
2.5 MHz or 10 MHz for Airspy R2)options
(table): Additional options, specifying:
gain_mode
(string, default “linearity”, choice of “custom”, “linearity”, “sensitivity”)lna_gain
(int, default 5 dB, for custom gain mode, range 0 to 15 dB)mixer_gain
(int, default 1 dB, for custom gain mode, range 0 to 15 dB)vga_gain
(int, default 5 dB, for custom gain mode, range 0 to 15 dB)lna_agc
(bool, default false, for custom gain mode)mixer_agc
(bool, default false, for custom gain mode)linearity_gain
(int, default 10, for linearity gain mode, range 0 to 21)sensitivity_gain
(int, default 10, for sensitivity gain mode, range 0 to 21)biastee_enable
(bool, default false)out
ComplexFloat32-- Source samples from 135 MHz sampled at 6 MHz
local src = radio.AirspySource(135e6, 6e6)
-- Source samples from 91.1 MHz sampled at 3 MHz, with custom gain settings
local src = radio.AirspySource(91.1e6, 3e6, {gain_mode = "custom", lna_gain = 4,
mixer_gain = 1, vga_gain = 6})
-- Source samples from 91.1 MHz sampled at 2.5 MHz, with linearity gain mode
local src = radio.AirspySource(91.1e6, 2.5e6, {gain_mode = "linearity", linearity_gain = 8})
-- Source samples from 91.1 MHz sampled at 2.5 MHz, with sensitivity gain mode
local src = radio.AirspySource(91.1e6, 2.5e6, {gain_mode = "sensitivity", sensitivity_gain = 8})
-- Source samples from 144.390 MHz sampled at 2.5 MHz, with bias tee enabled
local src = radio.AirspySource(144.390e6, 2.5e6, {biastee_enable = true})
Source a complex-valued signal from a BladeRF. This source requires the libbladeRF library.
radio.BladeRFSource(frequency, rate[, options={}])
frequency
(number): Tuning frequency in Hzrate
(number): Sample rate in Hzoptions
(table): Additional options, specifying:
device_id
(string, default “”)channel
(int, default 0)gain
(number in dB, manual gain, default nil)bandwidth
(number in Hz, default 80% of sample rate)autogain
(bool, default true if manual gain is nil)out
ComplexFloat32-- Source samples from a BladeRF at 91.1 MHz sampled at 2 MHz
local src = radio.BladeRFSource(91.1e6, 2e6)
-- Source samples from a BladeRF at 915 MHz sampled at 10 MHz, with 20 dB
-- overall gain
local src = radio.BladeRFSource(915e6, 10e6, {gain = 20})
-- Source samples from a BladeRF at 144.390 MHz sampled at 8 MHz, with
-- 2.5 MHz baseband bandwidth
local src = radio.BladeRFSource(144.390e6, 8e6, {bandwidth = 2.5e6})
Source a complex-valued signal from a HackRF One. This source requires the libhackrf library.
radio.HackRFSource(frequency, rate[, options={}])
frequency
(number): Tuning frequency in Hzrate
(number): Sample rate in Hzoptions
(table): Additional options, specifying:
lna_gain
(int, default 8 dB, range 0 to 40 dB, 8 dB step)vga_gain
(int, default 40 dB, range 0 to 62 dB, 2 dB step)bandwidth
(number in Hz, default round down from sample rate)rf_amplifier_enable
(bool, default false)antenna_power_enable
(bool, default false)out
ComplexFloat32-- Source samples from 135 MHz sampled at 10 MHz
local src = radio.HackRFSource(135e6, 10e6)
-- Source samples from 135 MHz sampled at 10 MHz, with 2.5 MHz bandwidth
local src = radio.HackRFSource(135e6, 10e6, {bandwidth = 2.5e6})
-- Source samples from 91.1 MHz sampled at 8 MHz, with custom gain settings
local src = radio.HackRFSource(91.1e6, 8e6, {lna_gain = 16, vga_gain = 22})
-- Source samples from 144.390 MHz sampled at 8 MHz, with antenna power enabled
local src = radio.HackRFSource(144.390e6, 8e6, {antenna_power_enable = true})
Source a complex-valued signal from a binary “IQ” file. The file format may be 8/16/32-bit signed/unsigned integers or 32/64-bit floats, in little or big endianness, and interleaved as real component followed by imaginary component.
radio.IQFileSource(file, format, rate[, repeat_on_eof=false])
file
(string|file|int): Filename, file object, or file descriptorformat
(string): File format specifying signedness, bit width, and
endianness of samples. Choice of “s8”, “u8”, “u16le”,
“u16be”, “s16le”, “s16be”, “u32le”, “u32be”, “s32le”,
“s32be”, “f32le”, “f32be”, “f64le”, “f64be”.rate
(number): Sample rate in Hzrepeat_on_eof
(bool): Repeat on end of fileout
ComplexFloat32-- Source signed 8-bit IQ samples from a file sampled at 1 MHz
local src = radio.IQFileSource('samples.s8.iq', 's8', 1e6)
-- Source little-endian 32-bit IQ samples from a file sampled at 1 MHz, repeating on EOF
local src = radio.IQFileSource('samples.f32le.iq', 'f32le', 1e6, true)
-- Source little-endian signed 16-bit IQ samples from stdin sampled at 500 kHz
local src = radio.IQFileSource(io.stdin, 's16le', 500e3)
Source a signal from a JSON file. Samples are deserialized from individual,
newline delimited objects. This source supports any data type that
implements from_json()
.
radio.JSONSource(file, data_type, rate[, repeat_on_eof=false])
file
(string|file|int): Filename, file object, or file descriptordata_type
(type): LuaRadio data type that implements from_json()
rate
(number): Sample rate of filerepeat_on_eof
(bool): Repeat on end of fileout
data_type-- Source AX25FrameType samples sampled at 1 Hz from a file descriptor
local src = radio.JSONSource(3, radio.AX25FramerBlock.AX25FrameType, 1)
-- Source AX25FrameType samples sampled at 1 Hz from a file, repeating on EOF
local src = radio.JSONSource('data.bin', radio.AX25FramerBlock.AX25FrameType, 1, true)
Source a signal from a network client. The source supports TCP and UNIX socket transports. The samples are deserialized according to the specified signedness, bit width, and endianness format. Complex-valued signals are deinterleaved as real component followed by imaginary component. C structure types may be deserialized raw with the “raw” format. Object types may be deserialized from newline delimited JSON with the “json” format. The source can be configured to automatically reconnect (default) or terminate on connection loss.
radio.NetworkClientSource(data_type, rate, format, transport, address[, options={}])
data_type
(string): LuaRadio data typerate
(number): Sample rate of dataformat
(string): Binary format of the samples specifying signedness,
bit width, and endianness of samples, or “raw” (for
raw serialization, useful for C structure types), or
“json” (for JSON serialization, useful for Object
types). Choice of “s8”, “u8”, “u16le”, “u16be”,
“s16le”, “s16be”, “u32le”, “u32be”, “s32le”, “s32be”,
“f32le”, “f32be”, “f64le”, “f64be”, “raw”, “json”.transport
(string): Transport type. Choice of “tcp” or “unix”.address
(string): Address, as host:port for TCP, or as a file path for
UNIX.options
(table): Additional options, specifying:
reconnect
(bool, default true, reconnect on
connection loss)out
data_type-- Source ComplexFloat32 samples sampled at 1 MHz decoded from little-endian
-- 32-bit float format from a TCP client connected to 192.168.1.105:5000
local src = radio.NetworkClientSource(radio.types.ComplexFloat32, 1e6, 'f32le', 'tcp', '192.168.1.105:5000')
-- Source Float32 samples sampled at 100 kHz decoded from little-endian
-- signed 16-bit real format from a UNIX socket client connected to
-- /tmp/radio.sock
local src = radio.NetworkClientSource(radio.types.Float32, 100e3, 's16le', 'unix', '/tmp/radio.sock')
-- Source RDSFrameType samples decoded from their C structure from a TCP
-- client connected to 192.168.1.105:5000
local src = radio.NetworkClientSource(radio.RDSFramerBlock.RDSFrameType, 0, 'raw', 'tcp', '192.168.1.105:5000')
-- Source RDSPacketType samples decoded from their JSON format from a TCP
-- client connected to 192.168.1.105:5000
local src = radio.NetworkClientSource(radio.RDSDecoderBlock.RDSPacketType, 0, 'json', 'tcp', '192.168.1.105:5000')
Source a signal from a network server. The source supports TCP and UNIX socket transports. The samples are deserialized according to the specified signedness, bit width, and endianness format. Complex-valued signals are deinterleaved as real component followed by imaginary component. C structure types may be deserialized raw with the “raw” format. Object types may be deserialized from newline delimited JSON with the “json” format. The source can be configured to automatically reconnect (default) or terminate on connection loss.
radio.NetworkServerSource(data_type, rate, format, transport, address[, options={}])
data_type
(string): LuaRadio data typerate
(number): Sample rate of dataformat
(string): Binary format of the samples specifying signedness,
bit width, and endianness of samples, or “raw” (for
raw serialization, useful for C structure types), or
“json” (for JSON serialization, useful for Object
types). Choice of “s8”, “u8”, “u16le”, “u16be”,
“s16le”, “s16be”, “u32le”, “u32be”, “s32le”, “s32be”,
“f32le”, “f32be”, “f64le”, “f64be”, “raw”, “json”.transport
(string): Transport type. Choice of “tcp” or “unix”.address
(string): Address, as host:port for TCP, or as a file path for
UNIX.options
(table): Additional options, specifying:
reconnect
(bool, default true, reconnect on
connection loss)out
data_type-- Source ComplexFloat32 samples sampled at 1 MHz decoded from little-endian
-- 32-bit float format from a TCP server listening on 0.0.0.0:5000
local src = radio.NetworkServerSource(radio.types.ComplexFloat32, 1e6, 'f32le', 'tcp', '0.0.0.0:5000')
-- Source Float32 samples sampled at 100 kHz decoded from little-endian
-- signed 16-bit real format from a UNIX socket server listening on
-- /tmp/radio.sock
local src = radio.NetworkServerSource(radio.types.Float32, 100e3, 's16le', 'unix', '/tmp/radio.sock')
-- Source RDSFrameType samples decoded from their C structure from a TCP
-- server listening on 0.0.0.0:5000
local src = radio.NetworkServerSource(radio.RDSFramerBlock.RDSFrameType, 0, 'raw', 'tcp', '0.0.0.0:5000')
-- Source RDSPacketType samples decoded from their JSON format from a TCP
-- server listening on 0.0.0.0:5000
local src = radio.NetworkServerSource(radio.RDSDecoderBlock.RDSPacketType, 0, 'json', 'tcp', '0.0.0.0:5000')
Source one or more real-valued signals from the system’s audio device with PortAudio. This source requires PortAudio.
radio.PortAudioSource(num_channels, rate)
num_channels
(int): Number of channels (e.g. 1 for mono, 2 for stereo)rate
(int): Sample rate in Hzout
Float32out1
Float32, out2
Float32, ...
-- Source one channel (mono) audio sampled at 44100 Hz
local src = radio.PortAudioSource(1, 44100)
-- Source two channel (stereo) audio sampled at 48000 Hz
local src = radio.PortAudioSource(2, 48000)
-- Compose the two channels into a complex-valued signal
local floattocomplex = radio.FloatToComplex()
top:connect(src, 'out1', floattocomplex, 'real')
top:connect(src, 'out2', floattocomplex, 'imag')
top:connect(floattocomplex, ...)
Source one or more real-valued signals from the system’s audio device with PulseAudio. This source requires PulseAudio.
radio.PulseAudioSource(num_channels, rate)
num_channels
(int): Number of channels (e.g. 1 for mono, 2 for stereo)rate
(int): Sample rate in Hzout
Float32out1
Float32, out2
Float32, ...
-- Source one channel (mono) audio sampled at 44100 Hz
local src = radio.PulseAudioSource(1, 44100)
-- Source two channel (stereo) audio sampled at 48000 Hz
local src = radio.PulseAudioSource(2, 48000)
-- Compose the two channels into a complex-valued signal
local floattocomplex = radio.FloatToComplex()
top:connect(src, 'out1', floattocomplex, 'real')
top:connect(src, 'out2', floattocomplex, 'imag')
top:connect(floattocomplex, ...)
Source a signal of the specified data type from a binary file. The raw binary samples are cast to the specified data type with no signedness conversion, endian conversion, or interpretation. This is useful for serializing data types across a pipe or other file descriptor based IPC.
radio.RawFileSource(file, data_type, rate[, repeat_on_eof=false])
file
(string|file|int): Filename, file object, or file descriptordata_type
(type): LuaRadio data typerate
(number): Sample rate of filerepeat_on_eof
(bool): Repeat on end of fileout
data_type-- Source ComplexFloat32 samples sampled at 1 MHz from a file descriptor
local src = radio.RawFileSource(3, radio.types.ComplexFloat32, 1e6)
-- Source Byte samples sampled at 100 kHz from a file, repeating on EOF
local src = radio.RawFileSource('data.bin', radio.types.Byte, 100e3, true)
Source a real-valued signal from a binary file. The file format may be
8/16/32-bit signed/unsigned integers or 32/64-bit floats, in little or big
endianness. This is the real-valued counterpart of
IQFileSource
.
radio.RealFileSource(file, format, rate[, repeat_on_eof=false])
file
(string|file|int): Filename, file object, or file descriptorformat
(string): File format specifying signedness, bit width, and
endianness of samples. Choice of “s8”, “u8”, “u16le”,
“u16be”, “s16le”, “s16be”, “u32le”, “u32be”, “s32le”,
“s32be”, “f32le”, “f32be”, “f64le”, “f64be”.rate
(number): Sample rate in Hzrepeat_on_eof
(bool): Repeat on end of fileout
Float32-- Source signed 8-bit real samples from a file sampled at 1 MHz
local src = radio.RealFileSource('samples.s8.real', 's8', 1e6)
-- Source little-endian 32-bit real samples from a file sampled at 1 MHz, repeating on EOF
local src = radio.RealFileSource('samples.f32le.real', 'f32le', 1e6, true)
-- Source little-endian signed 16-bit real samples from stdin sampled at 500 kHz
local src = radio.RealFileSource(0, 's16le', 500e3)
Source a complex-valued signal from an RTL-SDR dongle. This source requires the librtlsdr library.
radio.RtlSdrSource(frequency, rate[, options={}])
frequency
(number): Tuning frequency in Hzrate
(number): Sample rate in Hzoptions
(table): Additional options, specifying:
biastee
(bool, default false)direct_sampling
(string, default “disabled”, choice of “disabled”, “i”, “q”)bandwidth
(number, default equal to sample rate)autogain
(bool, default true if manual gain is nil)rf_gain
(number in dB, manual gain, default nil)freq_correction
PPM (number, default 0.0)device_index
(integer, default 0)out
ComplexFloat32-- Source samples from 162.400 MHz sampled at 1 MHz, with autogain enabled
local src = radio.RtlSdrSource(162.400e6, 1e6, {autogain = true})
-- Source samples from 91.1 MHz sampled at 1.102500 MHz, with -1 PPM correction
local src = radio.RtlSdrSource(91.1e6, 1102500, {freq_correction = -1.0})
-- Source samples from 144.390 MHz sampled at 1 MHz, with RF gain of 15dB
local src = radio.RtlSdrSource(144.390e6, 1e6, {rf_gain = 15.0})
Source a complex-valued signal from an SDRplay RSP (1, 1A, 2, Duo, or Dx). This source requires the libsdrplay_api or libmirsdrapi-rsp library.
radio.SDRplaySource(frequency, rate[, options={}])
frequency
(number): Tuning frequency in Hzrate
(number): Sample rate in Hzoptions
(table): Additional options, specifying:
gain_reduction
(int, default 40 dB, range of 20 to 59 dB)bandwidth
(number, default closest, choice of 0.200 MHz, 0.300 MHz,
0.600 MHz, 1.536 MHz, 5.000 MHz, 6.000 MHz, 7.000 MHz, 8.000 MHz)out
ComplexFloat32-- Source samples from 91.1 MHz sampled at 2 MHz
local src = radio.SDRplaySource(91.1e6, 2e6)
-- Source samples from 144.390 MHz sampled at 4 MHz, with 0.6 MHz bandwidth
local src = radio.SDRplaySource(144.390e6, 4e6, {bandwidth = 0.6e6})
-- Source samples from 15 MHz sampled at 10 MHz, with 30 dB gain reduction
local src = radio.SDRplaySource(15e6, 10e6, {gain_reduction = 30})
Source a complex or real valued signal from a signal generator.
Note: the “exponential” waveform generates a complex-valued signal, all other waveform types generate a real-valued signal.
radio.SignalSource(signal, frequency, rate[, options={}])
signal
(string): Waveform type, either “exponential”, “cosine”, “sine”,
“square”, “triangle”, “sawtooth”, “constant”.frequency
(number): Frequency in Hzrate
(number|nil): Sample rate in Hzoptions
(table): Additional options, specifying:
amplitude
(number, default 1.0)offset
(number, default 0.0)phase
(number in radians, default 0.0)out
ComplexFloat32out
Float32-- Source a 250 kHz complex exponential sampled at 2 MHz
local src = radio.SignalSource('exponential', 250e3, 2e6)
-- Source a 100 kHz cosine sampled at 1 MHz, with amplitude 2.5
local src = radio.SignalSource('cosine', 100e3, 1e6, {amplitude = 2.5})
-- Source a 1 kHz square wave sampled at 2 MHz, with offset 1.0
local src = radio.SignalSource('square', 1e3, 2e6, {offset = 1.0})
Source a complex-valued signal from a SoapySDR device. This source requires SoapySDR.
radio.SoapySDRSource(driver, frequency, rate[, options={}])
driver
(string|table): Driver string or key-value tablefrequency
(number): Tuning frequency in Hzrate
(number): Sample rate in Hzoptions
(table): Additional options, specifying:
channel
(int, default 0)bandwidth
(number in Hz)autogain
(bool)antenna
(string)gain
(number in dB, overall gain)gains
(table, gain element name to value in dB)frequencies
(table, frequency element name to value in Hz)settings
(table, string key-value pairs of driver-specific settings)out
ComplexFloat32-- Source samples from an RTL-SDR at 91.1 MHz sampled at 1 MHz
local src = radio.SoapySDRSource("driver=rtlsdr", 91.1e6, 1e6)
-- Source samples from an Airspy at 15 MHz sampled at 6 MHz, with 10 dB overall gain
local src = radio.SoapySDRSource("driver=airspy", 15e6, 6e6, {gain = 10})
-- Source samples from a LimeSDR at 915 MHz sampled at 10 MHz,
-- with 20 dB overall gain and 4 MHz baseband bandwidth
local src = radio.SoapySDRSource("driver=limesdr", 915e6, 10e6, {gain = 20, bandwidth = 4e6})
-- Source samples from a HackRF at 144.390 MHz sampled at 8 MHz,
-- with 2.5 MHz baseband bandwidth
local src = radio.SoapySDRSource("driver=hackrf", 144.390e6, 8e6, {bandwidth = 2.5e6})
Source a complex-valued signal from a USRP. This source requires the libuhd library.
radio.UHDSource(device_address, frequency, rate[, options={}])
device_address
(string): Device address stringfrequency
(number): Tuning frequency in Hzrate
(number): Sample rate in Hzoptions
(table): Additional options, specifying:
channel
(int, default 0)gain
(number in dB, manual overall gain, default nil)bandwidth
(number in Hz)antenna
(string)autogain
(bool, default true if manual gain is nil)gains
(table, gain element name to value in dB)out
ComplexFloat32-- Source samples from a B200 at 91.1 MHz sampled at 2 MHz
local src = radio.UHDSource("type=b200", 91.1e6, 2e6)
-- Source samples from a B200 at 915 MHz sampled at 10 MHz, with 20 dB
-- overall gain
local src = radio.UHDSource("type=b200", 915e6, 10e6, {gain = 20})
-- Source samples from a B200 at 144.390 MHz sampled at 8 MHz, with 2.5 MHz
-- baseband bandwidth
local src = radio.UHDSource("type=b200", 144.390e6, 8e6, {bandwidth = 2.5e6})
Source a signal with values drawn from a uniform random distribution.
radio.UniformRandomSource(data_type, rate[, range={}, options={}])
data_type
(type): LuaRadio data type, choice of
radio.types.ComplexFloat32
, radio.types.Float32
,
radio.types.Byte
, or radio.types.Bit
data types.rate
(number): Sample rate in Hzrange
(array): Value range as an array, e.g {10, 100}
.options
(table): Additional options, specifying:
seed
(number)out
ComplexFloat32out
Float32out
Byteout
Bit-- Source a random ComplexFloat32 signal sampled at 1 MHz
local src = radio.UniformRandomSource(radio.types.ComplexFloat32, 1e6)
-- Source a random Float32 signal sampled at 1 MHz
local src = radio.UniformRandomSource(radio.types.Float32, 1e6)
-- Source a random Byte signal sampled at 1 kHz, ranging from 65 to 90
local src = radio.UniformRandomSource(radio.types.Byte, 1e3, {65, 90})
-- Source a random bit stream sampled at 1 kHz
local src = radio.UniformRandomSource(radio.types.Bit, 1e3)
Source one or more real-valued signals from a WAV file. The supported sample formats are 8-bit unsigned integer, 16-bit signed integer, and 32-bit signed integer.
radio.WAVFileSource(file, num_channels[, repeat_on_eof=false])
file
(string|file|int): Filename, file object, or file descriptornum_channels
(int): Number of channels (e.g. 1 for mono, 2 for stereo, etc.)repeat_on_eof
(bool): Repeat on end of fileout
Float32out1
Float32, out2
Float32, ...
-- Source one channel WAV file
local src = radio.WAVFileSource('test.wav', 1)
-- Source two channel WAV file
local src = radio.WAVFileSource('test.wav', 2)
-- Compose the two channels into a complex-valued signal
top:connect(src, 'out1', floattocomplex, 'real')
top:connect(src, 'out2', floattocomplex, 'imag')
top:connect(floattocomplex, ..., snk)
Source a zero-valued signal of the specified data type.
radio.ZeroSource(data_type, rate)
data_type
(type): LuaRadio data typerate
(number): Sample rate in Hzout
data_type-- Source a zero complex-valued signal sampled at 1 MHz
local src = radio.ZeroSource(radio.types.ComplexFloat32, 1e6)
-- Source a zero real-valued signal sampled at 500 kHz
local src = radio.ZeroSource(radio.types.Bit, 500e3)
-- Source a zero bit stream sampled at 2 kHz
local src = radio.ZeroSource(radio.types.Bit, 2e3)
Report the average rate of samples delivered to the sink.
[BenchmarkSink] 314.38 MS/s (2.52 GB/s)
[BenchmarkSink] 313.32 MS/s (2.51 GB/s)
[BenchmarkSink] 313.83 MS/s (2.51 GB/s)
...
radio.BenchmarkSink([file=io.stderr, use_json=false, title="BenchmarkSink"])
file
(string|file|int): Filename, file object, or file descriptoruse_json
(bool): Serialize aggregate results in JSON on terminationtitle
(string): Title in reportingin
any ➔❑-- Benchmark a source, writing periodic results to stderr
local snk = radio.BenchmarkSink()
top:connect(src, snk)
-- Benchmark a source and a block, writing final results in JSON to fd 3
local snk = radio.BenchmarkSink(3, true)
top:connect(src, blk, snk)
Sink a complex-valued signal to a BladeRF. This sink requires the libbladeRF library.
radio.BladeRFSink(frequency[, options={}])
frequency
(number): Tuning frequency in Hzoptions
(table): Additional options, specifying:
device_id
(string, default “”)channel
(int, default 0)gain
(number in dB, manual gain, default nil)bandwidth
(number in Hz, default 80% of sample rate)autogain
(bool, default true if manual gain is nil)in
ComplexFloat32 ➔❑-- Sink samples to a BladeRF at 433.92 MHz
local snk = radio.BladeRFSink(433.92e6)
-- Sink samples to a BladeRF at 915 MHz, with 10 dB overall gain and 5 MHz baseband bandwidth
local snk = radio.BladeRFSink(915e6, {gain = 10, bandwidth = 5e6})
Plot a real-valued signal in a gnuplot time plot. This sink requires the gnuplot program. This sink should be used with relatively low sample rates, as it does not skip any samples, or it may otherwise throttle a flow graph.
radio.GnuplotPlotSink(num_samples[, title="", options={}])
num_samples
(int): Number of samples to plottitle
(string): Title of plotoptions
(table): Additional options, specifying:
xlabel
(string, default “Sample Number”)ylabel
(string, default “Value”)yrange
(array of two numbers, default nil
for autoscale)extra_settings
(array of strings containing
gnuplot commands)in
Float32 ➔❑-- Plot a 1 kHz cosine sampled at 250 kHz
local src = radio.SignalSource('cosine', 1e3, 250e3)
local throttle = radio.ThrottleBlock()
local snk = radio.GnuplotPlotSink(1000, 'Cosine')
top:connect(src, throttle, snk)
Plot the power spectrum of a complex or real-valued signal. This sink requires the gnuplot program. The power spectral density is estimated with Bartlett’s or Welch’s method of averaging periodograms.
radio.GnuplotSpectrumSink([num_samples=1024, title="", options={}])
num_samples
(int): Number of samples in periodogramtitle
(string): Title of plotoptions
(table): Additional options, specifying:
update_time
(number, default 0.10 seconds)overlap
fraction (number from 0.0 to 1.0,
default 0.0)reference_level
(number, default 0.0 dB)window
(string, default “hamming”)onesided
(bool, default true)xrange
(array of two numbers, default nil
for autoscale)yrange
(array of two numbers, default nil
for autoscale)extra_settings
(array of strings containing
gnuplot commands)in
ComplexFloat32 ➔❑in
Float32 ➔❑-- Plot the spectrum of a 1 kHz complex exponential sampled at 250 kHz
local src = radio.SignalSource('exponential', 1e3, 250e3)
local throttle = radio.ThrottleBlock()
local snk = radio.GnuplotSpectrumSink()
top:connect(src, throttle, snk)
Plot the vertical power spectrogram (waterfall) of a complex or real-valued signal. This sink requires the gnuplot program. The power spectral density is estimated with Bartlett’s or Welch’s method of averaging periodograms.
Note: this sink’s performance is currently limited and should only be used with very low sample rates, or it may otherwise throttle a flow graph.
radio.GnuplotWaterfallSink([num_samples=1024, title="", options={}])
num_samples
(int): Number of samples in periodogramtitle
(string): Title of plotoptions
(table): Additional options, specifying:
update_time
(number, default 0.10 seconds)overlap
fraction (number from 0.0 to 1.0,
default 0.0)height
in rows (number, default 64)min_magnitude
(number, default -150.0 dB)max_magnitude
(number, default 0.0 dB)window
(string, default “hamming”)onesided
(boolean, default true)xrange
(array of two numbers, default nil
for autoscale)yrange
(array of two numbers, default nil
for autoscale)extra_settings
(array of strings containing
gnuplot commands)in
ComplexFloat32 ➔❑in
Float32 ➔❑-- Plot the waterfall of a 1 kHz complex exponential sampled at 250 kHz
local src = radio.SignalSource('exponential', 1e3, 250e3)
local throttle = radio.ThrottleBlock()
local snk = radio.GnuplotWaterfallSink()
top:connect(src, throttle, snk)
Plot two real-valued signals, or the real and imaginary components of one complex-valued signal, in a gnuplot XY plot. This sink requires the gnuplot program. This sink should be used with relatively low sample rates, as it does not skip any samples, or it may otherwise throttle a flow graph.
radio.GnuplotXYPlotSink(num_samples[, title="", options={}])
num_samples
(int): Number of samples to plottitle
(string): Title of plotoptions
(table): Additional options, specifying:
complex
(bool, default false)xlabel
(string, default “”)ylabel
(string, default “”)xrange
(array of two numbers, default nil
for autoscale)yrange
(array of two numbers, default nil
for autoscale)extra_settings
(array of strings containing
gnuplot commands)x
Float32, y
Float32 ➔❑in
ComplexFloat32 ➔❑-- Plot a 1 kHz complex exponential sampled at 250 kHz
local src = radio.SignalSource('exponential', 1e3, 250e3)
local throttle = radio.ThrottleBlock()
local snk = radio.GnuplotXYPlotSink(1000, 'Complex Exponential', {complex = true})
top:connect(src, throttle, snk)
-- Plot two real-valued signals
local snk = radio.GnuplotXYPlotSink(1000, 'XY')
top:connect(src1, 'out', snk, 'x')
top:connect(src2, 'out', snk, 'y')
Sink a complex-valued signal to a HackRF One. This sink requires the libhackrf library.
radio.HackRFSink(frequency[, options={}])
frequency
(number): Tuning frequency in Hzoptions
(table): Additional options, specifying:
vga_gain
(int in dB, default 0 dB, range 0 to 47 dB, 1 dB step)bandwidth
(number in Hz, default round down from sample rate)rf_amplifier_enable
(bool, default false)antenna_power_enable
(bool, default false)in
ComplexFloat32 ➔❑-- Sink samples to 146 MHz
local snk = radio.HackRFSink(146e6)
-- Sink samples to 433.92 MHz, with 1.75 MHz baseband bandwidth
local src = radio.HackRFSink(433.92e6, {bandwidth = 1.75e6})
-- Sink samples to 915 MHz, with 22 dB VGA gain
local src = radio.HackRFSink(915e6, {vga_gain = 22})
-- Sink samples to 144.390 MHz, with antenna power enabled
local src = radio.HackRFSink(144.390e6, {antenna_power_enable = true})
Sink a complex-valued signal to a binary “IQ” file. The file format may be 8/16/32-bit signed/unsigned integers or 32/64-bit floats, in little or big endianness, and will be interleaved as real component followed by imaginary component.
radio.IQFileSink(file, format)
file
(string|file|int): Filename, file object, or file descriptorformat
(string): File format specifying signedness, bit width, and
endianness of samples. Choice of “s8”, “u8”, “u16le”,
“u16be”, “s16le”, “s16be”, “u32le”, “u32be”, “s32le”,
“s32be”, “f32le”, “f32be”, “f64le”, “f64be”.in
ComplexFloat32 ➔❑-- Sink signed 8-bit IQ samples to a file
local snk = radio.IQFileSink('samples.s8.iq', 's8')
-- Sink little-endian 32-bit IQ samples to a file
local snk = radio.IQFileSink('samples.f32le.iq', 'f32le')
-- Sink little-endian signed 16-bit IQ samples to stdout
local snk = radio.IQFileSink(1, 's16le')
Sink a signal to a file, serialized in JSON. Samples are serialized
individually and newline delimited. This sink accepts any data type that
implements to_json()
.
radio.JSONSink([file=io.stdout])
file
(string|file|int): Filename, file object, or file descriptorin
supported ➔❑-- Sink JSON serialized samples to stdout
local snk = radio.JSONSink()
top:connect(src, snk)
-- Sink JSON serialized samples to a file
local snk = radio.JSONSink('out.json')
top:connect(src, snk)
Sink a signal to a network client. The sink supports TCP and UNIX socket transports. The samples are serialized according to the specified signedness, bit width, and endianness format. Complex-valued signals are interleaved as real component followed by imaginary component. C structure types are serialized raw with the “raw” format. Object types are serialized as newline delimited JSON with the “json” format. The sink will automatically reconnect on connection loss.
radio.NetworkClientSink(format, transport, address[, options={}])
format
(string): Binary format of the samples specifying signedness,
bit width, and endianness of samples, or “raw” (for
raw serialization, useful for C structure types), or
“json” (for JSON serialization, useful for Object
types). Choice of “s8”, “u8”, “u16le”, “u16be”,
“s16le”, “s16be”, “u32le”, “u32be”, “s32le”, “s32be”,
“f32le”, “f32be”, “f64le”, “f64be”, “raw”, “json”.transport
(string): Transport type. Choice of “tcp” or “unix”.address
(string): Address, as host:port for TCP, or as a file path for
UNIX.options
(table): Additional options, specifying:
backpressure
(bool, default false, backpressure
samples on connection loss)in
ComplexFloat32 ➔❑in
Float32 ➔❑in
supported ➔❑-- Sink ComplexFloat32 samples encoded as little-endian 32-bit float IQ to a
-- TCP client connected to 192.168.1.105:5000
local snk = radio.NetworkClientSink('f32le', 'tcp', '192.168.1.105:5000')
-- Sink Float32 samples encoded as little-endian 16-bit real to a UNIX
-- socket client connected to /tmp/radio.sock
local snk = radio.NetworkClientSink('s16le', 'unix', '/tmp/radio.sock')
-- Sink C structure type samples to a TCP client connected to
-- 192.168.1.105:5000
local snk = radio.NetworkClientSink('raw', 'tcp', '192.168.1.105:5000')
-- Sink a JSON serialized objects to a TCP client connected to
-- 192.168.1.105:5000
local snk = radio.NetworkClientSink('json', 'tcp', '192.168.1.105:5000')
Sink a signal to a network server. The sink supports TCP and UNIX socket transports. The samples are serialized according to the specified signedness, bit width, and endianness format. Complex-valued signals are interleaved as real component followed by imaginary component. C structure types are serialized raw with the “raw” format. Object types are serialized as newline delimited JSON with the “json” format. The sink will automatically reconnect on connection loss.
radio.NetworkServerSink(format, transport, address[, options={}])
format
(string): Binary format of the samples specifying signedness,
bit width, and endianness of samples, or “raw” (for
raw serialization, useful for C structure types), or
“json” (for JSON serialization, useful for Object
types). Choice of “s8”, “u8”, “u16le”, “u16be”,
“s16le”, “s16be”, “u32le”, “u32be”, “s32le”, “s32be”,
“f32le”, “f32be”, “f64le”, “f64be”, “raw”, “json”.transport
(string): Transport type. Choice of “tcp” or “unix”.address
(string): Address, as host:port for TCP, or as a file path for
UNIX.options
(table): Additional options, specifying:
backpressure
(bool, default false, backpressure
samples on connection loss)in
ComplexFloat32 ➔❑in
Float32 ➔❑in
supported ➔❑-- Sink ComplexFloat32 samples encoded as little-endian 32-bit float IQ to a
-- TCP server listening on 0.0.0.0:5000
local snk = radio.NetworkServerSink('f32le', 'tcp', '0.0.0.0:5000')
-- Sink Float32 samples encoded as little-endian 16-bit real to a UNIX
-- socket server listening on /tmp/radio.sock
local snk = radio.NetworkServerSink('s16le', 'unix', '/tmp/radio.sock')
-- Sink C structure type samples to a TCP server listening on 0.0.0.0:5000
local snk = radio.NetworkServerSink('raw', 'tcp', '0.0.0.0:5000')
-- Sink JSON serialized objects to a TCP server listening on 0.0.0.0:5000
local snk = radio.NetworkServerSink('json', 'tcp', '0.0.0.0:5000')
Sink a signal and do nothing. This sink accepts any data type.
radio.NopSink()
in
any ➔❑local snk = radio.NopSink()
top:connect(src, snk)
Sink one or more real-valued signals to the system’s audio device with PortAudio. This sink requires the PortAudio library.
radio.PortAudioSink(num_channels)
num_channels
(int): Number of channels (e.g. 1 for mono, 2 for stereo)in
Float32 ➔❑in1
Float32, in2
Float32, ...
➔❑-- Sink to one channel (mono) audio
local snk = radio.PortAudioSink(1)
top:connect(src, snk)
-- Sink to two channel (stereo) audio
local snk = radio.PortAudioSink(2)
top:connect(src_left, 'out', snk, 'in1')
top:connect(src_right, 'out', snk, 'in2')
Sink a signal to a file, formatted as a string. Samples are formatted
individually and newline delimited. This sink accepts any data type that
implements __tostring()
.
radio.PrintSink([file=io.stdout, options={}])
file
(string|file|int): Filename, file object, or file descriptoroptions
(table): Additional options, specifying:
title
(string, default nil)timestamp
(bool, default false)in
supported ➔❑-- Sink string formatted samples to stdout
local snk = radio.PrintSink()
top:connect(src, snk)
Sink one or more real-valued signals to the system’s audio device with PulseAudio. This sink requires PulseAudio.
radio.PulseAudioSink(num_channels)
num_channels
(int): Number of channels (e.g. 1 for mono, 2 for stereo)in
Float32 ➔❑in1
Float32, in2
Float32, ...
➔❑-- Sink to one channel (mono) audio
local snk = radio.PulseAudioSink(1)
top:connect(src, snk)
-- Sink to two channel (stereo) audio
local snk = radio.PulseAudioSink(2)
top:connect(src_left, 'out', snk, 'in1')
top:connect(src_right, 'out', snk, 'in2')
Sink a signal to a binary file. The samples are serialized raw, in their native binary representation, with no signedness conversion, endian conversion, or interpretation. This is useful for serializing data types across a pipe or other file descriptor based IPC.
radio.RawFileSink(file)
file
(string|file|int): Filename, file object, or file descriptorin
any ➔❑-- Sink raw samples to a file
local snk = radio.RawFileSink('samples.raw')
top:connect(src, snk)
-- Sink raw samples to file descriptor 3
local snk = radio.RawFileSink(3)
top:connect(src, snk)
Sink a real-valued signal to a binary file. The file format may be
8/16/32-bit signed/unsigned integers or 32/64-bit floats, in little or big
endianness. This is the real-valued counterpart of
IQFileSink
.
radio.RealFileSink(file, format)
file
(string|file|int): Filename, file object, or file descriptorformat
(string): File format specifying signedness, bit width, and
endianness of samples. Choice of “s8”, “u8”, “u16le”,
“u16be”, “s16le”, “s16be”, “u32le”, “u32be”, “s32le”,
“s32be”, “f32le”, “f32be”, “f64le”, “f64be”.in
Float32 ➔❑-- Sink signed 8-bit real samples to a file
local snk = radio.RealFileSink('samples.s8.real', 's8')
-- Sink little-endian 32-bit real samples to a file
local snk = radio.RealFileSink('samples.f32le.real', 'f32le', 1e6, true)
-- Sink little-endian signed 16-bit real samples to stdout
local snk = radio.RealFileSink(1, 's16le')
Sink a complex-valued signal to a SoapySDR device. This sink requires SoapySDR.
radio.SoapySDRSink(driver, frequency[, options={}])
driver
(string|table): Driver string or key-value tablefrequency
(number): Tuning frequency in Hzoptions
(table): Additional options, specifying:
channel
(int, default 0)bandwidth
(number in Hz)autogain
(bool)antenna
(string)gain
(number in dB, overall gain)gains
(table, gain element name to value in dB)frequencies
(table, frequency element name to value in Hz)settings
(table, string key-value pairs of driver-specific settings)in
ComplexFloat32 ➔❑-- Sink samples to a HackRF at 433.92 MHz
local snk = radio.SoapySDRSink("driver=hackrf", 433.92e6)
-- Sink samples to a LimeSDR at 915 MHz, with 10 dB overall gain and 5 MHz baseband bandwidth
local snk = radio.SoapySDRSink("driver=limesdr", 915e6, {gain = 10, bandwidth = 5e6})
Sink a complex-valued signal to a USRP. This sink requires the libuhd library.
radio.UHDSink(device_address, frequency[, options={}])
device_address
(string): Device address stringfrequency
(number): Tuning frequency in Hzoptions
(table): Additional options, specifying:
channel
(int, default 0)gain
(number in dB, overall gain, default 0.0 dB)bandwidth
(number in Hz)antenna
(string)gains
(table, gain element name to value in dB)in
ComplexFloat32 ➔❑-- Sink samples to a B200 at 433.92 MHz
local snk = radio.UHDSink("type=b200", 433.92e6)
-- Sink samples to a B200 at 915 MHz, with 10 dB overall gain and 5 MHz baseband bandwidth
local snk = radio.UHDSink("type=b200", 915e6, {gain = 10, bandwidth = 5e6})
Sink one or more real-valued signals to a WAV file. The supported sample formats are 8-bit unsigned integer, 16-bit signed integer, and 32-bit signed integer.
radio.WAVFileSink(file, num_channels[, bits_per_sample=16])
file
(string|file|int): Filename, file object, or file descriptornum_channels
(int): Number of channels (e.g. 1 for mono, 2 for stereo, etc.)bits_per_sample
(int): Bits per sample, choice of 8, 16, or 32in
Float32 ➔❑in1
Float32, in2
Float32, ...
➔❑-- Sink to a one channel WAV file
local snk = radio.WAVFileSink('test.wav', 1)
top:connect(src, snk)
-- Sink to a two channel WAV file
local snk = radio.WAVFileSink('test.wav', 2)
top:connect(src1, 'out', snk, 'in1')
top:connect(src2, 'out', snk, 'in2')
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.BandpassFilterBlock(num_taps, cutoffs[, nyquist=nil, window='hamming'])
num_taps
(int): Number of FIR taps, must be oddcutoffs
({number,number}): Cutoff frequencies in Hznyquist
(number): Nyquist frequency, if specifying
normalized cutoff frequencieswindow
(string): Window typein
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Bandpass filter, 128 taps, 18 kHz to 20 kHz
local bpf = radio.BandpassFilterBlock(128, {18e3, 20e3})
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.BandstopFilterBlock(num_taps, cutoffs[, nyquist=nil, window='hamming'])
num_taps
(int): Number of FIR taps, must be oddcutoffs
({number,number}): Cutoff frequencies in Hznyquist
(number): Nyquist frequency, if specifying
normalized cutoff frequencieswindow
(string): Window typein
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Bandstop filter, 128 taps, 18 kHz to 20 kHz
local bpf = radio.BandstopFilterBlock(128, {18e3, 20e3})
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.ComplexBandpassFilterBlock(num_taps, cutoffs[, nyquist=nil, window='hamming'])
num_taps
(int): Number of FIR taps, must be oddcutoffs
({number,number}): Cutoff frequencies in Hznyquist
(number): Nyquist frequency, if specifying
normalized cutoff frequencieswindow
(string): Window typein
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Complex bandpass filter, 128 taps, 18 kHz to 20 kHz
local bpf1 = radio.BandpassFilterBlock(128, {18e3, 20e3})
-- Complex bandpass filter, 128 taps, -18 kHz to -20 kHz
local bpf2 = radio.BandpassFilterBlock(128, {-18e3, -20e3})
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.ComplexBandstopFilterBlock(num_taps, cutoffs[, nyquist=nil, window='hamming'])
num_taps
(int): Number of FIR taps, must be oddcutoffs
({number,number}): Cutoff frequencies in Hznyquist
(number): Nyquist frequency, if specifying
normalized cutoff frequencieswindow
(string): Window typein
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Complex bandstop filter, 128 taps, 18 kHz to 20 kHz
local bpf1 = radio.BandstopFilterBlock(128, {18e3, 20e3})
-- Complex bandstop filter, 128 taps, -18 kHz to -20 kHz
local bpf2 = radio.BandstopFilterBlock(128, {-18e3, -20e3})
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.FIRFilterBlock(taps[, use_fft=true])
taps
(array|vector): Real-valued taps specified with a number array or
a Float32 vector, or complex-valued taps specified
with a ComplexFloat32 vectoruse_fft
(bool): Use FFT overlap-save convolution. Defaults to true
when acceleration is available and taps length is
greater than 16in
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Moving average FIR filter with 5 real taps
local filter = radio.FIRFilterBlock({1/5, 1/5, 1/5, 1/5, 1/5})
-- Moving average FIR filter with 5 real taps
local taps = radio.types.Float32.vector({1/5, 1/5, 1/5, 1/5, 1/5})
local filter = radio.FIRFilterBlock(taps)
-- FIR filter with 3 complex taps
local taps = radio.types.ComplexFloat32.vector({{1, 1}, {0.5, 0.5}, {0.25, 0.25}})
local filter = radio.FIRFilterBlock(taps)
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.FMDeemphasisFilterBlock(tau)
tau
(number): Time constant of filterin
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- FM de-emphasis filter with 75uS time constant for the Americas
local fmdeemph = radio.FMDeemphasisFilterBlock(75e-6)
Filter a complex or real valued signal with an FM Pre-emphasis filter, a single-pole high-pass IIR filter.
\[y[n] = (x * h_{fmpreemph})[n]\]radio.FMPreemphasisFilterBlock(tau)
tau
(number): Time constant of filterin
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- FM pre-emphasis filter with 75uS time constant for the Americas
local fmpreemph = radio.FMPreemphasisFilterBlock(75e-6)
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.HighpassFilterBlock(num_taps, cutoff[, nyquist=nil, window='hamming'])
num_taps
(int): Number of FIR taps, must be oddcutoff
(number): Cutoff frequency in Hznyquist
(number): Nyquist frequency, if specifying a
normalized cutoff frequencywindow
(string): Window typein
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Highpass filter, 128 taps, 18 kHz
local hpf = radio.HighpassFilterBlock(128, 18e3)
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.IIRFilterBlock(b_taps, a_taps)
b_taps
(array|vector): Real-valued feedforward taps specified with a
number array or a Float32 vectora_taps
(array|vector): Real-valued feedback taps specified with a
number array or a Float32 vector, must be at
least length 1in
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- 2nd order Butterworth IIR filter, Wn=0.1
local filter = radio.IIRFilterBlock({0.02008337, 0.04016673, 0.02008337},
{1, -1.56101808, 0.64135154})
-- 2nd order Butterworth IIR filter, Wn=0.1
local b_taps = radio.types.Float32.vector_from_array({0.02008337, 0.04016673, 0.02008337})
local a_taps = radio.types.Float32.vector_from_array({1, -1.56101808, 0.64135154})
local filter = radio.IIRFilterBlock(b_taps, a_taps)
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.LowpassFilterBlock(num_taps, cutoff[, nyquist=nil, window='hamming'])
num_taps
(int): Number of FIR tapscutoff
(number): Cutoff frequency in Hznyquist
(number): Nyquist frequency, if specifying a
normalized cutoff frequencywindow
(string): Window typein
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Lowpass filter, 128 taps, 18 kHz
local lpf = radio.LowpassFilterBlock(128, 18e3)
Correlate a real valued signal with a matched filter of a 1 to 0 pulse transition. The resulting signal will have positive peaks at 1 to 0 transitions and negative peaks at 0 to 1 transitions, representing Manchester coded one and zero data bits, respectively.
\[y[n] = (x * h_{mf})[n]\] \[h_{-mf}[n] = \begin{cases} +1 & 0 \le n \lt T \\ -1 & T \le n \lt 2T \end{cases}\]radio.ManchesterMatchedFilterBlock(baudrate[, invert=false])
baudrate
(number): Baudrate of coded symbols in Hzinvert
(bool): Invert matched filterin
Float32 ➔❑➔ out
Float32-- Manchester coded matched filter with 32768 baudrate
local matched_filter = radio.ManchesterMatchedFilterBlock(32768)
Correlate a real valued signal with a matched filter of a pulse width of the specified symbol rate. The resulting signal will have positive peaks at positive pulses and negative peaks at negative pulses.
\[y[n] = (x * h_{mf})[n]\] \[h_{-mf}[n] = \begin{cases} 1 & 0 \le n \lt T \\ 0 & \text{otherwise} \end{cases}\]radio.PulseMatchedFilterBlock(baudrate[, invert=false])
baudrate
(number): Symbol baudrate in Hzinvert
(bool): Invert matched filterin
Float32 ➔❑➔ out
Float32-- Pulse matched filter with 32768 baudrate
local matched_filter = radio.PulseMatchedFilterBlock(32768)
Filter a complex or real valued signal with an FIR approximation of a root raised cosine filter.
\[y[n] = (x * h_{rrc})[n]\]radio.RootRaisedCosineFilterBlock(num_taps, beta, symbol_rate)
num_taps
(int): Number of FIR taps, must be oddbeta
(number): Roll-off factorsymbol_rate
(number): Symbol rate in Hzin
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Root raised cosine filter with 101 taps, 1.0 beta, 1187.5 symbol rate
local rrcfilter = radio.RootRaisedCosineFilterBlock(101, 1.0, 1187.5)
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.SinglepoleHighpassFilterBlock(cutoff)
cutoff
(number): Cutoff frequency in Hzin
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Single-pole highpass filter with 100 Hz cutoff
local hpf = radio.SinglepoleHighpassFilterBlock(100)
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.SinglepoleLowpassFilterBlock(cutoff)
cutoff
(number): Cutoff frequency in Hzin
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Single-pole lowpass filter with 100 kHz cutoff
local lpf = radio.SinglepoleLowpassFilterBlock(100e3)
Compute the absolute value of a real-valued signal.
\[y[n] = \text{abs}(x[n])\]radio.AbsoluteValueBlock()
in
Float32 ➔❑➔ out
Float32local abs = radio.AbsoluteValueBlock()
Add two complex or real valued signals.
\[y[n] = x_{1}[n] + x_{2}[n]\]radio.AddBlock()
in1
ComplexFloat32, in2
ComplexFloat32 ➔❑➔ out
ComplexFloat32in1
Float32, in2
Float32 ➔❑➔ out
Float32local summer = radio.AddBlock()
top:connect(src1, 'out', summer, 'in1')
top:connect(src2, 'out', summer, 'in2')
top:connect(summer, snk)
Add a real-valued constant to a complex or real valued signal, or a complex-valued constant to a complex-valued signal.
\[y[n] = x[n] + C\]radio.AddConstantBlock(constant)
constant
(number|Float32|ComplexFloat32): Constantin
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Add a number (Float32) constant
local addconstant = radio.AddConstantBlock(1.0)
-- Add a Float32 constant
local addconstant = radio.AddConstantBlock(radio.types.Float32(1.0))
-- Add a ComplexFloat32 constant
local addconstant = radio.AddConstantBlock(radio.types.ComplexFloat32(1.0))
Compute the complex conjugate of a complex-valued signal.
\[y[n] = x^*[n]\]radio.ComplexConjugateBlock()
in
ComplexFloat32 ➔❑➔ out
ComplexFloat32local conj = radio.ComplexConjugateBlock()
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.ComplexMagnitudeBlock()
in
ComplexFloat32 ➔❑➔ out
Float32local magnitude = radio.ComplexMagnitudeBlock()
Compute the argument (phase) of a complex-valued signal.
\[y[n] = \text{arg}(x[n])\] \[y[n] = \text{atan2}(\text{Im}(x[n]), \text{Re}(x[n]))\]radio.ComplexPhaseBlock()
in
ComplexFloat32 ➔❑➔ out
Float32local phase = radio.ComplexPhaseBlock()
Multiply two complex or real valued signals.
\[y[n] = x_{1}[n] \; x_{2}[n]\]radio.MultiplyBlock()
in1
ComplexFloat32, in2
ComplexFloat32 ➔❑➔ out
ComplexFloat32in1
Float32, in2
Float32 ➔❑➔ out
Float32local multiplier = radio.MultipyBlock()
top:connect(src1, 'out', multiplier, 'in1')
top:connect(src2, 'out', multiplier, 'in2')
top:connect(multiplier, snk)
Multiply a complex-valued signal by the complex conjugate of another complex-valued signal.
\[y[n] = x_{1}[n] \; x_{2}^*[n]\]radio.MultiplyConjugateBlock()
in1
ComplexFloat32, in2
ComplexFloat32 ➔❑➔ out
ComplexFloat32local multiplier = radio.MultipyConjugateBlock()
top:connect(src1, 'out', multiplier, 'in1')
top:connect(src2, 'out', multiplier, 'in2')
top:connect(multiplier, snk)
Multiply a complex or real valued signal by a real-valued constant, or multiply a complex-valued signal by a complex-valued constant.
\[y[n] = C \; x[n]\]radio.MultiplyConstantBlock(constant)
constant
(number|Float32|ComplexFloat32): Constantin
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Multiply by number (Float32) constant
local gain = radio.MultiplyConstantBlock(5.0)
-- Multiply by Float32 constant
local gain = radio.MultiplyConstantBlock(radio.types.Float32(5.0))
-- Complex rotation by 45 degrees
local rotator = radio.MultiplyConstantBlock(radio.types.ComplexFloat32(math.cos(math.pi/4),
math.sin(math.pi/4)))
Subtract two complex or real valued signals.
\[y[n] = x_{1}[n] - x_{2}[n]\]radio.SubtractBlock()
in1
ComplexFloat32, in2
ComplexFloat32 ➔❑➔ out
ComplexFloat32in1
Float32, in2
Float32 ➔❑➔ out
Float32local subtractor = radio.SubtractBlock()
top:connect(src1, 'out', subtractor, 'in1')
top:connect(src2, 'out', subtractor, 'in2')
top:connect(subtractor, snk)
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.AGCBlock(mode[, target=-35, threshold=-75, options={}])
mode
(string): Mode, choice of “fast”, “slow”, “custom”target
(number): Target power in dBFSthreshold
(number): Threshold power in dBFSoptions
(table): Additional options, specifying:
gain_tau
(number, default 0.1 seconds for
fast, 3.0 seconds for slow)power_tau
(number, default 1.0 seconds)in
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Automatic gain control with fast gain
local agc = radio.AGCBlock('fast')
-- Automatic gain control with slow gain, -20 dbFS target
local agc = radio.AGCBlock('slow', -20)
-- Automatic gain control with custom time constant, -30 dbFS target, -100 dbFS threshold
local agc = radio.AGCBlock('custom', -30, -100, {gain_tau = 0.5})
Squelch a real or complex valued signal by its average power.
\[y[n] = \begin{cases} x[n] & \text{if } P_\text{average}(x[n]) > P_\text{threshold} \\ 0.0 & \text{otherwise} \end{cases}\]radio.PowerSquelchBlock(threshold[, tau=0.001])
threshold
(number): Power threshold in dBFStau
(number): Time constant of moving average filter in secondsin
Float32 ➔❑➔ out
Float32in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Squelch at -40 dBFS power
local squelch = radio.PowerSquelchBlock(-40)
Decimate a complex or real valued signal. This block band-limits and downsamples the input signal. It reduces the sample rate for downstream blocks in the flow graph by a factor of M.
\[y[n] = (x * h_{lpf})[nM]\]radio.DecimatorBlock(decimation[, options={}])
decimation
(int): Downsampling factor Moptions
(table): Additional options, specifying:
num_taps
(int, default 128)window
(string, default “hamming”)in
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Decimate by 5
local decimator = radio.DecimatorBlock(5)
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. Use the
DecimatorBlock
for signal decimation with anti-alias
filtering.
radio.DownsamplerBlock(factor)
factor
(int): Downsampling factor Min
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Downsample by 5
local downsampler = radio.DownsamplerBlock(5)
Interpolate a complex or real valued signal. This block scales, band-limits, and upsamples the input signal. It increases the sample rate for downstream blocks in the flow graph by a factor of L.
\[y'[n] = \begin{cases} Lx[n/L] & \text{for integer } n/L \\ 0 & \text{otherwise} \end{cases}\] \[y[n] = (y' * h_{lpf})[n]\]radio.InterpolatorBlock(interpolation[, options={}])
interpolation
(int): Upsampling factor Loptions
(table): Additional options, specifying:
num_taps
(int, default 128)window
(string, default “hamming”)in
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Interpolate by 5
local interpolator = radio.InterpolatorBlock(5)
Resample a complex or real valued signal by a rational factor. This block band-limits and resamples the input signal. It changes the sample rate for downstream blocks in the flow graph by a factor of L/M.
\[y[n] = \text{Decimate}(\text{Interpolate}(x[n], L), M)\]radio.RationalResamplerBlock(interpolation, decimation[, options={}])
interpolation
(int): Upsampling factor Ldecimation
(int): Downsampling factor Moptions
(table): Additional options, specifying:
num_taps
(int, default 128)window
(string, default “hamming”)in
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Resample by 5/3
local resampler = radio.RationalResamplerBlock(5, 3)
Upsample a complex or real valued signal. This block increases the sample rate for downstream blocks in the flow graph by a factor of L.
\[y[n] = \begin{cases} x[n/L] & \text{for integer } n/L \\ 0 & \text{otherwise} \end{cases}\]Note: this block performs no scaling or anti-alias filtering. Use the
InterpolatorBlock
for signal interpolation with
scaling and anti-alias filtering.
radio.UpsamplerBlock(factor)
factor
(int): Upsampling factor Lin
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32-- Upsample by 5
local upsampler = radio.UpsamplerBlock(5)
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.FrequencyTranslatorBlock(offset)
offset
(number): Translation offset in Hzin
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Frequency translate -200 kHz
local translator = radio.FrequencyTranslatorBlock(-200e3)
Hilbert transform a real-valued signal into a complex-valued signal with a windowed FIR approximation of the IIR Hilbert transform filter.
\[y[n] = x[n-N/2] + j \, (x * h_{hilb})[n]\]radio.HilbertTransformBlock(num_taps[, window='hamming'])
num_taps
(number): Number of FIR taps, must be oddwindow
(string): Window typein
Float32 ➔❑➔ out
ComplexFloat32-- Hilbert transform with 129 taps
local ht = radio.HilbertTransformBlock(129)
Frequency translate, low-pass filter, and decimate a complex-valued signal. This block reduces the sample rate for downstream blocks in the flow graph by a factor of M.
\[y[n] = (\text{FrequencyTranslate}(x[n], f_{offset}) * h_{lpf})[nM]\]This block is convenient for translating signals to baseband and decimating them.
radio.TunerBlock(offset, bandwidth, decimation[, options={}])
offset
(number): Translation offset in Hzbandwidth
(number): Signal bandwidth in Hzdecimation
(int): Downsampling factor Moptions
(table): Additional options, specifying:
num_taps
(int, default 128)window
(string, default “hamming”)in
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Translate -100 kHz, filter 12 kHz, and decimate by 5
local tuner = radio.TunerBlock(-100e3, 12e3, 5)
Generate a phase-locked complex-valued sinusoid to a complex-valued reference signal.
\[y[n] = \text{PLL}(x[n], f_{BW}, f_{min}, f_{max}, M)\]radio.PLLBlock(loop_bandwidth, frequency_min, frequency_max[, multiplier=1.0])
loop_bandwidth
(number): Loop bandwidth in Hzfrequency_min
(number): Minimum frequency in Hzfrequency_max
(number): Maximum frequency in Hzmultiplier
(number): Multiplier, can be fractionalin
ComplexFloat32 ➔❑➔ out
ComplexFloat32, error
Float32-- PLL with 1 kHz loop bandwidth, 18 kHz - 21 kHz capture range, 3 multiplier
local pll = radio.PLLBlock(1e3, 18e3, 21e3, 3)
-- PLL with 1 kHz loop bandwidth, 18 kHz - 21 kHz capture range, 1/16 multiplier
local pll = radio.PLLBlock(1e3, 18e3, 21e3, 1/16)
Generate a real-valued clock signal from zero-crossings in a data signal.
This clock signal can then be used to sample the data signal with a
SamplerBlock
.
radio.ZeroCrossingClockRecoveryBlock(baudrate[, threshold=0.0])
baudrate
(number): Baudrate in symbols per secondthreshold
(number): Zero-crossing thresholdin
Float32 ➔❑➔ out
Float32-- Zero-crossing clock recovery of 1200 baudrate data signal
local clock_recoverer = radio.ZeroCrossingClockRecoveryBlock(1200)
top:connect(src, clock_recoverer)
top:connect(src, 'out', sampler, 'data')
top:connect(clock_recoverer, 'out', sampler, 'clock')
top:connect(sampler, snk)
Correct the phase of a complex-valued BPSK modulated signal, by rotating it against a moving average of the phase angle.
\[y[n] = x[n] \; e^{-j\phi_{avg}[n]}\]radio.BinaryPhaseCorrectorBlock(num_samples[, sample_interval=32])
num_samples
(int): Number of samples in phase angle moving averagesample_interval
(int): Number of samples to skip between phase
measurementsin
ComplexFloat32 ➔❑➔ out
ComplexFloat32-- Binary phase corrector with a 3000 sample moving average
local phase_corrector = radio.BinaryPhaseCorrector(3000)
Decode a differentially encoded bit stream.
\[y[n] = x[n-1] \oplus x[n]\]radio.DifferentialDecoderBlock([invert=false])
invert
(bool): Invert the output.in
Bit ➔❑➔ out
Bitlocal diff_decoder = radio.DifferentialDecoderBlock()
Decode a Manchester encoded bit stream.
\[y[n] = \begin{cases} 0 & \text{for }\{0, 1\} \\ 1 & \text{for }\{1, 0\} \\ \text{slip input} & \text{otherwise} \end{cases}\]radio.ManchesterDecoderBlock([invert=false])
invert
(bool): Invert the output.in
Bit ➔❑➔ out
Bitlocal manchester_decoder = radio.ManchesterDecoderBlock()
Sample a real valued signal into a fixed number of samples, by detecting a preamble bit sequence at the specified baudrate. The sampling position is optimized by maximizing the energy of the detected preamble.
This block assumes a zero threshold when slicing samples into bits for comparison to the preamble.
\[y[n] = \text{PreambleSampler}(x[m], \text{baudrate}, \text{preamble}, \text{num_samples})\]radio.PreambleSamplerBlock(baudrate, preamble, num_samples)
baudrate
(number): Baudrate in symbols per secondpreamble
(Vector): Preamble Bit vectornum_samples
(number): Number of samples per frame, including preamblein
Float32 ➔❑➔ out
Float32-- Sample a 16384 baudrate data signal with the 16-bit preamble 0x16a3 into 128 samples
local preamble = radio.types.Bit.vector_from_array({0,0,0,1,0,1,1,0,1,0,1,0,0,0,1,1})
local sampler = radio.PreambleSamplerBlock(16384, preamble, 128)
local slicer = radio.SlicerBlock()
top:connect(src, sampler, slicer)
Sample a complex or real valued data signal on positive zero-crossing transitions of a real-valued clock signal.
\[y[n] = x_{data}[m] \,\text{ when }\, \begin{align}&x_{clk}[m] > 0 \\ &x_{clk}[m-1] < 0\end{align}\]radio.SamplerBlock()
data
ComplexFloat32, clock
Float32 ➔❑➔ out
ComplexFloat32data
Float32, clock
Float32 ➔❑➔ out
Float32local sampler = radio.SamplerBlock()
top:connect(data_src, 'out', sampler, 'data')
top:connect(clock_src, 'out', sampler, 'clock')
top:connect(sampler, snk)
Slice a real-valued signal on a threshold into a bit stream.
\[y[n] = \begin{cases} 1 & \text{if } x[n] > \text{threshold} \\ 0 & \text{if } x[n] < \text{threshold} \end{cases}\]radio.SlicerBlock([threshold=0.0])
threshold
(number): Thresholdin
Float32 ➔❑➔ out
Bit-- Slice at default threshold 0.0
local slicer = radio.SlicerBlock()
-- Slice at threshold 0.5
local slicer = radio.SlicerBlock(0.5)
Decompose the real and imaginary parts of a complex-valued signal.
\[y_{real}[n],\, y_{imag}[n] = \text{Re}(x[n]),\, \text{Im}(x[n])\]radio.ComplexToFloatBlock()
in
ComplexFloat32 ➔❑➔ real
Float32, imag
Float32local complextofloat = radio.ComplexToFloatBlock()
Decompose the imaginary part of a complex-valued signal.
\[y[n] = \text{Im}(x[n])\]radio.ComplexToImagBlock()
in
ComplexFloat32 ➔❑➔ out
Float32local complextoimag = radio.ComplexToImagBlock()
Decompose the real part of a complex-valued signal.
\[y[n] = \text{Re}(x[n])\]radio.ComplexToRealBlock()
in
ComplexFloat32 ➔❑➔ out
Float32local complextoreal = radio.ComplexToRealBlock()
Compose two real-valued signals into the real and imaginary parts of a complex-valued signal.
\[y[n] = x_{real}[n] + j \, x_{imag}[n]\]radio.FloatToComplexBlock()
real
Float32, imag
Float32 ➔❑➔ out
ComplexFloat32local floattocomplex = radio.FloatToComplexBlock()
Compose a complex-valued signal from a real-valued signal and a zero-valued imaginary part.
\[y[n] = x[n] + 0 \, j\]radio.RealToComplexBlock()
in
Float32 ➔❑➔ out
ComplexFloat32local realtocomplex = radio.RealToComplexBlock()
Deinterleave a complex or real valued signal.
\[y_1[n],\, y_2[n],\, ... = x[Nn+0],\, x[Nn+1],\, ...\]radio.DeinterleaveBlock([num_channels=2])
num_channels
(int): Number of channelsin
Float32 ➔❑➔ out1
Float32, out2
Float32, ...
in
ComplexFloat32 ➔❑➔ out1
ComplexFloat32, out2
ComplexFloat32, ...
-- Deinterleave two channels
local deinterleaver = radio.DeinterleaveBlock()
-- Deinterleave four channels
local deinterleaver = radio.DeinterleaveBlock(4)
Delay a signal by a fixed number of samples.
\[y[n] = x[n-d]\]radio.DelayBlock(num_samples)
num_samples
(int): Number of samples to delayin
ComplexFloat32 ➔❑➔ out
ComplexFloat32in
Float32 ➔❑➔ out
Float32in
Byte ➔❑➔ out
Bytein
Bit ➔❑➔ out
Bit-- Delay by 128 samples
local delay = radio.DelayBlock(128)
Interleave a complex or real valued signal.
\[y[n] = \left\{x_1[0],\, x_2[0],\, ...,\, x_N[0],\, x_1[1],\, x_2[1],\, ...,\, x_N[1],\, ...\right\}\]radio.InterleaveBlock([num_channels=2])
num_channels
(int): Number of channelsin1
Float32, in2
Float32, ...
➔❑➔ out
Float32in1
ComplexFloat32, in2
ComplexFloat32, ...
➔❑➔ out
ComplexFloat32-- Interleave two channels
local interleaver = radio.InterleaveBlock()
-- Interleave four channels
local interleaver = radio.InterleaveBlock(4)
Pass a signal through, performing no operation.
\[y[n] = x[n]\]radio.NopBlock()
in
any ➔❑➔ out
copylocal nop = radio.NopBlock()
top:connect(src, nop, snk)
Throttle a signal to limit CPU usage and pace plotting sinks.
\[y[n] = x[n]\]radio.ThrottleBlock()
in
any ➔❑➔ out
copylocal throttle = radio.ThrottleBlock()
top:connect(src, throttle, snk)
Frequency modulate a real-valued signal into a baseband complex-valued signal.
\[y[n] = e^{j 2 \pi k \sum x[n]}\]radio.FrequencyModulatorBlock(modulation_index)
modulation_index
(number): Modulation index (Carrier Deviation / Maximum Modulation Frequency)in
Float32 ➔❑➔ out
ComplexFloat32-- Frequency modulator with modulation index 0.2
local fm_mod = radio.FrequencyModulatorBlock(0.2)
Pulse amplitude modulate bits into a baseband real-valued signal. The resulting signal is non-return-to-zero, bipolar, with normalized energy.
\[y[n] = \text{PAM}(x[n], \text{symbol_rate}, \text{sample_rate}, \text{levels})\]radio.PulseAmplitudeModulatorBlock(symbol_rate, sample_rate, levels[, options={}])
symbol_rate
(number): Symbol rate in Hzsample_rate
(number): Sample rate in Hzlevels
(number): Number of amplitude levels (must be power of 2)options
(table): Additional options, specifying:
msb_first
(boolean, default true)amplitudes
(table, mapping of symbol value
to amplitude)in
Bit ➔❑➔ out
Float32-- 4-PAM modulator with 1200 Hz symbol rate, 96 kHz sample rate
local modulator = radio.PulseAmplitudeModulatorBlock(1200, 96000, 4)
Quadrature amplitude modulate bits into a baseband complex-valued signal.
\[y[n] = \text{QAM}(x[n], \text{symbol_rate}, \text{sample_rate}, \text{points})\]radio.QuadratureAmplitudeModulatorBlock(symbol_rate, sample_rate, points[, options={}])
symbol_rate
(number): Symbol rate in Hzsample_rate
(number): Sample rate in Hzpoints
(number): Number of constellation points (must be power of 2)options
(table): Additional options, specifying:
msb_first
(boolean, default true)constellation
(table, mapping of symbol
value to complex amplitude)in
Bit ➔❑➔ out
ComplexFloat32-- 4-QAM modulator with 1200 Hz symbol rate, 96 kHz sample rate
local modulator = radio.QuadratureAmplitudeModulatorBlock(1200, 96000, 4)
Modulate a real-valued signal into a baseband, single-sideband amplitude modulated complex-valued signal.
\[y[n] = \text{SSBModulate}(x[n], \text{sideband}, \text{bandwidth})\]radio.SSBModulator(sideband[, bandwidth=3e3])
sideband
(string): Sideband, choice of “lsb” or “usb”.bandwidth
(number): Bandwidth in Hzin
Float32 ➔❑➔ out
ComplexFloat32-- SSB LSB modulator with 3 kHz bandwidth
local mod = radio.SSBModulator("lsb", 3e3)
Demodulate a baseband, double-sideband amplitude modulated complex-valued signal with an envelope detector.
\[y[n] = \text{AMDemodulate}(x[n], \text{bandwidth})\]radio.AMEnvelopeDemodulator([bandwidth=5e3])
bandwidth
(number): Bandwidth in Hzin
ComplexFloat32 ➔❑➔ out
Float32-- AM demodulator with 5 kHz bandwidth
local demod = radio.AMEnvelopeDemodulator(5e3)
Demodulate a double-sideband amplitude modulated complex-valued signal with a synchronous detector. The input signal should be centered on the specified intermediate frequency.
\[y[n] = \text{AMDemodulate}(x[n], \text{IF}, \text{bandwidth})\]radio.AMSynchronousDemodulator(ifreq[, bandwidth=5e3])
ifreq
(number): Intermediate frequency in Hzbandwidth
(number): Bandwidth in Hzin
ComplexFloat32 ➔❑➔ out
Float32-- AM demodulator with 100 kHz IF, 5 kHz bandwidth
local demod = radio.AMSynchronousDemodulator(100e3, 5e3)
Frequency discriminate a complex-valued signal. This is a method of frequency demodulation.
\[y[n] = \frac{\text{arg}(x[n] \; x^*[n-1])}{2 \pi k}\]radio.FrequencyDiscriminatorBlock(modulation_index)
modulation_index
(number): Modulation index (Carrier Deviation / Maximum Modulation Frequency)in
ComplexFloat32 ➔❑➔ out
Float32-- Frequency discriminator with modulation index 1.25
local fm_demod = radio.FrequencyDiscriminatorBlock(1.25)
Demodulate a baseband, narrowband FM modulated complex-valued signal.
\[y[n] = \text{NBFMDemodulate}(x[n], \text{deviation}, \text{bandwidth})\]The input signal will be band-limited by the specified deviation and bandwidth with a cutoff frequency calculated by Carson’s rule.
radio.NBFMDemodulator([deviation=5e3, bandwidth=4e3])
deviation
(number): Deviation in Hzbandwidth
(number): Bandwidth in Hzin
ComplexFloat32 ➔❑➔ out
Float32-- NBFM demodulator with 5 kHz deviation and 4 kHz bandwidth
local demod = radio.NBFMDemodulator(5e3, 4e3)
Demodulate a baseband, single-sideband amplitude modulated complex-valued signal.
\[y[n] = \text{SSBDemodulate}(x[n], \text{sideband}, \text{bandwidth})\]radio.SSBDemodulator(sideband[, bandwidth=3e3])
sideband
(string): Sideband, choice of “lsb” or “usb”.bandwidth
(number): Bandwidth in Hzin
ComplexFloat32 ➔❑➔ out
Float32-- SSB LSB demodulator with 3 kHz bandwidth
local demod = radio.SSBDemodulator("lsb", 3e3)
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], \tau)\]radio.WBFMMonoDemodulator([tau=75e-6])
tau
(number): FM de-emphasis time constantin
ComplexFloat32 ➔❑➔ out
Float32local demod = radio.WBFMMonoDemodulator()
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], \tau)\]radio.WBFMStereoDemodulator([tau=75e-6])
tau
(number): FM de-emphasis time constantin
ComplexFloat32 ➔❑➔ left
Float32, right
Float32local demod = radio.WBFMStereoDemodulator()
Validate and extract AX.25 frames from a bit stream.
radio.AX25FramerBlock()
in
Bit ➔❑➔ out
AX25FrameTypelocal framer = radio.AX25FramerBlock()
radio.AX25FramerBlock.AX25FrameType(addresses, control, pid, payload)
AX.25 frame type, a Lua object with properties:
{
addresses = {
{
callsign = <string>,
ssid = <integer>
},
...
},
control = <integer>,
pid = <integer>,
payload = <byte string>,
}
addresses
(array): Array of addresses, each a table with key callsign
containing a 6-character string callsign and key
ssid
containing a 7-bit wide integer SSIDcontrol
(int): Control field, 8-bits widepid
(int): PID field, 8-bits widepayload
(string): Payload byte string (variable length)Validate and extract IDM frames from a bit stream.
radio.IDMFramerBlock()
in
Bit ➔❑➔ out
IDMFrameTypelocal framer = radio.IDMFramerBlock()
radio.IDMFramerBlock.IDMFrameType(type, application_version, ert_type, ert_id, consumption_interval_count, module_programming_state, tamper_count, async_count, power_outage_flags, last_consumption_count, differential_consumption_intervals, transmit_time_offset, serial_crc, packet_crc)
IDM frame type, a Lua object with properties:
{
type = "idm",
application_version = <8-bit integer>,
ert_type = <8-bit integer>,
ert_id = <32-bit integer>,
consumption_interval_count = <8-bit integer>,
module_programming_state = <8-bit integer>,
tamper_count = <6-byte string>,
async_count = <2-byte string>,
power_outage_flags = <6-byte string>,
last_consumption_count = <32-bit integer>,
differential_consumption_intervals = <53-byte string>,
transmit_time_offset = <16-bit integer>,
serial_crc = <16-bit integer>,
packet_crc = <16-bit integer>,
}
type
(string): Protocol type, constant “idm”application_version
(int): Application version field, 8-bits wideert_type
(int): ERT Type field, 8-bits wideert_id
(int): ERT ID field, 32-bits wideconsumption_interval_count
(int): Consumption interval count field, 8-bits widemodule_programming_state
(int): Module programming state field, 8-bits widetamper_count
(string): Tamper count bytes, 6 bytes longasync_count
(string): Async count bytes, 2 bytes longpower_outage_flags
(string): Power outage bytes, 6 bytes longlast_consumption_count
(int): Last consumption count field, 32-bits widedifferential_consumption_intervals
(string): Differential consumption intevals string, 53 bytes longtransmit_time_offset
(int): Transmit time offset field, 16-bits wideserial_crc
(int): Serial CRC field, 16-bits widepacket_crc
(int): Packet CRC field, 16-bits wideDecode POCSAG frames into POCSAG messages. This block decodes alphanumeric strings, numeric strings, or both.
radio.POCSAGDecoderBlock([mode='alphanumeric'])
mode
(string): Decoding mode, choice of
“alphanumeric”, “numeric”, or
“both”.in
POCSAGFrameType ➔❑➔ out
POCSAGMessageTypelocal decoder = radio.POCSAGDecoderBlock()
radio.POCSAGDecoderBlock.POCSAGMessageType(address, func, alphanumeric, numeric)
POCSAG message type, a Lua object with properties:
{
address = <21-bit integer>,
func = <2-bit integer>,
alphanumeric = <string>,
numeric = <string>,
}
address
(int): Address bits, 21-bits widefunc
(int): Function bits, 2-bits widealphanumeric
(string): Decoded alphanumeric stringnumeric
(string): Decoded numeric stringDetect, correct, validate, and extract POCSAG frames from a bit stream. Each frame contains a single message with address, function bits, and data, so a POCSAG transmission of several batches may yield several frames.
radio.POCSAGFramerBlock()
in
Bit ➔❑➔ out
POCSAGFrameTypelocal framer = radio.POCSAGFramerBlock()
radio.POCSAGFramerBlock.POCSAGFrameType(address, func, data)
POCSAG frame type, a Lua object with properties:
{
address = <21-bit integer>,
func = <2-bit integer>,
data = {<20-bit integer>, ...},
}
address
(int): Address bits, 21-bits widefunc
(int): Function bits, 2-bits widedata
(array): Array of data words, each 20-bits wideDecode RDS frames into RDS packets with a header and data payload. The supported data payloads are basic tuning, radiotext, and datetime.
radio.RDSDecoderBlock()
in
RDSFrameType ➔❑➔ out
RDSPacketTypelocal decoder = radio.RDSDecoderBlock()
radio.RDSDecoderBlock.RDSPacketType(header, data)
RDS packet type, a Lua object with properties:
{
header = {
pi_code = <16-bit integer>
group_code = <4-bit integer>
group_version = <1-bit integer>,
tp_code = <1-bit integer>,
pty_code = <5-bit integer>,
},
data = <payload object>,
}
The payload object can be one of the four below.
Basic tuning data payload:
{
type = "basictuning",
ta_code = <1-bit integer>,
ms_code = <1-bit integer>,
di_position = <2-bit integer>,
di_value = <1-bit integer>,
af_code = {<8-bit integer>, <8-bit integer>} or nil,
text_address = <2-bit integer>,
text_data = <string, length 2>,
}
Radio text data payload:
{
type = "radiotext",
ab_flag = <1-bit integer>,
text_address = <4-bit integer>,
text_data = <string, length 4 or 2>,
}
Datetime data payload:
{
type = "datetime",
date = {year = <integer>, month = <integer>, day = <integer>},
time = {hour = <integer>, minute = <integer>, offset = <integer>},
}
Raw data payload (for unsupported group/version codes):
{
type = "raw",
frame = {<16-bit integer>, <16-bit integer>, <16-bit integer>, <16-bit integer>},
}
header
(table): Header table, as outlined abovedata
(table): Data payload table, as outlined aboveCorrect, validate, and extract 104-bit RDS data groups from a bit stream into frames.
radio.RDSFramerBlock()
in
Bit ➔❑➔ out
RDSFrameTypelocal framer = radio.RDSFramerBlock()
radio.RDSFramerBlock.RDSFrameType(data)
RDS frame type, a C structure defined as:
typedef struct {
uint16_t blocks[4];
} rds_frame_t;
data
(table): Array of four data words, e.g. {{0x3aab, 0x02c9, 0x0608, 0x6469}}
Validate and extract SCM frames from a bit stream.
radio.SCMFramerBlock()
in
Bit ➔❑➔ out
SCMFrameTypelocal framer = radio.SCMFramerBlock()
radio.SCMFramerBlock.SCMFrameType(type, ert_type, ert_id, consumption, physical_tamper, encoder_tamper, reserved, crc)
SCM frame type, a Lua object with properties:
{
type = "scm",
ert_type = <4-bit integer>,
ert_id = <26-bit integer>,
consumption = <24-bit integer>,
physical_tamper = <2-bit integer>,
encoder_tamper = <2-bit integer>,
reserved = <1-bit integer>,
crc = <16-bit integer>,
}
type
(string): Protocol type, constant “scm”ert_type
(int): ERT Type field, 4-bits wideert_id
(int): ERT ID Field, 26-bits wideconsumption
(int): Consumption field, 24-bits widephysical_tamper
(int): Physcal tamper field, 2-bits wideencoder_tamper
(int): Encoder tamper field, 2-bits widereserved
(int): Reserved field, 1-bit widecrc
(int): CRC field, 16-bits wideValidate and extract SCM+ frames from a bit stream.
radio.SCMPlusFramerBlock()
in
Bit ➔❑➔ out
SCMPlusFrameTypelocal framer = radio.SCMPlusFramerBlock()
radio.SCMPlusFramerBlock.SCMPlusFrameType(type, protocol_id, ert_type, ert_id, consumption, tamper, crc)
SCM+ frame type, a Lua object with properties:
{
type = "scm+",
protocol_id = <8-bit integer>,
ert_type = <8-bit integer>,
ert_id = <32-bit integer>,
consumption = <32-bit integer>,
tamper = <16-bit integer>,
crc = <16-bit integer>,
}
type
(string): Protocol type, constant “scm+”protocol_id
(int): Protocol ID field, 8-bits wideert_type
(int): ERT Type field, 8-bits wideert_id
(int): ERT ID field, 32-bits wideconsumption
(int): Consumption field, 32-bits widetamper
(int): Tamper field, 16-bits widecrc
(int): CRC field, 16-bits wideDecode a Varicode encoded bit stream into bytes.
radio.VaricodeDecoderBlock()
in
Bit ➔❑➔ out
Bytelocal decoder = radio.VaricodeDecoderBlock()
Demodulate and decode AX.25 frames from a baseband, narrowband FM, Bell 202 AFSK modulated complex-valued signal.
radio.AX25Receiver()
in
ComplexFloat32 ➔❑➔ out
AX25FrameTypelocal receiver = radio.AX25Receiver()
local snk = radio.JSONSink()
top:connect(src, receiver, snk)
Demodulate and decode bytes from a baseband BPSK31 modulated complex-valued signal.
radio.BPSK31Receiver()
in
ComplexFloat32 ➔❑➔ out
Bytelocal receiver = radio.BPSK31Receiver()
local snk = radio.RawFileSink(io.stdout)
top:connect(src, receiver, snk)
Demodulate and decode ERT frames from an OOK modulated complex-valued signal. IDM, SCM, SCM+ protocols are supported.
This receiver is based on rtlamr’s excellent description: https://github.com/bemasher/rtlamr/wiki/Signal-Processing
radio.ERTReceiver([protocols={'idm','scm','scm+'}, options={}])
protocols
(array): Protocols to decode,
choice of ‘idm’, ‘scm’,
‘scm+’. Default is all
three.options
(table): Additional options, specifying:
decimation
Downsampling factor (int, default 6)in
ComplexFloat32 ➔❑➔ out1
IDMFrameType, out2
SCMFrameType, ...
local receiver = radio.ERTReceiver({'scm', 'scm+'})
local scm_sink = radio.PrintSink()
local scm_plus_sink = radio.PrintSink()
top:connect(src, receiver)
top:connect(receiver, 'out1', scm_sink, 'in')
top:connect(receiver, 'out2', scm_plus_sink, 'in')
Demodulate and decode POCSAG messages from a baseband, 4.5 kHz shift FSK modulated complex-valued signal.
radio.POCSAGReceiver()
in
ComplexFloat32 ➔❑➔ out
POCSAGMessageTypelocal receiver = radio.POCSAGReceiver()
local snk = radio.JSONSink()
top:connect(src, receiver, snk)
Demodulate and decode RDS frames from a baseband, wideband FM broadcast modulated complex-valued signal.
radio.RDSReceiver()
in
ComplexFloat32 ➔❑➔ out
RDSPacketTypelocal receiver = radio.RDSReceiver()
local snk = radio.JSONSink()
top:connect(src, receiver, snk)
LuaRadio package.
radio._VERSION
string: Package version as a string, e.g. “1.0.0”.
radio.version
string: Package version as a string, e.g. “1.0.0”.
radio.version_number
int: Package version as a number, encoded in decimal as xxyyzz, e.g. v1.2.15 would be 10215.
radio.version_info
table: Package version as a table, with keys major
, minor
, patch
and integer values.
radio.types
module: Types module.
radio.block
module: Block module.
radio.debug
module: Debug module.
radio.platform
module: Platform module.
radio.types.ComplexFloat32([real=0.0, imag=0.0])
ComplexFloat32 data type, a C structure defined as:
typedef struct complex_float32 {
float real;
float imag;
} complex_float32_t;
real
(float): Initial real partimag
(float): Initial imaginary partComplexFloat32.vector(num)
Construct a zero-initialized ComplexFloat32 vector.
num
(int): Number of elements in the vectorlocal vec = radio.types.ComplexFloat32.vector(100)
ComplexFloat32.vector_from_array(arr)
Construct a ComplexFloat32 vector initialized from an array.
arr
(array): Array with element initializerslocal vec = radio.types.ComplexFloat32.vector_from_array({{1.0, 2.0}, {2.0, 3.0}, {3.0, 4.0}})
ComplexFloat32:__add(other)
Add two ComplexFloat32s.
other
(ComplexFloat32): OperandComplexFloat32:__sub(other)
Subtract two ComplexFloat32s.
other
(ComplexFloat32): OperandComplexFloat32:__mul(other)
Multiply two ComplexFloat32s.
other
(ComplexFloat32): OperandComplexFloat32:__div(other)
Divide two ComplexFloat32s.
other
(ComplexFloat32): OperandComplexFloat32:__eq(other)
Compare two ComplexFloat32s for equality.
other
(ComplexFloat32): Other ComplexFloat32ComplexFloat32:__lt(other)
Compare two ComplexFloat32s for less than.
other
(ComplexFloat32): Other ComplexFloat32ComplexFloat32:__le(other)
Compare two ComplexFloat32s for less than or equal.
other
(ComplexFloat32): Other ComplexFloat32ComplexFloat32:scalar_mul(other)
Multiply a ComplexFloat32 by a scalar.
other
(number): ScalarComplexFloat32:scalar_div(other)
Divide a ComplexFloat32 by a scalar.
other
(number): ScalarComplexFloat32:arg()
Compute the complex argument, in interval \((-\pi, \pi]\).
\[\angle z = \text{atan2}(\text{Im}(z), \text{Re}(z))\]ComplexFloat32:abs()
Compute the complex magnitude.
\[|z| = \sqrt{\text{Re}(z)^2 + \text{Im}(z)^2}\]ComplexFloat32:abs_squared()
Compute the complex magnitude squared.
\[|z|^2 = \text{Re}(z)^2 + \text{Im}(z)^2\]ComplexFloat32:conj()
Get the complex conjugate.
ComplexFloat32.approx_equal(x, y, epsilon)
Compare two ComplexFloat32s for approximate equality within the specified epsilon.
x
(ComplexFloat32): First ComplexFloat32y
(ComplexFloat32): Second ComplexFloat32epsilon
(number): EpsilonComplexFloat32:__tostring()
Get a string representation.
local x = radio.types.ComplexFloat32()
print(x)) --> ComplexFloat32<real=0, imag=0>
ComplexFloat32.type_name
Type name of ComplexFloat32.
print(radio.types.ComplexFloat32.type_name) --> ComplexFloat32
radio.types.Float32([value=0.0])
Float32 data type, a C structure defined as:
typedef struct float32 {
float value;
} float32_t;
value
(float): Initial valueFloat32.vector(num)
Construct a zero-initialized Float32 vector.
num
(int): Number of elements in the vectorlocal vec = radio.types.Float32.vector(100)
Float32.vector_from_array(arr)
Construct a Float32 vector initialized from an array.
arr
(array): Array with element initializerslocal vec = radio.types.Float32.vector_from_array({1.0, 2.0, 3.0})
Float32:__add(other)
Add two Float32s.
other
(Float32): OperandFloat32:__sub(other)
Subtract two Float32s.
other
(Float32): OperandFloat32:__mul(other)
Multiply two Float32s.
other
(Float32): OperandFloat32:__div(other)
Divide two Float32s.
other
(Float32): OperandFloat32:__eq(other)
Compare two Float32s for equality.
other
(Float32): Other Float32Float32:__lt(other)
Compare two Float32s for less than.
other
(Float32): Other Float32Float32:__le(other)
Compare two Float32s for less than or equal.
other
(Float32): Other Float32Float32.approx_equal(x, y, epsilon)
Compare two Float32s for approximate equality within the specified epsilon.
x
(Float32): First Float32y
(Float32): Second Float32epsilon
(number): EpsilonFloat32:__tostring()
Get a string representation.
local x = radio.types.Float32()
print(x)) --> Float32<value=0>
Float32.type_name
Type name of Float32.
print(radio.types.Float32.type_name) --> Float32
radio.types.Bit([value=0])
Bit data type, a C structure defined as:
typedef struct bit {
uint8_t value;
} bit_t;
value
(int): Initial valueBit.vector(num)
Construct a zero-initialized Bit vector.
num
(int): Number of elements in the vectorlocal vec = radio.types.Bit.vector(100)
Bit.vector_from_array(arr)
Construct a Bit vector initialized from an array.
arr
(array): Array with element initializerslocal vec = radio.types.Bit.vector_from_array({1, 0, 1, 0, 1, 1, 0})
Bit:band(other)
Bitwise-AND two Bits.
other
(Bit): OperandBit:bor(other)
Bitwise-OR two Bits.
other
(Bit): OperandBit:bxor(other)
Bitwise-XOR two Bits.
other
(Bit): OperandBit:bnot()
Bitwise-NOT a Bit.
Bit:__eq(other)
Compare two Bits for equality.
other
(Bit): Other bitBit:__tostring()
Get a string representation.
local x = radio.types.Bit()
print(x)) --> Bit<value=0>
Bit.type_name
Type name of Bit.
print(radio.types.Bit.type_name) --> Bit
Bit.tonumber(vec, length[, offset=0, order="msb"])
Convert a Bit vector to a number.
vec
(Vector): Bit vectoroffset
(int): Offset in bitslength
(int): Length in bitsorder
(string): Bit order. Choice of “msb” or “lsb”.local vec = radio.types.Bit.vector_from_array({0, 1, 0, 1})
assert(radio.types.Bit.tonumber(vec) == 5)
assert(radio.types.Bit.tonumber(vec, 0, 4, 'lsb') == 10)
assert(radio.types.Bit.tonumber(vec, 2, 2, 'msb') == 1)
assert(radio.types.Bit.tonumber(vec, 2, 2, 'lsb') == 2)
Bit.tobytes(vec, length[, offset=0])
Convert a Bit vector to a byte string. Assumes MSB bit order.
vec
(Vector): Bit vectoroffset
(int): Offset in bitslength
(int): Length in bits-- Convert bits starting at offset 16 to an 8-byte byte string
local data = radio.types.Bit.tobytes(vec, 16, 10*8)
Bit.tostring(vec, length[, offset=0])
Format a Bit vector to a string. Assumes MSB bit order.
vec
(Vector): Bit vectoroffset
(int): Offset in bitslength
(int): Length in bitslocal vec = radio.types.Bit.vector_from_array({0, 1, 0, 1, 1, 1})
print(radio.types.Bit.tostring(vec)) --> '010111'
print(radio.types.Bit.tostring(vec, 1, 4)) --> '1011'
radio.types.Byte([value=0])
Byte data type, a C structure defined as:
typedef struct byte {
uint8_t value;
} byte_t;
value
(int): Initial valueByte.vector(num)
Construct a zero-initialized Byte vector.
num
(int): Number of elements in the vectorlocal vec = radio.types.Byte.vector(100)
Byte.vector_from_array(arr)
Construct a Byte vector initialized from an array.
arr
(array): Array with element initializerslocal vec = radio.types.Byte.vector_from_array({0xde, 0xad, 0xbe, 0xef})
Byte:__add(other)
Add two Bytes.
other
(Bit): OperandByte:__sub(other)
Subtract two Bytes.
other
(Bit): OperandByte:__mul(other)
Multiply two Bytes.
other
(Bit): OperandByte:__div(other)
Divide two Bytes.
other
(Bit): OperandByte:__eq(other)
Compare two Bytes for equality.
other
(Bit): Other byteByte:__lt(other)
Compare two Bytes for less than.
other
(Bit): Other byteByte:__le(other)
Compare two Bytes for less than or equal.
other
(Bit): Other byteByte:__tostring()
Get a string representation.
local x = radio.types.Byte()
print(x)) --> Byte<value=0>
Byte.type_name
Type name of Byte.
print(radio.types.Byte.type_name) --> Byte
radio.types.CStructType()
CStruct data type base class.
CStructType.factory(ctype[, methods={}])
Construct a new data type based on a C structure type. The data type will be serializable between blocks in a flow graph.
ctype
(string|ctype): C typemethods
(table): Table of methods and metamethodsCStructType.new(...)
Construct a new instance of this type.
...
: ArgumentsCStructType.vector(num)
Construct a zero-initialized vector of this type.
num
(int): Number of elements in the vectorCStructType.vector_from_array(arr)
Construct a vector of this type initialized from an array.
arr
(array): Array with element initializersCStructType:__eq(other)
Compare two instances of this type.
other
(CStructType): Other instanceCStructType.type_name
Type name of this CStructType.
radio.types.ObjectType()
Object data type base class.
ObjectType.factory([methods={}])
Construct a new data type based on a Lua object. The data type will be serializable between blocks in a flow graph.
The new()
constructor must be provided by the implementation.
methods
(table): Table of methods and metamethodsObjectType.vector(num)
Construct a vector of this type.
num
(int): Number of elements in the vectorObjectType.vector_from_array(arr)
Construct a vector of this type initialized from an array.
arr
(array): Array with element initializersObjectType:to_msgpack()
Serialize this object with MessagePack.
ObjectType:to_json()
Serialize this object with JSON.
ObjectType:from_msgpack(str)
Deserialize an instance of this type with MessagePack.
str
(string): MessagePack serialized objectObjectType:from_json(str)
Deserialize an instance of this type with JSON.
str
(string): JSON serialized objectObjectType.type_name
Type name of this ObjectType.
Vector classes.
radio.vector.Vector(ctype[, num=0])
A dynamic array of a C structure type.
ctype
(ctype): C typenum
(int): LengthVector:__eq(other)
Compare two vectors for equality.
other
(vector): Other vectorVector:__tostring()
Get a string representation.
Vector:resize(num)
Resize the vector.
num
(int): New lengthVector:append(elem)
Append an element to the vector.
elem
: ElementVector:fill(elem)
Fill a vector with an element.
elem
: Elementradio.vector.ObjectVector(type[, num=0])
A dynamic array of a Lua object type.
type
(type): Lua classnum
(int): LengthObjectVector:__tostring()
Get a string representation.
ObjectVector:resize(num)
Resize the vector.
num
(int): New lengthObjectVector:append(elem)
Append an element to the vector.
elem
: ElementSupport classes for creating blocks.
radio.block.Input(name, data_type)
Block input port descriptor. This contains the name and data type of a block input port.
name
(string): Namedata_type
(type|function): Data type, e.g. radio.types.ComplexFloat32
, or a function predicatelocal inputs = {radio.block.Input("in1", radio.types.ComplexFloat32),
radio.block.Input("in2", radio.types.ComplexFloat32)}
local outputs = {...}
...
self:add_type_signature(inputs, outputs)
radio.block.Output(name, data_type)
Block output port descriptor. This contains the name and data type of a block output port.
name
(string): Namedata_type
(type|str): Data type, e.g. radio.types.ComplexFloat32
, or “copy” to copy input data typelocal inputs = {...}
local outputs = {radio.block.Output("out", radio.types.ComplexFloat32)}
...
self:add_type_signature(inputs, outputs)
radio.block.Block()
Block base class.
Block:add_type_signature(inputs, outputs[, process_func=nil, initialize_func=nil])
Add a type signature.
inputs
(array): Input ports, array of radio.block.Input
instancesoutputs
(array): Output ports, array of radio.block.Output
instancesprocess_func
(function): Optional process function for this
type signature, defaults to
process()
initialize_func
(function): Optional process initialization
for this type signature, defaults
to initialize()
Block:differentiate(input_data_types)
Differentiate this block to a type signature.
input_data_types
(array): Array of input data typesBlock:get_input_type([index=1])
Get the differentiated input data type.
index
(int): Index of input, starting at 1Block:get_output_type([index=1])
Get the differentiated output data type.
index
(int): Index of output, starting at 1Block:get_rate()
Get the block rate.
Block:__tostring()
Get a string representation with the block name and port connectivity.
Block:instantiate()
Instantiate hook, default no-op implementation.
Block:initialize()
Initialize hook, default no-op implementation.
Block:process()
Process hook, default implementation raises a not implemented error.
Block:cleanup()
Cleanup hook, default no-op implementation.
radio.block.factory(name[, parent_class=nil])
Block class factory.
name
(string): Block nameparent_class
(class): Inherited parent classlocal MyBlock = radio.block.factory("MyBlock")
function MyBlock:instantiate(a, b)
self.param = a + b
self:add_type_signature({radio.block.Input("in", radio.types.Float32)},
{radio.block.Output("out", radio.types.Float32)})
end
function MyBlock:initialize()
-- Differentiated data type and sample rate dependent initialization
end
function MyBlock:process(x)
return x
end
Debug logging support.
radio.debug.enabled
bool: Debug logging enabled.
radio.debug.print(s)
Debug print.
s
(string): String to printradio.debug.printf(...)
Debug formatted print.
...
: Format string and argumentsPlatform constants.
radio.platform.luajit_version
string: LuaJIT version (e.g. “LuaJIT 2.0.4”).
radio.platform.os
string: Operating System (e.g. “Linux”, “OSX”, “BSD”).
radio.platform.arch
string: Architecture (e.g. “x64”, “x86”, “arm”).
radio.platform.page_size
int: Page size (e.g. 4096).
radio.platform.cpu_count
int: CPU count (e.g. 4).
radio.platform.cpu_model
int: CPU model (e.g. “Intel(R) Core(TM) i5-4570T CPU @ 2.90GHz”).
radio.platform.alloc
function: Platform page-aligned allocator function.
radio.platform.load
function: Platform FFI load library helper function.
radio.platform.time_us
function: Platform timestamp function.
radio.platform.features.liquid
bool: Liquid-dsp library found and enabled.
radio.platform.features.volk
bool: VOLK library found and enabled.
radio.platform.features.fftw3f
bool: FFTW3F library found and enabled.
radio.platform.versions.liquid
string: Liquid-dsp library version.
radio.platform.versions.volk
string: VOLK library version.
radio.platform.versions.fftw3f
string: FFTW3F library version.