From 499b9a56daf327513a48cc9c842290df436eda28 Mon Sep 17 00:00:00 2001 From: Fabrice Weinberg <Fabrice@weinberg.me> Date: Sun, 20 Dec 2015 18:27:43 +0100 Subject: [PATCH] Extract ui state into struct and pass it to the frames and overlays --- SSD1306Ui.cpp | 95 +++++++++++++++++++++++++-------------------------- SSD1306Ui.h | 38 ++++++++++++--------- 2 files changed, 68 insertions(+), 65 deletions(-) diff --git a/SSD1306Ui.cpp b/SSD1306Ui.cpp index 018e2d9..f301d27 100644 --- a/SSD1306Ui.cpp +++ b/SSD1306Ui.cpp @@ -22,10 +22,10 @@ void SSD1306Ui::setTargetFPS(byte fps){ // -/------ Automatic controll ------\- void SSD1306Ui::enableAutoTransition(){ - autoTransition = true; + this->autoTransition = true; } void SSD1306Ui::disableAutoTransition(){ - autoTransition = false; + this->autoTransition = false; } void SSD1306Ui::setAutoTransitionForwards(){ this->frameTransitionDirection = 1; @@ -54,22 +54,22 @@ void SSD1306Ui::setActiveSymbole(const char* symbole) { this->dirty = true; } void SSD1306Ui::setInactiveSymbole(const char* symbole) { - this->inactiveSymbole = symbole; + this->inactiveSymbole = symbole; this->dirty = true; } // -/----- Frame settings -----\- -void SSD1306Ui::setFrameAnimation(AnimationDirection dir) { +void SSD1306Ui::setFrameAnimation(AnimationDirection dir) { this->frameAnimationDirection = dir; } -void SSD1306Ui::setFrames(bool (*frameFunctions[])(SSD1306 *display, int x, int y), int frameCount) { +void SSD1306Ui::setFrames(bool (*frameFunctions[])(SSD1306 *display, SSD1306UiState* state, int x, int y), int frameCount) { this->frameCount = frameCount; this->frameFunctions = frameFunctions; } // -/----- Overlays ------\- -void SSD1306Ui::setOverlays(bool (*overlayFunctions[])(SSD1306 *display), int overlayCount){ +void SSD1306Ui::setOverlays(bool (*overlayFunctions[])(SSD1306 *display, SSD1306UiState* state), int overlayCount){ this->overlayCount = overlayCount; this->overlayFunctions = overlayFunctions; } @@ -77,67 +77,67 @@ void SSD1306Ui::setOverlays(bool (*overlayFunctions[])(SSD1306 *display), int ov // -/----- Manuel control -----\- void SSD1306Ui::nextFrame() { - this->frameState = IN_TRANSITION; - this->ticksSinceLastStateSwitch = 0; + this->state.frameState = IN_TRANSITION; + this->state.ticksSinceLastStateSwitch = 0; this->frameTransitionDirection = 1; } void SSD1306Ui::previousFrame() { - this->frameState = IN_TRANSITION; - this->ticksSinceLastStateSwitch = 0; + this->state.frameState = IN_TRANSITION; + this->state.ticksSinceLastStateSwitch = 0; this->frameTransitionDirection = -1; } // -/----- State information -----\- FrameState SSD1306Ui::getFrameState(){ - return this->frameState; + return this->state.frameState; } + int SSD1306Ui::getCurrentFrame(){ - return this->currentFrame; + return this->state.currentFrame; } int SSD1306Ui::update(){ - int timeBudget = this->updateInterval - (millis() - this->lastUpdate); + int timeBudget = this->updateInterval - (millis() - this->state.lastUpdate); if ( timeBudget <= 0) { - // Implement frame skipping to ensure time budget is keept - if (this->autoTransition && this->lastUpdate != 0) this->ticksSinceLastStateSwitch += abs(timeBudget) / this->updateInterval; - - this->lastUpdate = millis(); + if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil(-timeBudget / this->updateInterval); + + this->state.lastUpdate = millis(); this->tick(); - } + } return timeBudget; } void SSD1306Ui::tick() { - this->ticksSinceLastStateSwitch++; + this->state.ticksSinceLastStateSwitch++; - switch (this->frameState) { + switch (this->state.frameState) { case IN_TRANSITION: this->dirty = true; - if (this->ticksSinceLastStateSwitch >= this->ticksPerTransition){ - this->frameState = FIXED; - this->currentFrame = getNextFrameNumber(); - this->ticksSinceLastStateSwitch = 0; + if (this->state.ticksSinceLastStateSwitch >= this->ticksPerTransition){ + this->state.frameState = FIXED; + this->state.currentFrame = getNextFrameNumber(); + this->state.ticksSinceLastStateSwitch = 0; } break; case FIXED: - if (this->ticksSinceLastStateSwitch >= this->ticksPerFrame){ + if (this->state.ticksSinceLastStateSwitch >= this->ticksPerFrame){ if (this->autoTransition){ - this->frameState = IN_TRANSITION; + this->state.frameState = IN_TRANSITION; this->dirty = true; } - this->ticksSinceLastStateSwitch = 0; + this->state.ticksSinceLastStateSwitch = 0; } break; } - + if (this->dirty) { this->dirty = false; this->display->clear(); - this->drawIndicator(); + this->drawIndicator(); this->drawFrame(); this->drawOverlays(); this->display->display(); @@ -145,9 +145,9 @@ void SSD1306Ui::tick() { } void SSD1306Ui::drawFrame(){ - switch (this->frameState){ + switch (this->state.frameState){ case IN_TRANSITION: { - float progress = (float) this->ticksSinceLastStateSwitch / (float) this->ticksPerTransition; + float progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition; int x, y, x1, y1; switch(this->frameAnimationDirection){ case SLIDE_LEFT: @@ -180,36 +180,36 @@ void SSD1306Ui::drawFrame(){ int dir = frameTransitionDirection >= 0 ? 1 : -1; x *= dir; y *= dir; x1 *= dir; y1 *= dir; - this->dirty |= (*this->frameFunctions[this->currentFrame])(this->display, x, y); - this->dirty |= (*this->frameFunctions[this->getNextFrameNumber()])(this->display, x1, y1); + this->dirty |= (*this->frameFunctions[this->state.currentFrame])(this->display, &this->state, x, y); + this->dirty |= (*this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1); break; } case FIXED: - this->dirty |= (*this->frameFunctions[this->currentFrame])(this->display, 0, 0); + this->dirty |= (*this->frameFunctions[this->state.currentFrame])(this->display, &this->state, 0, 0); break; } } void SSD1306Ui::drawIndicator() { - byte posOfCurrentFrame; - + byte posOfCurrentFrame; + switch (this->indicatorDirection){ case LEFT_RIGHT: - posOfCurrentFrame = this->currentFrame; + posOfCurrentFrame = this->state.currentFrame; break; case RIGHT_LEFT: - posOfCurrentFrame = (this->frameCount - 1) - this->currentFrame; + posOfCurrentFrame = (this->frameCount - 1) - this->state.currentFrame; break; } - + for (byte i = 0; i < this->frameCount; i++) { - + const char *xbm; - + if (posOfCurrentFrame == i) { xbm = this->activeSymbole; } else { - xbm = this->inactiveSymbole; + xbm = this->inactiveSymbole; } int x,y; @@ -231,24 +231,23 @@ void SSD1306Ui::drawIndicator() { y = 32 - (12 * frameCount / 2) + 12 * i; break; } - + this->display->drawXbm(x, y, 8, 8, xbm); - } + } } void SSD1306Ui::drawOverlays() { for (int i=0;i<this->overlayCount;i++){ - this->dirty |= (*this->overlayFunctions[i])(this->display); + this->dirty |= (*this->overlayFunctions[i])(this->display, &this->state); } } int SSD1306Ui::getNextFrameNumber(){ - int nextFrame = (this->currentFrame + this->frameTransitionDirection) % this->frameCount; + int nextFrame = (this->state.currentFrame + this->frameTransitionDirection) % this->frameCount; if (nextFrame < 0){ nextFrame = this->frameCount + nextFrame; } - return nextFrame; + return nextFrame; } - diff --git a/SSD1306Ui.h b/SSD1306Ui.h index e43f898..6ffad32 100644 --- a/SSD1306Ui.h +++ b/SSD1306Ui.h @@ -60,6 +60,16 @@ const char ANIMATION_inactiveSymbole[] PROGMEM = { 0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00 }; + +// Structure of the UiState +struct SSD1306UiState { + int lastUpdate = 0; + int ticksSinceLastStateSwitch = 0; + + FrameState frameState = FIXED; + int currentFrame = 0; +}; + class SSD1306Ui { private: SSD1306 *display; @@ -76,29 +86,26 @@ class SSD1306Ui { // Values for the Frames AnimationDirection frameAnimationDirection = SLIDE_RIGHT; - FrameState frameState = FIXED; int frameTransitionDirection = 1; - int ticksPerFrame = 313; // ~ 5000ms at 60 FPS - int ticksPerTransition = 32; // ~ 500ms at 60 FPS - int ticksSinceLastStateSwitch = 0; - int currentFrame = 0; + int ticksPerFrame = 151; // ~ 5000ms at 30 FPS + int ticksPerTransition = 15; // ~ 500ms at 30 FPS bool autoTransition = true; - bool (**frameFunctions)(SSD1306 *display, int x, int y); + bool (**frameFunctions)(SSD1306 *display, SSD1306UiState* state, int x, int y); int frameCount = 0; // Values for Overlays - bool (**overlayFunctions)(SSD1306 *display); + bool (**overlayFunctions)(SSD1306 *display, SSD1306UiState* state); int overlayCount = 0; + // UI State + SSD1306UiState state; // Bookeeping for update - int updateInterval = 16; - unsigned long lastUpdate = 0; - + int updateInterval = 33; int getNextFrameNumber(); void drawIndicator(); @@ -147,7 +154,7 @@ class SSD1306Ui { */ void setTimePerTransition(int time); - // Customize Indicator Position and style + // Customize indicator position and style /** * Set the position of the indicator bar. */ @@ -178,25 +185,22 @@ class SSD1306Ui { /** * Add frame drawing functions */ - void setFrames(bool (*frameFunctions[])(SSD1306 *display, int x, int y), int frameCount); + void setFrames(bool (*frameFunctions[])(SSD1306 *display, SSD1306UiState* state, int x, int y), int frameCount); // Overlay /** * Add overlays drawing functions that are draw independent of the Frames */ - void setOverlays(bool (*overlayFunctions[])(SSD1306 *display), int overlayCount); + void setOverlays(bool (*overlayFunctions[])(SSD1306 *display, SSD1306UiState* state), int overlayCount); // Manuell Controll void nextFrame(); void previousFrame(); // State Info - FrameState getFrameState(); - int getCurrentFrame(); - + FrameState getUiState(); int update(); }; - -- GitLab