#define KEYPAD_ROWS 5
#define KEYPAD_COLS 4
#define ENCODER_COUNT 5
#define DEBOUNCE_DELAY 50
const uint8_t keypadRowPins[KEYPAD_ROWS] = { 23, 22, 21, 19, 18 };
const uint8_t keypadColPins[KEYPAD_COLS] = { 5, 17, 16, 4 };
const uint8_t encoderClkPins[ENCODER_COUNT] = { 2, 12, 27, 25, 32 };
const uint8_t encoderDtPins[ENCODER_COUNT] = { 15, 13, 14, 26, 33 };
const uint8_t encoderDownPins[ENCODER_COUNT] = { 20, 22, 24, 26, 28 };
const uint8_t encoderUpPins[ENCODER_COUNT] = { 21, 23, 25, 27, 29 };
volatile int encoderClkStates[ENCODER_COUNT] = { HIGH, HIGH, HIGH, HIGH, HIGH };
volatile unsigned long encoderLastClkTimes[ENCODER_COUNT] = { 0, 0, 0, 0, 0 };
void setup() {
Serial.begin(115200);
// Initialize encoder pins
for (uint8_t i = 0; i < ENCODER_COUNT; i++) {
pinMode(encoderClkPins[i], INPUT_PULLUP);
pinMode(encoderDtPins[i], INPUT_PULLUP);
}
// Initialize keypad row pins
for (uint8_t row = 0; row < KEYPAD_ROWS; row++) {
pinMode(keypadRowPins[row], OUTPUT);
digitalWrite(keypadRowPins[row], HIGH);
}
// Initialize keypad column pins
for (uint8_t col = 0; col < KEYPAD_COLS; col++) {
pinMode(keypadColPins[col], INPUT_PULLUP);
}
Serial.println("Booted!");
}
void loop() {
handleRotaryEncoders();
handleKeypad();
}
void handleRotaryEncoders() {
for (uint8_t i = 0; i < ENCODER_COUNT; i++) {
int newClk = digitalRead(encoderClkPins[i]);
// Check for state change and debounce
if (newClk != encoderClkStates[i]) {
unsigned long now = millis();
if (now - encoderLastClkTimes[i] > DEBOUNCE_DELAY) {
encoderClkStates[i] = newClk;
encoderLastClkTimes[i] = now;
int dtValue = digitalRead(encoderDtPins[i]);
if (newClk == LOW && dtValue == HIGH) {
sendKey(encoderUpPins[i]);
}
if (newClk == LOW && dtValue == LOW) {
sendKey(encoderDownPins[i]);
}
}
}
}
}
void handleKeypad() {
for (uint8_t row = 0; row < KEYPAD_ROWS; row++) {
digitalWrite(keypadRowPins[row], LOW);
for (uint8_t col = 0; col < KEYPAD_COLS; col++) {
// Track button state for debouncing
static bool buttonStates[KEYPAD_ROWS][KEYPAD_COLS] = { false };
bool currentState = digitalRead(keypadColPins[col]) == LOW;
if (currentState != buttonStates[row][col]) { // State change detected
delay(DEBOUNCE_DELAY); // Wait for debounce delay
currentState = digitalRead(keypadColPins[col]) == LOW; // Read again after delay
if (currentState != buttonStates[row][col]) { // If still different, consider it a valid state change
buttonStates[row][col] = currentState;
uint8_t key = row * KEYPAD_COLS + col;
if (currentState) {
pressKey(key);
} else {
releaseKey(key);
}
}
}
}
digitalWrite(keypadRowPins[row], HIGH);
}
}
void sendKey(uint8_t key) {
uint32_t gamepadButton = pow(2, key);
Serial.print("pulse\t");
Serial.println(key);
}
void pressKey(uint8_t key) {
uint32_t gamepadButton = pow(2, key);
Serial.print("hold\t");
Serial.println(key);
}
void releaseKey(uint8_t key) {
uint32_t gamepadButton = pow(2, key);
Serial.print("release\t");
Serial.println(key);
}