Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 55 additions & 33 deletions OLEDDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,35 @@

#include "OLEDDisplay.h"

OLEDDisplay::~OLEDDisplay() {
end();
}

bool OLEDDisplay::init() {
if (!this->connect()) {
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n");
return false;
}

if(this->buffer==NULL) {
this->buffer = (uint8_t*) malloc(sizeof(uint8_t) * displayBufferSize);

if(!this->buffer) {
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create display\n");
return false;
}
}

#ifdef OLEDDISPLAY_DOUBLE_BUFFER
if(this->buffer_back==NULL) {
this->buffer_back = (uint8_t*) malloc(sizeof(uint8_t) * displayBufferSize);

if(!this->buffer_back) {
DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n");
free(this->buffer);
return false;
}
}
#endif

sendInitCommands();
Expand All @@ -54,10 +65,11 @@ bool OLEDDisplay::init() {
}

void OLEDDisplay::end() {
if (this->buffer) free(this->buffer);
if (this->buffer) { free(this->buffer); this->buffer = NULL; }
#ifdef OLEDDISPLAY_DOUBLE_BUFFER
if (this->buffer_back) free(this->buffer_back);
if (this->buffer_back) { free(this->buffer_back); this->buffer_back = NULL; }
#endif
if (this->logBuffer != NULL) { free(this->logBuffer); this->logBuffer = NULL; }
}

void OLEDDisplay::resetDisplay(void) {
Expand All @@ -77,12 +89,11 @@ OLEDDISPLAY_COLOR OLEDDisplay::getColor() {
}

void OLEDDisplay::setPixel(int16_t x, int16_t y) {
if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {

if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) {
switch (color) {
case WHITE: buffer[x + (y / 8) * displayWidth] |= (1 << (y & 7)); break;
case BLACK: buffer[x + (y / 8) * displayWidth] &= ~(1 << (y & 7)); break;
case INVERSE: buffer[x + (y / 8) * displayWidth] ^= (1 << (y & 7)); break;
case WHITE: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break;
case BLACK: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break;
case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break;
}
}
}
Expand Down Expand Up @@ -227,21 +238,21 @@ void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) {
}

void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
if (y < 0 || y >= displayHeight) { return; }
if (y < 0 || y >= this->height()) { return; }

if (x < 0) {
length += x;
x = 0;
}

if ( (x + length) > displayWidth) {
length = (displayWidth - x);
if ( (x + length) > this->width()) {
length = (this->width() - x);
}

if (length <= 0) { return; }

uint8_t * bufferPtr = buffer;
bufferPtr += (y >> 3) * displayWidth;
bufferPtr += (y >> 3) * this->width();
bufferPtr += x;

uint8_t drawBit = 1 << (y & 7);
Expand All @@ -260,15 +271,15 @@ void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) {
}

void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
if (x < 0 || x > displayWidth) return;
if (x < 0 || x >= this->width()) return;

if (y < 0) {
length += y;
y = 0;
}

if ( (y + length) > displayHeight) {
length = (displayHeight - y);
if ( (y + length) > this->height()) {
length = (this->height() - y);
}

if (length <= 0) return;
Expand All @@ -278,7 +289,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
uint8_t drawBit;
uint8_t *bufferPtr = buffer;

bufferPtr += (y >> 3) * displayWidth;
bufferPtr += (y >> 3) * this->width();
bufferPtr += x;

if (yOffset) {
Expand All @@ -298,7 +309,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
if (length < yOffset) return;

length -= yOffset;
bufferPtr += displayWidth;
bufferPtr += this->width();
}

if (length >= 8) {
Expand All @@ -308,14 +319,14 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
drawBit = (color == WHITE) ? 0xFF : 0x00;
do {
*bufferPtr = drawBit;
bufferPtr += displayWidth;
bufferPtr += this->width();
length -= 8;
} while (length >= 8);
break;
case INVERSE:
do {
*bufferPtr = ~(*bufferPtr);
bufferPtr += displayWidth;
bufferPtr += this->width();
length -= 8;
} while (length >= 8);
break;
Expand Down Expand Up @@ -398,8 +409,8 @@ void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, u
}

// Don't draw anything if it is not on the screen.
if (xMove + textWidth < 0 || xMove > displayWidth ) {return;}
if (yMove + textHeight < 0 || yMove > displayHeight) {return;}
if (xMove + textWidth < 0 || xMove > this->width() ) {return;}
if (yMove + textHeight < 0 || yMove > this->width() ) {return;}

for (uint16_t j = 0; j < textLength; j++) {
int16_t xPos = xMove + cursorX;
Expand Down Expand Up @@ -552,9 +563,16 @@ void OLEDDisplay::normalDisplay(void) {
sendCommand(NORMALDISPLAY);
}

void OLEDDisplay::setContrast(char contrast) {
void OLEDDisplay::setContrast(char contrast, char precharge, char comdetect) {
sendCommand(SETPRECHARGE); //0xD9
sendCommand(precharge); //0xF1 default, to lower the contrast, put 1-1F
sendCommand(SETCONTRAST);
sendCommand(contrast);
sendCommand(contrast); // 0-255
sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast)
sendCommand(comdetect); //0x40 default, to lower the contrast, put 0
sendCommand(DISPLAYALLON_RESUME);
sendCommand(NORMALDISPLAY);
sendCommand(DISPLAYON);
}

void OLEDDisplay::resetOrientation() {
Expand Down Expand Up @@ -621,6 +639,7 @@ bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){
uint16_t size = lines * chars;
if (size > 0) {
this->logBufferLine = 0; // Lines printed
this->logBufferFilled = 0; // Nothing stored yet
this->logBufferMaxLines = lines; // Lines max printable
this->logBufferSize = size; // Total number of characters the buffer can hold
this->logBuffer = (char *) malloc(size * sizeof(uint8_t));
Expand Down Expand Up @@ -700,8 +719,7 @@ void OLEDDisplay::sendInitCommands(void) {
sendCommand(SETDISPLAYCLOCKDIV);
sendCommand(0xF0); // Increase speed of the display max ~96Hz
sendCommand(SETMULTIPLEX);
//sendCommand(0x3F);
sendCommand(displayHeight - 1);
sendCommand(this->height() - 1);
sendCommand(SETDISPLAYOFFSET);
sendCommand(0x00);
sendCommand(SETSTARTLINE);
Expand All @@ -718,7 +736,7 @@ void OLEDDisplay::sendInitCommands(void) {
} else if (geometry == GEOMETRY_128_32) {
sendCommand(0x02);
}

sendCommand(SETCONTRAST);

if (geometry == GEOMETRY_128_64) {
Expand All @@ -729,6 +747,8 @@ void OLEDDisplay::sendInitCommands(void) {

sendCommand(SETPRECHARGE);
sendCommand(0xF1);
sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast)
sendCommand(0x40); //0x40 default, to lower the contrast, put 0
sendCommand(DISPLAYALLON_RESUME);
sendCommand(NORMALDISPLAY);
sendCommand(0x2e); // stop scroll
Expand All @@ -737,8 +757,8 @@ void OLEDDisplay::sendInitCommands(void) {

void 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) {
if (width < 0 || height < 0) return;
if (yMove + height < 0 || yMove > displayHeight) return;
if (xMove + width < 0 || xMove > displayWidth) return;
if (yMove + height < 0 || yMove > this->height()) return;
if (xMove + width < 0 || xMove > this->width()) return;

uint8_t rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0)
int8_t yOffset = yMove & 7;
Expand All @@ -760,24 +780,26 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt
byte currentByte = pgm_read_byte(data + offset + i);

int16_t xPos = xMove + (i / rasterHeight);
int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * displayWidth;
int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * this->width();

// int16_t yScreenPos = yMove + yOffset;
int16_t dataPos = xPos + yPos;

if (dataPos >= 0 && dataPos < displayBufferSize &&
xPos >= 0 && xPos < displayWidth ) {
xPos >= 0 && xPos < this->width() ) {

if (yOffset >= 0) {
switch (this->color) {
case WHITE: buffer[dataPos] |= currentByte << yOffset; break;
case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break;
case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break;
}
if (dataPos < (displayBufferSize - displayWidth)) {

if (dataPos < (displayBufferSize - this->width())) {
switch (this->color) {
case WHITE: buffer[dataPos + displayWidth] |= currentByte >> (8 - yOffset); break;
case BLACK: buffer[dataPos + displayWidth] &= ~(currentByte >> (8 - yOffset)); break;
case INVERSE: buffer[dataPos + displayWidth] ^= currentByte >> (8 - yOffset); break;
case WHITE: buffer[dataPos + this->width()] |= currentByte >> (8 - yOffset); break;
case BLACK: buffer[dataPos + this->width()] &= ~(currentByte >> (8 - yOffset)); break;
case INVERSE: buffer[dataPos + this->width()] ^= currentByte >> (8 - yOffset); break;
}
}
} else {
Expand Down
20 changes: 14 additions & 6 deletions OLEDDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,15 @@ typedef byte (*FontTableLookupFunction)(const byte ch);


class OLEDDisplay : public Print {
private:
const int _width, _height;

public:
virtual ~OLEDDisplay() {}

virtual ~OLEDDisplay();

const int width(void) const { return displayWidth; };
const int height(void) const { return displayHeight; };

// Initialize the display
bool init();

Expand Down Expand Up @@ -211,7 +217,9 @@ class OLEDDisplay : public Print {
void normalDisplay(void);

// Set display contrast
void setContrast(char contrast);
// really low brightness & contrast: contrast = 10, precharge = 5, comdetect = 0
// normal brightness & contrast: contrast = 100
void setContrast(char contrast, char precharge = 241, char comdetect = 64);

// Reset display rotation or mirroring
void resetOrientation();
Expand Down Expand Up @@ -246,10 +254,10 @@ class OLEDDisplay : public Print {
size_t write(uint8_t c);
size_t write(const char* s);

uint8_t *buffer;
uint8_t *buffer = NULL;

#ifdef OLEDDISPLAY_DOUBLE_BUFFER
uint8_t *buffer_back;
uint8_t *buffer_back = NULL;
#endif

protected:
Expand All @@ -276,7 +284,7 @@ class OLEDDisplay : public Print {
virtual void sendCommand(uint8_t com) {(void)com;};

// Connect to the display
virtual bool connect() {return false;};
virtual bool connect() { return false; };

// Send all the init commands
void sendInitCommands();
Expand Down
33 changes: 17 additions & 16 deletions OLEDDisplayUi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,32 +251,32 @@ void OLEDDisplayUi::drawFrame(){
switch (this->state.frameState){
case IN_TRANSITION: {
float progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition;
int16_t x = 0, y = 0, x1 = 0, y1 = 0;
int16_t x = 0, y = 0, x1 = 0, y1 = 0;
switch(this->frameAnimationDirection){
case SLIDE_LEFT:
x = -(this->display->getWidth()) * progress;
x = -this->display->width() * progress;
y = 0;
x1 = x + this->display->getWidth();
x1 = x + this->display->width();
y1 = 0;
break;
case SLIDE_RIGHT:
x = this->display->getWidth() * progress;
x = this->display->width() * progress;
y = 0;
x1 = x - this->display->getWidth();
x1 = x - this->display->width();
y1 = 0;
break;
case SLIDE_UP:
x = 0;
y = -(this->display->getHeight()) * progress;
y = -this->display->height() * progress;
x1 = 0;
y1 = y + (this->display->getHeight());
y1 = y + this->display->height();
break;
case SLIDE_DOWN:
default:
x = 0;
y = (this->display->getHeight()) * progress;
y = this->display->height() * progress;
x1 = 0;
y1 = y - (this->display->getHeight());
y1 = y - this->display->height();
break;
}

Expand Down Expand Up @@ -371,27 +371,28 @@ void OLEDDisplayUi::drawIndicator() {
uint16_t frameStartPos = (indicatorSpacing * frameCount / 2);
const uint8_t *image;

uint16_t x,y;
uint16_t x = 0,y = 0;


for (byte i = 0; i < this->frameCount; i++) {

switch (this->indicatorPosition){
case TOP:
y = 0 - (8 * indicatorFadeProgress);
x = (this->display->getWidth() / 2) - frameStartPos + indicatorSpacing * i;
x = (this->display->width() / 2) - frameStartPos + 12 * i;
break;
case BOTTOM:
y = (this->display->getHeight() - 8) + (8 * indicatorFadeProgress);
x = (this->display->getWidth() / 2) - frameStartPos + indicatorSpacing * i;
y = (this->display->height() - 8) + (8 * indicatorFadeProgress);
x = (this->display->width() / 2) - frameStartPos + 12 * i;
break;
case RIGHT:
x = (this->display->getWidth() - 8) + (8 * indicatorFadeProgress);
y = (this->display->getHeight() / 2) - frameStartPos + indicatorSpacing * i;
x = (this->display->width() - 8) + (8 * indicatorFadeProgress);
y = (this->display->height() / 2) - frameStartPos + 2 + 12 * i;
break;
case LEFT:
default:
x = 0 - (8 * indicatorFadeProgress);
y = (this->display->getHeight() / 2) - frameStartPos + indicatorSpacing * i;
y = (this->display->height() / 2) - frameStartPos + 2 + indicatorSpacing * i;
break;
}

Expand Down
Loading