Neurobeat Loop documentation
Neurobeat Loop is an RP2354-based USB bridge. It presents a single USB composite device whose one configuration exposes four functions at once: a 16-channel audio input, a serial port, a HID device, and a vendor bulk channel, so a host can consume biopotential data through standard, driverless interfaces.
This is a developer preview. The USB design below has been verified for enumeration and on-chip memory fit; the descriptions reflect the current prototype and may change.
Overview
The bridge is a Raspberry Pi RP2354 with a USB-C connector. Its USB controller is full-speed (12 Mb/s), which sets the key constraint for the audio path. All four functions share one configuration with six interfaces and seven endpoints (plus control endpoint 0), and they're class-compliant: audio, serial and HID use the operating system's built-in drivers.
USB interface map
| Interface | Function | Endpoints |
|---|---|---|
| ITF 0 | Audio Control (AC) | — |
| ITF 1 | Audio Streaming (AS) | alt 0: 0 EP · alt 1: iso IN 0x81 |
| ITF 2 | CDC Control | INT IN 0x82 |
| ITF 3 | CDC Data | bulk OUT 0x03, bulk IN 0x83 |
| ITF 4 | HID (kbd + mouse + joystick) | INT IN 0x84 |
| ITF 5 | Vendor | bulk OUT 0x05, bulk IN 0x85 |
The HID interface collapses keyboard, mouse and joystick into three HID report IDs on one interrupt endpoint. The device uses an Interface Association Descriptor (IAD) class triplet so the host correctly groups the audio and CDC functions.
Audio format
The audio function is a UAC2 input terminal with 16 channels at 16-bit.
On a full-speed link the isochronous endpoint is capped at 1023 bytes per
frame, and the per-frame size is (kHz + 1) × bytes × channels.
That makes 48 kHz impossible for 16×16-bit (1568 B > 1023 B), so the sample rate is
the free variable:
- 16 kHz → 544 B/frame. Chosen: a standard rate, the widest host compatibility, and the most on-chip memory headroom.
- 32 kHz → 1056 B/frame — over the ceiling.
- 30 kHz → 992 B/frame — fits, but non-standard.
The channel count, bit depth and all four functions are preserved; sample rate is the only parameter reduced to fit full-speed USB.
On-chip memory budget
The RP2354 USB controller has a fixed 4 KB of packet buffer (DPRAM). Each endpoint buffer rounds up to 64 bytes; bulk endpoints are double-buffered, iso/interrupt are single-buffered. Everything fits with room to spare:
| Endpoint | Type | Max packet | DPRAM (B) |
|---|---|---|---|
0x81 audio | ISO | 544 | 576 |
0x82 CDC notif | INT | 8 | 64 |
0x03 CDC data | BULK | 64 | 128 |
0x83 CDC data | BULK | 64 | 128 |
0x84 HID | INT | 16 | 64 |
0x05 vendor | BULK | 64 | 128 |
0x85 vendor | BULK | 64 | 128 |
| Total of 3840 B pool | 1216 (≈32%) | ||
Host quickstart
Confirm enumeration and the interface set:
lsusb -d 2e8a: -v # expect one config, 6 interfaces, classes: Audio, CDC, HID, Vendor Exercise the vendor loopback with pyusb (write to bulk OUT, read it back from bulk IN):
import usb.core, os
dev = usb.core.find(idVendor=0x2E8A)
dev.set_configuration()
payload = os.urandom(64)
dev.write(0x05, payload) # bulk OUT
echo = dev.read(0x85, 64).tobytes() # bulk IN
assert echo == payload, "loopback mismatch"
print("LOOPBACK OK")
On Linux, a udev rule grants user access to the vendor interface so the script runs
without sudo (match on the product string and add TAG+="uaccess").
Host notes & caveats
- The device is identified by its product string, not by a unique USB product ID — it reuses a standard Raspberry Pi PID per the usb-pid convention. Linux is unaffected; on Windows the only nuance is driver caching.
- Audio, serial and HID need no driver install — they bind to built-in OS class drivers. Only the vendor interface uses libusb.
- The audio stream opens only after the host's mandatory sample-rate query succeeds; enumeration and coexistence don't depend on it.