[](https://crates.io/crates/libbladerf-rs)
[](https://docs.rs/libbladerf-rs)
[](https://github.com/ratzrattillo/libbladerf-rs#license)
[](https://github.com/ratzrattillo/libbladerf-rs/actions)
[](https://crates.io/crates/libbladerf-rs)
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.
[nusb]: https://github.com/kevinmehall/nusb
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.
[libbladeRF]: https://github.com/Nuand/bladeRF
[libbladerf-rs]: https://github.com/ratzrattillo/libbladerf-rs
## 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:
```bash
cargo run --package info
```
The `rx_tx` example demonstrates the streaming API:
```rust
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]
[libbladeRF-doc]: https://www.nuand.com/libbladeRF-doc/v2.5.0/modules.html
[Wireshark]: https://www.wireshark.org/download.html
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:
```bash
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.
```wireshark
usb.bus_id == 1 and usb.device_address == 2
```
Datasheets for the BladeRF1 hardware are available at the following resources:
### SI5338
[SI5338 Datasheet](https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/Si5338.pdf)
[SI5338 Reference Manual](https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/reference-manuals/Si5338-RM.pdf)
### LMS6002D
[LMS6002D Datasheet](https://cdn.sanity.io/files/yv2p7ubm/production/47449c61cd388c058561bfd3121b8a10b3d2c987.pdf)
[LMS6002D Programming and Calibration Guide](https://cdn.sanity.io/files/yv2p7ubm/production/d20182c51057add570a74bd51d9c1336e814ea90.pdf)
### DAC161S055
[DAC Datasheet](https://www.ti.com/lit/ds/symlink/dac161s055.pdf?ts=1739140548819&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252Fde-de%252FDAC161S055)
## Documentation
Build and open the docs locally:
```bash
cargo doc --features bladerf1 --open
```
## Testing
### Run unit tests (no hardware required)
```bash
cargo test --lib
```
### Run integration tests (requires BladeRF1 connected)
```bash
cargo test --features bladerf1 --tests -- --test-threads=1
```
### Run a specific test with output
```bash
cargo test --features bladerf1 --test integration_bladerf1_frequency -- --nocapture --test-threads=1
```