140 lines
3.0 KiB
C
140 lines
3.0 KiB
C
/*
|
|
* ssd1306.c
|
|
*
|
|
* Created on: Jan 13, 2016
|
|
* Author: tkl
|
|
*/
|
|
|
|
#include <string.h>
|
|
#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;
|
|
}
|