Skip to content

Commit

Permalink
Added functions to detect SysEx packets
Browse files Browse the repository at this point in the history
  • Loading branch information
sourcebox committed Dec 22, 2024
1 parent 5f08120 commit 1f2203f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ This release focuses on:
- `UsbMidiEventPacket::as_raw_bytes` function.
- `UsbMidiEventPacket::to_raw_bytes` function.
- `UsbMidiEventPacket::try_from_payload_bytes` function.
- `UsbMidiEventPacket::is_sysex` function.
- `UsbMidiEventPacket::is_sysex_start` function.
- `UsbMidiEventPacket::is_sysex_end` function.
- `TryFrom<&UsbMidiEventPacket>` implementation for `Message` type.
- `Message::into_packet` function.
- `Message::code_index_number` function.
Expand Down
1 change: 1 addition & 0 deletions examples/example-esp32s3/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ esp-println = { version = "0.12.0", features = ["esp32s3", "log"] }
usb-device = { version = "0.3.2", features = ["control-buffer-256"] }
usbd-midi = { path = "../../" }
midi-convert = "0.2.0"
heapless = "0.8.0"
31 changes: 28 additions & 3 deletions examples/example-esp32s3/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use core::ptr::addr_of_mut;
use esp_backtrace as _;
use esp_hal::{clock, gpio, otg_fs, xtensa_lx_rt, Config};
use esp_println::println;
use heapless::Vec;
use midi_convert::midi_types::{Channel, MidiMessage, Note, Value7};
use midi_convert::{parse::MidiTryParseSlice, render_slice::MidiRenderSlice};
use usb_device::prelude::*;
Expand Down Expand Up @@ -41,17 +42,41 @@ fn main() -> ! {
let button = gpio::Input::new(peripherals.GPIO0, gpio::Pull::Up);
let mut last_button_level = button.level();

let mut sysex_buffer = Vec::<u8, 64>::new();

loop {
if usb_dev.poll(&mut [&mut midi_class]) {
// Receive messages.
let mut buffer = [0; 64];

if let Ok(size) = midi_class.read(&mut buffer) {
let buffer_reader = MidiPacketBufferReader::new(&buffer, size);
for packet in buffer_reader.into_iter() {
if let Ok(packet) = packet {
for packet in buffer_reader.into_iter().flatten() {
if !packet.is_sysex() {
let message = MidiMessage::try_parse_slice(packet.payload_bytes());
println!("Cable: {:?}, Message: {:?}", packet.cable_number(), message);
println!(
"Regular Message, cable: {:?}, message: {:?}",
packet.cable_number(),
message
);
} else {
if packet.is_sysex_start() {
println!("SysEx message start");
sysex_buffer.clear();
}

match sysex_buffer.extend_from_slice(packet.payload_bytes()) {
Ok(_) => {
if packet.is_sysex_end() {
println!("SysEx message end");
println!("Buffered SysEx message: {:?}", sysex_buffer);
}
}
Err(_) => {
println!("SysEx buffer overflow.");
break;
}
}
}
}
}
Expand Down
26 changes: 26 additions & 0 deletions src/packet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,30 @@ impl UsbMidiEventPacket {

Ok(Self { raw })
}

/// Returns if the packet payload is part of a SysEx message.
pub fn is_sysex(&self) -> bool {
let Ok(cin) = CodeIndexNumber::try_from(self.raw[0] & 0x0F) else {
return false;
};

match cin {
CodeIndexNumber::SysexStartsOrContinues
| CodeIndexNumber::SysexEnds2Bytes
| CodeIndexNumber::SysexEnds3Bytes => true,
CodeIndexNumber::SystemCommon1Byte => self.raw[1] == 0xF7,
CodeIndexNumber::SingleByte => self.raw[1] < 0x80,
_ => false,
}
}

/// Returns if the packet payload contains the start of a SysEx message.
pub fn is_sysex_start(&self) -> bool {
self.is_sysex() && self.raw[1] == 0xF0
}

/// Returns if the packet payload contains the end of a SysEx message.
pub fn is_sysex_end(&self) -> bool {
self.is_sysex() && (self.raw[1] == 0xF7 || self.raw[2] == 0xF7 || self.raw[3] == 0xF7)
}
}

0 comments on commit 1f2203f

Please sign in to comment.