aboutsummaryrefslogtreecommitdiffstats
path: root/src/displayapp
diff options
context:
space:
mode:
authorJan Hustak <coding@journey.sk>2024-10-20 12:01:36 +0200
committerJF <JF002@users.noreply.github.com>2025-11-04 21:25:31 +0100
commitdb5d4704cc4a7361c80d1eab199af268364545c7 (patch)
tree060efe2965b0984637fc8054353c1dcea5ffb622 /src/displayapp
parent74cf69bb6716657575f52e0e207ff123c6e01575 (diff)
StopWatch: add persistence
# Conflicts: # src/displayapp/screens/StopWatch.h
Diffstat (limited to 'src/displayapp')
-rw-r--r--src/displayapp/Controllers.h2
-rw-r--r--src/displayapp/DisplayApp.cpp3
-rw-r--r--src/displayapp/DisplayApp.h3
-rw-r--r--src/displayapp/DisplayAppRecovery.cpp1
-rw-r--r--src/displayapp/DisplayAppRecovery.h2
-rw-r--r--src/displayapp/screens/StopWatch.cpp178
-rw-r--r--src/displayapp/screens/StopWatch.h106
7 files changed, 153 insertions, 142 deletions
diff --git a/src/displayapp/Controllers.h b/src/displayapp/Controllers.h
index 9992426c..223c7c69 100644
--- a/src/displayapp/Controllers.h
+++ b/src/displayapp/Controllers.h
@@ -18,6 +18,7 @@ namespace Pinetime {
class Settings;
class MotorController;
class MotionController;
+ class StopWatchController;
class AlarmController;
class BrightnessController;
class SimpleWeatherService;
@@ -41,6 +42,7 @@ namespace Pinetime {
Pinetime::Controllers::Settings& settingsController;
Pinetime::Controllers::MotorController& motorController;
Pinetime::Controllers::MotionController& motionController;
+ Pinetime::Controllers::StopWatchController& stopWatchController;
Pinetime::Controllers::AlarmController& alarmController;
Pinetime::Controllers::BrightnessController& brightnessController;
Pinetime::Controllers::SimpleWeatherService* weatherController;
diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index 5c50e85f..7585c55d 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -82,6 +82,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
Controllers::Settings& settingsController,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
+ Pinetime::Controllers::StopWatchController& stopWatchController,
Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::BrightnessController& brightnessController,
Pinetime::Controllers::TouchHandler& touchHandler,
@@ -98,6 +99,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
settingsController {settingsController},
motorController {motorController},
motionController {motionController},
+ stopWatchController {stopWatchController},
alarmController {alarmController},
brightnessController {brightnessController},
touchHandler {touchHandler},
@@ -113,6 +115,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
settingsController,
motorController,
motionController,
+ stopWatchController,
alarmController,
brightnessController,
nullptr,
diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h
index dabed99e..016f91d3 100644
--- a/src/displayapp/DisplayApp.h
+++ b/src/displayapp/DisplayApp.h
@@ -13,6 +13,7 @@
#include "components/settings/Settings.h"
#include "displayapp/screens/Screen.h"
#include "components/timer/Timer.h"
+#include "components/stopwatch/StopWatchController.h"
#include "components/alarm/AlarmController.h"
#include "touchhandler/TouchHandler.h"
@@ -63,6 +64,7 @@ namespace Pinetime {
Controllers::Settings& settingsController,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
+ Pinetime::Controllers::StopWatchController& stopWatchController,
Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::BrightnessController& brightnessController,
Pinetime::Controllers::TouchHandler& touchHandler,
@@ -93,6 +95,7 @@ namespace Pinetime {
Pinetime::Controllers::Settings& settingsController;
Pinetime::Controllers::MotorController& motorController;
Pinetime::Controllers::MotionController& motionController;
+ Pinetime::Controllers::StopWatchController& stopWatchController;
Pinetime::Controllers::AlarmController& alarmController;
Pinetime::Controllers::BrightnessController& brightnessController;
Pinetime::Controllers::TouchHandler& touchHandler;
diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp
index bcb8db0e..cb358d60 100644
--- a/src/displayapp/DisplayAppRecovery.cpp
+++ b/src/displayapp/DisplayAppRecovery.cpp
@@ -21,6 +21,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
Controllers::Settings& /*settingsController*/,
Pinetime::Controllers::MotorController& /*motorController*/,
Pinetime::Controllers::MotionController& /*motionController*/,
+ Pinetime::Controllers::StopWatchController& /*stopWatchController*/,
Pinetime::Controllers::AlarmController& /*alarmController*/,
Pinetime::Controllers::BrightnessController& /*brightnessController*/,
Pinetime::Controllers::TouchHandler& /*touchHandler*/,
diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h
index 162ff257..ed387a8b 100644
--- a/src/displayapp/DisplayAppRecovery.h
+++ b/src/displayapp/DisplayAppRecovery.h
@@ -31,6 +31,7 @@ namespace Pinetime {
class MotionController;
class TouchHandler;
class MotorController;
+ class StopWatchController;
class AlarmController;
class BrightnessController;
class FS;
@@ -57,6 +58,7 @@ namespace Pinetime {
Controllers::Settings& settingsController,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
+ Pinetime::Controllers::StopWatchController& stopWatchController,
Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::BrightnessController& brightnessController,
Pinetime::Controllers::TouchHandler& touchHandler,
diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp
index ff852beb..397cd365 100644
--- a/src/displayapp/screens/StopWatch.cpp
+++ b/src/displayapp/screens/StopWatch.cpp
@@ -4,9 +4,10 @@
#include "displayapp/InfiniTimeTheme.h"
using namespace Pinetime::Applications::Screens;
+using namespace Pinetime::Controllers;
namespace {
- TimeSeparated_t convertTicksToTimeSegments(const TickType_t timeElapsed) {
+ TimeSeparated convertTicksToTimeSegments(const TickType_t timeElapsed) {
// Centiseconds
const int timeElapsedCentis = timeElapsed * 100 / configTICK_RATE_HZ;
@@ -14,27 +15,29 @@ namespace {
const int secs = (timeElapsedCentis / 100) % 60;
const int mins = ((timeElapsedCentis / 100) / 60) % 60;
const int hours = ((timeElapsedCentis / 100) / 60) / 60;
- return TimeSeparated_t {hours, mins, secs, hundredths};
+ return TimeSeparated {hours, mins, secs, hundredths};
}
void play_pause_event_handler(lv_obj_t* obj, lv_event_t event) {
auto* stopWatch = static_cast<StopWatch*>(obj->user_data);
if (event == LV_EVENT_CLICKED) {
- stopWatch->playPauseBtnEventHandler();
+ stopWatch->PlayPauseBtnEventHandler();
}
}
void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) {
auto* stopWatch = static_cast<StopWatch*>(obj->user_data);
if (event == LV_EVENT_CLICKED) {
- stopWatch->stopLapBtnEventHandler();
+ stopWatch->StopLapBtnEventHandler();
}
}
constexpr TickType_t blinkInterval = pdMS_TO_TICKS(1000);
}
-StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) {
+StopWatch::StopWatch(System::SystemTask& systemTask,
+ StopWatchController& stopWatchController)
+ : wakeLock(systemTask), stopWatchController {stopWatchController} {
static constexpr uint8_t btnWidth = 115;
static constexpr uint8_t btnHeight = 80;
btnPlayPause = lv_btn_create(lv_scr_act(), nullptr);
@@ -72,9 +75,28 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) {
lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray);
lv_obj_align(time, msecTime, LV_ALIGN_OUT_TOP_MID, 0, 0);
- SetInterfaceStopped();
-
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
+
+ // Figure out what the current state of the stopwatch is and select the correct display
+ if (stopWatchController.IsCleared()) {
+ DisplayCleared();
+ } else {
+ if (stopWatchController.GetLapCount() > 0) {
+ RenderLaps();
+ }
+ RenderTime();
+
+ if (stopWatchController.IsRunning()) {
+ lv_obj_set_state(btnStopLap, LV_STATE_DISABLED);
+ lv_obj_set_state(txtStopLap, LV_STATE_DISABLED);
+ DisplayStarted();
+ wakeLock.Lock();
+ } else if (stopWatchController.IsPaused()) {
+ lv_obj_set_state(btnStopLap, LV_STATE_DEFAULT);
+ lv_obj_set_state(txtStopLap, LV_STATE_DEFAULT);
+ DisplayPaused();
+ }
+ }
}
StopWatch::~StopWatch() {
@@ -82,14 +104,14 @@ StopWatch::~StopWatch() {
lv_obj_clean(lv_scr_act());
}
-void StopWatch::SetInterfacePaused() {
+void StopWatch::DisplayPaused() {
lv_obj_set_style_local_bg_color(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::blue);
lv_label_set_text_static(txtPlayPause, Symbols::play);
lv_label_set_text_static(txtStopLap, Symbols::stop);
}
-void StopWatch::SetInterfaceRunning() {
+void StopWatch::DisplayStarted() {
lv_obj_set_state(time, LV_STATE_DEFAULT);
lv_obj_set_state(msecTime, LV_STATE_DEFAULT);
lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt);
@@ -102,7 +124,7 @@ void StopWatch::SetInterfaceRunning() {
lv_obj_set_state(txtStopLap, LV_STATE_DEFAULT);
}
-void StopWatch::SetInterfaceStopped() {
+void StopWatch::DisplayCleared() {
lv_obj_set_state(time, LV_STATE_DISABLED);
lv_obj_set_state(msecTime, LV_STATE_DISABLED);
lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::blue);
@@ -123,96 +145,86 @@ void StopWatch::SetInterfaceStopped() {
lv_obj_set_state(txtStopLap, LV_STATE_DISABLED);
}
-void StopWatch::Reset() {
- SetInterfaceStopped();
- currentState = States::Init;
- oldTimeElapsed = 0;
- lapsDone = 0;
+void StopWatch::RenderTime() {
+ TimeSeparated currentTimeSeparated = convertTicksToTimeSegments(stopWatchController.GetElapsedTime());
+ if (currentTimeSeparated.hours == 0) {
+ lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs);
+ } else {
+ lv_label_set_text_fmt(time, "%02d:%02d:%02d", currentTimeSeparated.hours, currentTimeSeparated.mins, currentTimeSeparated.secs);
+ if (!isHoursLabelUpdated) {
+ lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
+ lv_obj_realign(time);
+ isHoursLabelUpdated = true;
+ }
+ }
+ lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths);
}
-void StopWatch::Start() {
- SetInterfaceRunning();
- startTime = xTaskGetTickCount();
- currentState = States::Running;
- wakeLock.Lock();
+void StopWatch::RenderPause() {
+ const TickType_t currentTime = xTaskGetTickCount();
+ if (currentTime > blinkTime) {
+ blinkTime = currentTime + blinkInterval;
+ if (lv_obj_get_state(time, LV_LABEL_PART_MAIN) == LV_STATE_DEFAULT) {
+ lv_obj_set_state(time, LV_STATE_DISABLED);
+ lv_obj_set_state(msecTime, LV_STATE_DISABLED);
+ } else {
+ lv_obj_set_state(time, LV_STATE_DEFAULT);
+ lv_obj_set_state(msecTime, LV_STATE_DEFAULT);
+ }
+ }
}
-void StopWatch::Pause() {
- SetInterfacePaused();
- startTime = 0;
- // Store the current time elapsed in cache
- oldTimeElapsed = laps[lapsDone];
- blinkTime = xTaskGetTickCount() + blinkInterval;
- currentState = States::Halted;
- wakeLock.Release();
+void StopWatch::RenderLaps() {
+ lv_label_set_text(lapText, "");
+ for (int i = 0; i < displayedLaps; i++) {
+ LapInfo* lap = stopWatchController.LastLap(i);
+
+ if (lap->count != 0) {
+ TimeSeparated laptime = convertTicksToTimeSegments(lap->time);
+ char buffer[16];
+ sprintf(buffer, "#%2d %2d:%02d.%02d\n", lap->count, laptime.mins, laptime.secs, laptime.hundredths);
+ lv_label_ins_text(lapText, LV_LABEL_POS_LAST, buffer);
+ }
+ }
}
void StopWatch::Refresh() {
- if (currentState == States::Running) {
- laps[lapsDone] = oldTimeElapsed + xTaskGetTickCount() - startTime;
-
- TimeSeparated_t currentTimeSeparated = convertTicksToTimeSegments(laps[lapsDone]);
- if (currentTimeSeparated.hours == 0) {
- lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs);
- } else {
- lv_label_set_text_fmt(time, "%02d:%02d:%02d", currentTimeSeparated.hours, currentTimeSeparated.mins, currentTimeSeparated.secs);
- if (!isHoursLabelUpdated) {
- lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
- lv_obj_realign(time);
- isHoursLabelUpdated = true;
- }
- }
- lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths);
- } else if (currentState == States::Halted) {
- const TickType_t currentTime = xTaskGetTickCount();
- if (currentTime > blinkTime) {
- blinkTime = currentTime + blinkInterval;
- if (lv_obj_get_state(time, LV_LABEL_PART_MAIN) == LV_STATE_DEFAULT) {
- lv_obj_set_state(time, LV_STATE_DISABLED);
- lv_obj_set_state(msecTime, LV_STATE_DISABLED);
- } else {
- lv_obj_set_state(time, LV_STATE_DEFAULT);
- lv_obj_set_state(msecTime, LV_STATE_DEFAULT);
- }
- }
+ if (stopWatchController.IsRunning()) {
+ RenderTime();
+ } else if (stopWatchController.IsPaused()) {
+ RenderPause();
}
}
-void StopWatch::playPauseBtnEventHandler() {
- if (currentState == States::Init || currentState == States::Halted) {
- Start();
- } else if (currentState == States::Running) {
- Pause();
+void StopWatch::PlayPauseBtnEventHandler() {
+ if (stopWatchController.IsCleared() || stopWatchController.IsPaused()) {
+ stopWatchController.Start();
+ DisplayStarted();
+ wakeLock.Lock();
+ } else if (stopWatchController.IsRunning()) {
+ stopWatchController.Pause();
+ blinkTime = xTaskGetTickCount() + blinkInterval;
+ DisplayPaused();
+ wakeLock.Release();
}
}
-void StopWatch::stopLapBtnEventHandler() {
- // If running, then this button is used to save laps
- if (currentState == States::Running) {
- lv_label_set_text(lapText, "");
- lapsDone = std::min(lapsDone + 1, maxLapCount);
- for (int i = lapsDone - displayedLaps; i < lapsDone; i++) {
- if (i < 0) {
- lv_label_ins_text(lapText, LV_LABEL_POS_LAST, "\n");
- continue;
- }
- TimeSeparated_t times = convertTicksToTimeSegments(laps[i]);
- char buffer[17];
- if (times.hours == 0) {
- snprintf(buffer, sizeof(buffer), "#%2d %2d:%02d.%02d\n", i + 1, times.mins, times.secs, times.hundredths);
- } else {
- snprintf(buffer, sizeof(buffer), "#%2d %2d:%02d:%02d.%02d\n", i + 1, times.hours, times.mins, times.secs, times.hundredths);
- }
- lv_label_ins_text(lapText, LV_LABEL_POS_LAST, buffer);
- }
- } else if (currentState == States::Halted) {
- Reset();
+void StopWatch::StopLapBtnEventHandler() {
+ if (stopWatchController.IsRunning()) {
+ stopWatchController.PushLap();
+ RenderLaps();
+ } else if (stopWatchController.IsPaused()) {
+ stopWatchController.Clear();
+ DisplayCleared();
+ wakeLock.Release();
}
}
bool StopWatch::OnButtonPushed() {
- if (currentState == States::Running) {
- Pause();
+ if (stopWatchController.IsRunning()) {
+ stopWatchController.Pause();
+ DisplayPaused();
+ wakeLock.Release();
return true;
}
return false;
diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h
index 7256dd5b..b2e85b7a 100644
--- a/src/displayapp/screens/StopWatch.h
+++ b/src/displayapp/screens/StopWatch.h
@@ -3,76 +3,64 @@
#include "displayapp/screens/Screen.h"
#include <lvgl/lvgl.h>
-#include <FreeRTOS.h>
-#include "portmacro_cmsis.h"
-
+#include "components/stopwatch/StopWatchController.h"
#include "systemtask/SystemTask.h"
#include "systemtask/WakeLock.h"
-#include "displayapp/apps/Apps.h"
-#include "displayapp/Controllers.h"
#include "Symbols.h"
-namespace Pinetime {
- namespace Applications {
- namespace Screens {
-
- enum class States { Init, Running, Halted };
-
- struct TimeSeparated_t {
- int hours;
- int mins;
- int secs;
- int hundredths;
- };
+namespace Pinetime::Applications {
+ namespace Screens {
- class StopWatch : public Screen {
- public:
- explicit StopWatch(System::SystemTask& systemTask);
- ~StopWatch() override;
- void Refresh() override;
-
- void playPauseBtnEventHandler();
- void stopLapBtnEventHandler();
- bool OnButtonPushed() override;
+ struct TimeSeparated {
+ int hours;
+ int mins;
+ int secs;
+ int hundredths;
+ };
- private:
- void SetInterfacePaused();
- void SetInterfaceRunning();
- void SetInterfaceStopped();
+ class StopWatch : public Screen {
+ public:
+ explicit StopWatch(System::SystemTask& systemTask,
+ Controllers::StopWatchController& stopWatchController);
+ ~StopWatch() override;
+ void Refresh() override;
- void Reset();
- void Start();
- void Pause();
+ void PlayPauseBtnEventHandler();
+ void StopLapBtnEventHandler();
+ bool OnButtonPushed() override;
- Pinetime::System::WakeLock wakeLock;
- States currentState = States::Init;
- TickType_t startTime;
- TickType_t oldTimeElapsed = 0;
- TickType_t blinkTime = 0;
- static constexpr int maxLapCount = 20;
- TickType_t laps[maxLapCount + 1];
- static constexpr int displayedLaps = 2;
- int lapsDone = 0;
- lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap;
- lv_obj_t* lapText;
- bool isHoursLabelUpdated = false;
+ private:
+ void DisplayPaused();
+ void DisplayStarted();
+ void DisplayCleared();
- lv_task_t* taskRefresh;
- };
- }
+ void RenderTime();
+ void RenderPause();
+ void RenderLaps();
- template <>
- struct AppTraits<Apps::StopWatch> {
- static constexpr Apps app = Apps::StopWatch;
- static constexpr const char* icon = Screens::Symbols::stopWatch;
+ Pinetime::System::WakeLock wakeLock;
+ Controllers::StopWatchController& stopWatchController;
+ TickType_t blinkTime = 0;
+ static constexpr int displayedLaps = 2;
+ lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap;
+ lv_obj_t* lapText;
+ bool isHoursLabelUpdated = false;
- static Screens::Screen* Create(AppControllers& controllers) {
- return new Screens::StopWatch(*controllers.systemTask);
- };
-
- static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
- return true;
- };
+ lv_task_t* taskRefresh;
};
}
+
+ template <>
+ struct AppTraits<Apps::StopWatch> {
+ static constexpr Apps app = Apps::StopWatch;
+ static constexpr const char* icon = Screens::Symbols::stopWatch;
+
+ static Screens::Screen* Create(AppControllers& controllers) {
+ return new Screens::StopWatch(*controllers.systemTask,
+ controllers.stopWatchController);
+ }
+ static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
+ return true;
+ }
+ };
}