Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save TomWhitwell/a7023fb08c8570e4fb55077bc7cf05da to your computer and use it in GitHub Desktop.
Save TomWhitwell/a7023fb08c8570e4fb55077bc7cf05da to your computer and use it in GitHub Desktop.
Notes on fix for Music Thing Workshop System MIDI on Windows devices
Solutions in these notes entirely generated by ChatGPT - use with caution
1 Service the USB device every pass through loop()
Symptom fixed: hard-fault a few seconds after Windows starts flooding the control endpoint.
Windows sends class–specific SET_INTERFACE / SET_CUR requests in quick bursts; if the device
code is busy in analogRead() etc. and never re-enters TinyUSB for > ~3 ms the control EP0
state machine underflows and panics.
void loop() {
// --- PATCH 1: keep TinyUSB alive on Windows -------------
TinyUSBDevice.task(); // << NEW – poll USB engine
2 Trim over-long string descriptors (< 31 chars)
Windows’ built-in USB-Audio/MIDI driver rejects interface strings ≥ 32 UTF-16 code-units and tears
the whole device down .
Your current strings are 32 chars long.
void setup() {
// Initialise MIDI
- TinyUSBDevice.setManufacturerDescriptor("Music Thing Modular");
- TinyUSBDevice.setProductDescriptor("Workshop System MIDI");
+ TinyUSBDevice.setManufacturerDescriptor("MT Modular");
+ TinyUSBDevice.setProductDescriptor("Workshop MIDI");
3 Give Windows a unique iSerialNumber
Without one, each time you plug into a new USB port Windows adds a fresh registry entry,
quickly exhausting the 10-device MIDI quota and corrupting earlier entries
– after which new connections crash during enumeration.
Add just after the other descriptors:
#include "pico/unique_id.h" // <-- NEW
void setup() {
...
+ // --- PATCH 3: per-board serial number -------------------
+ char serial[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1];
+ pico_get_unique_board_id_string(serial, sizeof serial);
+ TinyUSBDevice.setSerialDescriptor(serial);
NB: I'm not certain this is working
4 Enlarge TinyUSB’s MIDI FIFOs (Windows bursts > 64 bytes)
Windows DAWs often dump several hundred bytes of parameter state immediately after opening a port.
With the default 64-byte RX buffer TinyUSB overruns, asserts, and the RP2040 reboots
#define CFG_TUD_MIDI_RX_BUFSIZE 512
#define CFG_TUD_MIDI_TX_BUFSIZE 512
#define CFG_TUD_MIDI_EP_BUFSIZE 64
5 Throttle your own CC spam just enough
Even with bigger FIFOs you’re sending up to 8 CCs every ~2 ms when a DAW is also sending data.
Give TinyUSB a chance to flush:
if (analog[i]->hasChanged()) {
MIDI.sendControlChange(45 + i, analog[i]->getValue() >> 5, 1);
- delay(1); // old
+ tud_task(); // << replace delay with USB poll
}
delay(1) blocks interrupts; tud_task() services USB and returns in ~30 µs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment