aboutsummaryrefslogtreecommitdiffstats
path: root/src/displayapp/DisplayApp.cpp
diff options
context:
space:
mode:
authormark9064 <30447455+mark9064@users.noreply.github.com>2024-09-22 00:34:34 +0100
committerJF <JF002@users.noreply.github.com>2024-10-27 16:56:47 +0100
commit06b721a71fabc2213498dfc50a36681eb300a129 (patch)
tree79700c105718a0d08d85d2f1ea2fe09b12ccbd8c /src/displayapp/DisplayApp.cpp
parent771008495edf0144dd528818bafa77bc10096002 (diff)
Improve sleep time calculation docs
Diffstat (limited to 'src/displayapp/DisplayApp.cpp')
-rw-r--r--src/displayapp/DisplayApp.cpp33
1 files changed, 19 insertions, 14 deletions
diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index 918dd9f9..98a28258 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -157,15 +157,20 @@ void DisplayApp::InitHw() {
}
TickType_t DisplayApp::CalculateSleepTime() {
- TickType_t ticksElapsed = xTaskGetTickCount() - alwaysOnStartTime;
- // Divide both the numerator and denominator by 8 to increase the number of ticks (frames) before the overflow tick is reached
+ // Calculates how many system ticks DisplayApp should sleep before rendering the next AOD frame
+ // Next frame time is frame count * refresh period (ms) * tick rate
+
auto RoundedDiv = [](uint32_t a, uint32_t b) {
return ((a + (b / 2)) / b);
};
- TickType_t elapsedTarget = RoundedDiv((configTICK_RATE_HZ / 8) * alwaysOnTickCount * alwaysOnRefreshPeriod, 1000 / 8);
// RoundedDiv overflows when numerator + (denominator floordiv 2) > uint32 max
- // in this case around 9 hours
- constexpr TickType_t overflowTick = (UINT32_MAX - (1000 / 16)) / ((configTICK_RATE_HZ / 8) * alwaysOnRefreshPeriod);
+ // in this case around 9 hours (=overflow frame count / always on refresh period)
+ constexpr TickType_t overflowFrameCount = (UINT32_MAX - (1000 / 16)) / ((configTICK_RATE_HZ / 8) * alwaysOnRefreshPeriod);
+
+ TickType_t ticksElapsed = xTaskGetTickCount() - alwaysOnStartTime;
+ // Divide both the numerator and denominator by 8 (=GCD(1000,1024))
+ // to increase the number of ticks (frames) before the overflow tick is reached
+ TickType_t targetRenderTick = RoundedDiv((configTICK_RATE_HZ / 8) * alwaysOnFrameCount * alwaysOnRefreshPeriod, 1000 / 8);
// Assumptions
@@ -173,17 +178,17 @@ TickType_t DisplayApp::CalculateSleepTime() {
// Needed for division trick above
static_assert(configTICK_RATE_HZ % 8 == 0);
- // Local tick count must always wraparound before the system tick count does
- // As a static assert we can use 64 bit ints and therefore dodge overflows
+ // Frame count must always wraparound more often than the system tick count does
// Always on overflow time (ms) < system tick overflow time (ms)
- static_assert((uint64_t) overflowTick * (uint64_t) alwaysOnRefreshPeriod < (uint64_t) UINT32_MAX * 1000ULL / configTICK_RATE_HZ);
+ // Using 64bit ints here to avoid overflow
+ static_assert((uint64_t) overflowFrameCount * (uint64_t) alwaysOnRefreshPeriod < (uint64_t) UINT32_MAX * 1000ULL / configTICK_RATE_HZ);
- if (alwaysOnTickCount == overflowTick) {
- alwaysOnTickCount = 0;
+ if (alwaysOnFrameCount == overflowFrameCount) {
+ alwaysOnFrameCount = 0;
alwaysOnStartTime = xTaskGetTickCount();
}
- if (elapsedTarget > ticksElapsed) {
- return elapsedTarget - ticksElapsed;
+ if (targetRenderTick > ticksElapsed) {
+ return targetRenderTick - ticksElapsed;
} else {
return 0;
}
@@ -240,7 +245,7 @@ void DisplayApp::Refresh() {
if (lv_task_handler() > 0) {
// Drop frames that we've missed if drawing/event handling took way longer than expected
while (queueTimeout == 0) {
- alwaysOnTickCount += 1;
+ alwaysOnFrameCount += 1;
queueTimeout = CalculateSleepTime();
}
}
@@ -311,7 +316,7 @@ void DisplayApp::Refresh() {
if (msg == Messages::GoToAOD) {
lcd.LowPowerOn();
// Record idle entry time
- alwaysOnTickCount = 0;
+ alwaysOnFrameCount = 0;
alwaysOnStartTime = xTaskGetTickCount();
PushMessageToSystemTask(Pinetime::System::Messages::OnDisplayTaskAOD);
state = States::AOD;