Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
492 commits
Select commit Hold shift + click to select a range
734ae1f
The C pump can run at 48 kHz, and stops assuming its sink is mono
bdbarnett Sep 16, 2026
946a999
Merge usbif#12: the C pump runs at 48 kHz and respects its sink's cha…
bdbarnett Sep 16, 2026
3ec459e
audiopump: a C pull loop and a pthread pump, for the live-audio-path …
bdbarnett Sep 18, 2026
4b7a2b7
audiopump: an esp32 backend — a pinned FreeRTOS task, a RAM ring, an …
bdbarnett Sep 18, 2026
d6cd175
esp32: key the port branch off AUDIOPUMP_ESP32, not ESP_PLATFORM
bdbarnett Sep 18, 2026
45870f8
spike probes: board_pump and board_race live in the anchor
bdbarnett Sep 18, 2026
2c6ca5e
README: the esp32 side, the ESP_PLATFORM trap, and what still is not …
bdbarnett Sep 18, 2026
c14cb79
esp32: die with the VM -- a finaliser teardown, plus duplex I2S, an I…
bdbarnett Sep 20, 2026
bf151e8
README: the soft-reset finaliser, retarget, duplex I2S, Input and rt_…
bdbarnett Sep 20, 2026
f723657
teardown must not unroot the guard -- a later collection would finali…
bdbarnett Sep 20, 2026
d0eedb3
the guard root is dropped by the finaliser only -- two opposite failu…
bdbarnett Sep 20, 2026
43abcc2
The pump holds audioif's lock for a block, and retargets under it
bdbarnett Sep 20, 2026
a0c36a0
The pump checks its own tail for deinit
bdbarnett Sep 20, 2026
2224f71
A push ring that is an audiosample, so one mechanism covers both kind…
bdbarnett Sep 21, 2026
d641c67
A timestamped event queue and a tap: sequenced music keeps time on th…
bdbarnett Sep 21, 2026
43c01fe
the push ring's buffer positions are tracked, not derived from a wrap…
bdbarnett Sep 21, 2026
78cb134
The pump on the windows port: a native thread, QPC, and the sink in b…
bdbarnett Sep 21, 2026
c68b097
Merge the push ring's wrap fix into the main spike line
bdbarnett Sep 21, 2026
01f38fb
The same loop, entered from a timer: the pump on a port with no thread
bdbarnett Sep 21, 2026
84ab35c
Duplex across two I2S peripherals, because the T-Embed's mic and spea…
bdbarnett Sep 21, 2026
9251bdb
Merge branch 'spike/lap-s3' into spike/land
bdbarnett Sep 21, 2026
bdddc69
Three platforms in one #if chain: the wasm service loop beside the wi…
bdbarnett Sep 21, 2026
69763ab
The portable costume API knows about video
claude Sep 21, 2026
048e08b
Everything left in here is a platform: _audioif, the pump's driver
bdbarnett Sep 21, 2026
aab6bee
docs: the README is the hardware layer now, not the spike
bdbarnett Sep 21, 2026
e1003b5
audiobusio: CircuitPython's I2S output, with the pump underneath
bdbarnett Sep 21, 2026
de122e6
audiobusio: drive the pump where there is no thread to drive it
bdbarnett Sep 21, 2026
37623be
audiobusio: paused is a flag, the way CircuitPython has it
bdbarnett Sep 21, 2026
4d1ae87
audiobusio: the I2S descriptor is sized in time, and the ring is only…
bdbarnett Sep 21, 2026
9c8b891
ci: this repository had no CI at all
bdbarnett Sep 21, 2026
6788705
Merge branch 'spike/p4-six' into spike/split
bdbarnett Sep 21, 2026
ec230f1
driver: the desktop waits are real waits now, and the wake is real
bdbarnett Sep 21, 2026
86e25aa
Merge branch 'spike/backpressure' into spike/split
bdbarnett Sep 21, 2026
05ce246
audiobusio: I2SOut can swap its tail, show its status, and take the b…
bdbarnett Sep 21, 2026
6196cd3
busio_probe: a leg for the three that are ours
bdbarnett Sep 21, 2026
49ac3bf
README: this IS a PyDevices repository, and audiobusio is documented
bdbarnett Sep 21, 2026
942947e
windows driver: one pace timer per thread, and a watchdog that prints…
bdbarnett Sep 21, 2026
3896af0
Merge branch 'spike/winhang' into spike/split
bdbarnett Sep 21, 2026
aedc249
Follow the DSP repo's rename: its hooks, lock and paths are audiodsp_…
bdbarnett Sep 21, 2026
c7bc6ae
audioif is audiodsp: the DSP repository was renamed on 2026-09-21 (#17)
bdbarnett Sep 21, 2026
2400e8a
audioif is audiodsp: the DSP repository was renamed on 2026-09-21 (#30)
bdbarnett Sep 21, 2026
34a3fd9
A LICENSE file and a changelog, ahead of this repository going public…
bdbarnett Sep 21, 2026
cb5e6c3
This repository is audioif: the README's opening, the build steps and…
bdbarnett Sep 21, 2026
46f17e6
The *if family as it is now: displayif, audioif, cameraif (#18)
bdbarnett Sep 21, 2026
3c418f4
build: check out the engine at v0.5.1, not audiodsp's default branch …
bdbarnett Sep 22, 2026
e2e74fa
dotclockframebuffer: size the bounce buffers against the internal DMA…
bdbarnett Sep 22, 2026
a798eed
available() reports whether a sensor driver was linked, instead of Tr…
bdbarnett Sep 22, 2026
30583bc
Applications reach USB through usbif.auto, never through _usbif (#19)
bdbarnett Sep 22, 2026
95a6905
starved() reports silence on the wire, and it takes two witnesses to …
bdbarnett Sep 22, 2026
e2e4e1f
_audioif.lock_probe(): ask FreeRTOS whether it refuses a non-owner's …
bdbarnett Sep 22, 2026
c6003f0
A qstr must be reachable on every port that compiles the file (i80bus…
bdbarnett Sep 22, 2026
409ddab
fill_rect on every framebuffer backend that owns the pointer and the …
bdbarnett Sep 22, 2026
227e79f
A local probe runner, which refuses an interpreter that does not cont…
bdbarnett Sep 22, 2026
03093e2
fill_rect on picodvi.Framebuffer, at every colour depth it has (#34) …
bdbarnett Sep 22, 2026
d88fabd
micropython.cmake: skip the driver on non-esp32 CMake ports (#16)
bdbarnett Sep 22, 2026
f5d575c
manifest: name this repo's C module with c_module() (MicroPython 1.29)
bdbarnett Sep 22, 2026
99da9b7
manifest: name this repo's C module with c_module() (MicroPython 1.29)
bdbarnett Sep 22, 2026
7a2ae1a
manifest: name this repo's C module with c_module() (MicroPython 1.29)
bdbarnett Sep 22, 2026
c59d060
flake8: c_module is manifest vocabulary, not an undefined name
bdbarnett Sep 22, 2026
be1aba0
flake8: c_module is manifest vocabulary, not an undefined name
bdbarnett Sep 22, 2026
7685166
A manifest that names the C module, jpegio's sibling detection off th…
bdbarnett Sep 22, 2026
7d88f27
__revision__: which audioif this firmware was built from (#17)
bdbarnett Sep 22, 2026
611e460
__revision__: which cameraif this firmware was built from (#6)
bdbarnett Sep 22, 2026
8721612
__revision__: which usbif this firmware was built from (#20)
bdbarnett Sep 22, 2026
0d4c658
__revision__: which displayif this firmware was built from (#37)
bdbarnett Sep 22, 2026
f0a0fbc
micropython.mk: the include path for displayif/build.h on every Make …
bdbarnett Sep 22, 2026
d080fa7
lint: drop the flake8 builtins option, which 7.4.0 crashes on
bdbarnett Sep 23, 2026
e89b385
lint: drop the flake8 builtins option, which 7.4.0 crashes on
bdbarnett Sep 23, 2026
b298181
CircuitPython: usdl2's __revision__ entry compiles there too (#38)
bdbarnett Sep 23, 2026
ca8ff0f
apply_patches.sh: the MicroPython checkout is beside this repo, not i…
bdbarnett Sep 23, 2026
c475c54
The esp32 patches live here, with an apply script
bdbarnett Sep 23, 2026
da9293d
The interpreter and the stamper live in the workspace anchor, not cmods
bdbarnett Sep 23, 2026
7286814
Drop package.json: the Python half is frozen with the C half, and not…
bdbarnett Sep 23, 2026
6fce65a
Boot as CDC alone; MSC is worn only when Python asks (usbif#14) (#22)
bdbarnett Sep 23, 2026
c9c91a3
spikes: rebuild IDF's usb_host_lib example for the P4 panel -- the us…
bdbarnett Sep 23, 2026
008b052
device: number endpoints per costume; refuse a costume past the contr…
bdbarnett Sep 23, 2026
61ba01c
device: size every bulk endpoint for the negotiated speed, not only M…
bdbarnett Sep 23, 2026
2a9cfb3
host: USB Audio 2.0 devices, a FIFO split per session, full-speed aud…
bdbarnett Sep 23, 2026
eaa3353
docs: add cameraif newcomer guide (#7)
bdbarnett Sep 23, 2026
498495b
docs: add usbif newcomer guide (#31)
bdbarnett Sep 23, 2026
45babd4
docs: add audioif newcomer guide (#18)
bdbarnett Sep 23, 2026
82702e4
docs: add displayif newcomer guide (#39)
bdbarnett Sep 23, 2026
4779bfa
README: point at issue #3, not the private findings (#32)
bdbarnett Sep 23, 2026
3c0a916
README: add this module to your own MicroPython build with one includ…
bdbarnett Sep 24, 2026
8c0244f
README: add this module to your own MicroPython build with one includ…
bdbarnett Sep 24, 2026
e9d1c00
README: add this module to your own MicroPython build with one includ…
bdbarnett Sep 24, 2026
fc7e48c
README: add this module to your own MicroPython build with one includ…
bdbarnett Sep 24, 2026
ff572fb
Comments stop naming cmods and the workspace aggregator (#20)
bdbarnett Sep 24, 2026
cc9b7f9
Comments stop naming cmods and the workspace aggregator (#34)
bdbarnett Sep 24, 2026
5a035a5
UAC: offer 44.1 kHz beside 48 kHz, and let the pump follow the host's…
bdbarnett Sep 24, 2026
7ad238a
UAC: one packet per millisecond at high speed, so the stream stops lo…
bdbarnett Sep 24, 2026
ce99fde
UAC host: a ring the caller sizes, in PSRAM when large, with space() …
bdbarnett Sep 24, 2026
71c7841
audioif 0.1.1: VERSION and the changelog's section for it
bdbarnett Sep 24, 2026
7f118c2
UAC host: publish a C sink a usermod's own task can write (usbif#43) …
bdbarnett Sep 24, 2026
f841529
DotClockFramebuffer(bounce_rows=): cap the bounce buffers' size (#42)
bdbarnett Sep 25, 2026
6ea4d30
jpegio: require import-time registration on the desktop interpreters …
bdbarnett Sep 25, 2026
48879e3
hid_keyboard: take the keyboard table from pydevices' keys.py (#45)
bdbarnett Sep 25, 2026
08913de
soundcard: run the I2S wire at the host's 48 kHz when the board can c…
bdbarnett Sep 26, 2026
c37ce17
UAC: take each packet in the USB interrupt, so a busy interpreter no …
bdbarnett Sep 26, 2026
5b63fca
Spike: spectrum meter levels computed in the UAC pump task (#50)
bdbarnett Sep 26, 2026
4c01722
sd_drive: refuse a card that never answered instead of serving no blo…
bdbarnett Sep 26, 2026
370dad6
DotClockFramebuffer: the bounce_rows range is defined where the const…
bdbarnett Oct 5, 2026
b6b35a4
docs: build with micropython-pydevices' build_mp.py; its presets are …
bdbarnett Oct 5, 2026
77b20b1
sdkconfig.esp32p4: the OV5647 driver settings, carried by the module …
bdbarnett Oct 6, 2026
2b9397a
Carry the build settings usbif needs: sdkconfig fragments by name, an…
bdbarnett Oct 6, 2026
7b955e5
DotClockFramebuffer: keep both panel buffers in step with what was pa…
bdbarnett Oct 6, 2026
cd6f82c
jpegio builds without LVGL: its LVGL decoder is chosen by this build'…
bdbarnett Oct 6, 2026
b836678
mipidsi.Display: non_burst and continuous_clock, for DSI-to-RGB bridg…
bdbarnett Oct 6, 2026
17b3750
jpegio moves to micropython-pydevices' modules/jpegio (#50)
bdbarnett Oct 6, 2026
2d89135
uvc_display: jpegio is micropython-pydevices' module now (#53)
bdbarnett Oct 6, 2026
274ca6f
capture_jpeg() encodes through jpegio's C API; cameraif owns no JPEG …
bdbarnett Oct 6, 2026
fdb65ca
capture_scaled() and capture_yuy2() go through ppa's C API; cameraif'…
bdbarnett Oct 7, 2026
95bcb3b
The spectrum meter leaves for audiodsp's audiometer; the pump feeds i…
bdbarnett Oct 7, 2026
f975164
Add ROADMAP.md for planned work, and make public text stand on its ow…
bdbarnett Oct 7, 2026
ece6bae
Add ROADMAP.md for planned work, and make public text stand on its ow…
bdbarnett Oct 7, 2026
710b2c5
Add ROADMAP.md for planned work, and make public text stand on its ow…
bdbarnett Oct 7, 2026
22de545
Add ROADMAP.md for planned work, and make public text stand on its ow…
bdbarnett Oct 7, 2026
0f73001
Roadmap: MIDI moves to mididev (#56)
bdbarnett Oct 8, 2026
9f9126d
Roadmap: closer to MicroPython's USB (#57)
bdbarnett Oct 8, 2026
4ddddfb
CI: run once per change, and skip documentation-only changes (#58)
bdbarnett Oct 8, 2026
c308aa9
CI: run once per change, and skip documentation-only changes (#52)
bdbarnett Oct 8, 2026
a75199d
CI: run once per change, and skip documentation-only changes (#13)
bdbarnett Oct 8, 2026
4e4a025
CI: run once per change, and skip documentation-only changes (#23)
bdbarnett Oct 8, 2026
38acfed
usdl2 builds into CircuitPython's unix port as a user C module (#53)
bdbarnett Oct 8, 2026
028be76
camera_formats: reopen the camera through the board's own camera() he…
bdbarnett Oct 8, 2026
5a0d87f
Roadmap: stereo on one speaker, audioi2sin.I2SIn, and one-channel cap…
bdbarnett Oct 8, 2026
57f1f8e
Sound card: send explicit feedback so the host follows the codec's cl…
bdbarnett Oct 8, 2026
be7669e
usdl2 builds into CircuitPython as a user C module only: the patch sc…
bdbarnett Oct 8, 2026
76fc96d
Record while playing on one I2S port: rx_open/rx_read over the channe…
bdbarnett Oct 9, 2026
265648b
Move the IDF host-example builder to tools/; remove the Spike B and C…
bdbarnett Oct 9, 2026
1f9b835
tools/p4_idf_host_example.sh: its usage line names its new path (#61)
bdbarnett Oct 9, 2026
720b517
CircuitPython: build on the ESP32-P4, join a busio.I2C, close at the …
bdbarnett Oct 9, 2026
b9dc8c4
I2SOut.starved() counts silence as DMA events, so a clean playback re…
bdbarnett Oct 9, 2026
9543757
machine.USBDevice runtime interfaces open beside a costume (#63)
bdbarnett Oct 9, 2026
b46219f
ESP32-P4: the host and a full-speed device run at once (#62)
bdbarnett Oct 9, 2026
c9f3eb0
uvc_display: start the frame tick on the current App.every (#64)
bdbarnett Oct 9, 2026
843044a
host_stop() releases a device stuck in enumeration, or says the host …
bdbarnett Oct 9, 2026
825b8db
uvc_display: full frame rate on the P4 (one blit per frame, hardware …
bdbarnett Oct 9, 2026
4230cab
camera_still: take the shutter from boot_button, wrapped as a key in …
bdbarnett Oct 9, 2026
dd07297
host_stop() waits in milliseconds, so a 1000 Hz board no longer repor…
bdbarnett Oct 9, 2026
97e5520
hid_host.py reads a keyboard that puts a report ID before each report…
bdbarnett Oct 9, 2026
3cacf1c
examples: usb_drive_read.py reads a file off a hosted drive and check…
bdbarnett Oct 10, 2026
6edc138
UVC host: queue three ticks of isochronous schedule, so YUY2 isn't sc…
bdbarnett Oct 10, 2026
a6e0172
host_start(full_speed=True): full-speed devices behind a hub on the E…
bdbarnett Oct 10, 2026
3b49639
host_stop() retires a control transfer the device never answered, so …
bdbarnett Oct 10, 2026
452c99f
HID and CDC hosts: free transfers after the interface is released (#77)
bdbarnett Oct 10, 2026
4657f79
usb_mic.py: a FULL_SPEED switch for a mic behind a hub on an ESP32-P4…
bdbarnett Oct 10, 2026
f220b32
CI: move actions off Node 20 to the versions the rest of the org uses…
bdbarnett Oct 10, 2026
02b5480
CI: move actions off Node 20 to the versions the rest of the org uses…
bdbarnett Oct 10, 2026
0360c53
Docs: copy wifi.py only when the firmware doesn't freeze pydevices (#55)
bdbarnett Oct 10, 2026
0fa4a36
audioif 0.1.2: VERSION and the changelog's section for it
bdbarnett Oct 10, 2026
5e2d66a
soundcard.py: show a spectrum of what it plays on a board with a disp…
bdbarnett Oct 10, 2026
f3f16c6
soundcard.py: main() starts the card and returns to the REPL; stats()…
bdbarnett Oct 10, 2026
c26db61
The sound card's spectrum meter reads what plays, after the host's vo…
bdbarnett Oct 10, 2026
efb470d
Polling uac_read(), uac_available() and MidiPort.read() allocates not…
bdbarnett Oct 10, 2026
8f80b90
UAC host: open isochronous endpoints up to 1024 bytes, not 256 (#84)
bdbarnett Oct 10, 2026
d8acf6b
UAC host: play and record at once, one stream per direction (#86)
bdbarnett Oct 10, 2026
013b16e
OV5647: every mode, opens upright, true colour (white balance, colour…
bdbarnett Oct 11, 2026
d1a7aa8
Enable the colour matrix once per open; enabling it again logged an e…
bdbarnett Oct 11, 2026
56a6881
Find audiodsp among the build's modules, and stop when it isn't there…
bdbarnett Oct 12, 2026
0c545ff
Quiet the "MICROPY_HW_USB_EXT_DESC_CFG_LEN redefined" warning on esp3…
bdbarnett Oct 12, 2026
d1d1812
Stop the host, the I2S pump and the drive on a soft reset (#88)
bdbarnett Oct 12, 2026
7f1cd37
esp32: give audiodsp's codecs PSRAM through the port table's memory h…
bdbarnett Oct 12, 2026
efbd186
UVC device: move the streaming header's endpoint with the endpoint (#89)
bdbarnett Oct 13, 2026
d8252b6
Each costume with the camera in it gets its own product id (#90)
bdbarnett Oct 13, 2026
f87f164
usbif_webcam.py: count the frame rate from the first frame a host tak…
bdbarnett Oct 13, 2026
3217cc9
Roadmap: usbif rebuilds on MicroPython's own USB support (#92)
bdbarnett Oct 13, 2026
f5992cf
Roadmap: USB MIDI gives ports adafruit_midi reads (#93)
bdbarnett Oct 13, 2026
c2405e2
Roadmap: HID devices take adafruit_hid's API, over USB as over BLE (#94)
bdbarnett Oct 13, 2026
9f7616d
Roadmap: meet espcamera's API where the jobs overlap (#20)
bdbarnett Oct 13, 2026
900fd14
Roadmap: both speeds in every class; the host on usb.core over ESP-ID…
bdbarnett Oct 14, 2026
43f2208
alignment/usb: pin MicroPython main at 3843e4a0e for the usbif realig…
bdbarnett Oct 16, 2026
52c623a
packages: usb-device-msc and usb_hid on machine.USBDevice
bdbarnett Oct 16, 2026
1da6d35
Overlay: USBDevice at high speed and the S3's IN endpoint check (0031…
bdbarnett Oct 16, 2026
0e7068d
patches: 0007 moves to micropython-pydevices; 0003 refreshed on top o…
bdbarnett Oct 16, 2026
4e414b1
Device classes leave usbif for machine.USBDevice: CDC extras, MSC, MI…
bdbarnett Oct 16, 2026
d389661
tools/matrix: the device-class proof matrix
bdbarnett Oct 16, 2026
53582c2
matrix: what Windows received, checked; foreground echo; the board's …
bdbarnett Oct 16, 2026
0783b80
Overlay 0033: streaming endpoints on machine.USBDevice (Ring, stream,…
bdbarnett Oct 16, 2026
93232a6
packages: usb-device-audio, a UAC2 sound card on machine.USBDevice's …
bdbarnett Oct 16, 2026
c9ed040
usb-device-audio: feedback gain as meant; the board's own speaker pla…
bdbarnett Oct 16, 2026
f352038
Overlay 0034: UVC payloads on machine.USBDevice IN streams (frame=)
bdbarnett Oct 16, 2026
36dab4a
packages: usb-device-video, a UVC webcam on machine.USBDevice's strea…
bdbarnett Oct 16, 2026
82a1b12
Overlay 0035: a streaming OUT endpoint can feed a C sink (for audiopu…
bdbarnett Oct 16, 2026
a790c05
usb-device-msc: a drive the computer ejected reads as absent until in…
bdbarnett Oct 16, 2026
f8bb3db
usb-device-audio: sink= sends the stream from the USB interrupt into …
bdbarnett Oct 16, 2026
6b294d2
stream tools: the pump plays the ring through a BusioDriver; packet l…
bdbarnett Oct 16, 2026
f3279b7
usb.core over the host: generic claim, control, bulk and interrupt tr…
bdbarnett Oct 16, 2026
f925648
core_probe: an HID keyboard's report descriptor and interrupt reads
bdbarnett Oct 16, 2026
cfea060
usb.core: read with timeout 0 waits for good, as CircuitPython's does
bdbarnett Oct 16, 2026
2a15201
usb-host-msc: mount a flash drive over usb.core; transfers deliver wi…
bdbarnett Oct 16, 2026
410c295
host transfers: data that lands as a read times out is handed over, n…
bdbarnett Oct 16, 2026
fa66d0e
usb-host-hid: a keyboard or mouse on the host port in boot protocol, …
bdbarnett Oct 16, 2026
f046fa4
usb-core: usb_host.Port starts and stops the host port, as CircuitPyt…
bdbarnett Oct 16, 2026
bc7ad74
examples/usb_soundcard.py: the sound card on usb-device-audio and aud…
bdbarnett Oct 16, 2026
4945b53
matrix: interrupt a board that boots into an app; wait up to 30 s for…
bdbarnett Oct 16, 2026
f97a654
examples/usb_webcam.py: the board's MIPI camera as a USB webcam, thro…
bdbarnett Oct 16, 2026
ee39644
usb-device-video: MJPEG, frames of any size; the webcam example sends…
bdbarnett Oct 16, 2026
8296424
Overlay 0036: UVC frames of any size on a streaming IN endpoint (MJPEG)
bdbarnett Oct 16, 2026
b10d598
usb_webcam: rewrap the docstring
bdbarnett Oct 16, 2026
14470a9
IMX219 sensor driver: the Pi Camera v2 found by probing, three RAW10 …
bdbarnett Oct 16, 2026
e08d27b
HID: usb_hid sends boot reports without their ID once a host asks for…
bdbarnett Oct 16, 2026
50f8ecd
IMX219: probing an empty address is quiet
bdbarnett Oct 16, 2026
39eda05
tools/host/s3_uvc_grab.py: host a UVC camera, stream, save a frame
bdbarnett Oct 16, 2026
411d5c6
usb-device-video: each session starts at a frame boundary; a host tha…
bdbarnett Oct 16, 2026
610a886
Webcam sizes: usb-device-video offers several and streams the one the…
bdbarnett Oct 16, 2026
2ef7346
uvc_display: decode straight into the panel's framebuffer, TEAR_FREE …
bdbarnett Oct 16, 2026
2026a05
usb-host-video: a hosted webcam on usb.core (negotiation in Python, f…
bdbarnett Oct 16, 2026
ae3719c
usb-host-audio: a hosted speaker or microphone on usb.core (stream ch…
bdbarnett Oct 16, 2026
9061dd2
usb-host-cdc: a USB serial device on usb.core, read and written like …
bdbarnett Oct 16, 2026
0d2a14d
Remove the device side's C: the sound card, webcam, descriptor costum…
bdbarnett Oct 16, 2026
bc2cbb4
usb-device-audio: service(level=) steers the computer's clock by wher…
bdbarnett Oct 16, 2026
5812369
usb.host.net: internet through a phone's USB tethering
bdbarnett Oct 16, 2026
20a74f2
README: tethering works through a high-speed hub too
bdbarnett Oct 16, 2026
bcdcb17
usb-host-net: say which tethering protocols are not implemented
bdbarnett Oct 16, 2026
d7b5f03
Host FIFO: room for high-speed bulk OUT beside a camera on the P4
bdbarnett Oct 16, 2026
2b337ca
README: tethering speed on the ESP32-S3
bdbarnett Oct 16, 2026
40c4a68
S3: the P4's 64 KB TCP window and receive queues
bdbarnett Oct 16, 2026
bdcdf07
README: S3 tethering speed with the larger TCP window
bdbarnett Oct 16, 2026
3ee2a5f
Auto-exposure, black level, and colour controls from Python
bdbarnett Oct 17, 2026
5e1514e
Sensors described in Python: Camera(sensor=...)
bdbarnett Oct 17, 2026
1e66f5e
White balance in the gain block on revision 3; keywords as documented
bdbarnett Oct 17, 2026
c938680
Auto-exposure steers the OV5647 too
bdbarnett Oct 17, 2026
9097856
Overlay 0037: USBDevice.Ring from C, for a USB host's isochronous str…
bdbarnett Oct 19, 2026
22ea86e
Examples and host checks on usb.host.audio and usb.host.video
bdbarnett Oct 19, 2026
4d328c8
Host audio and video on isochronous host streams; the UAC and UVC eng…
bdbarnett Oct 19, 2026
2e1783e
Unix builds again: usbif_ip_str only where there is a host
bdbarnett Oct 19, 2026
039f24f
Host examples and their tests on usb.core and the host packages
bdbarnett Oct 19, 2026
4789e94
The older host API goes: lib/usbif and the C class drivers
bdbarnett Oct 19, 2026
cf1e26c
usb.core and usb.host.msc: errno names an ESP32 build lacks
bdbarnett Oct 19, 2026
b8d5980
A polling read stays armed: no library timeout on a kept IN transfer
bdbarnett Oct 19, 2026
96eb784
usb.host.video: say when in_limit is why no mode fits
bdbarnett Oct 19, 2026
e794915
Microphone(channels=1) from a stereo-only microphone: downmixed in C
bdbarnett Oct 19, 2026
e900c94
usb_webcam: 512-byte packets at full speed by default; main(packet=) …
bdbarnett Oct 19, 2026
d27b944
WIFI6_DEV_KIT_H2 freezes usbif's USB packages and midiports; a board …
bdbarnett Oct 19, 2026
fc233ff
Overlay 0038: FatFs takes and returns UTF-8 names, so non-ASCII filen…
bdbarnett Oct 19, 2026
3b0b293
usbif moves in as modules/usbhost, its history kept (git subtree add …
bdbarnett Oct 19, 2026
c245491
usbhost: the binding is _usbhost, the C, cmake and mk names follow, a…
bdbarnett Oct 19, 2026
4886faa
audioif moves in as modules/audioif, its history kept (git subtree ad…
bdbarnett Oct 19, 2026
18f9212
displayif moves in as modules/displayif, its history kept (git subtre…
bdbarnett Oct 19, 2026
0b10225
cameraif moves in as modules/cameraif, its history kept, with its ali…
bdbarnett Oct 19, 2026
42e6593
audioif, cameraif and displayif are tracked here now: their modules.l…
bdbarnett Oct 19, 2026
1a1b5ef
Move the MicroPython pin to main at b70ae1aca (v1.30.0-preview-160), …
bdbarnett Oct 19, 2026
a2c7d8d
CI for audioif, displayif and cameraif runs here now, and their prose…
bdbarnett Oct 19, 2026
a95299c
The proof matrix's host leg: run_host.py drives the host checks from …
bdbarnett Oct 19, 2026
55dca10
Carry micropython-lib's usb-device-midi 0.1.1 fix: a MIDI burst no lo…
bdbarnett Oct 19, 2026
d34933a
build_mp.py: clone MicroPython at UPSTREAM through clone_at, so a ful…
bdbarnett Oct 19, 2026
6d798fe
usbhost tools: drop four unused names flake8 flags
bdbarnett Oct 19, 2026
3e83a10
modules.lock: pydevices and audiodsp at the commits that carry the US…
bdbarnett Oct 19, 2026
383c481
pngio's Pillow check: grey at 1, 2 and 4 bits is compared with Pillow…
bdbarnett Oct 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
71 changes: 71 additions & 0 deletions .github/workflows/audioif.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# audioif on the unix port beside audiodsp: the driver binds with a thread, each probe's planted fault fails first, then the probes and CircuitPython's own I2SOut example pass. (These checks moved here with audioif from its own repository, 2026-10-19.)
name: audioif

on:
push:
branches: [main]
paths:
- 'modules/audioif/**'
- 'build_mp.py'
- 'modules.lock'
- 'patches/**'
- '.github/workflows/audioif.yml'
pull_request:
paths:
- 'modules/audioif/**'
- 'build_mp.py'
- 'modules.lock'
- 'patches/**'
- '.github/workflows/audioif.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
unix-driver:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- name: Install the unix port's build dependencies
run: |
sudo apt-get update
sudo apt-get install -y libffi-dev pkg-config
# audiodsp comes at its modules.lock commit; audioif's glue finds it
# as its sibling in modules/.
- name: Build the unix port with audiodsp and audioif
run: python3 build_mp.py --port unix --modules audiodsp,audioif

- name: The driver bound, and it has a thread
run: |
./builds/unix/standard/micropython -c "
import audiopump, audiobusio
name = audiopump.driver()
assert name == 'pthread', 'driver() says %r' % name
assert audiopump.threaded(), 'a bound driver with no thread'
print('driver:', name, 'threaded:', audiopump.threaded())"

# A probe whose failing mode is never exercised is not a gate.
- name: The probes, and proof each one can fail
run: |
MP=./builds/unix/standard/micropython
TMP="${RUNNER_TEMP:-/tmp}"
run () { "$MP" -X heapsize=256M "modules/audioif/tests/$@"; }
for planted in "busio_probe.py $TMP --fault deaf" \
"sink_probe.py $TMP --fault flip" \
"sink_probe.py $TMP --fault truncate"; do
if run $planted > /dev/null; then
echo "the planted fault passed: $planted" >&2
exit 1
fi
done
run sink_probe.py "$TMP"
run busio_probe.py "$TMP"

- name: CircuitPython's documented example, unmodified
run: |
OUT="${RUNNER_TEMP:-/tmp}/cp_example.raw"
./builds/unix/standard/micropython -X heapsize=256M modules/audioif/tests/cp_example_probe.py "$OUT"
test -s "$OUT" || { echo "the example played nothing" >&2; exit 1; }
echo "$(stat -c%s "$OUT") bytes out of the docstring example"
38 changes: 38 additions & 0 deletions .github/workflows/cameraif.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# cameraif: flake8 over its examples (defect checks only, configured in modules/cameraif/.flake8). Its C is MIPI-CSI hardware, proven on the P4. (These checks moved here with cameraif from its own repository, 2026-10-19.)
name: cameraif

on:
push:
branches: [main]
paths:
- 'modules/cameraif/**'
- 'build_mp.py'
- 'modules.lock'
- 'patches/**'
- '.github/workflows/cameraif.yml'
pull_request:
paths:
- 'modules/cameraif/**'
- 'build_mp.py'
- 'modules.lock'
- 'patches/**'
- '.github/workflows/cameraif.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
flake8:
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: modules/cameraif
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- run: python -m pip install flake8
- run: python -m flake8
57 changes: 57 additions & 0 deletions .github/workflows/displayif.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# displayif on the unix port: every qstr reachable on every port that compiles it, usdl2 opens a window headless, the lifecycle API, and the packed fill in C. (These checks moved here with displayif from its own repository, 2026-10-19.)
name: displayif

on:
push:
branches: [main]
paths:
- 'modules/displayif/**'
- 'build_mp.py'
- 'modules.lock'
- 'patches/**'
- '.github/workflows/displayif.yml'
pull_request:
paths:
- 'modules/displayif/**'
- 'build_mp.py'
- 'modules.lock'
- 'patches/**'
- '.github/workflows/displayif.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
unix-usdl2:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- name: Every qstr is reachable on every port that compiles it
run: python3 modules/displayif/tools/check_qstr_reachability.py
- name: The packed framebuffer fill, every depth
working-directory: modules/displayif
run: cc -I src/include -o /tmp/t tests/test_fb_fill_packed.c && /tmp/t
- name: Install SDL2 and the unix port's build dependencies
run: |
sudo apt-get update
sudo apt-get install -y libsdl2-dev libffi-dev pkg-config
- name: Build the unix port with displayif
run: python3 build_mp.py --port unix --modules displayif
- name: Smoke the result (usdl2 import + window init, headless)
env:
SDL_VIDEODRIVER: dummy
run: |
./builds/unix/standard/micropython -c "
import usdl2
assert usdl2.SDL_Init(usdl2.SDL_INIT_VIDEO) == 0, usdl2.SDL_GetError()
win = usdl2.SDL_CreateWindow(
'displayif smoke', usdl2.SDL_WINDOWPOS_UNDEFINED, usdl2.SDL_WINDOWPOS_UNDEFINED,
320, 240, usdl2.SDL_WINDOW_SHOWN)
assert win, usdl2.SDL_GetError()
print('displayif OK: usdl2 window created:', win)
usdl2.SDL_DestroyWindow(win)
usdl2.SDL_Quit()"
- name: tests/test_lifecycle_api.py under the built interpreter
run: ./builds/unix/standard/micropython modules/displayif/tests/test_lifecycle_api.py
138 changes: 138 additions & 0 deletions .github/workflows/usbhost.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# usbhost: the host-testable C (rings, the C sink's gate, the host streams'
# pacing, framing and downmix), each with planted faults it has to catch;
# the examples' checks on CPython; and the unix port built with the module,
# the only place mod_usbhost.c compiles on a runner. (These moved here with
# usbhost from usbif's own workflows, 2026-10-19.)
name: usbhost

on:
push:
branches: [main]
paths:
- 'modules/usbhost/**'
- 'build_mp.py'
- 'modules.lock'
- 'patches/**'
- '.github/workflows/usbhost.yml'
pull_request:
paths:
- 'modules/usbhost/**'
- 'build_mp.py'
- 'modules.lock'
- 'patches/**'
- '.github/workflows/usbhost.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
c:
name: Host-testable C
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: modules/usbhost
steps:
- uses: actions/checkout@v7
- name: The SPSC ring and the byte ring
run: |
cc -std=c11 -Wall -Wextra -Werror -Isrc -o /tmp/test_ringbuf tests/test_ringbuf.c src/shared/usbhost_ringbuf.c
/tmp/test_ringbuf
cc -std=c11 -Wall -Wextra -Werror -Isrc -o /tmp/test_byte_ring tests/test_byte_ring.c src/shared/usbhost_byte_ring.c
/tmp/test_byte_ring
- name: The C sink's lifetime (usbif#43), plain, under ASan and under TSan
# Real threads: a writer racing close() and free().
run: |
SRCS="tests/test_pcm_sink.c src/shared/usbhost_byte_ring.c"
cc -std=c11 -Wall -Wextra -Werror -O2 -pthread -Isrc -o /tmp/test_pcm_sink $SRCS
/tmp/test_pcm_sink
cc -std=c11 -Wall -Wextra -Werror -O1 -g -pthread -fsanitize=address,undefined \
-Isrc -o /tmp/test_pcm_sink_asan $SRCS
/tmp/test_pcm_sink_asan
cc -std=c11 -Wall -Wextra -Werror -O1 -g -pthread -fsanitize=thread \
-Isrc -o /tmp/test_pcm_sink_tsan $SRCS
setarch -R /tmp/test_pcm_sink_tsan
- name: The C sink tests can fail (planted faults must be caught)
run: |
SRCS="tests/test_pcm_sink.c src/shared/usbhost_byte_ring.c"
for fault in USBHOST_PCM_SINK_PLANT_NO_WAIT USBHOST_PCM_SINK_PLANT_NO_TRYLOCK; do
cc -std=c11 -Wall -Wextra -Werror -O1 -g -pthread -fsanitize=address,undefined \
-Isrc -D$fault -o /tmp/test_pcm_sink_planted $SRCS
if /tmp/test_pcm_sink_planted > /tmp/planted.log 2>&1; then
cat /tmp/planted.log
echo "planted fault $fault was NOT caught"; exit 1
fi
echo "planted fault $fault caught:"; grep -E "FAIL|ERROR: AddressSanitizer" /tmp/planted.log | head -3
done
- name: The host streams' queue sizing, pacing, UVC framing and downmix
run: |
cc -std=c11 -Wall -Wextra -Werror -Isrc -o /tmp/test_iso_queue tests/test_iso_queue.c
/tmp/test_iso_queue
cc -std=c11 -Wall -Wextra -Werror -O1 -g -fsanitize=address,undefined -Isrc \
-o /tmp/test_iso_stream tests/test_iso_stream.c
/tmp/test_iso_stream
- name: The pacing, framing and downmix tests can fail
run: |
for fault in USBHOST_UVC_FRAME_PLANT_NO_SYNC USBHOST_ISO_PACE_PLANT_DROP_REMAINDER USBHOST_DOWNMIX_PLANT_LEFT_ONLY; do
cc -std=c11 -Wall -Wextra -Werror -Isrc -D$fault -o /tmp/test_iso_planted tests/test_iso_stream.c
if /tmp/test_iso_planted > /tmp/planted.log 2>&1; then
cat /tmp/planted.log
echo "planted fault $fault was NOT caught"; exit 1
fi
echo "planted fault $fault caught:"; grep FAIL /tmp/planted.log | head -3
done
- name: The sound card pump block (the meter reads what plays), and its planted fault
run: |
cc -std=c11 -Wall -Wextra -Werror -O1 -g -fsanitize=address,undefined -Isrc \
-o /tmp/test_pump_block tests/test_pump_block.c
/tmp/test_pump_block
cc -std=c11 -Wall -Wextra -Werror -Isrc -DUSBHOST_PUMP_PLANT_METER_BEFORE_GAIN \
-o /tmp/test_pump_block_planted tests/test_pump_block.c
if /tmp/test_pump_block_planted > /tmp/planted.log 2>&1; then
cat /tmp/planted.log
echo "metering before the gain was NOT caught"; exit 1
fi
echo "planted fault caught:"; grep FAIL /tmp/planted.log | head -3

python:
# The examples' checks, the guard that keeps _usbhost out of examples
# and docs, and the tick-rate scan of src/. The examples lean on
# pydevices' events, found at modules/pydevices.
name: Examples and source checks (CPython)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v7
with:
repository: PyDevices/pydevices
path: modules/pydevices
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- name: Run the suite
working-directory: modules/usbhost
run: python -m unittest discover -s tests -p "test_*.py" -v
- name: flake8 (defect checks only, configured in modules/usbhost/.flake8)
working-directory: modules/usbhost
run: |
python -m pip install flake8
python -m flake8

unix:
name: The unix port with usbhost
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- name: Install the unix port's build dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential pkg-config libffi-dev
- name: Build the unix port with usbhost
run: python3 build_mp.py --port unix --modules usbhost
- name: _usbhost imports and says which tree it was built from
run: |
./builds/unix/standard/micropython -c "import _usbhost; print(_usbhost.__revision__)"
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
!/modules/manifest.py
!/modules/all/
!/modules/castif/
!/modules/usbhost/
!/modules/audioif/
!/modules/cameraif/
!/modules/displayif/
!/modules/h264enc/
!/modules/tsmux/
!/modules/ppa/
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ New here? The [newcomer's guide](docs/newcomers.md) explains the model; the
- [`patches/tinyusb/`](patches/tinyusb/) — patches to the TinyUSB the esp32 port builds on the
S2, S3 and P4, which `build_mp.py` applies to `deps/espressif__tinyusb`
(at its `deps.lock` tag) and builds in place of the port's own copy.
- [`patches/micropython-lib/`](patches/micropython-lib/) — micropython-lib's own fixes from
after the commit MicroPython's `lib/micropython-lib` points at, which `apply_patches.py`
puts on the submodule after every update. A firmware that freezes those packages, and
a board whose `/lib` you fill from the submodule, both get them.
- [`variants/`](variants/) — our variants: `unix/` and `windows/` (`pydevices`,
`vst3-engine`), and `webassembly/` (`pydevices`, with the `wasmbridge`
module and a Fetch-backed `requests`), and `esp32/`: the sdkconfig
Expand Down
2 changes: 1 addition & 1 deletion UPSTREAM
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v1.29.0
b70ae1aca657bb93e2857dac4e2a2d21a3803200
20 changes: 15 additions & 5 deletions build_mp.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,8 @@ def ensure_micropython(ws):
if ws:
link(MP, ws / "micropython")
else:
upstream = (REPO / "UPSTREAM").read_text().strip()
say(f"cloning MicroPython {upstream}")
run(["git", "-c", "advice.detachedHead=false", "clone", "-q", "--depth", "1", "--branch", upstream, "https://github.com/micropython/micropython", str(MP)])
# UPSTREAM is a tag or a full commit: clone --branch takes only the first.
clone_at("https://github.com/micropython/micropython", (REPO / "UPSTREAM").read_text().strip(), MP)


# lvgl-bindings is pinned in modules.lock beside the modules, but it is not a
Expand Down Expand Up @@ -400,6 +399,17 @@ def our_variant_dir(port, variant):
return d if d.is_dir() else None


def frozen_manifest(port, board, variant):
"""The manifest a build freezes. A variant of ours, of a port or of a
board, may carry a manifest.py that includes modules/manifest.py and adds
what only that variant freezes; every other build freezes
modules/manifest.py itself."""
mine = board_variant_dir(port, board, variant) if board else our_variant_dir(port, variant)
if mine and (mine / "manifest.py").exists():
return mine / "manifest.py"
return MODULES_DIR / "manifest.py"


def module_choices():
return sorted(p.name for p in MODULES_DIR.iterdir() if p.is_dir() and not p.name.startswith("."))

Expand Down Expand Up @@ -1214,8 +1224,7 @@ def main():
make = ["make", "-C", str(port_dir), "-j", JOBS, f"BUILD={build.as_posix()}", *winpy]
prefix = ""
ours = our_variant_dir(port, variant) if not board else None
manifest = ours / "manifest.py" if ours and (ours / "manifest.py").exists() else MODULES_DIR / "manifest.py"
make.append(f"FROZEN_MANIFEST={manifest.as_posix()}")
make.append(f"FROZEN_MANIFEST={frozen_manifest(port, board, variant).as_posix()}")
if board:
make.append(f"BOARD={board}")
if variant:
Expand Down Expand Up @@ -1339,6 +1348,7 @@ def shell(cmd, log=None):
rec["rp2_storage_bytes"] = rp2_storage
rec["micropython"] = git_out(mp, "describe", "--always", "--abbrev=12")
rec["module_revisions"] = revisions
rec["micropython_lib"] = apply_patches.lib_record(mp)
if port == "esp32" and tinyusb:
rec["tinyusb"] = git_out(tinyusb, "describe", "--tags", "--always")
rec_path.write_text(json.dumps(rec, indent=1) + "\n")
Expand Down
Loading
Loading