diff --git a/README.md b/README.md
index b75595d..636493c 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
[](https://registry.platformio.org/libraries/thingpulse/ESP8266%20and%20ESP32%20OLED%20driver%20for%20SSD1306%20displays)
[](https://github.com/ThingPulse/esp8266-oled-ssd1306/actions)
-This is a driver for SSD1306 and SH1106 128x64, 128x32, 64x48 and 64x32 OLED displays running on the Arduino/ESP8266 & ESP32 and mbed-os platforms.
+This is a driver for SSD1306 128x64, 128x32, 64x48 and 64x32 OLED displays running on the Arduino/ESP8266 & ESP32 and mbed-os platforms.
Can be used with either the I2C or SPI version of the display.
This library drives the OLED display included in the [ThingPulse IoT starter kit](https://thingpulse.com/product/esp8266-iot-electronics-starter-kit-weatherstation-planespotter-worldclock/) aka classic kit aka weather station kit.
@@ -262,27 +262,6 @@ void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment);
void setFont(const uint8_t* fontData);
```
-## Arduino `Print` functionality
-
-Because this class has been "derived" from Arduino's `Print` class, you can use the functions it provides. In plain language, this means that you can use `print`, `println` and `printf` to the display. Internally, a buffer holds the text that was printed to the display previously (that would still fit on the display) and every time you print something, this buffer is put on the screen, using the functions from the previous section.
-
-What that means is that printing using `print` and "manually" putting things on the display are somewhat mutually exclusive: as soon as you print, everything that was on the display already is gone and only what you put there before with `print`, `println` or `printf` remains. Still, using `print` is a very simple way to put something on the display quickly.
-
-One extra function is provided: `cls()`
-```cpp
-// cls() will clear the display immediately and empty the logBuffer, meaning
-// the next print statement will print at the top of the display again.
-// cls() should not be confused with clear(), which only clears the internal
-// graphics buffer, which can then be shown on the display with display().
-void cls();
-
-> _Note that printing to the display, contrary to what you might expect, does not wrap your lines, so everything on a line that doesn't fit on the screen is cut off._
-```
-
-
-
-
-
## Ui Library (OLEDDisplayUi)
The Ui Library is used to provide a basic set of user interface elements called `Frames` and `Overlays`. A `Frame` is used to provide
diff --git a/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino b/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino
index eb1d30f..d684e7d 100644
--- a/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino
+++ b/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino
@@ -171,6 +171,10 @@ void drawCircle(void) {
}
void printBuffer(void) {
+ // Initialize the log buffer
+ // allocate memory to store 8 lines of text and 30 chars per line.
+ display.setLogBuffer(5, 30);
+
// Some test data
const char* test[] = {
"Hello",
@@ -185,10 +189,15 @@ void printBuffer(void) {
"scrolling is",
"working"
};
- display.clear();
+
for (uint8_t i = 0; i < 11; i++) {
+ display.clear();
// Print to the screen
display.println(test[i]);
+ // Draw it to the internal screen buffer
+ display.drawLogBuffer(0, 0);
+ // Display it on the screen
+ display.display();
delay(500);
}
}
diff --git a/library.json b/library.json
index 757885e..53fb48a 100644
--- a/library.json
+++ b/library.json
@@ -1,6 +1,6 @@
{
"name": "ESP8266 and ESP32 OLED driver for SSD1306 displays",
- "version": "4.5.0",
+ "version": "4.4.1",
"keywords": "ssd1306, oled, display, i2c",
"description": "I2C display driver for SSD1306 OLED displays connected to ESP8266, ESP32, Mbed-OS",
"license": "MIT",
diff --git a/library.properties b/library.properties
index c732e23..f3dceec 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=ESP8266 and ESP32 OLED driver for SSD1306 displays
-version=4.5.0
+version=4.4.1
author=ThingPulse, Fabrice Weinberg
maintainer=ThingPulse
sentence=I2C display driver for SSD1306 OLED displays connected to ESP8266, ESP32, Mbed-OS
diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp
index cb82154..dca2ad1 100644
--- a/src/OLEDDisplay.cpp
+++ b/src/OLEDDisplay.cpp
@@ -32,6 +32,7 @@
/*
* TODO Helmut
* - test/finish dislplay.printf() on mbed-os
+ * - Finish _putc with drawLogBuffer when running display
*/
#include "OLEDDisplay.h"
@@ -41,7 +42,6 @@ OLEDDisplay::OLEDDisplay() {
displayWidth = 128;
displayHeight = 64;
displayBufferSize = displayWidth * displayHeight / 8;
- inhibitDrawLogBuffer = false;
color = WHITE;
geometry = GEOMETRY_128_64;
textAlignment = TEXT_ALIGN_LEFT;
@@ -764,12 +764,6 @@ void OLEDDisplay::setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment) {
void OLEDDisplay::setFont(const uint8_t *fontData) {
this->fontData = fontData;
- // New font, so must recalculate. Whatever was there is gone at next print.
- setLogBuffer();
-}
-
-void OLEDDisplay::setFont(const char *fontData) {
- setFont(static_cast(reinterpret_cast(fontData)));
}
void OLEDDisplay::displayOn(void) {
@@ -838,10 +832,6 @@ void OLEDDisplay::clear(void) {
}
void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) {
- Serial.println("[deprecated] Print functionality now handles buffer management automatically. This is a no-op.");
-}
-
-void OLEDDisplay::drawLogBuffer() {
uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS);
// Always align left
setTextAlignment(TEXT_ALIGN_LEFT);
@@ -851,27 +841,25 @@ void OLEDDisplay::drawLogBuffer() {
uint16_t line = 0;
uint16_t lastPos = 0;
- // If the lineHeight and the display height are not cleanly divisible, we need
- // to start off the screen when the buffer has logBufferMaxLines so that the
- // first line, and not the last line, drops off.
- uint16_t shiftUp = (this->logBufferLine == this->logBufferMaxLines) ? (lineHeight - (displayHeight % lineHeight)) % lineHeight : 0;
-
for (uint16_t i=0;ilogBufferFilled;i++){
- length++;
// Everytime we have a \n print
if (this->logBuffer[i] == 10) {
+ length++;
// Draw string on line `line` from lastPos to length
// Passing 0 as the lenght because we are in TEXT_ALIGN_LEFT
- drawStringInternal(0, 0 - shiftUp + (line++) * lineHeight, &this->logBuffer[lastPos], length, 0, false);
+ drawStringInternal(xMove, yMove + (line++) * lineHeight, &this->logBuffer[lastPos], length, 0, false);
// Remember last pos
lastPos = i;
// Reset length
length = 0;
+ } else {
+ // Count chars until next linebreak
+ length++;
}
}
// Draw the remaining string
if (length > 0) {
- drawStringInternal(0, 0 - shiftUp + line * lineHeight, &this->logBuffer[lastPos], length, 0, false);
+ drawStringInternal(xMove, yMove + line * lineHeight, &this->logBuffer[lastPos], length, 0, false);
}
}
@@ -883,146 +871,102 @@ uint16_t OLEDDisplay::getHeight(void) {
return displayHeight;
}
-void OLEDDisplay::cls() {
- clear();
- this->logBufferFilled = 0;
- this->logBufferLine = 0;
- display();
-}
-
-bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars) {
- Serial.println("[deprecated] Print functionality now handles buffer management automatically. This is a no-op.");
- return true;
-}
-
-bool OLEDDisplay::setLogBuffer(){
- // don't know how big we need it without a font set.
- if (!fontData)
- return false;
-
- // we're always starting over
- if (logBuffer != NULL)
- free(logBuffer);
-
- // figure out how big it needs to be
- uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS);
- if (!textHeight)
- return false; // Prevent division by zero crashes
- uint16_t lines = this->displayHeight / textHeight + (this->displayHeight % textHeight ? 1 : 0);
- uint16_t chars = 5 * (this->displayWidth / textHeight);
- uint16_t size = lines * (chars + 1); // +1 is for \n
-
- // Something weird must have happened
- if (size == 0)
- return false;
-
- // All good, initialize logBuffer
- this->logBufferLine = 0; // Lines printed
- this->logBufferFilled = 0; // Nothing stored yet
- this->logBufferMaxLines = lines; // Lines max printable
- this->logBufferLineLen = chars; // Chars per line
- this->logBufferSize = size; // Total number of characters the buffer can hold
- this->logBuffer = (char *) malloc(size * sizeof(uint8_t));
- if(!this->logBuffer) {
- DEBUG_OLEDDISPLAY("[OLEDDISPLAY][setLogBuffer] Not enough memory to create log buffer\n");
- return false;
+bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){
+ if (logBuffer != NULL) free(logBuffer);
+ uint16_t size = lines * chars;
+ if (size > 0) {
+ this->logBufferLine = 0; // Lines printed
+ this->logBufferFilled = 0; // Nothing stored yet
+ this->logBufferMaxLines = lines; // Lines max printable
+ this->logBufferSize = size; // Total number of characters the buffer can hold
+ this->logBuffer = (char *) malloc(size * sizeof(uint8_t));
+ if(!this->logBuffer) {
+ DEBUG_OLEDDISPLAY("[OLEDDISPLAY][setLogBuffer] Not enough memory to create log buffer\n");
+ return false;
+ }
}
-
return true;
}
size_t OLEDDisplay::write(uint8_t c) {
- if (!fontData)
- return 1;
-
- // Create a logBuffer if there isn't one
- if (!logBufferSize) {
- // Give up if we can't create a logBuffer somehow
- if (!setLogBuffer())
- return 1;
- }
-
- // Don't waste space on \r\n line endings, dropping \r
- if (c == 13) return 1;
-
- // convert UTF-8 character to font table index
- c = (this->fontTableLookupFunction)(c);
- // drop unknown character
- if (c == 0) return 1;
-
- bool maxLineReached = this->logBufferLine >= this->logBufferMaxLines;
- bool bufferFull = this->logBufferFilled >= this->logBufferSize;
-
- // Can we write to the buffer? If not, make space.
- if (bufferFull || maxLineReached) {
- // See if we can chop off the first line
- uint16_t firstLineEnd = 0;
- for (uint16_t i = 0; i < this->logBufferFilled; i++) {
- if (this->logBuffer[i] == 10){
- // Include last char too
- firstLineEnd = i + 1;
+ if (this->logBufferSize > 0) {
+ // Don't waste space on \r\n line endings, dropping \r
+ if (c == 13) return 1;
+
+ // convert UTF-8 character to font table index
+ c = (this->fontTableLookupFunction)(c);
+ // drop unknown character
+ if (c == 0) return 1;
+
+ bool maxLineNotReached = this->logBufferLine < this->logBufferMaxLines;
+ bool bufferNotFull = this->logBufferFilled < this->logBufferSize;
+
+ // Can we write to the buffer?
+ if (bufferNotFull && maxLineNotReached) {
+ this->logBuffer[logBufferFilled] = c;
+ this->logBufferFilled++;
+ // Keep track of lines written
+ if (c == 10) this->logBufferLine++;
+ } else {
+ // Max line number is reached
+ if (!maxLineNotReached) this->logBufferLine--;
+
+ // Find the end of the first line
+ uint16_t firstLineEnd = 0;
+ for (uint16_t i=0;ilogBufferFilled;i++) {
+ if (this->logBuffer[i] == 10){
+ // Include last char too
+ firstLineEnd = i + 1;
+ break;
+ }
+ }
+ // If there was a line ending
+ if (firstLineEnd > 0) {
// Calculate the new logBufferFilled value
this->logBufferFilled = logBufferFilled - firstLineEnd;
- // Now move other lines to front of the buffer
+ // Now we move the lines infront of the buffer
memcpy(this->logBuffer, &this->logBuffer[firstLineEnd], logBufferFilled);
- // And voila, buffer one line shorter
- this->logBufferLine--;
- break;
+ } else {
+ // Let's reuse the buffer if it was full
+ if (!bufferNotFull) {
+ this->logBufferFilled = 0;
+ }// else {
+ // Nothing to do here
+ //}
}
+ write(c);
}
- // In we can't take off first line, we just empty the buffer
- if (!firstLineEnd) {
- this->logBufferFilled = 0;
- this->logBufferLine = 0;
- }
- }
-
- // So now we know for sure we have space in the buffer
-
- // Find the length of the last line
- uint16_t lastLineLen= 0;
- for (uint16_t i = 0; i < this->logBufferFilled; i++) {
- lastLineLen++;
- if (this->logBuffer[i] == 10) lastLineLen = 0;
- }
- // if last line is max length, ignore anything but linebreaks
- if (lastLineLen >= this->logBufferLineLen) {
- if (c != 10) return 1;
}
-
- // Write to buffer
- this->logBuffer[this->logBufferFilled++] = c;
- // Keep track of lines written
- if (c == 10) this->logBufferLine++;
-
- // Draw to screen unless we're writing a whole string at a time
- if (!this->inhibitDrawLogBuffer) {
- clear();
- drawLogBuffer();
- display();
- }
-
- // We always claim we printed it all
+ // We are always writing all uint8_t to the buffer
return 1;
}
size_t OLEDDisplay::write(const char* str) {
if (str == NULL) return 0;
size_t length = strlen(str);
- // If we write a string, only do the drawLogBuffer at the end, not every time we write a char
- this->inhibitDrawLogBuffer = true;
for (size_t i = 0; i < length; i++) {
write(str[i]);
}
- this->inhibitDrawLogBuffer = false;
- clear();
- drawLogBuffer();
- display();
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
diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h
index 0e07a86..23e6845 100644
--- a/src/OLEDDisplay.h
+++ b/src/OLEDDisplay.h
@@ -274,9 +274,6 @@ class OLEDDisplay : public Stream {
// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
void setFont(const uint8_t *fontData);
- // Set the current font when supplied as a char* instead of a uint8_t*
- void setFont(const char *fontData);
-
// Set the function that will convert utf-8 to font table index
void setFontTableLookupFunction(FontTableLookupFunction function);
@@ -317,24 +314,14 @@ class OLEDDisplay : public Stream {
// Clear the local pixel buffer
void clear(void);
- // Print class device
-
- // Because this display class is "derived" from Arduino's Print class,
- // various function that work on it also work here. These functions include
- // print, println and printf.
-
- // cls() will clear the display immediately and empty the logBuffer, meaning
- // the next print statement will print at the top of the display again.
- // cls() should not be confused with clear(), which only clears the internal
- // graphics buffer, which can then be shown on the display with display().
- void cls();
+ // Log buffer implementation
- // Replaced by setLogBuffer() , which is protected
+ // This will define the lines and characters you can
+ // print to the screen. When you exeed the buffer size (lines * chars)
+ // the output may be truncated due to the size constraint.
bool setLogBuffer(uint16_t lines, uint16_t chars);
// Draw the log buffer at position (x, y)
- //
- // (Automatically called with you use print, println or printf)
void drawLogBuffer(uint16_t x, uint16_t y);
// Get screen geometry
@@ -379,9 +366,7 @@ class OLEDDisplay : public Stream {
uint16_t logBufferFilled;
uint16_t logBufferLine;
uint16_t logBufferMaxLines;
- uint16_t logBufferLineLen;
char *logBuffer;
- bool inhibitDrawLogBuffer;
// the header size of the buffer used, e.g. for the SPI command header
@@ -404,13 +389,6 @@ class OLEDDisplay : public Stream {
uint16_t drawStringInternal(int16_t xMove, int16_t yMove, const char* text, uint16_t textLength, uint16_t textWidth, bool utf8);
- // (re)creates the logBuffer that printing uses to remember what was on the
- // screen already
- bool setLogBuffer();
-
- // Draws the contents of the logBuffer to the screen
- void drawLogBuffer();
-
FontTableLookupFunction fontTableLookupFunction;
};