USB Serial application

Fork of USBSerial_HelloWorld by Samuel Mokrani

Committer:
Zaitsev
Date:
Tue Jan 10 20:42:26 2017 +0000
Revision:
10:41552d038a69
USB Serial bi-directional bridge

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Zaitsev 10:41552d038a69 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
Zaitsev 10:41552d038a69 2 *
Zaitsev 10:41552d038a69 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
Zaitsev 10:41552d038a69 4 * and associated documentation files (the "Software"), to deal in the Software without
Zaitsev 10:41552d038a69 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
Zaitsev 10:41552d038a69 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
Zaitsev 10:41552d038a69 7 * Software is furnished to do so, subject to the following conditions:
Zaitsev 10:41552d038a69 8 *
Zaitsev 10:41552d038a69 9 * The above copyright notice and this permission notice shall be included in all copies or
Zaitsev 10:41552d038a69 10 * substantial portions of the Software.
Zaitsev 10:41552d038a69 11 *
Zaitsev 10:41552d038a69 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
Zaitsev 10:41552d038a69 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Zaitsev 10:41552d038a69 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
Zaitsev 10:41552d038a69 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Zaitsev 10:41552d038a69 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Zaitsev 10:41552d038a69 17 */
Zaitsev 10:41552d038a69 18
Zaitsev 10:41552d038a69 19 #ifndef MIDIMESSAGE_H
Zaitsev 10:41552d038a69 20 #define MIDIMESSAGE_H
Zaitsev 10:41552d038a69 21
Zaitsev 10:41552d038a69 22 #include "mbed.h"
Zaitsev 10:41552d038a69 23
Zaitsev 10:41552d038a69 24 #define MAX_MIDI_MESSAGE_SIZE 256 // Max message size. SysEx can be up to 65536 but 256 should be fine for most usage
Zaitsev 10:41552d038a69 25
Zaitsev 10:41552d038a69 26 // MIDI Message Format
Zaitsev 10:41552d038a69 27 //
Zaitsev 10:41552d038a69 28 // [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ]
Zaitsev 10:41552d038a69 29 //
Zaitsev 10:41552d038a69 30 // MIDI Data Messages (Channel Specific)
Zaitsev 10:41552d038a69 31 //
Zaitsev 10:41552d038a69 32 // Message msg n m
Zaitsev 10:41552d038a69 33 // ---------------------------------------------
Zaitsev 10:41552d038a69 34 // Note Off 0x8 Key Velocity
Zaitsev 10:41552d038a69 35 // Note On 0x9 Key Velocity
Zaitsev 10:41552d038a69 36 // Polyphonic Aftertouch 0xA Key Pressure
Zaitsev 10:41552d038a69 37 // Control Change 0xB Controller Value
Zaitsev 10:41552d038a69 38 // Program Change 0xC Program -
Zaitsev 10:41552d038a69 39 // Channel Aftertouch 0xD Pressure -
Zaitsev 10:41552d038a69 40 // Pitch Wheel 0xE LSB MSB
Zaitsev 10:41552d038a69 41
Zaitsev 10:41552d038a69 42 #define CABLE_NUM (0<<4)
Zaitsev 10:41552d038a69 43
Zaitsev 10:41552d038a69 44 /** A MIDI message container */
Zaitsev 10:41552d038a69 45 class MIDIMessage {
Zaitsev 10:41552d038a69 46 public:
Zaitsev 10:41552d038a69 47 MIDIMessage() : length(4) {}
Zaitsev 10:41552d038a69 48
Zaitsev 10:41552d038a69 49 MIDIMessage(uint8_t *buf) : length(4) {
Zaitsev 10:41552d038a69 50 for (int i = 0; i < 4; i++)
Zaitsev 10:41552d038a69 51 data[i] = buf[i];
Zaitsev 10:41552d038a69 52 }
Zaitsev 10:41552d038a69 53
Zaitsev 10:41552d038a69 54 // New constructor, buf is a true MIDI message (not USBMidi message) and buf_len true message length.
Zaitsev 10:41552d038a69 55 MIDIMessage(uint8_t *buf, int buf_len) {
Zaitsev 10:41552d038a69 56 length=buf_len+1;
Zaitsev 10:41552d038a69 57 // first byte keeped for retro-compatibility
Zaitsev 10:41552d038a69 58 data[0]=0;
Zaitsev 10:41552d038a69 59
Zaitsev 10:41552d038a69 60 for (int i = 0; i < buf_len; i++)
Zaitsev 10:41552d038a69 61 data[i+1] = buf[i];
Zaitsev 10:41552d038a69 62 }
Zaitsev 10:41552d038a69 63
Zaitsev 10:41552d038a69 64 // create messages
Zaitsev 10:41552d038a69 65
Zaitsev 10:41552d038a69 66 /** Create a NoteOff message
Zaitsev 10:41552d038a69 67 * @param key Key ID
Zaitsev 10:41552d038a69 68 * @param velocity Key velocity (0-127, default = 127)
Zaitsev 10:41552d038a69 69 * @param channel Key channel (0-15, default 0)
Zaitsev 10:41552d038a69 70 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 71 */
Zaitsev 10:41552d038a69 72 static MIDIMessage NoteOff(int key, int velocity = 127, int channel = 0) {
Zaitsev 10:41552d038a69 73 MIDIMessage msg;
Zaitsev 10:41552d038a69 74 msg.data[0] = CABLE_NUM | 0x08;
Zaitsev 10:41552d038a69 75 msg.data[1] = 0x80 | (channel & 0x0F);
Zaitsev 10:41552d038a69 76 msg.data[2] = key & 0x7F;
Zaitsev 10:41552d038a69 77 msg.data[3] = velocity & 0x7F;
Zaitsev 10:41552d038a69 78 return msg;
Zaitsev 10:41552d038a69 79 }
Zaitsev 10:41552d038a69 80
Zaitsev 10:41552d038a69 81 /** Create a NoteOn message
Zaitsev 10:41552d038a69 82 * @param key Key ID
Zaitsev 10:41552d038a69 83 * @param velocity Key velocity (0-127, default = 127)
Zaitsev 10:41552d038a69 84 * @param channel Key channel (0-15, default 0)
Zaitsev 10:41552d038a69 85 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 86 */
Zaitsev 10:41552d038a69 87 static MIDIMessage NoteOn(int key, int velocity = 127, int channel = 0) {
Zaitsev 10:41552d038a69 88 MIDIMessage msg;
Zaitsev 10:41552d038a69 89 msg.data[0] = CABLE_NUM | 0x09;
Zaitsev 10:41552d038a69 90 msg.data[1] = 0x90 | (channel & 0x0F);
Zaitsev 10:41552d038a69 91 msg.data[2] = key & 0x7F;
Zaitsev 10:41552d038a69 92 msg.data[3] = velocity & 0x7F;
Zaitsev 10:41552d038a69 93 return msg;
Zaitsev 10:41552d038a69 94 }
Zaitsev 10:41552d038a69 95
Zaitsev 10:41552d038a69 96 /** Create a PolyPhonic Aftertouch message
Zaitsev 10:41552d038a69 97 * @param key Key ID
Zaitsev 10:41552d038a69 98 * @param pressure Aftertouch pressure (0-127)
Zaitsev 10:41552d038a69 99 * @param channel Key channel (0-15, default 0)
Zaitsev 10:41552d038a69 100 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 101 */
Zaitsev 10:41552d038a69 102 static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) {
Zaitsev 10:41552d038a69 103 MIDIMessage msg;
Zaitsev 10:41552d038a69 104 msg.data[0] = CABLE_NUM | 0x0A;
Zaitsev 10:41552d038a69 105 msg.data[1] = 0xA0 | (channel & 0x0F);
Zaitsev 10:41552d038a69 106 msg.data[2] = key & 0x7F;
Zaitsev 10:41552d038a69 107 msg.data[3] = pressure & 0x7F;
Zaitsev 10:41552d038a69 108 return msg;
Zaitsev 10:41552d038a69 109 }
Zaitsev 10:41552d038a69 110
Zaitsev 10:41552d038a69 111 /** Create a Control Change message
Zaitsev 10:41552d038a69 112 * @param control Controller ID
Zaitsev 10:41552d038a69 113 * @param value Controller value (0-127)
Zaitsev 10:41552d038a69 114 * @param channel Controller channel (0-15, default 0)
Zaitsev 10:41552d038a69 115 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 116 */
Zaitsev 10:41552d038a69 117 static MIDIMessage ControlChange(int control, int value, int channel = 0) {
Zaitsev 10:41552d038a69 118 MIDIMessage msg;
Zaitsev 10:41552d038a69 119 msg.data[0] = CABLE_NUM | 0x0B;
Zaitsev 10:41552d038a69 120 msg.data[1] = 0xB0 | (channel & 0x0F);
Zaitsev 10:41552d038a69 121 msg.data[2] = control & 0x7F;
Zaitsev 10:41552d038a69 122 msg.data[3] = value & 0x7F;
Zaitsev 10:41552d038a69 123 return msg;
Zaitsev 10:41552d038a69 124 }
Zaitsev 10:41552d038a69 125
Zaitsev 10:41552d038a69 126 /** Create a Program Change message
Zaitsev 10:41552d038a69 127 * @param program Program ID
Zaitsev 10:41552d038a69 128 * @param channel Channel (0-15, default 0)
Zaitsev 10:41552d038a69 129 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 130 */
Zaitsev 10:41552d038a69 131 static MIDIMessage ProgramChange(int program, int channel = 0) {
Zaitsev 10:41552d038a69 132 MIDIMessage msg;
Zaitsev 10:41552d038a69 133 msg.data[0] = CABLE_NUM | 0x0C;
Zaitsev 10:41552d038a69 134 msg.data[1] = 0xC0 | (channel & 0x0F);
Zaitsev 10:41552d038a69 135 msg.data[2] = program & 0x7F;
Zaitsev 10:41552d038a69 136 msg.data[3] = 0x00;
Zaitsev 10:41552d038a69 137 return msg;
Zaitsev 10:41552d038a69 138 }
Zaitsev 10:41552d038a69 139
Zaitsev 10:41552d038a69 140 /** Create a Channel Aftertouch message
Zaitsev 10:41552d038a69 141 * @param pressure Pressure
Zaitsev 10:41552d038a69 142 * @param channel Key channel (0-15, default 0)
Zaitsev 10:41552d038a69 143 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 144 */
Zaitsev 10:41552d038a69 145 static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) {
Zaitsev 10:41552d038a69 146 MIDIMessage msg;
Zaitsev 10:41552d038a69 147 msg.data[0] = CABLE_NUM | 0x0D;
Zaitsev 10:41552d038a69 148 msg.data[1] = 0xD0 | (channel & 0x0F);
Zaitsev 10:41552d038a69 149 msg.data[2] = pressure & 0x7F;
Zaitsev 10:41552d038a69 150 msg.data[3] = 0x00;
Zaitsev 10:41552d038a69 151 return msg;
Zaitsev 10:41552d038a69 152 }
Zaitsev 10:41552d038a69 153
Zaitsev 10:41552d038a69 154 /** Create a Pitch Wheel message
Zaitsev 10:41552d038a69 155 * @param pitch Pitch (-8192 - 8191, default = 0)
Zaitsev 10:41552d038a69 156 * @param channel Channel (0-15, default 0)
Zaitsev 10:41552d038a69 157 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 158 */
Zaitsev 10:41552d038a69 159 static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) {
Zaitsev 10:41552d038a69 160 MIDIMessage msg;
Zaitsev 10:41552d038a69 161 int p = pitch + 8192; // 0 - 16383, 8192 is center
Zaitsev 10:41552d038a69 162 msg.data[0] = CABLE_NUM | 0x0E;
Zaitsev 10:41552d038a69 163 msg.data[1] = 0xE0 | (channel & 0x0F);
Zaitsev 10:41552d038a69 164 msg.data[2] = p & 0x7F;
Zaitsev 10:41552d038a69 165 msg.data[3] = (p >> 7) & 0x7F;
Zaitsev 10:41552d038a69 166 return msg;
Zaitsev 10:41552d038a69 167 }
Zaitsev 10:41552d038a69 168
Zaitsev 10:41552d038a69 169 /** Create an All Notes Off message
Zaitsev 10:41552d038a69 170 * @param channel Channel (0-15, default 0)
Zaitsev 10:41552d038a69 171 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 172 */
Zaitsev 10:41552d038a69 173 static MIDIMessage AllNotesOff(int channel = 0) {
Zaitsev 10:41552d038a69 174 return ControlChange(123, 0, channel);
Zaitsev 10:41552d038a69 175 }
Zaitsev 10:41552d038a69 176
Zaitsev 10:41552d038a69 177 /** Create a SysEx message
Zaitsev 10:41552d038a69 178 * @param data SysEx data (including 0xF0 .. 0xF7)
Zaitsev 10:41552d038a69 179 * @param len SysEx data length
Zaitsev 10:41552d038a69 180 * @returns A MIDIMessage
Zaitsev 10:41552d038a69 181 */
Zaitsev 10:41552d038a69 182 static MIDIMessage SysEx(uint8_t *data, int len) {
Zaitsev 10:41552d038a69 183 MIDIMessage msg=MIDIMessage(data,len);
Zaitsev 10:41552d038a69 184 return msg;
Zaitsev 10:41552d038a69 185 }
Zaitsev 10:41552d038a69 186
Zaitsev 10:41552d038a69 187 // decode messages
Zaitsev 10:41552d038a69 188
Zaitsev 10:41552d038a69 189 /** MIDI Message Types */
Zaitsev 10:41552d038a69 190 enum MIDIMessageType {
Zaitsev 10:41552d038a69 191 ErrorType,
Zaitsev 10:41552d038a69 192 NoteOffType,
Zaitsev 10:41552d038a69 193 NoteOnType,
Zaitsev 10:41552d038a69 194 PolyphonicAftertouchType,
Zaitsev 10:41552d038a69 195 ControlChangeType,
Zaitsev 10:41552d038a69 196 ProgramChangeType,
Zaitsev 10:41552d038a69 197 ChannelAftertouchType,
Zaitsev 10:41552d038a69 198 PitchWheelType,
Zaitsev 10:41552d038a69 199 AllNotesOffType,
Zaitsev 10:41552d038a69 200 SysExType
Zaitsev 10:41552d038a69 201 };
Zaitsev 10:41552d038a69 202
Zaitsev 10:41552d038a69 203 /** Read the message type
Zaitsev 10:41552d038a69 204 * @returns MIDIMessageType
Zaitsev 10:41552d038a69 205 */
Zaitsev 10:41552d038a69 206 MIDIMessageType type() {
Zaitsev 10:41552d038a69 207 switch((data[1] >> 4) & 0xF) {
Zaitsev 10:41552d038a69 208 case 0x8: return NoteOffType;
Zaitsev 10:41552d038a69 209 case 0x9: return NoteOnType;
Zaitsev 10:41552d038a69 210 case 0xA: return PolyphonicAftertouchType;
Zaitsev 10:41552d038a69 211 case 0xB:
Zaitsev 10:41552d038a69 212 if(controller() < 120) { // standard controllers
Zaitsev 10:41552d038a69 213 return ControlChangeType;
Zaitsev 10:41552d038a69 214 } else if(controller() == 123) {
Zaitsev 10:41552d038a69 215 return AllNotesOffType;
Zaitsev 10:41552d038a69 216 } else {
Zaitsev 10:41552d038a69 217 return ErrorType; // unsupported atm
Zaitsev 10:41552d038a69 218 }
Zaitsev 10:41552d038a69 219 case 0xC: return ProgramChangeType;
Zaitsev 10:41552d038a69 220 case 0xD: return ChannelAftertouchType;
Zaitsev 10:41552d038a69 221 case 0xE: return PitchWheelType;
Zaitsev 10:41552d038a69 222 case 0xF: return SysExType;
Zaitsev 10:41552d038a69 223 default: return ErrorType;
Zaitsev 10:41552d038a69 224 }
Zaitsev 10:41552d038a69 225 }
Zaitsev 10:41552d038a69 226
Zaitsev 10:41552d038a69 227 /** Read the channel number */
Zaitsev 10:41552d038a69 228 int channel() {
Zaitsev 10:41552d038a69 229 return (data[1] & 0x0F);
Zaitsev 10:41552d038a69 230 }
Zaitsev 10:41552d038a69 231
Zaitsev 10:41552d038a69 232 /** Read the key ID */
Zaitsev 10:41552d038a69 233 int key() {
Zaitsev 10:41552d038a69 234 return (data[2] & 0x7F);
Zaitsev 10:41552d038a69 235 }
Zaitsev 10:41552d038a69 236
Zaitsev 10:41552d038a69 237 /** Read the velocity */
Zaitsev 10:41552d038a69 238 int velocity() {
Zaitsev 10:41552d038a69 239 return (data[3] & 0x7F);
Zaitsev 10:41552d038a69 240 }
Zaitsev 10:41552d038a69 241
Zaitsev 10:41552d038a69 242 /** Read the controller value */
Zaitsev 10:41552d038a69 243 int value() {
Zaitsev 10:41552d038a69 244 return (data[3] & 0x7F);
Zaitsev 10:41552d038a69 245 }
Zaitsev 10:41552d038a69 246
Zaitsev 10:41552d038a69 247 /** Read the aftertouch pressure */
Zaitsev 10:41552d038a69 248 int pressure() {
Zaitsev 10:41552d038a69 249 if(type() == PolyphonicAftertouchType) {
Zaitsev 10:41552d038a69 250 return (data[3] & 0x7F);
Zaitsev 10:41552d038a69 251 } else {
Zaitsev 10:41552d038a69 252 return (data[2] & 0x7F);
Zaitsev 10:41552d038a69 253 }
Zaitsev 10:41552d038a69 254 }
Zaitsev 10:41552d038a69 255
Zaitsev 10:41552d038a69 256 /** Read the controller number */
Zaitsev 10:41552d038a69 257 int controller() {
Zaitsev 10:41552d038a69 258 return (data[2] & 0x7F);
Zaitsev 10:41552d038a69 259 }
Zaitsev 10:41552d038a69 260
Zaitsev 10:41552d038a69 261 /** Read the program number */
Zaitsev 10:41552d038a69 262 int program() {
Zaitsev 10:41552d038a69 263 return (data[2] & 0x7F);
Zaitsev 10:41552d038a69 264 }
Zaitsev 10:41552d038a69 265
Zaitsev 10:41552d038a69 266 /** Read the pitch value */
Zaitsev 10:41552d038a69 267 int pitch() {
Zaitsev 10:41552d038a69 268 int p = ((data[3] & 0x7F) << 7) | (data[2] & 0x7F);
Zaitsev 10:41552d038a69 269 return p - 8192; // 0 - 16383, 8192 is center
Zaitsev 10:41552d038a69 270 }
Zaitsev 10:41552d038a69 271
Zaitsev 10:41552d038a69 272 uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
Zaitsev 10:41552d038a69 273 uint8_t length;
Zaitsev 10:41552d038a69 274 };
Zaitsev 10:41552d038a69 275
Zaitsev 10:41552d038a69 276 #endif