1 /* Jim Lindblom @ SparkFun Electronics
3 * https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED
6 * Emil Varughese @ Edwin Robotics Pvt. Ltd.
8 * https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/
10 * This code was heavily based around the MicroView library, written by GeekAmmo
11 * (https://github.com/geekammo/MicroView-Arduino-Library).
14 * Jack Humbert <jack.humb@gmail.com>
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.
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.
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/>.
30 #include "micro_oled.h"
32 #include "util/font5x7.h"
33 #include "util/font8x16.h"
37 const unsigned char * fonts_pointer[]= { font5x7, font8x16 };
39 uint8_t foreColor,drawMode,fontWidth, fontHeight, fontType, fontStartChar, fontTotalChar, cursorX, cursorY;
40 uint16_t fontMapWidth;
42 #define _BV(x) (1 << (x))
43 #define swap(a, b) { uint8_t t = a; a = b; b = t; }
45 uint8_t micro_oled_transfer_buffer[20];
46 static uint8_t micro_oled_screen_current[LCDWIDTH*LCDWIDTH/8] = { 0 };
48 /* LCD Memory organised in 64 horizontal pixel and 6 rows of byte
49 B B .............B -----
55 D0 D0.............D0 \
56 D1 D1.............D1 / ROW 0
57 D2 D2.............D2 /
58 D3 D3.............D3 /
59 D4 D4.............D4 /
60 D5 D5.............D5 /
61 D6 D6.............D6 /
62 D7 D7.............D7 ----
67 static uint8_t micro_oled_screen_buffer[] = {
68 // QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00,
73 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00,
74 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60,
78 0xF8, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF,
79 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF,
80 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE,
81 0xFE, 0xF8, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
85 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
86 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
87 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF,
91 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF,
92 0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7,
93 0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
94 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06,
97 0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
98 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF,
99 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
100 0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
105 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
106 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00
111 #elif LCDWIDTH == 128
113 static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xFC, 0xFC,
118 0xE0, 0xF0, 0xFC, 0xE0, 0xE0, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC,
119 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x30, 0xE0, 0x00, 0x00,
122 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
123 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80,
124 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
125 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
126 0x80, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xB2, 0xB2, 0xFF,
130 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0x03,
131 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF,
132 0xFF, 0xB7, 0xB2, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x1F, 0x02, 0x02, 0x03, 0x01, 0x00, 0x06, 0x1F, 0x10,
135 0x10, 0x10, 0x1F, 0x06, 0x00, 0x03, 0x1E, 0x18, 0x0F, 0x01,
136 0x0F, 0x18, 0x1E, 0x01, 0x00, 0x0F, 0x1F, 0x12, 0x02, 0x12,
137 0x13, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0x12,
138 0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x1F,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x48, 0x4D, 0x4D, 0xFF, 0xFF, 0xFF,
143 0xFF, 0xFF, 0xFE, 0xF8, 0xF9, 0xF3, 0xF3, 0xC0, 0x80, 0xF3,
144 0xF3, 0xF3, 0xF9, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED,
145 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0xC0, 0x00, 0x70, 0xC0,
148 0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C,
149 0x04, 0x04, 0x04, 0x04, 0x1C, 0xF0, 0x00, 0x00, 0xFC, 0x0C,
150 0x38, 0xE0, 0x00, 0x00, 0xC0, 0x38, 0x0C, 0xFC, 0x00, 0x00,
151 0xFC, 0xFC, 0x60, 0x90, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x3F,
156 0x3F, 0x07, 0x3F, 0x3F, 0x07, 0x0F, 0x3F, 0x07, 0x07, 0x3F,
157 0x07, 0x07, 0x3F, 0x3F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
160 0x06, 0x04, 0x04, 0x07, 0x01, 0x00, 0x00, 0x13, 0x1E, 0x03,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x04, 0x04,
162 0x04, 0x04, 0x07, 0x0D, 0x08, 0x00, 0x07, 0x00, 0x00, 0x01,
163 0x07, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x07,
164 0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 #elif LCDHEIGHT == 64
169 static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0,
178 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00,
179 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0xC0, 0xC0, 0xC0, 0xC0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF,
193 0x7F, 0x7E, 0xFE, 0xFF, 0xFF, 0xFE, 0xFE, 0x7F, 0x7F, 0xFE,
194 0xFE, 0xFF, 0xFF, 0xFE, 0x7E, 0x7F, 0xFF, 0xFE, 0xFE, 0xFC,
195 0xFC, 0xF8, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x88, 0x88, 0x88, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
208 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
209 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
210 0xFF, 0xFF, 0xFF, 0xDD, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF,
223 0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF3, 0xF3, 0xE7, 0xE7, 0x00,
224 0x00, 0xE7, 0xE7, 0xF3, 0xF3, 0xF0, 0xF8, 0xFE, 0xFF, 0xFF,
225 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00,
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x1F, 0x3F,
238 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F,
239 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF,
240 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x00,
241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00,
254 0x80, 0x03, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x80, 0x01,
255 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0x00, 0x00, 0x00, 0xFF, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x70,
265 0x88, 0x04, 0x04, 0x04, 0xF8, 0x00, 0x00, 0x3C, 0xE0, 0xC0,
266 0x38, 0x1C, 0xE0, 0x80, 0x70, 0x0C, 0x00, 0xF8, 0xAC, 0x24,
267 0x24, 0x3C, 0x30, 0x00, 0x00, 0xFC, 0x0C, 0x04, 0x00, 0xF8,
268 0xAC, 0x24, 0x24, 0x2C, 0x30, 0x00, 0x70, 0xDC, 0x04, 0x04,
269 0x88, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
270 0x8C, 0x04, 0x04, 0xF8, 0x00, 0x04, 0x3C, 0xE0, 0x80, 0xF0,
271 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x83, 0x01, 0x01,
272 0x01, 0x81, 0xFE, 0x3C, 0x00, 0x00, 0xFF, 0x03, 0x0E, 0x70,
273 0xC0, 0xE0, 0x38, 0x06, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0x18,
274 0x38, 0x66, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
280 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
281 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
282 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
283 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
284 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
287 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00,
288 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
289 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
307 //TODO: generate bitmap of QMK logo here
310 //catchall for custom screen szies
311 static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {0};
316 void micro_oled_init(void) {
319 i2c_start(I2C_ADDRESS_SA0_1);
321 // Display Init sequence for 64x48 OLED module
322 send_command(DISPLAYOFF); // 0xAE
324 send_command(SETDISPLAYCLOCKDIV); // 0xD5
325 send_command(0x80); // the suggested ratio 0x80
327 send_command(SETMULTIPLEX); // 0xA8
328 send_command(LCDHEIGHT - 1);
330 send_command(SETDISPLAYOFFSET); // 0xD3
331 send_command(0x00); // no offset
333 send_command(SETSTARTLINE | 0x00); // line #0
335 send_command(CHARGEPUMP); // enable charge pump
338 send_command(NORMALDISPLAY); // 0xA6
339 send_command(DISPLAYALLONRESUME); // 0xA4
341 //display at regular orientation
342 send_command(SEGREMAP | 0x1);
343 send_command(COMSCANDEC);
346 #ifdef micro_oled_rotate_180
347 send_command(SEGREMAP);
348 send_command(COMSCANINC);
351 send_command(MEMORYMODE);
354 send_command(SETCOMPINS); // 0xDA
355 if (LCDHEIGHT > 32) {
360 send_command(SETCONTRAST); // 0x81
363 send_command(SETPRECHARGE); // 0xd9
366 send_command(SETVCOMDESELECT); // 0xDB
369 send_command(DISPLAYON); //--turn on oled panel
370 clear_screen(); // Erase hardware memory inside the OLED controller to avoid random data in memory.
374 void send_command(uint8_t command) {
375 micro_oled_transfer_buffer[0] = I2C_COMMAND;
376 micro_oled_transfer_buffer[1] = command;
377 i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
380 void send_data(uint8_t data) {
381 micro_oled_transfer_buffer[0] = I2C_DATA;
382 micro_oled_transfer_buffer[1] = data;
383 i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100);
386 /** \brief Set SSD1306 page address.
387 Send page address command and address to the SSD1306 OLED controller.
389 void set_page_address(uint8_t address) {
390 address = (0xB0 | address);
391 send_command(address);
394 /** \brief Set SSD1306 column address.
395 Send column address command and address to the SSD1306 OLED controller.
397 void set_column_address(uint8_t address) {
398 send_command( ( 0x10 | (address >> 4) ) + ((128 - LCDWIDTH) >> 8) );
399 send_command( 0x0F & address );
402 /** \brief Clear SSD1306's memory.
403 To clear GDRAM inside the LCD controller.
405 void clear_screen(void) {
406 for (int i=0;i<8; i++) {
408 set_column_address(0);
409 for (int j=0; j<0x80; j++) {
415 /** \brief Clear SSD1306's memory.
416 To clear GDRAM inside the LCD controller.
418 void clear_buffer(void) {
420 memset(micro_oled_screen_buffer, 0, LCDWIDTH*LCDWIDTH/8);
423 /** \brief Invert display.
424 The PIXEL_ON color of the display will turn to PIXEL_OFF and the PIXEL_OFF will turn to PIXEL_ON.
426 void invert_screen(bool invert) {
428 send_command(INVERTDISPLAY);
430 send_command(NORMALDISPLAY);
434 /** \brief Set contrast.
435 OLED contract value from 0 to 255. Note: Contrast level is not very obvious.
437 void set_contrast(uint8_t contrast) {
438 send_command(SETCONTRAST); // 0x81
439 send_command(contrast);
442 /** \brief Transfer display buffer.
443 Sends the updated buffer to the controller - the current status is checked before to save i2c exectution time
445 void send_buffer(void) {
448 uint8_t page_addr = 0xFF;
449 for (i = 0; i < LCDHEIGHT/8; i++) {
450 uint8_t col_addr = 0xFF;
451 for (j = 0; j < LCDWIDTH; j++) {
452 if (micro_oled_screen_buffer[i*LCDWIDTH+j] != micro_oled_screen_current[i*LCDWIDTH+j]) {
453 if (page_addr != i) {
457 set_column_address(j);
459 send_data(micro_oled_screen_buffer[i*LCDWIDTH+j]);
460 micro_oled_screen_current[i*LCDWIDTH+j] = micro_oled_screen_buffer[i*LCDWIDTH+j];
467 /** \brief Draw pixel with color and mode.
468 Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode.
470 void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) {
471 if ((x<0) || (x>=LCDWIDTH) || (y<0) || (y>=LCDHEIGHT))
475 if (color == PIXEL_ON)
476 micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] ^= _BV((y%8));
478 if (color == PIXEL_ON)
479 micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] |= _BV((y%8));
481 micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] &= ~_BV((y%8));
485 /** \brief Draw line with color and mode.
486 Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.
488 void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode) {
489 uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
512 for (; x0<x1; x0++) {
514 draw_pixel(y0, x0, color, mode);
516 draw_pixel(x0, y0, color, mode);
526 /** \brief Draw horizontal line with color and mode.
527 Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer.
529 void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode) {
530 draw_line(x,y,x+width,y,color,mode);
533 /** \brief Draw vertical line.
534 Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer.
536 void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode) {
537 draw_line(x,y,x,y+height,color,mode);
540 /** \brief Draw rectangle with color and mode.
541 Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
543 void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
546 draw_line_hori(x,y, width, color, mode);
547 draw_line_hori(x,y+height-1, width, color, mode);
551 // skip drawing vertical lines to avoid overlapping of pixel that will
552 // affect XOR plot if no pixel in between horizontal lines
553 if (tempHeight<1) return;
555 draw_line_vert(x,y+1, tempHeight, color, mode);
556 draw_line_vert(x+width-1, y+1, tempHeight, color, mode);
559 /** \brief Draw rectangle with color and mode.
560 Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
562 void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
565 draw_line_hori(x+1,y, width-2, color, mode);
566 draw_line_hori(x+1,y+height-1, width-2, color, mode);
570 // skip drawing vertical lines to avoid overlapping of pixel that will
571 // affect XOR plot if no pixel in between horizontal lines
572 if (tempHeight<1) return;
574 draw_line_vert(x,y+1, tempHeight, color, mode);
575 draw_line_vert(x+width-1, y+1, tempHeight, color, mode);
578 /** \brief Draw filled rectangle with color and mode.
579 Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
581 void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
582 // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
583 for (int i=x; i<x+width;i++) {
584 draw_line_vert(i,y, height, color, mode);
588 /** \brief Draw filled rectangle with color and mode.
589 Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer.
591 void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) {
592 // TODO - need to optimise the memory map draw so that this function will not call pixel one by one
593 for (int i=x; i<x+width;i++) {
594 if (i == x || i == (x + width - 1))
595 draw_line_vert(i, y+1, height-2, color, mode);
597 draw_line_vert(i, y, height, color, mode);
601 /** \brief Draw character with color and mode.
602 Draw character c using color and draw mode at x,y.
604 void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font) {
605 // TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels
607 uint8_t rowsToDraw,row, tempC;
609 uint16_t charPerBitmapRow,charColPositionOnBitmap,charRowPositionOnBitmap,charBitmapStartPosition;
611 if ((font>=TOTALFONTS) || (font<0))
614 uint8_t fontType = font;
615 uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType]+0);
616 uint8_t fontHeight = pgm_read_byte(fonts_pointer[fontType]+1);
617 uint8_t fontStartChar = pgm_read_byte(fonts_pointer[fontType]+2);
618 uint8_t fontTotalChar = pgm_read_byte(fonts_pointer[fontType]+3);
619 uint16_t fontMapWidth = (pgm_read_byte(fonts_pointer[fontType]+4)*100)+pgm_read_byte(fonts_pointer[fontType]+5); // two bytes values into integer 16
621 if ((c<fontStartChar) || (c>(fontStartChar+fontTotalChar-1))) // no bitmap for the required c
624 tempC=c-fontStartChar;
626 // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn
627 rowsToDraw=fontHeight/8; // 8 is LCD's page size, see SSD1306 datasheet
628 if (rowsToDraw<=1) rowsToDraw=1;
630 // the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw
632 for (i=0;i<fontWidth+1;i++) {
633 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
636 temp=pgm_read_byte(fonts_pointer[fontType]+FONTHEADERSIZE+(tempC*fontWidth)+i);
638 for (j=0;j<8;j++) { // 8 is the LCD's page height (see datasheet for explanation)
640 draw_pixel(x+i, y+j, color,mode);
643 draw_pixel(x+i, y+j, !color,mode);
652 // font height over 8 bit
653 // take character "0" ASCII 48 as example
654 charPerBitmapRow = fontMapWidth/fontWidth; // 256/8 =32 char per row
655 charColPositionOnBitmap = tempC % charPerBitmapRow; // =16
656 charRowPositionOnBitmap = (int)(tempC/charPerBitmapRow); // =1
657 charBitmapStartPosition = (charRowPositionOnBitmap * fontMapWidth * (fontHeight/8)) + (charColPositionOnBitmap * fontWidth) ;
659 // each row on LCD is 8 bit height (see datasheet for explanation)
660 for(row=0;row<rowsToDraw;row++) {
661 for (i=0; i<fontWidth;i++) {
662 temp=pgm_read_byte(fonts_pointer[fontType]+FONTHEADERSIZE+(charBitmapStartPosition+i+(row*fontMapWidth)));
663 for (j=0;j<8;j++) { // 8 is the LCD's page height (see datasheet for explanation)
665 draw_pixel(x+i,y+j+(row*8), color, mode);
668 draw_pixel(x+i,y+j+(row*8), !color, mode);
677 void draw_string(uint8_t x, uint8_t y, char * string, uint8_t color, uint8_t mode, uint8_t font) {
679 if ((font>=TOTALFONTS) || (font<0))
682 uint8_t fontType = font;
683 uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType]+0);
686 for (int i = 0; i < strlen(string); i++) {
687 draw_char(cur_x, y, string[i], color, mode, font);
688 cur_x += fontWidth + 1;