Added switching logic between voice and menu.

Added autotmatic volume screen for left encoder (right/left).
pull/3/head
Holger Wirtz 5 years ago
parent 19cf6d9275
commit 1d4c19e49c
  1. 88
      LiquidCrystalPlus_I2C.h
  2. 10
      MicroDexed.ino
  3. 157
      UI.hpp
  4. 3
      config.h
  5. 1
      dexed.h

@ -0,0 +1,88 @@
/*
MicroDexed
MicroDexed is a port of the Dexed sound engine
(https://github.com/asb2m10/dexed) for the Teensy-3.5/3.6 with audio shield.
Dexed ist heavily based on https://github.com/google/music-synthesizer-for-android
(c)2018 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
*/
#include <LiquidCrystal_I2C.h> // https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c
#ifndef LIQUIDCRYSTALPLUS_I2C_H_INCLUDED
#define LIQUIDCRYSTALPLUS_I2C_H_INCLUDED
#define STRING_BUFFER_SIZE 21
class LiquidCrystalPlus_I2C : public LiquidCrystal_I2C
{
public:
using LiquidCrystal_I2C::LiquidCrystal_I2C;
void show(uint8_t y, uint8_t x, uint8_t fs, char *str)
{
_show(y, x, fs, str, false, false);
}
void show(uint8_t y, uint8_t x, uint8_t fs, long num)
{
char _buf10[STRING_BUFFER_SIZE];
_show(y, x, fs, itoa(num, _buf10, 10), true, true);
}
private:
void _show(uint8_t pos_y, uint8_t pos_x, uint8_t field_size, char *str, bool justify_right, bool fill_zero)
{
{
char tmp[STRING_BUFFER_SIZE];
char *s = tmp;
uint8_t l = strlen(str);
memset(tmp, 0, sizeof(tmp));
if (fill_zero == true)
memset(tmp, '0', field_size);
else
memset(tmp, 0x20, field_size - 1); // blank
if (l > field_size)
l = field_size;
if (justify_right == true)
s += field_size - l;
strncpy(s, str, l);
setCursor(pos_x, pos_y);
print(tmp);
#ifdef DEBUG
Serial.print(pos_y, DEC);
Serial.print(F("/"));
Serial.print(pos_x, DEC);
Serial.print(F(": ["));
Serial.print(tmp);
Serial.println(F("]"));
#endif
}
}
};
#endif

@ -110,8 +110,9 @@ value_change_t soften_filter_cut = {0.0, 0};
/*********************************************************************** /***********************************************************************
LCDMenuLib2 LCDMenuLib2
***********************************************************************/ ***********************************************************************/
extern LiquidCrystal_I2C lcd; extern LiquidCrystalPlus_I2C lcd;
extern LCDMenuLib2 LCDML; extern LCDMenuLib2 LCDML;
extern uint8_t menu_state;
#endif #endif
void setup() void setup()
@ -338,6 +339,13 @@ void loop()
#ifdef ENABLE_LCD_UI #ifdef ENABLE_LCD_UI
// LCD Menu // LCD Menu
LCDML.loop(); LCDML.loop();
// initial starts voice selection menu as default
if (menu_state == MENU_START)
{
menu_state = MENU_VOICE;
UI_func_voice_selection(0);
}
#endif #endif
control_rate = 0; control_rate = 0;

157
UI.hpp

@ -27,7 +27,7 @@
#define _UI_HPP_ #define _UI_HPP_
#include "config.h" #include "config.h"
#include <LiquidCrystal_I2C.h> #include "LiquidCrystalPlus_I2C.h"
#include <LCDMenuLib2.h> #include <LCDMenuLib2.h>
#include <Encoder.h> #include <Encoder.h>
@ -37,10 +37,20 @@
#define _LCDML_DISP_cfg_cursor 0x7E // cursor Symbol #define _LCDML_DISP_cfg_cursor 0x7E // cursor Symbol
#define _LCDML_DISP_cfg_scrollbar 1 // enable a scrollbar #define _LCDML_DISP_cfg_scrollbar 1 // enable a scrollbar
extern config_t configuration;
void set_volume(float v, float p);
extern char bank_names[MAX_BANKS][BANK_NAME_LEN];
extern char bank_name[BANK_NAME_LEN];
extern char voice_name[VOICE_NAME_LEN];
extern char voice_names[MAX_VOICES][VOICE_NAME_LEN];
extern void strip_extension(char* s, char *target);
/*********************************************************************** /***********************************************************************
GLOBAL GLOBAL
***********************************************************************/ ************************************************************************/
LiquidCrystal_I2C lcd(0x27, _LCDML_DISP_cols, _LCDML_DISP_rows); elapsedMillis back_from_volume;
LiquidCrystalPlus_I2C lcd(LCD_I2C_ADDRESS, _LCDML_DISP_cols, _LCDML_DISP_rows);
const uint8_t scroll_bar[5][8] = { const uint8_t scroll_bar[5][8] = {
{B10001, B10001, B10001, B10001, B10001, B10001, B10001, B10001}, // scrollbar top {B10001, B10001, B10001, B10001, B10001, B10001, B10001, B10001}, // scrollbar top
@ -51,8 +61,8 @@ const uint8_t scroll_bar[5][8] = {
}; };
enum { ENC_R, ENC_L }; enum { ENC_R, ENC_L };
enum { MENU_VOICE, MENU_EDIT}; enum { MENU_START, MENU_VOICE, MENU_EDIT, MENU_VOLUME };
uint8_t menu_state = MENU_EDIT; uint8_t menu_state = MENU_START;
void lcdml_menu_display(void); void lcdml_menu_display(void);
void lcdml_voice_menu_display(void); void lcdml_voice_menu_display(void);
@ -79,6 +89,7 @@ void UI_func_polyphony(uint8_t param);
void UI_func_engine(uint8_t param); void UI_func_engine(uint8_t param);
void UI_func_information(uint8_t param); void UI_func_information(uint8_t param);
void UI_func_voice_selection(uint8_t param); void UI_func_voice_selection(uint8_t param);
void UI_func_volume(uint8_t param);
void UI_func_back(uint8_t param); void UI_func_back(uint8_t param);
void UI_func_goToRootMenu(uint8_t param); void UI_func_goToRootMenu(uint8_t param);
@ -121,8 +132,8 @@ LCDML_createMenu(_LCDML_DISP_cnt);
/*********************************************************************** /***********************************************************************
CONTROL CONTROL
***********************************************************************/ ***********************************************************************/
#define g_LCDML_CONTROL_button_long_press 800 // ms #define g_LCDML_CONTROL_button_long_press LONG_BUTTON_PRESS
#define g_LCDML_CONTROL_button_short_press 40 // ms #define g_LCDML_CONTROL_button_short_press BUT_DEBOUNCE_MS
//#define ENCODER_OPTIMIZE_INTERRUPTS //Only when using pin2/3 (or 20/21 on mega) //#define ENCODER_OPTIMIZE_INTERRUPTS //Only when using pin2/3 (or 20/21 on mega)
Encoder ENCODER[NUM_ENCODER] = {Encoder(ENC_R_PIN_B, ENC_R_PIN_A), Encoder(ENC_L_PIN_B, ENC_L_PIN_A)}; Encoder ENCODER[NUM_ENCODER] = {Encoder(ENC_R_PIN_B, ENC_R_PIN_A), Encoder(ENC_L_PIN_B, ENC_L_PIN_A)};
@ -140,11 +151,19 @@ void lcdml_menu_control(void)
pinMode(BUT_L_PIN, INPUT_PULLUP); pinMode(BUT_L_PIN, INPUT_PULLUP);
} }
if (back_from_volume > BACK_FROM_VOLUME_MS && menu_state == MENU_VOLUME)
{
UI_func_voice_selection(0);
return;
}
//Volatile Variable //Volatile Variable
long g_LCDML_CONTROL_Encoder_position[NUM_ENCODER] = {ENCODER[ENC_R].read(), ENCODER[ENC_L].read()}; long g_LCDML_CONTROL_Encoder_position[NUM_ENCODER] = {ENCODER[ENC_R].read(), ENCODER[ENC_L].read()};
bool button[NUM_ENCODER] = {digitalRead(BUT_R_PIN), digitalRead(BUT_L_PIN)}; bool button[NUM_ENCODER] = {digitalRead(BUT_R_PIN), digitalRead(BUT_L_PIN)};
// Right encoder /************************************************************************************
Right encoder
************************************************************************************/
if (g_LCDML_CONTROL_Encoder_position[ENC_R] <= -3) if (g_LCDML_CONTROL_Encoder_position[ENC_R] <= -3)
{ {
if (!button[ENC_R]) if (!button[ENC_R])
@ -155,8 +174,19 @@ void lcdml_menu_control(void)
} }
else else
{ {
if (menu_state == MENU_EDIT) switch (menu_state)
{
case MENU_EDIT:
case MENU_VOLUME:
menu_state = MENU_EDIT;
LCDML.BT_down(); LCDML.BT_down();
break;
case MENU_VOICE:
#ifdef DEBUG
Serial.println(F("State: MENU_VOICE, Encoder left down"));
break;
#endif
}
} }
ENCODER[ENC_R].write(g_LCDML_CONTROL_Encoder_position[ENC_R] + 4); ENCODER[ENC_R].write(g_LCDML_CONTROL_Encoder_position[ENC_R] + 4);
} }
@ -171,8 +201,19 @@ void lcdml_menu_control(void)
} }
else else
{ {
if (menu_state == MENU_EDIT) switch (menu_state)
{
case MENU_EDIT:
case MENU_VOLUME:
menu_state = MENU_EDIT;
LCDML.BT_up(); LCDML.BT_up();
break;
case MENU_VOICE:
#ifdef DEBUG
Serial.println(F("State: MENU_VOICE, Encoder left up"));
break;
#endif
}
} }
ENCODER[ENC_R].write(g_LCDML_CONTROL_Encoder_position[ENC_R] - 4); ENCODER[ENC_R].write(g_LCDML_CONTROL_Encoder_position[ENC_R] - 4);
} }
@ -195,15 +236,36 @@ void lcdml_menu_control(void)
else if ((millis() - g_LCDML_CONTROL_button_press_time[ENC_R]) >= g_LCDML_CONTROL_button_long_press) else if ((millis() - g_LCDML_CONTROL_button_press_time[ENC_R]) >= g_LCDML_CONTROL_button_long_press)
{ {
LCDML.BT_quit(); LCDML.BT_quit();
if (menu_state == MENU_EDIT)
{
LCDML.BT_quit();
}
else if (menu_state == MENU_VOICE)
{
#ifdef DEBUG
Serial.println(F("State: MENU_VOICE, button long press"));
#endif
}
} }
else if ((millis() - g_LCDML_CONTROL_button_press_time[ENC_R]) >= g_LCDML_CONTROL_button_short_press) else if ((millis() - g_LCDML_CONTROL_button_press_time[ENC_R]) >= g_LCDML_CONTROL_button_short_press)
{
if (menu_state == MENU_EDIT)
{ {
LCDML.BT_enter(); LCDML.BT_enter();
} }
else if (menu_state == MENU_VOICE)
{
#ifdef DEBUG
Serial.println(F("State: MENU_VOICE, button short press"));
#endif
}
}
} }
} }
// Left encoder /************************************************************************************
Left encoder
************************************************************************************/
if (g_LCDML_CONTROL_Encoder_position[ENC_L] <= -3) if (g_LCDML_CONTROL_Encoder_position[ENC_L] <= -3)
{ {
if (!button[ENC_L]) if (!button[ENC_L])
@ -214,10 +276,14 @@ void lcdml_menu_control(void)
} }
else else
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("Volume +")); Serial.println(F("Volume +"));
#endif #endif
if (configuration.vol < 1.0)
{
set_volume(configuration.vol + 0.05, configuration.pan);
UI_func_volume(0);
}
} }
ENCODER[ENC_L].write(g_LCDML_CONTROL_Encoder_position[ENC_L] + 4); ENCODER[ENC_L].write(g_LCDML_CONTROL_Encoder_position[ENC_L] + 4);
} }
@ -235,6 +301,11 @@ void lcdml_menu_control(void)
#ifdef DEBUG #ifdef DEBUG
Serial.println(F("Volume -")); Serial.println(F("Volume -"));
#endif #endif
if (configuration.vol > 0.0)
{
set_volume(configuration.vol - 0.05, configuration.pan);
UI_func_volume(0);
}
} }
ENCODER[ENC_L].write(g_LCDML_CONTROL_Encoder_position[ENC_L] - 4); ENCODER[ENC_L].write(g_LCDML_CONTROL_Encoder_position[ENC_L] - 4);
} }
@ -270,7 +341,7 @@ void lcdml_menu_control(void)
if (menu_state == MENU_EDIT) if (menu_state == MENU_EDIT)
{ {
menu_state = MENU_VOICE; menu_state = MENU_VOICE;
LCDML.OTHER_jumpToFunc(UI_func_voice_selection,0); UI_func_voice_selection(0);
} }
else if (menu_state == MENU_VOICE) else if (menu_state == MENU_VOICE)
{ {
@ -542,31 +613,53 @@ void UI_func_information(uint8_t param)
void UI_func_voice_selection(uint8_t param) void UI_func_voice_selection(uint8_t param)
{ {
if (LCDML.FUNC_setup()) // ****** SETUP ********* #ifdef DEBUG
{ Serial.println(F("UI_func_voice_selection()"));
#endif
menu_state = MENU_VOICE;
// update LCD content // update LCD content
lcd.clear(); LCDML.DISP_clear();
lcd.show(0, 0, 2, configuration.bank);
lcd.show(0, 2, 1, " ");
strip_extension(bank_names[configuration.bank], bank_name);
lcd.show(0, 2, 1, " ");
lcd.show(0, 3, 8, bank_name);
lcd.show(0, 11, 1, " ");
lcd.show(1, 0, 2, configuration.voice + 1);
lcd.show(1, 2, 1, " ");
lcd.show(1, 2, 1, "[");
lcd.show(1, 3, 10, voice_names[configuration.voice]);
lcd.show(1, 14, 1, "]");
}
void UI_func_volume(uint8_t param)
{
#ifdef DEBUG
Serial.println(F("UI_func_volume()"));
#endif
menu_state = MENU_VOLUME;
back_from_volume = 0;
// update LCD content
LCDML.DISP_clear();
lcd.setCursor(0, 0); // set cursor lcd.setCursor(0, 0); // set cursor
lcd.print("screensaver"); // print change content lcd.print("Volume"); // print change content
lcd.setCursor(0, 1); // set cursor lcd.setCursor(0, 1); // set cursor
lcd.print("press any key");
LCDML.FUNC_setLoopInterval(100); // starts a trigger event for the loop function every 100 milliseconds
}
if (LCDML.FUNC_loop()) for (uint8_t i = 0; i < LCD_cols; i++)
{ {
if (LCDML.BT_checkEnter()) if (i < int(LCD_cols * configuration.vol + 0.5))
{ lcd.print("*");
LCDML.MENU_goRoot(); else
} lcd.print(" ");
}
if (LCDML.FUNC_close())
{
// The screensaver go to the root menu
LCDML.MENU_goRoot();
} }
} }
#endif #endif
#endif #endif

@ -102,10 +102,13 @@
//* UI //* UI
//************************************************************************************************* //*************************************************************************************************
#define ENABLE_LCD_UI 1 #define ENABLE_LCD_UI 1
#define LCD_I2C_ADDRESS 0x27
#define LCD_cols 16 #define LCD_cols 16
#define LCD_rows 2 #define LCD_rows 2
#define CONTROL_RATE_MS 50 #define CONTROL_RATE_MS 50
#define BACK_FROM_VOLUME_MS 1000
//************************************************************************************************* //*************************************************************************************************
//* DEBUG OUTPUT SETTINGS //* DEBUG OUTPUT SETTINGS
//************************************************************************************************* //*************************************************************************************************

@ -44,7 +44,6 @@ extern AudioControlSGTL5000 sgtl5000_1;
extern float vol; extern float vol;
extern float vol_right; extern float vol_right;
extern float vol_left; extern float vol_left;
extern void set_volume(float master_volume, float volume_right, float volume_left);
extern char voice_name[11]; extern char voice_name[11];
struct ProcessorVoice { struct ProcessorVoice {

Loading…
Cancel
Save