ThingPulse OLED SSD1306

Dependents:   Turtle_RadioShuttle

Committer:
Helmut Tschemernjak
Date:
Thu Jun 06 09:29:02 2019 +0200
Revision:
3:99a409809366
Parent:
1:9270c15c6aea
Updated with latest version for github

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Helmut64 0:56dd5df33ab4 1 /**
Helmut64 0:56dd5df33ab4 2 * The MIT License (MIT)
Helmut64 0:56dd5df33ab4 3 *
Helmut64 0:56dd5df33ab4 4 * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
Helmut64 0:56dd5df33ab4 5 * Copyright (c) 2018 by Fabrice Weinberg
Helmut64 0:56dd5df33ab4 6 * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de
Helmut64 0:56dd5df33ab4 7 *
Helmut64 0:56dd5df33ab4 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
Helmut64 0:56dd5df33ab4 9 * of this software and associated documentation files (the "Software"), to deal
Helmut64 0:56dd5df33ab4 10 * in the Software without restriction, including without limitation the rights
Helmut64 0:56dd5df33ab4 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Helmut64 0:56dd5df33ab4 12 * copies of the Software, and to permit persons to whom the Software is
Helmut64 0:56dd5df33ab4 13 * furnished to do so, subject to the following conditions:
Helmut64 0:56dd5df33ab4 14 *
Helmut64 0:56dd5df33ab4 15 * The above copyright notice and this permission notice shall be included in all
Helmut64 0:56dd5df33ab4 16 * copies or substantial portions of the Software.
Helmut64 0:56dd5df33ab4 17 *
Helmut64 0:56dd5df33ab4 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Helmut64 0:56dd5df33ab4 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Helmut64 0:56dd5df33ab4 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Helmut64 0:56dd5df33ab4 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Helmut64 0:56dd5df33ab4 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Helmut64 0:56dd5df33ab4 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Helmut64 0:56dd5df33ab4 24 * SOFTWARE.
Helmut64 0:56dd5df33ab4 25 *
Helmut64 0:56dd5df33ab4 26 * ThingPulse invests considerable time and money to develop these open source libraries.
Helmut64 0:56dd5df33ab4 27 * Please support us by buying our products (and not the clones) from
Helmut64 0:56dd5df33ab4 28 * https://thingpulse.com
Helmut64 0:56dd5df33ab4 29 *
Helmut64 0:56dd5df33ab4 30 */
Helmut64 0:56dd5df33ab4 31
Helmut64 0:56dd5df33ab4 32 #include "OLEDDisplayUi.h"
Helmut64 0:56dd5df33ab4 33
Helmut64 0:56dd5df33ab4 34 void LoadingDrawDefault(OLEDDisplay *display, LoadingStage* stage, uint8_t progress) {
Helmut64 0:56dd5df33ab4 35 display->setTextAlignment(TEXT_ALIGN_CENTER);
Helmut64 0:56dd5df33ab4 36 display->setFont(ArialMT_Plain_10);
Helmut64 0:56dd5df33ab4 37 display->drawString(64, 18, stage->process);
Helmut64 0:56dd5df33ab4 38 display->drawProgressBar(4, 32, 120, 8, progress);
Helmut64 0:56dd5df33ab4 39 };
Helmut64 0:56dd5df33ab4 40
Helmut64 0:56dd5df33ab4 41
Helmut64 0:56dd5df33ab4 42 OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) {
Helmut64 0:56dd5df33ab4 43 this->display = display;
Helmut64 0:56dd5df33ab4 44
Helmut64 0:56dd5df33ab4 45 indicatorPosition = BOTTOM;
Helmut64 0:56dd5df33ab4 46 indicatorDirection = LEFT_RIGHT;
Helmut64 0:56dd5df33ab4 47 activeSymbol = ANIMATION_activeSymbol;
Helmut64 0:56dd5df33ab4 48 inactiveSymbol = ANIMATION_inactiveSymbol;
Helmut64 0:56dd5df33ab4 49 frameAnimationDirection = SLIDE_RIGHT;
Helmut64 0:56dd5df33ab4 50 lastTransitionDirection = 1;
Helmut64 0:56dd5df33ab4 51 ticksPerFrame = 151; // ~ 5000ms at 30 FPS
Helmut64 0:56dd5df33ab4 52 ticksPerTransition = 15; // ~ 500ms at 30 FPS
Helmut64 0:56dd5df33ab4 53 frameCount = 0;
Helmut64 0:56dd5df33ab4 54 nextFrameNumber = -1;
Helmut64 0:56dd5df33ab4 55 overlayCount = 0;
Helmut64 0:56dd5df33ab4 56 indicatorDrawState = 1;
Helmut64 0:56dd5df33ab4 57 loadingDrawFunction = LoadingDrawDefault;
Helmut64 0:56dd5df33ab4 58 updateInterval = 33;
Helmut64 0:56dd5df33ab4 59 state.lastUpdate = 0;
Helmut64 0:56dd5df33ab4 60 state.ticksSinceLastStateSwitch = 0;
Helmut64 0:56dd5df33ab4 61 state.frameState = FIXED;
Helmut64 0:56dd5df33ab4 62 state.currentFrame = 0;
Helmut64 0:56dd5df33ab4 63 state.frameTransitionDirection = 1;
Helmut64 0:56dd5df33ab4 64 state.isIndicatorDrawen = true;
Helmut64 0:56dd5df33ab4 65 state.manuelControll = false;
Helmut64 0:56dd5df33ab4 66 state.userData = NULL;
Helmut64 0:56dd5df33ab4 67 shouldDrawIndicators = true;
Helmut64 0:56dd5df33ab4 68 autoTransition = true;
Helmut64 0:56dd5df33ab4 69 }
Helmut64 0:56dd5df33ab4 70
Helmut64 0:56dd5df33ab4 71 void OLEDDisplayUi::init() {
Helmut64 0:56dd5df33ab4 72 this->display->init();
Helmut64 0:56dd5df33ab4 73 }
Helmut64 0:56dd5df33ab4 74
Helmut64 0:56dd5df33ab4 75 void OLEDDisplayUi::setTargetFPS(uint8_t fps){
Helmut64 0:56dd5df33ab4 76 float oldInterval = this->updateInterval;
Helmut64 0:56dd5df33ab4 77 this->updateInterval = ((float) 1.0 / (float) fps) * 1000;
Helmut64 0:56dd5df33ab4 78
Helmut64 0:56dd5df33ab4 79 // Calculate new ticksPerFrame
Helmut64 0:56dd5df33ab4 80 float changeRatio = oldInterval / (float) this->updateInterval;
Helmut64 0:56dd5df33ab4 81 this->ticksPerFrame *= changeRatio;
Helmut64 0:56dd5df33ab4 82 this->ticksPerTransition *= changeRatio;
Helmut64 0:56dd5df33ab4 83 }
Helmut64 0:56dd5df33ab4 84
Helmut64 0:56dd5df33ab4 85 // -/------ Automatic controll ------\-
Helmut64 0:56dd5df33ab4 86
Helmut64 0:56dd5df33ab4 87 void OLEDDisplayUi::enableAutoTransition(){
Helmut64 0:56dd5df33ab4 88 this->autoTransition = true;
Helmut64 0:56dd5df33ab4 89 }
Helmut64 0:56dd5df33ab4 90 void OLEDDisplayUi::disableAutoTransition(){
Helmut64 0:56dd5df33ab4 91 this->autoTransition = false;
Helmut64 0:56dd5df33ab4 92 }
Helmut64 0:56dd5df33ab4 93 void OLEDDisplayUi::setAutoTransitionForwards(){
Helmut64 0:56dd5df33ab4 94 this->state.frameTransitionDirection = 1;
Helmut64 0:56dd5df33ab4 95 this->lastTransitionDirection = 1;
Helmut64 0:56dd5df33ab4 96 }
Helmut64 0:56dd5df33ab4 97 void OLEDDisplayUi::setAutoTransitionBackwards(){
Helmut64 0:56dd5df33ab4 98 this->state.frameTransitionDirection = -1;
Helmut64 0:56dd5df33ab4 99 this->lastTransitionDirection = -1;
Helmut64 0:56dd5df33ab4 100 }
Helmut64 0:56dd5df33ab4 101 void OLEDDisplayUi::setTimePerFrame(uint16_t time){
Helmut64 0:56dd5df33ab4 102 this->ticksPerFrame = (uint16_t) ( (float) time / (float) updateInterval);
Helmut64 0:56dd5df33ab4 103 }
Helmut64 0:56dd5df33ab4 104 void OLEDDisplayUi::setTimePerTransition(uint16_t time){
Helmut64 0:56dd5df33ab4 105 this->ticksPerTransition = (uint16_t) ( (float) time / (float) updateInterval);
Helmut64 0:56dd5df33ab4 106 }
Helmut64 0:56dd5df33ab4 107
Helmut64 0:56dd5df33ab4 108 // -/------ Customize indicator position and style -------\-
Helmut64 0:56dd5df33ab4 109 void OLEDDisplayUi::enableIndicator(){
Helmut64 0:56dd5df33ab4 110 this->state.isIndicatorDrawen = true;
Helmut64 0:56dd5df33ab4 111 }
Helmut64 0:56dd5df33ab4 112
Helmut64 0:56dd5df33ab4 113 void OLEDDisplayUi::disableIndicator(){
Helmut64 0:56dd5df33ab4 114 this->state.isIndicatorDrawen = false;
Helmut64 0:56dd5df33ab4 115 }
Helmut64 0:56dd5df33ab4 116
Helmut64 0:56dd5df33ab4 117 void OLEDDisplayUi::enableAllIndicators(){
Helmut64 0:56dd5df33ab4 118 this->shouldDrawIndicators = true;
Helmut64 0:56dd5df33ab4 119 }
Helmut64 0:56dd5df33ab4 120
Helmut64 0:56dd5df33ab4 121 void OLEDDisplayUi::disableAllIndicators(){
Helmut64 0:56dd5df33ab4 122 this->shouldDrawIndicators = false;
Helmut64 0:56dd5df33ab4 123 }
Helmut64 0:56dd5df33ab4 124
Helmut64 0:56dd5df33ab4 125 void OLEDDisplayUi::setIndicatorPosition(IndicatorPosition pos) {
Helmut64 0:56dd5df33ab4 126 this->indicatorPosition = pos;
Helmut64 0:56dd5df33ab4 127 }
Helmut64 0:56dd5df33ab4 128 void OLEDDisplayUi::setIndicatorDirection(IndicatorDirection dir) {
Helmut64 0:56dd5df33ab4 129 this->indicatorDirection = dir;
Helmut64 0:56dd5df33ab4 130 }
Helmut64 0:56dd5df33ab4 131 void OLEDDisplayUi::setActiveSymbol(const uint8_t* symbol) {
Helmut64 0:56dd5df33ab4 132 this->activeSymbol = symbol;
Helmut64 0:56dd5df33ab4 133 }
Helmut64 0:56dd5df33ab4 134 void OLEDDisplayUi::setInactiveSymbol(const uint8_t* symbol) {
Helmut64 0:56dd5df33ab4 135 this->inactiveSymbol = symbol;
Helmut64 0:56dd5df33ab4 136 }
Helmut64 0:56dd5df33ab4 137
Helmut64 0:56dd5df33ab4 138
Helmut64 0:56dd5df33ab4 139 // -/----- Frame settings -----\-
Helmut64 0:56dd5df33ab4 140 void OLEDDisplayUi::setFrameAnimation(AnimationDirection dir) {
Helmut64 0:56dd5df33ab4 141 this->frameAnimationDirection = dir;
Helmut64 0:56dd5df33ab4 142 }
Helmut64 0:56dd5df33ab4 143 void OLEDDisplayUi::setFrames(FrameCallback* frameFunctions, uint8_t frameCount) {
Helmut64 0:56dd5df33ab4 144 this->frameFunctions = frameFunctions;
Helmut64 0:56dd5df33ab4 145 this->frameCount = frameCount;
Helmut64 0:56dd5df33ab4 146 this->resetState();
Helmut64 0:56dd5df33ab4 147 }
Helmut64 0:56dd5df33ab4 148
Helmut64 0:56dd5df33ab4 149 // -/----- Overlays ------\-
Helmut64 0:56dd5df33ab4 150 void OLEDDisplayUi::setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount){
Helmut64 0:56dd5df33ab4 151 this->overlayFunctions = overlayFunctions;
Helmut64 0:56dd5df33ab4 152 this->overlayCount = overlayCount;
Helmut64 0:56dd5df33ab4 153 }
Helmut64 0:56dd5df33ab4 154
Helmut64 0:56dd5df33ab4 155 // -/----- Loading Process -----\-
Helmut64 0:56dd5df33ab4 156
Helmut64 0:56dd5df33ab4 157 void OLEDDisplayUi::setLoadingDrawFunction(LoadingDrawFunction loadingDrawFunction) {
Helmut64 0:56dd5df33ab4 158 this->loadingDrawFunction = loadingDrawFunction;
Helmut64 0:56dd5df33ab4 159 }
Helmut64 0:56dd5df33ab4 160
Helmut64 0:56dd5df33ab4 161 void OLEDDisplayUi::runLoadingProcess(LoadingStage* stages, uint8_t stagesCount) {
Helmut64 0:56dd5df33ab4 162 uint8_t progress = 0;
Helmut64 0:56dd5df33ab4 163 uint8_t increment = 100 / stagesCount;
Helmut64 0:56dd5df33ab4 164
Helmut64 0:56dd5df33ab4 165 for (uint8_t i = 0; i < stagesCount; i++) {
Helmut64 0:56dd5df33ab4 166 display->clear();
Helmut64 0:56dd5df33ab4 167 this->loadingDrawFunction(this->display, &stages[i], progress);
Helmut64 0:56dd5df33ab4 168 display->display();
Helmut64 0:56dd5df33ab4 169
Helmut64 0:56dd5df33ab4 170 stages[i].callback();
Helmut64 0:56dd5df33ab4 171
Helmut64 0:56dd5df33ab4 172 progress += increment;
Helmut64 0:56dd5df33ab4 173 yield();
Helmut64 0:56dd5df33ab4 174 }
Helmut64 0:56dd5df33ab4 175
Helmut64 0:56dd5df33ab4 176 display->clear();
Helmut64 0:56dd5df33ab4 177 this->loadingDrawFunction(this->display, &stages[stagesCount-1], progress);
Helmut64 0:56dd5df33ab4 178 display->display();
Helmut64 0:56dd5df33ab4 179
Helmut64 0:56dd5df33ab4 180 delay(150);
Helmut64 0:56dd5df33ab4 181 }
Helmut64 0:56dd5df33ab4 182
Helmut64 0:56dd5df33ab4 183 // -/----- Manuel control -----\-
Helmut64 0:56dd5df33ab4 184 void OLEDDisplayUi::nextFrame() {
Helmut64 0:56dd5df33ab4 185 if (this->state.frameState != IN_TRANSITION) {
Helmut64 0:56dd5df33ab4 186 this->state.manuelControll = true;
Helmut64 0:56dd5df33ab4 187 this->state.frameState = IN_TRANSITION;
Helmut64 0:56dd5df33ab4 188 this->state.ticksSinceLastStateSwitch = 0;
Helmut64 0:56dd5df33ab4 189 this->lastTransitionDirection = this->state.frameTransitionDirection;
Helmut64 0:56dd5df33ab4 190 this->state.frameTransitionDirection = 1;
Helmut64 0:56dd5df33ab4 191 }
Helmut64 0:56dd5df33ab4 192 }
Helmut64 0:56dd5df33ab4 193 void OLEDDisplayUi::previousFrame() {
Helmut64 0:56dd5df33ab4 194 if (this->state.frameState != IN_TRANSITION) {
Helmut64 0:56dd5df33ab4 195 this->state.manuelControll = true;
Helmut64 0:56dd5df33ab4 196 this->state.frameState = IN_TRANSITION;
Helmut64 0:56dd5df33ab4 197 this->state.ticksSinceLastStateSwitch = 0;
Helmut64 0:56dd5df33ab4 198 this->lastTransitionDirection = this->state.frameTransitionDirection;
Helmut64 0:56dd5df33ab4 199 this->state.frameTransitionDirection = -1;
Helmut64 0:56dd5df33ab4 200 }
Helmut64 0:56dd5df33ab4 201 }
Helmut64 0:56dd5df33ab4 202
Helmut64 0:56dd5df33ab4 203 void OLEDDisplayUi::switchToFrame(uint8_t frame) {
Helmut64 0:56dd5df33ab4 204 if (frame >= this->frameCount) return;
Helmut64 0:56dd5df33ab4 205 this->state.ticksSinceLastStateSwitch = 0;
Helmut64 0:56dd5df33ab4 206 if (frame == this->state.currentFrame) return;
Helmut64 0:56dd5df33ab4 207 this->state.frameState = FIXED;
Helmut64 0:56dd5df33ab4 208 this->state.currentFrame = frame;
Helmut64 0:56dd5df33ab4 209 this->state.isIndicatorDrawen = true;
Helmut64 0:56dd5df33ab4 210 }
Helmut64 0:56dd5df33ab4 211
Helmut64 0:56dd5df33ab4 212 void OLEDDisplayUi::transitionToFrame(uint8_t frame) {
Helmut64 0:56dd5df33ab4 213 if (frame >= this->frameCount) return;
Helmut64 0:56dd5df33ab4 214 this->state.ticksSinceLastStateSwitch = 0;
Helmut64 0:56dd5df33ab4 215 if (frame == this->state.currentFrame) return;
Helmut64 0:56dd5df33ab4 216 this->nextFrameNumber = frame;
Helmut64 0:56dd5df33ab4 217 this->lastTransitionDirection = this->state.frameTransitionDirection;
Helmut64 0:56dd5df33ab4 218 this->state.manuelControll = true;
Helmut64 0:56dd5df33ab4 219 this->state.frameState = IN_TRANSITION;
Helmut64 0:56dd5df33ab4 220 this->state.frameTransitionDirection = frame < this->state.currentFrame ? -1 : 1;
Helmut64 0:56dd5df33ab4 221 }
Helmut64 0:56dd5df33ab4 222
Helmut64 0:56dd5df33ab4 223
Helmut64 0:56dd5df33ab4 224 // -/----- State information -----\-
Helmut64 0:56dd5df33ab4 225 OLEDDisplayUiState* OLEDDisplayUi::getUiState(){
Helmut64 0:56dd5df33ab4 226 return &this->state;
Helmut64 0:56dd5df33ab4 227 }
Helmut64 0:56dd5df33ab4 228
Helmut64 0:56dd5df33ab4 229
Helmut64 0:56dd5df33ab4 230 int8_t OLEDDisplayUi::update(){
Helmut64 0:56dd5df33ab4 231 #ifdef ARDUINO
Helmut64 0:56dd5df33ab4 232 unsigned long frameStart = millis();
Helmut64 0:56dd5df33ab4 233 #elif __MBED__
Helmut64 0:56dd5df33ab4 234 Timer t;
Helmut64 0:56dd5df33ab4 235 t.start();
Helmut64 0:56dd5df33ab4 236 unsigned long frameStart = t.read_ms();
Helmut64 0:56dd5df33ab4 237 #else
Helmut64 0:56dd5df33ab4 238 #error "Unkown operating system"
Helmut64 0:56dd5df33ab4 239 #endif
Helmut64 0:56dd5df33ab4 240 int8_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate);
Helmut64 0:56dd5df33ab4 241 if ( timeBudget <= 0) {
Helmut64 0:56dd5df33ab4 242 // Implement frame skipping to ensure time budget is keept
Helmut64 0:56dd5df33ab4 243 if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil((double)-timeBudget / (double)this->updateInterval);
Helmut64 0:56dd5df33ab4 244
Helmut64 0:56dd5df33ab4 245 this->state.lastUpdate = frameStart;
Helmut64 0:56dd5df33ab4 246 this->tick();
Helmut64 0:56dd5df33ab4 247 }
Helmut64 0:56dd5df33ab4 248 #ifdef ARDUINO
Helmut64 0:56dd5df33ab4 249 return this->updateInterval - (millis() - frameStart);
Helmut64 0:56dd5df33ab4 250 #elif __MBED__
Helmut64 0:56dd5df33ab4 251 return this->updateInterval - (t.read_ms() - frameStart);
Helmut64 0:56dd5df33ab4 252 #else
Helmut64 0:56dd5df33ab4 253 #error "Unkown operating system"
Helmut64 0:56dd5df33ab4 254 #endif
Helmut64 0:56dd5df33ab4 255 }
Helmut64 0:56dd5df33ab4 256
Helmut64 0:56dd5df33ab4 257
Helmut64 0:56dd5df33ab4 258 void OLEDDisplayUi::tick() {
Helmut64 0:56dd5df33ab4 259 this->state.ticksSinceLastStateSwitch++;
Helmut64 0:56dd5df33ab4 260
Helmut64 0:56dd5df33ab4 261 switch (this->state.frameState) {
Helmut64 0:56dd5df33ab4 262 case IN_TRANSITION:
Helmut64 0:56dd5df33ab4 263 if (this->state.ticksSinceLastStateSwitch >= this->ticksPerTransition){
Helmut64 0:56dd5df33ab4 264 this->state.frameState = FIXED;
Helmut64 0:56dd5df33ab4 265 this->state.currentFrame = getNextFrameNumber();
Helmut64 0:56dd5df33ab4 266 this->state.ticksSinceLastStateSwitch = 0;
Helmut64 0:56dd5df33ab4 267 this->nextFrameNumber = -1;
Helmut64 0:56dd5df33ab4 268 }
Helmut64 0:56dd5df33ab4 269 break;
Helmut64 0:56dd5df33ab4 270 case FIXED:
Helmut64 0:56dd5df33ab4 271 // Revert manuelControll
Helmut64 0:56dd5df33ab4 272 if (this->state.manuelControll) {
Helmut64 0:56dd5df33ab4 273 this->state.frameTransitionDirection = this->lastTransitionDirection;
Helmut64 0:56dd5df33ab4 274 this->state.manuelControll = false;
Helmut64 0:56dd5df33ab4 275 }
Helmut64 0:56dd5df33ab4 276 if (this->state.ticksSinceLastStateSwitch >= this->ticksPerFrame){
Helmut64 0:56dd5df33ab4 277 if (this->autoTransition){
Helmut64 0:56dd5df33ab4 278 this->state.frameState = IN_TRANSITION;
Helmut64 0:56dd5df33ab4 279 }
Helmut64 0:56dd5df33ab4 280 this->state.ticksSinceLastStateSwitch = 0;
Helmut64 0:56dd5df33ab4 281 }
Helmut64 0:56dd5df33ab4 282 break;
Helmut64 0:56dd5df33ab4 283 }
Helmut64 0:56dd5df33ab4 284
Helmut64 0:56dd5df33ab4 285 this->display->clear();
Helmut64 0:56dd5df33ab4 286 this->drawFrame();
Helmut64 0:56dd5df33ab4 287 if (shouldDrawIndicators) {
Helmut64 0:56dd5df33ab4 288 this->drawIndicator();
Helmut64 0:56dd5df33ab4 289 }
Helmut64 0:56dd5df33ab4 290 this->drawOverlays();
Helmut64 0:56dd5df33ab4 291 this->display->display();
Helmut64 0:56dd5df33ab4 292 }
Helmut64 0:56dd5df33ab4 293
Helmut64 0:56dd5df33ab4 294 void OLEDDisplayUi::resetState() {
Helmut64 0:56dd5df33ab4 295 this->state.lastUpdate = 0;
Helmut64 0:56dd5df33ab4 296 this->state.ticksSinceLastStateSwitch = 0;
Helmut64 0:56dd5df33ab4 297 this->state.frameState = FIXED;
Helmut64 0:56dd5df33ab4 298 this->state.currentFrame = 0;
Helmut64 0:56dd5df33ab4 299 this->state.isIndicatorDrawen = true;
Helmut64 0:56dd5df33ab4 300 }
Helmut64 0:56dd5df33ab4 301
Helmut64 0:56dd5df33ab4 302 void OLEDDisplayUi::drawFrame(){
Helmut64 0:56dd5df33ab4 303 switch (this->state.frameState){
Helmut64 0:56dd5df33ab4 304 case IN_TRANSITION: {
Helmut64 0:56dd5df33ab4 305 float progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition;
Helmut64 0:56dd5df33ab4 306 int16_t x = 0, y = 0, x1 = 0, y1 = 0;
Helmut64 0:56dd5df33ab4 307 switch(this->frameAnimationDirection){
Helmut64 0:56dd5df33ab4 308 case SLIDE_LEFT:
Helmut64 0:56dd5df33ab4 309 x = -this->display->width() * progress;
Helmut64 0:56dd5df33ab4 310 y = 0;
Helmut64 0:56dd5df33ab4 311 x1 = x + this->display->width();
Helmut64 0:56dd5df33ab4 312 y1 = 0;
Helmut64 0:56dd5df33ab4 313 break;
Helmut64 0:56dd5df33ab4 314 case SLIDE_RIGHT:
Helmut64 0:56dd5df33ab4 315 x = this->display->width() * progress;
Helmut64 0:56dd5df33ab4 316 y = 0;
Helmut64 0:56dd5df33ab4 317 x1 = x - this->display->width();
Helmut64 0:56dd5df33ab4 318 y1 = 0;
Helmut64 0:56dd5df33ab4 319 break;
Helmut64 0:56dd5df33ab4 320 case SLIDE_UP:
Helmut64 0:56dd5df33ab4 321 x = 0;
Helmut64 0:56dd5df33ab4 322 y = -this->display->height() * progress;
Helmut64 0:56dd5df33ab4 323 x1 = 0;
Helmut64 0:56dd5df33ab4 324 y1 = y + this->display->height();
Helmut64 0:56dd5df33ab4 325 break;
Helmut64 0:56dd5df33ab4 326 case SLIDE_DOWN:
Helmut64 0:56dd5df33ab4 327 default:
Helmut64 0:56dd5df33ab4 328 x = 0;
Helmut64 0:56dd5df33ab4 329 y = this->display->height() * progress;
Helmut64 0:56dd5df33ab4 330 x1 = 0;
Helmut64 0:56dd5df33ab4 331 y1 = y - this->display->height();
Helmut64 0:56dd5df33ab4 332 break;
Helmut64 0:56dd5df33ab4 333 }
Helmut64 0:56dd5df33ab4 334
Helmut64 0:56dd5df33ab4 335 // Invert animation if direction is reversed.
Helmut64 0:56dd5df33ab4 336 int8_t dir = this->state.frameTransitionDirection >= 0 ? 1 : -1;
Helmut64 0:56dd5df33ab4 337 x *= dir; y *= dir; x1 *= dir; y1 *= dir;
Helmut64 0:56dd5df33ab4 338
Helmut64 0:56dd5df33ab4 339 bool drawenCurrentFrame;
Helmut64 0:56dd5df33ab4 340
Helmut64 0:56dd5df33ab4 341
Helmut64 0:56dd5df33ab4 342 // Prope each frameFunction for the indicator Drawen state
Helmut64 0:56dd5df33ab4 343 this->enableIndicator();
Helmut64 0:56dd5df33ab4 344 (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, x, y);
Helmut64 0:56dd5df33ab4 345 drawenCurrentFrame = this->state.isIndicatorDrawen;
Helmut64 0:56dd5df33ab4 346
Helmut64 0:56dd5df33ab4 347 this->enableIndicator();
Helmut64 0:56dd5df33ab4 348 (this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1);
Helmut64 0:56dd5df33ab4 349
Helmut64 0:56dd5df33ab4 350 // Build up the indicatorDrawState
Helmut64 0:56dd5df33ab4 351 if (drawenCurrentFrame && !this->state.isIndicatorDrawen) {
Helmut64 0:56dd5df33ab4 352 // Drawen now but not next
Helmut64 0:56dd5df33ab4 353 this->indicatorDrawState = 2;
Helmut64 0:56dd5df33ab4 354 } else if (!drawenCurrentFrame && this->state.isIndicatorDrawen) {
Helmut64 0:56dd5df33ab4 355 // Not drawen now but next
Helmut64 0:56dd5df33ab4 356 this->indicatorDrawState = 1;
Helmut64 0:56dd5df33ab4 357 } else if (!drawenCurrentFrame && !this->state.isIndicatorDrawen) {
Helmut64 0:56dd5df33ab4 358 // Not drawen in both frames
Helmut64 0:56dd5df33ab4 359 this->indicatorDrawState = 3;
Helmut64 0:56dd5df33ab4 360 }
Helmut64 0:56dd5df33ab4 361
Helmut64 0:56dd5df33ab4 362 // If the indicator isn't draw in the current frame
Helmut64 0:56dd5df33ab4 363 // reflect it in state.isIndicatorDrawen
Helmut64 0:56dd5df33ab4 364 if (!drawenCurrentFrame) this->state.isIndicatorDrawen = false;
Helmut64 0:56dd5df33ab4 365
Helmut64 0:56dd5df33ab4 366 break;
Helmut64 0:56dd5df33ab4 367 }
Helmut64 0:56dd5df33ab4 368 case FIXED:
Helmut64 0:56dd5df33ab4 369 // Always assume that the indicator is drawn!
Helmut64 0:56dd5df33ab4 370 // And set indicatorDrawState to "not known yet"
Helmut64 0:56dd5df33ab4 371 this->indicatorDrawState = 0;
Helmut64 0:56dd5df33ab4 372 this->enableIndicator();
Helmut64 0:56dd5df33ab4 373 (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, 0, 0);
Helmut64 0:56dd5df33ab4 374 break;
Helmut64 0:56dd5df33ab4 375 }
Helmut64 0:56dd5df33ab4 376 }
Helmut64 0:56dd5df33ab4 377
Helmut64 0:56dd5df33ab4 378 void OLEDDisplayUi::drawIndicator() {
Helmut64 0:56dd5df33ab4 379
Helmut64 0:56dd5df33ab4 380 // Only draw if the indicator is invisible
Helmut64 0:56dd5df33ab4 381 // for both frames or
Helmut64 0:56dd5df33ab4 382 // the indiactor is shown and we are IN_TRANSITION
Helmut64 0:56dd5df33ab4 383 if (this->indicatorDrawState == 3 || (!this->state.isIndicatorDrawen && this->state.frameState != IN_TRANSITION)) {
Helmut64 0:56dd5df33ab4 384 return;
Helmut64 0:56dd5df33ab4 385 }
Helmut64 0:56dd5df33ab4 386
Helmut64 0:56dd5df33ab4 387 uint8_t posOfHighlightFrame = 0;
Helmut64 0:56dd5df33ab4 388 float indicatorFadeProgress = 0;
Helmut64 0:56dd5df33ab4 389
Helmut64 0:56dd5df33ab4 390 // if the indicator needs to be slided in we want to
Helmut64 0:56dd5df33ab4 391 // highlight the next frame in the transition
Helmut64 0:56dd5df33ab4 392 uint8_t frameToHighlight = this->indicatorDrawState == 1 ? this->getNextFrameNumber() : this->state.currentFrame;
Helmut64 0:56dd5df33ab4 393
Helmut64 0:56dd5df33ab4 394 // Calculate the frame that needs to be highlighted
Helmut64 0:56dd5df33ab4 395 // based on the Direction the indiactor is drawn
Helmut64 0:56dd5df33ab4 396 switch (this->indicatorDirection){
Helmut64 0:56dd5df33ab4 397 case LEFT_RIGHT:
Helmut64 0:56dd5df33ab4 398 posOfHighlightFrame = frameToHighlight;
Helmut64 0:56dd5df33ab4 399 break;
Helmut64 0:56dd5df33ab4 400 case RIGHT_LEFT:
Helmut64 0:56dd5df33ab4 401 default:
Helmut64 0:56dd5df33ab4 402 posOfHighlightFrame = this->frameCount - frameToHighlight;
Helmut64 0:56dd5df33ab4 403 break;
Helmut64 0:56dd5df33ab4 404 }
Helmut64 0:56dd5df33ab4 405
Helmut64 0:56dd5df33ab4 406 switch (this->indicatorDrawState) {
Helmut64 0:56dd5df33ab4 407 case 1: // Indicator was not drawn in this frame but will be in next
Helmut64 0:56dd5df33ab4 408 // Slide IN
Helmut64 0:56dd5df33ab4 409 indicatorFadeProgress = 1 - ((float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition);
Helmut64 0:56dd5df33ab4 410 break;
Helmut64 0:56dd5df33ab4 411 case 2: // Indicator was drawn in this frame but not in next
Helmut64 0:56dd5df33ab4 412 // Slide OUT
Helmut64 0:56dd5df33ab4 413 indicatorFadeProgress = ((float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition);
Helmut64 0:56dd5df33ab4 414 break;
Helmut64 0:56dd5df33ab4 415 }
Helmut64 0:56dd5df33ab4 416
Helmut64 0:56dd5df33ab4 417 //Space between indicators - reduce for small screen sizes
Helmut64 0:56dd5df33ab4 418 uint16_t indicatorSpacing = 12;
Helmut64 0:56dd5df33ab4 419 if (this->display->getHeight() < 64 && (this->indicatorPosition == RIGHT || this->indicatorPosition == LEFT)) {
Helmut64 0:56dd5df33ab4 420 indicatorSpacing = 6;
Helmut64 0:56dd5df33ab4 421 }
Helmut64 0:56dd5df33ab4 422
Helmut64 0:56dd5df33ab4 423 uint16_t frameStartPos = (indicatorSpacing * frameCount / 2);
Helmut64 0:56dd5df33ab4 424 const uint8_t *image;
Helmut64 0:56dd5df33ab4 425
Helmut64 0:56dd5df33ab4 426 uint16_t x = 0,y = 0;
Helmut64 0:56dd5df33ab4 427
Helmut64 0:56dd5df33ab4 428
Helmut64 0:56dd5df33ab4 429 for (uint8_t i = 0; i < this->frameCount; i++) {
Helmut64 0:56dd5df33ab4 430
Helmut64 0:56dd5df33ab4 431 switch (this->indicatorPosition){
Helmut64 0:56dd5df33ab4 432 case TOP:
Helmut64 0:56dd5df33ab4 433 y = 0 - (8 * indicatorFadeProgress);
Helmut64 0:56dd5df33ab4 434 x = (this->display->width() / 2) - frameStartPos + 12 * i;
Helmut64 0:56dd5df33ab4 435 break;
Helmut64 0:56dd5df33ab4 436 case BOTTOM:
Helmut64 0:56dd5df33ab4 437 y = (this->display->height() - 8) + (8 * indicatorFadeProgress);
Helmut64 0:56dd5df33ab4 438 x = (this->display->width() / 2) - frameStartPos + 12 * i;
Helmut64 0:56dd5df33ab4 439 break;
Helmut64 0:56dd5df33ab4 440 case RIGHT:
Helmut64 0:56dd5df33ab4 441 x = (this->display->width() - 8) + (8 * indicatorFadeProgress);
Helmut64 0:56dd5df33ab4 442 y = (this->display->height() / 2) - frameStartPos + 2 + 12 * i;
Helmut64 0:56dd5df33ab4 443 break;
Helmut64 0:56dd5df33ab4 444 case LEFT:
Helmut64 0:56dd5df33ab4 445 default:
Helmut64 0:56dd5df33ab4 446 x = 0 - (8 * indicatorFadeProgress);
Helmut64 0:56dd5df33ab4 447 y = (this->display->height() / 2) - frameStartPos + 2 + indicatorSpacing * i;
Helmut64 0:56dd5df33ab4 448 break;
Helmut64 0:56dd5df33ab4 449 }
Helmut64 0:56dd5df33ab4 450
Helmut64 0:56dd5df33ab4 451 if (posOfHighlightFrame == i) {
Helmut64 0:56dd5df33ab4 452 image = this->activeSymbol;
Helmut64 0:56dd5df33ab4 453 } else {
Helmut64 0:56dd5df33ab4 454 image = this->inactiveSymbol;
Helmut64 0:56dd5df33ab4 455 }
Helmut64 0:56dd5df33ab4 456
Helmut64 0:56dd5df33ab4 457 this->display->drawFastImage(x, y, 8, 8, image);
Helmut64 0:56dd5df33ab4 458 }
Helmut64 0:56dd5df33ab4 459 }
Helmut64 0:56dd5df33ab4 460
Helmut64 0:56dd5df33ab4 461 void OLEDDisplayUi::drawOverlays() {
Helmut64 0:56dd5df33ab4 462 for (uint8_t i=0;i<this->overlayCount;i++){
Helmut64 0:56dd5df33ab4 463 (this->overlayFunctions[i])(this->display, &this->state);
Helmut64 0:56dd5df33ab4 464 }
Helmut64 0:56dd5df33ab4 465 }
Helmut64 0:56dd5df33ab4 466
Helmut64 0:56dd5df33ab4 467 uint8_t OLEDDisplayUi::getNextFrameNumber(){
Helmut64 0:56dd5df33ab4 468 if (this->nextFrameNumber != -1) return this->nextFrameNumber;
Helmut64 0:56dd5df33ab4 469 return (this->state.currentFrame + this->frameCount + this->state.frameTransitionDirection) % this->frameCount;
Helmut64 0:56dd5df33ab4 470 }