Fix button handling

This commit is contained in:
Djuri Baars 2024-12-21 17:36:07 +01:00
parent 8a818c66a0
commit 4fdd6b6b4f
3 changed files with 66 additions and 45 deletions

View file

@ -19,41 +19,52 @@ TickType_t lastDebounceTime = 0;
void buttonTask(void *parameter) { void buttonTask(void *parameter) {
while (1) { while (1) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
std::lock_guard<std::mutex> lock(mcpMutex);
TickType_t currentTime = xTaskGetTickCount(); TickType_t currentTime = xTaskGetTickCount();
if ((currentTime - lastDebounceTime) >= debounceDelay) { if ((currentTime - lastDebounceTime) >= debounceDelay) {
lastDebounceTime = currentTime; lastDebounceTime = currentTime;
if (!digitalRead(MCP_INT_PIN)) { std::lock_guard<std::mutex> lock(mcpMutex);
uint pin = mcp1.getInterruptFlagRegister();
switch (pin) { if (!digitalRead(MCP_INT_PIN)) {
case BTN_1: uint16_t intFlags = mcp1.getInterruptFlagRegister();
toggleTimerActive(); uint16_t intCap = mcp1.getInterruptCaptureRegister();
break;
case BTN_2: // Check each button individually
nextScreen(); if (intFlags & BTN_1) handleButton1();
break; if (intFlags & BTN_2) handleButton2();
case BTN_3: if (intFlags & BTN_3) handleButton3();
previousScreen(); if (intFlags & BTN_4) handleButton4();
break;
case BTN_4:
showSystemStatusScreen();
break;
}
} }
mcp1.getInterruptCaptureRegister();
} else {
} }
// Very ugly, but for some reason this is necessary
// Clear interrupt state
while (!digitalRead(MCP_INT_PIN)) { while (!digitalRead(MCP_INT_PIN)) {
std::lock_guard<std::mutex> lock(mcpMutex);
mcp1.getInterruptCaptureRegister(); mcp1.getInterruptCaptureRegister();
delay(1); // Small delay to prevent tight loop
} }
} }
} }
// Helper functions to handle each button
void handleButton1() {
toggleTimerActive();
}
void handleButton2() {
nextScreen();
}
void handleButton3() {
previousScreen();
}
void handleButton4() {
showSystemStatusScreen();
}
void IRAM_ATTR handleButtonInterrupt() { void IRAM_ATTR handleButtonInterrupt() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken); xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
@ -67,4 +78,5 @@ void setupButtonTask() {
&buttonTaskHandle); // Create the FreeRTOS task &buttonTaskHandle); // Create the FreeRTOS task
// Use interrupt instead of task // Use interrupt instead of task
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE); attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE);
Serial.printf("Button task created\n");
} }

View file

@ -8,6 +8,13 @@
extern TaskHandle_t buttonTaskHandle; extern TaskHandle_t buttonTaskHandle;
// Task and setup functions
void buttonTask(void *pvParameters); void buttonTask(void *pvParameters);
void IRAM_ATTR handleButtonInterrupt(); void IRAM_ATTR handleButtonInterrupt();
void setupButtonTask(); void setupButtonTask();
// Individual button handlers
void handleButton1();
void handleButton2();
void handleButton3();
void handleButton4();

View file

@ -466,32 +466,34 @@ void setupHardware()
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000); Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
if (!mcp1.begin()) if (!mcp1.begin()) {
{
Serial.println(F("Error MCP23017 1")); Serial.println(F("Error MCP23017 1"));
} else {
// while (1)
// ;
}
else
{
pinMode(MCP_INT_PIN, INPUT_PULLUP); pinMode(MCP_INT_PIN, INPUT_PULLUP);
// mcp1.setupInterrupts(false, false, LOW);
mcp1.enableControlRegister(MCP23x17_IOCR_ODR);
mcp1.mirrorInterrupts(true); // Enable mirrored interrupts (both INTA and INTB pins signal any interrupt)
if (!mcp1.mirrorInterrupts(true)) {
Serial.println(F("Error setting up mirrored interrupts"));
}
for (int i = 0; i < 4; i++) // Configure all 4 button pins as inputs with pullups and interrupts
{ for (int i = 0; i < 4; i++) {
mcp1.pinMode1(i, INPUT_PULLUP); if (!mcp1.pinMode1(i, INPUT_PULLUP)) {
mcp1.enableInterrupt(i, LOW); Serial.printf("Error setting pin %d to input pull up\n", i);
}
// Enable interrupt on CHANGE for each pin
if (!mcp1.enableInterrupt(i, CHANGE)) {
Serial.printf("Error enabling interrupt for pin %d\n", i);
}
} }
#ifndef IS_BTCLOCK_V8
for (int i = 8; i <= 14; i++) // Set interrupt pins as open drain with active-low polarity
{ if (!mcp1.setInterruptPolarity(2)) { // 2 = Open drain
mcp1.pinMode1(i, OUTPUT); Serial.println(F("Error setting interrupt polarity"));
} }
#endif
// Clear any pending interrupts
mcp1.getInterruptCaptureRegister();
} }
#ifdef IS_HW_REV_B #ifdef IS_HW_REV_B