Removed complete UI code for a clean start with LCDMenuLib2.

pull/3/head
Holger Wirtz 5 years ago
parent 911ceb6a3f
commit 6049fa6e91
  1. 48
      Encoder4.h
  2. 88
      LiquidCrystalPlus_I2C.h
  3. 88
      MicroDexed.ino
  4. 591
      UI.cpp
  5. 86
      UI.h
  6. 1
      dexed_sysex.cpp

@ -1,48 +0,0 @@
/*
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 <Encoder.h>
#ifndef ENCODER4_H_INCLUDED
#define ENCODER4_H_INCLUDED
class Encoder4 : public Encoder
{
public:
using Encoder::Encoder;
int32_t read()
{
return (Encoder::read() / 4);
}
void write(int32_t p)
{
Encoder::write(p * 4);
}
};
#endif

@ -1,88 +0,0 @@
/*
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_BUF_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_BUF_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_BUF_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

@ -35,21 +35,6 @@
#include "dexed.h"
#include "dexed_sysex.h"
#include "PluginFx.h"
#ifdef I2C_DISPLAY // selecting sounds by encoder, button and display
#include "UI.h"
#define BOUNCE_WITH_PROMPT_DETECTION
#include <Bounce.h>
#define ENCODER_DO_NOT_USE_INTERRUPTS
#include "Encoder4.h"
#include "LiquidCrystalPlus_I2C.h"
LiquidCrystalPlus_I2C lcd(LCD_I2C_ADDRESS, LCD_CHARS, LCD_LINES);
Encoder4 enc[2] = {Encoder4(ENC_L_PIN_A, ENC_L_PIN_B), Encoder4(ENC_R_PIN_A, ENC_R_PIN_B)};
int32_t enc_val[2] = {INITIAL_ENC_L_VALUE, INITIAL_ENC_R_VALUE};
Bounce but[2] = {Bounce(BUT_L_PIN, BUT_DEBOUNCE_MS), Bounce(BUT_R_PIN, BUT_DEBOUNCE_MS)};
elapsedMillis master_timer;
uint8_t ui_state = UI_MAIN;
uint8_t ui_main_state = UI_MAIN_VOICE;
#endif
AudioPlayQueue queue1;
AudioAnalyzePeak peak1;
@ -125,23 +110,8 @@ void setup()
//while (!Serial) ; // wait for Arduino Serial Monitor
Serial.begin(SERIAL_SPEED);
#ifdef I2C_DISPLAY
lcd.init();
lcd.blink_off();
lcd.cursor_off();
lcd.backlight();
lcd.noAutoscroll();
lcd.clear();
lcd.display();
lcd.show(0, 0, 16, "MicroDexed");
lcd.show(0, 11, 16, VERSION);
lcd.show(1, 0, 16, "(c)parasiTstudio");
pinMode(BUT_L_PIN, INPUT_PULLUP);
pinMode(BUT_R_PIN, INPUT_PULLUP);
#endif
delay(220);
Serial.println(F("MicroDexed based on https://github.com/asb2m10/dexed"));
Serial.println(F("(c)2018,2019 H. Wirtz <wirtz@parasitstudio.de>"));
Serial.println(F("https://codeberg.org/dcoredump/MicroDexed"));
@ -237,13 +207,13 @@ void setup()
}
// Init effects
delay1.delay(0, mapfloat(effect_delay_feedback, 0, ENC_DELAY_TIME_STEPS, 0.0, DELAY_MAX_TIME));
////delay1.delay(0, mapfloat(effect_delay_feedback, 0, ENC_DELAY_TIME_STEPS, 0.0, DELAY_MAX_TIME));
// mixer1 is the feedback-adding mixer, mixer2 the whole delay (with/without feedback) mixer
mixer1.gain(0, 1.0); // original signal
mixer1.gain(1, mapfloat(effect_delay_feedback, 0, ENC_DELAY_FB_STEPS, 0.0, 1.0)); // amount of feedback
mixer2.gain(0, 1.0 - mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // original signal
mixer2.gain(1, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // delayed signal (including feedback)
mixer2.gain(2, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // only delayed signal (without feedback)
////mixer1.gain(1, mapfloat(effect_delay_feedback, 0, ENC_DELAY_FB_STEPS, 0.0, 1.0)); // amount of feedback
////mixer2.gain(0, 1.0 - mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // original signal
////mixer2.gain(1, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // delayed signal (including feedback)
////mixer2.gain(2, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // only delayed signal (without feedback)
dexed->fx.Gain = 1.0;
dexed->fx.Reso = 1.0 - float(effect_filter_resonance) / ENC_FILTER_RES_STEPS;
dexed->fx.Cutoff = 1.0 - float(effect_filter_cutoff) / ENC_FILTER_CUT_STEPS;
@ -251,15 +221,6 @@ void setup()
// set initial volume and pan (read from EEPROM)
set_volume(configuration.vol, configuration.pan);
#ifdef I2C_DISPLAY
enc[0].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[0] = enc[0].read();
enc[1].write(configuration.voice);
enc_val[1] = enc[1].read();
but[0].update();
but[1].update();
#endif
#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
// Initialize processor and memory measurements
AudioProcessorUsageMaxReset();
@ -285,11 +246,6 @@ void setup()
show_cpu_and_mem_usage();
#endif
#ifdef I2C_DISPLAY
lcd.clear();
ui_show_main();
#endif
AudioInterrupts();
Serial.println(F("<setup end>"));
}
@ -387,16 +343,6 @@ void loop()
}
}
#ifdef I2C_DISPLAY
// UI-HANDLING
if (master_timer >= TIMER_UI_HANDLING_MS)
{
master_timer -= TIMER_UI_HANDLING_MS;
handle_ui();
}
#endif
#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
if (cpu_mem_millis >= SHOW_CPU_LOAD_MSEC)
{
@ -441,7 +387,6 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
if (inValue < MAX_BANKS)
{
configuration.bank = inValue;
handle_ui();
}
break;
case 1:
@ -481,27 +426,22 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
case 103: // CC 103: filter resonance
effect_filter_resonance = map(inValue, 0, 127, 0, ENC_FILTER_RES_STEPS);
dexed->fx.Reso = 1.0 - float(effect_filter_resonance) / ENC_FILTER_RES_STEPS;
handle_ui();
break;
case 104: // CC 104: filter cutoff
effect_filter_cutoff = map(inValue, 0, 127, 0, ENC_FILTER_CUT_STEPS);
dexed->fx.Cutoff = 1.0 - float(effect_filter_cutoff) / ENC_FILTER_CUT_STEPS;
handle_ui();
break;
case 105: // CC 105: delay time
effect_delay_time = map(inValue, 0, 127, 0, ENC_DELAY_TIME_STEPS);
delay1.delay(0, mapfloat(effect_delay_time, 0, ENC_DELAY_TIME_STEPS, 0.0, DELAY_MAX_TIME));
handle_ui();
////delay1.delay(0, mapfloat(effect_delay_time, 0, ENC_DELAY_TIME_STEPS, 0.0, DELAY_MAX_TIME));
break;
case 106: // CC 106: delay feedback
effect_delay_feedback = map(inValue, 0, 127, 0, ENC_DELAY_FB_STEPS);
mixer1.gain(1, mapfloat(float(effect_delay_feedback), 0, ENC_DELAY_FB_STEPS, 0.0, 1.0));
handle_ui();
////mixer1.gain(1, mapfloat(float(effect_delay_feedback), 0, ENC_DELAY_FB_STEPS, 0.0, 1.0));
break;
case 107: // CC 107: delay volume
effect_delay_volume = map(inValue, 0, 127, 0, ENC_DELAY_VOLUME_STEPS);
mixer2.gain(1, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // delay tap1 signal (with added feedback)
handle_ui();
////mixer2.gain(1, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // delay tap1 signal (with added feedback)
break;
case 120:
dexed->panic();
@ -538,7 +478,6 @@ void handleProgramChange(byte inChannel, byte inProgram)
if (inProgram < MAX_VOICES)
{
load_sysex(configuration.bank, inProgram);
handle_ui();
}
}
@ -709,13 +648,14 @@ void handleSystemExclusive(byte * sysex, uint len)
}
// load sysex-data into voice memory
dexed->loadVoiceParameters(&sysex[6]);
//dexed->initGlobalParameters();
// manipulate UI names and numbers
strncpy(voice_name, (char *)&sysex[151], sizeof(voice_name) - 1);
Serial.print(F("Found Voice ["));
Serial.print(F("Got voice ["));
Serial.print(voice_name);
Serial.println(F("]."));
dexed->loadVoiceParameters(&sysex[6]);
//dexed->initGlobalParameters();
}
#ifdef DEBUG
else

591
UI.cpp

@ -1,591 +0,0 @@
/*
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,2019 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 <Arduino.h>
#include <limits.h>
#include "config.h"
#include "dexed.h"
#include "dexed_sysex.h"
#include "UI.h"
#ifdef I2C_DISPLAY // selecting sounds by encoder, button and display
elapsedMillis ui_back_to_main;
void handle_ui(void)
{
if (ui_back_to_main >= UI_AUTO_BACK_MS && (ui_state != UI_MAIN && ui_state != UI_EFFECTS_FILTER && ui_state != UI_EFFECTS_DELAY))
{
enc[0].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[0] = enc[0].read();
ui_show_main();
}
if (autostore >= AUTOSTORE_MS && (ui_main_state == UI_MAIN_VOICE_SELECTED || ui_main_state == UI_MAIN_BANK_SELECTED))
{
switch (ui_main_state)
{
case UI_MAIN_VOICE_SELECTED:
ui_main_state = UI_MAIN_VOICE;
break;
case UI_MAIN_BANK_SELECTED:
ui_main_state = UI_MAIN_BANK;
break;
}
}
for (uint8_t i = 0; i < NUM_ENCODER; i++)
{
but[i].update();
if (but[i].fallingEdge())
long_button_pressed = 0;
if (but[i].risingEdge())
{
uint32_t button_released = long_button_pressed;
if (button_released > LONG_BUTTON_PRESS)
{
// long pressing of button detected
#ifdef DEBUG
Serial.print(F("Long button pressing detected for button "));
Serial.println(i, DEC);
#endif
switch (i)
{
case 0: // long press for left button
break;
case 1: // long press for right button
switch (ui_state)
{
case UI_MAIN:
ui_main_state = UI_MAIN_FILTER_RES;
enc[i].write(effect_filter_resonance);
enc_val[i] = enc[i].read();
ui_show_effects_filter();
break;
case UI_EFFECTS_FILTER:
ui_main_state = UI_MAIN_DELAY_TIME;
enc[i].write(effect_delay_time);
enc_val[i] = enc[i].read();
ui_show_effects_delay();
break;
case UI_EFFECTS_DELAY:
ui_main_state = UI_MAIN_VOICE;
enc[i].write(configuration.voice);
enc_val[i] = enc[i].read();
ui_show_main();
break;
}
break;
}
}
else
{
// Button pressed
switch (i)
{
case 0: // left button pressed
switch (ui_state)
{
case UI_MAIN:
enc[i].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[i] = enc[i].read();
ui_show_volume();
break;
case UI_VOLUME:
enc[i].write(configuration.midi_channel);
enc_val[i] = enc[i].read();
ui_show_midichannel();
break;
case UI_MIDICHANNEL:
enc[i].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[i] = enc[i].read();
ui_show_main();
break;
}
break;
case 1: // right button pressed
switch (ui_state)
{
case UI_MAIN:
switch (ui_main_state)
{
case UI_MAIN_BANK:
case UI_MAIN_BANK_SELECTED:
ui_main_state = UI_MAIN_VOICE;
enc[i].write(configuration.voice);
enc_val[i] = enc[i].read();
break;
case UI_MAIN_VOICE:
case UI_MAIN_VOICE_SELECTED:
ui_main_state = UI_MAIN_BANK;
enc[i].write(configuration.bank);
enc_val[i] = enc[i].read();
break;
}
ui_show_main();
break;
case UI_EFFECTS_FILTER:
case UI_EFFECTS_DELAY:
switch (ui_main_state)
{
case UI_MAIN_FILTER_RES:
ui_main_state = UI_MAIN_FILTER_CUT;
enc[i].write(effect_filter_cutoff);
enc_val[i] = enc[i].read();
ui_show_effects_filter();
break;
case UI_MAIN_FILTER_CUT:
ui_main_state = UI_MAIN_FILTER_RES;
enc[i].write(effect_filter_resonance);
enc_val[i] = enc[i].read();
ui_show_effects_filter();
break;
case UI_MAIN_DELAY_TIME:
ui_main_state = UI_MAIN_DELAY_FEEDBACK;
enc[i].write(effect_delay_feedback);
enc_val[i] = enc[i].read();
ui_show_effects_delay();
break;
case UI_MAIN_DELAY_VOLUME:
ui_main_state = UI_MAIN_DELAY_TIME;
enc[i].write(effect_delay_time);
enc_val[i] = enc[i].read();
ui_show_effects_delay();
break;
case UI_MAIN_DELAY_FEEDBACK:
ui_main_state = UI_MAIN_DELAY_VOLUME;
enc[i].write(effect_delay_volume);
enc_val[i] = enc[i].read();
ui_show_effects_delay();
break;
}
break;
}
}
}
#ifdef DEBUG
Serial.print(F("Button "));
Serial.println(i, DEC);
#endif
}
if (enc[i].read() == enc_val[i])
continue;
else
{
switch (i)
{
case 0: // left encoder moved
float tmp;
switch (ui_state)
{
case UI_MAIN:
case UI_VOLUME:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() >= ENC_VOL_STEPS)
enc[i].write(ENC_VOL_STEPS);
enc_val[i] = enc[i].read();
//set_volume(float(map(enc[i].read(), 0, ENC_VOL_STEPS, 0, 100)) / 100, configuration.pan);
tmp = (float(map(enc[i].read(), 0, ENC_VOL_STEPS, 0, 100)) / 100) - configuration.vol;
soften_volume.diff = tmp / SOFTEN_VALUE_CHANGE_STEPS;
soften_volume.steps = SOFTEN_VALUE_CHANGE_STEPS;
#ifdef DEBUG
Serial.print(F("Setting soften volume from: "));
Serial.print(configuration.vol, 5);
Serial.print(F("/Volume step: "));
Serial.print(soften_volume.steps);
Serial.print(F("/Volume diff: "));
Serial.println(soften_volume.diff, 5);
#endif
eeprom_write();
ui_show_volume();
break;
case UI_MIDICHANNEL:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() >= 16)
enc[i].write(16);
configuration.midi_channel = enc[i].read();
eeprom_write();
ui_show_midichannel();
break;
}
break;
case 1: // right encoder moved
switch (ui_state)
{
case UI_VOLUME:
ui_state = UI_MAIN;
lcd.clear();
enc[1].write(configuration.voice);
eeprom_write();
ui_show_main();
break;
case UI_MAIN:
switch (ui_main_state)
{
case UI_MAIN_BANK:
ui_main_state = UI_MAIN_BANK_SELECTED;
case UI_MAIN_BANK_SELECTED:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() > max_loaded_banks - 1)
enc[i].write(max_loaded_banks - 1);
configuration.bank = enc[i].read();
get_voice_names_from_bank(configuration.bank);
load_sysex(configuration.bank, configuration.voice);
eeprom_write();
break;
case UI_MAIN_VOICE:
ui_main_state = UI_MAIN_VOICE_SELECTED;
case UI_MAIN_VOICE_SELECTED:
if (enc[i].read() <= 0)
{
if (configuration.bank > 0)
{
enc[i].write(MAX_VOICES - 1);
configuration.bank--;
get_voice_names_from_bank(configuration.bank);
}
else
enc[i].write(0);
}
else if (enc[i].read() > MAX_VOICES - 1)
{
if (configuration.bank < MAX_BANKS - 1)
{
enc[i].write(0);
configuration.bank++;
get_voice_names_from_bank(configuration.bank);
}
else
enc[i].write(MAX_VOICES - 1);
}
configuration.voice = enc[i].read();
load_sysex(configuration.bank, configuration.voice);
eeprom_write();
break;
}
ui_show_main();
break;
case UI_EFFECTS_FILTER:
switch (ui_main_state)
{
case UI_MAIN_FILTER_RES:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() >= ENC_FILTER_RES_STEPS)
enc[i].write(ENC_FILTER_RES_STEPS);
enc_val[i] = enc[i].read();
effect_filter_resonance = enc[i].read();
tmp = 1.0 - (float(map(enc[i].read(), 0, ENC_FILTER_RES_STEPS, 0, 100)) / 100) - dexed->fx.Reso;
soften_filter_res.diff = tmp / SOFTEN_VALUE_CHANGE_STEPS;
soften_filter_res.steps = SOFTEN_VALUE_CHANGE_STEPS;
#ifdef DEBUG
Serial.print(F("Setting soften filter-resonance from: "));
Serial.print(dexed->fx.Reso, 5);
Serial.print(F("/Filter-Resonance step: "));
Serial.print(soften_filter_res.steps);
Serial.print(F("/Filter-Resonance diff: "));
Serial.println(soften_filter_res.diff, 5);
#endif
break;
case UI_MAIN_FILTER_CUT:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() >= ENC_FILTER_CUT_STEPS)
enc[i].write(ENC_FILTER_CUT_STEPS);
enc_val[i] = enc[i].read();
effect_filter_cutoff = enc[i].read();
tmp = 1.0 - (float(map(enc[i].read(), 0, ENC_FILTER_CUT_STEPS, 0, 100)) / 100) - dexed->fx.Cutoff;
soften_filter_cut.diff = tmp / SOFTEN_VALUE_CHANGE_STEPS;
soften_filter_cut.steps = SOFTEN_VALUE_CHANGE_STEPS;
#ifdef DEBUG
Serial.print(F("Setting soften filter-cutoff from: "));
Serial.print(dexed->fx.Cutoff, 5);
Serial.print(F("/Filter-Cutoff step: "));
Serial.print(soften_filter_cut.steps);
Serial.print(F("/Filter-Cutoff diff: "));
Serial.println(soften_filter_cut.diff, 5);
#endif
break;
}
ui_show_effects_filter();
break;
case UI_EFFECTS_DELAY:
switch (ui_main_state)
{
case UI_MAIN_DELAY_TIME:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() > ENC_DELAY_TIME_STEPS)
enc[i].write(ENC_DELAY_TIME_STEPS);
effect_delay_time = enc[i].read();;
delay1.delay(0, mapfloat(effect_delay_time, 0, ENC_DELAY_TIME_STEPS, 0.0, DELAY_MAX_TIME));
#ifdef DEBUG
Serial.print(F("Setting delay time to: "));
Serial.println(map(effect_delay_time, 0, ENC_DELAY_TIME_STEPS, 0, DELAY_MAX_TIME));
#endif
break;
case UI_MAIN_DELAY_FEEDBACK:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() > ENC_DELAY_FB_STEPS)
enc[i].write(ENC_DELAY_FB_STEPS);
effect_delay_feedback = enc[i].read();
mixer1.gain(1, mapfloat(float(effect_delay_feedback), 0, ENC_DELAY_FB_STEPS, 0.0, 1.0));
#ifdef DEBUG
Serial.print(F("Setting delay feedback to: "));
Serial.println(mapfloat(float(effect_delay_feedback), 0, ENC_DELAY_FB_STEPS, 0.0, 1.0));
#endif
break;
case UI_MAIN_DELAY_VOLUME:
if (enc[i].read() <= 0)
enc[i].write(0);
else if (enc[i].read() > ENC_DELAY_VOLUME_STEPS)
enc[i].write(ENC_DELAY_VOLUME_STEPS);
effect_delay_volume = enc[i].read();
float tmp_vol = mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0);
//mixer2.gain(0, 1.0 - mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // delay tap1 signal (with added feedback)
mixer2.gain(0, 1.0 - tmp_vol); // delay tap1 signal (with added feedback)
mixer2.gain(1, tmp_vol); // delay tap1 signal (with added feedback)
mixer2.gain(2, tmp_vol); // delay tap1 signal
#ifdef DEBUG
Serial.print(F("Setting delay volume to: "));
Serial.println(effect_delay_volume);
#endif
break;
}
ui_show_effects_delay();
break;
}
break;
}
#ifdef DEBUG
Serial.print(F("Encoder "));
Serial.print(i, DEC);
Serial.print(F(": "));
Serial.println(enc[i].read(), DEC);
#endif
}
enc_val[i] = enc[i].read();
}
}
void ui_show_main(void)
{
if (ui_state != UI_MAIN)
{
lcd.clear();
}
lcd.show(0, 0, 2, configuration.bank);
lcd.show(0, 2, 1, " ");
strip_extension(bank_names[configuration.bank], bank_name);
if (ui_main_state == UI_MAIN_BANK || ui_main_state == UI_MAIN_BANK_SELECTED)
{
lcd.show(0, 2, 1, "[");
lcd.show(0, 3, 8, bank_name);
lcd.show(0, 11, 1, "]");
}
else
{
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, " ");
if (ui_main_state == UI_MAIN_VOICE || ui_main_state == UI_MAIN_VOICE_SELECTED)
{
lcd.show(1, 2, 1, "[");
lcd.show(1, 3, 10, voice_names[configuration.voice]);
lcd.show(1, 14, 1, "]");
}
else
{
lcd.show(1, 2, 1, " ");
lcd.show(1, 3, 10, voice_names[configuration.voice]);
lcd.show(1, 14, 1, " ");
}
ui_state = UI_MAIN;
}
void ui_show_volume(void)
{
uint8_t pos;
static uint8_t old_pos;
ui_back_to_main = 0;
// erase old marker and show new marker
pos = map(configuration.vol * 100 + 0.5, 0, 100, 0, LCD_CHARS - 1);
if (ui_state != UI_VOLUME)
{
lcd.clear();
lcd.show(0, 0, LCD_CHARS - 1, "Volume");
lcd.show(1, pos, 1, "*");
old_pos = pos;
}
// show value
lcd.show(0, LCD_CHARS - 3, 3, (configuration.vol * 100 + 0.5));
if (pos != old_pos)
{
lcd.show(1, pos, 1, "*");
lcd.show(1, old_pos, 1, " ");
old_pos = pos;
}
ui_state = UI_VOLUME;
}
void ui_show_midichannel(void)
{
ui_back_to_main = 0;
if (ui_state != UI_MIDICHANNEL)
{
lcd.clear();
lcd.show(0, 0, LCD_CHARS, "MIDI Channel");
}
if (configuration.midi_channel == MIDI_CHANNEL_OMNI)
lcd.show(1, 0, 4, "OMNI");
else
{
lcd.show(1, 0, 2, configuration.midi_channel);
if (configuration.midi_channel == 1)
lcd.show(1, 2, 2, " ");
}
ui_state = UI_MIDICHANNEL;
}
void ui_show_effects_filter(void)
{
if (ui_state != UI_EFFECTS_FILTER)
{
lcd.clear();
lcd.show(0, 0, LCD_CHARS, "Filter");
lcd.show(1, 0, 4, "Res:");
lcd.show(1, 8, 4, "Cut:");
}
lcd.show(1, 5, 2, map(effect_filter_resonance, 0, ENC_FILTER_RES_STEPS, 0, 99));
lcd.show(1, 13, 2, map(effect_filter_cutoff, 0, ENC_FILTER_CUT_STEPS, 0, 99));
if (ui_main_state == UI_MAIN_FILTER_RES)
{
lcd.show(1, 4, 1, "[");
lcd.show(1, 7, 1, "]");
}
else
{
lcd.show(1, 4, 1, " ");
lcd.show(1, 7, 1, " ");
}
if (ui_main_state == UI_MAIN_FILTER_CUT)
{
lcd.show(1, 12, 1, "[");
lcd.show(1, 15, 1, "]");
}
else
{
lcd.show(1, 12, 1, " ");
lcd.show(1, 15, 1, " ");
}
ui_state = UI_EFFECTS_FILTER;
}
void ui_show_effects_delay(void)
{
if (ui_state != UI_EFFECTS_DELAY)
{
lcd.clear();
lcd.show(0, 0, 5, "Delay");
lcd.show(0, 6, 2, "T:");
lcd.show(0, 14, 2, "ms");
lcd.show(1, 0, 3, "FB:");
lcd.show(1, 8, 5, "Vol:");
}
lcd.show(0, 9, 4, map(effect_delay_time, 0, ENC_DELAY_TIME_STEPS, 0, DELAY_MAX_TIME));
lcd.show(1, 4, 2, map(effect_delay_feedback, 0, ENC_DELAY_FB_STEPS, 0, 99));
lcd.show(1, 13, 2, map(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0, 99));
if (ui_main_state == UI_MAIN_DELAY_TIME)
{
lcd.show(0, 8, 1, "[");
lcd.show(0, 13, 1, "]");
}
else
{
lcd.show(0, 8, 1, " ");
lcd.show(0, 13, 1, " ");
}
if (ui_main_state == UI_MAIN_DELAY_FEEDBACK)
{
lcd.show(1, 3, 1, "[");
lcd.show(1, 6, 1, "]");
}
else
{
lcd.show(1, 3, 1, " ");
lcd.show(1, 6, 1, " ");
}
if (ui_main_state == UI_MAIN_DELAY_VOLUME)
{
lcd.show(1, 12, 1, "[");
lcd.show(1, 15, 1, "]");
}
else
{
lcd.show(1, 12, 1, " ");
lcd.show(1, 15, 1, " ");
}
ui_state = UI_EFFECTS_DELAY;
}
float mapfloat(float val, float in_min, float in_max, float out_min, float out_max)
{
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
#endif

86
UI.h

@ -1,86 +0,0 @@
/*
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,2019 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 "config.h"
#define BOUNCE_WITH_PROMPT_DETECTION
#include <Bounce.h>
#include <EEPROM.h>
#include <MIDI.h>
#include "LiquidCrystalPlus_I2C.h"
#include "Encoder4.h"
#ifndef UI_H_INCLUDED
#define UI_H_INCLUDED
extern Encoder4 enc[2];
extern int32_t enc_val[2];
extern Bounce but[2];
extern LiquidCrystalPlus_I2C lcd;
extern config_t configuration;
extern uint8_t max_loaded_banks;
extern char bank_name[BANK_NAME_LEN];
extern char voice_name[VOICE_NAME_LEN];
extern uint8_t ui_state;
extern uint8_t ui_main_state;
extern void eeprom_write(void);
extern void set_volume(float v, float pan);
extern elapsedMillis autostore;
extern elapsedMillis long_button_pressed;
extern uint8_t effect_filter_cutoff;
extern uint8_t effect_filter_resonance;
extern uint8_t effect_delay_time;
extern uint8_t effect_delay_feedback;
extern uint8_t effect_delay_volume;
extern bool effect_delay_sync;
extern AudioEffectDelay delay1;
extern AudioMixer4 mixer1;
extern AudioMixer4 mixer2;
extern value_change_t soften_volume;
extern value_change_t soften_filter_res;
extern value_change_t soften_filter_cut;
void handle_ui(void);
void ui_show_main(void);
void ui_show_volume(void);
void ui_show_midichannel(void);
void ui_show_effects_filter(void);
void ui_show_effects_delay(void);
float mapfloat(float val, float in_min, float in_max, float out_min, float out_max);
enum ui_states {UI_MAIN, UI_VOLUME, UI_MIDICHANNEL, UI_EFFECTS_FILTER, UI_EFFECTS_DELAY};
enum ui_main_states {UI_MAIN_BANK, UI_MAIN_VOICE, UI_MAIN_BANK_SELECTED, UI_MAIN_VOICE_SELECTED, UI_MAIN_FILTER_RES, UI_MAIN_FILTER_CUT, UI_MAIN_DELAY_TIME, UI_MAIN_DELAY_FEEDBACK, UI_MAIN_DELAY_VOLUME};
class MyEncoder : public Encoder
{
int32_t read()
{
return (Encoder::read() / 4);
}
void write(int32_t p)
{
Encoder::write(p * 4);
}
};
#endif

@ -30,7 +30,6 @@
#include "dexed.h"
#include "dexed_sysex.h"
#include "config.h"
#include "UI.h"
void create_sysex_filename(uint8_t b, char* sysex_file_name)
{

Loading…
Cancel
Save