From 83fd304d412f72c0faf6ca19eda677752fa069f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saulo=20Ver=C3=ADssimo?= Date: Wed, 8 Jul 2026 23:06:10 -0300 Subject: [PATCH] fix(umpToBytestream): reset (N)RPN and running-status cache on group change Ref #30 --- include/umpToBytestream.h | 26 ++++++++++---- tests/tests.cpp | 71 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/include/umpToBytestream.h b/include/umpToBytestream.h index 036932e..b3381d8 100644 --- a/include/umpToBytestream.h +++ b/include/umpToBytestream.h @@ -44,6 +44,21 @@ class umpToBytestream{ uint8_t lastRPN_LSB[16]; uint8_t lastNRPN_MSB[16]; uint8_t lastNRPN_LSB[16]; + uint8_t lastGroupSeen = 255; + + void resetGroupState(){ + lastRunningStatus = 255; + for (int ch = 0; ch < 16; ch++) { + lastRPN_MSB[ch] = 255; + lastRPN_LSB[ch] = 255; + lastNRPN_MSB[ch] = 255; + lastNRPN_LSB[ch] = 255; + } + } + + void checkGroupChange(){ + if (group != lastGroupSeen) { resetGroupState(); lastGroupSeen = group; } + } void increaseWrite(){ bufferLength++; @@ -86,13 +101,8 @@ class umpToBytestream{ readIndex = 0; writeIndex = 0; bufferLength = 0; - lastRunningStatus = 255; - for (int ch = 0; ch < 16; ch++) { - lastRPN_MSB[ch] = 255; - lastRPN_LSB[ch] = 255; - lastNRPN_MSB[ch] = 255; - lastNRPN_LSB[ch] = 255; - } + resetGroupState(); + lastGroupSeen = 255; } bool availableBS(){ @@ -151,6 +161,7 @@ class umpToBytestream{ if(filterByGroup<16 && group != filterByGroup){ return; } + checkGroupChange(); uint8_t stsCh = UMP >> 16 & 0xFF; checkRunningStatusAndAddByte(stsCh); @@ -231,6 +242,7 @@ class umpToBytestream{ if(filterByGroup<16 && group != filterByGroup){ return; } + checkGroupChange(); uint8_t status = ump64word1 >> 16 & 0xF0; uint8_t channel = ump64word1 >> 16 & 0xF; uint8_t val1 = ump64word1 >> 8 & 0x7F; diff --git a/tests/tests.cpp b/tests/tests.cpp index 5691c50..bbafc26 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -487,6 +487,77 @@ int main(){ passFail(rtMetSub2, 3); printf(" FlexMetronome roundtrip\n"); + //***** Cross-Group RPN (issue #30) *************************************** + printf("Cross-Group RPN (issue #30) \n"); + + // Test #30-1: reproduce cross-group contamination. Same channel, same param. + umpToBytestream xg; + auto g0 = UMPMessage::mt4RPN(0, 0, 1, 2, 0); // group 0, ch 0, bank 1, idx 2 + auto g1 = UMPMessage::mt4RPN(1, 0, 1, 2, 0); // group 1, ch 0, bank 1, idx 2 + uint8_t xgOut[64]; int xgLen = 0; + for(int i=0;i<2;i++){ xg.UMPStreamParse(g0[i]); while(xg.availableBS()) xgOut[xgLen++]=xg.readBS(); } + for(int i=0;i<2;i++){ xg.UMPStreamParse(g1[i]); while(xg.availableBS()) xgOut[xgLen++]=xg.readBS(); } + // Both group segments must carry the parameter number (24 bytes). + uint8_t xgExpected[24] = { + 0xB0,0x65,0x01, 0xB0,0x64,0x02, 0xB0,0x06,0x00, 0xB0,0x26,0x00, + 0xB0,0x65,0x01, 0xB0,0x64,0x02, 0xB0,0x06,0x00, 0xB0,0x26,0x00 + }; + passFail(xgLen, 24); + for(int i=0;i<24 && i