From 9f00f0e0dbbf4d132f53efe9a7425dc59797f219 Mon Sep 17 00:00:00 2001 From: Deqing Sun Date: Sun, 6 Mar 2022 02:03:02 -0500 Subject: [PATCH 1/3] add displayRegional method update region instead of full screen to save time --- Adafruit_SSD1306.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++ Adafruit_SSD1306.h | 1 + 2 files changed, 105 insertions(+) diff --git a/Adafruit_SSD1306.cpp b/Adafruit_SSD1306.cpp index 11f415a6..7ac80fdd 100644 --- a/Adafruit_SSD1306.cpp +++ b/Adafruit_SSD1306.cpp @@ -1035,6 +1035,110 @@ void Adafruit_SSD1306::display(void) { #endif } +/*! + @brief Push regional data currently in RAM to SSD1306 display. + @param x + Column of display -- 0 at left to (screen width - 1) at right. + @param y + Row of display -- 0 at top to (screen height -1) at bottom. + @param w + Region width in pixels + @param h + Region height in pixels + @return None (void). + @note Drawing operations are not visible until this function is + called. Call after each graphics command, or after a whole set + of graphics commands, as best needed by one's own application. +*/ +void Adafruit_SSD1306::displayRegional(int16_t x, int16_t y, int16_t w, int16_t h) { + if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())){ + return; + } + if ((w <= 0) || (h <= 0 )){ + return; + } + if (((x + w) > width()) || ((y + h) > height())){ + return; + } + uint8_t startPage = y / 8; + uint8_t endPage = (y + h - 1) / 8; + uint8_t startColumn = x; + uint8_t endColumn = x + w - 1; + TRANSACTION_START + + uint8_t dlist[] = { + SSD1306_PAGEADDR, startPage, endPage, + SSD1306_COLUMNADDR, startColumn, endColumn}; + + { + //ssd1306_commandList need to write from progmem, using own version + uint8_t *c = dlist; + uint8_t n = sizeof(dlist); + if (wire) { // I2C + wire->beginTransmission(i2caddr); + WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0 + uint16_t bytesOut = 1; + while (n--) { + if (bytesOut >= WIRE_MAX) { + wire->endTransmission(); + wire->beginTransmission(i2caddr); + WIRE_WRITE((uint8_t)0x00); // Co = 0, D/C = 0 + bytesOut = 1; + } + WIRE_WRITE((*c++)); + bytesOut++; + } + wire->endTransmission(); + } else { // SPI -- transaction started in calling function + SSD1306_MODE_COMMAND + while (n--) + SPIwrite((*c++)); + } + } + +#if defined(ESP8266) + // ESP8266 needs a periodic yield() call to avoid watchdog reset. + // With the limited size of SSD1306 displays, and the fast bitrate + // being used (1 MHz or more), I think one yield() immediately before + // a screen write and one immediately after should cover it. But if + // not, if this becomes a problem, yields() might be added in the + // 32-byte transfer condition below. + yield(); +#endif + uint16_t count = w * (endPage-startPage+1); + uint16_t columnCount = 0; + uint8_t *ptr = buffer + x + startPage * width(); + if (wire) { // I2C + wire->beginTransmission(i2caddr); + WIRE_WRITE((uint8_t)0x40); + uint16_t bytesOut = 1; + while (count--) { + if (bytesOut >= WIRE_MAX) { + wire->endTransmission(); + wire->beginTransmission(i2caddr); + WIRE_WRITE((uint8_t)0x40); + bytesOut = 1; + } + WIRE_WRITE(*ptr++); + columnCount++; + if (columnCount >= w){ + columnCount = 0; + ptr += (width()-w); + } + bytesOut++; + } + wire->endTransmission(); + } else { // SPI + SSD1306_MODE_DATA + while (count--) + SPIwrite(*ptr++); + } + TRANSACTION_END +#if defined(ESP8266) + yield(); +#endif +} + // SCROLLING FUNCTIONS ----------------------------------------------------- /*! diff --git a/Adafruit_SSD1306.h b/Adafruit_SSD1306.h index ae3eb4d0..0a67674c 100644 --- a/Adafruit_SSD1306.h +++ b/Adafruit_SSD1306.h @@ -148,6 +148,7 @@ class Adafruit_SSD1306 : public Adafruit_GFX { bool begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = 0, bool reset = true, bool periphBegin = true); void display(void); + void displayRegional(int16_t x, int16_t y, int16_t w, int16_t h); void clearDisplay(void); void invertDisplay(bool i); void dim(bool dim); From 543929e96b9cb6acbe0b189141302b0ae468ab1c Mon Sep 17 00:00:00 2001 From: Deqing Sun Date: Sun, 6 Mar 2022 02:06:50 -0500 Subject: [PATCH 2/3] fix spi --- Adafruit_SSD1306.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Adafruit_SSD1306.cpp b/Adafruit_SSD1306.cpp index 7ac80fdd..017b52d1 100644 --- a/Adafruit_SSD1306.cpp +++ b/Adafruit_SSD1306.cpp @@ -1130,8 +1130,14 @@ void Adafruit_SSD1306::displayRegional(int16_t x, int16_t y, int16_t w, int16_t wire->endTransmission(); } else { // SPI SSD1306_MODE_DATA - while (count--) + while (count--){ SPIwrite(*ptr++); + columnCount++; + if (columnCount >= w){ + columnCount = 0; + ptr += (width()-w); + } + } } TRANSACTION_END #if defined(ESP8266) From 578821a75e10bbddbfc8ab4f7fd15a5159e047ec Mon Sep 17 00:00:00 2001 From: Deqing Sun Date: Sun, 6 Mar 2022 02:24:49 -0500 Subject: [PATCH 3/3] format --- Adafruit_SSD1306.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Adafruit_SSD1306.cpp b/Adafruit_SSD1306.cpp index 017b52d1..13ea0230 100644 --- a/Adafruit_SSD1306.cpp +++ b/Adafruit_SSD1306.cpp @@ -1050,14 +1050,15 @@ void Adafruit_SSD1306::display(void) { called. Call after each graphics command, or after a whole set of graphics commands, as best needed by one's own application. */ -void Adafruit_SSD1306::displayRegional(int16_t x, int16_t y, int16_t w, int16_t h) { - if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())){ +void Adafruit_SSD1306::displayRegional(int16_t x, int16_t y, int16_t w, + int16_t h) { + if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())) { return; } - if ((w <= 0) || (h <= 0 )){ + if ((w <= 0) || (h <= 0)) { return; } - if (((x + w) > width()) || ((y + h) > height())){ + if (((x + w) > width()) || ((y + h) > height())) { return; } uint8_t startPage = y / 8; @@ -1065,13 +1066,12 @@ void Adafruit_SSD1306::displayRegional(int16_t x, int16_t y, int16_t w, int16_t uint8_t startColumn = x; uint8_t endColumn = x + w - 1; TRANSACTION_START - - uint8_t dlist[] = { - SSD1306_PAGEADDR, startPage, endPage, - SSD1306_COLUMNADDR, startColumn, endColumn}; - + + uint8_t dlist[] = {SSD1306_PAGEADDR, startPage, endPage, + SSD1306_COLUMNADDR, startColumn, endColumn}; + { - //ssd1306_commandList need to write from progmem, using own version + // ssd1306_commandList need to write from progmem, using own version uint8_t *c = dlist; uint8_t n = sizeof(dlist); if (wire) { // I2C @@ -1095,7 +1095,7 @@ void Adafruit_SSD1306::displayRegional(int16_t x, int16_t y, int16_t w, int16_t SPIwrite((*c++)); } } - + #if defined(ESP8266) // ESP8266 needs a periodic yield() call to avoid watchdog reset. // With the limited size of SSD1306 displays, and the fast bitrate @@ -1105,7 +1105,7 @@ void Adafruit_SSD1306::displayRegional(int16_t x, int16_t y, int16_t w, int16_t // 32-byte transfer condition below. yield(); #endif - uint16_t count = w * (endPage-startPage+1); + uint16_t count = w * (endPage - startPage + 1); uint16_t columnCount = 0; uint8_t *ptr = buffer + x + startPage * width(); if (wire) { // I2C @@ -1121,21 +1121,21 @@ void Adafruit_SSD1306::displayRegional(int16_t x, int16_t y, int16_t w, int16_t } WIRE_WRITE(*ptr++); columnCount++; - if (columnCount >= w){ + if (columnCount >= (uint16_t)w) { columnCount = 0; - ptr += (width()-w); + ptr += (width() - w); } bytesOut++; } wire->endTransmission(); } else { // SPI SSD1306_MODE_DATA - while (count--){ + while (count--) { SPIwrite(*ptr++); columnCount++; - if (columnCount >= w){ + if (columnCount >= (uint16_t)w) { columnCount = 0; - ptr += (width()-w); + ptr += (width() - w); } } }