waverave-hackrf

Crates.iowaverave-hackrf
lib.rswaverave-hackrf
version0.1.2
created_at2025-06-28 20:18:22.767478+00
updated_at2025-07-09 04:38:12.448373+00
descriptionHackRF backend in pure Rust
homepagehttps://github.com/Cognoscan/waverave
repositoryhttps://github.com/Cognoscan/waverave
max_upload_size
id1730099
size138,793
Richard Scott Teal (Cognoscan)

documentation

https://docs.rs/waverave-hackrf

README

waverave-hackrf

This is a complete, strongly-asynchronous host crate for the HackRF, made using the pure-rust nusb crate for USB interfacing. It reproduces all the functionality of the original libhackrf library.

The standard entry point for this library is open_hackrf(), which will open the first available HackRF device.

Getting started is easy: open up a HackRF peripheral, configure it as needed, and enter into transmit, receive, or RX sweep mode. Changing the operating mode also changes the struct used, i.e. it uses the typestate pattern. The different states and their corresponding structs are:

  • HackRf - The default, off, state.
  • Receive - Receiving RF signals.
  • Transmit - Transmitting RF signals.
  • Sweep - Running a receive sweep through multiple tuning frequencies.

If a mode change error occurs, the HackRf struct is returned alongside the error, and it can potentially be reset back to the off state by running HackRf::turn_off.

As for what using this library looks like in practice, here's an example program that configures the system, enters receive mode, and processes samples to estimate the average received power relative to full scale:

use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
    let hackrf = waverave_hackrf::open_hackrf()?;

    // Configure: 20MHz sample rate, turn on the RF amp, set IF & BB gains to 16 dB,
    // and tune to 915 MHz.
    hackrf.set_sample_rate(20e6).await?;
    hackrf.set_amp_enable(true).await?;
    hackrf.set_lna_gain(16).await?;
    hackrf.set_vga_gain(16).await?;
    hackrf.set_freq(915_000_000).await?;

    // Start receiving, in bursts of 16384 samples
    let mut hackrf_rx = hackrf.start_rx(16384).await.map_err(|e| e.err)?;

    // Queue up 64 transfers, retrieve them, and measure average power.
    for _ in 0..64 {
        hackrf_rx.submit();
    }
    let mut count = 0;
    let mut pow_sum = 0.0;
    while hackrf_rx.pending() > 0 {
        let buf = hackrf_rx.next_complete().await?;
        for x in buf.samples() {
            let re = x.re as f64;
            let im = x.im as f64;
            pow_sum += re * re + im * im;
        }
        count += buf.len();
    }

    // Stop receiving
    hackrf_rx.stop().await?;

    // Print out our measurement
    let average_power = (pow_sum / (count as f64 * 127.0 * 127.0)).log10() * 10.;
    println!("Average Power = {average_power} dbFS");
    Ok(())
}

Commit count: 0

cargo fmt