mirror of https://github.com/ARMmbed/mbed-os.git
USBMIDI: Add SysEx support
parent
8311bafba5
commit
1793b6a80a
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include "mbed.h"
|
||||
|
||||
#define MAX_MIDI_MESSAGE_SIZE 256 // Max message size. SysEx can be up to 65536 but 256 should be fine for most usage
|
||||
|
||||
// MIDI Message Format
|
||||
//
|
||||
// [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ]
|
||||
|
@ -49,6 +51,16 @@ public:
|
|||
data[i] = buf[i];
|
||||
}
|
||||
|
||||
// New constructor, buf is a true MIDI message (not USBMidi message) and buf_len true message length.
|
||||
MIDIMessage(uint8_t *buf, int buf_len) {
|
||||
length=buf_len+1;
|
||||
// first byte keeped for retro-compatibility
|
||||
data[0]=0;
|
||||
|
||||
for (int i = 0; i < buf_len; i++)
|
||||
data[i+1] = buf[i];
|
||||
}
|
||||
|
||||
// create messages
|
||||
|
||||
/** Create a NoteOff message
|
||||
|
@ -174,7 +186,8 @@ public:
|
|||
ProgramChangeType,
|
||||
ChannelAftertouchType,
|
||||
PitchWheelType,
|
||||
AllNotesOffType
|
||||
AllNotesOffType,
|
||||
SysExType
|
||||
};
|
||||
|
||||
/** Read the message type
|
||||
|
@ -196,6 +209,7 @@ public:
|
|||
case 0xC: return ProgramChangeType;
|
||||
case 0xD: return ChannelAftertouchType;
|
||||
case 0xE: return PitchWheelType;
|
||||
case 0xF: return SysExType;
|
||||
default: return ErrorType;
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +259,8 @@ public:
|
|||
return p - 8192; // 0 - 16383, 8192 is center
|
||||
}
|
||||
|
||||
uint8_t data[4];
|
||||
uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
|
||||
uint8_t length=4;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,8 +25,41 @@ USBMIDI::USBMIDI(uint16_t vendor_id, uint16_t product_id, uint16_t product_relea
|
|||
USBDevice::connect();
|
||||
}
|
||||
|
||||
// write plain MIDIMessage that will be converted to USBMidi event packet
|
||||
void USBMIDI::write(MIDIMessage m) {
|
||||
USBDevice::write(EPBULK_IN, m.data, 4, MAX_PACKET_SIZE_EPBULK);
|
||||
// first byte keeped for retro-compatibility
|
||||
for(int p=1; p < m.length; p+=3) {
|
||||
uint8_t buf[4];
|
||||
// Midi message to USBMidi event packet
|
||||
buf[0]=m.data[p] >> 4;
|
||||
// SysEx
|
||||
if(buf[0] == 0xF) {
|
||||
if(p < m.length-1) {
|
||||
// SysEx start or continue
|
||||
buf[0]=0x4;
|
||||
} else {
|
||||
switch(m.length - p) {
|
||||
case 1:
|
||||
// SysEx end with one byte
|
||||
buf[0]=0x5;
|
||||
break;
|
||||
case 2:
|
||||
// SysEx end with two bytes
|
||||
buf[0]=0x6;
|
||||
break;
|
||||
case 3:
|
||||
// SysEx end with three bytes
|
||||
buf[0]=0x7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
buf[1]=m.data[p];
|
||||
buf[2]=m.data[p+1];
|
||||
buf[3]=m.data[p+2];
|
||||
|
||||
USBDevice::write(EPBULK_IN, buf, 4, MAX_PACKET_SIZE_EPBULK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,16 +67,61 @@ void USBMIDI::attach(void (*fptr)(MIDIMessage)) {
|
|||
midi_evt = fptr;
|
||||
}
|
||||
|
||||
|
||||
bool USBMIDI::EPBULK_OUT_callback() {
|
||||
uint8_t buf[64];
|
||||
uint32_t len;
|
||||
readEP(EPBULK_OUT, buf, &len, 64);
|
||||
|
||||
if (midi_evt != NULL) {
|
||||
for (uint32_t i=0; i<len; i+=4) {
|
||||
midi_evt(MIDIMessage(buf+i));
|
||||
}
|
||||
for (uint32_t i=0; i<len; i+=4) {
|
||||
uint8_t data_read;
|
||||
data_end=true;
|
||||
switch(buf[i]) {
|
||||
case 0x2:
|
||||
// Two-bytes System Common Message - undefined in USBMidi 1.0
|
||||
data_read=2;
|
||||
break;
|
||||
case 0x4:
|
||||
// SysEx start or continue
|
||||
data_end=false;
|
||||
data_read=3;
|
||||
break;
|
||||
case 0x5:
|
||||
// Single-byte System Common Message or SysEx end with one byte
|
||||
data_read=1;
|
||||
break;
|
||||
case 0x6:
|
||||
// SysEx end with two bytes
|
||||
data_read=2;
|
||||
break;
|
||||
case 0xC:
|
||||
// Program change
|
||||
data_read=2;
|
||||
break;
|
||||
case 0xD:
|
||||
// Channel pressure
|
||||
data_read=2;
|
||||
break;
|
||||
case 0xF:
|
||||
// Single byte
|
||||
data_read=1;
|
||||
break;
|
||||
default:
|
||||
// Others three-bytes messages
|
||||
data_read=3;
|
||||
break;
|
||||
}
|
||||
|
||||
for(uint8_t j=1;j<data_read+1;j++) {
|
||||
data[cur_data]=buf[i+j];
|
||||
cur_data++;
|
||||
}
|
||||
|
||||
if(data_end) {
|
||||
midi_evt(MIDIMessage(data,cur_data));
|
||||
cur_data=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We reactivate the endpoint to receive next characters
|
||||
|
@ -51,8 +129,6 @@ bool USBMIDI::EPBULK_OUT_callback() {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Called in ISR context
|
||||
// Set configuration. Return false if the
|
||||
// configuration is not supported.
|
||||
|
|
|
@ -102,8 +102,11 @@ protected:
|
|||
virtual uint8_t * configurationDesc();
|
||||
|
||||
private:
|
||||
uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
|
||||
uint8_t cur_data=0;
|
||||
bool data_end = true;
|
||||
|
||||
void (*midi_evt)(MIDIMessage);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue