Skip to content

dprokopiev/sdr-source-rs

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔌 sdr-source-rs: Common SDR Abstraction

CI MSRV

🎯 Overview

Common abstraction for SDR sources used by the main orchestrator. One trait, a few shared types, no third-party SDR dependencies. Every backend (USRP, HackRF, ADALM-Pluto, file / SigMF, Aaronia HTTP / SDK / RTSA) implements SdrSource and emits the same IqPacket shape so the orchestrator can dispatch detection uniformly.

🎯 The Trait

pub trait SdrSource: Send {
    fn start(
        self: Box<Self>,
        config: SourceConfig,
        advice: Arc<dyn DwellAdvice>,
    ) -> Result<SdrHandle, SdrError>;
}

start consumes the builder (Box<Self>), spawns whatever capture threads the backend needs, and returns an SdrHandle:

pub struct SdrHandle {
    pub receiver: Receiver<IqPacket>,
    pub stop: Box<dyn FnOnce() + Send>,
}

receiver is a crossbeam::channel::Receiver<IqPacket>. Every backend, regardless of how it got the data, emits the same shape:

pub struct IqPacket {
    pub samples: PooledIqBuffer,  // Deref<Target = [Complex32]>
    pub center_frequency_hz: f64,
    pub sample_rate_hz: f32,
    pub overrun: bool,
}

samples is a PooledIqBuffer — a smart wrapper around Vec<Complex32> that automatically returns the vector to a recycling pool when dropped. It implements Deref<Target = [Complex32]>, so consumers treat it exactly like a &[Complex32] slice.

sample_rate_hz is f32 rather than f64 because the downstream DSP (FFT, polyphase resampler) is single-precision — keeping the rate at the same width avoids silent narrowings at the boundary.

stop is the shutdown hook; calling it (or dropping the handle and letting receiver disconnect on the next iteration) winds the capture thread down.

🧪 Test trait contract

tests/contract.rs exercises a minimal mock implementation to verify the basic shape: start returns a non-empty receiver, dropping the handle releases the receiver, stop() is idempotent.

📦 Dependencies

Tiny on purpose:

crossbeam     = "0.8"      # channel
num-complex   = "0.4"      # Complex32
thiserror     = "2.0"      # SdrError
anyhow        = "1.0"      # SdrError::Backend pass-through

No SDR hardware dependencies — those live in the implementation crates.

📚 Documentation

📄 License

This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later) - see the LICENSE file for details.

📞 Support

About

A comprehensive Rust library defining common traits and foundational types for SDR sources.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Rust 100.0%