Line data Source code
1 : #include "USBMIDI_Parser.hpp" 2 : #include <Settings/SettingsWrapper.hpp> 3 : 4 : BEGIN_CS_NAMESPACE 5 : 6 : // https://usb.org/sites/default/files/midi10.pdf 7 40 : MIDIReadEvent USBMIDI_Parser::parse(uint8_t *packet) { 8 40 : DEBUG("MIDIUSB packet:\t" << hex << packet[0] << ' ' << packet[1] << ' ' 9 : << packet[2] << ' ' << packet[3] << dec); 10 : // MIDI USB cable number 11 40 : uint8_t CN = packet[0] >> 4; 12 : // MIDI USB code index number 13 40 : MIDICodeIndexNumber CIN = static_cast<MIDICodeIndexNumber>(packet[0] & 0xF); 14 : 15 : // SysEx constants 16 40 : constexpr uint8_t SysExEnd = 17 : static_cast<uint8_t>(MIDIMessageType::SYSEX_END); 18 40 : constexpr uint8_t SysExStart = 19 : static_cast<uint8_t>(MIDIMessageType::SYSEX_START); 20 : 21 : // Main parser logic 22 : // ========================================================================= 23 : 24 : // ------------------- Channel message (2 or 3 bytes) ------------------- // 25 : 26 40 : if (CIN >= MIDICodeIndexNumber::NOTE_OFF && 27 9 : CIN <= MIDICodeIndexNumber::PITCH_BEND) { 28 : // 2- or 3-byte MIDI channel message 29 : 30 : // uint8_t type = packet[1] & 0xF0; 31 : // if (CIN != type) // invalid MIDI USB packet 32 : // return NO_MESSAGE; 33 6 : midimsg.header = packet[1]; 34 6 : midimsg.data1 = packet[2]; 35 6 : midimsg.data2 = packet[3]; 36 6 : midimsg.CN = CN; 37 6 : return MIDIReadEvent::CHANNEL_MESSAGE; 38 : } 39 : 40 : // ---------------- SysEx starts or continues (3 bytes) ----------------- // 41 : 42 : #if !IGNORE_SYSEX 43 34 : else if (CIN == MIDICodeIndexNumber::SYSEX_START_CONT) { 44 : // SysEx starts or continues (3 bytes) 45 16 : if (packet[1] == SysExStart) 46 9 : startSysEx(CN); // start a new message 47 : // (overwrite previous unfinished message) 48 7 : else if (!receivingSysEx(CN)) { // If we haven't received a SysExStart 49 0 : DEBUGREF(F("Error: No SysExStart received")); 50 0 : return MIDIReadEvent::NO_MESSAGE; // ignore the data 51 : } 52 16 : addSysExByte(CN, packet[1]) && // add three data bytes to buffer 53 16 : addSysExByte(CN, packet[2]) && // 54 16 : addSysExByte(CN, packet[3]); 55 16 : return MIDIReadEvent::NO_MESSAGE; // SysEx is not finished yet 56 : } 57 : 58 : // --------------- SysEx ends with following single byte ---------------- // 59 : 60 18 : else if (CIN == MIDICodeIndexNumber::SYSEX_END_1B) { 61 : // SysEx ends with following single byte 62 : // (or Single-byte System Common Message, not implemented) 63 5 : if (packet[1] != SysExEnd) { 64 : // System Common (not implemented) 65 0 : return MIDIReadEvent::NO_MESSAGE; 66 5 : } else if (!receivingSysEx(CN)) { // If we haven't received a SysExStart 67 1 : DEBUGFN(F("Error: No SysExStart received")); 68 1 : return MIDIReadEvent::NO_MESSAGE; // ignore the data 69 : } 70 4 : if (addSysExByte(CN, packet[1])) { 71 4 : endSysEx(CN); 72 4 : return MIDIReadEvent::SYSEX_MESSAGE; 73 : } else { 74 0 : return MIDIReadEvent::NO_MESSAGE; // Buffer full, ignore message 75 : } 76 : } 77 : 78 : // ---------------- SysEx ends with following two bytes ----------------- // 79 : 80 13 : else if (CIN == MIDICodeIndexNumber::SYSEX_END_2B) { 81 : // SysEx ends with following two bytes 82 5 : if (packet[1] == SysExStart) 83 1 : startSysEx(CN); // start a new message 84 : // (overwrite previous unfinished message) 85 4 : else if (!receivingSysEx(CN)) { // If we haven't received a SysExStart 86 1 : DEBUGFN(F("Error: No SysExStart received")); 87 1 : return MIDIReadEvent::NO_MESSAGE; // ignore the data 88 : } 89 : if ( // add two data bytes to buffer 90 4 : addSysExByte(CN, packet[1]) && addSysExByte(CN, SysExEnd)) { 91 4 : endSysEx(CN); 92 4 : return MIDIReadEvent::SYSEX_MESSAGE; 93 : } else 94 0 : return MIDIReadEvent::NO_MESSAGE; // Buffer full, ignore message 95 : } 96 : 97 : // --------------- SysEx ends with following three bytes ---------------- // 98 : 99 8 : else if (CIN == MIDICodeIndexNumber::SYSEX_END_3B) { 100 : // SysEx ends with following three bytes 101 5 : if (packet[1] == SysExStart) 102 1 : startSysEx(CN); // start a new message 103 : // (overwrite previous unfinished message) 104 4 : else if (!receivingSysEx(CN)) { // If we haven't received a SysExStart 105 2 : DEBUGFN(F("Error: No SysExStart received")); 106 2 : return MIDIReadEvent::NO_MESSAGE; // ignore the data 107 : } 108 : if ( // add three data bytes to buffer 109 6 : addSysExByte(CN, packet[1]) && // 110 3 : addSysExByte(CN, packet[2]) && // 111 3 : addSysExByte(CN, SysExEnd)) { 112 3 : endSysEx(CN); 113 3 : return MIDIReadEvent::SYSEX_MESSAGE; 114 : } else { 115 0 : return MIDIReadEvent::NO_MESSAGE; // Buffer full, ignore message 116 : } 117 : } 118 : #endif // IGNORE_SYSEX 119 : 120 3 : else if (CIN == MIDICodeIndexNumber::MISC_FUNCTION_CODES) { 121 : // Miscellaneous function codes. Reserved for future extensions. 122 : // (not implemented) 123 3 : } else if (CIN == MIDICodeIndexNumber::CABLE_EVENTS) { 124 : // Cable events. Reserved for future expansion. 125 : // (not implemented) 126 3 : } else if (CIN == MIDICodeIndexNumber::SYSTEM_COMMON_2B) { 127 : // Two-byte System Common message 128 : // (not implemented) 129 3 : } else if (CIN == MIDICodeIndexNumber::SYSTEM_COMMON_3B) { 130 : // Three-byte System Common message 131 : // (not implemented) 132 0 : } 133 : 134 : // ---------------------- Single byte (real-time) ----------------------- // 135 : 136 3 : else if (CIN == MIDICodeIndexNumber::SINGLE_BYTE) { 137 : // Single Byte 138 3 : rtmsg.message = packet[1]; 139 3 : rtmsg.CN = CN; 140 3 : return MIDIReadEvent::REALTIME_MESSAGE; 141 : } 142 : 143 0 : return MIDIReadEvent::NO_MESSAGE; 144 40 : } 145 : 146 : END_CS_NAMESPACE