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. 16
      config.h
  4. 315
      dexed_sd.cpp
  5. 10
      dexed_sd.h

@ -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;
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();
}

@ -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."));

@ -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 !!!
@ -240,6 +244,7 @@ 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_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;

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

@ -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);

Loading…
Cancel
Save