#include <Bounce2.h>
// #include <MIDI.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
// Tempo em milissegundos para considerar um pressionamento longo
#define LONG_PRESS_TIME 1000
// Intervalo máximo em milissegundos entre cliques para considerar duplo ou triplo clique
#define CLICK_INTERVAL 500
// Estrutura para armazenar type, val e channel
struct ButtonAction {
int type;
int val;
int channel;
};
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};
// Variáveis de estado para o toggle
bool toggleStateButtonActions[numButtons][numClicks] = {false};
bool toggleStateSimultaneousActions[4] = {false};
bool toggleStateLongpressActions[numButtons] = {false};
// Atualiza o valor de val para toggle
int getToggleValue(bool &toggleState) {
toggleState = !toggleState;
return toggleState ? 127 : 0;
}
// Variável para armazenar o banco atual
int currentBank = 1;
const int maxBank = 1;
int lastStateFxPot = 0; // Último valor lido do potenciômetro
bool hasPotentiometer = false;
bool debugMode = true;
// Matriz para armazenar as ações para cada botão e banco
ButtonAction buttonActions[numButtons][numClicks] = {
{{70, 127, 1}, {71, 127, 1}, {72, 127, 1}}, // Botão 1, Banco 1 (simples, duplo, triplo)
{{73, 127, 1}, {74, 127, 1}, {75, 127, 1}}, // Botão 2, Banco 1
{{76, 127, 1}, {77, 127, 1}, {78, 127, 1}}, // Botão 3, Banco 1
{{79, 127, 1}, {80, 127, 1}, {81, 127, 1}}, // Botão 4, Banco 1
{{82, 127, 1}, {83, 127, 1}, {84, 127, 1}}, // Botão 5, Banco 1
{{85, 127, 1}, {86, 127, 1}, {87, 127, 1}} // Botão 6, Banco 1
};
// Matriz para armazenar as ações simultâneas
ButtonAction simultaneousActions[4] = {
{88, 127, 1}, // Botões 1 e 2
{89, 127, 1}, // Botões 2 e 3
{90, 127, 1}, // Botões 4 e 5
{91, 127, 1} // Botões 5 e 6
};
// Matriz para armazenar as ações de pressionamento longo
ButtonAction longpressActions[numButtons] = {
{92, 127, 1}, // Botão 1
{93, 127, 1}, // Botão 2
{94, 127, 1}, // Botão 3
{95, 127, 1}, // Botão 4
{96, 127, 1}, // Botão 5
{97, 127, 1} // Botão 6
};
ButtonAction getActionForButtonAndBank(int buttonIndex, int clickCount) {
if (buttonIndex >= 0 && buttonIndex < numButtons && clickCount >= 1 && clickCount <= numClicks) {
buttonActions[buttonIndex][clickCount - 1].val = getToggleValue(toggleStateButtonActions[buttonIndex][clickCount - 1]);
return buttonActions[buttonIndex][clickCount - 1];
}
return {-1, -1, -1}; // Ação inválida
}
ButtonAction getSimultaneousAction(int index) {
if (index >= 0 && index < 4) {
simultaneousActions[index].val = getToggleValue(toggleStateSimultaneousActions[index]);
return simultaneousActions[index];
}
return {-1, -1, -1}; // Ação inválida
}
ButtonAction getLongpressAction(int buttonIndex) {
if (buttonIndex >= 0 && buttonIndex < numButtons) {
longpressActions[buttonIndex].val = getToggleValue(toggleStateLongpressActions[buttonIndex]);
return longpressActions[buttonIndex];
}
return {-1, -1, -1}; // Ação inválida
}
void processClicks(int buttonIndex, int clickCount) {
ButtonAction action = getActionForButtonAndBank(buttonIndex, clickCount);
const char* clickTypes[] = {"Clique simples detectado!", "Duplo clique detectado!", "Triplo clique detectado!"};
if (debugMode) {
Serial.print("Botão ");
Serial.print(buttonIndex + 1);
Serial.print(": ");
Serial.print(clickTypes[clickCount - 1]);
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);
}
}
void loop() {
for (int i = 0; i < numButtons; i++) {
debouncers[i].update();
handleButton(i);
}
handleSimultaneousPress();
}
void sendControlChange(ButtonAction action) {
Serial.print("Type: ");
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.println(action.channel);
// } else {
// MIDI.sendControlChange(action.type, action.val, action.channel);
// }
}
}