From 77a20654f427cb8b6707ced7f1ac35cbc0e075c4 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Tue, 29 Oct 2019 14:03:09 +0100 Subject: [PATCH] Adding possibility to use 2 Dexed engines (can be enabled with NUM_DEXED=2 but is currently not fully suported). Extending own sysex config for using 2 engines in future. --- MicroDexed.ino | 131 ++++++++-------- README.md | 2 +- UI.hpp | 212 ++++++++++++++------------ config.h | 30 ++-- doc/sysex-format_controller-setup.txt | 109 ++++++++----- 5 files changed, 268 insertions(+), 216 deletions(-) diff --git a/MicroDexed.ino b/MicroDexed.ino index 0791e2e..1b0cadf 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -155,10 +155,9 @@ elapsedMillis cpu_mem_millis; #endif //uint32_t overload = 0; uint32_t peak = 0; - -config_t configuration; - bool eeprom_update_flag = false; +config_t configuration; +uint8_t selected_dexed_instance = 0; // Allocate the delay lines for chorus short delayline[MOD_DELAY_SAMPLE_BUFFER]; @@ -284,13 +283,13 @@ void setup() // read all bank names max_loaded_banks = get_bank_names(); - strip_extension(bank_names[configuration.bank], bank_name); + strip_extension(bank_names[configuration.bank[0]], bank_name); // read all voice name for actual bank - get_voice_names_from_bank(configuration.bank); + get_voice_names_from_bank(configuration.bank[0]); #ifdef DEBUG Serial.print(F("Bank [")); - Serial.print(bank_names[configuration.bank]); + Serial.print(bank_names[configuration.bank[0]]); Serial.print(F("/")); Serial.print(bank_name); Serial.println(F("]")); @@ -307,7 +306,7 @@ void setup() #endif // load default SYSEX data - load_sysex(configuration.bank, configuration.voice); + load_sysex(configuration.bank[0], configuration.voice[0]); } #ifdef DISPLAY_LCD_SPI change_disp_sd(true); @@ -330,8 +329,8 @@ void setup() // INIT REVERB freeverbs1.roomsize(mapfloat(configuration.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 0.0, 1.0)); freeverbs1.damping(mapfloat(configuration.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0)); - master_mixer_r.gain(1, mapfloat(configuration.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)); - master_mixer_l.gain(1, mapfloat(configuration.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)); + master_mixer_r.gain(1, mapfloat(configuration.reverb_level[0], REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)); + master_mixer_l.gain(1, mapfloat(configuration.reverb_level[0], REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)); #endif // INIT DELAY @@ -340,8 +339,8 @@ void setup() //delay_fb_mixer.gain(0, 1.0 - (mapfloat(configuration.delay_feedback, DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 0.0, 1.0))); // original signal delay_fb_mixer.gain(0, 1.0); // original signal delay_fb_mixer.gain(1, mapfloat(configuration.delay_feedback, DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 0.0, 1.0)); // amount of feedback - master_mixer_r.gain(2, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); - master_mixer_l.gain(2, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); + master_mixer_r.gain(2, mapfloat(configuration.delay_level[0], DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); + master_mixer_l.gain(2, mapfloat(configuration.delay_level[0], DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); // INIT CHORUS switch (configuration.chorus_waveform) @@ -372,20 +371,20 @@ void setup() modchorus_inverter.gain(-1.0); // stereo mode else modchorus_inverter.gain(1.0); // mono mode - master_mixer_r.gain(3, mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); - master_mixer_l.gain(3, mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); + master_mixer_r.gain(3, mapfloat(configuration.chorus_level[0], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); + master_mixer_l.gain(3, mapfloat(configuration.chorus_level[0], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); for (uint8_t i = 0; i < NUM_DEXED; i++) { - soften_filter_res[i].init(configuration.filter_resonance); - soften_filter_cut[i].init(configuration.filter_cutoff); - MicroDexed[i]->fx.Gain = mapfloat(configuration.loudness, LOUDNESS_MIN, LOUDNESS_MAX, 0.0, 1.0); - MicroDexed[i]->fx.Reso = mapfloat(configuration.filter_resonance, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX, 0.0, 1.0); - MicroDexed[i]->fx.Cutoff = mapfloat(configuration.filter_cutoff, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX, 0.0, 1.0); + soften_filter_res[i].init(configuration.filter_resonance[i]); + soften_filter_cut[i].init(configuration.filter_cutoff[i]); + MicroDexed[i]->fx.Gain = mapfloat(configuration.loudness[i], LOUDNESS_MIN, LOUDNESS_MAX, 0.0, 1.0); + MicroDexed[i]->fx.Reso = mapfloat(configuration.filter_resonance[i], FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX, 0.0, 1.0); + MicroDexed[i]->fx.Cutoff = mapfloat(configuration.filter_cutoff[i], FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX, 0.0, 1.0); } // set initial volume and pan (read from EEPROM) - set_volume(configuration.vol, configuration.pan, configuration.mono); + set_volume(configuration.vol, configuration.pan[0], configuration.mono); soften_volume.init(configuration.vol); #if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC) @@ -396,9 +395,9 @@ void setup() #ifdef DEBUG Serial.print(F("Bank/Voice from EEPROM [")); - Serial.print(configuration.bank, DEC); + Serial.print(configuration.bank[0], DEC); Serial.print(F("/")); - Serial.print(configuration.voice, DEC); + Serial.print(configuration.voice[0], DEC); Serial.println(F("]")); show_patch(); #endif @@ -519,7 +518,7 @@ void loop() } if (soften_volume.running()) { - set_volume(soften_volume.value(), configuration.pan, configuration.mono); + set_volume(soften_volume.value(), configuration.pan[0], configuration.mono); #ifdef DEBUG Serial.print(F("Volume: ")); Serial.print(configuration.vol, DEC); @@ -580,7 +579,7 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) case 0: if (inValue < MAX_BANKS) { - configuration.bank = inValue; + configuration.bank[0] = inValue; } break; case 1: @@ -609,11 +608,11 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) soften_volume.update(configuration.vol, SOFTEN_VALUE_CHANGE_STEPS); break; case 10: // Pan - configuration.pan = map(inValue, 0, 0x7f, PANORAMA_MIN, PANORAMA_MAX); - set_volume(configuration.vol, configuration.pan, configuration.mono); + configuration.pan[0] = map(inValue, 0, 0x7f, PANORAMA_MIN, PANORAMA_MAX); + set_volume(configuration.vol, configuration.pan[0], configuration.mono); break; case 32: // BankSelect LSB - configuration.bank = inValue; + configuration.bank[0] = inValue; break; case 64: for (uint8_t i = 0; i < NUM_DEXED; i++) @@ -630,17 +629,17 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) } break; case 103: // CC 103: filter resonance - configuration.filter_resonance = map(inValue, 0, 0x7f, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX); + configuration.filter_resonance[0] = map(inValue, 0, 0x7f, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX); for (uint8_t i = 0; i < NUM_DEXED; i++) { - MicroDexed[i]->fx.Reso = configuration.filter_resonance / 100.0; + MicroDexed[i]->fx.Reso = configuration.filter_resonance[i] / 100.0; } break; case 104: // CC 104: filter cutoff - configuration.filter_cutoff = map(inValue, 0, 0x7f, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX); + configuration.filter_cutoff[0] = map(inValue, 0, 0x7f, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX); for (uint8_t i = 0; i < NUM_DEXED; i++) { - MicroDexed[i]->fx.Cutoff = configuration.filter_cutoff / 100.0; + MicroDexed[i]->fx.Cutoff = configuration.filter_cutoff[i] / 100.0; } break; case 105: // CC 105: delay time @@ -652,9 +651,9 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) delay_fb_mixer.gain(0, 1.0 - configuration.delay_feedback / 100.0); // original signalbreak; break; case 107: // CC 107: delay volume - configuration.delay_level = map(inValue, 0, 0x7f, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX); - master_mixer_r.gain(2, configuration.delay_level / 100.0); - master_mixer_l.gain(2, configuration.delay_level / 100.0); + configuration.delay_level[0] = map(inValue, 0, 0x7f, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX); + master_mixer_r.gain(2, configuration.delay_level[0] / 100.0); + master_mixer_l.gain(2, configuration.delay_level[0] / 100.0); break; case 120: for (uint8_t i = 0; i < NUM_DEXED; i++) @@ -714,7 +713,7 @@ void handleProgramChange(byte inChannel, byte inProgram) #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sysex(configuration.bank, inProgram); + load_sysex(configuration.bank[0], inProgram); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -978,17 +977,17 @@ void handleSystemReset(void) bool checkMidiChannel(byte inChannel) { // check for MIDI channel - if (configuration.midi_channel == MIDI_CHANNEL_OMNI) + if (configuration.midi_channel[0] == MIDI_CHANNEL_OMNI) { return (true); } - else if (inChannel != configuration.midi_channel) + else if (inChannel != configuration.midi_channel[0]) { #ifdef DEBUG Serial.print(F("Ignoring MIDI data on channel ")); Serial.print(inChannel); Serial.print(F("(listening on ")); - Serial.print(configuration.midi_channel); + Serial.print(configuration.midi_channel[0]); Serial.println(F(")")); #endif return (false); @@ -1003,11 +1002,11 @@ bool checkMidiChannel(byte inChannel) void set_volume(uint8_t v, int8_t p, uint8_t m) { configuration.vol = v; - configuration.pan = p; + configuration.pan[0] = p; configuration.mono = m; uint16_t tmp = v / 100.0 * 1023.0 + 0.5; - float tmp2 = mapfloat(configuration.pan, PANORAMA_MIN, PANORAMA_MAX, 0.0, 1.0); + float tmp2 = mapfloat(configuration.pan[0], PANORAMA_MIN, PANORAMA_MAX, 0.0, 1.0); float tmp3 = (float)(tmp * (tmp + 2)) / (float)(1 << 20); #ifdef DEBUG @@ -1038,19 +1037,19 @@ void set_volume(uint8_t v, int8_t p, uint8_t m) break; case 1: // mono both stereomono1.stereo(false); - configuration.pan = 0.5; + configuration.pan[0] = 0.5; modchorus_inverter.gain(1.0); // stereo mode break; case 2: // mono right volume_l.gain(0.0); stereomono1.stereo(false); - configuration.pan = 0.5; + configuration.pan[0] = 0.5; modchorus_inverter.gain(1.0); // stereo mode break; case 3: // mono left volume_r.gain(0.0); stereomono1.stereo(false); - configuration.pan = 0.5; + configuration.pan[0] = 0.5; modchorus_inverter.gain(1.0); // stereo mode break; } @@ -1087,27 +1086,27 @@ void initial_values_from_eeprom(void) Serial.print(F(" - mismatch -> initializing EEPROM!")); #endif configuration.checksum = 0xffff; - configuration.bank = SYSEXBANK_DEFAULT; - configuration.voice = SYSEXSOUND_DEFAULT; + configuration.bank[0] = SYSEXBANK_DEFAULT; + configuration.voice[0] = SYSEXSOUND_DEFAULT; configuration.vol = VOLUME_DEFAULT; - configuration.pan = PANORAMA_DEFAULT; + configuration.pan[0] = PANORAMA_DEFAULT; configuration.mono = MONO_DEFAULT; - configuration.midi_channel = DEFAULT_MIDI_CHANNEL; + configuration.midi_channel[0] = DEFAULT_MIDI_CHANNEL; configuration.reverb_roomsize = REVERB_ROOMSIZE_DEFAULT; configuration.reverb_damping = REVERB_DAMPING_DEFAULT; - configuration.reverb_level = REVERB_LEVEL_DEFAULT; + configuration.reverb_level[0] = REVERB_LEVEL_DEFAULT; configuration.chorus_frequency = CHORUS_FREQUENCY_DEFAULT; configuration.chorus_waveform = CHORUS_WAVEFORM_DEFAULT; configuration.chorus_depth = CHORUS_DEPTH_DEFAULT; - configuration.chorus_level = CHORUS_LEVEL_DEFAULT; + configuration.chorus_level[0] = CHORUS_LEVEL_DEFAULT; configuration.delay_time = DELAY_TIME_DEFAULT; configuration.delay_feedback = DELAY_FEEDBACK_DEFAULT; - configuration.delay_level = DELAY_LEVEL_DEFAULT; - configuration.filter_cutoff = FILTER_CUTOFF_DEFAULT; - configuration.filter_resonance = FILTER_RESONANCE_DEFAULT; - configuration.loudness = LOUDNESS_DEFAULT; - configuration.polyphony = POLYPHONY_DEFAULT; - configuration.engine = ENGINE_DEFAULT; + configuration.delay_level[0] = DELAY_LEVEL_DEFAULT; + configuration.filter_cutoff[0] = FILTER_CUTOFF_DEFAULT; + configuration.filter_resonance[0] = FILTER_RESONANCE_DEFAULT; + configuration.loudness[0] = LOUDNESS_DEFAULT; + configuration.polyphony[0] = POLYPHONY_DEFAULT; + configuration.engine[0] = ENGINE_DEFAULT; eeprom_update(); } else @@ -1199,27 +1198,27 @@ void show_configuration(void) Serial.println(); Serial.println(F("CONFIGURATION:")); Serial.print(F("Checksum 0x")); Serial.println(configuration.checksum, HEX); - Serial.print(F("Bank ")); Serial.println(configuration.bank, DEC); - Serial.print(F("Voice ")); Serial.println(configuration.voice, DEC); + Serial.print(F("Bank ")); Serial.println(configuration.bank[0], DEC); + Serial.print(F("Voice ")); Serial.println(configuration.voice[0], DEC); Serial.print(F("Volume ")); Serial.println(configuration.vol, DEC); - Serial.print(F("Panorama ")); Serial.println(configuration.pan, DEC); + Serial.print(F("Panorama ")); Serial.println(configuration.pan[0], DEC); Serial.print(F("Mono ")); Serial.println(configuration.mono, DEC); - Serial.print(F("MIDI-Channel ")); Serial.println(configuration.midi_channel, DEC); + Serial.print(F("MIDI-Channel ")); Serial.println(configuration.midi_channel[0], DEC); Serial.print(F("Reverb Roomsize ")); Serial.println(configuration.reverb_roomsize, DEC); Serial.print(F("Reverb Damping ")); Serial.println(configuration.reverb_damping, DEC); - Serial.print(F("Reverb Level ")); Serial.println(configuration.reverb_level, DEC); + Serial.print(F("Reverb Level ")); Serial.println(configuration.reverb_level[0], DEC); Serial.print(F("Chorus Frequency ")); Serial.println(configuration.chorus_frequency, DEC); Serial.print(F("Chorus Waveform ")); Serial.println(configuration.chorus_waveform, DEC); Serial.print(F("Chorus Depth ")); Serial.println(configuration.chorus_depth, DEC); - Serial.print(F("Chorus Level ")); Serial.println(configuration.chorus_level, DEC); + Serial.print(F("Chorus Level ")); Serial.println(configuration.chorus_level[0], DEC); Serial.print(F("Delay Time ")); Serial.println(configuration.delay_time, DEC); Serial.print(F("Delay Feedback ")); Serial.println(configuration.delay_feedback, DEC); - Serial.print(F("Delay Level ")); Serial.println(configuration.delay_level, DEC); - Serial.print(F("Filter Cutoff ")); Serial.println(configuration.filter_cutoff, DEC); - Serial.print(F("Filter Resonance ")); Serial.println(configuration.filter_resonance, DEC); - Serial.print(F("Loudness ")); Serial.println(configuration.loudness, DEC); - Serial.print(F("Polyphony ")); Serial.println(configuration.polyphony, DEC); - Serial.print(F("Engine ")); Serial.println(configuration.engine, DEC); + Serial.print(F("Delay Level ")); Serial.println(configuration.delay_level[0], DEC); + Serial.print(F("Filter Cutoff ")); Serial.println(configuration.filter_cutoff[0], DEC); + Serial.print(F("Filter Resonance ")); Serial.println(configuration.filter_resonance[0], DEC); + Serial.print(F("Loudness ")); Serial.println(configuration.loudness[0], DEC); + Serial.print(F("Polyphony ")); Serial.println(configuration.polyphony[0], DEC); + Serial.print(F("Engine ")); Serial.println(configuration.engine[0], DEC); Serial.println(); } diff --git a/README.md b/README.md index 0b4cca1..a424395 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # MicroDexed -## Dexed port for Teensy (3.5/3.6 with audio shield) +## Dexed port for Teensy (3.5/3.6/4.0 with audio shield and LCD or OLED display) This is a port of the original Dexed/msfa engine (see https://github.com/asb2m10/dexed and https://github.com/google/music-synthesizer-for-android) to be used on a Teensy-3.5 or Teensy-3.6. The current state is: work in progress... diff --git a/UI.hpp b/UI.hpp index 0a3d386..2c51118 100644 --- a/UI.hpp +++ b/UI.hpp @@ -75,6 +75,7 @@ extern AudioAmplifier volume_r; extern AudioAmplifier volume_l; extern AudioEffectStereoMono stereomono1; extern AudioSourceMicroDexed * MicroDexed[NUM_DEXED]; +extern uint8_t selected_dexed_instance; /*********************************************************************** GLOBAL @@ -422,14 +423,14 @@ void encoder_right_up(void) switch (menu_voice) { case MENU_VOICE_BANK: - if (configuration.bank < MAX_BANKS) + if (configuration.bank[0] < MAX_BANKS) { - configuration.bank++; + configuration.bank[0]++; #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sysex(configuration.bank, configuration.voice); - get_voice_names_from_bank(configuration.bank); + load_sysex(configuration.bank[0], configuration.voice[0]); + get_voice_names_from_bank(configuration.bank[0]); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -437,21 +438,21 @@ void encoder_right_up(void) } break; case MENU_VOICE_SOUND: - if (configuration.voice < MAX_VOICES - 1) - configuration.voice++; + if (configuration.voice[0] < MAX_VOICES - 1) + configuration.voice[0]++; else { - if (configuration.bank < MAX_BANKS) + if (configuration.bank[0] < MAX_BANKS) { - configuration.bank++; - configuration.voice = 0; + configuration.bank[0]++; + configuration.voice[0] = 0; } } #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sysex(configuration.bank, configuration.voice); - get_voice_names_from_bank(configuration.bank); + load_sysex(configuration.bank[0], configuration.voice[0]); + get_voice_names_from_bank(configuration.bank[0]); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -479,15 +480,15 @@ void encoder_right_down(void) switch (menu_voice) { case MENU_VOICE_BANK: - if (configuration.bank > 0) + if (configuration.bank[0] > 0) { - configuration.bank--; + configuration.bank[0]--; #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sysex(configuration.bank, configuration.voice); - get_voice_names_from_bank(configuration.bank); + load_sysex(configuration.bank[0], configuration.voice[0]); + get_voice_names_from_bank(configuration.bank[0]); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -495,21 +496,21 @@ void encoder_right_down(void) } break; case MENU_VOICE_SOUND: - if (configuration.voice > 0) - configuration.voice--; + if (configuration.voice[0] > 0) + configuration.voice[0]--; else { - if (configuration.bank > 0) + if (configuration.bank[0] > 0) { - configuration.bank--; - configuration.voice = 31; + configuration.bank[0]--; + configuration.voice[0] = 31; } } #ifdef DISPLAY_LCD_SPI change_disp_sd(false); #endif - load_sysex(configuration.bank, configuration.voice); - get_voice_names_from_bank(configuration.bank); + load_sysex(configuration.bank[0], configuration.voice[0]); + get_voice_names_from_bank(configuration.bank[0]); #ifdef DISPLAY_LCD_SPI change_disp_sd(true); #endif @@ -886,25 +887,25 @@ void UI_func_reverb_level(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.reverb_level < REVERB_LEVEL_MAX) + if (configuration.reverb_level[0] < REVERB_LEVEL_MAX) { - configuration.reverb_level++; + configuration.reverb_level[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.reverb_level > REVERB_LEVEL_MIN) + if (configuration.reverb_level[0] > REVERB_LEVEL_MIN) { - configuration.reverb_level--; + configuration.reverb_level[0]--; } } lcd.setCursor(0, 1); - lcd_display_int(configuration.reverb_level, 3, true, true, false); + lcd_display_int(configuration.reverb_level[0], 3, true, true, false); - master_mixer_r.gain(1, configuration.reverb_level / 100.0); - master_mixer_l.gain(1, configuration.reverb_level / 100.0); + master_mixer_r.gain(1, configuration.reverb_level[0] / 100.0); + master_mixer_l.gain(1, configuration.reverb_level[0] / 100.0); } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -1076,24 +1077,24 @@ void UI_func_chorus_level(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.chorus_level < CHORUS_LEVEL_MAX) + if (configuration.chorus_level[0] < CHORUS_LEVEL_MAX) { - configuration.chorus_level++; + configuration.chorus_level[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.chorus_level > CHORUS_LEVEL_MIN) + if (configuration.chorus_level[0] > CHORUS_LEVEL_MIN) { - configuration.chorus_level--; + configuration.chorus_level[0]--; } } lcd.setCursor(0, 1); - lcd_display_int(configuration.chorus_level, 3, true, true, false); + lcd_display_int(configuration.chorus_level[0], 3, true, true, false); - master_mixer_r.gain(3, configuration.chorus_level / 100.0); - master_mixer_l.gain(3, configuration.chorus_level / 100.0); + master_mixer_r.gain(3, configuration.chorus_level[0] / 100.0); + master_mixer_l.gain(3, configuration.chorus_level[0] / 100.0); } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -1208,24 +1209,24 @@ void UI_func_delay_level(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.delay_level < DELAY_LEVEL_MAX) + if (configuration.delay_level[0] < DELAY_LEVEL_MAX) { - configuration.delay_level++; + configuration.delay_level[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.delay_level > DELAY_LEVEL_MIN) + if (configuration.delay_level[0] > DELAY_LEVEL_MIN) { - configuration.delay_level--; + configuration.delay_level[0]--; } } lcd.setCursor(0, 1); - lcd_display_int(configuration.delay_level, 3, true, true, false); + lcd_display_int(configuration.delay_level[0], 3, true, true, false); - master_mixer_r.gain(2, configuration.delay_level / 100.0); - master_mixer_l.gain(2, configuration.delay_level / 100.0); + master_mixer_r.gain(2, configuration.delay_level[0] / 100.0); + master_mixer_l.gain(2, configuration.delay_level[0] / 100.0); } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -1252,25 +1253,25 @@ void UI_func_filter_cutoff(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.filter_cutoff < FILTER_CUTOFF_MAX) + if (configuration.filter_cutoff[0] < FILTER_CUTOFF_MAX) { - configuration.filter_cutoff++; + configuration.filter_cutoff[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.filter_cutoff > FILTER_CUTOFF_MIN) + if (configuration.filter_cutoff[0] > FILTER_CUTOFF_MIN) { - configuration.filter_cutoff--; + configuration.filter_cutoff[0]--; } } lcd.setCursor(0, 1); - lcd_display_int(configuration.filter_cutoff, 3, true, true, false); + lcd_display_int(configuration.filter_cutoff[0], 3, true, true, false); for (uint8_t i = 0; i < NUM_DEXED; i++) { - MicroDexed[i]->fx.Cutoff = configuration.filter_cutoff / 100.0; + MicroDexed[i]->fx.Cutoff = configuration.filter_cutoff[i] / 100.0; } } @@ -1298,25 +1299,25 @@ void UI_func_filter_resonance(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.filter_resonance < FILTER_RESONANCE_MAX) + if (configuration.filter_resonance[0] < FILTER_RESONANCE_MAX) { - configuration.filter_resonance++; + configuration.filter_resonance[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.filter_resonance > FILTER_RESONANCE_MIN) + if (configuration.filter_resonance[0] > FILTER_RESONANCE_MIN) { - configuration.filter_resonance--; + configuration.filter_resonance[0]--; } } lcd.setCursor(0, 1); - lcd_display_int(configuration.filter_resonance, 3, true, true, false); + lcd_display_int(configuration.filter_resonance[0], 3, true, true, false); for (uint8_t i = 0; i < NUM_DEXED; i++) { - MicroDexed[i]->fx.Reso = configuration.filter_resonance / 100.0; + MicroDexed[i]->fx.Reso = configuration.filter_resonance[i] / 100.0; } } @@ -1344,27 +1345,27 @@ void UI_func_midi_channel(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.midi_channel < MIDI_CHANNEL_MAX) + if (configuration.midi_channel[0] < MIDI_CHANNEL_MAX) { - configuration.midi_channel++; + configuration.midi_channel[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.midi_channel > MIDI_CHANNEL_MIN) + if (configuration.midi_channel[0] > MIDI_CHANNEL_MIN) { - configuration.midi_channel--; + configuration.midi_channel[0]--; } } lcd.setCursor(0, 1); - if (configuration.midi_channel == 0) + if (configuration.midi_channel[0] == 0) { lcd.print(F("[OMNI]")); } else { - lcd_display_int(configuration.midi_channel, 4, false, true, false); + lcd_display_int(configuration.midi_channel[0], 4, false, true, false); } } @@ -1392,25 +1393,25 @@ void UI_func_loudness(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.loudness < LOUDNESS_MAX) + if (configuration.loudness[0] < LOUDNESS_MAX) { - configuration.loudness++; + configuration.loudness[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.loudness > LOUDNESS_MIN) + if (configuration.loudness[0] > LOUDNESS_MIN) { - configuration.loudness--; + configuration.loudness[0]--; } } lcd.setCursor(0, 1); - lcd_display_int(configuration.loudness, 3, true, true, false); + lcd_display_int(configuration.loudness[0], 3, true, true, false); for (uint8_t i = 0; i < NUM_DEXED; i++) { - MicroDexed[i]->fx.Gain = configuration.loudness / 100.0; + MicroDexed[i]->fx.Gain = configuration.loudness[0] / 100.0; } } @@ -1443,25 +1444,25 @@ void UI_func_panorama(uint8_t param) } else if (LCDML.BT_checkDown() && configuration.mono == 0) { - if (configuration.pan < PANORAMA_MAX) + if (configuration.pan[0] < PANORAMA_MAX) { - configuration.pan++; + configuration.pan[0]++; } } else if (LCDML.BT_checkUp() && configuration.mono == 0) { - if (configuration.pan > PANORAMA_MIN) + if (configuration.pan[0] > PANORAMA_MIN) { - configuration.pan--; + configuration.pan[0]--; } } if (configuration.mono == 0) { lcd.setCursor(0, 1); - lcd_display_int(configuration.pan, 2, false, true, true); + lcd_display_int(configuration.pan[0], 2, false, true, true); - set_volume(configuration.vol, configuration.pan, configuration.mono); + set_volume(configuration.vol, configuration.pan[0], configuration.mono); } } @@ -1521,7 +1522,7 @@ void UI_func_stereo_mono(uint8_t param) stereomono1.stereo(false); break; } - set_volume(configuration.vol, configuration.pan, configuration.mono); + set_volume(configuration.vol, configuration.pan[0], configuration.mono); } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -1548,25 +1549,25 @@ void UI_func_polyphony(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.polyphony < POLYPHONY_MAX) + if (configuration.polyphony[0] < POLYPHONY_MAX) { - configuration.polyphony++; + configuration.polyphony[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.polyphony > POLYPHONY_MIN) + if (configuration.polyphony[0] > POLYPHONY_MIN) { - configuration.polyphony--; + configuration.polyphony[0]--; } } lcd.setCursor(0, 1); - lcd_display_int(configuration.polyphony, 2, false, true, false); + lcd_display_int(configuration.polyphony[0], 2, false, true, false); for (uint8_t i = 0; i < NUM_DEXED; i++) { - MicroDexed[i]->setMaxNotes(configuration.polyphony); + MicroDexed[i]->setMaxNotes(configuration.polyphony[0]); } } @@ -1594,21 +1595,21 @@ void UI_func_engine(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.engine < ENGINE_MAX) + if (configuration.engine[0] < ENGINE_MAX) { - configuration.engine++; + configuration.engine[0]++; } } else if (LCDML.BT_checkUp()) { - if (configuration.engine > ENGINE_MIN) + if (configuration.engine[0] > ENGINE_MIN) { - configuration.engine--; + configuration.engine[0]--; } } lcd.setCursor(0, 1); - switch (configuration.engine) + switch (configuration.engine[0]) { case 0: lcd.print(F("[MODERN]")); @@ -1623,7 +1624,7 @@ void UI_func_engine(uint8_t param) for (uint8_t i = 0; i < NUM_DEXED; i++) { - MicroDexed[i]->setEngineType(configuration.engine); + MicroDexed[i]->setEngineType(configuration.engine[0]); } } @@ -1669,32 +1670,53 @@ void UI_func_voice_selection(uint8_t param) menu_state = MENU_VOICE; - strip_extension(bank_names[configuration.bank], bank_name); + strip_extension(bank_names[configuration.bank[0]], bank_name); //LCDML.DISP_clear(); // display bank and voice number - lcd.show(0, 0, 2, configuration.bank); - lcd.show(1, 0, 2, configuration.voice + 1); + lcd.show(0, 0, 2, configuration.bank[0]); + lcd.show(1, 0, 2, configuration.voice[0] + 1); // display names lcd.show(0, 4, 10, bank_name); - lcd.show(1, 4, 10, voice_names[configuration.voice]); + lcd.show(1, 4, 10, voice_names[configuration.voice[0]]); + + // display selected Dexed instance + if (selected_dexed_instance == 1) + { +#if NUM_DEXED > 1 + lcd.show(0, 15, 1, "o"); +#else + lcd.show(0, 15, 1, " "); +#endif + lcd.show(1, 15, 1, "*"); + } + else + { + selected_dexed_instance = 0; + lcd.show(0, 15, 1, "*"); +#if NUM_DEXED > 1 + lcd.show(1, 15, 1, "o"); +#else + lcd.show(1, 15, 1, " "); +#endif + } // display selections switch (menu_voice) { case MENU_VOICE_BANK: lcd.show(0, 2, 2, " ["); - lcd.show(0, 14, 2, "] "); + lcd.show(0, 14, 1, "]"); lcd.show(1, 2, 2, " "); - lcd.show(1, 14, 2, " "); + lcd.show(1, 14, 1, " "); break; case MENU_VOICE_SOUND: lcd.show(0, 2, 2, " "); - lcd.show(0, 14, 2, " "); + lcd.show(0, 14, 1, " "); lcd.show(1, 2, 2, " ["); - lcd.show(1, 14, 2, "] "); + lcd.show(1, 14, 1, "]"); break; } for (int x = 2; x < LCD_rows; x++) { @@ -1723,7 +1745,7 @@ void UI_func_volume(uint8_t param) else lcd.print(F(" ")); } - set_volume(configuration.vol, configuration.pan, configuration.mono); + set_volume(configuration.vol, configuration.pan[0], configuration.mono); lcd.show(1, 0, 1, "["); lcd.show(1, 15, 1, "]"); } diff --git a/config.h b/config.h index c532539..fc1a92f 100644 --- a/config.h +++ b/config.h @@ -127,21 +127,21 @@ #define I2C_DISPLAY // [I2C] SCL: Pin 19, SDA: Pin 18 (https://www.pjrc.com/teensy/td_libs_Wire.html) //#define LCD_GFX 1 -#endif +#endif #ifdef OLED_SPI #define LCD_cols 16 #define LCD_rows 4 //enable U8X8 support #define U8X8_DISPLAY -//enable SPI CS switching +//enable SPI CS switching #define DISPLAY_LCD_SPI #define U8X8_DISPLAY_CLASS U8X8_SSD1322_NHD_256X64_4W_HW_SPI //#define U8X8_DISPLAY_CLASS U8X8_SSD1306_128X64_NONAME_HW_I2C #define U8X8_CS_PIN 9 #define U8X8_DC_PIN 15 #define U8X8_RESET_PIN 14 -#endif +#endif #define CONTROL_RATE_MS 50 #define BACK_FROM_VOLUME_MS 1000 @@ -343,27 +343,27 @@ // struct for holding the current configuration struct config_t { uint32_t checksum; - uint8_t bank; - uint8_t voice; + uint8_t bank[NUM_DEXED]; + uint8_t voice[NUM_DEXED]; uint8_t vol; - int8_t pan; + int8_t pan[NUM_DEXED]; uint8_t mono; - uint8_t midi_channel; + uint8_t midi_channel[NUM_DEXED]; uint8_t reverb_roomsize; uint8_t reverb_damping; - uint8_t reverb_level; + uint8_t reverb_level[NUM_DEXED]; uint8_t chorus_frequency; uint8_t chorus_waveform; uint8_t chorus_depth; - uint8_t chorus_level; + uint8_t chorus_level[NUM_DEXED]; uint8_t delay_time; uint8_t delay_feedback; - uint8_t delay_level; - uint8_t filter_cutoff; - uint8_t filter_resonance; - uint8_t loudness; - uint8_t polyphony; - uint8_t engine; + uint8_t delay_level[NUM_DEXED]; + uint8_t filter_cutoff[NUM_DEXED]; + uint8_t filter_resonance[NUM_DEXED]; + uint8_t loudness[NUM_DEXED]; + uint8_t polyphony[NUM_DEXED]; + uint8_t engine[NUM_DEXED]; }; inline float mapfloat(float val, float in_min, float in_max, float out_min, float out_max) diff --git a/doc/sysex-format_controller-setup.txt b/doc/sysex-format_controller-setup.txt index d396c0e..246a167 100644 --- a/doc/sysex-format_controller-setup.txt +++ b/doc/sysex-format_controller-setup.txt @@ -24,42 +24,73 @@ Data Structure: Single Controller-Set Dump Parameter Number Parameter Value Range --------- --------- ----------- - 0 MONO/POLY MODE CHANGE 0-1 O=POLY - 1 PITCH BEND RANGE 0-12 - 2 " " STEP 0-12 - 3 PORTAMENTO MODE 0-1 0=RETAIN 1=FOLLOW - 4 " GLISS 0-1 - 5 " TIME 0-99 - 6 MOD WHEEL RANGE 0-99 - 7 " " ASSIGN 0-7 b0: pitch, b1:amp, b2: EG bias - 8 FOOT CONTROL RANGE 0-99 - 9 " " ASSIGN 0-7 " -10 BREATH CONT RANGE 0-99 -11 " " ASSIGN 0-7 " -12 AFTERTOUCH RANGE 0-99 -13 " ASSIGN 0-7 " -14 OP1_ENABLE 0-1 -15 OP2_ENABLE 0-1 -16 OP3_ENABLE 0-1 -17 OP4_ENABLE 0-1 -18 OP5_ENABLE 0-1 -19 OP6_ENABLE 0-1 -20 MAX_NOTES 0-32 -21 LOUDNESS 0-100 -22 PANORAMA 0-40 (20 is middle) -23 STERO/MONO 0-3 (0=stereo, 1=mono, 2=mono-r, 3=mono-l) -24 REVERB-ROOMSIZE 0-100 -25 REVERB-DAMPING 0-100 -26 REVERB-LEVEL 0-100 -27 CHORUS-FREQUENCY 0-100 (multiplied by 1/10 Hz) -28 CHORUS-WAVEFORM 0-1 (0=triangle, 1=sine) -29 CHORUS-DEPTH 0-100 -30 CHORUS-LEVEL 0-100 -31 DELAY-TIME 0-60 (multiplied by 10ms) -32 DELAY-FEEDBACK 0-100 -33 DELAY-LEVEL 0-100 -34 FILTER-CUTOFF 0-100 -35 FILTER-RESONANCE 0-100 -26 MIDI-CHANNEL 0-16 (0=OMNI) -37 POLYPHONY 0-32 (depends on CPU and FX) -38 DEXED-ENGINE 0-2 (1=modern, 2=Mark1, 2=OPL) + 0 GLOBAL STERO/MONO 0-3 (0=stereo, 1=mono, 2=mono-r, 3=mono-l) + 1 GLOBAL REVERB-ROOMSIZE 0-100 + 2 GLOBAL REVERB-DAMPING 0-100 + 3 GLOBAL CHORUS-FREQUENCY 0-100 (multiplied by 1/10 Hz) + 4 GLOBAL CHORUS-WAVEFORM 0-1 (0=triangle, 1=sine) + 5 GLOBAL CHORUS-DEPTH 0-100 + 6 GLOBAL DELAY-TIME 0-60 (multiplied by 10ms) + 7 GLOBAL DELAY-FEEDBACK 0-100 + 8 DEXED 1 MONO/POLY MODE CHANGE 0-1 O=POLY + 9 DEXED 1 PITCH BEND RANGE 0-12 +10 DEXED 1 " " STEP 0-12 +11 DEXED 1 PORTAMENTO MODE 0-1 0=RETAIN 1=FOLLOW +12 DEXED 1 " GLISS 0-1 +13 DEXED 1 " TIME 0-99 +14 DEXED 1 MOD WHEEL RANGE 0-99 +15 DEXED 1 " " ASSIGN 0-7 b0: pitch, b1:amp, b2: EG bias +16 DEXED 1 FOOT CONTROL RANGE 0-99 +17 DEXED 1 " " ASSIGN 0-7 " +18 DEXED 1 BREATH CONT RANGE 0-99 +19 DEXED 1 " " ASSIGN 0-7 " +20 DEXED 1 AFTERTOUCH RANGE 0-99 +21 DEXED 1 " ASSIGN 0-7 " +22 DEXED 1 OP1_ENABLE 0-1 +23 DEXED 1 OP2_ENABLE 0-1 +24 DEXED 1 OP3_ENABLE 0-1 +25 DEXED 1 OP4_ENABLE 0-1 +26 DEXED 1 OP5_ENABLE 0-1 +27 DEXED 1 OP6_ENABLE 0-1 +28 DEXED 1 MAX_NOTES 0-32 +29 DEXED 1 LOUDNESS 0-100 +30 DEXED 1 PANORAMA 0-40 (20 is middle) +31 DEXED 1 REVERB-LEVEL 0-100 +32 DEXED 1 CHORUS-LEVEL 0-100 +33 DEXED 1 DELAY-LEVEL 0-100 +34 DEXED 1 FILTER-CUTOFF 0-100 +35 DEXED 1 FILTER-RESONANCE 0-100 +26 DEXED 1 MIDI-CHANNEL 0-16 (0=OMNI) +37 DEXED 1 POLYPHONY 0-32 (depends on CPU and FX) +38 DEXED 1 ENGINE 0-2 (1=modern, 2=Mark1, 2=OPL) +39 DEXED 2 MONO/POLY MODE CHANGE 0-1 O=POLY +40 DEXED 2 PITCH BEND RANGE 0-12 + 2 DEXED 2 " " STEP 0-12 + 3 DEXED 2 PORTAMENTO MODE 0-1 0=RETAIN 1=FOLLOW + 4 DEXED 2 " GLISS 0-1 + 5 DEXED 2 " TIME 0-99 + 6 DEXED 2 MOD WHEEL RANGE 0-99 + 7 DEXED 2 " " ASSIGN 0-7 b0: pitch, b1:amp, b2: EG bias + 8 DEXED 2 FOOT CONTROL RANGE 0-99 + 9 DEXED 2 " " ASSIGN 0-7 " +10 DEXED 2 BREATH CONT RANGE 0-99 +11 DEXED 2 " " ASSIGN 0-7 " +12 DEXED 2 AFTERTOUCH RANGE 0-99 +13 DEXED 2 " ASSIGN 0-7 " +14 DEXED 2 OP1_ENABLE 0-1 +15 DEXED 2 OP2_ENABLE 0-1 +16 DEXED 2 OP3_ENABLE 0-1 +17 DEXED 2 OP4_ENABLE 0-1 +18 DEXED 2 OP5_ENABLE 0-1 +19 DEXED 2 OP6_ENABLE 0-1 +20 DEXED 2 MAX_NOTES 0-32 +21 DEXED 2 LOUDNESS 0-100 +22 DEXED 2 PANORAMA 0-40 (20 is middle) +26 DEXED 2 REVERB-LEVEL 0-100 +30 DEXED 2 CHORUS-LEVEL 0-100 +33 DEXED 2 DELAY-LEVEL 0-100 +34 DEXED 2 FILTER-CUTOFF 0-100 +35 DEXED 2 FILTER-RESONANCE 0-100 +26 DEXED 2 MIDI-CHANNEL 0-16 (0=OMNI) +37 DEXED 2 POLYPHONY 0-32 (depends on CPU and FX) +38 DEXED 2 ENGINE 0-2 (1=modern, 2=Mark1, 2=OPL)