diff options
Diffstat (limited to 'drivers/avr/ssd1306.c')
| -rw-r--r-- | drivers/avr/ssd1306.c | 174 |
1 files changed, 14 insertions, 160 deletions
diff --git a/drivers/avr/ssd1306.c b/drivers/avr/ssd1306.c index e454f5437..03a909e9d 100644 --- a/drivers/avr/ssd1306.c +++ b/drivers/avr/ssd1306.c | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | #ifdef SSD1306OLED | 1 | #ifdef SSD1306OLED |
| 2 | 2 | ||
| 3 | #include "ssd1306.h" | 3 | #include "ssd1306.h" |
| 4 | #include "config.h" | ||
| 5 | #include "i2c.h" | 4 | #include "i2c.h" |
| 6 | #include <string.h> | 5 | #include <string.h> |
| 7 | #include "print.h" | 6 | #include "print.h" |
| @@ -13,18 +12,7 @@ | |||
| 13 | #include "lufa.h" | 12 | #include "lufa.h" |
| 14 | #endif | 13 | #endif |
| 15 | #include "sendchar.h" | 14 | #include "sendchar.h" |
| 16 | #include "pincontrol.h" | 15 | #include "timer.h" |
| 17 | |||
| 18 | //assign the right code to your layers | ||
| 19 | #define _BASE 0 | ||
| 20 | #define _LOWER 8 | ||
| 21 | #define _RAISE 16 | ||
| 22 | #define _FNLAYER 64 | ||
| 23 | #define _NUMLAY 128 | ||
| 24 | #define _NLOWER 136 | ||
| 25 | #define _NFNLAYER 192 | ||
| 26 | #define _MOUSECURSOR 256 | ||
| 27 | #define _ADJUST 65560 | ||
| 28 | 16 | ||
| 29 | // Set this to 1 to help diagnose early startup problems | 17 | // Set this to 1 to help diagnose early startup problems |
| 30 | // when testing power-on with ble. Turn it off otherwise, | 18 | // when testing power-on with ble. Turn it off otherwise, |
| @@ -32,26 +20,6 @@ | |||
| 32 | // with the matrix scan, causing keys to drop. | 20 | // with the matrix scan, causing keys to drop. |
| 33 | #define DEBUG_TO_SCREEN 0 | 21 | #define DEBUG_TO_SCREEN 0 |
| 34 | 22 | ||
| 35 | // Controls the SSD1306 128x32 OLED display via i2c | ||
| 36 | |||
| 37 | #define i2cAddress 0x3C | ||
| 38 | |||
| 39 | #define DisplayHeight 32 | ||
| 40 | #define DisplayWidth 128 | ||
| 41 | |||
| 42 | #define FontHeight 8 | ||
| 43 | #define FontWidth 6 | ||
| 44 | |||
| 45 | #define MatrixRows (DisplayHeight / FontHeight) | ||
| 46 | #define MatrixCols (DisplayWidth / FontWidth) | ||
| 47 | |||
| 48 | struct CharacterMatrix { | ||
| 49 | uint8_t display[MatrixRows][MatrixCols]; | ||
| 50 | uint8_t *cursor; | ||
| 51 | bool dirty; | ||
| 52 | }; | ||
| 53 | |||
| 54 | static struct CharacterMatrix display; | ||
| 55 | //static uint16_t last_battery_update; | 23 | //static uint16_t last_battery_update; |
| 56 | //static uint32_t vbat; | 24 | //static uint32_t vbat; |
| 57 | //#define BatteryUpdateInterval 10000 /* milliseconds */ | 25 | //#define BatteryUpdateInterval 10000 /* milliseconds */ |
| @@ -61,54 +29,13 @@ static uint8_t displaying; | |||
| 61 | #endif | 29 | #endif |
| 62 | static uint16_t last_flush; | 30 | static uint16_t last_flush; |
| 63 | 31 | ||
| 64 | enum ssd1306_cmds { | ||
| 65 | DisplayOff = 0xAE, | ||
| 66 | DisplayOn = 0xAF, | ||
| 67 | |||
| 68 | SetContrast = 0x81, | ||
| 69 | DisplayAllOnResume = 0xA4, | ||
| 70 | |||
| 71 | DisplayAllOn = 0xA5, | ||
| 72 | NormalDisplay = 0xA6, | ||
| 73 | InvertDisplay = 0xA7, | ||
| 74 | SetDisplayOffset = 0xD3, | ||
| 75 | SetComPins = 0xda, | ||
| 76 | SetVComDetect = 0xdb, | ||
| 77 | SetDisplayClockDiv = 0xD5, | ||
| 78 | SetPreCharge = 0xd9, | ||
| 79 | SetMultiPlex = 0xa8, | ||
| 80 | SetLowColumn = 0x00, | ||
| 81 | SetHighColumn = 0x10, | ||
| 82 | SetStartLine = 0x40, | ||
| 83 | |||
| 84 | SetMemoryMode = 0x20, | ||
| 85 | ColumnAddr = 0x21, | ||
| 86 | PageAddr = 0x22, | ||
| 87 | |||
| 88 | ComScanInc = 0xc0, | ||
| 89 | ComScanDec = 0xc8, | ||
| 90 | SegRemap = 0xa0, | ||
| 91 | SetChargePump = 0x8d, | ||
| 92 | ExternalVcc = 0x01, | ||
| 93 | SwitchCapVcc = 0x02, | ||
| 94 | |||
| 95 | ActivateScroll = 0x2f, | ||
| 96 | DeActivateScroll = 0x2e, | ||
| 97 | SetVerticalScrollArea = 0xa3, | ||
| 98 | RightHorizontalScroll = 0x26, | ||
| 99 | LeftHorizontalScroll = 0x27, | ||
| 100 | VerticalAndRightHorizontalScroll = 0x29, | ||
| 101 | VerticalAndLeftHorizontalScroll = 0x2a, | ||
| 102 | }; | ||
| 103 | |||
| 104 | |||
| 105 | // Write command sequence. | 32 | // Write command sequence. |
| 106 | // Returns true on success. | 33 | // Returns true on success. |
| 107 | static inline bool _send_cmd1(uint8_t cmd) { | 34 | static inline bool _send_cmd1(uint8_t cmd) { |
| 108 | bool res = false; | 35 | bool res = false; |
| 109 | 36 | ||
| 110 | if (i2c_start_write(i2cAddress)) { | 37 | if (i2c_start_write(SSD1306_ADDRESS)) { |
| 111 | xprintf("failed to start write to %d\n", i2cAddress); | 38 | xprintf("failed to start write to %d\n", SSD1306_ADDRESS); |
| 112 | goto done; | 39 | goto done; |
| 113 | } | 40 | } |
| 114 | 41 | ||
| @@ -153,8 +80,6 @@ static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { | |||
| 153 | #define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;} | 80 | #define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;} |
| 154 | #define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;} | 81 | #define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;} |
| 155 | 82 | ||
| 156 | static void matrix_clear(struct CharacterMatrix *matrix); | ||
| 157 | |||
| 158 | static void clear_display(void) { | 83 | static void clear_display(void) { |
| 159 | matrix_clear(&display); | 84 | matrix_clear(&display); |
| 160 | 85 | ||
| @@ -163,7 +88,7 @@ static void clear_display(void) { | |||
| 163 | send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); | 88 | send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); |
| 164 | send_cmd3(ColumnAddr, 0, DisplayWidth - 1); | 89 | send_cmd3(ColumnAddr, 0, DisplayWidth - 1); |
| 165 | 90 | ||
| 166 | if (i2c_start_write(i2cAddress)) { | 91 | if (i2c_start_write(SSD1306_ADDRESS)) { |
| 167 | goto done; | 92 | goto done; |
| 168 | } | 93 | } |
| 169 | if (i2c_master_write(0x40)) { | 94 | if (i2c_master_write(0x40)) { |
| @@ -262,7 +187,7 @@ done: | |||
| 262 | return success; | 187 | return success; |
| 263 | } | 188 | } |
| 264 | 189 | ||
| 265 | static void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { | 190 | void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { |
| 266 | *matrix->cursor = c; | 191 | *matrix->cursor = c; |
| 267 | ++matrix->cursor; | 192 | ++matrix->cursor; |
| 268 | 193 | ||
| @@ -275,7 +200,7 @@ static void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) { | |||
| 275 | } | 200 | } |
| 276 | } | 201 | } |
| 277 | 202 | ||
| 278 | static void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { | 203 | void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { |
| 279 | matrix->dirty = true; | 204 | matrix->dirty = true; |
| 280 | 205 | ||
| 281 | if (c == '\n') { | 206 | if (c == '\n') { |
| @@ -296,7 +221,7 @@ void iota_gfx_write_char(uint8_t c) { | |||
| 296 | matrix_write_char(&display, c); | 221 | matrix_write_char(&display, c); |
| 297 | } | 222 | } |
| 298 | 223 | ||
| 299 | static void matrix_write(struct CharacterMatrix *matrix, const char *data) { | 224 | void matrix_write(struct CharacterMatrix *matrix, const char *data) { |
| 300 | const char *end = data + strlen(data); | 225 | const char *end = data + strlen(data); |
| 301 | while (data < end) { | 226 | while (data < end) { |
| 302 | matrix_write_char(matrix, *data); | 227 | matrix_write_char(matrix, *data); |
| @@ -308,7 +233,7 @@ void iota_gfx_write(const char *data) { | |||
| 308 | matrix_write(&display, data); | 233 | matrix_write(&display, data); |
| 309 | } | 234 | } |
| 310 | 235 | ||
| 311 | static void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { | 236 | void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { |
| 312 | while (true) { | 237 | while (true) { |
| 313 | uint8_t c = pgm_read_byte(data); | 238 | uint8_t c = pgm_read_byte(data); |
| 314 | if (c == 0) { | 239 | if (c == 0) { |
| @@ -323,7 +248,7 @@ void iota_gfx_write_P(const char *data) { | |||
| 323 | matrix_write_P(&display, data); | 248 | matrix_write_P(&display, data); |
| 324 | } | 249 | } |
| 325 | 250 | ||
| 326 | static void matrix_clear(struct CharacterMatrix *matrix) { | 251 | void matrix_clear(struct CharacterMatrix *matrix) { |
| 327 | memset(matrix->display, ' ', sizeof(matrix->display)); | 252 | memset(matrix->display, ' ', sizeof(matrix->display)); |
| 328 | matrix->cursor = &matrix->display[0][0]; | 253 | matrix->cursor = &matrix->display[0][0]; |
| 329 | matrix->dirty = true; | 254 | matrix->dirty = true; |
| @@ -333,7 +258,7 @@ void iota_gfx_clear_screen(void) { | |||
| 333 | matrix_clear(&display); | 258 | matrix_clear(&display); |
| 334 | } | 259 | } |
| 335 | 260 | ||
| 336 | static void matrix_render(struct CharacterMatrix *matrix) { | 261 | void matrix_render(struct CharacterMatrix *matrix) { |
| 337 | last_flush = timer_read(); | 262 | last_flush = timer_read(); |
| 338 | iota_gfx_on(); | 263 | iota_gfx_on(); |
| 339 | #if DEBUG_TO_SCREEN | 264 | #if DEBUG_TO_SCREEN |
| @@ -344,7 +269,7 @@ static void matrix_render(struct CharacterMatrix *matrix) { | |||
| 344 | send_cmd3(PageAddr, 0, MatrixRows - 1); | 269 | send_cmd3(PageAddr, 0, MatrixRows - 1); |
| 345 | send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); | 270 | send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); |
| 346 | 271 | ||
| 347 | if (i2c_start_write(i2cAddress)) { | 272 | if (i2c_start_write(SSD1306_ADDRESS)) { |
| 348 | goto done; | 273 | goto done; |
| 349 | } | 274 | } |
| 350 | if (i2c_master_write(0x40)) { | 275 | if (i2c_master_write(0x40)) { |
| @@ -379,84 +304,13 @@ void iota_gfx_flush(void) { | |||
| 379 | matrix_render(&display); | 304 | matrix_render(&display); |
| 380 | } | 305 | } |
| 381 | 306 | ||
| 382 | static void matrix_update(struct CharacterMatrix *dest, | 307 | __attribute__((weak)) |
| 383 | const struct CharacterMatrix *source) { | 308 | void iota_gfx_task_user(void) { |
| 384 | if (memcmp(dest->display, source->display, sizeof(dest->display))) { | ||
| 385 | memcpy(dest->display, source->display, sizeof(dest->display)); | ||
| 386 | dest->dirty = true; | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | static void render_status_info(void) { | ||
| 391 | #if DEBUG_TO_SCREEN | ||
| 392 | if (debug_enable) { | ||
| 393 | return; | ||
| 394 | } | ||
| 395 | #endif | ||
| 396 | |||
| 397 | struct CharacterMatrix matrix; | ||
| 398 | |||
| 399 | matrix_clear(&matrix); | ||
| 400 | matrix_write_P(&matrix, PSTR("USB: ")); | ||
| 401 | #ifdef PROTOCOL_LUFA | ||
| 402 | switch (USB_DeviceState) { | ||
| 403 | case DEVICE_STATE_Unattached: | ||
| 404 | matrix_write_P(&matrix, PSTR("Unattached")); | ||
| 405 | break; | ||
| 406 | case DEVICE_STATE_Suspended: | ||
| 407 | matrix_write_P(&matrix, PSTR("Suspended")); | ||
| 408 | break; | ||
| 409 | case DEVICE_STATE_Configured: | ||
| 410 | matrix_write_P(&matrix, PSTR("Connected")); | ||
| 411 | break; | ||
| 412 | case DEVICE_STATE_Powered: | ||
| 413 | matrix_write_P(&matrix, PSTR("Powered")); | ||
| 414 | break; | ||
| 415 | case DEVICE_STATE_Default: | ||
| 416 | matrix_write_P(&matrix, PSTR("Default")); | ||
| 417 | break; | ||
| 418 | case DEVICE_STATE_Addressed: | ||
| 419 | matrix_write_P(&matrix, PSTR("Addressed")); | ||
| 420 | break; | ||
| 421 | default: | ||
| 422 | matrix_write_P(&matrix, PSTR("Invalid")); | ||
| 423 | } | ||
| 424 | #endif | ||
| 425 | 309 | ||
| 426 | // Define layers here, Have not worked out how to have text displayed for each layer. Copy down the number you see and add a case for it below | ||
| 427 | |||
| 428 | char buf[40]; | ||
| 429 | snprintf(buf,sizeof(buf), "Undef-%ld", layer_state); | ||
| 430 | matrix_write_P(&matrix, PSTR("\n\nLayer: ")); | ||
| 431 | switch (layer_state) { | ||
| 432 | case _BASE: | ||
| 433 | matrix_write_P(&matrix, PSTR("Default")); | ||
| 434 | break; | ||
| 435 | case _RAISE: | ||
| 436 | matrix_write_P(&matrix, PSTR("Raise")); | ||
| 437 | break; | ||
| 438 | case _LOWER: | ||
| 439 | matrix_write_P(&matrix, PSTR("Lower")); | ||
| 440 | break; | ||
| 441 | case _ADJUST: | ||
| 442 | matrix_write_P(&matrix, PSTR("ADJUST")); | ||
| 443 | break; | ||
| 444 | default: | ||
| 445 | matrix_write(&matrix, buf); | ||
| 446 | } | ||
| 447 | |||
| 448 | // Host Keyboard LED Status | ||
| 449 | char led[40]; | ||
| 450 | snprintf(led, sizeof(led), "\n%s %s %s", | ||
| 451 | (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) ? "NUMLOCK" : " ", | ||
| 452 | (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) ? "CAPS" : " ", | ||
| 453 | (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) ? "SCLK" : " "); | ||
| 454 | matrix_write(&matrix, led); | ||
| 455 | matrix_update(&display, &matrix); | ||
| 456 | } | 310 | } |
| 457 | 311 | ||
| 458 | void iota_gfx_task(void) { | 312 | void iota_gfx_task(void) { |
| 459 | render_status_info(); | 313 | iota_gfx_task_user(); |
| 460 | 314 | ||
| 461 | if (display.dirty) { | 315 | if (display.dirty) { |
| 462 | iota_gfx_flush(); | 316 | iota_gfx_flush(); |
