FastLED 3.9.15
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages

◆ parse()

template<class Transport, class Settings, class Platform>
bool MidiInterface< Transport, Settings, Platform >::parse ( )
private

Definition at line 783 of file MIDI.hpp.

784{
785 if (mTransport.available() == 0)
786 return false; // No data available.
787
788 // clear the ErrorParse bit
789 mLastError &= ~(1UL << ErrorParse);
790
791 // Parsing algorithm:
792 // Get a byte from the serial buffer.
793 // If there is no pending message to be recomposed, start a new one.
794 // - Find type and channel (if pertinent)
795 // - Look for other bytes in buffer, call parser recursively,
796 // until the message is assembled or the buffer is empty.
797 // Else, add the extracted byte to the pending message, and check validity.
798 // When the message is done, store it.
799
800 const byte extracted = mTransport.read();
801
802 // Ignore Undefined
803 if (extracted == Undefined_FD)
805
806 if (mPendingMessageIndex == 0)
807 {
808 // Start a new pending message
810
811 // Check for running status first
813 {
814 // Only these types allow Running Status
815
816 // If the status byte is not received, prepend it
817 // to the pending message
818 if (extracted < 0x80)
819 {
823 }
824 // Else: well, we received another status byte,
825 // so the running status does not apply here.
826 // It will be updated upon completion of this message.
827 }
828
830
831 switch (pendingType)
832 {
833 // 1 byte messages
834 case Start:
835 case Continue:
836 case Stop:
837 case Clock:
838 case Tick:
839 case ActiveSensing:
840 case SystemReset:
841 case TuneRequest:
842 // Handle the message type directly here.
843 mMessage.type = pendingType;
844 mMessage.channel = 0;
845 mMessage.data1 = 0;
846 mMessage.data2 = 0;
847 mMessage.valid = true;
848
849 // Do not reset all input attributes, Running Status must remain unchanged.
850 // We still need to reset these
853
854 return true;
855 break;
856
857 // 2 bytes messages
858 case ProgramChange:
861 case SongSelect:
863 break;
864
865 // 3 bytes messages
866 case NoteOn:
867 case NoteOff:
868 case ControlChange:
869 case PitchBend:
870 case AfterTouchPoly:
871 case SongPosition:
873 break;
874
877 // The message can be any length
878 // between 3 and MidiMessage::sSysExMaxSize bytes
881 mMessage.sysexArray[0] = pendingType;
882 break;
883
884 case InvalidType:
885 default:
886 // This is obviously wrong. Let's get the hell out'a here.
887 mLastError |= 1UL << ErrorParse; // set the ErrorParse bit
888 if (mErrorCallback)
889 mErrorCallback(mLastError); // LCOV_EXCL_LINE
890
891 resetInput();
892 return false;
893 break;
894 }
895
897 {
898 // Reception complete
899 mMessage.type = pendingType;
901 mMessage.data1 = mPendingMessage[1];
902 mMessage.data2 = 0; // Completed new message has 1 data byte
903 mMessage.length = 1;
904
907 mMessage.valid = true;
908
909 return true;
910 }
911 else
912 {
913 // Waiting for more data
915 }
916
918 }
919 else
920 {
921 // First, test if this is a status byte
922 if (extracted >= 0x80)
923 {
924 // Reception of status bytes in the middle of an uncompleted message
925 // are allowed only for interleaved Real Time message or EOX
926 switch (extracted)
927 {
928 case Clock:
929 case Start:
930 case Tick:
931 case Continue:
932 case Stop:
933 case ActiveSensing:
934 case SystemReset:
935
936 // Here we will have to extract the one-byte message,
937 // pass it to the structure for being read outside
938 // the MIDI class, and recompose the message it was
939 // interleaved into. Oh, and without killing the running status..
940 // This is done by leaving the pending message as is,
941 // it will be completed on next calls.
942
944 mMessage.data1 = 0;
945 mMessage.data2 = 0;
946 mMessage.channel = 0;
947 mMessage.length = 1;
948 mMessage.valid = true;
949
950 return true;
951
952 // Exclusive
955 if ((mMessage.sysexArray[0] == SystemExclusiveStart)
956 || (mMessage.sysexArray[0] == SystemExclusiveEnd))
957 {
958 // Store the last byte (EOX)
961
962 // Get length
963 mMessage.data1 = mPendingMessageIndex & 0xff; // LSB
964 mMessage.data2 = byte(mPendingMessageIndex >> 8); // MSB
965 mMessage.channel = 0;
967 mMessage.valid = true;
968
969 resetInput();
970
971 return true;
972 }
973 else
974 {
975 // Well well well.. error.
976 mLastError |= 1UL << ErrorParse; // set the error bits
977 if (mErrorCallback)
978 mErrorCallback(mLastError); // LCOV_EXCL_LINE
979
980 resetInput();
981 return false;
982 }
983
984 default:
985 break; // LCOV_EXCL_LINE - Coverage blind spot
986 }
987 }
988
989 // Add extracted data byte to pending message
993 else
995
996 // Now we are going to check if we have reached the end of the message
998 {
999 // SysEx larger than the allocated buffer size,
1000 // Split SysEx like so:
1001 // first: 0xF0 .... 0xF0
1002 // midlle: 0xF7 .... 0xF0
1003 // last: 0xF7 .... 0xF7
1006 {
1007 auto lastByte = mMessage.sysexArray[Settings::SysExMaxSize - 1];
1010
1011 // Get length
1012 mMessage.data1 = Settings::SysExMaxSize & 0xff; // LSB
1013 mMessage.data2 = byte(Settings::SysExMaxSize >> 8); // MSB
1014 mMessage.channel = 0;
1016 mMessage.valid = true;
1017
1018 // No need to check against the inputChannel,
1019 // SysEx ignores input channel
1021
1022 mMessage.sysexArray[0] = SystemExclusiveEnd;
1023 mMessage.sysexArray[1] = lastByte;
1024
1026
1027 return false;
1028 }
1029
1031
1032 if (isChannelMessage(mMessage.type))
1034 else
1035 mMessage.channel = 0;
1036
1037 mMessage.data1 = mPendingMessage[1];
1038 // Save data2 only if applicable
1040
1041 // Reset local variables
1044
1045 mMessage.valid = true;
1046
1047 // Activate running status (if enabled for the received type)
1048 switch (mMessage.type)
1049 {
1050 case NoteOff:
1051 case NoteOn:
1052 case AfterTouchPoly:
1053 case ControlChange:
1054 case ProgramChange:
1055 case AfterTouchChannel:
1056 case PitchBend:
1057 // Running status enabled: store it from received message
1059 break;
1060
1061 default:
1062 // No running status
1064 break;
1065 }
1066 return true;
1067 }
1068 else
1069 {
1070 // Then update the index of the pending message.
1072
1073 return (Settings::Use1ByteParsing) ? false : parse();
1074 }
1075 }
1076}
StatusByte mRunningStatus_RX
Definition MIDI.h:274
void launchCallback()
Definition MIDI.hpp:1294
ErrorCallback mErrorCallback
Definition MIDI.h:215
unsigned mPendingMessageExpectedLength
Definition MIDI.h:277
int8_t mLastError
Definition MIDI.h:288
byte mPendingMessage[3]
Definition MIDI.h:276
Transport & mTransport
Definition MIDI.h:267
unsigned mPendingMessageIndex
Definition MIDI.h:278
MidiMessage mMessage
Definition MIDI.h:283
The main class for MIDI handling. It is templated over the type of serial port to provide abstraction...
Definition MIDI.h:55
static Channel getChannelFromStatusByte(byte inStatus)
Returns channel in the range 1-16.
Definition MIDI.hpp:1236
static MidiType getTypeFromStatusByte(byte inStatus)
Extract an enumerated MIDI type from a status byte.
Definition MIDI.hpp:1218
static bool isChannelMessage(MidiType inType)
Definition MIDI.hpp:1242
void resetInput()
Definition MIDI.hpp:1120
bool parse()
Definition MIDI.hpp:783
uint8_t byte
Definition midi_Defs.h:36
static const unsigned sSysExMaxSize

References ActiveSensing, AfterTouchChannel, AfterTouchPoly, Clock, Continue, ControlChange, ErrorParse, getChannelFromStatusByte(), getTypeFromStatusByte(), InvalidType, isChannelMessage(), launchCallback(), mErrorCallback, mLastError, mMessage, mPendingMessage, mPendingMessageExpectedLength, mPendingMessageIndex, mRunningStatus_RX, mTransport, NoteOff, NoteOn, parse(), PitchBend, ProgramChange, resetInput(), SongPosition, SongSelect, Message< Settings::SysExMaxSize >::sSysExMaxSize, Start, Stop, SystemExclusive, SystemExclusiveEnd, SystemExclusiveStart, SystemReset, Tick, TimeCodeQuarterFrame, TuneRequest, and Undefined_FD.

Referenced by parse(), and read().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: