3 releases (breaking)
Uses new Rust 2024
| 0.3.0 | May 3, 2026 |
|---|---|
| 0.2.0 | Apr 6, 2026 |
| 0.1.0 | Mar 15, 2026 |
#351 in Hardware support
Used in seify
245KB
6.5K
SLoC
A pure Rust driver for the Nuand BladeRF1 SDR, based on nusb USB backend. No C libbladeRF dependency. Supports BladeRF1 on Windows, macOS, and Linux.
Use libbladerf-rs to control your BladeRF1 from your Rust application. This software is not yet a full replacement for the official libbladeRF — some features are still missing.
VCTCXO Oscillator Calibration
The BladeRF1 uses a 38.4 MHz VCTCXO (temperature-compensated voltage-controlled crystal oscillator) as its master clock reference. The oscillator's tuning voltage is generated by a DAC161S055 (16-bit voltage-output DAC) and set by a DAC trim value.
- DAC trim is a 16-bit value (0–65535) written to the DAC161S055. It maps to a control voltage in the range of 0.4 V to 2.4 V at the VCTCXO tuning pin.
- The VCTCXO (ASV TX12) can be pulled approximately ±5 PPM to ±9.5 PPM from its 38.4 MHz nominal frequency across the full control-voltage span. This gives a total tuning range of roughly ±20 PPM (±386 Hz at 38.4 MHz). The exact band varies per unit due to manufacturing tolerance.
- At the center of the DAC range (about code
0x8000≈ 32768), the oscillator is closest to its rated 38.4 MHz. Moving the DAC code up or down shifts the output frequency proportionally. - If the DAC trim is wrong, the oscillator drifts from its nominal frequency. At a few PPM, signals are still detectable but demodulation quality degrades. If the required correction exceeds the VCTCXO's pull range (the DAC hits its rail), no code value can compensate — the board's clock is fundamentally out of spec.
- Over time, ambient conditions (temperature, sunlight, aging) cause the oscillator to drift, necessitating re-calibration.
The kalibrate example in this repository demonstrates VCTCXO calibration using GSM FCCH signals as an external frequency reference. It performs a binary search over the 16-bit DAC trim range to minimize detected frequency offset, then optionally writes the corrected value to the device's calibration flash. See examples/kalibrate/README.md for details.
Usage overview
After a BladeRF1 is connected via USB (High or SuperSpeed required) and fully booted,
open a device using bladerf1::BladeRf1::from_first,
bladerf1::BladeRf1::from_bus_addr, or bladerf1::BladeRf1::from_serial.
After obtaining an instance of a bladerf1::BladeRf1, you can set basic parameters like Gain, Frequency
and Sample Rate or Bandwidth.
Examples
The info example demonstrates basic device access:
cargo run --package info
The rx_tx example demonstrates the streaming API:
use anyhow::Result;
use libbladerf_rs::bladerf1::{BladeRf1, SampleFormat};
use libbladerf_rs::Channel;
fn main() -> Result<()> {
let mut device = BladeRf1::from_first()?;
device.initialize()?;
let mut rx = BladeRf1::rx_builder(&mut device)
.buffer_size(65536)
.buffer_count(8)
.format(SampleFormat::Sc16Q11)
.build()?;
let buf = rx.read(None)?;
println!("Got {} bytes", buf.len());
rx.recycle(buf)?;
rx.close(&mut device)?;
Ok(())
}
More examples can be found in the examples/ directory.
Limitations
libbladerf-rs currently only supports the BladeRF1. Support for BladeRF2 is currently not possible, as the maintainer is not in possession of one.
Missing Features
- Support for BladeRF2
- Support for Firmware and FPGA flashing/validation
- AGC DC calibration table support (see
AGC_PLAN.md) - Usage from both async and blocking contexts (currently sync only)
Developers
Contributions of any kind are welcome!
If possible, method names should adhere to the documented methods in libbladeRF-doc
For debugging purposes, it is useful to compare the communication between the SDR and the original libbladeRF with the communication of libbladerf-rs. Hand tooling for this purpose is Wireshark. Allow wireshark to monitor USB traffic:
sudo usermod -a -G wireshark <your_user>
sudo modprobe usbmon
sudo setfacl -m u:<your_user>:r /dev/usbmon*
Filter out unwanted traffic by using a Wireshark filter like e.g.
usb.bus_id == 1 and usb.device_address == 2
Datasheets for the BladeRF1 hardware are available at the following resources:
SI5338
LMS6002D
LMS6002D Programming and Calibration Guide
DAC161S055
Documentation
Build and open the docs locally:
cargo doc --features bladerf1 --open
Testing
Run unit tests (no hardware required)
cargo test --lib
Run integration tests (requires BladeRF1 connected)
cargo test --features bladerf1 --tests -- --test-threads=1
Run a specific test with output
cargo test --features bladerf1 --test integration_bladerf1_frequency -- --nocapture --test-threads=1
Dependencies
~0.6–5MB
~117K SLoC