diff --git a/MicroDexed.ino b/MicroDexed.ino index 95060cd..a67fd55 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -390,13 +390,13 @@ void setup() { // read all bank names max_loaded_banks = get_bank_names(instance_id); - strip_extension(bank_names[instance_id][configuration.dexed[instance_id].bank], bank_name[instance_id]); + strip_extension(bank_names[instance_id][configuration.performance.bank[instance_id]], bank_name[instance_id]); // read all voice name for actual bank - get_voice_names_from_bank(configuration.dexed[instance_id].bank, instance_id); + get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id); #ifdef DEBUG Serial.print(F("Bank [")); - Serial.print(bank_names[instance_id][configuration.dexed[instance_id].bank]); + Serial.print(bank_names[instance_id][configuration.performance.bank[instance_id]]); Serial.print(F("/")); Serial.print(bank_name[instance_id]); Serial.println(F("]")); @@ -413,7 +413,7 @@ void setup() #endif // load default SYSEX data - load_sd_voice(configuration.dexed[instance_id].bank, configuration.dexed[instance_id].voice, instance_id); + load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id); } } @@ -559,9 +559,9 @@ void setup() Serial.print(instance_id); Serial.println(F(":")); Serial.print(F("Bank/Voice from EEPROM [")); - Serial.print(configuration.dexed[instance_id].bank, DEC); + Serial.print(configuration.performance.bank[instance_id], DEC); Serial.print(F("/")); - Serial.print(configuration.dexed[instance_id].voice, DEC); + Serial.print(configuration.performance.voice[instance_id], DEC); Serial.println(F("]")); Serial.print(F("Polyphony: ")); Serial.println(configuration.dexed[instance_id].polyphony, DEC); @@ -708,7 +708,7 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) case 0: if (inValue < MAX_BANKS - 1) { - configuration.dexed[instance_id].bank = inValue; + configuration.performance.bank[instance_id] = inValue; eeprom_write(); } break; @@ -763,7 +763,7 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) #ifdef DEBUG Serial.println(F("BANK-SELECT CC")); #endif - configuration.dexed[instance_id].bank = inValue; + configuration.performance.bank[instance_id] = inValue; eeprom_write(); break; case 64: @@ -871,7 +871,7 @@ void handleProgramChange(byte inChannel, byte inProgram) #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sd_voice(configuration.dexed[instance_id].bank, inProgram, instance_id); + load_sd_voice(configuration.performance.bank[instance_id], inProgram, instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -1266,6 +1266,8 @@ void initial_values_from_eeprom(bool init) eeprom_get_sys(); eeprom_get_fx(); + eeprom_get_performance(); + for (uint8_t i = 0; i < NUM_DEXED; i++) eeprom_get_dexed(i); @@ -1341,8 +1343,8 @@ void check_configuration(void) for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { configuration.dexed[instance_id].midi_channel = constrain(configuration.dexed[instance_id].midi_channel, MIDI_CHANNEL_MIN, MIDI_CHANNEL_MAX); - configuration.dexed[instance_id].bank = constrain(configuration.dexed[instance_id].bank, 0, MAX_BANKS - 1); - configuration.dexed[instance_id].voice = constrain(configuration.dexed[instance_id].voice, 0, MAX_VOICES - 1); + configuration.performance.bank[instance_id] = constrain(configuration.performance.bank[instance_id], 0, MAX_BANKS - 1); + configuration.performance.voice[instance_id] = constrain(configuration.performance.voice[instance_id], 0, MAX_VOICES - 1); configuration.dexed[instance_id].lowest_note = constrain(configuration.dexed[instance_id].lowest_note, INSTANCE_LOWEST_NOTE_MIN, INSTANCE_LOWEST_NOTE_MAX); configuration.dexed[instance_id].highest_note = constrain(configuration.dexed[instance_id].highest_note, INSTANCE_HIGHEST_NOTE_MIN, INSTANCE_HIGHEST_NOTE_MAX); configuration.dexed[instance_id].reverb_send = constrain(configuration.dexed[instance_id].reverb_send, REVERB_SEND_MIN, REVERB_SEND_MAX); @@ -1397,6 +1399,8 @@ void init_configuration(void) configuration.sys.instances = INSTANCES_DEFAULT; configuration.sys.vol = VOLUME_DEFAULT; configuration.sys.mono = MONO_DEFAULT; + configuration.sys.soft_midi_thru = SOFT_MIDI_THRU_DEFAULT; + configuration.fx.checksum = 0xffff; configuration.fx.reverb_roomsize = REVERB_ROOMSIZE_DEFAULT; configuration.fx.reverb_damping = REVERB_DAMPING_DEFAULT; @@ -1408,14 +1412,16 @@ void init_configuration(void) configuration.fx.delay_time = DELAY_TIME_DEFAULT / 10; configuration.fx.delay_feedback = DELAY_FEEDBACK_DEFAULT; configuration.fx.delay_level = DELAY_LEVEL_DEFAULT; - configuration.sys.soft_midi_thru = SOFT_MIDI_THRU_DEFAULT; + + configuration.performance.checksum = 0xffff; + configuration.performance.fx_number = 0; for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { configuration.dexed[instance_id].checksum = 0xffff; configuration.dexed[instance_id].midi_channel = DEFAULT_MIDI_CHANNEL; - configuration.dexed[instance_id].bank = SYSEXBANK_DEFAULT; - configuration.dexed[instance_id].voice = SYSEXSOUND_DEFAULT; + configuration.performance.bank[instance_id] = SYSEXBANK_DEFAULT; + configuration.performance.voice[instance_id] = SYSEXSOUND_DEFAULT; configuration.dexed[instance_id].lowest_note = INSTANCE_LOWEST_NOTE_MIN; configuration.dexed[instance_id].highest_note = INSTANCE_HIGHEST_NOTE_MAX; configuration.dexed[instance_id].reverb_send = REVERB_SEND_DEFAULT; @@ -1427,7 +1433,12 @@ void init_configuration(void) configuration.dexed[instance_id].pan = PANORAMA_DEFAULT; configuration.dexed[instance_id].transpose = TRANSPOSE_DEFAULT; configuration.dexed[instance_id].tune = TUNE_DEFAULT; - configuration.dexed[instance_id].polyphony = POLYPHONY_DEFAULT; + + if (instance_id == 0) + configuration.dexed[instance_id].polyphony = POLYPHONY_DEFAULT; + else + configuration.dexed[instance_id].polyphony = 0; + configuration.dexed[instance_id].velocity_level = VELOCITY_LEVEL_DEFAULT; configuration.dexed[instance_id].engine = ENGINE_DEFAULT; configuration.dexed[instance_id].monopoly = MONOPOLY_DEFAULT; @@ -1450,12 +1461,18 @@ void init_configuration(void) configuration.dexed[instance_id].portamento_glissando = PORTAMENTO_GLISSANDO_DEFAULT; configuration.dexed[instance_id].portamento_time = PORTAMENTO_TIME_DEFAULT; configuration.dexed[instance_id].op_enabled = OP_ENABLED_DEFAULT; + + configuration.performance.bank[instance_id] = SYSEXBANK_DEFAULT; + configuration.performance.voice[instance_id] = SYSEXSOUND_DEFAULT; + MicroDexed[instance_id]->controllers.refresh(); } set_volume(configuration.sys.vol, configuration.sys.mono); eeprom_update_sys(); eeprom_update_fx(); + eeprom_update_performance(); + for (uint8_t i = 0; i < NUM_DEXED; i++) eeprom_update_dexed(i); } @@ -1478,8 +1495,7 @@ void eeprom_update_sys(void) configuration.sys.checksum = crc32((byte*)&configuration.sys + 4, sizeof(configuration.sys) - 4); EEPROM.put(EEPROM_SYS_START_ADDRESS, configuration.sys); #ifdef DEBUG - Serial.println(F("Updating EEPROM sys")); - show_configuration(); + Serial.println(F("Updating EEPROM sys.")); #endif } } @@ -1501,7 +1517,6 @@ bool eeprom_get_sys(void) { #ifdef DEBUG Serial.print(F("EEPROM sys loaded.")); - show_configuration(); #endif return (true); } @@ -1512,8 +1527,7 @@ void eeprom_update_fx(void) configuration.fx.checksum = crc32((byte*)&configuration.fx + 4, sizeof(configuration.fx) - 4); EEPROM.put(EEPROM_FX_START_ADDRESS, configuration.fx); #ifdef DEBUG - Serial.println(F("Updating EEPROM fx")); - show_configuration(); + Serial.println(F("Updating EEPROM fx.")); #endif } @@ -1533,7 +1547,6 @@ bool eeprom_get_fx(void) { #ifdef DEBUG Serial.print(F("EEPROM fx loaded.")); - show_configuration(); #endif return (true); } @@ -1546,8 +1559,7 @@ void eeprom_update_dexed(uint8_t instance_id) #ifdef DEBUG Serial.print(F("Updating EEPROM dexed (instance ")); Serial.print(instance_id); - Serial.println(F(")")); - show_configuration(); + Serial.println(F(").")); #endif } @@ -1571,7 +1583,36 @@ bool eeprom_get_dexed(uint8_t instance_id) Serial.print(F("EEPROM dexed (instance ")); Serial.print(instance_id); Serial.println(F(") loaded.")); - show_configuration(); +#endif + return (true); + } +} + +void eeprom_update_performance() +{ + configuration.performance.checksum = crc32((byte*)&configuration.performance + 4, sizeof(configuration.performance) - 4); + EEPROM.put(EEPROM_PERFORMANCE_START_ADDRESS, configuration.performance); +#ifdef DEBUG + Serial.println(F("Updating EEPROM performance.")); +#endif +} + +bool eeprom_get_performance() +{ + EEPROM.get(EEPROM_PERFORMANCE_START_ADDRESS, configuration.performance); + uint32_t checksum = crc32((byte*)&configuration.performance + 4, sizeof(configuration.performance) - 4); + + if (checksum != configuration.performance.checksum) + { +#ifdef DEBUG + Serial.println(F("Checksum error reading EEPROM performance.")); +#endif + return (false); + } + else + { +#ifdef DEBUG + Serial.println(F("EEPROM performance loaded.")); #endif return (true); } @@ -1839,14 +1880,15 @@ void show_configuration(void) Serial.print(F(" Delay Time ")); Serial.println(configuration.fx.delay_time, DEC); Serial.print(F(" Delay Feedback ")); Serial.println(configuration.fx.delay_feedback, DEC); Serial.print(F(" Delay Level ")); Serial.println(configuration.fx.delay_level, DEC); + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { Serial.print(F("Dexed instance ")); Serial.println(instance_id, DEC); Serial.print(F(" Checksum 0x")); Serial.println(configuration.dexed[instance_id].checksum, HEX); Serial.print(F(" MIDI-Channel ")); Serial.println(configuration.dexed[instance_id].midi_channel, DEC); - Serial.print(F(" Bank ")); Serial.println(configuration.dexed[instance_id].bank, DEC); - Serial.print(F(" Voice ")); Serial.println(configuration.dexed[instance_id].voice, DEC); + Serial.print(F(" Bank ")); Serial.println(configuration.performance.bank[instance_id], DEC); + Serial.print(F(" Voice ")); Serial.println(configuration.performance.voice[instance_id], DEC); Serial.print(F(" Lowest Note ")); Serial.println(configuration.dexed[instance_id].lowest_note, DEC); Serial.print(F(" Highest Note ")); Serial.println(configuration.dexed[instance_id].highest_note, DEC); Serial.print(F(" Reverb Send ")); Serial.println(configuration.dexed[instance_id].reverb_send, DEC); @@ -1882,6 +1924,16 @@ void show_configuration(void) Serial.print(F(" OP Enabled ")); Serial.println(configuration.dexed[instance_id].op_enabled, DEC); Serial.flush(); } + + Serial.println(F("Performance")); + Serial.print(F(" Checksum 0x")); Serial.println(configuration.performance.checksum, HEX); + for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) + { + Serial.print(F(" Bank ")); Serial.print(instance_id, DEC); Serial.print(" "); Serial.println(configuration.performance.bank[instance_id], DEC); + Serial.print(F(" Voice ")); Serial.print(instance_id, DEC); Serial.print(" "); Serial.println(configuration.performance.voice[instance_id], DEC); + } + Serial.print(F(" FX-Number ")); Serial.println(configuration.performance.fx_number, DEC); + Serial.println(); Serial.flush(); } diff --git a/UI.hpp b/UI.hpp index 3f244a3..51adc7e 100644 --- a/UI.hpp +++ b/UI.hpp @@ -2908,7 +2908,7 @@ void UI_func_eeprom_reset(uint8_t param) encoderDir[ENC_R].reset(); // setup function - lcd.print("Firmware reset?"); + lcd.print("EEPROM reset?"); lcd.setCursor(0, 1); lcd.print("[NO ]"); } @@ -2965,12 +2965,12 @@ void UI_func_voice_select(uint8_t param) { encoderDir[ENC_R].reset(); - strip_extension(bank_names[instance_id][configuration.dexed[instance_id].bank], bank_name[instance_id]); + strip_extension(bank_names[instance_id][configuration.performance.bank[instance_id]], bank_name[instance_id]); - lcd.show(0, 0, 2, configuration.dexed[instance_id].bank); - lcd.show(1, 0, 2, configuration.dexed[instance_id].voice + 1); + lcd.show(0, 0, 2, configuration.performance.bank[instance_id]); + lcd.show(1, 0, 2, configuration.performance.voice[instance_id] + 1); lcd.show(0, 4, 10, bank_name[instance_id]); - lcd.show(1, 4, 10, voice_names[instance_id][configuration.dexed[instance_id].voice]); + lcd.show(1, 4, 10, voice_names[instance_id][configuration.performance.voice[instance_id]]); switch (menu_voice_select) { @@ -3000,38 +3000,38 @@ void UI_func_voice_select(uint8_t param) switch (menu_voice_select) { case MENU_VOICE_BANK: - bank_tmp = constrain(configuration.dexed[instance_id].bank - ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1); - configuration.dexed[instance_id].bank = bank_tmp; + bank_tmp = constrain(configuration.performance.bank[instance_id] - ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1); + configuration.performance.bank[instance_id] = bank_tmp; #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sd_voice(configuration.dexed[instance_id].bank, configuration.dexed[instance_id].voice, instance_id); - get_voice_names_from_bank(configuration.dexed[instance_id].bank, instance_id); + load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id); + get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif eeprom_write(); break; case MENU_VOICE_SOUND: - voice_tmp = configuration.dexed[instance_id].voice - ENCODER[ENC_R].speed(); - if (voice_tmp < 0 && configuration.dexed[instance_id].bank - 1 >= 0) + voice_tmp = configuration.performance.voice[instance_id] - ENCODER[ENC_R].speed(); + if (voice_tmp < 0 && configuration.performance.bank[instance_id] - 1 >= 0) { - configuration.dexed[instance_id].bank--; - configuration.dexed[instance_id].bank = constrain(configuration.dexed[instance_id].bank, 0, MAX_BANKS - 1); + configuration.performance.bank[instance_id]--; + configuration.performance.bank[instance_id] = constrain(configuration.performance.bank[instance_id], 0, MAX_BANKS - 1); } - else if (voice_tmp < 0 && configuration.dexed[instance_id].bank - 1 <= 0) + else if (voice_tmp < 0 && configuration.performance.bank[instance_id] - 1 <= 0) { voice_tmp = 0; } if (voice_tmp < 0) voice_tmp = MAX_VOICES + voice_tmp; - configuration.dexed[instance_id].voice = voice_tmp; + configuration.performance.voice[instance_id] = voice_tmp; #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sd_voice(configuration.dexed[instance_id].bank, configuration.dexed[instance_id].voice, instance_id); - get_voice_names_from_bank(configuration.dexed[instance_id].bank, instance_id); + load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id); + get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -3043,37 +3043,37 @@ void UI_func_voice_select(uint8_t param) switch (menu_voice_select) { case MENU_VOICE_BANK: - bank_tmp = constrain(configuration.dexed[instance_id].bank + ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1); - configuration.dexed[instance_id].bank = bank_tmp; + bank_tmp = constrain(configuration.performance.bank[instance_id] + ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1); + configuration.performance.bank[instance_id] = bank_tmp; #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sd_voice(configuration.dexed[instance_id].bank, configuration.dexed[instance_id].voice, instance_id); - get_voice_names_from_bank(configuration.dexed[instance_id].bank, instance_id); + load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id); + get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif eeprom_write(); break; case MENU_VOICE_SOUND: - voice_tmp = configuration.dexed[instance_id].voice + ENCODER[ENC_R].speed(); - if (voice_tmp >= MAX_VOICES && configuration.dexed[instance_id].bank + 1 < MAX_BANKS) + voice_tmp = configuration.performance.voice[instance_id] + ENCODER[ENC_R].speed(); + if (voice_tmp >= MAX_VOICES && configuration.performance.bank[instance_id] + 1 < MAX_BANKS) { voice_tmp %= MAX_VOICES; - configuration.dexed[instance_id].bank++; - configuration.dexed[instance_id].bank = constrain(configuration.dexed[instance_id].bank, 0, MAX_BANKS - 1); + configuration.performance.bank[instance_id]++; + configuration.performance.bank[instance_id] = constrain(configuration.performance.bank[instance_id], 0, MAX_BANKS - 1); } - else if (voice_tmp >= MAX_VOICES && configuration.dexed[instance_id].bank + 1 >= MAX_BANKS) + else if (voice_tmp >= MAX_VOICES && configuration.performance.bank[instance_id] + 1 >= MAX_BANKS) { voice_tmp = MAX_VOICES - 1; } - configuration.dexed[instance_id].voice = voice_tmp; + configuration.performance.voice[instance_id] = voice_tmp; #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sd_voice(configuration.dexed[instance_id].bank, configuration.dexed[instance_id].voice, instance_id); - get_voice_names_from_bank(configuration.dexed[instance_id].bank, instance_id); + load_sd_voice(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id); + get_voice_names_from_bank(configuration.performance.bank[instance_id], instance_id); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -3090,12 +3090,12 @@ void UI_func_voice_select(uint8_t param) menu_voice_select = MENU_VOICE_BANK; } - strip_extension(bank_names[instance_id][configuration.dexed[instance_id].bank], bank_name[instance_id]); + strip_extension(bank_names[instance_id][configuration.performance.bank[instance_id]], bank_name[instance_id]); - lcd.show(0, 0, 2, configuration.dexed[instance_id].bank); - lcd.show(1, 0, 2, configuration.dexed[instance_id].voice + 1); + lcd.show(0, 0, 2, configuration.performance.bank[instance_id]); + lcd.show(1, 0, 2, configuration.performance.voice[instance_id] + 1); lcd.show(0, 4, 10, bank_name[instance_id]); - lcd.show(1, 4, 10, voice_names[instance_id][configuration.dexed[instance_id].voice]); + lcd.show(1, 4, 10, voice_names[instance_id][configuration.performance.voice[instance_id]]); switch (menu_voice_select) { @@ -3317,7 +3317,7 @@ void UI_func_save_config(uint8_t param) LCDML.DISP_clear(); lcd.print(F("Save Cfg SD")); - save_sd_voiceconfig(configuration.dexed[instance_id].bank, configuration.dexed[instance_id].voice, instance_id); + save_sd_voiceconfig(configuration.performance.bank[instance_id], configuration.performance.voice[instance_id], instance_id); lcd.setCursor(0, 1); lcd.print(F("Done.")); diff --git a/config.h b/config.h index e075cf2..39b4d67 100644 --- a/config.h +++ b/config.h @@ -221,10 +221,14 @@ #define MAX_BANKS 100 #define MAX_VOICES 32 // voices per bank +#define MAX_FX 15 +#define MAX_PERFORMANCE 15 #define BANK_NAME_LEN 13 // FAT12 filenames (plus '\0') #define VOICE_NAME_LEN 11 // 10 (plus '\0') #define FILENAME_LEN BANK_NAME_LEN + VOICE_NAME_LEN #define VOICE_CONFIG_NAME "VCFG" +#define FX_CONFIG_NAME "FXCFG" +#define PERFORMANCE_CONFIG_NAME "PCFG" //************************************************************************************************* //* DO NO CHANGE ANYTHING BEYOND IF YOU DON'T KNOW WHAT YOU ARE DOING !!! @@ -239,7 +243,8 @@ enum { DEXED, CHORUS, DELAY, REVERB}; #define EEPROM_SYS_START_ADDRESS EEPROM_START_ADDRESS #define EEPROM_FX_START_ADDRESS EEPROM_START_ADDRESS + sizeof(configuration.sys) -#define EEPROM_DEXED_START_ADDRESS EEPROM_START_ADDRESS + sizeof(configuration.sys)+ sizeof(configuration.fx) +#define EEPROM_DEXED_START_ADDRESS EEPROM_START_ADDRESS + sizeof(configuration.sys) + sizeof(configuration.fx) +#define EEPROM_PERFORMANCE_START_ADDRESS EEPROM_START_ADDRESS + sizeof(configuration.sys) + sizeof(configuration.fx) + NUM_DEXED * sizeof(configuration.dexed) // MIDI #ifdef MIDI_DEVICE_USB @@ -543,8 +548,6 @@ typedef struct { uint8_t portamento_time; uint8_t op_enabled; uint8_t midi_channel; - uint8_t bank; - uint8_t voice; } dexed_t; typedef struct { @@ -561,17 +564,26 @@ typedef struct { uint8_t delay_level; } fx_t; +typedef struct { + uint32_t checksum; + uint8_t bank[NUM_DEXED]; + uint8_t voice[NUM_DEXED]; + uint8_t fx_number; +} performance_t; + typedef struct { uint32_t checksum; uint8_t instances; uint8_t vol; uint8_t mono; uint8_t soft_midi_thru; + uint8_t performance_number; } sys_t; typedef struct { sys_t sys; fx_t fx; + performance_t performance; dexed_t dexed[NUM_DEXED]; } config_t; diff --git a/dexed_sd.cpp b/dexed_sd.cpp index 514f462..3c89982 100644 --- a/dexed_sd.cpp +++ b/dexed_sd.cpp @@ -174,10 +174,13 @@ bool get_sd_voice(File sysex, uint8_t voice_number, uint8_t* data) } /****************************************************************************** - SD VOICE CONFIG + SD VOICECONFIG ******************************************************************************/ bool load_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id) { + v = constrain(v, 0, MAX_VOICES - 1); + b = constrain(b, 0, MAX_BANKS - 1); + if (sd_card > 0) { File sysex; @@ -195,15 +198,120 @@ bool load_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id) Serial.println(F("]... loading...")); #endif sysex = SD.open(filename); - if (!sysex) + if (sysex) { + get_sd_data(sysex, 0x42, (uint8_t*)&configuration.dexed[instance_id]); + configuration.dexed[instance_id].checksum = crc32((uint8_t*)&configuration.dexed[instance_id] + 4, sizeof(configuration.dexed[instance_id]) - 4); + return (true); + } #ifdef DEBUG + else + { Serial.print(F("E : Cannot open ")); Serial.print(filename); Serial.println(F(" on SD.")); + } +#endif + } + else + { +#ifdef DEBUG + Serial.print(F("No ")); + Serial.print(filename); + Serial.println(F(" available.")); +#endif + } + } + return (false); +} + +bool save_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id) +{ + v = constrain(v, 0, MAX_VOICES - 1); + b = constrain(b, 0, MAX_BANKS - 1); + + if (sd_card > 0) + { + File sysex; + char filename[FILENAME_LEN]; + + sprintf(filename, "/%d/%s%d.syx", b, VOICE_CONFIG_NAME, v); + +#ifdef DEBUG + Serial.print(F("Saving voice config ")); + Serial.print(b); + Serial.print(F("/")); + Serial.print(v); + Serial.print(F("[")); + Serial.print(instance_id); + Serial.print(F("]")); + Serial.print(F(" to ")); + Serial.println(filename); +#endif + + sysex = SD.open(filename, FILE_WRITE); + if (!sysex) + { +#ifdef DEBUG + Serial.print(F("E : Cannot open ")); + Serial.print(filename); + Serial.println(F(" on SD.")); +#endif + return (false); + } + + if (write_sd_data(sysex, 0x42, (uint8_t*)&configuration.dexed[instance_id], sizeof(configuration.dexed[instance_id]))) + { + sysex.close(); + return (true); + } +#ifdef DEBUG + else + Serial.println(F("E : Cannot save voice data")); +#endif + } + + return (false); +} + +/****************************************************************************** + SD FX + ******************************************************************************/ +bool load_sd_fx(uint8_t fx) +{ + fx = constrain(fx, 0, MAX_FX); + + if (sd_card > 0) + { + File sysex; + char filename[FILENAME_LEN]; + + sprintf(filename, "/%s%d.syx", FX_CONFIG_NAME, fx); + + // first check if file exists... + if (SD.exists(filename)) + { + // ... and if: load +#ifdef DEBUG + Serial.print(F("Found fx configuration [")); + Serial.print(filename); + Serial.println(F("]... loading...")); #endif - return (get_sd_voiceconfig(sysex, (uint8_t*)&configuration.dexed[instance_id], instance_id)); + sysex = SD.open(filename); + if (sysex) + { + get_sd_data(sysex, 0x43, (uint8_t*)&configuration.fx); + configuration.fx.checksum = crc32((uint8_t*)&configuration.fx + 4, sizeof(configuration.fx) - 4); + return (true); + } +#ifdef DEBUG + else + { + Serial.print(F("E : Cannot open ")); + Serial.print(filename); + Serial.println(F(" on SD.")); } +#endif } else { @@ -218,7 +326,146 @@ bool load_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id) return (false); } -bool get_sd_voiceconfig(File sysex, uint8_t* conf, uint8_t instance_id) +bool save_sd_fx(uint8_t fx) +{ + fx = constrain(fx, 0, MAX_FX); + + if (sd_card > 0) + { + File sysex; + char filename[FILENAME_LEN]; + + sprintf(filename, "/%s%d.syx", FX_CONFIG_NAME, fx); + +#ifdef DEBUG + Serial.print(F("Saving fx config ")); + Serial.print(fx); + Serial.print(F(" to ")); + Serial.println(filename); +#endif + + sysex = SD.open(filename, FILE_WRITE); + if (!sysex) + { +#ifdef DEBUG + Serial.print(F("E : Cannot open ")); + Serial.print(filename); + Serial.println(F(" on SD.")); +#endif + return (false); + } + + if (write_sd_data(sysex, 0x43, (uint8_t*)&configuration.fx, sizeof(configuration.fx))) + { + sysex.close(); + return (true); + } +#ifdef DEBUG + else + Serial.println(F("E : Cannot save fx data")); +#endif + } + + return (false); +} + +/****************************************************************************** + SD PERFORMANCE + ******************************************************************************/ +bool load_sd_performance(uint8_t p) +{ + p = constrain(p, 0, MAX_PERFORMANCE); + + if (sd_card > 0) + { + File sysex; + char filename[FILENAME_LEN]; + + sprintf(filename, "/%s%d.syx", PERFORMANCE_CONFIG_NAME, p); + + // first check if file exists... + if (SD.exists(filename)) + { + // ... and if: load +#ifdef DEBUG + Serial.print(F("Found performance configuration [")); + Serial.print(filename); + Serial.println(F("]... loading...")); +#endif + sysex = SD.open(filename); + if (sysex) + { + get_sd_data(sysex, 0x44, (uint8_t*)&configuration.performance); + configuration.performance.checksum = crc32((uint8_t*)&configuration.performance + 4, sizeof(configuration.performance) - 4); + return (true); + } +#ifdef DEBUG + else + { + Serial.print(F("E : Cannot open ")); + Serial.print(filename); + Serial.println(F(" on SD.")); + } +#endif + } + else + { +#ifdef DEBUG + Serial.print(F("No ")); + Serial.print(filename); + Serial.println(F(" available.")); +#endif + } + } + return (false); +} + +bool save_sd_performance(uint8_t p) +{ + p = constrain(p, 0, MAX_PERFORMANCE); + + if (sd_card > 0) + { + File sysex; + char filename[FILENAME_LEN]; + + sprintf(filename, "/%s%d.syx", PERFORMANCE_CONFIG_NAME, p); + +#ifdef DEBUG + Serial.print(F("Saving performance config ")); + Serial.print(p); + Serial.print(F(" to ")); + Serial.println(filename); +#endif + + sysex = SD.open(filename, FILE_WRITE); + if (!sysex) + { +#ifdef DEBUG + Serial.print(F("E : Cannot open ")); + Serial.print(filename); + Serial.println(F(" on SD.")); +#endif + return (false); + } + + if (write_sd_data(sysex, 0x44, (uint8_t*)&configuration.performance, sizeof(configuration.performance))) + { + sysex.close(); + return (true); + } +#ifdef DEBUG + else + Serial.println(F("E : Cannot save performance data")); +#endif + } + return (false); +} + +/****************************************************************************** + HELPER FUNCTIONS + ******************************************************************************/ +bool get_sd_data(File sysex, uint8_t format, uint8_t* conf) { uint16_t n; int32_t bulk_checksum_calc = 0; @@ -238,10 +485,10 @@ bool get_sd_voiceconfig(File sysex, uint8_t* conf, uint8_t instance_id) #endif return (false); } - if (sysex.read() != 0x42) // check for sysex type (66 = MicroDexed voice setup) + if (sysex.read() != format) // check for sysex type { #ifdef DEBUG - Serial.println(F("E : SysEx type not MicroDexed setup.")); + Serial.println(F("E : SysEx type not found.")); #endif return (false); } @@ -287,82 +534,28 @@ bool get_sd_voiceconfig(File sysex, uint8_t* conf, uint8_t instance_id) #ifdef DEBUG Serial.println(F("Voice config loaded.")); #endif - configuration.dexed[instance_id].checksum = crc32((uint8_t*)&configuration.dexed[instance_id] + 4, sizeof(configuration.dexed[instance_id]) - 4); return (true); } -bool save_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id) -{ - v = constrain(v, 0, MAX_VOICES - 1); - b = constrain(b, 0, MAX_BANKS - 1); - - if (sd_card > 0) - { - File sysex; - char filename[FILENAME_LEN]; - - sprintf(filename, "/%d/%s%d.syx", b, VOICE_CONFIG_NAME, v); - -#ifdef DEBUG - Serial.print(F("Saving config ")); - Serial.print(b); - Serial.print(F("/")); - Serial.print(v); - Serial.print(F("[")); - Serial.print(instance_id); - Serial.print(F("]")); - Serial.print(F(" to ")); - Serial.println(filename); -#endif - - sysex = SD.open(filename, FILE_WRITE); - if (!sysex) - { -#ifdef DEBUG - Serial.print(F("E : Cannot open ")); - Serial.print(filename); - Serial.println(F(" on SD.")); -#endif - return (false); - } - - if (write_sd_voiceconfig(sysex, (uint8_t*)&configuration.dexed[instance_id], sizeof(configuration.dexed[instance_id]))) - { - sysex.close(); - return (true); - } -#ifdef DEBUG - else - Serial.println(F("E : Cannot save voice data")); -#endif - } - - return (false); -} - -bool write_sd_voiceconfig(File sysex, uint8_t* data, uint16_t len) +bool write_sd_data(File sysex, uint8_t format, uint8_t* data, uint16_t len) { // write sysex start sysex.write(0xf0); // write sysex vendor is unofficial SYSEX-ID for MicroDexed sysex.write(0x67); - // write sysex format number (f=66 MicroDexed voice config) - sysex.write(0x42); + // write sysex format number + sysex.write(format); // write data - sysex.write(data, len - 2); // minus 2 because at the end of the struct are voice and ban number - not very interesting here... + sysex.write(data, len); // write checksum - sysex.write(calc_checksum(data, len - 2)); + sysex.write(calc_checksum(data, len)); // write sysex end sysex.write(0xf7); return (true); } -/****************************************************************************** - HELPER FUNCTIONS - ******************************************************************************/ - uint8_t calc_checksum(uint8_t* data, uint16_t len) { int32_t bulk_checksum_calc = 0; diff --git a/dexed_sd.h b/dexed_sd.h index e924876..5aee272 100644 --- a/dexed_sd.h +++ b/dexed_sd.h @@ -49,10 +49,16 @@ bool load_sd_voice(uint8_t b, uint8_t v, uint8_t instance_id); bool get_sd_voice(File sysex, uint8_t voice_number, uint8_t* data); bool load_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id); -bool get_sd_voiceconfig(File sysex, uint8_t* conf, uint8_t instance_id); bool save_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id); -bool write_sd_voiceconfig(File sysex, uint8_t* data, uint16_t len); +bool load_sd_fx(uint8_t fx); +bool save_sd_fx(uint8_t fx); + +bool load_sd_performance(uint8_t p); +bool save_sd_performance(uint8_t p); + +bool get_sd_data(File sysex, uint8_t format, uint8_t* conf); +bool write_sd_data(File sysex, uint8_t format, uint8_t* data, uint16_t len); uint8_t calc_checksum(uint8_t* data, uint16_t len); void strip_extension(char* s, char *target); bool get_voice_names_from_bank(uint8_t b, uint8_t i);