summaryrefslogtreecommitdiff
path: root/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI
diff options
context:
space:
mode:
authorJun Wako <wakojun@gmail.com>2015-04-24 16:26:14 +0900
committerJun Wako <wakojun@gmail.com>2015-04-24 16:26:14 +0900
commit1fe4406f374291ab2e86e95a97341fd9c475fcb8 (patch)
tree1be0e16b4b07b5a31ea97ec50a9eb13a288c3d27 /tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI
parenta20ef7052c6e937d2f7672dd59456e55a5c08296 (diff)
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
b9e0ea0 Merge commit '7fa9d8bdea3773d1195b04d98fcf27cf48ddd81d' as 'tool/mbed/mbed-sdk' 7fa9d8b Squashed 'tool/mbed/mbed-sdk/' content from commit 7c21ce5 git-subtree-dir: tmk_core git-subtree-split: b9e0ea08cb940de20b3610ecdda18e9d8cd7c552
Diffstat (limited to 'tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI')
-rw-r--r--tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/MIDIMessage.h276
-rw-r--r--tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/USBMIDI.cpp207
-rw-r--r--tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/USBMIDI.h112
3 files changed, 595 insertions, 0 deletions
diff --git a/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/MIDIMessage.h b/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/MIDIMessage.h
new file mode 100644
index 0000000000..9cfcf13635
--- /dev/null
+++ b/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/MIDIMessage.h
@@ -0,0 +1,276 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MIDIMESSAGE_H
+#define MIDIMESSAGE_H
+
+#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) ]
+//
+// MIDI Data Messages (Channel Specific)
+//
+// Message msg n m
+// ---------------------------------------------
+// Note Off 0x8 Key Velocity
+// Note On 0x9 Key Velocity
+// Polyphonic Aftertouch 0xA Key Pressure
+// Control Change 0xB Controller Value
+// Program Change 0xC Program -
+// Channel Aftertouch 0xD Pressure -
+// Pitch Wheel 0xE LSB MSB
+
+#define CABLE_NUM (0<<4)
+
+/** A MIDI message container */
+class MIDIMessage {
+public:
+ MIDIMessage() : length(4) {}
+
+ MIDIMessage(uint8_t *buf) : length(4) {
+ for (int i = 0; i < 4; i++)
+ 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
+ * @param key Key ID
+ * @param velocity Key velocity (0-127, default = 127)
+ * @param channel Key channel (0-15, default 0)
+ * @returns A MIDIMessage
+ */
+ static MIDIMessage NoteOff(int key, int velocity = 127, int channel = 0) {
+ MIDIMessage msg;
+ msg.data[0] = CABLE_NUM | 0x08;
+ msg.data[1] = 0x80 | (channel & 0x0F);
+ msg.data[2] = key & 0x7F;
+ msg.data[3] = velocity & 0x7F;
+ return msg;
+ }
+
+ /** Create a NoteOn message
+ * @param key Key ID
+ * @param velocity Key velocity (0-127, default = 127)
+ * @param channel Key channel (0-15, default 0)
+ * @returns A MIDIMessage
+ */
+ static MIDIMessage NoteOn(int key, int velocity = 127, int channel = 0) {
+ MIDIMessage msg;
+ msg.data[0] = CABLE_NUM | 0x09;
+ msg.data[1] = 0x90 | (channel & 0x0F);
+ msg.data[2] = key & 0x7F;
+ msg.data[3] = velocity & 0x7F;
+ return msg;
+ }
+
+ /** Create a PolyPhonic Aftertouch message
+ * @param key Key ID
+ * @param pressure Aftertouch pressure (0-127)
+ * @param channel Key channel (0-15, default 0)
+ * @returns A MIDIMessage
+ */
+ static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) {
+ MIDIMessage msg;
+ msg.data[0] = CABLE_NUM | 0x0A;
+ msg.data[1] = 0xA0 | (channel & 0x0F);
+ msg.data[2] = key & 0x7F;
+ msg.data[3] = pressure & 0x7F;
+ return msg;
+ }
+
+ /** Create a Control Change message
+ * @param control Controller ID
+ * @param value Controller value (0-127)
+ * @param channel Controller channel (0-15, default 0)
+ * @returns A MIDIMessage
+ */
+ static MIDIMessage ControlChange(int control, int value, int channel = 0) {
+ MIDIMessage msg;
+ msg.data[0] = CABLE_NUM | 0x0B;
+ msg.data[1] = 0xB0 | (channel & 0x0F);
+ msg.data[2] = control & 0x7F;
+ msg.data[3] = value & 0x7F;
+ return msg;
+ }
+
+ /** Create a Program Change message
+ * @param program Program ID
+ * @param channel Channel (0-15, default 0)
+ * @returns A MIDIMessage
+ */
+ static MIDIMessage ProgramChange(int program, int channel = 0) {
+ MIDIMessage msg;
+ msg.data[0] = CABLE_NUM | 0x0C;
+ msg.data[1] = 0xC0 | (channel & 0x0F);
+ msg.data[2] = program & 0x7F;
+ msg.data[3] = 0x00;
+ return msg;
+ }
+
+ /** Create a Channel Aftertouch message
+ * @param pressure Pressure
+ * @param channel Key channel (0-15, default 0)
+ * @returns A MIDIMessage
+ */
+ static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) {
+ MIDIMessage msg;
+ msg.data[0] = CABLE_NUM | 0x0D;
+ msg.data[1] = 0xD0 | (channel & 0x0F);
+ msg.data[2] = pressure & 0x7F;
+ msg.data[3] = 0x00;
+ return msg;
+ }
+
+ /** Create a Pitch Wheel message
+ * @param pitch Pitch (-8192 - 8191, default = 0)
+ * @param channel Channel (0-15, default 0)
+ * @returns A MIDIMessage
+ */
+ static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) {
+ MIDIMessage msg;
+ int p = pitch + 8192; // 0 - 16383, 8192 is center
+ msg.data[0] = CABLE_NUM | 0x0E;
+ msg.data[1] = 0xE0 | (channel & 0x0F);
+ msg.data[2] = p & 0x7F;
+ msg.data[3] = (p >> 7) & 0x7F;
+ return msg;
+ }
+
+ /** Create an All Notes Off message
+ * @param channel Channel (0-15, default 0)
+ * @returns A MIDIMessage
+ */
+ static MIDIMessage AllNotesOff(int channel = 0) {
+ 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 */
+ enum MIDIMessageType {
+ ErrorType,
+ NoteOffType,
+ NoteOnType,
+ PolyphonicAftertouchType,
+ ControlChangeType,
+ ProgramChangeType,
+ ChannelAftertouchType,
+ PitchWheelType,
+ AllNotesOffType,
+ SysExType
+ };
+
+ /** Read the message type
+ * @returns MIDIMessageType
+ */
+ MIDIMessageType type() {
+ switch((data[1] >> 4) & 0xF) {
+ case 0x8: return NoteOffType;
+ case 0x9: return NoteOnType;
+ case 0xA: return PolyphonicAftertouchType;
+ case 0xB:
+ if(controller() < 120) { // standard controllers
+ return ControlChangeType;
+ } else if(controller() == 123) {
+ return AllNotesOffType;
+ } else {
+ return ErrorType; // unsupported atm
+ }
+ case 0xC: return ProgramChangeType;
+ case 0xD: return ChannelAftertouchType;
+ case 0xE: return PitchWheelType;
+ case 0xF: return SysExType;
+ default: return ErrorType;
+ }
+ }
+
+ /** Read the channel number */
+ int channel() {
+ return (data[1] & 0x0F);
+ }
+
+ /** Read the key ID */
+ int key() {
+ return (data[2] & 0x7F);
+ }
+
+ /** Read the velocity */
+ int velocity() {
+ return (data[3] & 0x7F);
+ }
+
+ /** Read the controller value */
+ int value() {
+ return (data[3] & 0x7F);
+ }
+
+ /** Read the aftertouch pressure */
+ int pressure() {
+ if(type() == PolyphonicAftertouchType) {
+ return (data[3] & 0x7F);
+ } else {
+ return (data[2] & 0x7F);
+ }
+ }
+
+ /** Read the controller number */
+ int controller() {
+ return (data[2] & 0x7F);
+ }
+
+ /** Read the program number */
+ int program() {
+ return (data[2] & 0x7F);
+ }
+
+ /** Read the pitch value */
+ int pitch() {
+ int p = ((data[3] & 0x7F) << 7) | (data[2] & 0x7F);
+ return p - 8192; // 0 - 16383, 8192 is center
+ }
+
+ uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
+ uint8_t length;
+};
+
+#endif
diff --git a/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/USBMIDI.cpp b/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/USBMIDI.cpp
new file mode 100644
index 0000000000..084574a790
--- /dev/null
+++ b/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/USBMIDI.cpp
@@ -0,0 +1,207 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMIDI.h"
+
+
+USBMIDI::USBMIDI(uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
+ : USBDevice(vendor_id, product_id, product_release), cur_data(0), data_end(true)
+{
+ midi_evt = NULL;
+ USBDevice::connect();
+}
+
+// write plain MIDIMessage that will be converted to USBMidi event packet
+void USBMIDI::write(MIDIMessage m) {
+ // 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);
+ }
+}
+
+
+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) {
+ 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
+ readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+ return true;
+}
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported.
+bool USBMIDI::USBCallback_setConfiguration(uint8_t configuration) {
+ if (configuration != DEFAULT_CONFIGURATION) {
+ return false;
+ }
+
+ // Configure endpoints > 0
+ addEndpoint(EPBULK_IN, MAX_PACKET_SIZE_EPBULK);
+ addEndpoint(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+
+ // We activate the endpoint to be able to receive data
+ readStart(EPBULK_OUT, MAX_PACKET_SIZE_EPBULK);
+ return true;
+}
+
+
+uint8_t * USBMIDI::stringIinterfaceDesc() {
+ static uint8_t stringIinterfaceDescriptor[] = {
+ 0x0c, //bLength
+ STRING_DESCRIPTOR, //bDescriptorType 0x03
+ 'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
+ };
+ return stringIinterfaceDescriptor;
+}
+
+uint8_t * USBMIDI::stringIproductDesc() {
+ static uint8_t stringIproductDescriptor[] = {
+ 0x16, //bLength
+ STRING_DESCRIPTOR, //bDescriptorType 0x03
+ 'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
+ };
+ return stringIproductDescriptor;
+}
+
+
+uint8_t * USBMIDI::configurationDesc() {
+ static uint8_t configDescriptor[] = {
+ // configuration descriptor
+ 0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50,
+
+ // The Audio Interface Collection
+ 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, // Standard AC Interface Descriptor
+ 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, // Class-specific AC Interface Descriptor
+ 0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, // MIDIStreaming Interface Descriptors
+ 0x07, 0x24, 0x01, 0x00, 0x01, 0x41, 0x00, // Class-Specific MS Interface Header Descriptor
+
+ // MIDI IN JACKS
+ 0x06, 0x24, 0x02, 0x01, 0x01, 0x00,
+ 0x06, 0x24, 0x02, 0x02, 0x02, 0x00,
+
+ // MIDI OUT JACKS
+ 0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00,
+ 0x09, 0x24, 0x03, 0x02, 0x06, 0x01, 0x01, 0x01, 0x00,
+
+ // OUT endpoint descriptor
+ 0x09, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x25, 0x01, 0x01, 0x01,
+
+ // IN endpoint descriptor
+ 0x09, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x25, 0x01, 0x01, 0x03,
+ };
+ return configDescriptor;
+}
diff --git a/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/USBMIDI.h b/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/USBMIDI.h
new file mode 100644
index 0000000000..cc5be5b7d8
--- /dev/null
+++ b/tool/mbed/mbed-sdk/libraries/USBDevice/USBMIDI/USBMIDI.h
@@ -0,0 +1,112 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBMIDI_H
+#define USBMIDI_H
+
+/* These headers are included for child class. */
+#include "USBEndpoints.h"
+#include "USBDescriptor.h"
+#include "USBDevice_Types.h"
+
+#include "USBDevice.h"
+#include "MIDIMessage.h"
+
+#define DEFAULT_CONFIGURATION (1)
+
+/**
+* USBMIDI example
+*
+* @code
+* #include "mbed.h"
+* #include "USBMIDI.h"
+*
+* USBMIDI midi;
+*
+* int main() {
+* while (1) {
+* for(int i=48; i<83; i++) { // send some messages!
+* midi.write(MIDIMessage::NoteOn(i));
+* wait(0.25);
+* midi.write(MIDIMessage::NoteOff(i));
+* wait(0.5);
+* }
+* }
+* }
+* @endcode
+*/
+class USBMIDI: public USBDevice {
+public:
+
+ /**
+ * Constructor
+ *
+ * @param vendor_id Your vendor_id
+ * @param product_id Your product_id
+ * @param product_release Your preoduct_release
+ */
+ USBMIDI(uint16_t vendor_id = 0x0700, uint16_t product_id = 0x0101, uint16_t product_release = 0x0001);
+
+ /**
+ * Send a MIDIMessage
+ *
+ * @param m The MIDIMessage to send
+ */
+ void write(MIDIMessage m);
+
+ /**
+ * Attach a callback for when a MIDIEvent is received
+ *
+ * @param fptr function pointer
+ */
+ void attach(void (*fptr)(MIDIMessage));
+
+
+protected:
+ virtual bool EPBULK_OUT_callback();
+ virtual bool USBCallback_setConfiguration(uint8_t configuration);
+ /*
+ * Get string product descriptor
+ *
+ * @returns pointer to the string product descriptor
+ */
+ virtual uint8_t * stringIproductDesc();
+
+ /*
+ * Get string interface descriptor
+ *
+ * @returns pointer to the string interface descriptor
+ */
+ virtual uint8_t * stringIinterfaceDesc();
+
+ /*
+ * Get configuration descriptor
+ *
+ * @returns pointer to the configuration descriptor
+ */
+ virtual uint8_t * configurationDesc();
+
+private:
+ uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
+ uint8_t cur_data;
+ bool data_end;
+
+ void (*midi_evt)(MIDIMessage);
+};
+
+#endif