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)
/**
sarg: short argument
- larg: long argument
+ larg: long argument
*/
static int arg_is(const char *arg, const char *sarg, const char *larg)
{
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;
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);
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);
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)
*/
/**
- 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"
};
};
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)
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;
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);
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)
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)
ossd_goto(line, 0);
ossd_fill_line(data, 128);
}
-}
+}
void ossd_sleep(uint8_t on_off)
{
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)))
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);
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);
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)
#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
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
*/
/**
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);
/** 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)
*/