/* display.c */ #include #include #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 }