Skip to content

Commit d5dfa80

Browse files
committed
Newer buttonhandler
1 parent 82ca526 commit d5dfa80

9 files changed

Lines changed: 194 additions & 36 deletions

File tree

src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ list(APPEND SOURCE_FILES
507507
components/heartrate/Ptagc.cpp
508508
components/heartrate/HeartRateController.cpp
509509

510+
buttonhandler/ButtonHandler.cpp
510511
touchhandler/TouchHandler.cpp
511512
)
512513

@@ -567,6 +568,7 @@ list(APPEND RECOVERY_SOURCE_FILES
567568
components/heartrate/Ptagc.cpp
568569
components/motor/MotorController.cpp
569570
components/fs/FS.cpp
571+
buttonhandler/ButtonHandler.cpp
570572
touchhandler/TouchHandler.cpp
571573
)
572574

@@ -681,6 +683,7 @@ set(INCLUDE_FILES
681683
components/heartrate/Ptagc.h
682684
components/heartrate/HeartRateController.h
683685
components/motor/MotorController.h
686+
buttonhandler/ButtonHandler.h
684687
touchhandler/TouchHandler.h
685688
)
686689

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include "ButtonHandler.h"
2+
3+
using namespace Pinetime::Controllers;
4+
5+
void ButtonTimerCallback(TimerHandle_t xTimer) {
6+
auto* buttonHandler = static_cast<ButtonHandler*>(pvTimerGetTimerID(xTimer));
7+
buttonHandler->HandleEvent(ButtonHandler::Timer);
8+
}
9+
10+
void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) {
11+
this->systemTask = systemTask;
12+
buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, this, ButtonTimerCallback);
13+
}
14+
15+
void ButtonHandler::HandleEvent(events event) {
16+
static constexpr TickType_t doubleClickTime = pdMS_TO_TICKS(200);
17+
static constexpr TickType_t longPressTime = pdMS_TO_TICKS(400);
18+
static constexpr TickType_t longerPressTime = pdMS_TO_TICKS(2000);
19+
20+
if (systemTask->IsSleeping()) {
21+
// This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping
22+
systemTask->PushMessage(System::Messages::GoToRunning);
23+
} else {
24+
systemTask->PushMessage(System::Messages::ReloadIdleTimer);
25+
}
26+
27+
if (event == Press) {
28+
buttonPressed = true;
29+
} else if (event == Release) {
30+
releaseTime = xTaskGetTickCount();
31+
buttonPressed = false;
32+
}
33+
34+
switch (state) {
35+
case Idle:
36+
if (event == Press) {
37+
xTimerChangePeriod(buttonTimer, doubleClickTime, 0);
38+
xTimerStart(buttonTimer, 0);
39+
state = Pressed;
40+
}
41+
break;
42+
case Pressed:
43+
if (event == Press) {
44+
if (xTaskGetTickCount() - releaseTime < doubleClickTime) {
45+
systemTask->PushMessage(System::Messages::OnButtonDoubleClicked);
46+
xTimerStop(buttonTimer, 0);
47+
state = Idle;
48+
}
49+
} else if (event == Release) {
50+
xTimerChangePeriod(buttonTimer, doubleClickTime, 0);
51+
xTimerStart(buttonTimer, 0);
52+
} else if (event == Timer) {
53+
if (buttonPressed) {
54+
xTimerChangePeriod(buttonTimer, longPressTime - doubleClickTime, 0);
55+
xTimerStart(buttonTimer, 0);
56+
state = Holding;
57+
} else {
58+
systemTask->PushMessage(System::Messages::OnButtonPushed);
59+
state = Idle;
60+
}
61+
}
62+
break;
63+
case Holding:
64+
if (event == Release) {
65+
systemTask->PushMessage(System::Messages::OnButtonPushed);
66+
xTimerStop(buttonTimer, 0);
67+
state = Idle;
68+
} else if (event == Timer) {
69+
xTimerChangePeriod(buttonTimer, longerPressTime - longPressTime - doubleClickTime, 0);
70+
xTimerStart(buttonTimer, 0);
71+
systemTask->PushMessage(System::Messages::OnButtonLongPressed);
72+
state = LongHeld;
73+
}
74+
break;
75+
case LongHeld:
76+
if (event == Release) {
77+
xTimerStop(buttonTimer, 0);
78+
state = Idle;
79+
} else if (event == Timer) {
80+
systemTask->PushMessage(System::Messages::OnButtonLongerPressed);
81+
state = Idle;
82+
}
83+
break;
84+
}
85+
}

src/buttonhandler/ButtonHandler.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include "systemtask/SystemTask.h"
4+
#include <FreeRTOS.h>
5+
#include <timers.h>
6+
7+
namespace Pinetime {
8+
namespace Controllers {
9+
class ButtonHandler {
10+
public:
11+
enum events { Press, Release, Timer };
12+
void Init(Pinetime::System::SystemTask* systemTask);
13+
void HandleEvent(events event);
14+
15+
private:
16+
Pinetime::System::SystemTask* systemTask = nullptr;
17+
TickType_t releaseTime = 0;
18+
TimerHandle_t buttonTimer;
19+
bool buttonPressed = false;
20+
enum states { Idle, Pressed, Holding, LongHeld };
21+
states state = Idle;
22+
};
23+
}
24+
}

src/displayapp/DisplayApp.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,20 @@ void DisplayApp::Refresh() {
260260
}
261261
}
262262
break;
263+
case Messages::ButtonLongPressed:
264+
if (currentApp != Apps::Clock) {
265+
LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::Down);
266+
}
267+
break;
268+
case Messages::ButtonLongerPressed:
269+
// Create reboot app and open it instead
270+
LoadApp(Apps::SysInfo, DisplayApp::FullRefreshDirections::Up);
271+
break;
272+
case Messages::ButtonDoubleClicked:
273+
if (currentApp != Apps::Notifications && currentApp != Apps::NotificationsPreview) {
274+
LoadApp(Apps::Notifications, DisplayApp::FullRefreshDirections::Down);
275+
}
276+
break;
263277

264278
case Messages::BleFirmwareUpdateStarted:
265279
LoadApp(Apps::FirmwareUpdate, DisplayApp::FullRefreshDirections::Down);

src/displayapp/Messages.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ namespace Pinetime {
99
UpdateBleConnection,
1010
TouchEvent,
1111
ButtonPushed,
12+
ButtonLongPressed,
13+
ButtonLongerPressed,
14+
ButtonDoubleClicked,
1215
NewNotification,
1316
TimerDone,
1417
BleFirmwareUpdateStarted,

src/main.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "systemtask/SystemTask.h"
4848
#include "drivers/PinMap.h"
4949
#include "touchhandler/TouchHandler.h"
50+
#include "buttonhandler/ButtonHandler.h"
5051

5152
#if NRF_LOG_ENABLED
5253
#include "logging/NrfLogger.h"
@@ -96,8 +97,6 @@ TimerHandle_t debounceTimer;
9697
TimerHandle_t debounceChargeTimer;
9798
Pinetime::Controllers::Battery batteryController;
9899
Pinetime::Controllers::Ble bleController;
99-
static constexpr uint8_t pinTouchIrq = Pinetime::PinMap::Cst816sIrq;
100-
static constexpr uint8_t pinPowerPresentIrq = Pinetime::PinMap::PowerPresent;
101100

102101
Pinetime::Controllers::HeartRateController heartRateController;
103102
Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController);
@@ -110,6 +109,7 @@ Pinetime::Controllers::MotionController motionController;
110109
Pinetime::Controllers::TimerController timerController;
111110
Pinetime::Controllers::AlarmController alarmController {dateTimeController};
112111
Pinetime::Controllers::TouchHandler touchHandler(touchPanel, lvgl);
112+
Pinetime::Controllers::ButtonHandler buttonHandler;
113113

114114
Pinetime::Controllers::FS fs {spiNorFlash};
115115
Pinetime::Controllers::Settings settingsController {fs};
@@ -153,7 +153,8 @@ Pinetime::System::SystemTask systemTask(spi,
153153
displayApp,
154154
heartRateApp,
155155
fs,
156-
touchHandler);
156+
touchHandler,
157+
buttonHandler);
157158

158159
/* Variable Declarations for variables in noinit SRAM
159160
Increment NoInit_MagicValue upon adding variables to this area
@@ -176,21 +177,20 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action
176177
if (pin == Pinetime::PinMap::PowerPresent and action == NRF_GPIOTE_POLARITY_TOGGLE) {
177178
xTimerStartFromISR(debounceChargeTimer, &xHigherPriorityTaskWoken);
178179
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
179-
return;
180+
} else if (pin == Pinetime::PinMap::Button) {
181+
// This activates on button release as well due to bouncing
182+
xTimerStartFromISR(debounceTimer, &xHigherPriorityTaskWoken);
183+
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
180184
}
181-
182-
xTimerStartFromISR(debounceTimer, &xHigherPriorityTaskWoken);
183-
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
184185
}
185186

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

191-
void DebounceTimerCallback(TimerHandle_t xTimer) {
192-
xTimerStop(xTimer, 0);
193-
systemTask.OnButtonPushed();
192+
void DebounceTimerCallback(TimerHandle_t /*unused*/) {
193+
systemTask.PushMessage(Pinetime::System::Messages::HandleButtonEvent);
194194
}
195195

196196
void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) {
@@ -319,8 +319,8 @@ int main(void) {
319319
}
320320
nrf_gpio_cfg_default(Pinetime::PinMap::TwiScl);
321321

322-
debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback);
323-
debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback);
322+
debounceTimer = xTimerCreate("debounceTimer", 10, pdFALSE, nullptr, DebounceTimerCallback);
323+
debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, nullptr, DebounceTimerChargeCallback);
324324

325325
// retrieve version stored by bootloader
326326
Pinetime::BootloaderVersion::SetVersion(NRF_TIMER2->CC[0]);

src/systemtask/Messages.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ namespace Pinetime {
1515
BleFirmwareUpdateStarted,
1616
BleFirmwareUpdateFinished,
1717
OnTouchEvent,
18-
OnButtonEvent,
18+
OnButtonPushed,
19+
OnButtonLongPressed,
20+
OnButtonLongerPressed,
21+
OnButtonDoubleClicked,
22+
HandleButtonEvent,
1923
OnDisplayTaskSleeping,
2024
EnableSleeping,
2125
DisableSleeping,
2226
OnNewDay,
2327
OnChargingEvent,
28+
ReloadIdleTimer,
2429
SetOffAlarm,
2530
StopRinging,
2631
MeasureBatteryTimerExpired,

src/systemtask/SystemTask.cpp

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include "main.h"
2626
#include "BootErrors.h"
2727

28-
2928
#include <memory>
3029

3130
using 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

108115
void 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,9 +335,32 @@ 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);
338+
case Messages::OnButtonPushed:
339+
if (!isSleeping && !isGoingToSleep) {
340+
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed);
341+
}
342+
break;
343+
case Messages::OnButtonLongPressed:
344+
if (!isSleeping) {
345+
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonLongPressed);
346+
}
347+
break;
348+
case Messages::OnButtonLongerPressed:
349+
if (!isSleeping) {
350+
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonLongerPressed);
351+
}
352+
break;
353+
case Messages::OnButtonDoubleClicked:
354+
if (!isSleeping) {
355+
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonDoubleClicked);
356+
}
357+
break;
358+
case Messages::HandleButtonEvent:
359+
if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) {
360+
buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Release);
361+
} else {
362+
buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Press);
363+
}
332364
break;
333365
case Messages::OnDisplayTaskSleeping:
334366
if (BootloaderVersion::IsValid()) {
@@ -366,6 +398,9 @@ void SystemTask::Work() {
366398
case Messages::BatteryPercentageUpdated:
367399
nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
368400
break;
401+
case Messages::ReloadIdleTimer:
402+
ReloadIdleTimer();
403+
break;
369404

370405
default:
371406
break;
@@ -414,20 +449,6 @@ void SystemTask::UpdateMotion() {
414449
}
415450
}
416451

417-
void SystemTask::OnButtonPushed() {
418-
if (isGoingToSleep)
419-
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-
}
428-
}
429-
}
430-
431452
void SystemTask::GoToRunning() {
432453
if (isGoingToSleep or (not isSleeping) or isWakingUp)
433454
return;

0 commit comments

Comments
 (0)