Hi all! Ive been working on this for a week and just can't get things to work. I have a Teensy 4.1, encoder, and tft screen. The audio part works, I just need to get the submenu to work like the main menu does. I can scroll and edit values in the main menu. So far im only working on the first submenu. I can enter it, but I can't edit values or return to the main menu. The main menu has 5 functions to operate - draw value,
adjustValue, redrawValue, redrawMenuItem, and drawMenu. I have duplicated these for the submenu. I also have a handle encoder and handle button code. Any suggestions would be greatly appreciated!
#include "OpenAudio_ArduinoLibrary.h"
#include "AudioStream_F32.h"
#include "TD_filterIIR.h"
#include <Audio.h>
#include <ILI9341_t3n.h>
#include <Encoder.h>
#include <Bounce.h>
#include <EEPROM.h>
#include <SPI.h>
#include "ili9341_t3n_font_Arial.h"
#include "ili9341_t3n_font_ArialBold.h"
#include <effect_dynamics_F32.h>
#include <effect_platervbstereo.h>
AudioInputI2S_F32 input1;
AudioAnalyzePeak_F32 peak1;
AudioAnalyzePeak_F32 peak2;
filterIIR hp1;
filterIIR eq1;
filterIIR hp2;
filterIIR eq2;
AudioEffectDynamics_F32 dynamics1;
AudioEffectDynamics_F32 dynamics2;
AudioConvert_F32toI16 convert1;
AudioConvert_F32toI16 convert2;
AudioConvert_I16toF32 convert3;
AudioConvert_I16toF32 convert4;
AudioEffectPlateReverb reverb;
AudioMixer4_F32 volume;
AudioMixer4_F32 reverb_send;
AudioOutputI2S_F32 output1;
AudioConnection_F32 patchCord1(input1, 0, peak1, 0);
AudioConnection_F32 patchCord2(input1, 1, peak2, 0);
AudioConnection_F32 patchCord3(input1, 0, hp1, 0);
AudioConnection_F32 patchCord4(input1, 1, hp2, 0);
AudioConnection_F32 patchCord5(hp1, 0, eq1, 0);
AudioConnection_F32 patchCord6(hp2, 0, eq2, 0);
AudioConnection_F32 patchCord7(eq1, 0, dynamics1, 0);
AudioConnection_F32 patchCord8(eq2, 0, dynamics2, 0);
AudioConnection_F32 patchCord9(dynamics1, 0, volume, 0);
AudioConnection_F32 patchCord10(dynamics2, 0, volume, 1);
AudioConnection_F32 patchCord11(dynamics1, 0, reverb_send, 0);
AudioConnection_F32 patchCord12(dynamics2, 0, reverb_send, 1);
AudioConnection_F32 patchCord13(reverb_send, 0, convert1, 0);
AudioConnection_F32 patchCord14(reverb_send, 0, convert2, 0);
AudioConnection patchCord15(convert1, 0, reverb, 0);
AudioConnection patchCord16(convert2, 0, reverb, 1);
AudioConnection patchCord17(reverb, 0, convert3, 0);
AudioConnection patchCord18(reverb, 1, convert4, 0);
AudioConnection_F32 patchCord19(convert3, 0, volume, 2);
AudioConnection_F32 patchCord20(convert4, 0, volume, 3);
AudioConnection_F32 patchCord21(volume, 0, output1, 0);
AudioConnection_F32 patchCord22(volume, 0, output1, 1);
AudioControlSGTL5000 codec;
#define TFT_DC 9
#define TFT_CS 10
#define ENCODER_A_PIN 5
#define ENCODER_B_PIN 6
#define ENCODER_BTN_PIN A0
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC);
Encoder encoder(ENCODER_A_PIN, ENCODER_B_PIN);
Bounce encoderButton = Bounce(ENCODER_BTN_PIN, 10);
// Main Menu items
const char* menuItems[] = { "Mic Volume", "Guitar Volume", "Mic Reverb", "Guitar Reverb",
"Mic EQ", "Guitar EQ", "Mic Compressor",
"Guitar Compressor", "Reverb Settings", "Input Levels" };
const int menuItemCount = sizeof(menuItems) / sizeof(menuItems[0]);
int currentSelectedItem = 0;
enum Mode {
MAIN_MENU,
SUB_MENU,
EDIT_MODE,
SUB_MENU_EDIT_MODE
};
Mode currentMode = MAIN_MENU;
struct Menu {
const char** items;
int itemCount;
int currentItem;
const char* title;
bool isMain;
int selected;
void (*drawFunction)();
};
Menu mainMenu;
// Initialize the Mic EQ menu
const char* micEqMenuItems[] = {"Low Cut", "Low Freq", "Low Q", "Low Gain", "High Freq", "High Q", "High Gain", "Back"};
Menu micEqMenu = {
micEqMenuItems, // Items
sizeof(micEqMenuItems) / sizeof(char*), // Item count
0, // Initial selected item
"Mic EQ", // Title
false, // Not a main menu
0, // Initial selected item for submenu
nullptr // Draw function (if any)
};
// EEPROM addresses for each setting
const int EEPROM_ADDR_MIC_VOLUME = 0;
const int EEPROM_ADDR_GUITAR_VOLUME = EEPROM_ADDR_MIC_VOLUME + sizeof(float);
const int EEPROM_ADDR_MIC_REVERB = EEPROM_ADDR_GUITAR_VOLUME + sizeof(float);
const int EEPROM_ADDR_GUITAR_REVERB = EEPROM_ADDR_MIC_REVERB + sizeof(float);
const int EEPROM_ADDR_MIC_IN_LVL = EEPROM_ADDR_GUITAR_REVERB + sizeof(float);
const int EEPROM_ADDR_GUITAR_IN_LVL = EEPROM_ADDR_MIC_IN_LVL + sizeof(float);
const int EEPROM_ADDR_OUTPUT_LVL = EEPROM_ADDR_GUITAR_IN_LVL + sizeof(float);
const int EEPROM_ADDR_HP1_LOWCUT = EEPROM_ADDR_OUTPUT_LVL + sizeof(float);
const int EEPROM_ADDR_HP2_LOWCUT = EEPROM_ADDR_HP1_LOWCUT + sizeof(float);
const int EEPROM_ADDR_EQ1_LOWF = EEPROM_ADDR_HP2_LOWCUT + sizeof(float);
const int EEPROM_ADDR_EQ1_LOWQ = EEPROM_ADDR_EQ1_LOWF + sizeof(float);
const int EEPROM_ADDR_EQ1_LOWGAIN = EEPROM_ADDR_EQ1_LOWQ + sizeof(float);
const int EEPROM_ADDR_EQ1_MEDF = EEPROM_ADDR_EQ1_LOWGAIN + sizeof(float);
const int EEPROM_ADDR_EQ1_MEDQ = EEPROM_ADDR_EQ1_MEDF + sizeof(float);
const int EEPROM_ADDR_EQ1_MEDGAIN = EEPROM_ADDR_EQ1_MEDQ + sizeof(float);
const int EEPROM_ADDR_EQ1_HIGHF = EEPROM_ADDR_EQ1_MEDGAIN + sizeof(float);
const int EEPROM_ADDR_EQ1_HIGHQ = EEPROM_ADDR_EQ1_HIGHF + sizeof(float);
const int EEPROM_ADDR_EQ1_HIGHGAIN = EEPROM_ADDR_EQ1_HIGHQ + sizeof(float);
const int EEPROM_ADDR_EQ2_LOWF = EEPROM_ADDR_EQ1_HIGHGAIN + sizeof(float);
const int EEPROM_ADDR_EQ2_LOWQ = EEPROM_ADDR_EQ2_LOWF + sizeof(float);
const int EEPROM_ADDR_EQ2_LOWGAIN = EEPROM_ADDR_EQ2_LOWQ + sizeof(float);
const int EEPROM_ADDR_EQ2_MEDF = EEPROM_ADDR_EQ2_LOWGAIN + sizeof(float);
const int EEPROM_ADDR_EQ2_MEDQ = EEPROM_ADDR_EQ2_MEDF + sizeof(float);
const int EEPROM_ADDR_EQ2_MEDGAIN = EEPROM_ADDR_EQ2_MEDQ + sizeof(float);
const int EEPROM_ADDR_EQ2_HIGHF = EEPROM_ADDR_EQ2_MEDGAIN + sizeof(float);
const int EEPROM_ADDR_EQ2_HIGHQ = EEPROM_ADDR_EQ2_HIGHF + sizeof(float);
const int EEPROM_ADDR_EQ2_HIGHGAIN = EEPROM_ADDR_EQ2_HIGHQ + sizeof(float);
const int EEPROM_ADDR_GATE_THRESHOLD1 = EEPROM_ADDR_EQ2_HIGHGAIN + sizeof(float);
const int EEPROM_ADDR_GATE_ATTACK1 = EEPROM_ADDR_GATE_THRESHOLD1 + sizeof(float);
const int EEPROM_ADDR_GATE_RELEASE1 = EEPROM_ADDR_GATE_ATTACK1 + sizeof(float);
const int EEPROM_ADDR_GATE_HYSTERESIS1 = EEPROM_ADDR_GATE_RELEASE1 + sizeof(float);
const int EEPROM_ADDR_GATE_ATTENUATION1 = EEPROM_ADDR_GATE_HYSTERESIS1 + sizeof(float);
const int EEPROM_ADDR_GATE_THRESHOLD2 = EEPROM_ADDR_GATE_ATTENUATION1 + sizeof(float);
const int EEPROM_ADDR_GATE_ATTACK2 = EEPROM_ADDR_GATE_THRESHOLD2 + sizeof(float);
const int EEPROM_ADDR_GATE_RELEASE2 = EEPROM_ADDR_GATE_ATTACK2 + sizeof(float);
const int EEPROM_ADDR_GATE_HYSTERESIS2 = EEPROM_ADDR_GATE_RELEASE2 + sizeof(float);
const int EEPROM_ADDR_GATE_ATTENUATION2 = EEPROM_ADDR_GATE_HYSTERESIS2 + sizeof(float);
const int EEPROM_ADDR_COMP_THRESHOLD1 = EEPROM_ADDR_GATE_ATTENUATION2 + sizeof(float);
const int EEPROM_ADDR_COMP_ATTACK1 = EEPROM_ADDR_COMP_THRESHOLD1 + sizeof(float);
const int EEPROM_ADDR_COMP_RELEASE1 = EEPROM_ADDR_COMP_ATTACK1 + sizeof(float);
const int EEPROM_ADDR_COMP_RATIO1 = EEPROM_ADDR_COMP_RELEASE1 + sizeof(float);
const int EEPROM_ADDR_COMP_KNEE_WIDTH1 = EEPROM_ADDR_COMP_RATIO1 + sizeof(float);
const int EEPROM_ADDR_COMP_THRESHOLD2 = EEPROM_ADDR_COMP_KNEE_WIDTH1 + sizeof(float);
const int EEPROM_ADDR_COMP_ATTACK2 = EEPROM_ADDR_COMP_THRESHOLD2 + sizeof(float);
const int EEPROM_ADDR_COMP_RELEASE2 = EEPROM_ADDR_COMP_ATTACK2 + sizeof(float);
const int EEPROM_ADDR_COMP_RATIO2 = EEPROM_ADDR_COMP_RELEASE2 + sizeof(float);
const int EEPROM_ADDR_COMP_KNEE_WIDTH2 = EEPROM_ADDR_COMP_RATIO2 + sizeof(float);
const int EEPROM_ADDR_LIM_THRESHOLD1 = EEPROM_ADDR_COMP_KNEE_WIDTH2 + sizeof(float);
const int EEPROM_ADDR_LIM_ATTACK1 = EEPROM_ADDR_LIM_THRESHOLD1 + sizeof(float);
const int EEPROM_ADDR_LIM_RELEASE1 = EEPROM_ADDR_LIM_ATTACK1 + sizeof(float);
const int EEPROM_ADDR_LIM_THRESHOLD2 = EEPROM_ADDR_LIM_RELEASE1 + sizeof(float);
const int EEPROM_ADDR_LIM_ATTACK2 = EEPROM_ADDR_LIM_THRESHOLD2 + sizeof(float);
const int EEPROM_ADDR_LIM_RELEASE2 = EEPROM_ADDR_LIM_ATTACK2 + sizeof(float);
const int EEPROM_ADDR_MAKEUP_GAIN1 = EEPROM_ADDR_LIM_RELEASE2 + sizeof(float);
const int EEPROM_ADDR_MAKEUP_GAIN2 = EEPROM_ADDR_MAKEUP_GAIN1 + sizeof(float);
const int EEPROM_ADDR_REVERB_SIZE = EEPROM_ADDR_MAKEUP_GAIN2 + sizeof(float);
const int EEPROM_ADDR_REVERB_LOWPASS = EEPROM_ADDR_REVERB_SIZE + sizeof(float);
const int EEPROM_ADDR_REVERB_LODAMP = EEPROM_ADDR_REVERB_LOWPASS + sizeof(float);
const int EEPROM_ADDR_REVERB_HIDAMP = EEPROM_ADDR_REVERB_LODAMP + sizeof(float);
const int EEPROM_ADDR_REVERB_DIFFUSION = EEPROM_ADDR_REVERB_HIDAMP + sizeof(float);
const int EEPROM_ADDR_REVERB_MIC_SEND = EEPROM_ADDR_REVERB_DIFFUSION + sizeof(float);
const int EEPROM_ADDR_REVERB_GUITAR_SEND = EEPROM_ADDR_REVERB_MIC_SEND + sizeof(float);
// Variables for editable values
float micVolume = 0.5;
float guitarVolume = 0.5;
float micReverb = 0.5;
float guitarReverb = 0.5;
float micInLvl = 5; // 5: 1.33v p-p(default), 0: 3.12v, 15: 0.24v
float guitarInLvl = 5; // 5: 1.33v p-p(default), 0: 3.12v, 15: 0.24v
float outPutLvl = 29; //29: 1.29v p-p(default), 13: 3.16v, 31: 1.16v
float hp1_lowcut = 80;
float hp2_lowcut = 80;
float eq1_lowf = 250;
float eq1_lowq = 1.0;
float eq1_lowgain = 0.0;
float eq1_medf = 2500;
float eq1_medq = 1.0;
float eq1_medgain = 0.0;
float eq1_highf = 8000;
float eq1_highq = 1.0;
float eq1_highgain = 0.0;
float eq2_lowf = 250;
float eq2_lowq = 3.0;
float eq2_lowgain = 0.0;
float eq2_medf = 2500;
float eq2_medq = 1.0;
float eq2_medgain = 0.0;
float eq2_highf = 8000;
float eq2_highq = 1.0;
float eq2_highgain = 0.0;
float gateThreshold1 = -50.0f;
float gateAttack1 = 0.01f;
float gateRelease1 = 0.1f;
float gateHysteresis1 = 6.0f;
float gateAttenuation1 = -12.0f;
float gateThreshold2 = -50.0f;
float gateAttack2 = 0.01f;
float gateRelease2 = 0.1f;
float gateHysteresis2 = 6.0f;
float gateAttenuation2 = -12.0f;
float compThreshold1 = -10.0f;
float compAttack1 = 0.1f;
float compRelease1 = 0.2f;
float compRatio1 = 4.0f;
float compKneeWidth1 = 6.0f;
float compThreshold2 = -10.0f;
float compAttack2 = 0.1f;
float compRelease2 = 0.2f;
float compRatio2 = 4.0f;
float compKneeWidth2 = 6.0f;
float limThreshold1 = -0.1f;
float limAttack1 = 0.01f;
float limRelease1 = 0.1f;
float limThreshold2 = -0.1f;
float limAttack2 = 0.01f;
float limRelease2 = 0.1f;
float makeupGain1 = 6.0f;
float makeupGain2 = 6.0f;
float reverbSize = 0.7f;
float reverbLowpass = 1.0f;
float reverbLodamp = 0.4f;
float reverbHidamp = 1.0f;
float reverbDiffusion = 1.0f;
float reverbMicSend = 0.5f;
float reverbGuitarSend = 0.5f;
void saveSettingsToEEPROM() {
// Save each setting
EEPROM.put(EEPROM_ADDR_MIC_VOLUME, micVolume);
EEPROM.put(EEPROM_ADDR_GUITAR_VOLUME, guitarVolume);
EEPROM.put(EEPROM_ADDR_MIC_REVERB, micReverb);
EEPROM.put(EEPROM_ADDR_GUITAR_REVERB, guitarReverb);
EEPROM.put(EEPROM_ADDR_MIC_IN_LVL, micInLvl);
EEPROM.put(EEPROM_ADDR_GUITAR_IN_LVL, guitarInLvl);
EEPROM.put(EEPROM_ADDR_OUTPUT_LVL, outPutLvl);
EEPROM.put(EEPROM_ADDR_HP1_LOWCUT, hp1_lowcut);
EEPROM.put(EEPROM_ADDR_HP2_LOWCUT, hp2_lowcut);
EEPROM.put(EEPROM_ADDR_EQ1_LOWF, eq1_lowf);
EEPROM.put(EEPROM_ADDR_EQ1_LOWQ, eq1_lowq);
EEPROM.put(EEPROM_ADDR_EQ1_LOWGAIN, eq1_lowgain);
EEPROM.put(EEPROM_ADDR_EQ1_MEDF, eq1_medf);
EEPROM.put(EEPROM_ADDR_EQ1_MEDQ, eq1_medq);
EEPROM.put(EEPROM_ADDR_EQ1_MEDGAIN, eq1_medgain);
EEPROM.put(EEPROM_ADDR_EQ1_HIGHF, eq1_highf);
EEPROM.put(EEPROM_ADDR_EQ1_HIGHQ, eq1_highq);
EEPROM.put(EEPROM_ADDR_EQ1_HIGHGAIN, eq1_highgain);
EEPROM.put(EEPROM_ADDR_EQ2_LOWF, eq2_lowf);
EEPROM.put(EEPROM_ADDR_EQ2_LOWQ, eq2_lowq);
EEPROM.put(EEPROM_ADDR_EQ2_LOWGAIN, eq2_lowgain);
EEPROM.put(EEPROM_ADDR_EQ2_MEDF, eq2_medf);
EEPROM.put(EEPROM_ADDR_EQ2_MEDQ, eq2_medq);
EEPROM.put(EEPROM_ADDR_EQ2_MEDGAIN, eq2_medgain);
EEPROM.put(EEPROM_ADDR_EQ2_HIGHF, eq2_highf);
EEPROM.put(EEPROM_ADDR_EQ2_HIGHQ, eq2_highq);
EEPROM.put(EEPROM_ADDR_EQ2_HIGHGAIN, eq2_highgain);
EEPROM.put(EEPROM_ADDR_GATE_THRESHOLD1, gateThreshold1);
EEPROM.put(EEPROM_ADDR_GATE_ATTACK1, gateAttack1);
EEPROM.put(EEPROM_ADDR_GATE_RELEASE1, gateRelease1);
EEPROM.put(EEPROM_ADDR_GATE_HYSTERESIS1, gateHysteresis1);
EEPROM.put(EEPROM_ADDR_GATE_ATTENUATION1, gateAttenuation1);
EEPROM.put(EEPROM_ADDR_GATE_THRESHOLD2, gateThreshold2);
EEPROM.put(EEPROM_ADDR_GATE_ATTACK2, gateAttack2);
EEPROM.put(EEPROM_ADDR_GATE_RELEASE2, gateRelease2);
EEPROM.put(EEPROM_ADDR_GATE_HYSTERESIS2, gateHysteresis2);
EEPROM.put(EEPROM_ADDR_GATE_ATTENUATION2, gateAttenuation2);
EEPROM.put(EEPROM_ADDR_COMP_THRESHOLD1, compThreshold1);
EEPROM.put(EEPROM_ADDR_COMP_ATTACK1, compAttack1);
EEPROM.put(EEPROM_ADDR_COMP_RELEASE1, compRelease1);
EEPROM.put(EEPROM_ADDR_COMP_RATIO1, compRatio1);
EEPROM.put(EEPROM_ADDR_COMP_KNEE_WIDTH1, compKneeWidth1);
EEPROM.put(EEPROM_ADDR_COMP_THRESHOLD2, compThreshold2);
EEPROM.put(EEPROM_ADDR_COMP_ATTACK2, compAttack2);
EEPROM.put(EEPROM_ADDR_COMP_RELEASE2, compRelease2);
EEPROM.put(EEPROM_ADDR_COMP_RATIO2, compRatio2);
EEPROM.put(EEPROM_ADDR_COMP_KNEE_WIDTH2, compKneeWidth2);
EEPROM.put(EEPROM_ADDR_LIM_THRESHOLD1, limThreshold1);
EEPROM.put(EEPROM_ADDR_LIM_ATTACK1, limAttack1);
EEPROM.put(EEPROM_ADDR_LIM_RELEASE1, limRelease1);
EEPROM.put(EEPROM_ADDR_LIM_THRESHOLD2, limThreshold2);
EEPROM.put(EEPROM_ADDR_LIM_ATTACK2, limAttack2);
EEPROM.put(EEPROM_ADDR_LIM_RELEASE2, limRelease2);
EEPROM.put(EEPROM_ADDR_MAKEUP_GAIN1, makeupGain1);
EEPROM.put(EEPROM_ADDR_MAKEUP_GAIN2, makeupGain2);
EEPROM.put(EEPROM_ADDR_REVERB_SIZE, reverbSize);
EEPROM.put(EEPROM_ADDR_REVERB_LOWPASS, reverbLowpass);
EEPROM.put(EEPROM_ADDR_REVERB_LODAMP, reverbLodamp);
EEPROM.put(EEPROM_ADDR_REVERB_HIDAMP, reverbHidamp);
EEPROM.put(EEPROM_ADDR_REVERB_DIFFUSION, reverbDiffusion);
}
void loadSettingsFromEEPROM() {
EEPROM.get(EEPROM_ADDR_MIC_VOLUME, micVolume);
EEPROM.get(EEPROM_ADDR_GUITAR_VOLUME, guitarVolume);
EEPROM.get(EEPROM_ADDR_MIC_REVERB, micReverb);
EEPROM.get(EEPROM_ADDR_GUITAR_REVERB, guitarReverb);
EEPROM.get(EEPROM_ADDR_MIC_IN_LVL, micInLvl);
EEPROM.get(EEPROM_ADDR_GUITAR_IN_LVL, guitarInLvl);
EEPROM.get(EEPROM_ADDR_OUTPUT_LVL, outPutLvl);
EEPROM.get(EEPROM_ADDR_HP1_LOWCUT, hp1_lowcut);
EEPROM.get(EEPROM_ADDR_HP2_LOWCUT, hp2_lowcut);
EEPROM.get(EEPROM_ADDR_EQ1_LOWF, eq1_lowf);
EEPROM.get(EEPROM_ADDR_EQ1_LOWQ, eq1_lowq);
EEPROM.get(EEPROM_ADDR_EQ1_LOWGAIN, eq1_lowgain);
EEPROM.get(EEPROM_ADDR_EQ1_MEDF, eq1_medf);
EEPROM.get(EEPROM_ADDR_EQ1_MEDQ, eq1_medq);
EEPROM.get(EEPROM_ADDR_EQ1_MEDGAIN, eq1_medgain);
EEPROM.get(EEPROM_ADDR_EQ1_HIGHF, eq1_highf);
EEPROM.get(EEPROM_ADDR_EQ1_HIGHQ, eq1_highq);
EEPROM.get(EEPROM_ADDR_EQ1_HIGHGAIN, eq1_highgain);
EEPROM.get(EEPROM_ADDR_EQ2_LOWF, eq2_lowf);
EEPROM.get(EEPROM_ADDR_EQ2_LOWQ, eq2_lowq);
EEPROM.get(EEPROM_ADDR_EQ2_LOWGAIN, eq2_lowgain);
EEPROM.get(EEPROM_ADDR_EQ2_MEDF, eq2_medf);
EEPROM.get(EEPROM_ADDR_EQ2_MEDQ, eq2_medq);
EEPROM.get(EEPROM_ADDR_EQ2_MEDGAIN, eq2_medgain);
EEPROM.get(EEPROM_ADDR_EQ2_HIGHF, eq2_highf);
EEPROM.get(EEPROM_ADDR_EQ2_HIGHQ, eq2_highq);
EEPROM.get(EEPROM_ADDR_EQ2_HIGHGAIN, eq2_highgain);
EEPROM.get(EEPROM_ADDR_GATE_THRESHOLD1, gateThreshold1);
EEPROM.get(EEPROM_ADDR_GATE_ATTACK1, gateAttack1);
EEPROM.get(EEPROM_ADDR_GATE_RELEASE1, gateRelease1);
EEPROM.get(EEPROM_ADDR_GATE_HYSTERESIS1, gateHysteresis1);
EEPROM.get(EEPROM_ADDR_GATE_ATTENUATION1, gateAttenuation1);
EEPROM.get(EEPROM_ADDR_COMP_THRESHOLD1, compThreshold1);
EEPROM.get(EEPROM_ADDR_COMP_ATTACK1, compAttack1);
EEPROM.get(EEPROM_ADDR_COMP_RELEASE1, compRelease1);
EEPROM.get(EEPROM_ADDR_COMP_RATIO1, compRatio1);
EEPROM.get(EEPROM_ADDR_COMP_KNEE_WIDTH1, compKneeWidth1);
EEPROM.get(EEPROM_ADDR_LIM_THRESHOLD1, limThreshold1);
EEPROM.get(EEPROM_ADDR_LIM_ATTACK1, limAttack1);
EEPROM.get(EEPROM_ADDR_LIM_RELEASE1, limRelease1);
EEPROM.get(EEPROM_ADDR_MAKEUP_GAIN1, makeupGain1);
EEPROM.get(EEPROM_ADDR_GATE_THRESHOLD2, gateThreshold2);
EEPROM.get(EEPROM_ADDR_GATE_ATTACK2, gateAttack2);
EEPROM.get(EEPROM_ADDR_GATE_RELEASE2, gateRelease2);
EEPROM.get(EEPROM_ADDR_GATE_HYSTERESIS2, gateHysteresis2);
EEPROM.get(EEPROM_ADDR_GATE_ATTENUATION2, gateAttenuation2);
EEPROM.get(EEPROM_ADDR_COMP_THRESHOLD2, compThreshold2);
EEPROM.get(EEPROM_ADDR_COMP_ATTACK2, compAttack2);
EEPROM.get(EEPROM_ADDR_COMP_RELEASE2, compRelease2);
EEPROM.get(EEPROM_ADDR_COMP_RATIO2, compRatio2);
EEPROM.get(EEPROM_ADDR_COMP_KNEE_WIDTH2, compKneeWidth2);
EEPROM.get(EEPROM_ADDR_LIM_THRESHOLD2, limThreshold2);
EEPROM.get(EEPROM_ADDR_LIM_ATTACK2, limAttack2);
EEPROM.get(EEPROM_ADDR_LIM_RELEASE2, limRelease2);
EEPROM.get(EEPROM_ADDR_MAKEUP_GAIN2, makeupGain2);
EEPROM.get(EEPROM_ADDR_REVERB_SIZE, reverbSize);
EEPROM.get(EEPROM_ADDR_REVERB_LOWPASS, reverbLowpass);
EEPROM.get(EEPROM_ADDR_REVERB_LODAMP, reverbLodamp);
EEPROM.get(EEPROM_ADDR_REVERB_HIDAMP, reverbHidamp);
EEPROM.get(EEPROM_ADDR_REVERB_DIFFUSION, reverbDiffusion);
EEPROM.get(EEPROM_ADDR_REVERB_MIC_SEND, reverbMicSend);
EEPROM.get(EEPROM_ADDR_REVERB_GUITAR_SEND, reverbGuitarSend);
}
void setup() {
AudioMemory(6);
AudioMemory_F32(12);
codec.enable();
codec.inputSelect(AUDIO_INPUT_LINEIN);
codec.adcHighPassFilterDisable();
codec.lineInLevel(micInLvl, guitarInLvl); // 5: 1.33v p-p(default), 0: 3.12v, 15: 0.24v
codec.volume(0.6); //headphone volume 0 - 1.0
codec.lineOutLevel(outPutLvl); //29: 1.29v p-p(default), 13: 3.16v, 31: 1.16v
loadSettingsFromEEPROM();
tft.begin();
tft.setRotation(3); // Adjust as per your display's orientation
drawMenuBar("Main Menu");
Menu mainMenu = {
menuItems, // The array of main menu item strings
menuItemCount, // The count of main menu items
0, // Initial selected item index
"Main Menu", // Title of the menu
true, // Indicates it's the main menu
0,
nullptr
};
drawMenu(mainMenu);
volume.gain(0, micVolume);
volume.gain(1, guitarVolume);
volume.gain(2, micReverb);
volume.gain(3, guitarReverb);
reverb_send.gain(0, reverbMicSend);
reverb_send.gain(1, reverbGuitarSend);
// Apply the loaded settings to the filters
hp1.setBiQuadEq(0, 'H', hp1_lowcut, 1.1, 0);
hp1.setBiQuadEq(1, 'H', hp1_lowcut, 1.1, 0);
hp2.setBiQuadEq(0, 'H', hp2_lowcut, 1.1, 0);
hp2.setBiQuadEq(1, 'H', hp2_lowcut, 1.1, 0);
eq1.setBiQuadEq(0, 'P', eq1_lowf, eq1_lowq, eq1_lowgain);
eq1.setBiQuadEq(1, 'P', eq2_medf, eq2_medq, eq2_medgain);
eq1.setBiQuadEq(2, 'P', eq2_highf, eq2_highq, eq2_highgain);
eq2.setBiQuadEq(0, 'P', eq1_lowf, eq1_lowq, eq1_lowgain);
eq2.setBiQuadEq(1, 'P', eq2_medf, eq2_medq, eq2_medgain);
eq2.setBiQuadEq(2, 'P', eq2_highf, eq2_highq, eq2_highgain);
// Gate (threshold = -50.0f, attack = 0.01f, release = 0.1f, hysterisis = 6.0f, attenuation = -12.0f);
dynamics1.gate(gateThreshold1, gateAttack1, gateRelease1, gateHysteresis1, gateAttenuation1);
// Compressor (threshold = -10.0f, attack = 0.1f, release = 0.2f, ratio = 4.0f, kneeWidth = 6.0f);
dynamics1.compression(compThreshold1, compAttack1, compRelease1, compRatio1, compKneeWidth1);
// Limiter (threshold = -0.1f, attack = 0.01f, release = 0.1f);
dynamics1.limit(limThreshold1, limAttack1, limRelease1);
// Auto Makeup Gain (headroom = 6.0f);
dynamics1.autoMakeupGain(makeupGain1);
// Gate (threshold = -50.0f, attack = 0.01f, release = 0.1f, hysterisis = 6.0f, attenuation = -12.0f);
dynamics2.gate(gateThreshold2, gateAttack2, gateRelease2, gateHysteresis2, gateAttenuation2);
// Compressor (threshold = -10.0f, attack = 0.1f, release = 0.2f, ratio = 4.0f, kneeWidth = 6.0f);
dynamics2.compression(compThreshold2, compAttack2, compRelease2, compRatio2, compKneeWidth2);
// Limiter (threshold = -0.1f, attack = 0.01f, release = 0.1f);
dynamics2.limit(limThreshold2, limAttack2, limRelease2);
// Auto Makeup Gain (headroom = 6.0f);
dynamics2.autoMakeupGain(makeupGain2);
reverb.size(reverbSize); // max reverb length
reverb.lowpass(reverbLowpass); // sets the reverb master lowpass filter
reverb.lodamp(reverbLodamp); // amount of low end loss in the reverb tail
reverb.hidamp(reverbHidamp); // amount of treble loss in the reverb tail
reverb.diffusion(reverbDiffusion); // 1.0 is the detault setting, lower it to create more "echoey" reverb
}
void loop() {
handleEncoder();
handleButton();
}
void handleEncoder() {
static int lastEncoderPosition = 0;
int currentEncoderPosition = encoder.read() / 4; // Adjust the divisor based on your encoder's sensitivity
if (currentEncoderPosition != lastEncoderPosition) {
if (currentMode == MAIN_MENU) {
int previousSelectedItem = currentSelectedItem;
currentSelectedItem += (currentEncoderPosition - lastEncoderPosition);
if (currentSelectedItem < 0) {
currentSelectedItem = 0;
} else if (currentSelectedItem >= menuItemCount) {
currentSelectedItem = menuItemCount - 1;
}
// Redraw only the previously and currently selected items
if (previousSelectedItem != currentSelectedItem) {
redrawMenuItem(previousSelectedItem, false);
redrawMenuItem(currentSelectedItem, true);
}
} else if (currentMode == EDIT_MODE) {
// Logic to adjust the value of the current selected item
adjustValue(currentEncoderPosition - lastEncoderPosition);
}
if (currentMode == SUB_MENU) {
int previousSubMenuItem = micEqMenu.currentItem;
int encoderChange = currentEncoderPosition - lastEncoderPosition;
if (encoderChange != 0) {
micEqMenu.currentItem += encoderChange;
micEqMenu.currentItem = constrain(micEqMenu.currentItem, 0, micEqMenu.itemCount - 1);
// Redraw only the changed items
if (previousSubMenuItem != micEqMenu.currentItem) {
redrawMicEqItem(previousSubMenuItem, false);
redrawMicEqItem(micEqMenu.currentItem, true);
}
}
}
lastEncoderPosition = currentEncoderPosition;
}
}
void handleButton() {
encoderButton.update();
if (encoderButton.fallingEdge()) {
if (currentMode == MAIN_MENU && currentSelectedItem < 4) {
currentMode = EDIT_MODE;
// Immediately redraw the selected menu item with the value in blue
drawValue(currentSelectedItem, true); // true indicates edit mode
}
else if (currentSelectedItem == 4) { // Mic EQ submenu
currentMode = SUB_MENU;
micEqMenu.currentItem = 0; // Reset submenu selection
drawMicEqMenu(); // Draw Mic EQ submenu
}
else if (currentMode == EDIT_MODE) {
currentMode = MAIN_MENU;
// Save to EEPROM
saveSettingsToEEPROM();
// Redraw the selected menu item with the value in white
drawValue(currentSelectedItem, false); // false indicates normal mode
}
else if (currentMode == SUB_MENU) {
if (micEqMenu.currentItem == micEqMenu.itemCount - 1) { // "Back" option
currentMode = MAIN_MENU;
drawMenu(mainMenu);
} else {
currentMode = SUB_MENU_EDIT_MODE;
drawMicEqValue(micEqMenu.currentItem, true);
}
} else if (currentMode == SUB_MENU_EDIT_MODE) {
currentMode = SUB_MENU;
// Add logic to save edited values
drawMicEqMenu();
}
}
}
void drawValue(int itemIndex, bool inEditMode) {
// Get the x, y position for the value
int x = 200; // Adjust the X position as needed
int y = 35 + 21 * itemIndex;
// Clear the area for the value
tft.fillRect(x, y, 50, 15, ILI9341_BLACK); // Adjust the size as needed
// Set the text color based on the mode
tft.setTextColor(inEditMode ? ILI9341_BLUE : ILI9341_WHITE);
// Display the value
tft.setCursor(x, y);
switch (itemIndex) {
case 0:
tft.println(micVolume, 2);
break;
case 1:
tft.println(guitarVolume, 2);
break;
case 2:
tft.println(micReverb, 2);
break;
case 3:
tft.println(guitarReverb, 2);
break;
}
}
void adjustValue(int encoderChange) {
// Ensure we are editing an adjustable item
if (currentSelectedItem < 0 || currentSelectedItem >= 4) return;
// Adjust the value based on encoder change
float* value;
switch (currentSelectedItem) {
case 0: value = &micVolume; break;
case 1: value = &guitarVolume; break;
case 2: value = &micReverb; break;
case 3: value = &guitarReverb; break;
}
*value += encoderChange * 0.01; // Adjust the step size as necessary
*value = constrain(*value, 0.0, 1.0); // Constrain the value between 0 and 1
// Update the display to show the new value
redrawValue(currentSelectedItem);
}
void redrawValue(int itemIndex) {
tft.fillRect(200, 35 + 21 * itemIndex, 50, 15, ILI9341_BLACK); // Adjust size as needed
tft.setTextColor(ILI9341_BLUE); // Color for edit mode
tft.setCursor(200, 35 + 21 * itemIndex); // Adjust position as needed
switch (itemIndex) {
case 0: tft.println(micVolume, 2); break;
case 1: tft.println(guitarVolume, 2); break;
case 2: tft.println(micReverb, 2); break;
case 3: tft.println(guitarReverb, 2); break;
}
}
void redrawMenuItem(int itemIndex, bool highlight) {
tft.setFont(Arial_13);
tft.setCursor(10, 35 + 21 * itemIndex);
if (highlight) {
tft.setTextColor(ILI9341_BLUE);
} else {
tft.setTextColor(ILI9341_WHITE);
}
// Draw the separator line after the item
tft.drawFastHLine(0, 52 + 21 * itemIndex, tft.width(), 0x18E3);
tft.print(menuItems[itemIndex]);
// Update value display if necessary
if (itemIndex < 4) {
tft.fillRect(200, 35 + 21 * itemIndex, 50, 15, ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(200, 35 + 21 * itemIndex);
switch (itemIndex) {
case 0:
tft.println(micVolume, 2);
break;
case 1:
tft.println(guitarVolume, 2);
break;
case 2:
tft.println(micReverb, 2);
break;
case 3:
tft.println(guitarReverb, 2);
break;
}
}
}
void drawMenuBar(const char* title) {
tft.fillScreen(ILI9341_BLACK);
tft.setFont(Arial_16_Bold);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(4);
tft.setCursor(10, 5);
tft.println(title);
tft.drawFastHLine(0, 27, tft.width(), ILI9341_WHITE);
tft.drawFastHLine(0, 28, tft.width(), 0x7BEF);
tft.drawFastHLine(0, 29, tft.width(), 0x39E7);
tft.drawFastHLine(0, 30, tft.width(), ILI9341_WHITE); // Draw a line under the menu bar
}
void drawMenu(Menu menu) {
drawMenuBar(menu.title); // Assume drawMenuBar() is adjusted to take a string title
tft.setFont(Arial_13);
for (int i = 0; i < menu.itemCount; ++i) {
tft.setCursor(10, 35 + 21 * i);
tft.setTextColor(i == menu.currentItem ? ILI9341_BLUE : ILI9341_WHITE);
tft.print(menu.items[i]);
// Draw separator
tft.drawFastHLine(0, 52 + 21 * i, tft.width(), 0x18E3);
// Special handling for items with values (first 4 items in your main menu)
if (menu.isMain && i < 4) {
tft.fillRect(200, 35 + 21 * i, 50, 15, ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(200, 35 + 21 * i);
// Display the corresponding value based on the menu item
switch (i) {
case 0: tft.println(micVolume, 2); break;
case 1: tft.println(guitarVolume, 2); break;
case 2: tft.println(micReverb, 2); break;
case 3: tft.println(guitarReverb, 2); break;
}
}
}
}
void drawMicEqMenu() {
drawMenuBar(micEqMenu.title);
tft.setFont(Arial_13);
for (int i = 0; i < micEqMenu.itemCount; ++i) {
tft.setCursor(10, 35 + 21 * i);
tft.setTextColor(i == micEqMenu.currentItem ? ILI9341_BLUE : ILI9341_WHITE);
tft.print(micEqMenu.items[i]);
// Draw separator lines
tft.drawFastHLine(0, 52 + 21 * i, tft.width(), 0x18E3);
// Check if this item has an associated value to display
if (i < (micEqMenu.itemCount - 1)) { // Assuming last item is "Back", which doesn't have a value
int x = 200; // X position for value display
int y = 35 + 21 * i; // Y position for value display
// Display the value for each submenu item
tft.fillRect(x, y, 50, 15, ILI9341_BLACK); // Clear area
tft.setTextColor(ILI9341_WHITE); // Text color
tft.setCursor(x, y);
switch (i) {
case 0: tft.println(hp1_lowcut, 2); break;
case 1: tft.println(eq1_lowf, 2); break;
case 2: tft.println(eq1_lowq, 2); break;
case 3: tft.println(eq1_lowgain, 2); break;
case 4: tft.println(eq1_highf, 2); break;
case 5: tft.println(eq1_highq, 2); break;
case 6: tft.println(eq1_highgain, 2); break;
}
}
}
}
//Mic Eq Menu
void drawMicEqValue(int itemIndex, bool inEditMode) {
// Get the x, y position for the value
int x = 200; // Adjust the X position as needed
int y = 35 + 21 * itemIndex;
// Clear the area for the value
tft.fillRect(x, y, 50, 15, ILI9341_BLACK); // Adjust the size as needed
// Set the text color based on the mode
tft.setTextColor(inEditMode ? ILI9341_BLUE : ILI9341_WHITE);
// Display the value
tft.setCursor(x, y);
switch (itemIndex) {
case 0: tft.println(hp1_lowcut, 2); break;
case 1: tft.println(eq1_lowf, 2); break;
case 2: tft.println(eq1_lowq, 2); break;
case 3: tft.println(eq1_lowgain, 2); break;
case 4: tft.println(eq1_highf, 2); break;
case 5: tft.println(eq1_highq, 2); break;
case 6: tft.println(eq1_highgain, 2); break;
}
}
void adjustMicEqValue(int encoderChange) {
// Ensure we are editing an adjustable item
if (currentSelectedItem < 0 || currentSelectedItem >= 4) return;
// Adjust the value based on encoder change
float* value;
switch (currentSelectedItem) {
case 0: value = &hp1_lowcut; break;
case 1: value = &eq1_lowf; break;
case 2: value = &eq1_lowq; break;
case 3: value = &eq1_lowgain; break;
case 4: value = &eq1_highf; break;
case 5: value = &eq1_highq; break;
case 6: value = &eq1_highgain; break;
}
*value += encoderChange * 0.01; // Adjust the step size as necessary
*value = constrain(*value, 0.0, 1.0); // Constrain the value between 0 and 1
// Update the display to show the new value
redrawMicEqValue(currentSelectedItem);
}
void redrawMicEqItem(int itemIndex, bool highlight) {
tft.setFont(Arial_13);
tft.setCursor(10, 35 + 21 * itemIndex);
if (highlight) {
tft.setTextColor(ILI9341_BLUE);
} else {
tft.setTextColor(ILI9341_WHITE);
}
// Draw the separator line after the item
tft.drawFastHLine(0, 52 + 21 * itemIndex, tft.width(), 0x18E3);
tft.print(micEqMenu.items[itemIndex]);
// Update value display if necessary
if (itemIndex < 6) {
tft.fillRect(200, 35 + 21 * itemIndex, 50, 15, ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(200, 35 + 21 * itemIndex);
switch (itemIndex) {
case 0: tft.println(hp1_lowcut, 2); break;
case 1: tft.println(eq1_lowf, 2); break;
case 2: tft.println(eq1_lowq, 2); break;
case 3: tft.println(eq1_lowgain, 2); break;
case 4: tft.println(eq1_highf, 2); break;
case 5: tft.println(eq1_highq, 2); break;
case 6: tft.println(eq1_highgain, 2); break;
}
}
}
void redrawMicEqValue(int itemIndex) {
tft.fillRect(200, 35 + 21 * itemIndex, 50, 15, ILI9341_BLACK); // Adjust size as needed
tft.setTextColor(ILI9341_BLUE); // Color for edit mode
tft.setCursor(200, 35 + 21 * itemIndex); // Adjust position as needed
switch (itemIndex) {
case 0: tft.println(hp1_lowcut, 2); break;
case 1: tft.println(eq1_lowf, 2); break;
case 2: tft.println(eq1_lowq, 2); break;
case 3: tft.println(eq1_lowgain, 2); break;
case 4: tft.println(eq1_highf, 2); break;
case 5: tft.println(eq1_highq, 2); break;
case 6: tft.println(eq1_highgain, 2); break;
}
}