From d349d919048c5d1dc9e2208a95d584fca1757e61 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 21 Feb 2020 10:08:08 -0800 Subject: [PATCH] Fix problem of transitions getting faster with each call of setTargetFPS On my app I noticed that each time I called setTargetFPS the transitions would become faster and faster, until finally they don't even take one frame. The problem was that the FP math for calculating changeRatio would (because of rounding err) keep shrinking the number of ticksPerFrame. This change instead computs ticksPerFrame/perTransition based on the requested display time, so error can't accumulate from a series of calls. (In my app I only bump up target FPS before each transition but then I lower it down again afterwards to save CPU) --- src/OLEDDisplayUi.cpp | 17 ++++++++--------- src/OLEDDisplayUi.h | 3 +++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/OLEDDisplayUi.cpp b/src/OLEDDisplayUi.cpp index 4d3b3de..6fcfafb 100644 --- a/src/OLEDDisplayUi.cpp +++ b/src/OLEDDisplayUi.cpp @@ -48,8 +48,6 @@ OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) { inactiveSymbol = ANIMATION_inactiveSymbol; frameAnimationDirection = SLIDE_RIGHT; lastTransitionDirection = 1; - ticksPerFrame = 151; // ~ 5000ms at 30 FPS - ticksPerTransition = 15; // ~ 500ms at 30 FPS frameCount = 0; nextFrameNumber = -1; overlayCount = 0; @@ -66,6 +64,8 @@ OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) { state.userData = NULL; shouldDrawIndicators = true; autoTransition = true; + setTimePerFrame(5000); + setTimePerTransition(500); } void OLEDDisplayUi::init() { @@ -73,13 +73,10 @@ void OLEDDisplayUi::init() { } void OLEDDisplayUi::setTargetFPS(uint8_t fps){ - float oldInterval = this->updateInterval; this->updateInterval = ((float) 1.0 / (float) fps) * 1000; - // Calculate new ticksPerFrame - float changeRatio = oldInterval / (float) this->updateInterval; - this->ticksPerFrame *= changeRatio; - this->ticksPerTransition *= changeRatio; + this->ticksPerFrame = timePerFrame / updateInterval; + this->ticksPerTransition = timePerTransition / updateInterval; } // -/------ Automatic controll ------\- @@ -99,10 +96,12 @@ void OLEDDisplayUi::setAutoTransitionBackwards(){ this->lastTransitionDirection = -1; } void OLEDDisplayUi::setTimePerFrame(uint16_t time){ - this->ticksPerFrame = (uint16_t) ( (float) time / (float) updateInterval); + this->timePerFrame = time; + this->ticksPerFrame = timePerFrame / updateInterval; } void OLEDDisplayUi::setTimePerTransition(uint16_t time){ - this->ticksPerTransition = (uint16_t) ( (float) time / (float) updateInterval); + this->timePerTransition = time; + this->ticksPerTransition = timePerTransition / updateInterval; } // -/------ Customize indicator position and style -------\- diff --git a/src/OLEDDisplayUi.h b/src/OLEDDisplayUi.h index c2dffba..9aa3f32 100644 --- a/src/OLEDDisplayUi.h +++ b/src/OLEDDisplayUi.h @@ -159,6 +159,9 @@ class OLEDDisplayUi { // Bookeeping for update uint16_t updateInterval = 33; + uint16_t timePerFrame; + uint16_t timePerTransition; + uint8_t getNextFrameNumber(); void drawIndicator(); void drawFrame();