Skip to content

Commit cd87e28

Browse files
committed
Merge remote-tracking branch 'squix78/master'
* squix78/master: Merge with update stream Update sample to use extended UI Refactor Ui into separate class Remove Ui related function from core
2 parents 49dcafd + ef64c27 commit cd87e28

File tree

6 files changed

+619
-237
lines changed

6 files changed

+619
-237
lines changed

SSD1306Ui.cpp

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
#include "SSD1306Ui.h"
2+
3+
4+
SSD1306Ui::SSD1306Ui(SSD1306 *display) {
5+
this->display = display;
6+
}
7+
8+
void SSD1306Ui::init() {
9+
this->display->init();
10+
}
11+
12+
void SSD1306Ui::setTargetFPS(byte fps){
13+
this->updateInterval = ((float) 1.0 / (float) fps) * 1000;
14+
Serial.println(this->updateInterval);
15+
}
16+
17+
// -/------ Automatic controll ------\-
18+
19+
void SSD1306Ui::enableAutoTransition(){
20+
autoTransition = true;
21+
}
22+
void SSD1306Ui::disableAutoTransition(){
23+
autoTransition = false;
24+
}
25+
void SSD1306Ui::setAutoTransitionForwards(){
26+
this->frameTransitionDirection = 1;
27+
}
28+
void SSD1306Ui::setAutoTransitionBackwards(){
29+
this->frameTransitionDirection = 1;
30+
}
31+
void SSD1306Ui::setTimePerFrame(int time){
32+
this->ticksPerFrame = (int) ( (float) time / (float) updateInterval);
33+
}
34+
void SSD1306Ui::setTimePerTransition(int time){
35+
this->ticksPerTransition = (int) ( (float) time / (float) updateInterval);
36+
}
37+
38+
39+
// -/------ Customize indicator position and style -------\-
40+
void SSD1306Ui::setIndicatorPosition(IndicatorPosition pos) {
41+
this->indicatorPosition = pos;
42+
this->dirty = true;
43+
}
44+
void SSD1306Ui::setIndicatorDirection(IndicatorDirection dir) {
45+
this->indicatorDirection = dir;
46+
}
47+
void SSD1306Ui::setActiveSymbole(const char* symbole) {
48+
this->activeSymbole = symbole;
49+
this->dirty = true;
50+
}
51+
void SSD1306Ui::setInactiveSymbole(const char* symbole) {
52+
this->inactiveSymbole = symbole;
53+
this->dirty = true;
54+
}
55+
56+
57+
// -/----- Frame settings -----\-
58+
void SSD1306Ui::setFrameAnimation(AnimationDirection dir) {
59+
this->frameAnimationDirection = dir;
60+
}
61+
void SSD1306Ui::setFrames(bool (*frameFunctions[])(SSD1306 *display, int x, int y), int frameCount) {
62+
this->frameCount = frameCount;
63+
this->frameFunctions = frameFunctions;
64+
}
65+
66+
// -/----- Overlays ------\-
67+
void SSD1306Ui::setOverlays(bool (*overlayFunctions[])(SSD1306 *display), int overlayCount){
68+
this->overlayCount = overlayCount;
69+
this->overlayFunctions = overlayFunctions;
70+
}
71+
72+
73+
// -/----- Manuel control -----\-
74+
void SSD1306Ui::nextFrame() {
75+
this->frameState = IN_TRANSITION;
76+
this->ticksSinceLastStateSwitch = 0;
77+
this->frameTransitionDirection = 1;
78+
}
79+
void SSD1306Ui::previousFrame() {
80+
this->frameState = IN_TRANSITION;
81+
this->ticksSinceLastStateSwitch = 0;
82+
this->frameTransitionDirection = -1;
83+
}
84+
85+
86+
// -/----- State information -----\-
87+
FrameState SSD1306Ui::getFrameState(){
88+
return this->frameState;
89+
}
90+
int SSD1306Ui::getCurrentFrame(){
91+
return this->currentFrame;
92+
}
93+
94+
95+
int SSD1306Ui::update(){
96+
int timeBudget = this->updateInterval - (millis() - this->lastUpdate);
97+
if ( timeBudget <= 0) {
98+
99+
// Implement frame skipping to ensure time budget is keept
100+
if (this->autoTransition && this->lastUpdate != 0) this->ticksSinceLastStateSwitch += abs(timeBudget) / this->updateInterval;
101+
102+
this->lastUpdate = millis();
103+
this->tick();
104+
}
105+
return timeBudget;
106+
}
107+
108+
109+
void SSD1306Ui::tick() {
110+
this->ticksSinceLastStateSwitch++;
111+
112+
switch (this->frameState) {
113+
case IN_TRANSITION:
114+
this->dirty = true;
115+
if (this->ticksSinceLastStateSwitch >= this->ticksPerTransition){
116+
this->frameState = FIXED;
117+
this->currentFrame = getNextFrameNumber();
118+
this->ticksSinceLastStateSwitch = 0;
119+
}
120+
break;
121+
case FIXED:
122+
if (this->ticksSinceLastStateSwitch >= this->ticksPerFrame){
123+
if (this->autoTransition){
124+
this->frameState = IN_TRANSITION;
125+
this->dirty = true;
126+
}
127+
this->ticksSinceLastStateSwitch = 0;
128+
}
129+
break;
130+
}
131+
132+
if (this->dirty) {
133+
this->dirty = false;
134+
this->display->clear();
135+
this->drawIndicator();
136+
this->drawFrame();
137+
this->drawOverlays();
138+
this->display->display();
139+
}
140+
}
141+
142+
void SSD1306Ui::drawFrame(){
143+
switch (this->frameState){
144+
case IN_TRANSITION: {
145+
float progress = (float) this->ticksSinceLastStateSwitch / (float) this->ticksPerTransition;
146+
int x, y, x1, y1;
147+
switch(this->frameAnimationDirection){
148+
case SLIDE_LEFT:
149+
x = -128 * progress;
150+
y = 0;
151+
x1 = x + 128;
152+
y1 = 0;
153+
break;
154+
case SLIDE_RIGHT:
155+
x = 128 * progress;
156+
y = 0;
157+
x1 = x - 128;
158+
y1 = 0;
159+
break;
160+
case SLIDE_UP:
161+
x = 0;
162+
y = -64 * progress;
163+
x1 = 0;
164+
y1 = y + 64;
165+
break;
166+
case SLIDE_DOWN:
167+
x = 0;
168+
y = 64 * progress;
169+
x1 = 0;
170+
y1 = y - 64;
171+
break;
172+
}
173+
174+
// Invert animation if direction is reversed.
175+
int dir = frameTransitionDirection >= 0 ? 1 : -1;
176+
x *= dir; y *= dir; x1 *= dir; y1 *= dir;
177+
178+
this->dirty |= (*this->frameFunctions[this->currentFrame])(this->display, x, y);
179+
this->dirty |= (*this->frameFunctions[this->getNextFrameNumber()])(this->display, x1, y1);
180+
break;
181+
}
182+
case FIXED:
183+
this->dirty |= (*this->frameFunctions[this->currentFrame])(this->display, 0, 0);
184+
break;
185+
}
186+
}
187+
188+
void SSD1306Ui::drawIndicator() {
189+
byte posOfCurrentFrame;
190+
191+
switch (this->indicatorDirection){
192+
case LEFT_RIGHT:
193+
posOfCurrentFrame = this->currentFrame;
194+
break;
195+
case RIGHT_LEFT:
196+
posOfCurrentFrame = (this->frameCount - 1) - this->currentFrame;
197+
break;
198+
}
199+
200+
for (byte i = 0; i < this->frameCount; i++) {
201+
202+
const char *xbm;
203+
204+
if (posOfCurrentFrame == i) {
205+
xbm = this->activeSymbole;
206+
} else {
207+
xbm = this->inactiveSymbole;
208+
}
209+
210+
int x,y;
211+
switch (this->indicatorPosition){
212+
case TOP:
213+
y = 0;
214+
x = 64 - (12 * frameCount / 2) + 12 * i;
215+
break;
216+
case BOTTOM:
217+
y = 56;
218+
x = 64 - (12 * frameCount / 2) + 12 * i;
219+
break;
220+
case RIGHT:
221+
x = 120;
222+
y = 32 - (12 * frameCount / 2) + 12 * i;
223+
break;
224+
case LEFT:
225+
x = 0;
226+
y = 32 - (12 * frameCount / 2) + 12 * i;
227+
break;
228+
}
229+
230+
this->display->drawXbm(x, y, 8, 8, xbm);
231+
}
232+
}
233+
234+
void SSD1306Ui::drawOverlays() {
235+
for (int i=0;i<this->overlayCount;i++){
236+
this->dirty |= (*this->overlayFunctions[i])(this->display);
237+
}
238+
}
239+
240+
int SSD1306Ui::getNextFrameNumber(){
241+
int nextFrame = (this->currentFrame + this->frameTransitionDirection) % this->frameCount;
242+
if (nextFrame < 0){
243+
nextFrame = this->frameCount + nextFrame;
244+
}
245+
return nextFrame;
246+
}
247+
248+
249+

0 commit comments

Comments
 (0)