From 724f2908f0d940d4deb0f7ce4a7d8eaa45fd75db Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Wed, 8 Apr 2020 13:43:05 +0200 Subject: [PATCH] Several additions for storing configuration data. --- MicroDexed.ino | 3 +- UI.hpp | 320 +++++++++++++++++--- UI_1_FX.h | 98 +++--- config.h | 5 +- dexed.cpp | 83 +++-- dexed.h | 3 +- dexed_sysex.cpp | 138 ++++----- dexed_sysex.h | 10 +- doc/sysex-format_dexed-setup.txt | 6 - third-party/LCDMenuLib2/src/LCDMenuLib2.cpp | 14 - third-party/LCDMenuLib2/src/LCDMenuLib2.h | 2 - 11 files changed, 479 insertions(+), 203 deletions(-) diff --git a/MicroDexed.ino b/MicroDexed.ino index cfc11c2..889e622 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -676,7 +676,6 @@ void loop() show_cpu_and_mem_usage(); } #endif - //} } /****************************************************************************** @@ -1046,7 +1045,7 @@ void handleSystemExclusive(byte * sysex, uint len) #ifdef DEBUG else { - Serial.println(F("E: Unknown SysEx voce or function.")); + Serial.println(F("E: Unknown SysEx voice or function.")); } #endif } diff --git a/UI.hpp b/UI.hpp index 194b97d..85a75fa 100644 --- a/UI.hpp +++ b/UI.hpp @@ -202,12 +202,18 @@ void UI_func_OP6(uint8_t param); void UI_handle_OP(uint8_t param, uint8_t op, uint8_t instance_id); void UI_func_information(uint8_t param); void UI_func_volume(uint8_t param); -void UI_func_load(uint8_t param); -void UI_func_save(uint8_t param); +void UI_func_load_performance(uint8_t param); +void UI_func_save_performance(uint8_t param); +void UI_func_save_config(uint8_t param); void UI_func_midi_soft_thru(uint8_t param); void UI_func_velocity_level(uint8_t param); -void UI_func_firmware_reset(uint8_t param); +void UI_func_eeprom_reset(uint8_t param); void UI_func_voice_select(uint8_t param); +void UI_func_sysex_send_voice(uint8_t param); +void UI_func_sysex_receive_voice(uint8_t param); +void UI_func_save_voice(uint8_t param); +void UI_func_sysex_receive_bank(uint8_t param); +void UI_func_sysex_send_bank(uint8_t param); void UI_function_not_enabled(void); void UI_function_not_implemented(uint8_t param); void lcd_display_int(int16_t var, uint8_t size, bool zeros, bool brackets, bool sign); @@ -649,10 +655,12 @@ void lcdml_menu_control(void) Serial.println(F("ENC-L short")); #endif encoderDir[ENC_L].ButtonShort(true); - menu_init = false; - if (LCDML.MENU_getLastActivFunctionID() == 0xff && LCDML.MENU_getLastCursorPositionID() == 0) + if ((LCDML.MENU_getLastActivFunctionID() == 0xff && LCDML.MENU_getLastCursorPositionID() == 0) || menu_init == true) + { LCDML.MENU_goRoot(); + menu_init = false; + } else LCDML.BT_quit(); } @@ -2933,7 +2941,7 @@ void UI_func_velocity_level(uint8_t param) } } -void UI_func_firmware_reset(uint8_t param) +void UI_func_eeprom_reset(uint8_t param) { static bool yesno = false; @@ -2998,12 +3006,6 @@ void UI_func_voice_select(uint8_t param) { encoderDir[ENC_R].reset(); - if (menu_init == true) - { - LCDML.FUNC_setGBAToLastFunc(0xff); - LCDML.FUNC_setGBAToLastCursorPos(0); - } - strip_extension(bank_names[instance_id][configuration.dexed[instance_id].bank], bank_name[instance_id]); lcd.show(0, 0, 2, configuration.dexed[instance_id].bank); @@ -3202,14 +3204,16 @@ void UI_func_volume(uint8_t param) } } -void UI_func_load(uint8_t param) +void UI_func_load_performance(uint8_t param) { if (LCDML.FUNC_setup()) // ****** SETUP ********* { encoderDir[ENC_R].reset(); lcd.setCursor(0, 0); - lcd.print(F("Load setup")); + lcd.print(F("Load Perf. SD")); + lcd.setCursor(0, 1); + lcd.print(F("Not implemented.")); } if (LCDML.FUNC_loop()) // ****** LOOP ********* @@ -3218,24 +3222,213 @@ void UI_func_load(uint8_t param) { if (LCDML.BT_checkDown()) { - if (dexed_setup_number < 100) - { - dexed_setup_number++; - } + ; } else if (LCDML.BT_checkUp()) { - if (dexed_setup_number > 1) + ; + } + } + } + + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + eeprom_write(); + encoderDir[ENC_R].reset(); + } +} + +void UI_func_save_performance(uint8_t param) +{ + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + + lcd.setCursor(0, 0); + lcd.print(F("Save Perf. SD")); + lcd.setCursor(0, 1); + lcd.print(F("Not implemented.")); + } + + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())) + { + if (LCDML.BT_checkDown()) + { + ; + } + else if (LCDML.BT_checkUp()) + { + ; + } + } + } + + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + eeprom_write(); + encoderDir[ENC_R].reset(); + } +} + +void UI_func_save_config(uint8_t param) +{ +#if NUMDEXED > 1 + static int8_t instance_id; + static uint8_t chosen; +#else + uint8_t instance_id = 0; +#endif + static bool yesno; + + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + + lcd.setCursor(0, 0); + lcd.print(F("Save Config SD")); + +#if NUMDEXED > 1 + instance_id = -1; + chosen = 0; + lcd.setCursor(0, 1); + lcd.print(F("Instance [1]")); +#else + int8_t instance_id = 0; + lcd.setCursor(0, 1); + lcd.print(F("[NO ]")); +#endif + + yesno = false; + } + + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if ((LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()) || (LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())) + { +#if NUMDEXED > 1 + if ((LCDML.BT_checkDown() || LCDML.BT_checkUp()) && instance_id < 0) + { + chosen = (chosen + 1) % 2; + } + else if (LCDML.BT_checkEnter() && instance_id < 0) + { + instance_id = chosen; + lcd.setCursor(0, 1); + lcd.print(F("[NO ] ")); + } + else if ((LCDML.BT_checkDown() || LCDML.BT_checkUp()) && instance_id >= 0) +#else + if ((LCDML.BT_checkDown() || LCDML.BT_checkUp())) +#endif + { + yesno = !yesno; + } + +#if NUMDEXED > 1 + if (instance_id < 0) + { + lcd.setCursor(10, 1); + lcd.print(chosen + 1); + } + else + { +#endif + if (yesno == true) + { + lcd.setCursor(1, 1); + lcd.print(F("YES")); + } + else { - dexed_setup_number--; + lcd.setCursor(1, 1); + lcd.print(F("NO ")); } +#if NUMDEXED > 1 } +#endif + //encoderDir[ENC_R].reset(); + } + } + + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + if (yesno == true) + { + LCDML.DISP_clear(); + lcd.print(F("Storing config")); + + save_sysex_config(configuration.dexed[instance_id].bank, configuration.dexed[instance_id].voice, instance_id); + + lcd.setCursor(0, 1); + lcd.print(F("Done.")); + delay(500); + } + + encoderDir[ENC_R].reset(); + } +} + +void UI_func_sysex_send_voice(uint8_t param) +{ + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + + lcd.setCursor(0, 0); + lcd.print(F("Send Voice")); + lcd.setCursor(0, 1); + lcd.print(F("Not implemented.")); + } - //LOAD SYSEX FILE + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())) + { + if (LCDML.BT_checkDown()) + { + ; + } + else if (LCDML.BT_checkUp()) + { + ; + } } + } + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + eeprom_write(); + encoderDir[ENC_R].reset(); + } +} + +void UI_func_sysex_receive_voice(uint8_t param) +{ + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + + lcd.setCursor(0, 0); + lcd.print(F("Receive Voice")); lcd.setCursor(0, 1); - lcd_display_int(dexed_setup_number, 2, false, true, false); + lcd.print(F("Not implemented.")); + } + + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())) + { + if (LCDML.BT_checkDown()) + { + ; + } + else if (LCDML.BT_checkUp()) + { + ; + } + } } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -3245,14 +3438,16 @@ void UI_func_load(uint8_t param) } } -void UI_func_save(uint8_t param) +void UI_func_save_voice(uint8_t param) { if (LCDML.FUNC_setup()) // ****** SETUP ********* { encoderDir[ENC_R].reset(); lcd.setCursor(0, 0); - lcd.print(F("Save setup")); + lcd.print(F("Save Voice SD")); + lcd.setCursor(0, 1); + lcd.print(F("Not implemented.")); } if (LCDML.FUNC_loop()) // ****** LOOP ********* @@ -3261,24 +3456,81 @@ void UI_func_save(uint8_t param) { if (LCDML.BT_checkDown()) { - if (dexed_setup_number < 100) - { - dexed_setup_number++; - } + ; } else if (LCDML.BT_checkUp()) { - if (dexed_setup_number > 1) - { - dexed_setup_number--; - } + ; } + } + } - //SAVE SYSEX FILE + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + eeprom_write(); + encoderDir[ENC_R].reset(); + } +} + +void UI_func_sysex_receive_bank(uint8_t param) +{ + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + + lcd.setCursor(0, 0); + lcd.print(F("MIDI Recv Bank")); + lcd.setCursor(0, 1); + lcd.print(F("Not implemented.")); + } + + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())) + { + if (LCDML.BT_checkDown()) + { + ; + } + else if (LCDML.BT_checkUp()) + { + ; + } } + } + if (LCDML.FUNC_close()) // ****** STABLE END ********* + { + eeprom_write(); + encoderDir[ENC_R].reset(); + } +} + +void UI_func_sysex_send_bank(uint8_t param) +{ + if (LCDML.FUNC_setup()) // ****** SETUP ********* + { + encoderDir[ENC_R].reset(); + + lcd.setCursor(0, 0); + lcd.print(F("MIDI Send Bank")); lcd.setCursor(0, 1); - lcd_display_int(dexed_setup_number, 2, false, true, false); + lcd.print(F("Not implemented.")); + } + + if (LCDML.FUNC_loop()) // ****** LOOP ********* + { + if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())) + { + if (LCDML.BT_checkDown()) + { + ; + } + else if (LCDML.BT_checkUp()) + { + ; + } + } } if (LCDML.FUNC_close()) // ****** STABLE END ********* diff --git a/UI_1_FX.h b/UI_1_FX.h index 723c498..bb6887c 100644 --- a/UI_1_FX.h +++ b/UI_1_FX.h @@ -61,50 +61,56 @@ LCDML_add(32, LCDML_0_1, 4, "MIDI", NULL); LCDML_add(33, LCDML_0_1_4, 1, "MIDI Channel", UI_func_midi_channel); LCDML_add(34, LCDML_0_1_4, 2, "Lowest Note", UI_func_lowest_note); LCDML_add(35, LCDML_0_1_4, 3, "Highest Note", UI_func_highest_note); -LCDML_add(36, LCDML_0_1, 5, "Setup", NULL); -LCDML_add(37, LCDML_0_1_5, 1, "Portamento", NULL); -LCDML_add(38, LCDML_0_1_5_1, 1, "Port. Mode", UI_func_portamento_mode); -LCDML_add(39, LCDML_0_1_5_1, 2, "Port. Gliss", UI_func_portamento_glissando); -LCDML_add(40, LCDML_0_1_5_1, 3, "Port. Time", UI_func_portamento_time); -LCDML_add(41, LCDML_0_1_5, 2, "Polyphony", UI_func_polyphony); -LCDML_add(42, LCDML_0_1_5, 3, "Transpose", UI_func_transpose); -LCDML_add(43, LCDML_0_1_5, 4, "Fine Tune", UI_func_tune); -LCDML_add(44, LCDML_0_1_5, 5, "Mono/Poly", UI_func_mono_poly); -LCDML_add(45, LCDML_0_1, 6, "Internal", NULL); -LCDML_add(46, LCDML_0_1_6, 1, "Note Refresh", UI_func_note_refresh); -LCDML_add(47, LCDML_0_1_6, 2, "Velocity Lvl", UI_func_velocity_level); -LCDML_add(48, LCDML_0_1_6, 3, "Engine", UI_func_engine); -LCDML_add(49, LCDML_0_1, 7, "Operator", NULL); -LCDML_add(50, LCDML_0_1_7, 1, "OP1", UI_func_OP1); -LCDML_add(51, LCDML_0_1_7, 2, "OP2", UI_func_OP2); -LCDML_add(52, LCDML_0_1_7, 3, "OP3", UI_func_OP3); -LCDML_add(53, LCDML_0_1_7, 4, "OP4", UI_func_OP4); -LCDML_add(54, LCDML_0_1_7, 5, "OP5", UI_func_OP5); -LCDML_add(55, LCDML_0_1_7, 6, "OP6", UI_func_OP6); -LCDML_add(56, LCDML_0, 2, "Effect", NULL); -LCDML_add(57, LCDML_0_2, 1, "Chorus", NULL); -LCDML_add(58, LCDML_0_2_1, 1, "Frequency", UI_func_chorus_frequency); -LCDML_add(59, LCDML_0_2_1, 2, "Waveform", UI_func_chorus_waveform); -LCDML_add(60, LCDML_0_2_1, 3, "Depth", UI_func_chorus_depth); -LCDML_add(61, LCDML_0_2_1, 4, "Level", UI_func_chorus_level); -LCDML_add(62, LCDML_0_2, 2, "Delay", NULL); -LCDML_add(63, LCDML_0_2_2, 1, "Time", UI_func_delay_time); -LCDML_add(64, LCDML_0_2_2, 2, "Feedback", UI_func_delay_feedback); -LCDML_add(65, LCDML_0_2_2, 3, "Level", UI_func_delay_level); -LCDML_add(66, LCDML_0_2, 3, "Reverb", NULL); -LCDML_add(67, LCDML_0_2_3, 1, "Roomsize", UI_func_reverb_roomsize); -LCDML_add(68, LCDML_0_2_3, 2, "Damping", UI_func_reverb_damping); -LCDML_add(69, LCDML_0_2_3, 3, "Level", UI_func_reverb_level); -LCDML_add(70, LCDML_0, 3, "Load/Save", NULL); -LCDML_add(71, LCDML_0_3, 1, "Load", UI_func_load); -LCDML_add(72, LCDML_0_3, 2, "Save", UI_func_save); -LCDML_add(73, LCDML_0_3, 3, "Firmware Reset", UI_func_firmware_reset); -LCDML_add(74, LCDML_0, 4, "System", NULL); -LCDML_add(75, LCDML_0_4, 3, "Volume", UI_func_volume); -LCDML_add(76, LCDML_0_4, 1, "Stereo/Mono", UI_func_stereo_mono); -LCDML_add(77, LCDML_0_4, 2, "MIDI Soft THRU", UI_func_midi_soft_thru); -LCDML_add(78, LCDML_0, 6, "Info", UI_func_information); -#define _LCDML_DISP_cnt 78 -#define MENU_ID_OF_INSTANCE_2 56 -#define VOLUME_MENU_ID 75 +LCDML_add(36, LCDML_0_1_4, 4, "Send Voice", UI_func_sysex_send_voice); +LCDML_add(37, LCDML_0_1_4, 5, "Receive Voice", UI_func_sysex_receive_voice); +LCDML_add(38, LCDML_0_1, 5, "Setup", NULL); +LCDML_add(39, LCDML_0_1_5, 1, "Portamento", NULL); +LCDML_add(40, LCDML_0_1_5_1, 1, "Port. Mode", UI_func_portamento_mode); +LCDML_add(41, LCDML_0_1_5_1, 2, "Port. Gliss", UI_func_portamento_glissando); +LCDML_add(42, LCDML_0_1_5_1, 3, "Port. Time", UI_func_portamento_time); +LCDML_add(43, LCDML_0_1_5, 2, "Polyphony", UI_func_polyphony); +LCDML_add(44, LCDML_0_1_5, 3, "Transpose", UI_func_transpose); +LCDML_add(45, LCDML_0_1_5, 4, "Fine Tune", UI_func_tune); +LCDML_add(46, LCDML_0_1_5, 5, "Mono/Poly", UI_func_mono_poly); +LCDML_add(47, LCDML_0_1, 6, "Internal", NULL); +LCDML_add(48, LCDML_0_1_6, 1, "Note Refresh", UI_func_note_refresh); +LCDML_add(49, LCDML_0_1_6, 2, "Velocity Lvl", UI_func_velocity_level); +LCDML_add(50, LCDML_0_1_6, 3, "Engine", UI_func_engine); +LCDML_add(51, LCDML_0_1, 7, "Operator", NULL); +LCDML_add(52, LCDML_0_1_7, 1, "OP1", UI_func_OP1); +LCDML_add(53, LCDML_0_1_7, 2, "OP2", UI_func_OP2); +LCDML_add(54, LCDML_0_1_7, 3, "OP3", UI_func_OP3); +LCDML_add(55, LCDML_0_1_7, 4, "OP4", UI_func_OP4); +LCDML_add(56, LCDML_0_1_7, 5, "OP5", UI_func_OP5); +LCDML_add(57, LCDML_0_1_7, 6, "OP6", UI_func_OP6); +LCDML_add(58, LCDML_0, 2, "Effect", NULL); +LCDML_add(59, LCDML_0_2, 1, "Chorus", NULL); +LCDML_add(60, LCDML_0_2_1, 1, "Frequency", UI_func_chorus_frequency); +LCDML_add(61, LCDML_0_2_1, 2, "Waveform", UI_func_chorus_waveform); +LCDML_add(62, LCDML_0_2_1, 3, "Depth", UI_func_chorus_depth); +LCDML_add(63, LCDML_0_2_1, 4, "Level", UI_func_chorus_level); +LCDML_add(64, LCDML_0_2, 2, "Delay", NULL); +LCDML_add(65, LCDML_0_2_2, 1, "Time", UI_func_delay_time); +LCDML_add(66, LCDML_0_2_2, 2, "Feedback", UI_func_delay_feedback); +LCDML_add(67, LCDML_0_2_2, 3, "Level", UI_func_delay_level); +LCDML_add(68, LCDML_0_2, 3, "Reverb", NULL); +LCDML_add(69, LCDML_0_2_3, 1, "Roomsize", UI_func_reverb_roomsize); +LCDML_add(70, LCDML_0_2_3, 2, "Damping", UI_func_reverb_damping); +LCDML_add(71, LCDML_0_2_3, 3, "Level", UI_func_reverb_level); +LCDML_add(72, LCDML_0, 3, "Load/Save", NULL); +//LCDML_add(74, LCDML_0_3, 2, "Load Perf. SD", UI_func_load_performance); +//LCDML_add(74, LCDML_0_3, 2, "Save Perf. SD", UI_func_save_performance); +LCDML_add(73, LCDML_0_3, 1, "Save Config SD", UI_func_save_config); +LCDML_add(74, LCDML_0_3, 3, "Save Voice SD", UI_func_save_voice); +LCDML_add(75, LCDML_0_3, 4, "MIDI Recv Bank", UI_func_sysex_receive_bank); +LCDML_add(76, LCDML_0_3, 5, "MIDI Send Bank", UI_func_sysex_send_bank); +LCDML_add(77, LCDML_0_3, 6, "EEPROM Reset", UI_func_eeprom_reset); +LCDML_add(78, LCDML_0, 4, "System", NULL); +LCDML_add(79, LCDML_0_4, 3, "Volume", UI_func_volume); +LCDML_add(80, LCDML_0_4, 1, "Stereo/Mono", UI_func_stereo_mono); +LCDML_add(81, LCDML_0_4, 2, "MIDI Soft THRU", UI_func_midi_soft_thru); +LCDML_add(82, LCDML_0, 6, "Info", UI_func_information); +#define _LCDML_DISP_cnt 82 +#define MENU_ID_OF_INSTANCE_2 58 +#define VOLUME_MENU_ID 79 #endif diff --git a/config.h b/config.h index b9fea24..19654ca 100644 --- a/config.h +++ b/config.h @@ -223,6 +223,7 @@ #define MAX_VOICES 32 // voices per bank #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 //************************************************************************************************* //* DO NO CHANGE ANYTHING BEYOND IF YOU DON'T KNOW WHAT YOU ARE DOING !!! @@ -233,7 +234,7 @@ #define CPU_OVERLOAD_THROTTLE_TIMER 100 // timer (in ms) when next throttling is possible enum { DEXED, CHORUS, DELAY, REVERB}; -#define CONTROL_RATE_MS 30 +#define CONTROL_RATE_MS 100 // MIDI #ifdef MIDI_DEVICE_USB @@ -425,7 +426,7 @@ enum { DEXED, CHORUS, DELAY, REVERB}; #define MW_MODE_MIN 0 #define MW_MODE_MAX MIDI_CONTROLLER_MODE_MAX -#define MW_MODE_DEFAULT 1 +#define MW_MODE_DEFAULT 0 #define FC_RANGE_MIN 0 #define FC_RANGE_MAX 99 diff --git a/dexed.cpp b/dexed.cpp index aa8689d..f22c610 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -464,7 +464,7 @@ uint8_t Dexed::getNumNotesPlaying(void) return (count_playing_voices); } -bool Dexed::loadPackedVoiceParameters(uint8_t* new_data) +bool Dexed::decodeVoice(uint8_t* encoded_data) { uint8_t* p_data = data; uint8_t op; @@ -486,21 +486,21 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data) // DEXED_OP_LEV_SCL_BRK_PT, // 8 // DEXED_OP_SCL_LEFT_DEPTH, // 9 // DEXED_OP_SCL_RGHT_DEPTH, // 10 - memcpy(&data[op * 21], &new_data[op * 17], 11); - tmp = new_data[(op * 17) + 11]; - *(p_data + DEXED_OP_SCL_LEFT_CURVE + (op * 21)) = (tmp & 0x3); + memcpy(&data[op * 21], &encoded_data[op * 17], 11); + tmp = encoded_data[(op * 17) + 11]; + *(p_data + DEXED_OP_SCL_LEFT_CURVE + (op * 21)) = (tmp & 0x03); *(p_data + DEXED_OP_SCL_RGHT_CURVE + (op * 21)) = (tmp & 0x0c) >> 2; - tmp = new_data[(op * 17) + 12]; + tmp = encoded_data[(op * 17) + 12]; *(p_data + DEXED_OP_OSC_DETUNE + (op * 21)) = (tmp & 0x78) >> 3; *(p_data + DEXED_OP_OSC_RATE_SCALE + (op * 21)) = (tmp & 0x07); - tmp = new_data[(op * 17) + 13]; + tmp = encoded_data[(op * 17) + 13]; *(p_data + DEXED_OP_KEY_VEL_SENS + (op * 21)) = (tmp & 0x1c) >> 2; *(p_data + DEXED_OP_AMP_MOD_SENS + (op * 21)) = (tmp & 0x03); - *(p_data + DEXED_OP_OUTPUT_LEV + (op * 21)) = new_data[(op * 17) + 14]; - tmp = new_data[(op * 17) + 15]; + *(p_data + DEXED_OP_OUTPUT_LEV + (op * 21)) = encoded_data[(op * 17) + 14]; + tmp = encoded_data[(op * 17) + 15]; *(p_data + DEXED_OP_FREQ_COARSE + (op * 21)) = (tmp & 0x3e) >> 1; *(p_data + DEXED_OP_OSC_MODE + (op * 21)) = (tmp & 0x01); - *(p_data + DEXED_OP_FREQ_FINE + (op * 21)) = new_data[(op * 17) + 16]; + *(p_data + DEXED_OP_FREQ_FINE + (op * 21)) = encoded_data[(op * 17) + 16]; } // DEXED_PITCH_EG_R1, // 0 // DEXED_PITCH_EG_R2, // 1 @@ -510,29 +510,29 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data) // DEXED_PITCH_EG_L2, // 5 // DEXED_PITCH_EG_L3, // 6 // DEXED_PITCH_EG_L4, // 7 - memcpy(&data[DEXED_VOICE_OFFSET], &new_data[102], 8); - tmp = new_data[110]; + memcpy(&data[DEXED_VOICE_OFFSET], &encoded_data[102], 8); + tmp = encoded_data[110]; *(p_data + DEXED_VOICE_OFFSET + DEXED_ALGORITHM) = (tmp & 0x1f); - tmp = new_data[111]; + tmp = encoded_data[111]; *(p_data + DEXED_VOICE_OFFSET + DEXED_OSC_KEY_SYNC) = (tmp & 0x08) >> 3; *(p_data + DEXED_VOICE_OFFSET + DEXED_FEEDBACK) = (tmp & 0x07); // DEXED_LFO_SPEED, // 11 // DEXED_LFO_DELAY, // 12 // DEXED_LFO_PITCH_MOD_DEP, // 13 // DEXED_LFO_AMP_MOD_DEP, // 14 - memcpy(&data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], &new_data[112], 4); - tmp = new_data[116]; + memcpy(&data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], &encoded_data[112], 4); + tmp = encoded_data[116]; *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS) = (tmp & 0x30) >> 4; *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_WAVE) = (tmp & 0x0e) >> 1; *(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_SYNC) = (tmp & 0x01); - *(p_data + DEXED_VOICE_OFFSET + DEXED_TRANSPOSE) = new_data[117]; - memcpy(&data[DEXED_VOICE_OFFSET + DEXED_NAME], &new_data[118], 10); + *(p_data + DEXED_VOICE_OFFSET + DEXED_TRANSPOSE) = encoded_data[117]; + memcpy(&data[DEXED_VOICE_OFFSET + DEXED_NAME], &encoded_data[118], 10); panic(); doRefreshVoice(); //activate(); - strncpy(dexed_voice_name, (char *)&new_data[118], sizeof(dexed_voice_name) - 1); + strncpy(dexed_voice_name, (char *)&encoded_data[118], sizeof(dexed_voice_name) - 1); dexed_voice_name[10] = '\0'; #ifdef DEBUG Serial.print(F("Voice [")); @@ -543,6 +543,55 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data) return (true); } +bool Dexed::encodeVoice(uint8_t* encoded_data) +{ + uint8_t* p_data = data; + uint8_t op; + + for (op = 0; op < 6; op++) + { + // DEXED_OP_EG_R1, // 0 + // DEXED_OP_EG_R2, // 1 + // DEXED_OP_EG_R3, // 2 + // DEXED_OP_EG_R4, // 3 + // DEXED_OP_EG_L1, // 4 + // DEXED_OP_EG_L2, // 5 + // DEXED_OP_EG_L3, // 6 + // DEXED_OP_EG_L4, // 7 + // DEXED_OP_LEV_SCL_BRK_PT, // 8 + // DEXED_OP_SCL_LEFT_DEPTH, // 9 + // DEXED_OP_SCL_RGHT_DEPTH, // 10 + memcpy(&encoded_data[op * 17], &data[op * 21], 11); + encoded_data[(op * 17) + 11] = ((*(p_data + DEXED_OP_SCL_RGHT_CURVE + (op * 21)) & 0x0c) << 2) & (*(p_data + DEXED_OP_SCL_LEFT_CURVE + (op * 21)) & 0x03); + encoded_data[(op * 17) + 12] = ((*(p_data + DEXED_OP_OSC_DETUNE + (op * 21)) & 0x78) << 3) & (*(p_data + DEXED_OP_OSC_RATE_SCALE + (op * 21)) & 0x07); + encoded_data[(op * 17) + 13] = ((*(p_data + DEXED_OP_KEY_VEL_SENS + (op * 21)) & 0x1c) << 2) & (*(p_data + DEXED_OP_AMP_MOD_SENS + (op * 21)) & 0x03); + encoded_data[(op * 17) + 14] = *(p_data + DEXED_OP_OUTPUT_LEV + (op * 21)); + encoded_data[(op * 17) + 15] = ((*(p_data + DEXED_OP_FREQ_COARSE + (op * 21)) & 0x3e) << 1) & (*(p_data + DEXED_OP_OSC_MODE + (op * 21)) & 0x01); + encoded_data[(op * 17) + 16] = *(p_data + DEXED_OP_FREQ_FINE + (op * 21)); + } + // DEXED_PITCH_EG_R1, // 0 + // DEXED_PITCH_EG_R2, // 1 + // DEXED_PITCH_EG_R3, // 2 + // DEXED_PITCH_EG_R4, // 3 + // DEXED_PITCH_EG_L1, // 4 + // DEXED_PITCH_EG_L2, // 5 + // DEXED_PITCH_EG_L3, // 6 + // DEXED_PITCH_EG_L4, // 7 + memcpy(&encoded_data[102], &data[DEXED_VOICE_OFFSET], 8); + encoded_data[110] = (*(p_data + DEXED_VOICE_OFFSET + DEXED_ALGORITHM) & 0x1f); + encoded_data[111] = ((*(p_data + DEXED_VOICE_OFFSET + DEXED_OSC_KEY_SYNC) & 0x08) << 3) & (*(p_data + DEXED_VOICE_OFFSET + DEXED_FEEDBACK) & 0x07); + // DEXED_LFO_SPEED, // 11 + // DEXED_LFO_DELAY, // 12 + // DEXED_LFO_PITCH_MOD_DEP, // 13 + // DEXED_LFO_AMP_MOD_DEP, // 14 + memcpy(&encoded_data[112], &data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], 4); + encoded_data[116] = ((*(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS) & 0x30) << 4) & ((*(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_WAVE) & 0x0e) << 1) & (*(p_data + DEXED_VOICE_OFFSET + DEXED_LFO_SYNC) & 0x01); + encoded_data[117] = *(p_data + DEXED_VOICE_OFFSET + DEXED_TRANSPOSE); + memcpy(&encoded_data[118], &data[DEXED_VOICE_OFFSET + DEXED_NAME], 10); + + return (true); +} + bool Dexed::loadVoiceParameters(uint8_t* new_data) { char dexed_voice_name[11]; diff --git a/dexed.h b/dexed.h index c0ac588..c6ec2af 100644 --- a/dexed.h +++ b/dexed.h @@ -158,7 +158,8 @@ class Dexed uint8_t getMaxNotes(void); void doRefreshVoice(void); void setOPs(uint8_t ops); - bool loadPackedVoiceParameters(uint8_t* data); + bool decodeVoice(uint8_t* encoded_data); + bool encodeVoice(uint8_t* encoded_data); bool loadVoiceParameters(uint8_t* data); bool loadGlobalParameters(uint8_t* data); bool initGlobalParameters(void); diff --git a/dexed_sysex.cpp b/dexed_sysex.cpp index 0f46be4..9c49c73 100644 --- a/dexed_sysex.cpp +++ b/dexed_sysex.cpp @@ -33,15 +33,16 @@ extern AudioSourceMicroDexed * MicroDexed[NUM_DEXED]; extern void show_patch(uint8_t instance_id); -void create_sysex_filename(uint8_t b, char* sysex_file_name, uint8_t instance_id) -{ +/* + void create_sysex_filename(uint8_t b, char* sysex_file_name, uint8_t instance_id) + { // init and set name for actual bank memset(sysex_file_name, 0, 4 + VOICE_NAME_LEN); sysex_file_name[0] = '/'; itoa(b, &sysex_file_name[1], 10); strcat(sysex_file_name, "/"); strcat(sysex_file_name, bank_names[instance_id][b]); -#ifdef DEBUG + #ifdef DEBUG Serial.print(F("Created sysex_filename from bank ")); Serial.print(b, DEC); Serial.print(F(" and name ")); @@ -49,6 +50,23 @@ void create_sysex_filename(uint8_t b, char* sysex_file_name, uint8_t instance_id Serial.print(F(": [")); Serial.print(sysex_file_name); Serial.println(F("]")); + #endif + } +*/ + +void create_sysex_bankfilename(char* filename, uint8_t b, uint8_t instance_id) +{ + // init and set name for actual bank + memset(filename, 0, FILENAME_LEN); + sprintf(filename, "/%d/%s", b, bank_names[instance_id][b]); +#ifdef DEBUG + Serial.print(F("Created sysex_filename from bank ")); + Serial.print(b, DEC); + Serial.print(F(" and name ")); + Serial.print(bank_names[instance_id][b]); + Serial.print(F(": [")); + Serial.print(filename); + Serial.println(F("]")); #endif } @@ -79,10 +97,10 @@ bool get_voice_names_from_bank(uint8_t b, uint8_t instance_id) if (sd_card > 0) { - char sysex_file_name[4 + VOICE_NAME_LEN]; + char sysex_file_name[FILENAME_LEN]; // init and set name for actual bank - create_sysex_filename(b, sysex_file_name, instance_id); + create_sysex_bankfilename(sysex_file_name, b, instance_id); #ifdef DEBUG Serial.print(F("Reading voice names for bank [")); @@ -229,10 +247,10 @@ bool load_sysex(uint8_t b, uint8_t v, uint8_t instance_id) if (sd_card > 0) { File sysex; - char sysex_file_name[10 + VOICE_NAME_LEN]; + char sysex_file_name[FILENAME_LEN]; uint8_t data[128]; - create_sysex_filename(b, sysex_file_name, instance_id); + create_sysex_bankfilename(sysex_file_name, b, instance_id); sysex = SD.open(sysex_file_name); if (!sysex) @@ -254,7 +272,7 @@ bool load_sysex(uint8_t b, uint8_t v, uint8_t instance_id) Serial.print(voice_names[instance_id][v]); Serial.println(F("]")); #endif - bool ret = MicroDexed[instance_id]->loadPackedVoiceParameters(data); + bool ret = MicroDexed[instance_id]->decodeVoice(data); #ifdef DEBUG show_patch(instance_id); #endif @@ -356,27 +374,29 @@ bool get_sysex_voice(File sysex, uint8_t voice_number, uint8_t* data) return (true); } -void create_sysex_setup_filename(uint8_t b, uint8_t v, char* sysex_setup_file_name) +bool write_sysex_config(File sysex, config_t configuration) { - // init and set name for actual bank - memset(sysex_setup_file_name, 0, SYSEXFILENAME_LEN); - sysex_setup_file_name[0] = '/'; - itoa(b, &sysex_setup_file_name[1], 10); - strcat(sysex_setup_file_name, "/"); - itoa(v, &sysex_setup_file_name[3], 10); - strcat(sysex_setup_file_name, ".syx"); -#ifdef DEBUG - Serial.print(F("Created sysex_setup_file_name from bank ")); - Serial.print(b, DEC); - Serial.print(F(" and voice ")); - Serial.print(v, DEC); - Serial.print(F(": [")); - Serial.print(sysex_setup_file_name); - Serial.println(F("]")); -#endif + uint16_t n; + char* c = (char*)&configuration; + + // write sysex start + sysex.write(0xf0); + // write sysex vendor is unofficial SYSEX-ID for MicroDexed + sysex.write(0x67); + // write sysex format number (f=66..69; 1..4 MicroDexed setup(s)) + sysex.write(0x66); + + // write configuration data + for (n = 0; n < sizeof(configuration); n++) + sysex.write(c + n); + + // write sysex end + sysex.write(0xf7); + + return (true); } -bool get_sysex_setup(File sysex, config_t configuration) +bool read_sysex_config(File sysex, config_t configuration) { uint16_t n; int32_t bulk_checksum_calc = 0; @@ -473,41 +493,43 @@ bool get_sysex_setup(File sysex, config_t configuration) return (true); } -bool load_sysex_setup(uint8_t b, uint8_t v, uint8_t instance_id) +bool save_sysex_config(uint8_t b, uint8_t v, uint8_t instance_id) { -#if DEBUG - bool found = false; -#endif v = constrain(v, 0, MAX_VOICES - 1); b = constrain(b, 0, MAX_BANKS - 1); if (sd_card > 0) { File sysex; - char sysex_setup_file_name[SYSEXFILENAME_LEN]; + char sysex_config_filename[FILENAME_LEN]; - create_sysex_setup_filename(b, v, sysex_setup_file_name); + sprintf(sysex_config_filename, "/%d/config%d.syx", b, v); - sysex = SD.open(sysex_setup_file_name); +#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(sysex_config_filename); +#endif + + sysex = SD.open(sysex_config_filename, FILE_WRITE); if (!sysex) { #ifdef DEBUG Serial.print(F("E : Cannot open ")); - Serial.print(sysex_setup_file_name); - Serial.println(F("from SD.")); + Serial.print(sysex_config_filename); + Serial.println(F(" on SD.")); #endif return (false); } - if (get_sysex_setup(sysex, configuration)) + if (write_sysex_config(sysex, configuration)) { -#ifdef DEBUG - Serial.print(F("Loading sysex setup ")); - Serial.print(sysex_setup_file_name); - Serial.print(F(" [")); - Serial.print(voice_names[instance_id][v]); - Serial.println(F("]")); -#endif return (true); } #ifdef DEBUG @@ -515,36 +537,6 @@ bool load_sysex_setup(uint8_t b, uint8_t v, uint8_t instance_id) Serial.println(F("E : Cannot load setup data")); #endif } -#ifdef DEBUG - if (found == false) - Serial.println(F("E : File not found.")); -#endif - - return (false); -} - -bool save_sysex_setup(uint8_t b, uint8_t v, config_t configuration) -{ - const char* sysex_filename = "config.syx"; - - if (sd_card > 0) - { - File sysex; - char sysex_file_name[20]; - - create_sysex_filename(b, sysex_file_name, v); - - sysex = SD.open(sysex_file_name); - if (!sysex) - { -#ifdef DEBUG - Serial.print(F("E : Cannot create ")); - Serial.print(sysex_file_name); - Serial.println(F("on SD.")); -#endif - return (false); - } - } return (false); } diff --git a/dexed_sysex.h b/dexed_sysex.h index 7d97fdf..3622906 100644 --- a/dexed_sysex.h +++ b/dexed_sysex.h @@ -29,8 +29,6 @@ #ifndef DEXED_SYSEX_H_INCLUDED #define DEXED_SYSEX_H_INCLUDED -#define SYSEXFILENAME_LEN 10 - extern uint8_t sd_card; extern Dexed* dexed; extern AudioSourceMicroDexed * MicroDexed[NUM_DEXED]; @@ -46,7 +44,7 @@ extern uint8_t ui_main_state; extern config_t configuration; extern uint32_t crc32(byte * calc_start, uint16_t calc_bytes); -void create_sysex_filename(uint8_t b, char* sysex_file_name); +void create_sysex_bankfilename(char* filename, uint8_t b, uint8_t instance_id); void strip_extension(char* s, char *target); bool get_voice_names_from_bank(uint8_t b, uint8_t i); uint8_t get_bank_names(uint8_t instance_id); @@ -54,8 +52,8 @@ bool get_bank_voice_name(uint8_t b, uint8_t v); bool load_sysex(uint8_t b, uint8_t v, uint8_t instance_id); bool get_sysex_voice(File sysex, uint8_t voice_number, uint8_t* data); void create_sysex_setup_filename(uint8_t b, uint8_t v, char* sysex_setup_file_name); -bool get_sysex_setup(File sysex, uint8_t voice_number, uint8_t* data); -bool load_sysex_setup(uint8_t b, uint8_t v, uint8_t instance_id); -bool save_sysex_setup(uint8_t b, uint8_t v, config_t configuration); +bool write_sysex_config(File sysex, config_t configuration); +bool load_sysex_config(uint8_t b, uint8_t v, uint8_t instance_id); +bool save_sysex_config(uint8_t b, uint8_t v, uint8_t instance_id); #endif diff --git a/doc/sysex-format_dexed-setup.txt b/doc/sysex-format_dexed-setup.txt index 582dc0f..5b6940d 100644 --- a/doc/sysex-format_dexed-setup.txt +++ b/doc/sysex-format_dexed-setup.txt @@ -6,13 +6,7 @@ SYSEX Message Controller-Set 11110000 F0 Status byte - start sysex 0iiiiiii 67 ID # (i=103; unofficial SYSEX-ID for MicroDexed) - 0sssnnnn 00 Sub-status (s=0) & channel number (n=0; ch 1) 0fffffff ** format number (f=66..69; 1..4 MicroDexed setup(s)) - 0bbbbbbb ** byte count MS byte - 0bbbbbbb ** byte count LS byte (b=44; 1 instance - b=75; 2 instances - b=106; 3 instances - b=137; 4 instances) 0ddddddd ** data byte 1 setup config | | | diff --git a/third-party/LCDMenuLib2/src/LCDMenuLib2.cpp b/third-party/LCDMenuLib2/src/LCDMenuLib2.cpp index 7055a37..a979ea7 100644 --- a/third-party/LCDMenuLib2/src/LCDMenuLib2.cpp +++ b/third-party/LCDMenuLib2/src/LCDMenuLib2.cpp @@ -1928,13 +1928,6 @@ void LCDMenuLib2::FUNC_disableScreensaver(void) bitSet(REG_special, _LCDML_REG_special_disable_screensaver); } -/* ******************************************************************** */ -void LCDMenuLib2::FUNC_setGBAToLastCursorPos(uint8_t p) -/* ******************************************************************** */ -{ - actMenu_lastCursorPositionID=p; -} - /* ******************************************************************** */ void LCDMenuLib2::FUNC_setGBAToLastCursorPos(void) /* ******************************************************************** */ @@ -1949,13 +1942,6 @@ void LCDMenuLib2::FUNC_setGBAToLastCursorPos(void) bitSet(REG_MenuFunction, _LCDML_REG_MenuFunction_setCursorToID); } -/* ******************************************************************** */ -void LCDMenuLib2::FUNC_setGBAToLastFunc(uint8_t p) -/* ******************************************************************** */ -{ - actMenu_lastFuncID=p; -} - /* ******************************************************************** */ void LCDMenuLib2::FUNC_setGBAToLastFunc(void) /* ******************************************************************** */ diff --git a/third-party/LCDMenuLib2/src/LCDMenuLib2.h b/third-party/LCDMenuLib2/src/LCDMenuLib2.h index e306572..bccdad9 100644 --- a/third-party/LCDMenuLib2/src/LCDMenuLib2.h +++ b/third-party/LCDMenuLib2/src/LCDMenuLib2.h @@ -368,9 +368,7 @@ void FUNC_setLoopInterval(unsigned long p_t); // set a loop intervall for the current menu function the default loop intervall is 100000000 ms void FUNC_disableScreensaver(void); // disable the screensaver for the current menu function void FUNC_setGBAToLastCursorPos(void); // set a special "go back handling" - void FUNC_setGBAToLastCursorPos(uint8_t p); // set a special "go back handling" void FUNC_setGBAToLastFunc(void); // set a special "go back handling" - void FUNC_setGBAToLastFunc(uint8_t p); // set a special "go back handling" void FUNC_setGBA(void); // set a special "go back handling" which decide between the two function above // timer methods