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+
40+ if (this ->buffer ==NULL ) {
3541 this ->buffer = (uint8_t *) malloc (sizeof (uint8_t ) * displayBufferSize);
42+
3643 if (!this ->buffer ) {
3744 DEBUG_OLEDDISPLAY (" [OLEDDISPLAY][init] Not enough memory to create display\n " );
3845 return false ;
3946 }
47+ }
4048
4149 #ifdef OLEDDISPLAY_DOUBLE_BUFFER
50+ if (this ->buffer_back ==NULL ) {
4251 this ->buffer_back = (uint8_t *) malloc (sizeof (uint8_t ) * displayBufferSize);
52+
4353 if (!this ->buffer_back ) {
4454 DEBUG_OLEDDISPLAY (" [OLEDDISPLAY][init] Not enough memory to create back buffer\n " );
4555 free (this ->buffer );
4656 return false ;
4757 }
58+ }
4859 #endif
4960
5061 sendInitCommands ();
@@ -54,10 +65,11 @@ bool OLEDDisplay::init() {
5465}
5566
5667void OLEDDisplay::end () {
57- if (this ->buffer ) free (this ->buffer );
68+ if (this ->buffer ) { free (this ->buffer ); this -> buffer = NULL ; }
5869 #ifdef OLEDDISPLAY_DOUBLE_BUFFER
59- if (this ->buffer_back ) free (this ->buffer_back );
70+ if (this ->buffer_back ) { free (this ->buffer_back ); this -> buffer_back = NULL ; }
6071 #endif
72+ if (this ->logBuffer != NULL ) { free (this ->logBuffer ); this ->logBuffer = NULL ; }
6173}
6274
6375void OLEDDisplay::resetDisplay (void ) {
@@ -77,12 +89,11 @@ OLEDDISPLAY_COLOR OLEDDisplay::getColor() {
7789}
7890
7991void OLEDDisplay::setPixel (int16_t x, int16_t y) {
80- if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
81-
92+ if (x >= 0 && x < this ->width () && y >= 0 && y < this ->height ()) {
8293 switch (color) {
83- case WHITE: buffer[x + (y / 8 ) * displayWidth ] |= (1 << (y & 7 )); break ;
84- case BLACK: buffer[x + (y / 8 ) * displayWidth ] &= ~(1 << (y & 7 )); break ;
85- case INVERSE: buffer[x + (y / 8 ) * displayWidth ] ^= (1 << (y & 7 )); break ;
94+ case WHITE: buffer[x + (y / 8 ) * this -> width () ] |= (1 << (y & 7 )); break ;
95+ case BLACK: buffer[x + (y / 8 ) * this -> width () ] &= ~(1 << (y & 7 )); break ;
96+ case INVERSE: buffer[x + (y / 8 ) * this -> width () ] ^= (1 << (y & 7 )); break ;
8697 }
8798 }
8899}
@@ -227,21 +238,21 @@ void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) {
227238}
228239
229240void OLEDDisplay::drawHorizontalLine (int16_t x, int16_t y, int16_t length) {
230- if (y < 0 || y >= displayHeight ) { return ; }
241+ if (y < 0 || y >= this -> height () ) { return ; }
231242
232243 if (x < 0 ) {
233244 length += x;
234245 x = 0 ;
235246 }
236247
237- if ( (x + length) > displayWidth ) {
238- length = (displayWidth - x);
248+ if ( (x + length) > this -> width () ) {
249+ length = (this -> width () - x);
239250 }
240251
241252 if (length <= 0 ) { return ; }
242253
243254 uint8_t * bufferPtr = buffer;
244- bufferPtr += (y >> 3 ) * displayWidth ;
255+ bufferPtr += (y >> 3 ) * this -> width () ;
245256 bufferPtr += x;
246257
247258 uint8_t drawBit = 1 << (y & 7 );
@@ -260,15 +271,15 @@ void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
260271}
261272
262273void OLEDDisplay::drawVerticalLine (int16_t x, int16_t y, int16_t length) {
263- if (x < 0 || x > displayWidth ) return ;
274+ if (x < 0 || x >= this -> width () ) return ;
264275
265276 if (y < 0 ) {
266277 length += y;
267278 y = 0 ;
268279 }
269280
270- if ( (y + length) > displayHeight ) {
271- length = (displayHeight - y);
281+ if ( (y + length) > this -> height () ) {
282+ length = (this -> height () - y);
272283 }
273284
274285 if (length <= 0 ) return ;
@@ -278,7 +289,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
278289 uint8_t drawBit;
279290 uint8_t *bufferPtr = buffer;
280291
281- bufferPtr += (y >> 3 ) * displayWidth ;
292+ bufferPtr += (y >> 3 ) * this -> width () ;
282293 bufferPtr += x;
283294
284295 if (yOffset) {
@@ -298,7 +309,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
298309 if (length < yOffset) return ;
299310
300311 length -= yOffset;
301- bufferPtr += displayWidth ;
312+ bufferPtr += this -> width () ;
302313 }
303314
304315 if (length >= 8 ) {
@@ -308,14 +319,14 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
308319 drawBit = (color == WHITE) ? 0xFF : 0x00 ;
309320 do {
310321 *bufferPtr = drawBit;
311- bufferPtr += displayWidth ;
322+ bufferPtr += this -> width () ;
312323 length -= 8 ;
313324 } while (length >= 8 );
314325 break ;
315326 case INVERSE:
316327 do {
317328 *bufferPtr = ~(*bufferPtr);
318- bufferPtr += displayWidth ;
329+ bufferPtr += this -> width () ;
319330 length -= 8 ;
320331 } while (length >= 8 );
321332 break ;
@@ -398,8 +409,8 @@ void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, u
398409 }
399410
400411 // Don't draw anything if it is not on the screen.
401- if (xMove + textWidth < 0 || xMove > displayWidth ) {return ;}
402- if (yMove + textHeight < 0 || yMove > displayHeight ) {return ;}
412+ if (xMove + textWidth < 0 || xMove > this -> width () ) {return ;}
413+ if (yMove + textHeight < 0 || yMove > this -> width () ) {return ;}
403414
404415 for (uint16_t j = 0 ; j < textLength; j++) {
405416 int16_t xPos = xMove + cursorX;
@@ -552,9 +563,16 @@ void OLEDDisplay::normalDisplay(void) {
552563 sendCommand (NORMALDISPLAY);
553564}
554565
555- void OLEDDisplay::setContrast (char contrast) {
566+ void OLEDDisplay::setContrast (char contrast, char precharge, char comdetect) {
567+ sendCommand (SETPRECHARGE); // 0xD9
568+ sendCommand (precharge); // 0xF1 default, to lower the contrast, put 1-1F
556569 sendCommand (SETCONTRAST);
557- sendCommand (contrast);
570+ sendCommand (contrast); // 0-255
571+ sendCommand (SETVCOMDETECT); // 0xDB, (additionally needed to lower the contrast)
572+ sendCommand (comdetect); // 0x40 default, to lower the contrast, put 0
573+ sendCommand (DISPLAYALLON_RESUME);
574+ sendCommand (NORMALDISPLAY);
575+ sendCommand (DISPLAYON);
558576}
559577
560578void OLEDDisplay::resetOrientation () {
@@ -621,6 +639,7 @@ bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){
621639 uint16_t size = lines * chars;
622640 if (size > 0 ) {
623641 this ->logBufferLine = 0 ; // Lines printed
642+ this ->logBufferFilled = 0 ; // Nothing stored yet
624643 this ->logBufferMaxLines = lines; // Lines max printable
625644 this ->logBufferSize = size; // Total number of characters the buffer can hold
626645 this ->logBuffer = (char *) malloc (size * sizeof (uint8_t ));
@@ -700,8 +719,7 @@ void OLEDDisplay::sendInitCommands(void) {
700719 sendCommand (SETDISPLAYCLOCKDIV);
701720 sendCommand (0xF0 ); // Increase speed of the display max ~96Hz
702721 sendCommand (SETMULTIPLEX);
703- // sendCommand(0x3F);
704- sendCommand (displayHeight - 1 );
722+ sendCommand (this ->height () - 1 );
705723 sendCommand (SETDISPLAYOFFSET);
706724 sendCommand (0x00 );
707725 sendCommand (SETSTARTLINE);
@@ -718,7 +736,7 @@ void OLEDDisplay::sendInitCommands(void) {
718736 } else if (geometry == GEOMETRY_128_32) {
719737 sendCommand (0x02 );
720738 }
721-
739+
722740 sendCommand (SETCONTRAST);
723741
724742 if (geometry == GEOMETRY_128_64) {
@@ -729,6 +747,8 @@ void OLEDDisplay::sendInitCommands(void) {
729747
730748 sendCommand (SETPRECHARGE);
731749 sendCommand (0xF1 );
750+ sendCommand (SETVCOMDETECT); // 0xDB, (additionally needed to lower the contrast)
751+ sendCommand (0x40 ); // 0x40 default, to lower the contrast, put 0
732752 sendCommand (DISPLAYALLON_RESUME);
733753 sendCommand (NORMALDISPLAY);
734754 sendCommand (0x2e ); // stop scroll
@@ -737,8 +757,8 @@ void OLEDDisplay::sendInitCommands(void) {
737757
738758void inline OLEDDisplay::drawInternal (int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) {
739759 if (width < 0 || height < 0 ) return ;
740- if (yMove + height < 0 || yMove > displayHeight ) return ;
741- if (xMove + width < 0 || xMove > displayWidth ) return ;
760+ if (yMove + height < 0 || yMove > this -> height () ) return ;
761+ if (xMove + width < 0 || xMove > this -> width () ) return ;
742762
743763 uint8_t rasterHeight = 1 + ((height - 1 ) >> 3 ); // fast ceil(height / 8.0)
744764 int8_t yOffset = yMove & 7 ;
@@ -760,24 +780,26 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt
760780 byte currentByte = pgm_read_byte (data + offset + i);
761781
762782 int16_t xPos = xMove + (i / rasterHeight);
763- int16_t yPos = ((yMove >> 3 ) + (i % rasterHeight)) * displayWidth ;
783+ int16_t yPos = ((yMove >> 3 ) + (i % rasterHeight)) * this -> width () ;
764784
785+ // int16_t yScreenPos = yMove + yOffset;
765786 int16_t dataPos = xPos + yPos;
766787
767788 if (dataPos >= 0 && dataPos < displayBufferSize &&
768- xPos >= 0 && xPos < displayWidth ) {
789+ xPos >= 0 && xPos < this -> width () ) {
769790
770791 if (yOffset >= 0 ) {
771792 switch (this ->color ) {
772793 case WHITE: buffer[dataPos] |= currentByte << yOffset; break ;
773794 case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break ;
774795 case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break ;
775796 }
776- if (dataPos < (displayBufferSize - displayWidth)) {
797+
798+ if (dataPos < (displayBufferSize - this ->width ())) {
777799 switch (this ->color ) {
778- case WHITE: buffer[dataPos + displayWidth ] |= currentByte >> (8 - yOffset); break ;
779- case BLACK: buffer[dataPos + displayWidth ] &= ~(currentByte >> (8 - yOffset)); break ;
780- case INVERSE: buffer[dataPos + displayWidth ] ^= currentByte >> (8 - yOffset); break ;
800+ case WHITE: buffer[dataPos + this -> width () ] |= currentByte >> (8 - yOffset); break ;
801+ case BLACK: buffer[dataPos + this -> width () ] &= ~(currentByte >> (8 - yOffset)); break ;
802+ case INVERSE: buffer[dataPos + this -> width () ] ^= currentByte >> (8 - yOffset); break ;
781803 }
782804 }
783805 } else {
0 commit comments