Added performance structure.

Added functions for loading and saving fx and perfomance data in EEPROM and on SD.
pull/32/head
Holger Wirtz 5 years ago
parent cd8ca8944b
commit 862ed77428
  1. 102
      MicroDexed.ino
  2. 68
      UI.hpp
  3. 18
      config.h
  4. 321
      dexed_sd.cpp
  5. 10
      dexed_sd.h

@ -390,13 +390,13 @@ void setup()
{ {
// read all bank names // read all bank names
max_loaded_banks = get_bank_names(instance_id); 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 // 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 #ifdef DEBUG
Serial.print(F("Bank [")); 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(F("/"));
Serial.print(bank_name[instance_id]); Serial.print(bank_name[instance_id]);
Serial.println(F("]")); Serial.println(F("]"));
@ -413,7 +413,7 @@ void setup()
#endif #endif
// load default SYSEX data // 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.print(instance_id);
Serial.println(F(":")); Serial.println(F(":"));
Serial.print(F("Bank/Voice from EEPROM [")); 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(F("/"));
Serial.print(configuration.dexed[instance_id].voice, DEC); Serial.print(configuration.performance.voice[instance_id], DEC);
Serial.println(F("]")); Serial.println(F("]"));
Serial.print(F("Polyphony: ")); Serial.print(F("Polyphony: "));
Serial.println(configuration.dexed[instance_id].polyphony, DEC); Serial.println(configuration.dexed[instance_id].polyphony, DEC);
@ -708,7 +708,7 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
case 0: case 0:
if (inValue < MAX_BANKS - 1) if (inValue < MAX_BANKS - 1)
{ {
configuration.dexed[instance_id].bank = inValue; configuration.performance.bank[instance_id] = inValue;
eeprom_write(); eeprom_write();
} }
break; break;
@ -763,7 +763,7 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("BANK-SELECT CC")); Serial.println(F("BANK-SELECT CC"));
#endif #endif
configuration.dexed[instance_id].bank = inValue; configuration.performance.bank[instance_id] = inValue;
eeprom_write(); eeprom_write();
break; break;
case 64: case 64:
@ -871,7 +871,7 @@ void handleProgramChange(byte inChannel, byte inProgram)
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #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 #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
@ -1266,6 +1266,8 @@ void initial_values_from_eeprom(bool init)
eeprom_get_sys(); eeprom_get_sys();
eeprom_get_fx(); eeprom_get_fx();
eeprom_get_performance();
for (uint8_t i = 0; i < NUM_DEXED; i++) for (uint8_t i = 0; i < NUM_DEXED; i++)
eeprom_get_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++) 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].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.performance.bank[instance_id] = constrain(configuration.performance.bank[instance_id], 0, MAX_BANKS - 1);
configuration.dexed[instance_id].voice = constrain(configuration.dexed[instance_id].voice, 0, MAX_VOICES - 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].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].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); 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.instances = INSTANCES_DEFAULT;
configuration.sys.vol = VOLUME_DEFAULT; configuration.sys.vol = VOLUME_DEFAULT;
configuration.sys.mono = MONO_DEFAULT; configuration.sys.mono = MONO_DEFAULT;
configuration.sys.soft_midi_thru = SOFT_MIDI_THRU_DEFAULT;
configuration.fx.checksum = 0xffff; configuration.fx.checksum = 0xffff;
configuration.fx.reverb_roomsize = REVERB_ROOMSIZE_DEFAULT; configuration.fx.reverb_roomsize = REVERB_ROOMSIZE_DEFAULT;
configuration.fx.reverb_damping = REVERB_DAMPING_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_time = DELAY_TIME_DEFAULT / 10;
configuration.fx.delay_feedback = DELAY_FEEDBACK_DEFAULT; configuration.fx.delay_feedback = DELAY_FEEDBACK_DEFAULT;
configuration.fx.delay_level = DELAY_LEVEL_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++) for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{ {
configuration.dexed[instance_id].checksum = 0xffff; configuration.dexed[instance_id].checksum = 0xffff;
configuration.dexed[instance_id].midi_channel = DEFAULT_MIDI_CHANNEL; configuration.dexed[instance_id].midi_channel = DEFAULT_MIDI_CHANNEL;
configuration.dexed[instance_id].bank = SYSEXBANK_DEFAULT; configuration.performance.bank[instance_id] = SYSEXBANK_DEFAULT;
configuration.dexed[instance_id].voice = SYSEXSOUND_DEFAULT; configuration.performance.voice[instance_id] = SYSEXSOUND_DEFAULT;
configuration.dexed[instance_id].lowest_note = INSTANCE_LOWEST_NOTE_MIN; configuration.dexed[instance_id].lowest_note = INSTANCE_LOWEST_NOTE_MIN;
configuration.dexed[instance_id].highest_note = INSTANCE_HIGHEST_NOTE_MAX; configuration.dexed[instance_id].highest_note = INSTANCE_HIGHEST_NOTE_MAX;
configuration.dexed[instance_id].reverb_send = REVERB_SEND_DEFAULT; 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].pan = PANORAMA_DEFAULT;
configuration.dexed[instance_id].transpose = TRANSPOSE_DEFAULT; configuration.dexed[instance_id].transpose = TRANSPOSE_DEFAULT;
configuration.dexed[instance_id].tune = TUNE_DEFAULT; configuration.dexed[instance_id].tune = TUNE_DEFAULT;
if (instance_id == 0)
configuration.dexed[instance_id].polyphony = POLYPHONY_DEFAULT; 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].velocity_level = VELOCITY_LEVEL_DEFAULT;
configuration.dexed[instance_id].engine = ENGINE_DEFAULT; configuration.dexed[instance_id].engine = ENGINE_DEFAULT;
configuration.dexed[instance_id].monopoly = MONOPOLY_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_glissando = PORTAMENTO_GLISSANDO_DEFAULT;
configuration.dexed[instance_id].portamento_time = PORTAMENTO_TIME_DEFAULT; configuration.dexed[instance_id].portamento_time = PORTAMENTO_TIME_DEFAULT;
configuration.dexed[instance_id].op_enabled = OP_ENABLED_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(); MicroDexed[instance_id]->controllers.refresh();
} }
set_volume(configuration.sys.vol, configuration.sys.mono); set_volume(configuration.sys.vol, configuration.sys.mono);
eeprom_update_sys(); eeprom_update_sys();
eeprom_update_fx(); eeprom_update_fx();
eeprom_update_performance();
for (uint8_t i = 0; i < NUM_DEXED; i++) for (uint8_t i = 0; i < NUM_DEXED; i++)
eeprom_update_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); configuration.sys.checksum = crc32((byte*)&configuration.sys + 4, sizeof(configuration.sys) - 4);
EEPROM.put(EEPROM_SYS_START_ADDRESS, configuration.sys); EEPROM.put(EEPROM_SYS_START_ADDRESS, configuration.sys);
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("Updating EEPROM sys")); Serial.println(F("Updating EEPROM sys."));
show_configuration();
#endif #endif
} }
} }
@ -1501,7 +1517,6 @@ bool eeprom_get_sys(void)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("EEPROM sys loaded.")); Serial.print(F("EEPROM sys loaded."));
show_configuration();
#endif #endif
return (true); return (true);
} }
@ -1512,8 +1527,7 @@ void eeprom_update_fx(void)
configuration.fx.checksum = crc32((byte*)&configuration.fx + 4, sizeof(configuration.fx) - 4); configuration.fx.checksum = crc32((byte*)&configuration.fx + 4, sizeof(configuration.fx) - 4);
EEPROM.put(EEPROM_FX_START_ADDRESS, configuration.fx); EEPROM.put(EEPROM_FX_START_ADDRESS, configuration.fx);
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("Updating EEPROM fx")); Serial.println(F("Updating EEPROM fx."));
show_configuration();
#endif #endif
} }
@ -1533,7 +1547,6 @@ bool eeprom_get_fx(void)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("EEPROM fx loaded.")); Serial.print(F("EEPROM fx loaded."));
show_configuration();
#endif #endif
return (true); return (true);
} }
@ -1546,8 +1559,7 @@ void eeprom_update_dexed(uint8_t instance_id)
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Updating EEPROM dexed (instance ")); Serial.print(F("Updating EEPROM dexed (instance "));
Serial.print(instance_id); Serial.print(instance_id);
Serial.println(F(")")); Serial.println(F(")."));
show_configuration();
#endif #endif
} }
@ -1571,7 +1583,36 @@ bool eeprom_get_dexed(uint8_t instance_id)
Serial.print(F("EEPROM dexed (instance ")); Serial.print(F("EEPROM dexed (instance "));
Serial.print(instance_id); Serial.print(instance_id);
Serial.println(F(") loaded.")); 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 #endif
return (true); 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 Time ")); Serial.println(configuration.fx.delay_time, DEC);
Serial.print(F(" Delay Feedback ")); Serial.println(configuration.fx.delay_feedback, 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); Serial.print(F(" Delay Level ")); Serial.println(configuration.fx.delay_level, DEC);
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{ {
Serial.print(F("Dexed instance ")); Serial.print(F("Dexed instance "));
Serial.println(instance_id, DEC); Serial.println(instance_id, DEC);
Serial.print(F(" Checksum 0x")); Serial.println(configuration.dexed[instance_id].checksum, HEX); 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(" 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(" Bank ")); Serial.println(configuration.performance.bank[instance_id], DEC);
Serial.print(F(" Voice ")); Serial.println(configuration.dexed[instance_id].voice, 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(" 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(" 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); 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.print(F(" OP Enabled ")); Serial.println(configuration.dexed[instance_id].op_enabled, DEC);
Serial.flush(); 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.println();
Serial.flush(); Serial.flush();
} }

@ -2908,7 +2908,7 @@ void UI_func_eeprom_reset(uint8_t param)
encoderDir[ENC_R].reset(); encoderDir[ENC_R].reset();
// setup function // setup function
lcd.print("Firmware reset?"); lcd.print("EEPROM reset?");
lcd.setCursor(0, 1); lcd.setCursor(0, 1);
lcd.print("[NO ]"); lcd.print("[NO ]");
} }
@ -2965,12 +2965,12 @@ void UI_func_voice_select(uint8_t param)
{ {
encoderDir[ENC_R].reset(); 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(0, 0, 2, configuration.performance.bank[instance_id]);
lcd.show(1, 0, 2, configuration.dexed[instance_id].voice + 1); lcd.show(1, 0, 2, configuration.performance.voice[instance_id] + 1);
lcd.show(0, 4, 10, bank_name[instance_id]); 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) switch (menu_voice_select)
{ {
@ -3000,38 +3000,38 @@ void UI_func_voice_select(uint8_t param)
switch (menu_voice_select) switch (menu_voice_select)
{ {
case MENU_VOICE_BANK: case MENU_VOICE_BANK:
bank_tmp = constrain(configuration.dexed[instance_id].bank - ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1); bank_tmp = constrain(configuration.performance.bank[instance_id] - ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1);
configuration.dexed[instance_id].bank = bank_tmp; configuration.performance.bank[instance_id] = bank_tmp;
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #endif
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);
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 DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
eeprom_write(); eeprom_write();
break; break;
case MENU_VOICE_SOUND: case MENU_VOICE_SOUND:
voice_tmp = configuration.dexed[instance_id].voice - ENCODER[ENC_R].speed(); voice_tmp = configuration.performance.voice[instance_id] - ENCODER[ENC_R].speed();
if (voice_tmp < 0 && configuration.dexed[instance_id].bank - 1 >= 0) if (voice_tmp < 0 && configuration.performance.bank[instance_id] - 1 >= 0)
{ {
configuration.dexed[instance_id].bank--; configuration.performance.bank[instance_id]--;
configuration.dexed[instance_id].bank = constrain(configuration.dexed[instance_id].bank, 0, MAX_BANKS - 1); 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; voice_tmp = 0;
} }
if (voice_tmp < 0) if (voice_tmp < 0)
voice_tmp = MAX_VOICES + voice_tmp; voice_tmp = MAX_VOICES + voice_tmp;
configuration.dexed[instance_id].voice = voice_tmp; configuration.performance.voice[instance_id] = voice_tmp;
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #endif
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);
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 DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
@ -3043,37 +3043,37 @@ void UI_func_voice_select(uint8_t param)
switch (menu_voice_select) switch (menu_voice_select)
{ {
case MENU_VOICE_BANK: case MENU_VOICE_BANK:
bank_tmp = constrain(configuration.dexed[instance_id].bank + ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1); bank_tmp = constrain(configuration.performance.bank[instance_id] + ENCODER[ENC_R].speed(), 0, MAX_BANKS - 1);
configuration.dexed[instance_id].bank = bank_tmp; configuration.performance.bank[instance_id] = bank_tmp;
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #endif
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);
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 DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
eeprom_write(); eeprom_write();
break; break;
case MENU_VOICE_SOUND: case MENU_VOICE_SOUND:
voice_tmp = configuration.dexed[instance_id].voice + ENCODER[ENC_R].speed(); voice_tmp = configuration.performance.voice[instance_id] + ENCODER[ENC_R].speed();
if (voice_tmp >= MAX_VOICES && configuration.dexed[instance_id].bank + 1 < MAX_BANKS) if (voice_tmp >= MAX_VOICES && configuration.performance.bank[instance_id] + 1 < MAX_BANKS)
{ {
voice_tmp %= MAX_VOICES; voice_tmp %= MAX_VOICES;
configuration.dexed[instance_id].bank++; configuration.performance.bank[instance_id]++;
configuration.dexed[instance_id].bank = constrain(configuration.dexed[instance_id].bank, 0, MAX_BANKS - 1); 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; voice_tmp = MAX_VOICES - 1;
} }
configuration.dexed[instance_id].voice = voice_tmp; configuration.performance.voice[instance_id] = voice_tmp;
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(false); change_disp_sd(false);
#endif #endif
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);
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 DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
change_disp_sd(true); change_disp_sd(true);
#endif #endif
@ -3090,12 +3090,12 @@ void UI_func_voice_select(uint8_t param)
menu_voice_select = MENU_VOICE_BANK; 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(0, 0, 2, configuration.performance.bank[instance_id]);
lcd.show(1, 0, 2, configuration.dexed[instance_id].voice + 1); lcd.show(1, 0, 2, configuration.performance.voice[instance_id] + 1);
lcd.show(0, 4, 10, bank_name[instance_id]); 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) switch (menu_voice_select)
{ {
@ -3317,7 +3317,7 @@ void UI_func_save_config(uint8_t param)
LCDML.DISP_clear(); LCDML.DISP_clear();
lcd.print(F("Save Cfg SD")); 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.setCursor(0, 1);
lcd.print(F("Done.")); lcd.print(F("Done."));

@ -221,10 +221,14 @@
#define MAX_BANKS 100 #define MAX_BANKS 100
#define MAX_VOICES 32 // voices per bank #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 BANK_NAME_LEN 13 // FAT12 filenames (plus '\0')
#define VOICE_NAME_LEN 11 // 10 (plus '\0') #define VOICE_NAME_LEN 11 // 10 (plus '\0')
#define FILENAME_LEN BANK_NAME_LEN + VOICE_NAME_LEN #define FILENAME_LEN BANK_NAME_LEN + VOICE_NAME_LEN
#define VOICE_CONFIG_NAME "VCFG" #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 !!! //* 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_SYS_START_ADDRESS EEPROM_START_ADDRESS
#define EEPROM_FX_START_ADDRESS EEPROM_START_ADDRESS + sizeof(configuration.sys) #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 // MIDI
#ifdef MIDI_DEVICE_USB #ifdef MIDI_DEVICE_USB
@ -543,8 +548,6 @@ typedef struct {
uint8_t portamento_time; uint8_t portamento_time;
uint8_t op_enabled; uint8_t op_enabled;
uint8_t midi_channel; uint8_t midi_channel;
uint8_t bank;
uint8_t voice;
} dexed_t; } dexed_t;
typedef struct { typedef struct {
@ -561,17 +564,26 @@ typedef struct {
uint8_t delay_level; uint8_t delay_level;
} fx_t; } 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 { typedef struct {
uint32_t checksum; uint32_t checksum;
uint8_t instances; uint8_t instances;
uint8_t vol; uint8_t vol;
uint8_t mono; uint8_t mono;
uint8_t soft_midi_thru; uint8_t soft_midi_thru;
uint8_t performance_number;
} sys_t; } sys_t;
typedef struct { typedef struct {
sys_t sys; sys_t sys;
fx_t fx; fx_t fx;
performance_t performance;
dexed_t dexed[NUM_DEXED]; dexed_t dexed[NUM_DEXED];
} config_t; } config_t;

@ -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) 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) if (sd_card > 0)
{ {
File sysex; File sysex;
@ -195,15 +198,20 @@ bool load_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id)
Serial.println(F("]... loading...")); Serial.println(F("]... loading..."));
#endif #endif
sysex = SD.open(filename); 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 #ifdef DEBUG
else
{
Serial.print(F("E : Cannot open ")); Serial.print(F("E : Cannot open "));
Serial.print(filename); Serial.print(filename);
Serial.println(F(" on SD.")); Serial.println(F(" on SD."));
#endif
return (get_sd_voiceconfig(sysex, (uint8_t*)&configuration.dexed[instance_id], instance_id));
} }
#endif
} }
else else
{ {
@ -214,104 +222,218 @@ bool load_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id)
#endif #endif
} }
} }
return (false); return (false);
} }
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)
{ {
uint16_t n; v = constrain(v, 0, MAX_VOICES - 1);
int32_t bulk_checksum_calc = 0; b = constrain(b, 0, MAX_BANKS - 1);
int8_t bulk_checksum;
if (sysex.read() != 0xf0) // check sysex start-byte if (sd_card > 0)
{ {
File sysex;
char filename[FILENAME_LEN];
sprintf(filename, "/%d/%s%d.syx", b, VOICE_CONFIG_NAME, v);
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("E : SysEx start byte not found.")); 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 #endif
return (false);
} sysex = SD.open(filename, FILE_WRITE);
if (sysex.read() != 0x67) // check sysex vendor is unofficial SYSEX-ID for MicroDexed if (!sysex)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("E : SysEx vendor not unofficial SYSEX-ID for MicroDexed.")); Serial.print(F("E : Cannot open "));
Serial.print(filename);
Serial.println(F(" on SD."));
#endif #endif
return (false); return (false);
} }
if (sysex.read() != 0x42) // check for sysex type (66 = MicroDexed voice setup)
if (write_sd_data(sysex, 0x42, (uint8_t*)&configuration.dexed[instance_id], sizeof(configuration.dexed[instance_id])))
{ {
sysex.close();
return (true);
}
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("E : SysEx type not MicroDexed setup.")); else
Serial.println(F("E : Cannot save voice data"));
#endif #endif
}
return (false); 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
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);
} }
sysex.seek(sysex.size()); #ifdef DEBUG
if (sysex.read() != 0xf7) // check sysex end-byte else
{
Serial.print(F("E : Cannot open "));
Serial.print(filename);
Serial.println(F(" on SD."));
}
#endif
}
else
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("E : SysEx end byte not found.")); Serial.print(F("No "));
Serial.print(filename);
Serial.println(F(" available."));
#endif #endif
return (false); }
} }
sysex.seek(sysex.size() - 1); // Bulk checksum return (false);
bulk_checksum = sysex.read(); }
sysex.seek(3); // start of bulk data bool save_sd_fx(uint8_t fx)
for (n = 0; n < sysex.size() - 3; n++) {
fx = constrain(fx, 0, MAX_FX);
if (sd_card > 0)
{ {
uint8_t d = sysex.read(); File sysex;
bulk_checksum_calc -= d; char filename[FILENAME_LEN];
*conf++ = d;
} sprintf(filename, "/%s%d.syx", FX_CONFIG_NAME, fx);
bulk_checksum_calc &= 0x7f;
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Bulk checksum : 0x")); Serial.print(F("Saving fx config "));
Serial.print(bulk_checksum_calc, HEX); Serial.print(fx);
Serial.print(F(" [0x")); Serial.print(F(" to "));
Serial.print(bulk_checksum, HEX); Serial.println(filename);
Serial.println(F("]"));
#endif #endif
if (bulk_checksum_calc != bulk_checksum) sysex = SD.open(filename, FILE_WRITE);
if (!sysex)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("E : Bulk checksum mismatch : 0x")); Serial.print(F("E : Cannot open "));
Serial.print(bulk_checksum_calc, HEX); Serial.print(filename);
Serial.print(F(" != 0x")); Serial.println(F(" on SD."));
Serial.println(bulk_checksum, HEX);
#endif #endif
return (false); return (false);
} }
if (write_sd_data(sysex, 0x43, (uint8_t*)&configuration.fx, sizeof(configuration.fx)))
{
sysex.close();
return (true);
}
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("Voice config loaded.")); else
Serial.println(F("E : Cannot save fx data"));
#endif #endif
configuration.dexed[instance_id].checksum = crc32((uint8_t*)&configuration.dexed[instance_id] + 4, sizeof(configuration.dexed[instance_id]) - 4); }
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); 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) bool save_sd_performance(uint8_t p)
{ {
v = constrain(v, 0, MAX_VOICES - 1); p = constrain(p, 0, MAX_PERFORMANCE);
b = constrain(b, 0, MAX_BANKS - 1);
if (sd_card > 0) if (sd_card > 0)
{ {
File sysex; File sysex;
char filename[FILENAME_LEN]; char filename[FILENAME_LEN];
sprintf(filename, "/%d/%s%d.syx", b, VOICE_CONFIG_NAME, v); sprintf(filename, "/%s%d.syx", PERFORMANCE_CONFIG_NAME, p);
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Saving config ")); Serial.print(F("Saving performance config "));
Serial.print(b); Serial.print(p);
Serial.print(F("/"));
Serial.print(v);
Serial.print(F("["));
Serial.print(instance_id);
Serial.print(F("]"));
Serial.print(F(" to ")); Serial.print(F(" to "));
Serial.println(filename); Serial.println(filename);
#endif #endif
@ -327,42 +449,113 @@ bool save_sd_voiceconfig(uint8_t b, uint8_t v, uint8_t instance_id)
return (false); return (false);
} }
if (write_sd_voiceconfig(sysex, (uint8_t*)&configuration.dexed[instance_id], sizeof(configuration.dexed[instance_id]))) if (write_sd_data(sysex, 0x44, (uint8_t*)&configuration.performance, sizeof(configuration.performance)))
{ {
sysex.close(); sysex.close();
return (true); return (true);
} }
#ifdef DEBUG #ifdef DEBUG
else else
Serial.println(F("E : Cannot save voice data")); Serial.println(F("E : Cannot save performance data"));
#endif #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;
int8_t bulk_checksum;
if (sysex.read() != 0xf0) // check sysex start-byte
{
#ifdef DEBUG
Serial.println(F("E : SysEx start byte not found."));
#endif
return (false);
}
if (sysex.read() != 0x67) // check sysex vendor is unofficial SYSEX-ID for MicroDexed
{
#ifdef DEBUG
Serial.println(F("E : SysEx vendor not unofficial SYSEX-ID for MicroDexed."));
#endif
return (false);
}
if (sysex.read() != format) // check for sysex type
{
#ifdef DEBUG
Serial.println(F("E : SysEx type not found."));
#endif
return (false);
}
sysex.seek(sysex.size());
if (sysex.read() != 0xf7) // check sysex end-byte
{
#ifdef DEBUG
Serial.println(F("E : SysEx end byte not found."));
#endif
return (false);
}
sysex.seek(sysex.size() - 1); // Bulk checksum
bulk_checksum = sysex.read();
sysex.seek(3); // start of bulk data
for (n = 0; n < sysex.size() - 3; n++)
{
uint8_t d = sysex.read();
bulk_checksum_calc -= d;
*conf++ = d;
}
bulk_checksum_calc &= 0x7f;
#ifdef DEBUG
Serial.print(F("Bulk checksum : 0x"));
Serial.print(bulk_checksum_calc, HEX);
Serial.print(F(" [0x"));
Serial.print(bulk_checksum, HEX);
Serial.println(F("]"));
#endif
if (bulk_checksum_calc != bulk_checksum)
{
#ifdef DEBUG
Serial.print(F("E : Bulk checksum mismatch : 0x"));
Serial.print(bulk_checksum_calc, HEX);
Serial.print(F(" != 0x"));
Serial.println(bulk_checksum, HEX);
#endif
return (false); return (false);
}
#ifdef DEBUG
Serial.println(F("Voice config loaded."));
#endif
return (true);
} }
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 // write sysex start
sysex.write(0xf0); sysex.write(0xf0);
// write sysex vendor is unofficial SYSEX-ID for MicroDexed // write sysex vendor is unofficial SYSEX-ID for MicroDexed
sysex.write(0x67); sysex.write(0x67);
// write sysex format number (f=66 MicroDexed voice config) // write sysex format number
sysex.write(0x42); sysex.write(format);
// write data // 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 // write checksum
sysex.write(calc_checksum(data, len - 2)); sysex.write(calc_checksum(data, len));
// write sysex end // write sysex end
sysex.write(0xf7); sysex.write(0xf7);
return (true); return (true);
} }
/******************************************************************************
HELPER FUNCTIONS
******************************************************************************/
uint8_t calc_checksum(uint8_t* data, uint16_t len) uint8_t calc_checksum(uint8_t* data, uint16_t len)
{ {
int32_t bulk_checksum_calc = 0; int32_t bulk_checksum_calc = 0;

@ -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 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 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 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); uint8_t calc_checksum(uint8_t* data, uint16_t len);
void strip_extension(char* s, char *target); void strip_extension(char* s, char *target);
bool get_voice_names_from_bank(uint8_t b, uint8_t i); bool get_voice_names_from_bank(uint8_t b, uint8_t i);

Loading…
Cancel
Save