#include "USBMIDI_Parser.hpp" #include BEGIN_CS_NAMESPACE MIDIReadEvent USBMIDI_Parser::handleChannelMessage(MIDIUSBPacket_t packet, Cable cable) { midimsg.header = packet[1]; midimsg.data1 = packet[2]; midimsg.data2 = packet[3]; midimsg.cable = cable; return MIDIReadEvent::CHANNEL_MESSAGE; } MIDIReadEvent USBMIDI_Parser::handleSysExStartCont(MIDIUSBPacket_t packet, Cable cable) { #if !IGNORE_SYSEX if (packet[1] == uint8_t(MIDIMessageType::SysExStart)) { startSysEx(cable); } else if (!receivingSysEx(cable)) { DEBUGREF(F("No SysExStart received")); return MIDIReadEvent::NO_MESSAGE; } if (!hasSysExSpace(cable, 3)) { storePacket(packet); endSysExChunk(cable); return MIDIReadEvent::SYSEX_CHUNK; } addSysExBytes(cable, &packet[1], 3); #else (void)packet; (void)cable; #endif return MIDIReadEvent::NO_MESSAGE; } template MIDIReadEvent USBMIDI_Parser::handleSysExEnd(MIDIUSBPacket_t packet, Cable cable) { static_assert(NumBytes == 2 || NumBytes == 3, "Only 2- or 3-byte SysEx packets are supported"); #if !IGNORE_SYSEX if (packet[1] == uint8_t(MIDIMessageType::SysExStart)) { startSysEx(cable); } else if (!receivingSysEx(cable)) { DEBUGFN(F("No SysExStart received")); return MIDIReadEvent::NO_MESSAGE; } if (!hasSysExSpace(cable, NumBytes)) { storePacket(packet); endSysExChunk(cable); return MIDIReadEvent::SYSEX_CHUNK; } addSysExBytes(cable, &packet[1], NumBytes); endSysEx(cable); return MIDIReadEvent::SYSEX_MESSAGE; #else (void)packet; (void)cable; return MIDIReadEvent::NO_MESSAGE; #endif } template <> MIDIReadEvent USBMIDI_Parser::handleSysExEnd<1>(MIDIUSBPacket_t packet, Cable cable) { if (packet[1] != uint8_t(MIDIMessageType::SysExEnd)) { midimsg.header = packet[1]; midimsg.cable = cable; return MIDIReadEvent::SYSCOMMON_MESSAGE; } #if !IGNORE_SYSEX else { if (!receivingSysEx(cable)) { DEBUGREF(F("No SysExStart received")); return MIDIReadEvent::NO_MESSAGE; } if (!hasSysExSpace(cable, 1)) { storePacket(packet); endSysExChunk(cable); return MIDIReadEvent::SYSEX_CHUNK; } addSysExByte(cable, packet[1]); endSysEx(cable); return MIDIReadEvent::SYSEX_MESSAGE; } #else (void)packet; (void)cable; return MIDIReadEvent::NO_MESSAGE; #endif } MIDIReadEvent USBMIDI_Parser::handleSysCommon(MIDIUSBPacket_t packet, Cable cable) { midimsg.header = packet[1]; midimsg.data1 = packet[2]; midimsg.data2 = packet[3]; midimsg.cable = cable; return MIDIReadEvent::SYSCOMMON_MESSAGE; } MIDIReadEvent USBMIDI_Parser::handleSingleByte(MIDIUSBPacket_t packet, Cable cable) { rtmsg.message = packet[1]; rtmsg.cable = cable; return MIDIReadEvent::REALTIME_MESSAGE; } MIDIReadEvent USBMIDI_Parser::feed(MIDIUSBPacket_t packet) { Cable cable = Cable(packet[0] >> 4); MIDICodeIndexNumber CIN = MIDICodeIndexNumber(packet[0] & 0xF); if (cable.getRaw() >= USB_MIDI_NUMBER_OF_CABLES) return MIDIReadEvent::NO_MESSAGE; using M = MIDICodeIndexNumber; switch (CIN) { case M::MiscFunctionCodes: break; case M::CableEvents: break; case M::SystemCommon2B: case M::SystemCommon3B: return handleSysCommon(packet, cable); case M::SysExStartCont: return handleSysExStartCont(packet, cable); case M::SysExEnd1B: return handleSysExEnd<1>(packet, cable); case M::SysExEnd2B: return handleSysExEnd<2>(packet, cable); case M::SysExEnd3B: return handleSysExEnd<3>(packet, cable); case M::NoteOff: case M::NoteOn: case M::KeyPressure: case M::ControlChange: case M::ProgramChange: case M::ChannelPressure: case M::PitchBend: return handleChannelMessage(packet, cable); case M::SingleByte: return handleSingleByte(packet, cable); default: break; } return MIDIReadEvent::NO_MESSAGE; } MIDIReadEvent USBMIDI_Parser::resume() { #if !IGNORE_SYSEX if (!hasStoredPacket()) return MIDIReadEvent::NO_MESSAGE; MIDIUSBPacket_t packet = popStoredPacket(); if (receivingSysEx(activeCable)) { startSysEx(activeCable); } return feed(packet); #else return MIDIReadEvent::NO_MESSAGE; #endif } END_CS_NAMESPACE