aboutsummaryrefslogtreecommitdiff
path: root/drivers/qwiic/micro_oled.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/qwiic/micro_oled.c')
-rw-r--r--drivers/qwiic/micro_oled.c482
1 files changed, 0 insertions, 482 deletions
diff --git a/drivers/qwiic/micro_oled.c b/drivers/qwiic/micro_oled.c
deleted file mode 100644
index 8dfff6968..000000000
--- a/drivers/qwiic/micro_oled.c
+++ /dev/null
@@ -1,482 +0,0 @@
1/* Jim Lindblom @ SparkFun Electronics
2 * October 26, 2014
3 * https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
4 *
5 * Modified by:
6 * Emil Varughese @ Edwin Robotics Pvt. Ltd.
7 * July 27, 2015
8 * https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
9 *
10 * This code was heavily based around the MicroView library, written by GeekAmmo
11 * (https://github.com/geekammo/MicroView-Arduino-Library).
12 *
13 * Adapted for QMK by:
14 * Jack Humbert <jack.humb@gmail.com>
15 * October 11, 2018
16 *
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 */
30#include "micro_oled.h"
31#include "print.h"
32#include <stdlib.h>
33#include "util/font5x7.h"
34#include "util/font8x16.h"
35#include <string.h>
36
37#define TOTALFONTS 2
38const unsigned char* fonts_pointer[] = {font5x7, font8x16};
39
40uint8_t foreColor, drawMode, fontWidth, fontHeight, fontType, fontStartChar, fontTotalChar, cursorX, cursorY;
41uint16_t fontMapWidth;
42
43#ifndef _BV
44# define _BV(x) (1 << (x))
45#endif
46
47#define swap(a, b) \
48 { \
49 uint8_t t = a; \
50 a = b; \
51 b = t; \
52 }
53
54uint8_t micro_oled_transfer_buffer[20];
55static uint8_t micro_oled_screen_current[LCDWIDTH * LCDHEIGHT / 8] = {0};
56
57/* LCD Memory organised in 64 horizontal pixel and 6 rows of byte
58 B B .............B -----
59 y y .............y \
60 t t .............t \
61 e e .............e \
62 0 1 .............63 \
63 \
64 D0 D0.............D0 \
65 D1 D1.............D1 / ROW 0
66 D2 D2.............D2 /
67 D3 D3.............D3 /
68 D4 D4.............D4 /
69 D5 D5.............D5 /
70 D6 D6.............D6 /
71 D7 D7.............D7 ----
72 */
73#ifdef NO_LCD_SPLASH
74// do not initialize with a splash screen
75static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0};
76#else
77# if LCDWIDTH == 64
78# if LCDHEIGHT == 48
79static uint8_t micro_oled_screen_buffer[] = {
80 // QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php
81 // 64x48 image
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 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, 0x60, 0x60, 0x60, 0x60, 0xF8, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xF8, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF, 0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7, 0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 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, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
85# endif
86# elif LCDWIDTH == 128
87# if LCDHEIGHT == 32
88static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {
89 // 128x32 qmk image
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xFC, 0xFC, 0xE0, 0xF0, 0xFC, 0xE0, 0xE0, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x30, 0xE0, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xB2, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0x03, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xB2, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x02, 0x02, 0x03, 0x01, 0x00, 0x06, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x06, 0x00, 0x03, 0x1E, 0x18, 0x0F, 0x01, 0x0F, 0x18, 0x1E, 0x01, 0x00, 0x0F, 0x1F, 0x12, 0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0x12, 0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x4D, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF9, 0xF3, 0xF3, 0xC0, 0x80, 0xF3, 0xF3, 0xF3, 0xF9, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0xC0, 0x00, 0x70, 0xC0, 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x1C, 0xF0, 0x00, 0x00, 0xFC, 0x0C, 0x38, 0xE0, 0x00, 0x00, 0xC0, 0x38, 0x0C, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x60, 0x90, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x3F, 0x3F, 0x07, 0x3F, 0x3F, 0x07, 0x0F, 0x3F, 0x07, 0x07, 0x3F, 0x07, 0x07, 0x3F, 0x3F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x06, 0x04, 0x04, 0x07, 0x01, 0x00, 0x00, 0x13, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, 0x07, 0x0D, 0x08, 0x00, 0x07, 0x00, 0x00, 0x01, 0x07, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
94# elif LCDHEIGHT == 64
95static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {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, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 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,
96 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, 0xC0, 0xC0, 0xC0, 0xC0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, 0x7F, 0x7E, 0xFE, 0xFF, 0xFF, 0xFE, 0xFE, 0x7F, 0x7F, 0xFE, 0xFE, 0xFF, 0xFF, 0xFE, 0x7E, 0x7F, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xC0, 0xC0, 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,
97 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, 0x88, 0x88, 0x88, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x88, 0x88, 0x88, 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,
98 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, 0x99, 0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF3, 0xF3, 0xE7, 0xE7, 0x00, 0x00, 0xE7, 0xE7, 0xF3, 0xF3, 0xF0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x99, 0x99, 0x99, 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,
99 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, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x1F, 0x3F, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x01, 0x01, 0x01, 0x01, 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,
100 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, 0x03, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x80, 0x03, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x80, 0x01, 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, 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,
101 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, 0xFF, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x70, 0x88, 0x04, 0x04, 0x04, 0xF8, 0x00, 0x00, 0x3C, 0xE0, 0xC0, 0x38, 0x1C, 0xE0, 0x80, 0x70, 0x0C, 0x00, 0xF8, 0xAC, 0x24, 0x24, 0x3C, 0x30, 0x00, 0x00, 0xFC, 0x0C, 0x04, 0x00, 0xF8, 0xAC, 0x24, 0x24, 0x2C, 0x30, 0x00, 0x70, 0xDC, 0x04, 0x04, 0x88, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x8C, 0x04, 0x04, 0xF8, 0x00, 0x04, 0x3C, 0xE0, 0x80, 0xF0, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x83, 0x01, 0x01, 0x01, 0x81, 0xFE, 0x3C, 0x00, 0x00, 0xFF, 0x03, 0x0E, 0x70, 0xC0, 0xE0, 0x38, 0x06, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0x18, 0x38, 0x66, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
104// TODO: generate bitmap of QMK logo here
105# endif
106# else
107// catchall for custom screen sizes
108static uint8_t micro_oled_screen_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0};
109# endif
110#endif
111
112void micro_oled_init(void) {
113 i2c_init();
114
115#ifdef __AVR__
116 i2c_start(I2C_ADDRESS_SA0_1, 100);
117#else
118 i2c_start(I2C_ADDRESS_SA0_1);
119#endif
120
121 // Display Init sequence for 64x48 OLED module
122 send_command(DISPLAYOFF); // 0xAE
123
124 send_command(SETDISPLAYCLOCKDIV); // 0xD5
125 send_command(0x80); // the suggested ratio 0x80
126
127 send_command(SETMULTIPLEX); // 0xA8
128 send_command(LCDHEIGHT - 1);
129
130 send_command(SETDISPLAYOFFSET); // 0xD3
131 send_command(0x00); // no offset
132
133 send_command(SETSTARTLINE | 0x00); // line #0
134
135 send_command(CHARGEPUMP); // enable charge pump
136 send_command(0x14);
137
138 send_command(NORMALDISPLAY); // 0xA6
139 send_command(DISPLAYALLONRESUME); // 0xA4
140
141 // display at regular orientation
142 send_command(SEGREMAP | 0x1);
143 send_command(COMSCANDEC);
144
145// rotate display 180
146#ifdef micro_oled_rotate_180
147 send_command(SEGREMAP);
148 send_command(COMSCANINC);
149#endif
150
151 send_command(MEMORYMODE);
152 send_command(0x02); // 0x02 = 10b, Page addressing mode
153
154 send_command(SETCOMPINS); // 0xDA
155 if (LCDHEIGHT > 32) {
156 send_command(0x12);
157 } else {
158 send_command(0x02);
159 }
160 send_command(SETCONTRAST); // 0x81
161 send_command(0x8F);
162
163 send_command(SETPRECHARGE); // 0xd9
164 send_command(0xF1);
165
166 send_command(SETVCOMDESELECT); // 0xDB
167 send_command(0x40);
168
169 send_command(DISPLAYON); //--turn on oled panel
170 clear_screen(); // Erase hardware memory inside the OLED controller to avoid random data in memory.
171 send_buffer();
172}
173
174void send_command(uint8_t command) {
175 micro_oled_transfer_buffer[0] = I2C_COMMAND;
176 micro_oled_transfer_buffer[1] = command;
177 i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
178}
179
180void send_data(uint8_t data) {
181 micro_oled_transfer_buffer[0] = I2C_DATA;
182 micro_oled_transfer_buffer[1] = data;
183 i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
184}
185
186/** \brief Set SSD1306 page address.
187 Send page address command and address to the SSD1306 OLED controller.
188*/
189void set_page_address(uint8_t address) {
190 address = (0xB0 | address);
191 send_command(address);
192}
193
194/** \brief Set SSD1306 column address.
195 Send column address command and address to the SSD1306 OLED controller.
196*/
197void set_column_address(uint8_t address) {
198 send_command((0x10 | (address >> 4)) + ((128 - LCDWIDTH) >> 8));
199 send_command(0x0F & address);
200}
201
202/** \brief Clear SSD1306's memory.
203 To clear GDRAM inside the LCD controller.
204*/
205void clear_screen(void) {
206 for (int i = 0; i < 8; i++) {
207 set_page_address(i);
208 set_column_address(0);
209 for (int j = 0; j < 0x80; j++) {
210 send_data(0);
211 }
212 }
213
214 memset(micro_oled_screen_current, 0, LCDWIDTH * LCDHEIGHT / 8);
215}
216
217/** \brief Clear SSD1306's memory.
218 To clear GDRAM inside the LCD controller.
219*/
220void clear_buffer(void) {
221 // 384
222 memset(micro_oled_screen_buffer, 0, LCDWIDTH * LCDHEIGHT / 8);
223}
224
225/** \brief Invert display.
226 The PIXEL_ON color of the display will turn to PIXEL_OFF and the PIXEL_OFF will turn to PIXEL_ON.
227*/
228void invert_screen(bool invert) {
229 if (invert) {
230 send_command(INVERTDISPLAY);
231 } else {
232 send_command(NORMALDISPLAY);
233 }
234}
235
236/** \brief Set contrast.
237 OLED contract value from 0 to 255. Note: Contrast level is not very obvious.
238*/
239void set_contrast(uint8_t contrast) {
240 send_command(SETCONTRAST); // 0x81
241 send_command(contrast);
242}
243
244/** \brief Transfer display buffer.
245 Sends the updated buffer to the controller - the current status is checked before to save i2c exectution time
246*/
247void send_buffer(void) {
248 uint8_t i, j;
249
250 uint8_t page_addr = 0xFF;
251 for (i = 0; i < LCDHEIGHT / 8; i++) {
252 uint8_t col_addr = 0xFF;
253 for (j = 0; j < LCDWIDTH; j++) {
254 if (micro_oled_screen_buffer[i * LCDWIDTH + j] != micro_oled_screen_current[i * LCDWIDTH + j]) {
255 if (page_addr != i) {
256 set_page_address(i);
257 page_addr = i;
258 }
259 if (col_addr != j) {
260 set_column_address(j);
261 col_addr = j + 1;
262 }
263 send_data(micro_oled_screen_buffer[i * LCDWIDTH + j]);
264 micro_oled_screen_current[i * LCDWIDTH + j] = micro_oled_screen_buffer[i * LCDWIDTH + j];
265 }
266 }
267 }
268}
269
270/** \brief Draw pixel with color and mode.
271 Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode.
272*/
273void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) {
274 if ((x < 0) || (x >= LCDWIDTH) || (y < 0) || (y >= LCDHEIGHT)) return;
275
276 if (mode == XOR) {
277 if (color == PIXEL_ON) micro_oled_screen_buffer[x + (y / 8) * LCDWIDTH] ^= _BV((y % 8));
278 } else {
279 if (color == PIXEL_ON)
280 micro_oled_screen_buffer[x + (y / 8) * LCDWIDTH] |= _BV((y % 8));
281 else
282 micro_oled_screen_buffer[x + (y / 8) * LCDWIDTH] &= ~_BV((y % 8));
283 }
284}
285
286/** \brief Draw line with color and mode.
287Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.
288*/
289void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode) {
290 uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
291 if (steep) {
292 swap(x0, y0);
293 swap(x1, y1);
294 }
295
296 if (x0 > x1) {
297 swap(x0, x1);
298 swap(y0, y1);
299 }
300
301 uint8_t dx, dy;
302 dx = x1 - x0;
303 dy = abs(y1 - y0);
304
305 int8_t err = dx / 2;
306 int8_t ystep;
307
308 if (y0 < y1) {
309 ystep = 1;
310 } else {
311 ystep = -1;
312 }
313
314 for (; x0 < x1; x0++) {
315 if (steep) {
316 draw_pixel(y0, x0, color, mode);
317 } else {
318 draw_pixel(x0, y0, color, mode);
319 }
320 err -= dy;
321 if (err < 0) {
322 y0 += ystep;
323 err += dx;
324 }
325 }
326}
327
328/** \brief Draw horizontal line with color and mode.
329Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer.
330*/
331void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode) { draw_line(x, y, x + width, y, color, mode); }
332
333/** \brief Draw vertical line.
334Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer.
335*/
336void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode) { draw_line(x, y, x, y + height, color, mode); }
337
338/** \brief Draw rectangle with color and mode.
339Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
340*/
341void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
342 uint8_t tempHeight;
343
344 draw_line_hori(x, y, width, color, mode);
345 draw_line_hori(x, y + height - 1, width, color, mode);
346
347 tempHeight = height - 2;
348
349 // skip drawing vertical lines to avoid overlapping of pixel that will
350 // affect XOR plot if no pixel in between horizontal lines
351 if (tempHeight < 1) return;
352
353 draw_line_vert(x, y + 1, tempHeight, color, mode);
354 draw_line_vert(x + width - 1, y + 1, tempHeight, color, mode);
355}
356
357/** \brief Draw rectangle with color and mode.
358Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
359*/
360void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
361 uint8_t tempHeight;
362
363 draw_line_hori(x + 1, y, width - 2, color, mode);
364 draw_line_hori(x + 1, y + height - 1, width - 2, color, mode);
365
366 tempHeight = height - 2;
367
368 // skip drawing vertical lines to avoid overlapping of pixel that will
369 // affect XOR plot if no pixel in between horizontal lines
370 if (tempHeight < 1) return;
371
372 draw_line_vert(x, y + 1, tempHeight, color, mode);
373 draw_line_vert(x + width - 1, y + 1, tempHeight, color, mode);
374}
375
376/** \brief Draw filled rectangle with color and mode.
377Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
378*/
379void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
380 // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
381 for (int i = x; i < x + width; i++) {
382 draw_line_vert(i, y, height, color, mode);
383 }
384}
385
386/** \brief Draw filled rectangle with color and mode.
387Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
388*/
389void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
390 // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
391 for (int i = x; i < x + width; i++) {
392 if (i == x || i == (x + width - 1))
393 draw_line_vert(i, y + 1, height - 2, color, mode);
394 else
395 draw_line_vert(i, y, height, color, mode);
396 }
397}
398
399/** \brief Draw character with color and mode.
400 Draw character c using color and draw mode at x,y.
401*/
402void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font) {
403 // TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels
404
405 uint8_t rowsToDraw, row, tempC;
406 uint8_t i, j, temp;
407 uint16_t charPerBitmapRow, charColPositionOnBitmap, charRowPositionOnBitmap, charBitmapStartPosition;
408
409 if ((font >= TOTALFONTS) || (font < 0)) return;
410
411 uint8_t fontType = font;
412 uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType] + 0);
413 uint8_t fontHeight = pgm_read_byte(fonts_pointer[fontType] + 1);
414 uint8_t fontStartChar = pgm_read_byte(fonts_pointer[fontType] + 2);
415 uint8_t fontTotalChar = pgm_read_byte(fonts_pointer[fontType] + 3);
416 uint16_t fontMapWidth = (pgm_read_byte(fonts_pointer[fontType] + 4) * 100) + pgm_read_byte(fonts_pointer[fontType] + 5); // two bytes values into integer 16
417
418 if ((c < fontStartChar) || (c > (fontStartChar + fontTotalChar - 1))) // no bitmap for the required c
419 return;
420
421 tempC = c - fontStartChar;
422
423 // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn
424 rowsToDraw = fontHeight / 8; // 8 is LCD's page size, see SSD1306 datasheet
425 if (rowsToDraw <= 1) rowsToDraw = 1;
426
427 // the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw
428 if (rowsToDraw == 1) {
429 for (i = 0; i < fontWidth + 1; i++) {
430 if (i == fontWidth) // this is done in a weird way because for 5x7 font, there is no margin, this code add a margin after col 5
431 temp = 0;
432 else
433 temp = pgm_read_byte(fonts_pointer[fontType] + FONTHEADERSIZE + (tempC * fontWidth) + i);
434
435 for (j = 0; j < 8; j++) { // 8 is the LCD's page height (see datasheet for explanation)
436 if (temp & 0x1) {
437 draw_pixel(x + i, y + j, color, mode);
438 } else {
439 draw_pixel(x + i, y + j, !color, mode);
440 }
441
442 temp >>= 1;
443 }
444 }
445 return;
446 }
447
448 // font height over 8 bit
449 // take character "0" ASCII 48 as example
450 charPerBitmapRow = fontMapWidth / fontWidth; // 256/8 =32 char per row
451 charColPositionOnBitmap = tempC % charPerBitmapRow; // =16
452 charRowPositionOnBitmap = (int)(tempC / charPerBitmapRow); // =1
453 charBitmapStartPosition = (charRowPositionOnBitmap * fontMapWidth * (fontHeight / 8)) + (charColPositionOnBitmap * fontWidth);
454
455 // each row on LCD is 8 bit height (see datasheet for explanation)
456 for (row = 0; row < rowsToDraw; row++) {
457 for (i = 0; i < fontWidth; i++) {
458 temp = pgm_read_byte(fonts_pointer[fontType] + FONTHEADERSIZE + (charBitmapStartPosition + i + (row * fontMapWidth)));
459 for (j = 0; j < 8; j++) { // 8 is the LCD's page height (see datasheet for explanation)
460 if (temp & 0x1) {
461 draw_pixel(x + i, y + j + (row * 8), color, mode);
462 } else {
463 draw_pixel(x + i, y + j + (row * 8), !color, mode);
464 }
465 temp >>= 1;
466 }
467 }
468 }
469}
470
471void draw_string(uint8_t x, uint8_t y, char* string, uint8_t color, uint8_t mode, uint8_t font) {
472 if ((font >= TOTALFONTS) || (font < 0)) return;
473
474 uint8_t fontType = font;
475 uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType] + 0);
476
477 uint8_t cur_x = x;
478 for (int i = 0; i < strlen(string); i++) {
479 draw_char(cur_x, y, string[i], color, mode, font);
480 cur_x += fontWidth + 1;
481 }
482}