Skip to content

Commit 2a3bdf8

Browse files
committed
Merged lots of PR + fix some memory leaks
Library did some allocs without free and lots of un-initialized variables. Applied pull requests from esp8266-oled-ssd1306: #169 #157 #144 And applied the suggestions from issues: #170 #161 Support multiple display resolutions Applied PR from esp8266-oled-ssd1306: #133 Better Brightness / Contrast control Suggestions taken from this issue: #134 It is now the same version as being used in ESPeasy.
1 parent 7262836 commit 2a3bdf8

File tree

4 files changed

+108
-70
lines changed

4 files changed

+108
-70
lines changed

OLEDDisplay.cpp

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,32 @@
2727

2828
#include "OLEDDisplay.h"
2929

30+
OLEDDisplay::~OLEDDisplay() {
31+
end();
32+
}
33+
3034
bool OLEDDisplay::init() {
3135
if (!this->connect()) {
3236
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n");
3337
return false;
3438
}
39+
if(this->buffer==NULL) {
3540
this->buffer = (uint8_t*) malloc(sizeof(uint8_t) * DISPLAY_BUFFER_SIZE);
3641
if(!this->buffer) {
3742
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create display\n");
3843
return false;
3944
}
45+
}
4046

4147
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
48+
if(this->buffer_back==NULL) {
4249
this->buffer_back = (uint8_t*) malloc(sizeof(uint8_t) * DISPLAY_BUFFER_SIZE);
4350
if(!this->buffer_back) {
4451
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n");
4552
free(this->buffer);
4653
return false;
4754
}
55+
}
4856
#endif
4957

5058
sendInitCommands();
@@ -54,10 +62,11 @@ bool OLEDDisplay::init() {
5462
}
5563

5664
void OLEDDisplay::end() {
57-
if (this->buffer) free(this->buffer);
65+
if (this->buffer) { free(this->buffer); this->buffer = NULL; }
5866
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
59-
if (this->buffer_back) free(this->buffer_back);
67+
if (this->buffer_back) { free(this->buffer_back); this->buffer_back = NULL; }
6068
#endif
69+
if (this->logBuffer != NULL) { free(this->logBuffer); this->logBuffer = NULL; }
6170
}
6271

6372
void OLEDDisplay::resetDisplay(void) {
@@ -73,11 +82,11 @@ void OLEDDisplay::setColor(OLEDDISPLAY_COLOR color) {
7382
}
7483

7584
void OLEDDisplay::setPixel(int16_t x, int16_t y) {
76-
if (x >= 0 && x < 128 && y >= 0 && y < 64) {
85+
if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) {
7786
switch (color) {
78-
case WHITE: buffer[x + (y / 8) * DISPLAY_WIDTH] |= (1 << (y & 7)); break;
79-
case BLACK: buffer[x + (y / 8) * DISPLAY_WIDTH] &= ~(1 << (y & 7)); break;
80-
case INVERSE: buffer[x + (y / 8) * DISPLAY_WIDTH] ^= (1 << (y & 7)); break;
87+
case WHITE: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break;
88+
case BLACK: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break;
89+
case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break;
8190
}
8291
}
8392
}
@@ -222,21 +231,21 @@ void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) {
222231
}
223232

224233
void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
225-
if (y < 0 || y >= DISPLAY_HEIGHT) { return; }
234+
if (y < 0 || y >= this->height()) { return; }
226235

227236
if (x < 0) {
228237
length += x;
229238
x = 0;
230239
}
231240

232-
if ( (x + length) > DISPLAY_WIDTH) {
233-
length = (DISPLAY_WIDTH - x);
241+
if ( (x + length) > this->width()) {
242+
length = (this->width() - x);
234243
}
235244

236245
if (length <= 0) { return; }
237246

238247
uint8_t * bufferPtr = buffer;
239-
bufferPtr += (y >> 3) * DISPLAY_WIDTH;
248+
bufferPtr += (y >> 3) * this->width();
240249
bufferPtr += x;
241250

242251
uint8_t drawBit = 1 << (y & 7);
@@ -255,15 +264,15 @@ void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
255264
}
256265

257266
void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
258-
if (x < 0 || x >= DISPLAY_WIDTH) return;
267+
if (x < 0 || x >= this->width()) return;
259268

260269
if (y < 0) {
261270
length += y;
262271
y = 0;
263272
}
264273

265-
if ( (y + length) > DISPLAY_HEIGHT) {
266-
length = (DISPLAY_HEIGHT - y);
274+
if ( (y + length) > this->height()) {
275+
length = (this->height() - y);
267276
}
268277

269278
if (length <= 0) return;
@@ -273,7 +282,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
273282
uint8_t drawBit;
274283
uint8_t *bufferPtr = buffer;
275284

276-
bufferPtr += (y >> 3) * DISPLAY_WIDTH;
285+
bufferPtr += (y >> 3) * this->width();
277286
bufferPtr += x;
278287

279288
if (yOffset) {
@@ -293,7 +302,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
293302
if (length < yOffset) return;
294303

295304
length -= yOffset;
296-
bufferPtr += DISPLAY_WIDTH;
305+
bufferPtr += this->width();
297306
}
298307

299308
if (length >= 8) {
@@ -303,14 +312,14 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
303312
drawBit = (color == WHITE) ? 0xFF : 0x00;
304313
do {
305314
*bufferPtr = drawBit;
306-
bufferPtr += DISPLAY_WIDTH;
315+
bufferPtr += this->width();
307316
length -= 8;
308317
} while (length >= 8);
309318
break;
310319
case INVERSE:
311320
do {
312321
*bufferPtr = ~(*bufferPtr);
313-
bufferPtr += DISPLAY_WIDTH;
322+
bufferPtr += this->width();
314323
length -= 8;
315324
} while (length >= 8);
316325
break;
@@ -353,7 +362,7 @@ void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int
353362

354363
void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *xbm) {
355364
int16_t widthInXbm = (width + 7) / 8;
356-
uint8_t data;
365+
uint8_t data = 0;
357366

358367
for(int16_t y = 0; y < height; y++) {
359368
for(int16_t x = 0; x < width; x++ ) {
@@ -388,11 +397,13 @@ void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, u
388397
case TEXT_ALIGN_RIGHT:
389398
xMove -= textWidth;
390399
break;
400+
case TEXT_ALIGN_LEFT:
401+
break;
391402
}
392403

393404
// Don't draw anything if it is not on the screen.
394-
if (xMove + textWidth < 0 || xMove > DISPLAY_WIDTH ) {return;}
395-
if (yMove + textHeight < 0 || yMove > DISPLAY_HEIGHT) {return;}
405+
if (xMove + textWidth < 0 || xMove > this->width() ) {return;}
406+
if (yMove + textHeight < 0 || yMove > this->width() ) {return;}
396407

397408
for (uint16_t j = 0; j < textLength; j++) {
398409
int16_t xPos = xMove + cursorX;
@@ -545,9 +556,16 @@ void OLEDDisplay::normalDisplay(void) {
545556
sendCommand(NORMALDISPLAY);
546557
}
547558

548-
void OLEDDisplay::setContrast(char contrast) {
559+
void OLEDDisplay::setContrast(char contrast, char precharge, char comdetect) {
560+
sendCommand(SETPRECHARGE); //0xD9
561+
sendCommand(precharge); //0xF1 default, to lower the contrast, put 1-1F
549562
sendCommand(SETCONTRAST);
550-
sendCommand(contrast);
563+
sendCommand(contrast); // 0-255
564+
sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast)
565+
sendCommand(comdetect); //0x40 default, to lower the contrast, put 0
566+
sendCommand(DISPLAYALLON_RESUME);
567+
sendCommand(NORMALDISPLAY);
568+
sendCommand(DISPLAYON);
551569
}
552570

553571
void OLEDDisplay::flipScreenVertically() {
@@ -596,6 +614,7 @@ bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){
596614
uint16_t size = lines * chars;
597615
if (size > 0) {
598616
this->logBufferLine = 0; // Lines printed
617+
this->logBufferFilled = 0; // Nothing stored yet
599618
this->logBufferMaxLines = lines; // Lines max printable
600619
this->logBufferSize = size; // Total number of characters the buffer can hold
601620
this->logBuffer = (char *) malloc(size * sizeof(uint8_t));
@@ -670,7 +689,7 @@ void OLEDDisplay::sendInitCommands(void) {
670689
sendCommand(SETDISPLAYCLOCKDIV);
671690
sendCommand(0xF0); // Increase speed of the display max ~96Hz
672691
sendCommand(SETMULTIPLEX);
673-
sendCommand(0x3F);
692+
sendCommand(this->height() - 1);
674693
sendCommand(SETDISPLAYOFFSET);
675694
sendCommand(0x00);
676695
sendCommand(SETSTARTLINE);
@@ -681,11 +700,13 @@ void OLEDDisplay::sendInitCommands(void) {
681700
sendCommand(SEGREMAP);
682701
sendCommand(COMSCANINC);
683702
sendCommand(SETCOMPINS);
684-
sendCommand(0x12);
703+
sendCommand(0x12); // according to the adafruit lib, sometimes this may need to be 0x02
685704
sendCommand(SETCONTRAST);
686705
sendCommand(0xCF);
687706
sendCommand(SETPRECHARGE);
688707
sendCommand(0xF1);
708+
sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast)
709+
sendCommand(0x40); //0x40 default, to lower the contrast, put 0
689710
sendCommand(DISPLAYALLON_RESUME);
690711
sendCommand(NORMALDISPLAY);
691712
sendCommand(0x2e); // stop scroll
@@ -694,8 +715,8 @@ void OLEDDisplay::sendInitCommands(void) {
694715

695716
void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData) {
696717
if (width < 0 || height < 0) return;
697-
if (yMove + height < 0 || yMove > DISPLAY_HEIGHT) return;
698-
if (xMove + width < 0 || xMove > DISPLAY_WIDTH) return;
718+
if (yMove + height < 0 || yMove > this->height()) return;
719+
if (xMove + width < 0 || xMove > this->width()) return;
699720

700721
uint8_t rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0)
701722
int8_t yOffset = yMove & 7;
@@ -717,25 +738,25 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt
717738
byte currentByte = pgm_read_byte(data + offset + i);
718739

719740
int16_t xPos = xMove + (i / rasterHeight);
720-
int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * DISPLAY_WIDTH;
741+
int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * this->width();
721742

722-
int16_t yScreenPos = yMove + yOffset;
743+
// int16_t yScreenPos = yMove + yOffset;
723744
int16_t dataPos = xPos + yPos;
724745

725746
if (dataPos >= 0 && dataPos < DISPLAY_BUFFER_SIZE &&
726-
xPos >= 0 && xPos < DISPLAY_WIDTH ) {
747+
xPos >= 0 && xPos < this->width() ) {
727748

728749
if (yOffset >= 0) {
729750
switch (this->color) {
730751
case WHITE: buffer[dataPos] |= currentByte << yOffset; break;
731752
case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break;
732753
case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break;
733754
}
734-
if (dataPos < (DISPLAY_BUFFER_SIZE - DISPLAY_WIDTH)) {
755+
if (dataPos < (DISPLAY_BUFFER_SIZE - this->width())) {
735756
switch (this->color) {
736-
case WHITE: buffer[dataPos + DISPLAY_WIDTH] |= currentByte >> (8 - yOffset); break;
737-
case BLACK: buffer[dataPos + DISPLAY_WIDTH] &= ~(currentByte >> (8 - yOffset)); break;
738-
case INVERSE: buffer[dataPos + DISPLAY_WIDTH] ^= currentByte >> (8 - yOffset); break;
757+
case WHITE: buffer[dataPos + this->width()] |= currentByte >> (8 - yOffset); break;
758+
case BLACK: buffer[dataPos + this->width()] &= ~(currentByte >> (8 - yOffset)); break;
759+
case INVERSE: buffer[dataPos + this->width()] ^= currentByte >> (8 - yOffset); break;
739760
}
740761
}
741762
} else {

OLEDDisplay.h

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,13 @@
4444

4545

4646
// Display settings
47-
#define DISPLAY_WIDTH 128
48-
#define DISPLAY_HEIGHT 64
49-
#define DISPLAY_BUFFER_SIZE 1024
47+
#ifndef DISPLAY_WIDTH
48+
#define DISPLAY_WIDTH 128
49+
#endif
50+
#ifndef DISPLAY_HEIGHT
51+
#define DISPLAY_HEIGHT 64
52+
#endif
53+
#define DISPLAY_BUFFER_SIZE DISPLAY_WIDTH * DISPLAY_HEIGHT / 8
5054

5155
// Header Values
5256
#define JUMPTABLE_BYTES 4
@@ -109,7 +113,16 @@ enum OLEDDISPLAY_TEXT_ALIGNMENT {
109113

110114

111115
class OLEDDisplay : public Print {
116+
private:
117+
const int _width, _height;
118+
112119
public:
120+
OLEDDisplay(const int width = DISPLAY_WIDTH, const int height = DISPLAY_HEIGHT) : _width(width), _height(height){ };
121+
virtual ~OLEDDisplay();
122+
123+
const int width(void) const { return _width; };
124+
const int height(void) const { return _height; };
125+
113126
// Initialize the display
114127
bool init();
115128

@@ -150,7 +163,7 @@ class OLEDDisplay : public Print {
150163
// Draw a lin vertically
151164
void drawVerticalLine(int16_t x, int16_t y, int16_t length);
152165

153-
// Draws a rounded progress bar with the outer dimensions given by width and height. Progress is
166+
// Draws a rounded progress bar with the outer dimensions given by width and height. Progress is
154167
// a unsigned byte value between 0 and 100
155168
void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress);
156169

@@ -201,7 +214,9 @@ class OLEDDisplay : public Print {
201214
void normalDisplay(void);
202215

203216
// Set display contrast
204-
void setContrast(char contrast);
217+
// really low brightness & contrast: contrast = 10, precharge = 5, comdetect = 0
218+
// normal brightness & contrast: contrast = 100
219+
void setContrast(char contrast, char precharge = 241, char comdetect = 64);
205220

206221
// Turn the display upside down
207222
void flipScreenVertically();
@@ -226,10 +241,10 @@ class OLEDDisplay : public Print {
226241
size_t write(uint8_t c);
227242
size_t write(const char* s);
228243

229-
uint8_t *buffer;
244+
uint8_t *buffer = NULL;
230245

231246
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
232-
uint8_t *buffer_back;
247+
uint8_t *buffer_back = NULL;
233248
#endif
234249

235250
protected:
@@ -247,10 +262,10 @@ class OLEDDisplay : public Print {
247262
char *logBuffer = NULL;
248263

249264
// Send a command to the display (low level function)
250-
virtual void sendCommand(uint8_t com) {};
265+
virtual void sendCommand(uint8_t com) {(void)com;};
251266

252267
// Connect to the display
253-
virtual bool connect() {};
268+
virtual bool connect() { return false; };
254269

255270
// Send all the init commands
256271
void sendInitCommands();

0 commit comments

Comments
 (0)