2021-10-25 09:53:14 +00:00
|
|
|
#include "ButtonHandler.h"
|
|
|
|
|
|
|
|
using namespace Pinetime::Controllers;
|
|
|
|
|
|
|
|
void ButtonTimerCallback(TimerHandle_t xTimer) {
|
2021-10-25 13:57:29 +00:00
|
|
|
auto* sysTask = static_cast<Pinetime::System::SystemTask*>(pvTimerGetTimerID(xTimer));
|
|
|
|
sysTask->PushMessage(Pinetime::System::Messages::HandleButtonTimerEvent);
|
2021-10-25 09:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) {
|
2021-12-04 01:10:34 +00:00
|
|
|
buttonTimer = xTimerCreate("buttonTimer", pdMS_TO_TICKS(200), pdFALSE, systemTask, ButtonTimerCallback);
|
2021-10-25 09:53:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-25 13:57:29 +00:00
|
|
|
ButtonActions ButtonHandler::HandleEvent(Events event) {
|
2021-10-25 09:53:14 +00:00
|
|
|
static constexpr TickType_t doubleClickTime = pdMS_TO_TICKS(200);
|
|
|
|
static constexpr TickType_t longPressTime = pdMS_TO_TICKS(400);
|
|
|
|
static constexpr TickType_t longerPressTime = pdMS_TO_TICKS(2000);
|
|
|
|
|
2021-10-25 10:40:43 +00:00
|
|
|
if (event == Events::Press) {
|
2021-10-25 09:53:14 +00:00
|
|
|
buttonPressed = true;
|
2021-10-25 10:40:43 +00:00
|
|
|
} else if (event == Events::Release) {
|
2021-10-25 09:53:14 +00:00
|
|
|
releaseTime = xTaskGetTickCount();
|
|
|
|
buttonPressed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (state) {
|
2021-10-25 10:40:43 +00:00
|
|
|
case States::Idle:
|
|
|
|
if (event == Events::Press) {
|
2021-10-25 09:53:14 +00:00
|
|
|
xTimerChangePeriod(buttonTimer, doubleClickTime, 0);
|
|
|
|
xTimerStart(buttonTimer, 0);
|
2021-10-25 10:40:43 +00:00
|
|
|
state = States::Pressed;
|
2021-10-25 09:53:14 +00:00
|
|
|
}
|
|
|
|
break;
|
2021-10-25 10:40:43 +00:00
|
|
|
case States::Pressed:
|
|
|
|
if (event == Events::Press) {
|
2021-10-25 09:53:14 +00:00
|
|
|
if (xTaskGetTickCount() - releaseTime < doubleClickTime) {
|
|
|
|
xTimerStop(buttonTimer, 0);
|
2021-10-25 10:40:43 +00:00
|
|
|
state = States::Idle;
|
2021-10-25 13:57:29 +00:00
|
|
|
return ButtonActions::DoubleClick;
|
2021-10-25 09:53:14 +00:00
|
|
|
}
|
2021-10-25 10:40:43 +00:00
|
|
|
} else if (event == Events::Release) {
|
2021-10-25 09:53:14 +00:00
|
|
|
xTimerChangePeriod(buttonTimer, doubleClickTime, 0);
|
|
|
|
xTimerStart(buttonTimer, 0);
|
2021-10-25 10:40:43 +00:00
|
|
|
} else if (event == Events::Timer) {
|
2021-10-25 09:53:14 +00:00
|
|
|
if (buttonPressed) {
|
|
|
|
xTimerChangePeriod(buttonTimer, longPressTime - doubleClickTime, 0);
|
|
|
|
xTimerStart(buttonTimer, 0);
|
2021-10-25 10:40:43 +00:00
|
|
|
state = States::Holding;
|
2021-10-25 09:53:14 +00:00
|
|
|
} else {
|
2021-10-25 10:40:43 +00:00
|
|
|
state = States::Idle;
|
2021-10-25 13:57:29 +00:00
|
|
|
return ButtonActions::Click;
|
2021-10-25 09:53:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2021-10-25 10:40:43 +00:00
|
|
|
case States::Holding:
|
|
|
|
if (event == Events::Release) {
|
2021-10-25 09:53:14 +00:00
|
|
|
xTimerStop(buttonTimer, 0);
|
2021-10-25 10:40:43 +00:00
|
|
|
state = States::Idle;
|
2021-10-25 13:57:29 +00:00
|
|
|
return ButtonActions::Click;
|
2021-10-25 10:40:43 +00:00
|
|
|
} else if (event == Events::Timer) {
|
2021-10-25 09:53:14 +00:00
|
|
|
xTimerChangePeriod(buttonTimer, longerPressTime - longPressTime - doubleClickTime, 0);
|
|
|
|
xTimerStart(buttonTimer, 0);
|
2021-10-25 10:40:43 +00:00
|
|
|
state = States::LongHeld;
|
2021-10-25 13:57:29 +00:00
|
|
|
return ButtonActions::LongPress;
|
2021-10-25 09:53:14 +00:00
|
|
|
}
|
|
|
|
break;
|
2021-10-25 10:40:43 +00:00
|
|
|
case States::LongHeld:
|
|
|
|
if (event == Events::Release) {
|
2021-10-25 09:53:14 +00:00
|
|
|
xTimerStop(buttonTimer, 0);
|
2021-10-25 10:40:43 +00:00
|
|
|
state = States::Idle;
|
|
|
|
} else if (event == Events::Timer) {
|
|
|
|
state = States::Idle;
|
2021-10-25 13:57:29 +00:00
|
|
|
return ButtonActions::LongerPress;
|
2021-10-25 09:53:14 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-10-25 13:57:29 +00:00
|
|
|
return ButtonActions::None;
|
2021-10-25 09:53:14 +00:00
|
|
|
}
|