From 49cfe4a4e8076d92c68e7688f5a9216ad00f3826 Mon Sep 17 00:00:00 2001 From: Eitan Mosenkis Date: Thu, 29 Dec 2022 00:19:10 +0200 Subject: [PATCH 1/6] Count up, set background red, and ring when timer completes. --- src/components/timer/TimerController.cpp | 27 ++++--- src/components/timer/TimerController.h | 11 ++- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/Timer.cpp | 89 ++++++++++++++++-------- src/displayapp/screens/Timer.h | 1 + src/systemtask/SystemTask.cpp | 2 +- 6 files changed, 92 insertions(+), 40 deletions(-) diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp index ea945213ba..62bd7bde17 100644 --- a/src/components/timer/TimerController.cpp +++ b/src/components/timer/TimerController.cpp @@ -16,24 +16,35 @@ void TimerController::Init(Pinetime::System::SystemTask* systemTask) { void TimerController::StartTimer(uint32_t duration) { xTimerChangePeriod(timer, pdMS_TO_TICKS(duration), 0); xTimerStart(timer, 0); + state = TimerState::Running; } uint32_t TimerController::GetTimeRemaining() { - if (IsRunning()) { - TickType_t remainingTime = xTimerGetExpiryTime(timer) - xTaskGetTickCount(); - return (remainingTime * 1000 / configTICK_RATE_HZ); + TickType_t remainingTime = 0; + switch (state) { + case TimerState::Not_Running: + break; + case TimerState::Running: + remainingTime = xTimerGetExpiryTime(timer) - xTaskGetTickCount(); + break; + case TimerState::Alerting: + remainingTime = xTaskGetTickCount() - xTimerGetExpiryTime(timer); + break; } - return 0; + return (remainingTime * 1000 / configTICK_RATE_HZ); } void TimerController::StopTimer() { xTimerStop(timer, 0); -} - -bool TimerController::IsRunning() { - return (xTimerIsTimerActive(timer) == pdTRUE); + state = TimerState::Not_Running; } void TimerController::OnTimerEnd() { + state = TimerState::Alerting; systemTask->PushMessage(System::Messages::OnTimerDone); } + +void TimerController::StopAlerting() { + state = TimerState::Not_Running; + systemTask->PushMessage(System::Messages::StopRinging); +} diff --git a/src/components/timer/TimerController.h b/src/components/timer/TimerController.h index 20f07e8210..19188adfda 100644 --- a/src/components/timer/TimerController.h +++ b/src/components/timer/TimerController.h @@ -22,13 +22,20 @@ namespace Pinetime { uint32_t GetTimeRemaining(); - bool IsRunning(); - void OnTimerEnd(); + void StopAlerting(); + + enum class TimerState { Not_Running, Running, Alerting }; + + TimerState State() const { + return state; + } + private: System::SystemTask* systemTask = nullptr; TimerHandle_t timer; + TimerState state = TimerState::Not_Running; }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 69830eadbd..11b85ffeeb 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -203,7 +203,7 @@ void DisplayApp::Refresh() { case Messages::TimerDone: if (currentApp == Apps::Timer) { auto* timer = static_cast(currentScreen.get()); - timer->Reset(); + timer->SetTimerAlerting(); } else { LoadNewScreen(Apps::Timer, DisplayApp::FullRefreshDirections::Up); } diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index 136d6b52af..6ecfc5403b 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -20,6 +20,7 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : Screen(app), timerController {timerController} { lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_obj_set_style_local_text_color(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_label_set_text_static(colonLabel, ":"); @@ -62,10 +63,16 @@ Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : S txtPlayPause = lv_label_create(lv_scr_act(), nullptr); lv_obj_align(txtPlayPause, btnPlayPause, LV_ALIGN_CENTER, 0, 0); - if (timerController.IsRunning()) { - SetTimerRunning(); - } else { - SetTimerStopped(); + switch (timerController.State()) { + case Controllers::TimerController::TimerState::Running: + SetTimerRunning(); + break; + case Controllers::TimerController::TimerState::Not_Running: + SetTimerStopped(); + break; + case Controllers::TimerController::TimerState::Alerting: + SetTimerAlerting(); + break; } taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); @@ -85,7 +92,7 @@ void Timer::MaskReset() { buttonPressing = false; // A click event is processed before a release event, // so the release event would override the "Pause" text without this check - if (!timerController.IsRunning()) { + if (timerController.State() == Controllers::TimerController::TimerState::Not_Running) { lv_label_set_text_static(txtPlayPause, "Start"); } maskPosition = 0; @@ -103,19 +110,25 @@ void Timer::UpdateMask() { } void Timer::Refresh() { - if (timerController.IsRunning()) { - uint32_t seconds = timerController.GetTimeRemaining() / 1000; - minuteCounter.SetValue(seconds / 60); - secondCounter.SetValue(seconds % 60); - } else if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) { - lv_label_set_text_static(txtPlayPause, "Reset"); - maskPosition += 15; - if (maskPosition > 240) { - MaskReset(); - Reset(); - } else { - UpdateMask(); - } + switch (timerController.State()) { + case Controllers::TimerController::TimerState::Running: + case Controllers::TimerController::TimerState::Alerting: { + uint32_t seconds = timerController.GetTimeRemaining() / 1000; + minuteCounter.SetValue(seconds / 60); + secondCounter.SetValue(seconds % 60); + } break; + case Controllers::TimerController::TimerState::Not_Running: + if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) { + lv_label_set_text_static(txtPlayPause, "Reset"); + maskPosition += 15; + if (maskPosition > 240) { + MaskReset(); + Reset(); + } else { + UpdateMask(); + } + } + break; } } @@ -123,25 +136,45 @@ void Timer::SetTimerRunning() { minuteCounter.HideControls(); secondCounter.HideControls(); lv_label_set_text_static(txtPlayPause, "Pause"); + MaskReset(); + lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); +} + +void Timer::SetTimerAlerting() { + minuteCounter.HideControls(); + secondCounter.HideControls(); + lv_label_set_text_static(txtPlayPause, "Reset"); + lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); } void Timer::SetTimerStopped() { minuteCounter.ShowControls(); secondCounter.ShowControls(); lv_label_set_text_static(txtPlayPause, "Start"); + lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); } void Timer::ToggleRunning() { - if (timerController.IsRunning()) { - uint32_t seconds = timerController.GetTimeRemaining() / 1000; - minuteCounter.SetValue(seconds / 60); - secondCounter.SetValue(seconds % 60); - timerController.StopTimer(); - SetTimerStopped(); - } else if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) { - timerController.StartTimer((secondCounter.GetValue() + minuteCounter.GetValue() * 60) * 1000); - Refresh(); - SetTimerRunning(); + switch (timerController.State()) { + case Controllers::TimerController::TimerState::Running: { + uint32_t seconds = timerController.GetTimeRemaining() / 1000; + minuteCounter.SetValue(seconds / 60); + secondCounter.SetValue(seconds % 60); + } + timerController.StopTimer(); + SetTimerStopped(); + break; + case Controllers::TimerController::TimerState::Alerting: + timerController.StopAlerting(); + Reset(); + break; + case Controllers::TimerController::TimerState::Not_Running: + if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) { + timerController.StartTimer((secondCounter.GetValue() + minuteCounter.GetValue() * 60) * 1000); + Refresh(); + SetTimerRunning(); + } + break; } } diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h index 306281d778..bf583eacf8 100644 --- a/src/displayapp/screens/Timer.h +++ b/src/displayapp/screens/Timer.h @@ -19,6 +19,7 @@ namespace Pinetime::Applications::Screens { void ToggleRunning(); void ButtonPressed(); void MaskReset(); + void SetTimerAlerting(); private: void SetTimerRunning(); diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 73f573fa0e..4c6dc4e574 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -295,7 +295,7 @@ void SystemTask::Work() { if (state == SystemTaskState::Sleeping) { GoToRunning(); } - motorController.RunForDuration(35); + motorController.StartRinging(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone); break; case Messages::SetOffAlarm: From 74100d537ee28b5dc8104d68d8e228242c6c048c Mon Sep 17 00:00:00 2001 From: Eitan Mosenkis Date: Thu, 29 Dec 2022 13:28:16 +0200 Subject: [PATCH 2/6] Change text color instead of whole screen's background color. --- src/displayapp/screens/Timer.cpp | 19 +++++++++++++------ src/displayapp/screens/Timer.h | 2 ++ src/displayapp/widgets/Counter.cpp | 2 ++ src/displayapp/widgets/Counter.h | 5 +++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index 6ecfc5403b..00a603786b 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -18,9 +18,7 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { } Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : Screen(app), timerController {timerController} { - - lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + colonLabel = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_obj_set_style_local_text_color(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_label_set_text_static(colonLabel, ":"); @@ -132,26 +130,35 @@ void Timer::Refresh() { } } +void Timer::UpdateColor() { + lv_color_t color = timerController.State() == Controllers::TimerController::TimerState::Alerting ? LV_COLOR_RED : LV_COLOR_WHITE; + lv_obj_set_style_local_text_color(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color); + lv_style_set_text_color(minuteCounter.GetLabelStyle(), LV_STATE_DEFAULT, color); + lv_obj_refresh_style(minuteCounter.GetObject(), LV_OBJ_PART_MAIN, LV_STYLE_TEXT_COLOR); + lv_style_set_text_color(secondCounter.GetLabelStyle(), LV_STATE_DEFAULT, color); + lv_obj_refresh_style(secondCounter.GetObject(), LV_OBJ_PART_MAIN, LV_STYLE_TEXT_COLOR); +} + void Timer::SetTimerRunning() { minuteCounter.HideControls(); secondCounter.HideControls(); lv_label_set_text_static(txtPlayPause, "Pause"); MaskReset(); - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + UpdateColor(); } void Timer::SetTimerAlerting() { minuteCounter.HideControls(); secondCounter.HideControls(); lv_label_set_text_static(txtPlayPause, "Reset"); - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + UpdateColor(); } void Timer::SetTimerStopped() { minuteCounter.ShowControls(); secondCounter.ShowControls(); lv_label_set_text_static(txtPlayPause, "Start"); - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + UpdateColor(); } void Timer::ToggleRunning() { diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h index bf583eacf8..074476c806 100644 --- a/src/displayapp/screens/Timer.h +++ b/src/displayapp/screens/Timer.h @@ -25,6 +25,7 @@ namespace Pinetime::Applications::Screens { void SetTimerRunning(); void SetTimerStopped(); void UpdateMask(); + void UpdateColor(); Controllers::TimerController& timerController; lv_obj_t* btnPlayPause; @@ -37,6 +38,7 @@ namespace Pinetime::Applications::Screens { lv_task_t* taskRefresh; Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); + lv_obj_t* colonLabel; Widgets::Counter secondCounter = Widgets::Counter(0, 59, jetbrains_mono_76); bool buttonPressing = false; diff --git a/src/displayapp/widgets/Counter.cpp b/src/displayapp/widgets/Counter.cpp index b486e3727f..16990adce4 100644 --- a/src/displayapp/widgets/Counter.cpp +++ b/src/displayapp/widgets/Counter.cpp @@ -121,10 +121,12 @@ void Counter::SetValueChangedEventCallback(void* userData, void (*handler)(void* } void Counter::Create() { + lv_style_init(&labelStyle); counterContainer = lv_obj_create(lv_scr_act(), nullptr); lv_obj_set_style_local_bg_color(counterContainer, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); number = lv_label_create(counterContainer, nullptr); + lv_obj_add_style(number, LV_LABEL_PART_MAIN, &labelStyle); lv_obj_set_style_local_text_font(number, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &font); lv_obj_align(number, nullptr, LV_ALIGN_CENTER, 0, 0); lv_obj_set_auto_realign(number, true); diff --git a/src/displayapp/widgets/Counter.h b/src/displayapp/widgets/Counter.h index 825860b8d9..9184869ada 100644 --- a/src/displayapp/widgets/Counter.h +++ b/src/displayapp/widgets/Counter.h @@ -27,6 +27,10 @@ namespace Pinetime { return counterContainer; }; + lv_style_t* GetLabelStyle() { + return &labelStyle; + } + private: void UpdateLabel(); void (*ValueChangedHandler)(void* userData) = nullptr; @@ -45,6 +49,7 @@ namespace Pinetime { bool twelveHourMode = false; bool monthMode = false; lv_font_t& font; + lv_style_t labelStyle; void* userData = nullptr; }; From f49de045af5d33825a36e2465f0552a5ab05105b Mon Sep 17 00:00:00 2001 From: Eitan Mosenkis Date: Thu, 29 Dec 2022 17:22:55 +0200 Subject: [PATCH 3/6] Address review comments. --- src/components/timer/TimerController.cpp | 6 +++--- src/components/timer/TimerController.h | 4 ++-- src/displayapp/screens/Timer.cpp | 16 +++++++--------- src/displayapp/widgets/Counter.cpp | 6 ++++-- src/displayapp/widgets/Counter.h | 6 +----- 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp index 62bd7bde17..b59694dc13 100644 --- a/src/components/timer/TimerController.cpp +++ b/src/components/timer/TimerController.cpp @@ -22,7 +22,7 @@ void TimerController::StartTimer(uint32_t duration) { uint32_t TimerController::GetTimeRemaining() { TickType_t remainingTime = 0; switch (state) { - case TimerState::Not_Running: + case TimerState::Stopped: break; case TimerState::Running: remainingTime = xTimerGetExpiryTime(timer) - xTaskGetTickCount(); @@ -36,7 +36,7 @@ uint32_t TimerController::GetTimeRemaining() { void TimerController::StopTimer() { xTimerStop(timer, 0); - state = TimerState::Not_Running; + state = TimerState::Stopped; } void TimerController::OnTimerEnd() { @@ -45,6 +45,6 @@ void TimerController::OnTimerEnd() { } void TimerController::StopAlerting() { - state = TimerState::Not_Running; + state = TimerState::Stopped; systemTask->PushMessage(System::Messages::StopRinging); } diff --git a/src/components/timer/TimerController.h b/src/components/timer/TimerController.h index 19188adfda..2dabaa18e6 100644 --- a/src/components/timer/TimerController.h +++ b/src/components/timer/TimerController.h @@ -26,7 +26,7 @@ namespace Pinetime { void StopAlerting(); - enum class TimerState { Not_Running, Running, Alerting }; + enum class TimerState { Stopped, Running, Alerting }; TimerState State() const { return state; @@ -35,7 +35,7 @@ namespace Pinetime { private: System::SystemTask* systemTask = nullptr; TimerHandle_t timer; - TimerState state = TimerState::Not_Running; + TimerState state = TimerState::Stopped; }; } } diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index 00a603786b..5f682ff89b 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -65,7 +65,7 @@ Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : S case Controllers::TimerController::TimerState::Running: SetTimerRunning(); break; - case Controllers::TimerController::TimerState::Not_Running: + case Controllers::TimerController::TimerState::Stopped: SetTimerStopped(); break; case Controllers::TimerController::TimerState::Alerting: @@ -90,7 +90,7 @@ void Timer::MaskReset() { buttonPressing = false; // A click event is processed before a release event, // so the release event would override the "Pause" text without this check - if (timerController.State() == Controllers::TimerController::TimerState::Not_Running) { + if (timerController.State() == Controllers::TimerController::TimerState::Stopped) { lv_label_set_text_static(txtPlayPause, "Start"); } maskPosition = 0; @@ -115,7 +115,7 @@ void Timer::Refresh() { minuteCounter.SetValue(seconds / 60); secondCounter.SetValue(seconds % 60); } break; - case Controllers::TimerController::TimerState::Not_Running: + case Controllers::TimerController::TimerState::Stopped: if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) { lv_label_set_text_static(txtPlayPause, "Reset"); maskPosition += 15; @@ -133,10 +133,8 @@ void Timer::Refresh() { void Timer::UpdateColor() { lv_color_t color = timerController.State() == Controllers::TimerController::TimerState::Alerting ? LV_COLOR_RED : LV_COLOR_WHITE; lv_obj_set_style_local_text_color(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color); - lv_style_set_text_color(minuteCounter.GetLabelStyle(), LV_STATE_DEFAULT, color); - lv_obj_refresh_style(minuteCounter.GetObject(), LV_OBJ_PART_MAIN, LV_STYLE_TEXT_COLOR); - lv_style_set_text_color(secondCounter.GetLabelStyle(), LV_STATE_DEFAULT, color); - lv_obj_refresh_style(secondCounter.GetObject(), LV_OBJ_PART_MAIN, LV_STYLE_TEXT_COLOR); + minuteCounter.SetTextColor(color); + secondCounter.SetTextColor(color); } void Timer::SetTimerRunning() { @@ -150,7 +148,7 @@ void Timer::SetTimerRunning() { void Timer::SetTimerAlerting() { minuteCounter.HideControls(); secondCounter.HideControls(); - lv_label_set_text_static(txtPlayPause, "Reset"); + lv_label_set_text_static(txtPlayPause, "Stop"); UpdateColor(); } @@ -175,7 +173,7 @@ void Timer::ToggleRunning() { timerController.StopAlerting(); Reset(); break; - case Controllers::TimerController::TimerState::Not_Running: + case Controllers::TimerController::TimerState::Stopped: if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) { timerController.StartTimer((secondCounter.GetValue() + minuteCounter.GetValue() * 60) * 1000); Refresh(); diff --git a/src/displayapp/widgets/Counter.cpp b/src/displayapp/widgets/Counter.cpp index 16990adce4..512211a922 100644 --- a/src/displayapp/widgets/Counter.cpp +++ b/src/displayapp/widgets/Counter.cpp @@ -120,13 +120,15 @@ void Counter::SetValueChangedEventCallback(void* userData, void (*handler)(void* this->ValueChangedHandler = handler; } +void Counter::SetTextColor(lv_color_t color) { + lv_obj_set_style_local_text_color(number, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color); +} + void Counter::Create() { - lv_style_init(&labelStyle); counterContainer = lv_obj_create(lv_scr_act(), nullptr); lv_obj_set_style_local_bg_color(counterContainer, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); number = lv_label_create(counterContainer, nullptr); - lv_obj_add_style(number, LV_LABEL_PART_MAIN, &labelStyle); lv_obj_set_style_local_text_font(number, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &font); lv_obj_align(number, nullptr, LV_ALIGN_CENTER, 0, 0); lv_obj_set_auto_realign(number, true); diff --git a/src/displayapp/widgets/Counter.h b/src/displayapp/widgets/Counter.h index 9184869ada..dbf41b09fb 100644 --- a/src/displayapp/widgets/Counter.h +++ b/src/displayapp/widgets/Counter.h @@ -18,6 +18,7 @@ namespace Pinetime { void EnableMonthMode(); void SetMax(int newMax); void SetValueChangedEventCallback(void* userData, void (*handler)(void* userData)); + void SetTextColor(lv_color_t color); int GetValue() const { return value; @@ -27,10 +28,6 @@ namespace Pinetime { return counterContainer; }; - lv_style_t* GetLabelStyle() { - return &labelStyle; - } - private: void UpdateLabel(); void (*ValueChangedHandler)(void* userData) = nullptr; @@ -49,7 +46,6 @@ namespace Pinetime { bool twelveHourMode = false; bool monthMode = false; lv_font_t& font; - lv_style_t labelStyle; void* userData = nullptr; }; From aff7cfc5fc538715931759f97c3f0c1d0adf54fc Mon Sep 17 00:00:00 2001 From: Eitan Mosenkis Date: Thu, 29 Dec 2022 19:22:05 +0200 Subject: [PATCH 4/6] Stop vibrating after 10s. --- src/components/timer/TimerController.cpp | 24 ++++++++++++++---- src/components/timer/TimerController.h | 7 +++--- src/displayapp/DisplayApp.cpp | 2 +- src/displayapp/screens/Timer.cpp | 31 ++++++++++++------------ src/displayapp/screens/Timer.h | 2 +- src/systemtask/Messages.h | 1 + src/systemtask/SystemTask.cpp | 5 ++++ 7 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp index b59694dc13..382b7a8573 100644 --- a/src/components/timer/TimerController.cpp +++ b/src/components/timer/TimerController.cpp @@ -8,9 +8,15 @@ void TimerCallback(TimerHandle_t xTimer) { controller->OnTimerEnd(); } +void SetTimerToStopRingingCallback(TimerHandle_t xTimer) { + auto* controller = static_cast(pvTimerGetTimerID(xTimer)); + controller->StopRinging(); +} + void TimerController::Init(Pinetime::System::SystemTask* systemTask) { this->systemTask = systemTask; timer = xTimerCreate("Timer", 1, pdFALSE, this, TimerCallback); + stopRingingTimer = xTimerCreate("StopRingingTimer", 1, pdFALSE, this, SetTimerToStopRingingCallback); } void TimerController::StartTimer(uint32_t duration) { @@ -27,7 +33,7 @@ uint32_t TimerController::GetTimeRemaining() { case TimerState::Running: remainingTime = xTimerGetExpiryTime(timer) - xTaskGetTickCount(); break; - case TimerState::Alerting: + case TimerState::Finished: remainingTime = xTaskGetTickCount() - xTimerGetExpiryTime(timer); break; } @@ -36,15 +42,23 @@ uint32_t TimerController::GetTimeRemaining() { void TimerController::StopTimer() { xTimerStop(timer, 0); + if (state == TimerState::Finished) { + StopRinging(); + } state = TimerState::Stopped; } void TimerController::OnTimerEnd() { - state = TimerState::Alerting; + state = TimerState::Finished; systemTask->PushMessage(System::Messages::OnTimerDone); + ringing = true; + xTimerChangePeriod(stopRingingTimer, pdMS_TO_TICKS(10000), 0); + xTimerStart(stopRingingTimer, 0); } -void TimerController::StopAlerting() { - state = TimerState::Stopped; - systemTask->PushMessage(System::Messages::StopRinging); +void TimerController::StopRinging() { + if (ringing) { + systemTask->PushMessage(System::Messages::OnTimerDoneRinging); + ringing = false; + } } diff --git a/src/components/timer/TimerController.h b/src/components/timer/TimerController.h index 2dabaa18e6..c5201c40f2 100644 --- a/src/components/timer/TimerController.h +++ b/src/components/timer/TimerController.h @@ -23,10 +23,9 @@ namespace Pinetime { uint32_t GetTimeRemaining(); void OnTimerEnd(); + void StopRinging(); - void StopAlerting(); - - enum class TimerState { Stopped, Running, Alerting }; + enum class TimerState { Stopped, Running, Finished }; TimerState State() const { return state; @@ -36,6 +35,8 @@ namespace Pinetime { System::SystemTask* systemTask = nullptr; TimerHandle_t timer; TimerState state = TimerState::Stopped; + TimerHandle_t stopRingingTimer; + bool ringing = false; }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 11b85ffeeb..a58fafe8aa 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -203,7 +203,7 @@ void DisplayApp::Refresh() { case Messages::TimerDone: if (currentApp == Apps::Timer) { auto* timer = static_cast(currentScreen.get()); - timer->SetTimerAlerting(); + timer->SetTimerFinished(); } else { LoadNewScreen(Apps::Timer, DisplayApp::FullRefreshDirections::Up); } diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index 5f682ff89b..93317c77f3 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -5,6 +5,7 @@ #include using namespace Pinetime::Applications::Screens; +using Pinetime::Controllers::TimerController; static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast(obj->user_data); @@ -17,7 +18,7 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { } } -Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : Screen(app), timerController {timerController} { +Timer::Timer(DisplayApp* app, TimerController& timerController) : Screen(app), timerController {timerController} { colonLabel = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_obj_set_style_local_text_color(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); @@ -62,14 +63,14 @@ Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : S lv_obj_align(txtPlayPause, btnPlayPause, LV_ALIGN_CENTER, 0, 0); switch (timerController.State()) { - case Controllers::TimerController::TimerState::Running: + case TimerController::TimerState::Running: SetTimerRunning(); break; - case Controllers::TimerController::TimerState::Stopped: + case TimerController::TimerState::Stopped: SetTimerStopped(); break; - case Controllers::TimerController::TimerState::Alerting: - SetTimerAlerting(); + case TimerController::TimerState::Finished: + SetTimerFinished(); break; } @@ -90,7 +91,7 @@ void Timer::MaskReset() { buttonPressing = false; // A click event is processed before a release event, // so the release event would override the "Pause" text without this check - if (timerController.State() == Controllers::TimerController::TimerState::Stopped) { + if (timerController.State() == TimerController::TimerState::Stopped) { lv_label_set_text_static(txtPlayPause, "Start"); } maskPosition = 0; @@ -109,13 +110,13 @@ void Timer::UpdateMask() { void Timer::Refresh() { switch (timerController.State()) { - case Controllers::TimerController::TimerState::Running: - case Controllers::TimerController::TimerState::Alerting: { + case TimerController::TimerState::Running: + case TimerController::TimerState::Finished: { uint32_t seconds = timerController.GetTimeRemaining() / 1000; minuteCounter.SetValue(seconds / 60); secondCounter.SetValue(seconds % 60); } break; - case Controllers::TimerController::TimerState::Stopped: + case TimerController::TimerState::Stopped: if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) { lv_label_set_text_static(txtPlayPause, "Reset"); maskPosition += 15; @@ -131,7 +132,7 @@ void Timer::Refresh() { } void Timer::UpdateColor() { - lv_color_t color = timerController.State() == Controllers::TimerController::TimerState::Alerting ? LV_COLOR_RED : LV_COLOR_WHITE; + lv_color_t color = timerController.State() == TimerController::TimerState::Finished ? LV_COLOR_RED : LV_COLOR_WHITE; lv_obj_set_style_local_text_color(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color); minuteCounter.SetTextColor(color); secondCounter.SetTextColor(color); @@ -145,7 +146,7 @@ void Timer::SetTimerRunning() { UpdateColor(); } -void Timer::SetTimerAlerting() { +void Timer::SetTimerFinished() { minuteCounter.HideControls(); secondCounter.HideControls(); lv_label_set_text_static(txtPlayPause, "Stop"); @@ -161,7 +162,7 @@ void Timer::SetTimerStopped() { void Timer::ToggleRunning() { switch (timerController.State()) { - case Controllers::TimerController::TimerState::Running: { + case TimerController::TimerState::Running: { uint32_t seconds = timerController.GetTimeRemaining() / 1000; minuteCounter.SetValue(seconds / 60); secondCounter.SetValue(seconds % 60); @@ -169,11 +170,11 @@ void Timer::ToggleRunning() { timerController.StopTimer(); SetTimerStopped(); break; - case Controllers::TimerController::TimerState::Alerting: - timerController.StopAlerting(); + case TimerController::TimerState::Finished: + timerController.StopTimer(); Reset(); break; - case Controllers::TimerController::TimerState::Stopped: + case TimerController::TimerState::Stopped: if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) { timerController.StartTimer((secondCounter.GetValue() + minuteCounter.GetValue() * 60) * 1000); Refresh(); diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h index 074476c806..568e5e1b92 100644 --- a/src/displayapp/screens/Timer.h +++ b/src/displayapp/screens/Timer.h @@ -19,7 +19,7 @@ namespace Pinetime::Applications::Screens { void ToggleRunning(); void ButtonPressed(); void MaskReset(); - void SetTimerAlerting(); + void SetTimerFinished(); private: void SetTimerRunning(); diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index b7fee8a52c..6bda7a596e 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -10,6 +10,7 @@ namespace Pinetime { OnNewTime, OnNewNotification, OnTimerDone, + OnTimerDoneRinging, OnNewCall, BleConnected, UpdateTimeOut, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 4c6dc4e574..57105d912c 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -297,6 +297,11 @@ void SystemTask::Work() { } motorController.StartRinging(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone); + PushMessage(Messages::DisableSleeping); + break; + case Messages::OnTimerDoneRinging: + motorController.StopRinging(); + PushMessage(Messages::EnableSleeping); break; case Messages::SetOffAlarm: if (state == SystemTaskState::Sleeping) { From 11574baab7518f2b763160b5555fc3c65cf616b7 Mon Sep 17 00:00:00 2001 From: Eitan Mosenkis Date: Tue, 10 Jan 2023 10:49:00 +0200 Subject: [PATCH 5/6] Move control of ringing from TimerController to Timer and add button control of ringing. --- src/components/timer/TimerController.cpp | 21 +----- src/components/timer/TimerController.h | 5 +- src/displayapp/DisplayApp.cpp | 7 +- src/displayapp/Messages.h | 1 + src/displayapp/screens/Timer.cpp | 85 ++++++++++++++++++------ src/displayapp/screens/Timer.h | 7 +- src/systemtask/Messages.h | 2 +- src/systemtask/SystemTask.cpp | 11 +-- 8 files changed, 86 insertions(+), 53 deletions(-) diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp index 382b7a8573..da47cde44b 100644 --- a/src/components/timer/TimerController.cpp +++ b/src/components/timer/TimerController.cpp @@ -8,15 +8,9 @@ void TimerCallback(TimerHandle_t xTimer) { controller->OnTimerEnd(); } -void SetTimerToStopRingingCallback(TimerHandle_t xTimer) { - auto* controller = static_cast(pvTimerGetTimerID(xTimer)); - controller->StopRinging(); -} - void TimerController::Init(Pinetime::System::SystemTask* systemTask) { this->systemTask = systemTask; timer = xTimerCreate("Timer", 1, pdFALSE, this, TimerCallback); - stopRingingTimer = xTimerCreate("StopRingingTimer", 1, pdFALSE, this, SetTimerToStopRingingCallback); } void TimerController::StartTimer(uint32_t duration) { @@ -25,7 +19,7 @@ void TimerController::StartTimer(uint32_t duration) { state = TimerState::Running; } -uint32_t TimerController::GetTimeRemaining() { +uint32_t TimerController::GetTimeRemainingMs() { TickType_t remainingTime = 0; switch (state) { case TimerState::Stopped: @@ -42,23 +36,10 @@ uint32_t TimerController::GetTimeRemaining() { void TimerController::StopTimer() { xTimerStop(timer, 0); - if (state == TimerState::Finished) { - StopRinging(); - } state = TimerState::Stopped; } void TimerController::OnTimerEnd() { state = TimerState::Finished; systemTask->PushMessage(System::Messages::OnTimerDone); - ringing = true; - xTimerChangePeriod(stopRingingTimer, pdMS_TO_TICKS(10000), 0); - xTimerStart(stopRingingTimer, 0); -} - -void TimerController::StopRinging() { - if (ringing) { - systemTask->PushMessage(System::Messages::OnTimerDoneRinging); - ringing = false; - } } diff --git a/src/components/timer/TimerController.h b/src/components/timer/TimerController.h index c5201c40f2..a26ccfbb3c 100644 --- a/src/components/timer/TimerController.h +++ b/src/components/timer/TimerController.h @@ -20,10 +20,9 @@ namespace Pinetime { void StopTimer(); - uint32_t GetTimeRemaining(); + uint32_t GetTimeRemainingMs(); void OnTimerEnd(); - void StopRinging(); enum class TimerState { Stopped, Running, Finished }; @@ -35,8 +34,6 @@ namespace Pinetime { System::SystemTask* systemTask = nullptr; TimerHandle_t timer; TimerState state = TimerState::Stopped; - TimerHandle_t stopRingingTimer; - bool ringing = false; }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index a58fafe8aa..c79d1cd5b1 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -200,6 +200,11 @@ void DisplayApp::Refresh() { case Messages::NewNotification: LoadNewScreen(Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down); break; + case Messages::GoToClock: + if (currentApp != Apps::Clock) { + LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::None); + } + break; case Messages::TimerDone: if (currentApp == Apps::Timer) { auto* timer = static_cast(currentScreen.get()); @@ -396,7 +401,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio Screens::Notifications::Modes::Preview); break; case Apps::Timer: - currentScreen = std::make_unique(this, timerController); + currentScreen = std::make_unique(this, timerController, *systemTask); break; case Apps::Alarm: currentScreen = std::make_unique(this, alarmController, settingsController.GetClockType(), *systemTask); diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index afa7709a9d..759cee3c35 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -7,6 +7,7 @@ namespace Pinetime { enum class Messages : uint8_t { GoToSleep, GoToRunning, + GoToClock, UpdateDateTime, UpdateBleConnection, TouchEvent, diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index 93317c77f3..c0a9ab9bb1 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -7,6 +7,8 @@ using namespace Pinetime::Applications::Screens; using Pinetime::Controllers::TimerController; +#define TIMER_RING_DURATION_MSEC (10 * 1000) + static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast(obj->user_data); if (event == LV_EVENT_PRESSED) { @@ -18,7 +20,13 @@ static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { } } -Timer::Timer(DisplayApp* app, TimerController& timerController) : Screen(app), timerController {timerController} { +static void StopRingingTaskCallback(lv_task_t* task) { + auto* screen = static_cast(task->user_data); + screen->StopRinging(); +} + +Timer::Timer(DisplayApp* app, TimerController& timerController, System::SystemTask& systemTask) + : Screen(app), timerController {timerController}, systemTask {systemTask} { colonLabel = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_obj_set_style_local_text_color(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); @@ -90,9 +98,11 @@ void Timer::ButtonPressed() { void Timer::MaskReset() { buttonPressing = false; // A click event is processed before a release event, - // so the release event would override the "Pause" text without this check + // so the release event would override the text without this check if (timerController.State() == TimerController::TimerState::Stopped) { lv_label_set_text_static(txtPlayPause, "Start"); + } else if (timerController.State() == TimerController::TimerState::Finished) { + lv_label_set_text_static(txtPlayPause, "Stop"); } maskPosition = 0; UpdateMask(); @@ -109,25 +119,29 @@ void Timer::UpdateMask() { } void Timer::Refresh() { - switch (timerController.State()) { - case TimerController::TimerState::Running: - case TimerController::TimerState::Finished: { - uint32_t seconds = timerController.GetTimeRemaining() / 1000; - minuteCounter.SetValue(seconds / 60); - secondCounter.SetValue(seconds % 60); - } break; - case TimerController::TimerState::Stopped: - if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) { - lv_label_set_text_static(txtPlayPause, "Reset"); - maskPosition += 15; - if (maskPosition > 240) { - MaskReset(); - Reset(); - } else { - UpdateMask(); - } + if (timerController.State() != TimerController::TimerState::Stopped) { + // Update counters if running or finished + uint32_t seconds = timerController.GetTimeRemainingMs() / 1000; + minuteCounter.SetValue(seconds / 60); + secondCounter.SetValue(seconds % 60); + } + if (timerController.State() != TimerController::TimerState::Running && buttonPressing && + xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) { + // Support long-pressing the button if stopped or finished + lv_label_set_text_static(txtPlayPause, "Reset"); + maskPosition += 15; + if (maskPosition > 240) { + MaskReset(); + if (timerController.State() == TimerController::TimerState::Stopped) { + Reset(); + } else { + StopRinging(); + timerController.StopTimer(); + systemTask.PushMessage(System::Messages::GoToClock); } - break; + } else { + UpdateMask(); + } } } @@ -151,6 +165,23 @@ void Timer::SetTimerFinished() { secondCounter.HideControls(); lv_label_set_text_static(txtPlayPause, "Stop"); UpdateColor(); + uint32_t msecRemaining = timerController.GetTimeRemainingMs(); + if (msecRemaining < TIMER_RING_DURATION_MSEC) { + taskStopRinging = + lv_task_create(StopRingingTaskCallback, pdMS_TO_TICKS(TIMER_RING_DURATION_MSEC - msecRemaining), LV_TASK_PRIO_MID, this); + systemTask.PushMessage(System::Messages::DisableSleeping); + } +} + +bool Timer::StopRinging() { + if (taskStopRinging == nullptr) { + return false; + } + lv_task_del(taskStopRinging); + taskStopRinging = nullptr; + systemTask.PushMessage(System::Messages::StopRinging); + systemTask.PushMessage(System::Messages::EnableSleeping); + return true; } void Timer::SetTimerStopped() { @@ -163,7 +194,7 @@ void Timer::SetTimerStopped() { void Timer::ToggleRunning() { switch (timerController.State()) { case TimerController::TimerState::Running: { - uint32_t seconds = timerController.GetTimeRemaining() / 1000; + uint32_t seconds = timerController.GetTimeRemainingMs() / 1000; minuteCounter.SetValue(seconds / 60); secondCounter.SetValue(seconds % 60); } @@ -171,6 +202,7 @@ void Timer::ToggleRunning() { SetTimerStopped(); break; case TimerController::TimerState::Finished: + StopRinging(); timerController.StopTimer(); Reset(); break; @@ -189,3 +221,14 @@ void Timer::Reset() { secondCounter.SetValue(0); SetTimerStopped(); } + +bool Timer::OnButtonPushed() { + return StopRinging(); +} + +bool Timer::OnTouchEvent(TouchEvents event) { + if (event == TouchEvents::SwipeDown) { + StopRinging(); + } + return false; +} \ No newline at end of file diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h index 568e5e1b92..906f389e8e 100644 --- a/src/displayapp/screens/Timer.h +++ b/src/displayapp/screens/Timer.h @@ -12,7 +12,7 @@ namespace Pinetime::Applications::Screens { class Timer : public Screen { public: - Timer(DisplayApp* app, Controllers::TimerController& timerController); + Timer(DisplayApp* app, Controllers::TimerController& timerController, System::SystemTask& systemTask); ~Timer() override; void Refresh() override; void Reset(); @@ -20,6 +20,9 @@ namespace Pinetime::Applications::Screens { void ButtonPressed(); void MaskReset(); void SetTimerFinished(); + bool StopRinging(); + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; private: void SetTimerRunning(); @@ -27,6 +30,7 @@ namespace Pinetime::Applications::Screens { void UpdateMask(); void UpdateColor(); Controllers::TimerController& timerController; + System::SystemTask& systemTask; lv_obj_t* btnPlayPause; lv_obj_t* txtPlayPause; @@ -40,6 +44,7 @@ namespace Pinetime::Applications::Screens { Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); lv_obj_t* colonLabel; Widgets::Counter secondCounter = Widgets::Counter(0, 59, jetbrains_mono_76); + lv_task_t* taskStopRinging = nullptr; bool buttonPressing = false; lv_coord_t maskPosition = 0; diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index 6bda7a596e..593c2efe19 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -6,11 +6,11 @@ namespace Pinetime { enum class Messages : uint8_t { GoToSleep, GoToRunning, + GoToClock, TouchWakeUp, OnNewTime, OnNewNotification, OnTimerDone, - OnTimerDoneRinging, OnNewCall, BleConnected, UpdateTimeOut, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 57105d912c..06c04c23b5 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -281,6 +281,12 @@ void SystemTask::Work() { alarmController.ScheduleAlarm(); } break; + case Messages::GoToClock: + if (state == SystemTaskState::Sleeping) { + GoToRunning(); + } + displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToClock); + break; case Messages::OnNewNotification: if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::On) { if (state == SystemTaskState::Sleeping) { @@ -297,11 +303,6 @@ void SystemTask::Work() { } motorController.StartRinging(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone); - PushMessage(Messages::DisableSleeping); - break; - case Messages::OnTimerDoneRinging: - motorController.StopRinging(); - PushMessage(Messages::EnableSleeping); break; case Messages::SetOffAlarm: if (state == SystemTaskState::Sleeping) { From 6755c5924a25cc38c3aebc6ff13296780ed87176 Mon Sep 17 00:00:00 2001 From: Eitan Mosenkis Date: Wed, 11 Jan 2023 15:41:48 +0200 Subject: [PATCH 6/6] Fix after rebase. --- src/displayapp/DisplayApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index c79d1cd5b1..7e6c1d59bf 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -202,7 +202,7 @@ void DisplayApp::Refresh() { break; case Messages::GoToClock: if (currentApp != Apps::Clock) { - LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::None); + LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); } break; case Messages::TimerDone: