/*
   MicroMDAEPiano

   MicroMDAEPiano is a port of the MDA-EPiano sound engine
   (https://sourceforge.net/projects/mda-vst/) for the Teensy-3.5/3.6 with audio shield.

   (c)2019-2020 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

*/

/* Don't forget to change parameters in ../libraries/LiquidMenu/src/LiquidMenu_config.h

  /// Configures the number of available variables per line.
  const uint8_t MAX_VARIABLES = 5; ///< @note Default: 5

  /// Configures the number of available functions per line.
  const uint8_t MAX_FUNCTIONS = 42; ///< @note Default: 8

  /// Configures the number of available lines per screen.
  const uint8_t MAX_LINES = 20; ///< @note Default: 12

  /// Configures the number of available screens per menu.
  const uint8_t MAX_SCREENS = 2; ///< @note Default: 14

  /// Configures the number of available menus per menus system.
  const uint8_t MAX_MENUS = 45; ///< @note Default: 8

*/

#ifndef UI_HPP_INCLUDED
#define UI_HPP_INCLUDED
#include <LiquidCrystal_I2C.h>
#include <LiquidMenu.h>
#include "source_micromdaepiano.h"
#define BOUNCE_WITH_PROMPT_DETECTION
#include <Bounce.h>
#include "Encoder4.h"
#include "config.h"

LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, LCD_CHARS, LCD_LINES);
Encoder4 enc[NUM_ENCODER] = {Encoder4(ENC_L_PIN_A, ENC_L_PIN_B), Encoder4(ENC_R_PIN_A, ENC_R_PIN_B)};
int32_t encoder_value[NUM_ENCODER];
Bounce but[NUM_ENCODER] = {Bounce(BUT_L_PIN, BUT_DEBOUNCE_MS), Bounce(BUT_R_PIN, BUT_DEBOUNCE_MS)};
elapsedMillis back_to_main;

#define NUM_MENUS 44

#define MAIN 0
/*************************************/
#define LOAD_SOUND 1
#define EDIT_SOUND 2
#define EFFECTS 3
#define SAVE_SOUND 4
#define SYSTEM 5
#define INFO 6
/*************************************/
#define DECAY 7
#define RELEASE 8
#define HARDNESS 9
#define TREBLE 10
#define STEREO_LEVEL 11
#define TRANSPOSE 12
#define TUNE 13
#define DETUNE 14
#define VELOCITY_SENSE 15
/*************************************/
#define PAN_TREM_FREQUENCY 16
#define PAN_TREM_LEVEL 17
#define OVERDRIVE 18
#define COMP_GAIN 19
#define COMP_RESPONSE 20
#define COMP_LIMIT 21
#define COMP_THRESHOLD 22
#define COMP_ATTACK 23
#define COMP_DECAY 24
#define REV_ROOMSIZE 25
#define REV_DAMPING 26
#define REV_LEVEL 27
#define CHORUS_FREQ 28
#define CHORUS_INTENSITY 29
#define CHORUS_WAVEFORM 30
#define CHORUS_LEVEL 31
#define BASS_LR_LEVEL 32
#define BASS_MONO_LEVEL 33
#define EQ_BASS 34
#define EQ_TREBLE 35
/*************************************/
#define LOUDNESS 36
#define MIDI_CHANNEL 37
#define MIDI_SOFT_THRU 38
#define MAX_POLY 39
#define MONO 40
#define PANORAMA 41
/*************************************/
#define STORE_QUESTION 42
/*************************************/
#define MASTER_VOLUME 43
/*************************************/

int8_t menu_position[NUM_MENUS];
bool yes_no = false;

#define LEFT_ENCODER 0
#define RIGHT_ENCODER 1

extern void set_master_volume(uint8_t value);
extern void config_from_eeprom(void);
extern void eeprom_config_write(uint8_t value);

extern AudioControlSGTL5000 sgtl5000_1;
extern AudioSourceMicroMDAEPiano ep;
extern AudioEffectFreeverb freeverb_r;
extern AudioEffectFreeverb freeverb_l;
extern AudioSynthWaveform modulator;
extern AudioEffectModulatedDelay modchorus_r;
extern AudioEffectModulatedDelay modchorus_l;
extern AudioMixer4 mixer_r;
extern AudioMixer4 mixer_l;
extern AudioAmplifier volume_r;
extern AudioAmplifier volume_l;
extern AudioAmplifier inverter;
extern config_t configuration;
extern uint8_t sound;
extern uint8_t master_volume;
extern int8_t pan;

/******************************************
   TEXT GETTER FUCTIONS
 ******************************************/
char comp_gain_value_text1[] = "  0 dB";
char comp_gain_value_text2[] = "+ 6 dB";
char comp_gain_value_text3[] = "+12 dB";
char* get_comp_gain_value_text(void)
{
  switch (configuration.comp_gain)
  {
    case 0:
      return (comp_gain_value_text1);
      break;
    case 1:
      return (comp_gain_value_text2);
      break;
    case 2:
      return (comp_gain_value_text3);
      break;
  }
  return ('\0');
}

char comp_response_value_text1[] = "  0 ms";
char comp_response_value_text2[] = " 25 ms";
char comp_response_value_text3[] = " 50 ms";
char comp_response_value_text4[] = "100 ms";
char* get_comp_response_value_text(void)
{
  switch (configuration.comp_response)
  {
    case 0:
      return (comp_response_value_text1);
      break;
    case 1:
      return (comp_response_value_text2);
      break;
    case 2:
      return (comp_response_value_text3);
      break;
    case 3:
      return (comp_response_value_text4);
      break;
  }
  return ('\0');
}

char comp_limit_value_text1[] = "soft Knee";
char comp_limit_value_text2[] = "hard Knee";
char* get_comp_limit_value_text(void)
{
  if (configuration.comp_limit == false)
    return (comp_limit_value_text1);
  else
    return (comp_limit_value_text2);
}

char comp_threshold_value_text1[] = "        ";
char* get_comp_threshold_value_text(void)
{
  if (configuration.comp_threshold == 0)
    sprintf(comp_threshold_value_text1, " %0d dBFS", configuration.comp_threshold);
  else
    sprintf(comp_threshold_value_text1, "-%0d dBFS", configuration.comp_threshold);

  return (comp_threshold_value_text1);
}

char comp_attack_value_text1[] = "       ";
char* get_comp_attack_value_text(void)
{
  sprintf(comp_attack_value_text1, "%0.1f dB/s", (float)configuration.comp_attack / 10);

  return (comp_attack_value_text1);
}

char comp_decay_value_text1[] = "       ";
char* get_comp_decay_value_text(void)
{
  sprintf(comp_decay_value_text1, "%0.1f dB/s", float(configuration.comp_decay) / 10);

  return (comp_decay_value_text1);
}

char tune_value_text1[] = "        ";
char* get_tune_value_text(void)
{
  sprintf(tune_value_text1, "%3d cent", configuration.tune);

  return (tune_value_text1);
}

char chorus_frequency_value_text1[] = "       ";
char* get_chorus_frequency_value_text(void)
{
  sprintf(chorus_frequency_value_text1, "%2.1f Hz", float(configuration.chorus_frequency) / 10);

  return (chorus_frequency_value_text1);
}

char chorus_waveform_value_text1[] = "       ";
char* get_chorus_waveform_value_text(void)
{
  switch (configuration.chorus_waveform)
  {
    case 1:
      sprintf(chorus_waveform_value_text1, "TRIANGLE");
      break;
    case 2:
      sprintf(chorus_waveform_value_text1, "SINE");
      break;
    default:
      sprintf(chorus_waveform_value_text1, "TRIANGLE");
  }
  return (chorus_waveform_value_text1);
}

char midi_channel_value_text1[] = "   ";
char* get_midi_channel_value_text(void)
{
  if (configuration.midi_channel == 0)
    sprintf(midi_channel_value_text1, "OMNI");
  else
    sprintf(midi_channel_value_text1, "%02d", configuration.midi_channel);

  return (midi_channel_value_text1);
}

char midi_soft_thru_value_text1[] = "   ";
char* get_midi_soft_thru_value_text(void)
{
  if (configuration.midi_soft_thru == false)
    sprintf(midi_soft_thru_value_text1, "Off");
  else
    sprintf(midi_soft_thru_value_text1, "On ");

  return (midi_soft_thru_value_text1);
}

char mono_value_text1[] = "      ";
char* get_mono_value_text(void)
{
  if (configuration.mono == 0)
    sprintf(mono_value_text1, "Stereo");
  else if (configuration.mono == 1)
    sprintf(mono_value_text1, "Mono  ");
  else if (configuration.mono == 2)
    sprintf(mono_value_text1, "Mono R");
  else
    sprintf(mono_value_text1, "Mono L");

  return (mono_value_text1);
}

char yes_no_value_text1[] = "   ";
char* get_yes_no_value_text(void)
{
  if (yes_no == false)
    sprintf(yes_no_value_text1, "No ");
  else
    sprintf(yes_no_value_text1, "Yes");

  return (yes_no_value_text1);
}

/******************************************
   MAIN MENU
 ******************************************/
#define NUM_MAIN_MENUS 6
const char main_text1[] PROGMEM = "Load Sound";
const char main_text2[] PROGMEM = "Edit Sound";
const char main_text3[] PROGMEM = "Effects";
const char main_text4[] PROGMEM = "Save Sound";
const char main_text5[] PROGMEM = "System";
const char main_text6[] PROGMEM = "Info";
LiquidLine main_line1(1, 0, main_text1);
LiquidLine main_line2(1, 1, main_text2);
LiquidLine main_line3(1, 1, main_text3);
LiquidLine main_line4(1, 1, main_text4);
LiquidLine main_line5(1, 1, main_text5);
LiquidLine main_line6(1, 1, main_text6);
LiquidScreen main_screen;
LiquidMenu main_menu(lcd);

/******************************************
   LOAD SOUND MENU
 ******************************************/
#define NUM_LOAD_SOUNDS_MENUS 1
const char load_sound_text1[] PROGMEM = "Load Sound";
LiquidLine load_sound_line1(1, 0, load_sound_text1);
LiquidLine load_sound_line2(1, 1, sound);
LiquidScreen load_sound_screen;
LiquidMenu load_sound_menu(lcd);

/******************************************
   EDIT SOUND MENU
 ******************************************/
#define NUM_EDIT_SOUND_MENUS 9
const char edit_sound_text1[] PROGMEM = "Decay";
const char edit_sound_text2[] PROGMEM = "Release";
const char edit_sound_text3[] PROGMEM = "Hardness";
const char edit_sound_text4[] PROGMEM = "Treble";
const char edit_sound_text5[] PROGMEM = "Stereo Level";
const char edit_sound_text6[] PROGMEM = "Transpose";
const char edit_sound_text7[] PROGMEM = "Tune";
const char edit_sound_text8[] PROGMEM = "Detune";
const char edit_sound_text9[] PROGMEM = "Velocity Sense";
LiquidLine edit_sound_line1(1, 0, edit_sound_text1);
LiquidLine edit_sound_line2(1, 1, edit_sound_text2);
LiquidLine edit_sound_line3(1, 1, edit_sound_text3);
LiquidLine edit_sound_line4(1, 1, edit_sound_text4);
LiquidLine edit_sound_line5(1, 1, edit_sound_text5);
LiquidLine edit_sound_line6(1, 1, edit_sound_text6);
LiquidLine edit_sound_line7(1, 1, edit_sound_text7);
LiquidLine edit_sound_line8(1, 1, edit_sound_text8);
LiquidLine edit_sound_line9(1, 1, edit_sound_text9);
LiquidScreen edit_sound_screen;
LiquidMenu edit_sound_menu(lcd);

/******************************************
   DECAY MENU
 ******************************************/
#define NUM_DECAY_MENUS 1
const char decay_text1[] PROGMEM = "Decay";
LiquidLine decay_line1(1, 0, decay_text1);
LiquidLine decay_line2(1, 1, configuration.decay);
LiquidScreen decay_screen;
LiquidMenu decay_menu(lcd);

/******************************************
   RELEASE MENU
 ******************************************/
#define NUM_RELEASE_MENUS 1
const char release_text1[] PROGMEM = "Release";
LiquidLine release_line1(1, 0, release_text1);
LiquidLine release_line2(1, 1, configuration.release);
LiquidScreen release_screen;
LiquidMenu release_menu(lcd);

/******************************************
   HARDNESS MENU
 ******************************************/
#define NUM_HARDNESS_MENUS 1
const char hardness_text1[] PROGMEM = "Hardness";
LiquidLine hardness_line1(1, 0, hardness_text1);
LiquidLine hardness_line2(1, 1, configuration.hardness);
LiquidScreen hardness_screen;
LiquidMenu hardness_menu(lcd);

/******************************************
   TREBLE MENU
 ******************************************/
#define NUM_TREBLE_MENUS 1
const char treble_text1[] PROGMEM = "Treble";
LiquidLine treble_line1(1, 0, treble_text1);
LiquidLine treble_line2(1, 1, configuration.treble);
LiquidScreen treble_screen;
LiquidMenu treble_menu(lcd);

/******************************************
   STEREO MENU
 ******************************************/
#define NUM_TREBLE_MENUS 1
const char stereo_text1[] PROGMEM = "Stereo";
LiquidLine stereo_line1(1, 0, stereo_text1);
LiquidLine stereo_line2(1, 1, configuration.stereo);
LiquidScreen stereo_screen;
LiquidMenu stereo_menu(lcd);

/******************************************
   TRANSPOSE MENU
 ******************************************/
#define NUM_TRANSPOSE_MENUS 1
const char transpose_text1[] PROGMEM = "Transpose";
LiquidLine transpose_line1(1, 0, transpose_text1);
LiquidLine transpose_line2(1, 1, configuration.transpose);
LiquidScreen transpose_screen;
LiquidMenu transpose_menu(lcd);

/******************************************
   TUNE MENU
 ******************************************/
#define NUM_TUNE_MENUS 1
const char tune_text1[] PROGMEM = "Tune";
LiquidLine tune_line1(1, 0, tune_text1);
//LiquidLine tune_line2(1, 1, configuration.tune);
LiquidLine tune_line2(1, 1, get_tune_value_text);
LiquidScreen tune_screen;
LiquidMenu tune_menu(lcd);

/******************************************
   DETUNE MENU
 ******************************************/
#define NUM_DETUNE_MENUS 1
const char detune_text1[] PROGMEM = "Detune";
LiquidLine detune_line1(1, 0, detune_text1);
LiquidLine detune_line2(1, 1, configuration.detune);
LiquidScreen detune_screen;
LiquidMenu detune_menu(lcd);

/******************************************
   VELOCITY MENU
 ******************************************/
#define NUM_VELOCITY_MENUS 1
const char velocity_sense_text1[] PROGMEM = "Velocity Sense";
LiquidLine velocity_sense_line1(1, 0, velocity_sense_text1);
LiquidLine velocity_sense_line2(1, 1, configuration.velocity_sense);
LiquidScreen velocity_sense_screen;
LiquidMenu velocity_sense_menu(lcd);

/******************************************
   EFFECTS MENU
 ******************************************/
#define NUM_EFFECTS_MENUS 20
const char effects_text1[] PROGMEM = "Pan/Trem Freq.";
const char effects_text2[] PROGMEM = "Pan/Trem Level";
const char effects_text3[] PROGMEM = "Overdrive";
const char effects_text4[] PROGMEM = "Comp. Gain";
const char effects_text5[] PROGMEM = "Comp. Response";
const char effects_text6[] PROGMEM = "Comp. Limit";
const char effects_text7[] PROGMEM = "Comp. Threshold";
const char effects_text8[] PROGMEM = "Comp. Attack";
const char effects_text9[] PROGMEM = "Comp. Decay";
const char effects_text10[] PROGMEM = "Reverb Roomsize";
const char effects_text11[] PROGMEM = "Reverb Damping";
const char effects_text12[] PROGMEM = "Reverb Level";
const char effects_text13[] PROGMEM = "Chorus Freq.";
const char effects_text14[] PROGMEM = "Chorus Intens.";
const char effects_text15[] PROGMEM = "Chorus Waveform";
const char effects_text16[] PROGMEM = "Chorus Level";
const char effects_text17[] PROGMEM = "Bass LR Level";
const char effects_text18[] PROGMEM = "Bass M Level";
const char effects_text19[] PROGMEM = "EQ Bass";
const char effects_text20[] PROGMEM = "EQ Treble";
LiquidLine effects_line1(1, 0, effects_text1);
LiquidLine effects_line2(1, 1, effects_text2);
LiquidLine effects_line3(1, 1, effects_text3);
LiquidLine effects_line4(1, 1, effects_text4);
LiquidLine effects_line5(1, 1, effects_text5);
LiquidLine effects_line6(1, 1, effects_text6);
LiquidLine effects_line7(1, 1, effects_text7);
LiquidLine effects_line8(1, 1, effects_text8);
LiquidLine effects_line9(1, 1, effects_text9);
LiquidLine effects_line10(1, 1, effects_text10);
LiquidLine effects_line11(1, 1, effects_text11);
LiquidLine effects_line12(1, 1, effects_text12);
LiquidLine effects_line13(1, 1, effects_text13);
LiquidLine effects_line14(1, 1, effects_text14);
LiquidLine effects_line15(1, 1, effects_text15);
LiquidLine effects_line16(1, 1, effects_text16);
LiquidLine effects_line17(1, 1, effects_text17);
LiquidLine effects_line18(1, 1, effects_text18);
LiquidLine effects_line19(1, 1, effects_text19);
LiquidLine effects_line20(1, 1, effects_text20);
LiquidScreen effects_screen;
LiquidMenu effects_menu(lcd);

/******************************************
   PAN_TREM_FRQUENCY MENU
 ******************************************/
#define NUM_PAN_TREM_FRQUENCY_MENUS 1
const char pan_trem_frequency_text1[] PROGMEM = "PAN/Trem Freq.";
LiquidLine pan_trem_frequency_line1(1, 0, pan_trem_frequency_text1);
LiquidLine pan_trem_frequency_line2(1, 1, configuration.pan_trem_frequency);
LiquidScreen pan_trem_frequency_screen;
LiquidMenu pan_trem_frequency_menu(lcd);

/******************************************
   PAN_TREM_LEVEL MENU
 ******************************************/
#define NUM_PAN_TREM_LEVEL_MENUS 1
const char pan_trem_level_text1[] PROGMEM = "Pan/Trem Level";
LiquidLine pan_trem_level_line1(1, 0, pan_trem_level_text1);
LiquidLine pan_trem_level_line2(1, 1, configuration.pan_trem_level);
LiquidScreen pan_trem_level_screen;
LiquidMenu pan_trem_level_menu(lcd);

/******************************************
   OVERDRIVE MENU
 ******************************************/
#define NUM_OVERDRIVE_MENUS 1
const char overdrive_text1[] PROGMEM = "Overdrive";
LiquidLine overdrive_line1(1, 0, overdrive_text1);
LiquidLine overdrive_line2(1, 1, configuration.overdrive);
LiquidScreen overdrive_screen;
LiquidMenu overdrive_menu(lcd);

/******************************************
   COMP_GAIN MENU
 ******************************************/
#define NUM_COMP_GAIN_MENUS 1
const char comp_gain_text1[] PROGMEM = "Comp. Gain";
LiquidLine comp_gain_line1(1, 0, comp_gain_text1);
//LiquidLine comp_gain_line2(1, 1, configuration.comp_gain);
LiquidLine comp_gain_line2(1, 1, get_comp_gain_value_text);
LiquidScreen comp_gain_screen;
LiquidMenu comp_gain_menu(lcd);

/******************************************
   COMP_RESPONSE MENU
 ******************************************/
#define NUM_COMP_RESPONSE_MENUS 1
const char comp_response_text1[] PROGMEM = "Comp. Response";
LiquidLine comp_response_line1(1, 0, comp_response_text1);
LiquidLine comp_response_line2(1, 1, get_comp_response_value_text);
LiquidScreen comp_response_screen;
LiquidMenu comp_response_menu(lcd);

/******************************************
   COMP_LIMIT MENU
 ******************************************/
#define NUM_COMP_LIMIT_MENUS 1
const char comp_limit_text1[] PROGMEM = "Comp. Limit";
LiquidLine comp_limit_line1(1, 0, comp_limit_text1);
LiquidLine comp_limit_line2(1, 1, get_comp_limit_value_text);
LiquidScreen comp_limit_screen;
LiquidMenu comp_limit_menu(lcd);

/******************************************
   COMP_THRESHOLD MENU
 ******************************************/
#define NUM_COMP_THRESHOLD_MENUS 1
const char comp_threshold_text1[] PROGMEM = "Comp. Threshold";
LiquidLine comp_threshold_line1(1, 0, comp_threshold_text1);
LiquidLine comp_threshold_line2(1, 1, get_comp_threshold_value_text);
LiquidScreen comp_threshold_screen;
LiquidMenu comp_threshold_menu(lcd);

/******************************************
   COMP_ATTACK MENU
 ******************************************/
#define NUM_COMP_ATTACK_MENUS 1
const char comp_attack_text1[] PROGMEM = "Comp. Attack";
LiquidLine comp_attack_line1(1, 0, comp_attack_text1);
LiquidLine comp_attack_line2(1, 1, get_comp_attack_value_text);
LiquidScreen comp_attack_screen;
LiquidMenu comp_attack_menu(lcd);

/******************************************
   COMP_DECAY MENU
 ******************************************/
#define NUM_COMP_DECAY_MENUS 1
const char comp_decay_text1[] PROGMEM = "Comp. Decay";
LiquidLine comp_decay_line1(1, 0, comp_decay_text1);
//LiquidLine comp_decay_line2(1, 1, configuration.comp_decay);
LiquidLine comp_decay_line2(1, 1, get_comp_decay_value_text);
LiquidScreen comp_decay_screen;
LiquidMenu comp_decay_menu(lcd);

/******************************************
   REVERB_ROOMSIZE MENU
 ******************************************/
#define NUM_REVERB_ROOMSIZE_MENUS 1
const char reverb_roomsize_text1[] PROGMEM = "Reverb Roomsize";
LiquidLine reverb_roomsize_line1(1, 0, reverb_roomsize_text1);
LiquidLine reverb_roomsize_line2(1, 1, configuration.reverb_roomsize);
LiquidScreen reverb_roomsize_screen;
LiquidMenu reverb_roomsize_menu(lcd);

/******************************************
   REVERB_DAMPING MENU
 ******************************************/
#define NUM_REVERB_DAMPING_MENUS 1
const char reverb_damping_text1[] PROGMEM = "Reverb Damping";
LiquidLine reverb_damping_line1(1, 0, reverb_damping_text1);
LiquidLine reverb_damping_line2(1, 1, configuration.reverb_damping);
LiquidScreen reverb_damping_screen;
LiquidMenu reverb_damping_menu(lcd);

/******************************************
   REVERB_LEVEL MENU
 ******************************************/
#define NUM_REVERB_LEVEL_MENUS 1
const char reverb_level_text1[] PROGMEM = "Reverb Level";
LiquidLine reverb_level_line1(1, 0, reverb_level_text1);
LiquidLine reverb_level_line2(1, 1, configuration.reverb_level);
LiquidScreen reverb_level_screen;
LiquidMenu reverb_level_menu(lcd);

/******************************************
   CHORUS_FREQUENCY MENU
 ******************************************/
#define NUM_CHORUS_FREQUENCY_MENUS 1
const char chorus_frequency_text1[] PROGMEM = "Chorus Freq.";
LiquidLine chorus_frequency_line1(1, 0, chorus_frequency_text1);
LiquidLine chorus_frequency_line2(1, 1, get_chorus_frequency_value_text);
LiquidScreen chorus_frequency_screen;
LiquidMenu chorus_frequency_menu(lcd);

/******************************************
   CHORUS_INTENSITY MENU
 ******************************************/
#define NUM_CHORUS_INTENSITY_MENUS 1
const char chorus_intensity_text1[] PROGMEM = "Chorus Intens.";
LiquidLine chorus_intensity_line1(1, 0, chorus_intensity_text1);
LiquidLine chorus_intensity_line2(1, 1, configuration.chorus_intensity);
LiquidScreen chorus_intensity_screen;
LiquidMenu chorus_intensity_menu(lcd);

/******************************************
   CHORUS_WAVEFORM MENU
 ******************************************/
#define NUM_CHORUS_WAVEFORM_MENUS 1
const char chorus_waveform_text1[] PROGMEM = "Chorus Waveform";
LiquidLine chorus_waveform_line1(1, 0, chorus_waveform_text1);
LiquidLine chorus_waveform_line2(1, 1, get_chorus_waveform_value_text);
LiquidScreen chorus_waveform_screen;
LiquidMenu chorus_waveform_menu(lcd);

/******************************************
   CHORUS_LEVEL MENU
 ******************************************/
#define NUM_CHORUS_LEVEL_MENUS 1
const char chorus_level_text1[] PROGMEM = "Chorus Level";
LiquidLine chorus_level_line1(1, 0, chorus_level_text1);
LiquidLine chorus_level_line2(1, 1, configuration.chorus_level);
LiquidScreen chorus_level_screen;
LiquidMenu chorus_level_menu(lcd);

/******************************************
   BASS_LR_LEVEL MENU
 ******************************************/
#define NUM_BASS_LR_LEVEL_MENUS 1
const char bass_lr_level_text1[] PROGMEM = "Bass L/R Level";
LiquidLine bass_lr_level_line1(1, 0, bass_lr_level_text1);
LiquidLine bass_lr_level_line2(1, 1, configuration.bass_lr_level);
LiquidScreen bass_lr_level_screen;
LiquidMenu bass_lr_level_menu(lcd);

/******************************************
   BASS_MONO_LEVEL MENU
 ******************************************/
#define NUM_BASS_MONO_LEVEL_MENUS 1
const char bass_mono_level_text1[] PROGMEM = "Bass mono Level";
LiquidLine bass_mono_level_line1(1, 0, bass_mono_level_text1);
LiquidLine bass_mono_level_line2(1, 1, configuration.bass_mono_level);
LiquidScreen bass_mono_level_screen;
LiquidMenu bass_mono_level_menu(lcd);

/******************************************
   EQ_BASS MENU
 ******************************************/
#define NUM_EQ_BASS_MENUS 1
const char eq_bass_text1[] PROGMEM = "EQ Bass";
LiquidLine eq_bass_line1(1, 0, eq_bass_text1);
LiquidLine eq_bass_line2(1, 1, configuration.eq_bass);
LiquidScreen eq_bass_screen;
LiquidMenu eq_bass_menu(lcd);

/******************************************
   EQ_TREBLE MENU
 ******************************************/
#define NUM_EQ_TREBLE_MENUS 1
const char eq_treble_text1[] PROGMEM = "EQ Treble";
LiquidLine eq_treble_line1(1, 0, eq_treble_text1);
LiquidLine eq_treble_line2(1, 1, configuration.eq_treble);
LiquidScreen eq_treble_screen;
LiquidMenu eq_treble_menu(lcd);

/******************************************
   SAVE SOUND MENU
 ******************************************/
#define NUM_SAVE_SOUNDS_MENUS 2
const char save_sound_text1[] PROGMEM = "Save Sound";
LiquidLine save_sound_line1(1, 0, save_sound_text1);
LiquidLine save_sound_line2(1, 1, sound);
LiquidScreen save_sound_screen;
LiquidMenu save_sound_menu(lcd);

/******************************************
   SYSTEM MENU
 ******************************************/
#define NUM_SYSTEM_MENUS 6
const char system_text1[] PROGMEM = "Loudness";
const char system_text2[] PROGMEM = "MIDI Channel";
const char system_text3[] PROGMEM = "MIDI Soft-Thru";
const char system_text4[] PROGMEM = "Max. Polyphony";
const char system_text5[] PROGMEM = "Mono/Stereo";
const char system_text6[] PROGMEM = "Panorama";
LiquidLine system_line1(1, 0, system_text1);
LiquidLine system_line2(1, 1, system_text2);
LiquidLine system_line3(1, 1, system_text3);
LiquidLine system_line4(1, 1, system_text4);
LiquidLine system_line5(1, 1, system_text5);
LiquidLine system_line6(1, 1, system_text6);
LiquidScreen system_screen;
LiquidMenu system_menu(lcd);

/******************************************
   LOUDNESS MENU
 ******************************************/
#define NUM_LOUDNESS_MENUS 1
const char loudness_text1[] PROGMEM = "Loudness";
LiquidLine loudness_line1(1, 0, loudness_text1);
LiquidLine loudness_line2(1, 1, configuration.loudness);
LiquidScreen loudness_screen;
LiquidMenu loudness_menu(lcd);

/******************************************
   MIDI_CHANNEL MENU
 ******************************************/
#define NUM_MIDI_CHANNEL_MENUS 1
const char midi_channel_text1[] PROGMEM = "MIDI Channel";
LiquidLine midi_channel_line1(1, 0, midi_channel_text1);
LiquidLine midi_channel_line2(1, 1, get_midi_channel_value_text);
LiquidScreen midi_channel_screen;
LiquidMenu midi_channel_menu(lcd);

/******************************************
   MIDI_SOFT_THRU MENU
 ******************************************/
#define NUM_MIDI_SOFT_THRU_MENUS 1
const char midi_soft_thru_text1[] PROGMEM = "MIDI Soft Thru";
LiquidLine midi_soft_thru_line1(1, 0, midi_soft_thru_text1);
LiquidLine midi_soft_thru_line2(1, 1, get_midi_soft_thru_value_text);
LiquidScreen midi_soft_thru_screen;
LiquidMenu midi_soft_thru_menu(lcd);

/******************************************
   MAX_POLY MENU
 ******************************************/
#define NUM_MAX_POLY_MENUS 1
const char max_poly_text1[] PROGMEM = "Max. Polyphony";
LiquidLine max_poly_line1(1, 0, max_poly_text1);
LiquidLine max_poly_line2(1, 1, configuration.max_poly);
LiquidScreen max_poly_screen;
LiquidMenu max_poly_menu(lcd);

/******************************************
   MONO/STEREO MENU
 ******************************************/
#define NUM_MONO_MENUS 1
const char mono_text1[] PROGMEM = "Mono/Stereo";
LiquidLine mono_line1(1, 0, mono_text1);
LiquidLine mono_line2(1, 1, get_mono_value_text);
LiquidScreen mono_screen;
LiquidMenu mono_menu(lcd);

/******************************************
   PANORAMA MENU
 ******************************************/
#define NUM_PANORAMA_MENUS 1
const char panorama_text1[] PROGMEM = "Panorama";
LiquidLine panorama_line1(1, 0, panorama_text1);
LiquidLine panorama_line2(1, 1, configuration.pan);
LiquidScreen panorama_screen;
LiquidMenu panorama_menu(lcd);

/******************************************
   INFO MENU
 ******************************************/
#define NUM_INFO_MENUS 1
const char info_text1[] PROGMEM = "MicroMDAEPiano";
const char info_text2[] PROGMEM = MICRO_MDAEPIANO_VERSION;
LiquidLine info_line1(0, 0, info_text1);
LiquidLine info_line2(0, 1, info_text2);
LiquidScreen info_screen;
LiquidMenu info_menu(lcd);

/******************************************
  MASTER_VOLUME DISPLAY
 ******************************************/
const char master_volume_text1[] PROGMEM = "Master Volume";
LiquidLine master_volume_line1(1, 0, master_volume_text1);
LiquidLine master_volume_line2(1, 1, master_volume);
LiquidScreen master_volume_screen;
LiquidMenu master_volume_menu(lcd);

/******************************************
  STORE_QUESTION DISPLAY
 ******************************************/
const char store_question_text1[] PROGMEM = "Overwrite?";
LiquidLine store_question_line1(1, 0, store_question_text1);
LiquidLine store_question_line2(1, 1, get_yes_no_value_text);
LiquidScreen store_question_screen;
LiquidMenu store_question_menu(lcd);

/******************************************
   GLOBAL MENU OBJECTS
 ******************************************/
LiquidSystem menu_system;

/******************************************
   LOAD SOUND CALLBACKS
 ******************************************/
void callback_load_sound_function(void) {
#ifdef SHOW_DEBUG
  Serial.println(F("callback_load_sound_function"));
#endif
  menu_system.change_menu(load_sound_menu);
  menu_position[MAIN] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = sound;
  enc[RIGHT_ENCODER].write(sound, 1, MAX_SOUNDS);
  menu_system.update();
}

/******************************************
   EDIT SOUND CALLBACKS
 ******************************************/
void callback_edit_sound_function(void)
{
#ifdef SHOW_DEBUG
  Serial.print(F("callback_edit_sound_function, focus position:"));
  Serial.println(menu_position[EDIT_SOUND], DEC);
#endif
  menu_system.change_menu(edit_sound_menu);
  menu_system.set_focusPosition(Position::LEFT);
  menu_position[MAIN] = encoder_value[RIGHT_ENCODER];
  if (menu_position[EDIT_SOUND] < 0)
  {
    menu_position[EDIT_SOUND] = 0;
    encoder_value[RIGHT_ENCODER] = 0;
    enc[RIGHT_ENCODER].write(0, 0, NUM_EDIT_SOUND_MENUS - 1);
    menu_system.switch_focus();
  }
  else
  {
    encoder_value[RIGHT_ENCODER] = menu_position[EDIT_SOUND];
    enc[RIGHT_ENCODER].write(menu_position[EDIT_SOUND], 0, NUM_EDIT_SOUND_MENUS - 1);
  }
  menu_system.update();
}

void callback_decay_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_decay_function"));
#endif
  menu_system.change_menu(decay_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.decay;
  enc[RIGHT_ENCODER].write(configuration.decay, ENC_DECAY_MIN, ENC_DECAY_MAX);
  menu_system.update();
}

void callback_release_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_release_function"));
#endif
  menu_system.change_menu(release_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.release;
  enc[RIGHT_ENCODER].write(configuration.release, ENC_RELEASE_MIN, ENC_RELEASE_MAX);
  menu_system.update();
}

void callback_hardness_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_hardness_function"));
#endif
  menu_system.change_menu(hardness_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.hardness;
  enc[RIGHT_ENCODER].write(configuration.hardness, ENC_HARDNESS_MIN, ENC_HARDNESS_MAX);
  menu_system.update();
}

void callback_treble_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_treble_function"));
#endif
  menu_system.change_menu(treble_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.treble;
  enc[RIGHT_ENCODER].write(configuration.treble, ENC_TREBLE_MIN, ENC_TREBLE_MAX);
  menu_system.update();
}

void callback_stereo_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_stereo_function"));
#endif
  menu_system.change_menu(stereo_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.stereo;
  enc[RIGHT_ENCODER].write(configuration.stereo, ENC_STEREO_MIN, ENC_STEREO_MAX);
  menu_system.update();
}

void callback_transpose_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_transpose_function"));
#endif
  menu_system.change_menu(transpose_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.transpose;
  enc[RIGHT_ENCODER].write(configuration.transpose, ENC_TRANSPOSE_MIN, ENC_TRANSPOSE_MAX);
  menu_system.update();
}

void callback_tune_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_tune_function"));
#endif
  menu_system.change_menu(tune_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.tune;
  enc[RIGHT_ENCODER].write(configuration.tune, ENC_TUNE_MIN, ENC_TUNE_MAX);
  menu_system.update();
}

void callback_detune_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_detune_function"));
#endif
  menu_system.change_menu(detune_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.detune;
  enc[RIGHT_ENCODER].write(configuration.detune, ENC_DETUNE_MIN, ENC_DETUNE_MAX);
  menu_system.update();
}

void callback_velocity_sense_function(void)
{
#ifdef SHOW_DEBUG
  Serial.print(F("callback_velocity_sense_function"));
#endif
  menu_system.change_menu(velocity_sense_menu);
  menu_position[EDIT_SOUND] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.velocity_sense;
  enc[RIGHT_ENCODER].write(configuration.velocity_sense, ENC_VELOCITY_SENSE_MIN, ENC_VELOCITY_SENSE_MAX);
  menu_system.update();
}

/******************************************
   EFFECTS CALLBACKS
 ******************************************/
void callback_effect_function(void)
{
#ifdef SHOW_DEBUG
  Serial.print(F("callback_effect_function, focus position:"));
  Serial.println(menu_position[EFFECTS]);
#endif
  menu_system.change_menu(effects_menu);
  menu_system.set_focusPosition(Position::LEFT);
  menu_position[MAIN] = encoder_value[RIGHT_ENCODER];
  if (menu_position[EFFECTS] < 0)
  {
    menu_position[EFFECTS] = 0;
    encoder_value[RIGHT_ENCODER] = 0;
    enc[RIGHT_ENCODER].write(0, 0, NUM_EFFECTS_MENUS - 1);
    menu_system.switch_focus();
  }
  else
  {
    encoder_value[RIGHT_ENCODER] = menu_position[EFFECTS];
    enc[RIGHT_ENCODER].write(menu_position[EFFECTS], 0, NUM_EFFECTS_MENUS - 1);
  }
  menu_system.update();
}

void callback_pan_trem_frequency_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_pan_trem_frequency_function"));
#endif
  menu_system.change_menu(pan_trem_frequency_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.pan_trem_frequency;
  enc[RIGHT_ENCODER].write(configuration.pan_trem_frequency, ENC_PAN_TREM_FREQUENCY_MIN, ENC_PAN_TREM_FREQUENCY_MAX);
  menu_system.update();
}

void callback_pan_trem_level_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_pan_trem_level_function"));
#endif
  menu_system.change_menu(pan_trem_level_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.pan_trem_level;
  enc[RIGHT_ENCODER].write(configuration.pan_trem_level, ENC_PAN_TREM_LEVEL_MIN, ENC_PAN_TREM_LEVEL_MAX);
  menu_system.update();
}

void callback_overdrive_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_overdrive_function"));
#endif
  menu_system.change_menu(overdrive_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.overdrive;
  enc[RIGHT_ENCODER].write(configuration.overdrive, ENC_OVERDRIVE_MIN, ENC_OVERDRIVE_MAX);
  menu_system.update();
}

void callback_comp_gain_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_comp_gain_function"));
#endif
  menu_system.change_menu(comp_gain_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.comp_gain;
  enc[RIGHT_ENCODER].write(configuration.comp_gain, ENC_COMP_GAIN_MIN, ENC_COMP_GAIN_MAX);
  menu_system.update();
}

void callback_comp_response_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_comp_response_function"));
#endif
  menu_system.change_menu(comp_response_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.comp_response;
  enc[RIGHT_ENCODER].write(configuration.comp_response, ENC_COMP_RESPONSE_MIN, ENC_COMP_RESPONSE_MAX);
  menu_system.update();
}

void callback_comp_limit_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_comp_limit_function"));
#endif
  menu_system.change_menu(comp_limit_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.comp_limit;
  enc[RIGHT_ENCODER].write(configuration.comp_limit, ENC_COMP_LIMIT_MIN, ENC_COMP_LIMIT_MAX);
  menu_system.update();
}

void callback_comp_threshold_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_comp_threshold_function"));
#endif
  menu_system.change_menu(comp_threshold_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.comp_threshold;
  enc[RIGHT_ENCODER].write(configuration.comp_threshold, ENC_COMP_THRESHOLD_MIN, ENC_COMP_THRESHOLD_MAX);
  menu_system.update();
}

void callback_comp_attack_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_comp_attack_function"));
#endif
  menu_system.change_menu(comp_attack_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.comp_attack;
  enc[RIGHT_ENCODER].write(configuration.comp_attack, ENC_COMP_ATTACK_MIN, ENC_COMP_ATTACK_MAX);
  menu_system.update();
}

void callback_comp_decay_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_comp_decay_function"));
#endif
  menu_system.change_menu(comp_decay_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.comp_decay;
  enc[RIGHT_ENCODER].write(configuration.comp_decay, ENC_COMP_DECAY_MIN, ENC_COMP_DECAY_MAX);
  menu_system.update();
}

void callback_reverb_roomsize_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_reverb_roomsize_function"));
#endif
  menu_system.change_menu(reverb_roomsize_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.reverb_roomsize;
  enc[RIGHT_ENCODER].write(configuration.reverb_roomsize, ENC_REVERB_ROOMSIZE_MIN, ENC_REVERB_ROOMSIZE_MAX);
  menu_system.update();
}

void callback_reverb_damping_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_reverb_damping_function"));
#endif
  menu_system.change_menu(reverb_damping_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.reverb_damping;
  enc[RIGHT_ENCODER].write(configuration.reverb_damping, ENC_REVERB_DAMPING_MIN, ENC_REVERB_DAMPING_MAX);
  menu_system.update();
}

void callback_reverb_level_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_reverb_level_function"));
#endif
  menu_system.change_menu(reverb_level_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.reverb_level;
  enc[RIGHT_ENCODER].write(configuration.reverb_level, ENC_REVERB_LEVEL_MIN, ENC_REVERB_LEVEL_MAX);
  menu_system.update();
}

void callback_chorus_frequency_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_chorus_frequency_function"));
#endif
  menu_system.change_menu(chorus_frequency_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.chorus_frequency;
  enc[RIGHT_ENCODER].write(configuration.chorus_frequency, ENC_CHORUS_FREQUENCY_MIN, ENC_CHORUS_FREQUENCY_MAX);
  menu_system.update();
}

void callback_chorus_intensity_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_chorus_intensity_function"));
#endif
  menu_system.change_menu(chorus_intensity_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.chorus_intensity;
  enc[RIGHT_ENCODER].write(configuration.chorus_intensity, ENC_CHORUS_INTENSITY_MIN, ENC_CHORUS_INTENSITY_MAX);
  menu_system.update();
}

void callback_chorus_waveform_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_chorus_waveform_function"));
#endif
  menu_system.change_menu(chorus_waveform_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.chorus_waveform;
  enc[RIGHT_ENCODER].write(configuration.chorus_waveform, ENC_CHORUS_WAVEFORM_MIN, ENC_CHORUS_WAVEFORM_MAX);
  menu_system.update();
}

void callback_chorus_level_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_chorus_level_function"));
#endif
  menu_system.change_menu(chorus_level_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.chorus_level;
  enc[RIGHT_ENCODER].write(configuration.chorus_level, ENC_CHORUS_LEVEL_MIN, ENC_CHORUS_LEVEL_MAX);
  menu_system.update();
}

void callback_bass_lr_level_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_bass_lr_level_function"));
#endif
  menu_system.change_menu(bass_lr_level_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.bass_lr_level;
  enc[RIGHT_ENCODER].write(configuration.bass_lr_level, ENC_BASS_LR_LEVEL_MIN, ENC_BASS_LR_LEVEL_MAX);
  menu_system.update();
}

void callback_bass_mono_level_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_bass_mono_level_function"));
#endif
  menu_system.change_menu(bass_mono_level_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.bass_mono_level;
  enc[RIGHT_ENCODER].write(configuration.bass_mono_level, ENC_BASS_MONO_LEVEL_MIN, ENC_BASS_MONO_LEVEL_MAX);
  menu_system.update();
}

void callback_eq_bass_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_eq_bass_function"));
#endif
  menu_system.change_menu(eq_bass_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.eq_bass;
  enc[RIGHT_ENCODER].write(configuration.eq_bass, ENC_EQ_BASS_MIN, ENC_EQ_BASS_MAX);
  menu_system.update();
}

void callback_eq_treble_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_eq_treble_function"));
#endif
  menu_system.change_menu(eq_treble_menu);
  menu_position[EFFECTS] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.eq_treble;
  enc[RIGHT_ENCODER].write(configuration.eq_treble, ENC_EQ_TREBLE_MIN, ENC_EQ_TREBLE_MAX);
  menu_system.update();
}

/******************************************
   SAVE SOUND CALLBACKS
 ******************************************/
void callback_save_sound_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_save_sound_function"));
#endif
  menu_system.change_menu(save_sound_menu);
  menu_position[MAIN] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = sound;
  enc[RIGHT_ENCODER].write(sound, 1, MAX_SOUNDS);
  menu_system.update();
}

void callback_store_question_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_store_question_function"));
#endif
  menu_system.change_menu(store_question_menu);
  //menu_position[MAIN] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = yes_no;
  enc[RIGHT_ENCODER].write(yes_no, 0, 1);
  menu_system.update();
}
/******************************************
   SYSTEM MENU CALLBACKS
 ******************************************/
void callback_system_function(void)
{
#ifdef SHOW_DEBUG
  Serial.print(F("callback_system_function, focus position:"));
  Serial.println(menu_position[SYSTEM]);
#endif
  menu_system.change_menu(system_menu);
  menu_system.set_focusPosition(Position::LEFT);
  menu_position[MAIN] = encoder_value[RIGHT_ENCODER];
  if (menu_position[SYSTEM] < 0)
  {
    menu_position[SYSTEM] = 0;
    encoder_value[RIGHT_ENCODER] = 0;
    enc[RIGHT_ENCODER].write(0, 0, NUM_SYSTEM_MENUS - 1);
    menu_system.switch_focus();
  }
  else
  {
    encoder_value[RIGHT_ENCODER] = menu_position[SYSTEM];
    enc[RIGHT_ENCODER].write(menu_position[SYSTEM], 0, NUM_SYSTEM_MENUS - 1);
  }
  menu_system.update();
}

void callback_loudness_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_loudness_function"));
#endif
  menu_system.change_menu(loudness_menu);
  menu_position[SYSTEM] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.loudness;
  enc[RIGHT_ENCODER].write(configuration.loudness, ENC_LOUDNESS_MIN, ENC_LOUDNESS_MAX);
  menu_system.update();
}

void callback_midi_channel_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_midi_channel_function"));
#endif
  menu_system.change_menu(midi_channel_menu);
  menu_position[SYSTEM] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.midi_channel;
  enc[RIGHT_ENCODER].write(configuration.midi_channel, ENC_MIDI_CHANNEL_MIN, ENC_MIDI_CHANNEL_MAX);
  menu_system.update();
}

void callback_midi_soft_thru_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_midi_soft_thru_function"));
#endif
  menu_system.change_menu(midi_soft_thru_menu);
  menu_position[SYSTEM] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.midi_soft_thru;
  enc[RIGHT_ENCODER].write(configuration.midi_soft_thru, ENC_MIDI_SOFT_THRU_MIN, ENC_MIDI_SOFT_THRU_MAX);
  menu_system.update();
}

void callback_max_poly_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_max_poly_function"));
#endif
  menu_system.change_menu(max_poly_menu);
  menu_position[SYSTEM] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.max_poly;
  enc[RIGHT_ENCODER].write(configuration.max_poly, ENC_MAX_POLY_MIN, ENC_MAX_POLY_MAX);
  menu_system.update();
}

void callback_mono_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_mono_function"));
#endif
  menu_system.change_menu(mono_menu);
  menu_position[SYSTEM] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.mono;
  enc[RIGHT_ENCODER].write(configuration.mono, ENC_MONO_MIN, ENC_MONO_MAX);
  menu_system.update();
}

void callback_panorama_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_panorama_function"));
#endif
  menu_system.change_menu(panorama_menu);
  menu_position[SYSTEM] = encoder_value[RIGHT_ENCODER];
  encoder_value[RIGHT_ENCODER] = configuration.mono;
  enc[RIGHT_ENCODER].write(configuration.mono, ENC_MASTER_PAN_MIN, ENC_MASTER_PAN_MAX);
  menu_system.update();
}

/******************************************
   INFO MENU CALLBACKS
 ******************************************/
void callback_info_function(void)
{
#ifdef SHOW_DEBUG
  Serial.println(F("callback_info_function"));
#endif
  menu_system.change_menu(info_menu);
  menu_position[MAIN] = encoder_value[RIGHT_ENCODER];
  menu_system.update();
}

/******************************************
   HELPER MENU FUNCTION
 ******************************************/

float mapfloat(float val, float in_min, float in_max, float out_min, float out_max)
// e.g. mapfloat(float(effect_delay_feedback), 0, ENC_DELAY_FB_STEPS, 0.0, 1.0)
{
  return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void encoder_switch_focus(uint8_t encoder_last, uint8_t encoder_value)
{
  uint8_t i;
  int8_t diff;

  diff = encoder_value - encoder_last;

  for (i = 0; i < abs(diff); i++)
  {
    if (diff < 0)
      menu_system.switch_focus(true);
    else
      menu_system.switch_focus(false);
  }
}

void goto_main_menu(uint8_t menu_number)
{
  menu_position[menu_number] = enc[RIGHT_ENCODER].read();
  menu_system.change_menu(main_menu);
  menu_system.set_focusPosition(Position::LEFT);
  encoder_value[RIGHT_ENCODER] = menu_position[MAIN];
  enc[RIGHT_ENCODER].write(menu_position[MAIN], 0, NUM_MAIN_MENUS - 1);
}

void goto_edit_sound_menu(uint8_t menu_number)
{
  menu_position[menu_number] = enc[RIGHT_ENCODER].read();
  menu_system.change_menu(edit_sound_menu);
  menu_system.set_focusPosition(Position::LEFT);
  encoder_value[RIGHT_ENCODER] = menu_position[EDIT_SOUND];
  enc[RIGHT_ENCODER].write(menu_position[EDIT_SOUND], 0, NUM_EDIT_SOUND_MENUS - 1);
}

void goto_effects_menu(uint8_t menu_number)
{
  menu_position[menu_number] = enc[RIGHT_ENCODER].read();
  menu_system.change_menu(effects_menu);
  menu_system.set_focusPosition(Position::LEFT);
  encoder_value[RIGHT_ENCODER] = menu_position[EFFECTS];
  enc[RIGHT_ENCODER].write(menu_position[EFFECTS], 0, NUM_EFFECTS_MENUS - 1);
}

void goto_system_menu(uint8_t menu_number)
{
  menu_position[menu_number] = enc[RIGHT_ENCODER].read();
  menu_system.change_menu(system_menu);
  menu_system.set_focusPosition(Position::LEFT);
  encoder_value[RIGHT_ENCODER] = menu_position[SYSTEM];
  enc[RIGHT_ENCODER].write(menu_position[SYSTEM], 0, NUM_SYSTEM_MENUS - 1);
}

void goto_store_question_menu(uint8_t menu_number)
{
  menu_position[menu_number] = enc[RIGHT_ENCODER].read();
  menu_system.change_menu(store_question_menu);
  menu_system.set_focusPosition(Position::LEFT);
  //encoder_value[RIGHT_ENCODER] = menu_position[STORE_QUESTION];
  enc[RIGHT_ENCODER].write(menu_position[STORE_QUESTION], 0, 1);
}

/******************************************
   INIT MENU FUNCTION
 ******************************************/
void init_menus(void)
{
  uint8_t i;

  // LCD display setup
  lcd.init();
  lcd.blink_off();
  lcd.cursor_off();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("MicroMDAEPiano");
  lcd.setCursor(0, 1);
  lcd.print("(c)parasiTstudio");
  delay(1000);

  // setup main menu
  main_screen.add_line(main_line1);
  main_screen.add_line(main_line2);
  main_screen.add_line(main_line3);
  main_screen.add_line(main_line4);
  main_screen.add_line(main_line5);
  main_screen.add_line(main_line6);
  main_screen.set_displayLineCount(2);
  main_menu.add_screen(main_screen);

  main_line1.attach_function(LOAD_SOUND, callback_load_sound_function);
  main_line2.attach_function(EDIT_SOUND, callback_edit_sound_function);
  main_line3.attach_function(EFFECTS, callback_effect_function);
  main_line4.attach_function(SAVE_SOUND, callback_save_sound_function);
  main_line5.attach_function(SYSTEM, callback_system_function);
  main_line6.attach_function(INFO, callback_info_function);

  // setup load_sound menu
  load_sound_screen.add_line(load_sound_line1);
  load_sound_screen.add_line(load_sound_line2);
  load_sound_screen.set_displayLineCount(2);
  load_sound_menu.add_screen(load_sound_screen);

  // setup sound menu
  edit_sound_screen.add_line(edit_sound_line1);
  edit_sound_screen.add_line(edit_sound_line2);
  edit_sound_screen.add_line(edit_sound_line3);
  edit_sound_screen.add_line(edit_sound_line4);
  edit_sound_screen.add_line(edit_sound_line5);
  edit_sound_screen.add_line(edit_sound_line6);
  edit_sound_screen.add_line(edit_sound_line7);
  edit_sound_screen.add_line(edit_sound_line8);
  edit_sound_screen.add_line(edit_sound_line9);
  edit_sound_screen.set_displayLineCount(2);
  edit_sound_menu.add_screen(edit_sound_screen);

  edit_sound_line1.attach_function(DECAY, callback_decay_function);
  edit_sound_line2.attach_function(RELEASE, callback_release_function);
  edit_sound_line3.attach_function(HARDNESS, callback_hardness_function);
  edit_sound_line4.attach_function(TREBLE, callback_treble_function);
  edit_sound_line5.attach_function(STEREO_LEVEL, callback_stereo_function);
  edit_sound_line6.attach_function(TRANSPOSE, callback_transpose_function);
  edit_sound_line7.attach_function(TUNE, callback_tune_function);
  edit_sound_line8.attach_function(DETUNE, callback_detune_function);
  edit_sound_line9.attach_function(VELOCITY_SENSE, callback_velocity_sense_function);

  // setup decay menu
  decay_screen.add_line(decay_line1);
  decay_screen.add_line(decay_line2);
  decay_screen.set_displayLineCount(2);
  decay_menu.add_screen(decay_screen);

  // setup release menu
  release_screen.add_line(release_line1);
  release_screen.add_line(release_line2);
  release_screen.set_displayLineCount(2);
  release_menu.add_screen(release_screen);

  // setup hardness menu
  hardness_screen.add_line(hardness_line1);
  hardness_screen.add_line(hardness_line2);
  hardness_screen.set_displayLineCount(2);
  hardness_menu.add_screen(hardness_screen);

  // setup treble menu
  treble_screen.add_line(treble_line1);
  treble_screen.add_line(treble_line2);
  treble_screen.set_displayLineCount(2);
  treble_menu.add_screen(treble_screen);

  // setup stereo menu
  stereo_screen.add_line(stereo_line1);
  stereo_screen.add_line(stereo_line2);
  stereo_screen.set_displayLineCount(2);
  stereo_menu.add_screen(stereo_screen);

  // setup transpose menu
  transpose_screen.add_line(transpose_line1);
  transpose_screen.add_line(transpose_line2);
  transpose_screen.set_displayLineCount(2);
  transpose_menu.add_screen(transpose_screen);

  // setup tune menu
  tune_screen.add_line(tune_line1);
  tune_screen.add_line(tune_line2);
  tune_screen.set_displayLineCount(2);
  tune_menu.add_screen(tune_screen);

  // setup detune menu
  detune_screen.add_line(detune_line1);
  detune_screen.add_line(detune_line2);
  detune_screen.set_displayLineCount(2);
  detune_menu.add_screen(detune_screen);

  // setup velocity_sense menu
  velocity_sense_screen.add_line(velocity_sense_line1);
  velocity_sense_screen.add_line(velocity_sense_line2);
  velocity_sense_screen.set_displayLineCount(2);
  velocity_sense_menu.add_screen(velocity_sense_screen);

  // setup effects menu
  effects_screen.add_line(effects_line1);
  effects_screen.add_line(effects_line2);
  effects_screen.add_line(effects_line3);
  effects_screen.add_line(effects_line4);
  effects_screen.add_line(effects_line5);
  effects_screen.add_line(effects_line6);
  effects_screen.add_line(effects_line7);
  effects_screen.add_line(effects_line8);
  effects_screen.add_line(effects_line9);
  effects_screen.add_line(effects_line10);
  effects_screen.add_line(effects_line11);
  effects_screen.add_line(effects_line12);
  effects_screen.add_line(effects_line13);
  effects_screen.add_line(effects_line14);
  effects_screen.add_line(effects_line15);
  effects_screen.add_line(effects_line16);
  effects_screen.add_line(effects_line17);
  effects_screen.add_line(effects_line18);
  effects_screen.add_line(effects_line19);
  effects_screen.add_line(effects_line20);
  effects_screen.set_displayLineCount(2);
  effects_menu.add_screen(effects_screen);

  effects_line1.attach_function(PAN_TREM_FREQUENCY, callback_pan_trem_frequency_function);
  effects_line2.attach_function(PAN_TREM_LEVEL, callback_pan_trem_level_function);
  effects_line3.attach_function(OVERDRIVE, callback_overdrive_function);
  effects_line4.attach_function(COMP_GAIN, callback_comp_gain_function);
  effects_line5.attach_function(COMP_RESPONSE, callback_comp_response_function);
  effects_line6.attach_function(COMP_LIMIT, callback_comp_limit_function);
  effects_line7.attach_function(COMP_THRESHOLD, callback_comp_threshold_function);
  effects_line8.attach_function(COMP_ATTACK, callback_comp_attack_function);
  effects_line9.attach_function(COMP_DECAY, callback_comp_decay_function);
  effects_line10.attach_function(REV_ROOMSIZE, callback_reverb_roomsize_function);
  effects_line11.attach_function(REV_DAMPING, callback_reverb_damping_function);
  effects_line12.attach_function(REV_LEVEL, callback_reverb_level_function);
  effects_line13.attach_function(CHORUS_FREQ, callback_chorus_frequency_function);
  effects_line14.attach_function(CHORUS_INTENSITY, callback_chorus_intensity_function);
  effects_line15.attach_function(CHORUS_WAVEFORM, callback_chorus_waveform_function);
  effects_line16.attach_function(CHORUS_LEVEL, callback_chorus_level_function);
  effects_line17.attach_function(BASS_LR_LEVEL, callback_bass_lr_level_function);
  effects_line18.attach_function(BASS_MONO_LEVEL, callback_bass_mono_level_function);
  effects_line19.attach_function(EQ_BASS, callback_eq_bass_function);
  effects_line20.attach_function(EQ_TREBLE, callback_eq_treble_function);

  // setup pan_trem_frequency menu
  pan_trem_frequency_screen.add_line(pan_trem_frequency_line1);
  pan_trem_frequency_screen.add_line(pan_trem_frequency_line2);
  pan_trem_frequency_screen.set_displayLineCount(2);
  pan_trem_frequency_menu.add_screen(pan_trem_frequency_screen);

  // setup pan_trem_level menu
  pan_trem_level_screen.add_line(pan_trem_level_line1);
  pan_trem_level_screen.add_line(pan_trem_level_line2);
  pan_trem_level_screen.set_displayLineCount(2);
  pan_trem_level_menu.add_screen(pan_trem_level_screen);

  // setup overdrive menu
  overdrive_screen.add_line(overdrive_line1);
  overdrive_screen.add_line(overdrive_line2);
  overdrive_screen.set_displayLineCount(2);
  overdrive_menu.add_screen(overdrive_screen);

  // setup comp_gain menu
  comp_gain_screen.add_line(comp_gain_line1);
  comp_gain_screen.add_line(comp_gain_line2);
  comp_gain_screen.set_displayLineCount(2);
  comp_gain_menu.add_screen(comp_gain_screen);

  // setup comp_response menu
  comp_response_screen.add_line(comp_response_line1);
  comp_response_screen.add_line(comp_response_line2);
  comp_response_screen.set_displayLineCount(2);
  comp_response_menu.add_screen(comp_response_screen);

  // setup comp_limit menu
  comp_limit_screen.add_line(comp_limit_line1);
  comp_limit_screen.add_line(comp_limit_line2);
  comp_limit_screen.set_displayLineCount(2);
  comp_limit_menu.add_screen(comp_limit_screen);

  // setup comp_threshold menu
  comp_threshold_screen.add_line(comp_threshold_line1);
  comp_threshold_screen.add_line(comp_threshold_line2);
  comp_threshold_screen.set_displayLineCount(2);
  comp_threshold_menu.add_screen(comp_threshold_screen);

  // setup comp_attack menu
  comp_attack_screen.add_line(comp_attack_line1);
  comp_attack_screen.add_line(comp_attack_line2);
  comp_attack_screen.set_displayLineCount(2);
  comp_attack_menu.add_screen(comp_attack_screen);

  // setup comp_decay menu
  comp_decay_screen.add_line(comp_decay_line1);
  comp_decay_screen.add_line(comp_decay_line2);
  comp_decay_screen.set_displayLineCount(2);
  comp_decay_menu.add_screen(comp_decay_screen);

  // setup reverb_roomsize menu
  reverb_roomsize_screen.add_line(reverb_roomsize_line1);
  reverb_roomsize_screen.add_line(reverb_roomsize_line2);
  reverb_roomsize_screen.set_displayLineCount(2);
  reverb_roomsize_menu.add_screen(reverb_roomsize_screen);

  // setup reverb_damping menu
  reverb_damping_screen.add_line(reverb_damping_line1);
  reverb_damping_screen.add_line(reverb_damping_line2);
  reverb_damping_screen.set_displayLineCount(2);
  reverb_damping_menu.add_screen(reverb_damping_screen);

  // setup reverb_level menu
  reverb_level_screen.add_line(reverb_level_line1);
  reverb_level_screen.add_line(reverb_level_line2);
  reverb_level_screen.set_displayLineCount(2);
  reverb_level_menu.add_screen(reverb_level_screen);

  // setup chorus_frequency menu
  chorus_frequency_screen.add_line(chorus_frequency_line1);
  chorus_frequency_screen.add_line(chorus_frequency_line2);
  chorus_frequency_screen.set_displayLineCount(2);
  chorus_frequency_menu.add_screen(chorus_frequency_screen);

  // setup chorus_intensity menu
  chorus_intensity_screen.add_line(chorus_intensity_line1);
  chorus_intensity_screen.add_line(chorus_intensity_line2);
  chorus_intensity_screen.set_displayLineCount(2);
  chorus_intensity_menu.add_screen(chorus_intensity_screen);

  // setup chorus_waveform menu
  chorus_waveform_screen.add_line(chorus_waveform_line1);
  chorus_waveform_screen.add_line(chorus_waveform_line2);
  chorus_waveform_screen.set_displayLineCount(2);
  chorus_waveform_menu.add_screen(chorus_waveform_screen);

  // setup chorus_level menu
  chorus_level_screen.add_line(chorus_level_line1);
  chorus_level_screen.add_line(chorus_level_line2);
  chorus_level_screen.set_displayLineCount(2);
  chorus_level_menu.add_screen(chorus_level_screen);

  // setup bass_lr_level menu
  bass_lr_level_screen.add_line(bass_lr_level_line1);
  bass_lr_level_screen.add_line(bass_lr_level_line2);
  bass_lr_level_screen.set_displayLineCount(2);
  bass_lr_level_menu.add_screen(bass_lr_level_screen);

  // setup bass_mono_level menu
  bass_mono_level_screen.add_line(bass_mono_level_line1);
  bass_mono_level_screen.add_line(bass_mono_level_line2);
  bass_mono_level_screen.set_displayLineCount(2);
  bass_mono_level_menu.add_screen(bass_mono_level_screen);

  // setup eq_bass menu
  eq_bass_screen.add_line(eq_bass_line1);
  eq_bass_screen.add_line(eq_bass_line2);
  eq_bass_screen.set_displayLineCount(2);
  eq_bass_menu.add_screen(eq_bass_screen);

  // setup eq_treble menu
  eq_treble_screen.add_line(eq_treble_line1);
  eq_treble_screen.add_line(eq_treble_line2);
  eq_treble_screen.set_displayLineCount(2);
  eq_treble_menu.add_screen(eq_treble_screen);

  // setup save_sound menu
  save_sound_screen.add_line(save_sound_line1);
  save_sound_screen.add_line(save_sound_line2);
  save_sound_screen.set_displayLineCount(2);
  save_sound_menu.add_screen(save_sound_screen);

  // setup store_question display
  store_question_line1.attach_function(STORE_QUESTION, callback_store_question_function);

  store_question_screen.add_line(store_question_line1);
  store_question_screen.add_line(store_question_line2);
  store_question_screen.set_displayLineCount(2);
  store_question_menu.add_screen(store_question_screen);

  // setup system menu
  system_screen.add_line(system_line1);
  system_screen.add_line(system_line2);
  system_screen.add_line(system_line3);
  system_screen.add_line(system_line4);
  system_screen.add_line(system_line5);
  system_screen.add_line(system_line6);
  system_screen.set_displayLineCount(2);
  system_menu.add_screen(system_screen);

  system_line1.attach_function(LOUDNESS, callback_loudness_function);
  system_line2.attach_function(MIDI_CHANNEL, callback_midi_channel_function);
  system_line3.attach_function(MIDI_SOFT_THRU, callback_midi_soft_thru_function);
  system_line4.attach_function(MAX_POLY, callback_max_poly_function);
  system_line5.attach_function(MONO, callback_mono_function);
  system_line6.attach_function(PANORAMA, callback_panorama_function);

  // setup loudness
  loudness_screen.add_line(loudness_line1);
  loudness_screen.add_line(loudness_line2);
  loudness_screen.set_displayLineCount(2);
  loudness_menu.add_screen(loudness_screen);

  // setup midi_channel
  midi_channel_screen.add_line(midi_channel_line1);
  midi_channel_screen.add_line(midi_channel_line2);
  midi_channel_screen.set_displayLineCount(2);
  midi_channel_menu.add_screen(midi_channel_screen);

  // setup midi_soft_thru
  midi_soft_thru_screen.add_line(midi_soft_thru_line1);
  midi_soft_thru_screen.add_line(midi_soft_thru_line2);
  midi_soft_thru_screen.set_displayLineCount(2);
  midi_soft_thru_menu.add_screen(midi_soft_thru_screen);

  // setup max_poly
  max_poly_screen.add_line(max_poly_line1);
  max_poly_screen.add_line(max_poly_line2);
  max_poly_screen.set_displayLineCount(2);
  max_poly_menu.add_screen(max_poly_screen);

  // setup mono
  mono_screen.add_line(mono_line1);
  mono_screen.add_line(mono_line2);
  mono_screen.set_displayLineCount(2);
  mono_menu.add_screen(mono_screen);

  // setup panorama
  panorama_screen.add_line(panorama_line1);
  panorama_screen.add_line(panorama_line2);
  panorama_screen.set_displayLineCount(2);
  panorama_menu.add_screen(panorama_screen);

  // setup info menu
  info_screen.add_line(info_line1);
  info_screen.add_line(info_line2);
  info_screen.set_displayLineCount(2);
  info_menu.add_screen(info_screen);

  // setup master_volume display
  master_volume_screen.add_line(master_volume_line1);
  master_volume_screen.add_line(master_volume_line2);
  master_volume_screen.set_displayLineCount(2);
  master_volume_menu.add_screen(master_volume_screen);

  // setup global system menu
  menu_system.add_menu(main_menu);
  menu_system.add_menu(load_sound_menu);
  menu_system.add_menu(edit_sound_menu);
  menu_system.add_menu(effects_menu);
  menu_system.add_menu(decay_menu);
  menu_system.add_menu(release_menu);
  menu_system.add_menu(hardness_menu);
  menu_system.add_menu(treble_menu);
  menu_system.add_menu(stereo_menu);
  menu_system.add_menu(transpose_menu);
  menu_system.add_menu(tune_menu);
  menu_system.add_menu(detune_menu);
  menu_system.add_menu(velocity_sense_menu);
  menu_system.add_menu(effects_menu);
  menu_system.add_menu(pan_trem_frequency_menu);
  menu_system.add_menu(pan_trem_level_menu);
  menu_system.add_menu(overdrive_menu);
  menu_system.add_menu(comp_gain_menu);
  menu_system.add_menu(comp_response_menu);
  menu_system.add_menu(comp_limit_menu);
  menu_system.add_menu(comp_threshold_menu);
  menu_system.add_menu(comp_attack_menu);
  menu_system.add_menu(comp_decay_menu);
  menu_system.add_menu(reverb_roomsize_menu);
  menu_system.add_menu(reverb_damping_menu);
  menu_system.add_menu(reverb_level_menu);
  menu_system.add_menu(chorus_frequency_menu);
  menu_system.add_menu(chorus_intensity_menu);
  menu_system.add_menu(chorus_waveform_menu);
  menu_system.add_menu(chorus_level_menu);
  menu_system.add_menu(bass_lr_level_menu);
  menu_system.add_menu(bass_mono_level_menu);
  menu_system.add_menu(eq_bass_menu);
  menu_system.add_menu(eq_treble_menu);
  menu_system.add_menu(save_sound_menu);
  menu_system.add_menu(store_question_menu);
  menu_system.add_menu(system_menu);
  menu_system.add_menu(loudness_menu);
  menu_system.add_menu(midi_channel_menu);
  menu_system.add_menu(midi_soft_thru_menu);
  menu_system.add_menu(max_poly_menu);
  menu_system.add_menu(mono_menu);
  menu_system.add_menu(panorama_menu);
  menu_system.add_menu(info_menu);
  menu_system.add_menu(master_volume_menu);

  menu_system.set_focusPosition(Position::LEFT);
  menu_system.switch_focus();
  menu_system.update();
  for ( i = 0; i < NUM_MENUS; i++)
    menu_position[i] = -1;
  menu_position[MAIN] = 0;

  // setup encoder
  for (i = 0; i < NUM_ENCODER; i++)
    but[i].update();
  master_volume = EEPROM.read(EEPROM_MASTER_VOLUME);
  enc[LEFT_ENCODER].write(master_volume, ENC_MASTER_VOLUME_MIN, ENC_MASTER_VOLUME_MAX);
  encoder_value[LEFT_ENCODER] = master_volume;
  enc[RIGHT_ENCODER].write(0, 0, NUM_MAIN_MENUS - 1);
  encoder_value[RIGHT_ENCODER] = 0;
}

void load_sound(void)
{
#ifdef SHOW_DEBUG
  Serial.print(F("Load sound "));
  Serial.println(sound, DEC);
#endif
  EEPROM.update(EEPROM_SOUND, sound);
  config_from_eeprom();
}

void save_sound(void)
{
#ifdef SHOW_DEBUG
  Serial.print(F("Save sound "));
  Serial.println(sound);
#endif
  eeprom_config_write(sound);
  yes_no = false;
}

void set_decay(uint8_t value)
{
  if (value > ENC_DECAY_MAX)
    value = ENC_DECAY_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set DECAY "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_DECAY_MIN, ENC_DECAY_MAX, 0.0, 1.0);
  ep.setDecay(tmp);
  configuration.decay = value;
}

void set_release(uint8_t value)
{
  if (value > ENC_RELEASE_MAX)
    value = ENC_RELEASE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set RELEASE "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_RELEASE_MIN, ENC_RELEASE_MAX, 0.0, 1.0);
  ep.setRelease(tmp);
  configuration.release = value;
}

void set_hardness(uint8_t value)
{
  if (value > ENC_HARDNESS_MAX)
    value = ENC_HARDNESS_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set HARDNESS "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_HARDNESS_MIN, ENC_HARDNESS_MAX, 0.0, 1.0);
  ep.setHardness(tmp);
  configuration.hardness = value;
}

void set_treble(uint8_t value)
{
  if (value > ENC_TREBLE_MAX)
    value = ENC_TREBLE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set TREBLE "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_TREBLE_MIN, ENC_TREBLE_MAX, 0.0, 1.0);
  ep.setTreble(tmp);
  configuration.treble = value;
}

void set_stereo(uint8_t value)
{
  if (value > ENC_STEREO_MAX)
    value = ENC_STEREO_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set STEREO "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_STEREO_MIN, ENC_STEREO_MAX, 0.0, 1.0);
  ep.setStereo(tmp);
  configuration.stereo = value;
}

void set_transpose(int8_t value)
{
  if (value < ENC_TRANSPOSE_MIN)
    value = ENC_TRANSPOSE_MIN;
  if (value > ENC_TRANSPOSE_MAX)
    value = ENC_TRANSPOSE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set TRANSPOSE "));
  Serial.println(value);
#endif
  // Nothing special todo, because value will be added inside NoteOn/NoteOff
  configuration.transpose = value;
}

void set_tune(int8_t value)
{
  if (value < ENC_TUNE_MIN)
    value = ENC_TUNE_MIN;
  if (value > ENC_TUNE_MAX)
    value = ENC_TUNE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set TUNE "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_TUNE_MIN, ENC_TUNE_MAX, 0.0, 1.0);
  ep.setTune(tmp);
  configuration.tune = value;
}

void set_detune(uint8_t value)
{
  if (value > ENC_DETUNE_MAX)
    value = ENC_DETUNE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set DETUNE "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_DETUNE_MIN, ENC_DETUNE_MAX, 0.0, 1.0);
  ep.setDetune(tmp);
  configuration.detune = value;
}

void set_velocity_sense(uint8_t value)
{
  if (value > ENC_VELOCITY_SENSE_MAX)
    value = ENC_VELOCITY_SENSE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set VELOCITY_SENSE "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_VELOCITY_SENSE_MIN, ENC_VELOCITY_SENSE_MAX, 0.0, 1.0);
  ep.setVelocitySense(tmp);
  configuration.velocity_sense = value;
}

void set_pan_trem_frequency(int8_t value)
{
  if (value > ENC_PAN_TREM_FREQUENCY_MAX)
    value = ENC_PAN_TREM_FREQUENCY_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set PAN_TREM_FREQENCY "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_PAN_TREM_FREQUENCY_MIN, ENC_PAN_TREM_FREQUENCY_MAX, 0.0, 1.0);
  ep.setPanLFO(tmp);
  configuration.pan_trem_frequency = value;
}

void set_pan_trem_level(uint8_t value)
{
  if (value > ENC_PAN_TREM_LEVEL_MAX)
    value = ENC_PAN_TREM_LEVEL_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set PAN_TREM_LEVEL "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_PAN_TREM_LEVEL_MIN, ENC_PAN_TREM_LEVEL_MAX, 0.0, 1.0);
  ep.setPanTremolo(tmp);
  configuration.pan_trem_level = value;
}

void set_overdrive(uint8_t value)
{
  if (value > ENC_OVERDRIVE_MAX)
    value = ENC_OVERDRIVE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set OVERDRIVE "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_OVERDRIVE_MIN, ENC_OVERDRIVE_MAX, 0.0, 1.0);
  ep.setOverdrive(tmp);
  configuration.overdrive = value;
}

void set_comp_gain(uint8_t value)
{
  if (value > ENC_COMP_GAIN_MAX)
    value = ENC_COMP_GAIN_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set COMP_GAIN "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_COMP_GAIN_MIN, ENC_COMP_GAIN_MAX, 0.0, 1.0);
  sgtl5000_1.autoVolumeControl(tmp, configuration.comp_response, configuration.comp_limit, (float)configuration.comp_threshold, (float)configuration.comp_attack / 10, (float)configuration.comp_decay / 10); // maxGain, response, hardLimit, threshold, attack, decay, e.g.: 1, 1, 1, 0.9, 0.01, 0.05
  configuration.comp_gain = value;
}

void set_comp_response(uint8_t value)
{
  if (value > ENC_COMP_RESPONSE_MAX)
    value = ENC_COMP_RESPONSE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set COMP_RESPONSE "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_COMP_RESPONSE_MIN, ENC_COMP_RESPONSE_MAX, 0.0, 1.0);
  sgtl5000_1.autoVolumeControl(configuration.comp_gain, tmp, configuration.comp_limit, (float)configuration.comp_threshold, (float)configuration.comp_attack / 10, (float)configuration.comp_decay / 10); // maxGain, response, hardLimit, threshold, attack, decay, e.g.: 1, 1, 1, 0.9, 0.01, 0.05
  configuration.comp_response = value;
}

void set_comp_limit(uint8_t value)
{
  if (value > ENC_COMP_LIMIT_MAX)
    value = ENC_COMP_LIMIT_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set COMP_LIMIT "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_COMP_LIMIT_MIN, ENC_COMP_LIMIT_MAX, 0.0, 1.0);
  sgtl5000_1.autoVolumeControl(configuration.comp_gain, configuration.comp_response, tmp, (float)configuration.comp_threshold, (float)configuration.comp_attack / 10, (float)configuration.comp_decay / 10); // maxGain, response, hardLimit, threshold, attack, decay, e.g.: 1, 1, 1, 0.9, 0.01, 0.05
  configuration.comp_limit = value;
}

void set_comp_threshold(uint8_t value)
{
  if (value > ENC_COMP_THRESHOLD_MAX)
    value = ENC_COMP_THRESHOLD_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set COMP_THRESHOLD "));
  Serial.println(value);
#endif
  //float tmp = mapfloat(float(value), ENC_COMP_THRESHOLD_MIN, ENC_COMP_THRESHOLD_MAX, 0.0, 1.0);
  sgtl5000_1.autoVolumeControl(configuration.comp_gain, configuration.comp_response, configuration.comp_limit, (float)value, (float)configuration.comp_attack / 10, (float)configuration.comp_decay / 10); // maxGain, response, hardLimit, threshold, attack, decay, e.g.: 1, 1, 1, 0.9, 0.01, 0.05
  configuration.comp_threshold = value;
}

void set_comp_attack(uint8_t value)
{
  if (value > ENC_COMP_ATTACK_MAX)
    value = ENC_COMP_ATTACK_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set COMP_ATTACK "));
  Serial.println(value);
#endif
  //float tmp = mapfloat(float(value), ENC_COMP_ATTACK_MIN, ENC_COMP_ATTACK_MAX, 0.0, 1.0);
  sgtl5000_1.autoVolumeControl(configuration.comp_gain, configuration.comp_response, configuration.comp_limit, (float)configuration.comp_threshold, (float)value / 10, (float)configuration.comp_decay / 10); // maxGain, response, hardLimit, threshold, attack, decay, e.g.: 1, 1, 1, 0.9, 0.01, 0.05
  configuration.comp_attack = value;
}

void set_comp_decay(uint8_t value)
{
  if (value > ENC_COMP_DECAY_MAX)
    value = ENC_COMP_DECAY_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set COMP_DECAY "));
  Serial.println(value);
#endif
  //float tmp = mapfloat(float(value), ENC_COMP_DECAY_MIN, ENC_COMP_DECAY_MAX, 0.0, 1.0);
  sgtl5000_1.autoVolumeControl(configuration.comp_gain, configuration.comp_response, configuration.comp_limit, (float)configuration.comp_threshold, (float)configuration.comp_attack / 10, (float)value / 10); // maxGain, response, hardLimit, threshold, attack, decay, e.g.: 1, 1, 1, 0.9, 0.01, 0.05
  configuration.comp_decay = value;
}

void set_reverb_roomsize(uint8_t value)
{
  if (value > ENC_REVERB_ROOMSIZE_MAX)
    value = ENC_REVERB_ROOMSIZE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set REVERB_ROOMSIZE "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_REVERB_ROOMSIZE_MIN, ENC_REVERB_ROOMSIZE_MAX, 0.0, 1.0);
  freeverb_r.roomsize(tmp);
  freeverb_l.roomsize(tmp);
  configuration.reverb_roomsize = value;
}

void set_reverb_damping(uint8_t value)
{
  if (value > ENC_REVERB_DAMPING_MAX)
    value = ENC_REVERB_DAMPING_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set REVERB_DAMPING "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_REVERB_DAMPING_MIN, ENC_REVERB_DAMPING_MAX, 0.0, 1.0);
  freeverb_r.damping(tmp);
  freeverb_l.damping(tmp);
  configuration.reverb_damping = value;
}

void set_reverb_level(uint8_t value)
{
  if (value > ENC_REVERB_LEVEL_MAX)
    value = ENC_REVERB_LEVEL_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set REVERB_LEVEL "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_REVERB_LEVEL_MIN, ENC_REVERB_LEVEL_MAX, 0.0, 1.0);
  mixer_r.gain(1, tmp);
  mixer_l.gain(1, tmp);
  configuration.reverb_level = value;
}

void set_chorus_frequency(uint8_t value)
{
  if (value > ENC_CHORUS_FREQUENCY_MAX)
    value = ENC_CHORUS_FREQUENCY_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set CHORUS_FREQUENCY "));
  Serial.println(value);
#endif
  modulator.frequency(float(value) / 10);
  configuration.chorus_frequency = value;
}

void set_chorus_intensity(uint8_t value)
{
  if (value > ENC_CHORUS_INTENSITY_MAX)
    value = ENC_CHORUS_INTENSITY_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set CHORUS_INTENSITY "));
  Serial.println(value);
#endif
  modulator.amplitude(mapfloat(float(value), ENC_CHORUS_INTENSITY_MIN, ENC_CHORUS_INTENSITY_MAX, 0.0, 1.0));
  configuration.chorus_intensity = value;
}

void set_chorus_waveform(uint8_t value)
{
#ifdef SHOW_DEBUG
  Serial.print(F("Set CHORUS_WAVEFORM "));
#endif
  switch (value)
  {
    case 1:
      modulator.begin(WAVEFORM_TRIANGLE);
      break;
    case 2:
      modulator.begin(WAVEFORM_SINE);
      break;
    default:
      modulator.begin(WAVEFORM_TRIANGLE);
      value = 1;
      break;
  }
  configuration.chorus_waveform = value;
  Serial.println(value);
}

void set_chorus_level(uint8_t value)
{
  if (value > ENC_CHORUS_LEVEL_MAX)
    value = ENC_CHORUS_LEVEL_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set CHORUS_LEVEL "));
  Serial.println(value);
#endif
  float tmp = mapfloat(float(value), ENC_CHORUS_LEVEL_MIN, ENC_CHORUS_LEVEL_MAX, 0.0, 0.5);
  mixer_r.gain(0, 1.0 - tmp);
  mixer_l.gain(0, 1.0 - tmp);
  mixer_r.gain(2, tmp);
  mixer_l.gain(2, tmp);
  configuration.chorus_level = value;
}

void set_bass_lr_level(uint8_t value)
{
  if (value > ENC_BASS_MONO_LEVEL_MAX)
    value = ENC_BASS_MONO_LEVEL_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set BASS_LR_LEVEL "));
  Serial.println(value);
#endif
  float tmp1 = mapfloat(float(value), ENC_BASS_LR_LEVEL_MIN, ENC_BASS_LR_LEVEL_MAX, 0.0, 1.0);
  float tmp2 = mapfloat(float(configuration.bass_mono_level), ENC_BASS_MONO_LEVEL_MIN, ENC_BASS_MONO_LEVEL_MAX, 0.0, 1.0);
  sgtl5000_1.enhanceBass(tmp1, tmp2);
  configuration.bass_lr_level = value;
}

void set_bass_mono_level(uint8_t value)
{
  if (value > ENC_BASS_LR_LEVEL_MAX)
    value = ENC_BASS_LR_LEVEL_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set BASS_MONO_LEVEL "));
  Serial.println(value);
#endif
  float tmp1 = mapfloat(float(configuration.bass_lr_level), ENC_BASS_LR_LEVEL_MIN, ENC_BASS_LR_LEVEL_MAX, 0.0, 1.0);
  float tmp2 = mapfloat(float(value), ENC_BASS_MONO_LEVEL_MIN, ENC_BASS_MONO_LEVEL_MAX, 0.0, 1.0);
  sgtl5000_1.enhanceBass(tmp1, tmp2);
  configuration.bass_mono_level = value;
}

void set_eq_bass(int8_t value)
{
  if (value > ENC_EQ_TREBLE_MAX)
    value = ENC_EQ_TREBLE_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set EQ_BASS "));
  Serial.println(value);
#endif
  float tmp1 = mapfloat(float(value), ENC_EQ_BASS_MIN, ENC_EQ_BASS_MAX, -1.0, 1.0);
  float tmp2 = mapfloat(float(configuration.eq_treble), ENC_EQ_TREBLE_MIN, ENC_EQ_TREBLE_MAX, -1.0, 1.0);
  sgtl5000_1.eqBands(tmp1, tmp2);
  configuration.eq_bass = value;
}

void set_eq_treble(int8_t value)
{
  if (value > ENC_EQ_BASS_MAX )
    value = ENC_EQ_BASS_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set EQ_TREBLE "));
  Serial.println(value);
#endif
  float tmp1 = mapfloat(float(configuration.eq_bass), ENC_EQ_BASS_MIN, ENC_EQ_BASS_MAX, -1.0, 1.0);
  float tmp2 = mapfloat(float(value), ENC_EQ_TREBLE_MIN, ENC_EQ_TREBLE_MAX, -1.0, 1.0);
  sgtl5000_1.eqBands(tmp1, tmp2);
  configuration.eq_treble = value;
}

void set_loudness(uint8_t value)
{
  if (value > ENC_LOUDNESS_MAX)
    value = ENC_LOUDNESS_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set LOUDNESS "));
  Serial.println(value);
#endif
  ep.setLoudness(mapfloat(float(value), ENC_LOUDNESS_MIN, ENC_LOUDNESS_MAX, 0.0, 1.0));
  //volume_r.gain(tmp);
  //volume_l.gain(tmp);
  configuration.loudness = value;
}

void set_midi_channel(uint8_t value)
{
  if (value > 16)
    value = 16;
#ifdef SHOW_DEBUG
  Serial.print(F("Set MIDI_CHANNEL "));
  Serial.println(value);
#endif
  configuration.midi_channel = value;
}

void set_midi_soft_thru(uint8_t value)
{
  if (value > 1)
    value = 1;
#ifdef SHOW_DEBUG
  Serial.print(F("Set MIDI_SOFT_THRU "));
  Serial.println(value);
#endif
  configuration.midi_soft_thru = value;
}

void set_max_poly(uint8_t value)
{
  if (value > ENC_MAX_POLY_MAX)
    value = ENC_MAX_POLY_MAX;
#ifdef SHOW_DEBUG
  Serial.print(F("Set MAX_POLY "));
  Serial.println(value);
#endif
  ep.setMaxPolyphony(value);
  configuration.max_poly = value;
  ep.reset_voices();
}

void set_mono(uint8_t mode)
{
#ifdef SHOW_DEBUG
  Serial.print(F("Set MONO "));
  Serial.println(mode);
#endif
  configuration.mono = mode;
  if (mode == 0)
  {
    // stereo
    ep.setStereo(mapfloat(float(configuration.stereo), ENC_STEREO_MIN, ENC_STEREO_MAX, 0.0, 1.0));
    inverter.gain(-1.0); // change phase for second modulated delay (faked stereo mode)
  }
  else
  {
    // mono
    ep.setStereo(0.0);
    inverter.gain(1.0);
    set_master_volume(master_volume);
  }
}

void set_panorama(uint8_t value)
{
  if (value < ENC_MASTER_PAN_MIN)
    value = ENC_MASTER_PAN_MIN;
  if (value > ENC_MASTER_PAN_MAX)
#ifdef SHOW_DEBUG
  Serial.print(F("Set MASTER_PANORAMA "));
  Serial.println(value);
#endif
  configuration.pan = value;
  set_master_volume(master_volume);
}

void set_complete_configuration(void)
{
  set_decay(configuration.decay);
  set_release(configuration.release);
  set_hardness(configuration.hardness);
  set_treble(configuration.treble);
  set_stereo(configuration.stereo);
  set_tune(configuration.tune);
  set_detune(configuration.detune);
  set_velocity_sense(configuration.velocity_sense);
  set_pan_trem_frequency(configuration.pan_trem_frequency);
  set_pan_trem_level(configuration.pan_trem_level);
  set_overdrive(configuration.overdrive);
  set_comp_gain(configuration.comp_gain);
  set_comp_response(configuration.comp_response);
  set_comp_limit(configuration.comp_limit);
  set_comp_threshold(configuration.comp_threshold);
  set_comp_attack(configuration.comp_attack);
  set_comp_decay(configuration.comp_decay);
  set_reverb_roomsize(configuration.reverb_roomsize);
  set_reverb_damping(configuration.reverb_damping);
  set_reverb_level(configuration.reverb_level);
  set_chorus_frequency(configuration.chorus_frequency);
  set_chorus_intensity(configuration.chorus_intensity);
  set_chorus_waveform(configuration.chorus_waveform);
  set_chorus_level(configuration.chorus_level);
  set_bass_lr_level(configuration.bass_lr_level);
  set_bass_mono_level(configuration.bass_mono_level);
  set_eq_bass(configuration.eq_bass);
  set_eq_treble(configuration.eq_treble);
  set_loudness(configuration.loudness);
  set_midi_channel(configuration.midi_channel);
  set_midi_soft_thru(configuration.midi_soft_thru);
  set_max_poly(configuration.max_poly);
  set_mono(configuration.mono);
  set_panorama(configuration.pan);
}

//********************************************************************************************+
void handle_ui(void)
{
  uint8_t i;
  int32_t encoder_tmp;

  if (back_to_main > BACK_TO_MAIN_MS && menu_system.get_currentScreen() == &master_volume_screen)
  {
    {
#ifdef SHOW_DEBUG
      Serial.println(F("from master_volume to main"));
#endif
      goto_main_menu(MASTER_VOLUME);
    }
  }

  for (i = 0; i < NUM_ENCODER; i++)
  {
    but[i].update();

    switch (i)
    {
      case RIGHT_ENCODER:
        // Encoder handling
        encoder_tmp = enc[RIGHT_ENCODER].read();

        if (menu_system.get_currentScreen() == &load_sound_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            sound = encoder_tmp;
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &decay_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_decay(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &release_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_release(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &hardness_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_hardness(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &treble_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_treble(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &stereo_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_stereo(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &transpose_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_transpose(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &tune_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_tune(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &detune_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_detune(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &velocity_sense_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_velocity_sense(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &pan_trem_frequency_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_pan_trem_frequency(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &pan_trem_level_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_pan_trem_level(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &overdrive_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_overdrive(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &comp_gain_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_comp_gain(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &comp_response_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_comp_response(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &comp_limit_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_comp_limit(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &comp_threshold_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_comp_threshold(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &comp_attack_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_comp_attack(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &comp_decay_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_comp_decay(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &reverb_roomsize_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_reverb_roomsize(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &reverb_damping_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_reverb_damping(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &reverb_level_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_reverb_level(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &chorus_frequency_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_chorus_frequency(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &chorus_intensity_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_chorus_intensity(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &chorus_waveform_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_chorus_waveform(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &chorus_level_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_chorus_level(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &bass_lr_level_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_bass_lr_level(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &bass_mono_level_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_bass_mono_level(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &eq_bass_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_eq_bass(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &eq_treble_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_eq_treble(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &save_sound_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            sound = encoder_tmp;
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &store_question_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            yes_no = encoder_tmp;
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &loudness_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_loudness(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &midi_channel_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_midi_channel(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &midi_soft_thru_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_midi_soft_thru(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &max_poly_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_max_poly(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &mono_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_mono(encoder_tmp);
            menu_system.update();
          }
        }
        else if (menu_system.get_currentScreen() == &panorama_screen)
        {
          if (encoder_tmp != encoder_value[RIGHT_ENCODER])
          {
            // value up/down
            set_panorama(encoder_tmp);
            menu_system.update();
          }
        }
        else
        {
          // Move menu focus
          if (encoder_tmp > encoder_value[RIGHT_ENCODER])
          {
            // move down
#ifdef SHOW_DEBUG
            Serial.print(F("ENC-R-DOWN: "));
            Serial.println(encoder_tmp);
#endif
            encoder_switch_focus(encoder_tmp, encoder_value[RIGHT_ENCODER]);
            menu_system.softUpdate();
          }
          else if (encoder_tmp < encoder_value[RIGHT_ENCODER])
          {
            // move up
#ifdef SHOW_DEBUG
            Serial.print(F("ENC-R-UP: "));
            Serial.println(encoder_tmp);
#endif
            encoder_switch_focus(encoder_tmp, encoder_value[RIGHT_ENCODER]);
            menu_system.softUpdate();
          }
        }
        encoder_value[RIGHT_ENCODER] = encoder_tmp;

        // button handling
        if (but[i].fallingEdge()) // SELECT
        {
#ifdef SHOW_DEBUG
          Serial.println(F("SELECT-R"));
#endif

          if (menu_system.get_currentScreen() == &load_sound_screen)
          {
            // load sound
#ifdef SHOW_DEBUG
            Serial.print("Load sound ");
            Serial.println();
#endif
            load_sound();
            goto_main_menu(LOAD_SOUND);
          }
          else if (menu_system.get_currentScreen() == &save_sound_screen)
          {
            // ask for storing sound
#ifdef SHOW_DEBUG
            Serial.print("Storing sound?");
            Serial.println();
#endif
            goto_store_question_menu(SAVE_SOUND);
          }
          else if (menu_system.get_currentScreen() == &store_question_screen)
          {
            // save sound
            if (encoder_tmp == 1)
            {
#ifdef SHOW_DEBUG
              Serial.print(F("Save sound "));
              Serial.println(sound, DEC);
#endif
              save_sound();
            }
#ifdef SHOW_DEBUG
            else
              Serial.println(F("Not saving sound!"));
#endif
            goto_main_menu(SAVE_SOUND);
          }
          else
          {
            uint8_t menu_callback_offset = 0;

            if (menu_system.get_currentScreen() == &edit_sound_screen)
              menu_callback_offset = NUM_MAIN_MENUS;
            else if (menu_system.get_currentScreen() == &effects_screen)
              menu_callback_offset = NUM_MAIN_MENUS + NUM_EDIT_SOUND_MENUS;
            else if (menu_system.get_currentScreen() == &system_screen)
              menu_callback_offset = NUM_MAIN_MENUS + NUM_EDIT_SOUND_MENUS + NUM_EFFECTS_MENUS;

#ifdef SHOW_DEBUG
            Serial.print(F("Starting callback number "));
            Serial.println(encoder_value[RIGHT_ENCODER] + menu_callback_offset, DEC);
            Serial.print(F("encoder_value[RIGHT_ENCODER]="));
            Serial.print(encoder_value[RIGHT_ENCODER], DEC);
            Serial.print(F(" menu_callback_offset="));
            Serial.println(menu_callback_offset, DEC);
#endif

            if (menu_system.is_callable(encoder_value[RIGHT_ENCODER] + 1 + menu_callback_offset))
            {
              // change menu
              menu_system.call_function(encoder_value[RIGHT_ENCODER] + 1 + menu_callback_offset);
              //menu_system.update();
            }
#ifdef SHOW_DEBUG
            else
            {
              Serial.print(F("No callback for "));
              Serial.println(encoder_value[RIGHT_ENCODER] + 1 + menu_callback_offset, DEC);
            }
#endif
          }
        }
        break;
      case LEFT_ENCODER:
        // Encoder handling
        encoder_tmp = enc[LEFT_ENCODER].read();

        // Change volume
        if (encoder_tmp > encoder_value[LEFT_ENCODER])
        {
          // move down
#ifdef SHOW_DEBUG
          Serial.print(F("ENC-L-DOWN: "));
          Serial.println(encoder_tmp);
#endif
        }
        else if (encoder_tmp < encoder_value[LEFT_ENCODER])
        {
          // move up
#ifdef SHOW_DEBUG
          Serial.print(F("ENC-L-UP: "));
          Serial.println(encoder_tmp);
#endif
        }
        if (encoder_tmp != encoder_value[LEFT_ENCODER])
        {
          master_volume = encoder_tmp;
          set_master_volume(master_volume);
#ifdef SHOW_DEBUG
          Serial.print(F("master_volume: "));
          Serial.println(master_volume);
#endif
          menu_system.change_menu(master_volume_menu);
          menu_system.update();
          back_to_main = 0;
        }
        encoder_value[LEFT_ENCODER] = encoder_tmp;

        // button handling
        if (but[i].fallingEdge()) // BACK
        {
#ifdef SHOW_DEBUG
          Serial.print("Back press detected: ");
#endif
          if (menu_system.get_currentScreen() == &load_sound_screen) // load_sound menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from load_sound to main"));
#endif
            goto_main_menu(LOAD_SOUND);
          }
          else if (menu_system.get_currentScreen() == &edit_sound_screen) // sound menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from edit_sound to main"));
#endif
            goto_main_menu(EDIT_SOUND);

          }
          else if (menu_system.get_currentScreen() == &decay_screen) // decay menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from decay to edit_sound"));
#endif
            goto_edit_sound_menu(DECAY);
          }
          else if (menu_system.get_currentScreen() == &release_screen) // release menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from release to edit_sound"));
#endif
            goto_edit_sound_menu(RELEASE);
          }
          else if (menu_system.get_currentScreen() == &hardness_screen) // hardness menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from hardness to edit_sound"));
#endif
            goto_edit_sound_menu(HARDNESS);
          }
          else if (menu_system.get_currentScreen() == &treble_screen) // treble menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from treble to edit_sound"));
#endif
            goto_edit_sound_menu(TREBLE);
          }
          else if (menu_system.get_currentScreen() == &stereo_screen) // stereo menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from stereo to edit_sound"));
#endif
            goto_edit_sound_menu(STEREO_LEVEL);
          }
          else if (menu_system.get_currentScreen() == &transpose_screen) // transpose menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from transpose to edit_sound"));
#endif
            goto_edit_sound_menu(TRANSPOSE);
          }
          else if (menu_system.get_currentScreen() == &tune_screen) // tune menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from tune to edit_sound"));
#endif
            goto_edit_sound_menu(TUNE);
          }
          else if (menu_system.get_currentScreen() == &detune_screen) // detune menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from detune to edit_sound"));
#endif
            goto_edit_sound_menu(DETUNE);
          }
          else if (menu_system.get_currentScreen() == &velocity_sense_screen) // velocity_sense menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from velocity_sense to edit_sound"));
#endif
            goto_edit_sound_menu(VELOCITY_SENSE);
          }
          else if (menu_system.get_currentScreen() == &effects_screen) // effect menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from effect to main"));
#endif
            goto_main_menu(EFFECTS);
          }
          else if (menu_system.get_currentScreen() == &pan_trem_frequency_screen) //pan_trem_frequency  menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from pan_trem_frequency to effects"));
#endif
            goto_effects_menu(PAN_TREM_FREQUENCY);
          }
          else if (menu_system.get_currentScreen() == &pan_trem_level_screen) // pan_trem_level menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from pan_trem_level to effects"));
#endif
            goto_effects_menu(PAN_TREM_LEVEL);
          }
          else if (menu_system.get_currentScreen() == &overdrive_screen) // overdrive menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from overdrive to effects"));
#endif
            goto_effects_menu(OVERDRIVE);
          }
          else if (menu_system.get_currentScreen() == &comp_gain_screen) // comp_gain menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from comp_gain to effects"));
#endif
            goto_effects_menu(COMP_GAIN);
          }
          else if (menu_system.get_currentScreen() == &comp_response_screen) // comp_response menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from comp_response to effects"));
#endif
            goto_effects_menu(COMP_RESPONSE);
          }
          else if (menu_system.get_currentScreen() == &comp_limit_screen) // comp_limit menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from  comp_limit to effects"));
#endif
            goto_effects_menu(COMP_LIMIT);
          }
          else if (menu_system.get_currentScreen() == &comp_threshold_screen) // comp_threshold menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from comp_threshold to effects"));
#endif
            goto_effects_menu(COMP_THRESHOLD);
          }
          else if (menu_system.get_currentScreen() == &comp_attack_screen) // comp_attack menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from comp_attack to effects"));
#endif
            goto_effects_menu(COMP_ATTACK);
          }
          else if (menu_system.get_currentScreen() == &comp_decay_screen) // comp_decay menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from comp_decay to effects"));
#endif
            goto_effects_menu(COMP_DECAY);
          }
          else if (menu_system.get_currentScreen() == &reverb_roomsize_screen) // reverb_roomsize menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from reverb_roomsize to effects"));
#endif
            goto_effects_menu(REV_ROOMSIZE);
          }
          else if (menu_system.get_currentScreen() == &reverb_damping_screen) // reverb_damping menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from reverb_damping to effects"));
#endif
            goto_effects_menu(REV_DAMPING);
          }
          else if (menu_system.get_currentScreen() == &reverb_level_screen) // reverb_level menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from reverb_level to effects"));
#endif
            goto_effects_menu(REV_LEVEL);
          }
          else if (menu_system.get_currentScreen() == &chorus_frequency_screen) // chorus_frequency menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from chorus_frequency to effects"));
#endif
            goto_effects_menu(CHORUS_FREQ);
          }
          else if (menu_system.get_currentScreen() == &chorus_intensity_screen) // chorus_intensity menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from chorus_intensity to effects"));
#endif
            goto_effects_menu(CHORUS_INTENSITY);
          }
          else if (menu_system.get_currentScreen() == &chorus_waveform_screen) // chorus_waveform menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from chorus_waveform to effects"));
#endif
            goto_effects_menu(CHORUS_WAVEFORM);
          }
          else if (menu_system.get_currentScreen() == &chorus_level_screen) // chorus_level menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from chorus_level to effects"));
#endif
            goto_effects_menu(CHORUS_LEVEL);
          }
          else if (menu_system.get_currentScreen() == &bass_lr_level_screen) // bass_lr_level menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from bass_lr_level to effects"));
#endif
            goto_effects_menu(BASS_LR_LEVEL);
          }
          else if (menu_system.get_currentScreen() == &bass_mono_level_screen) // bass_mono_level menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from bass_mono_level to effects"));
#endif
            goto_effects_menu(BASS_MONO_LEVEL);
          }
          else if (menu_system.get_currentScreen() == &eq_bass_screen) // eq_bass menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from eq_bass to effects"));
#endif
            goto_effects_menu(EQ_BASS);
          }
          else if (menu_system.get_currentScreen() == &eq_treble_screen) // eq_treble menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from eq_treble to main"));
#endif
            goto_effects_menu(EQ_TREBLE);
          }
          else if (menu_system.get_currentScreen() == &save_sound_screen) // save_sound menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from save_sound to main"));
#endif
            goto_main_menu(SAVE_SOUND);
          }
          else if (menu_system.get_currentScreen() == &store_question_screen) // store_question menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from store_question to main"));
#endif
            goto_main_menu(SAVE_SOUND);
          }
          else if (menu_system.get_currentScreen() == &system_screen) // system menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from system to main"));
#endif
            goto_main_menu(SYSTEM);
          }
          else if (menu_system.get_currentScreen() == &loudness_screen) // loudness menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from loudness to system"));
#endif
            goto_system_menu(LOUDNESS);
          }
          else if (menu_system.get_currentScreen() == &midi_channel_screen) // midi_channel menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from midi_channel to system"));
#endif
            goto_system_menu(MIDI_CHANNEL);
          }
          else if (menu_system.get_currentScreen() == &midi_soft_thru_screen) // midi_soft_thru menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from midi_soft_thru to system"));
#endif
            goto_system_menu(MIDI_SOFT_THRU);
          }
          else if (menu_system.get_currentScreen() == &max_poly_screen) // max_poly menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from max_poly to system"));
#endif
            goto_system_menu(MAX_POLY);
          }
          else if (menu_system.get_currentScreen() == &mono_screen) // mono menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from mono to system"));
#endif
            goto_system_menu(MONO);
          }
          else if (menu_system.get_currentScreen() == &panorama_screen) // panorama menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from panorama to system"));
#endif
            goto_system_menu(PANORAMA);
          }
          else if (menu_system.get_currentScreen() == &info_screen) // info menu
          {
#ifdef SHOW_DEBUG
            Serial.println(F("from info to main"));
#endif
            goto_main_menu(INFO);
          }
        }
    }
  }
}
#endif
