ThingPulse OLED SSD1306

Dependents:   Turtle_RadioShuttle

Committer:
Helmut Tschemernjak
Date:
Thu Jun 06 09:29:02 2019 +0200
Revision:
3:99a409809366
Parent:
2:4ed55dfe5be7
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 /*
Helmut64 0:56dd5df33ab4 33 * TODO Helmut
Helmut64 0:56dd5df33ab4 34 * - test/finish dislplay.printf() on mbed-os
Helmut64 0:56dd5df33ab4 35 * - Finish _putc with drawLogBuffer when running display
Helmut64 0:56dd5df33ab4 36 */
Helmut64 0:56dd5df33ab4 37
Helmut64 0:56dd5df33ab4 38 #include "OLEDDisplay.h"
Helmut64 0:56dd5df33ab4 39
Helmut64 0:56dd5df33ab4 40 OLEDDisplay::OLEDDisplay() {
Helmut64 0:56dd5df33ab4 41
Helmut64 0:56dd5df33ab4 42 displayWidth = 128;
Helmut64 0:56dd5df33ab4 43 displayHeight = 64;
Helmut Tschemernjak 2:4ed55dfe5be7 44 displayBufferSize = displayWidth * displayHeight / 8;
Helmut64 0:56dd5df33ab4 45 color = WHITE;
Helmut64 0:56dd5df33ab4 46 geometry = GEOMETRY_128_64;
Helmut64 0:56dd5df33ab4 47 textAlignment = TEXT_ALIGN_LEFT;
Helmut64 0:56dd5df33ab4 48 fontData = ArialMT_Plain_10;
Helmut64 0:56dd5df33ab4 49 fontTableLookupFunction = DefaultFontTableLookup;
Helmut64 0:56dd5df33ab4 50 buffer = NULL;
Helmut Tschemernjak 1:9270c15c6aea 51 #ifdef OLEDDISPLAY_DOUBLE_BUFFER
Helmut64 0:56dd5df33ab4 52 buffer_back = NULL;
Helmut Tschemernjak 1:9270c15c6aea 53 #endif
Helmut64 0:56dd5df33ab4 54 }
Helmut64 0:56dd5df33ab4 55
Helmut64 0:56dd5df33ab4 56 OLEDDisplay::~OLEDDisplay() {
Helmut64 0:56dd5df33ab4 57 end();
Helmut64 0:56dd5df33ab4 58 }
Helmut64 0:56dd5df33ab4 59
Helmut64 0:56dd5df33ab4 60 bool OLEDDisplay::init() {
Helmut64 0:56dd5df33ab4 61
Helmut64 0:56dd5df33ab4 62 logBufferSize = 0;
Helmut64 0:56dd5df33ab4 63 logBufferFilled = 0;
Helmut64 0:56dd5df33ab4 64 logBufferLine = 0;
Helmut64 0:56dd5df33ab4 65 logBufferMaxLines = 0;
Helmut64 0:56dd5df33ab4 66 logBuffer = NULL;
Helmut64 0:56dd5df33ab4 67
Helmut64 0:56dd5df33ab4 68 if (!this->connect()) {
Helmut64 0:56dd5df33ab4 69 DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n");
Helmut64 0:56dd5df33ab4 70 return false;
Helmut64 0:56dd5df33ab4 71 }
Helmut64 0:56dd5df33ab4 72
Helmut64 0:56dd5df33ab4 73 if(this->buffer==NULL) {
Helmut64 0:56dd5df33ab4 74 this->buffer = (uint8_t*) malloc((sizeof(uint8_t) * displayBufferSize) + getBufferOffset());
Helmut64 0:56dd5df33ab4 75 this->buffer += getBufferOffset();
Helmut64 0:56dd5df33ab4 76
Helmut64 0:56dd5df33ab4 77 if(!this->buffer) {
Helmut64 0:56dd5df33ab4 78 DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create display\n");
Helmut64 0:56dd5df33ab4 79 return false;
Helmut64 0:56dd5df33ab4 80 }
Helmut64 0:56dd5df33ab4 81 }
Helmut64 0:56dd5df33ab4 82
Helmut64 0:56dd5df33ab4 83 #ifdef OLEDDISPLAY_DOUBLE_BUFFER
Helmut64 0:56dd5df33ab4 84 if(this->buffer_back==NULL) {
Helmut64 0:56dd5df33ab4 85 this->buffer_back = (uint8_t*) malloc((sizeof(uint8_t) * displayBufferSize) + getBufferOffset());
Helmut64 0:56dd5df33ab4 86 this->buffer_back += getBufferOffset();
Helmut64 0:56dd5df33ab4 87
Helmut64 0:56dd5df33ab4 88 if(!this->buffer_back) {
Helmut64 0:56dd5df33ab4 89 DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n");
Helmut64 0:56dd5df33ab4 90 free(this->buffer - getBufferOffset());
Helmut64 0:56dd5df33ab4 91 return false;
Helmut64 0:56dd5df33ab4 92 }
Helmut64 0:56dd5df33ab4 93 }
Helmut64 0:56dd5df33ab4 94 #endif
Helmut64 0:56dd5df33ab4 95
Helmut64 0:56dd5df33ab4 96 sendInitCommands();
Helmut64 0:56dd5df33ab4 97 resetDisplay();
Helmut64 0:56dd5df33ab4 98
Helmut64 0:56dd5df33ab4 99 return true;
Helmut64 0:56dd5df33ab4 100 }
Helmut64 0:56dd5df33ab4 101
Helmut64 0:56dd5df33ab4 102 void OLEDDisplay::end() {
Helmut64 0:56dd5df33ab4 103 if (this->buffer) { free(this->buffer - getBufferOffset()); this->buffer = NULL; }
Helmut64 0:56dd5df33ab4 104 #ifdef OLEDDISPLAY_DOUBLE_BUFFER
Helmut64 0:56dd5df33ab4 105 if (this->buffer_back) { free(this->buffer_back - getBufferOffset()); this->buffer_back = NULL; }
Helmut64 0:56dd5df33ab4 106 #endif
Helmut64 0:56dd5df33ab4 107 if (this->logBuffer != NULL) { free(this->logBuffer); this->logBuffer = NULL; }
Helmut64 0:56dd5df33ab4 108 }
Helmut64 0:56dd5df33ab4 109
Helmut64 0:56dd5df33ab4 110 void OLEDDisplay::resetDisplay(void) {
Helmut64 0:56dd5df33ab4 111 clear();
Helmut64 0:56dd5df33ab4 112 #ifdef OLEDDISPLAY_DOUBLE_BUFFER
Helmut64 0:56dd5df33ab4 113 memset(buffer_back, 1, displayBufferSize);
Helmut64 0:56dd5df33ab4 114 #endif
Helmut64 0:56dd5df33ab4 115 display();
Helmut64 0:56dd5df33ab4 116 }
Helmut64 0:56dd5df33ab4 117
Helmut64 0:56dd5df33ab4 118 void OLEDDisplay::setColor(OLEDDISPLAY_COLOR color) {
Helmut64 0:56dd5df33ab4 119 this->color = color;
Helmut64 0:56dd5df33ab4 120 }
Helmut64 0:56dd5df33ab4 121
Helmut64 0:56dd5df33ab4 122 OLEDDISPLAY_COLOR OLEDDisplay::getColor() {
Helmut64 0:56dd5df33ab4 123 return this->color;
Helmut64 0:56dd5df33ab4 124 }
Helmut64 0:56dd5df33ab4 125
Helmut64 0:56dd5df33ab4 126 void OLEDDisplay::setPixel(int16_t x, int16_t y) {
Helmut64 0:56dd5df33ab4 127 if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) {
Helmut64 0:56dd5df33ab4 128 switch (color) {
Helmut64 0:56dd5df33ab4 129 case WHITE: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break;
Helmut64 0:56dd5df33ab4 130 case BLACK: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break;
Helmut64 0:56dd5df33ab4 131 case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break;
Helmut64 0:56dd5df33ab4 132 }
Helmut64 0:56dd5df33ab4 133 }
Helmut64 0:56dd5df33ab4 134 }
Helmut64 0:56dd5df33ab4 135
Helmut Tschemernjak 3:99a409809366 136 void OLEDDisplay::clearPixel(int16_t x, int16_t y) {
Helmut Tschemernjak 3:99a409809366 137 if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) {
Helmut Tschemernjak 3:99a409809366 138 switch (color) {
Helmut Tschemernjak 3:99a409809366 139 case BLACK: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break;
Helmut Tschemernjak 3:99a409809366 140 case WHITE: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break;
Helmut Tschemernjak 3:99a409809366 141 case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break;
Helmut Tschemernjak 3:99a409809366 142 }
Helmut Tschemernjak 3:99a409809366 143 }
Helmut Tschemernjak 3:99a409809366 144 }
Helmut Tschemernjak 3:99a409809366 145
Helmut Tschemernjak 3:99a409809366 146
Helmut64 0:56dd5df33ab4 147 // Bresenham's algorithm - thx wikipedia and Adafruit_GFX
Helmut64 0:56dd5df33ab4 148 void OLEDDisplay::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
Helmut64 0:56dd5df33ab4 149 int16_t steep = abs(y1 - y0) > abs(x1 - x0);
Helmut64 0:56dd5df33ab4 150 if (steep) {
Helmut64 0:56dd5df33ab4 151 _swap_int16_t(x0, y0);
Helmut64 0:56dd5df33ab4 152 _swap_int16_t(x1, y1);
Helmut64 0:56dd5df33ab4 153 }
Helmut64 0:56dd5df33ab4 154
Helmut64 0:56dd5df33ab4 155 if (x0 > x1) {
Helmut64 0:56dd5df33ab4 156 _swap_int16_t(x0, x1);
Helmut64 0:56dd5df33ab4 157 _swap_int16_t(y0, y1);
Helmut64 0:56dd5df33ab4 158 }
Helmut64 0:56dd5df33ab4 159
Helmut64 0:56dd5df33ab4 160 int16_t dx, dy;
Helmut64 0:56dd5df33ab4 161 dx = x1 - x0;
Helmut64 0:56dd5df33ab4 162 dy = abs(y1 - y0);
Helmut64 0:56dd5df33ab4 163
Helmut64 0:56dd5df33ab4 164 int16_t err = dx / 2;
Helmut64 0:56dd5df33ab4 165 int16_t ystep;
Helmut64 0:56dd5df33ab4 166
Helmut64 0:56dd5df33ab4 167 if (y0 < y1) {
Helmut64 0:56dd5df33ab4 168 ystep = 1;
Helmut64 0:56dd5df33ab4 169 } else {
Helmut64 0:56dd5df33ab4 170 ystep = -1;
Helmut64 0:56dd5df33ab4 171 }
Helmut64 0:56dd5df33ab4 172
Helmut64 0:56dd5df33ab4 173 for (; x0<=x1; x0++) {
Helmut64 0:56dd5df33ab4 174 if (steep) {
Helmut64 0:56dd5df33ab4 175 setPixel(y0, x0);
Helmut64 0:56dd5df33ab4 176 } else {
Helmut64 0:56dd5df33ab4 177 setPixel(x0, y0);
Helmut64 0:56dd5df33ab4 178 }
Helmut64 0:56dd5df33ab4 179 err -= dy;
Helmut64 0:56dd5df33ab4 180 if (err < 0) {
Helmut64 0:56dd5df33ab4 181 y0 += ystep;
Helmut64 0:56dd5df33ab4 182 err += dx;
Helmut64 0:56dd5df33ab4 183 }
Helmut64 0:56dd5df33ab4 184 }
Helmut64 0:56dd5df33ab4 185 }
Helmut64 0:56dd5df33ab4 186
Helmut64 0:56dd5df33ab4 187 void OLEDDisplay::drawRect(int16_t x, int16_t y, int16_t width, int16_t height) {
Helmut64 0:56dd5df33ab4 188 drawHorizontalLine(x, y, width);
Helmut64 0:56dd5df33ab4 189 drawVerticalLine(x, y, height);
Helmut64 0:56dd5df33ab4 190 drawVerticalLine(x + width - 1, y, height);
Helmut64 0:56dd5df33ab4 191 drawHorizontalLine(x, y + height - 1, width);
Helmut64 0:56dd5df33ab4 192 }
Helmut64 0:56dd5df33ab4 193
Helmut64 0:56dd5df33ab4 194 void OLEDDisplay::fillRect(int16_t xMove, int16_t yMove, int16_t width, int16_t height) {
Helmut64 0:56dd5df33ab4 195 for (int16_t x = xMove; x < xMove + width; x++) {
Helmut64 0:56dd5df33ab4 196 drawVerticalLine(x, yMove, height);
Helmut64 0:56dd5df33ab4 197 }
Helmut64 0:56dd5df33ab4 198 }
Helmut64 0:56dd5df33ab4 199
Helmut64 0:56dd5df33ab4 200 void OLEDDisplay::drawCircle(int16_t x0, int16_t y0, int16_t radius) {
Helmut64 0:56dd5df33ab4 201 int16_t x = 0, y = radius;
Helmut64 0:56dd5df33ab4 202 int16_t dp = 1 - radius;
Helmut64 0:56dd5df33ab4 203 do {
Helmut64 0:56dd5df33ab4 204 if (dp < 0)
Helmut64 0:56dd5df33ab4 205 dp = dp + 2 * (x++) + 3;
Helmut64 0:56dd5df33ab4 206 else
Helmut64 0:56dd5df33ab4 207 dp = dp + 2 * (x++) - 2 * (y--) + 5;
Helmut64 0:56dd5df33ab4 208
Helmut64 0:56dd5df33ab4 209 setPixel(x0 + x, y0 + y); //For the 8 octants
Helmut64 0:56dd5df33ab4 210 setPixel(x0 - x, y0 + y);
Helmut64 0:56dd5df33ab4 211 setPixel(x0 + x, y0 - y);
Helmut64 0:56dd5df33ab4 212 setPixel(x0 - x, y0 - y);
Helmut64 0:56dd5df33ab4 213 setPixel(x0 + y, y0 + x);
Helmut64 0:56dd5df33ab4 214 setPixel(x0 - y, y0 + x);
Helmut64 0:56dd5df33ab4 215 setPixel(x0 + y, y0 - x);
Helmut64 0:56dd5df33ab4 216 setPixel(x0 - y, y0 - x);
Helmut64 0:56dd5df33ab4 217
Helmut64 0:56dd5df33ab4 218 } while (x < y);
Helmut64 0:56dd5df33ab4 219
Helmut64 0:56dd5df33ab4 220 setPixel(x0 + radius, y0);
Helmut64 0:56dd5df33ab4 221 setPixel(x0, y0 + radius);
Helmut64 0:56dd5df33ab4 222 setPixel(x0 - radius, y0);
Helmut64 0:56dd5df33ab4 223 setPixel(x0, y0 - radius);
Helmut64 0:56dd5df33ab4 224 }
Helmut64 0:56dd5df33ab4 225
Helmut64 0:56dd5df33ab4 226 void OLEDDisplay::drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads) {
Helmut64 0:56dd5df33ab4 227 int16_t x = 0, y = radius;
Helmut64 0:56dd5df33ab4 228 int16_t dp = 1 - radius;
Helmut64 0:56dd5df33ab4 229 while (x < y) {
Helmut64 0:56dd5df33ab4 230 if (dp < 0)
Helmut64 0:56dd5df33ab4 231 dp = dp + 2 * (x++) + 3;
Helmut64 0:56dd5df33ab4 232 else
Helmut64 0:56dd5df33ab4 233 dp = dp + 2 * (x++) - 2 * (y--) + 5;
Helmut64 0:56dd5df33ab4 234 if (quads & 0x1) {
Helmut64 0:56dd5df33ab4 235 setPixel(x0 + x, y0 - y);
Helmut64 0:56dd5df33ab4 236 setPixel(x0 + y, y0 - x);
Helmut64 0:56dd5df33ab4 237 }
Helmut64 0:56dd5df33ab4 238 if (quads & 0x2) {
Helmut64 0:56dd5df33ab4 239 setPixel(x0 - y, y0 - x);
Helmut64 0:56dd5df33ab4 240 setPixel(x0 - x, y0 - y);
Helmut64 0:56dd5df33ab4 241 }
Helmut64 0:56dd5df33ab4 242 if (quads & 0x4) {
Helmut64 0:56dd5df33ab4 243 setPixel(x0 - y, y0 + x);
Helmut64 0:56dd5df33ab4 244 setPixel(x0 - x, y0 + y);
Helmut64 0:56dd5df33ab4 245 }
Helmut64 0:56dd5df33ab4 246 if (quads & 0x8) {
Helmut64 0:56dd5df33ab4 247 setPixel(x0 + x, y0 + y);
Helmut64 0:56dd5df33ab4 248 setPixel(x0 + y, y0 + x);
Helmut64 0:56dd5df33ab4 249 }
Helmut64 0:56dd5df33ab4 250 }
Helmut64 0:56dd5df33ab4 251 if (quads & 0x1 && quads & 0x8) {
Helmut64 0:56dd5df33ab4 252 setPixel(x0 + radius, y0);
Helmut64 0:56dd5df33ab4 253 }
Helmut64 0:56dd5df33ab4 254 if (quads & 0x4 && quads & 0x8) {
Helmut64 0:56dd5df33ab4 255 setPixel(x0, y0 + radius);
Helmut64 0:56dd5df33ab4 256 }
Helmut64 0:56dd5df33ab4 257 if (quads & 0x2 && quads & 0x4) {
Helmut64 0:56dd5df33ab4 258 setPixel(x0 - radius, y0);
Helmut64 0:56dd5df33ab4 259 }
Helmut64 0:56dd5df33ab4 260 if (quads & 0x1 && quads & 0x2) {
Helmut64 0:56dd5df33ab4 261 setPixel(x0, y0 - radius);
Helmut64 0:56dd5df33ab4 262 }
Helmut64 0:56dd5df33ab4 263 }
Helmut64 0:56dd5df33ab4 264
Helmut64 0:56dd5df33ab4 265
Helmut64 0:56dd5df33ab4 266 void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) {
Helmut64 0:56dd5df33ab4 267 int16_t x = 0, y = radius;
Helmut64 0:56dd5df33ab4 268 int16_t dp = 1 - radius;
Helmut64 0:56dd5df33ab4 269 do {
Helmut64 0:56dd5df33ab4 270 if (dp < 0)
Helmut64 0:56dd5df33ab4 271 dp = dp + 2 * (x++) + 3;
Helmut64 0:56dd5df33ab4 272 else
Helmut64 0:56dd5df33ab4 273 dp = dp + 2 * (x++) - 2 * (y--) + 5;
Helmut64 0:56dd5df33ab4 274
Helmut64 0:56dd5df33ab4 275 drawHorizontalLine(x0 - x, y0 - y, 2*x);
Helmut64 0:56dd5df33ab4 276 drawHorizontalLine(x0 - x, y0 + y, 2*x);
Helmut64 0:56dd5df33ab4 277 drawHorizontalLine(x0 - y, y0 - x, 2*y);
Helmut64 0:56dd5df33ab4 278 drawHorizontalLine(x0 - y, y0 + x, 2*y);
Helmut64 0:56dd5df33ab4 279
Helmut64 0:56dd5df33ab4 280
Helmut64 0:56dd5df33ab4 281 } while (x < y);
Helmut64 0:56dd5df33ab4 282 drawHorizontalLine(x0 - radius, y0, 2 * radius);
Helmut64 0:56dd5df33ab4 283
Helmut64 0:56dd5df33ab4 284 }
Helmut64 0:56dd5df33ab4 285
Helmut64 0:56dd5df33ab4 286 void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
Helmut64 0:56dd5df33ab4 287 if (y < 0 || y >= this->height()) { return; }
Helmut64 0:56dd5df33ab4 288
Helmut64 0:56dd5df33ab4 289 if (x < 0) {
Helmut64 0:56dd5df33ab4 290 length += x;
Helmut64 0:56dd5df33ab4 291 x = 0;
Helmut64 0:56dd5df33ab4 292 }
Helmut64 0:56dd5df33ab4 293
Helmut64 0:56dd5df33ab4 294 if ( (x + length) > this->width()) {
Helmut64 0:56dd5df33ab4 295 length = (this->width() - x);
Helmut64 0:56dd5df33ab4 296 }
Helmut64 0:56dd5df33ab4 297
Helmut64 0:56dd5df33ab4 298 if (length <= 0) { return; }
Helmut64 0:56dd5df33ab4 299
Helmut64 0:56dd5df33ab4 300 uint8_t * bufferPtr = buffer;
Helmut64 0:56dd5df33ab4 301 bufferPtr += (y >> 3) * this->width();
Helmut64 0:56dd5df33ab4 302 bufferPtr += x;
Helmut64 0:56dd5df33ab4 303
Helmut64 0:56dd5df33ab4 304 uint8_t drawBit = 1 << (y & 7);
Helmut64 0:56dd5df33ab4 305
Helmut64 0:56dd5df33ab4 306 switch (color) {
Helmut64 0:56dd5df33ab4 307 case WHITE: while (length--) {
Helmut64 0:56dd5df33ab4 308 *bufferPtr++ |= drawBit;
Helmut64 0:56dd5df33ab4 309 }; break;
Helmut64 0:56dd5df33ab4 310 case BLACK: drawBit = ~drawBit; while (length--) {
Helmut64 0:56dd5df33ab4 311 *bufferPtr++ &= drawBit;
Helmut64 0:56dd5df33ab4 312 }; break;
Helmut64 0:56dd5df33ab4 313 case INVERSE: while (length--) {
Helmut64 0:56dd5df33ab4 314 *bufferPtr++ ^= drawBit;
Helmut64 0:56dd5df33ab4 315 }; break;
Helmut64 0:56dd5df33ab4 316 }
Helmut64 0:56dd5df33ab4 317 }
Helmut64 0:56dd5df33ab4 318
Helmut64 0:56dd5df33ab4 319 void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
Helmut64 0:56dd5df33ab4 320 if (x < 0 || x >= this->width()) return;
Helmut64 0:56dd5df33ab4 321
Helmut64 0:56dd5df33ab4 322 if (y < 0) {
Helmut64 0:56dd5df33ab4 323 length += y;
Helmut64 0:56dd5df33ab4 324 y = 0;
Helmut64 0:56dd5df33ab4 325 }
Helmut64 0:56dd5df33ab4 326
Helmut64 0:56dd5df33ab4 327 if ( (y + length) > this->height()) {
Helmut64 0:56dd5df33ab4 328 length = (this->height() - y);
Helmut64 0:56dd5df33ab4 329 }
Helmut64 0:56dd5df33ab4 330
Helmut64 0:56dd5df33ab4 331 if (length <= 0) return;
Helmut64 0:56dd5df33ab4 332
Helmut64 0:56dd5df33ab4 333
Helmut64 0:56dd5df33ab4 334 uint8_t yOffset = y & 7;
Helmut64 0:56dd5df33ab4 335 uint8_t drawBit;
Helmut64 0:56dd5df33ab4 336 uint8_t *bufferPtr = buffer;
Helmut64 0:56dd5df33ab4 337
Helmut64 0:56dd5df33ab4 338 bufferPtr += (y >> 3) * this->width();
Helmut64 0:56dd5df33ab4 339 bufferPtr += x;
Helmut64 0:56dd5df33ab4 340
Helmut64 0:56dd5df33ab4 341 if (yOffset) {
Helmut64 0:56dd5df33ab4 342 yOffset = 8 - yOffset;
Helmut64 0:56dd5df33ab4 343 drawBit = ~(0xFF >> (yOffset));
Helmut64 0:56dd5df33ab4 344
Helmut64 0:56dd5df33ab4 345 if (length < yOffset) {
Helmut64 0:56dd5df33ab4 346 drawBit &= (0xFF >> (yOffset - length));
Helmut64 0:56dd5df33ab4 347 }
Helmut64 0:56dd5df33ab4 348
Helmut64 0:56dd5df33ab4 349 switch (color) {
Helmut64 0:56dd5df33ab4 350 case WHITE: *bufferPtr |= drawBit; break;
Helmut64 0:56dd5df33ab4 351 case BLACK: *bufferPtr &= ~drawBit; break;
Helmut64 0:56dd5df33ab4 352 case INVERSE: *bufferPtr ^= drawBit; break;
Helmut64 0:56dd5df33ab4 353 }
Helmut64 0:56dd5df33ab4 354
Helmut64 0:56dd5df33ab4 355 if (length < yOffset) return;
Helmut64 0:56dd5df33ab4 356
Helmut64 0:56dd5df33ab4 357 length -= yOffset;
Helmut64 0:56dd5df33ab4 358 bufferPtr += this->width();
Helmut64 0:56dd5df33ab4 359 }
Helmut64 0:56dd5df33ab4 360
Helmut64 0:56dd5df33ab4 361 if (length >= 8) {
Helmut64 0:56dd5df33ab4 362 switch (color) {
Helmut64 0:56dd5df33ab4 363 case WHITE:
Helmut64 0:56dd5df33ab4 364 case BLACK:
Helmut64 0:56dd5df33ab4 365 drawBit = (color == WHITE) ? 0xFF : 0x00;
Helmut64 0:56dd5df33ab4 366 do {
Helmut64 0:56dd5df33ab4 367 *bufferPtr = drawBit;
Helmut64 0:56dd5df33ab4 368 bufferPtr += this->width();
Helmut64 0:56dd5df33ab4 369 length -= 8;
Helmut64 0:56dd5df33ab4 370 } while (length >= 8);
Helmut64 0:56dd5df33ab4 371 break;
Helmut64 0:56dd5df33ab4 372 case INVERSE:
Helmut64 0:56dd5df33ab4 373 do {
Helmut64 0:56dd5df33ab4 374 *bufferPtr = ~(*bufferPtr);
Helmut64 0:56dd5df33ab4 375 bufferPtr += this->width();
Helmut64 0:56dd5df33ab4 376 length -= 8;
Helmut64 0:56dd5df33ab4 377 } while (length >= 8);
Helmut64 0:56dd5df33ab4 378 break;
Helmut64 0:56dd5df33ab4 379 }
Helmut64 0:56dd5df33ab4 380 }
Helmut64 0:56dd5df33ab4 381
Helmut64 0:56dd5df33ab4 382 if (length > 0) {
Helmut64 0:56dd5df33ab4 383 drawBit = (1 << (length & 7)) - 1;
Helmut64 0:56dd5df33ab4 384 switch (color) {
Helmut64 0:56dd5df33ab4 385 case WHITE: *bufferPtr |= drawBit; break;
Helmut64 0:56dd5df33ab4 386 case BLACK: *bufferPtr &= ~drawBit; break;
Helmut64 0:56dd5df33ab4 387 case INVERSE: *bufferPtr ^= drawBit; break;
Helmut64 0:56dd5df33ab4 388 }
Helmut64 0:56dd5df33ab4 389 }
Helmut64 0:56dd5df33ab4 390 }
Helmut64 0:56dd5df33ab4 391
Helmut64 0:56dd5df33ab4 392 void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress) {
Helmut64 0:56dd5df33ab4 393 uint16_t radius = height / 2;
Helmut64 0:56dd5df33ab4 394 uint16_t xRadius = x + radius;
Helmut64 0:56dd5df33ab4 395 uint16_t yRadius = y + radius;
Helmut64 0:56dd5df33ab4 396 uint16_t doubleRadius = 2 * radius;
Helmut64 0:56dd5df33ab4 397 uint16_t innerRadius = radius - 2;
Helmut64 0:56dd5df33ab4 398
Helmut64 0:56dd5df33ab4 399 setColor(WHITE);
Helmut64 0:56dd5df33ab4 400 drawCircleQuads(xRadius, yRadius, radius, 0b00000110);
Helmut64 0:56dd5df33ab4 401 drawHorizontalLine(xRadius, y, width - doubleRadius + 1);
Helmut64 0:56dd5df33ab4 402 drawHorizontalLine(xRadius, y + height, width - doubleRadius + 1);
Helmut64 0:56dd5df33ab4 403 drawCircleQuads(x + width - radius, yRadius, radius, 0b00001001);
Helmut64 0:56dd5df33ab4 404
Helmut64 0:56dd5df33ab4 405 uint16_t maxProgressWidth = (width - doubleRadius + 1) * progress / 100;
Helmut64 0:56dd5df33ab4 406
Helmut64 0:56dd5df33ab4 407 fillCircle(xRadius, yRadius, innerRadius);
Helmut64 0:56dd5df33ab4 408 fillRect(xRadius + 1, y + 2, maxProgressWidth, height - 3);
Helmut64 0:56dd5df33ab4 409 fillCircle(xRadius + maxProgressWidth, yRadius, innerRadius);
Helmut64 0:56dd5df33ab4 410 }
Helmut64 0:56dd5df33ab4 411
Helmut64 0:56dd5df33ab4 412 void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *image) {
Helmut64 0:56dd5df33ab4 413 drawInternal(xMove, yMove, width, height, image, 0, 0);
Helmut64 0:56dd5df33ab4 414 }
Helmut64 0:56dd5df33ab4 415
Helmut64 0:56dd5df33ab4 416 void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *xbm) {
Helmut64 0:56dd5df33ab4 417 int16_t widthInXbm = (width + 7) / 8;
Helmut64 0:56dd5df33ab4 418 uint8_t data = 0;
Helmut64 0:56dd5df33ab4 419
Helmut64 0:56dd5df33ab4 420 for(int16_t y = 0; y < height; y++) {
Helmut64 0:56dd5df33ab4 421 for(int16_t x = 0; x < width; x++ ) {
Helmut64 0:56dd5df33ab4 422 if (x & 7) {
Helmut64 0:56dd5df33ab4 423 data >>= 1; // Move a bit
Helmut64 0:56dd5df33ab4 424 } else { // Read new data every 8 bit
Helmut64 0:56dd5df33ab4 425 data = pgm_read_byte(xbm + (x / 8) + y * widthInXbm);
Helmut64 0:56dd5df33ab4 426 }
Helmut64 0:56dd5df33ab4 427 // if there is a bit draw it
Helmut64 0:56dd5df33ab4 428 if (data & 0x01) {
Helmut64 0:56dd5df33ab4 429 setPixel(xMove + x, yMove + y);
Helmut64 0:56dd5df33ab4 430 }
Helmut64 0:56dd5df33ab4 431 }
Helmut64 0:56dd5df33ab4 432 }
Helmut64 0:56dd5df33ab4 433 }
Helmut64 0:56dd5df33ab4 434
Helmut64 0:56dd5df33ab4 435 void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth) {
Helmut64 0:56dd5df33ab4 436 uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS);
Helmut64 0:56dd5df33ab4 437 uint8_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS);
Helmut64 0:56dd5df33ab4 438 uint16_t sizeOfJumpTable = pgm_read_byte(fontData + CHAR_NUM_POS) * JUMPTABLE_BYTES;
Helmut64 0:56dd5df33ab4 439
Helmut Tschemernjak 2:4ed55dfe5be7 440 uint16_t cursorX = 0;
Helmut Tschemernjak 2:4ed55dfe5be7 441 uint16_t cursorY = 0;
Helmut64 0:56dd5df33ab4 442
Helmut64 0:56dd5df33ab4 443 switch (textAlignment) {
Helmut64 0:56dd5df33ab4 444 case TEXT_ALIGN_CENTER_BOTH:
Helmut64 0:56dd5df33ab4 445 yMove -= textHeight >> 1;
Helmut64 0:56dd5df33ab4 446 // Fallthrough
Helmut64 0:56dd5df33ab4 447 case TEXT_ALIGN_CENTER:
Helmut64 0:56dd5df33ab4 448 xMove -= textWidth >> 1; // divide by 2
Helmut64 0:56dd5df33ab4 449 break;
Helmut64 0:56dd5df33ab4 450 case TEXT_ALIGN_RIGHT:
Helmut64 0:56dd5df33ab4 451 xMove -= textWidth;
Helmut64 0:56dd5df33ab4 452 break;
Helmut64 0:56dd5df33ab4 453 case TEXT_ALIGN_LEFT:
Helmut64 0:56dd5df33ab4 454 break;
Helmut64 0:56dd5df33ab4 455 }
Helmut64 0:56dd5df33ab4 456
Helmut64 0:56dd5df33ab4 457 // Don't draw anything if it is not on the screen.
Helmut64 0:56dd5df33ab4 458 if (xMove + textWidth < 0 || xMove > this->width() ) {return;}
Helmut64 0:56dd5df33ab4 459 if (yMove + textHeight < 0 || yMove > this->width() ) {return;}
Helmut64 0:56dd5df33ab4 460
Helmut64 0:56dd5df33ab4 461 for (uint16_t j = 0; j < textLength; j++) {
Helmut64 0:56dd5df33ab4 462 int16_t xPos = xMove + cursorX;
Helmut64 0:56dd5df33ab4 463 int16_t yPos = yMove + cursorY;
Helmut64 0:56dd5df33ab4 464
Helmut64 0:56dd5df33ab4 465 uint8_t code = text[j];
Helmut64 0:56dd5df33ab4 466 if (code >= firstChar) {
Helmut64 0:56dd5df33ab4 467 uint8_t charCode = code - firstChar;
Helmut64 0:56dd5df33ab4 468
Helmut64 0:56dd5df33ab4 469 // 4 Bytes per char code
Helmut64 0:56dd5df33ab4 470 uint8_t msbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES ); // MSB \ JumpAddress
Helmut64 0:56dd5df33ab4 471 uint8_t lsbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_LSB); // LSB /
Helmut64 0:56dd5df33ab4 472 uint8_t charByteSize = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_SIZE); // Size
Helmut64 0:56dd5df33ab4 473 uint8_t currentCharWidth = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); // Width
Helmut64 0:56dd5df33ab4 474
Helmut64 0:56dd5df33ab4 475 // Test if the char is drawable
Helmut64 0:56dd5df33ab4 476 if (!(msbJumpToChar == 255 && lsbJumpToChar == 255)) {
Helmut64 0:56dd5df33ab4 477 // Get the position of the char data
Helmut64 0:56dd5df33ab4 478 uint16_t charDataPosition = JUMPTABLE_START + sizeOfJumpTable + ((msbJumpToChar << 8) + lsbJumpToChar);
Helmut64 0:56dd5df33ab4 479 drawInternal(xPos, yPos, currentCharWidth, textHeight, fontData, charDataPosition, charByteSize);
Helmut64 0:56dd5df33ab4 480 }
Helmut64 0:56dd5df33ab4 481
Helmut64 0:56dd5df33ab4 482 cursorX += currentCharWidth;
Helmut64 0:56dd5df33ab4 483 }
Helmut64 0:56dd5df33ab4 484 }
Helmut64 0:56dd5df33ab4 485 }
Helmut64 0:56dd5df33ab4 486
Helmut64 0:56dd5df33ab4 487
Helmut64 0:56dd5df33ab4 488 void OLEDDisplay::drawString(int16_t xMove, int16_t yMove, String strUser) {
Helmut64 0:56dd5df33ab4 489 uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS);
Helmut64 0:56dd5df33ab4 490
Helmut64 0:56dd5df33ab4 491 // char* text must be freed!
Helmut64 0:56dd5df33ab4 492 char* text = utf8ascii(strUser);
Helmut64 0:56dd5df33ab4 493
Helmut64 0:56dd5df33ab4 494 uint16_t yOffset = 0;
Helmut64 0:56dd5df33ab4 495 // If the string should be centered vertically too
Helmut64 0:56dd5df33ab4 496 // we need to now how heigh the string is.
Helmut64 0:56dd5df33ab4 497 if (textAlignment == TEXT_ALIGN_CENTER_BOTH) {
Helmut64 0:56dd5df33ab4 498 uint16_t lb = 0;
Helmut64 0:56dd5df33ab4 499 // Find number of linebreaks in text
Helmut64 0:56dd5df33ab4 500 for (uint16_t i=0;text[i] != 0; i++) {
Helmut64 0:56dd5df33ab4 501 lb += (text[i] == 10);
Helmut64 0:56dd5df33ab4 502 }
Helmut64 0:56dd5df33ab4 503 // Calculate center
Helmut64 0:56dd5df33ab4 504 yOffset = (lb * lineHeight) / 2;
Helmut64 0:56dd5df33ab4 505 }
Helmut64 0:56dd5df33ab4 506
Helmut64 0:56dd5df33ab4 507 uint16_t line = 0;
Helmut64 0:56dd5df33ab4 508 char* textPart = strtok(text,"\n");
Helmut64 0:56dd5df33ab4 509 while (textPart != NULL) {
Helmut64 0:56dd5df33ab4 510 uint16_t length = strlen(textPart);
Helmut64 0:56dd5df33ab4 511 drawStringInternal(xMove, yMove - yOffset + (line++) * lineHeight, textPart, length, getStringWidth(textPart, length));
Helmut64 0:56dd5df33ab4 512 textPart = strtok(NULL, "\n");
Helmut64 0:56dd5df33ab4 513 }
Helmut64 0:56dd5df33ab4 514 free(text);
Helmut64 0:56dd5df33ab4 515 }
Helmut64 0:56dd5df33ab4 516
Helmut64 0:56dd5df33ab4 517 void OLEDDisplay::drawStringMaxWidth(int16_t xMove, int16_t yMove, uint16_t maxLineWidth, String strUser) {
Helmut64 0:56dd5df33ab4 518 uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS);
Helmut64 0:56dd5df33ab4 519 uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS);
Helmut64 0:56dd5df33ab4 520
Helmut64 0:56dd5df33ab4 521 char* text = utf8ascii(strUser);
Helmut64 0:56dd5df33ab4 522
Helmut64 0:56dd5df33ab4 523 uint16_t length = strlen(text);
Helmut64 0:56dd5df33ab4 524 uint16_t lastDrawnPos = 0;
Helmut64 0:56dd5df33ab4 525 uint16_t lineNumber = 0;
Helmut64 0:56dd5df33ab4 526 uint16_t strWidth = 0;
Helmut64 0:56dd5df33ab4 527
Helmut64 0:56dd5df33ab4 528 uint16_t preferredBreakpoint = 0;
Helmut64 0:56dd5df33ab4 529 uint16_t widthAtBreakpoint = 0;
Helmut64 0:56dd5df33ab4 530
Helmut64 0:56dd5df33ab4 531 for (uint16_t i = 0; i < length; i++) {
Helmut64 0:56dd5df33ab4 532 strWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[i] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH);
Helmut64 0:56dd5df33ab4 533
Helmut64 0:56dd5df33ab4 534 // Always try to break on a space or dash
Helmut64 0:56dd5df33ab4 535 if (text[i] == ' ' || text[i]== '-') {
Helmut64 0:56dd5df33ab4 536 preferredBreakpoint = i;
Helmut64 0:56dd5df33ab4 537 widthAtBreakpoint = strWidth;
Helmut64 0:56dd5df33ab4 538 }
Helmut64 0:56dd5df33ab4 539
Helmut64 0:56dd5df33ab4 540 if (strWidth >= maxLineWidth) {
Helmut64 0:56dd5df33ab4 541 if (preferredBreakpoint == 0) {
Helmut64 0:56dd5df33ab4 542 preferredBreakpoint = i;
Helmut64 0:56dd5df33ab4 543 widthAtBreakpoint = strWidth;
Helmut64 0:56dd5df33ab4 544 }
Helmut64 0:56dd5df33ab4 545 drawStringInternal(xMove, yMove + (lineNumber++) * lineHeight , &text[lastDrawnPos], preferredBreakpoint - lastDrawnPos, widthAtBreakpoint);
Helmut64 0:56dd5df33ab4 546 lastDrawnPos = preferredBreakpoint + 1;
Helmut64 0:56dd5df33ab4 547 // It is possible that we did not draw all letters to i so we need
Helmut64 0:56dd5df33ab4 548 // to account for the width of the chars from `i - preferredBreakpoint`
Helmut64 0:56dd5df33ab4 549 // by calculating the width we did not draw yet.
Helmut64 0:56dd5df33ab4 550 strWidth = strWidth - widthAtBreakpoint;
Helmut64 0:56dd5df33ab4 551 preferredBreakpoint = 0;
Helmut64 0:56dd5df33ab4 552 }
Helmut64 0:56dd5df33ab4 553 }
Helmut64 0:56dd5df33ab4 554
Helmut64 0:56dd5df33ab4 555 // Draw last part if needed
Helmut64 0:56dd5df33ab4 556 if (lastDrawnPos < length) {
Helmut64 0:56dd5df33ab4 557 drawStringInternal(xMove, yMove + lineNumber * lineHeight , &text[lastDrawnPos], length - lastDrawnPos, getStringWidth(&text[lastDrawnPos], length - lastDrawnPos));
Helmut64 0:56dd5df33ab4 558 }
Helmut64 0:56dd5df33ab4 559
Helmut64 0:56dd5df33ab4 560 free(text);
Helmut64 0:56dd5df33ab4 561 }
Helmut64 0:56dd5df33ab4 562
Helmut64 0:56dd5df33ab4 563 uint16_t OLEDDisplay::getStringWidth(const char* text, uint16_t length) {
Helmut64 0:56dd5df33ab4 564 uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS);
Helmut64 0:56dd5df33ab4 565
Helmut64 0:56dd5df33ab4 566 uint16_t stringWidth = 0;
Helmut64 0:56dd5df33ab4 567 uint16_t maxWidth = 0;
Helmut64 0:56dd5df33ab4 568
Helmut64 0:56dd5df33ab4 569 while (length--) {
Helmut64 0:56dd5df33ab4 570 stringWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[length] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH);
Helmut64 0:56dd5df33ab4 571 if (text[length] == 10) {
Helmut64 0:56dd5df33ab4 572 maxWidth = max(maxWidth, stringWidth);
Helmut64 0:56dd5df33ab4 573 stringWidth = 0;
Helmut64 0:56dd5df33ab4 574 }
Helmut64 0:56dd5df33ab4 575 }
Helmut64 0:56dd5df33ab4 576
Helmut64 0:56dd5df33ab4 577 return max(maxWidth, stringWidth);
Helmut64 0:56dd5df33ab4 578 }
Helmut64 0:56dd5df33ab4 579
Helmut64 0:56dd5df33ab4 580 uint16_t OLEDDisplay::getStringWidth(String strUser) {
Helmut64 0:56dd5df33ab4 581 char* text = utf8ascii(strUser);
Helmut64 0:56dd5df33ab4 582 uint16_t length = strlen(text);
Helmut64 0:56dd5df33ab4 583 uint16_t width = getStringWidth(text, length);
Helmut64 0:56dd5df33ab4 584 free(text);
Helmut64 0:56dd5df33ab4 585 return width;
Helmut64 0:56dd5df33ab4 586 }
Helmut64 0:56dd5df33ab4 587
Helmut64 0:56dd5df33ab4 588 void OLEDDisplay::setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment) {
Helmut64 0:56dd5df33ab4 589 this->textAlignment = textAlignment;
Helmut64 0:56dd5df33ab4 590 }
Helmut64 0:56dd5df33ab4 591
Helmut64 0:56dd5df33ab4 592 void OLEDDisplay::setFont(const uint8_t *fontData) {
Helmut64 0:56dd5df33ab4 593 this->fontData = fontData;
Helmut64 0:56dd5df33ab4 594 }
Helmut64 0:56dd5df33ab4 595
Helmut64 0:56dd5df33ab4 596 void OLEDDisplay::displayOn(void) {
Helmut64 0:56dd5df33ab4 597 sendCommand(DISPLAYON);
Helmut64 0:56dd5df33ab4 598 }
Helmut64 0:56dd5df33ab4 599
Helmut64 0:56dd5df33ab4 600 void OLEDDisplay::displayOff(void) {
Helmut64 0:56dd5df33ab4 601 sendCommand(DISPLAYOFF);
Helmut64 0:56dd5df33ab4 602 }
Helmut64 0:56dd5df33ab4 603
Helmut64 0:56dd5df33ab4 604 void OLEDDisplay::invertDisplay(void) {
Helmut64 0:56dd5df33ab4 605 sendCommand(INVERTDISPLAY);
Helmut64 0:56dd5df33ab4 606 }
Helmut64 0:56dd5df33ab4 607
Helmut64 0:56dd5df33ab4 608 void OLEDDisplay::normalDisplay(void) {
Helmut64 0:56dd5df33ab4 609 sendCommand(NORMALDISPLAY);
Helmut64 0:56dd5df33ab4 610 }
Helmut64 0:56dd5df33ab4 611
Helmut64 0:56dd5df33ab4 612 void OLEDDisplay::setContrast(uint8_t contrast, uint8_t precharge, uint8_t comdetect) {
Helmut64 0:56dd5df33ab4 613 sendCommand(SETPRECHARGE); //0xD9
Helmut64 0:56dd5df33ab4 614 sendCommand(precharge); //0xF1 default, to lower the contrast, put 1-1F
Helmut64 0:56dd5df33ab4 615 sendCommand(SETCONTRAST);
Helmut64 0:56dd5df33ab4 616 sendCommand(contrast); // 0-255
Helmut64 0:56dd5df33ab4 617 sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast)
Helmut64 0:56dd5df33ab4 618 sendCommand(comdetect); //0x40 default, to lower the contrast, put 0
Helmut64 0:56dd5df33ab4 619 sendCommand(DISPLAYALLON_RESUME);
Helmut64 0:56dd5df33ab4 620 sendCommand(NORMALDISPLAY);
Helmut64 0:56dd5df33ab4 621 sendCommand(DISPLAYON);
Helmut64 0:56dd5df33ab4 622 }
Helmut64 0:56dd5df33ab4 623
Helmut64 0:56dd5df33ab4 624 void OLEDDisplay::setBrightness(uint8_t brightness) {
Helmut64 0:56dd5df33ab4 625 uint8_t contrast = brightness;
Helmut64 0:56dd5df33ab4 626 if (brightness < 128) {
Helmut64 0:56dd5df33ab4 627 // Magic values to get a smooth/ step-free transition
Helmut64 0:56dd5df33ab4 628 contrast = brightness * 1.171;
Helmut64 0:56dd5df33ab4 629 } else {
Helmut64 0:56dd5df33ab4 630 contrast = brightness * 1.171 - 43;
Helmut64 0:56dd5df33ab4 631 }
Helmut64 0:56dd5df33ab4 632
Helmut64 0:56dd5df33ab4 633 uint8_t precharge = 241;
Helmut64 0:56dd5df33ab4 634 if (brightness == 0) {
Helmut64 0:56dd5df33ab4 635 precharge = 0;
Helmut64 0:56dd5df33ab4 636 }
Helmut64 0:56dd5df33ab4 637 uint8_t comdetect = brightness / 8;
Helmut64 0:56dd5df33ab4 638
Helmut64 0:56dd5df33ab4 639 setContrast(contrast, precharge, comdetect);
Helmut64 0:56dd5df33ab4 640 }
Helmut64 0:56dd5df33ab4 641
Helmut64 0:56dd5df33ab4 642 void OLEDDisplay::resetOrientation() {
Helmut64 0:56dd5df33ab4 643 sendCommand(SEGREMAP);
Helmut64 0:56dd5df33ab4 644 sendCommand(COMSCANINC); //Reset screen rotation or mirroring
Helmut64 0:56dd5df33ab4 645 }
Helmut64 0:56dd5df33ab4 646
Helmut64 0:56dd5df33ab4 647 void OLEDDisplay::flipScreenVertically() {
Helmut64 0:56dd5df33ab4 648 sendCommand(SEGREMAP | 0x01);
Helmut64 0:56dd5df33ab4 649 sendCommand(COMSCANDEC); //Rotate screen 180 Deg
Helmut64 0:56dd5df33ab4 650 }
Helmut64 0:56dd5df33ab4 651
Helmut64 0:56dd5df33ab4 652 void OLEDDisplay::mirrorScreen() {
Helmut64 0:56dd5df33ab4 653 sendCommand(SEGREMAP);
Helmut64 0:56dd5df33ab4 654 sendCommand(COMSCANDEC); //Mirror screen
Helmut64 0:56dd5df33ab4 655 }
Helmut64 0:56dd5df33ab4 656
Helmut64 0:56dd5df33ab4 657 void OLEDDisplay::clear(void) {
Helmut64 0:56dd5df33ab4 658 memset(buffer, 0, displayBufferSize);
Helmut64 0:56dd5df33ab4 659 }
Helmut64 0:56dd5df33ab4 660
Helmut64 0:56dd5df33ab4 661 void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) {
Helmut64 0:56dd5df33ab4 662 uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS);
Helmut64 0:56dd5df33ab4 663 // Always align left
Helmut64 0:56dd5df33ab4 664 setTextAlignment(TEXT_ALIGN_LEFT);
Helmut64 0:56dd5df33ab4 665
Helmut64 0:56dd5df33ab4 666 // State values
Helmut64 0:56dd5df33ab4 667 uint16_t length = 0;
Helmut64 0:56dd5df33ab4 668 uint16_t line = 0;
Helmut64 0:56dd5df33ab4 669 uint16_t lastPos = 0;
Helmut64 0:56dd5df33ab4 670
Helmut64 0:56dd5df33ab4 671 for (uint16_t i=0;i<this->logBufferFilled;i++){
Helmut64 0:56dd5df33ab4 672 // Everytime we have a \n print
Helmut64 0:56dd5df33ab4 673 if (this->logBuffer[i] == 10) {
Helmut64 0:56dd5df33ab4 674 length++;
Helmut64 0:56dd5df33ab4 675 // Draw string on line `line` from lastPos to length
Helmut64 0:56dd5df33ab4 676 // Passing 0 as the lenght because we are in TEXT_ALIGN_LEFT
Helmut64 0:56dd5df33ab4 677 drawStringInternal(xMove, yMove + (line++) * lineHeight, &this->logBuffer[lastPos], length, 0);
Helmut64 0:56dd5df33ab4 678 // Remember last pos
Helmut64 0:56dd5df33ab4 679 lastPos = i;
Helmut64 0:56dd5df33ab4 680 // Reset length
Helmut64 0:56dd5df33ab4 681 length = 0;
Helmut64 0:56dd5df33ab4 682 } else {
Helmut64 0:56dd5df33ab4 683 // Count chars until next linebreak
Helmut64 0:56dd5df33ab4 684 length++;
Helmut64 0:56dd5df33ab4 685 }
Helmut64 0:56dd5df33ab4 686 }
Helmut64 0:56dd5df33ab4 687 // Draw the remaining string
Helmut64 0:56dd5df33ab4 688 if (length > 0) {
Helmut64 0:56dd5df33ab4 689 drawStringInternal(xMove, yMove + line * lineHeight, &this->logBuffer[lastPos], length, 0);
Helmut64 0:56dd5df33ab4 690 }
Helmut64 0:56dd5df33ab4 691 }
Helmut64 0:56dd5df33ab4 692
Helmut64 0:56dd5df33ab4 693 uint16_t OLEDDisplay::getWidth(void) {
Helmut64 0:56dd5df33ab4 694 return displayWidth;
Helmut64 0:56dd5df33ab4 695 }
Helmut64 0:56dd5df33ab4 696
Helmut64 0:56dd5df33ab4 697 uint16_t OLEDDisplay::getHeight(void) {
Helmut64 0:56dd5df33ab4 698 return displayHeight;
Helmut64 0:56dd5df33ab4 699 }
Helmut64 0:56dd5df33ab4 700
Helmut64 0:56dd5df33ab4 701 bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){
Helmut64 0:56dd5df33ab4 702 if (logBuffer != NULL) free(logBuffer);
Helmut64 0:56dd5df33ab4 703 uint16_t size = lines * chars;
Helmut64 0:56dd5df33ab4 704 if (size > 0) {
Helmut64 0:56dd5df33ab4 705 this->logBufferLine = 0; // Lines printed
Helmut64 0:56dd5df33ab4 706 this->logBufferFilled = 0; // Nothing stored yet
Helmut64 0:56dd5df33ab4 707 this->logBufferMaxLines = lines; // Lines max printable
Helmut64 0:56dd5df33ab4 708 this->logBufferSize = size; // Total number of characters the buffer can hold
Helmut64 0:56dd5df33ab4 709 this->logBuffer = (char *) malloc(size * sizeof(uint8_t));
Helmut64 0:56dd5df33ab4 710 if(!this->logBuffer) {
Helmut64 0:56dd5df33ab4 711 DEBUG_OLEDDISPLAY("[OLEDDISPLAY][setLogBuffer] Not enough memory to create log buffer\n");
Helmut64 0:56dd5df33ab4 712 return false;
Helmut64 0:56dd5df33ab4 713 }
Helmut64 0:56dd5df33ab4 714 }
Helmut64 0:56dd5df33ab4 715 return true;
Helmut64 0:56dd5df33ab4 716 }
Helmut64 0:56dd5df33ab4 717
Helmut64 0:56dd5df33ab4 718 size_t OLEDDisplay::write(uint8_t c) {
Helmut64 0:56dd5df33ab4 719 if (this->logBufferSize > 0) {
Helmut64 0:56dd5df33ab4 720 // Don't waste space on \r\n line endings, dropping \r
Helmut64 0:56dd5df33ab4 721 if (c == 13) return 1;
Helmut64 0:56dd5df33ab4 722
Helmut64 0:56dd5df33ab4 723 // convert UTF-8 character to font table index
Helmut64 0:56dd5df33ab4 724 c = (this->fontTableLookupFunction)(c);
Helmut64 0:56dd5df33ab4 725 // drop unknown character
Helmut64 0:56dd5df33ab4 726 if (c == 0) return 1;
Helmut64 0:56dd5df33ab4 727
Helmut64 0:56dd5df33ab4 728 bool maxLineNotReached = this->logBufferLine < this->logBufferMaxLines;
Helmut64 0:56dd5df33ab4 729 bool bufferNotFull = this->logBufferFilled < this->logBufferSize;
Helmut64 0:56dd5df33ab4 730
Helmut64 0:56dd5df33ab4 731 // Can we write to the buffer?
Helmut64 0:56dd5df33ab4 732 if (bufferNotFull && maxLineNotReached) {
Helmut64 0:56dd5df33ab4 733 this->logBuffer[logBufferFilled] = c;
Helmut64 0:56dd5df33ab4 734 this->logBufferFilled++;
Helmut64 0:56dd5df33ab4 735 // Keep track of lines written
Helmut64 0:56dd5df33ab4 736 if (c == 10) this->logBufferLine++;
Helmut64 0:56dd5df33ab4 737 } else {
Helmut64 0:56dd5df33ab4 738 // Max line number is reached
Helmut64 0:56dd5df33ab4 739 if (!maxLineNotReached) this->logBufferLine--;
Helmut64 0:56dd5df33ab4 740
Helmut64 0:56dd5df33ab4 741 // Find the end of the first line
Helmut64 0:56dd5df33ab4 742 uint16_t firstLineEnd = 0;
Helmut64 0:56dd5df33ab4 743 for (uint16_t i=0;i<this->logBufferFilled;i++) {
Helmut64 0:56dd5df33ab4 744 if (this->logBuffer[i] == 10){
Helmut64 0:56dd5df33ab4 745 // Include last char too
Helmut64 0:56dd5df33ab4 746 firstLineEnd = i + 1;
Helmut64 0:56dd5df33ab4 747 break;
Helmut64 0:56dd5df33ab4 748 }
Helmut64 0:56dd5df33ab4 749 }
Helmut64 0:56dd5df33ab4 750 // If there was a line ending
Helmut64 0:56dd5df33ab4 751 if (firstLineEnd > 0) {
Helmut64 0:56dd5df33ab4 752 // Calculate the new logBufferFilled value
Helmut64 0:56dd5df33ab4 753 this->logBufferFilled = logBufferFilled - firstLineEnd;
Helmut64 0:56dd5df33ab4 754 // Now we move the lines infront of the buffer
Helmut64 0:56dd5df33ab4 755 memcpy(this->logBuffer, &this->logBuffer[firstLineEnd], logBufferFilled);
Helmut64 0:56dd5df33ab4 756 } else {
Helmut64 0:56dd5df33ab4 757 // Let's reuse the buffer if it was full
Helmut64 0:56dd5df33ab4 758 if (!bufferNotFull) {
Helmut64 0:56dd5df33ab4 759 this->logBufferFilled = 0;
Helmut64 0:56dd5df33ab4 760 }// else {
Helmut64 0:56dd5df33ab4 761 // Nothing to do here
Helmut64 0:56dd5df33ab4 762 //}
Helmut64 0:56dd5df33ab4 763 }
Helmut64 0:56dd5df33ab4 764 write(c);
Helmut64 0:56dd5df33ab4 765 }
Helmut64 0:56dd5df33ab4 766 }
Helmut64 0:56dd5df33ab4 767 // We are always writing all uint8_t to the buffer
Helmut64 0:56dd5df33ab4 768 return 1;
Helmut64 0:56dd5df33ab4 769 }
Helmut64 0:56dd5df33ab4 770
Helmut64 0:56dd5df33ab4 771 size_t OLEDDisplay::write(const char* str) {
Helmut64 0:56dd5df33ab4 772 if (str == NULL) return 0;
Helmut64 0:56dd5df33ab4 773 size_t length = strlen(str);
Helmut64 0:56dd5df33ab4 774 for (size_t i = 0; i < length; i++) {
Helmut64 0:56dd5df33ab4 775 write(str[i]);
Helmut64 0:56dd5df33ab4 776 }
Helmut64 0:56dd5df33ab4 777 return length;
Helmut64 0:56dd5df33ab4 778 }
Helmut64 0:56dd5df33ab4 779
Helmut64 0:56dd5df33ab4 780 #ifdef __MBED__
Helmut64 0:56dd5df33ab4 781 int OLEDDisplay::_putc(int c) {
Helmut64 0:56dd5df33ab4 782
Helmut64 0:56dd5df33ab4 783 if (!fontData)
Helmut64 0:56dd5df33ab4 784 return 1;
Helmut64 0:56dd5df33ab4 785 if (!logBufferSize) {
Helmut64 0:56dd5df33ab4 786 uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS);
Helmut64 0:56dd5df33ab4 787 uint16_t lines = this->displayHeight / textHeight;
Helmut64 0:56dd5df33ab4 788 uint16_t chars = 2 * (this->displayWidth / textHeight);
Helmut64 0:56dd5df33ab4 789
Helmut64 0:56dd5df33ab4 790 if (this->displayHeight % textHeight)
Helmut64 0:56dd5df33ab4 791 lines++;
Helmut64 0:56dd5df33ab4 792 if (this->displayWidth % textHeight)
Helmut64 0:56dd5df33ab4 793 chars++;
Helmut64 0:56dd5df33ab4 794 setLogBuffer(lines, chars);
Helmut64 0:56dd5df33ab4 795 }
Helmut64 0:56dd5df33ab4 796
Helmut64 0:56dd5df33ab4 797 return this->write((uint8_t)c);
Helmut64 0:56dd5df33ab4 798 }
Helmut64 0:56dd5df33ab4 799 #endif
Helmut64 0:56dd5df33ab4 800
Helmut64 0:56dd5df33ab4 801 // Private functions
Helmut Tschemernjak 2:4ed55dfe5be7 802 void OLEDDisplay::setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width, uint16_t height) {
Helmut64 0:56dd5df33ab4 803 this->geometry = g;
Helmut Tschemernjak 2:4ed55dfe5be7 804 switch (g) {
Helmut Tschemernjak 2:4ed55dfe5be7 805 case GEOMETRY_128_64:
Helmut Tschemernjak 2:4ed55dfe5be7 806 this->displayWidth = 128;
Helmut Tschemernjak 2:4ed55dfe5be7 807 this->displayHeight = 64;
Helmut Tschemernjak 2:4ed55dfe5be7 808 break;
Helmut Tschemernjak 2:4ed55dfe5be7 809 case GEOMETRY_128_32:
Helmut Tschemernjak 2:4ed55dfe5be7 810 this->displayWidth = 128;
Helmut Tschemernjak 2:4ed55dfe5be7 811 this->displayHeight = 32;
Helmut Tschemernjak 2:4ed55dfe5be7 812 break;
Helmut Tschemernjak 2:4ed55dfe5be7 813 case GEOMETRY_RAWMODE:
Helmut Tschemernjak 2:4ed55dfe5be7 814 this->displayWidth = width > 0 ? width : 128;
Helmut Tschemernjak 2:4ed55dfe5be7 815 this->displayHeight = height > 0 ? height : 64;
Helmut Tschemernjak 2:4ed55dfe5be7 816 break;
Helmut64 0:56dd5df33ab4 817 }
Helmut Tschemernjak 2:4ed55dfe5be7 818 this->displayBufferSize = displayWidth * displayHeight /8;
Helmut64 0:56dd5df33ab4 819 }
Helmut64 0:56dd5df33ab4 820
Helmut64 0:56dd5df33ab4 821 void OLEDDisplay::sendInitCommands(void) {
Helmut Tschemernjak 2:4ed55dfe5be7 822 if (geometry == GEOMETRY_RAWMODE)
Helmut Tschemernjak 2:4ed55dfe5be7 823 return;
Helmut64 0:56dd5df33ab4 824 sendCommand(DISPLAYOFF);
Helmut64 0:56dd5df33ab4 825 sendCommand(SETDISPLAYCLOCKDIV);
Helmut64 0:56dd5df33ab4 826 sendCommand(0xF0); // Increase speed of the display max ~96Hz
Helmut64 0:56dd5df33ab4 827 sendCommand(SETMULTIPLEX);
Helmut64 0:56dd5df33ab4 828 sendCommand(this->height() - 1);
Helmut64 0:56dd5df33ab4 829 sendCommand(SETDISPLAYOFFSET);
Helmut64 0:56dd5df33ab4 830 sendCommand(0x00);
Helmut64 0:56dd5df33ab4 831 sendCommand(SETSTARTLINE);
Helmut64 0:56dd5df33ab4 832 sendCommand(CHARGEPUMP);
Helmut64 0:56dd5df33ab4 833 sendCommand(0x14);
Helmut64 0:56dd5df33ab4 834 sendCommand(MEMORYMODE);
Helmut64 0:56dd5df33ab4 835 sendCommand(0x00);
Helmut64 0:56dd5df33ab4 836 sendCommand(SEGREMAP);
Helmut64 0:56dd5df33ab4 837 sendCommand(COMSCANINC);
Helmut64 0:56dd5df33ab4 838 sendCommand(SETCOMPINS);
Helmut64 0:56dd5df33ab4 839
Helmut64 0:56dd5df33ab4 840 if (geometry == GEOMETRY_128_64) {
Helmut64 0:56dd5df33ab4 841 sendCommand(0x12);
Helmut64 0:56dd5df33ab4 842 } else if (geometry == GEOMETRY_128_32) {
Helmut64 0:56dd5df33ab4 843 sendCommand(0x02);
Helmut64 0:56dd5df33ab4 844 }
Helmut64 0:56dd5df33ab4 845
Helmut64 0:56dd5df33ab4 846 sendCommand(SETCONTRAST);
Helmut64 0:56dd5df33ab4 847
Helmut64 0:56dd5df33ab4 848 if (geometry == GEOMETRY_128_64) {
Helmut64 0:56dd5df33ab4 849 sendCommand(0xCF);
Helmut64 0:56dd5df33ab4 850 } else if (geometry == GEOMETRY_128_32) {
Helmut64 0:56dd5df33ab4 851 sendCommand(0x8F);
Helmut64 0:56dd5df33ab4 852 }
Helmut64 0:56dd5df33ab4 853
Helmut64 0:56dd5df33ab4 854 sendCommand(SETPRECHARGE);
Helmut64 0:56dd5df33ab4 855 sendCommand(0xF1);
Helmut64 0:56dd5df33ab4 856 sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast)
Helmut64 0:56dd5df33ab4 857 sendCommand(0x40); //0x40 default, to lower the contrast, put 0
Helmut64 0:56dd5df33ab4 858 sendCommand(DISPLAYALLON_RESUME);
Helmut64 0:56dd5df33ab4 859 sendCommand(NORMALDISPLAY);
Helmut64 0:56dd5df33ab4 860 sendCommand(0x2e); // stop scroll
Helmut64 0:56dd5df33ab4 861 sendCommand(DISPLAYON);
Helmut64 0:56dd5df33ab4 862 }
Helmut64 0:56dd5df33ab4 863
Helmut64 0:56dd5df33ab4 864 void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) {
Helmut64 0:56dd5df33ab4 865 if (width < 0 || height < 0) return;
Helmut64 0:56dd5df33ab4 866 if (yMove + height < 0 || yMove > this->height()) return;
Helmut64 0:56dd5df33ab4 867 if (xMove + width < 0 || xMove > this->width()) return;
Helmut64 0:56dd5df33ab4 868
Helmut64 0:56dd5df33ab4 869 uint8_t rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0)
Helmut64 0:56dd5df33ab4 870 int8_t yOffset = yMove & 7;
Helmut64 0:56dd5df33ab4 871
Helmut64 0:56dd5df33ab4 872 bytesInData = bytesInData == 0 ? width * rasterHeight : bytesInData;
Helmut64 0:56dd5df33ab4 873
Helmut64 0:56dd5df33ab4 874 int16_t initYMove = yMove;
Helmut64 0:56dd5df33ab4 875 int8_t initYOffset = yOffset;
Helmut64 0:56dd5df33ab4 876
Helmut64 0:56dd5df33ab4 877
Helmut64 0:56dd5df33ab4 878 for (uint16_t i = 0; i < bytesInData; i++) {
Helmut64 0:56dd5df33ab4 879
Helmut64 0:56dd5df33ab4 880 // Reset if next horizontal drawing phase is started.
Helmut64 0:56dd5df33ab4 881 if ( i % rasterHeight == 0) {
Helmut64 0:56dd5df33ab4 882 yMove = initYMove;
Helmut64 0:56dd5df33ab4 883 yOffset = initYOffset;
Helmut64 0:56dd5df33ab4 884 }
Helmut64 0:56dd5df33ab4 885
Helmut64 0:56dd5df33ab4 886 uint8_t currentByte = pgm_read_byte(data + offset + i);
Helmut64 0:56dd5df33ab4 887
Helmut64 0:56dd5df33ab4 888 int16_t xPos = xMove + (i / rasterHeight);
Helmut64 0:56dd5df33ab4 889 int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * this->width();
Helmut64 0:56dd5df33ab4 890
Helmut64 0:56dd5df33ab4 891 // int16_t yScreenPos = yMove + yOffset;
Helmut64 0:56dd5df33ab4 892 int16_t dataPos = xPos + yPos;
Helmut64 0:56dd5df33ab4 893
Helmut64 0:56dd5df33ab4 894 if (dataPos >= 0 && dataPos < displayBufferSize &&
Helmut64 0:56dd5df33ab4 895 xPos >= 0 && xPos < this->width() ) {
Helmut64 0:56dd5df33ab4 896
Helmut64 0:56dd5df33ab4 897 if (yOffset >= 0) {
Helmut64 0:56dd5df33ab4 898 switch (this->color) {
Helmut64 0:56dd5df33ab4 899 case WHITE: buffer[dataPos] |= currentByte << yOffset; break;
Helmut64 0:56dd5df33ab4 900 case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break;
Helmut64 0:56dd5df33ab4 901 case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break;
Helmut64 0:56dd5df33ab4 902 }
Helmut64 0:56dd5df33ab4 903
Helmut64 0:56dd5df33ab4 904 if (dataPos < (displayBufferSize - this->width())) {
Helmut64 0:56dd5df33ab4 905 switch (this->color) {
Helmut64 0:56dd5df33ab4 906 case WHITE: buffer[dataPos + this->width()] |= currentByte >> (8 - yOffset); break;
Helmut64 0:56dd5df33ab4 907 case BLACK: buffer[dataPos + this->width()] &= ~(currentByte >> (8 - yOffset)); break;
Helmut64 0:56dd5df33ab4 908 case INVERSE: buffer[dataPos + this->width()] ^= currentByte >> (8 - yOffset); break;
Helmut64 0:56dd5df33ab4 909 }
Helmut64 0:56dd5df33ab4 910 }
Helmut64 0:56dd5df33ab4 911 } else {
Helmut64 0:56dd5df33ab4 912 // Make new offset position
Helmut64 0:56dd5df33ab4 913 yOffset = -yOffset;
Helmut64 0:56dd5df33ab4 914
Helmut64 0:56dd5df33ab4 915 switch (this->color) {
Helmut64 0:56dd5df33ab4 916 case WHITE: buffer[dataPos] |= currentByte >> yOffset; break;
Helmut64 0:56dd5df33ab4 917 case BLACK: buffer[dataPos] &= ~(currentByte >> yOffset); break;
Helmut64 0:56dd5df33ab4 918 case INVERSE: buffer[dataPos] ^= currentByte >> yOffset; break;
Helmut64 0:56dd5df33ab4 919 }
Helmut64 0:56dd5df33ab4 920
Helmut64 0:56dd5df33ab4 921 // Prepare for next iteration by moving one block up
Helmut64 0:56dd5df33ab4 922 yMove -= 8;
Helmut64 0:56dd5df33ab4 923
Helmut64 0:56dd5df33ab4 924 // and setting the new yOffset
Helmut64 0:56dd5df33ab4 925 yOffset = 8 - yOffset;
Helmut64 0:56dd5df33ab4 926 }
Helmut64 0:56dd5df33ab4 927 #ifndef __MBED__
Helmut64 0:56dd5df33ab4 928 yield();
Helmut64 0:56dd5df33ab4 929 #endif
Helmut64 0:56dd5df33ab4 930 }
Helmut64 0:56dd5df33ab4 931 }
Helmut64 0:56dd5df33ab4 932 }
Helmut64 0:56dd5df33ab4 933
Helmut64 0:56dd5df33ab4 934 // You need to free the char!
Helmut64 0:56dd5df33ab4 935 char* OLEDDisplay::utf8ascii(String str) {
Helmut64 0:56dd5df33ab4 936 uint16_t k = 0;
Helmut64 0:56dd5df33ab4 937 uint16_t length = str.length() + 1;
Helmut64 0:56dd5df33ab4 938
Helmut64 0:56dd5df33ab4 939 // Copy the string into a char array
Helmut64 0:56dd5df33ab4 940 char* s = (char*) malloc(length * sizeof(char));
Helmut64 0:56dd5df33ab4 941 if(!s) {
Helmut64 0:56dd5df33ab4 942 DEBUG_OLEDDISPLAY("[OLEDDISPLAY][utf8ascii] Can't allocate another char array. Drop support for UTF-8.\n");
Helmut64 0:56dd5df33ab4 943 return (char*) str.c_str();
Helmut64 0:56dd5df33ab4 944 }
Helmut64 0:56dd5df33ab4 945 str.toCharArray(s, length);
Helmut64 0:56dd5df33ab4 946
Helmut64 0:56dd5df33ab4 947 length--;
Helmut64 0:56dd5df33ab4 948
Helmut64 0:56dd5df33ab4 949 for (uint16_t i=0; i < length; i++) {
Helmut64 0:56dd5df33ab4 950 char c = (this->fontTableLookupFunction)(s[i]);
Helmut64 0:56dd5df33ab4 951 if (c!=0) {
Helmut64 0:56dd5df33ab4 952 s[k++]=c;
Helmut64 0:56dd5df33ab4 953 }
Helmut64 0:56dd5df33ab4 954 }
Helmut64 0:56dd5df33ab4 955
Helmut64 0:56dd5df33ab4 956 s[k]=0;
Helmut64 0:56dd5df33ab4 957
Helmut64 0:56dd5df33ab4 958 // This will leak 's' be sure to free it in the calling function.
Helmut64 0:56dd5df33ab4 959 return s;
Helmut64 0:56dd5df33ab4 960 }
Helmut64 0:56dd5df33ab4 961
Helmut64 0:56dd5df33ab4 962 void OLEDDisplay::setFontTableLookupFunction(FontTableLookupFunction function) {
Helmut64 0:56dd5df33ab4 963 this->fontTableLookupFunction = function;
Helmut64 0:56dd5df33ab4 964 }
Helmut64 0:56dd5df33ab4 965
Helmut64 0:56dd5df33ab4 966
Helmut Tschemernjak 2:4ed55dfe5be7 967 char DefaultFontTableLookup(const uint8_t ch) {
Helmut64 0:56dd5df33ab4 968 // UTF-8 to font table index converter
Helmut64 0:56dd5df33ab4 969 // Code form http://playground.arduino.cc/Main/Utf8ascii
Helmut64 0:56dd5df33ab4 970 static uint8_t LASTCHAR;
Helmut64 0:56dd5df33ab4 971
Helmut64 0:56dd5df33ab4 972 if (ch < 128) { // Standard ASCII-set 0..0x7F handling
Helmut64 0:56dd5df33ab4 973 LASTCHAR = 0;
Helmut64 0:56dd5df33ab4 974 return ch;
Helmut64 0:56dd5df33ab4 975 }
Helmut64 0:56dd5df33ab4 976
Helmut64 0:56dd5df33ab4 977 uint8_t last = LASTCHAR; // get last char
Helmut64 0:56dd5df33ab4 978 LASTCHAR = ch;
Helmut64 0:56dd5df33ab4 979
Helmut64 0:56dd5df33ab4 980 switch (last) { // conversion depnding on first UTF8-character
Helmut64 0:56dd5df33ab4 981 case 0xC2: return (uint8_t) ch;
Helmut64 0:56dd5df33ab4 982 case 0xC3: return (uint8_t) (ch | 0xC0);
Helmut64 0:56dd5df33ab4 983 case 0x82: if (ch == 0xAC) return (uint8_t) 0x80; // special case Euro-symbol
Helmut64 0:56dd5df33ab4 984 }
Helmut64 0:56dd5df33ab4 985
Helmut64 0:56dd5df33ab4 986 return (uint8_t) 0; // otherwise: return zero, if character has to be ignored
Helmut64 0:56dd5df33ab4 987 }