Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions examples/atmega32u4-device-arduino/src/ci_responder.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@ static uint32_t ci_rng(void *ctx) {

static uint32_t ci_write_fn(const uint32_t *words, uint32_t count, void *ctx) {
(void)ctx;
for (uint32_t i = 0; i < count; i++)
if (!midi2duino_write_word(words[i]))
return i; /* ring full: partial write reported */
return count;
/* Whole packet or nothing: a split would leave half a UMP in the ring and
* corrupt the USB output. Pump the transport while the ring is full, with
* a bound so a host that stops reading cannot hang the responder. */
for (uint16_t tries = 0; tries < 1000; tries++) {
if (midi2duino_write(words, (uint8_t)count))
return count;
midi2duino_task();
}
return 0;
}

void ci_responder_init(void) {
Expand Down
14 changes: 10 additions & 4 deletions examples/atmega32u4-device-arduino/src/midi2_usb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ static midi2_dispatch g_dp;
static midi2_proc_state g_proc;
static uint8_t g_sysex7_buf[160]; /* MIDI-CI reassembly */

/* Stream messages (MT 0xF) drive the responder; everything else echoes back.
/* Stream messages drive the responder; everything else echoes back.
* SysEx7 never lands here: the processor reassembles it and delivers it
* through on_sysex7 to the MIDI-CI responder. */
static void on_ump(const uint32_t *words, uint8_t word_count, void *ctx) {
(void)ctx;
if ((words[0] >> 28) == 0xF)
if (midi2_msg_get_mt(words) == MIDI2_MT_STREAM)
midi2_dispatch_feed(words, word_count, &g_dp);
else
midi2duino_write(words, word_count);
Expand Down Expand Up @@ -56,13 +56,19 @@ void Midi2Usb::task() {
return;
have = 1;
}
uint8_t need = midi2_msg_word_count((uint8_t)(msg[0] >> 28));
uint8_t mt = midi2_msg_get_mt(msg);
uint8_t need = midi2_msg_word_count(mt);
while (have < need) {
if (!midi2duino_read(&w))
return; /* rest of the message next round */
msg[have++] = w;
}
midi2_proc_feed(&g_proc, msg, need);
/* Data128 (SysEx8 / MDS) is echoed raw: midi2_proc consumes it for
* reassembly, which is off here, so it never reaches on_ump. */
if (mt == MIDI2_MT_DATA128)
midi2duino_write(msg, need);
else
midi2_proc_feed(&g_proc, msg, need);
have = 0;
}
}
Expand Down
9 changes: 8 additions & 1 deletion examples/atmega32u4-device-arduino/src/stream_responder.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@
#define IDENT_VERSION 0x00010000UL /* 1.0 */
#define FB_NUM_MAIN 0

/* A dropped Stream reply breaks host discovery, so pump the transport until
* the packet fits. Bounded so a host that stops reading cannot hang the loop
* (the pump only moves rings to endpoints; it never re-enters the processor). */
static void send4(const uint32_t *w) {
midi2duino_write(w, 4);
for (uint16_t tries = 0; tries < 1000; tries++) {
if (midi2duino_write(w, 4))
return;
midi2duino_task();
}
}

/* multi-packet text notification, 14 bytes per UMP (13 for FB name) */
Expand Down
Loading