AuraScope
The idea
Take a Bluetooth LE Audio (Auracast) broadcast, receive it on an nRF5340, and present the receiver to a Zynq-7000 Linux host as a plain USB sound card. Then make that audio pipeline observable two different ways — from inside the kernel with a character driver I write, and from outside with eBPF — and surface the data in a small live dashboard.
The observability layer is the point. The wireless half is the delivery mechanism that gets a real, live audio stream into Linux so there is something worth instrumenting.
✓ Already built — the wireless half
Both nRF5340s are done and verified. One acts as a gateway: an I2S microphone in, LC3 encode, Auracast broadcast out — two BIS streams at 48 kHz / 96 kbps, one per channel. The other acts as a receiver: it syncs to both streams, decodes LC3, and presents itself over USB as a standard USB Audio Class device.
Confirmed end to end on a dev host by feeding a 1 kHz sine into the gateway's mic and recording it back off the USB sound card. The full logs and captures are in the progress log. Because this half is finished, it isn't broken out into build steps below — the numbered steps pick up where the audio reaches Linux.
Why it's worth reading
- eBPF on embedded Linux — the same data the driver owns, observed from the outside, so you can see the tradeoff between the two approaches. This is the part I care most about.
- A kernel module I actually wrote — file_operations, ioctls, sysfs, and correct locking.
- Real Yocto — a custom image and recipes on a Zynq target, not a pre-baked distro, including the device-tree and FSBL work needed to reach a login prompt.
- Auracast / LC3 on Zephyr — the new BLE Audio stack, used here as the audio source rather than as the subject.
The build, step by step
Each step links to its own write-up as it ships. Greyed steps are planned but not yet published.
Audio is flowing and instrumented. aurascope-dash runs on the board serving a
live scope — waveform, spectrum and 30 s of level history — and eBPF kprobes on the ALSA
hot path now feed a period-latency histogram and xrun counter into the same page. 9350 period
events, all in the 16–32 ms bucket, zero xruns, while real program audio played through
it. Next is the character driver, so the same data can be compared from inside the kernel.
Phase 1 — Foundation: Linux on the Zynq
Yocto on the Arty Z7-20
A minimal custom image that boots on the board.
Custom image & recipe
My own layer and recipes — through first boot, a login prompt, and SSH.
Phase 2 — Getting the audio into Linux
USB host + ALSA on the Zynq
Device tree for the ChipIdea host port, permanent kernel config for USB + snd-usb-audio.
Streaming, and a scope to watch it with
Audio confirmed flowing, and a live dashboard: per-channel waveforms + spectrum, plus 30 s of level history.
Phase 3 — Observability: eBPF & kernel module
eBPF in the same dashboard
kprobes on the ALSA hot path via ply — latency histogram and xrun counter, merged into the same feed.
Char driver: /dev/audiomon
The inside view to set against eBPF's outside one: file_operations, ioctl, sysfs, locking.
Phase 4 — Integration & publish
Full integration
End-to-end, with both observability layers running side by side.
Audio-status LED
Blinks while audio is arriving, stops when the stream goes silent — the physical version of what the dashboard plots.
Reflections
What I'd change, what's next.
// tap a lit step to read it · greyed steps are planned, not yet published
Repo
Source and tagged history: github.com/a-teresa/aurascope