You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
2.5 KiB
141 lines
2.5 KiB
9 years ago
|
/* display.c */
|
||
|
|
||
|
#include <avr/io.h>
|
||
|
#include <avr/pgmspace.h>
|
||
|
|
||
|
#include "common.h"
|
||
|
#include "i2c.h"
|
||
|
#include "font.h"
|
||
|
|
||
|
#define ADDRESS 0x3c
|
||
|
|
||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||
|
|
||
|
#define HORIZONTAL_FLIP 0
|
||
|
#define VERTICAL_FLIP 0
|
||
|
|
||
|
#define COM_ALT 1
|
||
|
#define COM_LR_REMAP 0
|
||
|
|
||
|
#define DISPLAY_INVERT 0
|
||
|
|
||
|
#define DEFAULT_CONTRAST 0x7f
|
||
|
|
||
|
/* Init sequence from SSD1306 datasheet */
|
||
|
const uint8 display_init_seq[] = {
|
||
|
0xa8, 0x3f, /* Multiplex ratio */
|
||
|
0xd3, 0x00, /* Display offset */
|
||
|
0x40, /* Display start line */
|
||
|
0xa0 | HORIZONTAL_FLIP,
|
||
|
0xc0 | (VERTICAL_FLIP << 3),
|
||
|
0xda, 0x02 | (COM_ALT << 4) | (COM_LR_REMAP << 5),
|
||
|
0x81, DEFAULT_CONTRAST,
|
||
|
0xa4, /* Disable entire display on */
|
||
|
0xa6 | DISPLAY_INVERT,
|
||
|
0xd5, 0x80, /* clock divide ratio */
|
||
|
0x8d, 0x14, /* charge pump setting */
|
||
|
0xaf /* display on */
|
||
|
};
|
||
|
|
||
|
uint8 curpos;
|
||
|
|
||
|
#if 0
|
||
|
void delay(uint8_t count)
|
||
|
{
|
||
|
volatile uint8_t i;
|
||
|
|
||
|
while (count--)
|
||
|
for (i = 255; i; i--)
|
||
|
;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void display_command(uint8_t command)
|
||
|
{
|
||
|
i2c_set_xor(0);
|
||
|
i2c_write(ADDRESS, 0x80, 1, &command);
|
||
|
}
|
||
|
|
||
|
void display_init(void)
|
||
|
{
|
||
|
uint8 i;
|
||
|
|
||
|
i2c_init();
|
||
|
|
||
|
for (i = 0; i < ARRAY_SIZE(display_init_seq); i++)
|
||
|
display_command(display_init_seq[i]);
|
||
|
|
||
|
curpos = 0;
|
||
|
}
|
||
|
|
||
|
void display_data(uint8_t len, uint8_t *data)
|
||
|
{
|
||
|
i2c_write(ADDRESS, 0x40, len, data);
|
||
|
curpos += len;
|
||
|
#if 0
|
||
|
/* This bit is only needed if you are relying on wraparound. */
|
||
|
if (curpos > 127)
|
||
|
curpos -= 128;
|
||
|
#endif
|
||
|
//delay(255);
|
||
|
}
|
||
|
|
||
|
/* col = graphics column, row = text rows
|
||
|
* 0-127 0-7
|
||
|
*/
|
||
|
void display_setposition(uint8_t col, uint8_t row)
|
||
|
{
|
||
|
display_command(0xb0 + (row & 0x0f));
|
||
|
display_command(0x00 + (col & 0x0f));
|
||
|
display_command(0x10 + ((col >> 4) & 0x0f));
|
||
|
curpos = col;
|
||
|
}
|
||
|
|
||
|
void display_setinverse(bool on)
|
||
|
{
|
||
|
i2c_set_xor(on ? 0xff : 0);
|
||
|
}
|
||
|
|
||
|
void display_putchar(char c)
|
||
|
{
|
||
|
uint8_t *data = font_getchar(c);
|
||
|
display_data(6, data);
|
||
|
}
|
||
|
|
||
|
void display_putstr(char *s)
|
||
|
{
|
||
|
while (*s)
|
||
|
display_putchar(*(s++));
|
||
|
}
|
||
|
|
||
|
void display_putstr_P(const char *s)
|
||
|
{
|
||
|
char c;
|
||
|
while ((c = pgm_read_byte(s++)) != '\0')
|
||
|
display_putchar(c);
|
||
|
}
|
||
|
|
||
|
#ifdef FAST_CLEAR
|
||
|
const uint8_t zero_data[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||
|
#endif
|
||
|
|
||
|
void display_clearline(void)
|
||
|
{
|
||
|
uint8_t remaining = 128 - curpos;
|
||
|
|
||
|
#ifdef FAST_CLEAR
|
||
|
while (remaining) {
|
||
|
uint8_t todo = remaining;
|
||
|
if (todo > sizeof(zero_data))
|
||
|
todo = sizeof(zero_data);
|
||
|
display_data(todo, (uint8_t *)zero_data);
|
||
|
remaining -= todo;
|
||
|
}
|
||
|
#else
|
||
|
uint8_t zero = 0;
|
||
|
|
||
|
while (remaining--)
|
||
|
display_data(1, &zero);
|
||
|
#endif
|
||
|
}
|