2525#include " main.h"
2626#include " BootErrors.h"
2727
28-
2928#include < memory>
3029
3130using namespace Pinetime ::System;
@@ -77,7 +76,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
7776 Pinetime::Applications::DisplayApp& displayApp,
7877 Pinetime::Applications::HeartRateTask& heartRateApp,
7978 Pinetime::Controllers::FS& fs,
80- Pinetime::Controllers::TouchHandler& touchHandler)
79+ Pinetime::Controllers::TouchHandler& touchHandler,
80+ Pinetime::Controllers::ButtonHandler& buttonHandler)
8181 : spi {spi},
8282 lcd {lcd},
8383 spiNorFlash {spiNorFlash},
@@ -101,8 +101,15 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
101101 heartRateApp (heartRateApp),
102102 fs {fs},
103103 touchHandler {touchHandler},
104- nimbleController (*this , bleController, dateTimeController, notificationManager,
105- batteryController, spiNorFlash, heartRateController, motionController) {
104+ buttonHandler {buttonHandler},
105+ nimbleController (*this ,
106+ bleController,
107+ dateTimeController,
108+ notificationManager,
109+ batteryController,
110+ spiNorFlash,
111+ heartRateController,
112+ motionController) {
106113}
107114
108115void SystemTask::Start () {
@@ -163,6 +170,8 @@ void SystemTask::Work() {
163170 heartRateSensor.Disable ();
164171 heartRateApp.Start ();
165172
173+ buttonHandler.Init (this );
174+
166175 // Button
167176 nrf_gpio_cfg_output (15 );
168177 nrf_gpio_pin_set (15 );
@@ -326,10 +335,25 @@ void SystemTask::Work() {
326335 ReloadIdleTimer ();
327336 displayApp.PushMessage (Pinetime::Applications::Display::Messages::TouchEvent);
328337 break ;
329- case Messages::OnButtonEvent:
330- ReloadIdleTimer ();
331- displayApp.PushMessage (Pinetime::Applications::Display::Messages::ButtonPushed);
332- break ;
338+ case Messages::HandleButtonEvent: {
339+ Controllers::ButtonActions action;
340+ if (nrf_gpio_pin_read (Pinetime::PinMap::Button) == 0 ) {
341+ action = buttonHandler.HandleEvent (Controllers::ButtonHandler::Events::Release);
342+ } else {
343+ action = buttonHandler.HandleEvent (Controllers::ButtonHandler::Events::Press);
344+ // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping
345+ if (IsSleeping ()) {
346+ fastWakeUpDone = true ;
347+ GoToRunning ();
348+ break ;
349+ }
350+ }
351+ HandleButtonAction (action);
352+ } break ;
353+ case Messages::HandleButtonTimerEvent: {
354+ auto action = buttonHandler.HandleEvent (Controllers::ButtonHandler::Events::Timer);
355+ HandleButtonAction (action);
356+ } break ;
333357 case Messages::OnDisplayTaskSleeping:
334358 if (BootloaderVersion::IsValid ()) {
335359 // First versions of the bootloader do not expose their version and cannot initialize the SPI NOR FLASH
@@ -414,18 +438,36 @@ void SystemTask::UpdateMotion() {
414438 }
415439}
416440
417- void SystemTask::OnButtonPushed ( ) {
418- if (isGoingToSleep)
441+ void SystemTask::HandleButtonAction (Controllers::ButtonActions action ) {
442+ if (IsSleeping ()) {
419443 return ;
420- if (!isSleeping) {
421- NRF_LOG_INFO (" [systemtask] Button pushed" );
422- PushMessage (Messages::OnButtonEvent);
423- } else {
424- if (!isWakingUp) {
425- NRF_LOG_INFO (" [systemtask] Button pushed, waking up" );
426- GoToRunning ();
427- }
428444 }
445+
446+ ReloadIdleTimer ();
447+
448+ using Actions = Controllers::ButtonActions;
449+
450+ switch (action) {
451+ case Actions::Click:
452+ // If the first action after fast wakeup is a click, it should be ignored.
453+ if (!fastWakeUpDone && !isGoingToSleep) {
454+ displayApp.PushMessage (Applications::Display::Messages::ButtonPushed);
455+ }
456+ break ;
457+ case Actions::DoubleClick:
458+ displayApp.PushMessage (Applications::Display::Messages::ButtonDoubleClicked);
459+ break ;
460+ case Actions::LongPress:
461+ displayApp.PushMessage (Applications::Display::Messages::ButtonLongPressed);
462+ break ;
463+ case Actions::LongerPress:
464+ displayApp.PushMessage (Applications::Display::Messages::ButtonLongerPressed);
465+ break ;
466+ default :
467+ return ;
468+ }
469+
470+ fastWakeUpDone = false ;
429471}
430472
431473void SystemTask::GoToRunning () {
0 commit comments