diff options
Diffstat (limited to 'drivers/oled')
-rw-r--r-- | drivers/oled/glcdfont.c | 2 | ||||
-rw-r--r-- | drivers/oled/licenses.txt | 45 | ||||
-rw-r--r-- | drivers/oled/oled_driver.h | 38 | ||||
-rw-r--r-- | drivers/oled/ssd1306_sh1106.c (renamed from drivers/oled/oled_driver.c) | 66 |
4 files changed, 134 insertions, 17 deletions
diff --git a/drivers/oled/glcdfont.c b/drivers/oled/glcdfont.c index de58960189..0e201d71ee 100644 --- a/drivers/oled/glcdfont.c +++ b/drivers/oled/glcdfont.c @@ -4,7 +4,7 @@ // Online editor: http://teripom.x0.com/ static const unsigned char font[] PROGMEM = { - 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, + 0x07, 0x08, 0x7F, 0x08, 0x07, 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, 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, 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, 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, diff --git a/drivers/oled/licenses.txt b/drivers/oled/licenses.txt new file mode 100644 index 0000000000..111603ebf3 --- /dev/null +++ b/drivers/oled/licenses.txt @@ -0,0 +1,45 @@ +The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License. + + +This is the Linux-penguin again... + +Originally drewn by Larry Ewing (http://www.isc.tamu.edu/~lewing/) +(with the GIMP) the Linux Logo has been vectorized by me (Simon Budig, +http://www.home.unix-ag.org/simon/). + +This happened quite some time ago with Corel Draw 4. But luckily +meanwhile there are tools available to handle vector graphics with +Linux. Bernhard Herzog (bernhard@users.sourceforge.net) deserves kudos +for creating Sketch (http://sketch.sourceforge.net), a powerful free +tool for creating vector graphics. He converted the Corel Draw file to +the Sketch native format. Since I am unable to maintain the Corel Draw +file any longer, the Sketch version now is the "official" one. + +Anja Gerwinski (anja@gerwinski.de) has created an alternate version of +the penguin (penguin-variant.sk) with a thinner mouth line and slightly +altered gradients. It also features a nifty drop shadow. + +The third bird (penguin-flat.sk) is a version reduced to three colors +(black/white/yellow) for e.g. silk screen printing. I made this version +for a mug, available at the friendly folks at +http://www.kernelconcepts.de/ - they do good stuff, mail Petra +(pinguin@kernelconcepts.de) if you need something special or don't +understand the german :-) + +These drawings are copyrighted by Larry Ewing and Simon Budig +(penguin-variant.sk also by Anja Gerwinski), redistribution is free but +has to include this README/Copyright notice. + +The use of these drawings is free. However I am happy about a sample of +your mug/t-shirt/whatever with this penguin on it... + +Have fun + Simon Budig + + +Simon.Budig@unix-ag.org +http://www.home.unix-ag.org/simon/ + +Simon Budig +Am Hardtkoeppel 2 +D-61279 Graevenwiesbach diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h index 99acacd96e..13b73ede9d 100644 --- a/drivers/oled/oled_driver.h +++ b/drivers/oled/oled_driver.h @@ -154,10 +154,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # endif #endif +#if !defined(OLED_FADE_OUT_INTERVAL) +# define OLED_FADE_OUT_INTERVAL 0x00 +#endif + +#if OLED_FADE_OUT_INTERVAL > 0x0F || OLED_FADE_OUT_INTERVAL < 0x00 +# error OLED_FADE_OUT_INTERVAL must be between 0x00 and 0x0F +#endif + #if !defined(OLED_I2C_TIMEOUT) # define OLED_I2C_TIMEOUT 100 #endif +#if !defined(OLED_UPDATE_INTERVAL) && defined(SPLIT_KEYBOARD) +# define OLED_UPDATE_INTERVAL 50 +#endif + typedef struct __attribute__((__packed__)) { uint8_t *current_element; uint16_t remaining_element_count; @@ -173,12 +185,12 @@ typedef enum { // Initialize the oled display, rotating the rendered output based on the define passed in. // Returns true if the OLED was initialized successfully -bool oled_init(uint8_t rotation); +bool oled_init(oled_rotation_t rotation); // Called at the start of oled_init, weak function overridable by the user // rotation - the value passed into oled_init -// Return new uint8_t if you want to override default rotation -uint8_t oled_init_user(uint8_t rotation); +// Return new oled_rotation_t if you want to override default rotation +oled_rotation_t oled_init_user(oled_rotation_t rotation); // Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering void oled_clear(void); @@ -214,13 +226,17 @@ void oled_write(const char *data, bool invert); void oled_write_ln(const char *data, bool invert); // Pans the buffer to the right (or left by passing true) by moving contents of the buffer +// Useful for moving the screen in preparation for new drawing void oled_pan(bool left); // Returns a pointer to the requested start index in the buffer plus remaining // buffer length as struct oled_buffer_reader_t oled_read_raw(uint16_t start_index); +// Writes a string to the buffer at current cursor position void oled_write_raw(const char *data, uint16_t size); + +// Writes a single byte into the buffer at the specified index void oled_write_raw_byte(const char data, uint16_t index); // Sets a specific pixel on or off @@ -239,17 +255,11 @@ void oled_write_P(const char *data, bool invert); // Remapped to call 'void oled_write_ln(const char *data, bool invert);' on ARM void oled_write_ln_P(const char *data, bool invert); +// Writes a PROGMEM string to the buffer at current cursor position void oled_write_raw_P(const char *data, uint16_t size); #else -// Writes a string to the buffer at current cursor position -// Advances the cursor while writing, inverts the pixels if true # define oled_write_P(data, invert) oled_write(data, invert) - -// Writes a string to the buffer at current cursor position -// Advances the cursor while writing, inverts the pixels if true -// Advances the cursor to the next page, wiring ' ' to the remainder of the current page # define oled_write_ln_P(data, invert) oled_write(data, invert) - # define oled_write_raw_P(data, size) oled_write_raw(data, size) #endif // defined(__AVR__) @@ -303,6 +313,14 @@ bool oled_scroll_left(void); // Returns true if the screen was not scrolling or stops scrolling bool oled_scroll_off(void); +// Returns true if the oled is currently scrolling, false if it is +// not +bool is_oled_scrolling(void); + +// Inverts the display +// Returns true if the screen was or is inverted +bool oled_invert(bool invert); + // Returns the maximum number of characters that will fit on a line uint8_t oled_max_chars(void); diff --git a/drivers/oled/oled_driver.c b/drivers/oled/ssd1306_sh1106.c index 92c64399e2..e9049438f5 100644 --- a/drivers/oled/oled_driver.c +++ b/drivers/oled/ssd1306_sh1106.c @@ -24,6 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "progmem.h" +#include "keyboard.h" + // Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf // for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf @@ -32,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define DISPLAY_ALL_ON 0xA5 #define DISPLAY_ALL_ON_RESUME 0xA4 #define NORMAL_DISPLAY 0xA6 +#define INVERT_DISPLAY 0xA7 #define DISPLAY_ON 0xAF #define DISPLAY_OFF 0xAE #define NOP 0xE3 @@ -71,6 +74,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define PRE_CHARGE_PERIOD 0xD9 #define VCOM_DETECT 0xDB +// Advance Graphic Commands +#define FADE_BLINK 0x23 +#define ENABLE_FADE 0x20 +#define ENABLE_BLINK 0x30 + // Charge Pump Commands #define CHARGE_PUMP 0x8D @@ -107,8 +115,9 @@ OLED_BLOCK_TYPE oled_dirty = 0; bool oled_initialized = false; bool oled_active = false; bool oled_scrolling = false; +bool oled_inverted = false; uint8_t oled_brightness = OLED_BRIGHTNESS; -uint8_t oled_rotation = 0; +oled_rotation_t oled_rotation = 0; uint8_t oled_rotation_width = 0; uint8_t oled_scroll_speed = 0; // this holds the speed after being remapped to ssd1306 internal values uint8_t oled_scroll_start = 0; @@ -151,7 +160,13 @@ static void InvertCharacter(uint8_t *cursor) { } } -bool oled_init(uint8_t rotation) { +bool oled_init(oled_rotation_t rotation) { +#if defined(USE_I2C) && defined(SPLIT_KEYBOARD) + if (!is_keyboard_master()) { + return true; + } +#endif + oled_rotation = oled_init_user(rotation); if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { oled_rotation_width = OLED_DISPLAY_WIDTH; @@ -478,8 +493,9 @@ void oled_write_raw(const char *data, uint16_t size) { uint16_t cursor_start_index = oled_cursor - &oled_buffer[0]; if ((size + cursor_start_index) > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE - cursor_start_index; for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) { - if (oled_buffer[i] == data[i]) continue; - oled_buffer[i] = data[i]; + uint8_t c = *data++; + if (oled_buffer[i] == c) continue; + oled_buffer[i] = c; oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE)); } } @@ -539,7 +555,13 @@ bool oled_on(void) { oled_timeout = timer_read32() + OLED_TIMEOUT; #endif - static const uint8_t PROGMEM display_on[] = {I2C_CMD, DISPLAY_ON}; + static const uint8_t PROGMEM display_on[] = +#ifdef OLED_FADE_OUT + {I2C_CMD, FADE_BLINK, 0x00}; +#else + {I2C_CMD, DISPLAY_ON}; +#endif + if (!oled_active) { if (I2C_TRANSMIT_P(display_on) != I2C_STATUS_SUCCESS) { print("oled_on cmd failed\n"); @@ -555,7 +577,13 @@ bool oled_off(void) { return !oled_active; } - static const uint8_t PROGMEM display_off[] = {I2C_CMD, DISPLAY_OFF}; + static const uint8_t PROGMEM display_off[] = +#ifdef OLED_FADE_OUT + {I2C_CMD, FADE_BLINK, ENABLE_FADE | OLED_FADE_OUT_INTERVAL}; +#else + {I2C_CMD, DISPLAY_OFF}; +#endif + if (oled_active) { if (I2C_TRANSMIT_P(display_off) != I2C_STATUS_SUCCESS) { print("oled_off cmd failed\n"); @@ -664,6 +692,32 @@ bool oled_scroll_off(void) { return !oled_scrolling; } +bool is_oled_scrolling(void) { return oled_scrolling; } + +bool oled_invert(bool invert) { + if (!oled_initialized) { + return oled_inverted; + } + + if (invert && !oled_inverted) { + static const uint8_t PROGMEM display_inverted[] = {I2C_CMD, INVERT_DISPLAY}; + if (I2C_TRANSMIT_P(display_inverted) != I2C_STATUS_SUCCESS) { + print("oled_invert cmd failed\n"); + return oled_inverted; + } + oled_inverted = true; + } else if (!invert && oled_inverted) { + static const uint8_t PROGMEM display_normal[] = {I2C_CMD, NORMAL_DISPLAY}; + if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) { + print("oled_invert cmd failed\n"); + return oled_inverted; + } + oled_inverted = false; + } + + return oled_inverted; +} + uint8_t oled_max_chars(void) { if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) { return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH; |