diff --git a/README_GEOMETRY_64_48.md b/README_GEOMETRY_64_48.md new file mode 100644 index 0000000..9b9bf91 --- /dev/null +++ b/README_GEOMETRY_64_48.md @@ -0,0 +1,20 @@ +# GEOMETRY_64_48 + +The 64x48 geometry setting are working with the `Wire.h` and `brzo_i2c` libraries. + +I've tested it successfully with a WEMOS D1 mini Lite and a WEMOS OLED shield + +Initialization code: + +- Wire +``` +#include +#include +SSD1306Wire display(0x3c, D2, D1, GEOMETRY_64_48 ); // WEMOS OLED shield +``` + +- BRZO i2c +``` +#include +SSD1306Brzo display(0x3c, D2, D1, GEOMETRY_64_48 ); // WEMOS OLED Shield +``` diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp index 318c48e..2bbc195 100644 --- a/src/OLEDDisplay.cpp +++ b/src/OLEDDisplay.cpp @@ -514,6 +514,15 @@ void OLEDDisplay::drawString(int16_t xMove, int16_t yMove, String strUser) { free(text); } +void OLEDDisplay::drawStringf( int16_t x, int16_t y, char* buffer, String format, ... ) +{ + va_list myargs; + va_start(myargs, format); + vsprintf(buffer, format.c_str(), myargs); + va_end(myargs); + drawString( x, y, buffer ); +} + void OLEDDisplay::drawStringMaxWidth(int16_t xMove, int16_t yMove, uint16_t maxLineWidth, String strUser) { uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); @@ -801,15 +810,20 @@ int OLEDDisplay::_putc(int c) { // Private functions void OLEDDisplay::setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width, uint16_t height) { this->geometry = g; + switch (g) { case GEOMETRY_128_64: this->displayWidth = 128; this->displayHeight = 64; break; - case GEOMETRY_128_32: + case GEOMETRY_128_32: this->displayWidth = 128; this->displayHeight = 32; break; + case GEOMETRY_64_48: + this->displayWidth = 64; + this->displayHeight = 48; + break; case GEOMETRY_RAWMODE: this->displayWidth = width > 0 ? width : 128; this->displayHeight = height > 0 ? height : 64; @@ -837,7 +851,7 @@ void OLEDDisplay::sendInitCommands(void) { sendCommand(COMSCANINC); sendCommand(SETCOMPINS); - if (geometry == GEOMETRY_128_64) { + if (geometry == GEOMETRY_128_64 || geometry == GEOMETRY_64_48) { sendCommand(0x12); } else if (geometry == GEOMETRY_128_32) { sendCommand(0x02); @@ -845,7 +859,7 @@ void OLEDDisplay::sendInitCommands(void) { sendCommand(SETCONTRAST); - if (geometry == GEOMETRY_128_64) { + if (geometry == GEOMETRY_128_64 || geometry == GEOMETRY_64_48) { sendCommand(0xCF); } else if (geometry == GEOMETRY_128_32) { sendCommand(0x8F); diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h index 2482c86..c377682 100644 --- a/src/OLEDDisplay.h +++ b/src/OLEDDisplay.h @@ -137,8 +137,9 @@ enum OLEDDISPLAY_TEXT_ALIGNMENT { enum OLEDDISPLAY_GEOMETRY { GEOMETRY_128_64 = 0, - GEOMETRY_128_32, - GEOMETRY_RAWMODE, + GEOMETRY_128_32 = 1, + GEOMETRY_64_48 = 2, + GEOMETRY_RAWMODE = 4 }; typedef char (*FontTableLookupFunction)(const uint8_t ch); @@ -221,6 +222,9 @@ class OLEDDisplay : public Stream { // Draws a string at the given location void drawString(int16_t x, int16_t y, String text); + // Draws a formatted string (like printf) at the given location + void drawStringf(int16_t x, int16_t y, char* buffer, String format, ... ); + // Draws a String with a maximum width at the given location. // If the given String is wider than the specified width // The text will be wrapped to the next line at a space or dash @@ -264,7 +268,7 @@ class OLEDDisplay : public Stream { // normal brightness & contrast: contrast = 100 void setContrast(uint8_t contrast, uint8_t precharge = 241, uint8_t comdetect = 64); - // Convenience method to access + // Convenience method to access void setBrightness(uint8_t); // Reset display rotation or mirroring diff --git a/src/SSD1306Brzo.h b/src/SSD1306Brzo.h index 987dd5b..fbcffcd 100644 --- a/src/SSD1306Brzo.h +++ b/src/SSD1306Brzo.h @@ -61,6 +61,8 @@ class SSD1306Brzo : public OLEDDisplay { } void display(void) { + const int x_offset = (128 - this->width()) / 2; + #ifdef OLEDDISPLAY_DOUBLE_BUFFER uint8_t minBoundY = UINT8_MAX; uint8_t maxBoundY = 0; @@ -72,9 +74,9 @@ class SSD1306Brzo : public OLEDDisplay { // Calculate the Y bounding box of changes // and copy buffer[pos] to buffer_back[pos]; - for (y = 0; y < (displayHeight / 8); y++) { - for (x = 0; x < displayWidth; x++) { - uint16_t pos = x + y * displayWidth; + for (y = 0; y < (this->height() / 8); y++) { + for (x = 0; x < this->width(); x++) { + uint16_t pos = x + y * this->width(); if (buffer[pos] != buffer_back[pos]) { minBoundY = _min(minBoundY, y); maxBoundY = _max(maxBoundY, y); @@ -92,23 +94,26 @@ class SSD1306Brzo : public OLEDDisplay { if (minBoundY == UINT8_MAX) return; sendCommand(COLUMNADDR); - sendCommand(minBoundX); - sendCommand(maxBoundX); + sendCommand(x_offset + minBoundX); + sendCommand(x_offset + maxBoundX); sendCommand(PAGEADDR); sendCommand(minBoundY); sendCommand(maxBoundY); byte k = 0; - uint8_t sendBuffer[17]; + + int buflen = ( this->width() / 8 ) + 1; + + uint8_t sendBuffer[buflen]; sendBuffer[0] = 0x40; brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED); for (y = minBoundY; y <= maxBoundY; y++) { for (x = minBoundX; x <= maxBoundX; x++) { k++; - sendBuffer[k] = buffer[x + y * displayWidth]; - if (k == 16) { - brzo_i2c_write(sendBuffer, 17, true); + sendBuffer[k] = buffer[x + y * this->width()]; + if (k == (buflen-1)) { + brzo_i2c_write(sendBuffer, buflen, true); k = 0; } } @@ -119,28 +124,28 @@ class SSD1306Brzo : public OLEDDisplay { #else // No double buffering sendCommand(COLUMNADDR); - sendCommand(0x0); - sendCommand(0x7F); + + sendCommand(x_offset); + sendCommand(x_offset + (this->width() - 1)); sendCommand(PAGEADDR); sendCommand(0x0); + sendCommand((this->height() / 8) - 1); - if (geometry == GEOMETRY_128_64) { - sendCommand(0x7); - } else if (geometry == GEOMETRY_128_32) { - sendCommand(0x3); - } + int buflen = ( this->width() / 8 ) + 1; - uint8_t sendBuffer[17]; + uint8_t sendBuffer[buflen]; sendBuffer[0] = 0x40; + brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED); + for (uint16_t i=0; i_address); Wire.write(0x40);