MicroDexed is a compatible 6-operator-FM-synth based on the Teensy(-3.6/-4.x) Microcontroller. https://www.parasitstudio.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5847 lines
195 KiB

/*
MicroDexed
MicroDexed is a port of the Dexed sound engine
(https://github.com/asb2m10/dexed) for the Teensy-3.5/3.6/4.x with audio shield.
Dexed ist heavily based on https://github.com/google/music-synthesizer-for-android
(c)2018-2021 H. Wirtz <wirtz@parasitstudio.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef ENABLE_LCD_UI
#ifndef _UI_HPP_
#define _UI_HPP_
#endif
#include "config.h"
#include "disp_plus.h"
#include "effect_modulated_delay.h"
#include "effect_stereo_mono.h"
#ifdef USE_PLATEREVERB
#include "effect_platervbstereo.h"
#else
#include "effect_freeverbf.h"
#endif
#include "dexed.h"
#include <LCDMenuLib2.h>
//#include <Encoder.h>
#include <MD_REncoder.h>
#define _LCDML_DISP_cols LCD_cols
#define _LCDML_DISP_rows LCD_rows
#ifdef I2C_DISPLAY
#define _LCDML_DISP_cfg_cursor 0x7E // cursor Symbol
#else
#define _LCDML_DISP_cfg_cursor 0x8d // cursor Symbol
#endif
#define _LCDML_DISP_cfg_scrollbar 1 // enable a scrollbar
extern config_t configuration;
extern void set_volume(uint8_t v, uint8_t m);
extern bool load_sysex(uint8_t b, uint8_t v);
extern void generate_version_string(char* buffer, uint8_t len);
extern void initial_values_from_eeprom(bool init);
extern void _softRestart(void);
extern void eeprom_update_sys(void);
extern void eeprom_update_performance(void);
extern void eeprom_update_fx(void);
extern void eeprom_update_dexed(uint8_t instance_id);
extern float pseudo_log_curve(float value);
extern uint8_t selected_instance_id;
extern char receive_bank_filename[FILENAME_LEN];
#ifdef DISPLAY_LCD_SPI
extern void change_disp_sd(bool d);
#endif
extern AudioSourceMicroDexed* MicroDexed[NUM_DEXED];
#if defined(USE_FX)
extern AudioSynthWaveform* chorus_modulator[NUM_DEXED];
extern AudioEffectModulatedDelay* modchorus[NUM_DEXED];
extern AudioMixer4* chorus_mixer[NUM_DEXED];
extern AudioMixer4* delay_fb_mixer[NUM_DEXED];
extern AudioEffectDelay* delay_fx[NUM_DEXED];
extern AudioMixer4* delay_mixer[NUM_DEXED];
#endif
extern AudioEffectMonoStereo* mono2stereo[NUM_DEXED];
extern AudioMixer4 microdexed_peak_mixer;
extern AudioAnalyzePeak microdexed_peak;
#if defined(USE_FX)
extern AudioMixer4 reverb_mixer_r;
extern AudioMixer4 reverb_mixer_l;
#ifdef USE_PLATEREVERB
extern AudioEffectPlateReverb reverb;
#else
extern AudioEffectFreeverb freeverb_r;
extern AudioEffectFreeverb freeverb_l;
#endif
#endif
extern AudioMixer4 master_mixer_r;
extern AudioMixer4 master_mixer_l;
extern AudioEffectStereoMono stereo2mono;
extern AudioAnalyzePeak master_peak_r;
extern AudioAnalyzePeak master_peak_l;
extern char sd_string[LCD_cols + 1];
extern char g_voice_name[NUM_DEXED][VOICE_NAME_LEN];
extern char g_bank_name[NUM_DEXED][BANK_NAME_LEN];
/***********************************************************************
GLOBAL
************************************************************************/
elapsedMillis back_from_volume;
uint8_t instance_num[8][8];
const char accepted_chars[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-abcdefghijklmnopqrstuvwxyz";
#ifdef I2C_DISPLAY
#include <LiquidCrystal_I2C.h>
Disp_Plus<LiquidCrystal_I2C> lcd(LCD_I2C_ADDRESS, _LCDML_DISP_cols, _LCDML_DISP_rows);
#endif
#ifdef U8X8_DISPLAY
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
Disp_Plus<U8X8_DISPLAY_CLASS> lcd(/* cs=*/ U8X8_CS_PIN, /* dc=*/ U8X8_DC_PIN, /* reset=*/ U8X8_RESET_PIN);
//Disp_Plus<U8X8_DISPLAY_CLASS> lcd(U8X8_PIN_NONE);
#endif
const uint8_t scroll_bar[5][8] = {
{B10001, B10001, B10001, B10001, B10001, B10001, B10001, B10001}, // scrollbar top
{B11111, B11111, B10001, B10001, B10001, B10001, B10001, B10001}, // scroll state 1
{B10001, B10001, B11111, B11111, B10001, B10001, B10001, B10001}, // scroll state 2
{B10001, B10001, B10001, B10001, B11111, B11111, B10001, B10001}, // scroll state 3
{B10001, B10001, B10001, B10001, B10001, B10001, B11111, B11111} // scrollbar bottom
};
const uint8_t block_bar[5][8] = {
{B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000},
{B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000},
{B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100},
{B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110},
{B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111}
};
const uint8_t meter_bar[5][8] = {
{B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000},
{B01000, B01000, B01000, B01000, B01000, B01000, B01000, B01000},
{B00100, B00100, B00100, B00100, B00100, B00100, B00100, B00100},
{B00010, B00010, B00010, B00010, B00010, B00010, B00010, B00010},
{B00001, B00001, B00001, B00001, B00001, B00001, B00001, B00001}
};
const uint8_t special_chars[18][8] = {
{B11111, B11011, B10011, B11011, B11011, B11011, B11011, B11111}, // [0] 1 small invers
{B11111, B11011, B10101, B11101, B11011, B10111, B10001, B11111}, // [1] 2 small invers
{B11111, B11011, B10011, B11011, B11011, B11011, B11011, B11111}, // [2] 1 OP invers
{B11111, B11011, B10101, B11101, B11011, B10111, B10001, B11111}, // [3] 2 OP invers
{B11111, B10001, B11101, B11011, B11101, B10101, B11011, B11111}, // [4] 3 OP invers
{B11111, B10111, B10111, B10101, B10001, B11101, B11101, B11111}, // [5] 4 OP invers
{B11111, B10001, B10111, B10011, B11101, B11101, B10011, B11111}, // [6] 5 OP invers
{B11111, B11001, B10111, B10011, B10101, B10101, B11011, B11111}, // [7] 6 OP invers
{B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111}, // [8] Level 1
{B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111}, // [9] Level 2
{B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111}, // [10] Level 3
{B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111}, // [11] Level 4
{B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111}, // [12] Level 5
{B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111}, // [13] Level 6
{B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111}, // [14] Level 7
{B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111}, // [15] Level 8
{B00100, B00110, B00101, B00101, B01101, B11101, B11100, B11000}, // [16] Note
//{B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000} // [17] Disabled 2nd instance symbol
{B01110, B10001, B10001, B01110, B00100, B00100, B00110, B00110} // [17] Disabled 2nd instance symbol
};
enum { SCROLLBAR, BLOCKBAR, METERBAR };
enum { ENC_R, ENC_L };
enum {MENU_VOICE_BANK, MENU_VOICE_SOUND};
void lcdml_menu_display(void);
void lcdml_menu_clear(void);
void lcdml_menu_control(void);
#ifdef USE_FX
void UI_func_reverb_roomsize(uint8_t param);
void UI_func_reverb_damping(uint8_t param);
void UI_func_reverb_level(uint8_t param);
void UI_func_chorus_frequency(uint8_t param);
void UI_func_chorus_waveform(uint8_t param);
void UI_func_chorus_depth(uint8_t param);
void UI_func_chorus_level(uint8_t param);
void UI_func_delay_time(uint8_t param);
void UI_func_delay_feedback(uint8_t param);
void UI_func_delay_level(uint8_t param);
void UI_func_reverb_send(uint8_t param);
void UI_func_filter_cutoff(uint8_t param);
void UI_func_filter_resonance(uint8_t param);
#endif
void UI_func_transpose(uint8_t param);
void UI_func_tune(uint8_t param);
void UI_func_midi_channel(uint8_t param);
void UI_func_lowest_note(uint8_t param);
void UI_func_highest_note(uint8_t param);
void UI_func_sound_intensity(uint8_t param);
void UI_func_panorama(uint8_t param);
void UI_func_stereo_mono(uint8_t param);
void UI_func_note_refresh(uint8_t param);
void UI_func_polyphony(uint8_t param);
void UI_func_engine(uint8_t param);
void UI_func_mono_poly(uint8_t param);
void UI_func_pb_range(uint8_t param);
void UI_func_pb_step(uint8_t param);
void UI_func_mw_range(uint8_t param);
void UI_func_mw_assign(uint8_t param);
void UI_func_mw_mode(uint8_t param);
void UI_func_fc_range(uint8_t param);
void UI_func_fc_assign(uint8_t param);
void UI_func_fc_mode(uint8_t param);
void UI_func_bc_range(uint8_t param);
void UI_func_bc_assign(uint8_t param);
void UI_func_bc_mode(uint8_t param);
void UI_func_at_range(uint8_t param);
void UI_func_at_assign(uint8_t param);
void UI_func_at_mode(uint8_t param);
void UI_func_portamento_mode(uint8_t param);
void UI_func_portamento_glissando(uint8_t param);
void UI_func_portamento_time(uint8_t param);
void UI_handle_OP(uint8_t param);
void UI_func_information(uint8_t param);
void UI_func_volume(uint8_t param);
void UI_func_load_performance(uint8_t param);
void UI_func_save_performance(uint8_t param);
void UI_func_load_voiceconfig(uint8_t param);
void UI_func_save_voiceconfig(uint8_t param);
void UI_func_save_voice(uint8_t param);
void UI_func_load_fx(uint8_t param);
void UI_func_save_fx(uint8_t param);
void UI_func_eeprom_reset(uint8_t param);
void UI_func_midi_soft_thru(uint8_t param);
void UI_func_velocity_level(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_bank(uint8_t param);
void UI_func_sysex_send_bank(uint8_t param);
void UI_func_eq_bass(uint8_t param);
void UI_func_eq_treble(uint8_t param);
void UI_function_not_enabled(void);
void UI_function_not_implemented(uint8_t param);
bool UI_select_name(uint8_t y, uint8_t x, char* edit_string, uint8_t len, bool init);
uint8_t search_accepted_char(uint8_t c);
void lcd_display_int(int16_t var, uint8_t size, bool zeros, bool brackets, bool sign);
void lcd_display_float(float var, uint8_t size_number, uint8_t size_fraction, bool zeros, bool brackets, bool sign);
void lcd_display_bar_int(const char* title, uint32_t value, float factor, int32_t min_value, int32_t max_value, uint8_t size, bool zeros, bool sign, bool init);
void lcd_display_bar_float(const char* title, float value, float factor, int32_t min_value, int32_t max_value, uint8_t size_number, uint8_t size_fraction, bool zeros, bool sign, bool init);
void lcd_display_meter_int(const char* title, uint32_t value, float factor, float offset, int32_t min_value, int32_t max_value, uint8_t size, bool zeros, bool sign, bool init);
void lcd_display_meter_float(const char* title, float value, float factor, float offset, int32_t min_value, int32_t max_value, uint8_t size_number, uint8_t size_fraction, bool zeros, bool sign, bool init);
void lcd_active_instance_number(uint8_t instance_id);
void lcd_OP_active_instance_number(uint8_t instance_id, uint8_t op);
void lcd_special_chars(uint8_t mode);
void eeprom_update_var(uint16_t pos, uint8_t val, const char* val_string);
void string_trim(char *s);
// normal menu
LCDMenuLib2_menu LCDML_0(255, 0, 0, NULL, NULL); // normal root menu element (do not change)
LCDMenuLib2 LCDML(LCDML_0, _LCDML_DISP_rows, _LCDML_DISP_cols, lcdml_menu_display, lcdml_menu_clear, lcdml_menu_control);
#if defined(USE_FX)
#include "UI_FX.h"
#else
#include "UI_NO_FX.h"
#endif
// create menu
LCDML_createMenu(_LCDML_DISP_cnt);
/***********************************************************************
CONTROL
***********************************************************************/
class EncoderDirection
{
public:
EncoderDirection(void)
{
reset();
}
void reset(void)
{
button_short = false;
button_long = false;
button_pressed = false;
left = false;
right = false;
up = false;
down = false;
}
void ButtonShort(bool state)
{
button_short = state;
}
bool ButtonShort(void)
{
if (button_short == true)
{
button_short = false;
return (true);
}
return (false);
}
void ButtonLong(bool state)
{
button_long = state;
}
bool ButtonLong(void)
{
if (button_long == true)
{
button_long = false;
return (true);
}
return (false);
}
void ButtonPressed(bool state)
{
button_pressed = state;
}
bool ButtonPressed(void)
{
return (button_pressed);
}
void Left(bool state)
{
left = state;
}
bool Left(void)
{
if (left == true)
{
left = false;
return (true);
}
return (false);
}
void Right(bool state)
{
right = state;
}
bool Right(void)
{
if (right == true)
{
right = false;
return (true);
}
return (false);
}
void Up(bool state)
{
up = state;
}
bool Up(void)
{
if (up == true)
{
up = false;
return (true);
}
return (false);
}
void Down(bool state)
{
down = state;
}
bool Down(void)
{
if (down == true)
{
down = false;
return (true);
}
return (false);
}
private:
bool button_short;
bool button_long;
bool button_pressed;
bool left;
bool right;
bool up;
bool down;
};
//Encoder ENCODER[NUM_ENCODER] = {Encoder(ENC_R_PIN_B, ENC_R_PIN_A), Encoder(ENC_L_PIN_B, ENC_L_PIN_A)};
MD_REncoder ENCODER[NUM_ENCODER] = {MD_REncoder(ENC_R_PIN_B, ENC_R_PIN_A), MD_REncoder(ENC_L_PIN_B, ENC_L_PIN_A)};
EncoderDirection encoderDir[NUM_ENCODER];
long g_LCDML_CONTROL_button_press_time[NUM_ENCODER] = {0, 0};
bool g_LCDML_CONTROL_button_prev[NUM_ENCODER] = {HIGH, HIGH};
uint8_t g_LCDML_CONTROL_prev[NUM_ENCODER] = {0, 0};
bool menu_init = true;
#ifdef U8X8_DISPLAY
const uint8_t * flipped_scroll_bar[5];
const uint8_t * flipped_block_bar[7];
const uint8_t * flipped_meter_bar[7];
uint8_t * rotTile(const uint8_t * tile)
{
uint8_t * newt = new uint8_t[8];
for (int x = 0; x < 8; x++) {
uint8_t newb = 0;
for (int y = 0 ; y < 8; y++) {
newb |= (tile[y] << x) & 0x80;
newb >>= 1;
}
newt[x] = newb;
}
return newt;
}
#endif
void setup_ui(void)
{
// LCD Begin
#ifdef I2C_DISPLAY
lcd.init();
lcd.backlight();
lcd.clear();
lcd.noCursor();
#else
lcd.begin();
lcd.clear();
lcd.setFont(u8x8_font_amstrad_cpc_extended_f);
#endif
lcd.setCursor(3, 0);
lcd.print(F("MicroDexed"));
lcd.setCursor(0, 1);
lcd.print(F("(c)parasiTstudio"));
lcd_special_chars(SCROLLBAR);
// LCDMenuLib Setup
LCDML_setup(_LCDML_DISP_cnt);
// Enable Menu Rollover
//LCDML.MENU_enRollover();
// Enable Screensaver (screensaver menu function, time to activate in ms)
//LCDML.SCREEN_enable(UI_func_voice_select, VOICE_SELECTION_MS);
}
#ifdef DEBUG
void setup_debug_message(void)
{
// LCD Begin
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(F("* DEBUG MODE *"));
lcd.setCursor(1, 1);
lcd.print(F("ENABLE CONSOLE"));
delay(300);
lcd.setCursor(1, 1);
lcd.print(_LCDML_VERSION);
lcd.print(F(" "));
}
#endif
/***********************************************************************
MENU CONTROL
***********************************************************************/
uint8_t get_current_cursor_id(void)
{
LCDMenuLib2_menu *tmp;
if ((tmp = LCDML.MENU_getCurrentObj()) != NULL)
return (tmp->getChild(LCDML.MENU_getCursorPosAbs())->getID());
else
return (0);
}
void lcdml_menu_control(void)
{
// If something must init, put in in the setup condition
if (LCDML.BT_setup())
{
pinMode(BUT_R_PIN, INPUT_PULLUP);
pinMode(BUT_L_PIN, INPUT_PULLUP);
ENCODER[ENC_R].begin();
ENCODER[ENC_L].begin();
}
if (back_from_volume > BACK_FROM_VOLUME_MS && LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_volume))
{
encoderDir[ENC_L].reset();
encoderDir[ENC_R].reset();
if (LCDML.MENU_getLastActiveFunctionID() < 0xff)
LCDML.OTHER_jumpToID(LCDML.MENU_getLastActiveFunctionID());
else
LCDML.OTHER_setCursorToID(LCDML.MENU_getLastCursorPositionID());
//LCDML.FUNC_goBackToMenu();
}
// Volatile Variables
long g_LCDML_CONTROL_Encoder_position[NUM_ENCODER] = {ENCODER[ENC_R].read(), ENCODER[ENC_L].read()};
bool button[NUM_ENCODER] = {digitalRead(BUT_R_PIN), digitalRead(BUT_L_PIN)};
/************************************************************************************
Basic encoder handling (from LCDMenuLib2)
************************************************************************************/
// RIGHT
if (g_LCDML_CONTROL_Encoder_position[ENC_R] <= -3)
{
if (!button[ENC_R])
{
LCDML.BT_left();
#ifdef DEBUG
Serial.println(F("ENC-R left"));
#endif
encoderDir[ENC_R].Left(true);
g_LCDML_CONTROL_button_prev[ENC_R] = LOW;
g_LCDML_CONTROL_button_press_time[ENC_R] = -1;
}
else
{
#ifdef DEBUG
Serial.println(F("ENC-R down"));
#endif
encoderDir[ENC_R].Down(true);
LCDML.BT_down();
}
ENCODER[ENC_R].write(g_LCDML_CONTROL_Encoder_position[ENC_R] + 4);
}
else if (g_LCDML_CONTROL_Encoder_position[ENC_R] >= 3)
{
if (!button[ENC_R])
{
#ifdef DEBUG
Serial.println(F("ENC-R right"));
#endif
encoderDir[ENC_R].Right(true);
LCDML.BT_right();
g_LCDML_CONTROL_button_prev[ENC_R] = LOW;
g_LCDML_CONTROL_button_press_time[ENC_R] = -1;
}
else
{
#ifdef DEBUG
Serial.println(F("ENC-R up"));
#endif
encoderDir[ENC_R].Up(true);
LCDML.BT_up();
}
ENCODER[ENC_R].write(g_LCDML_CONTROL_Encoder_position[ENC_R] - 4);
}
else
{
if (!button[ENC_R] && g_LCDML_CONTROL_button_prev[ENC_R]) //falling edge, button pressed
{
encoderDir[ENC_R].ButtonPressed(true);
g_LCDML_CONTROL_button_prev[ENC_R] = LOW;
g_LCDML_CONTROL_button_press_time[ENC_R] = millis();
}
else if (button[ENC_R] && !g_LCDML_CONTROL_button_prev[ENC_R]) //rising edge, button not active
{
encoderDir[ENC_R].ButtonPressed(false);
g_LCDML_CONTROL_button_prev[ENC_R] = HIGH;
if (g_LCDML_CONTROL_button_press_time[ENC_R] < 0)
{
g_LCDML_CONTROL_button_press_time[ENC_R] = millis();
//Reset for left right action
}
else if ((millis() - g_LCDML_CONTROL_button_press_time[ENC_R]) >= LONG_BUTTON_PRESS)
{
#ifdef DEBUG
Serial.println("ENC-R long released");
#endif
//LCDML.BT_quit();
encoderDir[ENC_R].ButtonLong(true);
}
else if ((millis() - g_LCDML_CONTROL_button_press_time[ENC_R]) >= BUT_DEBOUNCE_MS)
{
#ifdef DEBUG
Serial.println(F("ENC-R short"));
#endif
encoderDir[ENC_R].ButtonShort(true);
LCDML.BT_enter();
}
}
}
if (encoderDir[ENC_R].ButtonPressed() == true && (millis() - g_LCDML_CONTROL_button_press_time[ENC_R]) >= LONG_BUTTON_PRESS)
{
#ifdef DEBUG
Serial.println("ENC-R long recognized");
#endif
encoderDir[ENC_R].ButtonLong(true);
if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_voice_select))
{
LCDML.BT_enter();
LCDML.OTHER_updateFunc();
LCDML.loop_menu();
encoderDir[ENC_R].ButtonPressed(false);
encoderDir[ENC_R].ButtonLong(false);
}
else
{
if (LCDML.FUNC_getID() < 0xff)
LCDML.FUNC_setGBAToLastFunc();
else
LCDML.FUNC_setGBAToLastCursorPos();
LCDML.OTHER_jumpToFunc(UI_func_voice_select);
encoderDir[ENC_R].reset();
}
}
// LEFT
if (g_LCDML_CONTROL_Encoder_position[ENC_L] <= -3)
{
if (!button[ENC_L])
{
#ifdef DEBUG
Serial.println(F("ENC-L left"));
#endif
encoderDir[ENC_L].Left(true);
LCDML.BT_left();
g_LCDML_CONTROL_button_prev[ENC_L] = LOW;
g_LCDML_CONTROL_button_press_time[ENC_L] = -1;
}
else
{
#ifdef DEBUG
Serial.println(F("ENC-L down"));
#endif
encoderDir[ENC_L].Down(true);
LCDML.BT_down();
if (LCDML.FUNC_getID() != LCDML.OTHER_getIDFromFunction(UI_func_volume))
{
LCDML.OTHER_jumpToFunc(UI_func_volume);
}
}
ENCODER[ENC_L].write(g_LCDML_CONTROL_Encoder_position[ENC_L] + 4);
}
else if (g_LCDML_CONTROL_Encoder_position[ENC_L] >= 3)
{
if (!button[ENC_L])
{
#ifdef DEBUG
Serial.println(F("ENC-L right"));
#endif
encoderDir[ENC_L].Right(true);
LCDML.BT_right();
g_LCDML_CONTROL_button_prev[ENC_L] = LOW;
g_LCDML_CONTROL_button_press_time[ENC_L] = -1;
}
else
{
#ifdef DEBUG
Serial.println(F("ENC-L up"));
#endif
encoderDir[ENC_L].Up(true);
LCDML.BT_up();
if (LCDML.FUNC_getID() != LCDML.OTHER_getIDFromFunction(UI_func_volume))
{
LCDML.OTHER_jumpToFunc(UI_func_volume);
}
}
ENCODER[ENC_L].write(g_LCDML_CONTROL_Encoder_position[ENC_L] - 4);
}
else
{
if (!button[ENC_L] && g_LCDML_CONTROL_button_prev[ENC_L]) //falling edge, button pressed
{
encoderDir[ENC_L].ButtonPressed(true);
g_LCDML_CONTROL_button_prev[ENC_L] = LOW;
g_LCDML_CONTROL_button_press_time[ENC_L] = millis();
}
else if (button[ENC_L] && !g_LCDML_CONTROL_button_prev[ENC_L]) //rising edge, button not active
{
encoderDir[ENC_L].ButtonPressed(false);
g_LCDML_CONTROL_button_prev[ENC_L] = HIGH;
if (g_LCDML_CONTROL_button_press_time[ENC_L] < 0)
{
g_LCDML_CONTROL_button_press_time[ENC_L] = millis();
//Reset for left right action
}
else if ((millis() - g_LCDML_CONTROL_button_press_time[ENC_L]) >= LONG_BUTTON_PRESS)
{
#ifdef DEBUG
Serial.println(F("ENC-L long released"));
#endif
//encoderDir[ENC_L].ButtonLong(true);
//LCDML.BT_quit();
}
else if ((millis() - g_LCDML_CONTROL_button_press_time[ENC_L]) >= BUT_DEBOUNCE_MS)
{
//LCDML.BT_enter();
#ifdef DEBUG
Serial.println(F("ENC-L short"));
#endif
encoderDir[ENC_L].ButtonShort(true);
if ((LCDML.MENU_getLastActiveFunctionID() == 0xff && LCDML.MENU_getLastCursorPositionID() == 0) || menu_init == true)
{
LCDML.MENU_goRoot();
menu_init = false;
}
else if (LCDML.FUNC_getID() == LCDML.OTHER_getIDFromFunction(UI_func_volume))
{
encoderDir[ENC_L].reset();
encoderDir[ENC_R].reset();
if (LCDML.MENU_getLastActiveFunctionID() < 0xff)
LCDML.OTHER_jumpToID(LCDML.MENU_getLastActiveFunctionID());
else
LCDML.OTHER_setCursorToID(LCDML.MENU_getLastCursorPositionID());
}
else
LCDML.BT_quit();
}
}
}
if (encoderDir[ENC_L].ButtonPressed() == true && (millis() - g_LCDML_CONTROL_button_press_time[ENC_L]) >= LONG_BUTTON_PRESS)
{
#ifdef DEBUG
Serial.println(F("ENC-L long recognized"));
#endif
for (uint8_t i = 0; i < NUM_DEXED; i++)
MicroDexed[i]->panic();
encoderDir[ENC_L].reset();
encoderDir[ENC_R].reset();
}
}
/***********************************************************************
MENU DISPLAY
***********************************************************************/
void lcdml_menu_clear(void)
{
lcd.clear();
lcd.setCursor(0, 0);
}
void lcdml_menu_display(void)
{
// update content
// ***************
if (LCDML.DISP_checkMenuUpdate()) {
// clear menu
// ***************
LCDML.DISP_clear();
// declaration of some variables
// ***************
// content variable
char content_text[_LCDML_DISP_cols]; // save the content text of every menu element
// menu element object
LCDMenuLib2_menu *tmp;
// some limit values
uint8_t i = LCDML.MENU_getScroll();
uint8_t maxi = _LCDML_DISP_rows + i;
uint8_t n = 0;
// check if this element has children
if ((tmp = LCDML.MENU_getDisplayedObj()) != NULL)
{
// loop to display lines
do
{
// check if a menu element has a condition and if the condition be true
if (tmp->checkCondition())
{
// check the type off a menu element
if (tmp->checkType_menu() == true)
{
// display normal content
LCDML_getContent(content_text, tmp->getID());
lcd.setCursor(1, n);
lcd.print(content_text);
}
else
{
if (tmp->checkType_dynParam()) {
tmp->callback(n);
}
}
// increment some values
i++;
n++;
}
// try to go to the next sibling and check the number of displayed rows
} while (((tmp = tmp->getSibling(1)) != NULL) && (i < maxi));
}
}
if (LCDML.DISP_checkMenuCursorUpdate())
{
// init vars
uint8_t n_max = (LCDML.MENU_getChilds() >= _LCDML_DISP_rows) ? _LCDML_DISP_rows : (LCDML.MENU_getChilds());
uint8_t scrollbar_min = 0;
uint8_t scrollbar_max = LCDML.MENU_getChilds();
uint8_t scrollbar_cur_pos = LCDML.MENU_getCursorPosAbs();
uint8_t scroll_pos = ((1.*n_max * _LCDML_DISP_rows) / (scrollbar_max - 1) * scrollbar_cur_pos);
// display rows
for (uint8_t n = 0; n < n_max; n++)
{
//set cursor
lcd.setCursor(0, n);
//set cursor char
if (n == LCDML.MENU_getCursorPos()) {
lcd.write(_LCDML_DISP_cfg_cursor);
} else {
lcd.write(' ');
}
// delete or reset scrollbar
if (_LCDML_DISP_cfg_scrollbar == 1) {
if (scrollbar_max > n_max) {
#ifdef I2C_DISPLAY
lcd.setCursor((_LCDML_DISP_cols - 1), n);
lcd.write((uint8_t)0);
#else
lcd.drawTile((_LCDML_DISP_cols - 1), n, 1, flipped_scroll_bar[0]);
lcd.setCursor((_LCDML_DISP_cols), n + 1);
#endif
}
else {
lcd.setCursor((_LCDML_DISP_cols - 1), n);
lcd.print(F(" "));
}
}
}
// display scrollbar
if (_LCDML_DISP_cfg_scrollbar == 1) {
if (scrollbar_max > n_max) {
//set scroll position
if (scrollbar_cur_pos == scrollbar_min) {
// min pos
#ifdef I2C_DISPLAY
lcd.setCursor((_LCDML_DISP_cols - 1), 0);
lcd.write((uint8_t)1);
#else
lcd.drawTile((_LCDML_DISP_cols - 1), 0, 1, flipped_scroll_bar[1]);
lcd.setCursor((_LCDML_DISP_cols), 1);
#endif
} else if (scrollbar_cur_pos == (scrollbar_max - 1)) {
// max pos
#ifdef I2C_DISPLAY
lcd.setCursor((_LCDML_DISP_cols - 1), (n_max - 1));
lcd.write((uint8_t)4);
#else
lcd.drawTile((_LCDML_DISP_cols - 1), (n_max - 1), 1, flipped_scroll_bar[4]);
lcd.setCursor((_LCDML_DISP_cols), (n_max));
#endif
} else {
// between
#ifdef I2C_DISPLAY
lcd.setCursor((_LCDML_DISP_cols - 1), scroll_pos / n_max);
lcd.write((uint8_t)(scroll_pos % n_max) + 1);
#else
lcd.drawTile((_LCDML_DISP_cols - 1), scroll_pos / n_max, 1, flipped_scroll_bar[(scroll_pos % n_max) + 1]);
lcd.setCursor((_LCDML_DISP_cols), (scroll_pos / n_max) + 1);
#endif
}
}
}
}
}
//####################################################################################################################################################################################################
/***********************************************************************
MENU
***********************************************************************/
#ifdef USE_FX
void UI_func_reverb_roomsize(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Reverb Room", configuration.fx.reverb_roomsize, 1.0, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 3, false, false, true);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()))
{
if (LCDML.BT_checkDown())
configuration.fx.reverb_roomsize = constrain(configuration.fx.reverb_roomsize + ENCODER[ENC_R].speed(), REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX);
else if (LCDML.BT_checkUp())
configuration.fx.reverb_roomsize = constrain(configuration.fx.reverb_roomsize - ENCODER[ENC_R].speed(), REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX);
}
lcd_display_bar_int("Reverb Room", configuration.fx.reverb_roomsize, 1.0, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 3, false, false, false);
#ifdef USE_PLATEREVERB
reverb.size(mapfloat(configuration.fx.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 0.0, 1.0));
#else
freeverb_r.roomsize(mapfloat(configuration.fx.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 0.0, 1.0));
freeverb_l.roomsize(mapfloat(configuration.fx.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 0.0, 1.0));
#endif
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.reverb_roomsize), configuration.fx.reverb_roomsize);
}
}
void UI_func_reverb_damping(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Reverb Damp.", configuration.fx.reverb_damping, 1.0, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 3, false, false, true);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()))
{
if (LCDML.BT_checkDown())
configuration.fx.reverb_damping = constrain(configuration.fx.reverb_damping + ENCODER[ENC_R].speed(), REVERB_DAMPING_MIN, REVERB_DAMPING_MAX);
else if (LCDML.BT_checkUp())
configuration.fx.reverb_damping = constrain(configuration.fx.reverb_damping - ENCODER[ENC_R].speed(), REVERB_DAMPING_MIN, REVERB_DAMPING_MAX);
}
lcd_display_bar_int("Reverb Damp.", configuration.fx.reverb_damping, 1.0, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 3, false, false, false);
#ifdef USE_PLATEREVERB
reverb.hidamp(mapfloat(configuration.fx.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0));
#else
freeverb_l.damping(mapfloat(configuration.fx.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0));
freeverb_r.damping(mapfloat(configuration.fx.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0));
#endif
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.reverb_damping), configuration.fx.reverb_damping);
}
}
void UI_func_reverb_level(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Reverb Level", configuration.fx.reverb_level, 1.0, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 3, false, false, true);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()))
{
if (LCDML.BT_checkDown())
configuration.fx.reverb_level = constrain(configuration.fx.reverb_level + ENCODER[ENC_R].speed(), REVERB_LEVEL_MIN, REVERB_LEVEL_MAX);
else if (LCDML.BT_checkUp())
configuration.fx.reverb_level = constrain(configuration.fx.reverb_level - ENCODER[ENC_R].speed(), REVERB_LEVEL_MIN, REVERB_LEVEL_MAX);
}
lcd_display_bar_int("Reverb Level", configuration.fx.reverb_level, 1.0, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 3, false, false, true);
master_mixer_r.gain(3, pseudo_log_curve(mapfloat(configuration.fx.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)));
master_mixer_l.gain(3, pseudo_log_curve(mapfloat(configuration.fx.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)));
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.reverb_level), configuration.fx.reverb_level);
}
}
void UI_func_chorus_frequency(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_float("Chorus Frq.", configuration.fx.chorus_frequency[selected_instance_id], 0.1, CHORUS_FREQUENCY_MIN, CHORUS_FREQUENCY_MAX, 2, 1, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
configuration.fx.chorus_frequency[selected_instance_id] = constrain(configuration.fx.chorus_frequency[selected_instance_id] + ENCODER[ENC_R].speed(), CHORUS_FREQUENCY_MIN, CHORUS_FREQUENCY_MAX);
else if (LCDML.BT_checkUp())
configuration.fx.chorus_frequency[selected_instance_id] = constrain(configuration.fx.chorus_frequency[selected_instance_id] - ENCODER[ENC_R].speed(), CHORUS_FREQUENCY_MIN, CHORUS_FREQUENCY_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_float("Chorus Frq.", configuration.fx.chorus_frequency[selected_instance_id], 0.1, CHORUS_FREQUENCY_MIN, CHORUS_FREQUENCY_MAX, 2, 1, false, false, false);
chorus_modulator[selected_instance_id]->frequency(configuration.fx.chorus_frequency[selected_instance_id] / 10.0);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.chorus_frequency[0]), configuration.fx.chorus_frequency[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.chorus_frequency[1]), configuration.fx.chorus_frequency[1]);
#endif
}
}
void UI_func_chorus_waveform(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd.setCursor(0, 0);
lcd.print(F("Chorus Wavefrm"));
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if (LCDML.BT_checkDown() && encoderDir[ENC_R].Down())
configuration.fx.chorus_waveform[selected_instance_id] = constrain(configuration.fx.chorus_waveform[selected_instance_id] + 1, CHORUS_WAVEFORM_MIN, CHORUS_WAVEFORM_MAX);
else if (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())
configuration.fx.chorus_waveform[selected_instance_id] = constrain(configuration.fx.chorus_waveform[selected_instance_id] - 1, CHORUS_WAVEFORM_MIN, CHORUS_WAVEFORM_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
lcd.setCursor(0, 1);
switch (configuration.fx.chorus_waveform[selected_instance_id])
{
case 0:
chorus_modulator[selected_instance_id]->begin(WAVEFORM_TRIANGLE);
lcd.print(F("[TRIANGLE]"));
break;
case 1:
chorus_modulator[selected_instance_id]->begin(WAVEFORM_SINE);
lcd.print(F("[SINE ]"));
break;
default:
chorus_modulator[selected_instance_id]->begin(WAVEFORM_TRIANGLE);
lcd.print(F("[TRIANGLE]"));
break;
}
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.chorus_waveform[0]), configuration.fx.chorus_waveform[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.chorus_waveform[1]), configuration.fx.chorus_waveform[1]);
#endif
}
}
void UI_func_chorus_depth(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Chorus Dpt.", configuration.fx.chorus_depth[selected_instance_id], 1.0, CHORUS_DEPTH_MIN, CHORUS_DEPTH_MAX, 3, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
configuration.fx.chorus_depth[selected_instance_id] = constrain(configuration.fx.chorus_depth[selected_instance_id] + ENCODER[ENC_R].speed(), CHORUS_DEPTH_MIN, CHORUS_DEPTH_MAX);
else if (LCDML.BT_checkUp())
configuration.fx.chorus_depth[selected_instance_id] = constrain(configuration.fx.chorus_depth[selected_instance_id] - ENCODER[ENC_R].speed(), CHORUS_DEPTH_MIN, CHORUS_DEPTH_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_int("Chorus Dpt.", configuration.fx.chorus_depth[selected_instance_id], 1.0, CHORUS_DEPTH_MIN, CHORUS_DEPTH_MAX, 3, false, false, false);
chorus_modulator[selected_instance_id]->amplitude(configuration.fx.chorus_depth[selected_instance_id] / 100.0);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.chorus_depth[0]), configuration.fx.chorus_depth[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.chorus_depth[1]), configuration.fx.chorus_depth[1]);
#endif
}
}
void UI_func_chorus_level(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Chorus Lvl.", configuration.fx.chorus_level[selected_instance_id], 1.0, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 3, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.fx.chorus_level[selected_instance_id] = constrain(configuration.fx.chorus_level[selected_instance_id] + ENCODER[ENC_R].speed(), CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 93, configuration.fx.chorus_level[selected_instance_id]);
}
else if (LCDML.BT_checkUp())
{
configuration.fx.chorus_level[selected_instance_id] = constrain(configuration.fx.chorus_level[selected_instance_id] - ENCODER[ENC_R].speed(), CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 93, configuration.fx.chorus_level[selected_instance_id]);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_int("Chorus Lvl.", configuration.fx.chorus_level[selected_instance_id], 1.0, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 3, false, false, false);
//chorus_mixer[selected_instance_id]->gain(0, pseudo_log_curve(1.0 - mapfloat(configuration.fx.chorus_level[selected_instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)));
//chorus_mixer[selected_instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.chorus_level[selected_instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5)));
//chorus_mixer[selected_instance_id]->gain(0, 1.0 - mapfloat(configuration.fx.chorus_level[selected_instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5));
chorus_mixer[selected_instance_id]->gain(1, mapfloat(configuration.fx.chorus_level[selected_instance_id], CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 0.5));
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.chorus_level[0]), configuration.fx.chorus_level[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.chorus_level[1]), configuration.fx.chorus_level[1]);
#endif
}
}
void UI_func_delay_time(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
#if DELAY_TIME_MAX >= 100
lcd_display_bar_int("Delay Time", configuration.fx.delay_time[selected_instance_id], 10.0, DELAY_TIME_MIN, DELAY_TIME_MAX, 4, false, false, true);
#else
lcd_display_bar_int("Delay Time", configuration.fx.delay_time[selected_instance_id], 10.0, DELAY_TIME_MIN, DELAY_TIME_MAX, 3, false, false, true);
#endif
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.fx.delay_time[selected_instance_id] = constrain(configuration.fx.delay_time[selected_instance_id] + ENCODER[ENC_R].speed(), DELAY_TIME_MIN, DELAY_TIME_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 105, configuration.fx.delay_time[selected_instance_id]);
}
else if (LCDML.BT_checkUp())
{
configuration.fx.delay_time[selected_instance_id] = constrain(configuration.fx.delay_time[selected_instance_id] - ENCODER[ENC_R].speed(), DELAY_TIME_MIN, DELAY_TIME_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 105, configuration.fx.delay_time[selected_instance_id]);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
#if DELAY_TIME_MAX >= 100
lcd_display_bar_int("Delay Time", configuration.fx.delay_time[selected_instance_id], 10.0, DELAY_TIME_MIN, DELAY_TIME_MAX, 4, false, false, true);
#else
lcd_display_bar_int("Delay Time", configuration.fx.delay_time[selected_instance_id], 10.0, DELAY_TIME_MIN, DELAY_TIME_MAX, 3, false, false, true);
#endif
if (configuration.fx.delay_time[selected_instance_id] <= DELAY_TIME_MIN)
delay_fx[selected_instance_id]->disable(0);
else
delay_fx[selected_instance_id]->delay(0, constrain(configuration.fx.delay_time[selected_instance_id], DELAY_TIME_MIN, DELAY_TIME_MAX) * 10);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.delay_time[0]), configuration.fx.delay_time[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.delay_time[1]), configuration.fx.delay_time[1]);
#endif
}
}
void UI_func_delay_feedback(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Delay Feedb.", configuration.fx.delay_feedback[selected_instance_id], 1.0, DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 3, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.fx.delay_feedback[selected_instance_id] = constrain(configuration.fx.delay_feedback[selected_instance_id] + ENCODER[ENC_R].speed(), DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 106, configuration.fx.delay_feedback[selected_instance_id]);
}
else if (LCDML.BT_checkUp())
{
configuration.fx.delay_feedback[selected_instance_id] = constrain(configuration.fx.delay_feedback[selected_instance_id] - ENCODER[ENC_R].speed(), DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 106, configuration.fx.delay_feedback[selected_instance_id]);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_int("Delay Feedb.", configuration.fx.delay_feedback[selected_instance_id], 1.0, DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 3, false, false, false);
delay_fb_mixer[selected_instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.delay_feedback[selected_instance_id], DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 0.0, 1.0))); // amount of feedback
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.delay_feedback[0]), configuration.fx.delay_feedback[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.delay_feedback[1]), configuration.fx.delay_feedback[1]);
#endif
}
}
void UI_func_delay_level(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Delay Lvl.", configuration.fx.delay_level[selected_instance_id], 1.0, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 3, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.fx.delay_level[selected_instance_id] = constrain(configuration.fx.delay_level[selected_instance_id] + ENCODER[ENC_R].speed(), DELAY_LEVEL_MIN, DELAY_LEVEL_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 107, configuration.fx.delay_level[selected_instance_id]);
}
else if (LCDML.BT_checkUp())
{
configuration.fx.delay_level[selected_instance_id] = constrain(configuration.fx.delay_level[selected_instance_id] - ENCODER[ENC_R].speed(), DELAY_LEVEL_MIN, DELAY_LEVEL_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 107, configuration.fx.delay_level[selected_instance_id]);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_int("Delay Lvl.", configuration.fx.delay_level[selected_instance_id], 1.0, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 3, false, false, false);
/*if (configuration.fx.delay_level[selected_instance_id] <= DELAY_LEVEL_MIN)
delay_fx[selected_instance_id]->disable(0);
else
delay_fx[selected_instance_id]->delay(0, constrain(configuration.fx.delay_time[selected_instance_id], DELAY_TIME_MIN, DELAY_TIME_MAX) * 10); */
delay_mixer[selected_instance_id]->gain(1, pseudo_log_curve(mapfloat(configuration.fx.delay_level[selected_instance_id], DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)));
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.delay_level[0]), configuration.fx.delay_level[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.delay_level[1]), configuration.fx.delay_level[1]);
#endif
}
}
void UI_func_reverb_send(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Reverb Send", configuration.fx.reverb_send[selected_instance_id], 1.0, REVERB_SEND_MIN, REVERB_SEND_MAX, 3, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.fx.reverb_send[selected_instance_id] = constrain(configuration.fx.reverb_send[selected_instance_id] + ENCODER[ENC_R].speed(), REVERB_SEND_MIN, REVERB_SEND_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 91, configuration.fx.reverb_send[selected_instance_id]);
}
else if (LCDML.BT_checkUp())
{
configuration.fx.reverb_send[selected_instance_id] = constrain(configuration.fx.reverb_send[selected_instance_id] - ENCODER[ENC_R].speed(), REVERB_SEND_MIN, REVERB_SEND_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 91, configuration.fx.reverb_send[selected_instance_id]);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_int("Reverb Send", configuration.fx.reverb_send[selected_instance_id], 1.0, REVERB_SEND_MIN, REVERB_SEND_MAX, 3, false, false, false);
reverb_mixer_r.gain(selected_instance_id, pseudo_log_curve(mapfloat(configuration.fx.reverb_send[selected_instance_id], REVERB_SEND_MIN, REVERB_SEND_MAX, 0.0, 1.0)));
reverb_mixer_l.gain(selected_instance_id, pseudo_log_curve(mapfloat(configuration.fx.reverb_send[selected_instance_id], REVERB_SEND_MIN, REVERB_SEND_MAX, 0.0, 1.0)));
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.reverb_send[0]), configuration.fx.reverb_send[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.reverb_send[1]), configuration.fx.reverb_send[1]);
#endif
}
}
void UI_func_filter_cutoff(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Filter Cut", configuration.fx.filter_cutoff[selected_instance_id], 1.0, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX, 3, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.fx.filter_cutoff[selected_instance_id] = constrain(configuration.fx.filter_cutoff[selected_instance_id] + ENCODER[ENC_R].speed(), FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 104, configuration.fx.filter_cutoff[selected_instance_id]);
}
else if (LCDML.BT_checkUp())
{
configuration.fx.filter_cutoff[selected_instance_id] = constrain(configuration.fx.filter_cutoff[selected_instance_id] - ENCODER[ENC_R].speed(), FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 104, configuration.fx.filter_cutoff[selected_instance_id]);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_int("Filter Cut", configuration.fx.filter_cutoff[selected_instance_id], 1.0, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX, 3, false, false, false);
MicroDexed[selected_instance_id]->fx.Cutoff = mapfloat(configuration.fx.filter_cutoff[selected_instance_id], FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX, 1.0, 0.0);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.filter_cutoff[0]), configuration.fx.filter_cutoff[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.filter_cutoff[1]), configuration.fx.filter_cutoff[1]);
#endif
}
}
void UI_func_filter_resonance(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Filter Res", configuration.fx.filter_resonance[selected_instance_id], 1.0, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX, 3, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.fx.filter_resonance[selected_instance_id] = constrain(configuration.fx.filter_resonance[selected_instance_id] + ENCODER[ENC_R].speed(), FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 103, configuration.fx.filter_resonance[selected_instance_id]);
}
else if (LCDML.BT_checkUp())
{
configuration.fx.filter_resonance[selected_instance_id] = constrain(configuration.fx.filter_resonance[selected_instance_id] - ENCODER[ENC_R].speed(), FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 103, configuration.fx.filter_resonance[selected_instance_id]);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_int("Filter Res", configuration.fx.filter_resonance[selected_instance_id], 1.0, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX, 3, false, false, false);
MicroDexed[selected_instance_id]->fx.Reso = mapfloat(configuration.fx.filter_resonance[selected_instance_id], FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX, 1.0, 0.0);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.filter_resonance[0]), configuration.fx.filter_resonance[0]);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, fx.filter_resonance[1]), configuration.fx.filter_resonance[1]);
#endif
}
}
#endif
void UI_func_transpose(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(METERBAR);
lcd_display_meter_int("Transpose", configuration.dexed[selected_instance_id].transpose, 1.0, -24.0, TRANSPOSE_MIN, TRANSPOSE_MAX, 2, false, true, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
configuration.dexed[selected_instance_id].transpose = constrain(configuration.dexed[selected_instance_id].transpose + ENCODER[ENC_R].speed(), TRANSPOSE_MIN, TRANSPOSE_MAX);
else if (LCDML.BT_checkUp())
configuration.dexed[selected_instance_id].transpose = constrain(configuration.dexed[selected_instance_id].transpose - ENCODER[ENC_R].speed(), TRANSPOSE_MIN, TRANSPOSE_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_meter_int("Transpose", configuration.dexed[selected_instance_id].transpose, 1.0, -24.0, TRANSPOSE_MIN, TRANSPOSE_MAX, 2, false, true, true);
MicroDexed[selected_instance_id]->data[DEXED_VOICE_OFFSET + DEXED_TRANSPOSE] = configuration.dexed[selected_instance_id].transpose;
MicroDexed[selected_instance_id]->notesOff();
send_sysex_param(configuration.dexed[selected_instance_id].midi_channel, 144, configuration.dexed[selected_instance_id].transpose, 0);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].transpose), configuration.dexed[0].transpose);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].transpose), configuration.dexed[1].transpose);
#endif
}
}
void UI_func_tune(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(METERBAR);
lcd_display_meter_int("Fine Tune", configuration.dexed[selected_instance_id].tune, 1.0, -100.0, TUNE_MIN, TUNE_MAX, 3, false, true, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.dexed[selected_instance_id].tune = constrain(configuration.dexed[selected_instance_id].tune + ENCODER[ENC_R].speed(), TUNE_MIN, TUNE_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 94, configuration.dexed[selected_instance_id].tune);
}
else if (LCDML.BT_checkUp())
{
configuration.dexed[selected_instance_id].tune = constrain(configuration.dexed[selected_instance_id].tune - ENCODER[ENC_R].speed(), TUNE_MIN, TUNE_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 94, configuration.dexed[selected_instance_id].tune);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_meter_int("Fine Tune", configuration.dexed[selected_instance_id].tune, 1.0, -100.0, TUNE_MIN, TUNE_MAX, 3, false, true, false);
MicroDexed[selected_instance_id]->controllers.masterTune = (int((configuration.dexed[selected_instance_id].tune - 100) / 100.0 * 0x4000) << 11) * (1.0 / 12);
MicroDexed[selected_instance_id]->doRefreshVoice();
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].tune), configuration.dexed[0].tune);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].tune), configuration.dexed[1].tune);
#endif
}
}
void UI_func_midi_channel(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd.setCursor(0, 0);
lcd.print(F("MIDI Channel"));
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if (LCDML.BT_checkDown() && encoderDir[ENC_R].Down())
configuration.dexed[selected_instance_id].midi_channel = constrain(configuration.dexed[selected_instance_id].midi_channel + ENCODER[ENC_R].speed(), MIDI_CHANNEL_MIN, MIDI_CHANNEL_MAX);
else if (LCDML.BT_checkUp() && encoderDir[ENC_R].Up())
configuration.dexed[selected_instance_id].midi_channel = constrain(configuration.dexed[selected_instance_id].midi_channel - ENCODER[ENC_R].speed(), MIDI_CHANNEL_MIN, MIDI_CHANNEL_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
lcd.setCursor(0, 1);
if (configuration.dexed[selected_instance_id].midi_channel == 0)
{
lcd.print(F("[OMNI]"));
}
else
{
lcd_display_int(configuration.dexed[selected_instance_id].midi_channel, 4, false, true, false);
}
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].midi_channel), configuration.dexed[0].midi_channel);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].midi_channel), configuration.dexed[1].midi_channel);
#endif
}
}
void getNoteName(char* noteName, uint8_t noteNumber)
{
char notes [12][3] = {"A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"};
uint8_t oct_index = noteNumber - 12;
noteNumber -= 21;
sprintf(noteName, "%2s%1d", notes[noteNumber % 12], oct_index / 12);
}
void UI_func_lowest_note(uint8_t param)
{
char note_name[4];
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
getNoteName(note_name, configuration.dexed[selected_instance_id].lowest_note);
lcd.setCursor(0, 0);
lcd.print(F("Lowest Note"));
lcd.setCursor(0, 1);
lcd.print(F("["));
lcd.print(note_name);
lcd.print(F("]"));
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
configuration.dexed[selected_instance_id].lowest_note = constrain(configuration.dexed[selected_instance_id].lowest_note + ENCODER[ENC_R].speed(), INSTANCE_LOWEST_NOTE_MIN, INSTANCE_LOWEST_NOTE_MAX);
else if (LCDML.BT_checkUp())
configuration.dexed[selected_instance_id].lowest_note = constrain(configuration.dexed[selected_instance_id].lowest_note - ENCODER[ENC_R].speed(), INSTANCE_LOWEST_NOTE_MIN, INSTANCE_LOWEST_NOTE_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
getNoteName(note_name, configuration.dexed[selected_instance_id].lowest_note);
lcd.setCursor(1, 1);
lcd.print(note_name);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].lowest_note), configuration.dexed[0].lowest_note);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].lowest_note), configuration.dexed[1].lowest_note);
#endif
}
}
void UI_func_highest_note(uint8_t param)
{
char note_name[4];
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
getNoteName(note_name, configuration.dexed[selected_instance_id].highest_note);
lcd.setCursor(0, 0);
lcd.print(F("Highest Note"));
lcd.setCursor(0, 1);
lcd.print(F("["));
lcd.print(note_name);
lcd.print(F("]"));
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
configuration.dexed[selected_instance_id].highest_note = constrain(configuration.dexed[selected_instance_id].highest_note + ENCODER[ENC_R].speed(), INSTANCE_HIGHEST_NOTE_MIN, INSTANCE_HIGHEST_NOTE_MAX);
else if (LCDML.BT_checkUp())
configuration.dexed[selected_instance_id].highest_note = constrain(configuration.dexed[selected_instance_id].highest_note - ENCODER[ENC_R].speed(), INSTANCE_HIGHEST_NOTE_MIN, INSTANCE_HIGHEST_NOTE_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
getNoteName(note_name, configuration.dexed[selected_instance_id].highest_note);
lcd.setCursor(1, 1);
lcd.print(note_name);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].highest_note), configuration.dexed[0].highest_note);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].highest_note), configuration.dexed[1].highest_note);
#endif
}
}
void UI_func_sound_intensity(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Voice Level", configuration.dexed[selected_instance_id].sound_intensity, 1.0, SOUND_INTENSITY_MIN, SOUND_INTENSITY_MAX, 3, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
encoderDir[ENC_R].reset();
if (LCDML.BT_checkDown())
{
configuration.dexed[selected_instance_id].sound_intensity = constrain(configuration.dexed[selected_instance_id].sound_intensity + ENCODER[ENC_R].speed(), SOUND_INTENSITY_MIN, SOUND_INTENSITY_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 7, configuration.dexed[selected_instance_id].sound_intensity);
}
else if (LCDML.BT_checkUp())
{
configuration.dexed[selected_instance_id].sound_intensity = constrain(configuration.dexed[selected_instance_id].sound_intensity - ENCODER[ENC_R].speed(), SOUND_INTENSITY_MIN, SOUND_INTENSITY_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 7, configuration.dexed[selected_instance_id].sound_intensity);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
lcd_display_bar_int("Voice Level", configuration.dexed[selected_instance_id].sound_intensity, 1.0, SOUND_INTENSITY_MIN, SOUND_INTENSITY_MAX, 3, false, false, false);
MicroDexed[selected_instance_id]->fx.Gain = pseudo_log_curve(mapfloat(configuration.dexed[selected_instance_id].sound_intensity, SOUND_INTENSITY_MIN, SOUND_INTENSITY_MAX, 0.0, SOUND_INTENSITY_AMP_MAX));
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].sound_intensity), configuration.dexed[0].sound_intensity);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].sound_intensity), configuration.dexed[1].sound_intensity);
#endif
}
}
void UI_func_panorama(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
if (configuration.sys.mono > 0)
{
lcd.setCursor(0, 0);
lcd.print(F("Panorama"));
lcd.setCursor(0, 1);
lcd.print(F("MONO-disabled"));
return;
}
lcd_special_chars(METERBAR);
lcd_display_meter_float("Panorama", configuration.dexed[selected_instance_id].pan, 0.05, -20.0, PANORAMA_MIN, PANORAMA_MAX, 1, 1, false, true, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if (LCDML.BT_checkDown() && encoderDir[ENC_R].Down() && configuration.sys.mono == 0)
{
configuration.dexed[selected_instance_id].pan = constrain(configuration.dexed[selected_instance_id].pan + ENCODER[ENC_R].speed(), PANORAMA_MIN, PANORAMA_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 10, map(configuration.dexed[selected_instance_id].pan, PANORAMA_MIN, PANORAMA_MAX, 0, 127));
}
else if (LCDML.BT_checkUp() && encoderDir[ENC_R].Up() && configuration.sys.mono == 0)
{
configuration.dexed[selected_instance_id].pan = constrain(configuration.dexed[selected_instance_id].pan - ENCODER[ENC_R].speed(), PANORAMA_MIN, PANORAMA_MAX);
MD_sendControlChange(configuration.dexed[selected_instance_id].midi_channel, 10, map(configuration.dexed[selected_instance_id].pan, PANORAMA_MIN, PANORAMA_MAX, 0, 127));
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
if (configuration.sys.mono == 0)
{
lcd_display_meter_float("Panorama", configuration.dexed[selected_instance_id].pan, 0.05, -20.0, PANORAMA_MIN, PANORAMA_MAX, 1, 1, false, true, false);
mono2stereo[selected_instance_id]->panorama(mapfloat(configuration.dexed[selected_instance_id].pan, PANORAMA_MIN, PANORAMA_MAX, -1.0, 1.0));
}
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].pan), configuration.dexed[0].pan);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].pan), configuration.dexed[1].pan);
#endif
}
}
void UI_func_stereo_mono(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd.setCursor(0, 0);
lcd.print(F("Stereo/Mono"));
lcd.setCursor(0, 1);
switch (configuration.sys.mono)
{
case 0:
lcd.print(F("[STEREO]"));
stereo2mono.stereo(true);
break;
case 1:
lcd.print(F("[MONO ]"));
stereo2mono.stereo(false);
break;
case 2:
lcd.print(F("[MONO-R]"));
stereo2mono.stereo(false);
break;
case 3:
lcd.print(F("[MONO-L]"));
stereo2mono.stereo(false);
break;
}
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if (LCDML.BT_checkDown())
configuration.sys.mono = constrain(configuration.sys.mono + 1, MONO_MIN, MONO_MAX);
else if (LCDML.BT_checkUp())
configuration.sys.mono = constrain(configuration.sys.mono - 1, MONO_MIN, MONO_MAX);
lcd.setCursor(0, 1);
switch (configuration.sys.mono)
{
case 0:
lcd.print(F("[STEREO]"));
stereo2mono.stereo(true);
break;
case 1:
lcd.print(F("[MONO ]"));
stereo2mono.stereo(false);
break;
case 2:
lcd.print(F("[MONO-R]"));
stereo2mono.stereo(false);
break;
case 3:
lcd.print(F("[MONO-L]"));
stereo2mono.stereo(false);
break;
}
set_volume(configuration.sys.vol, configuration.sys.mono);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, sys.mono), configuration.sys.mono);
}
}
void UI_func_polyphony(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd_special_chars(BLOCKBAR);
lcd_display_bar_int("Polyphony", configuration.dexed[selected_instance_id].polyphony, 1.0, POLYPHONY_MIN, POLYPHONY_MAX, 2, false, false, true);
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
{
configuration.dexed[selected_instance_id].polyphony = constrain(configuration.dexed[selected_instance_id].polyphony + 1, POLYPHONY_MIN, POLYPHONY_MAX);
}
else if (LCDML.BT_checkUp())
{
if (configuration.dexed[selected_instance_id].polyphony - 1 < 0)
configuration.dexed[selected_instance_id].polyphony = 0;
else
configuration.dexed[selected_instance_id].polyphony = constrain(configuration.dexed[selected_instance_id].polyphony - 1, POLYPHONY_MIN, POLYPHONY_MAX);
}
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
lcd_active_instance_number(selected_instance_id);
#endif
}
lcd_display_bar_int("Polyphony", configuration.dexed[selected_instance_id].polyphony, 1.0, POLYPHONY_MIN, POLYPHONY_MAX, 2, false, false, false);
MicroDexed[selected_instance_id]->setMaxNotes(configuration.dexed[selected_instance_id].polyphony);
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].polyphony), configuration.dexed[0].polyphony);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].polyphony), configuration.dexed[1].polyphony);
#endif
}
}
void UI_func_engine(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd.setCursor(0, 0);
lcd.print(F("Engine"));
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
configuration.dexed[selected_instance_id].engine = constrain(configuration.dexed[selected_instance_id].engine + 1, ENGINE_MIN, ENGINE_MAX);
else if (LCDML.BT_checkUp())
configuration.dexed[selected_instance_id].engine = constrain(configuration.dexed[selected_instance_id].engine - 1, ENGINE_MIN, ENGINE_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
#endif
}
MicroDexed[selected_instance_id]->setEngineType(configuration.dexed[selected_instance_id].engine);
lcd.setCursor(0, 1);
switch (configuration.dexed[selected_instance_id].engine)
{
case 0:
lcd.print(F("[MODERN]"));
break;
case 1:
lcd.print(F("[MARK 1]"));
break;
case 2:
lcd.print(F("[OPL ]"));
break;
}
}
if (LCDML.FUNC_close()) // ****** STABLE END *********
{
lcd_special_chars(SCROLLBAR);
encoderDir[ENC_R].reset();
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[0].engine), configuration.dexed[0].engine);
#if NUM_DEXED > 1
EEPROM.update(EEPROM_START_ADDRESS + offsetof(configuration_s, dexed[1].engine), configuration.dexed[1].engine);
#endif
}
}
void UI_func_mono_poly(uint8_t param)
{
if (LCDML.FUNC_setup()) // ****** SETUP *********
{
encoderDir[ENC_R].reset();
lcd.setCursor(0, 0);
lcd.print(F("Mono/Poly"));
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
if (LCDML.FUNC_loop()) // ****** LOOP *********
{
if ((LCDML.BT_checkDown() && encoderDir[ENC_R].Down()) || (LCDML.BT_checkUp() && encoderDir[ENC_R].Up()) || (LCDML.BT_checkEnter() && encoderDir[ENC_R].ButtonShort()))
{
if (LCDML.BT_checkDown())
configuration.dexed[selected_instance_id].monopoly = constrain(configuration.dexed[selected_instance_id].monopoly + 1, MONOPOLY_MIN, MONOPOLY_MAX);
else if (LCDML.BT_checkUp())
configuration.dexed[selected_instance_id].monopoly = constrain(configuration.dexed[selected_instance_id].monopoly - 1, MONOPOLY_MIN, MONOPOLY_MAX);
#if NUM_DEXED > 1
else if (LCDML.BT_checkEnter())
{
selected_instance_id = !selected_instance_id;
lcd_active_instance_number(selected_instance_id);
lcd.setCursor(14, 0);
lcd.write(0);
lcd.setCursor(15, 0);
lcd.write(1);
}
lcd_active_instance_number(selected_instance_id);
#endif