Skip to content

Commit 06b721a

Browse files
mark9064JF002
authored andcommitted
Improve sleep time calculation docs
1 parent 7710084 commit 06b721a

2 files changed

Lines changed: 20 additions & 15 deletions

File tree

src/displayapp/DisplayApp.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -157,33 +157,38 @@ void DisplayApp::InitHw() {
157157
}
158158

159159
TickType_t DisplayApp::CalculateSleepTime() {
160-
TickType_t ticksElapsed = xTaskGetTickCount() - alwaysOnStartTime;
161-
// Divide both the numerator and denominator by 8 to increase the number of ticks (frames) before the overflow tick is reached
160+
// Calculates how many system ticks DisplayApp should sleep before rendering the next AOD frame
161+
// Next frame time is frame count * refresh period (ms) * tick rate
162+
162163
auto RoundedDiv = [](uint32_t a, uint32_t b) {
163164
return ((a + (b / 2)) / b);
164165
};
165-
TickType_t elapsedTarget = RoundedDiv((configTICK_RATE_HZ / 8) * alwaysOnTickCount * alwaysOnRefreshPeriod, 1000 / 8);
166166
// RoundedDiv overflows when numerator + (denominator floordiv 2) > uint32 max
167-
// in this case around 9 hours
168-
constexpr TickType_t overflowTick = (UINT32_MAX - (1000 / 16)) / ((configTICK_RATE_HZ / 8) * alwaysOnRefreshPeriod);
167+
// in this case around 9 hours (=overflow frame count / always on refresh period)
168+
constexpr TickType_t overflowFrameCount = (UINT32_MAX - (1000 / 16)) / ((configTICK_RATE_HZ / 8) * alwaysOnRefreshPeriod);
169+
170+
TickType_t ticksElapsed = xTaskGetTickCount() - alwaysOnStartTime;
171+
// Divide both the numerator and denominator by 8 (=GCD(1000,1024))
172+
// to increase the number of ticks (frames) before the overflow tick is reached
173+
TickType_t targetRenderTick = RoundedDiv((configTICK_RATE_HZ / 8) * alwaysOnFrameCount * alwaysOnRefreshPeriod, 1000 / 8);
169174

170175
// Assumptions
171176

172177
// Tick rate is multiple of 8
173178
// Needed for division trick above
174179
static_assert(configTICK_RATE_HZ % 8 == 0);
175180

176-
// Local tick count must always wraparound before the system tick count does
177-
// As a static assert we can use 64 bit ints and therefore dodge overflows
181+
// Frame count must always wraparound more often than the system tick count does
178182
// Always on overflow time (ms) < system tick overflow time (ms)
179-
static_assert((uint64_t) overflowTick * (uint64_t) alwaysOnRefreshPeriod < (uint64_t) UINT32_MAX * 1000ULL / configTICK_RATE_HZ);
183+
// Using 64bit ints here to avoid overflow
184+
static_assert((uint64_t) overflowFrameCount * (uint64_t) alwaysOnRefreshPeriod < (uint64_t) UINT32_MAX * 1000ULL / configTICK_RATE_HZ);
180185

181-
if (alwaysOnTickCount == overflowTick) {
182-
alwaysOnTickCount = 0;
186+
if (alwaysOnFrameCount == overflowFrameCount) {
187+
alwaysOnFrameCount = 0;
183188
alwaysOnStartTime = xTaskGetTickCount();
184189
}
185-
if (elapsedTarget > ticksElapsed) {
186-
return elapsedTarget - ticksElapsed;
190+
if (targetRenderTick > ticksElapsed) {
191+
return targetRenderTick - ticksElapsed;
187192
} else {
188193
return 0;
189194
}
@@ -240,7 +245,7 @@ void DisplayApp::Refresh() {
240245
if (lv_task_handler() > 0) {
241246
// Drop frames that we've missed if drawing/event handling took way longer than expected
242247
while (queueTimeout == 0) {
243-
alwaysOnTickCount += 1;
248+
alwaysOnFrameCount += 1;
244249
queueTimeout = CalculateSleepTime();
245250
}
246251
}
@@ -311,7 +316,7 @@ void DisplayApp::Refresh() {
311316
if (msg == Messages::GoToAOD) {
312317
lcd.LowPowerOn();
313318
// Record idle entry time
314-
alwaysOnTickCount = 0;
319+
alwaysOnFrameCount = 0;
315320
alwaysOnStartTime = xTaskGetTickCount();
316321
PushMessageToSystemTask(Pinetime::System::Messages::OnDisplayTaskAOD);
317322
state = States::AOD;

src/displayapp/DisplayApp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ namespace Pinetime {
139139
bool isDimmed = false;
140140

141141
TickType_t CalculateSleepTime();
142-
TickType_t alwaysOnTickCount;
142+
TickType_t alwaysOnFrameCount;
143143
TickType_t alwaysOnStartTime;
144144
// If this is to be changed, make sure the actual always on refresh rate is changed
145145
// by configuring the LCD refresh timings

0 commit comments

Comments
 (0)