engine_control/source/firmware/kernel/driver/ssd1306.c
2016-07-23 07:59:54 +02:00

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;
}