|
|
|
@ -1394,8 +1394,8 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) |
|
|
|
|
case 64: |
|
|
|
|
MicroDexed[instance_id]->setSustain(inValue > 63); |
|
|
|
|
/*
|
|
|
|
|
if (!MicroDexed[instance_id]->getSustain()) |
|
|
|
|
{ |
|
|
|
|
if (!MicroDexed[instance_id]->getSustain()) |
|
|
|
|
{ |
|
|
|
|
for (uint8_t note = 0; note < MicroDexed[instance_id]->getMaxNotes(); note++) |
|
|
|
|
{ |
|
|
|
|
if (MicroDexed[instance_id]->voices[note].sustained && !MicroDexed[instance_id]->voices[note].keydown) |
|
|
|
@ -1404,7 +1404,7 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) |
|
|
|
|
MicroDexed[instance_id]->voices[note].sustained = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
break; |
|
|
|
|
case 65: |
|
|
|
@ -1584,8 +1584,10 @@ void handleProgramChange(byte inChannel, byte inProgram) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void handleSystemExclusive(byte * sysex, uint len) |
|
|
|
|
void handleSystemExclusive(byte* sysex, unsigned int len) |
|
|
|
|
{ |
|
|
|
|
int16_t sysex_return; |
|
|
|
|
|
|
|
|
|
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) |
|
|
|
|
{ |
|
|
|
|
if (!checkMidiChannel((sysex[2] & 0x0f) + 1 , instance_id)) |
|
|
|
@ -1624,61 +1626,97 @@ void handleSystemExclusive(byte * sysex, uint len) |
|
|
|
|
Serial.println(); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// Check for SYSEX end byte
|
|
|
|
|
if (sysex[len - 1] != 0xf7) |
|
|
|
|
{ |
|
|
|
|
sysex_return = MicroDexed[instance_id]->handleSystemExclusive(sysex, len); |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: SysEx end status byte not detected.")); |
|
|
|
|
Serial.print(F("SYSEX handler return value:")); |
|
|
|
|
Serial.print(sysex_return, DEC); |
|
|
|
|
Serial.println(); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (sysex[1] != 0x43) // check for Yamaha sysex
|
|
|
|
|
switch (sysex_return) |
|
|
|
|
{ |
|
|
|
|
case -1: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: SysEx vendor not Yamaha.")); |
|
|
|
|
Serial.println(F("E: SysEx end status byte not detected.")); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
case -2: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("Substatus: [")); |
|
|
|
|
Serial.print((sysex[2] & 0x70) >> 4); |
|
|
|
|
Serial.println(F("]")); |
|
|
|
|
Serial.println(F("E: SysEx vendor not Yamaha.")); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// parse parameter change
|
|
|
|
|
if (len == 7) |
|
|
|
|
{ |
|
|
|
|
if (((sysex[3] & 0x7c) >> 2) != 0 && ((sysex[3] & 0x7c) >> 2) != 2) |
|
|
|
|
{ |
|
|
|
|
break; |
|
|
|
|
case -3: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Not a SysEx parameter or function parameter change.")); |
|
|
|
|
Serial.println(F("E: Unknown SysEx parameter change.")); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
sysex[4] &= 0x7f; |
|
|
|
|
sysex[5] &= 0x7f; |
|
|
|
|
|
|
|
|
|
if ((sysex[3] & 0x7c) >> 2 == 0) |
|
|
|
|
{ |
|
|
|
|
break; |
|
|
|
|
case -4: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("SysEx Voice parameter:")); |
|
|
|
|
Serial.print("Parameter #"); |
|
|
|
|
Serial.print(sysex[4] + ((sysex[3] & 0x03) * 128), DEC); |
|
|
|
|
Serial.print(" Value: "); |
|
|
|
|
Serial.println(sysex[5], DEC); |
|
|
|
|
Serial.println(F("E: Unknown SysEx voice or function.")); |
|
|
|
|
#endif |
|
|
|
|
MicroDexed[instance_id]->setVoiceDataElement(sysex[4] + ((sysex[3] & 0x03) * 128), sysex[5]); |
|
|
|
|
} |
|
|
|
|
else if ((sysex[3] & 0x7c) >> 2 == 2) |
|
|
|
|
{ |
|
|
|
|
break; |
|
|
|
|
case -5: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("SysEx Function parameter:")); |
|
|
|
|
Serial.print("Parameter #"); |
|
|
|
|
Serial.println(F("E: Not a SysEx voice bulk upload.")); |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
|
case -6: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Wrong length for SysEx voice bulk upload (not 155).")); |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
|
case -7: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Checksum error for one voice.")); |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
|
case -8: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Not a SysEx bank bulk upload.")); |
|
|
|
|
#endif |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Error (TYPE) ")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
break; |
|
|
|
|
case -9: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Wrong length for SysEx bank bulk upload (not 4096).")); |
|
|
|
|
#endif |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Error (SIZE) ")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
break; |
|
|
|
|
case -10: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Checksum error for bank.")); |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
|
case -11: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Unknown SysEx message.")); |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
|
case 64: |
|
|
|
|
case 65: |
|
|
|
|
case 66: |
|
|
|
|
case 67: |
|
|
|
|
case 68: |
|
|
|
|
case 69: |
|
|
|
|
case 70: |
|
|
|
|
case 71: |
|
|
|
|
case 72: |
|
|
|
|
case 73: |
|
|
|
|
case 74: |
|
|
|
|
case 75: |
|
|
|
|
case 76: |
|
|
|
|
case 77: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("SysEx Function parameter change : ")); |
|
|
|
|
Serial.print(F("Parameter #")); |
|
|
|
|
Serial.print(sysex[4], DEC); |
|
|
|
|
Serial.print(" Value: "); |
|
|
|
|
Serial.print(F(" Value : ")); |
|
|
|
|
Serial.println(sysex[5], DEC); |
|
|
|
|
#endif |
|
|
|
|
switch (sysex[4]) |
|
|
|
@ -1800,189 +1838,87 @@ void handleSystemExclusive(byte * sysex, uint len) |
|
|
|
|
LCDML.loop_menu(); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
MicroDexed[instance_id]->setVoiceDataElement(sysex[4], sysex[5]); // set function parameter
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
MicroDexed[instance_id]->ControllersRefresh(); |
|
|
|
|
} |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
Serial.println(F("E: Unknown SysEx voice or function.")); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
else if (len == 163) |
|
|
|
|
{ |
|
|
|
|
int32_t bulk_checksum_calc = 0; |
|
|
|
|
int8_t bulk_checksum = sysex[161]; |
|
|
|
|
|
|
|
|
|
// 1 Voice bulk upload
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("One Voice bulk upload")); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if ((sysex[3] & 0x7f) != 0) |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Not a SysEx voice bulk upload.")); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (((sysex[4] << 7) | sysex[5]) != 0x9b) |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Wrong length for SysEx voice bulk upload (not 155).")); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// checksum calculation
|
|
|
|
|
for (uint8_t i = 0; i < 155 ; i++) |
|
|
|
|
{ |
|
|
|
|
bulk_checksum_calc -= sysex[i + 6]; |
|
|
|
|
} |
|
|
|
|
bulk_checksum_calc &= 0x7f; |
|
|
|
|
|
|
|
|
|
if (bulk_checksum_calc != bulk_checksum) |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("E: Checksum error for one voice [0x")); |
|
|
|
|
Serial.print(bulk_checksum, HEX); |
|
|
|
|
Serial.print(F("/0x")); |
|
|
|
|
Serial.print(bulk_checksum_calc, HEX); |
|
|
|
|
Serial.println(F("]")); |
|
|
|
|
#endif |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// fix voice name
|
|
|
|
|
for (uint8_t i = 0; i < 10; i++) |
|
|
|
|
{ |
|
|
|
|
if (sysex[151 + i] > 126) // filter characters
|
|
|
|
|
sysex[151 + i] = 32; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// load sysex-data into voice memory
|
|
|
|
|
MicroDexed[instance_id]->loadVoiceParameters(&sysex[6]); |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
show_patch(instance_id); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// show voice name
|
|
|
|
|
strncpy(g_voice_name[instance_id], (char*)&sysex[151], VOICE_NAME_LEN - 1); |
|
|
|
|
|
|
|
|
|
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select)) |
|
|
|
|
{ |
|
|
|
|
LCDML.OTHER_updateFunc(); |
|
|
|
|
LCDML.loop_menu(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (len == 4104) |
|
|
|
|
{ |
|
|
|
|
if (strlen(receive_bank_filename) > 0 && LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_sysex_receive_bank)) |
|
|
|
|
{ |
|
|
|
|
int32_t bulk_checksum_calc = 0; |
|
|
|
|
int8_t bulk_checksum = sysex[4102]; |
|
|
|
|
|
|
|
|
|
// 1 Bank bulk upload
|
|
|
|
|
if ((sysex[3] & 0x7f) != 9) |
|
|
|
|
break; |
|
|
|
|
case 100: |
|
|
|
|
// fix voice name
|
|
|
|
|
for (uint8_t i = 0; i < 10; i++) |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Not a SysEx bank bulk upload.")); |
|
|
|
|
#endif |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Error (TYPE) ")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
return; |
|
|
|
|
if (sysex[151 + i] > 126) // filter characters
|
|
|
|
|
sysex[151 + i] = 32; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Bank bulk upload.")); |
|
|
|
|
#endif |
|
|
|
|
// load sysex-data into voice memory
|
|
|
|
|
MicroDexed[instance_id]->loadVoiceParameters(&sysex[6]); |
|
|
|
|
|
|
|
|
|
if (((sysex[4] << 7) | sysex[5]) != 0x1000) |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("E: Wrong length for SysEx bank bulk upload (not 4096).")); |
|
|
|
|
Serial.println(F("One Voice bulk upload")); |
|
|
|
|
show_patch(instance_id); |
|
|
|
|
#endif |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Error (SIZE) ")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
strncpy(g_voice_name[instance_id], (char*)&sysex[151], VOICE_NAME_LEN - 1); |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Bank type ok")); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// checksum calculation
|
|
|
|
|
for (uint16_t i = 0; i < 4096 ; i++) |
|
|
|
|
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select)) |
|
|
|
|
{ |
|
|
|
|
bulk_checksum_calc -= sysex[i + 6]; |
|
|
|
|
LCDML.OTHER_updateFunc(); |
|
|
|
|
LCDML.loop_menu(); |
|
|
|
|
} |
|
|
|
|
bulk_checksum_calc &= 0x7f; |
|
|
|
|
|
|
|
|
|
if (bulk_checksum_calc != bulk_checksum) |
|
|
|
|
break; |
|
|
|
|
case 200: |
|
|
|
|
if (strlen(receive_bank_filename) > 0 && LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_sysex_receive_bank)) |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("E: Checksum error for bank [0x")); |
|
|
|
|
Serial.print(bulk_checksum, HEX); |
|
|
|
|
Serial.print(F("/0x")); |
|
|
|
|
Serial.print(bulk_checksum_calc, HEX); |
|
|
|
|
Serial.println(F("]")); |
|
|
|
|
#endif |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Error (CHECKSUM)")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Serial.println(F("Bank bulk upload.")); |
|
|
|
|
#endif |
|
|
|
|
if (save_sd_bank(receive_bank_filename, sysex)) |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Bank checksum ok")); |
|
|
|
|
Serial.print(F("Bank saved as [")); |
|
|
|
|
Serial.print(receive_bank_filename); |
|
|
|
|
Serial.println(F("]")); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (save_sd_bank(receive_bank_filename, sysex)) |
|
|
|
|
{ |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Done. ")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.print(F("Bank saved as [")); |
|
|
|
|
Serial.print(receive_bank_filename); |
|
|
|
|
Serial.println(F("]")); |
|
|
|
|
Serial.println(F("Error during saving bank as [")); |
|
|
|
|
Serial.print(receive_bank_filename); |
|
|
|
|
Serial.println(F("]")); |
|
|
|
|
#endif |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Done. ")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Error. ")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
} |
|
|
|
|
memset(receive_bank_filename, 0, FILENAME_LEN); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Error during saving bank as [")); |
|
|
|
|
Serial.print(receive_bank_filename); |
|
|
|
|
Serial.println(F("]")); |
|
|
|
|
else |
|
|
|
|
Serial.println(F("E : Not in MIDI receive bank mode.")); |
|
|
|
|
#endif |
|
|
|
|
display.setCursor(0, 1); |
|
|
|
|
display.print(F("Error. ")); |
|
|
|
|
delay(MESSAGE_WAIT_TIME); |
|
|
|
|
LCDML.FUNC_goBackToMenu(); |
|
|
|
|
} |
|
|
|
|
memset(receive_bank_filename, 0, FILENAME_LEN); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case 300: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
else |
|
|
|
|
Serial.println(F("E: Not in MIDI receive bank mode.")); |
|
|
|
|
Serial.println(F("SysEx Voice parameter:")); |
|
|
|
|
Serial.print(F("Parameter #")); |
|
|
|
|
Serial.print(sysex[4] + ((sysex[3] & 0x03) * 128), DEC); |
|
|
|
|
Serial.print(F(" Value: ")); |
|
|
|
|
Serial.println(sysex[5], DEC); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
else |
|
|
|
|
Serial.println(F("E: SysEx parameter length wrong.")); |
|
|
|
|
Serial.println(F("SysEx Voice parameter change : ")); |
|
|
|
|
Serial.print(F("Parameter #")); |
|
|
|
|
Serial.print(sysex_return); |
|
|
|
|
Serial.print(F(" Value : ")); |
|
|
|
|
Serial.println(sysex[5], DEC); |
|
|
|
|
#endif |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|