]> Chaos Git - corbenik/bdfe.git/commitdiff
Added support for SH1106
authorAndrey Chilikin <achilikin@gmail.com>
Wed, 7 Oct 2015 19:28:46 +0000 (20:28 +0100)
committerAndrey Chilikin <achilikin@gmail.com>
Wed, 7 Oct 2015 19:28:46 +0000 (20:28 +0100)
Now both SSD1306 and SH1106 controllers supported

main.c
ossd_i2c.c
ossd_i2c.h

diff --git a/main.c b/main.c
index d3158a5e729163169405088a51f6d53834ed5d4e..a5a29efdfc1e2aed04f2ddd8fc39b86f1fab25c1 100644 (file)
--- a/main.c
+++ b/main.c
@@ -16,7 +16,7 @@
     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-       OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+       OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
@@ -43,7 +43,7 @@
 
 /**
  sarg: short argument
- larg: long argument 
+ larg: long argument
  */
 static int arg_is(const char *arg, const char *sarg, const char *larg)
 {
@@ -77,6 +77,7 @@ int main(int argc, char **argv)
        char *file;
        bdfe_t *font;
        int flags = 0;
+       uint8_t driver = OSSD_SSD1306;
        uint8_t i2c_bus = 1;
        uint8_t i2c_address = 0x3C;
        uint8_t orientation = 0;
@@ -136,6 +137,12 @@ int main(int argc, char **argv)
                if (arg_is(argv[i], "-r", "rotate"))
                        flags |= BDF_ROTATE;
 
+               if (arg_is(argv[i], "-3", "ssd1306"))
+                       driver = OSSD_SSD1306;
+
+               if (arg_is(argv[i], "-1", "sh1106"))
+                       driver = OSSD_SH1106;
+
                if (arg_is(argv[i], "-B", "i2c_bus")) {
                        i++;
                        uint32_t i2bus = strtoul(argv[i], NULL, 16);
@@ -193,7 +200,7 @@ int main(int argc, char **argv)
        of.gn   = (uint8_t)font->chars;
        of.font = font->font;
 
-       ossd_init(i2c_bus, orientation);
+       ossd_init(driver, i2c_bus, orientation);
        ossd_set_user_font(&of, NULL);
        ossd_select_font(OSSD_FONT_USER);
 
index f183528c69d4595196b16ad8eea982287fb85386..6e2e151b1a597e4dc7a3ad29271f693576b2f70a 100644 (file)
@@ -16,7 +16,7 @@
     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-       OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+       OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
@@ -25,7 +25,7 @@
 */
 
 /**
-       Limited set of functions for SSD1306 compatible OLED 128x64 displays
+       Limited set of functions for SSD1306 / SH1106 compatible OLED 128x64 displays
        in text mode to minimize memory footprint if used on Atmel AVRs chips
        with low memory.
 */
 
 #include "ossd_i2c.h"
 
-#if (OSSD_TARGET == OSSD_IF_AVR) 
+#if (OSSD_TARGET == OSSD_IF_AVR)
        #include <avr/io.h>
        #include <avr/pgmspace.h>
        #include <util/atomic.h>
        #include "i2cmaster.h"
-#else 
+#else
        #define PROGMEM
        #define pgm_read_byte(x) (*((uint8_t *)x))
        #include <alloca.h>
 #define OSSD_CHARGE_PUMP_ON  0x14
 #define OSSD_CHARGE_PUMP_OFF 0x10
 
+#define OSSD_SET_DC_DC       0xAD
+#define OSSD_DC_DC_DISABLE   0x8A
+#define OSSD_DC_DC_ENABLE    0x8B
+
+#define OSSD_SET_PUMP_VPP    0x30
+#define OSSD_VPP_V74         0x00 // 7.4V
+#define OSSD_VPP_V80         0x01 // 8.0V
+#define OSSD_VPP_V84         0x02 // 8.4V
+#define OSSD_VPP_V90         0x03 // 9.0V
+
 static const uint8_t font68[] PROGMEM = {
 #include "font6x8.h"
 };
@@ -118,14 +128,14 @@ static const uint8_t font816[] PROGMEM = {
 };
 
 static ossd_font_t _ofont[OSSD_FONT_MAX+1] = {
-       {  6,  8, 32, 127-32, font68 }, 
+       {  6,  8, 32, 127-32, font68 },
        {  8,  8, 32, 127-32, font88 },
        {  8, 16, 32, 127-32, font816 },
        {  0,  0, 0,       0, NULL }
 };
 
 static uint8_t _cfont;
-static uint8_t _mode;
+static uint8_t _offset;
 static uint8_t _i2c_val;
 
 uint8_t ossd_select_font(uint8_t font)
@@ -146,7 +156,7 @@ void ossd_set_user_font(ossd_font_t *nfont, ossd_font_t *ofont)
                ofont->font = _ofont[OSSD_FONT_USER].font;
        }
        _ofont[OSSD_FONT_USER].gw = nfont->gw;
-       _ofont[OSSD_FONT_USER].gh = nfont->gh; 
+       _ofont[OSSD_FONT_USER].gh = nfont->gh;
        _ofont[OSSD_FONT_USER].go = nfont->go;
        _ofont[OSSD_FONT_USER].gn = nfont->gn;
        _ofont[OSSD_FONT_USER].font = nfont->font;
@@ -172,16 +182,6 @@ static void ossd_cmd_arg(uint8_t cmd, uint8_t arg)
        li2c_write(_i2c_val, data, 3);
 }
 
-static void ossd_cmd_arg2(uint8_t cmd, uint8_t arg1, uint8_t arg2)
-{
-       uint8_t data[4];
-       data[0] = OSSD_CMD;
-       data[1] = cmd;
-       data[2] = arg1;
-       data[3] = arg2;
-       li2c_write(_i2c_val, data, 4);
-}
-
 static void ossd_fill_line(uint8_t data, uint8_t num)
 {
        uint8_t *buf = (uint8_t *)alloca(num+1);
@@ -209,16 +209,6 @@ static void ossd_cmd_arg(uint8_t cmd, uint8_t arg)
        i2c_stop();
 }
 
-static void ossd_cmd_arg2(uint8_t cmd, uint8_t arg1, uint8_t arg2)
-{
-       i2c_start(_i2c_val);
-       i2c_write(OSSD_CMD);
-       i2c_write(cmd);
-       i2c_write(arg1);
-       i2c_write(arg2);
-       i2c_stop();
-}
-
 #if (OSSD_TARGET == OSSD_IF_AVR)
 
 static void ossd_fill_line(uint8_t data, uint8_t num)
@@ -255,35 +245,12 @@ static inline void ossd_data(uint8_t data)
        ossd_send_byte(OSSD_DATA, data);
 }
 
-static uint8_t ossd_set_addr_mode(uint8_t set_mode)
-{
-       uint8_t ret = _mode;
-       if (_mode != set_mode) {
-               ossd_cmd_arg(OSSD_SET_ADDR_MODE, set_mode);
-               // if switching back to page mode
-               // set full screen as output region
-               if (set_mode == OSSD_ADDR_MODE_PAGE) {
-                       ossd_cmd_arg2(OSSD_SET_PAGE_ADDR, 0, 7);
-                       ossd_cmd_arg2(OSSD_SET_COL_ADDR, 0, 127);
-               }
-               _mode = set_mode;
-       }
-       return ret;
-}
-
 void ossd_goto(uint8_t line, uint8_t x)
 {
-       if (_mode == OSSD_ADDR_MODE_PAGE) {
-               ossd_cmd(OSSD_SET_START_PAGE | (line & 0x07));
-               ossd_cmd(OSSD_SET_START_LCOL | (x & 0x0F));
-               ossd_cmd(OSSD_SET_START_HCOL | (x >> 4));
-       }
-       else {
-               uint8_t gw = _ofont[_cfont].gw;
-               // in OSSD_ADDR_MODE_HOR/VER mode we set output region (gw x 16)
-               ossd_cmd_arg2(OSSD_SET_COL_ADDR, x, x + gw - 1);
-               ossd_cmd_arg2(OSSD_SET_PAGE_ADDR, line, line+1);
-       }
+       x += _offset;
+       ossd_cmd(OSSD_SET_START_PAGE | (line & 0x07));
+       ossd_cmd(OSSD_SET_START_LCOL | (x & 0x0F));
+       ossd_cmd(OSSD_SET_START_HCOL | (x >> 4));
 }
 
 void ossd_fill_screen(uint8_t data)
@@ -294,7 +261,7 @@ void ossd_fill_screen(uint8_t data)
                ossd_goto(line, 0);
                ossd_fill_line(data, 128);
        }
-} 
+}
 
 void ossd_sleep(uint8_t on_off)
 {
@@ -365,22 +332,23 @@ void ossd_putlx(uint8_t line, int8_t x, const char *str, uint8_t atr)
                over = 0x01;
        if (atr & OSSD_TEXT_UNDERLINE)
                under = 0x80;
-       
+
        uint8_t gw = _ofont[_cfont].gw;
        uint8_t gh = _ofont[_cfont].gh;
        uint8_t go = _ofont[_cfont].go;
        uint8_t gb = gw*(gh / 8); // bytes per glyph
        const uint8_t *font = _ofont[_cfont].font;
-       uint8_t cmode = ossd_set_addr_mode(OSSD_ADDR_MODE_HOR);
        for(; *str != '\0'; str++, x += gw) {
                uint16_t idx = (*str - go) * gb;
                if ((uint8_t)x > (128 - gw)) {
                        x = 0;
                        line = (line + (gh+7)/8) & 0x07;
                }
-               ossd_goto(line, x);    
+               ossd_goto(line, x);
                uint8_t i;
                for(i = 0; i < gb; i++) {
+                       if ((gh > 8) && (i == 8))
+                               ossd_goto(line + 1, x);
                        uint8_t d = pgm_read_byte(&font[idx+i]);
                        d ^= rev;
                        if (under && (gh == 8 || i > (gw - 1)))
@@ -390,21 +358,23 @@ void ossd_putlx(uint8_t line, int8_t x, const char *str, uint8_t atr)
                        ossd_data(d);
                }
        }
-       ossd_set_addr_mode(cmode);
 }
 
-void ossd_init(uint8_t i2c_val, uint8_t orientation)
+void ossd_init(uint8_t driver, uint8_t i2c_val, uint8_t orientation)
 {
-       _mode = 0xFF;
+       _offset = 0;
        _i2c_val = i2c_val;
-#if (OSSD_TARGET == OSSD_IF_AVR) 
+#if (OSSD_TARGET == OSSD_IF_AVR)
        _i2c_val = (_i2c_val << 1) | I2C_WRITE;
 #endif
-       // set all default values
+       /* set all default values */
        ossd_cmd(OSSD_SET_SLEEP_ON);
-       ossd_cmd_arg(OSSD_SET_MUX_RATIO, 63);   
+       ossd_cmd_arg(OSSD_SET_MUX_RATIO, 63);
        ossd_cmd_arg(OSSD_SET_DISP_OFFSET, 0);
+       ossd_cmd(OSSD_SET_START_PAGE);
        ossd_cmd(OSSD_SET_START_LINE | 0);
+       ossd_cmd(OSSD_SET_START_LCOL | 2);
+       ossd_cmd(OSSD_SET_START_HCOL | 0);
        ossd_cmd(OSSD_SET_SEG_REMAP | (orientation & OSSD_SEG_REMAP_R2L));
        ossd_cmd(OSSD_SET_COM_DIR | (orientation & OSSD_COM_DIR_UPDOWN));
        ossd_cmd_arg(OSSD_SET_COM_CONFIG, OSSD_COM_ALT);
@@ -414,8 +384,15 @@ void ossd_init(uint8_t i2c_val, uint8_t orientation)
        ossd_cmd_arg(OSSD_SET_PRECHARGE, 0x22);
        ossd_cmd_arg(OSSD_SET_VCOMH_LEVEL, OSSD_VCOMH_L077);
        ossd_cmd(OSSD_SET_INVERSE_OFF);
-       ossd_cmd_arg(OSSD_SET_CHARGE_PUMP, OSSD_CHARGE_PUMP_ON);
-       ossd_set_addr_mode(OSSD_ADDR_MODE_PAGE);
+
+       if (driver != OSSD_SH1106)
+               ossd_cmd_arg(OSSD_SET_CHARGE_PUMP, OSSD_CHARGE_PUMP_ON);
+       else {
+               ossd_cmd_arg(OSSD_SET_DC_DC, OSSD_DC_DC_ENABLE); /* POR */
+               ossd_cmd(OSSD_SET_PUMP_VPP | OSSD_VPP_V74);
+               _offset = 2;
+       }
+
        ossd_fill_screen(0x00);
        ossd_cmd(OSSD_SET_SLEEP_OFF);
        ossd_goto(0, 0);
index d3a07c942fa5955cdfa40c9b04ae7450b96b93ce..c46262213e04c5a27083c84c9afe66871c6a7bda 100644 (file)
@@ -16,7 +16,7 @@
     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-       OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+       OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
@@ -27,8 +27,9 @@
 #define __OLED_SSD1306_I2C__
 
 /**
-       Limited set of functions for SSD1306 compatible OLED displays in text mode
-       to minimize memory footprint if used on Atmel AVRs with low memory.
+  Limited set of functions for SSD1306 / SH1106 compatible OLED 128x64 displays
+  in text mode to minimize memory footprint if used on Atmel AVRs chips
+  with low memory.
 */
 
 #ifdef __cplusplus
@@ -70,7 +71,13 @@ typedef struct ossd_font_s
        const uint8_t *font;
 } ossd_font_t;
 
-/** 
+/**
+  Most common OLED drivers SSD1306 and SH1106 are supported
+  */
+#define OSSD_SH1106  0
+#define OSSD_SSD1306 1
+
+/**
   flat cable connected at the top
   use ossd_init(OSSD_UPDOWN) to rotate screen
   */
@@ -79,10 +86,11 @@ typedef struct ossd_font_s
 
 /**
   set default parameters
-  for AVR i2c_val is I2C address
-  for Linux (Edison, RPi) i2c_val is I2C bus
+  driver: OSSD_SSD1306 or OSSD_SH1106
+  i2c_val: I2C address for AVR
+           I2C bus for Linux (Edison, RPi)
   */
-void ossd_init(uint8_t i2c_val, uint8_t orientation);
+void ossd_init(uint8_t driver, uint8_t i2c_val, uint8_t orientation);
 
 /** fill screen with specified pattern */
 void ossd_fill_screen(uint8_t data);
@@ -96,7 +104,7 @@ void ossd_set_contrast(uint8_t val);
 /** select one of three fonts for following ossd_putlx() calls */
 uint8_t ossd_select_font(uint8_t font);
 
-/** 
+/**
  set user font selectable by OSSD_FONT_USER to nfont
  store current user font in ofont (if not NULL)
  */