Measure dropped samples from stream timestamps instead of hiding them
Overflows were counted but the samples the driver dropped were simply missing, so a 5 s capture with 300 overflows still read as a clean 5.000 s file. Each read's hardware timestamp is now compared with where the previous read ended; gaps are sized exactly, zero-filled by default so the file timeline stays true, and reported as completed_with_gaps with a warning, samples_dropped and a gap list. This also catches drops the plugin never flags as overflows (libusb transfer timeouts). Timestamps are differenced before rounding: rounding each absolute timestamp to a sample index flips by +/-1 near half-sample boundaries and produced phantom 1-sample gaps. - stream buffers 128 x 64K samples (~280 ms at 30 Msps, was ~4 ms) - reject out-of-range gain, frequency, rate and bandwidth instead of letting the plugin clamp silently; default bandwidth clamps to range - spectrum returns a max-hold decimated summary (256 points) plus noise_floor_db; full arrays were 139 KB at fft_size 4096 - capture_iq background=True with stream_status polling, so stop_capture is reachable; device-changing tools refuse while it runs - OSError returned in the error shape; status drops "unknown" fields - README: gap accounting, keep captures off tmpfs; captures/ ignored
This commit is contained in:
@@ -83,7 +83,7 @@ claude -p "show bladerf status" --mcp-config .mcp.json --allowedTools "mcp__mcbl
|
||||
### IQ Capture
|
||||
- `bladerf_capture_iq` - Stream samples to file (CF32/CS16)
|
||||
- `bladerf_capture_spectrum` - Capture and compute FFT, power in dBFS
|
||||
- `bladerf_stream_status` - Check capture progress
|
||||
- `bladerf_stream_status` - Capture progress, or the result of a background capture
|
||||
- `bladerf_stop_capture` - Abort running capture
|
||||
|
||||
### Advanced
|
||||
@@ -103,7 +103,7 @@ claude -p "show bladerf status" --mcp-config .mcp.json --allowedTools "mcp__mcbl
|
||||
> Set frequency to 915 MHz with 2 MHz sample rate
|
||||
[Uses bladerf_set_frequency and bladerf_set_sample_rate]
|
||||
|
||||
> Capture 1 second of IQ data to /tmp/capture.cf32
|
||||
> Capture 1 second of IQ data to ~/claude/sdr/mcbladerf/captures/capture.cf32
|
||||
[Uses bladerf_capture_iq]
|
||||
|
||||
> Show me the spectrum around 100 MHz
|
||||
@@ -112,7 +112,13 @@ claude -p "show bladerf status" --mcp-config .mcp.json --allowedTools "mcp__mcbl
|
||||
|
||||
## Capture Files and Readings
|
||||
|
||||
CF32 files are complex64 scaled to ±1.0. CS16 files are the device's raw SC16 Q11 integers, interleaved I/Q with full scale 2048, the same layout `bladeRF-cli` writes with `format=bin`. Spectrum power is dBFS, so a full-scale tone reads 0. Every capture reports `overflows` (dropped-sample events), `clipped_samples` and `peak_dbfs`, so check those before trusting the data.
|
||||
CF32 files are complex64 scaled to ±1.0. CS16 files are the device's raw SC16 Q11 integers, interleaved I/Q with full scale 2048, the same layout `bladeRF-cli` writes with `format=bin`. Spectrum power is dBFS, so a full-scale tone reads 0. Every capture reports `clipped_samples` and `peak_dbfs`, so check those before trusting the data.
|
||||
|
||||
When the host falls behind, the driver drops samples, and not always with an overflow error (a libusb transfer timeout drops data silently). Each read carries a hardware timestamp, so every gap is measured exactly and, by default, zero-filled: sample N of the file is always N / rate seconds after the first. Such captures finish as `completed_with_gaps` with a `warning`, `samples_dropped` and a gap list in output-sample offsets. Pass `fill_gaps=false` to get a shorter file with the same report instead.
|
||||
|
||||
Long captures should use `background=true`: the call returns at once, `bladerf_stream_status` shows progress and then the result, and `bladerf_stop_capture` ends it early. Spectra come back as a 256-point max-hold summary with `noise_floor_db`; peak and floor are computed at full resolution. Out-of-range gain, frequency, rate or bandwidth values are rejected, not clamped. The sample rate resets to 4 MHz each time the device is opened, so always set it.
|
||||
|
||||
Write captures to disk, not `/tmp`. On many Linux systems `/tmp` is a tmpfs held in RAM, and 30 Msps CS16 is 120 MB per second, so a few long captures can push the machine into swap and the OOM killer. Once the host stalls, the stream drops samples. The project's `captures/` directory is gitignored for this.
|
||||
|
||||
Gains you leave out keep whatever the device last had, including values set by another process. The radio is often shared, so set all three RX gains explicitly.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user