2019-09-15 17:57:48 +10:00
|
|
|
usbd-midi
|
|
|
|
=========
|
|
|
|
|
|
|
|
A simple usb midi device class for [usb-device](https://crates.io/crates/usb-device).
|
|
|
|
|
|
|
|
Currently this aims to be a very simple implementation, that allows the micro
|
2020-12-30 12:04:00 +11:00
|
|
|
controller to send MIDI information to the PC and also receive MIDI information.
|
2019-09-15 17:57:48 +10:00
|
|
|
|
2019-12-27 21:39:18 +11:00
|
|
|
This crate requires the use of a hardware driver, that implements the
|
2019-09-15 17:57:48 +10:00
|
|
|
usb-device traits.
|
|
|
|
|
2020-12-30 12:04:00 +11:00
|
|
|
## Example
|
|
|
|
|
|
|
|
### Receive MIDI
|
|
|
|
Turn on the integrated LED of a STM32 BluePill board as long as C2 is pressed
|
|
|
|
```rust
|
|
|
|
fn main() -> ! {
|
|
|
|
let dp = pac::Peripherals::take().unwrap();
|
|
|
|
|
|
|
|
let mut rcc = dp.RCC.constrain();
|
|
|
|
|
|
|
|
let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
|
|
|
|
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
|
|
|
|
|
|
|
|
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
|
|
|
led.set_high().unwrap();
|
|
|
|
|
|
|
|
let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh);
|
|
|
|
|
|
|
|
let usb = Peripheral {
|
|
|
|
usb: dp.USB,
|
|
|
|
pin_dm: gpioa.pa11,
|
|
|
|
pin_dp: usb_dp.into_floating_input(&mut gpioa.crh),
|
|
|
|
};
|
|
|
|
|
|
|
|
let usb_bus = UsbBus::new(usb);
|
|
|
|
|
2021-04-13 09:03:24 +10:00
|
|
|
let mut midi = MidiClass::new(&usb_bus, 1, 1);
|
2020-12-30 12:04:00 +11:00
|
|
|
|
|
|
|
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x5e4))
|
|
|
|
.product("MIDI Test")
|
|
|
|
.device_class(USB_AUDIO_CLASS)
|
|
|
|
.device_sub_class(USB_MIDISTREAMING_SUBCLASS)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
loop {
|
|
|
|
if !usb_dev.poll(&mut [&mut midi]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut buffer = [0; 64];
|
|
|
|
|
|
|
|
if let Ok(size) = midi.read(&mut buffer) {
|
|
|
|
let buffer_reader = MidiPacketBufferReader::new(&buffer, size);
|
|
|
|
for packet in buffer_reader.into_iter() {
|
|
|
|
if let Ok(packet) = packet {
|
|
|
|
match packet.message {
|
|
|
|
Message::NoteOn(Channel1, Note::C2, ..) => {
|
|
|
|
led.set_low().unwrap();
|
|
|
|
},
|
|
|
|
Message::NoteOff(Channel1, Note::C2, ..) => {
|
|
|
|
led.set_high().unwrap();
|
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-13 09:03:24 +10:00
|
|
|
```
|
|
|
|
|
|
|
|
## Using more than one MIDI port
|
|
|
|
|
|
|
|
Calling `MidiClass::new(&usb_bus, N, M);` with `N, M >= 1` to provide more
|
|
|
|
than one input or output port requires the `control-buffer-256` feature of
|
|
|
|
the usb-device crate:
|
|
|
|
|
|
|
|
Cargo.toml:
|
|
|
|
```
|
|
|
|
usb-device = { version = ">=0.2.1", features = ["control-buffer-256"] }
|
|
|
|
```
|
|
|
|
|
|
|
|
Up to 5 in/out pairs can be used this way until we again run out of buffer
|
|
|
|
space. Note that exceeding the available buffer space will silently fail
|
|
|
|
to send the descriptors correctly, no obvious `panic!` will hint the
|
|
|
|
actual problem.
|