USBDevice with Nucleo 32L476RG support
Dependents: ObCP_ENSMM_V2020_Test_Accelero
Revision 48:03f8e580579a, committed 2015-04-16
- Comitter:
- mbed_official
- Date:
- Thu Apr 16 11:00:20 2015 +0100
- Parent:
- 47:a0cd9646ecd1
- Child:
- 49:bee5808e91e3
- Commit message:
- Synchronized with git revision 1b9e8d686fd7448739e56182eb1f7cc0634667b5
Full URL: https://github.com/mbedmicro/mbed/commit/1b9e8d686fd7448739e56182eb1f7cc0634667b5/
Add SysEx to USBMIDI device
Changed in this revision
--- a/USBMIDI/MIDIMessage.h Wed Apr 08 07:46:23 2015 +0100 +++ b/USBMIDI/MIDIMessage.h Thu Apr 16 11:00:20 2015 +0100 @@ -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 @@ 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 @@ -162,6 +174,16 @@ return ControlChange(123, 0, channel); } + /** Create a SysEx message + * @param data SysEx data (including 0xF0 .. 0xF7) + * @param len SysEx data length + * @returns A MIDIMessage + */ + static MIDIMessage SysEx(uint8_t *data, int len) { + MIDIMessage msg=MIDIMessage(data,len); + return msg; + } + // decode messages /** MIDI Message Types */ @@ -174,7 +196,8 @@ ProgramChangeType, ChannelAftertouchType, PitchWheelType, - AllNotesOffType + AllNotesOffType, + SysExType }; /** Read the message type @@ -196,6 +219,7 @@ case 0xC: return ProgramChangeType; case 0xD: return ChannelAftertouchType; case 0xE: return PitchWheelType; + case 0xF: return SysExType; default: return ErrorType; } } @@ -245,7 +269,8 @@ 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
--- a/USBMIDI/USBMIDI.cpp Wed Apr 08 07:46:23 2015 +0100 +++ b/USBMIDI/USBMIDI.cpp Thu Apr 16 11:00:20 2015 +0100 @@ -25,8 +25,49 @@ 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[1] >> 4; + // SysEx + if(buf[0] == 0xF) { + if((m.length - p) > 3) { + // 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]; + + if(p+1 < m.length) + buf[2]=m.data[p+1]; + else + buf[2]=0; + + if(p+2 < m.length) + buf[3]=m.data[p+2]; + else + buf[3]=0; + + USBDevice::write(EPBULK_IN, buf, 4, MAX_PACKET_SIZE_EPBULK); + } } @@ -34,16 +75,61 @@ 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 +137,6 @@ return true; } - - // Called in ISR context // Set configuration. Return false if the // configuration is not supported.
--- a/USBMIDI/USBMIDI.h Wed Apr 08 07:46:23 2015 +0100 +++ b/USBMIDI/USBMIDI.h Thu Apr 16 11:00:20 2015 +0100 @@ -102,8 +102,11 @@ 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