aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrashna Jaelre <drashna@live.com>2022-01-21 19:36:52 -0800
committerGitHub <noreply@github.com>2022-01-21 19:36:52 -0800
commitb090ff03ed4391f27e8e3d9a843f529bedd08e19 (patch)
treee734aa4541f05ed4f919f86ff36d85cbd17f795a
parent8901c9eca1db8d10b06f544553a5fc941eda51ae (diff)
downloadqmk_firmware-b090ff03ed4391f27e8e3d9a843f529bedd08e19.tar.gz
qmk_firmware-b090ff03ed4391f27e8e3d9a843f529bedd08e19.zip
[Keymap] Drashna's OLED rewrite (#15981)
-rw-r--r--keyboards/handwired/tractyl_manuform/5x6_right/config.h2
-rw-r--r--keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h1
-rw-r--r--keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h11
-rw-r--r--keyboards/handwired/tractyl_manuform/5x6_right/f411/post_config.h20
-rw-r--r--keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h6
-rw-r--r--keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c145
-rw-r--r--keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk2
-rw-r--r--keyboards/handwired/tractyl_manuform/tractyl_manuform.h2
-rw-r--r--keyboards/moonlander/keymaps/drashna/keymap.c2
-rw-r--r--keyboards/splitkb/kyria/keymaps/drashna/keymap.c2
-rw-r--r--layouts/community/ergodox/drashna/keymap.c4
-rw-r--r--layouts/community/ergodox/drashna/rules.mk3
-rw-r--r--layouts/community/ortho_4x12/drashna/keymap.c2
-rw-r--r--layouts/community/split_3x6_3/drashna/keymap.c2
-rw-r--r--users/drashna/callbacks.c15
-rw-r--r--users/drashna/config.h20
-rw-r--r--users/drashna/drashna.c96
-rw-r--r--users/drashna/drashna.h3
-rw-r--r--users/drashna/keyrecords/autocorrection/autocorrection.c19
-rw-r--r--users/drashna/keyrecords/caps_word.c10
-rw-r--r--users/drashna/keyrecords/process_records.c23
-rw-r--r--users/drashna/keyrecords/tap_dances.c12
-rw-r--r--users/drashna/keyrecords/unicode.c27
-rw-r--r--users/drashna/oled/oled_stuff.c670
-rw-r--r--users/drashna/oled/oled_stuff.h22
-rw-r--r--users/drashna/oled/sh110x.c860
-rw-r--r--users/drashna/pointing/pointing.c2
-rw-r--r--users/drashna/rules.mk13
-rw-r--r--users/drashna/split/transport_sync.c65
-rw-r--r--users/drashna/split/transport_sync.h4
30 files changed, 1773 insertions, 292 deletions
diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/config.h
index d7618912f..59cd098fd 100644
--- a/keyboards/handwired/tractyl_manuform/5x6_right/config.h
+++ b/keyboards/handwired/tractyl_manuform/5x6_right/config.h
@@ -50,7 +50,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
50#define NO_ACTION_MACRO 50#define NO_ACTION_MACRO
51#define NO_ACTION_FUNCTION 51#define NO_ACTION_FUNCTION
52 52
53#define OLED_DISPLAY_128X64
54
55#define POINTING_DEVICE_TASK_THROTTLE 53#define POINTING_DEVICE_TASK_THROTTLE
56#define POINTING_DEVICE_RIGHT 54#define POINTING_DEVICE_RIGHT
diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h
index 9daec0cd8..d8d36e824 100644
--- a/keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h
+++ b/keyboards/handwired/tractyl_manuform/5x6_right/elite_c/config.h
@@ -35,7 +35,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
35#define RGBLED_SPLIT \ 35#define RGBLED_SPLIT \
36 { 10, 10 } 36 { 10, 10 }
37#define RGBLIGHT_LIMIT_VAL 80 37#define RGBLIGHT_LIMIT_VAL 80
38#define OLED_BRIGHTNESS 50
39 38
40#define AUDIO_PIN C6 39#define AUDIO_PIN C6
41 40
diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h
index 986ccae69..6ae51ca6f 100644
--- a/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h
+++ b/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h
@@ -43,12 +43,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
43//#define WS2812_PWM_COMPLEMENTARY_OUTPUT // Define for a complementary timer output (TIMx_CHyN); omit for a normal timer output (TIMx_CHy). 43//#define WS2812_PWM_COMPLEMENTARY_OUTPUT // Define for a complementary timer output (TIMx_CHyN); omit for a normal timer output (TIMx_CHy).
44#define WS2812_DMA_STREAM STM32_DMA1_STREAM7 // DMA Stream for TIMx_UP, see the respective reference manual for the appropriate values for your MCU. 44#define WS2812_DMA_STREAM STM32_DMA1_STREAM7 // DMA Stream for TIMx_UP, see the respective reference manual for the appropriate values for your MCU.
45#define WS2812_DMA_CHANNEL 3 // DMA Channel for TIMx_UP, see the respective reference manual for the appropriate values for your MCU. 45#define WS2812_DMA_CHANNEL 3 // DMA Channel for TIMx_UP, see the respective reference manual for the appropriate values for your MCU.
46#define WS2812_PWM_TARGET_PERIOD 800000
47
46 48
47#define RGBLED_NUM 52 49#define RGBLED_NUM 52
48#define RGBLIGHT_SPLIT 50#define RGBLIGHT_SPLIT
49#define RGBLED_SPLIT \ 51#define RGBLED_SPLIT \
50 { 26, 26 } 52 { 26, 26 }
51#define RGBLIGHT_LIMIT_VAL 150
52 53
53#define DEBUG_LED_PIN C13 54#define DEBUG_LED_PIN C13
54 55
@@ -68,6 +69,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
68#define SERIAL_USART_RX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7 69#define SERIAL_USART_RX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
69#define SERIAL_USART_TIMEOUT 100 // USART driver timeout. default 100 70#define SERIAL_USART_TIMEOUT 100 // USART driver timeout. default 100
70 71
72
73#define CRC8_USE_TABLE
74#define CRC8_OPTIMIZE_SPEED
75
71/* i2c config for oleds */ 76/* i2c config for oleds */
72#define I2C_DRIVER I2CD1 77#define I2C_DRIVER I2CD1
73#define I2C1_SCL_PIN B8 78#define I2C1_SCL_PIN B8
@@ -75,9 +80,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
75#define I2C1_SCL_PAL_MODE 4 80#define I2C1_SCL_PAL_MODE 4
76#define I2C1_SDA_PAL_MODE 4 81#define I2C1_SDA_PAL_MODE 4
77// #define I2C1_CLOCK_SPEED 400000 82// #define I2C1_CLOCK_SPEED 400000
78/* For Legacy Compatibility: */
79#define I2C1_SCL 8
80#define I2C1_SDA 9
81 83
82/* encoder config */ 84/* encoder config */
83#define ENCODERS_PAD_A \ 85#define ENCODERS_PAD_A \
@@ -110,3 +112,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
110#define PMW3360_CS_PIN B0 112#define PMW3360_CS_PIN B0
111#define PMW3360_SPI_MODE 3 113#define PMW3360_SPI_MODE 3
112#define PMW3360_SPI_DIVISOR 64 114#define PMW3360_SPI_DIVISOR 64
115#define PMW3360_FIRMWARE_UPLOAD_FAST
diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/f411/post_config.h b/keyboards/handwired/tractyl_manuform/5x6_right/f411/post_config.h
new file mode 100644
index 000000000..0e33129e1
--- /dev/null
+++ b/keyboards/handwired/tractyl_manuform/5x6_right/f411/post_config.h
@@ -0,0 +1,20 @@
1// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#ifndef RGBLIGHT_LIMIT_VAL
7# if defined(OLED_ENABLE)
8# define RGBLIGHT_LIMIT_VAL 100
9# else
10# define RGBLIGHT_LIMIT_VAL 150
11# endif
12#endif
13
14#ifndef OLED_BRIGHTNESS
15# ifdef RGBLIGHT_ENABLE
16# define OLED_BRIGHTNESS 80
17# else
18# define OLED_BRIGHTNESS 150
19# endif
20#endif
diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h
index 85ddef103..0b33138ec 100644
--- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h
+++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h
@@ -18,5 +18,9 @@
18 18
19#define TRACKBALL_DPI_OPTIONS { 1200, 1800, 2600, 3400 } 19#define TRACKBALL_DPI_OPTIONS { 1200, 1800, 2600, 3400 }
20 20
21#define DEBOUNCE 45 21#define DEBOUNCE 60
22#define ENCODER_DEFAULT_POS 0x3 22#define ENCODER_DEFAULT_POS 0x3
23
24#ifdef OLED_DRIVER_SH1107
25# undef OLED_DISPLAY_128X64
26#endif
diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c
index 958f69417..b5310b37d 100644
--- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c
+++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c
@@ -125,7 +125,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
125 KEYLOCK, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS, 125 KEYLOCK, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
126 UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY, 126 UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY,
127 TG(_DIABLOII), AUTO_CTN, TG_GAME, TG_DBLO, 127 TG(_DIABLOII), AUTO_CTN, TG_GAME, TG_DBLO,
128 _______, _______, KC_NUKE, 128 _______, REBOOT, KC_NUKE,
129 _______, _______, _______, 129 _______, _______, _______,
130 _______, _______, KC_NUKE, _______ 130 _______, _______, KC_NUKE, _______
131 ), 131 ),
@@ -145,7 +145,7 @@ const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
145 [_MEDIA] = { { _______, _______ }, { _______, _______ } }, 145 [_MEDIA] = { { _______, _______ }, { _______, _______ } },
146 [_RAISE] = { { _______, _______ }, { KC_PGDN, KC_PGUP } }, 146 [_RAISE] = { { _______, _______ }, { KC_PGDN, KC_PGUP } },
147 [_LOWER] = { { RGB_MOD, RGB_RMOD}, { RGB_HUD, RGB_HUI } }, 147 [_LOWER] = { { RGB_MOD, RGB_RMOD}, { RGB_HUD, RGB_HUI } },
148 [_ADJUST] = { { CK_DOWN, CK_UP }, { _______, _______ } }, 148 [_ADJUST] = { { CK_DOWN, CK_UP }, { _______, _F______ } },
149}; 149};
150// clang-format on 150// clang-format on
151#else 151#else
@@ -165,144 +165,5 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
165#endif 165#endif
166 166
167#ifdef OLED_ENABLE 167#ifdef OLED_ENABLE
168// WPM-responsive animation stuff here 168oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return OLED_ROTATION_180; }
169# define SLEEP_FRAMES 2
170# define SLEEP_SPEED 10 // below this wpm value your animation will idle
171
172# define WAKE_FRAMES 2 // uncomment if >1
173
174# define KAKI_FRAMES 3
175# define KAKI_SPEED 40 // above this wpm value typing animation to triggere
176
177# define RTOGI_FRAMES 2
178//#define LTOGI_FRAMES 2
179
180//#define ANIM_FRAME_DURATION 500 // how long each frame lasts in ms
181// #define SLEEP_TIMER 60000 // should sleep after this period of 0 wpm, needs fixing
182# define ANIM_SIZE 512 // number of bytes in array, minimize for adequate firmware size, max is 1024
183
184uint32_t anim_timer = 0;
185uint32_t anim_frame_duration = 500;
186uint8_t current_sleep_frame = 0;
187uint8_t current_wake_frame = 0; // uncomment if WAKE_FRAMES >1
188uint8_t current_kaki_frame = 0;
189uint8_t current_rtogi_frame = 0;
190// uint8_t current_ltogi_frame = 0;
191
192void render_kitty(void) {
193 // Images credit j-inc(/James Incandenza) and pixelbenny. Credit to obosob for initial animation approach.
194 static const char PROGMEM sleep[SLEEP_FRAMES][ANIM_SIZE] = {{
195 // 'sleep1', 128x32px
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0xa8, 0x48, 0xa8, 0x18, 0x08, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x80, 0x44, 0x84, 0x06, 0x05, 0x04, 0x80, 0x40, 0x20, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x18, 0x04, 0x04, 0x02, 0x7a, 0x86, 0x01, 0x80, 0x80, 0x01, 0x03, 0x05, 0x07, 0x01, 0x00, 0x00, 0x80, 0x83, 0x45, 0xfa, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x33, 0x24, 0x28, 0x28, 0x29, 0x29, 0x29, 0x3a, 0x18, 0x1c, 0x39, 0x24, 0x24, 0x3a, 0x2d, 0x26, 0x31, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 },
201 {// 'sleep2', 128x32px
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x3a, 0x2a, 0x26, 0x22, 0x80, 0xc0, 0x80, 0x00, 0x24, 0x34, 0x2c, 0xe4, 0x60, 0x10, 0x70, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38, 0x04, 0x02, 0x02, 0x01, 0x79, 0x87, 0x01, 0x80, 0x81, 0x83, 0x05, 0x05, 0x03, 0x01, 0x00, 0x00, 0x80, 0x43, 0x05, 0xfa, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x33, 0x24, 0x28, 0x28, 0x28, 0x29, 0x29, 0x3a, 0x18, 0x1c, 0x39, 0x24, 0x24, 0x3a, 0x2d, 0x26, 0x31, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
206 static const char PROGMEM wake[WAKE_FRAMES][ANIM_SIZE] = {{
207 // 'mati2', 128x32px
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x30, 0x08, 0x10, 0x60, 0x80, 0x00, 0x80, 0x60, 0x10, 0x08, 0x30, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x40, 0x40, 0x5c, 0x00, 0x01, 0x41, 0x01, 0x00, 0x5c, 0x40, 0x40, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x80, 0xe1, 0x12, 0x0a, 0x06, 0x00, 0x80, 0x00, 0x06, 0x0a, 0x12, 0xe1, 0x80, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x11, 0x10, 0x10, 0x14, 0x14, 0x1f, 0x1c, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 },
213 {// 'mati3', 128x32px
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x30, 0x08, 0x10, 0x60, 0x80, 0x00, 0x80, 0x60, 0x10, 0x08, 0x30, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x90, 0x12, 0x0a, 0x02, 0xf4, 0x09, 0x0d, 0xf1, 0x04, 0x02, 0x0a, 0x12, 0x90, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x80, 0xe1, 0x12, 0x0a, 0x06, 0x01, 0x81, 0x00, 0x06, 0x0a, 0x12, 0xe1, 0x80, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x11, 0x10, 0x10, 0x14, 0x14, 0x1f, 0x1c, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
218 static const char PROGMEM kaki[KAKI_FRAMES][ANIM_SIZE] = {{
219 // 'jare2', 128x32px
220 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x40, 0x80, 0x80, 0x80, 0x00, 0xfc, 0x84, 0x08, 0x08, 0x10, 0x20, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1e, 0x60, 0x80, 0x00, 0x00, 0x91, 0xa1, 0x80, 0x00, 0x00, 0x22, 0x84, 0x40, 0x50, 0x48, 0xc1, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x41, 0x82, 0xe2, 0x12, 0x0a, 0x06, 0x00, 0x80, 0x88, 0x4f, 0x02, 0x22, 0xe2, 0x9f, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10, 0x14, 0x14, 0x1f, 0x1a, 0x0a, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 },
225 {
226 // 'kaki1', 128x32px
227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x06, 0x1a, 0x22, 0xc2, 0x04, 0x04, 0x04, 0x07, 0x00, 0xc0, 0x20, 0x10, 0x80, 0x80, 0x01, 0x01, 0x02, 0xfc, 0xfe, 0x02, 0x3c, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d, 0x55, 0x50, 0x94, 0xf0, 0x10, 0x09, 0x08, 0x00, 0x80, 0x00, 0x06, 0x09, 0x1b, 0xee, 0x00, 0x00, 0x00, 0x00, 0x81, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c, 0x14, 0x16, 0x15, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 },
232 {// 'kaki2', 128x32px
233 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x01, 0x02, 0x04, 0x04, 0x03, 0x80, 0x40, 0x40, 0x20, 0x00, 0x01, 0x02, 0x8c, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d, 0x55, 0x50, 0x94, 0xf0, 0x10, 0x0a, 0x0e, 0x1d, 0x95, 0x24, 0x24, 0x27, 0x13, 0xe1, 0x01, 0x01, 0x01, 0x01, 0x02, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
237 static const char PROGMEM rtogi[KAKI_FRAMES][ANIM_SIZE] = {{
238 // 'rtogi1', 128x32px
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x0f, 0x90, 0x10, 0x20, 0xf0, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x48, 0x47, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x88, 0xc7, 0xc4, 0x62, 0x23, 0x11, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x80, 0x40, 0x20, 0x10, 0x88, 0xcc, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c, 0x04, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, 0x05, 0x04, 0x04, 0x04, 0x07, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 },
244 {// 'rtogi2', 128x32px
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1f, 0xa0, 0x20, 0x40, 0x80, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x48, 0x47, 0x88, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x28, 0x6b, 0x40, 0xa0, 0x99, 0x86, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x0f, 0x11, 0x22, 0x44, 0x48, 0x4c, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c, 0x04, 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x06, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, 0x05, 0x04, 0x04, 0x04, 0x07, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
249
250 // assumes 1 frame prep stage
251 void animation_phase(void) {
252 if (tap_toggling) {
253 anim_frame_duration = 300;
254 current_rtogi_frame = (current_rtogi_frame + 1) % RTOGI_FRAMES;
255 oled_write_raw_P(rtogi[abs((RTOGI_FRAMES - 1) - current_rtogi_frame)], ANIM_SIZE);
256 } else {
257 if (get_current_wpm() <= SLEEP_SPEED) {
258 anim_frame_duration = 500;
259 current_sleep_frame = (current_sleep_frame + 1) % SLEEP_FRAMES;
260 oled_write_raw_P(sleep[abs((SLEEP_FRAMES - 1) - current_sleep_frame)], ANIM_SIZE);
261 }
262 // if(get_current_wpm() >IDLE_SPEED && get_current_wpm() <TAP_SPEED){
263 if (get_current_wpm() > SLEEP_SPEED) {
264 anim_frame_duration = 800;
265 current_wake_frame = (current_wake_frame + 1) % WAKE_FRAMES;
266 oled_write_raw_P(wake[abs((WAKE_FRAMES - 1) - current_wake_frame)], ANIM_SIZE);
267 // oled_write_raw_P(wake[0], ANIM_SIZE); // remove if IDLE_FRAMES >1
268 }
269 if (get_current_wpm() >= KAKI_SPEED) {
270 anim_frame_duration = 500;
271 current_kaki_frame = (current_kaki_frame + 1) % KAKI_FRAMES;
272 oled_write_raw_P(kaki[abs((KAKI_FRAMES - 1) - current_kaki_frame)], ANIM_SIZE);
273 }
274 }
275 }
276 if (get_current_wpm() != 000) {
277 // if(timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) {
278 if (timer_elapsed32(anim_timer) > anim_frame_duration) {
279 anim_timer = timer_read32();
280 animation_phase();
281 }
282 } else {
283 // if(timer_elapsed32(anim_timer) > ANIM_FRAME_DURATION) {
284 if (timer_elapsed32(anim_timer) > anim_frame_duration) {
285 anim_timer = timer_read32();
286 animation_phase();
287 }
288 }
289}
290
291void oled_driver_render_logo_left(void) {
292 render_kitty();
293
294 oled_set_cursor(6, 0);
295 oled_write_P(PSTR(" Tractyl "), false);
296 oled_set_cursor(6, 1);
297 oled_write_P(PSTR(" Manuform "), false);
298 oled_set_cursor(6, 2);
299# if defined(WPM_ENABLE)
300 render_wpm(1);
301# endif
302 oled_set_cursor(6, 3);
303# if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
304 render_pointing_dpi_status(0);
305# endif
306 oled_set_cursor(0, 4);
307}
308#endif 169#endif
diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk
index 0765bb2c6..9ef58ab5e 100644
--- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk
+++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk
@@ -32,3 +32,5 @@ ifeq ($(strip $(KEYBOARD)), handwired/tractyl_manuform/5x6_right/teensy2pp)
32 CAPS_WORD_ENABLE = yes 32 CAPS_WORD_ENABLE = yes
33endif 33endif
34# DEBOUNCE_TYPE = sym_eager_pk 34# DEBOUNCE_TYPE = sym_eager_pk
35
36OLED_DRIVER = custom
diff --git a/keyboards/handwired/tractyl_manuform/tractyl_manuform.h b/keyboards/handwired/tractyl_manuform/tractyl_manuform.h
index 6aa40fc18..c3acade6f 100644
--- a/keyboards/handwired/tractyl_manuform/tractyl_manuform.h
+++ b/keyboards/handwired/tractyl_manuform/tractyl_manuform.h
@@ -43,6 +43,8 @@ typedef struct {
43 uint16_t device_cpi; 43 uint16_t device_cpi;
44} kb_config_data_t; 44} kb_config_data_t;
45 45
46extern kb_config_data_t kb_config;
47
46void trackball_set_cpi(uint16_t cpi); 48void trackball_set_cpi(uint16_t cpi);
47void matrix_init_sub_kb(void); 49void matrix_init_sub_kb(void);
48void matrix_scan_sub_kb(void); 50void matrix_scan_sub_kb(void);
diff --git a/keyboards/moonlander/keymaps/drashna/keymap.c b/keyboards/moonlander/keymaps/drashna/keymap.c
index 82abdb005..ba0783461 100644
--- a/keyboards/moonlander/keymaps/drashna/keymap.c
+++ b/keyboards/moonlander/keymaps/drashna/keymap.c
@@ -111,7 +111,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
111 KEYLOCK, _________________ADJUST_L2_________________, _______, _______, _________________ADJUST_R2_________________, RGB_IDL, 111 KEYLOCK, _________________ADJUST_L2_________________, _______, _______, _________________ADJUST_R2_________________, RGB_IDL,
112 UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS, 112 UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS,
113 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, AUTO_CTN, 113 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, AUTO_CTN,
114 _______, _______, _______, _______, _______, _______ 114 REBOOT, _______, _______, _______, _______, _______
115 ), 115 ),
116}; 116};
117 117
diff --git a/keyboards/splitkb/kyria/keymaps/drashna/keymap.c b/keyboards/splitkb/kyria/keymaps/drashna/keymap.c
index 6c7ac34d5..1346616b2 100644
--- a/keyboards/splitkb/kyria/keymaps/drashna/keymap.c
+++ b/keyboards/splitkb/kyria/keymaps/drashna/keymap.c
@@ -93,7 +93,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
93 KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET, 93 KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET,
94 VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST, 94 VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
95 UC_MOD, _________________ADJUST_L3_________________, HPT_TOG, HPT_FBK, MG_NKRO, UC_MOD, _________________ADJUST_R3_________________, TG_MODS, 95 UC_MOD, _________________ADJUST_L3_________________, HPT_TOG, HPT_FBK, MG_NKRO, UC_MOD, _________________ADJUST_R3_________________, TG_MODS,
96 _______, _______, KEYLOCK, KC_NUKE, _______, _______, _______, _______, _______, _______ 96 REBOOT, _______, KEYLOCK, KC_NUKE, _______, _______, _______, _______, _______, AUTO_CTN
97 ), 97 ),
98// [_LAYERINDEX] = LAYOUT_wrapper( 98// [_LAYERINDEX] = LAYOUT_wrapper(
99// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, 99// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
diff --git a/layouts/community/ergodox/drashna/keymap.c b/layouts/community/ergodox/drashna/keymap.c
index 798680628..0b81232af 100644
--- a/layouts/community/ergodox/drashna/keymap.c
+++ b/layouts/community/ergodox/drashna/keymap.c
@@ -16,10 +16,6 @@
16 16
17#include "drashna.h" 17#include "drashna.h"
18 18
19#ifdef UNICODEMAP_ENABLE
20# include "drashna_unicode.h"
21#endif // UNICODEMAP_ENABLE
22#include "drivers/sensors/pimoroni_trackball.h"
23enum more_custom_keycodes { 19enum more_custom_keycodes {
24 KC_SWAP_NUM = NEW_SAFE_RANGE, 20 KC_SWAP_NUM = NEW_SAFE_RANGE,
25 PM_SCROLL, 21 PM_SCROLL,
diff --git a/layouts/community/ergodox/drashna/rules.mk b/layouts/community/ergodox/drashna/rules.mk
index 61b626307..f5e9b500e 100644
--- a/layouts/community/ergodox/drashna/rules.mk
+++ b/layouts/community/ergodox/drashna/rules.mk
@@ -2,7 +2,6 @@ BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
2TAP_DANCE_ENABLE = no 2TAP_DANCE_ENABLE = no
3COMMAND_ENABLE = no # Commands for debug and configuration 3COMMAND_ENABLE = no # Commands for debug and configuration
4CONSOLE_ENABLE = no 4CONSOLE_ENABLE = no
5SPACE_CADET_ENABLE = no
6 5
7ifeq ($(strip $(KEYBOARD)), ergodox_ez) 6ifeq ($(strip $(KEYBOARD)), ergodox_ez)
8 RGBLIGHT_ENABLE = yes 7 RGBLIGHT_ENABLE = yes
@@ -16,5 +15,3 @@ endif
16UNICODE_ENABLE = no 15UNICODE_ENABLE = no
17UNICDOEMAP_ENABLE = no 16UNICDOEMAP_ENABLE = no
18CUSTOM_UNICODE_ENABLE = no 17CUSTOM_UNICODE_ENABLE = no
19
20DEBOUNCE_TYPE = sym_eager_pr
diff --git a/layouts/community/ortho_4x12/drashna/keymap.c b/layouts/community/ortho_4x12/drashna/keymap.c
index ce241fd76..522fc772b 100644
--- a/layouts/community/ortho_4x12/drashna/keymap.c
+++ b/layouts/community/ortho_4x12/drashna/keymap.c
@@ -106,7 +106,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
106 KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RST, 106 KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RST,
107 VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST, 107 VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
108 TH_LVL, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL, 108 TH_LVL, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL,
109 KEYLOCK, _______, _______, _______, _______, KC_NUKE, _______, _______, _______, _______, _______, TG_MODS 109 KEYLOCK, _______, _______, REBOOT, _______, KC_NUKE, _______, _______, AUTO_CTN,_______, _______, TG_MODS
110 ) 110 )
111 111
112}; 112};
diff --git a/layouts/community/split_3x6_3/drashna/keymap.c b/layouts/community/split_3x6_3/drashna/keymap.c
index 476ca5fce..4bd4618d0 100644
--- a/layouts/community/split_3x6_3/drashna/keymap.c
+++ b/layouts/community/split_3x6_3/drashna/keymap.c
@@ -90,7 +90,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
90 KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET, 90 KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET,
91 VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST, 91 VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
92 KEYLOCK, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL, 92 KEYLOCK, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL,
93 AUTO_CTN,KC_NUKE, _______, _______, TG_MODS, HPT_FBK 93 REBOOT, KC_NUKE, _______, _______, TG_MODS, AUTO_CTN
94 ) 94 )
95}; 95};
96// clang-format on 96// clang-format on
diff --git a/users/drashna/callbacks.c b/users/drashna/callbacks.c
index 48b076b6b..ffc777692 100644
--- a/users/drashna/callbacks.c
+++ b/users/drashna/callbacks.c
@@ -70,6 +70,15 @@ void shutdown_user(void) {
70__attribute__((weak)) void suspend_power_down_keymap(void) {} 70__attribute__((weak)) void suspend_power_down_keymap(void) {}
71 71
72void suspend_power_down_user(void) { 72void suspend_power_down_user(void) {
73 if (layer_state_is(_GAMEPAD)) {
74 layer_off(_GAMEPAD);
75 }
76 if (layer_state_is(_DIABLO)) {
77 layer_off(_DIABLO);
78 }
79 if (layer_state_is(_DIABLOII)) {
80 layer_off(_DIABLOII);
81 }
73#ifdef OLED_ENABLE 82#ifdef OLED_ENABLE
74 oled_off(); 83 oled_off();
75#endif 84#endif
@@ -78,12 +87,6 @@ void suspend_power_down_user(void) {
78 87
79__attribute__((weak)) void suspend_wakeup_init_keymap(void) {} 88__attribute__((weak)) void suspend_wakeup_init_keymap(void) {}
80void suspend_wakeup_init_user(void) { 89void suspend_wakeup_init_user(void) {
81 if (layer_state_is(_GAMEPAD)) {
82 layer_off(_GAMEPAD);
83 }
84 if (layer_state_is(_DIABLO)) {
85 layer_off(_DIABLO);
86 }
87 suspend_wakeup_init_keymap(); 90 suspend_wakeup_init_keymap();
88} 91}
89 92
diff --git a/users/drashna/config.h b/users/drashna/config.h
index 46cd276dd..a6b4beb74 100644
--- a/users/drashna/config.h
+++ b/users/drashna/config.h
@@ -29,7 +29,7 @@
29# define SELECT_SOFT_SERIAL_SPEED 1 29# define SELECT_SOFT_SERIAL_SPEED 1
30# endif 30# endif
31# ifdef CUSTOM_SPLIT_TRANSPORT_SYNC 31# ifdef CUSTOM_SPLIT_TRANSPORT_SYNC
32# define SPLIT_TRANSACTION_IDS_USER RPC_ID_USER_STATE_SYNC, RPC_ID_USER_KEYMAP_SYNC, RPC_ID_USER_CONFIG_SYNC, RPC_ID_USER_WATCHDOG_SYNC 32# define SPLIT_TRANSACTION_IDS_USER RPC_ID_USER_STATE_SYNC, RPC_ID_USER_KEYMAP_SYNC, RPC_ID_USER_CONFIG_SYNC, RPC_ID_USER_WATCHDOG_SYNC, RPC_ID_USER_KEYLOG_STR
33# endif 33# endif
34#endif 34#endif
35 35
@@ -271,3 +271,21 @@
271# define C14 PAL_LINE(GPIOC, 14) 271# define C14 PAL_LINE(GPIOC, 14)
272# define C15 PAL_LINE(GPIOC, 15) 272# define C15 PAL_LINE(GPIOC, 15)
273#endif 273#endif
274
275#ifdef OLED_DRIVER_SH1107
276# define OLED_DISPLAY_CUSTOM
277# define OLED_IC_SH1107 2
278# define OLED_DISPLAY_128X128
279# define OLED_DISPLAY_WIDTH 128
280# define OLED_DISPLAY_HEIGHT 128
281# define OLED_MATRIX_SIZE (OLED_DISPLAY_HEIGHT / 8 * OLED_DISPLAY_WIDTH)
282# define OLED_BLOCK_TYPE uint16_t
283# define OLED_SOURCE_MAP \
284 { 0, 8, 16, 24, 32, 40, 48, 56 }
285# define OLED_TARGET_MAP \
286 { 56, 48, 40, 32, 24, 16, 8, 0 }
287# define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8)
288# define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)
289# define OLED_COM_PINS COM_PINS_ALT
290# define OLED_IC OLED_IC_SH1107
291#endif
diff --git a/users/drashna/drashna.c b/users/drashna/drashna.c
index 9128a89bc..6e8d4ac9b 100644
--- a/users/drashna/drashna.c
+++ b/users/drashna/drashna.c
@@ -2,25 +2,37 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "drashna.h" 4#include "drashna.h"
5#ifdef __AVR__
6# include <avr/wdt.h>
7#endif
5 8
6userspace_config_t userspace_config; 9userspace_config_t userspace_config;
7 10
11/**
12 * @brief Handle registering a keycode, with optional modifer based on timed event
13 *
14 * @param code keycode to send to host
15 * @param mod_code modifier to send with code, if held for tapping term or longer
16 * @param pressed the press/release event (can use "record->event.pressed" for this)
17 * @return true exits function
18 * @return false exits function
19 */
8bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed) { 20bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed) {
9 static uint16_t this_timer; 21 static uint16_t this_timer;
10 if (pressed) { 22 mod_key_press(code, mod_code, pressed, this_timer);
11 this_timer = timer_read();
12 } else {
13 if (timer_elapsed(this_timer) < TAPPING_TERM) {
14 tap_code(code);
15 } else {
16 register_code(mod_code);
17 tap_code(code);
18 unregister_code(mod_code);
19 }
20 }
21 return false; 23 return false;
22} 24}
23 25
26/**
27 * @brief Handle registation of keycode, with optional modifier based on custom timer
28 *
29 * @param code keycode to send to host
30 * @param mod_code modifier keycode to send with code, if held for tapping term or longer
31 * @param pressed the press/release event
32 * @param this_timer custom timer to use
33 * @return true
34 * @return false
35 */
24bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer) { 36bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer) {
25 if (pressed) { 37 if (pressed) {
26 this_timer = timer_read(); 38 this_timer = timer_read();
@@ -36,6 +48,14 @@ bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this
36 return false; 48 return false;
37} 49}
38 50
51/**
52 * @brief Performs exact match for modifier values
53 *
54 * @param value the modifer varible (get_mods/get_oneshot_mods/get_weak_mods)
55 * @param mask the modifier mask to check for
56 * @return true Has the exact modifiers specifed
57 * @return false Does not have the exact modifiers specified
58 */
39bool hasAllBitsInMask(uint8_t value, uint8_t mask) { 59bool hasAllBitsInMask(uint8_t value, uint8_t mask) {
40 value &= 0xF; 60 value &= 0xF;
41 mask &= 0xF; 61 mask &= 0xF;
@@ -43,10 +63,62 @@ bool hasAllBitsInMask(uint8_t value, uint8_t mask) {
43 return (value & mask) == mask; 63 return (value & mask) == mask;
44} 64}
45 65
46void tap_code16_nomods(uint8_t kc) { 66/**
67 * @brief Tap keycode, with no mods
68 *
69 * @param kc keycode to use
70 */
71void tap_code16_nomods(uint16_t kc) {
47 uint8_t temp_mod = get_mods(); 72 uint8_t temp_mod = get_mods();
48 clear_mods(); 73 clear_mods();
49 clear_oneshot_mods(); 74 clear_oneshot_mods();
50 tap_code16(kc); 75 tap_code16(kc);
51 set_mods(temp_mod); 76 set_mods(temp_mod);
52} 77}
78
79/**
80 * @brief Run shutdown routine and soft reboot firmware.
81 *
82 */
83
84#ifdef HAPTIC_ENABLE
85# include "haptic.h"
86#endif
87
88#ifdef AUDIO_ENABLE
89# ifndef GOODBYE_SONG
90# define GOODBYE_SONG SONG(GOODBYE_SOUND)
91# endif
92float reset_song[][2] = GOODBYE_SONG;
93#endif
94
95void software_reset(void) {
96 clear_keyboard();
97#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
98 process_midi_all_notes_off();
99#endif
100#ifdef AUDIO_ENABLE
101# ifndef NO_MUSIC_MODE
102 music_all_notes_off();
103# endif
104 uint16_t timer_start = timer_read();
105 PLAY_SONG(reset_song);
106 shutdown_user();
107 while (timer_elapsed(timer_start) < 250) wait_ms(1);
108 stop_all_notes();
109#else
110 shutdown_user();
111 wait_ms(250);
112#endif
113#ifdef HAPTIC_ENABLE
114 haptic_shutdown();
115#endif
116
117#if defined(PROTOCOL_LUFA)
118 wdt_enable(WDTO_250MS);
119#elif defined(PROTOCOL_CHIBIOS)
120# if defined(MCU_STM32) || defined(MCU_KINETIS)
121 NVIC_SystemReset();
122# endif
123#endif
124}
diff --git a/users/drashna/drashna.h b/users/drashna/drashna.h
index 5a9da1627..0bf1de84c 100644
--- a/users/drashna/drashna.h
+++ b/users/drashna/drashna.h
@@ -78,7 +78,8 @@ enum userspace_layers {
78bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed); 78bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed);
79bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer); 79bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer);
80bool hasAllBitsInMask(uint8_t value, uint8_t mask); 80bool hasAllBitsInMask(uint8_t value, uint8_t mask);
81void tap_code16_nomods(uint8_t kc); 81void tap_code16_nomods(uint16_t kc);
82void software_reset(void);
82 83
83// clang-format off 84// clang-format off
84typedef union { 85typedef union {
diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.c b/users/drashna/keyrecords/autocorrection/autocorrection.c
index e56122437..c7e938a34 100644
--- a/users/drashna/keyrecords/autocorrection/autocorrection.c
+++ b/users/drashna/keyrecords/autocorrection/autocorrection.c
@@ -17,6 +17,14 @@
17# error Dictionary size excees maximum size permitted 17# error Dictionary size excees maximum size permitted
18# endif 18# endif
19 19
20/**
21 * @brief Process handler for autocorrect feature
22 *
23 * @param keycode Keycode registered by matrix press, per keymap
24 * @param record keyrecord_t structure
25 * @return true Continue processing keycodes, and send to host
26 * @return false Stop processing keycodes, and don't send to host
27 */
20bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { 28bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
21 static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {KC_SPC}; 29 static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {KC_SPC};
22 static uint8_t typo_buffer_size = 1; 30 static uint8_t typo_buffer_size = 1;
@@ -53,6 +61,14 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
53 keycode &= 0xFF; 61 keycode &= 0xFF;
54 break; 62 break;
55# endif 63# endif
64# ifdef SWAP_HANDS_ENABLE
65 case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
66 if (keycode >= 0x56F0 || record->event.pressed || !record->tap.count) {
67 return true;
68 }
69 keycode &= 0xFF;
70 break;
71# endif
56# ifndef NO_ACTION_ONESHOT 72# ifndef NO_ACTION_ONESHOT
57 case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: 73 case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
58 if ((keycode & 0xF) == MOD_LSFT) { 74 if ((keycode & 0xF) == MOD_LSFT) {
@@ -70,7 +86,6 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
70 } 86 }
71 } 87 }
72 88
73
74 // Subtract buffer for Backspace key, reset for other non-alpha. 89 // Subtract buffer for Backspace key, reset for other non-alpha.
75 if (!(KC_A <= keycode && keycode <= KC_Z)) { 90 if (!(KC_A <= keycode && keycode <= KC_Z)) {
76 if (keycode == KC_BSPC) { 91 if (keycode == KC_BSPC) {
@@ -83,7 +98,7 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
83 // Set a word boundary if space, period, digit, etc. is pressed. 98 // Set a word boundary if space, period, digit, etc. is pressed.
84 // Behave more conservatively for the enter key. Reset, so that enter 99 // Behave more conservatively for the enter key. Reset, so that enter
85 // can't be used on a word ending. 100 // can't be used on a word ending.
86 if (keycode == KC_ENT) { 101 if (keycode == KC_ENT || (keycode == KC_MINUS && (get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT)) {
87 typo_buffer_size = 0; 102 typo_buffer_size = 0;
88 } 103 }
89 keycode = KC_SPC; 104 keycode = KC_SPC;
diff --git a/users/drashna/keyrecords/caps_word.c b/users/drashna/keyrecords/caps_word.c
index cc9ca93b7..0c7cd6cfe 100644
--- a/users/drashna/keyrecords/caps_word.c
+++ b/users/drashna/keyrecords/caps_word.c
@@ -10,6 +10,16 @@
10bool caps_word_enabled = false; 10bool caps_word_enabled = false;
11bool caps_word_shifted = false; 11bool caps_word_shifted = false;
12 12
13/**
14 * @brief Handler for Caps Word feature.
15 *
16 * This checks the keycodes, and applies shift to the correct keys, if and when needid.
17 *
18 * @param keycode Keycode from matrix
19 * @param record keyrecord_t data structure
20 * @return true Continue processing keycode and sent to host
21 * @return false Stop processing keycode, and do not send to host
22 */
13bool process_caps_word(uint16_t keycode, keyrecord_t* record) { 23bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
14 if (!caps_word_enabled) { 24 if (!caps_word_enabled) {
15 // Pressing both shift keys at the same time enables caps word. 25 // Pressing both shift keys at the same time enables caps word.
diff --git a/users/drashna/keyrecords/process_records.c b/users/drashna/keyrecords/process_records.c
index f49ac6ef6..012a57f7e 100644
--- a/users/drashna/keyrecords/process_records.c
+++ b/users/drashna/keyrecords/process_records.c
@@ -18,8 +18,24 @@ bool host_driver_disabled = false;
18// Defines actions tor my global custom keycodes. Defined in drashna.h file 18// Defines actions tor my global custom keycodes. Defined in drashna.h file
19// Then runs the _keymap's record handier if not processed here 19// Then runs the _keymap's record handier if not processed here
20 20
21/**
22 * @brief Keycode handler for keymaps
23 *
24 * This handles the keycodes at the keymap level, useful for keyboard specific customization
25 */
21__attribute__((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { return true; } 26__attribute__((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { return true; }
22__attribute__((weak)) bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { return true; } 27__attribute__((weak)) bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { return true; }
28
29/**
30 * @brief Main user keycode handler
31 *
32 * This handles all of the keycodes for the user, including calling feature handlers.
33 *
34 * @param keycode Keycode from matrix
35 * @param record keyrecord_t data structure
36 * @return true Continue processing keycode and send to host
37 * @return false Stop process keycode and do not send to host
38 */
23bool process_record_user(uint16_t keycode, keyrecord_t *record) { 39bool process_record_user(uint16_t keycode, keyrecord_t *record) {
24 // If console is enabled, it will print the matrix position and status of each key pressed 40 // If console is enabled, it will print the matrix position and status of each key pressed
25#ifdef KEYLOGGER_ENABLE 41#ifdef KEYLOGGER_ENABLE
@@ -215,12 +231,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *re
215 return false; 231 return false;
216 case REBOOT: 232 case REBOOT:
217 if (record->event.pressed) { 233 if (record->event.pressed) {
218 shutdown_user(); 234 software_reset();
219#ifdef __AVR__
220 wdt_enable(WDTO_250MS);
221#else
222 NVIC_SystemReset();
223#endif
224 } 235 }
225 return false; 236 return false;
226 237
diff --git a/users/drashna/keyrecords/tap_dances.c b/users/drashna/keyrecords/tap_dances.c
index 63eb0c334..a1a743916 100644
--- a/users/drashna/keyrecords/tap_dances.c
+++ b/users/drashna/keyrecords/tap_dances.c
@@ -11,7 +11,12 @@ diablo_timer_t diablo_timer[NUM_OF_DIABLO_KEYS];
11// Otherwise, you will need to hit a bunch of times, or hit the "clear" command 11// Otherwise, you will need to hit a bunch of times, or hit the "clear" command
12uint8_t diablo_times[] = {0, 1, 3, 5, 10, 30}; 12uint8_t diablo_times[] = {0, 1, 3, 5, 10, 30};
13 13
14// Cycle through the times for the macro, starting at 0, for disabled. 14/**
15 * @brief Main function for handling diable related tap dances.
16 *
17 * @param state Main data struction contining information about events
18 * @param user_data Local data for the dance. Allows customization to be passed on to function
19 */
15void diablo_tapdance_master(qk_tap_dance_state_t *state, void *user_data) { 20void diablo_tapdance_master(qk_tap_dance_state_t *state, void *user_data) {
16 diable_keys_t *diablo_keys = (diable_keys_t *)user_data; 21 diable_keys_t *diablo_keys = (diable_keys_t *)user_data;
17 // Sets the keycode based on the index 22 // Sets the keycode based on the index
@@ -43,7 +48,10 @@ qk_tap_dance_action_t tap_dance_actions[] = {
43 [TD_D3_4] = ACTION_TAP_DANCE_DIABLO(3, KC_4), 48 [TD_D3_4] = ACTION_TAP_DANCE_DIABLO(3, KC_4),
44}; 49};
45 50
46// Checks each of the 4 timers/keys to see if enough time has elapsed 51/**
52 * @brief Runs check to see if timer has elapsed for each dance, and sends keycodes, if it has.
53 *
54 */
47void run_diablo_macro_check(void) { 55void run_diablo_macro_check(void) {
48 for (uint8_t index = 0; index < NUM_OF_DIABLO_KEYS; index++) { 56 for (uint8_t index = 0; index < NUM_OF_DIABLO_KEYS; index++) {
49 // if key_interval is 0, it's disabled, so only run if it's set. If it's set, check the timer. 57 // if key_interval is 0, it's disabled, so only run if it's set. If it's set, check the timer.
diff --git a/users/drashna/keyrecords/unicode.c b/users/drashna/keyrecords/unicode.c
index 4010b9c1c..db2058e5d 100644
--- a/users/drashna/keyrecords/unicode.c
+++ b/users/drashna/keyrecords/unicode.c
@@ -8,6 +8,11 @@
8 8
9uint16_t typing_mode; 9uint16_t typing_mode;
10 10
11/**
12 * @brief Registers the unicode keystrokes based on desired unicode
13 *
14 * @param glyph Unicode character, supports up to 0x1FFFF (or higher)
15 */
11void tap_unicode_glyph_nomods(uint32_t glyph) { 16void tap_unicode_glyph_nomods(uint32_t glyph) {
12 uint8_t temp_mod = get_mods(); 17 uint8_t temp_mod = get_mods();
13 clear_mods(); 18 clear_mods();
@@ -43,6 +48,15 @@ typedef uint32_t (*translator_function_t)(bool is_shifted, uint32_t keycode);
43 return ret; \ 48 return ret; \
44 } 49 }
45 50
51/**
52 * @brief Handler function for outputting unicode.
53 *
54 * @param keycode Keycode from matrix.
55 * @param record keyrecord_t data structure
56 * @param translator translator lut for different unicode modes
57 * @return true Continue processing matrix press, and send to host
58 * @return false Replace keycode, and do not send to host
59 */
46bool process_record_glyph_replacement(uint16_t keycode, keyrecord_t *record, translator_function_t translator) { 60bool process_record_glyph_replacement(uint16_t keycode, keyrecord_t *record, translator_function_t translator) {
47 uint8_t temp_mod = get_mods(); 61 uint8_t temp_mod = get_mods();
48 uint8_t temp_osm = get_oneshot_mods(); 62 uint8_t temp_osm = get_oneshot_mods();
@@ -182,6 +196,15 @@ bool process_record_zalgo(uint16_t keycode, keyrecord_t *record) {
182 return true; 196 return true;
183} 197}
184 198
199/**
200 * @brief Main handler for unicode input
201 *
202 * @param keycode Keycode from switch matrix
203 * @param record keyrecord_t data struture
204 * @return true Send keycode from matrix to host
205 * @return false Stop processing and do not send to host
206 */
207
185bool process_record_unicode(uint16_t keycode, keyrecord_t *record) { 208bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
186 switch (keycode) { 209 switch (keycode) {
187 case UC_FLIP: // (ノಠ痊ಠ)ノ彡┻━┻ 210 case UC_FLIP: // (ノಠ痊ಠ)ノ彡┻━┻
@@ -265,6 +288,10 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
265 return process_unicode_common(keycode, record); 288 return process_unicode_common(keycode, record);
266} 289}
267 290
291/**
292 * @brief Initialize the default unicode mode on firmware startu
293 *
294 */
268void matrix_init_unicode(void) { 295void matrix_init_unicode(void) {
269 unicode_input_mode_init(); 296 unicode_input_mode_init();
270} 297}
diff --git a/users/drashna/oled/oled_stuff.c b/users/drashna/oled/oled_stuff.c
index de8476672..eeca010de 100644
--- a/users/drashna/oled/oled_stuff.c
+++ b/users/drashna/oled/oled_stuff.c
@@ -22,17 +22,12 @@
22 22
23extern bool host_driver_disabled; 23extern bool host_driver_disabled;
24 24
25#ifndef KEYLOGGER_LENGTH 25uint32_t oled_timer = 0;
26// # ifdef OLED_DISPLAY_128X64 26char keylog_str[OLED_KEYLOGGER_LENGTH] = {0};
27# define KEYLOGGER_LENGTH ((uint8_t)(OLED_DISPLAY_HEIGHT / OLED_FONT_WIDTH)) 27static uint16_t log_timer = 0;
28// # else 28static const char PROGMEM display_border[3] = {0x0, 0xFF, 0x0};
29// # define KEYLOGGER_LENGTH (uint8_t *(OLED_DISPLAY_WIDTH / OLED_FONT_HEIGHT))
30// # endif
31#endif
32 29
33uint32_t oled_timer = 0; 30deferred_token kittoken;
34static char keylog_str[KEYLOGGER_LENGTH + 1] = {0};
35static uint16_t log_timer = 0;
36 31
37// clang-format off 32// clang-format off
38static const char PROGMEM code_to_name[256] = { 33static const char PROGMEM code_to_name[256] = {
@@ -56,10 +51,16 @@ static const char PROGMEM code_to_name[256] = {
56}; 51};
57// clang-format on 52// clang-format on
58 53
54/**
55 * @brief parses pressed keycodes and saves to buffer
56 *
57 * @param keycode Keycode pressed from switch matrix
58 * @param record keyrecord_t data structure
59 */
59void add_keylog(uint16_t keycode, keyrecord_t *record) { 60void add_keylog(uint16_t keycode, keyrecord_t *record) {
60 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) || (keycode >= QK_MODS && keycode <= QK_MODS_MAX)) { 61 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) || (keycode >= QK_MODS && keycode <= QK_MODS_MAX)) {
61 if (((keycode & 0xFF) == KC_BSPC) && mod_config(get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) { 62 if (((keycode & 0xFF) == KC_BSPC) && mod_config(get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) {
62 memset(keylog_str, ' ', sizeof(keylog_str) - 1); 63 memset(keylog_str, ' ', OLED_KEYLOGGER_LENGTH);
63 return; 64 return;
64 } 65 }
65 if (record->tap.count) { 66 if (record->tap.count) {
@@ -72,23 +73,29 @@ void add_keylog(uint16_t keycode, keyrecord_t *record) {
72 return; 73 return;
73 } 74 }
74 75
75 for (uint8_t i = 1; i < KEYLOGGER_LENGTH; i++) { 76 memmove(keylog_str, keylog_str + 1, OLED_KEYLOGGER_LENGTH - 1);
76 keylog_str[i - 1] = keylog_str[i];
77 }
78 77
79 if (keycode < (sizeof(code_to_name) / sizeof(char))) { 78 if (keycode < (sizeof(code_to_name) / sizeof(char))) {
80 keylog_str[(KEYLOGGER_LENGTH - 1)] = pgm_read_byte(&code_to_name[keycode]); 79 keylog_str[(OLED_KEYLOGGER_LENGTH - 1)] = pgm_read_byte(&code_to_name[keycode]);
81 } 80 }
82 81
83 log_timer = timer_read(); 82 log_timer = timer_read();
84} 83}
85 84
85/**
86 * @brief Keycode handler for oled display.
87 *
88 * This adds pressed keys to buffer, but also resets the oled timer
89 *
90 * @param keycode Keycode from matrix
91 * @param record keyrecord data struture
92 * @return true
93 * @return false
94 */
86bool process_record_user_oled(uint16_t keycode, keyrecord_t *record) { 95bool process_record_user_oled(uint16_t keycode, keyrecord_t *record) {
87 if (record->event.pressed) { 96 if (record->event.pressed) {
88#ifdef OLED_ENABLE
89 oled_timer = timer_read32(); 97 oled_timer = timer_read32();
90 add_keylog(keycode, record); 98 add_keylog(keycode, record);
91#endif
92 } 99 }
93 return true; 100 return true;
94} 101}
@@ -99,12 +106,29 @@ void update_log(void) {
99 } 106 }
100} 107}
101 108
109/**
110 * @brief Renders keylogger buffer to oled
111 *
112 */
102void render_keylogger_status(void) { 113void render_keylogger_status(void) {
114#ifdef OLED_DISPLAY_VERBOSE
115 oled_set_cursor(1, 7);
116#endif
103 oled_write_P(PSTR(OLED_RENDER_KEYLOGGER), false); 117 oled_write_P(PSTR(OLED_RENDER_KEYLOGGER), false);
104 oled_write(keylog_str, false); 118 oled_write(keylog_str, false);
119#ifdef OLED_DISPLAY_VERBOSE
120 oled_advance_page(true);
121#endif
105} 122}
106 123
124/**
125 * @brief Renders default layer state (aka layout) to oled
126 *
127 */
107void render_default_layer_state(void) { 128void render_default_layer_state(void) {
129#ifdef OLED_DISPLAY_VERBOSE
130 oled_set_cursor(5, 2);
131#endif
108 oled_write_P(PSTR(OLED_RENDER_LAYOUT_NAME), false); 132 oled_write_P(PSTR(OLED_RENDER_LAYOUT_NAME), false);
109 switch (get_highest_layer(default_layer_state)) { 133 switch (get_highest_layer(default_layer_state)) {
110 case _QWERTY: 134 case _QWERTY:
@@ -120,46 +144,150 @@ void render_default_layer_state(void) {
120 oled_write_P(PSTR(OLED_RENDER_LAYOUT_DVORAK), false); 144 oled_write_P(PSTR(OLED_RENDER_LAYOUT_DVORAK), false);
121 break; 145 break;
122 } 146 }
123#ifdef OLED_DISPLAY_128X64 147#ifdef OLED_DISPLAY_VERBOSE
124 oled_advance_page(true); 148 oled_advance_page(true);
125#endif 149#endif
126} 150}
127 151
152/**
153 * @brief Renders the active layers to the OLED
154 *
155 */
128void render_layer_state(void) { 156void render_layer_state(void) {
129 oled_write_P(PSTR(OLED_RENDER_LAYER_NAME), false); 157#ifdef OLED_DISPLAY_VERBOSE
130#ifdef OLED_DISPLAY_128X64 158 static const char PROGMEM tri_layer_image[4][3][18] = {
131 oled_write_P(PSTR(" "), false); 159 {
132#endif 160 {
133 oled_write_P(PSTR(OLED_RENDER_LAYER_LOWER), layer_state_is(_LOWER)); 161 0x80, 0x80, 0x40, 0x40, 0x20, 0x20,
134#ifdef OLED_DISPLAY_128X64 162 0x10, 0x10, 0x08, 0x08, 0x10, 0x10,
163 0x20, 0x20, 0x40, 0x40, 0x80, 0x80
164 },
165 {
166 0x88, 0x88, 0x5D, 0x5D, 0x3E, 0x3E,
167 0x7C, 0x7C, 0xF8, 0xF8, 0x7C, 0x7C,
168 0x3E, 0x3E, 0x5D, 0x5D, 0x88, 0x88
169 },
170 {
171 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
172 0x04, 0x04, 0x08, 0x08, 0x04, 0x04,
173 0x02, 0x02, 0x01, 0x01, 0x00, 0x00
174 }
175 },
176 {
177 {
178 0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xE0,
179 0xF0, 0xF0, 0xF8, 0xF8, 0xF0, 0xF0,
180 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x80
181 },
182 {
183 0x88, 0x88, 0x55, 0x55, 0x23, 0x23,
184 0x47, 0x47, 0x8F, 0x8F, 0x47, 0x47,
185 0x23, 0x23, 0x55, 0x55, 0x88, 0x88
186 },
187 {
188 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
189 0x04, 0x04, 0x08, 0x08, 0x04, 0x04,
190 0x02, 0x02, 0x01, 0x01, 0x00, 0x00
191 }
192 },
193 {
194 {
195 0x80, 0x80, 0x40, 0x40, 0x20, 0x20,
196 0x10, 0x10, 0x08, 0x08, 0x10, 0x10,
197 0x20, 0x20, 0x40, 0x40, 0x80, 0x80
198 },
199 {
200 0x88, 0x88, 0xD5, 0xD5, 0xE2, 0xE2,
201 0xC4, 0xC4, 0x88, 0x88, 0xC4, 0xC4,
202 0xE2, 0xE2, 0xD5, 0xD5, 0x88, 0x88
203 },
204 {
205 0x00, 0x00, 0x01, 0x01, 0x03, 0x03,
206 0x07, 0x07, 0x0F, 0x0F, 0x07, 0x07,
207 0x03, 0x03, 0x01, 0x01, 0x00, 0x00
208 }
209 },
210 {
211 {
212 0x80, 0x80, 0x40, 0xC0, 0x60, 0xA0,
213 0x50, 0xB0, 0x58, 0xA8, 0x50, 0xB0,
214 0x60, 0xA0, 0x40, 0xC0, 0x80, 0x80
215 },
216 {
217 0x88, 0x88, 0x5D, 0xD5, 0x6B, 0xB6,
218 0x6D, 0xD6, 0xAD, 0xDA, 0x6D, 0xD6,
219 0x6B, 0xB6, 0x5D, 0xD5, 0x88, 0x88
220 },
221 {
222 0x00, 0x00, 0x01, 0x01, 0x03, 0x02,
223 0x05, 0x06, 0x0D, 0x0A, 0x05, 0x06,
224 0x03, 0x02, 0x01, 0x01, 0x00, 0x00
225 }
226 }
227 };
228
229 uint8_t layer_is = 0;
230 if (layer_state_is(_ADJUST)) {
231 layer_is = 3;
232 } else if (layer_state_is(_RAISE)) {
233 layer_is = 1;
234 } else if (layer_state_is(_LOWER)) {
235 layer_is = 2;
236 }
237
238 oled_set_cursor(1, 2);
239 oled_write_raw_P(tri_layer_image[layer_is][0], sizeof(tri_layer_image[0][0]));
240 oled_set_cursor(5, 3);
241 oled_write_P(PSTR("Diablo2"), layer_state_is(_DIABLOII));
135 oled_write_P(PSTR(" "), false); 242 oled_write_P(PSTR(" "), false);
136#endif 243 oled_write_P(PSTR("Diablo3"), layer_state_is(_DIABLO));
137 oled_write_P(PSTR(OLED_RENDER_LAYER_RAISE), layer_state_is(_RAISE));
138#ifdef OLED_DISPLAY_128X64
139 oled_advance_page(true); 244 oled_advance_page(true);
140 oled_write_P(PSTR(" "), false); 245
246 oled_set_cursor(1, 3);
247 oled_write_raw_P(tri_layer_image[layer_is][1], sizeof(tri_layer_image[0][0]));
248 oled_set_cursor(5, 4);
141 oled_write_P(PSTR("GamePad"), layer_state_is(_GAMEPAD)); 249 oled_write_P(PSTR("GamePad"), layer_state_is(_GAMEPAD));
142 oled_write_P(PSTR(" "), false); 250 oled_write_P(PSTR(" "), false);
143 oled_write_P(PSTR("Diablo"), layer_state_is(_DIABLO));
144 oled_write_P(PSTR(" "), false);
145 oled_write_P(PSTR("Mouse"), layer_state_is(_MOUSE)); 251 oled_write_P(PSTR("Mouse"), layer_state_is(_MOUSE));
252 oled_advance_page(true);
253
254 oled_set_cursor(1, 4);
255 oled_write_raw_P(tri_layer_image[layer_is][2], sizeof(tri_layer_image[0][0]));
256
257#else
258 oled_write_P(PSTR(OLED_RENDER_LAYER_NAME), false);
259 oled_write_P(PSTR(OLED_RENDER_LAYER_LOWER), layer_state_is(_LOWER));
260 oled_write_P(PSTR(OLED_RENDER_LAYER_RAISE), layer_state_is(_RAISE));
261 oled_advance_page(true);
146#endif 262#endif
147} 263}
148 264
265/**
266 * @brief Renders the current lock status to oled
267 *
268 * @param led_usb_state Current keyboard led state
269 */
149void render_keylock_status(uint8_t led_usb_state) { 270void render_keylock_status(uint8_t led_usb_state) {
271#if defined(OLED_DISPLAY_VERBOSE)
272 oled_set_cursor(1, 6);
273#endif
150 oled_write_P(PSTR(OLED_RENDER_LOCK_NAME), false); 274 oled_write_P(PSTR(OLED_RENDER_LOCK_NAME), false);
151#if !defined(OLED_DISPLAY_128X64) 275#if !defined(OLED_DISPLAY_VERBOSE)
152 oled_write_P(PSTR(" "), false); 276 oled_write_P(PSTR(" "), false);
153#endif 277#endif
154 oled_write_P(PSTR(OLED_RENDER_LOCK_NUML), led_usb_state & (1 << USB_LED_NUM_LOCK)); 278 oled_write_P(PSTR(OLED_RENDER_LOCK_NUML), led_usb_state & (1 << USB_LED_NUM_LOCK));
155 oled_write_P(PSTR(" "), false); 279 oled_write_P(PSTR(" "), false);
156 oled_write_P(PSTR(OLED_RENDER_LOCK_CAPS), led_usb_state & (1 << USB_LED_CAPS_LOCK)); 280 oled_write_P(PSTR(OLED_RENDER_LOCK_CAPS), led_usb_state & (1 << USB_LED_CAPS_LOCK));
157#if defined(OLED_DISPLAY_128X64) 281#if defined(OLED_DISPLAY_VERBOSE)
158 oled_write_P(PSTR(" "), false); 282 oled_write_P(PSTR(" "), false);
159 oled_write_P(PSTR(OLED_RENDER_LOCK_SCLK), led_usb_state & (1 << USB_LED_SCROLL_LOCK)); 283 oled_write_P(PSTR(OLED_RENDER_LOCK_SCLK), led_usb_state & (1 << USB_LED_SCROLL_LOCK));
160#endif 284#endif
161} 285}
162 286
287/**
288 * @brief Renders the matrix scan rate to the host system
289 *
290 */
163void render_matrix_scan_rate(void) { 291void render_matrix_scan_rate(void) {
164#ifdef DEBUG_MATRIX_SCAN_RATE 292#ifdef DEBUG_MATRIX_SCAN_RATE
165 oled_write_P(PSTR("MS:"), false); 293 oled_write_P(PSTR("MS:"), false);
@@ -167,10 +295,18 @@ void render_matrix_scan_rate(void) {
167#endif 295#endif
168} 296}
169 297
298/**
299 * @brief Renders the modifier state
300 *
301 * @param modifiers Modifiers to check against (real, weak, onesheot, etc;)
302 */
170void render_mod_status(uint8_t modifiers) { 303void render_mod_status(uint8_t modifiers) {
171 static const char PROGMEM mod_status[5][3] = {{0xE8, 0xE9, 0}, {0xE4, 0xE5, 0}, {0xE6, 0xE7, 0}, {0xEA, 0xEB, 0}, {0xEC, 0xED, 0}}; 304 static const char PROGMEM mod_status[5][3] = {{0xE8, 0xE9, 0}, {0xE4, 0xE5, 0}, {0xE6, 0xE7, 0}, {0xEA, 0xEB, 0}, {0xEC, 0xED, 0}};
305#if defined(OLED_DISPLAY_VERBOSE)
306 oled_set_cursor(1, 5);
307#endif
172 oled_write_P(PSTR(OLED_RENDER_MODS_NAME), false); 308 oled_write_P(PSTR(OLED_RENDER_MODS_NAME), false);
173#if defined(OLED_DISPLAY_128X64) 309#if defined(OLED_DISPLAY_VERBOSE)
174 oled_write_P(mod_status[0], (modifiers & MOD_BIT(KC_LSHIFT))); 310 oled_write_P(mod_status[0], (modifiers & MOD_BIT(KC_LSHIFT)));
175 oled_write_P(mod_status[!keymap_config.swap_lctl_lgui ? 3 : 4], (modifiers & MOD_BIT(KC_LGUI))); 311 oled_write_P(mod_status[!keymap_config.swap_lctl_lgui ? 3 : 4], (modifiers & MOD_BIT(KC_LGUI)));
176 oled_write_P(mod_status[2], (modifiers & MOD_BIT(KC_LALT))); 312 oled_write_P(mod_status[2], (modifiers & MOD_BIT(KC_LALT)));
@@ -200,26 +336,27 @@ void render_bootmagic_status(void) {
200 }; 336 };
201 337
202 bool is_bootmagic_on; 338 bool is_bootmagic_on;
203#ifdef OLED_DISPLAY_128X64 339#ifdef OLED_DISPLAY_VERBOSE
340 oled_set_cursor(7, 4);
204 is_bootmagic_on = !keymap_config.swap_lctl_lgui; 341 is_bootmagic_on = !keymap_config.swap_lctl_lgui;
205#else 342#else
206 is_bootmagic_on = keymap_config.swap_lctl_lgui; 343 is_bootmagic_on = keymap_config.swap_lctl_lgui;
207#endif 344#endif
208 345
209 oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NAME), false); 346#ifdef OLED_DISPLAY_VERBOSE
210#ifdef OLED_DISPLAY_128X64
211 if (keymap_config.swap_lctl_lgui) 347 if (keymap_config.swap_lctl_lgui)
212#else 348#else
349 oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NAME), false);
213 oled_write_P(PSTR(" "), false); 350 oled_write_P(PSTR(" "), false);
214#endif 351#endif
215 { 352 {
216 oled_write_P(logo[1][0], is_bootmagic_on); 353 oled_write_P(logo[1][0], is_bootmagic_on);
217#ifdef OLED_DISPLAY_128X64 354#ifdef OLED_DISPLAY_VERBOSE
218 } else { 355 } else {
219#endif 356#endif
220 oled_write_P(logo[0][0], !is_bootmagic_on); 357 oled_write_P(logo[0][0], !is_bootmagic_on);
221 } 358 }
222#ifndef OLED_DISPLAY_128X64 359#ifndef OLED_DISPLAY_VERBOSE
223 oled_write_P(PSTR(" "), false); 360 oled_write_P(PSTR(" "), false);
224 oled_write_P(logo[1][1], is_bootmagic_on); 361 oled_write_P(logo[1][1], is_bootmagic_on);
225 oled_write_P(logo[0][1], !is_bootmagic_on); 362 oled_write_P(logo[0][1], !is_bootmagic_on);
@@ -232,10 +369,8 @@ void render_bootmagic_status(void) {
232#else 369#else
233 oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui); 370 oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui);
234#endif 371#endif
235#ifdef OLED_DISPLAY_128X64 372#ifdef OLED_DISPLAY_VERBOSE
236 oled_advance_page(true); 373 oled_set_cursor(7, 5);
237 oled_write_P(PSTR("Magic"), false);
238 oled_write_P(PSTR(" "), false);
239 if (keymap_config.swap_lctl_lgui) { 374 if (keymap_config.swap_lctl_lgui) {
240 oled_write_P(logo[1][1], is_bootmagic_on); 375 oled_write_P(logo[1][1], is_bootmagic_on);
241 } else { 376 } else {
@@ -248,9 +383,6 @@ void render_bootmagic_status(void) {
248 oled_write_P(PSTR(" "), false); 383 oled_write_P(PSTR(" "), false);
249 oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_SWAP), swap_hands); 384 oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_SWAP), swap_hands);
250#endif 385#endif
251#ifdef OLED_DISPLAY_128X64
252 oled_advance_page(true);
253#endif
254} 386}
255 387
256#if defined(POINTING_DEVICE_ENABLE) 388#if defined(POINTING_DEVICE_ENABLE)
@@ -269,13 +401,16 @@ void render_user_status(void) {
269 is_clicky_on = is_clicky_on(); 401 is_clicky_on = is_clicky_on();
270# endif 402# endif
271#endif 403#endif
404#if defined(OLED_DISPLAY_VERBOSE)
405 oled_set_cursor(1, 6);
406#endif
272 oled_write_P(PSTR(OLED_RENDER_USER_NAME), false); 407 oled_write_P(PSTR(OLED_RENDER_USER_NAME), false);
273#if !defined(OLED_DISPLAY_128X64) 408#if !defined(OLED_DISPLAY_VERBOSE)
274 oled_write_P(PSTR(" "), false); 409 oled_write_P(PSTR(" "), false);
275#endif 410#endif
276#if defined(RGB_MATRIX_ENABLE) 411#if defined(RGB_MATRIX_ENABLE)
277 oled_write_P(PSTR(OLED_RENDER_USER_ANIM), userspace_config.rgb_matrix_idle_anim); 412 oled_write_P(PSTR(OLED_RENDER_USER_ANIM), userspace_config.rgb_matrix_idle_anim);
278# if !defined(OLED_DISPLAY_128X64) 413# if !defined(OLED_DISPLAY_VERBOSE)
279 oled_write_P(PSTR(" "), false); 414 oled_write_P(PSTR(" "), false);
280# endif 415# endif
281#elif defined(POINTING_DEVICE_ENABLE) 416#elif defined(POINTING_DEVICE_ENABLE)
@@ -289,7 +424,7 @@ void render_user_status(void) {
289# ifdef AUDIO_CLICKY 424# ifdef AUDIO_CLICKY
290 static const char PROGMEM audio_clicky_status[2][3] = {{0xF4, 0xF5, 0}, {0xF6, 0xF7, 0}}; 425 static const char PROGMEM audio_clicky_status[2][3] = {{0xF4, 0xF5, 0}, {0xF6, 0xF7, 0}};
291 oled_write_P(audio_clicky_status[is_clicky_on && is_audio_on], false); 426 oled_write_P(audio_clicky_status[is_clicky_on && is_audio_on], false);
292# if !defined(OLED_DISPLAY_128X64) 427# if !defined(OLED_DISPLAY_VERBOSE)
293 oled_write_P(PSTR(" "), false); 428 oled_write_P(PSTR(" "), false);
294# endif 429# endif
295# endif 430# endif
@@ -304,30 +439,20 @@ void render_user_status(void) {
304 oled_write_P(uc_mod_status[get_unicode_input_mode() == UC_MAC], false); 439 oled_write_P(uc_mod_status[get_unicode_input_mode() == UC_MAC], false);
305#endif 440#endif
306 if (userspace_config.nuke_switch) { 441 if (userspace_config.nuke_switch) {
307#if !defined(OLED_DISPLAY_128X64) 442#if !defined(OLED_DISPLAY_VERBOSE)
308 oled_write_P(PSTR(" "), false); 443 oled_write_P(PSTR(" "), false);
309#endif 444#endif
310 static const char PROGMEM nukem_good[2] = {0xFA, 0}; 445 static const char PROGMEM nukem_good[2] = {0xFA, 0};
311 oled_write_P(nukem_good, false); 446 oled_write_P(nukem_good, false);
312#if !defined(OLED_DISPLAY_128X64) 447#if !defined(OLED_DISPLAY_VERBOSE)
313 oled_advance_page(true); 448 oled_advance_page(true);
314#endif 449#endif
315 } 450 }
316#if defined(OLED_DISPLAY_128X64) 451#if defined(OLED_DISPLAY_VERBOSE)
317 oled_advance_page(true); 452 oled_advance_page(true);
318#endif 453#endif
319} 454}
320 455
321void oled_driver_render_logo(void) {
322 // clang-format off
323 static const char PROGMEM qmk_logo[] = {
324 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,
325 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,
326 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0};
327 // clang-format on
328 oled_write_P(qmk_logo, false);
329}
330
331void render_wpm(uint8_t padding) { 456void render_wpm(uint8_t padding) {
332#ifdef WPM_ENABLE 457#ifdef WPM_ENABLE
333 458
@@ -356,49 +481,389 @@ void render_pointing_dpi_status(uint8_t padding) {
356#endif 481#endif
357 482
358__attribute__((weak)) void oled_driver_render_logo_right(void) { 483__attribute__((weak)) void oled_driver_render_logo_right(void) {
359#if defined(OLED_DISPLAY_128X64) 484#if defined(OLED_DISPLAY_VERBOSE)
360 oled_driver_render_logo(); 485 oled_set_cursor(0, 2);
361 render_default_layer_state(); 486 render_default_layer_state();
362 oled_set_cursor(0, 4);
363#else 487#else
364 render_default_layer_state(); 488 render_default_layer_state();
365#endif 489#endif
366} 490}
367 491
368__attribute__((weak)) void oled_driver_render_logo_left(void) { 492// WPM-responsive animation stuff here
369#if defined(OLED_DISPLAY_128X64) 493#define OLED_SLEEP_FRAMES 2
370 oled_driver_render_logo(); 494#define OLED_SLEEP_SPEED 10 // below this wpm value your animation will idle
371# ifdef DEBUG_MATRIX_SCAN_RATE 495
496#define OLED_WAKE_FRAMES 2 // uncomment if >1
497#define OLED_WAKE_SPEED OLED_SLEEP_SPEED // below this wpm value your animation will idle
498
499#define OLED_KAKI_FRAMES 3
500#define OLED_KAKI_SPEED 40 // above this wpm value typing animation to triggere
501
502#define OLED_RTOGI_FRAMES 2
503//#define OLED_LTOGI_FRAMES 2
504
505//#define ANIM_FRAME_DURATION 500 // how long each frame lasts in ms
506// #define SLEEP_TIMER 60000 // should sleep after this period of 0 wpm, needs fixing
507#define OLED_ANIM_SIZE 32 // number of bytes in array, minimize for adequate firmware size, max is 1024
508#define OLED_ANIM_ROWS 4
509#define OLED_ANIM_MAX_FRAMES 3
510#if (OLED_SLEEP_FRAMES > OLED_ANIM_MAX_FRAMES) || (OLED_WAKE_FRAMES > OLED_ANIM_MAX_FRAMES) || (OLED_KAKI_FRAMES > OLED_ANIM_MAX_FRAMES) || (OLED_RTOGI_FRAMES > OLED_ANIM_MAX_FRAMES)
511# error frame size too large
512#endif
513
514static uint8_t animation_frame = 0;
515static uint8_t animation_type = 0;
516
517void render_kitty(void) {
518 // Images credit j-inc(/James Incandenza) and pixelbenny.
519 // Credit to obosob for initial animation approach.
520 // heavily modified by drashna because he's a glutton for punishment
521
522 // clang-format off
523 static const char PROGMEM animation[4][OLED_ANIM_MAX_FRAMES][OLED_ANIM_ROWS][OLED_ANIM_SIZE] = {
524 // sleep frames
525 {
526 {
527 {
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
529 0xa8, 0x48, 0xa8, 0x18, 0x08, 0x00, 0x00, 0x00,
530 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
532 },
533 {
534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03,
535 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x80,
536 0x44, 0x84, 0x06, 0x05, 0x04, 0x80, 0x40, 0x20,
537 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
538 },
539 {
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20,
541 0x18, 0x04, 0x04, 0x02, 0x7a, 0x86, 0x01, 0x80,
542 0x80, 0x01, 0x03, 0x05, 0x07, 0x01, 0x00, 0x00,
543 0x80, 0x83, 0x45, 0xfa, 0x3c, 0xe0, 0x00, 0x00
544 },
545 {
546 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08,
547 0x10, 0x10, 0x10, 0x10, 0x10, 0x33, 0x24, 0x28,
548 0x28, 0x29, 0x29, 0x29, 0x3a, 0x18, 0x1c, 0x39,
549 0x24, 0x24, 0x3a, 0x2d, 0x26, 0x31, 0x1f, 0x00
550 }
551 },
552 {
553 {
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
558 },
559 {
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561 0x22, 0x22, 0x3a, 0x2a, 0x26, 0x22, 0x80, 0xc0,
562 0x80, 0x00, 0x24, 0x34, 0x2c, 0xe4, 0x60, 0x10,
563 0x70, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
564 },
565 {
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38,
567 0x04, 0x02, 0x02, 0x01, 0x79, 0x87, 0x01, 0x80,
568 0x81, 0x83, 0x05, 0x05, 0x03, 0x01, 0x00, 0x00,
569 0x80, 0x43, 0x05, 0xfa, 0x3c, 0xe0, 0x00, 0x00
570 },
571 {
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08,
573 0x10, 0x10, 0x10, 0x10, 0x10, 0x33, 0x24, 0x28,
574 0x28, 0x28, 0x29, 0x29, 0x3a, 0x18, 0x1c, 0x39,
575 0x24, 0x24, 0x3a, 0x2d, 0x26, 0x31, 0x1f, 0x00
576 }
577 }
578 },
579 // wake frames
580 {
581 {
582 {
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0xc0, 0x30, 0x08, 0x10, 0x60, 0x80,
585 0x00, 0x80, 0x60, 0x10, 0x08, 0x30, 0xc0, 0x00,
586 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
587 },
588 {
589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x7f, 0x80, 0x40, 0x40, 0x5c, 0x00, 0x01,
591 0x41, 0x01, 0x00, 0x5c, 0x40, 0x40, 0x80, 0x7f,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
593 },
594 {
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
596 0x40, 0x40, 0x80, 0xe1, 0x12, 0x0a, 0x06, 0x00,
597 0x80, 0x00, 0x06, 0x0a, 0x12, 0xe1, 0x80, 0x40,
598 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
599 },
600 {
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14,
602 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18,
603 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x11, 0x10, 0x10,
604 0x14, 0x14, 0x1f, 0x1c, 0x14, 0x14, 0x14, 0x08
605 }
606 },
607 {
608 {
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0xc0, 0x30, 0x08, 0x10, 0x60, 0x80,
611 0x00, 0x80, 0x60, 0x10, 0x08, 0x30, 0xc0, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
613 },
614 {
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x7f, 0x90, 0x12, 0x0a, 0x02, 0xf4, 0x09,
617 0x0d, 0xf1, 0x04, 0x02, 0x0a, 0x12, 0x90, 0x7f,
618 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
619 },
620 {
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
622 0x40, 0x40, 0x80, 0xe1, 0x12, 0x0a, 0x06, 0x01,
623 0x81, 0x00, 0x06, 0x0a, 0x12, 0xe1, 0x80, 0x40,
624 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
625 },
626 {
627 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14,
628 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18,
629 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x11, 0x10, 0x10,
630 0x14, 0x14, 0x1f, 0x1c, 0x14, 0x14, 0x14, 0x08
631 }
632 }
633 },
634 // kaki frames
635 {
636 {
637 {
638 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x40,
639 0x80, 0x80, 0x80, 0x00, 0xfc, 0x84, 0x08, 0x08,
640 0x10, 0x20, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
642 },
643 {
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1e, 0x60,
645 0x80, 0x00, 0x00, 0x91, 0xa1, 0x80, 0x00, 0x00,
646 0x22, 0x84, 0x40, 0x50, 0x48, 0xc1, 0x3e, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
648 },
649 {
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
651 0x40, 0x41, 0x82, 0xe2, 0x12, 0x0a, 0x06, 0x00,
652 0x80, 0x88, 0x4f, 0x02, 0x22, 0xe2, 0x9f, 0x40,
653 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
654 },
655 {
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14,
657 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18,
658 0x0f, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x10,
659 0x14, 0x14, 0x1f, 0x1a, 0x0a, 0x0a, 0x04, 0x00
660 }
661 },
662 {
663 {
664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 0x00, 0xf0, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
668 },
669 {
670 0x00, 0x00, 0x06, 0x1a, 0x22, 0xc2, 0x04, 0x04,
671 0x04, 0x07, 0x00, 0xc0, 0x20, 0x10, 0x80, 0x80,
672 0x01, 0x01, 0x02, 0xfc, 0xfe, 0x02, 0x3c, 0x20,
673 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
674 },
675 {
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d,
677 0x55, 0x50, 0x94, 0xf0, 0x10, 0x09, 0x08, 0x00,
678 0x80, 0x00, 0x06, 0x09, 0x1b, 0xee, 0x00, 0x00,
679 0x00, 0x00, 0x81, 0xfe, 0x00, 0x00, 0x00, 0x00
680 },
681 {
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14,
683 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18,
684 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c,
685 0x14, 0x16, 0x15, 0x14, 0x14, 0x14, 0x14, 0x08
686 }
687 },
688 {
689 {
690 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x80, 0x00,
691 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x20, 0x40,
692 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
694 },
695 {
696 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x01,
697 0x02, 0x04, 0x04, 0x03, 0x80, 0x40, 0x40, 0x20,
698 0x00, 0x01, 0x02, 0x8c, 0x70, 0x00, 0x00, 0x00,
699 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
700 },
701 {
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d,
703 0x55, 0x50, 0x94, 0xf0, 0x10, 0x0a, 0x0e, 0x1d,
704 0x95, 0x24, 0x24, 0x27, 0x13, 0xe1, 0x01, 0x01,
705 0x01, 0x01, 0x02, 0xfc, 0x00, 0x00, 0x00, 0x00
706 },
707 {
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14,
709 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18,
710 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c,
711 0x14, 0x14, 0x17, 0x14, 0x14, 0x14, 0x14, 0x08
712 }
713 }
714 },
715 // rtogi frames
716 {
717 {
718 {
719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
721 0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02,
722 0x01, 0x0f, 0x90, 0x10, 0x20, 0xf0, 0xf8, 0xf8
723 },
724 {
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
726 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08,
727 0x48, 0x47, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00,
728 0x08, 0x88, 0xc7, 0xc4, 0x62, 0x23, 0x11, 0x3f
729 },
730 {
731 0x80, 0x40, 0x20, 0x10, 0x88, 0xcc, 0x43, 0x80,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0,
733 0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c,
734 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
735 },
736 {
737 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
738 0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04,
739 0x05, 0x04, 0x04, 0x04, 0x07, 0x07, 0x07, 0x03,
740 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
741 }
742 },
743 {
744 {
745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747 0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02,
748 0x01, 0x1f, 0xa0, 0x20, 0x40, 0x80, 0x00, 0xf0
749 },
750 {
751 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
752 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08,
753 0x48, 0x47, 0x88, 0x00, 0x00, 0x00, 0x00, 0x24,
754 0x24, 0x28, 0x6b, 0x40, 0xa0, 0x99, 0x86, 0xff
755 },
756 {
757 0x0f, 0x11, 0x22, 0x44, 0x48, 0x4c, 0x43, 0x80,
758 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0,
759 0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c,
760 0x04, 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x06, 0x01
761 },
762 {
763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04,
765 0x05, 0x04, 0x04, 0x04, 0x07, 0x07, 0x07, 0x03,
766 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
767 }
768 }
769 }
770 };
771 // clang-format on
772
773 for (uint8_t i = 0; i < 4; i++) {
774 oled_set_cursor(1, i + 2);
775 oled_write_raw_P(animation[animation_type][animation_frame][i], OLED_ANIM_SIZE);
776 }
777}
778
779uint32_t kitty_animation_phases(uint32_t triger_time, void *cb_arg) {
780 uint32_t anim_frame_duration = 500;
781 // can't change animation frame duration here, otherwise, it gets stuck.
782 // weirdly, it seems to work fine if it's in keymap.c but not here.
783 // Should move this block to the deferred execution?
784#ifdef POINTING_DEVICE_ENABLE
785 if (tap_toggling) {
786 animation_frame = (animation_frame + 1) % OLED_RTOGI_FRAMES;
787 animation_type = 3;
788 anim_frame_duration = 300;
789 } else
790#endif
791 {
792 if (get_current_wpm() <= OLED_SLEEP_SPEED) {
793 animation_frame = (animation_frame + 1) % OLED_SLEEP_FRAMES;
794 animation_type = 0;
795 anim_frame_duration = 500;
796 } else if (get_current_wpm() > OLED_WAKE_SPEED) {
797 animation_frame = (animation_frame + 1) % OLED_WAKE_FRAMES;
798 animation_type = 1;
799 anim_frame_duration = 800;
800 } else if (get_current_wpm() >= OLED_KAKI_SPEED) {
801 animation_frame = (animation_frame + 1) % OLED_KAKI_FRAMES;
802 animation_type = 2;
803 anim_frame_duration = 500;
804 }
805 }
806 return anim_frame_duration;
807}
808
809void oled_driver_render_logo_left(void) {
810#if defined(OLED_DISPLAY_VERBOSE)
811 oled_set_cursor(0, 2);
812 render_kitty();
813
814# if defined(KEYBOARD_handwired_tractyl_manuform)
815 oled_set_cursor(7, 0);
816 oled_write_P(PSTR("Tractyl"), true);
817# elif defined(KEYBOARD_bastardkb_charybdis)
818 oled_set_cursor(6, 0);
819 oled_write_P(PSTR("Charybdis"), true);
820# else
821 oled_set_cursor(8, 0);
822 oled_write_P(PSTR("Left"), true);
823# endif
824 oled_set_cursor(7, 2);
825# if defined(DEBUG_MATRIX_SCAN_RATE)
372 render_matrix_scan_rate(); 826 render_matrix_scan_rate();
373# elif defined(WPM_ENABLE) 827# elif defined(WPM_ENABLE)
374 render_wpm(0); 828 render_wpm(1);
375# endif 829# endif
376 oled_write_P(PSTR(" "), false); 830 oled_set_cursor(7, 3);
377# if defined(KEYBOARD_handwired_tractyl_manuform) || defined(KEYBOARD_bastardkb_charybdis) 831# if defined(KEYBOARD_handwired_tractyl_manuform)
832 render_pointing_dpi_status(0);
833# elif defined(KEYBOARD_bastardkb_charybdis)
378 render_pointing_dpi_status(1); 834 render_pointing_dpi_status(1);
379# endif 835# endif
380 oled_set_cursor(0, 4); 836 oled_set_cursor(0, 6);
381#else 837#else
382 render_default_layer_state(); 838 render_default_layer_state();
383#endif 839#endif
384} 840}
385 841
386void render_status_secondary(void) { 842void render_status_secondary(void) {
843# if defined(KEYBOARD_handwired_tractyl_manuform)
844 oled_set_cursor(7, 0);
845 oled_write_P(PSTR("Manuform"), true);
846# elif defined(KEYBOARD_bastardkb_charybdis)
847 oled_set_cursor(6, 0);
848 oled_write_P(PSTR("Charybdis"), true);
849# else
850 oled_set_cursor(8, 0);
851 oled_write_P(PSTR("Right"), true);
852# endif
387 oled_driver_render_logo_right(); 853 oled_driver_render_logo_right();
388 /* Show Keyboard Layout */ 854 /* Show Keyboard Layout */
389 render_layer_state(); 855 render_layer_state();
390 render_mod_status(get_mods() | get_oneshot_mods()); 856 render_mod_status(get_mods() | get_oneshot_mods());
391#if !defined(OLED_DISPLAY_128X64) && defined(WPM_ENABLE) && !defined(CONVERT_TO_PROTON_C) 857#if !defined(OLED_DISPLAY_VERBOSE) && defined(WPM_ENABLE) && !defined(CONVERT_TO_PROTON_C)
392 render_wpm(2); 858 render_wpm(2);
393#endif 859#endif
394 // render_keylock_status(host_keyboard_leds()); 860 render_keylock_status(host_keyboard_leds());
395} 861}
396 862
397void render_status_main(void) { 863void render_status_main(void) {
398 oled_driver_render_logo_left(); 864 oled_driver_render_logo_left();
399 865
400 /* Show Keyboard Layout */ 866 /* Show Keyboard Layout */
401 // render_keylock_status(host_keyboard_leds());
402 render_bootmagic_status(); 867 render_bootmagic_status();
403 render_user_status(); 868 render_user_status();
404 869
@@ -408,8 +873,14 @@ void render_status_main(void) {
408__attribute__((weak)) oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return rotation; } 873__attribute__((weak)) oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return rotation; }
409 874
410oled_rotation_t oled_init_user(oled_rotation_t rotation) { 875oled_rotation_t oled_init_user(oled_rotation_t rotation) {
411 memset(keylog_str, ' ', sizeof(keylog_str) - 1); 876 if (is_keyboard_master()) {
877 memset(keylog_str, ' ', OLED_KEYLOGGER_LENGTH);
878 }
879
880 kittoken = defer_exec(3000, kitty_animation_phases, NULL);
412 881
882 oled_clear();
883 oled_render();
413 return oled_init_keymap(rotation); 884 return oled_init_keymap(rotation);
414} 885}
415 886
@@ -417,22 +888,61 @@ bool oled_task_user(void) {
417 update_log(); 888 update_log();
418 889
419 if (is_keyboard_master()) { 890 if (is_keyboard_master()) {
891#ifndef OLED_DISPLAY_TEST
420 if (timer_elapsed32(oled_timer) > 30000) { 892 if (timer_elapsed32(oled_timer) > 30000) {
421 oled_off(); 893 oled_off();
422 return false; 894 return false;
423 } else { 895 } else
896#endif
897 {
424 oled_on(); 898 oled_on();
425 } 899 }
426 } 900 }
901#if defined(OLED_DISPLAY_VERBOSE)
902 static const char PROGMEM header_image[] = {
903 0,192, 32, 16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 7, 15, 31, 63,127,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127, 63, 31, 15, 7, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16, 32,192, 0,
904 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0
905 };
906 static const char PROGMEM footer_image[] = {
907 0, 3, 4, 8, 16, 32, 64,128,128,128,128,128,128,128,192,224,240,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,240,224,192,128,128,128,128,128,128,128, 64, 32, 16, 8, 4, 3, 0
908 };
909 oled_write_raw_P(header_image, sizeof(header_image));
910 oled_set_cursor(0, 1);
911#endif
912
913#ifndef OLED_DISPLAY_TEST
427 if (is_keyboard_left()) { 914 if (is_keyboard_left()) {
915#endif
428 render_status_main(); // Renders the current keyboard state (layer, lock, caps, scroll, etc) 916 render_status_main(); // Renders the current keyboard state (layer, lock, caps, scroll, etc)
917#ifndef OLED_DISPLAY_TEST
429 } else { 918 } else {
430 render_status_secondary(); 919 render_status_secondary();
431 } 920 }
432 if (is_keyboard_master()) { 921#endif
922
923#if defined(OLED_DISPLAY_128X128)
924 if (is_keyboard_left()) {
433 render_keylogger_status(); 925 render_keylogger_status();
434 } else {
435 render_keylock_status(host_keyboard_leds());
436 } 926 }
927#endif
928
929#if defined(OLED_DISPLAY_VERBOSE)
930 uint8_t num_of_rows;
931# if defined(OLED_DISPLAY_128X128)
932 num_of_rows = 15;
933# else
934 num_of_rows = 7;
935# endif
936 for (uint8_t i= 1; i < num_of_rows; i++) {
937 oled_set_cursor(0, i);
938 oled_write_raw_P(display_border, sizeof(display_border));
939 oled_set_cursor(21, i);
940 oled_write_raw_P(display_border, sizeof(display_border));
941 }
942
943 oled_set_cursor(0, num_of_rows);
944 oled_write_raw_P(footer_image, sizeof(footer_image));
945#endif
946
437 return false; 947 return false;
438} 948}
diff --git a/users/drashna/oled/oled_stuff.h b/users/drashna/oled/oled_stuff.h
index 8795684d6..985153c2f 100644
--- a/users/drashna/oled/oled_stuff.h
+++ b/users/drashna/oled/oled_stuff.h
@@ -18,6 +18,7 @@
18 18
19#include "quantum.h" 19#include "quantum.h"
20#include "oled_driver.h" 20#include "oled_driver.h"
21extern deferred_token kittoken;
21 22
22void oled_driver_render_logo(void); 23void oled_driver_render_logo(void);
23bool process_record_user_oled(uint16_t keycode, keyrecord_t *record); 24bool process_record_user_oled(uint16_t keycode, keyrecord_t *record);
@@ -37,12 +38,16 @@ void render_pointing_dpi_status(uint8_t padding);
37void oled_driver_render_logo_left(void); 38void oled_driver_render_logo_left(void);
38void oled_driver_render_logo_right(void); 39void oled_driver_render_logo_right(void);
39 40
40#ifdef OLED_DISPLAY_128X64 41#if defined(OLED_DISPLAY_128X128) || defined(OLED_DISPLAY_128X64)
41# define OLED_RENDER_KEYLOGGER "Keylogger: " 42# define OLED_DISPLAY_VERBOSE
42 43
44# define OLED_RENDER_KEYLOGGER "Keylogger: "
45# ifndef OLED_KEYLOGGER_LENGTH
46# define OLED_KEYLOGGER_LENGTH 9
47# endif
43# define OLED_RENDER_LAYOUT_NAME "Layout: " 48# define OLED_RENDER_LAYOUT_NAME "Layout: "
44# define OLED_RENDER_LAYOUT_QWERTY "Qwerty" 49# define OLED_RENDER_LAYOUT_QWERTY "Qwerty"
45# define OLED_RENDER_LAYOUT_COLEMAK_DH "Colemak-DH" 50# define OLED_RENDER_LAYOUT_COLEMAK_DH "ColemkDH"
46# define OLED_RENDER_LAYOUT_COLEMAK "Colemak" 51# define OLED_RENDER_LAYOUT_COLEMAK "Colemak"
47# define OLED_RENDER_LAYOUT_DVORAK "Dvorak" 52# define OLED_RENDER_LAYOUT_DVORAK "Dvorak"
48# define OLED_RENDER_LAYOUT_WORKMAN "Workman" 53# define OLED_RENDER_LAYOUT_WORKMAN "Workman"
@@ -58,11 +63,11 @@ void oled_driver_render_logo_right(void);
58# define OLED_RENDER_LAYER_MODS "Mods" 63# define OLED_RENDER_LAYER_MODS "Mods"
59 64
60# define OLED_RENDER_LOCK_NAME "Lock: " 65# define OLED_RENDER_LOCK_NAME "Lock: "
61# define OLED_RENDER_LOCK_NUML "NUML" 66# define OLED_RENDER_LOCK_NUML "NUM"
62# define OLED_RENDER_LOCK_CAPS "CAPS" 67# define OLED_RENDER_LOCK_CAPS "CAPS"
63# define OLED_RENDER_LOCK_SCLK "SCLK" 68# define OLED_RENDER_LOCK_SCLK "SCLK"
64 69
65# define OLED_RENDER_MODS_NAME "Mods:" 70# define OLED_RENDER_MODS_NAME "Mods"
66# define OLED_RENDER_MODS_SFT "Sft" 71# define OLED_RENDER_MODS_SFT "Sft"
67# define OLED_RENDER_MODS_CTL "Ctl" 72# define OLED_RENDER_MODS_CTL "Ctl"
68# define OLED_RENDER_MODS_ALT "Alt" 73# define OLED_RENDER_MODS_ALT "Alt"
@@ -84,6 +89,9 @@ void oled_driver_render_logo_right(void);
84# define OLED_RENDER_WPM_COUNTER "WPM: " 89# define OLED_RENDER_WPM_COUNTER "WPM: "
85#else 90#else
86# define OLED_RENDER_KEYLOGGER "KLogr" 91# define OLED_RENDER_KEYLOGGER "KLogr"
92# ifndef OLED_KEYLOGGER_LENGTH
93# define OLED_KEYLOGGER_LENGTH 5
94# endif
87 95
88# define OLED_RENDER_LAYOUT_NAME "Lyout" 96# define OLED_RENDER_LAYOUT_NAME "Lyout"
89# define OLED_RENDER_LAYOUT_QWERTY " QRTY" 97# define OLED_RENDER_LAYOUT_QWERTY " QRTY"
@@ -127,5 +135,7 @@ void oled_driver_render_logo_right(void);
127# define OLED_RENDER_USER_NUKE "Nuke" 135# define OLED_RENDER_USER_NUKE "Nuke"
128 136
129# define OLED_RENDER_WPM_COUNTER "WPM: " 137# define OLED_RENDER_WPM_COUNTER "WPM: "
130
131#endif 138#endif
139
140
141extern char keylog_str[OLED_KEYLOGGER_LENGTH];
diff --git a/users/drashna/oled/sh110x.c b/users/drashna/oled/sh110x.c
new file mode 100644
index 000000000..c850a4753
--- /dev/null
+++ b/users/drashna/oled/sh110x.c
@@ -0,0 +1,860 @@
1/*
2Copyright 2019 Ryan Caltabiano <https://github.com/XScorpion2>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17#include "i2c_master.h"
18#include "oled_driver.h"
19#include OLED_FONT_H
20#include "timer.h"
21#include "print.h"
22
23#include <string.h>
24
25#include "progmem.h"
26
27#include "keyboard.h"
28
29// Used commands from spec sheet: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
30// for SH1106: https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf
31
32// Fundamental Commands
33#define CONTRAST 0x81
34#define DISPLAY_ALL_ON 0xA5
35#define DISPLAY_ALL_ON_RESUME 0xA4
36#define NORMAL_DISPLAY 0xA6
37#define INVERT_DISPLAY 0xA7
38#define DISPLAY_ON 0xAF
39#define DISPLAY_OFF 0xAE
40#define NOP 0xE3
41
42// Scrolling Commands
43#define ACTIVATE_SCROLL 0x2F
44#define DEACTIVATE_SCROLL 0x2E
45#define SCROLL_RIGHT 0x26
46#define SCROLL_LEFT 0x27
47#define SCROLL_RIGHT_UP 0x29
48#define SCROLL_LEFT_UP 0x2A
49
50// Addressing Setting Commands
51#define MEMORY_MODE 0x20
52#define COLUMN_ADDR 0x21
53#define PAGE_ADDR 0x22
54#define PAM_SETCOLUMN_LSB 0x00
55#define PAM_SETCOLUMN_MSB 0x10
56#define PAM_PAGE_ADDR 0xB0 // 0xb0 -- 0xb7
57
58// Hardware Configuration Commands
59#define DISPLAY_START_LINE 0x40
60#define SEGMENT_REMAP 0xA0
61#define SEGMENT_REMAP_INV 0xA1
62#define MULTIPLEX_RATIO 0xA8
63#define COM_SCAN_INC 0xC0
64#define COM_SCAN_DEC 0xC8
65#define DISPLAY_OFFSET 0xD3
66#define COM_PINS 0xDA
67#define COM_PINS_SEQ 0x02
68#define COM_PINS_ALT 0x12
69#define COM_PINS_SEQ_LR 0x22
70#define COM_PINS_ALT_LR 0x32
71
72// Timing & Driving Commands
73#define DISPLAY_CLOCK 0xD5
74#define PRE_CHARGE_PERIOD 0xD9
75#define VCOM_DETECT 0xDB
76
77// Advance Graphic Commands
78#define FADE_BLINK 0x23
79#define ENABLE_FADE 0x20
80#define ENABLE_BLINK 0x30
81
82// Charge Pump Commands
83#define CHARGE_PUMP 0x8D
84
85// Commands specific to the SH1107 chip
86#define SH1107_DISPLAY_START_LINE 0xDC
87#define SH1107_MEMORY_MODE_PAGE 0x20
88#define SH1107_MEMORY_MODE_VERTICAL 0x21
89
90// Misc defines
91#ifndef OLED_BLOCK_COUNT
92# define OLED_BLOCK_COUNT (sizeof(OLED_BLOCK_TYPE) * 8)
93#endif
94#ifndef OLED_BLOCK_SIZE
95# define OLED_BLOCK_SIZE (OLED_MATRIX_SIZE / OLED_BLOCK_COUNT)
96#endif
97
98#define OLED_ALL_BLOCKS_MASK (((((OLED_BLOCK_TYPE)1 << (OLED_BLOCK_COUNT - 1)) - 1) << 1) | 1)
99
100#define OLED_IC_HAS_HORIZONTAL_MODE (OLED_IC == OLED_IC_SSD1306)
101#define OLED_IC_COM_PINS_ARE_COLUMNS (OLED_IC == OLED_IC_SH1107)
102
103#ifndef OLED_COM_PIN_COUNT
104# if OLED_IC == OLED_IC_SH1106
105# define OLED_COM_PIN_COUNT 64
106# elif OLED_IC == OLED_IC_SH1107
107# define OLED_COM_PIN_COUNT 128
108# else
109# error Invalid OLED_IC value
110# endif
111#endif
112
113#ifndef OLED_COM_PIN_OFFSET
114# define OLED_COM_PIN_OFFSET 0
115#endif
116
117// i2c defines
118#define I2C_CMD 0x00
119#define I2C_DATA 0x40
120#if defined(__AVR__)
121# define I2C_TRANSMIT_P(data) i2c_transmit_P((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT)
122#else // defined(__AVR__)
123# define I2C_TRANSMIT_P(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT)
124#endif // defined(__AVR__)
125#define I2C_TRANSMIT(data) i2c_transmit((OLED_DISPLAY_ADDRESS << 1), &data[0], sizeof(data), OLED_I2C_TIMEOUT)
126#define I2C_WRITE_REG(mode, data, size) i2c_writeReg((OLED_DISPLAY_ADDRESS << 1), mode, data, size, OLED_I2C_TIMEOUT)
127
128#define HAS_FLAGS(bits, flags) ((bits & flags) == flags)
129
130// Display buffer's is the same as the OLED memory layout
131// this is so we don't end up with rounding errors with
132// parts of the display unusable or don't get cleared correctly
133// and also allows for drawing & inverting
134uint8_t oled_buffer[OLED_MATRIX_SIZE];
135uint8_t * oled_cursor;
136OLED_BLOCK_TYPE oled_dirty = 0;
137bool oled_initialized = false;
138bool oled_active = false;
139bool oled_scrolling = false;
140bool oled_inverted = false;
141uint8_t oled_brightness = OLED_BRIGHTNESS;
142oled_rotation_t oled_rotation = 0;
143uint8_t oled_rotation_width = 0;
144uint8_t oled_scroll_speed = 0; // this holds the speed after being remapped to ssd1306 internal values
145uint8_t oled_scroll_start = 0;
146uint8_t oled_scroll_end = 7;
147#if OLED_TIMEOUT > 0
148uint32_t oled_timeout;
149#endif
150#if OLED_SCROLL_TIMEOUT > 0
151uint32_t oled_scroll_timeout;
152#endif
153#if OLED_UPDATE_INTERVAL > 0
154uint16_t oled_update_timeout;
155#endif
156
157// Internal variables to reduce math instructions
158
159#if defined(__AVR__)
160// identical to i2c_transmit, but for PROGMEM since all initialization is in PROGMEM arrays currently
161// probably should move this into i2c_master...
162static i2c_status_t i2c_transmit_P(uint8_t address, const uint8_t *data, uint16_t length, uint16_t timeout) {
163 i2c_status_t status = i2c_start(address | I2C_WRITE, timeout);
164
165 for (uint16_t i = 0; i < length && status >= 0; i++) {
166 status = i2c_write(pgm_read_byte((const char *)data++), timeout);
167 if (status) break;
168 }
169
170 i2c_stop();
171
172 return status;
173}
174#endif
175
176// Flips the rendering bits for a character at the current cursor position
177static void InvertCharacter(uint8_t *cursor) {
178 const uint8_t *end = cursor + OLED_FONT_WIDTH;
179 while (cursor < end) {
180 *cursor = ~(*cursor);
181 cursor++;
182 }
183}
184
185bool oled_init(oled_rotation_t rotation) {
186#if defined(USE_I2C) && defined(SPLIT_KEYBOARD)
187 if (!is_keyboard_master()) {
188 return true;
189 }
190#endif
191
192 oled_rotation = oled_init_user(oled_init_kb(rotation));
193 if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
194 oled_rotation_width = OLED_DISPLAY_WIDTH;
195 } else {
196 oled_rotation_width = OLED_DISPLAY_HEIGHT;
197 }
198 i2c_init();
199
200 static const uint8_t PROGMEM display_setup1[] = {
201 I2C_CMD,
202 DISPLAY_OFF,
203 DISPLAY_CLOCK,
204 0x80,
205 MULTIPLEX_RATIO,
206#if OLED_IC_COM_PINS_ARE_COLUMNS
207 OLED_DISPLAY_WIDTH - 1,
208#else
209 OLED_DISPLAY_HEIGHT - 1,
210#endif
211 DISPLAY_OFFSET,
212 0x00,
213 DISPLAY_START_LINE | 0x00,
214 CHARGE_PUMP,
215 0x14,
216#if (OLED_IC != OLED_IC_SH1106)
217 // MEMORY_MODE is unsupported on SH1106 (Page Addressing only)
218 MEMORY_MODE,
219 0x00, // Horizontal addressing mode
220#elif OLED_IC == OLED_IC_SH1107
221 // Page addressing mode
222 SH1107_MEMORY_MODE_PAGE,
223#endif
224 };
225 if (I2C_TRANSMIT_P(display_setup1) != I2C_STATUS_SUCCESS) {
226 print("oled_init cmd set 1 failed\n");
227 return false;
228 }
229
230 if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_180)) {
231 static const uint8_t PROGMEM display_normal[] = {
232 I2C_CMD, SEGMENT_REMAP_INV, COM_SCAN_DEC, DISPLAY_OFFSET, OLED_COM_PIN_OFFSET,
233 };
234 if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) {
235 print("oled_init cmd normal rotation failed\n");
236 return false;
237 }
238 } else {
239 static const uint8_t PROGMEM display_flipped[] = {
240 I2C_CMD, SEGMENT_REMAP, COM_SCAN_INC, DISPLAY_OFFSET, (OLED_COM_PIN_COUNT - OLED_COM_PIN_OFFSET) % OLED_COM_PIN_COUNT,
241 };
242 if (I2C_TRANSMIT_P(display_flipped) != I2C_STATUS_SUCCESS) {
243 print("display_flipped failed\n");
244 return false;
245 }
246 }
247
248 static const uint8_t PROGMEM display_setup2[] = {I2C_CMD, COM_PINS, OLED_COM_PINS, CONTRAST, OLED_BRIGHTNESS, PRE_CHARGE_PERIOD, 0x22, VCOM_DETECT, 0x35, DISPLAY_ALL_ON_RESUME, NORMAL_DISPLAY, DEACTIVATE_SCROLL, DISPLAY_ON}; if (I2C_TRANSMIT_P(display_setup2) != I2C_STATUS_SUCCESS) {
249 print("display_setup2 failed\n");
250 return false;
251 }
252
253#if OLED_TIMEOUT > 0
254 oled_timeout = timer_read32() + OLED_TIMEOUT;
255#endif
256#if OLED_SCROLL_TIMEOUT > 0
257 oled_scroll_timeout = timer_read32() + OLED_SCROLL_TIMEOUT;
258#endif
259
260 oled_clear();
261 oled_initialized = true;
262 oled_active = true;
263 oled_scrolling = false;
264 return true;
265}
266
267__attribute__((weak)) oled_rotation_t oled_init_kb(oled_rotation_t rotation) { return rotation; }
268__attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) { return rotation; }
269
270void oled_clear(void) {
271 memset(oled_buffer, 0, sizeof(oled_buffer));
272 oled_cursor = &oled_buffer[0];
273 oled_dirty = OLED_ALL_BLOCKS_MASK;
274}
275
276static void calc_bounds(uint8_t update_start, uint8_t *cmd_array) {
277 // Calculate commands to set memory addressing bounds.
278 uint8_t start_page = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_WIDTH;
279 uint8_t start_column = OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_WIDTH;
280#if !OLED_IC_HAS_HORIZONTAL_MODE
281 // Commands for Page Addressing Mode. Sets starting page and column; has no end bound.
282 // Column value must be split into high and low nybble and sent as two commands.
283 cmd_array[0] = PAM_PAGE_ADDR | start_page;
284 cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f);
285 cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f);
286 cmd_array[3] = NOP;
287 cmd_array[4] = NOP;
288 cmd_array[5] = NOP;
289#else
290 // Commands for use in Horizontal Addressing mode.
291 cmd_array[1] = start_column + OLED_COLUMN_OFFSET;
292 cmd_array[4] = start_page;
293 cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) % OLED_DISPLAY_WIDTH + cmd_array[1];
294 cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_WIDTH - 1) / OLED_DISPLAY_WIDTH - 1 + cmd_array[4];
295#endif
296}
297
298static void calc_bounds_90(uint8_t update_start, uint8_t *cmd_array) {
299 // Block numbering starts from the bottom left corner, going up and then to
300 // the right. The controller needs the page and column numbers for the top
301 // left and bottom right corners of that block.
302
303 // Total number of pages across the screen height.
304 const uint8_t height_in_pages = OLED_DISPLAY_HEIGHT / 8;
305
306 // Difference of starting page numbers for adjacent blocks; may be 0 if
307 // blocks are large enough to occupy one or more whole 8px columns.
308 const uint8_t page_inc_per_block = OLED_BLOCK_SIZE % OLED_DISPLAY_HEIGHT / 8;
309
310 // Top page number for a block which is at the bottom edge of the screen.
311 const uint8_t bottom_block_top_page = (height_in_pages - page_inc_per_block) % height_in_pages;
312
313#if !OLED_IC_HAS_HORIZONTAL_MODE
314 // Only the Page Addressing Mode is supported
315 uint8_t start_page = bottom_block_top_page - (OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_HEIGHT / 8);
316 uint8_t start_column = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_HEIGHT * 8;
317 cmd_array[0] = PAM_PAGE_ADDR | start_page;
318 cmd_array[1] = PAM_SETCOLUMN_LSB | ((OLED_COLUMN_OFFSET + start_column) & 0x0f);
319 cmd_array[2] = PAM_SETCOLUMN_MSB | ((OLED_COLUMN_OFFSET + start_column) >> 4 & 0x0f);
320#else
321 cmd_array[1] = OLED_BLOCK_SIZE * update_start / OLED_DISPLAY_HEIGHT * 8 + OLED_COLUMN_OFFSET;
322 cmd_array[4] = bottom_block_top_page - (OLED_BLOCK_SIZE * update_start % OLED_DISPLAY_HEIGHT / 8);
323 cmd_array[2] = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) / OLED_DISPLAY_HEIGHT * 8 - 1 + cmd_array[1];
324 cmd_array[5] = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) % OLED_DISPLAY_HEIGHT / 8 + cmd_array[4];
325#endif
326}
327
328uint8_t crot(uint8_t a, int8_t n) {
329 const uint8_t mask = 0x7;
330 n &= mask;
331 return a << n | a >> (-n & mask);
332}
333
334static void rotate_90(const uint8_t *src, uint8_t *dest) {
335 for (uint8_t i = 0, shift = 7; i < 8; ++i, --shift) {
336 uint8_t selector = (1 << i);
337 for (uint8_t j = 0; j < 8; ++j) {
338 dest[i] |= crot(src[j] & selector, shift - (int8_t)j);
339 }
340 }
341}
342
343void oled_render(void) {
344 if (!oled_initialized) {
345 return;
346 }
347
348 // Do we have work to do?
349 oled_dirty &= OLED_ALL_BLOCKS_MASK;
350 if (!oled_dirty || oled_scrolling) {
351 return;
352 }
353
354 // Find first dirty block
355 uint8_t update_start = 0;
356 while (!(oled_dirty & ((OLED_BLOCK_TYPE)1 << update_start))) {
357 ++update_start;
358 }
359
360 // Set column & page position
361#if OLED_IC_HAS_HORIZONTAL_MODE
362 static uint8_t display_start[] = {I2C_CMD, COLUMN_ADDR, 0, OLED_DISPLAY_WIDTH - 1, PAGE_ADDR, 0, OLED_DISPLAY_HEIGHT / 8 - 1};
363#else
364 static uint8_t display_start[] = {I2C_CMD, PAM_PAGE_ADDR, PAM_SETCOLUMN_LSB, PAM_SETCOLUMN_MSB};
365#endif
366 if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
367 calc_bounds(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start
368 } else {
369 calc_bounds_90(update_start, &display_start[1]); // Offset from I2C_CMD byte at the start
370 }
371
372 // Send column & page position
373 if (I2C_TRANSMIT(display_start) != I2C_STATUS_SUCCESS) {
374 print("oled_render offset command failed\n");
375 return;
376 }
377
378 if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
379 // Send render data chunk as is
380 if (I2C_WRITE_REG(I2C_DATA, &oled_buffer[OLED_BLOCK_SIZE * update_start], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) {
381 print("oled_render data failed\n");
382 return;
383 }
384 } else {
385 // Rotate the render chunks
386 const static uint8_t source_map[] = OLED_SOURCE_MAP;
387 const static uint8_t target_map[] = OLED_TARGET_MAP;
388
389 static uint8_t temp_buffer[OLED_BLOCK_SIZE];
390 memset(temp_buffer, 0, sizeof(temp_buffer));
391 for (uint8_t i = 0; i < sizeof(source_map); ++i) {
392 rotate_90(&oled_buffer[OLED_BLOCK_SIZE * update_start + source_map[i]], &temp_buffer[target_map[i]]);
393 }
394
395#if OLED_IC_HAS_HORIZONTAL_MODE
396 // Send render data chunk after rotating
397 if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[0], OLED_BLOCK_SIZE) != I2C_STATUS_SUCCESS) {
398 print("oled_render90 data failed\n");
399 return;
400 }
401#else
402 // For SH1106 or SH1107 the data chunk must be split into separate pieces for each page
403 const uint8_t columns_in_block = (OLED_BLOCK_SIZE + OLED_DISPLAY_HEIGHT - 1) / OLED_DISPLAY_HEIGHT * 8;
404 const uint8_t num_pages = OLED_BLOCK_SIZE / columns_in_block;
405 for (uint8_t i = 0; i < num_pages; ++i) {
406 // Send column & page position for all pages except the first one
407 if (i > 0) {
408 display_start[1]++;
409 if (I2C_TRANSMIT(display_start) != I2C_STATUS_SUCCESS) {
410 print("oled_render offset command failed\n");
411 return;
412 }
413 }
414 // Send data for the page
415 if (I2C_WRITE_REG(I2C_DATA, &temp_buffer[columns_in_block * i], columns_in_block) != I2C_STATUS_SUCCESS) {
416 print("oled_render90 data failed\n");
417 return;
418 }
419 }
420#endif
421 }
422
423 // Turn on display if it is off
424 oled_on();
425
426 // Clear dirty flag
427 oled_dirty &= ~((OLED_BLOCK_TYPE)1 << update_start);
428}
429
430void oled_set_cursor(uint8_t col, uint8_t line) {
431 uint16_t index = line * oled_rotation_width + col * OLED_FONT_WIDTH;
432
433 // Out of bounds?
434 if (index >= OLED_MATRIX_SIZE) {
435 index = 0;
436 }
437
438 oled_cursor = &oled_buffer[index];
439}
440
441void oled_advance_page(bool clearPageRemainder) {
442 uint16_t index = oled_cursor - &oled_buffer[0];
443 uint8_t remaining = oled_rotation_width - (index % oled_rotation_width);
444
445 if (clearPageRemainder) {
446 // Remaining Char count
447 remaining = remaining / OLED_FONT_WIDTH;
448
449 // Write empty character until next line
450 while (remaining--) oled_write_char(' ', false);
451 } else {
452 // Next page index out of bounds?
453 if (index + remaining >= OLED_MATRIX_SIZE) {
454 index = 0;
455 remaining = 0;
456 }
457
458 oled_cursor = &oled_buffer[index + remaining];
459 }
460}
461
462void oled_advance_char(void) {
463 uint16_t nextIndex = oled_cursor - &oled_buffer[0] + OLED_FONT_WIDTH;
464 uint8_t remainingSpace = oled_rotation_width - (nextIndex % oled_rotation_width);
465
466 // Do we have enough space on the current line for the next character
467 if (remainingSpace < OLED_FONT_WIDTH) {
468 nextIndex += remainingSpace;
469 }
470
471 // Did we go out of bounds
472 if (nextIndex >= OLED_MATRIX_SIZE) {
473 nextIndex = 0;
474 }
475
476 // Update cursor position
477 oled_cursor = &oled_buffer[nextIndex];
478}
479
480// Main handler that writes character data to the display buffer
481void oled_write_char(const char data, bool invert) {
482 // Advance to the next line if newline
483 if (data == '\n') {
484 // Old source wrote ' ' until end of line...
485 oled_advance_page(true);
486 return;
487 }
488
489 if (data == '\r') {
490 oled_advance_page(false);
491 return;
492 }
493
494 // copy the current render buffer to check for dirty after
495 static uint8_t oled_temp_buffer[OLED_FONT_WIDTH];
496 memcpy(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH);
497
498 _Static_assert(sizeof(font) >= ((OLED_FONT_END + 1 - OLED_FONT_START) * OLED_FONT_WIDTH), "OLED_FONT_END references outside array");
499
500 // set the reder buffer data
501 uint8_t cast_data = (uint8_t)data; // font based on unsigned type for index
502 if (cast_data < OLED_FONT_START || cast_data > OLED_FONT_END) {
503 memset(oled_cursor, 0x00, OLED_FONT_WIDTH);
504 } else {
505 const uint8_t *glyph = &font[(cast_data - OLED_FONT_START) * OLED_FONT_WIDTH];
506 memcpy_P(oled_cursor, glyph, OLED_FONT_WIDTH);
507 }
508
509 // Invert if needed
510 if (invert) {
511 InvertCharacter(oled_cursor);
512 }
513
514 // Dirty check
515 if (memcmp(&oled_temp_buffer, oled_cursor, OLED_FONT_WIDTH)) {
516 uint16_t index = oled_cursor - &oled_buffer[0];
517 oled_dirty |= ((OLED_BLOCK_TYPE)1 << (index / OLED_BLOCK_SIZE));
518 // Edgecase check if the written data spans the 2 chunks
519 oled_dirty |= ((OLED_BLOCK_TYPE)1 << ((index + OLED_FONT_WIDTH - 1) / OLED_BLOCK_SIZE));
520 }
521
522 // Finally move to the next char
523 oled_advance_char();
524}
525
526void oled_write(const char *data, bool invert) {
527 const char *end = data + strlen(data);
528 while (data < end) {
529 oled_write_char(*data, invert);
530 data++;
531 }
532}
533
534void oled_write_ln(const char *data, bool invert) {
535 oled_write(data, invert);
536 oled_advance_page(true);
537}
538
539void oled_pan(bool left) {
540 uint16_t i = 0;
541 for (uint16_t y = 0; y < OLED_DISPLAY_HEIGHT / 8; y++) {
542 if (left) {
543 for (uint16_t x = 0; x < OLED_DISPLAY_WIDTH - 1; x++) {
544 i = y * OLED_DISPLAY_WIDTH + x;
545 oled_buffer[i] = oled_buffer[i + 1];
546 }
547 } else {
548 for (uint16_t x = OLED_DISPLAY_WIDTH - 1; x > 0; x--) {
549 i = y * OLED_DISPLAY_WIDTH + x;
550 oled_buffer[i] = oled_buffer[i - 1];
551 }
552 }
553 }
554 oled_dirty = OLED_ALL_BLOCKS_MASK;
555}
556
557oled_buffer_reader_t oled_read_raw(uint16_t start_index) {
558 if (start_index > OLED_MATRIX_SIZE) start_index = OLED_MATRIX_SIZE;
559 oled_buffer_reader_t ret_reader;
560 ret_reader.current_element = &oled_buffer[start_index];
561 ret_reader.remaining_element_count = OLED_MATRIX_SIZE - start_index;
562 return ret_reader;
563}
564
565void oled_write_raw_byte(const char data, uint16_t index) {
566 if (index > OLED_MATRIX_SIZE) index = OLED_MATRIX_SIZE;
567 if (oled_buffer[index] == data) return;
568 oled_buffer[index] = data;
569 oled_dirty |= ((OLED_BLOCK_TYPE)1 << (index / OLED_BLOCK_SIZE));
570}
571
572void oled_write_raw(const char *data, uint16_t size) {
573 uint16_t cursor_start_index = oled_cursor - &oled_buffer[0];
574 if ((size + cursor_start_index) > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE - cursor_start_index;
575 for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
576 uint8_t c = *data++;
577 if (oled_buffer[i] == c) continue;
578 oled_buffer[i] = c;
579 oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE));
580 }
581}
582
583void oled_write_pixel(uint8_t x, uint8_t y, bool on) {
584 if (x >= oled_rotation_width) {
585 return;
586 }
587 uint16_t index = x + (y / 8) * oled_rotation_width;
588 if (index >= OLED_MATRIX_SIZE) {
589 return;
590 }
591 uint8_t data = oled_buffer[index];
592 if (on) {
593 data |= (1 << (y % 8));
594 } else {
595 data &= ~(1 << (y % 8));
596 }
597 if (oled_buffer[index] != data) {
598 oled_buffer[index] = data;
599 oled_dirty |= ((OLED_BLOCK_TYPE)1 << (index / OLED_BLOCK_SIZE));
600 }
601}
602
603#if defined(__AVR__)
604void oled_write_P(const char *data, bool invert) {
605 uint8_t c = pgm_read_byte(data);
606 while (c != 0) {
607 oled_write_char(c, invert);
608 c = pgm_read_byte(++data);
609 }
610}
611
612void oled_write_ln_P(const char *data, bool invert) {
613 oled_write_P(data, invert);
614 oled_advance_page(true);
615}
616
617void oled_write_raw_P(const char *data, uint16_t size) {
618 uint16_t cursor_start_index = oled_cursor - &oled_buffer[0];
619 if ((size + cursor_start_index) > OLED_MATRIX_SIZE) size = OLED_MATRIX_SIZE - cursor_start_index;
620 for (uint16_t i = cursor_start_index; i < cursor_start_index + size; i++) {
621 uint8_t c = pgm_read_byte(data++);
622 if (oled_buffer[i] == c) continue;
623 oled_buffer[i] = c;
624 oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE));
625 }
626}
627#endif // defined(__AVR__)
628
629bool oled_on(void) {
630 if (!oled_initialized) {
631 return oled_active;
632 }
633
634#if OLED_TIMEOUT > 0
635 oled_timeout = timer_read32() + OLED_TIMEOUT;
636#endif
637
638 static const uint8_t PROGMEM display_on[] =
639#ifdef OLED_FADE_OUT
640 {I2C_CMD, FADE_BLINK, 0x00};
641#else
642 {I2C_CMD, DISPLAY_ON};
643#endif
644
645 if (!oled_active) {
646 if (I2C_TRANSMIT_P(display_on) != I2C_STATUS_SUCCESS) {
647 print("oled_on cmd failed\n");
648 return oled_active;
649 }
650 oled_active = true;
651 }
652 return oled_active;
653}
654
655bool oled_off(void) {
656 if (!oled_initialized) {
657 return !oled_active;
658 }
659
660 static const uint8_t PROGMEM display_off[] =
661#ifdef OLED_FADE_OUT
662 {I2C_CMD, FADE_BLINK, ENABLE_FADE | OLED_FADE_OUT_INTERVAL};
663#else
664 {I2C_CMD, DISPLAY_OFF};
665#endif
666
667 if (oled_active) {
668 if (I2C_TRANSMIT_P(display_off) != I2C_STATUS_SUCCESS) {
669 print("oled_off cmd failed\n");
670 return oled_active;
671 }
672 oled_active = false;
673 }
674 return !oled_active;
675}
676
677bool is_oled_on(void) { return oled_active; }
678
679uint8_t oled_set_brightness(uint8_t level) {
680 if (!oled_initialized) {
681 return oled_brightness;
682 }
683
684 uint8_t set_contrast[] = {I2C_CMD, CONTRAST, level};
685 if (oled_brightness != level) {
686 if (I2C_TRANSMIT(set_contrast) != I2C_STATUS_SUCCESS) {
687 print("set_brightness cmd failed\n");
688 return oled_brightness;
689 }
690 oled_brightness = level;
691 }
692 return oled_brightness;
693}
694
695uint8_t oled_get_brightness(void) { return oled_brightness; }
696
697// Set the specific 8 lines rows of the screen to scroll.
698// 0 is the default for start, and 7 for end, which is the entire
699// height of the screen. For 128x32 screens, rows 4-7 are not used.
700void oled_scroll_set_area(uint8_t start_line, uint8_t end_line) {
701 oled_scroll_start = start_line;
702 oled_scroll_end = end_line;
703}
704
705void oled_scroll_set_speed(uint8_t speed) {
706 // Sets the speed for scrolling... does not take effect
707 // until scrolling is either started or restarted
708 // the ssd1306 supports 8 speeds
709 // FrameRate2 speed = 7
710 // FrameRate3 speed = 4
711 // FrameRate4 speed = 5
712 // FrameRate5 speed = 0
713 // FrameRate25 speed = 6
714 // FrameRate64 speed = 1
715 // FrameRate128 speed = 2
716 // FrameRate256 speed = 3
717 // for ease of use these are remaped here to be in order
718 static const uint8_t scroll_remap[8] = {7, 4, 5, 0, 6, 1, 2, 3};
719 oled_scroll_speed = scroll_remap[speed];
720}
721
722bool oled_scroll_right(void) {
723 if (!oled_initialized) {
724 return oled_scrolling;
725 }
726
727 // Dont enable scrolling if we need to update the display
728 // This prevents scrolling of bad data from starting the scroll too early after init
729 if (!oled_dirty && !oled_scrolling) {
730 uint8_t display_scroll_right[] = {I2C_CMD, SCROLL_RIGHT, 0x00, oled_scroll_start, oled_scroll_speed, oled_scroll_end, 0x00, 0xFF, ACTIVATE_SCROLL};
731 if (I2C_TRANSMIT(display_scroll_right) != I2C_STATUS_SUCCESS) {
732 print("oled_scroll_right cmd failed\n");
733 return oled_scrolling;
734 }
735 oled_scrolling = true;
736 }
737 return oled_scrolling;
738}
739
740bool oled_scroll_left(void) {
741 if (!oled_initialized) {
742 return oled_scrolling;
743 }
744
745 // Dont enable scrolling if we need to update the display
746 // This prevents scrolling of bad data from starting the scroll too early after init
747 if (!oled_dirty && !oled_scrolling) {
748 uint8_t display_scroll_left[] = {I2C_CMD, SCROLL_LEFT, 0x00, oled_scroll_start, oled_scroll_speed, oled_scroll_end, 0x00, 0xFF, ACTIVATE_SCROLL};
749 if (I2C_TRANSMIT(display_scroll_left) != I2C_STATUS_SUCCESS) {
750 print("oled_scroll_left cmd failed\n");
751 return oled_scrolling;
752 }
753 oled_scrolling = true;
754 }
755 return oled_scrolling;
756}
757
758bool oled_scroll_off(void) {
759 if (!oled_initialized) {
760 return !oled_scrolling;
761 }
762
763 if (oled_scrolling) {
764 static const uint8_t PROGMEM display_scroll_off[] = {I2C_CMD, DEACTIVATE_SCROLL};
765 if (I2C_TRANSMIT_P(display_scroll_off) != I2C_STATUS_SUCCESS) {
766 print("oled_scroll_off cmd failed\n");
767 return oled_scrolling;
768 }
769 oled_scrolling = false;
770 oled_dirty = OLED_ALL_BLOCKS_MASK;
771 }
772 return !oled_scrolling;
773}
774
775bool is_oled_scrolling(void) { return oled_scrolling; }
776
777bool oled_invert(bool invert) {
778 if (!oled_initialized) {
779 return oled_inverted;
780 }
781
782 if (invert && !oled_inverted) {
783 static const uint8_t PROGMEM display_inverted[] = {I2C_CMD, INVERT_DISPLAY};
784 if (I2C_TRANSMIT_P(display_inverted) != I2C_STATUS_SUCCESS) {
785 print("oled_invert cmd failed\n");
786 return oled_inverted;
787 }
788 oled_inverted = true;
789 } else if (!invert && oled_inverted) {
790 static const uint8_t PROGMEM display_normal[] = {I2C_CMD, NORMAL_DISPLAY};
791 if (I2C_TRANSMIT_P(display_normal) != I2C_STATUS_SUCCESS) {
792 print("oled_invert cmd failed\n");
793 return oled_inverted;
794 }
795 oled_inverted = false;
796 }
797
798 return oled_inverted;
799}
800
801uint8_t oled_max_chars(void) {
802 if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
803 return OLED_DISPLAY_WIDTH / OLED_FONT_WIDTH;
804 }
805 return OLED_DISPLAY_HEIGHT / OLED_FONT_WIDTH;
806}
807
808uint8_t oled_max_lines(void) {
809 if (!HAS_FLAGS(oled_rotation, OLED_ROTATION_90)) {
810 return OLED_DISPLAY_HEIGHT / OLED_FONT_HEIGHT;
811 }
812 return OLED_DISPLAY_WIDTH / OLED_FONT_HEIGHT;
813}
814
815void oled_task(void) {
816 if (!oled_initialized) {
817 return;
818 }
819
820#if OLED_UPDATE_INTERVAL > 0
821 if (timer_elapsed(oled_update_timeout) >= OLED_UPDATE_INTERVAL) {
822 oled_update_timeout = timer_read();
823 oled_set_cursor(0, 0);
824 oled_task_kb();
825 }
826#else
827 oled_set_cursor(0, 0);
828 oled_task_kb();
829#endif
830
831#if OLED_SCROLL_TIMEOUT > 0
832 if (oled_dirty && oled_scrolling) {
833 oled_scroll_timeout = timer_read32() + OLED_SCROLL_TIMEOUT;
834 oled_scroll_off();
835 }
836#endif
837
838 // Smart render system, no need to check for dirty
839 oled_render();
840
841 // Display timeout check
842#if OLED_TIMEOUT > 0
843 if (oled_active && timer_expired32(timer_read32(), oled_timeout)) {
844 oled_off();
845 }
846#endif
847
848#if OLED_SCROLL_TIMEOUT > 0
849 if (!oled_scrolling && timer_expired32(timer_read32(), oled_scroll_timeout)) {
850# ifdef OLED_SCROLL_TIMEOUT_RIGHT
851 oled_scroll_right();
852# else
853 oled_scroll_left();
854# endif
855 }
856#endif
857}
858
859__attribute__((weak)) bool oled_task_kb(void) { return oled_task_user(); }
860__attribute__((weak)) bool oled_task_user(void) { return true; }
diff --git a/users/drashna/pointing/pointing.c b/users/drashna/pointing/pointing.c
index 0bd14e477..0116ce090 100644
--- a/users/drashna/pointing/pointing.c
+++ b/users/drashna/pointing/pointing.c
@@ -105,7 +105,7 @@ bool process_record_pointing(uint16_t keycode, keyrecord_t* record) {
105 mouse_timer = timer_read(); 105 mouse_timer = timer_read();
106 break; 106 break;
107 } 107 }
108 if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) { 108 if (layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) {
109 layer_off(_MOUSE); 109 layer_off(_MOUSE);
110 } 110 }
111 mouse_keycode_tracker = 0; 111 mouse_keycode_tracker = 0;
diff --git a/users/drashna/rules.mk b/users/drashna/rules.mk
index 445d1cf5a..553cc2cbc 100644
--- a/users/drashna/rules.mk
+++ b/users/drashna/rules.mk
@@ -78,10 +78,20 @@ endif
78 78
79CUSTOM_OLED_DRIVER ?= yes 79CUSTOM_OLED_DRIVER ?= yes
80ifeq ($(strip $(OLED_ENABLE)), yes) 80ifeq ($(strip $(OLED_ENABLE)), yes)
81 ifeq ($(strip $(OLED_DRIVER)), custom)
82 OPT_DEFS += -DOLED_ENABLE \
83 -DOLED_DRIVER_SH1107
84 SRC += $(USER_PATH)/oled/sh110x.c
85 QUANTUM_LIB_SRC += i2c_master.c
86 endif
81 ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes) 87 ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes)
82 SRC += $(USER_PATH)/oled/oled_stuff.c
83 OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE 88 OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE
89 SRC += $(USER_PATH)/oled/oled_stuff.c
84 endif 90 endif
91 ifeq ($(strip $(OLED_DISPLAY_TEST)), yes)
92 OPT_DEFS += -DOLED_DISPLAY_TEST
93 endif
94 DEFERRED_EXEC_ENABLE = yes
85endif 95endif
86 96
87CUSTOM_POINTING_DEVICE ?= yes 97CUSTOM_POINTING_DEVICE ?= yes
@@ -97,6 +107,7 @@ ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes)
97 QUANTUM_LIB_SRC += $(USER_PATH)/split/transport_sync.c 107 QUANTUM_LIB_SRC += $(USER_PATH)/split/transport_sync.c
98 OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC 108 OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC
99 endif 109 endif
110
100endif 111endif
101 112
102AUTOCORRECTION_ENABLE ?= no 113AUTOCORRECTION_ENABLE ?= no
diff --git a/users/drashna/split/transport_sync.c b/users/drashna/split/transport_sync.c
index 794664293..2509e448c 100644
--- a/users/drashna/split/transport_sync.c
+++ b/users/drashna/split/transport_sync.c
@@ -9,7 +9,7 @@
9#endif 9#endif
10 10
11#ifdef CUSTOM_UNICODE_ENABLE 11#ifdef CUSTOM_UNICODE_ENABLE
12#include "process_unicode_common.h" 12# include "process_unicode_common.h"
13extern unicode_config_t unicode_config; 13extern unicode_config_t unicode_config;
14#endif 14#endif
15#ifdef AUDIO_ENABLE 15#ifdef AUDIO_ENABLE
@@ -24,8 +24,10 @@ extern bool tap_toggling;
24extern bool swap_hands; 24extern bool swap_hands;
25#endif 25#endif
26 26
27static bool watchdog_ping_done = false; 27#if defined(SPLIT_WATCHDOG_TIMEOUT)
28static uint32_t watchdog_timer = 0; 28static bool watchdog_ping_done = false;
29static uint32_t watchdog_timer = 0;
30#endif
29 31
30extern userspace_config_t userspace_config; 32extern userspace_config_t userspace_config;
31extern bool host_driver_disabled; 33extern bool host_driver_disabled;
@@ -51,20 +53,35 @@ void user_config_sync(uint8_t initiator2target_buffer_size, const void* initiato
51 } 53 }
52} 54}
53 55
56#if defined(SPLIT_WATCHDOG_TIMEOUT)
54void watchdog_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { watchdog_ping_done = true; } 57void watchdog_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { watchdog_ping_done = true; }
58#endif
55 59
60#ifdef OLED_ENABLE
61#include "oled/oled_stuff.h"
62void keylogger_string_sync(uint8_t initiator2target_buffer_size, const void* initiator2target_buffer, uint8_t target2initiator_buffer_size, void* target2initiator_buffer) {
63 if (initiator2target_buffer_size == OLED_KEYLOGGER_LENGTH) {
64 memcpy(&keylog_str, initiator2target_buffer, initiator2target_buffer_size);
65 }
66}
67#endif
56 68
57void keyboard_post_init_transport_sync(void) { 69void keyboard_post_init_transport_sync(void) {
58 // Register keyboard state sync split transaction 70 // Register keyboard state sync split transaction
59 transaction_register_rpc(RPC_ID_USER_STATE_SYNC, user_state_sync); 71 transaction_register_rpc(RPC_ID_USER_STATE_SYNC, user_state_sync);
60 transaction_register_rpc(RPC_ID_USER_KEYMAP_SYNC, user_keymap_sync); 72 transaction_register_rpc(RPC_ID_USER_KEYMAP_SYNC, user_keymap_sync);
61 transaction_register_rpc(RPC_ID_USER_CONFIG_SYNC, user_config_sync); 73 transaction_register_rpc(RPC_ID_USER_CONFIG_SYNC, user_config_sync);
74#ifdef OLED_ENABLE
75 transaction_register_rpc(RPC_ID_USER_KEYLOG_STR, keylogger_string_sync);
76#endif
62 77
63#ifdef __AVR__ 78#if defined(SPLIT_WATCHDOG_TIMEOUT)
79# if defined(PROTOCOL_LUFA)
64 wdt_disable(); 80 wdt_disable();
65#endif 81# endif
66 transaction_register_rpc(RPC_ID_USER_WATCHDOG_SYNC, watchdog_handler); 82 transaction_register_rpc(RPC_ID_USER_WATCHDOG_SYNC, watchdog_handler);
67 watchdog_timer = timer_read32(); 83 watchdog_timer = timer_read32();
84#endif
68} 85}
69 86
70void user_transport_update(void) { 87void user_transport_update(void) {
@@ -107,9 +124,12 @@ void user_transport_update(void) {
107void user_transport_sync(void) { 124void user_transport_sync(void) {
108 if (is_keyboard_master()) { 125 if (is_keyboard_master()) {
109 // Keep track of the last state, so that we can tell if we need to propagate to slave 126 // Keep track of the last state, so that we can tell if we need to propagate to slave
110 static uint16_t last_keymap = 0; 127 static uint16_t last_keymap = 0;
111 static uint32_t last_config = 0, last_sync[3], last_user_state = 0; 128 static uint32_t last_config = 0, last_sync[4], last_user_state = 0;
112 bool needs_sync = false; 129 bool needs_sync = false;
130#ifdef OLED_ENABLE
131 static char keylog_temp[OLED_KEYLOGGER_LENGTH] = { 0 };
132#endif
113 133
114 // Check if the state values are different 134 // Check if the state values are different
115 if (memcmp(&transport_user_state, &last_user_state, sizeof(transport_user_state))) { 135 if (memcmp(&transport_user_state, &last_user_state, sizeof(transport_user_state))) {
@@ -164,9 +184,30 @@ void user_transport_sync(void) {
164 if (transaction_rpc_send(RPC_ID_USER_CONFIG_SYNC, sizeof(transport_userspace_config), &transport_userspace_config)) { 184 if (transaction_rpc_send(RPC_ID_USER_CONFIG_SYNC, sizeof(transport_userspace_config), &transport_userspace_config)) {
165 last_sync[2] = timer_read32(); 185 last_sync[2] = timer_read32();
166 } 186 }
187 needs_sync = false;
188 }
189
190#ifdef OLED_ENABLE
191 // Check if the state values are different
192 if (memcmp(&keylog_str, &keylog_temp, OLED_KEYLOGGER_LENGTH)) {
193 needs_sync = true;
194 memcpy(&keylog_temp, &keylog_str, OLED_KEYLOGGER_LENGTH);
195 }
196 if (timer_elapsed32(last_sync[3]) > 250) {
197 needs_sync = true;
198 }
199
200 // Perform the sync if requested
201 if (needs_sync) {
202 if (transaction_rpc_send(RPC_ID_USER_KEYLOG_STR, OLED_KEYLOGGER_LENGTH, &keylog_str)) {
203 last_sync[3] = timer_read32();
204 }
205 needs_sync = false;
167 } 206 }
207#endif
168 } 208 }
169 209
210#if defined(SPLIT_WATCHDOG_TIMEOUT)
170 if (!watchdog_ping_done) { 211 if (!watchdog_ping_done) {
171 if (is_keyboard_master()) { 212 if (is_keyboard_master()) {
172 if (timer_elapsed32(watchdog_timer) > 100) { 213 if (timer_elapsed32(watchdog_timer) > 100) {
@@ -180,16 +221,14 @@ void user_transport_sync(void) {
180 } 221 }
181 } else { 222 } else {
182 if (timer_elapsed32(watchdog_timer) > 3500) { 223 if (timer_elapsed32(watchdog_timer) > 3500) {
183#ifdef __AVR__ 224 software_reset();
184 wdt_enable(WDTO_250MS);
185#else
186 NVIC_SystemReset();
187#endif
188 while (1) { 225 while (1) {
189 } 226 }
190 } 227 }
191 } 228 }
192 } 229 }
230#endif
231
193} 232}
194 233
195void housekeeping_task_user(void) { 234void housekeeping_task_user(void) {
diff --git a/users/drashna/split/transport_sync.h b/users/drashna/split/transport_sync.h
index 6b6f0c388..884586dfd 100644
--- a/users/drashna/split/transport_sync.h
+++ b/users/drashna/split/transport_sync.h
@@ -4,6 +4,10 @@
4#pragma once 4#pragma once
5 5
6#include "drashna.h" 6#include "drashna.h"
7#ifdef OLED_ENABLE
8# include "oled/oled_stuff.h"
9extern char keylog_str[OLED_KEYLOGGER_LENGTH];
10#endif
7 11
8typedef union { 12typedef union {
9 uint32_t raw; 13 uint32_t raw;