USB device stack

Dependents:   mbed-mX-USB-TEST1 USBMSD_SD_HID_HelloWorld HidTest MIDI_usb_bridge ... more

Legacy Warning

This is an mbed 2 library. To learn more about mbed OS 5, visit the docs.

Pull requests against this repository are no longer supported. Please raise against mbed OS 5 as documented above.

Files at this revision

API Documentation at this revision

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

USBMIDI/MIDIMessage.h Show annotated file Show diff for this revision Revisions of this file
USBMIDI/USBMIDI.cpp Show annotated file Show diff for this revision Revisions of this file
USBMIDI/USBMIDI.h Show annotated file Show diff for this revision Revisions of this file
--- 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