diff --git a/OLEDDisplay.cpp b/OLEDDisplay.cpp
index f8fc226519b37df85862d0ff3e72bd26a4691eaa..466bb687c10dfe41444aa1ea787eef9a4b5ef513 100644
--- a/OLEDDisplay.cpp
+++ b/OLEDDisplay.cpp
@@ -32,14 +32,14 @@ bool OLEDDisplay::init() {
     DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n");
     return false;
   }
-  this->buffer = (uint8_t*) malloc(sizeof(uint8_t) * DISPLAY_BUFFER_SIZE);
+  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
-  this->buffer_back = (uint8_t*) malloc(sizeof(uint8_t) * DISPLAY_BUFFER_SIZE);
+  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);
@@ -63,7 +63,7 @@ void OLEDDisplay::end() {
 void OLEDDisplay::resetDisplay(void) {
   clear();
   #ifdef OLEDDISPLAY_DOUBLE_BUFFER
-  memset(buffer_back, 1, DISPLAY_BUFFER_SIZE);
+  memset(buffer_back, 1, displayBufferSize);
   #endif
   display();
 }
@@ -72,12 +72,17 @@ void OLEDDisplay::setColor(OLEDDISPLAY_COLOR color) {
   this->color = color;
 }
 
+OLEDDISPLAY_COLOR OLEDDisplay::getColor() {
+  return this->color;
+}
+
 void OLEDDisplay::setPixel(int16_t x, int16_t y) {
-  if (x >= 0 && x < 128 && y >= 0 && y < 64) {
+  if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
+
     switch (color) {
-      case WHITE:   buffer[x + (y / 8) * DISPLAY_WIDTH] |=  (1 << (y & 7)); break;
-      case BLACK:   buffer[x + (y / 8) * DISPLAY_WIDTH] &= ~(1 << (y & 7)); break;
-      case INVERSE: buffer[x + (y / 8) * DISPLAY_WIDTH] ^=  (1 << (y & 7)); break;
+      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;
     }
   }
 }
@@ -222,21 +227,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 >= DISPLAY_HEIGHT) { return; }
+  if (y < 0 || y >= displayHeight) { return; }
 
   if (x < 0) {
     length += x;
     x = 0;
   }
 
-  if ( (x + length) > DISPLAY_WIDTH) {
-    length = (DISPLAY_WIDTH - x);
+  if ( (x + length) > displayWidth) {
+    length = (displayWidth - x);
   }
 
   if (length <= 0) { return; }
 
   uint8_t * bufferPtr = buffer;
-  bufferPtr += (y >> 3) * DISPLAY_WIDTH;
+  bufferPtr += (y >> 3) * displayWidth;
   bufferPtr += x;
 
   uint8_t drawBit = 1 << (y & 7);
@@ -255,15 +260,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 >= DISPLAY_WIDTH) return;
+  if (x < 0 || x > displayWidth) return;
 
   if (y < 0) {
     length += y;
     y = 0;
   }
 
-  if ( (y + length) > DISPLAY_HEIGHT) {
-    length = (DISPLAY_HEIGHT - y);
+  if ( (y + length) > displayHeight) {
+    length = (displayHeight - y);
   }
 
   if (length <= 0) return;
@@ -273,7 +278,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
   uint8_t drawBit;
   uint8_t *bufferPtr = buffer;
 
-  bufferPtr += (y >> 3) * DISPLAY_WIDTH;
+  bufferPtr += (y >> 3) * displayWidth;
   bufferPtr += x;
 
   if (yOffset) {
@@ -293,7 +298,7 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
     if (length < yOffset) return;
 
     length -= yOffset;
-    bufferPtr += DISPLAY_WIDTH;
+    bufferPtr += displayWidth;
   }
 
   if (length >= 8) {
@@ -303,14 +308,14 @@ void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) {
         drawBit = (color == WHITE) ? 0xFF : 0x00;
         do {
           *bufferPtr = drawBit;
-          bufferPtr += DISPLAY_WIDTH;
+          bufferPtr += displayWidth;
           length -= 8;
         } while (length >= 8);
         break;
       case INVERSE:
         do {
           *bufferPtr = ~(*bufferPtr);
-          bufferPtr += DISPLAY_WIDTH;
+          bufferPtr += displayWidth;
           length -= 8;
         } while (length >= 8);
         break;
@@ -347,13 +352,13 @@ void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16
   fillCircle(xRadius + maxProgressWidth, yRadius, innerRadius);
 }
 
-void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *image) {
+void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *image) {
   drawInternal(xMove, yMove, width, height, image, 0, 0);
 }
 
-void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *xbm) {
+void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *xbm) {
   int16_t widthInXbm = (width + 7) / 8;
-  uint8_t data;
+  uint8_t data = 0;
 
   for(int16_t y = 0; y < height; y++) {
     for(int16_t x = 0; x < width; x++ ) {
@@ -388,11 +393,13 @@ void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, u
     case TEXT_ALIGN_RIGHT:
       xMove -= textWidth;
       break;
+    case TEXT_ALIGN_LEFT:
+      break;
   }
 
   // Don't draw anything if it is not on the screen.
-  if (xMove + textWidth  < 0 || xMove > DISPLAY_WIDTH ) {return;}
-  if (yMove + textHeight < 0 || yMove > DISPLAY_HEIGHT) {return;}
+  if (xMove + textWidth  < 0 || xMove > displayWidth ) {return;}
+  if (yMove + textHeight < 0 || yMove > displayHeight) {return;}
 
   for (uint16_t j = 0; j < textLength; j++) {
     int16_t xPos = xMove + cursorX;
@@ -525,7 +532,7 @@ void OLEDDisplay::setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment) {
   this->textAlignment = textAlignment;
 }
 
-void OLEDDisplay::setFont(const char *fontData) {
+void OLEDDisplay::setFont(const uint8_t *fontData) {
   this->fontData = fontData;
 }
 
@@ -550,13 +557,23 @@ void OLEDDisplay::setContrast(char contrast) {
   sendCommand(contrast);
 }
 
+void OLEDDisplay::resetOrientation() {
+  sendCommand(SEGREMAP);
+  sendCommand(COMSCANINC);           //Reset screen rotation or mirroring
+}
+
 void OLEDDisplay::flipScreenVertically() {
   sendCommand(SEGREMAP | 0x01);
   sendCommand(COMSCANDEC);           //Rotate screen 180 Deg
 }
 
+void OLEDDisplay::mirrorScreen() {
+  sendCommand(SEGREMAP);
+  sendCommand(COMSCANDEC);           //Mirror screen
+}
+
 void OLEDDisplay::clear(void) {
-  memset(buffer, 0, DISPLAY_BUFFER_SIZE);
+  memset(buffer, 0, displayBufferSize);
 }
 
 void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) {
@@ -591,6 +608,14 @@ void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) {
   }
 }
 
+uint16_t OLEDDisplay::getWidth(void) {
+  return displayWidth;
+}
+
+uint16_t OLEDDisplay::getHeight(void) {
+  return displayHeight;
+}
+
 bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){
   if (logBuffer != NULL) free(logBuffer);
   uint16_t size = lines * chars;
@@ -612,12 +637,17 @@ size_t OLEDDisplay::write(uint8_t c) {
     // Don't waste space on \r\n line endings, dropping \r
     if (c == 13) return 1;
 
+    // convert UTF-8 character to font table index
+    c = (this->fontTableLookupFunction)(c);
+    // drop unknown character
+    if (c == 0) return 1;
+
     bool maxLineNotReached = this->logBufferLine < this->logBufferMaxLines;
     bool bufferNotFull = this->logBufferFilled < this->logBufferSize;
 
     // Can we write to the buffer?
     if (bufferNotFull && maxLineNotReached) {
-      this->logBuffer[logBufferFilled] = utf8ascii(c);
+      this->logBuffer[logBufferFilled] = c;
       this->logBufferFilled++;
       // Keep track of lines written
       if (c == 10) this->logBufferLine++;
@@ -670,7 +700,8 @@ void OLEDDisplay::sendInitCommands(void) {
   sendCommand(SETDISPLAYCLOCKDIV);
   sendCommand(0xF0); // Increase speed of the display max ~96Hz
   sendCommand(SETMULTIPLEX);
-  sendCommand(0x3F);
+  //sendCommand(0x3F);
+  sendCommand(displayHeight - 1);
   sendCommand(SETDISPLAYOFFSET);
   sendCommand(0x00);
   sendCommand(SETSTARTLINE);
@@ -681,9 +712,21 @@ void OLEDDisplay::sendInitCommands(void) {
   sendCommand(SEGREMAP);
   sendCommand(COMSCANINC);
   sendCommand(SETCOMPINS);
-  sendCommand(0x12);
+  
+  if (geometry == GEOMETRY_128_64) {
+    sendCommand(0x12);
+  } else if (geometry == GEOMETRY_128_32) {
+    sendCommand(0x02);
+  }
+  
   sendCommand(SETCONTRAST);
-  sendCommand(0xCF);
+  
+  if (geometry == GEOMETRY_128_64) {
+    sendCommand(0xCF);
+  } else if (geometry == GEOMETRY_128_32) {
+    sendCommand(0x8F);
+  }
+  
   sendCommand(SETPRECHARGE);
   sendCommand(0xF1);
   sendCommand(DISPLAYALLON_RESUME);
@@ -692,10 +735,10 @@ void OLEDDisplay::sendInitCommands(void) {
   sendCommand(DISPLAYON);
 }
 
-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) {
+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 > DISPLAY_HEIGHT)  return;
-  if (xMove + width  < 0 || xMove > DISPLAY_WIDTH)   return;
+  if (yMove + height < 0 || yMove > displayHeight)  return;
+  if (xMove + width  < 0 || xMove > displayWidth)   return;
 
   uint8_t  rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0)
   int8_t   yOffset      = yMove & 7;
@@ -717,13 +760,13 @@ 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)) * DISPLAY_WIDTH;
+    int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * displayWidth;
 
     int16_t yScreenPos = yMove + yOffset;
     int16_t dataPos    = xPos  + yPos;
 
-    if (dataPos >=  0  && dataPos < DISPLAY_BUFFER_SIZE &&
-        xPos    >=  0  && xPos    < DISPLAY_WIDTH ) {
+    if (dataPos >=  0  && dataPos < displayBufferSize &&
+        xPos    >=  0  && xPos    < displayWidth ) {
 
       if (yOffset >= 0) {
         switch (this->color) {
@@ -731,11 +774,11 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt
           case BLACK:   buffer[dataPos] &= ~(currentByte << yOffset); break;
           case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break;
         }
-        if (dataPos < (DISPLAY_BUFFER_SIZE - DISPLAY_WIDTH)) {
+        if (dataPos < (displayBufferSize - displayWidth)) {
           switch (this->color) {
-            case WHITE:   buffer[dataPos + DISPLAY_WIDTH] |= currentByte >> (8 - yOffset); break;
-            case BLACK:   buffer[dataPos + DISPLAY_WIDTH] &= ~(currentByte >> (8 - yOffset)); break;
-            case INVERSE: buffer[dataPos + DISPLAY_WIDTH] ^= currentByte >> (8 - yOffset); break;
+            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;
           }
         }
       } else {
@@ -760,27 +803,6 @@ void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t widt
   }
 }
 
-// Code form http://playground.arduino.cc/Main/Utf8ascii
-uint8_t OLEDDisplay::utf8ascii(byte ascii) {
-  static uint8_t LASTCHAR;
-
-  if ( ascii < 128 ) { // Standard ASCII-set 0..0x7F handling
-    LASTCHAR = 0;
-    return ascii;
-  }
-
-  uint8_t last = LASTCHAR;   // get last char
-  LASTCHAR = ascii;
-
-  switch (last) {    // conversion depnding on first UTF8-character
-    case 0xC2: return  (ascii);  break;
-    case 0xC3: return  (ascii | 0xC0);  break;
-    case 0x82: if (ascii == 0xAC) return (0x80);    // special case Euro-symbol
-  }
-
-  return  0; // otherwise: return zero, if character has to be ignored
-}
-
 // You need to free the char!
 char* OLEDDisplay::utf8ascii(String str) {
   uint16_t k = 0;
@@ -797,7 +819,7 @@ char* OLEDDisplay::utf8ascii(String str) {
   length--;
 
   for (uint16_t i=0; i < length; i++) {
-    char c = utf8ascii(s[i]);
+    char c = (this->fontTableLookupFunction)(s[i]);
     if (c!=0) {
       s[k++]=c;
     }
@@ -808,3 +830,7 @@ char* OLEDDisplay::utf8ascii(String str) {
   // This will leak 's' be sure to free it in the calling function.
   return s;
 }
+
+void OLEDDisplay::setFontTableLookupFunction(FontTableLookupFunction function) {
+  this->fontTableLookupFunction = function;
+}
\ No newline at end of file
diff --git a/OLEDDisplay.h b/OLEDDisplay.h
index 6286b9685579c0de8da72130c0c3aae76c110732..95dcbd2b9035135baaea16ee9f85afa55975abc4 100644
--- a/OLEDDisplay.h
+++ b/OLEDDisplay.h
@@ -42,12 +42,6 @@
 #define OLEDDISPLAY_DOUBLE_BUFFER
 #endif
 
-
-// Display settings
-#define DISPLAY_WIDTH 128
-#define DISPLAY_HEIGHT 64
-#define DISPLAY_BUFFER_SIZE 1024
-
 // Header Values
 #define JUMPTABLE_BYTES 4
 
@@ -108,6 +102,14 @@ enum OLEDDISPLAY_TEXT_ALIGNMENT {
 };
 
 
+enum OLEDDISPLAY_GEOMETRY {
+  GEOMETRY_128_64   = 0,
+  GEOMETRY_128_32   = 1
+};
+
+typedef byte (*FontTableLookupFunction)(const byte ch);
+
+
 class OLEDDisplay : public Print {
   public:
     virtual ~OLEDDisplay() {}
@@ -125,6 +127,9 @@ class OLEDDisplay : public Print {
     // Sets the color of all pixel operations
     void setColor(OLEDDISPLAY_COLOR color);
 
+    // Returns the current color.
+    OLEDDISPLAY_COLOR getColor();
+
     // Draw a pixel at given position
     void setPixel(int16_t x, int16_t y);
 
@@ -149,7 +154,7 @@ class OLEDDisplay : public Print {
     // Draw a line horizontally
     void drawHorizontalLine(int16_t x, int16_t y, int16_t length);
 
-    // Draw a lin vertically
+    // Draw a line vertically
     void drawVerticalLine(int16_t x, int16_t y, int16_t length);
 
     // Draws a rounded progress bar with the outer dimensions given by width and height. Progress is
@@ -157,10 +162,10 @@ class OLEDDisplay : public Print {
     void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress);
 
     // Draw a bitmap in the internal image format
-    void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const char *image);
+    void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *image);
 
     // Draw a XBM
-    void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const char *xbm);
+    void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *xbm);
 
     /* Text functions */
 
@@ -186,7 +191,10 @@ class OLEDDisplay : public Print {
 
     // Sets the current font. Available default fonts
     // ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
-    void setFont(const char *fontData);
+    void setFont(const uint8_t *fontData);
+
+    // Set the function that will convert utf-8 to font table index
+    void setFontTableLookupFunction(FontTableLookupFunction function);
 
     /* Display functions */
 
@@ -205,9 +213,15 @@ class OLEDDisplay : public Print {
     // Set display contrast
     void setContrast(char contrast);
 
+    // Reset display rotation or mirroring
+    void resetOrientation();
+
     // Turn the display upside down
     void flipScreenVertically();
 
+    // Mirror the display (to be used in a mirror or as a projector)
+    void mirrorScreen();
+
     // Write the buffer to the display memory
     virtual void display(void) = 0;
 
@@ -224,7 +238,11 @@ class OLEDDisplay : public Print {
     // Draw the log buffer at position (x, y)
     void drawLogBuffer(uint16_t x, uint16_t y);
 
-    // Implementent needed function to be compatible with Print class
+    // Get screen geometry
+    uint16_t getWidth(void);
+    uint16_t getHeight(void);
+
+    // Implement needed function to be compatible with Print class
     size_t write(uint8_t c);
     size_t write(const char* s);
 
@@ -236,10 +254,16 @@ class OLEDDisplay : public Print {
 
   protected:
 
+    OLEDDISPLAY_GEOMETRY geometry              = GEOMETRY_128_64;
+
+    uint16_t  displayWidth                     = 128;
+    uint16_t  displayHeight                    = 64;
+    uint16_t  displayBufferSize                = 1024;
+
     OLEDDISPLAY_TEXT_ALIGNMENT   textAlignment = TEXT_ALIGN_LEFT;
     OLEDDISPLAY_COLOR            color         = WHITE;
 
-    const char          *fontData              = ArialMT_Plain_10;
+    const uint8_t          *fontData     = ArialMT_Plain_10;
 
     // State values for logBuffer
     uint16_t   logBufferSize                   = 0;
@@ -252,19 +276,39 @@ class OLEDDisplay : public Print {
     virtual void sendCommand(uint8_t com) {};
 
     // Connect to the display
-    virtual bool connect() {};
+    virtual bool connect() {return true;};
 
     // Send all the init commands
     void sendInitCommands();
 
     // converts utf8 characters to extended ascii
-    static char* utf8ascii(String s);
-    static byte utf8ascii(byte ascii);
+    char* utf8ascii(String s);
 
-    void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline));
+    void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline));
 
     void drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth);
 
+    // UTF-8 to font table index converter
+    // Code form http://playground.arduino.cc/Main/Utf8ascii
+    FontTableLookupFunction fontTableLookupFunction = [](const byte ch) {
+      static uint8_t LASTCHAR;
+
+      if (ch < 128) { // Standard ASCII-set 0..0x7F handling
+        LASTCHAR = 0;
+        return ch;
+      }
+
+      uint8_t last = LASTCHAR;   // get last char
+      LASTCHAR = ch;
+
+      switch (last) {    // conversion depnding on first UTF8-character
+        case 0xC2: return (uint8_t) ch;  break;
+        case 0xC3: return (uint8_t) (ch | 0xC0);  break;
+        case 0x82: if (ch == 0xAC) return (uint8_t) 0x80;    // special case Euro-symbol
+      }
+
+      return (uint8_t) 0; // otherwise: return zero, if character has to be ignored
+    };
 };
 
 #endif
diff --git a/OLEDDisplayFonts.h b/OLEDDisplayFonts.h
index 6dd21ef60b9919ca2dd24935340f3a5f518735a8..3544edb80d1721237febea01c3f6389ee6e2ad60 100644
--- a/OLEDDisplayFonts.h
+++ b/OLEDDisplayFonts.h
@@ -1,7 +1,7 @@
 #ifndef OLEDDISPLAYFONTS_h
 #define OLEDDISPLAYFONTS_h
 
-const char ArialMT_Plain_10[] PROGMEM = {
+const uint8_t ArialMT_Plain_10[] PROGMEM = {
   0x0A, // Width: 10
   0x0D, // Height: 13
   0x20, // First Char: 32
@@ -425,7 +425,7 @@ const char ArialMT_Plain_10[] PROGMEM = {
   0x20,0x00,0xC8,0x09,0x00,0x06,0xC8,0x01,0x20  // 255
 };
 
-const char ArialMT_Plain_16[] PROGMEM = {
+const uint8_t ArialMT_Plain_16[] PROGMEM = {
   0x10, // Width: 16
   0x13, // Height: 19
   0x20, // First Char: 32
@@ -848,7 +848,7 @@ const char ArialMT_Plain_16[] PROGMEM = {
   0x00,0x00,0x00,0xF8,0xFF,0x03,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 254
   0xC0,0x01,0x00,0x00,0x06,0x02,0x10,0x38,0x02,0x00,0xE0,0x01,0x10,0x38,0x00,0x00,0x07,0x00,0xC0  // 255
 };
-const char ArialMT_Plain_24[] PROGMEM = {
+const uint8_t ArialMT_Plain_24[] PROGMEM = {
   0x18, // Width: 24
   0x1C, // Height: 28
   0x20, // First Char: 32
@@ -1271,4 +1271,4 @@ const char ArialMT_Plain_24[] PROGMEM = {
   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x00,0x1C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x03, // 254
   0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x06,0xC0,0xF0,0x01,0x06,0xC0,0x80,0x0F,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xFC,0x00,0xC0,0xC0,0x1F,0x00,0xC0,0xF8,0x03,0x00,0x00,0x3E,0x00,0x00,0x00,0x06 // 255
 };
-#endif 
+#endif
diff --git a/OLEDDisplayUi.cpp b/OLEDDisplayUi.cpp
index 3fb4326a4d6ead0584b61e2d6187b1e8b3241575..03eff9c4343d84efcfd328b3dcb763ef165fe0a0 100644
--- a/OLEDDisplayUi.cpp
+++ b/OLEDDisplayUi.cpp
@@ -90,10 +90,10 @@ void OLEDDisplayUi::setIndicatorPosition(IndicatorPosition pos) {
 void OLEDDisplayUi::setIndicatorDirection(IndicatorDirection dir) {
   this->indicatorDirection = dir;
 }
-void OLEDDisplayUi::setActiveSymbol(const char* symbol) {
+void OLEDDisplayUi::setActiveSymbol(const uint8_t* symbol) {
   this->activeSymbol = symbol;
 }
-void OLEDDisplayUi::setInactiveSymbol(const char* symbol) {
+void OLEDDisplayUi::setInactiveSymbol(const uint8_t* symbol) {
   this->inactiveSymbol = symbol;
 }
 
@@ -254,28 +254,29 @@ void OLEDDisplayUi::drawFrame(){
        int16_t x, y, x1, y1;
        switch(this->frameAnimationDirection){
         case SLIDE_LEFT:
-          x = -128 * progress;
+          x = -(this->display->getWidth()) * progress;
           y = 0;
-          x1 = x + 128;
+          x1 = x + this->display->getWidth();
           y1 = 0;
           break;
         case SLIDE_RIGHT:
-          x = 128 * progress;
+          x = this->display->getWidth() * progress;
           y = 0;
-          x1 = x - 128;
+          x1 = x - this->display->getWidth();
           y1 = 0;
           break;
         case SLIDE_UP:
           x = 0;
-          y = -64 * progress;
+          y = -(this->display->getHeight()) * progress;
           x1 = 0;
-          y1 = y + 64;
+          y1 = y + (this->display->getHeight());
           break;
         case SLIDE_DOWN:
+        default:
           x = 0;
-          y = 64 * progress;
+          y = (this->display->getHeight()) * progress;
           x1 = 0;
-          y1 = y - 64;
+          y1 = y - (this->display->getHeight());
           break;
        }
 
@@ -345,6 +346,7 @@ void OLEDDisplayUi::drawIndicator() {
         posOfHighlightFrame = frameToHighlight;
         break;
       case RIGHT_LEFT:
+      default:
         posOfHighlightFrame = this->frameCount - frameToHighlight;
         break;
     }
@@ -360,27 +362,35 @@ void OLEDDisplayUi::drawIndicator() {
         break;
     }
 
-    uint16_t frameStartPos = (12 * frameCount / 2);
-    const char *image;
+    //Space between indicators - reduce for small screen sizes
+    uint16_t indicatorSpacing = 12;
+    if (this->display->getHeight() < 64 && (this->indicatorPosition == RIGHT || this->indicatorPosition == LEFT)) {
+      indicatorSpacing = 6;
+    }
+    
+    uint16_t frameStartPos = (indicatorSpacing * frameCount / 2);
+    const uint8_t *image;
+
     uint16_t x,y;
     for (byte i = 0; i < this->frameCount; i++) {
 
       switch (this->indicatorPosition){
         case TOP:
           y = 0 - (8 * indicatorFadeProgress);
-          x = 64 - frameStartPos + 12 * i;
+          x = (this->display->getWidth() / 2) - frameStartPos + indicatorSpacing * i;
           break;
         case BOTTOM:
-          y = 56 + (8 * indicatorFadeProgress);
-          x = 64 - frameStartPos + 12 * i;
+          y = (this->display->getHeight() - 8) + (8 * indicatorFadeProgress);
+          x = (this->display->getWidth() / 2) - frameStartPos + indicatorSpacing * i;
           break;
         case RIGHT:
-          x = 120 + (8 * indicatorFadeProgress);
-          y = 32 - frameStartPos + 2 + 12 * i;
+          x = (this->display->getWidth() - 8) + (8 * indicatorFadeProgress);
+          y = (this->display->getHeight() / 2) - frameStartPos + indicatorSpacing * i;
           break;
         case LEFT:
+        default:
           x = 0 - (8 * indicatorFadeProgress);
-          y = 32 - frameStartPos + 2 + 12 * i;
+          y = (this->display->getHeight() / 2) - frameStartPos + indicatorSpacing * i;
           break;
       }
 
diff --git a/OLEDDisplayUi.h b/OLEDDisplayUi.h
index 35a1e99bcf449c3d2f5f4405f223949005fce497..a5f6c90083de0b8281fca8787eff19446ebde65b 100644
--- a/OLEDDisplayUi.h
+++ b/OLEDDisplayUi.h
@@ -61,11 +61,11 @@ enum FrameState {
 };
 
 
-const char ANIMATION_activeSymbol[] PROGMEM = {
+const uint8_t ANIMATION_activeSymbol[] PROGMEM = {
   0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00
 };
 
-const char ANIMATION_inactiveSymbol[] PROGMEM = {
+const uint8_t ANIMATION_inactiveSymbol[] PROGMEM = {
   0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00
 };
 
@@ -106,8 +106,8 @@ class OLEDDisplayUi {
     IndicatorPosition   indicatorPosition         = BOTTOM;
     IndicatorDirection  indicatorDirection        = LEFT_RIGHT;
 
-    const char*         activeSymbol              = ANIMATION_activeSymbol;
-    const char*         inactiveSymbol            = ANIMATION_inactiveSymbol;
+    const uint8_t*         activeSymbol              = ANIMATION_activeSymbol;
+    const uint8_t*         inactiveSymbol            = ANIMATION_inactiveSymbol;
 
     bool                shouldDrawIndicators      = true;
 
@@ -240,12 +240,12 @@ class OLEDDisplayUi {
     /**
      * Set the symbol to indicate an active frame in the indicator bar.
      */
-    void setActiveSymbol(const char* symbol);
+    void setActiveSymbol(const uint8_t* symbol);
 
     /**
      * Set the symbol to indicate an inactive frame in the indicator bar.
      */
-    void setInactiveSymbol(const char* symbol);
+    void setInactiveSymbol(const uint8_t* symbol);
 
 
     // Frame settings
diff --git a/README.md b/README.md
index 01c134c3506041cdd547a76b78b673f1d2659b49..28c11b55ac8c2c5e4ea8e5d58051802ebae25473 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
-esp8266-oled-ssd1306 [![Build Status](https://travis-ci.org/squix78/esp8266-oled-ssd1306.svg?branch=dev-branch-3.0.0)](https://travis-ci.org/squix78/esp8266-oled-ssd1306)
-============
+[![Build Status](https://travis-ci.org/ThingPulse/esp8266-oled-ssd1306.svg?branch=master)](https://travis-ci.org/ThingPulse/esp8266-oled-ssd1306)
+
+# ESP8266 OLED SSD1306 
 
 > We just released version 3.0.0. Please have a look at our [upgrade guide](UPGRADE-3.0.md)
 
@@ -19,7 +20,7 @@ The init sequence for the SSD1306 was inspired by Adafruit's library for the sam
 
 ## Usage
 
-Check out the examples folder for a few comprehensive demonstrations how to use the library. Also check out the ESP8266 Weather Station library (https://github.com/squix78/esp8266-weather-station) which uses the OLED library to display beautiful weather information.
+Check out the examples folder for a few comprehensive demonstrations how to use the library. Also check out the [ESP8266 Weather Station](https://github.com/ThingPulse/esp8266-weather-station) library which uses the OLED library to display beautiful weather information.
 
 ## Upgrade
 
@@ -141,6 +142,9 @@ void setContrast(char contrast);
 
 // Turn the display upside down
 void flipScreenVertically();
+
+// Draw the screen mirrored
+void mirrorScreen();
 ```
 
 ## Pixel drawing
diff --git a/SH1106Brzo.h b/SH1106Brzo.h
index 385630b3267a7191fe0c81a21fe34d4b5de0a2e4..a747cb68ebe2994cc1ad2a13eedf58335db765ba 100644
--- a/SH1106Brzo.h
+++ b/SH1106Brzo.h
@@ -44,7 +44,18 @@ class SH1106Brzo : public OLEDDisplay {
       uint8_t             _scl;
 
   public:
-    SH1106Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl) {
+    SH1106Brzo(OLEDDISPLAY_GEOMETRY g, uint8_t _address, uint8_t _sda, uint8_t _scl) {
+      this->geometry = g;
+      if (g == GEOMETRY_128_64) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 64;
+        this->displayBufferSize                = 1024;
+      } else if (g == GEOMETRY_128_32) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 32;
+        this->displayBufferSize                = 512;    
+      }
+
       this->_address = _address;
       this->_sda = _sda;
       this->_scl = _scl;
@@ -66,9 +77,9 @@ class SH1106Brzo : public OLEDDisplay {
 
        // Calculate the Y bounding box of changes
        // and copy buffer[pos] to buffer_back[pos];
-       for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
-         for (x = 0; x < DISPLAY_WIDTH; x++) {
-          uint16_t pos = x + y * DISPLAY_WIDTH;
+       for (y = 0; y < (displayHeight / 8); y++) {
+         for (x = 0; x < displayWidth; x++) {
+          uint16_t pos = x + y * displayWidth;
           if (buffer[pos] != buffer_back[pos]) {
             minBoundY = _min(minBoundY, y);
             maxBoundY = _max(maxBoundY, y);
@@ -101,7 +112,7 @@ class SH1106Brzo : public OLEDDisplay {
          sendCommand(minBoundXp2L);
          for (x = minBoundX; x <= maxBoundX; x++) {
              k++;
-             sendBuffer[k] = buffer[x + y * DISPLAY_WIDTH];
+             sendBuffer[k] = buffer[x + y * displayWidth];
              if (k == 16)  {
                brzo_i2c_write(sendBuffer, 17, true);
                k = 0;
diff --git a/SH1106Spi.h b/SH1106Spi.h
index 0a64e27568ff9fc1270e13ec0eec221ac9337a67..d81d90d38a2a4668ecca1329256d9f0bf22df788 100644
--- a/SH1106Spi.h
+++ b/SH1106Spi.h
@@ -38,7 +38,18 @@ class SH1106Spi : public OLEDDisplay {
 
   public:
 
-    SH1106Spi(uint8_t _rst, uint8_t _dc) {
+    SH1106Spi(OLEDDISPLAY_GEOMETRY g, uint8_t _rst, uint8_t _dc) {      
+      this->geometry = g;
+      if (g == GEOMETRY_128_64) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 64;
+        this->displayBufferSize                = 1024;
+      } else if (g == GEOMETRY_128_32) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 32;
+        this->displayBufferSize                = 512;    
+      }
+
       this->_rst = _rst;
       this->_dc  = _dc;
     }
@@ -71,9 +82,9 @@ class SH1106Spi : public OLEDDisplay {
 
        // Calculate the Y bounding box of changes
        // and copy buffer[pos] to buffer_back[pos];
-       for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
-         for (x = 0; x < DISPLAY_WIDTH; x++) {
-          uint16_t pos = x + y * DISPLAY_WIDTH;
+       for (y = 0; y < (displayHeight / 8); y++) {
+         for (x = 0; x < displayWidth; x++) {
+          uint16_t pos = x + y * displayWidth;
           if (buffer[pos] != buffer_back[pos]) {
             minBoundY = _min(minBoundY, y);
             maxBoundY = _max(maxBoundY, y);
@@ -100,18 +111,18 @@ class SH1106Spi : public OLEDDisplay {
          sendCommand(minBoundXp2L);
          digitalWrite(_dc, HIGH);   // data mode
          for (x = minBoundX; x <= maxBoundX; x++) {
-           SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
+           SPI.transfer(buffer[x + y * displayWidth]);
          }
          yield();
        }
      #else
-      for (uint8_t y=0; y<DISPLAY_HEIGHT/8; y++) {
+      for (uint8_t y=0; y<displayHeight/8; y++) {
         sendCommand(0xB0 + y);
         sendCommand(0x02);
         sendCommand(0x10);
         digitalWrite(_dc, HIGH);   // data mode
-        for( uint8_t x=0; x < DISPLAY_WIDTH; x++) {
-          SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
+        for( uint8_t x=0; x < displayWidth; x++) {
+          SPI.transfer(buffer[x + y * displayWidth]);
         }
         yield();
       }
diff --git a/SH1106Wire.h b/SH1106Wire.h
index f0784b9423051a4e91bf2e237b38347a2f6b6ede..3205ac06ad09ecdff37c63d4564c7a2022786e09 100644
--- a/SH1106Wire.h
+++ b/SH1106Wire.h
@@ -44,7 +44,18 @@ class SH1106Wire : public OLEDDisplay {
       uint8_t             _scl;
 
   public:
-    SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl) {
+    SH1106Wire(OLEDDISPLAY_GEOMETRY g, uint8_t _address, uint8_t _sda, uint8_t _scl) {      
+      this->geometry = g;
+      if (g == GEOMETRY_128_64) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 64;
+        this->displayBufferSize                = 1024;
+      } else if (g == GEOMETRY_128_32) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 32;
+        this->displayBufferSize                = 512;    
+      }
+
       this->_address = _address;
       this->_sda = _sda;
       this->_scl = _scl;
@@ -70,9 +81,9 @@ class SH1106Wire : public OLEDDisplay {
 
         // Calculate the Y bounding box of changes
         // and copy buffer[pos] to buffer_back[pos];
-        for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
-          for (x = 0; x < DISPLAY_WIDTH; x++) {
-           uint16_t pos = x + y * DISPLAY_WIDTH;
+        for (y = 0; y < (displayHeight / 8); y++) {
+          for (x = 0; x < displayWidth; x++) {
+           uint16_t pos = x + y * displayWidth;
            if (buffer[pos] != buffer_back[pos]) {
              minBoundY = _min(minBoundY, y);
              maxBoundY = _max(maxBoundY, y);
@@ -103,7 +114,7 @@ class SH1106Wire : public OLEDDisplay {
               Wire.beginTransmission(_address);
               Wire.write(0x40);
             }
-            Wire.write(buffer[x + y * DISPLAY_WIDTH]);
+            Wire.write(buffer[x + y * displayWidth]);
             k++;
             if (k == 16)  {
               Wire.endTransmission();
diff --git a/SSD1306Brzo.h b/SSD1306Brzo.h
index 3b99d82d2a196dbc0836b8e4ad13d7fa46b60813..a9a2aa0cccb0079b727a312c3be97171d88d7e84 100644
--- a/SSD1306Brzo.h
+++ b/SSD1306Brzo.h
@@ -44,7 +44,18 @@ class SSD1306Brzo : public OLEDDisplay {
       uint8_t             _scl;
 
   public:
-    SSD1306Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl) {
+    SSD1306Brzo(OLEDDISPLAY_GEOMETRY g, uint8_t _address, uint8_t _sda, uint8_t _scl) {
+      this->geometry = g;
+      if (g == GEOMETRY_128_64) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 64;
+        this->displayBufferSize                = 1024;
+      } else if (g == GEOMETRY_128_32) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 32;
+        this->displayBufferSize                = 512;    
+      }
+
       this->_address = _address;
       this->_sda = _sda;
       this->_scl = _scl;
@@ -67,9 +78,9 @@ class SSD1306Brzo : public OLEDDisplay {
 
        // Calculate the Y bounding box of changes
        // and copy buffer[pos] to buffer_back[pos];
-       for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
-         for (x = 0; x < DISPLAY_WIDTH; x++) {
-          uint16_t pos = x + y * DISPLAY_WIDTH;
+       for (y = 0; y < (displayHeight / 8); y++) {
+         for (x = 0; x < displayWidth; x++) {
+          uint16_t pos = x + y * displayWidth;
           if (buffer[pos] != buffer_back[pos]) {
             minBoundY = _min(minBoundY, y);
             maxBoundY = _max(maxBoundY, y);
@@ -101,7 +112,7 @@ class SSD1306Brzo : public OLEDDisplay {
        for (y = minBoundY; y <= maxBoundY; y++) {
            for (x = minBoundX; x <= maxBoundX; x++) {
                k++;
-               sendBuffer[k] = buffer[x + y * DISPLAY_WIDTH];
+               sendBuffer[k] = buffer[x + y * displayWidth];
                if (k == 16)  {
                  brzo_i2c_write(sendBuffer, 17, true);
                  k = 0;
@@ -119,12 +130,17 @@ class SSD1306Brzo : public OLEDDisplay {
 
        sendCommand(PAGEADDR);
        sendCommand(0x0);
-       sendCommand(0x7);
+       
+       if (geometry == GEOMETRY_128_64) {
+         sendCommand(0x7);
+       } else if (geometry == GEOMETRY_128_32) {
+         sendCommand(0x3);
+       }
 
        uint8_t sendBuffer[17];
        sendBuffer[0] = 0x40;
        brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
-       for (uint16_t i=0; i<DISPLAY_BUFFER_SIZE; i++) {
+       for (uint16_t i=0; i<displayBufferSize; i++) {
          for (uint8_t x=1; x<17; x++) {
            sendBuffer[x] = buffer[i];
            i++;
diff --git a/SSD1306Spi.h b/SSD1306Spi.h
index 21794587ac612cb951706546dadb2d2bb0c23593..9a41a0a264dbb1bca4a01d4dcf6fb28eb6e28fe4 100644
--- a/SSD1306Spi.h
+++ b/SSD1306Spi.h
@@ -44,7 +44,18 @@ class SSD1306Spi : public OLEDDisplay {
       uint8_t             _cs;
 
   public:
-    SSD1306Spi(uint8_t _rst, uint8_t _dc, uint8_t _cs) {
+    SSD1306Spi(OLEDDISPLAY_GEOMETRY g,  uint8_t _rst, uint8_t _dc, uint8_t _cs) {
+      this->geometry = g;
+      if (g == GEOMETRY_128_64) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 64;
+        this->displayBufferSize                = 1024;
+      } else if (g == GEOMETRY_128_32) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 32;
+        this->displayBufferSize                = 512;    
+      }
+      
       this->_rst = _rst;
       this->_dc  = _dc;
       this->_cs  = _cs;
@@ -79,9 +90,9 @@ class SSD1306Spi : public OLEDDisplay {
 
        // Calculate the Y bounding box of changes
        // and copy buffer[pos] to buffer_back[pos];
-       for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
-         for (x = 0; x < DISPLAY_WIDTH; x++) {
-          uint16_t pos = x + y * DISPLAY_WIDTH;
+       for (y = 0; y < (displayHeight / 8); y++) {
+         for (x = 0; x < displayWidth; x++) {
+          uint16_t pos = x + y * displayWidth;
           if (buffer[pos] != buffer_back[pos]) {
             minBoundY = _min(minBoundY, y);
             maxBoundY = _max(maxBoundY, y);
@@ -111,7 +122,7 @@ class SSD1306Spi : public OLEDDisplay {
        digitalWrite(_cs, LOW);
        for (y = minBoundY; y <= maxBoundY; y++) {
          for (x = minBoundX; x <= maxBoundX; x++) {
-           SPI.transfer(buffer[x + y * DISPLAY_WIDTH]);
+           SPI.transfer(buffer[x + y * displayWidth]);
          }
          yield();
        }
@@ -124,12 +135,17 @@ class SSD1306Spi : public OLEDDisplay {
 
        sendCommand(PAGEADDR);
        sendCommand(0x0);
-       sendCommand(0x7);
+
+       if (geometry == GEOMETRY_128_64) {
+         sendCommand(0x7);
+       } else if (geometry == GEOMETRY_128_32) {
+         sendCommand(0x3);
+       }
 
         digitalWrite(_cs, HIGH);
         digitalWrite(_dc, HIGH);   // data mode
         digitalWrite(_cs, LOW);
-        for (uint16_t i=0; i<DISPLAY_BUFFER_SIZE; i++) {
+        for (uint16_t i=0; i<displayBufferSize; i++) {
           SPI.transfer(buffer[i]);
           yield();
         }
diff --git a/SSD1306Wire.h b/SSD1306Wire.h
index ac12becd0964a7d93b20e3e8a42a5db9ab9c253e..e82d9b54d374f3558a348e3da314a7d9b7099952 100644
--- a/SSD1306Wire.h
+++ b/SSD1306Wire.h
@@ -38,7 +38,18 @@ class SSD1306Wire : public OLEDDisplay {
       uint8_t             _scl;
 
   public:
-    SSD1306Wire(uint8_t _address, uint8_t _sda, uint8_t _scl) {
+    SSD1306Wire(OLEDDISPLAY_GEOMETRY g, uint8_t _address, uint8_t _sda, uint8_t _scl) {
+      this->geometry = g;
+      if (g == GEOMETRY_128_64) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 64;
+        this->displayBufferSize                = 1024;
+      } else if (g == GEOMETRY_128_32) {
+        this->displayWidth                     = 128;
+        this->displayHeight                    = 32;
+        this->displayBufferSize                = 512;    
+      }
+
       this->_address = _address;
       this->_sda = _sda;
       this->_scl = _scl;
@@ -63,9 +74,9 @@ class SSD1306Wire : public OLEDDisplay {
 
         // Calculate the Y bounding box of changes
         // and copy buffer[pos] to buffer_back[pos];
-        for (y = 0; y < (DISPLAY_HEIGHT / 8); y++) {
-          for (x = 0; x < DISPLAY_WIDTH; x++) {
-           uint16_t pos = x + y * DISPLAY_WIDTH;
+        for (y = 0; y < (displayHeight / 8); y++) {
+          for (x = 0; x < displayWidth; x++) {
+           uint16_t pos = x + y * displayWidth;
            if (buffer[pos] != buffer_back[pos]) {
              minBoundY = _min(minBoundY, y);
              maxBoundY = _max(maxBoundY, y);
@@ -97,7 +108,7 @@ class SSD1306Wire : public OLEDDisplay {
               Wire.beginTransmission(_address);
               Wire.write(0x40);
             }
-            Wire.write(buffer[x + y * DISPLAY_WIDTH]);
+            Wire.write(buffer[x + y * displayWidth]);
             k++;
             if (k == 16)  {
               Wire.endTransmission();
@@ -118,9 +129,14 @@ class SSD1306Wire : public OLEDDisplay {
 
         sendCommand(PAGEADDR);
         sendCommand(0x0);
-        sendCommand(0x7);
+        
+        if (geometry == GEOMETRY_128_64) {
+          sendCommand(0x7);
+        } else if (geometry == GEOMETRY_128_32) {
+          sendCommand(0x3);
+        }
 
-        for (uint16_t i=0; i < DISPLAY_BUFFER_SIZE; i++) {
+        for (uint16_t i=0; i < displayBufferSize; i++) {
           Wire.beginTransmission(this->_address);
           Wire.write(0x40);
           for (uint8_t x = 0; x < 16; x++) {
diff --git a/examples/SSD1306ClockDemo/SSD1306ClockDemo.ino b/examples/SSD1306ClockDemo/SSD1306ClockDemo.ino
index e9db7d645a610f8c42d857ba20a774b2fe9cd89e..1f1a8c968575c8c5b9ee7e2a8e6aa6afe7dca68b 100644
--- a/examples/SSD1306ClockDemo/SSD1306ClockDemo.ino
+++ b/examples/SSD1306ClockDemo/SSD1306ClockDemo.ino
@@ -66,7 +66,7 @@
 // SH1106Brzo  display(0x3c, D3, D5);
 
 // Initialize the OLED display using Wire library
-SSD1306  display(0x3c, D3, D5);
+SSD1306  display(GEOMETRY_128_64, 0x3c, D3, D5);
 // SH1106 display(0x3c, D3, D5);
 
 OLEDDisplayUi ui ( &display );
diff --git a/examples/SSD1306ClockDemo/images.h b/examples/SSD1306ClockDemo/images.h
index a220a27c2b6637946f5df26f500f0eb88998a2c8..1889188fd489e49ef1a6dd8ce6a7ffaa4f956be0 100644
--- a/examples/SSD1306ClockDemo/images.h
+++ b/examples/SSD1306ClockDemo/images.h
@@ -1,4 +1,4 @@
-const char activeSymbol[] PROGMEM = {
+const unsigned char activeSymbol[] PROGMEM = {
     B00000000,
     B00000000,
     B00011000,
@@ -9,7 +9,7 @@ const char activeSymbol[] PROGMEM = {
     B00011000
 };
 
-const char inactiveSymbol[] PROGMEM = {
+const unsigned char inactiveSymbol[] PROGMEM = {
     B00000000,
     B00000000,
     B00000000,
diff --git a/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino b/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino
index cf37fb0412002492388ed3d71fbb1ec58866c233..3f6e0a4f1c90ee597abf6faf213980e29a088368 100644
--- a/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino
+++ b/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino
@@ -58,56 +58,56 @@
  // SH1106Brzo  display(0x3c, D3, D5);
 
  // Initialize the OLED display using Wire library
- SSD1306  display(0x3c, D3, D5);
+ SSD1306  display(GEOMETRY_128_64, 0x3c, D3, D5);
  // SH1106 display(0x3c, D3, D5);
 
 // Adapted from Adafruit_SSD1306
 void drawLines() {
-  for (int16_t i=0; i<DISPLAY_WIDTH; i+=4) {
-    display.drawLine(0, 0, i, DISPLAY_HEIGHT-1);
+  for (int16_t i=0; i<display.getWidth(); i+=4) {
+    display.drawLine(0, 0, i, display.getHeight()-1);
     display.display();
     delay(10);
   }
-  for (int16_t i=0; i<DISPLAY_HEIGHT; i+=4) {
-    display.drawLine(0, 0, DISPLAY_WIDTH-1, i);
+  for (int16_t i=0; i<display.getHeight(); i+=4) {
+    display.drawLine(0, 0, display.getWidth()-1, i);
     display.display();
     delay(10);
   }
   delay(250);
 
   display.clear();
-  for (int16_t i=0; i<DISPLAY_WIDTH; i+=4) {
-    display.drawLine(0, DISPLAY_HEIGHT-1, i, 0);
+  for (int16_t i=0; i<display.getWidth(); i+=4) {
+    display.drawLine(0, display.getHeight()-1, i, 0);
     display.display();
     delay(10);
   }
-  for (int16_t i=DISPLAY_HEIGHT-1; i>=0; i-=4) {
-    display.drawLine(0, DISPLAY_HEIGHT-1, DISPLAY_WIDTH-1, i);
+  for (int16_t i=display.getHeight()-1; i>=0; i-=4) {
+    display.drawLine(0, display.getHeight()-1, display.getWidth()-1, i);
     display.display();
     delay(10);
   }
   delay(250);
 
   display.clear();
-  for (int16_t i=DISPLAY_WIDTH-1; i>=0; i-=4) {
-    display.drawLine(DISPLAY_WIDTH-1, DISPLAY_HEIGHT-1, i, 0);
+  for (int16_t i=display.getWidth()-1; i>=0; i-=4) {
+    display.drawLine(display.getWidth()-1, display.getHeight()-1, i, 0);
     display.display();
     delay(10);
   }
-  for (int16_t i=DISPLAY_HEIGHT-1; i>=0; i-=4) {
-    display.drawLine(DISPLAY_WIDTH-1, DISPLAY_HEIGHT-1, 0, i);
+  for (int16_t i=display.getHeight()-1; i>=0; i-=4) {
+    display.drawLine(display.getWidth()-1, display.getHeight()-1, 0, i);
     display.display();
     delay(10);
   }
   delay(250);
   display.clear();
-  for (int16_t i=0; i<DISPLAY_HEIGHT; i+=4) {
-    display.drawLine(DISPLAY_WIDTH-1, 0, 0, i);
+  for (int16_t i=0; i<display.getHeight(); i+=4) {
+    display.drawLine(display.getWidth()-1, 0, 0, i);
     display.display();
     delay(10);
   }
-  for (int16_t i=0; i<DISPLAY_WIDTH; i+=4) {
-    display.drawLine(DISPLAY_WIDTH-1, 0, i, DISPLAY_HEIGHT-1);
+  for (int16_t i=0; i<display.getWidth(); i+=4) {
+    display.drawLine(display.getWidth()-1, 0, i, display.getHeight()-1);
     display.display();
     delay(10);
   }
@@ -116,8 +116,8 @@ void drawLines() {
 
 // Adapted from Adafruit_SSD1306
 void drawRect(void) {
-  for (int16_t i=0; i<DISPLAY_HEIGHT/2; i+=2) {
-    display.drawRect(i, i, DISPLAY_WIDTH-2*i, DISPLAY_HEIGHT-2*i);
+  for (int16_t i=0; i<display.getHeight()/2; i+=2) {
+    display.drawRect(i, i, display.getWidth()-2*i, display.getHeight()-2*i);
     display.display();
     delay(10);
   }
@@ -126,9 +126,9 @@ void drawRect(void) {
 // Adapted from Adafruit_SSD1306
 void fillRect(void) {
   uint8_t color = 1;
-  for (int16_t i=0; i<DISPLAY_HEIGHT/2; i+=3) {
+  for (int16_t i=0; i<display.getHeight()/2; i+=3) {
     display.setColor((color % 2 == 0) ? BLACK : WHITE); // alternate colors
-    display.fillRect(i, i, DISPLAY_WIDTH - i*2, DISPLAY_HEIGHT - i*2);
+    display.fillRect(i, i, display.getWidth() - i*2, display.getHeight() - i*2);
     display.display();
     delay(10);
     color++;
@@ -139,8 +139,8 @@ void fillRect(void) {
 
 // Adapted from Adafruit_SSD1306
 void drawCircle(void) {
-  for (int16_t i=0; i<DISPLAY_HEIGHT; i+=2) {
-    display.drawCircle(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, i);
+  for (int16_t i=0; i<display.getHeight(); i+=2) {
+    display.drawCircle(display.getWidth()/2, display.getHeight()/2, i);
     display.display();
     delay(10);
   }
@@ -153,16 +153,16 @@ void drawCircle(void) {
   //  ------|-----
   //   0100 | 1000
   //
-  display.drawCircleQuads(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, DISPLAY_HEIGHT/4, 0b00000001);
+  display.drawCircleQuads(display.getWidth()/2, display.getHeight()/2, display.getHeight()/4, 0b00000001);
   display.display();
   delay(200);
-  display.drawCircleQuads(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, DISPLAY_HEIGHT/4, 0b00000011);
+  display.drawCircleQuads(display.getWidth()/2, display.getHeight()/2, display.getHeight()/4, 0b00000011);
   display.display();
   delay(200);
-  display.drawCircleQuads(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, DISPLAY_HEIGHT/4, 0b00000111);
+  display.drawCircleQuads(display.getWidth()/2, display.getHeight()/2, display.getHeight()/4, 0b00000111);
   display.display();
   delay(200);
-  display.drawCircleQuads(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, DISPLAY_HEIGHT/4, 0b00001111);
+  display.drawCircleQuads(display.getWidth()/2, display.getHeight()/2, display.getHeight()/4, 0b00001111);
   display.display();
 }
 
diff --git a/examples/SSD1306OTADemo/SSD1306OTADemo.ino b/examples/SSD1306OTADemo/SSD1306OTADemo.ino
index 6460ff9e4a308dffa396d0db473c6708e0c14f34..856917a958d22b8fc5f2ee1e8a5286b40a8fe95e 100644
--- a/examples/SSD1306OTADemo/SSD1306OTADemo.ino
+++ b/examples/SSD1306OTADemo/SSD1306OTADemo.ino
@@ -69,7 +69,7 @@
 // SH1106Brzo  display(0x3c, D3, D5);
 
 // Initialize the OLED display using Wire library
-SSD1306  display(0x3c, D3, D5);
+SSD1306  display(GEOMETRY_128_64, 0x3c, D3, D5);
 // SH1106 display(0x3c, D3, D5);
 
 
@@ -90,7 +90,7 @@ void setup() {
     display.clear();
     display.setFont(ArialMT_Plain_10);
     display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
-    display.drawString(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2 - 10, "OTA Update");
+    display.drawString(display.getWidth()/2, display.getHeight()/2 - 10, "OTA Update");
     display.display();
   });
 
@@ -103,14 +103,14 @@ void setup() {
     display.clear();
     display.setFont(ArialMT_Plain_10);
     display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
-    display.drawString(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, "Restart");
+    display.drawString(display.getWidth()/2, display.getHeight()/2, "Restart");
     display.display();
   });
 
   // Align text vertical/horizontal center
   display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
   display.setFont(ArialMT_Plain_10);
-  display.drawString(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, "Ready for OTA:\n" + WiFi.localIP().toString());
+  display.drawString(display.getWidth()/2, display.getHeight()/2, "Ready for OTA:\n" + WiFi.localIP().toString());
   display.display();
 }
 
diff --git a/examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino b/examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino
index ed7401915861f89d9a1f4dd6f697bc82b44f3069..12ad6b111c57830117422b76bc9e28d86141cebd 100644
--- a/examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino
+++ b/examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino
@@ -58,7 +58,7 @@
 // SH1106Brzo  display(0x3c, D3, D5);
 
 // Initialize the OLED display using Wire library
-SSD1306  display(0x3c, D3, D5);
+SSD1306  display(GEOMETRY_128_64, 0x3c, D3, D5);
 // SH1106 display(0x3c, D3, D5);
 
 
diff --git a/examples/SSD1306SimpleDemo/images.h b/examples/SSD1306SimpleDemo/images.h
index 9daf8c1a25b9d006fc67f49c6868563d13c7ae77..50417990fd0d3d0854b4385afac1334d45223214 100644
--- a/examples/SSD1306SimpleDemo/images.h
+++ b/examples/SSD1306SimpleDemo/images.h
@@ -1,6 +1,6 @@
 #define WiFi_Logo_width 60
 #define WiFi_Logo_height 36
-const char WiFi_Logo_bits[] PROGMEM = {
+const uint8_t WiFi_Logo_bits[] PROGMEM = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
diff --git a/examples/SSD1306UiDemo/SSD1306UiDemo.ino b/examples/SSD1306UiDemo/SSD1306UiDemo.ino
index 31357569ff3849b6c1098165aa96f9880129327f..f19617af86301391786b15bbc80b23080556d865 100644
--- a/examples/SSD1306UiDemo/SSD1306UiDemo.ino
+++ b/examples/SSD1306UiDemo/SSD1306UiDemo.ino
@@ -64,7 +64,7 @@
 // SH1106Brzo  display(0x3c, D3, D5);
 
 // Initialize the OLED display using Wire library
-SSD1306  display(0x3c, D3, D5);
+SSD1306  display(GEOMETRY_128_64, 0x3c, D3, D5);
 // SH1106 display(0x3c, D3, D5);
 
 OLEDDisplayUi ui     ( &display );
diff --git a/examples/SSD1306UiDemo/images.h b/examples/SSD1306UiDemo/images.h
index 8b876a369e6f2609700798da9da47431e5e0db21..2489d1e5de658663f1bf16b456b18743193cf1c0 100644
--- a/examples/SSD1306UiDemo/images.h
+++ b/examples/SSD1306UiDemo/images.h
@@ -1,6 +1,6 @@
 #define WiFi_Logo_width 60
 #define WiFi_Logo_height 36
-const char WiFi_Logo_bits[] PROGMEM = {
+const uint8_t WiFi_Logo_bits[] PROGMEM = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
@@ -27,7 +27,7 @@ const char WiFi_Logo_bits[] PROGMEM = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   };
 
-const char activeSymbol[] PROGMEM = {
+const uint8_t activeSymbol[] PROGMEM = {
     B00000000,
     B00000000,
     B00011000,
@@ -38,7 +38,7 @@ const char activeSymbol[] PROGMEM = {
     B00011000
 };
 
-const char inactiveSymbol[] PROGMEM = {
+const uint8_t inactiveSymbol[] PROGMEM = {
     B00000000,
     B00000000,
     B00000000,