I didn't paste the whole sketch because it's long and not much of it is relevant to the dip switches but sure here's the full code. Rest of the project works perfectly it's just literally these dip switches that are giving me jip and the way I see it they should be fairly straight forward.
#include "Toggle.h"
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
const byte LEDs[] = {15, 14, 16, 10, 9, 8, 7, 6}; // Pins for LEDs
const byte dipSwitchPins[] = {4, 5}; // Pins for dip switches
static int progNo = 0;
static byte channelNo = 1; // Default MIDI channel
const byte b1Pin = 2;
const byte b2Pin = 3;
Toggle b1, b2;
const uint16_t deltaT = 850; // ms after that duration, a pressed button is considered in long press state
enum SystemState : byte {
B1R_B2R, B1P_B2R, B1L_B2R,
B1R_B2P, B1P_B2P, B1L_B2P,
B1R_B2L, B1P_B2L, B1L_B2L
} state = B1R_B2R;
const char* stateDescriptor[] = {
"B1R_B2R", "B1P_B2R", "B1L_B2R",
"B1R_B2P", "B1P_B2P", "B1L_B2P",
"B1R_B2L", "B1P_B2L", "B1L_B2L"
};
void manageState() {
static SystemState previousState = B1R_B2R;
switch (state) {
case B1R_B2R:
b1.poll();
if (b1.onPress()) {
b1.clearTimer();
state = B1P_B2R;
} else {
b2.poll();
if (b2.onPress()) {
b2.clearTimer();
state = B1R_B2P;
}
}
break;
case B1R_B2P:
b1.poll();
if (b1.onPress()) {
b1.clearTimer();
state = B1P_B2P;
} else {
b2.poll();
if (b2.onRelease()) {
state = B1R_B2R;
progNo--; // Decrement program change
if (progNo < 0) progNo = 7; // Wrap around to 7
MIDI.sendProgramChange(byte(progNo), channelNo);
} else {
if (b2.pressedFor(deltaT)) {
state = B1R_B2L;
MIDI.sendControlChange(19, 2, channelNo);
}
}
}
break;
case B1R_B2L:
b1.poll();
if (b1.onPress()) {
b1.clearTimer();
state = B1P_B2L;
} else {
b2.poll();
if (b2.onRelease()) {
state = B1R_B2R;
MIDI.sendControlChange(19, 3, channelNo);
}
}
break;
case B1P_B2R:
b1.poll();
if (b1.onRelease()) {
state = B1R_B2R;
progNo++; // Increment program change
if (progNo > 7) progNo = 0; // Wrap around to 0
MIDI.sendProgramChange(byte(progNo), channelNo);
} else {
b2.poll();
if (b2.onPress()) {
b2.clearTimer();
state = B1P_B2P;
}
else if (b1.pressedFor(deltaT)) {
state = B1L_B2R;
MIDI.sendControlChange(19, 1, channelNo);
}
}
break;
case B1P_B2P:
{
unsigned long releaseTime = millis(); // Record the time when the first button is released
b1.poll();
if (b1.onRelease()) {
state = B1R_B2R;
MIDI.sendControlChange(41, 127, channelNo);
MIDI.sendControlChange(49, 127, channelNo);
} else {
b2.poll();
if (b2.onRelease()) {
// Check if the second button is released within a short time after the first one
if ((millis() - releaseTime) < 700) {
state = B1R_B2P; // Buttons released within the time window
MIDI.sendControlChange(41, 127, channelNo);
MIDI.sendControlChange(49, 0, channelNo);
} else {
if ((millis() - releaseTime) < 700) {
state = B1P_B2R; // Second button released, treat as separate releases
MIDI.sendControlChange(41, 127, channelNo);
MIDI.sendControlChange(49, 0, channelNo);
}
}
}else if (b1.pressedFor(deltaT)) {
state = B1L_B2P;
MIDI.sendControlChange(46, 127, channelNo);
}
else if (b2.pressedFor(deltaT)) {
state = B1P_B2L;
MIDI.sendControlChange(46, 127, channelNo);
}
}
}
break;
case B1P_B2L:
b1.poll();
if (b1.onRelease()) {
state = B1R_B2L;
} else {
b2.poll();
if (b2.onRelease()) {
state = B1P_B2R;
}
else if (b1.pressedFor(deltaT)) {
state = B1L_B2L;
}
}
break;
case B1L_B2R:
b1.poll();
if (b1.onRelease()) {
state = B1R_B2R;
MIDI.sendControlChange(19, 3, channelNo);
} else {
b2.poll();
if (b2.onPress()) {
b2.clearTimer();
state = B1L_B2P;
}
}
break;
case B1L_B2P:
b1.poll();
if (b1.onRelease()) {
state = B1R_B2P;
} else {
b2.poll();
if (b2.onRelease()) {
state = B1L_B2R;
}
else if (b2.pressedFor(deltaT)) {
state = B1L_B2L;
}
}
break;
case B1L_B2L:
b1.poll();
if (b1.onRelease()) {
state = B1R_B2R;
MIDI.sendControlChange(46, 0, channelNo);
} else {
b2.poll();
if (b2.onRelease()) {
state = B1R_B2R;
MIDI.sendControlChange(46, 0, channelNo);
}
}
break;
}
// Update LEDs and print program and channel number
for (byte i = 0; i < 8; i++) digitalWrite(LEDs[i], progNo != i ? LOW : HIGH);
// Read dip switches to set MIDI channel
byte dipSwitchState = digitalRead(dipSwitchPins[0]) | (digitalRead(dipSwitchPins[1]) << 1);
channelNo = map(dipSwitchState, 0, 3, 1, 2);
}
void setup() {
MIDI.begin(MIDI_CHANNEL_OMNI);
b1.begin(b1Pin);
b2.begin(b2Pin);
pinMode(dipSwitchPins[0], INPUT_PULLUP); // Dip switch 1
pinMode(dipSwitchPins[1], INPUT_PULLUP); // Dip switch 2
for (byte i = 0; i < 8; i++) pinMode(LEDs[i], OUTPUT);
}
void loop() {
manageState();
}