Skip to content

Commit fd2e21b

Browse files
committed
Stopwatch: add persistence
Stopwatch now keeps running in background if screen is left. Implemented this by introducing a StopWatchController. Largely based on the work of Louis Pearson (@desttinghim@github.com), see #783
1 parent b56c5f2 commit fd2e21b

File tree

12 files changed

+259
-55
lines changed

12 files changed

+259
-55
lines changed

src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ list(APPEND SOURCE_FILES
472472
components/motor/MotorController.cpp
473473
components/settings/Settings.cpp
474474
components/timer/TimerController.cpp
475+
components/stopwatch/StopWatchController.cpp
475476
components/alarm/AlarmController.cpp
476477
components/fs/FS.cpp
477478
drivers/Cst816s.cpp
@@ -539,6 +540,7 @@ list(APPEND RECOVERY_SOURCE_FILES
539540
components/settings/Settings.cpp
540541
components/timer/TimerController.cpp
541542
components/alarm/AlarmController.cpp
543+
components/stopwatch/StopWatchController.cpp
542544
drivers/Cst816s.cpp
543545
FreeRTOS/port.c
544546
FreeRTOS/port_cmsis_systick.c
@@ -655,6 +657,7 @@ set(INCLUDE_FILES
655657
components/settings/Settings.h
656658
components/timer/TimerController.h
657659
components/alarm/AlarmController.h
660+
components/stopwatch/StopWatchController.h
658661
drivers/Cst816s.h
659662
FreeRTOS/portmacro.h
660663
FreeRTOS/portmacro_cmsis.h
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#include "StopWatchController.h"
2+
3+
using namespace Pinetime::Controllers;
4+
5+
namespace {
6+
TickType_t calculateDelta(const TickType_t startTime, const TickType_t currentTime) {
7+
TickType_t delta = 0;
8+
// Take care of overflow
9+
if (startTime > currentTime) {
10+
delta = 0xffffffff - startTime;
11+
delta += (currentTime + 1);
12+
} else {
13+
delta = currentTime - startTime;
14+
}
15+
return delta;
16+
}
17+
}
18+
19+
StopWatchController::StopWatchController() {
20+
Clear();
21+
}
22+
23+
// State Change
24+
25+
void StopWatchController::Start() {
26+
currentState = StopWatchStates::Running;
27+
startTime = xTaskGetTickCount();
28+
}
29+
30+
void StopWatchController::Pause() {
31+
currentState = StopWatchStates::Paused;
32+
timeElapsedPreviously += calculateDelta(startTime, xTaskGetTickCount());
33+
}
34+
35+
void StopWatchController::Clear() {
36+
currentState = StopWatchStates::Cleared;
37+
timeElapsedPreviously = 0;
38+
39+
for (int i = 0; i < LAP_CAPACITY; i++) {
40+
laps[i].count = 0;
41+
laps[i].time = 0;
42+
}
43+
lapCount = 0;
44+
lapHead = 0;
45+
}
46+
47+
// Lap
48+
49+
void StopWatchController::PushLap() {
50+
TickType_t lapEnd = GetElapsedTime();
51+
laps[lapHead].time = lapEnd;
52+
laps[lapHead].count = lapCount + 1;
53+
lapCount += 1;
54+
lapHead = lapCount % LAP_CAPACITY;
55+
}
56+
57+
int StopWatchController::GetLapNum() {
58+
if (lapCount < LAP_CAPACITY)
59+
return lapCount;
60+
else
61+
return LAP_CAPACITY;
62+
}
63+
64+
int StopWatchController::GetLapCount() {
65+
return lapCount;
66+
}
67+
68+
int wrap(int index) {
69+
return ((index % LAP_CAPACITY) + LAP_CAPACITY) % LAP_CAPACITY;
70+
}
71+
72+
LapInfo_t* StopWatchController::LastLap(int lap) {
73+
if (lap >= LAP_CAPACITY || lap > lapCount || lapCount == 0) {
74+
// Return "empty" LapInfo_t
75+
return &emptyLapInfo;
76+
}
77+
// Index backwards
78+
int index = wrap(lapHead - lap);
79+
return &laps[index];
80+
}
81+
82+
// Data / State acess
83+
84+
TickType_t StopWatchController::GetElapsedTime() {
85+
if (!IsRunning()) {
86+
return timeElapsedPreviously;
87+
}
88+
return timeElapsedPreviously + calculateDelta(startTime, xTaskGetTickCount());
89+
}
90+
91+
bool StopWatchController::IsRunning() {
92+
return currentState == StopWatchStates::Running;
93+
}
94+
95+
bool StopWatchController::IsCleared() {
96+
return currentState == StopWatchStates::Cleared;
97+
}
98+
99+
bool StopWatchController::IsPaused() {
100+
return currentState == StopWatchStates::Paused;
101+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#pragma once
2+
3+
#include <timers.h>
4+
5+
#define LAP_CAPACITY 2
6+
7+
namespace Pinetime {
8+
namespace System {
9+
class SystemTask;
10+
}
11+
namespace Controllers {
12+
13+
enum class StopWatchStates { Cleared, Running, Paused };
14+
15+
struct LapInfo_t {
16+
int count = 0; // Used to label the lap
17+
TickType_t time = 0; // Delta time from beginning of stopwatch
18+
};
19+
20+
class StopWatchController {
21+
public:
22+
StopWatchController();
23+
24+
// StopWatch functionality and data
25+
void Start();
26+
void Pause();
27+
void Clear();
28+
29+
TickType_t GetElapsedTime();
30+
31+
// Lap functionality
32+
33+
/// Only the latest laps are stored, the lap count is saved until reset
34+
void PushLap();
35+
36+
/// Returns actual count of stored laps
37+
int GetLapNum();
38+
39+
/// Returns lapCount
40+
int GetLapCount();
41+
42+
/// Indexes into lap history, with 0 being the latest lap.
43+
/// If the lap is unavailable, count and time will be 0. If there is a
44+
/// real value, count should be above 0
45+
LapInfo_t* LastLap(int lap = 0);
46+
47+
bool IsRunning();
48+
bool IsCleared();
49+
bool IsPaused();
50+
51+
private:
52+
// Current state of stopwatch
53+
StopWatchStates currentState = StopWatchStates::Cleared;
54+
// Start time of current duration
55+
TickType_t startTime = 0;
56+
// How much time was elapsed before current duration
57+
TickType_t timeElapsedPreviously = 0;
58+
// Stores lap times
59+
LapInfo_t laps[LAP_CAPACITY];
60+
LapInfo_t emptyLapInfo = {.count = 0, .time = 0};
61+
int lapCount = 0;
62+
int lapHead = 0;
63+
};
64+
}
65+
}

src/displayapp/DisplayApp.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
7474
Pinetime::Controllers::MotionController& motionController,
7575
Pinetime::Controllers::TimerController& timerController,
7676
Pinetime::Controllers::AlarmController& alarmController,
77+
Pinetime::Controllers::StopWatchController& stopWatchController,
7778
Pinetime::Controllers::BrightnessController& brightnessController,
7879
Pinetime::Controllers::TouchHandler& touchHandler,
7980
Pinetime::Controllers::FS& filesystem)
@@ -91,6 +92,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
9192
motionController {motionController},
9293
timerController {timerController},
9394
alarmController {alarmController},
95+
stopWatchController {stopWatchController},
9496
brightnessController {brightnessController},
9597
touchHandler {touchHandler},
9698
filesystem {filesystem} {
@@ -449,7 +451,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
449451
ReturnApp(Apps::QuickSettings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
450452
break;
451453
case Apps::StopWatch:
452-
currentScreen = std::make_unique<Screens::StopWatch>(this, *systemTask);
454+
currentScreen = std::make_unique<Screens::StopWatch>(this, *systemTask, stopWatchController);
453455
break;
454456
case Apps::Twos:
455457
currentScreen = std::make_unique<Screens::Twos>(this);

src/displayapp/DisplayApp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "components/timer/TimerController.h"
1717
#include "components/alarm/AlarmController.h"
1818
#include "touchhandler/TouchHandler.h"
19+
#include "components/stopwatch/StopWatchController.h"
1920

2021
#include "displayapp/Messages.h"
2122
#include "BootErrors.h"
@@ -61,6 +62,7 @@ namespace Pinetime {
6162
Pinetime::Controllers::MotionController& motionController,
6263
Pinetime::Controllers::TimerController& timerController,
6364
Pinetime::Controllers::AlarmController& alarmController,
65+
Pinetime::Controllers::StopWatchController& stopWatchController,
6466
Pinetime::Controllers::BrightnessController& brightnessController,
6567
Pinetime::Controllers::TouchHandler& touchHandler,
6668
Pinetime::Controllers::FS& filesystem);
@@ -89,6 +91,7 @@ namespace Pinetime {
8991
Pinetime::Controllers::MotionController& motionController;
9092
Pinetime::Controllers::TimerController& timerController;
9193
Pinetime::Controllers::AlarmController& alarmController;
94+
Pinetime::Controllers::StopWatchController& stopWatchController;
9295
Pinetime::Controllers::BrightnessController& brightnessController;
9396
Pinetime::Controllers::TouchHandler& touchHandler;
9497
Pinetime::Controllers::FS& filesystem;

src/displayapp/DisplayAppRecovery.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
2424
Pinetime::Controllers::MotionController& motionController,
2525
Pinetime::Controllers::TimerController& timerController,
2626
Pinetime::Controllers::AlarmController& alarmController,
27+
Pinetime::Controllers::StopWatchController& stopWatchController,
2728
Pinetime::Controllers::BrightnessController& brightnessController,
2829
Pinetime::Controllers::TouchHandler& touchHandler,
2930
Pinetime::Controllers::FS& filesystem)

src/displayapp/DisplayAppRecovery.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace Pinetime {
3434
class MotorController;
3535
class TimerController;
3636
class AlarmController;
37+
class StopWatchController;
3738
class BrightnessController;
3839
class FS;
3940
}
@@ -59,6 +60,7 @@ namespace Pinetime {
5960
Pinetime::Controllers::MotionController& motionController,
6061
Pinetime::Controllers::TimerController& timerController,
6162
Pinetime::Controllers::AlarmController& alarmController,
63+
Pinetime::Controllers::StopWatch& stopWatchController,
6264
Pinetime::Controllers::BrightnessController& brightnessController,
6365
Pinetime::Controllers::TouchHandler& touchHandler,
6466
Pinetime::Controllers::FS& filesystem);

0 commit comments

Comments
 (0)