USB device stack

Dependents:   MATSU-bed_blinky MATSU-bed_detection

Fork of USBDevice by mbed official

Revision:
48:03f8e580579a
Parent:
47:a0cd9646ecd1
Child:
50:a3c50882f2c5
diff -r a0cd9646ecd1 -r 03f8e580579a USBMIDI/USBMIDI.cpp
--- 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.