#include <MIDI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// set up MIDI interface
MIDI_CREATE_DEFAULT_INSTANCE();
const int MIDI_CHANNEL = 1;
// set up foot switches
const int SWITCH_COUNT = 7;
const int SWITCH_PINS[] = { 2, 3, 4, 5, 6, 7, 8 };
int switchStates[SWITCH_COUNT];
int lastSwitchStates[SWITCH_COUNT];
// set up mapping between switches and MIDI program changes for multiple banks
const int BANK_COUNT = 4; // adjust as needed for the number of banks
const int PROGRAM_CHANGE[BANK_COUNT][SWITCH_COUNT] = { { 0, 1, 2, 3, 4, 5, 6 }, // bank 1
{ 8, 9, 10, 11, 12, 13, 14 }, // bank 2
{ 16, 17, 18, 19, 20, 21, 22 }, // bank 3
{ 24, 25, 26, 27, 28, 29, 30 } }; // bank 4
const char* PROGRAM_NAMES[BANK_COUNT][SWITCH_COUNT] = { { "TILL MAIN", "TILL CLEAN", "TILL LEAD", "PHASER",
"PHASER CLEAN", "TTP CHORUS", "PROFESSOREN FUZZ" }, // bank 1
{ "NIRU MAIN", "NIRU LEAD", "NERO INTRO", "NERO DELAY",
"SLAP", "KOPF REVERB", "PILZ REVERB" }, // bank 2
{ "DOOKIE", "SILVER JUBILEE", "JTM50 SCHAFFER", "CRATEVC50 800MOD",
"IBANEZ 800MOD", "AC30 MID", "AC30 DIRTY" }, // bank 3
{ "Program 25", "Program 26", "Program 27", "Program 28",
"Program 29", "Program 30", "Program 31" } }; // bank 4
const char* BANK_NAMES[BANK_COUNT] = { "x Final Impact x", ".NIRU 8=====D", "MARSHALL", "VARIOUS" }; //bank names
int currentBank = 0;
// set up bank select switches
const int BANK_UP_PIN = A2;
const int BANK_DOWN_PIN = A3;
// set up LEDs
const int LED_PINS[] = { 9, 10, 11, 12, 13, A0, A1};
int lastPressedSwitch = -1;
// set up LCD display
LiquidCrystal_I2C lcd(0x27, 16, 2); // adjust the address and size as needed
void setup() {
// initialize foot switches
for (int i = 0; i < SWITCH_COUNT; i++) {
pinMode(SWITCH_PINS[i], INPUT_PULLUP);
switchStates[i] = 0;
lastSwitchStates[i] = 0;
}
// initialize bank select switches
pinMode(BANK_UP_PIN, INPUT_PULLUP);
pinMode(BANK_DOWN_PIN, INPUT_PULLUP);
// initialize LEDs
for (int i = 0; i < SWITCH_COUNT; i++) {
pinMode(LED_PINS[i], OUTPUT);
digitalWrite(LED_PINS[i], LOW);
}
// initialize MIDI interface
MIDI.begin(MIDI_CHANNEL);
//int i = 0; // define i here
// initialize LCD display
lcd.init();
lcd.backlight();
lcd.clear();
lcd.print("TILLs Footswitch");
delay(5000);
lcd.clear();
delay(1000);
lcd.setCursor(0, 1);
lcd.print(BANK_NAMES[currentBank]);
lcd.print(" ");
}
// keeps track of which switch last sent a program change
int lastProgramChangeSwitch = -1;
// keeps track of in which bank lastProgramChangeSwitch is located
int lastProgramChangeBank = -1;
void loop() {
// read bank select switches
if (digitalRead(BANK_UP_PIN) == LOW && currentBank < BANK_COUNT - 1) {
delay(200); // debounce delay
while (digitalRead(BANK_UP_PIN) == LOW) {} // wait until switch is released
currentBank = (currentBank + 1) % BANK_COUNT;
updateLedsAndDisplayForCurrentBank();
} else if (digitalRead(BANK_DOWN_PIN) == LOW && currentBank >= 1) {
delay(200); // debounce delay
while (digitalRead(BANK_DOWN_PIN) == LOW) {} // wait until switch is released
currentBank = (currentBank - 1 + BANK_COUNT) % BANK_COUNT;
updateLedsAndDisplayForCurrentBank();
}
// read foot switches and send MIDI messages
for (int i = 0; i < SWITCH_COUNT; i++) {
switchStates[i] = digitalRead(SWITCH_PINS[i]);
if (switchStates[i] != lastSwitchStates[i]) {
if (switchStates[i] == LOW) {
// switch was just pressed
int programChange = PROGRAM_CHANGE[currentBank][i];
MIDI.sendProgramChange(programChange, MIDI_CHANNEL);
updateLedsAndDisplayForSwitch(i);
lastPressedSwitch = i;
lastProgramChangeSwitch = i;
lastProgramChangeBank = currentBank;
// print the program name to the display
lcd.setCursor(0, 0);
lcd.print(PROGRAM_NAMES[currentBank][i]);
lcd.print(" ");
}
lastSwitchStates[i] = switchStates[i];
}
}
}
void updateLedsAndDisplayForCurrentBank() {
// turn off all LEDs
for (int i = 0; i < SWITCH_COUNT; i++) {
digitalWrite(LED_PINS[i], LOW);
}
// update LCD display with bank name
//int i = 0; // define i here
lcd.setCursor(0, 1);
lcd.print(BANK_NAMES[currentBank]);
lcd.print(" ");
//lcd.print("Bank ");
//lcd.print(currentBank + 1);
// turn on LED for last program change switch if current bank is the same
if (lastProgramChangeSwitch >= 0 && lastProgramChangeBank == currentBank) {
int switchIndex = lastProgramChangeSwitch;
int programChange = PROGRAM_CHANGE[currentBank][switchIndex];
// check if switch is in the same position in the bank's array
if (programChange >= 0 && switchIndex < SWITCH_COUNT && programChange == PROGRAM_CHANGE[currentBank][switchIndex]) {
digitalWrite(LED_PINS[switchIndex], HIGH);
}
}
}
void updateLedsAndDisplayForSwitch(int switchIndex) {
// turn off all LEDs
for (int i = 0; i < SWITCH_COUNT; i++) {
digitalWrite(LED_PINS[i], LOW);
}
// update LED for the pressed switch
int programChange = PROGRAM_CHANGE[switchIndex];
if (programChange >= 0) {
digitalWrite(LED_PINS[switchIndex], HIGH);
}
// allow time for other MIDI messages to be sent/received
MIDI.sendActiveSensing();
delay(5);
}