diff options
Diffstat (limited to 'drivers/oled')
| -rw-r--r-- | drivers/oled/glcdfont.c | 241 | ||||
| -rw-r--r-- | drivers/oled/oled_driver.c | 801 | ||||
| -rw-r--r-- | drivers/oled/oled_driver.h | 206 |
3 files changed, 507 insertions, 741 deletions
diff --git a/drivers/oled/glcdfont.c b/drivers/oled/glcdfont.c index 8b969057e..95c5d2ebf 100644 --- a/drivers/oled/glcdfont.c +++ b/drivers/oled/glcdfont.c | |||
| @@ -1,240 +1,25 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | 2 | ||
| 3 | #ifdef __AVR__ | 3 | #ifdef __AVR__ |
| 4 | #include <avr/io.h> | 4 | # include <avr/io.h> |
| 5 | #include <avr/pgmspace.h> | 5 | # include <avr/pgmspace.h> |
| 6 | #elif defined(ESP8266) | 6 | #elif defined(ESP8266) |
| 7 | #include <pgmspace.h> | 7 | # include <pgmspace.h> |
| 8 | #else | 8 | #else |
| 9 | #define PROGMEM | 9 | # define PROGMEM |
| 10 | #endif | 10 | #endif |
| 11 | 11 | ||
| 12 | // Helidox 8x6 font with QMK Firmware Logo | 12 | // Helidox 8x6 font with QMK Firmware Logo |
| 13 | // Online editor: http://teripom.x0.com/ | 13 | // Online editor: http://teripom.x0.com/ |
| 14 | 14 | ||
| 15 | static const unsigned char font[] PROGMEM = { | 15 | static const unsigned char font[] PROGMEM = { |
| 16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00, 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, 0x00, 0x18, 0x3C, 0x18, 0x00, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x00, 0x18, 0x24, 0x18, 0x00, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00, 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x00, 0x26, 0x29, 0x79, 0x29, 0x26, 0x00, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x00, 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x00, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00, 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00, 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x00, 0x66, 0x89, 0x95, 0x6A, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00, 0x08, 0x04, 0x7E, 0x04, 0x08, 0x00, |
| 17 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00, | 17 | 0x10, 0x20, 0x7E, 0x20, 0x10, 0x00, 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x00, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x00, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x00, 0x30, 0x38, 0x3E, 0x38, 0x30, 0x00, 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x80, 0x70, 0x30, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, |
| 18 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00, | 18 | 0x72, 0x49, 0x49, 0x49, 0x46, 0x00, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00, 0x41, 0x21, 0x11, 0x09, 0x07, 0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, 0x00, 0x02, 0x01, 0x59, 0x09, 0x06, 0x00, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, |
| 19 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00, | 19 | 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x03, 0x07, 0x08, 0x00, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x00, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00, 0x38, 0x44, 0x44, 0x44, 0x28, 0x00, |
| 20 | 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00, | 20 | 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0xFC, 0x18, 0x24, 0x24, 0x18, 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00, 0x48, 0x54, 0x54, 0x54, 0x24, 0x00, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, |
| 21 | 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00, | 21 | 0x00, 0x41, 0x36, 0x08, 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x00, 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0xF0, 0xF8, 0xF8, 0xFF, 0x38, 0xFF, 0xF8, 0xF8, 0x3F, 0xF8, 0xF8, 0xFF, 0x38, 0xFF, 0xF8, 0xF8, 0xF0, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xF8, 0xFC, 0x3E, |
| 22 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, | 22 | 0x1E, 0x06, 0x01, 0x00, 0x00, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x7E, 0x5B, 0x4F, 0x5B, 0xFE, 0xC0, 0x00, 0x00, 0xC0, 0x00, 0xDC, 0xD7, 0xDE, 0xDE, 0xDE, 0xD7, 0xDC, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x49, 0x49, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xDF, 0xBF, 0xBF, 0x00, 0xBF, 0xBF, 0xDF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x60, 0x60, 0xE0, 0xBF, 0x1F, 0x00, 0x7F, 0x7F, 0x07, 0x1E, 0x38, 0x1E, 0x07, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x0E, 0x1F, 0x3B, 0x71, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x0C, 0x0C, 0x0C, 0x00, 0x7E, 0x7E, 0x00, 0x7F, 0x7E, 0x03, 0x03, 0x00, 0x7F, 0x7E, 0x03, 0x03, 0x7E, 0x7E, 0x03, 0x03, 0x7F, 0x7E, 0x00, 0x0F, |
| 23 | 0x00, 0x18, 0x3C, 0x18, 0x00, 0x00, | 23 | 0x3E, 0x70, 0x3C, 0x06, 0x3C, 0x70, 0x3E, 0x0F, 0x00, 0x32, 0x7B, 0x49, 0x49, 0x3F, 0x7E, 0x00, 0x7F, 0x7E, 0x03, 0x03, 0x00, 0x1E, 0x3F, 0x69, 0x69, 0x6F, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x3C, 0x78, 0x70, 0x60, 0x00, 0x00, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00, 0x30, 0x7B, 0x7F, 0x78, 0x30, 0x20, 0x20, 0x30, 0x78, 0x7F, 0x3B, 0x00, 0x03, 0x00, 0x0F, 0x7F, 0x0F, 0x0F, 0x0F, 0x7F, 0x0F, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x07, 0x0F, 0x0F, 0x7F, 0x0F, 0x7F, 0x0F, 0x0F, 0x7E, 0x0F, 0x0F, 0x7F, 0x0F, 0x7F, 0x0F, 0x0F, 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 24 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, | 24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 25 | 0x00, 0x18, 0x24, 0x18, 0x00, 0x00, | ||
| 26 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00, | ||
| 27 | 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x00, | ||
| 28 | 0x26, 0x29, 0x79, 0x29, 0x26, 0x00, | ||
| 29 | 0x40, 0x7F, 0x05, 0x05, 0x07, 0x00, | ||
| 30 | 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x00, | ||
| 31 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00, | ||
| 32 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00, | ||
| 33 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00, | ||
| 34 | 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00, | ||
| 35 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00, | ||
| 36 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, | ||
| 37 | 0x00, 0x66, 0x89, 0x95, 0x6A, 0x00, | ||
| 38 | 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, | ||
| 39 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00, | ||
| 40 | 0x08, 0x04, 0x7E, 0x04, 0x08, 0x00, | ||
| 41 | 0x10, 0x20, 0x7E, 0x20, 0x10, 0x00, | ||
| 42 | 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00, | ||
| 43 | 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x00, | ||
| 44 | 0x1E, 0x10, 0x10, 0x10, 0x10, 0x00, | ||
| 45 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x00, | ||
| 46 | 0x30, 0x38, 0x3E, 0x38, 0x30, 0x00, | ||
| 47 | 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, | ||
| 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 49 | 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, | ||
| 50 | 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, | ||
| 51 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, | ||
| 52 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, | ||
| 53 | 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, | ||
| 54 | 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, | ||
| 55 | 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, | ||
| 56 | 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, | ||
| 57 | 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, | ||
| 58 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00, | ||
| 59 | 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, | ||
| 60 | 0x00, 0x80, 0x70, 0x30, 0x00, 0x00, | ||
| 61 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, | ||
| 62 | 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, | ||
| 63 | 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, | ||
| 64 | 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, | ||
| 65 | 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, | ||
| 66 | 0x72, 0x49, 0x49, 0x49, 0x46, 0x00, | ||
| 67 | 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00, | ||
| 68 | 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, | ||
| 69 | 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, | ||
| 70 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00, | ||
| 71 | 0x41, 0x21, 0x11, 0x09, 0x07, 0x00, | ||
| 72 | 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, | ||
| 73 | 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, | ||
| 74 | 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, | ||
| 75 | 0x00, 0x40, 0x34, 0x00, 0x00, 0x00, | ||
| 76 | 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, | ||
| 77 | 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, | ||
| 78 | 0x00, 0x41, 0x22, 0x14, 0x08, 0x00, | ||
| 79 | 0x02, 0x01, 0x59, 0x09, 0x06, 0x00, | ||
| 80 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00, | ||
| 81 | 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00, | ||
| 82 | 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, | ||
| 83 | 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, | ||
| 84 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00, | ||
| 85 | 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, | ||
| 86 | 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, | ||
| 87 | 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00, | ||
| 88 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, | ||
| 89 | 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, | ||
| 90 | 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, | ||
| 91 | 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, | ||
| 92 | 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, | ||
| 93 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00, | ||
| 94 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, | ||
| 95 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, | ||
| 96 | 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, | ||
| 97 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, | ||
| 98 | 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, | ||
| 99 | 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, | ||
| 100 | 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00, | ||
| 101 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, | ||
| 102 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, | ||
| 103 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, | ||
| 104 | 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, | ||
| 105 | 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, | ||
| 106 | 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, | ||
| 107 | 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00, | ||
| 108 | 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, | ||
| 109 | 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00, | ||
| 110 | 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, | ||
| 111 | 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, | ||
| 112 | 0x00, 0x03, 0x07, 0x08, 0x00, 0x00, | ||
| 113 | 0x20, 0x54, 0x54, 0x78, 0x40, 0x00, | ||
| 114 | 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00, | ||
| 115 | 0x38, 0x44, 0x44, 0x44, 0x28, 0x00, | ||
| 116 | 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00, | ||
| 117 | 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, | ||
| 118 | 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, | ||
| 119 | 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00, | ||
| 120 | 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, | ||
| 121 | 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00, | ||
| 122 | 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00, | ||
| 123 | 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, | ||
| 124 | 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, | ||
| 125 | 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00, | ||
| 126 | 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00, | ||
| 127 | 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, | ||
| 128 | 0xFC, 0x18, 0x24, 0x24, 0x18, 0x00, | ||
| 129 | 0x18, 0x24, 0x24, 0x18, 0xFC, 0x00, | ||
| 130 | 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00, | ||
| 131 | 0x48, 0x54, 0x54, 0x54, 0x24, 0x00, | ||
| 132 | 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00, | ||
| 133 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00, | ||
| 134 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, | ||
| 135 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, | ||
| 136 | 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, | ||
| 137 | 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00, | ||
| 138 | 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, | ||
| 139 | 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, | ||
| 140 | 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, | ||
| 141 | 0x00, 0x41, 0x36, 0x08, 0x00, 0x00, | ||
| 142 | 0x02, 0x01, 0x02, 0x04, 0x02, 0x00, | ||
| 143 | 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00, | ||
| 144 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 145 | 0x40, 0x40, 0x40, 0xF0, 0xF8, 0xF8, | ||
| 146 | 0xFF, 0x38, 0xFF, 0xF8, 0xF8, 0x3F, | ||
| 147 | 0xF8, 0xF8, 0xFF, 0x38, 0xFF, 0xF8, | ||
| 148 | 0xF8, 0xF0, 0x40, 0x40, 0x40, 0x00, | ||
| 149 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | ||
| 150 | 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x00, | ||
| 151 | 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, | ||
| 152 | 0x80, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, | ||
| 153 | 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x00, | ||
| 154 | 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, | ||
| 155 | 0xC0, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, | ||
| 156 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 157 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 158 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 159 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 160 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 161 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 162 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 163 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 164 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 165 | 0x00, 0xC0, 0xF0, 0xF8, 0xFC, 0x3E, | ||
| 166 | 0x1E, 0x06, 0x01, 0x00, 0x00, 0x00, | ||
| 167 | 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00, | ||
| 168 | 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00, | ||
| 169 | 0x00, 0x80, 0xC0, 0xE0, 0x7E, 0x5B, | ||
| 170 | 0x4F, 0x5B, 0xFE, 0xC0, 0x00, 0x00, | ||
| 171 | 0xC0, 0x00, 0xDC, 0xD7, 0xDE, 0xDE, | ||
| 172 | 0xDE, 0xD7, 0xDC, 0x00, 0xC0, 0x00, | ||
| 173 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 174 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 175 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 176 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 177 | 0x49, 0x49, 0x49, 0xFF, 0xFF, 0xFF, | ||
| 178 | 0xFF, 0xE0, 0xDF, 0xBF, 0xBF, 0x00, | ||
| 179 | 0xBF, 0xBF, 0xDF, 0xE0, 0xFF, 0xFF, | ||
| 180 | 0xFF, 0xFF, 0x49, 0x49, 0x49, 0x00, | ||
| 181 | 0x00, 0x00, 0x00, 0x00, 0x1F, 0x3F, | ||
| 182 | 0x60, 0x60, 0xE0, 0xBF, 0x1F, 0x00, | ||
| 183 | 0x7F, 0x7F, 0x07, 0x1E, 0x38, 0x1E, | ||
| 184 | 0x07, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, | ||
| 185 | 0x0E, 0x1F, 0x3B, 0x71, 0x60, 0x00, | ||
| 186 | 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, | ||
| 187 | 0x0C, 0x0C, 0x0C, 0x00, 0x7E, 0x7E, | ||
| 188 | 0x00, 0x7F, 0x7E, 0x03, 0x03, 0x00, | ||
| 189 | 0x7F, 0x7E, 0x03, 0x03, 0x7E, 0x7E, | ||
| 190 | 0x03, 0x03, 0x7F, 0x7E, 0x00, 0x0F, | ||
| 191 | 0x3E, 0x70, 0x3C, 0x06, 0x3C, 0x70, | ||
| 192 | 0x3E, 0x0F, 0x00, 0x32, 0x7B, 0x49, | ||
| 193 | 0x49, 0x3F, 0x7E, 0x00, 0x7F, 0x7E, | ||
| 194 | 0x03, 0x03, 0x00, 0x1E, 0x3F, 0x69, | ||
| 195 | 0x69, 0x6F, 0x26, 0x00, 0x00, 0x00, | ||
| 196 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 197 | 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x3C, | ||
| 198 | 0x78, 0x70, 0x60, 0x00, 0x00, 0x00, | ||
| 199 | 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00, | ||
| 200 | 0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00, | ||
| 201 | 0x30, 0x7B, 0x7F, 0x78, 0x30, 0x20, | ||
| 202 | 0x20, 0x30, 0x78, 0x7F, 0x3B, 0x00, | ||
| 203 | 0x03, 0x00, 0x0F, 0x7F, 0x0F, 0x0F, | ||
| 204 | 0x0F, 0x7F, 0x0F, 0x00, 0x03, 0x00, | ||
| 205 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 206 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 207 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 208 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 209 | 0x01, 0x01, 0x01, 0x07, 0x0F, 0x0F, | ||
| 210 | 0x7F, 0x0F, 0x7F, 0x0F, 0x0F, 0x7E, | ||
| 211 | 0x0F, 0x0F, 0x7F, 0x0F, 0x7F, 0x0F, | ||
| 212 | 0x0F, 0x07, 0x01, 0x01, 0x01, 0x00, | ||
| 213 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 214 | 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, | ||
| 215 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 216 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 217 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 218 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 219 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 220 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 221 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 222 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 223 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 224 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 225 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 226 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 227 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 228 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 229 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 230 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 231 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 233 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 234 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 235 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 236 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 237 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 238 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 240 | }; | 25 | }; |
diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c index 3dad72add..1a1b7299b 100644 --- a/drivers/oled/oled_driver.c +++ b/drivers/oled/oled_driver.c | |||
| @@ -23,64 +23,64 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 23 | #include <string.h> | 23 | #include <string.h> |
| 24 | 24 | ||
| 25 | #if defined(__AVR__) | 25 | #if defined(__AVR__) |
| 26 | #include <avr/io.h> | 26 | # include <avr/io.h> |
| 27 | #include <avr/pgmspace.h> | 27 | # include <avr/pgmspace.h> |
| 28 | #elif defined(ESP8266) | 28 | #elif defined(ESP8266) |
| 29 | #include <pgmspace.h> | 29 | # include <pgmspace.h> |
| 30 | #else // defined(ESP8266) | 30 | #else // defined(ESP8266) |
| 31 | #define PROGMEM | 31 | # define PROGMEM |
| 32 | #define memcpy_P(des, src, len) memcpy(des, src, len) | 32 | # define memcpy_P(des, src, len) memcpy(des, src, len) |
| 33 | #endif // defined(__AVR__) | 33 | #endif // defined(__AVR__) |
| 34 | 34 | ||
| 35 | // Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf | 35 | // Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf |
| 36 | // for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf | 36 | // for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf |
| 37 | 37 | ||
| 38 | // Fundamental Commands | 38 | // Fundamental Commands |
| 39 | #define CONTRAST 0x81 | 39 | #define CONTRAST 0x81 |
| 40 | #define DISPLAY_ALL_ON 0xA5 | 40 | #define DISPLAY_ALL_ON 0xA5 |
| 41 | #define DISPLAY_ALL_ON_RESUME 0xA4 | 41 | #define DISPLAY_ALL_ON_RESUME 0xA4 |
| 42 | #define NORMAL_DISPLAY 0xA6 | 42 | #define NORMAL_DISPLAY 0xA6 |
| 43 | #define DISPLAY_ON 0xAF | 43 | #define DISPLAY_ON 0xAF |
| 44 | #define DISPLAY_OFF 0xAE | 44 | #define DISPLAY_OFF 0xAE |
| 45 | #define NOP 0xE3 | 45 | #define NOP 0xE3 |
| 46 | 46 | ||
| 47 | // Scrolling Commands | 47 | // Scrolling Commands |
| 48 | #define ACTIVATE_SCROLL 0x2F | 48 | #define ACTIVATE_SCROLL 0x2F |
| 49 | #define DEACTIVATE_SCROLL 0x2E | 49 | #define DEACTIVATE_SCROLL 0x2E |
| 50 | #define SCROLL_RIGHT 0x26 | 50 | #define SCROLL_RIGHT 0x26 |
| 51 | #define SCROLL_LEFT 0x27 | 51 | #define SCROLL_LEFT 0x27 |
| 52 | #define SCROLL_RIGHT_UP 0x29 | 52 | #define SCROLL_RIGHT_UP 0x29 |
| 53 | #define SCROLL_LEFT_UP 0x2A | 53 | #define SCROLL_LEFT_UP 0x2A |
| 54 | 54 | ||
| 55 | // Addressing Setting Commands | 55 | // Addressing Setting Commands |
| 56 | #define MEMORY_MODE 0x20 | 56 | #define MEMORY_MODE 0x20 |
| 57 | #define COLUMN_ADDR 0x21 | 57 | #define COLUMN_ADDR 0x21 |
| 58 | #define PAGE_ADDR 0x22 | 58 | #define PAGE_ADDR 0x22 |
| 59 | #define PAM_SETCOLUMN_LSB 0x00 | 59 | #define PAM_SETCOLUMN_LSB 0x00 |
| 60 | #define PAM_SETCOLUMN_MSB 0x10 | 60 | #define PAM_SETCOLUMN_MSB 0x10 |
| 61 | #define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7 | 61 | #define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7 |
| 62 | 62 | ||
| 63 | // Hardware Configuration Commands | 63 | // Hardware Configuration Commands |
| 64 | #define DISPLAY_START_LINE 0x40 | 64 | #define DISPLAY_START_LINE 0x40 |
| 65 | #define SEGMENT_REMAP 0xA0 | 65 | #define SEGMENT_REMAP 0xA0 |
| 66 | #define SEGMENT_REMAP_INV 0xA1 | 66 | #define SEGMENT_REMAP_INV 0xA1 |
| 67 | #define MULTIPLEX_RATIO 0xA8 | 67 | #define MULTIPLEX_RATIO 0xA8 |
| 68 | #define COM_SCAN_INC 0xC0 | 68 | #define COM_SCAN_INC 0xC0 |
| 69 | #define COM_SCAN_DEC 0xC8 | 69 | #define COM_SCAN_DEC 0xC8 |
| 70 | #define DISPLAY_OFFSET 0xD3 | 70 | #define DISPLAY_OFFSET 0xD3 |
| 71 | #define COM_PINS 0xDA | 71 | #define COM_PINS 0xDA |
| 72 | #define COM_PINS_SEQ 0x02 | 72 | #define COM_PINS_SEQ 0x02 |
| 73 | #define COM_PINS_ALT 0x12 | 73 | #define COM_PINS_ALT 0x12 |
| 74 | #define COM_PINS_SEQ_LR 0x22 | 74 | #define COM_PINS_SEQ_LR 0x22 |
| 75 | #define COM_PINS_ALT_LR 0x32 | 75 | #define COM_PINS_ALT_LR 0x32 |
| 76 | 76 | ||
| 77 | // Timing & Driving Commands | 77 | // Timing & Driving Commands |
| 78 | #define DISPLAY_CLOCK 0xD5 | 78 | #define DISPLAY_CLOCK 0xD5 |
| 79 | #define PRE_CHARGE_PERIOD 0xD9 | 79 | #define PRE_CHARGE_PERIOD 0xD9 |
| 80 | #define VCOM_DETECT 0xDB | 80 | #define VCOM_DETECT 0xDB |
| 81 | 81 | ||
| 82 | // Charge Pump Commands | 82 | // Charge Pump Commands |
| 83 | #define CHARGE_PUMP 0x8D | 83 | #define CHARGE_PUMP 0x8D |
| 84 | 84 | ||
| 85 | // Misc defines | 85 | // Misc defines |
| 86 | #define OLED_TIMEOUT 60000 | 86 | #define OLED_TIMEOUT 60000 |
| @@ -91,12 +91,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 91 | #define I2C_CMD 0x00 | 91 | #define I2C_CMD 0x00 |
| 92 | #define I2C_DATA 0x40 | 92 | #define I2C_DATA 0x40 |
| 93 | #if defined(__AVR__) | 93 | #if defined(__AVR__) |
| 94 | // already defined on ARM | 94 | // already defined on ARM |
| 95 | #define I2C_TIMEOUT 100 | 95 | # define I2C_TIMEOUT 100 |
| 96 | #define I2C_TRANSMIT_P(data) i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), I2C_TIMEOUT) | 96 | # define I2C_TRANSMIT_P(data) i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), I2C_TIMEOUT) |
| 97 | #else // defined(__AVR__) | 97 | #else // defined(__AVR__) |
| 98 | #define I2C_TRANSMIT_P(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), I2C_TIMEOUT) | 98 | # define I2C_TRANSMIT_P(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), I2C_TIMEOUT) |
| 99 | #endif // defined(__AVR__) | 99 | #endif // defined(__AVR__) |
| 100 | #define I2C_TRANSMIT(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), I2C_TIMEOUT) | 100 | #define I2C_TRANSMIT(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), I2C_TIMEOUT) |
| 101 | #define I2C_WRITE_REG(mode, data, size) i2c_writeReg((OLED_DISPLAY_ADDRESS << 1), mode, data, size, I2C_TIMEOUT) | 101 | #define I2C_WRITE_REG(mode, data, size) i2c_writeReg((OLED_DISPLAY_ADDRESS << 1), mode, data, size, I2C_TIMEOUT) |
| 102 | 102 | ||
| @@ -106,19 +106,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 106 | // this is so we don't end up with rounding errors with | 106 | // this is so we don't end up with rounding errors with |
| 107 | // parts of the display unusable or don't get cleared correctly | 107 | // parts of the display unusable or don't get cleared correctly |
| 108 | // and also allows for drawing & inverting | 108 | // and also allows for drawing & inverting |
| 109 | uint8_t oled_buffer[OLED_MATRIX_SIZE]; | 109 | uint8_t oled_buffer[OLED_MATRIX_SIZE]; |
| 110 | uint8_t* oled_cursor; | 110 | uint8_t * oled_cursor; |
| 111 | OLED_BLOCK_TYPE oled_dirty = 0; | 111 | OLED_BLOCK_TYPE oled_dirty = 0; |
| 112 | bool oled_initialized = false; | 112 | bool oled_initialized = false; |
| 113 | bool oled_active = false; | 113 | bool oled_active = false; |
| 114 | bool oled_scrolling = false; | 114 | bool oled_scrolling = false; |
| 115 | uint8_t oled_rotation = 0; | 115 | uint8_t oled_rotation = 0; |
| 116 | uint8_t oled_rotation_width = 0; | 116 | uint8_t oled_rotation_width = 0; |
| 117 | #if OLED_TIMEOUT > 0 | 117 | #if OLED_TIMEOUT > 0 |
| 118 | uint32_t oled_timeout; | 118 | uint32_t oled_timeout; |
| 119 | #endif | 119 | #endif |
| 120 | #if OLED_SCROLL_TIMEOUT > 0 | 120 | #if OLED_SCROLL_TIMEOUT > 0 |
| 121 | uint32_t oled_scroll_timeout; | 121 | uint32_t oled_scroll_timeout; |
| 122 | #endif | 122 | #endif |
| 123 | 123 | ||
| 124 | // Internal variables to reduce math instructions | 124 | // Internal variables to reduce math instructions |
| @@ -126,468 +126,445 @@ uint8_t oled_rotation_width = 0; | |||
| 126 | #if defined(__AVR__) | 126 | #if defined(__AVR__) |
| 127 | // identical to i2c_transmit, but for PROGMEM since all initialization is in PROGMEM arrays currently | 127 | // identical to i2c_transmit, but for PROGMEM since all initialization is in PROGMEM arrays currently |
| 128 | // probably should move this into i2c_master... | 128 | // probably should move this into i2c_master... |
| 129 | static i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { | 129 | static i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout) { |
| 130 | i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); | 130 | i2c_status_t status = i2c_start(address | I2C_WRITE, timeout); |
| 131 | 131 | ||
| 132 | for (uint16_t i = 0; i < length && status >= 0; i++) { | 132 | for (uint16_t i = 0; i < length && status >= 0; i++) { |
| 133 | status = i2c_write(pgm_read_byte((const char*)data++), timeout); | 133 | status = i2c_write(pgm_read_byte((const char *)data++), timeout); |
| 134 | if (status) break; | 134 | if (status) break; |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | i2c_stop(); | 137 | i2c_stop(); |
| 138 | 138 | ||
| 139 | return status; | 139 | return status; |
| 140 | } | 140 | } |
| 141 | #endif | 141 | #endif |
| 142 | 142 | ||
| 143 | // Flips the rendering bits for a character at the current cursor position | 143 | // Flips the rendering bits for a character at the current cursor position |
| 144 | static void InvertCharacter(uint8_t *cursor) | 144 | static void InvertCharacter(uint8_t *cursor) { |
| 145 | { | 145 | const uint8_t *end = cursor + OLED_FONT_WIDTH; |
| 146 | const uint8_t *end = cursor + OLED_FONT_WIDTH; | 146 | while (cursor < end) { |
| 147 | while (cursor < end) { | 147 | *cursor = ~(*cursor); |
| 148 | *cursor = ~(*cursor); | 148 | cursor++; |
| 149 | cursor++; | 149 | } |
| 150 | } | ||
| 151 | } | 150 | } |
| 152 | 151 | ||
| 153 | bool oled_init(uint8_t rotation) { | 152 | bool oled_init(uint8_t rotation) { |
| 154 | oled_rotation = oled_init_user(rotation); | 153 | oled_rotation = oled_init_user(rotation); |
| 155 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { | 154 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { |
| 156 | oled_rotation_width = OLED_DISPLAY_WIDTH; | 155 | oled_rotation_width = OLED_DISPLAY_WIDTH; |
| 157 | } else { | 156 | } else { |
| 158 | oled_rotation_width = OLED_DISPLAY_HEIGHT; | 157 | oled_rotation_width = OLED_DISPLAY_HEIGHT; |
| 159 | } | 158 | } |
| 160 | i2c_init(); | 159 | i2c_init(); |
| 161 | 160 | ||
| 162 | static const uint8_t PROGMEM display_setup1[] = { | 161 | static const uint8_t PROGMEM display_setup1[] = { |
| 163 | I2C_CMD, | 162 | I2C_CMD, |
| 164 | DISPLAY_OFF, | 163 | DISPLAY_OFF, |
| 165 | DISPLAY_CLOCK, 0x80, | 164 | DISPLAY_CLOCK, |
| 166 | MULTIPLEX_RATIO, OLED_DISPLAY_HEIGHT - 1, | 165 | 0x80, |
| 167 | DISPLAY_OFFSET, 0x00, | 166 | MULTIPLEX_RATIO, |
| 168 | DISPLAY_START_LINE | 0x00, | 167 | OLED_DISPLAY_HEIGHT - 1, |
| 169 | CHARGE_PUMP, 0x14, | 168 | DISPLAY_OFFSET, |
| 169 | 0x00, | ||
| 170 | DISPLAY_START_LINE | 0x00, | ||
| 171 | CHARGE_PUMP, | ||
| 172 | 0x14, | ||
| 170 | #if (OLED_IC != OLED_IC_SH1106) | 173 | #if (OLED_IC != OLED_IC_SH1106) |
| 171 | // MEMORY_MODE is unsupported on SH1106 (Page Addressing only) | 174 | // MEMORY_MODE is unsupported on SH1106 (Page Addressing only) |
| 172 | MEMORY_MODE, 0x00, // Horizontal addressing mode | 175 | MEMORY_MODE, |
| 176 | 0x00, // Horizontal addressing mode | ||
| 173 | #endif | 177 | #endif |
| 174 | }; | 178 | }; |
| 175 | if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) { | 179 | if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) { |
| 176 | print("oled_init cmd set 1 failed\n"); | 180 | print("oled_init cmd set 1 failed\n"); |
| 177 | return false; | 181 | return false; |
| 178 | } | 182 | } |
| 179 | 183 | ||
| 180 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_180)) { | 184 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_180)) { |
| 181 | static const uint8_t PROGMEM display_normal[] = { | 185 | static const uint8_t PROGMEM display_normal[] = {I2C_CMD, SEGMENT_REMAP_INV, COM_SCAN_DEC}; |
| 182 | I2C_CMD, | 186 | if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) { |
| 183 | SEGMENT_REMAP_INV, | 187 | print("oled_init cmd normal rotation failed\n"); |
| 184 | COM_SCAN_DEC }; | 188 | return false; |
| 185 | if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) { | 189 | } |
| 186 | print("oled_init cmd normal rotation failed\n"); | 190 | } else { |
| 187 | return false; | 191 | static const uint8_t PROGMEM display_flipped[] = {I2C_CMD, SEGMENT_REMAP, COM_SCAN_INC}; |
| 188 | } | 192 | if (I2C_TRANSMIT_P(display_flipped) != I2C_STATUS_SUCCESS) { |
| 189 | } else { | 193 | print("display_flipped failed\n"); |
| 190 | static const uint8_t PROGMEM display_flipped[] = { | 194 | return false; |
| 191 | I2C_CMD, | 195 | } |
| 192 | SEGMENT_REMAP, | 196 | } |
| 193 | COM_SCAN_INC }; | 197 | |
| 194 | if (I2C_TRANSMIT_P(display_flipped) != I2C_STATUS_SUCCESS) { | 198 | static const uint8_t PROGMEM display_setup2[] = {I2C_CMD, COM_PINS, OLED_COM_PINS, CONTRAST, 0x8F, PRE_CHARGE_PERIOD, 0xF1, VCOM_DETECT, 0x40, DISPLAY_ALL_ON_RESUME, NORMAL_DISPLAY, DEACTIVATE_SCROLL, DISPLAY_ON}; |
| 195 | print("display_flipped failed\n"); | 199 | if (I2C_TRANSMIT_P(display_setup2) != I2C_STATUS_SUCCESS) { |
| 196 | return false; | 200 | print("display_setup2 failed\n"); |
| 197 | } | 201 | return false; |
| 198 | } | 202 | } |
| 199 | |||
| 200 | static const uint8_t PROGMEM display_setup2[] = { | ||
| 201 | I2C_CMD, | ||
| 202 | COM_PINS, OLED_COM_PINS, | ||
| 203 | CONTRAST, 0x8F, | ||
| 204 | PRE_CHARGE_PERIOD, 0xF1, | ||
| 205 | VCOM_DETECT, 0x40, | ||
| 206 | DISPLAY_ALL_ON_RESUME, | ||
| 207 | NORMAL_DISPLAY, | ||
| 208 | DEACTIVATE_SCROLL, | ||
| 209 | DISPLAY_ON }; | ||
| 210 | if (I2C_TRANSMIT_P(display_setup2) != I2C_STATUS_SUCCESS) { | ||
| 211 | print("display_setup2 failed\n"); | ||
| 212 | return false; | ||
| 213 | } | ||
| 214 | 203 | ||
| 215 | #if OLED_TIMEOUT > 0 | 204 | #if OLED_TIMEOUT > 0 |
| 216 | oled_timeout = timer_read32() + OLED_TIMEOUT; | 205 | oled_timeout = timer_read32() + OLED_TIMEOUT; |
| 217 | #endif | 206 | #endif |
| 218 | #if OLED_SCROLL_TIMEOUT > 0 | 207 | #if OLED_SCROLL_TIMEOUT > 0 |
| 219 | oled_scroll_timeout = timer_read32() + OLED_SCROLL_TIMEOUT; | 208 | oled_scroll_timeout = timer_read32() + OLED_SCROLL_TIMEOUT; |
| 220 | #endif | 209 | #endif |
| 221 | 210 | ||
| 222 | oled_clear(); | 211 | oled_clear(); |
| 223 | oled_initialized = true; | 212 | oled_initialized = true; |
| 224 | oled_active = true; | 213 | oled_active = true; |
| 225 | oled_scrolling = false; | 214 | oled_scrolling = false; |
| 226 | return true; | 215 | return true; |
| 227 | } | 216 | } |
| 228 | 217 | ||
| 229 | __attribute__((weak)) | 218 | __attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) { return rotation; } |
| 230 | oled_rotation_t oled_init_user(oled_rotation_t rotation) { | ||
| 231 | return rotation; | ||
| 232 | } | ||
| 233 | 219 | ||
| 234 | void oled_clear(void) { | 220 | void oled_clear(void) { |
| 235 | memset(oled_buffer, 0, sizeof(oled_buffer)); | 221 | memset(oled_buffer, 0, sizeof(oled_buffer)); |
| 236 | oled_cursor = &oled_buffer[0]; | 222 | oled_cursor = &oled_buffer[0]; |
| 237 | oled_dirty = -1; // -1 will be max value as long as display_dirty is unsigned type | 223 | oled_dirty = -1; // -1 will be max value as long as display_dirty is unsigned type |
| 238 | } | 224 | } |
| 239 | 225 | ||
| 240 | static void calc_bounds(uint8_t update_start, uint8_t* cmd_array) | 226 | static void calc_bounds(uint8_t update_start, uint8_t *cmd_array) { |
| 241 | { | 227 | // Calculate commands to set memory addressing bounds. |
| 242 | // Calculate commands to set memory addressing bounds. | 228 | uint8_t start_page = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH; |
| 243 | uint8_t start_page = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH; | 229 | uint8_t start_column = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH; |
| 244 | uint8_t start_column = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH; | ||
| 245 | #if (OLED_IC == OLED_IC_SH1106) | 230 | #if (OLED_IC == OLED_IC_SH1106) |
| 246 | // Commands for Page Addressing Mode. Sets starting page and column; has no end bound. | 231 | // Commands for Page Addressing Mode. Sets starting page and column; has no end bound. |
| 247 | // Column value must be split into high and low nybble and sent as two commands. | 232 | // Column value must be split into high and low nybble and sent as two commands. |
| 248 | cmd_array[0] = PAM_PAGE_ADDR | start_page; | 233 | cmd_array[0] = PAM_PAGE_ADDR | start_page; |
| 249 | cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f); | 234 | cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f); |
| 250 | cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f); | 235 | cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f); |
| 251 | cmd_array[3] = NOP; | 236 | cmd_array[3] = NOP; |
| 252 | cmd_array[4] = NOP; | 237 | cmd_array[4] = NOP; |
| 253 | cmd_array[5] = NOP; | 238 | cmd_array[5] = NOP; |
| 254 | #else | 239 | #else |
| 255 | // Commands for use in Horizontal Addressing mode. | 240 | // Commands for use in Horizontal Addressing mode. |
| 256 | cmd_array[1] = start_column; | 241 | cmd_array[1] = start_column; |
| 257 | cmd_array[4] = start_page; | 242 | cmd_array[4] = start_page; |
| 258 | cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) % OLED_DISPLAY_WIDTH + cmd_array[1]; | 243 | cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) % OLED_DISPLAY_WIDTH + cmd_array[1]; |
| 259 | cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) / OLED_DISPLAY_WIDTH - 1; | 244 | cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) / OLED_DISPLAY_WIDTH - 1; |
| 260 | #endif | 245 | #endif |
| 261 | } | 246 | } |
| 262 | 247 | ||
| 263 | static void calc_bounds_90(uint8_t update_start, uint8_t* cmd_array) | 248 | static void calc_bounds_90(uint8_t update_start, uint8_t *cmd_array) { |
| 264 | { | 249 | cmd_array[1] = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_HEIGHT * 8; |
| 265 | cmd_array[1] = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_HEIGHT * 8; | 250 | cmd_array[4] = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_HEIGHT; |
| 266 | cmd_array[4] = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_HEIGHT; | 251 | cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) / OLED_DISPLAY_HEIGHT * 8 - 1 + cmd_array[1]; |
| 267 | cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) / OLED_DISPLAY_HEIGHT * 8 - 1 + cmd_array[1];; | 252 | ; |
| 268 | cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) % OLED_DISPLAY_HEIGHT / 8; | 253 | cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) % OLED_DISPLAY_HEIGHT / 8; |
| 269 | } | 254 | } |
| 270 | 255 | ||
| 271 | uint8_t crot(uint8_t a, int8_t n) | 256 | uint8_t crot(uint8_t a, int8_t n) { |
| 272 | { | 257 | const uint8_t mask = 0x7; |
| 273 | const uint8_t mask = 0x7; | 258 | n &= mask; |
| 274 | n &= mask; | 259 | return a << n | a >> (-n & mask); |
| 275 | return a << n | a >> (-n & mask); | ||
| 276 | } | 260 | } |
| 277 | 261 | ||
| 278 | static void rotate_90(const uint8_t* src, uint8_t* dest) | 262 | static void rotate_90(const uint8_t *src, uint8_t *dest) { |
| 279 | { | 263 | for (uint8_t i = 0, shift = 7; i < 8; ++i, --shift) { |
| 280 | for (uint8_t i = 0, shift = 7; i < 8; ++i, --shift) { | 264 | uint8_t selector = (1 << i); |
| 281 | uint8_t selector = (1 << i); | 265 | for (uint8_t j = 0; j < 8; ++j) { |
| 282 | for (uint8_t j = 0; j < 8; ++j) { | 266 | dest[i] |= crot(src[j] & selector, shift - (int8_t)j); |
| 283 | dest[i] |= crot(src[j] & selector, shift - (int8_t)j); | 267 | } |
| 284 | } | 268 | } |
| 285 | } | ||
| 286 | } | 269 | } |
| 287 | 270 | ||
| 288 | void oled_render(void) { | 271 | void oled_render(void) { |
| 289 | // Do we have work to do? | 272 | // Do we have work to do? |
| 290 | if (!oled_dirty || oled_scrolling) { | 273 | if (!oled_dirty || oled_scrolling) { |
| 291 | return; | 274 | return; |
| 292 | } | 275 | } |
| 293 | 276 | ||
| 294 | // Find first dirty block | 277 | // Find first dirty block |
| 295 | uint8_t update_start = 0; | 278 | uint8_t update_start = 0; |
| 296 | while (!(oled_dirty & (1 << update_start))) { ++update_start; } | 279 | while (!(oled_dirty & (1 << update_start))) { |
| 297 | 280 | ++update_start; | |
| 298 | // Set column & page position | 281 | } |
| 299 | static uint8_t display_start[] = { | 282 | |
| 300 | I2C_CMD, | 283 | // Set column & page position |
| 301 | COLUMN_ADDR, 0, OLED_DISPLAY_WIDTH - 1, | 284 | static uint8_t display_start[] = {I2C_CMD, COLUMN_ADDR, 0, OLED_DISPLAY_WIDTH - 1, PAGE_ADDR, 0, OLED_DISPLAY_HEIGHT / 8 - 1}; |
| 302 | PAGE_ADDR, 0, OLED_DISPLAY_HEIGHT / 8 - 1 }; | 285 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { |
| 303 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { | 286 | calc_bounds(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start |
| 304 | calc_bounds(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start | 287 | } else { |
| 305 | } else { | 288 | calc_bounds_90(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start |
| 306 | calc_bounds_90(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start | 289 | } |
| 307 | } | 290 | |
| 308 | 291 | // Send column & page position | |
| 309 | // Send column & page position | 292 | if (I2C_TRANSMIT(display_start) != I2C_STATUS_SUCCESS) { |
| 310 | if (I2C_TRANSMIT(display_start) != I2C_STATUS_SUCCESS) { | 293 | print("oled_render offset command failed\n"); |
| 311 | print("oled_render offset command failed\n"); | 294 | return; |
| 312 | return; | 295 | } |
| 313 | } | 296 | |
| 314 | 297 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { | |
| 315 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { | 298 | // Send render data chunk as is |
| 316 | // Send render data chunk as is | 299 | if (I2C_WRITE_REG(I2C_DATA, &oled_buffer[OLED_BLOCK_SIZE * update_start], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { |
| 317 | if (I2C_WRITE_REG(I2C_DATA, &oled_buffer[OLED_BLOCK_SIZE * update_start], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { | 300 | print("oled_render data failed\n"); |
| 318 | print("oled_render data failed\n"); | 301 | return; |
| 319 | return; | 302 | } |
| 320 | } | 303 | } else { |
| 321 | } else { | 304 | // Rotate the render chunks |
| 322 | // Rotate the render chunks | 305 | const static uint8_t source_map[] = OLED_SOURCE_MAP; |
| 323 | const static uint8_t source_map[] = OLED_SOURCE_MAP; | 306 | const static uint8_t target_map[] = OLED_TARGET_MAP; |
| 324 | const static uint8_t target_map[] = OLED_TARGET_MAP; | 307 | |
| 325 | 308 | static uint8_t temp_buffer[OLED_BLOCK_SIZE]; | |
| 326 | static uint8_t temp_buffer[OLED_BLOCK_SIZE]; | 309 | memset(temp_buffer, 0, sizeof(temp_buffer)); |
| 327 | memset(temp_buffer, 0, sizeof(temp_buffer)); | 310 | for (uint8_t i = 0; i < sizeof(source_map); ++i) { |
| 328 | for(uint8_t i = 0; i < sizeof(source_map); ++i) { | 311 | rotate_90(&oled_buffer[OLED_BLOCK_SIZE * update_start + source_map[i]], &temp_buffer[target_map[i]]); |
| 329 | rotate_90(&oled_buffer[OLED_BLOCK_SIZE * update_start + source_map[i]], &temp_buffer[target_map[i]]); | 312 | } |
| 330 | } | 313 | |
| 331 | 314 | // Send render data chunk after rotating | |
| 332 | // Send render data chunk after rotating | 315 | if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[0], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { |
| 333 | if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[0], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) { | 316 | print("oled_render90 data failed\n"); |
| 334 | print("oled_render90 data failed\n"); | 317 | return; |
| 335 | return; | 318 | } |
| 336 | } | 319 | } |
| 337 | } | 320 | |
| 338 | 321 | // Turn on display if it is off | |
| 339 | // Turn on display if it is off | 322 | oled_on(); |
| 340 | oled_on(); | 323 | |
| 341 | 324 | // Clear dirty flag | |
| 342 | // Clear dirty flag | 325 | oled_dirty &= ~(1 << update_start); |
| 343 | oled_dirty &= ~(1 << update_start); | ||
| 344 | } | 326 | } |
| 345 | 327 | ||
| 346 | void oled_set_cursor(uint8_t col, uint8_t line) { | 328 | void oled_set_cursor(uint8_t col, uint8_t line) { |
| 347 | uint16_t index = line * oled_rotation_width + col * OLED_FONT_WIDTH; | 329 | uint16_t index = line * oled_rotation_width + col * OLED_FONT_WIDTH; |
| 348 | 330 | ||
| 349 | // Out of bounds? | 331 | // Out of bounds? |
| 350 | if (index >= OLED_MATRIX_SIZE) { | 332 | if (index >= OLED_MATRIX_SIZE) { |
| 351 | index = 0; | 333 | index = 0; |
| 352 | } | 334 | } |
| 353 | 335 | ||
| 354 | oled_cursor = &oled_buffer[index]; | 336 | oled_cursor = &oled_buffer[index]; |
| 355 | } | 337 | } |
| 356 | 338 | ||
| 357 | void oled_advance_page(bool clearPageRemainder) { | 339 | void oled_advance_page(bool clearPageRemainder) { |
| 358 | uint16_t index = oled_cursor - &oled_buffer[0]; | 340 | uint16_t index = oled_cursor - &oled_buffer[0]; |
| 359 | uint8_t remaining = oled_rotation_width - (index % oled_rotation_width); | 341 | uint8_t remaining = oled_rotation_width - (index % oled_rotation_width); |
| 360 | 342 | ||
| 361 | if (clearPageRemainder) { | 343 | if (clearPageRemainder) { |
| 362 | // Remaining Char count | 344 | // Remaining Char count |
| 363 | remaining = remaining / OLED_FONT_WIDTH; | 345 | remaining = remaining / OLED_FONT_WIDTH; |
| 364 | 346 | ||
| 365 | // Write empty character until next line | 347 | // Write empty character until next line |
| 366 | while (remaining--) | 348 | while (remaining--) oled_write_char(' ', false); |
| 367 | oled_write_char(' ', false); | 349 | } else { |
| 368 | } else { | 350 | // Next page index out of bounds? |
| 369 | // Next page index out of bounds? | 351 | if (index + remaining >= OLED_MATRIX_SIZE) { |
| 370 | if (index + remaining >= OLED_MATRIX_SIZE) { | 352 | index = 0; |
| 371 | index = 0; | 353 | remaining = 0; |
| 372 | remaining = 0; | 354 | } |
| 355 | |||
| 356 | oled_cursor = &oled_buffer[index + remaining]; | ||
| 373 | } | 357 | } |
| 374 | |||
| 375 | oled_cursor = &oled_buffer[index + remaining]; | ||
| 376 | } | ||
| 377 | } | 358 | } |
| 378 | 359 | ||
| 379 | void oled_advance_char(void) { | 360 | void oled_advance_char(void) { |
| 380 | uint16_t nextIndex = oled_cursor - &oled_buffer[0] + OLED_FONT_WIDTH; | 361 | uint16_t nextIndex = oled_cursor - &oled_buffer[0] + OLED_FONT_WIDTH; |
| 381 | uint8_t remainingSpace = oled_rotation_width - (nextIndex % oled_rotation_width); | 362 | uint8_t remainingSpace = oled_rotation_width - (nextIndex % oled_rotation_width); |
| 382 | 363 | ||
| 383 | // Do we have enough space on the current line for the next character | 364 | // Do we have enough space on the current line for the next character |
| 384 | if (remainingSpace < OLED_FONT_WIDTH) { | 365 | if (remainingSpace < OLED_FONT_WIDTH) { |
| 385 | nextIndex += remainingSpace; | 366 | nextIndex += remainingSpace; |
| 386 | } | 367 | } |
| 387 | 368 | ||
| 388 | // Did we go out of bounds | 369 | // Did we go out of bounds |
| 389 | if (nextIndex >= OLED_MATRIX_SIZE) { | 370 | if (nextIndex >= OLED_MATRIX_SIZE) { |
| 390 | nextIndex = 0; | 371 | nextIndex = 0; |
| 391 | } | 372 | } |
| 392 | 373 | ||
| 393 | // Update cursor position | 374 | // Update cursor position |
| 394 | oled_cursor = &oled_buffer[nextIndex]; | 375 | oled_cursor = &oled_buffer[nextIndex]; |
| 395 | } | 376 | } |
| 396 | 377 | ||
| 397 | // Main handler that writes character data to the display buffer | 378 | // Main handler that writes character data to the display buffer |
| 398 | void oled_write_char(const char data, bool invert) { | 379 | void oled_write_char(const char data, bool invert) { |
| 399 | // Advance to the next line if newline | 380 | // Advance to the next line if newline |
| 400 | if (data == '\n') { | 381 | if (data == '\n') { |
| 401 | // Old source wrote ' ' until end of line... | 382 | // Old source wrote ' ' until end of line... |
| 402 | oled_advance_page(true); | 383 | oled_advance_page(true); |
| 403 | return; | 384 | return; |
| 404 | } | 385 | } |
| 405 | 386 | ||
| 406 | if (data == '\r') { | 387 | if (data == '\r') { |
| 407 | oled_advance_page(false); | 388 | oled_advance_page(false); |
| 408 | return; | 389 | return; |
| 409 | } | 390 | } |
| 410 | 391 | ||
| 411 | // copy the current render buffer to check for dirty after | 392 | // copy the current render buffer to check for dirty after |
| 412 | static uint8_t oled_temp_buffer[OLED_FONT_WIDTH]; | 393 | static uint8_t oled_temp_buffer[OLED_FONT_WIDTH]; |
| 413 | memcpy(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH); | 394 | memcpy(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH); |
| 414 | 395 | ||
| 415 | // set the reder buffer data | 396 | // set the reder buffer data |
| 416 | uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index | 397 | uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index |
| 417 | if (cast_data < OLED_FONT_START || cast_data > OLED_FONT_END) { | 398 | if (cast_data < OLED_FONT_START || cast_data > OLED_FONT_END) { |
| 418 | memset(oled_cursor, 0x00, OLED_FONT_WIDTH); | 399 | memset(oled_cursor, 0x00, OLED_FONT_WIDTH); |
| 419 | } else { | 400 | } else { |
| 420 | const uint8_t *glyph = &font[(cast_data - OLED_FONT_START) * OLED_FONT_WIDTH]; | 401 | const uint8_t *glyph = &font[(cast_data - OLED_FONT_START) * OLED_FONT_WIDTH]; |
| 421 | memcpy_P(oled_cursor, glyph, OLED_FONT_WIDTH); | 402 | memcpy_P(oled_cursor, glyph, OLED_FONT_WIDTH); |
| 422 | } | 403 | } |
| 423 | 404 | ||
| 424 | // Invert if needed | 405 | // Invert if needed |
| 425 | if (invert) { | 406 | if (invert) { |
| 426 | InvertCharacter(oled_cursor); | 407 | InvertCharacter(oled_cursor); |
| 427 | } | 408 | } |
| 428 | 409 | ||
| 429 | // Dirty check | 410 | // Dirty check |
| 430 | if (memcmp(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH)) { | 411 | if (memcmp(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH)) { |
| 431 | uint16_t index = oled_cursor - &oled_buffer[0]; | 412 | uint16_t index = oled_cursor - &oled_buffer[0]; |
| 432 | oled_dirty |= (1 << (index / OLED_BLOCK_SIZE)); | 413 | oled_dirty |= (1 << (index / OLED_BLOCK_SIZE)); |
| 433 | // Edgecase check if the written data spans the 2 chunks | 414 | // Edgecase check if the written data spans the 2 chunks |
| 434 | oled_dirty |= (1 << ((index + OLED_FONT_WIDTH) / OLED_BLOCK_SIZE)); | 415 | oled_dirty |= (1 << ((index + OLED_FONT_WIDTH) / OLED_BLOCK_SIZE)); |
| 435 | } | 416 | } |
| 436 | 417 | ||
| 437 | // Finally move to the next char | 418 | // Finally move to the next char |
| 438 | oled_advance_char(); | 419 | oled_advance_char(); |
| 439 | } | 420 | } |
| 440 | 421 | ||
| 441 | void oled_write(const char *data, bool invert) { | 422 | void oled_write(const char *data, bool invert) { |
| 442 | const char *end = data + strlen(data); | 423 | const char *end = data + strlen(data); |
| 443 | while (data < end) { | 424 | while (data < end) { |
| 444 | oled_write_char(*data, invert); | 425 | oled_write_char(*data, invert); |
| 445 | data++; | 426 | data++; |
| 446 | } | 427 | } |
| 447 | } | 428 | } |
| 448 | 429 | ||
| 449 | void oled_write_ln(const char *data, bool invert) { | 430 | void oled_write_ln(const char *data, bool invert) { |
| 450 | oled_write(data, invert); | 431 | oled_write(data, invert); |
| 451 | oled_advance_page(true); | 432 | oled_advance_page(true); |
| 452 | } | 433 | } |
| 453 | 434 | ||
| 454 | #if defined(__AVR__) | 435 | #if defined(__AVR__) |
| 455 | void oled_write_P(const char *data, bool invert) { | 436 | void oled_write_P(const char *data, bool invert) { |
| 456 | uint8_t c = pgm_read_byte(data); | 437 | uint8_t c = pgm_read_byte(data); |
| 457 | while (c != 0) { | 438 | while (c != 0) { |
| 458 | oled_write_char(c, invert); | 439 | oled_write_char(c, invert); |
| 459 | c = pgm_read_byte(++data); | 440 | c = pgm_read_byte(++data); |
| 460 | } | 441 | } |
| 461 | } | 442 | } |
| 462 | 443 | ||
| 463 | void oled_write_ln_P(const char *data, bool invert) { | 444 | void oled_write_ln_P(const char *data, bool invert) { |
| 464 | oled_write_P(data, invert); | 445 | oled_write_P(data, invert); |
| 465 | oled_advance_page(true); | 446 | oled_advance_page(true); |
| 466 | } | 447 | } |
| 467 | #endif // defined(__AVR__) | 448 | #endif // defined(__AVR__) |
| 468 | 449 | ||
| 469 | bool oled_on(void) { | 450 | bool oled_on(void) { |
| 470 | #if OLED_TIMEOUT > 0 | 451 | #if OLED_TIMEOUT > 0 |
| 471 | oled_timeout = timer_read32() + OLED_TIMEOUT; | 452 | oled_timeout = timer_read32() + OLED_TIMEOUT; |
| 472 | #endif | 453 | #endif |
| 473 | 454 | ||
| 474 | static const uint8_t PROGMEM display_on[] = { I2C_CMD, DISPLAY_ON }; | 455 | static const uint8_t PROGMEM display_on[] = {I2C_CMD, DISPLAY_ON}; |
| 475 | if (!oled_active) { | 456 | if (!oled_active) { |
| 476 | if (I2C_TRANSMIT_P(display_on) != I2C_STATUS_SUCCESS) { | 457 | if (I2C_TRANSMIT_P(display_on) != I2C_STATUS_SUCCESS) { |
| 477 | print("oled_on cmd failed\n"); | 458 | print("oled_on cmd failed\n"); |
| 478 | return oled_active; | 459 | return oled_active; |
| 460 | } | ||
| 461 | oled_active = true; | ||
| 479 | } | 462 | } |
| 480 | oled_active = true; | 463 | return oled_active; |
| 481 | } | ||
| 482 | return oled_active; | ||
| 483 | } | 464 | } |
| 484 | 465 | ||
| 485 | bool oled_off(void) { | 466 | bool oled_off(void) { |
| 486 | static const uint8_t PROGMEM display_off[] = { I2C_CMD, DISPLAY_OFF }; | 467 | static const uint8_t PROGMEM display_off[] = {I2C_CMD, DISPLAY_OFF}; |
| 487 | if (oled_active) { | 468 | if (oled_active) { |
| 488 | if (I2C_TRANSMIT_P(display_off) != I2C_STATUS_SUCCESS) { | 469 | if (I2C_TRANSMIT_P(display_off) != I2C_STATUS_SUCCESS) { |
| 489 | print("oled_off cmd failed\n"); | 470 | print("oled_off cmd failed\n"); |
| 490 | return oled_active; | 471 | return oled_active; |
| 491 | } | 472 | } |
| 492 | oled_active = false; | 473 | oled_active = false; |
| 493 | } | 474 | } |
| 494 | return !oled_active; | 475 | return !oled_active; |
| 495 | } | 476 | } |
| 496 | 477 | ||
| 497 | bool oled_scroll_right(void) { | 478 | bool oled_scroll_right(void) { |
| 498 | // Dont enable scrolling if we need to update the display | 479 | // Dont enable scrolling if we need to update the display |
| 499 | // This prevents scrolling of bad data from starting the scroll too early after init | 480 | // This prevents scrolling of bad data from starting the scroll too early after init |
| 500 | if (!oled_dirty && !oled_scrolling) { | 481 | if (!oled_dirty && !oled_scrolling) { |
| 501 | static const uint8_t PROGMEM display_scroll_right[] = { | 482 | static const uint8_t PROGMEM display_scroll_right[] = {I2C_CMD, SCROLL_RIGHT, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xFF, ACTIVATE_SCROLL}; |
| 502 | I2C_CMD, SCROLL_RIGHT, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xFF, ACTIVATE_SCROLL }; | 483 | if (I2C_TRANSMIT_P(display_scroll_right) != I2C_STATUS_SUCCESS) { |
| 503 | if (I2C_TRANSMIT_P(display_scroll_right) != I2C_STATUS_SUCCESS) { | 484 | print("oled_scroll_right cmd failed\n"); |
| 504 | print("oled_scroll_right cmd failed\n"); | 485 | return oled_scrolling; |
| 505 | return oled_scrolling; | 486 | } |
| 506 | } | 487 | oled_scrolling = true; |
| 507 | oled_scrolling = true; | 488 | } |
| 508 | } | 489 | return oled_scrolling; |
| 509 | return oled_scrolling; | ||
| 510 | } | 490 | } |
| 511 | 491 | ||
| 512 | bool oled_scroll_left(void) { | 492 | bool oled_scroll_left(void) { |
| 513 | // Dont enable scrolling if we need to update the display | 493 | // Dont enable scrolling if we need to update the display |
| 514 | // This prevents scrolling of bad data from starting the scroll too early after init | 494 | // This prevents scrolling of bad data from starting the scroll too early after init |
| 515 | if (!oled_dirty && !oled_scrolling) { | 495 | if (!oled_dirty && !oled_scrolling) { |
| 516 | static const uint8_t PROGMEM display_scroll_left[] = { | 496 | static const uint8_t PROGMEM display_scroll_left[] = {I2C_CMD, SCROLL_LEFT, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xFF, ACTIVATE_SCROLL}; |
| 517 | I2C_CMD, SCROLL_LEFT, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xFF, ACTIVATE_SCROLL }; | 497 | if (I2C_TRANSMIT_P(display_scroll_left) != I2C_STATUS_SUCCESS) { |
| 518 | if (I2C_TRANSMIT_P(display_scroll_left) != I2C_STATUS_SUCCESS) { | 498 | print("oled_scroll_left cmd failed\n"); |
| 519 | print("oled_scroll_left cmd failed\n"); | 499 | return oled_scrolling; |
| 520 | return oled_scrolling; | 500 | } |
| 521 | } | 501 | oled_scrolling = true; |
| 522 | oled_scrolling = true; | 502 | } |
| 523 | } | 503 | return oled_scrolling; |
| 524 | return oled_scrolling; | ||
| 525 | } | 504 | } |
| 526 | 505 | ||
| 527 | bool oled_scroll_off(void) { | 506 | bool oled_scroll_off(void) { |
| 528 | if (oled_scrolling) { | 507 | if (oled_scrolling) { |
| 529 | static const uint8_t PROGMEM display_scroll_off[] = { I2C_CMD, DEACTIVATE_SCROLL }; | 508 | static const uint8_t PROGMEM display_scroll_off[] = {I2C_CMD, DEACTIVATE_SCROLL}; |
| 530 | if (I2C_TRANSMIT_P(display_scroll_off) != I2C_STATUS_SUCCESS) { | 509 | if (I2C_TRANSMIT_P(display_scroll_off) != I2C_STATUS_SUCCESS) { |
| 531 | print("oled_scroll_off cmd failed\n"); | 510 | print("oled_scroll_off cmd failed\n"); |
| 532 | return oled_scrolling; | 511 | return oled_scrolling; |
| 533 | } | 512 | } |
| 534 | oled_scrolling = false; | 513 | oled_scrolling = false; |
| 535 | oled_dirty = -1; | 514 | oled_dirty = -1; |
| 536 | } | 515 | } |
| 537 | return !oled_scrolling; | 516 | return !oled_scrolling; |
| 538 | } | 517 | } |
| 539 | 518 | ||
| 540 | uint8_t oled_max_chars(void) { | 519 | uint8_t oled_max_chars(void) { |
| 541 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { | 520 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { |
| 542 | return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH; | 521 | return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH; |
| 543 | } | 522 | } |
| 544 | return OLED_DISPLAY_HEIGHT / OLED_FONT_WIDTH; | 523 | return OLED_DISPLAY_HEIGHT / OLED_FONT_WIDTH; |
| 545 | } | 524 | } |
| 546 | 525 | ||
| 547 | uint8_t oled_max_lines(void) { | 526 | uint8_t oled_max_lines(void) { |
| 548 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { | 527 | if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { |
| 549 | return OLED_DISPLAY_HEIGHT / OLED_FONT_HEIGHT; | 528 | return OLED_DISPLAY_HEIGHT / OLED_FONT_HEIGHT; |
| 550 | } | 529 | } |
| 551 | return OLED_DISPLAY_WIDTH / OLED_FONT_HEIGHT; | 530 | return OLED_DISPLAY_WIDTH / OLED_FONT_HEIGHT; |
| 552 | } | 531 | } |
| 553 | 532 | ||
| 554 | void oled_task(void) { | 533 | void oled_task(void) { |
| 555 | if (!oled_initialized) { | 534 | if (!oled_initialized) { |
| 556 | return; | 535 | return; |
| 557 | } | 536 | } |
| 558 | 537 | ||
| 559 | oled_set_cursor(0, 0); | 538 | oled_set_cursor(0, 0); |
| 560 | 539 | ||
| 561 | oled_task_user(); | 540 | oled_task_user(); |
| 562 | 541 | ||
| 563 | #if OLED_SCROLL_TIMEOUT > 0 | 542 | #if OLED_SCROLL_TIMEOUT > 0 |
| 564 | if (oled_dirty && oled_scrolling) { | 543 | if (oled_dirty && oled_scrolling) { |
| 565 | oled_scroll_timeout = timer_read32() + OLED_SCROLL_TIMEOUT; | 544 | oled_scroll_timeout = timer_read32() + OLED_SCROLL_TIMEOUT; |
| 566 | oled_scroll_off(); | 545 | oled_scroll_off(); |
| 567 | } | 546 | } |
| 568 | #endif | 547 | #endif |
| 569 | 548 | ||
| 570 | // Smart render system, no need to check for dirty | 549 | // Smart render system, no need to check for dirty |
| 571 | oled_render(); | 550 | oled_render(); |
| 572 | 551 | ||
| 573 | // Display timeout check | 552 | // Display timeout check |
| 574 | #if OLED_TIMEOUT > 0 | 553 | #if OLED_TIMEOUT > 0 |
| 575 | if (oled_active && timer_expired32(timer_read32(), oled_timeout)) { | 554 | if (oled_active && timer_expired32(timer_read32(), oled_timeout)) { |
| 576 | oled_off(); | 555 | oled_off(); |
| 577 | } | 556 | } |
| 578 | #endif | 557 | #endif |
| 579 | 558 | ||
| 580 | #if OLED_SCROLL_TIMEOUT > 0 | 559 | #if OLED_SCROLL_TIMEOUT > 0 |
| 581 | if (!oled_scrolling && timer_expired32(timer_read32(), oled_scroll_timeout)) { | 560 | if (!oled_scrolling && timer_expired32(timer_read32(), oled_scroll_timeout)) { |
| 582 | #ifdef OLED_SCROLL_TIMEOUT_RIGHT | 561 | # ifdef OLED_SCROLL_TIMEOUT_RIGHT |
| 583 | oled_scroll_right(); | 562 | oled_scroll_right(); |
| 584 | #else | 563 | # else |
| 585 | oled_scroll_left(); | 564 | oled_scroll_left(); |
| 586 | #endif | 565 | # endif |
| 587 | } | 566 | } |
| 588 | #endif | 567 | #endif |
| 589 | } | 568 | } |
| 590 | 569 | ||
| 591 | __attribute__((weak)) | 570 | __attribute__((weak)) void oled_task_user(void) {} |
| 592 | void oled_task_user(void) { | ||
| 593 | } | ||
diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h index 4f6254c98..ac8a1c765 100644 --- a/drivers/oled/oled_driver.h +++ b/drivers/oled/oled_driver.h | |||
| @@ -21,129 +21,133 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 21 | 21 | ||
| 22 | // an enumeration of the chips this driver supports | 22 | // an enumeration of the chips this driver supports |
| 23 | #define OLED_IC_SSD1306 0 | 23 | #define OLED_IC_SSD1306 0 |
| 24 | #define OLED_IC_SH1106 1 | 24 | #define OLED_IC_SH1106 1 |
| 25 | 25 | ||
| 26 | #if defined(OLED_DISPLAY_CUSTOM) | 26 | #if defined(OLED_DISPLAY_CUSTOM) |
| 27 | // Expected user to implement the necessary defines | 27 | // Expected user to implement the necessary defines |
| 28 | #elif defined(OLED_DISPLAY_128X64) | 28 | #elif defined(OLED_DISPLAY_128X64) |
| 29 | // Double height 128x64 | 29 | // Double height 128x64 |
| 30 | #ifndef OLED_DISPLAY_WIDTH | 30 | # ifndef OLED_DISPLAY_WIDTH |
| 31 | #define OLED_DISPLAY_WIDTH 128 | 31 | # define OLED_DISPLAY_WIDTH 128 |
| 32 | #endif | 32 | # endif |
| 33 | #ifndef OLED_DISPLAY_HEIGHT | 33 | # ifndef OLED_DISPLAY_HEIGHT |
| 34 | #define OLED_DISPLAY_HEIGHT 64 | 34 | # define OLED_DISPLAY_HEIGHT 64 |
| 35 | #endif | 35 | # endif |
| 36 | #ifndef OLED_MATRIX_SIZE | 36 | # ifndef OLED_MATRIX_SIZE |
| 37 | #define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 1024 (compile time mathed) | 37 | # define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 1024 (compile time mathed) |
| 38 | #endif | 38 | # endif |
| 39 | #ifndef OLED_BLOCK_TYPE | 39 | # ifndef OLED_BLOCK_TYPE |
| 40 | #define OLED_BLOCK_TYPE uint16_t | 40 | # define OLED_BLOCK_TYPE uint16_t |
| 41 | #endif | 41 | # endif |
| 42 | #ifndef OLED_BLOCK_COUNT | 42 | # ifndef OLED_BLOCK_COUNT |
| 43 | #define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 32 (compile time mathed) | 43 | # define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 32 (compile time mathed) |
| 44 | #endif | 44 | # endif |
| 45 | #ifndef OLED_BLOCK_SIZE | 45 | # ifndef OLED_BLOCK_SIZE |
| 46 | #define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) | 46 | # define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) |
| 47 | #endif | 47 | # endif |
| 48 | #ifndef OLED_COM_PINS | 48 | # ifndef OLED_COM_PINS |
| 49 | #define OLED_COM_PINS COM_PINS_ALT | 49 | # define OLED_COM_PINS COM_PINS_ALT |
| 50 | #endif | 50 | # endif |
| 51 | 51 | ||
| 52 | // For 90 degree rotation, we map our internal matrix to oled matrix using fixed arrays | 52 | // For 90 degree rotation, we map our internal matrix to oled matrix using fixed arrays |
| 53 | // The OLED writes to it's memory horizontally, starting top left, but our memory starts bottom left in this mode | 53 | // The OLED writes to it's memory horizontally, starting top left, but our memory starts bottom left in this mode |
| 54 | #ifndef OLED_SOURCE_MAP | 54 | # ifndef OLED_SOURCE_MAP |
| 55 | #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } | 55 | # define OLED_SOURCE_MAP \ |
| 56 | #endif | 56 | { 0, 8, 16, 24, 32, 40, 48, 56 } |
| 57 | #ifndef OLED_TARGET_MAP | 57 | # endif |
| 58 | #define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 } | 58 | # ifndef OLED_TARGET_MAP |
| 59 | #endif | 59 | # define OLED_TARGET_MAP \ |
| 60 | // If OLED_BLOCK_TYPE is uint32_t, these tables would look like: | 60 | { 56, 48, 40, 32, 24, 16, 8, 0 } |
| 61 | // #define OLED_SOURCE_MAP { 32, 40, 48, 56 } | 61 | # endif |
| 62 | // #define OLED_TARGET_MAP { 24, 16, 8, 0 } | 62 | // If OLED_BLOCK_TYPE is uint32_t, these tables would look like: |
| 63 | // If OLED_BLOCK_TYPE is uint16_t, these tables would look like: | 63 | // #define OLED_SOURCE_MAP { 32, 40, 48, 56 } |
| 64 | // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } | 64 | // #define OLED_TARGET_MAP { 24, 16, 8, 0 } |
| 65 | // #define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 } | 65 | // If OLED_BLOCK_TYPE is uint16_t, these tables would look like: |
| 66 | // If OLED_BLOCK_TYPE is uint8_t, these tables would look like: | 66 | // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } |
| 67 | // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 } | 67 | // #define OLED_TARGET_MAP { 56, 48, 40, 32, 24, 16, 8, 0 } |
| 68 | // #define OLED_TARGET_MAP { 56, 120, 48, 112, 40, 104, 32, 96, 24, 88, 16, 80, 8, 72, 0, 64 } | 68 | // If OLED_BLOCK_TYPE is uint8_t, these tables would look like: |
| 69 | #else // defined(OLED_DISPLAY_128X64) | 69 | // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 } |
| 70 | // Default 128x32 | 70 | // #define OLED_TARGET_MAP { 56, 120, 48, 112, 40, 104, 32, 96, 24, 88, 16, 80, 8, 72, 0, 64 } |
| 71 | #ifndef OLED_DISPLAY_WIDTH | 71 | #else // defined(OLED_DISPLAY_128X64) |
| 72 | #define OLED_DISPLAY_WIDTH 128 | 72 | // Default 128x32 |
| 73 | #endif | 73 | # ifndef OLED_DISPLAY_WIDTH |
| 74 | #ifndef OLED_DISPLAY_HEIGHT | 74 | # define OLED_DISPLAY_WIDTH 128 |
| 75 | #define OLED_DISPLAY_HEIGHT 32 | 75 | # endif |
| 76 | #endif | 76 | # ifndef OLED_DISPLAY_HEIGHT |
| 77 | #ifndef OLED_MATRIX_SIZE | 77 | # define OLED_DISPLAY_HEIGHT 32 |
| 78 | #define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 512 (compile time mathed) | 78 | # endif |
| 79 | #endif | 79 | # ifndef OLED_MATRIX_SIZE |
| 80 | #ifndef OLED_BLOCK_TYPE | 80 | # define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH) // 512 (compile time mathed) |
| 81 | #define OLED_BLOCK_TYPE uint16_t // Type to use for segmenting the oled display for smart rendering, use unsigned types only | 81 | # endif |
| 82 | #endif | 82 | # ifndef OLED_BLOCK_TYPE |
| 83 | #ifndef OLED_BLOCK_COUNT | 83 | # define OLED_BLOCK_TYPE uint16_t // Type to use for segmenting the oled display for smart rendering, use unsigned types only |
| 84 | #define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 16 (compile time mathed) | 84 | # endif |
| 85 | #endif | 85 | # ifndef OLED_BLOCK_COUNT |
| 86 | #ifndef OLED_BLOCK_SIZE | 86 | # define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8) // 16 (compile time mathed) |
| 87 | #define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) | 87 | # endif |
| 88 | #endif | 88 | # ifndef OLED_BLOCK_SIZE |
| 89 | #ifndef OLED_COM_PINS | 89 | # define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT) // 32 (compile time mathed) |
| 90 | #define OLED_COM_PINS COM_PINS_SEQ | 90 | # endif |
| 91 | #endif | 91 | # ifndef OLED_COM_PINS |
| 92 | 92 | # define OLED_COM_PINS COM_PINS_SEQ | |
| 93 | // For 90 degree rotation, we map our internal matrix to oled matrix using fixed arrays | 93 | # endif |
| 94 | // The OLED writes to it's memory horizontally, starting top left, but our memory starts bottom left in this mode | 94 | |
| 95 | #ifndef OLED_SOURCE_MAP | 95 | // For 90 degree rotation, we map our internal matrix to oled matrix using fixed arrays |
| 96 | #define OLED_SOURCE_MAP { 0, 8, 16, 24 } | 96 | // The OLED writes to it's memory horizontally, starting top left, but our memory starts bottom left in this mode |
| 97 | #endif | 97 | # ifndef OLED_SOURCE_MAP |
| 98 | #ifndef OLED_TARGET_MAP | 98 | # define OLED_SOURCE_MAP \ |
| 99 | #define OLED_TARGET_MAP { 24, 16, 8, 0 } | 99 | { 0, 8, 16, 24 } |
| 100 | #endif | 100 | # endif |
| 101 | // If OLED_BLOCK_TYPE is uint8_t, these tables would look like: | 101 | # ifndef OLED_TARGET_MAP |
| 102 | // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } | 102 | # define OLED_TARGET_MAP \ |
| 103 | // #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 } | 103 | { 24, 16, 8, 0 } |
| 104 | #endif // defined(OLED_DISPLAY_CUSTOM) | 104 | # endif |
| 105 | // If OLED_BLOCK_TYPE is uint8_t, these tables would look like: | ||
| 106 | // #define OLED_SOURCE_MAP { 0, 8, 16, 24, 32, 40, 48, 56 } | ||
| 107 | // #define OLED_TARGET_MAP { 48, 32, 16, 0, 56, 40, 24, 8 } | ||
| 108 | #endif // defined(OLED_DISPLAY_CUSTOM) | ||
| 105 | 109 | ||
| 106 | #if !defined(OLED_IC) | 110 | #if !defined(OLED_IC) |
| 107 | #define OLED_IC OLED_IC_SSD1306 | 111 | # define OLED_IC OLED_IC_SSD1306 |
| 108 | #endif | 112 | #endif |
| 109 | 113 | ||
| 110 | // the column address corresponding to the first column in the display hardware | 114 | // the column address corresponding to the first column in the display hardware |
| 111 | #if !defined(OLED_COLUMN_OFFSET) | 115 | #if !defined(OLED_COLUMN_OFFSET) |
| 112 | #define OLED_COLUMN_OFFSET 0 | 116 | # define OLED_COLUMN_OFFSET 0 |
| 113 | #endif | 117 | #endif |
| 114 | 118 | ||
| 115 | // Address to use for the i2c oled communication | 119 | // Address to use for the i2c oled communication |
| 116 | #if !defined(OLED_DISPLAY_ADDRESS) | 120 | #if !defined(OLED_DISPLAY_ADDRESS) |
| 117 | #define OLED_DISPLAY_ADDRESS 0x3C | 121 | # define OLED_DISPLAY_ADDRESS 0x3C |
| 118 | #endif | 122 | #endif |
| 119 | 123 | ||
| 120 | // Custom font file to use | 124 | // Custom font file to use |
| 121 | #if !defined(OLED_FONT_H) | 125 | #if !defined(OLED_FONT_H) |
| 122 | #define OLED_FONT_H "glcdfont.c" | 126 | # define OLED_FONT_H "glcdfont.c" |
| 123 | #endif | 127 | #endif |
| 124 | // unsigned char value of the first character in the font file | 128 | // unsigned char value of the first character in the font file |
| 125 | #if !defined(OLED_FONT_START) | 129 | #if !defined(OLED_FONT_START) |
| 126 | #define OLED_FONT_START 0 | 130 | # define OLED_FONT_START 0 |
| 127 | #endif | 131 | #endif |
| 128 | // unsigned char value of the last character in the font file | 132 | // unsigned char value of the last character in the font file |
| 129 | #if !defined(OLED_FONT_END) | 133 | #if !defined(OLED_FONT_END) |
| 130 | #define OLED_FONT_END 224 | 134 | # define OLED_FONT_END 224 |
| 131 | #endif | 135 | #endif |
| 132 | // Font render width | 136 | // Font render width |
| 133 | #if !defined(OLED_FONT_WIDTH) | 137 | #if !defined(OLED_FONT_WIDTH) |
| 134 | #define OLED_FONT_WIDTH 6 | 138 | # define OLED_FONT_WIDTH 6 |
| 135 | #endif | 139 | #endif |
| 136 | // Font render height | 140 | // Font render height |
| 137 | #if !defined(OLED_FONT_HEIGHT) | 141 | #if !defined(OLED_FONT_HEIGHT) |
| 138 | #define OLED_FONT_HEIGHT 8 | 142 | # define OLED_FONT_HEIGHT 8 |
| 139 | #endif | 143 | #endif |
| 140 | 144 | ||
| 141 | #if !defined(OLED_TIMEOUT) | 145 | #if !defined(OLED_TIMEOUT) |
| 142 | #if defined(OLED_DISABLE_TIMEOUT) | 146 | # if defined(OLED_DISABLE_TIMEOUT) |
| 143 | #define OLED_TIMEOUT 0 | 147 | # define OLED_TIMEOUT 0 |
| 144 | #else | 148 | # else |
| 145 | #define OLED_TIMEOUT 60000 | 149 | # define OLED_TIMEOUT 60000 |
| 146 | #endif | 150 | # endif |
| 147 | #endif | 151 | #endif |
| 148 | 152 | ||
| 149 | // OLED Rotation enum values are flags | 153 | // OLED Rotation enum values are flags |
| @@ -151,7 +155,7 @@ typedef enum { | |||
| 151 | OLED_ROTATION_0 = 0, | 155 | OLED_ROTATION_0 = 0, |
| 152 | OLED_ROTATION_90 = 1, | 156 | OLED_ROTATION_90 = 1, |
| 153 | OLED_ROTATION_180 = 2, | 157 | OLED_ROTATION_180 = 2, |
| 154 | OLED_ROTATION_270 = 3, // OLED_ROTATION_90 | OLED_ROTATION_180 | 158 | OLED_ROTATION_270 = 3, // OLED_ROTATION_90 | OLED_ROTATION_180 |
| 155 | } oled_rotation_t; | 159 | } oled_rotation_t; |
| 156 | 160 | ||
| 157 | // Initialize the oled display, rotating the rendered output based on the define passed in. | 161 | // Initialize the oled display, rotating the rendered output based on the define passed in. |
| @@ -208,15 +212,15 @@ void oled_write_P(const char *data, bool invert); | |||
| 208 | // Remapped to call 'void oled_write_ln(const char *data, bool invert);' on ARM | 212 | // Remapped to call 'void oled_write_ln(const char *data, bool invert);' on ARM |
| 209 | void oled_write_ln_P(const char *data, bool invert); | 213 | void oled_write_ln_P(const char *data, bool invert); |
| 210 | #else | 214 | #else |
| 211 | // Writes a string to the buffer at current cursor position | 215 | // Writes a string to the buffer at current cursor position |
| 212 | // Advances the cursor while writing, inverts the pixels if true | 216 | // Advances the cursor while writing, inverts the pixels if true |
| 213 | #define oled_write_P(data, invert) oled_write(data, invert) | 217 | # define oled_write_P(data, invert) oled_write(data, invert) |
| 214 | 218 | ||
| 215 | // Writes a string to the buffer at current cursor position | 219 | // Writes a string to the buffer at current cursor position |
| 216 | // Advances the cursor while writing, inverts the pixels if true | 220 | // Advances the cursor while writing, inverts the pixels if true |
| 217 | // Advances the cursor to the next page, wiring ' ' to the remainder of the current page | 221 | // Advances the cursor to the next page, wiring ' ' to the remainder of the current page |
| 218 | #define oled_write_ln_P(data, invert) oled_write(data, invert) | 222 | # define oled_write_ln_P(data, invert) oled_write(data, invert) |
| 219 | #endif // defined(__AVR__) | 223 | #endif // defined(__AVR__) |
| 220 | 224 | ||
| 221 | // Can be used to manually turn on the screen if it is off | 225 | // Can be used to manually turn on the screen if it is off |
| 222 | // Returns true if the screen was on or turns on | 226 | // Returns true if the screen was on or turns on |
