/* * ssd1306.c * * Created on: Jan 13, 2016 * Author: tkl */ #include #include "i2c.h" #include "font.h" #include "bitmap.h" #include "ssd1306.h" #define MAX_COLUMN 128 #define MAX_ROW 64 #define PAGE_COUNT 8 #define HEAD_PAGE_COUNT 2 #define BODY_PAGE_COUNT PAGE_COUNT - HEAD_PAGE_COUNT #define CMD_MODE 0x80 #define DATA_MODE 0x40 #define COLUMN_ADDR 0x21 #define PAGE_ADDR 0x22 #define DISPLAY_OFF 0xAE static const char init_sequence[] = { 0x80, 0xAE, 0x80, 0x20, 0x80, 0x10, 0x80, 0xb0, 0x80, 0xc8, 0x80, 0x00, 0x80, 0x10, 0x80, 0x40, 0x80, 0x81, 0x80, 0x7f, 0x80, 0xa1, 0x80, 0xa6, 0x80, 0xa8, 0x80, 0x3f, 0x80, 0xa4, 0x80, 0xd3, 0x80, 0x00, 0x80, 0xd5, 0x80, 0xf0, 0x80, 0xd9, 0x80, 0x22, 0x80, 0xda, 0x80, 0x12, 0x80, 0xdb, 0x80, 0x20, 0x80, 0x8d, 0x80, 0x14, 0x80, 0xaf }; static int set_column(const struct ssd1306 *dev, char column) { char buf[6]; buf[0] = CMD_MODE; buf[1] = COLUMN_ADDR; buf[2] = CMD_MODE; buf[3] = column; buf[4] = CMD_MODE; buf[5] = MAX_COLUMN - 1; return i2c_write(dev->dev, dev->i2c_addr, buf, 6); } static int set_page(const struct ssd1306 *dev, char page) { char buf[6]; buf[0] = CMD_MODE; buf[1] = PAGE_ADDR; buf[2] = CMD_MODE; buf[3] = page; buf[4] = CMD_MODE; buf[5] = MAX_ROW / PAGE_COUNT - 1; return i2c_write(dev->dev, dev->i2c_addr, buf, 6); } static int clear_head(const struct ssd1306 *dev) { int ret, i, j; char buf[2]; ret = set_column(dev, 0); ret |= set_page(dev, 0); buf[0] = DATA_MODE; buf[1] = 0x00; for(i = 0; i < HEAD_PAGE_COUNT; i++) for(j = 0; j < MAX_COLUMN; j++) ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2); return ret; } static int clear_body(const struct ssd1306 *dev) { int ret, i, j; char buf[2]; ret = set_column(dev, 0); ret |= set_page(dev, 2); buf[0] = DATA_MODE; buf[1] = 0x00; for(i = 0; i < BODY_PAGE_COUNT; i++) for(j = 0; j < MAX_COLUMN; j++) ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2); return ret; } static int clear(const struct ssd1306 *dev) { int ret; ret = clear_head(dev); ret |= clear_body(dev); return ret; } int ssd1306_open(const struct ssd1306 *dev) { int ret; ret = i2c_open((struct i2c *)dev->dev); ret |= i2c_write(dev->dev, dev->i2c_addr, init_sequence, sizeof(init_sequence) / sizeof(init_sequence[0])); ret |= clear(dev); ret |= set_column(dev, 0); ret |= set_page(dev, 0); return ret; } int ssd1306_close(const struct ssd1306 *dev) { int ret; char buf[2]; buf[0] = CMD_MODE; buf[1] = DISPLAY_OFF; ret = i2c_write(dev->dev, dev->i2c_addr, buf, 2); ret |= i2c_close((struct i2c *)dev->dev); return ret; } int ssd1306_write(const struct ssd1306 *dev, const struct bitmap *bitmap) { int ret, i, len = bitmap->x_size * bitmap->y_size / 8; char buf[2] = {DATA_MODE, 0x00}; if(len != MAX_COLUMN * PAGE_COUNT) return -1; ret = set_column(dev, 0); ret |= set_page(dev, 0); for(i = 0; i < len; i++) { buf[1] = bitmap->buffer[i]; ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2); } return ret; }