#include <Bounce2.h>
// #include <MIDI.h>
#include <LCD_I2C.h>
#define BUTTON1_PIN 2
#define BUTTON2_PIN 3
#define BUTTON3_PIN 4
#define BUTTON4_PIN 5
#define BUTTON5_PIN 6
#define BUTTON6_PIN 7
// #define POT_PIN A0 // Pino analógico para o potenciômetro
#define LONG_PRESS_TIME 1000
#define CLICK_INTERVAL 450
struct ButtonAction {
int type;
int val;
int val1;
int val2;
int channel;
const char* name;
bool isToggle;
};
const int numButtons = 6;
const int numClicks = 3;
Bounce debouncers[numButtons];
unsigned long pressStartTime[numButtons] = {0};
int clickCount[numButtons] = {0};
bool longPressDetected[numButtons] = {false};
bool simultaneousPressDetected[4] = {false};
bool toggleStateButtonActions[numButtons][numClicks] = {false};
bool toggleStateSimultaneousActions[4] = {false};
bool toggleStateLongpressActions[numButtons] = {false};
int lastToggleValues[numButtons][numClicks] = {0};
int getToggleValue(bool &toggleState, int &lastValue, int val1, int val2, bool isToggle) {
Serial.print("toggleState: ");
Serial.print(toggleState);
Serial.print(", lastValue: ");
Serial.print(lastValue);
Serial.print(", Val1: ");
Serial.print(val1);
Serial.print(", Val2: ");
Serial.print(val2);
Serial.print(", isToggle: ");
Serial.println(isToggle);
toggleState = !toggleState;
if (isToggle) {
lastValue = (lastValue == val2) ? val1 : val2;
return lastValue;
}
return val1;
}
int currentBank = 1;
const int maxBank = 1;
int lastStateFxPot = 0;
bool hasPotentiometer = false;
bool debugMode = true;
LCD_I2C lcd(0x27, 16, 2);
// Definição do caractere "Smiley"
byte smiley[8] = {
0b00000,
0b01010,
0b01010,
0b00000,
0b10001,
0b01110,
0b00000,
0b00000
};
ButtonAction buttonActions[numButtons][numClicks] = {
{{25, 1, 1, -1, 1, "CENA 1", false}, {51, 127, 127, 0, 1, "A4", true}, {57, 127, 127, 0, 1, "B4", true}},
{{25, 2, 2, -1, 1, "CENA 2", false}, {52, 127, 127, 0, 1, "A5", true}, {58, 127, 127, 0, 1, "B5", true}},
{{25, 3, 3, -1, 1, "CENA 3", false}, {53, 127, 127, 0, 1, "A6", true}, {59, 127, 127, 0, 1, "B6", true}},
{{26, 127, 127, -1, 1, "PATCH DOWN", false}, {48, 127, 127, 0, 1, "A1", true}, {54, 127, 127, 0, 1, "B1", true}},
{{27, 127, 127, -1, 1, "PATCH UP", false}, {49, 127, 127, 0, 1, "A2", true}, {55, 127, 127, 0, 1, "B2", true}},
{{29, 127, 127, 0, 1, "MAIN DISPLAY", true}, {50, 127, 127, 0, 1, "A3", true}, {56, 127, 127, 0, 1, "B3", true}}
};
ButtonAction simultaneousActions[4] = {
{22, 127, 127, -1, 1, "BANK DOWN", false},
{23, 127, 127, -1, 1, "BANK UP", false},
{25, 3, 3, -1, 1, "CENA 3", false},
{60, 127, 127, 0, 1, "TUNER", true}
};
ButtonAction longpressActions[numButtons] = {
{22, 127, 127, 0, 1, "BANK DOWN", false},
{23, 127, 127, 0, 1, "BANK UP", false},
{60, 127, 127, 0, 1, "TUNER", true},
{26, 127, 127, 0, 1, "PATCH DOWN", false},
{27, 127, 127, 0, 1, "PATCH UP", false},
{60, 127, 127, 0, 1, "TUNER", true}
};
ButtonAction getActionForButtonAndBank(int buttonIndex, int clickCount) {
if (buttonIndex >= 0 && buttonIndex < numButtons && clickCount >= 1 && clickCount <= numClicks) {
ButtonAction &action = buttonActions[buttonIndex][clickCount - 1];
action.val = getToggleValue(toggleStateButtonActions[buttonIndex][clickCount - 1], lastToggleValues[buttonIndex][clickCount - 1], action.val1, action.val2, action.isToggle);
return action;
}
return {-1, -1, -1, -1, -1, "Invalid Action", false};
}
ButtonAction getSimultaneousAction(int index) {
if (index >= 0 && index < 4) {
simultaneousActions[index].val = getToggleValue(toggleStateSimultaneousActions[index], lastToggleValues[index][0], simultaneousActions[index].val1, simultaneousActions[index].val2, simultaneousActions[index].isToggle);
return simultaneousActions[index];
}
return {-1, -1, -1, -1, -1, "Invalid Action", false};
}
ButtonAction getLongpressAction(int buttonIndex) {
if (buttonIndex >= 0 && buttonIndex < numButtons) {
longpressActions[buttonIndex].val = getToggleValue(toggleStateLongpressActions[buttonIndex], lastToggleValues[buttonIndex][0], longpressActions[buttonIndex].val1, longpressActions[buttonIndex].val2, longpressActions[buttonIndex].isToggle);
return longpressActions[buttonIndex];
}
return {-1, -1, -1, -1, -1, "Invalid Action", false};
}
void processClicks(int buttonIndex, int clickCount) {
ButtonAction action = getActionForButtonAndBank(buttonIndex, clickCount);
if (debugMode) {
const char* clickTypes[] = {"Clique simples", "Duplo clique", "Triplo clique"};
Serial.print("Botão ");
Serial.print(buttonIndex + 1);
Serial.print(": ");
Serial.print(clickTypes[clickCount - 1]);
Serial.print(" ");
Serial.print(action.name);
Serial.print(" ");
}
sendControlChange(action);
}
void handleSimultaneousPress() {
if (debouncers[1].fell() && debouncers[0].read() == LOW) {
simultaneousPressDetected[0] = true;
ButtonAction action = getSimultaneousAction(0);
sendControlChange(action);
clickCount[0] = 0;
clickCount[1] = 0;
}
if (debouncers[2].fell() && debouncers[1].read() == LOW) {
simultaneousPressDetected[1] = true;
ButtonAction action = getSimultaneousAction(1);
sendControlChange(action);
clickCount[1] = 0;
clickCount[2] = 0;
}
if (debouncers[4].fell() && debouncers[3].read() == LOW) {
simultaneousPressDetected[2] = true;
ButtonAction action = getSimultaneousAction(2);
sendControlChange(action);
clickCount[4] = 0;
clickCount[3] = 0;
}
if (debouncers[5].fell() && debouncers[4].read() == LOW) {
simultaneousPressDetected[3] = true;
ButtonAction action = getSimultaneousAction(3);
sendControlChange(action);
clickCount[4] = 0;
clickCount[5] = 0;
}
}
void handleButton(int buttonIndex) {
if (debouncers[buttonIndex].fell()) {
pressStartTime[buttonIndex] = millis();
clickCount[buttonIndex]++;
longPressDetected[buttonIndex] = false;
simultaneousPressDetected[0] = false;
simultaneousPressDetected[1] = false;
simultaneousPressDetected[2] = false;
simultaneousPressDetected[3] = false;
}
if (debouncers[buttonIndex].read() == LOW) {
unsigned long pressDuration = millis() - pressStartTime[buttonIndex];
if (pressDuration >= LONG_PRESS_TIME && !longPressDetected[buttonIndex]) {
longPressDetected[buttonIndex] = true;
ButtonAction action = getLongpressAction(buttonIndex);
sendControlChange(action);
clickCount[buttonIndex] = 0;
}
} else {
if (millis() - pressStartTime[buttonIndex] > CLICK_INTERVAL && clickCount[buttonIndex] > 0 && !longPressDetected[buttonIndex] && !simultaneousPressDetected[0] && !simultaneousPressDetected[1] && !simultaneousPressDetected[2] && !simultaneousPressDetected[3]) {
processClicks(buttonIndex, clickCount[buttonIndex]);
clickCount[buttonIndex] = 0;
}
}
}
// MIDI_CREATE_DEFAULT_INSTANCE();
void setup() {
// MIDI.begin(MIDI_CHANNEL_OMNI);
int buttonPins[numButtons] = {BUTTON1_PIN, BUTTON2_PIN, BUTTON3_PIN, BUTTON4_PIN, BUTTON5_PIN, BUTTON6_PIN};
for (int i = 0; i < numButtons; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
debouncers[i].attach(buttonPins[i]);
debouncers[i].interval(25);
}
if (debugMode){
Serial.begin(9600);
}
lcd.begin();
lcd.backlight();
// Criar o caractere especial no slot 0
lcd.createChar(0, smiley);
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("MIDI S6");
lcd.setCursor(11, 0);
lcd.write(byte(0)); // Exibe o emoji 😊
delay(2000);
mainDisplay();
}
void loop() {
for (int i = 0; i < numButtons; i++) {
debouncers[i].update();
handleButton(i);
}
handleSimultaneousPress();
}
void mainDisplay() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("P-DW");
lcd.setCursor(6, 0);
lcd.print("P-UP");
lcd.setCursor(12, 0);
lcd.print("DPLY");
lcd.setCursor(0, 1);
lcd.print("CNA1");
lcd.setCursor(6, 1);
lcd.print("CNA2");
lcd.setCursor(12, 1);
lcd.print("CNA3");
}
void sendControlChange(ButtonAction action) {
if (action.type != -1 && action.val != -1 && action.channel != -1) {
if (debugMode) {
Serial.print("Type: ");
Serial.print(action.type);
Serial.print(", Val: ");
Serial.print(action.val);
Serial.print(", Channel: ");
Serial.print(action.channel);
Serial.print(", Name: ");
Serial.print(action.name);
Serial.print(", Toggle: ");
Serial.println(action.isToggle);
} else {
// MIDI.sendControlChange(action.type, action.val, action.channel);
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(action.name);
lcd.setCursor(0, 1);
if (!action.isToggle) {
lcd.print(action.val);
} else {
lcd.print(action.val == 127 ? "ON" : "OFF");
}
delay(1000);
mainDisplay();
}
}