diff --git a/examples/ssd1306_i2c/Makefile b/examples/ssd1306_example/Makefile
similarity index 100%
rename from examples/ssd1306_i2c/Makefile
rename to examples/ssd1306_example/Makefile
diff --git a/examples/ssd1306_example/README.md b/examples/ssd1306_example/README.md
new file mode 100644
index 0000000..9ffd1d5
--- /dev/null
+++ b/examples/ssd1306_example/README.md
@@ -0,0 +1,3 @@
+# SSD1306 I2C/SPI OLED LCD Example
+
+To run this example connect the SSD1306 OLED LCD and configure protocol, display size and pins in main.c file.
diff --git a/examples/ssd1306_i2c/image.xbm b/examples/ssd1306_example/image.xbm
similarity index 100%
rename from examples/ssd1306_i2c/image.xbm
rename to examples/ssd1306_example/image.xbm
diff --git a/examples/ssd1306_example/main.c b/examples/ssd1306_example/main.c
new file mode 100644
index 0000000..0238408
--- /dev/null
+++ b/examples/ssd1306_example/main.c
@@ -0,0 +1,96 @@
+#include <espressif/esp_common.h>
+#include <esp/uart.h>
+#include <FreeRTOS.h>
+#include <task.h>
+#include <queue.h>
+#include <string.h>
+#include <ssd1306/ssd1306.h>
+
+/* Remove this line if your display connected by SPI */
+#define I2C_CONNECTION
+
+#ifdef I2C_CONNECTION
+    #include <i2c/i2c.h>
+#endif
+
+#include "image.xbm"
+
+/* Change this according to you schematics and display size */
+#define DISPLAY_WIDTH  128
+#define DISPLAY_HEIGHT 64
+
+#ifdef I2C_CONNECTION
+    #define PROTOCOL SSD1306_PROTO_I2C
+    #define ADDR     SSD1306_I2C_ADDR_0
+    #define SCL_PIN  5
+    #define SDA_PIN  4
+#else
+    #define PROTOCOL SSD1306_PROTO_SPI4
+    #define CS_PIN   5
+    #define DC_PIN   4
+#endif
+
+/* Declare device descriptor */
+static const ssd1306_t dev = {
+    .protocol = PROTOCOL,
+#ifdef I2C_CONNECTION
+    .addr     = ADDR,
+#else
+    .cs_pin   = CS_PIN,
+    .dc_pin   = DC_PIN,
+#endif
+    .width    = DISPLAY_WIDTH,
+    .height   = DISPLAY_HEIGHT
+};
+
+/* Local frame buffer */
+static uint8_t buffer[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8];
+
+static void ssd1306_task(void *pvParameters)
+{
+    printf("%s: Started user interface task\n", __FUNCTION__);
+    vTaskDelay(1000/portTICK_PERIOD_MS);
+
+
+    if (ssd1306_load_xbm(&dev, image_bits, buffer))
+        goto error_loop;
+
+    ssd1306_set_whole_display_lighting(&dev, false);
+    bool fwd = false;
+    while (1) {
+        vTaskDelay(2000 / portTICK_PERIOD_MS);
+        printf("%s: still alive, flipping!\n", __FUNCTION__);
+        ssd1306_set_scan_direction_fwd(&dev, fwd);
+        fwd = !fwd;
+    }
+
+error_loop:
+    printf("%s: error while loading framebuffer into SSD1306\n", __func__);
+    for(;;){
+        vTaskDelay(2000 / portTICK_PERIOD_MS);
+        printf("%s: error loop\n", __FUNCTION__);
+    }
+}
+
+void user_init(void)
+{
+    // Setup HW
+    uart_set_baud(0, 115200);
+
+    printf("SDK version:%s\n", sdk_system_get_sdk_version());
+
+#ifdef I2C_CONNECTION
+    i2c_init(SCL_PIN, SDA_PIN);
+#endif
+
+    while (ssd1306_init(&dev) != 0)
+    {
+        printf("%s: failed to init SSD1306 lcd\n", __func__);
+        vTaskDelay(1000/portTICK_PERIOD_MS);
+    }
+
+    ssd1306_set_whole_display_lighting(&dev, true);
+    vTaskDelay(1000/portTICK_PERIOD_MS);
+    // Create user interface task
+    xTaskCreate(ssd1306_task, "ssd1306_task", 256, NULL, 2, NULL);
+}
diff --git a/examples/ssd1306_i2c/README.md b/examples/ssd1306_i2c/README.md
deleted file mode 100644
index 9c75bb3..0000000
--- a/examples/ssd1306_i2c/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# I2C / SSD1306 OLED LCD Example
-
-To run this example connect the SSD1306 OLED LCD and configure SDA/SCL pins in ssd1306_i2c.c file.
diff --git a/examples/ssd1306_i2c/ssd1306_i2c.c b/examples/ssd1306_i2c/ssd1306_i2c.c
deleted file mode 100644
index 7dadfb4..0000000
--- a/examples/ssd1306_i2c/ssd1306_i2c.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "espressif/esp_common.h"
-#include "esp/uart.h"
-
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-
-#include <string.h>
-
-#include "i2c/i2c.h"
-#include "ssd1306/ssd1306.h"
-
-#include "image.xbm"
-
-/* Change this according to you schematics */
-#define SCL_PIN GPIO_ID_PIN((14))
-#define SDA_PIN GPIO_ID_PIN((12))
-
-/* Local frame buffer */
-static uint8_t buffer[SSD1306_ROWS * SSD1306_COLS / 8];
-
-static void ssd1306_task(void *pvParameters)
-{
-    printf("%s: Started user interface task\n", __FUNCTION__);
-    vTaskDelay(1000/portTICK_PERIOD_MS);
-
-
-    if (ssd1306_load_xbm(image_bits, buffer))
-        goto error_loop;
-
-    ssd1306_set_whole_display_lighting(false);
-    while (1) {
-        vTaskDelay(2000 / portTICK_PERIOD_MS);
-        printf("%s: steel alive\n", __FUNCTION__);
-    }
-
-error_loop:
-    printf("%s: error while loading framebuffer into SSD1306\n", __func__);
-    for(;;){
-        vTaskDelay(2000 / portTICK_PERIOD_MS);
-        printf("%s: error loop\n", __FUNCTION__);
-    }
-}
-
-void user_init(void)
-{
-    // Setup HW
-    uart_set_baud(0, 115200);
-
-    printf("SDK version:%s\n", sdk_system_get_sdk_version());
-
-    i2c_init(SCL_PIN, SDA_PIN);
-
-    if (ssd1306_init()){
-        for (;;) {
-            printf("%s: failed to init SSD1306 lcd\n", __func__);
-            vTaskDelay(1000/portTICK_PERIOD_MS);
-        }
-    }
-
-    ssd1306_set_whole_display_lighting(true);
-    vTaskDelay(1000/portTICK_PERIOD_MS);
-    // Create user interface task
-    xTaskCreate(ssd1306_task, "ssd1306_task", 256, NULL, 2, NULL);
-}
diff --git a/extras/ssd1306/README.md b/extras/ssd1306/README.md
index cb283b9..f3a06e9 100644
--- a/extras/ssd1306/README.md
+++ b/extras/ssd1306/README.md
@@ -1,27 +1,80 @@
-# Driver for I2C SSD1306 128x64 OLED LCD
+# Driver for SSD1306 OLED LCD
 
 This driver is written for usage with the ESP8266 and FreeRTOS ([esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos)).
 
-### Usage
+## Supported display sizes
 
-Before using the SSD1306 LCD module, the function `i2c_init(SCL_PIN, SDA_PIN)` needs to be called to setup the I2C interface and then you must call ssd1306_init().
+ - 128x64
+ - 128x32
+ - 128x16
+ - 96x16
+
+## Supported connection interfaces
+
+Currently supported two of them: I2C and SPI4.
+
+## Usage
+
+If Reset pin is accesible in your display module, connect it to the RESET pin of ESP8266.
+If you don't do this, display RAM may be glitchy after the power lost/restore.
+
+### I2C protocol
+
+Before using the SSD1306 LCD module the function `i2c_init(SCL_PIN, SDA_PIN)` needs to be
+called to setup the I2C interface and then you must call `ssd1306_init()`.
 
 #### Example 
 
-```
-#define SCL_PIN GPIO_ID_PIN(0)
-#define SDA_PIN GPIO_ID_PIN(2)
+```C
+#define SCL_PIN 5
+#define SDA_PIN 4
+...
+
+static const ssd1306_t device = {
+	.protocol = SSD1306_PROTO_I2C,
+	.width = 128,
+	.height = 64
+};
+
 ...
 
 i2c_init(SCL_PIN, SDA_PIN);
 
-if (ssd1306_init()) {
-// An error occured, while performing SSD1306 init init (E.g device not found etc.)
+if (ssd1306_init(&device)) {
+// An error occured, while performing SSD1306 init (E.g device not found etc.)
 }
 
 // rest of the code
 ```
 
+### SPI4 protocol
 
+This protocol MUCH faster than I2C but uses 2 additional GPIO pins (beside of HSPI CLK
+and HSPI MOSI): Data/Command pin and Chip Select pin.
 
+No additional function calls are required before `ssd1306_init()`.
 
+#### Example 
+
+```C
+#define CS_PIN 5
+#define DC_PIN 4
+
+...
+
+static const ssd1306_t device = {
+	.protocol = SSD1306_PROTO_SPI4,
+	.cs_pin = CS_PIN,
+	.dc_pin = DC_PIN,
+	.width = 128,
+	.height = 64
+};
+
+...
+
+if (ssd1306_init(&device)) {
+// An error occured, while performing SSD1306 init
+}
+
+// rest of the code
+```
diff --git a/extras/ssd1306/component.mk b/extras/ssd1306/component.mk
index 7f93338..f12a292 100644
--- a/extras/ssd1306/component.mk
+++ b/extras/ssd1306/component.mk
@@ -3,7 +3,15 @@
 # expected anyone using ssd1306 driver includes it as 'ssd1306/ssd1306.h'
 INC_DIRS += $(ssd1306_ROOT)..
 
+# I2C support is on by default
+SSD1306_I2C_SUPPORT ?= 1
+# SPI4 support is on by default
+SSD1306_SPI4_SUPPORT ?= 1
+
 # args for passing into compile rule generation
-ssd1306_SRC_DIR =  $(ssd1306_ROOT)
+ssd1306_SRC_DIR = $(ssd1306_ROOT)
+
+ssd1306_CFLAGS = -DSSD1306_I2C_SUPPORT=${SSD1306_I2C_SUPPORT} -DSSD1306_SPI4_SUPPORT=${SSD1306_SPI4_SUPPORT} $(CFLAGS)
+
 
 $(eval $(call component_compile_rules,ssd1306))
diff --git a/extras/ssd1306/config.h b/extras/ssd1306/config.h
new file mode 100644
index 0000000..bd622c3
--- /dev/null
+++ b/extras/ssd1306/config.h
@@ -0,0 +1,12 @@
+#ifndef _EXTRAS_SSD1306_CONFIG_H_
+#define _EXTRAS_SSD1306_CONFIG_H_
+
+#ifndef SSD1306_I2C_SUPPORT
+#define SSD1306_I2C_SUPPORT 1
+#endif
+
+#ifndef SSD1306_SPI4_SUPPORT
+#define SSD1306_SPI4_SUPPORT 1
+#endif
+
+#endif /* _EXTRAS_SSD1306_CONFIG_H_ */
diff --git a/extras/ssd1306/ssd1306.c b/extras/ssd1306/ssd1306.c
index 85f641f..06370a8 100644
--- a/extras/ssd1306/ssd1306.c
+++ b/extras/ssd1306/ssd1306.c
@@ -1,376 +1,406 @@
+/**
+ * SSD1306 OLED display driver for esp-open-rtos.
+ *
+ * Copyright (c) 2016 urx (https://github.com/urx),
+ *                    Ruslan V. Uss (https://github.com/UncleRus)
+ *
+ * MIT Licensed as described in the file LICENSE
+ *
+ * @todo Scrolling, fonts
+ */
+#include "ssd1306.h"
 #include <stdio.h>
-#include <i2c/i2c.h>
+#if (SSD1306_I2C_SUPPORT)
+    #include <i2c/i2c.h>
+#endif
+#if (SSD1306_SPI4_SUPPORT)
+    #include <esp/spi.h>
+#endif
+#include <esp/gpio.h>
 #include <FreeRTOS.h>
 #include <task.h>
-#include "ssd1306.h"
+
+#define SPI_BUS 1
+
+//#define SSD1306_DEBUG
 
 /* SSD1306 commands */
-#define SSD1306_SET_MEM_ADDR_MODE   (0x20)
-#define SSD1306_ADDR_MODE_HORIZ     (0x0)
-#define SSD1306_ADDR_MODE_VERT      (0x1)
-#define SSD1306_ADDR_MODE_PAGE      (0x2)
+#define SSD1306_SET_MEM_ADDR_MODE    (0x20)
 
-#define SSD1306_SET_COL_ADDR        (0x21)
-#define SSD1306_SET_PAGE_ADDR       (0x22)
-#define SSD1306_SET_DISP_START_LINE (0x40)
-#define SSD1306_SET_CONTRAST        (0x81)
-#define SSD1306_SET_SEGMENT_REMAP0  (0xA0)
-#define SSD1306_SET_SEGMENT_REMAP1  (0xA1)
-#define SSD1306_SET_ENTIRE_DISP_ON  (0xA5)
-#define SSD1306_SET_ENTIRE_DISP_OFF (0xA4)
-#define SSD1306_SET_INVERSION_OFF   (0xA6)
-#define SSD1306_SET_INVERSION_ON    (0xA7)
+#define SSD1306_SET_COL_ADDR         (0x21)
+#define SSD1306_SET_PAGE_ADDR        (0x22)
+#define SSD1306_SET_DISP_START_LINE  (0x40)
+#define SSD1306_SET_CONTRAST         (0x81)
+#define SSD1306_SET_SEGMENT_REMAP0   (0xA0)
+#define SSD1306_SET_SEGMENT_REMAP1   (0xA1)
+#define SSD1306_SET_ENTIRE_DISP_ON   (0xA5)
+#define SSD1306_SET_ENTIRE_DISP_OFF  (0xA4)
+#define SSD1306_SET_INVERSION_OFF    (0xA6)
+#define SSD1306_SET_INVERSION_ON     (0xA7)
 
-#define SSD1306_SET_MUX_RATIO       (0xA8)
-#define SSD1306_MUX_RATIO_MASK      (0x3F)
-#define SSD1306_SET_DISPLAY_OFF     (0xAE)
-#define SSD1306_SET_DISPLAY_ON      (0xAF)
-#define SSD1306_SET_SCAN_DIR_FWD    (0xC0)
-#define SSD1306_SET_SCAN_DIR_BWD    (0xC8)
-#define SSD1306_SET_DISPLAY_OFFSET  (0xD3)
-#define SSD1306_SET_OSC_FREQ        (0xD5)
-#define SSD1306_SET_PRE_CHRG_PER    (0xD9)
+#define SSD1306_SET_MUX_RATIO        (0xA8)
+#define SSD1306_MUX_RATIO_MASK       (0x3F)
+#define SSD1306_SET_DISPLAY_OFF      (0xAE)
+#define SSD1306_SET_DISPLAY_ON       (0xAF)
+#define SSD1306_SET_SCAN_DIR_FWD     (0xC0)
+#define SSD1306_SET_SCAN_DIR_BWD     (0xC8)
+#define SSD1306_SET_DISPLAY_OFFSET   (0xD3)
+#define SSD1306_SET_OSC_FREQ         (0xD5)
+#define SSD1306_SET_PRE_CHRG_PER     (0xD9)
 
-#define SSD1306_SET_COM_PINS_HW_CFG (0xDA)
-#define SSD1306_COM_PINS_HW_CFG_MASK    (0x32)
-#define SSD1306_SEQ_COM_PINS_CFG    (0x02)
-#define SSD1306_ALT_COM_PINS_CFG    (0x12)
-#define SSD1306_COM_LR_REMAP_OFF    (0x02)
-#define SSD1306_COM_LR_REMAP_ON     (0x22)
+#define SSD1306_SET_COM_PINS_HW_CFG  (0xDA)
+#define SSD1306_COM_PINS_HW_CFG_MASK (0x32)
+#define SSD1306_SEQ_COM_PINS_CFG     (0x02)
+#define SSD1306_ALT_COM_PINS_CFG     (0x12)
+#define SSD1306_COM_LR_REMAP_OFF     (0x02)
+#define SSD1306_COM_LR_REMAP_ON      (0x22)
 
-#define SSD1306_SET_DESEL_LVL       (0xDB)
-#define SSD1306_SET_NOP             (0xE3)
+#define SSD1306_SET_DESEL_LVL        (0xDB)
+#define SSD1306_SET_NOP              (0xE3)
 
-#define SSD1306_SET_CHARGE_PUMP     (0x8D)
-#define SSD1306_CHARGE_PUMP_EN      (0x14)
-#define SSD1306_CHARGE_PUMP_DIS     (0x10)
+#define SSD1306_SET_CHARGE_PUMP      (0x8D)
+#define SSD1306_CHARGE_PUMP_EN       (0x14)
+#define SSD1306_CHARGE_PUMP_DIS      (0x10)
 
 #ifdef SSD1306_DEBUG
-#define debug(fmt, ...) printf("%s" fmt "\n", "SSD1306", ## __VA_ARGS__);
+#define debug(fmt, ...) printf("%s: " fmt "\n", "SSD1306", ## __VA_ARGS__)
 #else
 #define debug(fmt, ...)
 #endif
 
 /* Issue a command to SSD1306 device
- * format such follows:
+ * I2C proto format:
  * |S|Slave Address|W|ACK|0x00|Command|Ack|P|
  * 
  * in case of two-bytes command here will be Data byte
- * right after command byte.
+ * right after the command byte.
  */
-int ssd1306_command(uint8_t cmd)
+int ssd1306_command(const ssd1306_t *dev, uint8_t cmd)
 {
-    i2c_start();
-    if (!i2c_write(SSD1306_I2C_ADDR << 1)) {
-        debug("Error while xmitting I2C slave address\n");
-        i2c_stop();
-        return -EIO;
+    debug("Command: 0x%02x", cmd);
+    switch (dev->protocol) {
+#if (SSD1306_I2C_SUPPORT)
+        case SSD1306_PROTO_I2C:
+            i2c_start();
+            if (!i2c_write(dev->addr << 1)) {
+                debug("Error while xmitting I2C slave address\n");
+                i2c_stop();
+                return -EIO;
+            }
+            if (!i2c_write(0x00)) {
+                debug("Error while xmitting transmission type\n");
+                i2c_stop();
+                return -EIO;
+            }
+            if (!i2c_write(cmd)) {
+                debug("Error while xmitting command: 0x%02X\n", cmd);
+                i2c_stop();
+                return -EIO;
+            }
+            i2c_stop();
+            break;
+#endif
+#if (SSD1306_SPI4_SUPPORT)
+        case SSD1306_PROTO_SPI4:
+            gpio_write(dev->dc_pin, false); // command mode
+            gpio_write(dev->cs_pin, false);
+            spi_transfer_8(SPI_BUS, cmd);
+            gpio_write(dev->cs_pin, true);
+            break;
+#endif
+        default:
+            debug("Unsupported protocol");
+            return -EPROTONOSUPPORT;
     }
-    if (!i2c_write(0x00)) {
-        debug("Error while xmitting transmission type\n");
-        i2c_stop();
-        return -EIO;
-    }
-
-    if (!i2c_write(cmd)) {
-        debug("Error while xmitting command: 0x%02X\n", cmd);
-        i2c_stop();
-        return -EIO;
-    }
-
-    i2c_stop();
 
     return 0;
 }
 
 /* Perform default init routine according
 * to SSD1306 datasheet from adafruit.com */
-int ssd1306_init()
+int ssd1306_init(const ssd1306_t *dev)
 {
-    if (!ssd1306_display_on(false)                                  &&
-        !ssd1306_set_osc_freq(0x80)                                 &&
-        !ssd1306_set_mux_ratio(SSD1306_ROWS-1)                      &&
-        !ssd1306_set_display_offset(0x0)                            &&
-        !ssd1306_set_display_start_line(0x0)                        &&
-        !ssd1306_set_charge_pump_enabled(true)                      &&
-        !ssd1306_set_mem_addr_mode(SSD1306_ADDR_MODE_HORIZ)         &&
-        !ssd1306_set_segment_remapping_enabled(false)               &&
-        !ssd1306_set_scan_direction_fwd(true)                       &&
-        !ssd1306_set_com_pin_hw_config(SSD1306_ALT_COM_PINS_CFG)    &&
-        !ssd1306_set_contrast(0x9f)                                 &&
-        !ssd1306_set_precharge_period(0xf1)                         &&
-        !ssd1306_set_deseltct_lvl(0x40)                             &&
-        !ssd1306_set_whole_display_lighting(true)                   &&
-        !ssd1306_set_inversion(false)                               &&
-        !ssd1306_display_on(true)) {
+    uint8_t pin_cfg;
+    switch (dev->height) {
+        case 16:
+        case 32:
+            pin_cfg = 0x02;
+            break;
+        case 64:
+            pin_cfg = 0x12;
+            break;
+        default:
+            debug("Unsupported screen height");
+            return -ENOTSUP;
+    }
+
+    switch (dev->protocol) {
+#if (SSD1306_I2C_SUPPORT)
+        case SSD1306_PROTO_I2C:
+            break;
+#endif
+#if (SSD1306_SPI4_SUPPORT)
+        case SSD1306_PROTO_SPI4:
+            gpio_enable(dev->cs_pin, GPIO_OUTPUT);
+            gpio_write(dev->cs_pin, true);
+            gpio_enable(dev->dc_pin, GPIO_OUTPUT);
+            spi_init(SPI_BUS, SPI_MODE0, SPI_FREQ_DIV_8M, true, SPI_LITTLE_ENDIAN, true);
+            break;
+#endif
+        default:
+            debug("Unsupported protocol");
+            return -EPROTONOSUPPORT;
+    }
+
+    if (!ssd1306_display_on(dev, false)                                  &&
+        !ssd1306_set_osc_freq(dev, 0x80)                                 &&
+        !ssd1306_set_mux_ratio(dev, dev->height - 1)                     &&
+        !ssd1306_set_display_offset(dev, 0x0)                            &&
+        !ssd1306_set_display_start_line(dev, 0x0)                        &&
+        !ssd1306_set_charge_pump_enabled(dev, true)                      &&
+        !ssd1306_set_mem_addr_mode(dev, SSD1306_ADDR_MODE_HORIZONTAL)    &&
+        !ssd1306_set_segment_remapping_enabled(dev, false)               &&
+        !ssd1306_set_scan_direction_fwd(dev, true)                       &&
+        !ssd1306_set_com_pin_hw_config(dev, pin_cfg)                     &&
+        !ssd1306_set_contrast(dev, 0x9f)                                 &&
+        !ssd1306_set_precharge_period(dev, 0xf1)                         &&
+        !ssd1306_set_deseltct_lvl(dev, 0x40)                             &&
+        !ssd1306_set_whole_display_lighting(dev, true)                   &&
+        !ssd1306_set_inversion(dev, false)                               &&
+        !ssd1306_display_on(dev, true)) {
         return 0;
     }
 
     return -EIO;
 }
 
-/*
-    * frame buffer of SSD1306 consists of 8 pages of 128 bits each
-    *
-*/
-int ssd1306_load_frame_buffer(uint8_t buf[], uint16_t len)
+int ssd1306_load_frame_buffer(const ssd1306_t *dev, uint8_t buf[])
 {
     uint16_t i;
     uint8_t j;
 
-    ssd1306_set_column_addr(0, 127);
-    ssd1306_set_page_addr(0, 7);
+    ssd1306_set_column_addr(dev, 0, dev->width - 1);
+    ssd1306_set_page_addr(dev, 0, dev->height / 8 - 1);
 
-    for (i=0; i<len; i++) {
-        i2c_start();
-        if (!i2c_write(SSD1306_I2C_ADDR << 1)) {
-            debug("Error while xmitting I2C slave address\n");
-            i2c_stop();
-            return -EIO;
-        }
-        if (!i2c_write(0x40)) {
-            debug("Error while xmitting transmission type\n");
-            i2c_stop();
-            return -EIO;
-        }
+    size_t len = dev->width * dev->height / 8;
 
-        for (j=0;j<16;j++) {
-            if (!i2c_write(buf[i])) {
-                debug("Error while writing to GDDRAM\n");
+    switch (dev->protocol) {
+#if (SSD1306_I2C_SUPPORT)
+        case SSD1306_PROTO_I2C:
+            for (i = 0; i < len; i++) {
+                i2c_start();
+                if (!i2c_write(dev->addr << 1)) {
+                    debug("Error while xmitting I2C slave address\n");
+                    i2c_stop();
+                    return -EIO;
+                }
+                if (!i2c_write(0x40)) {
+                    debug("Error while xmitting transmission type\n");
+                    i2c_stop();
+                    return -EIO;
+                }
+
+                for (j = 0; j < 16; j++) {
+                    if (!i2c_write(buf ? buf[i] : 0)) {
+                        debug("Error while writing to GDDRAM\n");
+                        i2c_stop();
+                        return -EIO;
+                    }
+                    i++;
+                }
+                i--;
                 i2c_stop();
-                return -EIO;
+                taskYIELD();
             }
-            i++;
-        }
-        i--;
-        i2c_stop();
-        taskYIELD();
+            break;
+#endif
+#if (SSD1306_SPI4_SUPPORT)
+        case SSD1306_PROTO_SPI4:
+            gpio_write(dev->dc_pin, true); // data mode
+            gpio_write(dev->cs_pin, false);
+            if (buf)
+                spi_transfer(SPI_BUS, buf, NULL, len, SPI_8BIT);
+            else
+                for (i = 0; i < len; i ++) {
+                    spi_transfer_8(SPI_BUS, 0);
+                }
+            gpio_write(dev->cs_pin, true);
+            break;
+#endif
+        default:
+            debug("Unsupported protocol");
+            return -EPROTONOSUPPORT;
     }
 
     return 0;
 }
 
-int ssd1306_clear_screen()
+int ssd1306_display_on(const ssd1306_t *dev, bool on)
 {
-    uint16_t i = 0;
-    uint8_t j = 0;
-
-    ssd1306_set_column_addr(0, 127);
-    ssd1306_set_page_addr(0, 7);
-
-    while (i < (SSD1306_ROWS*SSD1306_COLS/8)) {
-        i2c_start();
-        if (!i2c_write(SSD1306_I2C_ADDR << 1)) {
-            debug("Error while xmitting I2C slave address\n");
-            i2c_stop();
-            return -EIO;
-        }
-        if (!i2c_write(0x40)) {
-            debug("Error while xmitting transmission type\n");
-            i2c_stop();
-            return -EIO;
-        }
-
-        /* write 16 bytes of data and then give resources to another task */
-        while (j < 16) {
-            if (!i2c_write(0x0)) {
-                debug("Error while writing to GDDRAM\n");
-                i2c_stop();
-                return -EIO;
-            }
-            i++;
-            j++;
-        }
-        i--;
-        j = 0;
-        i2c_stop();
-        taskYIELD();
-    }
-
-    return 0;
+    return ssd1306_command(dev, on ? SSD1306_SET_DISPLAY_ON : SSD1306_SET_DISPLAY_OFF);
 }
 
-int ssd1306_display_on(bool on)
+int ssd1306_set_display_start_line(const ssd1306_t *dev, uint8_t start)
 {
-    if (on)
-        return ssd1306_command(SSD1306_SET_DISPLAY_ON);
+    if (start > 63)
+        return -EINVAL;
 
-    return ssd1306_command(SSD1306_SET_DISPLAY_OFF);
+    return ssd1306_command(dev, SSD1306_SET_DISP_START_LINE | start);
 }
 
-int ssd1306_set_display_start_line(uint8_t start)
+int ssd1306_set_display_offset(const ssd1306_t *dev, uint8_t offset)
 {
-    return ssd1306_command(SSD1306_SET_DISP_START_LINE | start);
-}
-
-int ssd1306_set_display_offset(uint8_t offset)
-{
-    int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_DISPLAY_OFFSET)))
-        return err;
-
-    return ssd1306_command(offset);
-}
-
-int ssd1306_set_charge_pump_enabled(bool enabled)
-{
-    int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_CHARGE_PUMP)))
-        return err;
-
-    if (enabled)
-        return ssd1306_command(SSD1306_CHARGE_PUMP_EN);
-
-    return ssd1306_command(SSD1306_CHARGE_PUMP_DIS);
-}
-
-int ssd1306_set_mem_addr_mode(uint8_t mode)
-{
-    if (mode >= 0x3)
+    if (offset > 63)
         return -EINVAL;
 
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_MEM_ADDR_MODE)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_DISPLAY_OFFSET)))
         return err;
 
-    return ssd1306_command(mode);
+    return ssd1306_command(dev, offset);
 }
 
-int ssd1306_set_segment_remapping_enabled(bool on)
-{
-    if (on)
-        return ssd1306_command(SSD1306_SET_SEGMENT_REMAP1);
-
-    return ssd1306_command(SSD1306_SET_SEGMENT_REMAP0);
-}
-
-int ssd1306_set_scan_direction_fwd(bool fwd)
-{
-    if (fwd)
-        return ssd1306_command(SSD1306_SET_SCAN_DIR_FWD);
-
-    return ssd1306_command(SSD1306_SET_SCAN_DIR_BWD);
-}
-
-int ssd1306_set_com_pin_hw_config(uint8_t config)
+int ssd1306_set_charge_pump_enabled(const ssd1306_t *dev, bool enabled)
 {
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_COM_PINS_HW_CFG)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_CHARGE_PUMP)))
         return err;
 
-    return ssd1306_command(config & SSD1306_COM_PINS_HW_CFG_MASK);
+    return ssd1306_command(dev, enabled ? SSD1306_CHARGE_PUMP_EN : SSD1306_CHARGE_PUMP_DIS);
 }
 
-int ssd1306_set_contrast(uint8_t contrast)
+int ssd1306_set_mem_addr_mode(const ssd1306_t *dev, ssd1306_mem_addr_mode_t mode)
 {
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_CONTRAST)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_MEM_ADDR_MODE)))
         return err;
 
-    return ssd1306_command(contrast);
+    return ssd1306_command(dev, mode);
 }
 
-int ssd1306_set_inversion(bool on)
+int ssd1306_set_segment_remapping_enabled(const ssd1306_t *dev, bool on)
 {
-    if (on)
-        return ssd1306_command(SSD1306_SET_INVERSION_ON);
-
-    return ssd1306_command(SSD1306_SET_INVERSION_OFF);
+    return ssd1306_command(dev, on ? SSD1306_SET_SEGMENT_REMAP1 : SSD1306_SET_SEGMENT_REMAP0);
 }
 
-int ssd1306_set_osc_freq(uint8_t osc_freq)
+int ssd1306_set_scan_direction_fwd(const ssd1306_t *dev, bool fwd)
+{
+    return ssd1306_command(dev, fwd ? SSD1306_SET_SCAN_DIR_FWD : SSD1306_SET_SCAN_DIR_BWD);
+}
+
+int ssd1306_set_com_pin_hw_config(const ssd1306_t *dev, uint8_t config)
 {
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_OSC_FREQ)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_COM_PINS_HW_CFG)))
         return err;
 
-    return ssd1306_command(osc_freq);
+    return ssd1306_command(dev, config & SSD1306_COM_PINS_HW_CFG_MASK);
 }
 
-int ssd1306_set_mux_ratio(uint8_t ratio)
+int ssd1306_set_contrast(const ssd1306_t *dev, uint8_t contrast)
 {
-    if (ratio < 15)
+    int err = 0;
+    if ((err = ssd1306_command(dev, SSD1306_SET_CONTRAST)))
+        return err;
+
+    return ssd1306_command(dev, contrast);
+}
+
+int ssd1306_set_inversion(const ssd1306_t *dev, bool on)
+{
+    return ssd1306_command(dev, on ? SSD1306_SET_INVERSION_ON : SSD1306_SET_INVERSION_OFF);
+}
+
+int ssd1306_set_osc_freq(const ssd1306_t *dev, uint8_t osc_freq)
+{
+    int err = 0;
+    if ((err = ssd1306_command(dev, SSD1306_SET_OSC_FREQ)))
+        return err;
+
+    return ssd1306_command(dev, osc_freq);
+}
+
+int ssd1306_set_mux_ratio(const ssd1306_t *dev, uint8_t ratio)
+{
+    if (ratio < 15 || ratio > 63)
         return -EINVAL;
 
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_MUX_RATIO)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_MUX_RATIO)))
         return err;
 
-    return ssd1306_command(ratio);
+    return ssd1306_command(dev, ratio);
 }
 
-int ssd1306_set_column_addr(uint8_t start, uint8_t stop)
+int ssd1306_set_column_addr(const ssd1306_t *dev, uint8_t start, uint8_t stop)
 {
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_COL_ADDR)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_COL_ADDR)))
         return err;
 
-    if ((err = ssd1306_command(start)))
+    if ((err = ssd1306_command(dev, start)))
         return err;
 
-    return ssd1306_command(stop);
+    return ssd1306_command(dev, stop);
 }
 
-int ssd1306_set_page_addr(uint8_t start, uint8_t stop)
+int ssd1306_set_page_addr(const ssd1306_t *dev, uint8_t start, uint8_t stop)
 {
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_PAGE_ADDR)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_PAGE_ADDR)))
         return err;
 
-    if ((err = ssd1306_command(start)))
+    if ((err = ssd1306_command(dev, start)))
         return err;
 
-    return ssd1306_command(stop);
+    return ssd1306_command(dev, stop);
 }
 
-int ssd1306_set_precharge_period(uint8_t prchrg)
+int ssd1306_set_precharge_period(const ssd1306_t *dev, uint8_t prchrg)
 {
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_PRE_CHRG_PER)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_PRE_CHRG_PER)))
         return err;
 
-    return ssd1306_command(prchrg);
+    return ssd1306_command(dev, prchrg);
 }
 
-int ssd1306_set_deseltct_lvl(uint8_t lvl)
+int ssd1306_set_deseltct_lvl(const ssd1306_t *dev, uint8_t lvl)
 {
     int err = 0;
-    if ((err = ssd1306_command(SSD1306_SET_DESEL_LVL)))
+    if ((err = ssd1306_command(dev, SSD1306_SET_DESEL_LVL)))
         return err;
 
-    return ssd1306_command(lvl);
+    return ssd1306_command(dev, lvl);
 }
 
-int ssd1306_set_whole_display_lighting(bool light)
+int ssd1306_set_whole_display_lighting(const ssd1306_t *dev, bool light)
 {
-    if (light)
-        return ssd1306_command(SSD1306_SET_ENTIRE_DISP_ON);
-
-    return ssd1306_command(SSD1306_SET_ENTIRE_DISP_OFF);
+    return ssd1306_command(dev, light ? SSD1306_SET_ENTIRE_DISP_ON :  SSD1306_SET_ENTIRE_DISP_OFF);
 }
 
 
 /* one byte of xbm - 8 dots in line of picture source
  * one byte of fb - 8 rows for 1 column of screen
  */
-int ssd1306_load_xbm(uint8_t *xbm, uint8_t *fb)
+int ssd1306_load_xbm(const ssd1306_t *dev, uint8_t *xbm, uint8_t *fb)
 {
     uint8_t bit = 0;
 
     int row = 0;
     int column = 0;
-    for (row = 0; row < SSD1306_ROWS; row ++) {
-        for (column = 0; column < SSD1306_COLS/8; column++) {
+    for (row = 0; row < dev->height; row ++) {
+        for (column = 0; column < dev->width / 8; column++) {
             uint16_t xbm_offset = row * 16  + column;
             for (bit = 0; bit < 8; bit++) {
                 if (*(xbm + xbm_offset) & 1 << bit) {
-                    *(fb + SSD1306_COLS*(row/8)+column*8+bit) |= 1 << row%8;
+                    *(fb + dev->width * (row / 8) + column * 8 + bit) |= 1 << row % 8;
                 }
             }
         }
     }
 
-    return ssd1306_load_frame_buffer(fb, SSD1306_ROWS*SSD1306_COLS/8);
+    return ssd1306_load_frame_buffer(dev, fb);
 }
 
 
diff --git a/extras/ssd1306/ssd1306.h b/extras/ssd1306/ssd1306.h
index 933ceae..b4309f9 100644
--- a/extras/ssd1306/ssd1306.h
+++ b/extras/ssd1306/ssd1306.h
@@ -1,3 +1,11 @@
+/**
+ * SSD1306 OLED display driver for esp-open-rtos.
+ *
+ * Copyright (c) 2016 urx (https://github.com/urx),
+ *                    Ruslan V. Uss (https://github.com/UncleRus)
+ *
+ * MIT Licensed as described in the file LICENSE
+ */
 #ifndef _SSD1306__H_
 #define _SSD1306__H_
 
@@ -5,46 +13,271 @@
 #include <stdbool.h>
 #include <errno.h>
 
+#include "config.h"
+
 // shifted
-#define SSD1306_I2C_ADDR    (0x3C)
+#if (SSD1306_I2C_SUPPORT)
+    #define SSD1306_I2C_ADDR_0    (0x3C)
+    #define SSD1306_I2C_ADDR_1    (0x3D)
+#endif
 
-#define SSD1306_ROWS        (64)
-#define SSD1306_COLS        (128)
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 
-/* Issue single command on SSD1306 */
-int ssd1306_command(uint8_t cmd);
-
-/* Default init for SSD1306 */
-int ssd1306_init();
-
-/* Load picture in xbm format into SSD1306 RAM
- * xbm - pointer to xbm picture array
- * fb - pointer fo local buffer for storing converted xbm image
+/**
+ * I/O protocols
  */
-int ssd1306_load_xbm(uint8_t *xbm, uint8_t *fb);
+typedef enum
+{
+    SSD1306_PROTO_I2C = 0, //!< I2C
+    SSD1306_PROTO_SPI4,    //!< SPI 8 bits + D/C pin
+    SSD1306_PROTO_SPI3     //!< SPI 9 bits, currently not supported
+} ssd1306_protocol_t;
 
-/* Load local framebuffer into SSD1306 RAM */
-int ssd1306_load_frame_buffer(uint8_t buf[], uint16_t len);
+/**
+ * Device descriptor
+ */
+typedef struct
+{
+    ssd1306_protocol_t protocol;
+#if (SSD1306_I2C_SUPPORT)
+    uint8_t addr;                 //!< I2C address, used by SSD1306_PROTO_I2C
+#endif
+#if (SSD1306_SPI4_SUPPORT)
+    uint8_t cs_pin;               //!< Chip Select GPIO pin, used by SSD1306_PROTO_SPI3, SSD1306_PROTO_SPI4
+    uint8_t dc_pin;               //!< Data/Command GPIO pin, used by SSD1306_PROTO_SPI4
+#endif
+    uint8_t width;                //!< Screen width, currently supported 128px, 96px
+    uint8_t height;               //!< Screen height, currently supported 16px, 32px, 64px
+} ssd1306_t;
 
-/* Clears SSD1306 ram */
-int ssd1306_clear_screen();
+/**
+ * Addressing mode, see datasheet
+ */
+typedef enum
+{
+    SSD1306_ADDR_MODE_HORIZONTAL = 0,
+    SSD1306_ADDR_MODE_VERTICAL,
+    SSD1306_ADDR_MODE_PAGE
+} ssd1306_mem_addr_mode_t;
 
-int ssd1306_display_on(bool on);
-int ssd1306_set_display_start_line(uint8_t start);
-int ssd1306_set_display_offset(uint8_t offset);
-int ssd1306_set_charge_pump_enabled(bool enabled);
-int ssd1306_set_mem_addr_mode(uint8_t mode);
-int ssd1306_set_segment_remapping_enabled(bool on);
-int ssd1306_set_scan_direction_fwd(bool fwd);
-int ssd1306_set_com_pin_hw_config(uint8_t config);
-int ssd1306_set_contrast(uint8_t contrast);
-int ssd1306_set_inversion(bool on);
-int ssd1306_set_osc_freq(uint8_t osc_freq);
-int ssd1306_set_mux_ratio(uint8_t ratio);
-int ssd1306_set_column_addr(uint8_t start, uint8_t stop);
-int ssd1306_set_page_addr(uint8_t start, uint8_t stop);
-int ssd1306_set_precharge_period(uint8_t prchrg);
-int ssd1306_set_deseltct_lvl(uint8_t lvl);
-int ssd1306_set_whole_display_lighting(bool light);
+/**
+ * Issue a single command on SSD1306.
+ * @param dev Pointer to device descriptor
+ * @param cmd Command
+ * @return Non-zero if error occured
+ */
+int ssd1306_command(const ssd1306_t *dev, uint8_t cmd);
+
+/**
+ * Default init for SSD1306
+ * @param dev Pointer to device descriptor
+ * @return Non-zero if error occured
+ */
+int ssd1306_init(const ssd1306_t *dev);
+
+/**
+ * Load picture in xbm format into the SSD1306 RAM.
+ * @param dev Pointer to device descriptor
+ * @param xbm Pointer to xbm picture array
+ * @param fb Pointer to local buffer for storing converted xbm image
+ * @return Non-zero if error occured
+ */
+int ssd1306_load_xbm(const ssd1306_t *dev, uint8_t *xbm, uint8_t *fb);
+
+/**
+ * Load local framebuffer into the SSD1306 RAM.
+ * @param dev Pointer to device descriptor
+ * @param buf Pointer to framebuffer or NULL for clear RAM. Framebuffer size = width * height / 8
+ * @return Non-zero if error occured
+ */
+int ssd1306_load_frame_buffer(const ssd1306_t *dev, uint8_t buf[]);
+
+/**
+ * Clear SSD1306 RAM.
+ * @param dev Pointer to device descriptor
+ * @return Non-zero if error occured
+ */
+inline int ssd1306_clear_screen(const ssd1306_t *dev)
+{
+    return ssd1306_load_frame_buffer(dev, NULL);
+}
+
+/**
+ * Turn display on or off.
+ * @param dev Pointer to device descriptor
+ * @param on Turn on if true
+ * @return Non-zero if error occured
+ */
+int ssd1306_display_on(const ssd1306_t *dev, bool on);
+
+/**
+ * Set the Display Start Line register to determine starting address of
+ * display RAM, by selecting a value from 0 to 63. With value equal to 0,
+ * RAM row 0 is mapped to COM0. With value equal to 1, RAM row 1 is mapped
+ * to COM0 and so on.
+ * @param dev Pointer to device descriptor
+ * @param start Start line, 0..63
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_display_start_line(const ssd1306_t *dev, uint8_t start);
+
+/**
+ * Set display offset (see datasheet).
+ * @param dev Pointer to device descriptor
+ * @param offset Offset, 0..63
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_display_offset(const ssd1306_t *dev, uint8_t offset);
+
+/**
+ * Enable or disable the charge pump. See application note in datasheet.
+ * @param dev Pointer to device descriptor
+ * @param enabled Enable charge pump if true
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_charge_pump_enabled(const ssd1306_t *dev, bool enabled);
+
+/**
+ * Set memory addressing mode. See datasheet.
+ * @param dev Pointer to device descriptor
+ * @param mode Addressing mode
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_mem_addr_mode(const ssd1306_t *dev, ssd1306_mem_addr_mode_t mode);
+
+/**
+ * Change the mapping between the display data column address and the
+ * segment driver. See datasheet.
+ * @param dev Pointer to device descriptor
+ * @param on Enable segment remapping if true
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_segment_remapping_enabled(const ssd1306_t *dev, bool on);
+
+/**
+ * Set the scan direction of the COM output, allowing layout flexibility
+ * in the OLED module design. Additionally, the display will show once
+ * this command is issued. For example, if this command is sent during
+ * normal display then the graphic display will be vertically flipped
+ * immediately.
+ * @param dev Pointer to device descriptor
+ * @param fwd Forward direction if true, backward otherwise
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_scan_direction_fwd(const ssd1306_t *dev, bool fwd);
+
+/**
+ * Set the COM signals pin configuration to match the OLED panel
+ * hardware layout. See datasheet.
+ * @param dev Pointer to device descriptor
+ * @param config Sequential COM pin configuration
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_com_pin_hw_config(const ssd1306_t *dev, uint8_t config);
+
+/**
+ * Set the display contrast.
+ * @param dev Pointer to device descriptor
+ * @param contrast Contrast increases as the value increases.
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_contrast(const ssd1306_t *dev, uint8_t contrast);
+
+/**
+ * Set the display to be either normal or inverse. In normal display
+ * a RAM data of 1 indicates an “ON” pixel while in inverse display a
+ * RAM data of 0 indicates an “ON” pixel.
+ * @param dev Pointer to device descriptor
+ * @param on Inverse display if true
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_inversion(const ssd1306_t *dev, bool on);
+
+/**
+ * Set the divide ratio of display clock and oscillator frequency.
+ * See datasheet.
+ * @param dev Pointer to device descriptor
+ * @param osc_freq Lower nibble - DCLK divide ratio, high
+ *     nibble - oscillator frequency
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_osc_freq(const ssd1306_t *dev, uint8_t osc_freq);
+
+/**
+ * Switch the default 63 multiplex mode to any multiplex ratio,
+ * ranging from 16 to 63. The output pads COM0~COM63 will be switched
+ * to the corresponding COM signal.
+ * @param dev Pointer to device descriptor
+ * @param ratio Multiplex ratio, 16..63
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_mux_ratio(const ssd1306_t *dev, uint8_t ratio);
+
+/**
+ * Specify column start address and end address of the display data RAM.
+ * This command also sets the column address pointer to column start
+ * address. This pointer is used to define the current read/write column
+ * address in graphic display data RAM. If horizontal address increment mode
+ * is enabled by ssd1306_set_mem_addr_mode(), after finishing read/write
+ * one column data, it is incremented automatically to the next column
+ * address. Whenever the column address pointer finishes accessing the
+ * end column address, it is reset back to start column address and the
+ * row address is incremented to the next row.
+ * @param dev Pointer to device descriptor
+ * @param start Start RAM address
+ * @param stop End RAM address
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_column_addr(const ssd1306_t *dev, uint8_t start, uint8_t stop);
+
+/**
+ * Specify page start address and end address of the display data RAM.
+ * This command also sets the page address pointer to page start address.
+ * This pointer is used to define the current read/write page address in
+ * graphic display data RAM. If vertical address increment mode is enabled by
+ * ssd1306_set_mem_addr_mode(), after finishing read/write one page data,
+ * it is incremented automatically to the next page address. Whenever the page
+ * address pointer finishes accessing the end page address, it is reset back
+ * to start page address.
+ * @param dev Pointer to device descriptor
+ * @param start Start RAM address
+ * @param stop End RAM address
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_page_addr(const ssd1306_t *dev, uint8_t start, uint8_t stop);
+
+/**
+ * Set the duration of the pre-charge period. The interval is counted in
+ * number of DCLK, where RESET equals 2 DCLKs.
+ * @param dev Pointer to device descriptor
+ * @param prchrg Pre-charge period
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_precharge_period(const ssd1306_t *dev, uint8_t prchrg);
+
+/**
+ * Adjust the VCOMH regulator output. See datasheet.
+ * @param dev Pointer to device descriptor
+ * @param lvl Deselect level
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_deseltct_lvl(const ssd1306_t *dev, uint8_t lvl);
+
+/**
+ * Force the entire display to be “ON”, regardless of the contents of
+ * the display data RAM.
+ * @param dev Pointer to device descriptor
+ * @param light Force the entire display to be “ON if true
+ * @return Non-zero if error occured
+ */
+int ssd1306_set_whole_display_lighting(const ssd1306_t *dev, bool light);
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
 
 #endif // _SSD1306__H_