LuaRadio signal processing framework for software-defined radio

Інсталяція JIT LUA

Компіляція

git clone https://github.com/vsergeev/luaradio.git
cd luaradio/embed
sudo make install-lmod

Залежності

sudo apt-get install luajit libluajit-5.1-dev pkg-config
sudo apt-get install -y gnuplot
sudo apt-get install libliquid-dev libvolk2-dev libfftw3-dev

Перший запуск

luaradio ./rtlsdr_ssb.lua 14.225e6 usb

Приклади використання

Приймач wbfm_mono з pipeline до rtl_sdr

rtl_sdr -g 44.5 -f 103000000 - | /usr/local/bin/luaradio /home/admin/luaradio/examples/stdin_wbfm_mono.lua

local radio = require('radio')



--local tune_offset = -250e3
local tune_offset = 0

-- Blocks
local source = radio.IQFileSource(io.stdin, 's8', 2048000)
local tuner = radio.TunerBlock(tune_offset, 200e3, 5)
local fm_demod = radio.FrequencyDiscriminatorBlock(1.25)
local af_filter = radio.LowpassFilterBlock(128, 15e3)
local af_deemphasis = radio.FMDeemphasisFilterBlock(75e-6)
local af_downsampler = radio.DownsamplerBlock(5)
local sink = os.getenv('DISPLAY') and radio.PulseAudioSink(1) or radio.WAVFileSink('wbfm_mono.wav', 1)

-- Plotting sinks
local plot1 = radio.GnuplotSpectrumSink(2048, 'Demodulated FM Spectrum', {yrange = {-120, -40}})

-- Connections
local top = radio.CompositeBlock()
top:connect(source, tuner, fm_demod, af_filter, af_deemphasis, af_downsampler, sink)
if os.getenv('DISPLAY') then
    --top:connect(fm_demod, plot1)
    
end

top:run()

Запуск luaradio через pipeline до свистка

rtl_sdr -g 44.5 -f 103000000 - | /usr/local/bin/luaradio /home/admin/luaradio/examples/stdin_wbfm_mono.lua

local radio = require('radio')



--local tune_offset = -250e3
local tune_offset = 0

-- Blocks
local source = radio.IQFileSource(io.stdin, 's8', 2048000)
local tuner = radio.TunerBlock(tune_offset, 200e3, 5)
local fm_demod = radio.FrequencyDiscriminatorBlock(1.25)
local af_filter = radio.LowpassFilterBlock(128, 15e3)
local af_deemphasis = radio.FMDeemphasisFilterBlock(75e-6)
local af_downsampler = radio.DownsamplerBlock(5)
local sink = os.getenv('DISPLAY') and radio.PulseAudioSink(1) or radio.WAVFileSink('wbfm_mono.wav', 1)

-- Plotting sinks
local plot1 = radio.GnuplotSpectrumSink(2048, 'Demodulated FM Spectrum', {yrange = {-120, -40}})

-- Connections
local top = radio.CompositeBlock()
top:connect(source, tuner, fm_demod, af_filter, af_deemphasis, af_downsampler, sink)
if os.getenv('DISPLAY') then
    --top:connect(fm_demod, plot1)
    
end

top:run()

Приклад одночасного прийому сигналів з одного IQ потоку

Here is an example with 4 parallel WBFM mono receivers:

    local radio = require('radio')
   
    -- Source at center frequency 94.3 MHz, 6 MHz sample rate
    local source = radio.AirspySource(94.3e6, 6e6)
   
    -- Receiver #1 at 93.1 MHz
    local tuner1 = radio.TunerBlock(1.2e6, 250e3, 25)
    local demod1 = radio.WBFMMonoDemodulator()
    local downsampler1 = radio.DownsamplerBlock(5)
    local sink1 = radio.PulseAudioSink(1)
   
    -- Receiver #2 at 93.9 MHz
    local tuner2 = radio.TunerBlock(0.4e6, 250e3, 25)
    local demod2 = radio.WBFMMonoDemodulator()
    local downsampler2 = radio.DownsamplerBlock(5)
    local sink2 = radio.PulseAudioSink(1)
   
    -- Receiver #3 at 94.7 MHz
    local tuner3 = radio.TunerBlock(-0.4e6, 250e3, 25)
    local demod3 = radio.WBFMMonoDemodulator()
    local downsampler3 = radio.DownsamplerBlock(5)
    local sink3 = radio.PulseAudioSink(1)
   
    -- Receiver #4 at 95.5 MHz
    local tuner4 = radio.TunerBlock(-1.2e6, 250e3, 25)
    local demod4 = radio.WBFMMonoDemodulator()
    local downsampler4 = radio.DownsamplerBlock(5)
    local sink4 = radio.PulseAudioSink(1)
   
    local top = radio.CompositeBlock()
    top:connect(source, tuner1, demod1, downsampler1, sink1)
    top:connect(source, tuner2, demod2, downsampler2, sink2)
    top:connect(source, tuner3, demod3, downsampler3, sink3)
    top:connect(source, tuner4, demod4, downsampler4, sink4)
    top:run()

Or, more concisely with a loop:

    local radio = require('radio')
   
    local center_frequency = 94.3e6
    local stations = {93.1e6, 93.9e6, 94.7e6, 95.5e6}
   
    local top = radio.CompositeBlock()
   
    -- Source
    local source = radio.AirspySource(center_frequency, 6e6)
   
    -- Receivers
    for _, frequency in ipairs(stations) do
        local tuner = radio.TunerBlock(frequency - center_frequency, 250e3, 25)
        local demod = radio.WBFMMonoDemodulator()
        local downsampler = radio.DownsamplerBlock(5)
        local sink = radio.PulseAudioSink(1)
        top:connect(source, tuner, demod, downsampler, sink)
    end
   
    top:run()

Джерело

SSB receiver with RDL-SDR

Але треба підкрутити AGC

local radio = require('radio')

local bandwidth = 2e3


local source = radio.RtlSdrSource(68.330e6, 24e5, {rf_gain = 10.0})


local tuner = radio.TunerBlock(1700, 2*bandwidth, 50)
local sb_filter = radio.ComplexBandpassFilterBlock(129, {0, bandwidth})
local am_demod = radio.ComplexToRealBlock()
local af_filter = radio.LowpassFilterBlock(128, bandwidth)
local af_gain = radio.AGCBlock('custom', -30, -100, {gain_tau = 0.5})
--local af_gain = radio.MultiplyConstantBlock(100.0)
--local sink = radio.PulseAudioSink(1)
local sink = radio.WAVFileSink('ssb.wav', 1)

-- Plotting sinks
local plot1 = radio.GnuplotSpectrumSink(2048, 'RF Spectrum', {xrange = {-3100,
                                                                        3100},
                                                              yrange = {-120, -40}})

local top = radio.CompositeBlock()
top:connect(source, tuner, sb_filter, am_demod, af_filter, af_gain, sink)
--top:connect(tuner, plot1)


top:run()