diff --git a/SH1106.h b/SH1106.h
new file mode 100644
index 0000000000000000000000000000000000000000..55dd4090efc0d138d571d7418b4ef6360b1f610d
--- /dev/null
+++ b/SH1106.h
@@ -0,0 +1,36 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 by Daniel Eichhorn
+ * Copyright (c) 2016 by Fabrice Weinberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
+ */
+
+#ifndef SH1106_h
+#define SH1106_h
+#include "SH1106Wire.h"
+
+// For make SH1106 an alias for SH1106Wire
+typedef SH1106Wire SH1106;
+
+
+#endif
diff --git a/SH1106Brzo.h b/SH1106Brzo.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1a89c474273becc9243547dee542687d9373eaa
--- /dev/null
+++ b/SH1106Brzo.h
@@ -0,0 +1,117 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 by Daniel Eichhorn
+ * Copyright (c) 2016 by Fabrice Weinberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
+ */
+
+#ifndef SH1106Brzo_h
+#define SH1106Brzo_h
+
+#include "OLEDDisplay.h"
+#include <brzo_i2c.h>
+
+#if F_CPU == 160000000L
+  #define BRZO_I2C_SPEED 1000
+#else
+  #define BRZO_I2C_SPEED 800
+#endif
+
+class SH1106Brzo : public OLEDDisplay {
+  private:
+      uint8_t             _address;
+      uint8_t             _sda;
+      uint8_t             _scl;
+
+  public:
+    SH1106Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl) {
+      this->_address = _address;
+      this->_sda = _sda;
+      this->_scl = _scl;
+    }
+
+    bool connect(){
+      brzo_i2c_setup(_sda, _scl, 0);
+      return true;
+    }
+
+    void display(void) {
+    #ifdef OLEDDISPLAY_DOUBLE_BUFFER
+       uint8_t minBoundY = ~0;
+       uint8_t maxBoundY = 0;
+
+       uint8_t x, y;
+
+       // 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;
+          if (buffer[pos] != buffer_back[pos]) {
+            minBoundY = _min(minBoundY, y);
+            maxBoundY = _max(maxBoundY, y);
+          }
+          buffer_back[pos] = buffer[pos];
+        }
+        yield();
+       }
+
+       // If the minBoundY wasn't updated
+       // we can savely assume that buffer_back[pos] == buffer[pos]
+       // holdes true for all values of pos
+       if (minBoundY == ~0) return;
+
+       byte k = 0;
+       uint8_t sendBuffer[17];
+       sendBuffer[0] = 0x40;
+       brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED);
+       for (y = minBoundY; y <= maxBoundY; y++) {
+         sendCommand(0xB0 + y);
+         sendCommand(0x02);
+         sendCommand(0x10);
+         for (x = 0; x < DISPLAY_WIDTH; x++) {
+             k++;
+             sendBuffer[k] = buffer[x + y * DISPLAY_WIDTH];
+             if (k == 16)  {
+               brzo_i2c_write(sendBuffer, 17, true);
+               k = 0;
+             }
+         }
+         yield();
+       }
+       brzo_i2c_write(sendBuffer, k + 1, true);
+       brzo_i2c_end_transaction();
+     #else
+     #endif
+    }
+
+  private:
+    inline void sendCommand(uint8_t com) __attribute__((always_inline)){
+      uint8_t command[2] = {0x80 /* command mode */, com};
+      brzo_i2c_start_transaction(_address, BRZO_I2C_SPEED);
+      brzo_i2c_write(command, 2, true);
+      brzo_i2c_end_transaction();
+    }
+};
+
+#endif
diff --git a/SH1106Wire.h b/SH1106Wire.h
new file mode 100644
index 0000000000000000000000000000000000000000..d885fab38e049b070d0f40e0292292d98c72d391
--- /dev/null
+++ b/SH1106Wire.h
@@ -0,0 +1,138 @@
+/**
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 by Daniel Eichhorn
+ * Copyright (c) 2016 by Fabrice Weinberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Credits for parts of this code go to Mike Rankin. Thank you so much for sharing!
+ */
+
+#ifndef SH1106Wire_h
+#define SH1106Wire_h
+
+#include "OLEDDisplay.h"
+#include <Wire.h>
+
+#define SH1106_SET_PUMP_VOLTAGE 0X30
+#define SH1106_SET_PUMP_MODE 0XAD
+#define SH1106_PUMP_ON 0X8B
+#define SH1106_PUMP_OFF 0X8A
+//--------------------------------------
+
+class SH1106Wire : public OLEDDisplay {
+  private:
+      uint8_t             _address;
+      uint8_t             _sda;
+      uint8_t             _scl;
+
+  public:
+    SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl) {
+      this->_address = _address;
+      this->_sda = _sda;
+      this->_scl = _scl;
+    }
+
+    bool connect() {
+      Wire.begin(this->_sda, this->_scl);
+      // Let's use ~700khz if ESP8266 is in 160Mhz mode
+      // this will be limited to ~400khz if the ESP8266 in 80Mhz mode.
+      Wire.setClock(700000);
+      return true;
+    }
+
+    void display(void) {
+      #ifdef OLEDDISPLAY_DOUBLE_BUFFER
+        uint8_t minBoundY = ~0;
+        uint8_t maxBoundY = 0;
+        uint8_t x, y;
+
+        // 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;
+           if (buffer[pos] != buffer_back[pos]) {
+             minBoundY = _min(minBoundY, y);
+             maxBoundY = _max(maxBoundY, y);
+           }
+           buffer_back[pos] = buffer[pos];
+         }
+         yield();
+        }
+
+        // If the minBoundY wasn't updated
+        // we can savely assume that buffer_back[pos] == buffer[pos]
+        // holdes true for all values of pos
+        if (minBoundY == ~0) return;
+
+        byte k = 0;
+        for (y = minBoundY; y <= maxBoundY; y++) {
+          sendCommand(0xB0 + y);
+          sendCommand(0x02);
+          sendCommand(0x10);
+          for (x = 0; x < DISPLAY_WIDTH; x++) {
+            if (k == 0) {
+              Wire.beginTransmission(_address);
+              Wire.write(0x40);
+            }
+            Wire.write(buffer[x + y * DISPLAY_WIDTH]);
+            k++;
+            if (k == 16)  {
+              Wire.endTransmission();
+              k = 0;
+            }
+          }
+          yield();
+        }
+
+        if (k != 0) {
+          Wire.endTransmission();
+        }
+      #else
+        uint8_t * p = &buffer[0];
+        for (uint8_t y=0; y<8; y++) {
+          sendCommand(0xB0+y);
+          sendCommand(0x02);
+          sendCommand(0x10);
+          for( uint8_t x=0; x<8; x++) {
+            Wire.beginTransmission(_address);
+            Wire.write(0x40);
+            for (uint8_t k = 0; k < 16; k++) {
+              Wire.write(*p++);
+            }
+            Wire.endTransmission();
+          }
+        }
+      #endif
+    }
+
+  private:
+    inline void sendCommand(uint8_t command) __attribute__((always_inline)){
+      Wire.beginTransmission(_address);
+      Wire.write(0x80);
+      Wire.write(command);
+      Wire.endTransmission();
+    }
+
+
+};
+
+#endif