Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ list(APPEND SOURCE_FILES
components/heartrate/Ptagc.cpp
components/heartrate/HeartRateController.cpp

buttonhandler/ButtonHandler.cpp
touchhandler/TouchHandler.cpp
)

Expand Down Expand Up @@ -567,6 +568,7 @@ list(APPEND RECOVERY_SOURCE_FILES
components/heartrate/Ptagc.cpp
components/motor/MotorController.cpp
components/fs/FS.cpp
buttonhandler/ButtonHandler.cpp
touchhandler/TouchHandler.cpp
)

Expand Down Expand Up @@ -681,6 +683,7 @@ set(INCLUDE_FILES
components/heartrate/Ptagc.h
components/heartrate/HeartRateController.h
components/motor/MotorController.h
buttonhandler/ButtonHandler.h
touchhandler/TouchHandler.h
)

Expand Down
7 changes: 7 additions & 0 deletions src/buttonhandler/ButtonActions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

namespace Pinetime {
namespace Controllers {
enum class ButtonActions { None, Click, DoubleClick, LongPress, LongerPress };
}
}
78 changes: 78 additions & 0 deletions src/buttonhandler/ButtonHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "ButtonHandler.h"

using namespace Pinetime::Controllers;

void ButtonTimerCallback(TimerHandle_t xTimer) {
auto* sysTask = static_cast<Pinetime::System::SystemTask*>(pvTimerGetTimerID(xTimer));
sysTask->PushMessage(Pinetime::System::Messages::HandleButtonTimerEvent);
}

void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) {
buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, systemTask, ButtonTimerCallback);
}

ButtonActions ButtonHandler::HandleEvent(Events event) {
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);

if (event == Events::Press) {
buttonPressed = true;
} else if (event == Events::Release) {
releaseTime = xTaskGetTickCount();
buttonPressed = false;
}

switch (state) {
case States::Idle:
if (event == Events::Press) {
xTimerChangePeriod(buttonTimer, doubleClickTime, 0);
xTimerStart(buttonTimer, 0);
state = States::Pressed;
}
break;
case States::Pressed:
if (event == Events::Press) {
if (xTaskGetTickCount() - releaseTime < doubleClickTime) {
xTimerStop(buttonTimer, 0);
state = States::Idle;
return ButtonActions::DoubleClick;
}
} else if (event == Events::Release) {
xTimerChangePeriod(buttonTimer, doubleClickTime, 0);
xTimerStart(buttonTimer, 0);
} else if (event == Events::Timer) {
if (buttonPressed) {
xTimerChangePeriod(buttonTimer, longPressTime - doubleClickTime, 0);
xTimerStart(buttonTimer, 0);
state = States::Holding;
} else {
state = States::Idle;
return ButtonActions::Click;
}
}
break;
case States::Holding:
if (event == Events::Release) {
xTimerStop(buttonTimer, 0);
state = States::Idle;
return ButtonActions::Click;
} else if (event == Events::Timer) {
xTimerChangePeriod(buttonTimer, longerPressTime - longPressTime - doubleClickTime, 0);
xTimerStart(buttonTimer, 0);
state = States::LongHeld;
return ButtonActions::LongPress;
}
break;
case States::LongHeld:
if (event == Events::Release) {
xTimerStop(buttonTimer, 0);
state = States::Idle;
} else if (event == Events::Timer) {
state = States::Idle;
return ButtonActions::LongerPress;
}
break;
}
return ButtonActions::None;
}
24 changes: 24 additions & 0 deletions src/buttonhandler/ButtonHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include "ButtonActions.h"
#include "systemtask/SystemTask.h"
#include <FreeRTOS.h>
#include <timers.h>

namespace Pinetime {
namespace Controllers {
class ButtonHandler {
public:
enum class Events : uint8_t { Press, Release, Timer };
void Init(Pinetime::System::SystemTask* systemTask);
ButtonActions HandleEvent(Events event);

private:
enum class States : uint8_t { Idle, Pressed, Holding, LongHeld };
TickType_t releaseTime = 0;
TimerHandle_t buttonTimer;
bool buttonPressed = false;
States state = States::Idle;
};
}
}
14 changes: 14 additions & 0 deletions src/displayapp/DisplayApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,20 @@ void DisplayApp::Refresh() {
}
}
break;
case Messages::ButtonLongPressed:
if (currentApp != Apps::Clock) {
LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::Down);
}
break;
case Messages::ButtonLongerPressed:
// Create reboot app and open it instead
LoadApp(Apps::SysInfo, DisplayApp::FullRefreshDirections::Up);
break;
case Messages::ButtonDoubleClicked:
if (currentApp != Apps::Notifications && currentApp != Apps::NotificationsPreview) {
LoadApp(Apps::Notifications, DisplayApp::FullRefreshDirections::Down);
}
break;

case Messages::BleFirmwareUpdateStarted:
LoadApp(Apps::FirmwareUpdate, DisplayApp::FullRefreshDirections::Down);
Expand Down
3 changes: 3 additions & 0 deletions src/displayapp/Messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ namespace Pinetime {
UpdateBleConnection,
TouchEvent,
ButtonPushed,
ButtonLongPressed,
ButtonLongerPressed,
ButtonDoubleClicked,
NewNotification,
TimerDone,
BleFirmwareUpdateStarted,
Expand Down
23 changes: 11 additions & 12 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "systemtask/SystemTask.h"
#include "drivers/PinMap.h"
#include "touchhandler/TouchHandler.h"
#include "buttonhandler/ButtonHandler.h"

#if NRF_LOG_ENABLED
#include "logging/NrfLogger.h"
Expand Down Expand Up @@ -96,8 +97,6 @@ TimerHandle_t debounceTimer;
TimerHandle_t debounceChargeTimer;
Pinetime::Controllers::Battery batteryController;
Pinetime::Controllers::Ble bleController;
static constexpr uint8_t pinTouchIrq = Pinetime::PinMap::Cst816sIrq;
static constexpr uint8_t pinPowerPresentIrq = Pinetime::PinMap::PowerPresent;

Pinetime::Controllers::HeartRateController heartRateController;
Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController);
Expand All @@ -110,6 +109,7 @@ Pinetime::Controllers::MotionController motionController;
Pinetime::Controllers::TimerController timerController;
Pinetime::Controllers::AlarmController alarmController {dateTimeController};
Pinetime::Controllers::TouchHandler touchHandler(touchPanel, lvgl);
Pinetime::Controllers::ButtonHandler buttonHandler;

Pinetime::Controllers::FS fs {spiNorFlash};
Pinetime::Controllers::Settings settingsController {fs};
Expand Down Expand Up @@ -153,7 +153,8 @@ Pinetime::System::SystemTask systemTask(spi,
displayApp,
heartRateApp,
fs,
touchHandler);
touchHandler,
buttonHandler);

/* Variable Declarations for variables in noinit SRAM
Increment NoInit_MagicValue upon adding variables to this area
Expand All @@ -176,21 +177,19 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action
if (pin == Pinetime::PinMap::PowerPresent and action == NRF_GPIOTE_POLARITY_TOGGLE) {
xTimerStartFromISR(debounceChargeTimer, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
return;
} else if (pin == Pinetime::PinMap::Button) {
xTimerStartFromISR(debounceTimer, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

xTimerStartFromISR(debounceTimer, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void DebounceTimerChargeCallback(TimerHandle_t xTimer) {
xTimerStop(xTimer, 0);
systemTask.PushMessage(Pinetime::System::Messages::OnChargingEvent);
}

void DebounceTimerCallback(TimerHandle_t xTimer) {
xTimerStop(xTimer, 0);
systemTask.OnButtonPushed();
void DebounceTimerCallback(TimerHandle_t /*unused*/) {
systemTask.PushMessage(Pinetime::System::Messages::HandleButtonEvent);
}

void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) {
Expand Down Expand Up @@ -319,8 +318,8 @@ int main(void) {
}
nrf_gpio_cfg_default(Pinetime::PinMap::TwiScl);

debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback);
debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback);
debounceTimer = xTimerCreate("debounceTimer", 10, pdFALSE, nullptr, DebounceTimerCallback);
debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, nullptr, DebounceTimerChargeCallback);

// retrieve version stored by bootloader
Pinetime::BootloaderVersion::SetVersion(NRF_TIMER2->CC[0]);
Expand Down
3 changes: 2 additions & 1 deletion src/systemtask/Messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ namespace Pinetime {
BleFirmwareUpdateStarted,
BleFirmwareUpdateFinished,
OnTouchEvent,
OnButtonEvent,
HandleButtonEvent,
HandleButtonTimerEvent,
OnDisplayTaskSleeping,
EnableSleeping,
DisableSleeping,
Expand Down
78 changes: 60 additions & 18 deletions src/systemtask/SystemTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "main.h"
#include "BootErrors.h"


#include <memory>

using namespace Pinetime::System;
Expand Down Expand Up @@ -77,7 +76,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
Pinetime::Applications::DisplayApp& displayApp,
Pinetime::Applications::HeartRateTask& heartRateApp,
Pinetime::Controllers::FS& fs,
Pinetime::Controllers::TouchHandler& touchHandler)
Pinetime::Controllers::TouchHandler& touchHandler,
Pinetime::Controllers::ButtonHandler& buttonHandler)
: spi {spi},
lcd {lcd},
spiNorFlash {spiNorFlash},
Expand All @@ -101,8 +101,15 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
heartRateApp(heartRateApp),
fs {fs},
touchHandler {touchHandler},
nimbleController(*this, bleController, dateTimeController, notificationManager,
batteryController, spiNorFlash, heartRateController, motionController) {
buttonHandler {buttonHandler},
nimbleController(*this,
bleController,
dateTimeController,
notificationManager,
batteryController,
spiNorFlash,
heartRateController,
motionController) {
}

void SystemTask::Start() {
Expand Down Expand Up @@ -163,6 +170,8 @@ void SystemTask::Work() {
heartRateSensor.Disable();
heartRateApp.Start();

buttonHandler.Init(this);

// Button
nrf_gpio_cfg_output(15);
nrf_gpio_pin_set(15);
Expand Down Expand Up @@ -326,10 +335,25 @@ void SystemTask::Work() {
ReloadIdleTimer();
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
break;
case Messages::OnButtonEvent:
ReloadIdleTimer();
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed);
break;
case Messages::HandleButtonEvent: {
Controllers::ButtonActions action;
if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) {
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release);
} else {
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press);
// This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping
if (IsSleeping()) {
fastWakeUpDone = true;
GoToRunning();
break;
}
}
HandleButtonAction(action);
} break;
case Messages::HandleButtonTimerEvent: {
auto action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Timer);
HandleButtonAction(action);
} break;
case Messages::OnDisplayTaskSleeping:
if (BootloaderVersion::IsValid()) {
// First versions of the bootloader do not expose their version and cannot initialize the SPI NOR FLASH
Expand Down Expand Up @@ -414,18 +438,36 @@ void SystemTask::UpdateMotion() {
}
}

void SystemTask::OnButtonPushed() {
if (isGoingToSleep)
void SystemTask::HandleButtonAction(Controllers::ButtonActions action) {
if (IsSleeping()) {
return;
if (!isSleeping) {
NRF_LOG_INFO("[systemtask] Button pushed");
PushMessage(Messages::OnButtonEvent);
} else {
if (!isWakingUp) {
NRF_LOG_INFO("[systemtask] Button pushed, waking up");
GoToRunning();
}
}

ReloadIdleTimer();

using Actions = Controllers::ButtonActions;

switch (action) {
case Actions::Click:
// If the first action after fast wakeup is a click, it should be ignored.
if (!fastWakeUpDone && !isGoingToSleep) {
displayApp.PushMessage(Applications::Display::Messages::ButtonPushed);
}
break;
case Actions::DoubleClick:
displayApp.PushMessage(Applications::Display::Messages::ButtonDoubleClicked);
break;
case Actions::LongPress:
displayApp.PushMessage(Applications::Display::Messages::ButtonLongPressed);
break;
case Actions::LongerPress:
displayApp.PushMessage(Applications::Display::Messages::ButtonLongerPressed);
break;
default:
return;
}

fastWakeUpDone = false;
}

void SystemTask::GoToRunning() {
Expand Down
Loading