Make ScreenHandler class, fix button handling
This commit is contained in:
parent
698c3a3a43
commit
17fef80253
11 changed files with 484 additions and 410 deletions
|
@ -1,8 +1,7 @@
|
|||
#include "button_handler.hpp"
|
||||
|
||||
TaskHandle_t buttonTaskHandle = NULL;
|
||||
const TickType_t debounceDelay = pdMS_TO_TICKS(50);
|
||||
TickType_t lastDebounceTime = 0;
|
||||
ButtonState buttonStates[4];
|
||||
|
||||
#ifdef IS_BTCLOCK_V8
|
||||
#define BTN_1 256
|
||||
|
@ -17,65 +16,134 @@ TickType_t lastDebounceTime = 0;
|
|||
#endif
|
||||
|
||||
void buttonTask(void *parameter) {
|
||||
while (1) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
while (1) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
TickType_t currentTime = xTaskGetTickCount();
|
||||
|
||||
std::lock_guard<std::mutex> lock(mcpMutex);
|
||||
|
||||
if (!digitalRead(MCP_INT_PIN)) {
|
||||
uint16_t intFlags = mcp1.getInterruptFlagRegister();
|
||||
uint16_t intCap = mcp1.getInterruptCaptureRegister();
|
||||
|
||||
// Check button states
|
||||
if (intFlags & BTN_1) handleButtonPress(0);
|
||||
if (intFlags & BTN_2) handleButtonPress(1);
|
||||
if (intFlags & BTN_3) handleButtonPress(2);
|
||||
if (intFlags & BTN_4) handleButtonPress(3);
|
||||
|
||||
// Check for button releases
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (buttonStates[i].isPressed) {
|
||||
bool currentlyPressed = false;
|
||||
switch (i) {
|
||||
case 0: currentlyPressed = (intCap & BTN_1); break;
|
||||
case 1: currentlyPressed = (intCap & BTN_2); break;
|
||||
case 2: currentlyPressed = (intCap & BTN_3); break;
|
||||
case 3: currentlyPressed = (intCap & BTN_4); break;
|
||||
}
|
||||
if (!currentlyPressed) {
|
||||
handleButtonRelease(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for long press on pressed buttons
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (buttonStates[i].isPressed && !buttonStates[i].longPressHandled) {
|
||||
if ((currentTime - buttonStates[i].pressStartTime) >= longPressDelay) {
|
||||
handleLongPress(i);
|
||||
buttonStates[i].longPressHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear interrupt state
|
||||
while (!digitalRead(MCP_INT_PIN)) {
|
||||
mcp1.getInterruptCaptureRegister();
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleButtonPress(int buttonIndex) {
|
||||
TickType_t currentTime = xTaskGetTickCount();
|
||||
ButtonState &state = buttonStates[buttonIndex];
|
||||
|
||||
if ((currentTime - lastDebounceTime) >= debounceDelay) {
|
||||
lastDebounceTime = currentTime;
|
||||
|
||||
std::lock_guard<std::mutex> lock(mcpMutex);
|
||||
|
||||
if (!digitalRead(MCP_INT_PIN)) {
|
||||
uint16_t intFlags = mcp1.getInterruptFlagRegister();
|
||||
uint16_t intCap = mcp1.getInterruptCaptureRegister();
|
||||
|
||||
// Check each button individually
|
||||
if (intFlags & BTN_1) handleButton1();
|
||||
if (intFlags & BTN_2) handleButton2();
|
||||
if (intFlags & BTN_3) handleButton3();
|
||||
if (intFlags & BTN_4) handleButton4();
|
||||
}
|
||||
if ((currentTime - state.lastPressTime) >= debounceDelay) {
|
||||
state.isPressed = true;
|
||||
state.pressStartTime = currentTime;
|
||||
state.longPressHandled = false;
|
||||
|
||||
// Check for double click
|
||||
if ((currentTime - state.lastPressTime) <= doubleClickDelay) {
|
||||
state.clickCount++;
|
||||
if (state.clickCount == 2) {
|
||||
handleDoubleClick(buttonIndex);
|
||||
state.clickCount = 0;
|
||||
}
|
||||
} else {
|
||||
state.clickCount = 1;
|
||||
}
|
||||
|
||||
state.lastPressTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
void handleButtonRelease(int buttonIndex) {
|
||||
TickType_t currentTime = xTaskGetTickCount();
|
||||
ButtonState &state = buttonStates[buttonIndex];
|
||||
|
||||
// Clear interrupt state
|
||||
while (!digitalRead(MCP_INT_PIN)) {
|
||||
std::lock_guard<std::mutex> lock(mcpMutex);
|
||||
mcp1.getInterruptCaptureRegister();
|
||||
delay(1); // Small delay to prevent tight loop
|
||||
state.isPressed = false;
|
||||
|
||||
// If this wasn't a long press or double click, handle as single click
|
||||
if (!state.longPressHandled && state.clickCount == 1 &&
|
||||
(currentTime - state.pressStartTime) < longPressDelay) {
|
||||
handleSingleClick(buttonIndex);
|
||||
state.clickCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions to handle each button
|
||||
void handleButton1() {
|
||||
toggleTimerActive();
|
||||
// Button action handlers
|
||||
void handleSingleClick(int buttonIndex) {
|
||||
switch (buttonIndex) {
|
||||
case 0:
|
||||
toggleTimerActive();
|
||||
break;
|
||||
case 1:
|
||||
Serial.println("Button 2 single click");
|
||||
ScreenHandler::nextScreen();
|
||||
break;
|
||||
case 2:
|
||||
Serial.println("Button 3 single click");
|
||||
ScreenHandler::previousScreen();
|
||||
break;
|
||||
case 3:
|
||||
ScreenHandler::showSystemStatusScreen();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handleButton2() {
|
||||
nextScreen();
|
||||
void handleDoubleClick(int buttonIndex) {
|
||||
Serial.printf("Button %d double clicked\n", buttonIndex + 1);
|
||||
}
|
||||
|
||||
void handleButton3() {
|
||||
previousScreen();
|
||||
}
|
||||
|
||||
void handleButton4() {
|
||||
showSystemStatusScreen();
|
||||
void handleLongPress(int buttonIndex) {
|
||||
Serial.printf("Button %d long press detected\n", buttonIndex + 1);
|
||||
}
|
||||
|
||||
void IRAM_ATTR handleButtonInterrupt() {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
|
||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
|
||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
void setupButtonTask() {
|
||||
xTaskCreate(buttonTask, "ButtonTask", 3072, NULL, tskIDLE_PRIORITY,
|
||||
&buttonTaskHandle); // Create the FreeRTOS task
|
||||
// Use interrupt instead of task
|
||||
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE);
|
||||
xTaskCreate(buttonTask, "ButtonTask", 3072, NULL, tskIDLE_PRIORITY,
|
||||
&buttonTaskHandle);
|
||||
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, FALLING);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue