summaryrefslogtreecommitdiff
path: root/keyboards/satt
diff options
context:
space:
mode:
authorJoel Challis <git@zvecr.com>2022-07-31 15:35:42 +0100
committerGitHub <noreply@github.com>2022-07-31 15:35:42 +0100
commit409790457cdc509c0bf783745f27335ec6806b5d (patch)
treeca873998999b6367a159e5d389481a1483a64e4e /keyboards/satt
parentbaf34989f1847185a055e9d41783052eccb09d9c (diff)
Refactor satt/comet46 to use core OLED driver (#17856)
Diffstat (limited to 'keyboards/satt')
-rw-r--r--keyboards/satt/comet46/i2c.c162
-rw-r--r--keyboards/satt/comet46/i2c.h46
-rw-r--r--keyboards/satt/comet46/keymaps/default/config.h29
-rw-r--r--keyboards/satt/comet46/keymaps/default/keymap.c45
-rw-r--r--keyboards/satt/comet46/keymaps/default/rules.mk5
-rw-r--r--keyboards/satt/comet46/keymaps/satt/config.h29
-rw-r--r--keyboards/satt/comet46/keymaps/satt/keymap.c105
-rw-r--r--keyboards/satt/comet46/keymaps/satt/rules.mk4
-rw-r--r--keyboards/satt/comet46/lib/glcdfont.c137
-rw-r--r--keyboards/satt/comet46/rules.mk5
-rw-r--r--keyboards/satt/comet46/ssd1306.c343
-rw-r--r--keyboards/satt/comet46/ssd1306.h90
12 files changed, 54 insertions, 946 deletions
diff --git a/keyboards/satt/comet46/i2c.c b/keyboards/satt/comet46/i2c.c
deleted file mode 100644
index 4bee5c6398..0000000000
--- a/keyboards/satt/comet46/i2c.c
+++ /dev/null
@@ -1,162 +0,0 @@
1#include <util/twi.h>
2#include <avr/io.h>
3#include <stdlib.h>
4#include <avr/interrupt.h>
5#include <util/twi.h>
6#include <stdbool.h>
7#include "i2c.h"
8
9#ifdef USE_I2C
10
11// Limits the amount of we wait for any one i2c transaction.
12// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is
13// 9 bits, a single transaction will take around 90μs to complete.
14//
15// (F_CPU/SCL_CLOCK) => # of μC cycles to transfer a bit
16// poll loop takes at least 8 clock cycles to execute
17#define I2C_LOOP_TIMEOUT (9+1)*(F_CPU/SCL_CLOCK)/8
18
19#define BUFFER_POS_INC() (slave_buffer_pos = (slave_buffer_pos+1)%SLAVE_BUFFER_SIZE)
20
21volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
22
23static volatile uint8_t slave_buffer_pos;
24static volatile bool slave_has_register_set = false;
25
26// Wait for an i2c operation to finish
27inline static
28void i2c_delay(void) {
29 uint16_t lim = 0;
30 while(!(TWCR & (1<<TWINT)) && lim < I2C_LOOP_TIMEOUT)
31 lim++;
32
33 // easier way, but will wait slightly longer
34 // _delay_us(100);
35}
36
37// Setup twi to run at 100kHz or 400kHz (see ./i2c.h SCL_CLOCK)
38void i2c_master_init(void) {
39 // no prescaler
40 TWSR = 0;
41 // Set TWI clock frequency to SCL_CLOCK. Need TWBR>10.
42 // Check datasheets for more info.
43 TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
44}
45
46// Start a transaction with the given i2c slave address. The direction of the
47// transfer is set with I2C_READ and I2C_WRITE.
48// returns: 0 => success
49// 1 => error
50uint8_t i2c_master_start(uint8_t address) {
51 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
52
53 i2c_delay();
54
55 // check that we started successfully
56 if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START))
57 return 1;
58
59 TWDR = address;
60 TWCR = (1<<TWINT) | (1<<TWEN);
61
62 i2c_delay();
63
64 if ( (TW_STATUS != TW_MT_SLA_ACK) && (TW_STATUS != TW_MR_SLA_ACK) )
65 return 1; // slave did not acknowledge
66 else
67 return 0; // success
68}
69
70
71// Finish the i2c transaction.
72void i2c_master_stop(void) {
73 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
74
75 uint16_t lim = 0;
76 while(!(TWCR & (1<<TWSTO)) && lim < I2C_LOOP_TIMEOUT)
77 lim++;
78}
79
80// Write one byte to the i2c slave.
81// returns 0 => slave ACK
82// 1 => slave NACK
83uint8_t i2c_master_write(uint8_t data) {
84 TWDR = data;
85 TWCR = (1<<TWINT) | (1<<TWEN);
86
87 i2c_delay();
88
89 // check if the slave acknowledged us
90 return (TW_STATUS == TW_MT_DATA_ACK) ? 0 : 1;
91}
92
93// Read one byte from the i2c slave. If ack=1 the slave is acknowledged,
94// if ack=0 the acknowledge bit is not set.
95// returns: byte read from i2c device
96uint8_t i2c_master_read(int ack) {
97 TWCR = (1<<TWINT) | (1<<TWEN) | (ack<<TWEA);
98
99 i2c_delay();
100 return TWDR;
101}
102
103void i2c_reset_state(void) {
104 TWCR = 0;
105}
106
107void i2c_slave_init(uint8_t address) {
108 TWAR = address << 0; // slave i2c address
109 // TWEN - twi enable
110 // TWEA - enable address acknowledgement
111 // TWINT - twi interrupt flag
112 // TWIE - enable the twi interrupt
113 TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
114}
115
116ISR(TWI_vect);
117
118ISR(TWI_vect) {
119 uint8_t ack = 1;
120 switch(TW_STATUS) {
121 case TW_SR_SLA_ACK:
122 // this device has been addressed as a slave receiver
123 slave_has_register_set = false;
124 break;
125
126 case TW_SR_DATA_ACK:
127 // this device has received data as a slave receiver
128 // The first byte that we receive in this transaction sets the location
129 // of the read/write location of the slaves memory that it exposes over
130 // i2c. After that, bytes will be written at slave_buffer_pos, incrementing
131 // slave_buffer_pos after each write.
132 if(!slave_has_register_set) {
133 slave_buffer_pos = TWDR;
134 // don't acknowledge the master if this memory loctaion is out of bounds
135 if ( slave_buffer_pos >= SLAVE_BUFFER_SIZE ) {
136 ack = 0;
137 slave_buffer_pos = 0;
138 }
139 slave_has_register_set = true;
140 } else {
141 i2c_slave_buffer[slave_buffer_pos] = TWDR;
142 BUFFER_POS_INC();
143 }
144 break;
145
146 case TW_ST_SLA_ACK:
147 case TW_ST_DATA_ACK:
148 // master has addressed this device as a slave transmitter and is
149 // requesting data.
150 TWDR = i2c_slave_buffer[slave_buffer_pos];
151 BUFFER_POS_INC();
152 break;
153
154 case TW_BUS_ERROR: // something went wrong, reset twi state
155 TWCR = 0;
156 default:
157 break;
158 }
159 // Reset everything, so we are ready for the next TWI interrupt
160 TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
161}
162#endif
diff --git a/keyboards/satt/comet46/i2c.h b/keyboards/satt/comet46/i2c.h
deleted file mode 100644
index 710662c7ab..0000000000
--- a/keyboards/satt/comet46/i2c.h
+++ /dev/null
@@ -1,46 +0,0 @@
1#pragma once
2
3#include <stdint.h>
4
5#ifndef F_CPU
6#define F_CPU 16000000UL
7#endif
8
9#define I2C_READ 1
10#define I2C_WRITE 0
11
12#define I2C_ACK 1
13#define I2C_NACK 0
14
15#define SLAVE_BUFFER_SIZE 0x10
16
17// i2c SCL clock frequency 400kHz
18#define SCL_CLOCK 400000L
19
20extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
21
22void i2c_master_init(void);
23uint8_t i2c_master_start(uint8_t address);
24void i2c_master_stop(void);
25uint8_t i2c_master_write(uint8_t data);
26uint8_t i2c_master_read(int);
27void i2c_reset_state(void);
28void i2c_slave_init(uint8_t address);
29
30
31static inline unsigned char i2c_start_read(unsigned char addr) {
32 return i2c_master_start((addr << 1) | I2C_READ);
33}
34
35static inline unsigned char i2c_start_write(unsigned char addr) {
36 return i2c_master_start((addr << 1) | I2C_WRITE);
37}
38
39// from SSD1306 scrips
40extern unsigned char i2c_rep_start(unsigned char addr);
41extern void i2c_start_wait(unsigned char addr);
42extern unsigned char i2c_readAck(void);
43extern unsigned char i2c_readNak(void);
44extern unsigned char i2c_read(unsigned char ack);
45
46#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
diff --git a/keyboards/satt/comet46/keymaps/default/config.h b/keyboards/satt/comet46/keymaps/default/config.h
deleted file mode 100644
index ee02a94b7e..0000000000
--- a/keyboards/satt/comet46/keymaps/default/config.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2This is the c configuration file for the keymap
3
4Copyright 2012 Jun Wako <wakojun@gmail.com>
5Copyright 2015 Jack Humbert
6
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#pragma once
22
23// place overrides here
24
25
26/* Use I2C or Serial */
27
28#define USE_I2C
29#define SSD1306OLED
diff --git a/keyboards/satt/comet46/keymaps/default/keymap.c b/keyboards/satt/comet46/keymaps/default/keymap.c
index bccca0a091..3e6f9045ff 100644
--- a/keyboards/satt/comet46/keymaps/default/keymap.c
+++ b/keyboards/satt/comet46/keymaps/default/keymap.c
@@ -2,9 +2,6 @@
2// This is the canonical layout file for the Quantum project. If you want to add another keyboard, 2// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
3 3
4#include QMK_KEYBOARD_H 4#include QMK_KEYBOARD_H
5#ifdef SSD1306OLED
6 #include "ssd1306.h"
7#endif
8 5
9 6
10// Each layer gets a name for readability, which is then used in the keymap matrix below. 7// Each layer gets a name for readability, which is then used in the keymap matrix below.
@@ -148,8 +145,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
148 return update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST); 145 return update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST);
149} 146}
150 147
151//SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h 148#ifdef OLED_ENABLE
152#ifdef SSD1306OLED
153 149
154// You need to add source files to SRC in rules.mk when using OLED display functions 150// You need to add source files to SRC in rules.mk when using OLED display functions
155void set_keylog(uint16_t keycode); 151void set_keylog(uint16_t keycode);
@@ -157,25 +153,10 @@ const char *read_keylog(void);
157const char *read_modifier_state(void); 153const char *read_modifier_state(void);
158const char *read_host_led_state(void); 154const char *read_host_led_state(void);
159 155
160void matrix_init_user(void) { 156bool oled_task_user(void) {
161 iota_gfx_init(false); // turns on the display
162}
163
164void matrix_scan_user(void) {
165 iota_gfx_task(); // this is what updates the display continuously
166}
167
168void matrix_update(struct CharacterMatrix *dest, const struct CharacterMatrix *source) {
169 if (memcmp(dest->display, source->display, sizeof(dest->display))) {
170 memcpy(dest->display, source->display, sizeof(dest->display));
171 dest->dirty = true;
172 }
173}
174
175void render_status(struct CharacterMatrix *matrix) {
176 // Layer state 157 // Layer state
177 char layer_str[22]; 158 char layer_str[22];
178 matrix_write(matrix, "Layer: "); 159 oled_write_P(PSTR("Layer: "), false);
179 uint8_t layer = get_highest_layer(layer_state); 160 uint8_t layer = get_highest_layer(layer_state);
180 uint8_t default_layer = get_highest_layer(eeconfig_read_default_layer()); 161 uint8_t default_layer = get_highest_layer(eeconfig_read_default_layer());
181 switch (layer) { 162 switch (layer) {
@@ -207,27 +188,21 @@ void render_status(struct CharacterMatrix *matrix) {
207 default: 188 default:
208 snprintf(layer_str, sizeof(layer_str), "Undef-%d", layer); 189 snprintf(layer_str, sizeof(layer_str), "Undef-%d", layer);
209 } 190 }
210 matrix_write_ln(matrix, layer_str); 191 oled_write_ln(layer_str, false);
211 // Last entered keycode 192 // Last entered keycode
212 matrix_write_ln(matrix, read_keylog()); 193 oled_write_ln(read_keylog(), false);
213 // Modifier state 194 // Modifier state
214 matrix_write_ln(matrix, read_modifier_state()); 195 oled_write_ln(read_modifier_state(), false);
215 // Host Keyboard LED Status 196 // Host Keyboard LED Status
216 matrix_write(matrix, read_host_led_state()); 197 oled_write(read_host_led_state(), false);
217}
218 198
219 199 return false;
220void iota_gfx_task_user(void) {
221 struct CharacterMatrix matrix;
222 matrix_clear(&matrix);
223 render_status(&matrix);
224 matrix_update(&display, &matrix);
225} 200}
226 201
227#endif//SSD1306OLED 202#endif
228 203
229bool process_record_user(uint16_t keycode, keyrecord_t *record) { 204bool process_record_user(uint16_t keycode, keyrecord_t *record) {
230 #ifdef SSD1306OLED 205 #ifdef OLED_ENABLE
231 if (record->event.pressed) { 206 if (record->event.pressed) {
232 set_keylog(keycode); 207 set_keylog(keycode);
233 } 208 }
diff --git a/keyboards/satt/comet46/keymaps/default/rules.mk b/keyboards/satt/comet46/keymaps/default/rules.mk
index 3fa01f96af..3ceffe90ec 100644
--- a/keyboards/satt/comet46/keymaps/default/rules.mk
+++ b/keyboards/satt/comet46/keymaps/default/rules.mk
@@ -1,5 +1,6 @@
1# If you want to change display settings of the OLED, you need to change the following lines 1# If you want to change display settings of the OLED, you need to change the following lines
2SRC += ./lib/glcdfont.c \ 2SRC += ./lib/keylogger.c \
3 ./lib/keylogger.c \
4 ./lib/modifier_state_reader.c \ 3 ./lib/modifier_state_reader.c \
5 ./lib/host_led_state_reader.c 4 ./lib/host_led_state_reader.c
5
6OLED_ENABLE = yes
diff --git a/keyboards/satt/comet46/keymaps/satt/config.h b/keyboards/satt/comet46/keymaps/satt/config.h
deleted file mode 100644
index a3ca2ebfef..0000000000
--- a/keyboards/satt/comet46/keymaps/satt/config.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2This is the c configuration file for the keymap
3
4Copyright 2012 Jun Wako <wakojun@gmail.com>
5Copyright 2015 Jack Humbert
6
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#ifndef CONFIG_USER_H
22#define CONFIG_USER_H
23
24/* Use I2C or Serial */
25
26#define USE_I2C
27#define SSD1306OLED
28
29#endif
diff --git a/keyboards/satt/comet46/keymaps/satt/keymap.c b/keyboards/satt/comet46/keymaps/satt/keymap.c
index 54d1d791d7..505b7eaf0a 100644
--- a/keyboards/satt/comet46/keymaps/satt/keymap.c
+++ b/keyboards/satt/comet46/keymaps/satt/keymap.c
@@ -5,9 +5,6 @@
5#include "keymap_jis2us.h" 5#include "keymap_jis2us.h"
6#include "action_pseudo_lut.h" 6#include "action_pseudo_lut.h"
7#include "keymap_japanese.h" 7#include "keymap_japanese.h"
8#ifdef SSD1306OLED
9 #include "ssd1306.h"
10#endif
11 8
12// Each layer gets a name for readability, which is then used in the keymap matrix below. 9// Each layer gets a name for readability, which is then used in the keymap matrix below.
13// The underscores don't mean anything - you can have a layer called STUFF or any other name. 10// The underscores don't mean anything - you can have a layer called STUFF or any other name.
@@ -176,8 +173,7 @@ layer_state_t layer_state_set_user(layer_state_t state) {
176 } 173 }
177} 174}
178 175
179//SSD1306 OLED update loop, make sure to add #define SSD1306OLED in config.h 176#ifdef OLED_ENABLE
180#ifdef SSD1306OLED
181 177
182// You need to add source files to SRC in rules.mk when using OLED display functions 178// You need to add source files to SRC in rules.mk when using OLED display functions
183void set_keylog(uint16_t keycode); 179void set_keylog(uint16_t keycode);
@@ -185,86 +181,59 @@ const char *read_keylog(void);
185const char *read_modifier_state(void); 181const char *read_modifier_state(void);
186const char *read_host_led_state(void); 182const char *read_host_led_state(void);
187 183
188void matrix_init_user(void) { 184bool oled_task_user(void) {
189 iota_gfx_init(false); // turns on the display
190}
191
192void matrix_scan_user(void) {
193 iota_gfx_task(); // this is what updates the display continuously
194}
195
196void matrix_update(struct CharacterMatrix *dest, const struct CharacterMatrix *source) {
197 if (memcmp(dest->display, source->display, sizeof(dest->display))) {
198 memcpy(dest->display, source->display, sizeof(dest->display));
199 dest->dirty = true;
200 }
201}
202
203void render_status(struct CharacterMatrix *matrix) {
204 // Layer state 185 // Layer state
205 char layer_str[22]; 186 char layer_str[22];
206 matrix_write(matrix, "Layer: "); 187 oled_write_P(PSTR("Layer: "), false);
207 uint8_t layer = get_highest_layer(layer_state); 188 uint8_t layer = get_highest_layer(layer_state);
208 uint8_t default_layer = biton32(eeconfig_read_default_layer()); 189 uint8_t default_layer = get_highest_layer(eeconfig_read_default_layer());
209 switch (layer) { 190 switch (layer) {
210 case _QWERTY: 191 case _QWERTY:
211 switch (default_layer) { 192 switch (default_layer) {
212 case _QWERTY: 193 case _QWERTY:
213 snprintf(layer_str, sizeof(layer_str), "Qwerty"); 194 snprintf(layer_str, sizeof(layer_str), "Qwerty");
214 break; 195 break;
215 case _PSEUDO_US: 196 case _PSEUDO_US:
216 snprintf(layer_str, sizeof(layer_str), "Psuedo_US"); 197 snprintf(layer_str, sizeof(layer_str), "Psuedo_US");
217 break; 198 break;
218 default: 199 default:
219 snprintf(layer_str, sizeof(layer_str), "Undef-%d", default_layer); 200 snprintf(layer_str, sizeof(layer_str), "Undef-%d", default_layer);
220 break; 201 break;
221 } 202 }
222 break; 203 break;
223 case _RAISE: 204 case _RAISE:
224 snprintf(layer_str, sizeof(layer_str), "Raise"); 205 snprintf(layer_str, sizeof(layer_str), "Raise");
225 break; 206 break;
226 case _LOWER: 207 case _LOWER:
227 snprintf(layer_str, sizeof(layer_str), "Lower"); 208 snprintf(layer_str, sizeof(layer_str), "Lower");
228 break; 209 break;
229 case _PSEUDO_US_RAISE: 210 case _PSEUDO_US_RAISE:
230 snprintf(layer_str, sizeof(layer_str), "P_US_Raise"); 211 snprintf(layer_str, sizeof(layer_str), "P_US_Raise");
231 break; 212 break;
232 case _PSEUDO_US_LOWER: 213 case _PSEUDO_US_LOWER:
233 snprintf(layer_str, sizeof(layer_str), "P_US_Lower"); 214 snprintf(layer_str, sizeof(layer_str), "P_US_Lower");
234 break; 215 break;
235 case _ADJUST: 216 case _ADJUST:
236 snprintf(layer_str, sizeof(layer_str), "Adjust"); 217 snprintf(layer_str, sizeof(layer_str), "Adjust");
237 break; 218 break;
238 default: 219 default:
239 snprintf(layer_str, sizeof(layer_str), "Undef-%d", layer); 220 snprintf(layer_str, sizeof(layer_str), "Undef-%d", layer);
240 } 221 }
241 matrix_write_ln(matrix, layer_str); 222 oled_write_ln(layer_str, false);
242 // Last entered keycode 223 // Last entered keycode
243 matrix_write_ln(matrix, read_keylog()); 224 oled_write_ln(read_keylog(), false);
244 // Modifier state 225 // Modifier state
245 matrix_write_ln(matrix, read_modifier_state()); 226 oled_write_ln(read_modifier_state(), false);
246 // Host Keyboard LED Status 227 // Host Keyboard LED Status
247 matrix_write(matrix, read_host_led_state()); 228 oled_write(read_host_led_state(), false);
248}
249
250void iota_gfx_task_user(void) {
251 struct CharacterMatrix matrix;
252
253#if DEBUG_TO_SCREEN
254 if (debug_enable) {
255 return;
256 }
257#endif
258 229
259 matrix_clear(&matrix); 230 return false;
260 render_status(&matrix);
261 matrix_update(&display, &matrix);
262} 231}
263 232
264#endif//SSD1306OLED 233#endif
265 234
266bool process_record_user(uint16_t keycode, keyrecord_t *record) { 235bool process_record_user(uint16_t keycode, keyrecord_t *record) {
267 #ifdef SSD1306OLED 236 #ifdef OLED_ENABLE
268 if (record->event.pressed) { 237 if (record->event.pressed) {
269 set_keylog(keycode); 238 set_keylog(keycode);
270 } 239 }
diff --git a/keyboards/satt/comet46/keymaps/satt/rules.mk b/keyboards/satt/comet46/keymaps/satt/rules.mk
index 91609dd4fd..9c07b12fcb 100644
--- a/keyboards/satt/comet46/keymaps/satt/rules.mk
+++ b/keyboards/satt/comet46/keymaps/satt/rules.mk
@@ -1,8 +1,8 @@
1SRC += action_pseudo_lut.c 1SRC += action_pseudo_lut.c
2 2
3# If you want to change display settings of the OLED, you need to change the following lines 3# If you want to change display settings of the OLED, you need to change the following lines
4SRC += ./lib/glcdfont.c \ 4SRC += ./lib/keylogger.c \
5 ./lib/keylogger.c \
6 ./lib/modifier_state_reader.c \ 5 ./lib/modifier_state_reader.c \
7 ./lib/host_led_state_reader.c 6 ./lib/host_led_state_reader.c
8 7
8OLED_ENABLE = yes
diff --git a/keyboards/satt/comet46/lib/glcdfont.c b/keyboards/satt/comet46/lib/glcdfont.c
deleted file mode 100644
index 361d0c3dc6..0000000000
--- a/keyboards/satt/comet46/lib/glcdfont.c
+++ /dev/null
@@ -1,137 +0,0 @@
1// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
2// See gfxfont.h for newer custom bitmap font info.
3
4#include "progmem.h"
5
6// Standard ASCII 5x7 font
7
8const unsigned char font[] PROGMEM = {
9 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00,
11 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00,
12 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00,
13 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00,
14 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00,
15 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00,
16 0x00, 0x18, 0x3C, 0x18, 0x00, 0x00,
17 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00,
18 0x00, 0x18, 0x24, 0x18, 0x00, 0x00,
19 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00,
20 0x30, 0x48, 0x3A, 0x06, 0x0E, 0x00,
21 0x26, 0x29, 0x79, 0x29, 0x26, 0x00,
22 0x40, 0x7F, 0x05, 0x05, 0x07, 0x00,
23 0x40, 0x7F, 0x05, 0x25, 0x3F, 0x00,
24 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00,
25 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00,
26 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00,
27 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00,
28 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00,
29 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00,
30 0x00, 0x66, 0x89, 0x95, 0x6A, 0x00,
31 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
32 0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00,
33 0x08, 0x04, 0x7E, 0x04, 0x08, 0x00,
34 0x10, 0x20, 0x7E, 0x20, 0x10, 0x00,
35 0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00,
36 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x00,
37 0x1E, 0x10, 0x10, 0x10, 0x10, 0x00,
38 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x00,
39 0x30, 0x38, 0x3E, 0x38, 0x30, 0x00,
40 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00,
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00,
43 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
44 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00,
45 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00,
46 0x23, 0x13, 0x08, 0x64, 0x62, 0x00,
47 0x36, 0x49, 0x56, 0x20, 0x50, 0x00,
48 0x00, 0x08, 0x07, 0x03, 0x00, 0x00,
49 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00,
50 0x00, 0x41, 0x22, 0x1C, 0x00, 0x00,
51 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00,
52 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00,
53 0x00, 0x80, 0x70, 0x30, 0x00, 0x00,
54 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
55 0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
56 0x20, 0x10, 0x08, 0x04, 0x02, 0x00,
57 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00,
58 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00,
59 0x72, 0x49, 0x49, 0x49, 0x46, 0x00,
60 0x21, 0x41, 0x49, 0x4D, 0x33, 0x00,
61 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00,
62 0x27, 0x45, 0x45, 0x45, 0x39, 0x00,
63 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00,
64 0x41, 0x21, 0x11, 0x09, 0x07, 0x00,
65 0x36, 0x49, 0x49, 0x49, 0x36, 0x00,
66 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00,
67 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
68 0x00, 0x40, 0x34, 0x00, 0x00, 0x00,
69 0x00, 0x08, 0x14, 0x22, 0x41, 0x00,
70 0x14, 0x14, 0x14, 0x14, 0x14, 0x00,
71 0x00, 0x41, 0x22, 0x14, 0x08, 0x00,
72 0x02, 0x01, 0x59, 0x09, 0x06, 0x00,
73 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00,
74 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00,
75 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00,
76 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00,
77 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00,
78 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00,
79 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00,
80 0x3E, 0x41, 0x41, 0x51, 0x73, 0x00,
81 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00,
82 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00,
83 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00,
84 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00,
85 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00,
86 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00,
87 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00,
88 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00,
89 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00,
90 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00,
91 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00,
92 0x26, 0x49, 0x49, 0x49, 0x32, 0x00,
93 0x03, 0x01, 0x7F, 0x01, 0x03, 0x00,
94 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00,
95 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00,
96 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00,
97 0x63, 0x14, 0x08, 0x14, 0x63, 0x00,
98 0x03, 0x04, 0x78, 0x04, 0x03, 0x00,
99 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00,
100 0x00, 0x7F, 0x41, 0x41, 0x41, 0x00,
101 0x02, 0x04, 0x08, 0x10, 0x20, 0x00,
102 0x00, 0x41, 0x41, 0x41, 0x7F, 0x00,
103 0x04, 0x02, 0x01, 0x02, 0x04, 0x00,
104 0x40, 0x40, 0x40, 0x40, 0x40, 0x00,
105 0x00, 0x03, 0x07, 0x08, 0x00, 0x00,
106 0x20, 0x54, 0x54, 0x78, 0x40, 0x00,
107 0x7F, 0x28, 0x44, 0x44, 0x38, 0x00,
108 0x38, 0x44, 0x44, 0x44, 0x28, 0x00,
109 0x38, 0x44, 0x44, 0x28, 0x7F, 0x00,
110 0x38, 0x54, 0x54, 0x54, 0x18, 0x00,
111 0x00, 0x08, 0x7E, 0x09, 0x02, 0x00,
112 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00,
113 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00,
114 0x00, 0x44, 0x7D, 0x40, 0x00, 0x00,
115 0x20, 0x40, 0x40, 0x3D, 0x00, 0x00,
116 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00,
117 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00,
118 0x7C, 0x04, 0x78, 0x04, 0x78, 0x00,
119 0x7C, 0x08, 0x04, 0x04, 0x78, 0x00,
120 0x38, 0x44, 0x44, 0x44, 0x38, 0x00,
121 0xFC, 0x18, 0x24, 0x24, 0x18, 0x00,
122 0x18, 0x24, 0x24, 0x18, 0xFC, 0x00,
123 0x7C, 0x08, 0x04, 0x04, 0x08, 0x00,
124 0x48, 0x54, 0x54, 0x54, 0x24, 0x00,
125 0x04, 0x04, 0x3F, 0x44, 0x24, 0x00,
126 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00,
127 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00,
128 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00,
129 0x44, 0x28, 0x10, 0x28, 0x44, 0x00,
130 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00,
131 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00,
132 0x00, 0x08, 0x36, 0x41, 0x00, 0x00,
133 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
134 0x00, 0x41, 0x36, 0x08, 0x00, 0x00,
135 0x02, 0x01, 0x02, 0x04, 0x02, 0x00,
136 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00
137};
diff --git a/keyboards/satt/comet46/rules.mk b/keyboards/satt/comet46/rules.mk
index e177fc6441..83f7d905e9 100644
--- a/keyboards/satt/comet46/rules.mk
+++ b/keyboards/satt/comet46/rules.mk
@@ -17,9 +17,8 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
17RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow 17RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
18AUDIO_ENABLE = no # Audio output 18AUDIO_ENABLE = no # Audio output
19CUSTOM_MATRIX = lite 19CUSTOM_MATRIX = lite
20OLED_DRIVER = SSD1306
20 21
21# project specific files 22# project specific files
22SRC += matrix.c \ 23SRC += matrix.c
23 i2c.c \
24 ssd1306.c
25QUANTUM_LIB_SRC += uart.c 24QUANTUM_LIB_SRC += uart.c
diff --git a/keyboards/satt/comet46/ssd1306.c b/keyboards/satt/comet46/ssd1306.c
deleted file mode 100644
index 4bd2d80bc4..0000000000
--- a/keyboards/satt/comet46/ssd1306.c
+++ /dev/null
@@ -1,343 +0,0 @@
1#ifdef SSD1306OLED
2
3#include "ssd1306.h"
4#include "i2c.h"
5#include <string.h>
6#include "print.h"
7#ifdef PROTOCOL_LUFA
8#include "lufa.h"
9#endif
10#include "sendchar.h"
11#include "timer.h"
12
13struct CharacterMatrix display;
14
15extern const unsigned char font[] PROGMEM;
16
17// Set this to 1 to help diagnose early startup problems
18// when testing power-on with ble. Turn it off otherwise,
19// as the latency of printing most of the debug info messes
20// with the matrix scan, causing keys to drop.
21#define DEBUG_TO_SCREEN 0
22
23//static uint16_t last_battery_update;
24//static uint32_t vbat;
25//#define BatteryUpdateInterval 10000 /* milliseconds */
26
27// 'last_flush' is declared as uint16_t,
28// so this must be less than 65535
29#define ScreenOffInterval 60000 /* milliseconds */
30#if DEBUG_TO_SCREEN
31static uint8_t displaying;
32#endif
33static uint16_t last_flush;
34
35static bool force_dirty = true;
36
37// Write command sequence.
38// Returns true on success.
39static inline bool _send_cmd1(uint8_t cmd) {
40 bool res = false;
41
42 if (i2c_start_write(SSD1306_ADDRESS)) {
43 xprintf("failed to start write to %d\n", SSD1306_ADDRESS);
44 goto done;
45 }
46
47 if (i2c_master_write(0x0 /* command byte follows */)) {
48 print("failed to write control byte\n");
49
50 goto done;
51 }
52
53 if (i2c_master_write(cmd)) {
54 xprintf("failed to write command %d\n", cmd);
55 goto done;
56 }
57 res = true;
58done:
59 i2c_master_stop();
60 return res;
61}
62
63// Write 2-byte command sequence.
64// Returns true on success
65static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) {
66 if (!_send_cmd1(cmd)) {
67 return false;
68 }
69 return _send_cmd1(opr);
70}
71
72// Write 3-byte command sequence.
73// Returns true on success
74static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) {
75 if (!_send_cmd1(cmd)) {
76 return false;
77 }
78 if (!_send_cmd1(opr1)) {
79 return false;
80 }
81 return _send_cmd1(opr2);
82}
83
84#define send_cmd1(c) if (!_send_cmd1(c)) {goto done;}
85#define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;}
86#define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;}
87
88static void clear_display(void) {
89 matrix_clear(&display);
90
91 // Clear all of the display bits (there can be random noise
92 // in the RAM on startup)
93 send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
94 send_cmd3(ColumnAddr, 0, DisplayWidth - 1);
95
96 if (i2c_start_write(SSD1306_ADDRESS)) {
97 goto done;
98 }
99 if (i2c_master_write(0x40)) {
100 // Data mode
101 goto done;
102 }
103 for (uint8_t row = 0; row < MatrixRows; ++row) {
104 for (uint8_t col = 0; col < DisplayWidth; ++col) {
105 i2c_master_write(0);
106 }
107 }
108
109 display.dirty = false;
110
111done:
112 i2c_master_stop();
113}
114
115#if DEBUG_TO_SCREEN
116#undef sendchar
117static int8_t capture_sendchar(uint8_t c) {
118 sendchar(c);
119 iota_gfx_write_char(c);
120
121 if (!displaying) {
122 iota_gfx_flush();
123 }
124 return 0;
125}
126#endif
127
128bool iota_gfx_init(bool rotate) {
129 bool success = false;
130
131 i2c_master_init();
132 send_cmd1(DisplayOff);
133 send_cmd2(SetDisplayClockDiv, 0x80);
134 send_cmd2(SetMultiPlex, DisplayHeight - 1);
135
136 send_cmd2(SetDisplayOffset, 0);
137
138
139 send_cmd1(SetStartLine | 0x0);
140 send_cmd2(SetChargePump, 0x14 /* Enable */);
141 send_cmd2(SetMemoryMode, 0 /* horizontal addressing */);
142
143 if(rotate){
144 // the following Flip the display orientation 180 degrees
145 send_cmd1(SegRemap);
146 send_cmd1(ComScanInc);
147 }else{
148 // Flips the display orientation 0 degrees
149 send_cmd1(SegRemap | 0x1);
150 send_cmd1(ComScanDec);
151 }
152
153 send_cmd2(SetComPins, 0x2);
154 send_cmd2(SetContrast, 0x8f);
155 send_cmd2(SetPreCharge, 0xf1);
156 send_cmd2(SetVComDetect, 0x40);
157 send_cmd1(DisplayAllOnResume);
158 send_cmd1(NormalDisplay);
159 send_cmd1(DeActivateScroll);
160 send_cmd1(DisplayOn);
161
162 send_cmd2(SetContrast, 0); // Dim
163
164 clear_display();
165
166 success = true;
167
168 iota_gfx_flush();
169
170#if DEBUG_TO_SCREEN
171 print_set_sendchar(capture_sendchar);
172#endif
173
174done:
175 return success;
176}
177
178bool iota_gfx_off(void) {
179 bool success = false;
180
181 send_cmd1(DisplayOff);
182 success = true;
183
184done:
185 return success;
186}
187
188bool iota_gfx_on(void) {
189 bool success = false;
190
191 send_cmd1(DisplayOn);
192 success = true;
193
194done:
195 return success;
196}
197
198void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
199 *matrix->cursor = c;
200 ++matrix->cursor;
201
202 if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
203 // We went off the end; scroll the display upwards by one line
204 memmove(&matrix->display[0], &matrix->display[1],
205 MatrixCols * (MatrixRows - 1));
206 matrix->cursor = &matrix->display[MatrixRows - 1][0];
207 memset(matrix->cursor, ' ', MatrixCols);
208 }
209}
210
211void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
212 matrix->dirty = true;
213
214 if (c == '\n') {
215 // Clear to end of line from the cursor and then move to the
216 // start of the next line
217 uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
218
219 while (cursor_col++ < MatrixCols) {
220 matrix_write_char_inner(matrix, ' ');
221 }
222 return;
223 }
224
225 matrix_write_char_inner(matrix, c);
226}
227
228void iota_gfx_write_char(uint8_t c) {
229 matrix_write_char(&display, c);
230}
231
232void matrix_write(struct CharacterMatrix *matrix, const char *data) {
233 const char *end = data + strlen(data);
234 while (data < end) {
235 matrix_write_char(matrix, *data);
236 ++data;
237 }
238}
239
240void matrix_write_ln(struct CharacterMatrix *matrix, const char *data) {
241 char data_ln[strlen(data)+2];
242 snprintf(data_ln, sizeof(data_ln), "%s\n", data);
243 matrix_write(matrix, data_ln);
244}
245
246void iota_gfx_write(const char *data) {
247 matrix_write(&display, data);
248}
249
250void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
251 while (true) {
252 uint8_t c = pgm_read_byte(data);
253 if (c == 0) {
254 return;
255 }
256 matrix_write_char(matrix, c);
257 ++data;
258 }
259}
260
261void iota_gfx_write_P(const char *data) {
262 matrix_write_P(&display, data);
263}
264
265void matrix_clear(struct CharacterMatrix *matrix) {
266 memset(matrix->display, ' ', sizeof(matrix->display));
267 matrix->cursor = &matrix->display[0][0];
268 matrix->dirty = true;
269}
270
271void iota_gfx_clear_screen(void) {
272 matrix_clear(&display);
273}
274
275void matrix_render(struct CharacterMatrix *matrix) {
276 last_flush = timer_read();
277 iota_gfx_on();
278#if DEBUG_TO_SCREEN
279 ++displaying;
280#endif
281
282 // Move to the home position
283 send_cmd3(PageAddr, 0, MatrixRows - 1);
284 send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1);
285
286 if (i2c_start_write(SSD1306_ADDRESS)) {
287 goto done;
288 }
289 if (i2c_master_write(0x40)) {
290 // Data mode
291 goto done;
292 }
293
294 for (uint8_t row = 0; row < MatrixRows; ++row) {
295 for (uint8_t col = 0; col < MatrixCols; ++col) {
296 const uint8_t *glyph = font + (matrix->display[row][col] * FontWidth);
297
298 for (uint8_t glyphCol = 0; glyphCol < FontWidth; ++glyphCol) {
299 uint8_t colBits = pgm_read_byte(glyph + glyphCol);
300 i2c_master_write(colBits);
301 }
302
303 // 1 column of space between chars (it's not included in the glyph)
304 //i2c_master_write(0);
305 }
306 }
307
308 matrix->dirty = false;
309
310done:
311 i2c_master_stop();
312#if DEBUG_TO_SCREEN
313 --displaying;
314#endif
315}
316
317void iota_gfx_flush(void) {
318 matrix_render(&display);
319}
320
321__attribute__ ((weak))
322void iota_gfx_task_user(void) {
323}
324
325void iota_gfx_task(void) {
326 iota_gfx_task_user();
327
328 if (display.dirty|| force_dirty) {
329 iota_gfx_flush();
330 force_dirty = false;
331 }
332
333 if (timer_elapsed(last_flush) > ScreenOffInterval) {
334 iota_gfx_off();
335 }
336}
337
338bool process_record_gfx(uint16_t keycode, keyrecord_t *record) {
339 force_dirty = true;
340 return true;
341}
342
343#endif
diff --git a/keyboards/satt/comet46/ssd1306.h b/keyboards/satt/comet46/ssd1306.h
deleted file mode 100644
index 11a3cc67f4..0000000000
--- a/keyboards/satt/comet46/ssd1306.h
+++ /dev/null
@@ -1,90 +0,0 @@
1#pragma once
2
3#include <stdbool.h>
4#include <stdio.h>
5#include "action.h"
6
7enum ssd1306_cmds {
8 DisplayOff = 0xAE,
9 DisplayOn = 0xAF,
10
11 SetContrast = 0x81,
12 DisplayAllOnResume = 0xA4,
13
14 DisplayAllOn = 0xA5,
15 NormalDisplay = 0xA6,
16 InvertDisplay = 0xA7,
17 SetDisplayOffset = 0xD3,
18 SetComPins = 0xda,
19 SetVComDetect = 0xdb,
20 SetDisplayClockDiv = 0xD5,
21 SetPreCharge = 0xd9,
22 SetMultiPlex = 0xa8,
23 SetLowColumn = 0x00,
24 SetHighColumn = 0x10,
25 SetStartLine = 0x40,
26
27 SetMemoryMode = 0x20,
28 ColumnAddr = 0x21,
29 PageAddr = 0x22,
30
31 ComScanInc = 0xc0,
32 ComScanDec = 0xc8,
33 SegRemap = 0xa0,
34 SetChargePump = 0x8d,
35 ExternalVcc = 0x01,
36 SwitchCapVcc = 0x02,
37
38 ActivateScroll = 0x2f,
39 DeActivateScroll = 0x2e,
40 SetVerticalScrollArea = 0xa3,
41 RightHorizontalScroll = 0x26,
42 LeftHorizontalScroll = 0x27,
43 VerticalAndRightHorizontalScroll = 0x29,
44 VerticalAndLeftHorizontalScroll = 0x2a,
45};
46
47// Controls the SSD1306 128x32 OLED display via i2c
48
49#ifndef SSD1306_ADDRESS
50#define SSD1306_ADDRESS 0x3C
51#endif
52
53#define DisplayHeight 32
54#define DisplayWidth 128
55
56#define FontHeight 8
57#define FontWidth 6
58
59#define MatrixRows (DisplayHeight / FontHeight)
60#define MatrixCols (DisplayWidth / FontWidth)
61
62struct CharacterMatrix {
63 uint8_t display[MatrixRows][MatrixCols];
64 uint8_t *cursor;
65 bool dirty;
66};
67
68extern struct CharacterMatrix display;
69
70bool iota_gfx_init(bool rotate);
71void iota_gfx_task(void);
72bool iota_gfx_off(void);
73bool iota_gfx_on(void);
74void iota_gfx_flush(void);
75void iota_gfx_write_char(uint8_t c);
76void iota_gfx_write(const char *data);
77void iota_gfx_write_P(const char *data);
78void iota_gfx_clear_screen(void);
79
80void iota_gfx_task_user(void);
81
82void matrix_clear(struct CharacterMatrix *matrix);
83void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c);
84void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c);
85void matrix_write(struct CharacterMatrix *matrix, const char *data);
86void matrix_write_ln(struct CharacterMatrix *matrix, const char *data);
87void matrix_write_P(struct CharacterMatrix *matrix, const char *data);
88void matrix_render(struct CharacterMatrix *matrix);
89
90bool process_record_gfx(uint16_t keycode, keyrecord_t *record);