Skip to content

Commit 42d9d63

Browse files
ElderJoymarcelstoer
authored andcommitted
Add drawIco16x16, fix updateInterval overflow, optimize mult. operations (#236)
* Fix updateInterval overflow when frame rate lower than 8 * Optimize operations mult. 2, 4, 8 * Add drawIco16x16 and setPixelColor functions * return back clearPixel function for backward compatibility * optimize clearPixel division
1 parent 4fa903f commit 42d9d63

File tree

4 files changed

+56
-25
lines changed

4 files changed

+56
-25
lines changed

src/OLEDDisplay.cpp

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -126,19 +126,29 @@ OLEDDISPLAY_COLOR OLEDDisplay::getColor() {
126126
void OLEDDisplay::setPixel(int16_t x, int16_t y) {
127127
if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) {
128128
switch (color) {
129-
case WHITE: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break;
130-
case BLACK: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break;
131-
case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break;
129+
case WHITE: buffer[x + (y >> 3) * this->width()] |= (1 << (y & 7)); break;
130+
case BLACK: buffer[x + (y >> 3) * this->width()] &= ~(1 << (y & 7)); break;
131+
case INVERSE: buffer[x + (y >> 3) * this->width()] ^= (1 << (y & 7)); break;
132+
}
133+
}
134+
}
135+
136+
void OLEDDisplay::setPixelColor(int16_t x, int16_t y, OLEDDISPLAY_COLOR color) {
137+
if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) {
138+
switch (color) {
139+
case WHITE: buffer[x + (y >> 3) * this->width()] |= (1 << (y & 7)); break;
140+
case BLACK: buffer[x + (y >> 3) * this->width()] &= ~(1 << (y & 7)); break;
141+
case INVERSE: buffer[x + (y >> 3) * this->width()] ^= (1 << (y & 7)); break;
132142
}
133143
}
134144
}
135145

136146
void OLEDDisplay::clearPixel(int16_t x, int16_t y) {
137147
if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) {
138148
switch (color) {
139-
case BLACK: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break;
140-
case WHITE: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break;
141-
case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break;
149+
case BLACK: buffer[x + (y >> 3) * this->width()] |= (1 << (y & 7)); break;
150+
case WHITE: buffer[x + (y >> 3) * this->width()] &= ~(1 << (y & 7)); break;
151+
case INVERSE: buffer[x + (y >> 3) * this->width()] ^= (1 << (y & 7)); break;
142152
}
143153
}
144154
}
@@ -161,7 +171,7 @@ void OLEDDisplay::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
161171
dx = x1 - x0;
162172
dy = abs(y1 - y0);
163173

164-
int16_t err = dx / 2;
174+
int16_t err = dx >> 1;
165175
int16_t ystep;
166176

167177
if (y0 < y1) {
@@ -202,9 +212,9 @@ void OLEDDisplay::drawCircle(int16_t x0, int16_t y0, int16_t radius) {
202212
int16_t dp = 1 - radius;
203213
do {
204214
if (dp < 0)
205-
dp = dp + 2 * (x++) + 3;
215+
dp = dp + (++x) << 1 + 3;
206216
else
207-
dp = dp + 2 * (x++) - 2 * (y--) + 5;
217+
dp = dp + (++x) << 1 - (--y) << 1 + 5;
208218

209219
setPixel(x0 + x, y0 + y); //For the 8 octants
210220
setPixel(x0 - x, y0 + y);
@@ -228,9 +238,9 @@ void OLEDDisplay::drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_
228238
int16_t dp = 1 - radius;
229239
while (x < y) {
230240
if (dp < 0)
231-
dp = dp + 2 * (x++) + 3;
241+
dp = dp + (++x) << 1 + 3;
232242
else
233-
dp = dp + 2 * (x++) - 2 * (y--) + 5;
243+
dp = dp + (++x) << 1 - (--y) << 1 + 5;
234244
if (quads & 0x1) {
235245
setPixel(x0 + x, y0 - y);
236246
setPixel(x0 + y, y0 - x);
@@ -268,9 +278,9 @@ void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) {
268278
int16_t dp = 1 - radius;
269279
do {
270280
if (dp < 0)
271-
dp = dp + 2 * (x++) + 3;
272-
else
273-
dp = dp + 2 * (x++) - 2 * (y--) + 5;
281+
dp = dp + (++x) << 1 + 3;
282+
else
283+
dp = dp + (++x) << 1 - (--y) << 1 + 5;
274284

275285
drawHorizontalLine(x0 - x, y0 - y, 2*x);
276286
drawHorizontalLine(x0 - x, y0 + y, 2*x);
@@ -279,7 +289,7 @@ void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) {
279289

280290

281291
} while (x < y);
282-
drawHorizontalLine(x0 - radius, y0, 2 * radius);
292+
drawHorizontalLine(x0 - radius, y0, radius << 1);
283293

284294
}
285295

@@ -390,10 +400,10 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
390400
}
391401

392402
void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress) {
393-
uint16_t radius = height / 2;
403+
uint16_t radius = height >> 1;
394404
uint16_t xRadius = x + radius;
395405
uint16_t yRadius = y + radius;
396-
uint16_t doubleRadius = 2 * radius;
406+
uint16_t doubleRadius = radius << 1;
397407
uint16_t innerRadius = radius - 2;
398408

399409
setColor(WHITE);
@@ -414,15 +424,15 @@ void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int
414424
}
415425

416426
void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *xbm) {
417-
int16_t widthInXbm = (width + 7) / 8;
427+
int16_t widthInXbm = (width + 7) >> 3;
418428
uint8_t data = 0;
419429

420430
for(int16_t y = 0; y < height; y++) {
421431
for(int16_t x = 0; x < width; x++ ) {
422432
if (x & 7) {
423433
data >>= 1; // Move a bit
424434
} else { // Read new data every 8 bit
425-
data = pgm_read_byte(xbm + (x / 8) + y * widthInXbm);
435+
data = pgm_read_byte(xbm + (x >> 3) + y * widthInXbm);
426436
}
427437
// if there is a bit draw it
428438
if (data & 0x01) {
@@ -432,6 +442,22 @@ void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t h
432442
}
433443
}
434444

445+
void OLEDDisplay::drawIco16x16(int16_t xMove, int16_t yMove, const char *ico, bool inverse) {
446+
uint16_t data;
447+
448+
for(int16_t y = 0; y < 16; y++) {
449+
data = pgm_read_byte(ico + (y << 1)) + (pgm_read_byte(ico + (y << 1) + 1) << 8);
450+
for(int16_t x = 0; x < 16; x++ ) {
451+
if ((data & 0x01) ^ inverse) {
452+
setPixelColor(xMove + x, yMove + y, WHITE);
453+
} else {
454+
setPixelColor(xMove + x, yMove + y, BLACK);
455+
}
456+
data >>= 1; // Move a bit
457+
}
458+
}
459+
}
460+
435461
void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth) {
436462
uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS);
437463
uint8_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS);
@@ -501,7 +527,7 @@ void OLEDDisplay::drawString(int16_t xMove, int16_t yMove, String strUser) {
501527
lb += (text[i] == 10);
502528
}
503529
// Calculate center
504-
yOffset = (lb * lineHeight) / 2;
530+
yOffset = (lb * lineHeight) >> 1;
505531
}
506532

507533
uint16_t line = 0;

src/OLEDDisplay.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ class OLEDDisplay : public Stream {
179179
// Draw a pixel at given position
180180
void setPixel(int16_t x, int16_t y);
181181

182+
// Draw a pixel at given position and color
183+
void setPixelColor(int16_t x, int16_t y, OLEDDISPLAY_COLOR color);
184+
182185
// Clear a pixel at given position FIXME: INVERSE is untested with this function
183186
void clearPixel(int16_t x, int16_t y);
184187

@@ -216,6 +219,9 @@ class OLEDDisplay : public Stream {
216219
// Draw a XBM
217220
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *xbm);
218221

222+
// Draw icon 16x16 xbm format
223+
void drawIco16x16(int16_t x, int16_t y, const char *ico, bool inverse = false);
224+
219225
/* Text functions */
220226

221227
// Draws a string at the given location

src/OLEDDisplayUi.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,7 @@ OLEDDisplayUiState* OLEDDisplayUi::getUiState(){
226226
return &this->state;
227227
}
228228

229-
230-
int8_t OLEDDisplayUi::update(){
229+
int16_t OLEDDisplayUi::update(){
231230
#ifdef ARDUINO
232231
unsigned long frameStart = millis();
233232
#elif __MBED__
@@ -237,7 +236,7 @@ int8_t OLEDDisplayUi::update(){
237236
#else
238237
#error "Unkown operating system"
239238
#endif
240-
int8_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate);
239+
int16_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate);
241240
if ( timeBudget <= 0) {
242241
// Implement frame skipping to ensure time budget is keept
243242
if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil((double)-timeBudget / (double)this->updateInterval);

src/OLEDDisplayUi.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class OLEDDisplayUi {
157157
OLEDDisplayUiState state;
158158

159159
// Bookeeping for update
160-
uint8_t updateInterval;
160+
uint16_t updateInterval = 33;
161161

162162
uint8_t getNextFrameNumber();
163163
void drawIndicator();
@@ -307,6 +307,6 @@ class OLEDDisplayUi {
307307
// State Info
308308
OLEDDisplayUiState* getUiState();
309309

310-
int8_t update();
310+
int16_t update();
311311
};
312312
#endif

0 commit comments

Comments
 (0)