| name | gnu-radio |
| description | GNU Radio SDR toolkit for signal processing flowgraphs with Python blocks |
| metadata | {"skill_type":"SDR / Signal Processing / Python","interface_ports":["Flowgraphs","Python Blocks","Hardware SDR"]} |
| trit | -1 |
| color | #4A90D9 |
| parents | ["muchas-radio","whitehole-audio","gay-mcp"] |
| seed | 3800 |
GNU Radio SDR Skill
Status: Active
Trit: -1 (MINUS - signal consumption/analysis)
Seed: 3800 (RF frequency reference)
Color: #4A90D9 (radio blue)
"Flowgraphs are signal poems. Blocks are the words."
Overview
GNU Radio is a free, open-source software development toolkit for signal processing. It provides:
- Flowgraphs: Visual signal processing chains
- Blocks: Modular DSP components (filters, modulators, decoders)
- Python Integration: Embedded Python blocks for custom processing
- Hardware Support: RTL-SDR, HackRF, USRP, PlutoSDR, and more
Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GNU RADIO FLOWGRAPH โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โ
โ โ Source โโโโโถโ Filter โโโโโถโ Demod โโโโโถโ Sink โ โ
โ โ (SDR) โ โ (LPF) โ โ (FM) โ โ (Audio) โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โ
โ โ โ โ โ โ
โ โผ โผ โผ โผ โ
โ [complex] [complex] [float] [float] โ
โ trit: +1 trit: 0 trit: -1 trit: +1 โ
โ โ
โ GF(3) Conservation: +1 + 0 + (-1) + (+1) โก 1 (mod 3) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Installation
flox install gnuradio
brew install gnuradio
sudo apt install gnuradio
git clone https://github.com/gnuradio/gnuradio.git
cd gnuradio && mkdir build && cd build
cmake .. && make -j$(nproc) && sudo make install
Block Types
| Type | Purpose | GF(3) Role |
|---|
| Source | Generate/receive signals | +1 (PLUS) |
| Sync | Sample-rate processing | 0 (ERGODIC) |
| Sink | Output/consume signals | -1 (MINUS) |
| Hier | Hierarchical sub-flowgraph | 0 (ERGODIC) |
Embedded Python Block
"""
Embedded Python Block - GF(3) Trit Tagger
Tags samples with spatial trit based on frequency
"""
import numpy as np
from gnuradio import gr
class blk(gr.sync_block):
"""GF(3) Trit Tagger for RF signals"""
def __init__(self, center_freq=100e6):
gr.sync_block.__init__(
self,
name='GF3 Trit Tagger',
in_sig=[np.complex64],
out_sig=[np.complex64]
)
self.center_freq = center_freq
self.trit = self._freq_to_trit(center_freq)
def _freq_to_trit(self, freq):
"""Map frequency to GF(3) trit"""
if freq < 300e6:
return 1
elif freq < 3e9:
return 0
else:
return -1
def work(self, input_items, output_items):
self.add_item_tag(
0,
self.nitems_written(),
pmt.intern(),
pmt.from_long(.trit)
)
output_items[][:] = input_items[]
(output_items[])
Flowgraph Examples
FM Radio Receiver
from gnuradio import gr, blocks, analog, audio, filter
from gnuradio.filter import firdes
import osmosdr
class fm_radio(gr.top_block):
def __init__(self, freq=100.1e6):
gr.top_block.__init__(self, "FM Radio")
self.source = osmosdr.source(args="rtl=0")
self.source.set_sample_rate(2.4e6)
self.source.set_center_freq(freq)
self.source.set_gain(40)
self.lpf = filter.fir_filter_ccf(
10,
firdes.low_pass(1, 2.4e6, 100e3, 10e3)
)
self.demod = analog.wbfm_receive(
quad_rate=240e3,
audio_decimation=5
)
self.audio_sink = audio.sink(48000)
self.connect(self.source, .lpf, .demod, .audio_sink)
__name__ == :
tb = fm_radio(freq=)
tb.start()
()
tb.stop()
tb.wait()
Spectrum Analyzer
from gnuradio import gr, blocks, fft
from gnuradio.fft import window
import numpy as np
import json
class spectrum_analyzer(gr.top_block):
def __init__(self, center_freq=100e6, samp_rate=2.4e6):
gr.top_block.__init__(self, "Spectrum Analyzer")
self.fft_size = 1024
self.source = osmosdr.source(args="rtl=0")
self.source.set_sample_rate(samp_rate)
self.source.set_center_freq(center_freq)
self.fft = fft.fft_vcc(
self.fft_size,
True,
window.blackmanharris(self.fft_size),
True
)
self.s2v = blocks.stream_to_vector(
gr.sizeof_gr_complex,
self.fft_size
)
self.mag = blocks.complex_to_mag_squared(self.fft_size)
self.sink = blocks.probe_signal_vf(self.fft_size)
.connect(.source, .s2v, .fft, .mag, .sink)
():
data = .sink.level()
json.dumps({
: data.tolist(),
: ,
: .fft_size
})
Integration with Muchas Radio
from gnuradio import gr, audio
import subprocess
import os
class RadioToMPD(gr.top_block):
"""Stream GNU Radio audio to MPD via FIFO"""
def __init__(self, samp_rate=48000):
gr.top_block.__init__(self, "Radio to MPD")
self.fifo_path = "/tmp/gnuradio_audio.fifo"
if not os.path.exists(self.fifo_path):
os.mkfifo(self.fifo_path)
self.audio_source = audio.source(samp_rate)
self.file_sink = blocks.file_sink(
gr.sizeof_float,
self.fifo_path,
False
)
self.connect(self.audio_source, self.file_sink)
def start_mpd_stream(self):
"""Tell MPD to play from FIFO"""
subprocess.run([
"mpc", "add", f"file://{self.fifo_path}"
])
subprocess.run(["mpc", "play"])
GF(3) Signal Triads
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GF(3) SIGNAL TRIADS โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ RF Triad: โ
โ Source (+1) โ Channel (0) โ Sink (-1) = 0 โ โ
โ โ
โ Frequency Triad: โ
โ VHF (+1) โ UHF (0) โ SHF (-1) = 0 โ โ
โ โ
โ Processing Triad: โ
โ Modulate (+1) โ Filter (0) โ Demodulate (-1) = 0 โ โ
โ โ
โ Audio Triad: โ
โ Capture (+1) โ Process (0) โ Playback (-1) = 0 โ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Hardware Support
| Device | Interface | Freq Range | Sample Rate |
|---|
| RTL-SDR | USB | 24-1766 MHz | 2.4 MS/s |
| HackRF | USB | 1-6000 MHz | 20 MS/s |
| USRP | USB/Eth | DC-6 GHz | 200 MS/s |
| PlutoSDR | USB | 70-6000 MHz | 61.44 MS/s |
| LimeSDR | USB | 100k-3.8 GHz | 61.44 MS/s |
Commands
gnuradio-companion
python3 my_flowgraph.py
gr_modtool info
gr_modtool newmod my_blocks
gr_modtool add -t sync -l python my_block
cd build && cmake .. && make && sudo make install
GR4 (Next Generation)
GNU Radio 4.0 brings:
- C++20 with concepts and ranges
- Reflection-based block definitions
- Graph-based scheduling
- Better performance via SIMD
template<typename T>
struct Multiply : gr::Block<Multiply<T>> {
gr::PortIn<T> in;
gr::PortOut<T> out;
float factor = 1.0f;
gr::work::Status processBulk(auto& ins, auto& outs) {
std::ranges::transform(ins, outs.begin(),
[this](auto x) { return x * factor; });
return gr::work::Status::OK;
}
};
Related Skills
| Skill | Connection |
|---|
muchas-radio | Audio streaming integration |
whitehole-audio | Audio loopback driver |
gay-mcp | GF(3) trit coloring |
pluscode-zig | Location-based frequency allocation |
fokker-planck-analyzer | Signal diffusion analysis |
Environment Variables
GR_CONF_CONTROLPORT_ON=True
GR_CONF_CONTROLPORT_EDGES_LIST=True
PYTHONPATH=/usr/local/lib/python3/dist-packages:$PYTHONPATH
SOAPY_SDR_ROOT=/usr/local
RTL_TCP_SERVER=127.0.0.1:1234
GR_TRIT_TAGGING=true
GR_TRIT_SOURCE=pluscode
Skill Name: gnu-radio
Type: SDR / Signal Processing / Python
Trit: -1 (MINUS - signal consumption)
Seed: 3800
Key Insight: Flowgraphs are compositional signal processing with GF(3) conservation
Repository: github.com/gnuradio/gnuradio
Autopoietic Marginalia
The interaction IS the skill improving itself.
Every use of this skill is an opportunity for worlding:
- MEMORY (-1): Record what was learned
- REMEMBERING (0): Connect patterns to other skills
- WORLDING (+1): Evolve the skill based on use
Add Interaction Exemplars here as the skill is used.