ThingPulse OLED SSD1306
Dependents: Turtle_RadioShuttle mbed-os5-F303-18650-Manager-tp4056 Kretanje_kroz_izbornike_OLED128x64_4tipke
OLEDDisplayUi.cpp@3:99a409809366, 2019-06-06 (annotated)
- 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?
User | Revision | Line number | New 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 | } |