@@ -828,198 +828,199 @@ inline bool MidiInterface<Transport, Settings, Platform>::read(Channel inChannel
828
828
829
829
// Private method: MIDI parser
830
830
template <class Transport , class Settings , class Platform >
831
- bool MidiInterface<Transport, Settings, Platform>::parse() {
832
-
833
- if (mTransport .available () == 0 )
834
- return false ;
835
-
836
- mLastError &= ~(1UL << ErrorParse); // Clear ErrorParse bit
837
- /* Possible Errors:
838
- > SysEx Stop byte received with no pending SysEx Start.
839
- > Unsupported Status byte.
840
- > Data received without a valid Status byte or Running Status.
841
- > Warning SysEx split warning.
842
- .... could potentially add an error for when SysEx is aborted due to receiving a new non-realtime status byte.
843
- */
844
-
845
- const byte extracted = mTransport .read ();
846
-
847
- if (extracted >= 0x80 ) {
848
- // Lets try get a valid Status byte. Non-realtime status overides any current Status
849
- const MidiType pendingType = getTypeFromStatusByte (extracted);
850
- switch (pendingType) {
851
- // Realtime
852
- case Start:
853
- case Continue:
854
- case Stop:
855
- case Clock:
856
- case Tick:
857
- case ActiveSensing:
858
- case SystemReset:
859
- case TuneRequest:
860
- // Handle message now
861
- mMessage .type = pendingType;
862
- mMessage .channel = 0 ;
863
- mMessage .data1 = 0 ;
864
- mMessage .data2 = 0 ;
865
- mMessage .length = 1 ;
866
- mMessage .valid = true ;
867
- return true ;
868
- break ;
869
- // 2 byte messages
870
- case ProgramChange:
871
- case AfterTouchChannel:
872
- case TimeCodeQuarterFrame:
873
- case SongSelect:
874
- mPendingMessage [0 ] = extracted;
875
- mPendingMessageExpectedLength = 2 ;
876
- break ;
877
- // 3 byte messages
878
- case NoteOn:
879
- case NoteOff:
880
- case ControlChange:
881
- case PitchBend:
882
- case AfterTouchPoly:
883
- case SongPosition:
884
- mPendingMessage [0 ] = extracted;
885
- mPendingMessageExpectedLength = 3 ;
886
- break ;
887
- // SysEx
888
- case SystemExclusiveStart:
889
- mPendingMessage [0 ] = SystemExclusive;
890
- mPendingMessageExpectedLength = MidiMessage::sSysExMaxSize ;
891
- mMessage .sysexArray [0 ] = SystemExclusiveStart;
892
- mLastError &= ~(1UL << WarningSplitSysEx); // Reset Warning Split SysEx bit
893
- break ;
894
- case SystemExclusiveEnd:
895
- if (mPendingMessage [0 ] == SystemExclusive) {
896
- mMessage .sysexArray [mPendingMessageIndex ++] = SystemExclusiveEnd; // Post Inc pending index here for correct lenght data
897
- mMessage .type = SystemExclusive;
898
- mMessage .data1 = mPendingMessageIndex & 0xff ; // LSB
899
- mMessage .data2 = byte (mPendingMessageIndex >> 8 ); // MSB
900
- mMessage .channel = 0 ;
901
- mMessage .length = mPendingMessageIndex ;
902
- if (mMessage .sysexArray [0 ] == SystemExclusiveEnd) {
903
- // This is the last chunk of a split SysEx message, and is NOT a valid SysEx message (it starts with 0xF7)
904
- mMessage .valid = false ; // SysEx message is split so this not technically valid
905
- launchCallback (); // Lets notify callback to deal with this
906
- resetInput (); // Restart message
907
- return false ;
908
- } else {
909
- // We are in a valid SysEx message that hasn't overrun (starts with 0xF0) so lets complete it
910
- mMessage .valid = true ;
911
- resetInput (); // Restart message
912
- return true ;
913
- }
914
- } else { // Looks like a SysEx End without a Sysex Start
915
- mLastError |= 1UL << ErrorParse; // Error: SysEx Stop byte received with no pending SysEx Start.
916
- if (mErrorCallback )
917
- mErrorCallback (mLastError );
918
- resetInput (); // Restart message
919
- return false ;
920
- }
921
- break ;
922
- // Unsupported
923
- default :
924
- mPendingMessage [0 ] = InvalidType;
925
- mLastError |= 1UL << ErrorParse; // Error: Unsupported Status byte.
926
- if (mErrorCallback )
927
- mErrorCallback (mLastError );
928
- resetInput (); // Restart message
929
- return false ;
930
- break ;
931
- }
932
- mPendingMessageIndex = 1 ; // If we are here, we have a valid Status! Lets try get some Data for it....
933
- mRunningStatus_RX = InvalidType; // Lets also reset Running Status until we have a complete message
934
- return (Settings::Use1ByteParsing) ? false : parse ();
935
-
936
- } else {
937
- // Lets get some data... First off.. check for Status Byte, or use Running Status
938
- if (mPendingMessageIndex == 0 ) {
939
- if (mRunningStatus_RX ) {
940
- // Yay! We have Running Status
941
- mPendingMessage [0 ] = mRunningStatus_RX ;
942
- mPendingMessageIndex = 1 ;
943
- } else {
944
- // ooops.... No Status Byte... No Running Status... lets ignore this data
945
- mLastError |= 1UL << ErrorParse; // Error: Data received without a valid Status byte or Running Status.
946
- if (mErrorCallback )
947
- mErrorCallback (mLastError );
831
+ bool MidiInterface<Transport, Settings, Platform>::parse()
832
+ {
833
+
834
+ if (mTransport .available () == 0 )
948
835
return false ;
949
- }
950
- }
951
836
952
- // Status or Running Status is good so add extracted data byte to pending message
953
- if (mPendingMessage [0 ] == SystemExclusive)
954
- mMessage .sysexArray [mPendingMessageIndex ] = extracted;
955
- else
956
- mPendingMessage [mPendingMessageIndex ] = extracted;
957
-
958
- // Now we are going to check if we have reached the end of the message
959
- if (mPendingMessageIndex >= (mPendingMessageExpectedLength - 1 )) {
960
- // SysEx larger than the allocated buffer size,
961
- // Split SysEx like so:
962
- // first: 0xF0 .... 0xF0
963
- // middle: 0xF7 .... 0xF0
964
- // last: 0xF7 .... 0xF7
965
- // ***** If the buffer has overrun, this SysEx message can now no longer be considered a valid Midi message and must be dealt with via callbacks only! ****
966
- if (mPendingMessage [0 ] == SystemExclusive) {
967
- // Warn at start of SysEx split
968
- if (mMessage .sysexArray [0 ] == SystemExclusiveStart) {
969
- mLastError |= 1UL << WarningSplitSysEx; // We have this error already defined so may as well use it
970
- if (mErrorCallback )
971
- mErrorCallback (mLastError );
837
+ mLastError &= ~(1UL << ErrorParse); // Clear ErrorParse bit
838
+ /* Possible Errors:
839
+ > SysEx Stop byte received with no pending SysEx Start.
840
+ > Unsupported Status byte.
841
+ > Data received without a valid Status byte or Running Status.
842
+ > Warning SysEx split warning.
843
+ .... could potentially add an error for when SysEx is aborted due to receiving a new non-realtime status byte.
844
+ */
845
+
846
+ const byte extracted = mTransport .read ();
847
+
848
+ if (extracted >= 0x80 ) {
849
+ // Lets try get a valid Status byte. Non-realtime status overrides any current Status
850
+ const MidiType pendingType = getTypeFromStatusByte (extracted);
851
+ switch (pendingType) {
852
+ // Realtime
853
+ case Start:
854
+ case Continue:
855
+ case Stop:
856
+ case Clock:
857
+ case Tick:
858
+ case ActiveSensing:
859
+ case SystemReset:
860
+ case TuneRequest:
861
+ // Handle message now
862
+ mMessage .type = pendingType;
863
+ mMessage .channel = 0 ;
864
+ mMessage .data1 = 0 ;
865
+ mMessage .data2 = 0 ;
866
+ mMessage .length = 1 ;
867
+ mMessage .valid = true ;
868
+ return true ;
869
+ break ;
870
+ // 2 byte messages
871
+ case ProgramChange:
872
+ case AfterTouchChannel:
873
+ case TimeCodeQuarterFrame:
874
+ case SongSelect:
875
+ mPendingMessage [0 ] = extracted;
876
+ mPendingMessageExpectedLength = 2 ;
877
+ break ;
878
+ // 3 byte messages
879
+ case NoteOn:
880
+ case NoteOff:
881
+ case ControlChange:
882
+ case PitchBend:
883
+ case AfterTouchPoly:
884
+ case SongPosition:
885
+ mPendingMessage [0 ] = extracted;
886
+ mPendingMessageExpectedLength = 3 ;
887
+ break ;
888
+ // SysEx
889
+ case SystemExclusiveStart:
890
+ mPendingMessage [0 ] = SystemExclusive;
891
+ mPendingMessageExpectedLength = MidiMessage::sSysExMaxSize ;
892
+ mMessage .sysexArray [0 ] = SystemExclusiveStart;
893
+ mLastError &= ~(1UL << WarningSplitSysEx); // Reset Warning Split SysEx bit
894
+ break ;
895
+ case SystemExclusiveEnd:
896
+ if (mPendingMessage [0 ] == SystemExclusive) {
897
+ mMessage .sysexArray [mPendingMessageIndex ++] = SystemExclusiveEnd; // Post Inc pending index here for correct length data
898
+ mMessage .type = SystemExclusive;
899
+ mMessage .data1 = mPendingMessageIndex & 0xff ; // LSB
900
+ mMessage .data2 = byte (mPendingMessageIndex >> 8 ); // MSB
901
+ mMessage .channel = 0 ;
902
+ mMessage .length = mPendingMessageIndex ;
903
+ if (mMessage .sysexArray [0 ] == SystemExclusiveEnd) {
904
+ // This is the last chunk of a split SysEx message, and is NOT a valid SysEx message (it starts with 0xF7)
905
+ mMessage .valid = false ; // SysEx message is split so this is not technically valid
906
+ launchCallback (); // Lets notify callback to deal with this
907
+ resetInput (); // Restart message
908
+ return false ;
909
+ } else {
910
+ // We are in a valid SysEx message that hasn't overrun (starts with 0xF0) so lets complete it
911
+ mMessage .valid = true ;
912
+ resetInput (); // Restart message
913
+ return true ;
914
+ }
915
+ } else { // Looks like a SysEx End without a Sysex Start
916
+ mLastError |= 1UL << ErrorParse; // Error: SysEx Stop byte received with no pending SysEx Start.
917
+ if (mErrorCallback )
918
+ mErrorCallback (mLastError );
919
+ resetInput (); // Restart message
920
+ return false ;
921
+ }
922
+ break ;
923
+ // Unsupported
924
+ default :
925
+ mPendingMessage [0 ] = InvalidType;
926
+ mLastError |= 1UL << ErrorParse; // Error: Unsupported Status byte.
927
+ if (mErrorCallback )
928
+ mErrorCallback (mLastError );
929
+ resetInput (); // Restart message
930
+ return false ;
931
+ break ;
972
932
}
973
- auto lastByte = mMessage .sysexArray [Settings::SysExMaxSize - 1 ];
974
- mMessage .sysexArray [Settings::SysExMaxSize - 1 ] = SystemExclusiveStart;
975
- mMessage .type = SystemExclusive;
976
-
977
- // Get length
978
- mMessage .data1 = Settings::SysExMaxSize & 0xff ; // LSB
979
- mMessage .data2 = byte (Settings::SysExMaxSize >> 8 ); // MSB
980
- mMessage .channel = 0 ;
981
- mMessage .length = Settings::SysExMaxSize;
982
- mMessage .valid = false ; // SysEx message is split so this is not technically valid
983
-
984
- // Notify callback to deal with the SysEx data chunk
985
- launchCallback ();
933
+ mPendingMessageIndex = 1 ; // If we are here, we have a valid Status! Lets try get some Data for it....
934
+ mRunningStatus_RX = InvalidType; // Lets also reset Running Status until we have a complete message
935
+ return (Settings::Use1ByteParsing) ? false : parse ();
986
936
987
- // Prep next SysEx data chunk to start with 0xF7
988
- mMessage .sysexArray [0 ] = SystemExclusiveEnd;
989
- mMessage .sysexArray [1 ] = lastByte;
990
- mPendingMessageIndex = 2 ;
991
- // SysEx buffer has overrun so parse() will no longer return true, and will need to be dealt with via callbacks only
992
- return false ;
993
- }
937
+ } else {
938
+ // Lets get some data... First off.. check for Status Byte, or use Running Status
939
+ if (mPendingMessageIndex == 0 ) {
940
+ if (mRunningStatus_RX ) {
941
+ // Yay! We have Running Status
942
+ mPendingMessage [0 ] = mRunningStatus_RX ;
943
+ mPendingMessageIndex = 1 ;
944
+ } else {
945
+ // ooops.... No Status Byte... No Running Status... lets ignore this data
946
+ mLastError |= 1UL << ErrorParse; // Error: Data received without a valid Status byte or Running Status.
947
+ if (mErrorCallback )
948
+ mErrorCallback (mLastError );
949
+ return false ;
950
+ }
951
+ }
994
952
995
- // Pending message is complete so lets save it
996
- mMessage .type = getTypeFromStatusByte (mPendingMessage [0 ]);
953
+ // Status or Running Status is good so add extracted data byte to pending message
954
+ if (mPendingMessage [0 ] == SystemExclusive)
955
+ mMessage .sysexArray [mPendingMessageIndex ] = extracted;
956
+ else
957
+ mPendingMessage [mPendingMessageIndex ] = extracted;
958
+
959
+ // Now we are going to check if we have reached the end of the message
960
+ if (mPendingMessageIndex >= (mPendingMessageExpectedLength - 1 )) {
961
+ // SysEx larger than the allocated buffer size,
962
+ // Split SysEx like so:
963
+ // first: 0xF0 .... 0xF0
964
+ // middle: 0xF7 .... 0xF0
965
+ // last: 0xF7 .... 0xF7
966
+ // ***** If the buffer has overrun, this SysEx message can now no longer be considered a valid Midi message and must be dealt with via callbacks only! ****
967
+ if (mPendingMessage [0 ] == SystemExclusive) {
968
+ // Warn at start of SysEx split
969
+ if (mMessage .sysexArray [0 ] == SystemExclusiveStart) {
970
+ mLastError |= 1UL << WarningSplitSysEx; // We have this error already defined so may as well use it
971
+ if (mErrorCallback )
972
+ mErrorCallback (mLastError );
973
+ }
974
+ auto lastByte = mMessage .sysexArray [Settings::SysExMaxSize - 1 ];
975
+ mMessage .sysexArray [Settings::SysExMaxSize - 1 ] = SystemExclusiveStart;
976
+ mMessage .type = SystemExclusive;
977
+
978
+ // Get length
979
+ mMessage .data1 = Settings::SysExMaxSize & 0xff ; // LSB
980
+ mMessage .data2 = byte (Settings::SysExMaxSize >> 8 ); // MSB
981
+ mMessage .channel = 0 ;
982
+ mMessage .length = Settings::SysExMaxSize;
983
+ mMessage .valid = false ; // SysEx message is split so this is not technically valid
984
+
985
+ // Notify callback to deal with the SysEx data chunk
986
+ launchCallback ();
987
+
988
+ // Prep next SysEx data chunk to start with 0xF7
989
+ mMessage .sysexArray [0 ] = SystemExclusiveEnd;
990
+ mMessage .sysexArray [1 ] = lastByte;
991
+ mPendingMessageIndex = 2 ;
992
+ // SysEx buffer has overrun so parse() will no longer return true, and will need to be dealt with via callbacks only
993
+ return false ;
994
+ }
997
995
998
- if (isChannelMessage (mMessage .type )) {
999
- mMessage .channel = getChannelFromStatusByte (mPendingMessage [0 ]);
1000
- // Message will be completed soon so lets update RunningStatus now as this is obviously a valid Channel Message.
1001
- mRunningStatus_RX = mPendingMessage [0 ];
1002
- } else
1003
- mMessage .channel = 0 ;
996
+ // Pending message is complete so lets save it
997
+ mMessage .type = getTypeFromStatusByte (mPendingMessage [0 ]);
1004
998
1005
- mMessage .data1 = mPendingMessage [1 ];
1006
- // Save data2 only if applicable
1007
- mMessage .data2 = mPendingMessageExpectedLength == 3 ? mPendingMessage [2 ] : 0 ;
1008
- mMessage .length = mPendingMessageExpectedLength ;
1009
- mMessage .valid = true ;
999
+ if (isChannelMessage (mMessage .type )) {
1000
+ mMessage .channel = getChannelFromStatusByte (mPendingMessage [0 ]);
1001
+ // Message will be completed soon so lets update RunningStatus now as this is obviously a valid Channel Message.
1002
+ mRunningStatus_RX = mPendingMessage [0 ];
1003
+ } else
1004
+ mMessage .channel = 0 ;
1010
1005
1011
- // Reset index for next message
1012
- mPendingMessageIndex = 0 ;
1013
- // mPendingMessageExpectedLength = 0; // <-- No need to reset this as its valid still for Running Status, or will be updated on next Status byte received.
1006
+ mMessage .data1 = mPendingMessage [1 ];
1007
+ // Save data2 only if applicable
1008
+ mMessage .data2 = mPendingMessageExpectedLength == 3 ? mPendingMessage [2 ] : 0 ;
1009
+ mMessage .length = mPendingMessageExpectedLength ;
1010
+ mMessage .valid = true ;
1014
1011
1015
- return true ;
1016
- } else {
1017
- // We need more data...
1018
- mPendingMessageIndex ++;
1012
+ // Reset index for next message
1013
+ mPendingMessageIndex = 0 ;
1014
+ // mPendingMessageExpectedLength = 0; // <-- No need to reset this as its valid still for Running Status, or will be updated on next Status byte received.
1019
1015
1020
- return (Settings::Use1ByteParsing) ? false : parse ();
1016
+ return true ;
1017
+ } else {
1018
+ // We need more data...
1019
+ mPendingMessageIndex ++;
1020
+
1021
+ return (Settings::Use1ByteParsing) ? false : parse ();
1022
+ }
1021
1023
}
1022
- }
1023
1024
}
1024
1025
1025
1026
// Private method, see midi_Settings.h for documentation
0 commit comments