Skip to content

Commit 810302c

Browse files
committed
Fix for random uninitialized data in display RAM for displays less than 128 segments wide.
Bug was visible when scrolling. TDB: allow drawing outside visible area to exploit full 128 horizontal resolution in hardware scrolling.
1 parent 1c5e7c2 commit 810302c

File tree

2 files changed

+31
-37
lines changed

2 files changed

+31
-37
lines changed

Adafruit_SSD1306.cpp

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ void Adafruit_SSD1306::ssd1306_command(uint8_t c) {
451451
boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset,
452452
boolean periphBegin) {
453453

454-
if((!buffer) && !(buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))))
454+
if((!buffer) && !(buffer = (uint8_t *)malloc(SSD1306_SEGMENTS * ((HEIGHT + 7) / 8))))
455455
return false;
456456

457457
clearDisplay();
@@ -625,10 +625,11 @@ void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
625625
y = HEIGHT - y - 1;
626626
break;
627627
}
628+
if ((WIDTH == 64) && (HEIGHT == 48)) x += 32;
628629
switch(color) {
629-
case WHITE: buffer[x + (y/8)*WIDTH] |= (1 << (y&7)); break;
630-
case BLACK: buffer[x + (y/8)*WIDTH] &= ~(1 << (y&7)); break;
631-
case INVERSE: buffer[x + (y/8)*WIDTH] ^= (1 << (y&7)); break;
630+
case WHITE: buffer[x + (y/8)* SSD1306_SEGMENTS] |= (1 << (y&7)); break;
631+
case BLACK: buffer[x + (y/8)* SSD1306_SEGMENTS] &= ~(1 << (y&7)); break;
632+
case INVERSE: buffer[x + (y/8)* SSD1306_SEGMENTS] ^= (1 << (y&7)); break;
632633
}
633634
}
634635
}
@@ -641,7 +642,7 @@ void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
641642
commands as needed by one's own application.
642643
*/
643644
void Adafruit_SSD1306::clearDisplay(void) {
644-
memset(buffer, 0, WIDTH * ((HEIGHT + 7) / 8));
645+
memset(buffer, 0, SSD1306_SEGMENTS * ((HEIGHT + 7) / 8));
645646
}
646647

647648
/*!
@@ -702,8 +703,9 @@ void Adafruit_SSD1306::drawFastHLineInternal(
702703
w = (WIDTH - x);
703704
}
704705
if(w > 0) { // Proceed only if width is positive
705-
uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x],
706-
mask = 1 << (y & 7);
706+
if ((WIDTH == 64) && (HEIGHT == 48)) x += 32;
707+
uint8_t* pBuf = &buffer[x + (y / 8) * SSD1306_SEGMENTS];
708+
uint8_t mask = 1 << (y & 7);
707709
switch(color) {
708710
case WHITE: while(w--) { *pBuf++ |= mask; }; break;
709711
case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
@@ -774,7 +776,8 @@ void Adafruit_SSD1306::drawFastVLineInternal(
774776
// this display doesn't need ints for coordinates,
775777
// use local byte registers for faster juggling
776778
uint8_t y = __y, h = __h;
777-
uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x];
779+
if ((WIDTH == 64) && (HEIGHT == 48)) x += 32;
780+
uint8_t *pBuf = &buffer[x + (y / 8) * SSD1306_SEGMENTS];
778781

779782
// do the first partial byte, if necessary - this requires some masking
780783
uint8_t mod = (y & 7);
@@ -795,7 +798,7 @@ void Adafruit_SSD1306::drawFastVLineInternal(
795798
case BLACK: *pBuf &= ~mask; break;
796799
case INVERSE: *pBuf ^= mask; break;
797800
}
798-
pBuf += WIDTH;
801+
pBuf += SSD1306_SEGMENTS;
799802
}
800803

801804
if(h >= mod) { // More to go?
@@ -807,15 +810,15 @@ void Adafruit_SSD1306::drawFastVLineInternal(
807810
// black/white write version with an extra comparison per loop
808811
do {
809812
*pBuf ^= 0xFF; // Invert byte
810-
pBuf += WIDTH; // Advance pointer 8 rows
813+
pBuf += SSD1306_SEGMENTS; // Advance pointer 8 rows
811814
h -= 8; // Subtract 8 rows from height
812815
} while(h >= 8);
813816
} else {
814817
// store a local value to work with
815818
uint8_t val = (color != BLACK) ? 255 : 0;
816819
do {
817820
*pBuf = val; // Set byte
818-
pBuf += WIDTH; // Advance pointer 8 rows
821+
pBuf += SSD1306_SEGMENTS; // Advance pointer 8 rows
819822
h -= 8; // Subtract 8 rows from height
820823
} while(h >= 8);
821824
}
@@ -895,27 +898,16 @@ uint8_t *Adafruit_SSD1306::getBuffer(void) {
895898
*/
896899
void Adafruit_SSD1306::display(void) {
897900
TRANSACTION_START
898-
if ((WIDTH != 64) || (HEIGHT != 48)) {
899-
static const uint8_t PROGMEM dlist1a[] = {
900-
SSD1306_PAGEADDR,
901-
0, // Page start address
902-
0xFF, // Page end (not really, but works here)
903-
SSD1306_COLUMNADDR,
904-
0 }; // Column start address
905-
ssd1306_commandList(dlist1a, sizeof(dlist1a));
906-
ssd1306_command1(WIDTH - 1); // Column end address
907-
} else {
908-
static const uint8_t PROGMEM dlist1b[] = {
909-
SSD1306_PAGEADDR,
910-
0 }; // Page start address
911-
ssd1306_commandList(dlist1b, sizeof(dlist1b));
912-
ssd1306_command1((HEIGHT / 8) - 1); // Page end address
913-
static const uint8_t PROGMEM dlist2b[] = {
914-
SSD1306_COLUMNADDR,
915-
32 }; // Column start address
916-
ssd1306_commandList(dlist2b, sizeof(dlist2b));
917-
ssd1306_command1(32 + WIDTH - 1); // Column end address
918-
}
901+
static const uint8_t PROGMEM dlist1[] = {
902+
SSD1306_PAGEADDR,
903+
0 }; // Page start address
904+
ssd1306_commandList(dlist1, sizeof(dlist1));
905+
ssd1306_command1((HEIGHT + 7) / 8 - 1); // Page end address
906+
static const uint8_t PROGMEM dlist2[] = {
907+
SSD1306_COLUMNADDR,
908+
0 }; // Column start address
909+
ssd1306_commandList(dlist2, sizeof(dlist2));
910+
ssd1306_command1(SSD1306_SEGMENTS - 1); // Column end address
919911

920912
#if defined(ESP8266)
921913
// ESP8266 needs a periodic yield() call to avoid watchdog reset.
@@ -926,7 +918,7 @@ void Adafruit_SSD1306::display(void) {
926918
// 32-byte transfer condition below.
927919
yield();
928920
#endif
929-
uint16_t count = WIDTH * ((HEIGHT + 7) / 8);
921+
uint16_t count = SSD1306_SEGMENTS * ((HEIGHT + 7) / 8);
930922
uint8_t *ptr = buffer;
931923
if(wire) { // I2C
932924
wire->beginTransmission(i2caddr);

Adafruit_SSD1306.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@
9595
#define SSD1306_ACTIVATE_SCROLL 0x2F ///< Start scroll
9696
#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3 ///< Set scroll range
9797

98+
#define SSD1306_SEGMENTS 128 ///< See datasheet
99+
98100
// Deprecated size stuff for backwards compatibility with old sketches
99101
#if defined SSD1306_128_64
100102
#define SSD1306_LCDWIDTH 128 ///< DEPRECATED: width w/SSD1306_128_64 defined
@@ -140,11 +142,11 @@ class Adafruit_SSD1306 : public Adafruit_GFX {
140142
boolean periphBegin=true);
141143
void display(void);
142144
void clearDisplay(void);
143-
void invertDisplay(boolean i);
145+
virtual void invertDisplay(boolean i) override;
144146
void dim(boolean dim);
145-
void drawPixel(int16_t x, int16_t y, uint16_t color);
146-
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
147-
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
147+
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) override;
148+
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
149+
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
148150
void startscrollright(uint8_t start, uint8_t stop);
149151
void startscrollleft(uint8_t start, uint8_t stop);
150152
void startscrolldiagright(uint8_t start, uint8_t stop);

0 commit comments

Comments
 (0)