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.
140 lines
2.5 KiB
140 lines
2.5 KiB
/* 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 |
|
}
|
|
|