aboutsummaryrefslogtreecommitdiff
path: root/keyboards/sol/common/ssd1306.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/sol/common/ssd1306.c')
-rw-r--r--keyboards/sol/common/ssd1306.c329
1 files changed, 0 insertions, 329 deletions
diff --git a/keyboards/sol/common/ssd1306.c b/keyboards/sol/common/ssd1306.c
deleted file mode 100644
index b3e55a67c..000000000
--- a/keyboards/sol/common/ssd1306.c
+++ /dev/null
@@ -1,329 +0,0 @@
1#ifdef SSD1306OLED
2
3#include "ssd1306.h"
4#include "i2c.h"
5#include <string.h>
6#include "print.h"
7#ifndef LOCAL_GLCDFONT
8#include "common/glcdfont.c"
9#else
10#include <helixfont.h>
11#endif
12#ifdef ADAFRUIT_BLE_ENABLE
13#include "adafruit_ble.h"
14#endif
15#ifdef PROTOCOL_LUFA
16#include "lufa.h"
17#endif
18#include "sendchar.h"
19#include "timer.h"
20
21// Set this to 1 to help diagnose early startup problems
22// when testing power-on with ble. Turn it off otherwise,
23// as the latency of printing most of the debug info messes
24// with the matrix scan, causing keys to drop.
25#define DEBUG_TO_SCREEN 0
26
27//static uint16_t last_battery_update;
28//static uint32_t vbat;
29//#define BatteryUpdateInterval 10000 /* milliseconds */
30#define ScreenOffInterval 300000 /* milliseconds */
31#if DEBUG_TO_SCREEN
32static uint8_t displaying;
33#endif
34static uint16_t last_flush;
35
36// Write command sequence.
37// Returns true on success.
38static inline bool _send_cmd1(uint8_t cmd) {
39 bool res = false;
40
41 if (i2c_start_write(SSD1306_ADDRESS)) {
42 xprintf("failed to start write to %d\n", SSD1306_ADDRESS);
43 goto done;
44 }
45
46 if (i2c_master_write(0x0 /* command byte follows */)) {
47 print("failed to write control byte\n");
48
49 goto done;
50 }
51
52 if (i2c_master_write(cmd)) {
53 xprintf("failed to write command %d\n", cmd);
54 goto done;
55 }
56 res = true;
57done:
58 i2c_master_stop();
59 return res;
60}
61
62// Write 2-byte command sequence.
63// Returns true on success
64static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) {
65 if (!_send_cmd1(cmd)) {
66 return false;
67 }
68 return _send_cmd1(opr);
69}
70
71// Write 3-byte command sequence.
72// Returns true on success
73static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) {
74 if (!_send_cmd1(cmd)) {
75 return false;
76 }
77 if (!_send_cmd1(opr1)) {
78 return false;
79 }
80 return _send_cmd1(opr2);
81}
82
83#define send_cmd1(c) if (!_send_cmd1(c)) {goto done;}
84#define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;}
85#define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;}
86
87static void clear_display(void) {
88 matrix_clear(&display);
89
90 // Clear all of the display bits (there can be random noise
91 // in the RAM on startup)
92 send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
93 send_cmd3(ColumnAddr, 0, DisplayWidth - 1);
94
95 if (i2c_start_write(SSD1306_ADDRESS)) {
96 goto done;
97 }
98 if (i2c_master_write(0x40)) {
99 // Data mode
100 goto done;
101 }
102 for (uint8_t row = 0; row < MatrixRows; ++row) {
103 for (uint8_t col = 0; col < DisplayWidth; ++col) {
104 i2c_master_write(0);
105 }
106 }
107
108 display.dirty = false;
109
110done:
111 i2c_master_stop();
112}
113
114#if DEBUG_TO_SCREEN
115#undef sendchar
116static int8_t capture_sendchar(uint8_t c) {
117 sendchar(c);
118 iota_gfx_write_char(c);
119
120 if (!displaying) {
121 iota_gfx_flush();
122 }
123 return 0;
124}
125#endif
126
127bool iota_gfx_init(bool rotate) {
128 bool success = false;
129
130 i2c_master_init();
131 send_cmd1(DisplayOff);
132 send_cmd2(SetDisplayClockDiv, 0x80);
133 send_cmd2(SetMultiPlex, DisplayHeight - 1);
134
135 send_cmd2(SetDisplayOffset, 0);
136
137
138 send_cmd1(SetStartLine | 0x0);
139 send_cmd2(SetChargePump, 0x14 /* Enable */);
140 send_cmd2(SetMemoryMode, 0 /* horizontal addressing */);
141
142 if(rotate){
143 // the following Flip the display orientation 180 degrees
144 send_cmd1(SegRemap);
145 send_cmd1(ComScanInc);
146 }else{
147 // Flips the display orientation 0 degrees
148 send_cmd1(SegRemap | 0x1);
149 send_cmd1(ComScanDec);
150 }
151
152 send_cmd2(SetComPins, 0x2);
153 send_cmd2(SetContrast, 0x8f);
154 send_cmd2(SetPreCharge, 0xf1);
155 send_cmd2(SetVComDetect, 0x40);
156 send_cmd1(DisplayAllOnResume);
157 send_cmd1(NormalDisplay);
158 send_cmd1(DeActivateScroll);
159 send_cmd1(DisplayOn);
160
161 send_cmd2(SetContrast, 0); // Dim
162
163 clear_display();
164
165 success = true;
166
167 iota_gfx_flush();
168
169#if DEBUG_TO_SCREEN
170 print_set_sendchar(capture_sendchar);
171#endif
172
173done:
174 return success;
175}
176
177bool iota_gfx_off(void) {
178 bool success = false;
179
180 send_cmd1(DisplayOff);
181 success = true;
182
183done:
184 return success;
185}
186
187bool iota_gfx_on(void) {
188 bool success = false;
189
190 send_cmd1(DisplayOn);
191 success = true;
192
193done:
194 return success;
195}
196
197void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
198 *matrix->cursor = c;
199 ++matrix->cursor;
200
201 if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
202 // We went off the end; scroll the display upwards by one line
203 memmove(&matrix->display[0], &matrix->display[1],
204 MatrixCols * (MatrixRows - 1));
205 matrix->cursor = &matrix->display[MatrixRows - 1][0];
206 memset(matrix->cursor, ' ', MatrixCols);
207 }
208}
209
210void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
211 matrix->dirty = true;
212
213 if (c == '\n') {
214 // Clear to end of line from the cursor and then move to the
215 // start of the next line
216 uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
217
218 while (cursor_col++ < MatrixCols) {
219 matrix_write_char_inner(matrix, ' ');
220 }
221 return;
222 }
223
224 matrix_write_char_inner(matrix, c);
225}
226
227void iota_gfx_write_char(uint8_t c) {
228 matrix_write_char(&display, c);
229}
230
231void matrix_write(struct CharacterMatrix *matrix, const char *data) {
232 const char *end = data + strlen(data);
233 while (data < end) {
234 matrix_write_char(matrix, *data);
235 ++data;
236 }
237}
238
239void iota_gfx_write(const char *data) {
240 matrix_write(&display, data);
241}
242
243void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
244 while (true) {
245 uint8_t c = pgm_read_byte(data);
246 if (c == 0) {
247 return;
248 }
249 matrix_write_char(matrix, c);
250 ++data;
251 }
252}
253
254void iota_gfx_write_P(const char *data) {
255 matrix_write_P(&display, data);
256}
257
258void matrix_clear(struct CharacterMatrix *matrix) {
259 memset(matrix->display, ' ', sizeof(matrix->display));
260 matrix->cursor = &matrix->display[0][0];
261 matrix->dirty = true;
262}
263
264void iota_gfx_clear_screen(void) {
265 matrix_clear(&display);
266}
267
268void matrix_render(struct CharacterMatrix *matrix) {
269 last_flush = timer_read();
270 iota_gfx_on();
271#if DEBUG_TO_SCREEN
272 ++displaying;
273#endif
274
275 // Move to the home position
276 send_cmd3(PageAddr, 0, MatrixRows - 1);
277 send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1);
278
279 if (i2c_start_write(SSD1306_ADDRESS)) {
280 goto done;
281 }
282 if (i2c_master_write(0x40)) {
283 // Data mode
284 goto done;
285 }
286
287 for (uint8_t row = 0; row < MatrixRows; ++row) {
288 for (uint8_t col = 0; col < MatrixCols; ++col) {
289 const uint8_t *glyph = font + (matrix->display[row][col] * FontWidth);
290
291 for (uint8_t glyphCol = 0; glyphCol < FontWidth; ++glyphCol) {
292 uint8_t colBits = pgm_read_byte(glyph + glyphCol);
293 i2c_master_write(colBits);
294 }
295
296 // 1 column of space between chars (it's not included in the glyph)
297 //i2c_master_write(0);
298 }
299 }
300
301 matrix->dirty = false;
302
303done:
304 i2c_master_stop();
305#if DEBUG_TO_SCREEN
306 --displaying;
307#endif
308}
309
310void iota_gfx_flush(void) {
311 matrix_render(&display);
312}
313
314__attribute__ ((weak))
315void iota_gfx_task_user(void) {
316}
317
318void iota_gfx_task(void) {
319 iota_gfx_task_user();
320
321 if (display.dirty) {
322 iota_gfx_flush();
323 }
324
325 if (timer_elapsed(last_flush) > ScreenOffInterval) {
326 iota_gfx_off();
327 }
328}
329#endif