2727
2828#include " OLEDDisplay.h"
2929
30+ OLEDDisplay::~OLEDDisplay () {
31+ end ();
32+ }
33+
3034bool 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
5664void 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
6372void OLEDDisplay::resetDisplay (void ) {
@@ -73,11 +82,11 @@ void OLEDDisplay::setColor(OLEDDISPLAY_COLOR color) {
7382}
7483
7584void 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
224233void 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
257266void 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
354363void 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
553571void 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
695716void 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 {
0 commit comments