pm-grid: fix dropped notes in chords (queue USB-MIDI packets)
The bulk MIDI endpoint holds one 4-byte packet until the host reads it (~once per USB frame), so calling send_bytes twice for simultaneous lane hits dropped the 2nd note (WouldBlock, silently ignored). Queue note-ons in a VecDeque and drain one-per-poll, keeping the rest for the next iteration — chords now play in full (staggered ~1ms, imperceptible) instead of all-but-one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
56bff7e599
commit
47ffb46aa2
1 changed files with 17 additions and 2 deletions
|
|
@ -19,6 +19,7 @@
|
|||
#![no_main]
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::collections::VecDeque;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use embedded_alloc::LlffHeap as Heap;
|
||||
|
|
@ -781,6 +782,9 @@ fn main() -> ! {
|
|||
let (mut nextrep_x, mut nextrep_y) = (0i64, 0i64);
|
||||
let mut last_frame_us = 0i64;
|
||||
let mut hb_us = 0i64;
|
||||
// pending USB-MIDI packets: the bulk endpoint holds one 4-byte packet at a time, so simultaneous
|
||||
// notes are queued here and drained one-per-poll (otherwise the 2nd note of a chord is dropped).
|
||||
let mut note_q: VecDeque<[u8; 4]> = VecDeque::new();
|
||||
|
||||
loop {
|
||||
let us = now_us();
|
||||
|
|
@ -842,10 +846,21 @@ fn main() -> ! {
|
|||
px = x;
|
||||
py = y;
|
||||
|
||||
// ---- scheduler: advance clocks, send a USB-MIDI note-on per lane hit (ch10) ----
|
||||
// ---- scheduler: advance clocks, queue a USB-MIDI note-on per lane hit (ch10) ----
|
||||
app.tick(now_ns, |note, vel| {
|
||||
let _ = midi.send_bytes([0x09, 0x99, note, vel]); // cable 0, note-on, channel 10
|
||||
if note_q.len() < 64 {
|
||||
note_q.push_back([0x09, 0x99, note, vel]); // cable 0, note-on, channel 10
|
||||
}
|
||||
});
|
||||
// drain the queue to the endpoint: send until it's busy (WouldBlock), keep the rest for the
|
||||
// next poll. This is why chords play in full instead of dropping all but the first note.
|
||||
while let Some(&pkt) = note_q.front() {
|
||||
if midi.send_bytes(pkt).is_ok() {
|
||||
note_q.pop_front();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- ticker scroll advance (~120ms) ----
|
||||
// (uses the frame clock implicitly; scroll_off wraps mod scroll_total)
|
||||
|
|
|
|||
Loading…
Reference in a new issue