### Quick Start Source: https://github.com/xoolive/desperado/blob/main/crates/rs-rtl/readme.md Basic usage example for initializing an SDR device, setting parameters, and starting to stream IQ samples. ```rust use rs_rtl::{DeviceId, RtlSdr}; let mut sdr = RtlSdr::open(DeviceId::Index(0))?; sdr.set_center_freq(100_000_000)?; sdr.set_sample_rate(2_048_000)?; sdr.set_gain_manual(496)?; let reader = sdr.start_streaming()?; while let Some(data) = reader.recv() { // data contains interleaved u8 I/Q samples: [I0, Q0, I1, Q1, ...] println!("received {} bytes", data.len()); } ``` -------------------------------- ### Build and Run Commands Source: https://github.com/xoolive/desperado/blob/main/agents.md Commands for building and running specific applications and examples within the project. ```sh cargo build -p fmradio --release --bin fmradio # FM radio CLI app cargo run --example airspy_info # Airspy device info cargo run --example airspy_tune # Airspy tuning/configuration cargo run --example airspy_rx # Airspy streaming to file ``` -------------------------------- ### RTL-SDR Async Example Source: https://github.com/xoolive/desperado/blob/main/readme.md An example demonstrating how to access RTL-SDR devices using the asynchronous `IqAsyncSource`. ```rust use desperado::IqAsyncSource; use futures::StreamExt; #[tokio::main] async fn main() -> desperado::Result<()> { let device_index = 0; let sample_rate = 2_400_000; let center_freq = 1_090_000_000; let gain = Some(496); let reader = IqAsyncSource::from_rtlsdr(device_index, center_freq, sample_rate, gain).await?; while let Some(samples) = reader.next().await { // Process samples... } Ok(()) } ``` -------------------------------- ### Basic example (synchronous version) Source: https://github.com/xoolive/desperado/blob/main/readme.md A basic example demonstrating how to use the synchronous version of Desperado to read I/Q samples from a file. ```rust use desperado::{IqFormat, IqSource}; fn main() -> desperado::Result<()> { // Create an IQ source from a binary file let path = "sample.iq"; let sample_rate = 96_000; let center_freq = 162_000_000; let chunk_size = 8136; let iq_format = IqFormat::Cu8; for samples in IqSource::from_file(path, center_freq, sample_rate, chunk_size, iq_format)? { for s in samples? { // samples is a Result>, _> println!(" I: {}, Q: {}", s.re, s.im); } } Ok(()) } ``` -------------------------------- ### Building specific components Source: https://github.com/xoolive/desperado/blob/main/agents.md Core crates ```sh # Core crates cargo build -p desperado --release # I/Q streaming and DSP primitives cargo build -p fmradio --release # FM radio receiver cargo build -p rs-spy --release # Airspy hardware driver ``` -------------------------------- ### Initial build Source: https://github.com/xoolive/desperado/blob/main/agents.md Development build (thin LTO, faster: ~47s incremental, keeps symbols) ```sh # Development build (thin LTO, faster: ~47s incremental, keeps symbols) cargo build --release --all-features # Distribution build (full LTO, optimal binary: ~94s incremental, stripped) cargo build --profile dist --all-features ``` -------------------------------- ### Chunk Size Selection Examples Source: https://github.com/xoolive/desperado/blob/main/readme.md Examples of setting chunk sizes for different use cases: real-time decoding, general SDR processing, and batch file processing. ```rust // Real-time ADS-B decoding (low latency needed) let source = IqSource::from_file(path, freq, rate, 4096, format)?; // General SDR processing (balanced) let source = IqSource::from_file(path, freq, rate, 16384, format)?; // Batch file processing (maximum throughput) let source = IqSource::from_file(path, freq, rate, 65536, format)?; ``` -------------------------------- ### Device Discovery Source: https://github.com/xoolive/desperado/blob/main/crates/rs-rtl/readme.md Example demonstrating how to discover available RTL-SDR devices and print their details. ```rust use rs_rtl::DeviceDescriptors; for dev in DeviceDescriptors::new()?.iter() { println!("#{}: {} {} (serial: {:?})", dev.index, dev.manufacturer.as_deref().unwrap_or("?"), dev.product.as_deref().unwrap_or("?"), dev.serial, ); } ``` -------------------------------- ### Build MkDocs Site Source: https://github.com/xoolive/desperado/blob/main/agents.md Commands to serve a local preview of the MkDocs site and to build the static site. ```sh uvx --with "mkdocs-material[imaging]" mkdocs serve # Local preview uvx --with "mkdocs-material[imaging]" mkdocs build -d site # Build static site ``` -------------------------------- ### Extract Audio Example 2 Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Command to regenerate audio fixtures using the extract_audio example. ```bash cargo run --release --example extract_audio -- \ samples/gqrx_20251107_182558_116000000_1800000_fc.raw \ 116.0 116.0 tests/data/gqrx_20251107_182558_116000000_1800000_fc 26 ``` -------------------------------- ### Example 1: Listen and Log Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Listen to 99.1 MHz and save RDS data to a file. ```bash cargo run --release -p fmradio -- rtlsdr:// -c 99.1M > rds_log.jsonl & # Press Ctrl+C to stop ``` -------------------------------- ### Example 3: Headless Monitoring Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Monitor RDS with no audio playback. ```bash cargo run --release -p fmradio -- rtlsdr:// -c 98.1M --no-audio | jq '.ps' ``` -------------------------------- ### Example 2: Network Streaming Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Stream FM audio over network. ```bash # Receiver cargo run --release -p fmradio -- rtlsdr:// -c 103.5M | nc -l localhost 12345 # Client nc localhost 12345 | play -r 48000 -t raw -e s -b 16 -c 2 - ``` -------------------------------- ### Extract Audio Example 1 Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Command to regenerate audio fixtures using the extract_audio example. ```bash cargo run --release --example extract_audio -- \ samples/gqrx_20250925_144051_114647000_1800000_fc.raw \ 114.85 114.647 tests/data/gqrx_20250925_144051_114647000_1800000_fc ``` -------------------------------- ### Install Voracious Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Build the Voracious CLI tool from source using Cargo. ```bash cargo build --release -p voracious ``` ```bash cargo build --release -p voracious --no-default-features ``` -------------------------------- ### View GitHub Issue Source: https://github.com/xoolive/desperado/blob/main/agents.md Commands to view a specific GitHub issue and its comments. ```sh # Always read ALL comments before planning gh issue view 123 gh issue view 123 --comments ``` -------------------------------- ### Build All Workspace Crates Source: https://github.com/xoolive/desperado/blob/main/agents.md Command to build all crates in the workspace in release mode. ```sh cargo build --release --workspace ``` -------------------------------- ### Build and Open Rust API Docs Source: https://github.com/xoolive/desperado/blob/main/agents.md Command to build and open the Rust API documentation in the default browser. ```sh cargo doc --all-features --no-deps --open ``` -------------------------------- ### Project structure Source: https://github.com/xoolive/desperado/blob/main/agents.md The project is organized as a Rust workspace with specialized crates for DSP, hardware drivers, and domain-specific decoders. ```tree desperado/ ├── crates/ │ ├── dabradio/ # DAB/DAB+ decoder (OFDM, FIC/FIB, AAC audio) │ ├── desperado/ # Core I/Q streaming and DSP primitives │ ├── fmradio/ # FM radio receiver and RDS decoder │ ├── rs-rtl/ # RTL-SDR (RTL2832U) hardware driver (librtlsdr in Rust) │ ├── rs-spy/ # Airspy R2/Mini/HF+ hardware driver (libairspy in Rust) │ └── voracious/ # VOR/ILS/DME aviation navigation decoder ├── analysis/ # Analysis documents and refactoring recommendations ├── docs/ # MkDocs documentation (deployed to mode-s.org/desperado) ├── plan.md # Development roadmap and milestone tracking ├── agents.md # This file - agent development guidelines ├── lessons_learned.md # Project history, mistakes, and best practices └── README.md ``` -------------------------------- ### Runtime Control During Streaming Source: https://github.com/xoolive/desperado/blob/main/crates/rs-rtl/readme.md Example showing how to control SDR parameters like frequency and gain while streaming is active. ```rust use rs_rtl::{DeviceId, RtlSdr}; let mut sdr = RtlSdr::open(DeviceId::Index(0))?; sdr.set_center_freq(100_000_000)?; sdr.set_sample_rate(2_048_000)?; sdr.set_gain_manual(296)?; let reader = sdr.start_streaming()?; // Get a clonable control handle for use from any thread let ctrl = reader.control_handle(); ctrl.tune(200_000_000)?; ctrl.set_gain(400)?; ctrl.set_gain_auto()?; ``` -------------------------------- ### Run All Tests (Workspace-wide) Source: https://github.com/xoolive/desperado/blob/main/agents.md Command to execute all Rust tests across the entire workspace. ```sh cargo test --lib --workspace ``` -------------------------------- ### Build Rust Documentation Source: https://github.com/xoolive/desperado/blob/main/agents.md Commands to build Rust API documentation for the project, with options to include all features, exclude dependencies, and open in a browser. ```sh cargo doc --all-features --no-deps # Build docs cargo doc --all-features --no-deps --open # Build and open in browser ``` -------------------------------- ### Get Test Count Summary Source: https://github.com/xoolive/desperado/blob/main/agents.md Command to display the summary of test results, useful for counting tests. ```sh cargo test --lib --workspace 2>&1 | tail -5 # Shows summary ``` -------------------------------- ### Device Info Source: https://github.com/xoolive/desperado/blob/main/crates/rs-spy/readme.md Example of how to open a device, and retrieve firmware version, board ID, and supported sample rates. ```rust use rs_spy::Airspy; let device = Airspy::open_first()?; println!("Firmware: {}", device.version()?); println!("Board ID: {}", device.board_id()?); println!("Sample rates: {:?}", device.supported_sample_rates()?); let (part1, part2, serial) = device.board_partid_serialno()?; println!("Serial: {:016x}", serial); ``` -------------------------------- ### Release Command Source: https://github.com/xoolive/desperado/blob/main/agents.md Command for managing project releases using cargo-release. ```sh cargo release [patch,minor] ``` -------------------------------- ### Check Rust Documentation Issues Source: https://github.com/xoolive/desperado/blob/main/agents.md Command to check for documentation issues using RUSTDOCFLAGS. ```sh RUSTDOCFLAGS="-D rustdoc::all -A rustdoc::private-doc-tests" cargo doc --all-features --no-deps ``` -------------------------------- ### Rust Formatting Source: https://github.com/xoolive/desperado/blob/main/agents.md Commands to format all Rust code in the project and to check formatting without modifying files. ```sh cargo fmt --all # Format all code cargo fmt --all --check # Check without modifying ``` -------------------------------- ### Markdown for Lessons Learned Task Source: https://github.com/xoolive/desperado/blob/main/agents.md A markdown snippet demonstrating how to include the 'Update lessons_learned.md' task in a todo list. ```markdown - [ ] Update lessons_learned.md with any new insights or mistakes encountered ``` -------------------------------- ### Real-to-IQ Conversion Source: https://github.com/xoolive/desperado/blob/main/crates/rs-spy/readme.md Example demonstrating how to use the IqConverter to transform real ADC samples into complex I/Q pairs. ```rust use rs_spy::IqConverter; let mut converter = IqConverter::new(); // Convert 16-bit real samples to f32 first, then process let mut samples: Vec = raw_u16_samples.iter() .map(|&s| s as f32 / 32768.0) .collect(); // In-place conversion: even indices become I, odd become Q converter.process(&mut samples); // Or get Complex directly (output length = input length / 2) let iq_pairs = converter.process_to_complex(&mut samples); ``` -------------------------------- ### Live SDR sources Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md Examples for using live SDR sources like RTL-SDR, SoapySDR, and Airspy. Requires building with specific features. ```bash # RTL-SDR (build with --features rtlsdr) ./target/release/dabradio rtlsdr:// --channel 12A --service "FIP" # SoapySDR (build with --features soapy) ./target/release/dabradio soapy://driver=rtlsdr --channel 12A --service "FIP" # Airspy (build with --features airspy) ./target/release/dabradio airspy://0 --channel 12A --service "FIP" ``` -------------------------------- ### Open GitHub Issue Source: https://github.com/xoolive/desperado/blob/main/agents.md Command to create a new GitHub issue, emphasizing the need for user acknowledgement before execution. ```sh # Never open issues without user acknowledgement gh issue create --title "Title" --body "Description" ``` -------------------------------- ### Configuration & Synchronous Read Source: https://github.com/xoolive/desperado/blob/main/crates/rs-spy/readme.md Example of configuring the device (frequency, sample rate, gain) and performing a synchronous read of raw samples. ```rust use rs_spy::Airspy; let device = Airspy::open_first()?; device.set_freq(100_000_000)?; device.set_sample_rate(0)?; device.set_linearity_gain(15)?; device.start_rx()?; let mut buf = vec![0u8; rs_spy::RECOMMENDED_BUFFER_SIZE]; let n = device.read_sync(&mut buf)?; // buf contains raw 16-bit real ADC samples (little-endian) device.stop_rx()?; ``` -------------------------------- ### Run Tests for Specific Crate Source: https://github.com/xoolive/desperado/blob/main/agents.md Commands to run Rust tests for individual crates within the workspace. ```sh cargo test -p desperado --lib cargo test -p fmradio --lib cargo test -p rs-spy --lib ``` -------------------------------- ### Create GitHub Pull Request Source: https://github.com/xoolive/desperado/blob/main/agents.md Commands to create a new GitHub pull request, including linking to an issue and emphasizing the need for user acknowledgement. ```sh # Never open PR without user acknowledgement gh pr create --title "Title" --body "Description" # Link to issue gh pr create --title "Fix altitude bug" --body "Fixes #123" ``` -------------------------------- ### Library Usage Example Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Demonstrates how to use the Voracious library in Rust to decode VOR signals from an I/Q source, process the results, and handle potential errors. ```rust use voracious::{IqSource, IqFormat}; let source = IqSource::new( "samples.cf32", 1_800_000, // sample rate (Hz) IqFormat::Cf32, 114.85, // VOR frequency (MHz) 114.647, // SDR center frequency (MHz) 3.0, // radial window (seconds) 15.0, // Morse window (seconds) false, // debug_morse )?; for result in source { match result { Ok(radial) => println!({"radial_deg:.1}° ident={{:?}}", radial.radial_deg, radial.ident), Err(e) => eprintln!("Error: {}", e), } } ``` -------------------------------- ### I/Q File Validation Commands Source: https://github.com/xoolive/desperado/blob/main/agents.md Commands to validate various I/Q file decoders, including project, purpose, and the specific command to run. ```bash jet1090 file ``` ```bash ship162 file ``` ```bash dabradiod --input file ``` ```bash fmradio --center-freq 110.25M --sample-rate 1102500 file ``` ```bash dumpvdl2 -r file ``` ```bash acarsdec -r file ``` ```bash voracious --vor-freq 114.85 ``` ```bash voracious --vor-freq 116 ``` ```bash voracious --ils-freq 108.8 --center-freq 114.647 ``` -------------------------------- ### HackRF udev rule (Linux) Source: https://github.com/xoolive/desperado/blob/main/readme.md Example udev rule for granting access to HackRF USB device on Linux. ```bash # /etc/udev/rules.d/52-hackrf.rules SUBSYSTEM=="usb", ATTR{idVendor}=="1d50", ATTR{idProduct}=="6089", MODE="0666" ``` -------------------------------- ### Run Specific Test Source: https://github.com/xoolive/desperado/blob/main/agents.md Command to run a single, named Rust test, with output capture enabled. ```sh cargo test test_name -- --nocapture ``` -------------------------------- ### List all services in a DAB ensemble Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md Examples for listing services using different IQ sample formats (cu8, cf32, cs16). ```bash # cu8 format (RTL-SDR raw samples) ./target/release/dabradio recording.cu8 --channel 12A # cf32 format (gqrx raw complex float) ./target/release/dabradio recording.cf32 --channel 12A --format cf32 # cs16 format (signed 16-bit I/Q) ./target/release/dabradio recording.cs16 --channel 12A --format cs16 ``` -------------------------------- ### Multi-Transfer Streaming Source: https://github.com/xoolive/desperado/blob/main/crates/rs-spy/readme.md Example of setting up multi-transfer streaming, which allows for continuous data reception in a background thread and runtime control. ```rust use rs_spy::Airspy; let device = Airspy::open_first()?; device.set_freq(100_000_000)?; device.set_sample_rate(0)?; device.set_sensitivity_gain(18)?; device.start_rx()?; // Consumes device, starts background streaming thread let reader = device.into_multi_transfer_reader(0, 0)?; // Runtime control from any thread let ctrl = reader.control_handle(); ctrl.tune(200_000_000)?; while let Some(Ok(data)) = reader.recv() { // data: Vec of raw 16-bit real ADC samples println!("received {} bytes", data.len()); } ``` -------------------------------- ### Band Scan - Tune RDS Confirmation Workload Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Configures the RDS confirmation workload for the fm_scan example with specific thresholds and timeouts. ```bash cargo run --release -p fmradio --example fm_scan -- \ --source rtlsdr:// \ --rds-score-threshold 6.0 --rds-verify-seconds 4 --rds-min-separation-khz 300 ``` -------------------------------- ### Output formats Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md Examples for outputting service listings in JSON format and limiting frame processing. ```bash # JSON service listing ./target/release/dabradio recording.cu8 --channel 12A --json # Limit frame processing (useful for testing) ./target/release/dabradio recording.cu8 --channel 12A --max-frames 100 ``` -------------------------------- ### Rust Linting Source: https://github.com/xoolive/desperado/blob/main/agents.md Command to run Clippy linter across the entire workspace with all targets and features, enforcing warnings as errors. ```sh cargo clippy --workspace --all-targets --all-features -- -D warnings ``` -------------------------------- ### Band Scan (Naive Signal Ranking) - Recommended Default Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Performs a band scan using the fm_scan example, with default settings for RTL-SDR. ```bash cargo run --release -p fmradio --example fm_scan -- --source rtlsdr:// ``` -------------------------------- ### Band Scan - Debug RDS Selection Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Enables detailed logging for frequency selection and fallback logic during RDS verification in the fm_scan example. ```bash cargo run --release -p fmradio --example fm_scan --debug-rds-selection ``` -------------------------------- ### Extract DLS Metadata and MOT Slideshow Images Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md Examples for displaying DLS text metadata and extracting MOT slideshow images (album art, cover art) to a directory. ```bash # Display DLS text metadata while decoding audio ./target/release/dabradio recording.cu8 --channel 12A --service "FIP" --metadata # Extract MOT slideshow images to directory (album art, cover art, etc.) ./target/release/dabradio recording.cu8 --channel 12A --service "FIP" \ --metadata --slideshow /tmp/fip_slides # Extract images without audio playback ./target/release/dabradio recording.cu8 --channel 12A --service "FIP" \ --metadata --slideshow /tmp/fip_slides --no-audio ``` -------------------------------- ### Decode audio from a specific service Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md Examples for decoding audio from a specific service by label or SId, and for saving raw DAB+ frames to a file. ```bash # Play audio from "FRANCE CULTURE" to soundcard ./target/release/dabradio recording.cu8 --channel 12A --service "FRANCE CULTURE" # Decode by hex SId instead of label ./target/release/dabradio recording.cu8 --channel 12A --service 0xF202 # Save raw DAB+ frames to file (no audio output) ./target/release/dabradio recording.cu8 --channel 12A --service "FRANCE CULTURE" \ --output frames.bin --no-audio ``` -------------------------------- ### Testing Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Run the full test suite. ```bash cargo test -p fmradio ``` -------------------------------- ### Build with SoapySDR backend Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Builds the fmradio crate with optional SoapySDR backend support. ```bash cargo build --release -p fmradio --features soapy ``` -------------------------------- ### Capture I/Q Samples with SoapySDR Source: https://github.com/xoolive/desperado/blob/main/readme.md Command to capture I/Q samples using SoapySDR. ```bash SoapySDRUtil --rate=2.4e6 --freq=1090e6 --output=adsb_sample.iq ``` -------------------------------- ### Configuration & Synchronous Read Source: https://github.com/xoolive/desperado/blob/main/crates/rs-hackrf/readme.md Shows how to configure a HackRF device (frequency, sample rate, gains) and perform a synchronous read of I/Q samples. ```rust use rs_hackrf::HackRf; let mut device = HackRf::open_first()?; device.set_freq(100_000_000)?; // 100 MHz device.set_sample_rate(8_000_000)?; // 8 MS/s device.set_lna_gain(24)?; // 24 dB (0-40, 8 dB steps) device.set_vga_gain(20)?; // 20 dB (0-62, 2 dB steps) device.start_rx()?; let mut buf = vec![0u8; rs_hackrf::RECOMMENDED_BUFFER_SIZE]; let n = device.read_sync(&mut buf)?; // buf contains interleaved i8 I/Q: [I0, Q0, I1, Q1, ...] device.stop_rx()?; ``` -------------------------------- ### Example RDS JSON Output Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Illustrative JSON output for different RDS groups (0A, 2A, 4A) as produced by the fmradio. ```json {"group":"0A","ps":"KISS FM","af":[98.1,99.0,101.5]} {"group":"2A","rt":"Now Playing: Artist - Song Title"} {"group":"4A","time":"2026-02-11T14:23:45Z"} ``` -------------------------------- ### Testing Source: https://github.com/xoolive/desperado/blob/main/crates/rs-rtl/readme.md Command to run unit tests for the rs-rtl crate. ```bash cargo test -p rs-rtl ``` -------------------------------- ### Capture I/Q Samples with RTL-SDR Source: https://github.com/xoolive/desperado/blob/main/readme.md Command to capture I/Q samples using RTL-SDR. ```bash rtl_sdr -f 1090000000 -s 2400000 -n 24000000 adsb_sample.iq ``` -------------------------------- ### Build with default (RTL-SDR + Airspy) Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Builds the fmradio crate with support for RTL-SDR and Airspy backends. ```bash cargo build --release -p fmradio ``` -------------------------------- ### Building dabradio Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md Build dabradio from the desperado workspace root. Optionally enable live SDR backends. ```bash # From the desperado workspace root: cargo build --release -p dabradio # Enable live SDR backends as needed: cargo build --release -p dabradio --features rtlsdr cargo build --release -p dabradio --features soapy cargo build --release -p dabradio --features airspy ``` -------------------------------- ### Testing Commands Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md Commands for running tests, checking for clippy warnings, and building the project. ```bash # Run all tests cargo test -p dabradio # Run tests with output cargo test -p dabradio -- --nocapture # Check for clippy warnings cargo clippy -p dabradio --tests # Build with optimizations cargo build --release -p dabradio ``` -------------------------------- ### With redsea (Reference RDS Decoder) Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Integration with redsea. ```bash fmradio rtlsdr:// -c 103.5M --raw-out --resample-out 171000 | redsea -r 171000 ``` -------------------------------- ### With sox/play Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Integration with sox/play. ```bash fmradio rtlsdr:// -c 99.1M | play -t raw -r 48000 -e s -b 16 -c 2 - ``` -------------------------------- ### Enable trace-level logging Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md Enable trace-level logging to see frequency estimation and synchronization details. ```bash RUST_LOG=trace ./target/release/dabradio recording.cu8 --channel 12A --max-frames 5 ``` -------------------------------- ### Decode from a live SDR Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Decode VOR signals directly from a live Software Defined Radio (SDR) device. Examples are provided for RTL-SDR, Airspy, and generic SoapySDR devices. ```bash # RTL-SDR (center frequency defaults to VOR frequency) voracious rtlsdr:// --vor-freq 114.85 # Airspy device 0 voracious airspy:// --vor-freq 116 --sample-rate 2500000 # SoapySDR with embedded tuning voracious "soapy://driver=rtlsdr?freq=114.85M&rate=1.8M" --vor-freq 114.85 ``` -------------------------------- ### With ffmpeg Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Integration with ffmpeg. ```bash fmradio rtlsdr:// -c 103.5M | ffmpeg -f s16le -ar 48000 -ac 2 -i - output.mp3 ``` -------------------------------- ### Unit Tests Command Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Command to run unit tests for the voracious crate. ```bash cargo test -p voracious ``` -------------------------------- ### Multi-Transfer Streaming Source: https://github.com/xoolive/desperado/blob/main/crates/rs-hackrf/readme.md Illustrates setting up a HackRF device for multi-transfer streaming, allowing for continuous I/Q data reception and runtime control. ```rust use rs_hackrf::HackRf; let mut device = HackRf::open_first()?; device.set_freq(100_000_000)?; device.set_sample_rate(8_000_000)?; device.set_lna_gain(24)?; device.set_vga_gain(20)?; // Consumes device, starts background streaming thread let reader = device.into_streaming_reader(0, 0)?; // 0 = use defaults // Runtime control from any thread let ctrl = reader.control_handle(); ctrl.tune(200_000_000)?; ctrl.set_lna_gain(32)?; while let Some(Ok(data)) = reader.recv() { // data: Vec of interleaved i8 I/Q samples println!("received {} bytes", data.len()); } ``` -------------------------------- ### Unit Tests Source: https://github.com/xoolive/desperado/blob/main/crates/rs-hackrf/readme.md Command to run unit tests for the rs-hackrf crate. ```bash cargo test -p rs-hackrf ``` -------------------------------- ### Run Unit Tests Source: https://github.com/xoolive/desperado/blob/main/crates/rs-spy/readme.md Command to run unit tests for the rs-spy crate. ```bash cargo test -p rs-spy ``` -------------------------------- ### Configuration Source: https://github.com/xoolive/desperado/blob/main/crates/rs-rtl/readme.md Detailed configuration options for an RTL-SDR device, including frequency, sample rate, gain, bandwidth, and bias-T. ```rust use rs_rtl::{DeviceId, RtlSdr}; let mut sdr = RtlSdr::open(DeviceId::Index(0))?; // Frequency: 24 MHz – 1766 MHz (R820T), HF with Blog V4 sdr.set_center_freq(433_920_000)?; // Sample rate: 225,001–300,000 or 900,001–3,200,000 Hz sdr.set_sample_rate(2_400_000)?; // Gain: auto or manual (tenths of dB) sdr.set_gain_auto()?; sdr.set_gain_manual(297)?; // Bandwidth: 0 = automatic (matches sample rate) sdr.set_bandwidth(0)?; // Bias-T (antenna phantom power) sdr.set_bias_t(true)?; // Available gain steps println!("gains: {:?}", sdr.gains()); ``` -------------------------------- ### Command-line Usage Source: https://github.com/xoolive/desperado/blob/main/crates/dabradio/readme.md The command-line interface for the dabradio tool, including arguments, options, and their descriptions. ```bash USAGE: dabradio --channel [OPTIONS] ARGUMENTS: File path or SDR URI (rtlsdr://, soapy://, airspy://) OPTIONS: --channel DAB channel (e.g., "12A", "12C") -f, --freq Center frequency in Hz (alternative to --channel) --format IQ format for file sources: cu8, cs8, cs16, cf32 [default: cu8] --list List services and exit (no audio decoding) --json Output as JSON --service Service to decode (label or hex SId like "0xF201") -o, --output Output file for raw DAB+ logical frames --no-audio Disable audio output to soundcard --metadata Display DLS text metadata (song titles, artist names) --slideshow Extract MOT slideshow images to directory --max-frames Maximum number of OFDM frames to process [default: 0 = unlimited] --bypass-deinterleave Debug: skip time de-interleaving in MSC (testing only) -h, --help Print help information ``` -------------------------------- ### Integration Tests Command Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Command to run integration tests for the voracious crate. ```bash cargo test -p voracious --test vor_decoding ``` -------------------------------- ### Device Info Source: https://github.com/xoolive/desperado/blob/main/crates/rs-hackrf/readme.md Demonstrates how to open a HackRF device and retrieve basic information like firmware version, board ID, and serial number. ```rust use rs_hackrf::HackRf; let device = HackRf::open_first()?; println!("Firmware: {}", device.version()?); println!("Board: {}", rs_hackrf::board_id_name(device.board_id()?)); let (part0, part1, serial) = device.board_partid_serialno()?; println!("Serial: {}", serial); ``` -------------------------------- ### Pipe to redsea (External RDS Decoder) Source: https://github.com/xoolive/desperado/blob/main/crates/fmradio/readme.md Output raw MPX signal for comparison with reference implementation. ```bash cargo run --release -p fmradio -- rtlsdr:// -c 103.5M --raw-out --resample-out 228000 | redsea -r 228000 ``` -------------------------------- ### Architecture Overview Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Directory structure and main components of the Voracious crate. ```tree src/ ├── lib.rs — public re-exports ├── main.rs — CLI (clap, gqrx filename inference, SDR URI parsing) ├── source.rs — IqSource iterator: chunked I/Q → VorRadial ├── metrics.rs — signal quality computation (SNR, lock, variance) └── decoders/ ├── mod.rs — module coordinator and re-exports ├── vor.rs — VorDemodulator, VORtrack radial algorithm, DSP pipeline └── morse.rs — generic Morse ident parser (reusable for NDB, ILS, DME) ``` -------------------------------- ### SoapySDR Device Detection Source: https://github.com/xoolive/desperado/blob/main/readme.md Command to list available SoapySDR devices. ```bash SoapySDRUtil --find ``` -------------------------------- ### HackRF Device Detection Source: https://github.com/xoolive/desperado/blob/main/readme.md Commands to list available HackRF devices and query firmware/board info. ```bash cargo run --example hackrf_info -p rs-hackrf ``` -------------------------------- ### Signal Processing Pipeline Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Detailed steps of the signal processing pipeline from IQ samples to decoded radial and Morse ident. ```text IQ samples (cf32, 1.8 MSps) │ ├─ Frequency shift to VOR baseband ├─ 200 kHz Butterworth lowpass ├─ AM envelope detection ├─ 20 kHz lowpass └─ Decimate 38× → audio at ~47368 Hz │ ├─── VORtrack radial algorithm │ Tracks 30 Hz variable (9–11 kHz BPF + envelope) │ and reference (9.5–10.5 kHz BPF + FM demod) │ → radial_deg │ └─── Morse ident decoder (sliding 15-second windows) 900–1100 Hz BPF + Hilbert envelope → threshold → dot/dash detection → 3-letter ident ``` -------------------------------- ### Decode from any I/Q file Source: https://github.com/xoolive/desperado/blob/main/crates/voracious/readme.md Decode VOR signals from a generic I/Q sample file, specifying necessary parameters like VOR frequency, center frequency, sample rate, and I/Q format. ```bash voracious samples.cf32 \ --vor-freq 114.85 \ --center-freq 114.647 \ --sample-rate 1800000 \ --format cf32 \ --window 3.0 ``` -------------------------------- ### RTL-SDR Device Detection Source: https://github.com/xoolive/desperado/blob/main/readme.md Commands to list available RTL-SDR devices. ```bash rtl_test # or using the workspace example: cargo run --example rtl_sdr -p desperado --features rtlsdr ```