Skip to content

Commit

Permalink
Improve sleep time calculation docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mark9064 committed Sep 22, 2024
1 parent 3ebc25d commit 7ced109
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
33 changes: 19 additions & 14 deletions src/displayapp/DisplayApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,33 +157,38 @@ 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

// Tick rate is multiple of 8
// 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;
}
Expand Down Expand Up @@ -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();
}
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/displayapp/DisplayApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ namespace Pinetime {
bool isDimmed = false;

TickType_t CalculateSleepTime();
TickType_t alwaysOnTickCount;
TickType_t alwaysOnFrameCount;
TickType_t alwaysOnStartTime;
// If this is to be changed, make sure the actual always on refresh rate is changed
// by configuring the LCD refresh timings
Expand Down

0 comments on commit 7ced109

Please sign in to comment.