From e2512bde8c95765db690e4bb7a813ccc697d8a01 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Wed, 10 Apr 2019 13:51:30 +0200 Subject: [PATCH 01/17] Added getBufferOffset function into the drivers Added I2C mbed uspport via SSD1306I2C.h --- src/SH1106Brzo.h | 3 + src/SH1106Spi.h | 3 + src/SH1106Wire.h | 3 + src/SSD1306Brzo.h | 3 + src/SSD1306I2C.h | 149 ++++++++++++++++++++++++++++++++++++++++++++++ src/SSD1306Spi.h | 3 + src/SSD1306Wire.h | 3 + 7 files changed, 167 insertions(+) create mode 100644 src/SSD1306I2C.h diff --git a/src/SH1106Brzo.h b/src/SH1106Brzo.h index 8ef3d5b..be9c0c7 100644 --- a/src/SH1106Brzo.h +++ b/src/SH1106Brzo.h @@ -127,6 +127,9 @@ class SH1106Brzo : public OLEDDisplay { } private: + int getBufferOffset(void) { + return 0; + } inline void sendCommand(uint8_t com) __attribute__((always_inline)){ uint8_t command[2] = {0x80 /* command mode */, com}; brzo_i2c_start_transaction(_address, BRZO_I2C_SPEED); diff --git a/src/SH1106Spi.h b/src/SH1106Spi.h index cf8f088..23693bc 100644 --- a/src/SH1106Spi.h +++ b/src/SH1106Spi.h @@ -123,6 +123,9 @@ class SH1106Spi : public OLEDDisplay { } private: + int getBufferOffset(void) { + return 0; + } inline void sendCommand(uint8_t com) __attribute__((always_inline)){ digitalWrite(_dc, LOW); SPI.transfer(com); diff --git a/src/SH1106Wire.h b/src/SH1106Wire.h index 486ba1a..b088807 100644 --- a/src/SH1106Wire.h +++ b/src/SH1106Wire.h @@ -144,6 +144,9 @@ class SH1106Wire : public OLEDDisplay { } private: + int getBufferOffset(void) { + return 0; + } inline void sendCommand(uint8_t command) __attribute__((always_inline)){ Wire.beginTransmission(_address); Wire.write(0x80); diff --git a/src/SSD1306Brzo.h b/src/SSD1306Brzo.h index e90b7b3..987dd5b 100644 --- a/src/SSD1306Brzo.h +++ b/src/SSD1306Brzo.h @@ -148,6 +148,9 @@ class SSD1306Brzo : public OLEDDisplay { } private: + int getBufferOffset(void) { + return 0; + } inline void sendCommand(uint8_t com) __attribute__((always_inline)){ uint8_t command[2] = {0x80 /* command mode */, com}; brzo_i2c_start_transaction(_address, BRZO_I2C_SPEED); diff --git a/src/SSD1306I2C.h b/src/SSD1306I2C.h new file mode 100644 index 0000000..7241ded --- /dev/null +++ b/src/SSD1306I2C.h @@ -0,0 +1,149 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef SSD1306I2C_h +#define SSD1306I2C_h + + +#ifdef __MBED__ + +#include "OLEDDisplay.h" +#include + +class SSD1306I2C : public OLEDDisplay { +public: + SSD1306I2C(uint8_t _address, PinName _sda, PinName _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { + setGeometry(g); + + this->_address = _address << 1; // convert from 7 to 8 bit for mbed. + this->_sda = _sda; + this->_scl = _scl; + _i2c = new I2C(_sda, _scl); + } + + bool connect() { + // mbed supports 100k and 400k some device maybe 1000k +#ifdef TARGET_STM32L4 + _i2c->frequency(1000000); +#else + _i2c->frequency(400000); +#endif + return true; + } + + void display(void) { + const int x_offset = (128 - this->width()) / 2; +#ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t minBoundY = UINT8_MAX; + uint8_t maxBoundY = 0; + + uint8_t minBoundX = UINT8_MAX; + uint8_t maxBoundX = 0; + uint8_t x, y; + + // Calculate the Y bounding box of changes + // and copy buffer[pos] to buffer_back[pos]; + for (y = 0; y < (this->height() / 8); y++) { + for (x = 0; x < this->width(); x++) { + uint16_t pos = x + y * this->width(); + if (buffer[pos] != buffer_back[pos]) { + minBoundY = std::min(minBoundY, y); + maxBoundY = std::max(maxBoundY, y); + minBoundX = std::min(minBoundX, x); + maxBoundX = std::max(maxBoundX, x); + } + buffer_back[pos] = buffer[pos]; + } + yield(); + } + + // If the minBoundY wasn't updated + // we can savely assume that buffer_back[pos] == buffer[pos] + // holdes true for all values of pos + + if (minBoundY == UINT8_MAX) return; + + sendCommand(COLUMNADDR); + sendCommand(x_offset + minBoundX); // column start address (0 = reset) + sendCommand(x_offset + maxBoundX); // column end address (127 = reset) + + sendCommand(PAGEADDR); + sendCommand(minBoundY); // page start address + sendCommand(maxBoundY); // page end address + + for (y = minBoundY; y <= maxBoundY; y++) { + uint8_t *start = &buffer[(minBoundX + y * this->width())-1]; + uint8_t save = *start; + + *start = 0x40; // control + _i2c->write(_address, (char *)start, (maxBoundX-minBoundX) + 1 + 1); + *start = save; + } +#else + + sendCommand(COLUMNADDR); + sendCommand(x_offset); // column start address (0 = reset) + sendCommand(x_offset + (this->width() - 1));// column end address (127 = reset) + + sendCommand(PAGEADDR); + sendCommand(0x0); // page start address (0 = reset) + sendCommand((this->height() / 8) - 1); // page end address 7 + + if (geometry == GEOMETRY_128_64) { + sendCommand(0x7); + } else if (geometry == GEOMETRY_128_32) { + sendCommand(0x3); + } + + buffer[-1] = 0x40; // control + _i2c->write(_address, (char *)&buffer[-1], displayBufferSize + 1); +#endif + } + +private: + int getBufferOffset(void) { + return 0; + } + + inline void sendCommand(uint8_t command) __attribute__((always_inline)) { + char _data[2]; + _data[0] = 0x80; // control + _data[1] = command; + int ret = _i2c->write(_address, _data, sizeof(_data)); + } + + uint8_t _address; + PinName _sda; + PinName _scl; + I2C *_i2c; +}; + +#endif + +#endif diff --git a/src/SSD1306Spi.h b/src/SSD1306Spi.h index 988dc2c..e1b6458 100644 --- a/src/SSD1306Spi.h +++ b/src/SSD1306Spi.h @@ -148,6 +148,9 @@ class SSD1306Spi : public OLEDDisplay { } private: + int getBufferOffset(void) { + return 0; + } inline void sendCommand(uint8_t com) __attribute__((always_inline)){ digitalWrite(_cs, HIGH); digitalWrite(_dc, LOW); diff --git a/src/SSD1306Wire.h b/src/SSD1306Wire.h index a3d0a05..b2324d7 100644 --- a/src/SSD1306Wire.h +++ b/src/SSD1306Wire.h @@ -154,6 +154,9 @@ class SSD1306Wire : public OLEDDisplay { } private: + int getBufferOffset(void) { + return 0; + } inline void sendCommand(uint8_t command) __attribute__((always_inline)){ initI2cIfNeccesary(); Wire.beginTransmission(_address); From 6d36ef58bebf3564e315b1d56442ce4353981bc1 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Wed, 10 Apr 2019 13:54:59 +0200 Subject: [PATCH 02/17] Define PROGMEM as emtpy on mbed to omit PROGMEM for mbed-os --- src/OLEDDisplayFonts.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/OLEDDisplayFonts.h b/src/OLEDDisplayFonts.h index 3544edb..abc61ba 100644 --- a/src/OLEDDisplayFonts.h +++ b/src/OLEDDisplayFonts.h @@ -1,6 +1,10 @@ #ifndef OLEDDISPLAYFONTS_h #define OLEDDISPLAYFONTS_h +#ifdef __MBED__ +#define PROGMEM +#endif + const uint8_t ArialMT_Plain_10[] PROGMEM = { 0x0A, // Width: 10 0x0D, // Height: 13 From 8f4518fc2a3dcce3307bbfd2a81563aa41c509d5 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Wed, 10 Apr 2019 14:18:39 +0200 Subject: [PATCH 03/17] Removed warning --- src/SSD1306I2C.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SSD1306I2C.h b/src/SSD1306I2C.h index 7241ded..d161588 100644 --- a/src/SSD1306I2C.h +++ b/src/SSD1306I2C.h @@ -135,7 +135,7 @@ class SSD1306I2C : public OLEDDisplay { char _data[2]; _data[0] = 0x80; // control _data[1] = command; - int ret = _i2c->write(_address, _data, sizeof(_data)); + _i2c->write(_address, _data, sizeof(_data)); } uint8_t _address; From 4a732ec4087e9360e288c4b4045f1403f085f0ca Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Wed, 10 Apr 2019 14:27:17 +0200 Subject: [PATCH 04/17] Added display library support for mbed-os. At preset with SSD1306 with I2C, more displays and SPI will follow later. Added for mbed a very simple Arduino String emulation which allows to call drawString using UTF8 chars. Changed the Arduino byte into an uint8_t to be mbed compatible. Support the mbed-os Stream class (Arduino uses Print) mbed-os does not support C++11 initialisers in .h class files therefore I initialise variables in the constructor. Changed initialisers functions (fontTableLookupFunction, loadingDrawFunction) to be separate functions to support the mbed-os compiler To use the library for mbed-os copy the following files into your mbed-os project: OLEDDisplay.cpp OLEDDisplayFonts.h OLEDDisplayUi.h OLEDDisplay.h OLEDDisplayUi.cpp SSD1306I2C.h --- src/OLEDDisplay.cpp | 100 ++++++++++++++++++++++++++++++++++------ src/OLEDDisplay.h | 105 +++++++++++++++++++++++++++--------------- src/OLEDDisplayUi.cpp | 45 +++++++++++++++++- src/OLEDDisplayUi.h | 53 +++++++++++---------- 4 files changed, 226 insertions(+), 77 deletions(-) diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index 2c0c72a..4a507af 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -3,6 +3,7 @@ * * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn * Copyright (c) 2018 by Fabrice Weinberg + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,20 +29,47 @@ * */ + /* + * TODO Helmut + * - test/finish dislplay.printf() on mbed-os + * - Finish _putc with drawLogBuffer when running display + * - Fix problem that the x is larger than 0 (somehow shifted display) on single buffer + */ + #include "OLEDDisplay.h" +OLEDDisplay::OLEDDisplay() { + + displayWidth = 128; + displayHeight = 64; + displayBufferSize = 1024; + color = WHITE; + geometry = GEOMETRY_128_64; + textAlignment = TEXT_ALIGN_LEFT; + fontData = ArialMT_Plain_10; + fontTableLookupFunction = DefaultFontTableLookup; +} + OLEDDisplay::~OLEDDisplay() { end(); } bool OLEDDisplay::init() { + + logBufferSize = 0; + logBufferFilled = 0; + logBufferLine = 0; + logBufferMaxLines = 0; + logBuffer = NULL; + if (!this->connect()) { DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n"); return false; } if(this->buffer==NULL) { - this->buffer = (uint8_t*) malloc(sizeof(uint8_t) * displayBufferSize); + this->buffer = (uint8_t*) malloc((sizeof(uint8_t) * displayBufferSize) + getBufferOffset()); + this->buffer += getBufferOffset(); if(!this->buffer) { DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create display\n"); @@ -51,11 +79,12 @@ bool OLEDDisplay::init() { #ifdef OLEDDISPLAY_DOUBLE_BUFFER if(this->buffer_back==NULL) { - this->buffer_back = (uint8_t*) malloc(sizeof(uint8_t) * displayBufferSize); + this->buffer_back = (uint8_t*) malloc((sizeof(uint8_t) * displayBufferSize) + getBufferOffset()); + this->buffer_back += getBufferOffset(); if(!this->buffer_back) { DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n"); - free(this->buffer); + free(this->buffer - getBufferOffset()); return false; } } @@ -68,9 +97,9 @@ bool OLEDDisplay::init() { } void OLEDDisplay::end() { - if (this->buffer) { free(this->buffer); this->buffer = NULL; } + if (this->buffer) { free(this->buffer - getBufferOffset()); this->buffer = NULL; } #ifdef OLEDDISPLAY_DOUBLE_BUFFER - if (this->buffer_back) { free(this->buffer_back); this->buffer_back = NULL; } + if (this->buffer_back) { free(this->buffer_back - getBufferOffset()); this->buffer_back = NULL; } #endif if (this->logBuffer != NULL) { free(this->logBuffer); this->logBuffer = NULL; } } @@ -419,15 +448,15 @@ void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, u int16_t xPos = xMove + cursorX; int16_t yPos = yMove + cursorY; - byte code = text[j]; + uint8_t code = text[j]; if (code >= firstChar) { - byte charCode = code - firstChar; + uint8_t charCode = code - firstChar; // 4 Bytes per char code - byte msbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES ); // MSB \ JumpAddress - byte lsbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_LSB); // LSB / - byte charByteSize = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_SIZE); // Size - byte currentCharWidth = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); // Width + uint8_t msbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES ); // MSB \ JumpAddress + uint8_t lsbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_LSB); // LSB / + uint8_t charByteSize = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_SIZE); // Size + uint8_t currentCharWidth = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); // Width // Test if the char is drawable if (!(msbJumpToChar == 255 && lsbJumpToChar == 255)) { @@ -734,6 +763,27 @@ size_t OLEDDisplay::write(const char* str) { return length; } +#ifdef __MBED__ +int OLEDDisplay::_putc(int c) { + + if (!fontData) + return 1; + if (!logBufferSize) { + uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS); + uint16_t lines = this->displayHeight / textHeight; + uint16_t chars = 2 * (this->displayWidth / textHeight); + + if (this->displayHeight % textHeight) + lines++; + if (this->displayWidth % textHeight) + chars++; + setLogBuffer(lines, chars); + } + + return this->write((uint8_t)c); +} +#endif + // Private functions void OLEDDisplay::setGeometry(OLEDDISPLAY_GEOMETRY g) { this->geometry = g; @@ -810,7 +860,7 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt yOffset = initYOffset; } - byte currentByte = pgm_read_byte(data + offset + i); + uint8_t currentByte = pgm_read_byte(data + offset + i); int16_t xPos = xMove + (i / rasterHeight); int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * this->width(); @@ -851,8 +901,9 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt // and setting the new yOffset yOffset = 8 - yOffset; } - +#ifndef __MBED__ yield(); +#endif } } } @@ -888,3 +939,26 @@ char* OLEDDisplay::utf8ascii(String str) { void OLEDDisplay::setFontTableLookupFunction(FontTableLookupFunction function) { this->fontTableLookupFunction = function; } + + +char DefaultFontTableLookup(const char ch) { + // UTF-8 to font table index converter + // Code form http://playground.arduino.cc/Main/Utf8ascii + static uint8_t LASTCHAR; + + if (ch < 128) { // Standard ASCII-set 0..0x7F handling + LASTCHAR = 0; + return ch; + } + + uint8_t last = LASTCHAR; // get last char + LASTCHAR = ch; + + switch (last) { // conversion depnding on first UTF8-character + case 0xC2: return (uint8_t) ch; + case 0xC3: return (uint8_t) (ch | 0xC0); + case 0x82: if (ch == 0xAC) return (uint8_t) 0x80; // special case Euro-symbol + } + + return (uint8_t) 0; // otherwise: return zero, if character has to be ignored +} diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index ddf80bd..cec1e68 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -3,6 +3,7 @@ * * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn * Copyright (c) 2018 by Fabrice Weinberg + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,10 +32,39 @@ #ifndef OLEDDISPLAY_h #define OLEDDISPLAY_h +#ifdef ARDUINO #include +#elif __MBED__ +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + +#include +#define delay(x) wait_ms(x) +#define yield() void() + +/* + * This is a little Arduino String emulation to keep the OLEDDisplay + * library code in common between Arduino and mbed-os + */ +class String { +public: + String(const char *s) { _str = s; }; + int length() { return strlen(_str); }; + const char *c_str() { return _str; }; + void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const { + memcpy(buf, _str + index, std::min(bufsize, strlen(_str))); + }; +private: + const char *_str; +}; + +#else +#error "Unkown operating system" +#endif + #include "OLEDDisplayFonts.h" //#define DEBUG_OLEDDISPLAY(...) Serial.printf( __VA_ARGS__ ) +//#define DEBUG_OLEDDISPLAY(...) dprintf("%s", __VA_ARGS__ ) #ifndef DEBUG_OLEDDISPLAY #define DEBUG_OLEDDISPLAY(...) @@ -110,16 +140,24 @@ enum OLEDDISPLAY_GEOMETRY { GEOMETRY_128_32 = 1 }; -typedef byte (*FontTableLookupFunction)(const byte ch); +typedef char (*FontTableLookupFunction)(const char ch); +char DefaultFontTableLookup(const char ch); -class OLEDDisplay : public Print { +#ifdef ARDUINO +class OLEDDisplay : public Print { +#elif __MBED__ +class OLEDDisplay : public Stream { +#else +#error "Unkown operating system" +#endif public: + OLEDDisplay(); virtual ~OLEDDisplay(); - const uint16_t width(void) const { return displayWidth; }; - const uint16_t height(void) const { return displayHeight; }; + uint16_t width(void) const { return displayWidth; }; + uint16_t height(void) const { return displayHeight; }; // Initialize the display bool init(); @@ -257,6 +295,13 @@ class OLEDDisplay : public Print { // Implement needed function to be compatible with Print class size_t write(uint8_t c); size_t write(const char* s); + + // Implement needed function to be compatible with Stream class +#ifdef __MBED__ + int _putc(int c); + int _getc() { return -1; }; +#endif + uint8_t *buffer = NULL; @@ -266,27 +311,31 @@ class OLEDDisplay : public Print { protected: - OLEDDISPLAY_GEOMETRY geometry = GEOMETRY_128_64; + OLEDDISPLAY_GEOMETRY geometry; - uint16_t displayWidth = 128; - uint16_t displayHeight = 64; - uint16_t displayBufferSize = 1024; + uint16_t displayWidth; + uint16_t displayHeight; + uint16_t displayBufferSize; // Set the correct height, width and buffer for the geometry void setGeometry(OLEDDISPLAY_GEOMETRY g); - OLEDDISPLAY_TEXT_ALIGNMENT textAlignment = TEXT_ALIGN_LEFT; - OLEDDISPLAY_COLOR color = WHITE; + OLEDDISPLAY_TEXT_ALIGNMENT textAlignment; + OLEDDISPLAY_COLOR color; - const uint8_t *fontData = ArialMT_Plain_10; + const uint8_t *fontData; // State values for logBuffer - uint16_t logBufferSize = 0; - uint16_t logBufferFilled = 0; - uint16_t logBufferLine = 0; - uint16_t logBufferMaxLines = 0; - char *logBuffer = NULL; + uint16_t logBufferSize; + uint16_t logBufferFilled; + uint16_t logBufferLine; + uint16_t logBufferMaxLines; + char *logBuffer; + + // the header size of the buffer used, e.g. for the SPI command header + virtual int getBufferOffset(void) = 0; + // Send a command to the display (low level function) virtual void sendCommand(uint8_t com) {(void)com;}; @@ -302,28 +351,8 @@ class OLEDDisplay : public Print { void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline)); void drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth); - - // UTF-8 to font table index converter - // Code form http://playground.arduino.cc/Main/Utf8ascii - FontTableLookupFunction fontTableLookupFunction = [](const byte ch) { - static uint8_t LASTCHAR; - - if (ch < 128) { // Standard ASCII-set 0..0x7F handling - LASTCHAR = 0; - return ch; - } - - uint8_t last = LASTCHAR; // get last char - LASTCHAR = ch; - - switch (last) { // conversion depnding on first UTF8-character - case 0xC2: return (uint8_t) ch; - case 0xC3: return (uint8_t) (ch | 0xC0); - case 0x82: if (ch == 0xAC) return (uint8_t) 0x80; // special case Euro-symbol - } - - return (uint8_t) 0; // otherwise: return zero, if character has to be ignored - }; + + FontTableLookupFunction fontTableLookupFunction; }; #endif diff --git a/src/OLEDDisplayUi.cpp b/src/OLEDDisplayUi.cpp index cd371a0..5cfeb01 100644 --- a/src/OLEDDisplayUi.cpp +++ b/src/OLEDDisplayUi.cpp @@ -3,6 +3,7 @@ * * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn * Copyright (c) 2018 by Fabrice Weinberg + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,8 +31,36 @@ #include "OLEDDisplayUi.h" +void LoadingDrawDefault(OLEDDisplay *display, LoadingStage* stage, uint8_t progress) { + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->setFont(ArialMT_Plain_10); + display->drawString(64, 18, stage->process); + display->drawProgressBar(4, 32, 120, 8, progress); +}; + + OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) { this->display = display; + + indicatorPosition = BOTTOM; + indicatorDirection = LEFT_RIGHT; + activeSymbol = ANIMATION_activeSymbol; + inactiveSymbol = ANIMATION_inactiveSymbol; + frameAnimationDirection = SLIDE_RIGHT; + lastTransitionDirection = 1; + ticksPerFrame = 151; // ~ 5000ms at 30 FPS + ticksPerTransition = 15; // ~ 500ms at 30 FPS + frameCount = 0; + nextFrameNumber = -1; + overlayCount = 0; + indicatorDrawState = 1; + loadingDrawFunction = LoadingDrawDefault; + updateInterval = 33; + state.lastUpdate = 0; + state.ticksSinceLastStateSwitch = 0; + state.frameState = FIXED; + state.currentFrame = 0; + state.frameTransitionDirection = 1; } void OLEDDisplayUi::init() { @@ -194,7 +223,15 @@ OLEDDisplayUiState* OLEDDisplayUi::getUiState(){ int8_t OLEDDisplayUi::update(){ +#ifdef ARDUINO unsigned long frameStart = millis(); +#elif __MBED__ + Timer t; + t.start(); + unsigned long frameStart = t.read_ms(); +#else +#error "Unkown operating system" +#endif int8_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate); if ( timeBudget <= 0) { // Implement frame skipping to ensure time budget is keept @@ -203,7 +240,13 @@ int8_t OLEDDisplayUi::update(){ this->state.lastUpdate = frameStart; this->tick(); } +#ifdef ARDUINO return this->updateInterval - (millis() - frameStart); +#elif __MBED__ + return this->updateInterval - (t.read_ms() - frameStart); +#else +#error "Unkown operating system" +#endif } @@ -378,7 +421,7 @@ void OLEDDisplayUi::drawIndicator() { uint16_t x = 0,y = 0; - for (byte i = 0; i < this->frameCount; i++) { + for (uint8_t i = 0; i < this->frameCount; i++) { switch (this->indicatorPosition){ case TOP: diff --git a/src/OLEDDisplayUi.h b/src/OLEDDisplayUi.h index 2cabf30..e6f992a 100644 --- a/src/OLEDDisplayUi.h +++ b/src/OLEDDisplayUi.h @@ -3,6 +3,7 @@ * * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn * Copyright (c) 2018 by Fabrice Weinberg + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +32,14 @@ #ifndef OLEDDISPLAYUI_h #define OLEDDISPLAYUI_h +#ifdef ARDUINO #include +#elif __MBED__ +#include +#else +#error "Unkown operating system" +#endif + #include "OLEDDisplay.h" //#define DEBUG_OLEDDISPLAYUI(...) Serial.printf( __VA_ARGS__ ) @@ -76,16 +84,16 @@ const uint8_t ANIMATION_inactiveSymbol[] PROGMEM = { // Structure of the UiState struct OLEDDisplayUiState { - uint64_t lastUpdate = 0; - uint16_t ticksSinceLastStateSwitch = 0; + uint64_t lastUpdate; + uint16_t ticksSinceLastStateSwitch; - FrameState frameState = FIXED; - uint8_t currentFrame = 0; + FrameState frameState; + uint8_t currentFrame; bool isIndicatorDrawen = true; // Normal = 1, Inverse = -1; - int8_t frameTransitionDirection = 1; + int8_t frameTransitionDirection; bool manuelControll = false; @@ -107,54 +115,49 @@ class OLEDDisplayUi { OLEDDisplay *display; // Symbols for the Indicator - IndicatorPosition indicatorPosition = BOTTOM; - IndicatorDirection indicatorDirection = LEFT_RIGHT; + IndicatorPosition indicatorPosition; + IndicatorDirection indicatorDirection; - const uint8_t* activeSymbol = ANIMATION_activeSymbol; - const uint8_t* inactiveSymbol = ANIMATION_inactiveSymbol; + const uint8_t* activeSymbol; + const uint8_t* inactiveSymbol; bool shouldDrawIndicators = true; // Values for the Frames - AnimationDirection frameAnimationDirection = SLIDE_RIGHT; + AnimationDirection frameAnimationDirection; - int8_t lastTransitionDirection = 1; + int8_t lastTransitionDirection; - uint16_t ticksPerFrame = 151; // ~ 5000ms at 30 FPS - uint16_t ticksPerTransition = 15; // ~ 500ms at 30 FPS + uint16_t ticksPerFrame; // ~ 5000ms at 30 FPS + uint16_t ticksPerTransition; // ~ 500ms at 30 FPS bool autoTransition = true; FrameCallback* frameFunctions; - uint8_t frameCount = 0; + uint8_t frameCount; // Internally used to transition to a specific frame - int8_t nextFrameNumber = -1; + int8_t nextFrameNumber; // Values for Overlays OverlayCallback* overlayFunctions; - uint8_t overlayCount = 0; + uint8_t overlayCount; // Will the Indicator be drawen // 3 Not drawn in both frames // 2 Drawn this frame but not next // 1 Not drown this frame but next // 0 Not known yet - uint8_t indicatorDrawState = 1; + uint8_t indicatorDrawState; // Loading screen - LoadingDrawFunction loadingDrawFunction = [](OLEDDisplay *display, LoadingStage* stage, uint8_t progress) { - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->setFont(ArialMT_Plain_10); - display->drawString(64, 18, stage->process); - display->drawProgressBar(4, 32, 120, 8, progress); - }; - + LoadingDrawFunction loadingDrawFunction; + // UI State OLEDDisplayUiState state; // Bookeeping for update - uint8_t updateInterval = 33; + uint8_t updateInterval; uint8_t getNextFrameNumber(); void drawIndicator(); From 59e7bbf74b6031e2a081eb056c0ae90496a7b83d Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Wed, 10 Apr 2019 14:47:34 +0200 Subject: [PATCH 05/17] Updated with mbed-os info --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4f04d4e..9af3f3c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ [![Build Status](https://travis-ci.org/ThingPulse/esp8266-oled-ssd1306.svg?branch=master)](https://travis-ci.org/ThingPulse/esp8266-oled-ssd1306) -# ThingPulse ESP8266 OLED SSD1306 +# ThingPulse OLED SSD1306 (ESP8266/ESP32/Mbed-OS) > We just released version 4.0.0. Please have a look at our [upgrade guide](UPGRADE-4.0.md) -This is a driver for the SSD1306 based 128x64 pixel OLED display running on the Arduino/ESP8266 platform. +This is a driver for the SSD1306 based 128x64 pixel OLED display running on the Arduino (ESP8266 and ESP32) and mbed-os platform. Can be used with either the I2C or SPI version of the display -You can either download this library as a zip file and unpack it to your Arduino/libraries folder or (once it has been added) choose it from the Arduino library manager. +You can either download this library as a zip file and unpack it to your Arduino/libraries folder or (once it has been added) choose it from the Arduino library manager. For mbed-os a copy of the files are available as an mbed-os library It is also available as a platformio library. Just execute the following command: ``` @@ -24,6 +24,9 @@ platformio lib install 562 This library has initially been written by Daniel Eichhorn (@squix78). Many thanks go to Fabrice Weinberg (@FWeinb) for optimizing and refactoring many aspects of the library. Also many thanks to the many committers who helped to add new features and who fixed many bugs. The init sequence for the SSD1306 was inspired by Adafruit's library for the same display. +## mbed-os +This library has been adopted to support the ARM mbed-os environment. A copy of this library is available in mbed-os under the name OLED_SSD1306 by Helmut Tschemernjak. An alternate installation option is to copy the following files into your mbed-os project: OLEDDisplay.cpp OLEDDisplay.h OLEDDisplayFonts.h OLEDDisplayUi.cpp OLEDDisplayUi.h SSD1306I2C.h + ## Usage Check out the examples folder for a few comprehensive demonstrations how to use the library. Also check out the [ESP8266 Weather Station](https://github.com/ThingPulse/esp8266-weather-station) library which uses the OLED library to display beautiful weather information. From 10f150edc694176fc8409bc57ed6177f1503c942 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Wed, 10 Apr 2019 14:55:29 +0200 Subject: [PATCH 06/17] Merged poll requests #197 from DaveSprague fixing cirles --- src/OLEDDisplay.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index 4a507af..1455cba 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -188,9 +188,9 @@ void OLEDDisplay::drawCircle(int16_t x0, int16_t y0, int16_t radius) { int16_t dp = 1 - radius; do { if (dp < 0) - dp = dp + 2 * (++x) + 3; + dp = dp + 2 * (x++) + 3; else - dp = dp + 2 * (++x) - 2 * (--y) + 5; + dp = dp + 2 * (x++) - 2 * (y--) + 5; setPixel(x0 + x, y0 + y); //For the 8 octants setPixel(x0 - x, y0 + y); @@ -214,9 +214,9 @@ void OLEDDisplay::drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_ int16_t dp = 1 - radius; while (x < y) { if (dp < 0) - dp = dp + 2 * (++x) + 3; + dp = dp + 2 * (x++) + 3; else - dp = dp + 2 * (++x) - 2 * (--y) + 5; + dp = dp + 2 * (x++) - 2 * (y--) + 5; if (quads & 0x1) { setPixel(x0 + x, y0 - y); setPixel(x0 + y, y0 - x); @@ -254,9 +254,9 @@ void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) { int16_t dp = 1 - radius; do { if (dp < 0) - dp = dp + 2 * (++x) + 3; + dp = dp + 2 * (x++) + 3; else - dp = dp + 2 * (++x) - 2 * (--y) + 5; + dp = dp + 2 * (x++) - 2 * (y--) + 5; drawHorizontalLine(x0 - x, y0 - y, 2*x); drawHorizontalLine(x0 - x, y0 + y, 2*x); From 111a790a9a027d9634eef6e8739f250f8397729b Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Wed, 10 Apr 2019 16:24:30 +0200 Subject: [PATCH 07/17] Further mbed-os changes to work with the ARM C++ compiler the initial work was the GNU Compiler --- src/OLEDDisplay.cpp | 2 ++ src/OLEDDisplay.h | 4 ++-- src/OLEDDisplayUi.cpp | 7 ++++++- src/OLEDDisplayUi.h | 10 +++++----- src/SSD1306I2C.h | 4 ++++ 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index 1455cba..12be4d9 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -48,6 +48,8 @@ OLEDDisplay::OLEDDisplay() { textAlignment = TEXT_ALIGN_LEFT; fontData = ArialMT_Plain_10; fontTableLookupFunction = DefaultFontTableLookup; + buffer = NULL; + buffer_back = NULL; } OLEDDisplay::~OLEDDisplay() { diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index cec1e68..17e2623 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -303,10 +303,10 @@ class OLEDDisplay : public Stream { #endif - uint8_t *buffer = NULL; + uint8_t *buffer; #ifdef OLEDDISPLAY_DOUBLE_BUFFER - uint8_t *buffer_back = NULL; + uint8_t *buffer_back; #endif protected: diff --git a/src/OLEDDisplayUi.cpp b/src/OLEDDisplayUi.cpp index 5cfeb01..e1da0fd 100644 --- a/src/OLEDDisplayUi.cpp +++ b/src/OLEDDisplayUi.cpp @@ -61,6 +61,11 @@ OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) { state.frameState = FIXED; state.currentFrame = 0; state.frameTransitionDirection = 1; + state.isIndicatorDrawen = true; + state.manuelControll = false; + state.userData = NULL; + shouldDrawIndicators = true; + autoTransition = true; } void OLEDDisplayUi::init() { @@ -235,7 +240,7 @@ int8_t OLEDDisplayUi::update(){ int8_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate); if ( timeBudget <= 0) { // Implement frame skipping to ensure time budget is keept - if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil(-timeBudget / this->updateInterval); + if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil((double)-timeBudget / (double)this->updateInterval); this->state.lastUpdate = frameStart; this->tick(); diff --git a/src/OLEDDisplayUi.h b/src/OLEDDisplayUi.h index e6f992a..0769599 100644 --- a/src/OLEDDisplayUi.h +++ b/src/OLEDDisplayUi.h @@ -90,15 +90,15 @@ struct OLEDDisplayUiState { FrameState frameState; uint8_t currentFrame; - bool isIndicatorDrawen = true; + bool isIndicatorDrawen; // Normal = 1, Inverse = -1; int8_t frameTransitionDirection; - bool manuelControll = false; + bool manuelControll; // Custom data that can be used by the user - void* userData = NULL; + void* userData; }; struct LoadingStage { @@ -121,7 +121,7 @@ class OLEDDisplayUi { const uint8_t* activeSymbol; const uint8_t* inactiveSymbol; - bool shouldDrawIndicators = true; + bool shouldDrawIndicators; // Values for the Frames AnimationDirection frameAnimationDirection; @@ -131,7 +131,7 @@ class OLEDDisplayUi { uint16_t ticksPerFrame; // ~ 5000ms at 30 FPS uint16_t ticksPerTransition; // ~ 500ms at 30 FPS - bool autoTransition = true; + bool autoTransition; FrameCallback* frameFunctions; uint8_t frameCount; diff --git a/src/SSD1306I2C.h b/src/SSD1306I2C.h index d161588..77d18be 100644 --- a/src/SSD1306I2C.h +++ b/src/SSD1306I2C.h @@ -36,6 +36,10 @@ #include "OLEDDisplay.h" #include +#ifndef UINT8_MAX + #define UINT8_MAX 0xff +#endif + class SSD1306I2C : public OLEDDisplay { public: SSD1306I2C(uint8_t _address, PinName _sda, PinName _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { From 0bc22ebcd35a6b118c9832c90d4a9ac75f4ed2ed Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Sun, 14 Apr 2019 16:12:24 +0200 Subject: [PATCH 08/17] Added missing ifdef for single buffer version --- src/OLEDDisplay.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index 12be4d9..82a5c47 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -49,7 +49,9 @@ OLEDDisplay::OLEDDisplay() { fontData = ArialMT_Plain_10; fontTableLookupFunction = DefaultFontTableLookup; buffer = NULL; +#ifdef OLEDDISPLAY_DOUBLE_BUFFER buffer_back = NULL; +#endif } OLEDDisplay::~OLEDDisplay() { From 8339a4ccf32d72bb7b2ebcac251c8878b7fe856b Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Sun, 14 Apr 2019 17:36:19 +0200 Subject: [PATCH 09/17] Fixed an offset problem in the single buffer case PAGEADDR 0 resets the value, no ending page address is allowed This overcomes the around warpping problem --- src/SSD1306I2C.h | 1 - src/SSD1306Wire.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/SSD1306I2C.h b/src/SSD1306I2C.h index 77d18be..ab94840 100644 --- a/src/SSD1306I2C.h +++ b/src/SSD1306I2C.h @@ -117,7 +117,6 @@ class SSD1306I2C : public OLEDDisplay { sendCommand(PAGEADDR); sendCommand(0x0); // page start address (0 = reset) - sendCommand((this->height() / 8) - 1); // page end address 7 if (geometry == GEOMETRY_128_64) { sendCommand(0x7); diff --git a/src/SSD1306Wire.h b/src/SSD1306Wire.h index b2324d7..c6a09b1 100644 --- a/src/SSD1306Wire.h +++ b/src/SSD1306Wire.h @@ -128,7 +128,6 @@ class SSD1306Wire : public OLEDDisplay { sendCommand(PAGEADDR); sendCommand(0x0); - sendCommand((this->height() / 8) - 1); if (geometry == GEOMETRY_128_64) { sendCommand(0x7); From efe984b9604c0d634e22022a31ea77aa92a92e85 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Fri, 24 May 2019 10:01:00 +0200 Subject: [PATCH 10/17] Added an GEOMETRY_RAWMODE for other low level displays like the flip dots. Added setGeometry high/width optional parameters to allow custom bitmaps. --- src/OLEDDisplay.cpp | 29 +++++++++++++++++++---------- src/OLEDDisplay.h | 5 +++-- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index 82a5c47..f429591 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -42,7 +42,7 @@ OLEDDisplay::OLEDDisplay() { displayWidth = 128; displayHeight = 64; - displayBufferSize = 1024; + displayBufferSize = displayWidth * displayHeight / 8; color = WHITE; geometry = GEOMETRY_128_64; textAlignment = TEXT_ALIGN_LEFT; @@ -789,19 +789,28 @@ int OLEDDisplay::_putc(int c) { #endif // Private functions -void OLEDDisplay::setGeometry(OLEDDISPLAY_GEOMETRY g) { +void OLEDDisplay::setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width, uint16_t height) { this->geometry = g; - if (g == GEOMETRY_128_64) { - this->displayWidth = 128; - this->displayHeight = 64; - } else if (g == GEOMETRY_128_32) { - this->displayWidth = 128; - this->displayHeight = 32; - } - this->displayBufferSize = displayWidth*displayHeight/8; + switch (g) { + case GEOMETRY_128_64: + this->displayWidth = 128; + this->displayHeight = 64; + break; + case GEOMETRY_128_32: + this->displayWidth = 128; + this->displayHeight = 32; + break; + case GEOMETRY_RAWMODE: + this->displayWidth = width > 0 ? width : 128; + this->displayHeight = height > 0 ? height : 64; + break; + } + this->displayBufferSize = displayWidth * displayHeight /8; } void OLEDDisplay::sendInitCommands(void) { + if (geometry == GEOMETRY_RAWMODE) + return; sendCommand(DISPLAYOFF); sendCommand(SETDISPLAYCLOCKDIV); sendCommand(0xF0); // Increase speed of the display max ~96Hz diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index 17e2623..b653b4c 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -137,7 +137,8 @@ enum OLEDDISPLAY_TEXT_ALIGNMENT { enum OLEDDISPLAY_GEOMETRY { GEOMETRY_128_64 = 0, - GEOMETRY_128_32 = 1 + GEOMETRY_128_32, + GEOMETRY_RAWMODE, }; typedef char (*FontTableLookupFunction)(const char ch); @@ -318,7 +319,7 @@ class OLEDDisplay : public Stream { uint16_t displayBufferSize; // Set the correct height, width and buffer for the geometry - void setGeometry(OLEDDISPLAY_GEOMETRY g); + void setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width = 0, uint16_t height = 0); OLEDDISPLAY_TEXT_ALIGNMENT textAlignment; OLEDDISPLAY_COLOR color; From 63deb4b5d8dbd4b6ab692d414eb7e6fa3b7bdbbc Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Fri, 24 May 2019 10:42:55 +0200 Subject: [PATCH 11/17] Added AVR support --- src/SSD1306Wire.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/SSD1306Wire.h b/src/SSD1306Wire.h index c6a09b1..3a0ab10 100644 --- a/src/SSD1306Wire.h +++ b/src/SSD1306Wire.h @@ -34,6 +34,11 @@ #include "OLEDDisplay.h" #include +#ifdef ARDUINO_ARCH_AVR +#define _min min +#define _max max +#endif + class SSD1306Wire : public OLEDDisplay { private: uint8_t _address; @@ -51,7 +56,11 @@ class SSD1306Wire : public OLEDDisplay { } bool connect() { +#ifdef ARDUINO_ARCH_AVR + Wire.begin(); +#else Wire.begin(this->_sda, this->_scl); +#endif // Let's use ~700khz if ESP8266 is in 160Mhz mode // this will be limited to ~400khz if the ESP8266 in 80Mhz mode. Wire.setClock(700000); @@ -166,7 +175,11 @@ class SSD1306Wire : public OLEDDisplay { void initI2cIfNeccesary() { if (_doI2cAutoInit) { - Wire.begin(this->_sda, this->_scl); +#ifdef ARDUINO_ARCH_AVR + Wire.begin(); +#else + Wire.begin(this->_sda, this->_scl); +#endif } } From 1661b784a5e710665279f0e9d8abbb6e98b06239 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Mon, 27 May 2019 09:18:13 +0200 Subject: [PATCH 12/17] Fixed a problem that Umlauts where not working in the default FontTableLookup --- src/OLEDDisplay.cpp | 2 +- src/OLEDDisplay.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index f429591..0895763 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -954,7 +954,7 @@ void OLEDDisplay::setFontTableLookupFunction(FontTableLookupFunction function) { } -char DefaultFontTableLookup(const char ch) { +char DefaultFontTableLookup(const uint8_t ch) { // UTF-8 to font table index converter // Code form http://playground.arduino.cc/Main/Utf8ascii static uint8_t LASTCHAR; diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index b653b4c..4a54ac8 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -141,8 +141,8 @@ enum OLEDDISPLAY_GEOMETRY { GEOMETRY_RAWMODE, }; -typedef char (*FontTableLookupFunction)(const char ch); -char DefaultFontTableLookup(const char ch); +typedef char (*FontTableLookupFunction)(const uint8_t ch); +char DefaultFontTableLookup(const uint8_t ch); #ifdef ARDUINO From 0ad2be4535849a1d190a59e21b10463210372068 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Mon, 27 May 2019 09:24:48 +0200 Subject: [PATCH 13/17] Fixed a problem that long scrolling text did not work --- src/OLEDDisplay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index 0895763..6b27eb3 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -427,8 +427,8 @@ void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, u uint8_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); uint16_t sizeOfJumpTable = pgm_read_byte(fontData + CHAR_NUM_POS) * JUMPTABLE_BYTES; - uint8_t cursorX = 0; - uint8_t cursorY = 0; + uint16_t cursorX = 0; + uint16_t cursorY = 0; switch (textAlignment) { case TEXT_ALIGN_CENTER_BOTH: From cee8dc1a467d0dff14614a83587276debed65865 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Sun, 2 Jun 2019 11:28:46 +0200 Subject: [PATCH 14/17] Updated TODO --- src/OLEDDisplay.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index 6b27eb3..df8db71 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -33,7 +33,6 @@ * TODO Helmut * - test/finish dislplay.printf() on mbed-os * - Finish _putc with drawLogBuffer when running display - * - Fix problem that the x is larger than 0 (somehow shifted display) on single buffer */ #include "OLEDDisplay.h" From 008ef9c4bf2243c16c20a4feb45cd0875fac4f85 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Sun, 2 Jun 2019 11:44:44 +0200 Subject: [PATCH 15/17] Merged pull request #247 clearPixel function from szczys --- README.md | 3 +++ src/OLEDDisplay.cpp | 10 ++++++++++ src/OLEDDisplay.h | 3 +++ 3 files changed, 16 insertions(+) diff --git a/README.md b/README.md index 9af3f3c..a011110 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,9 @@ void setColor(OLEDDISPLAY_COLOR color); // Draw a pixel at given position void setPixel(int16_t x, int16_t y); +// Clear a pixel at given position FIXME: INVERSE is untested with this function +void clearPixel(int16_t x, int16_t y); + // Draw a line from position 0 to position 1 void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index df8db71..b043c75 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -133,6 +133,16 @@ void OLEDDisplay::setPixel(int16_t x, int16_t y) { } } +void OLEDDisplay::clearPixel(int16_t x, int16_t y) { + if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) { + switch (color) { + case BLACK: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break; + case WHITE: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break; + case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break; + } + } +} + // Bresenham's algorithm - thx wikipedia and Adafruit_GFX void OLEDDisplay::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { int16_t steep = abs(y1 - y0) > abs(x1 - x0); diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index 4a54ac8..4668bf6 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -178,6 +178,9 @@ class OLEDDisplay : public Stream { // Draw a pixel at given position void setPixel(int16_t x, int16_t y); + + // Clear a pixel at given position FIXME: INVERSE is untested with this function + void clearPixel(int16_t x, int16_t y); // Draw a line from position 0 to position 1 void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); From 47a369a3ef58d883602e764ec599d88caa7b71e1 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Sun, 2 Jun 2019 12:06:21 +0200 Subject: [PATCH 16/17] Merged pull request #238 (from smurf0969) to overwrite the default font. I believe this is a very important feature because it eliminates the memory requirement for a font never being used. --- README.md | 5 +++-- src/OLEDDisplay.cpp | 5 +++-- src/OLEDDisplay.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a011110..6c15b2a 100644 --- a/README.md +++ b/README.md @@ -118,8 +118,9 @@ SH1106Spi display(RES, DC, CS); ### Display Control ```C++ -// Initialize the display -void init(); +// Initialize the display via init(); +// Optionally the default fonts can be overwritten to save flash memory, e.g. init(ArialMT_Plain_10) +void init(const uint8_t *defaultFontData); // Free the memory used by the display void end(); diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index b043c75..74e93ce 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -45,7 +45,7 @@ OLEDDisplay::OLEDDisplay() { color = WHITE; geometry = GEOMETRY_128_64; textAlignment = TEXT_ALIGN_LEFT; - fontData = ArialMT_Plain_10; + fontData = NULL; fontTableLookupFunction = DefaultFontTableLookup; buffer = NULL; #ifdef OLEDDISPLAY_DOUBLE_BUFFER @@ -57,8 +57,9 @@ OLEDDisplay::~OLEDDisplay() { end(); } -bool OLEDDisplay::init() { +bool OLEDDisplay::init(const uint8_t *defaultFontData) { + fontData = defaultFontData; logBufferSize = 0; logBufferFilled = 0; logBufferLine = 0; diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index 4668bf6..4447152 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -161,7 +161,7 @@ class OLEDDisplay : public Stream { uint16_t height(void) const { return displayHeight; }; // Initialize the display - bool init(); + bool init(const uint8_t *defaultFontData = ArialMT_Plain_10); // Free the memory used by the display void end(); From 563dbc7ba891f7ffa2c4cfbf9cd5bb066d0e0ad4 Mon Sep 17 00:00:00 2001 From: Helmut Tschemernjak Date: Tue, 4 Jun 2019 12:41:28 +0200 Subject: [PATCH 17/17] Removed the duplicate clearPixel() in header file from last merge. --- src/OLEDDisplay.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index a8c4b1c..4447152 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -182,9 +182,6 @@ class OLEDDisplay : public Stream { // Clear a pixel at given position FIXME: INVERSE is untested with this function void clearPixel(int16_t x, int16_t y); - // Clear a pixel at given position FIXME: INVERSE is untested with this function - void clearPixel(int16_t x, int16_t y); - // Draw a line from position 0 to position 1 void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1);