aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/backlight/backlight.c24
-rw-r--r--quantum/backlight/backlight.h4
-rw-r--r--quantum/bootmagic/bootmagic.h24
-rw-r--r--quantum/bootmagic/bootmagic_full.c147
-rw-r--r--quantum/bootmagic/bootmagic_full.h115
-rw-r--r--quantum/bootmagic/bootmagic_lite.c66
-rw-r--r--quantum/bootmagic/bootmagic_lite.h25
-rw-r--r--quantum/bootmagic/magic.c54
-rw-r--r--quantum/bootmagic/magic.h18
-rw-r--r--quantum/config_common.h3
-rw-r--r--quantum/encoder.c10
-rw-r--r--quantum/encoder.h4
-rw-r--r--quantum/keycode_config.h1
-rw-r--r--quantum/led_matrix.c615
-rw-r--r--quantum/led_matrix.h144
-rw-r--r--quantum/led_matrix_animations/alpha_mods_anim.h24
-rw-r--r--quantum/led_matrix_animations/band_anim.h13
-rw-r--r--quantum/led_matrix_animations/band_pinwheel_anim.h10
-rw-r--r--quantum/led_matrix_animations/band_spiral_anim.h10
-rw-r--r--quantum/led_matrix_animations/breathing_anim.h19
-rw-r--r--quantum/led_matrix_animations/cycle_left_right_anim.h10
-rw-r--r--quantum/led_matrix_animations/cycle_out_in_anim.h10
-rw-r--r--quantum/led_matrix_animations/cycle_up_down_anim.h10
-rw-r--r--quantum/led_matrix_animations/dual_beacon_anim.h10
-rw-r--r--quantum/led_matrix_animations/led_matrix_effects.inc18
-rw-r--r--quantum/led_matrix_animations/solid_anim.h15
-rw-r--r--quantum/led_matrix_animations/solid_reactive_cross.h35
-rw-r--r--quantum/led_matrix_animations/solid_reactive_nexus.h32
-rw-r--r--quantum/led_matrix_animations/solid_reactive_simple_anim.h12
-rw-r--r--quantum/led_matrix_animations/solid_reactive_wide.h30
-rw-r--r--quantum/led_matrix_animations/solid_splash_anim.h30
-rw-r--r--quantum/led_matrix_animations/wave_left_right_anim.h10
-rw-r--r--quantum/led_matrix_animations/wave_up_down_anim.h10
-rw-r--r--quantum/led_matrix_drivers.c27
-rw-r--r--quantum/led_matrix_runners/effect_runner_dx_dy.h16
-rw-r--r--quantum/led_matrix_runners/effect_runner_dx_dy_dist.h17
-rw-r--r--quantum/led_matrix_runners/effect_runner_i.h14
-rw-r--r--quantum/led_matrix_runners/effect_runner_reactive.h28
-rw-r--r--quantum/led_matrix_runners/effect_runner_reactive_splash.h26
-rw-r--r--quantum/led_matrix_runners/effect_runner_sin_cos_i.h16
-rw-r--r--quantum/led_matrix_types.h46
-rw-r--r--quantum/matrix.c8
-rw-r--r--quantum/matrix.h5
-rw-r--r--quantum/mcu_selection.mk130
-rw-r--r--quantum/process_keycode/process_auto_shift.c20
-rw-r--r--quantum/process_keycode/process_auto_shift.h1
-rw-r--r--quantum/process_keycode/process_backlight.c29
-rw-r--r--quantum/process_keycode/process_leader.c5
-rw-r--r--quantum/process_keycode/process_leader.h7
-rw-r--r--quantum/process_keycode/process_rgb.c5
-rw-r--r--quantum/quantum.c28
-rw-r--r--quantum/quantum.h55
-rw-r--r--quantum/quantum_keycodes.h925
-rw-r--r--quantum/rgb_matrix.c61
-rw-r--r--quantum/rgb_matrix.h1
-rw-r--r--quantum/rgb_matrix_drivers.c39
-rw-r--r--quantum/rgb_matrix_types.h17
-rw-r--r--quantum/rgblight.c44
-rw-r--r--quantum/rgblight.h1
-rw-r--r--quantum/split_common/matrix.c11
-rw-r--r--quantum/split_common/split_util.c70
-rw-r--r--quantum/split_common/transport.c92
-rw-r--r--quantum/wpm.c38
-rw-r--r--quantum/wpm.h11
64 files changed, 2424 insertions, 931 deletions
diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c
index 113beb832..dfb98419e 100644
--- a/quantum/backlight/backlight.c
+++ b/quantum/backlight/backlight.c
@@ -17,11 +17,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18#include "quantum.h" 18#include "quantum.h"
19#include "backlight.h" 19#include "backlight.h"
20#include "eeprom.h"
20#include "eeconfig.h" 21#include "eeconfig.h"
21#include "debug.h" 22#include "debug.h"
22 23
23backlight_config_t backlight_config; 24backlight_config_t backlight_config;
24 25
26#ifndef BACKLIGHT_DEFAULT_LEVEL
27# define BACKLIGHT_DEFAULT_LEVEL BACKLIGHT_LEVELS
28#endif
29
25#ifdef BACKLIGHT_BREATHING 30#ifdef BACKLIGHT_BREATHING
26// TODO: migrate to backlight_config_t 31// TODO: migrate to backlight_config_t
27static uint8_t breathing_period = BREATHING_PERIOD; 32static uint8_t breathing_period = BREATHING_PERIOD;
@@ -35,6 +40,7 @@ void backlight_init(void) {
35 /* check signature */ 40 /* check signature */
36 if (!eeconfig_is_enabled()) { 41 if (!eeconfig_is_enabled()) {
37 eeconfig_init(); 42 eeconfig_init();
43 eeconfig_update_backlight_default();
38 } 44 }
39 backlight_config.raw = eeconfig_read_backlight(); 45 backlight_config.raw = eeconfig_read_backlight();
40 if (backlight_config.level > BACKLIGHT_LEVELS) { 46 if (backlight_config.level > BACKLIGHT_LEVELS) {
@@ -152,11 +158,23 @@ void backlight_level(uint8_t level) {
152 eeconfig_update_backlight(backlight_config.raw); 158 eeconfig_update_backlight(backlight_config.raw);
153} 159}
154 160
155/** \brief Update current backlight state to EEPROM 161uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
156 * 162
157 */ 163void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); }
164
158void eeconfig_update_backlight_current(void) { eeconfig_update_backlight(backlight_config.raw); } 165void eeconfig_update_backlight_current(void) { eeconfig_update_backlight(backlight_config.raw); }
159 166
167void eeconfig_update_backlight_default(void) {
168 backlight_config.enable = 1;
169#ifdef BACKLIGHT_DEFAULT_BREATHING
170 backlight_config.breathing = 1;
171#else
172 backlight_config.breathing = 0;
173#endif
174 backlight_config.level = BACKLIGHT_DEFAULT_LEVEL;
175 eeconfig_update_backlight(backlight_config.raw);
176}
177
160/** \brief Get backlight level 178/** \brief Get backlight level
161 * 179 *
162 * FIXME: needs doc 180 * FIXME: needs doc
diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h
index 3e506737d..c30c70fd6 100644
--- a/quantum/backlight/backlight.h
+++ b/quantum/backlight/backlight.h
@@ -55,7 +55,11 @@ void backlight_decrease(void);
55void backlight_level_noeeprom(uint8_t level); 55void backlight_level_noeeprom(uint8_t level);
56void backlight_level(uint8_t level); 56void backlight_level(uint8_t level);
57uint8_t get_backlight_level(void); 57uint8_t get_backlight_level(void);
58
59uint8_t eeconfig_read_backlight(void);
60void eeconfig_update_backlight(uint8_t val);
58void eeconfig_update_backlight_current(void); 61void eeconfig_update_backlight_current(void);
62void eeconfig_update_backlight_default(void);
59 63
60// implementation specific 64// implementation specific
61void backlight_init_ports(void); 65void backlight_init_ports(void);
diff --git a/quantum/bootmagic/bootmagic.h b/quantum/bootmagic/bootmagic.h
new file mode 100644
index 000000000..959750178
--- /dev/null
+++ b/quantum/bootmagic/bootmagic.h
@@ -0,0 +1,24 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#pragma once
17
18#if defined(BOOTMAGIC_ENABLE)
19# include "bootmagic_full.h"
20#elif defined(BOOTMAGIC_LITE)
21# include "bootmagic_lite.h"
22#endif
23
24void bootmagic(void);
diff --git a/quantum/bootmagic/bootmagic_full.c b/quantum/bootmagic/bootmagic_full.c
new file mode 100644
index 000000000..a7a0dcfcb
--- /dev/null
+++ b/quantum/bootmagic/bootmagic_full.c
@@ -0,0 +1,147 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include <stdint.h>
17#include <stdbool.h>
18#include "wait.h"
19#include "matrix.h"
20#include "bootloader.h"
21#include "debug.h"
22#include "keymap.h"
23#include "host.h"
24#include "action_layer.h"
25#include "eeconfig.h"
26#include "bootmagic.h"
27
28/** \brief Scan Keycode
29 *
30 * FIXME: needs doc
31 */
32static bool scan_keycode(uint8_t keycode) {
33 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
34 matrix_row_t matrix_row = matrix_get_row(r);
35 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
36 if (matrix_row & ((matrix_row_t)1 << c)) {
37 if (keycode == keymap_key_to_keycode(0, (keypos_t){.row = r, .col = c})) {
38 return true;
39 }
40 }
41 }
42 }
43 return false;
44}
45
46/** \brief Bootmagic Scan Keycode
47 *
48 * FIXME: needs doc
49 */
50static bool bootmagic_scan_keycode(uint8_t keycode) {
51 if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false;
52
53 return scan_keycode(keycode);
54}
55
56void bootmagic(void) {
57 /* do scans in case of bounce */
58 print("bootmagic scan: ... ");
59 uint8_t scan = 100;
60 while (scan--) {
61 matrix_scan();
62 wait_ms(10);
63 }
64 print("done.\n");
65
66 /* bootmagic skip */
67 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) {
68 return;
69 }
70
71 /* eeconfig clear */
72 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) {
73 eeconfig_init();
74 }
75
76 /* bootloader */
77 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) {
78 bootloader_jump();
79 }
80
81 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) {
82 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) {
83 debug_config.matrix = !debug_config.matrix;
84 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) {
85 debug_config.keyboard = !debug_config.keyboard;
86 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) {
87 debug_config.mouse = !debug_config.mouse;
88 } else {
89 debug_config.enable = !debug_config.enable;
90 }
91 }
92 eeconfig_update_debug(debug_config.raw);
93
94 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) {
95 keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
96 }
97 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) {
98 keymap_config.capslock_to_control = !keymap_config.capslock_to_control;
99 }
100 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) {
101 keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
102 }
103 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) {
104 keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
105 }
106 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) {
107 keymap_config.no_gui = !keymap_config.no_gui;
108 }
109 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) {
110 keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc;
111 }
112 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) {
113 keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace;
114 }
115 if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) {
116 keymap_config.nkro = !keymap_config.nkro;
117 }
118 eeconfig_update_keymap(keymap_config.raw);
119
120 /* default layer */
121 uint8_t default_layer = 0;
122 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) {
123 default_layer |= (1 << 0);
124 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) {
125 default_layer |= (1 << 1);
126 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) {
127 default_layer |= (1 << 2);
128 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) {
129 default_layer |= (1 << 3);
130 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) {
131 default_layer |= (1 << 4);
132 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) {
133 default_layer |= (1 << 5);
134 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) {
135 default_layer |= (1 << 6);
136 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) {
137 default_layer |= (1 << 7);
138 }
139 eeconfig_update_default_layer(default_layer);
140
141 /* EE_HANDS handedness */
142 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_LEFT)) {
143 eeconfig_update_handedness(true);
144 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_RIGHT)) {
145 eeconfig_update_handedness(false);
146 }
147}
diff --git a/quantum/bootmagic/bootmagic_full.h b/quantum/bootmagic/bootmagic_full.h
new file mode 100644
index 000000000..28f914c1b
--- /dev/null
+++ b/quantum/bootmagic/bootmagic_full.h
@@ -0,0 +1,115 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19/* FIXME: Add special doxygen comments for defines here. */
20
21/* bootmagic salt key */
22#ifndef BOOTMAGIC_KEY_SALT
23# define BOOTMAGIC_KEY_SALT KC_SPACE
24#endif
25
26/* skip bootmagic and eeconfig */
27#ifndef BOOTMAGIC_KEY_SKIP
28# define BOOTMAGIC_KEY_SKIP KC_ESC
29#endif
30
31/* eeprom clear */
32#ifndef BOOTMAGIC_KEY_EEPROM_CLEAR
33# define BOOTMAGIC_KEY_EEPROM_CLEAR KC_BSPACE
34#endif
35
36/* kick up bootloader */
37#ifndef BOOTMAGIC_KEY_BOOTLOADER
38# define BOOTMAGIC_KEY_BOOTLOADER KC_B
39#endif
40
41/* debug enable */
42#ifndef BOOTMAGIC_KEY_DEBUG_ENABLE
43# define BOOTMAGIC_KEY_DEBUG_ENABLE KC_D
44#endif
45#ifndef BOOTMAGIC_KEY_DEBUG_MATRIX
46# define BOOTMAGIC_KEY_DEBUG_MATRIX KC_X
47#endif
48#ifndef BOOTMAGIC_KEY_DEBUG_KEYBOARD
49# define BOOTMAGIC_KEY_DEBUG_KEYBOARD KC_K
50#endif
51#ifndef BOOTMAGIC_KEY_DEBUG_MOUSE
52# define BOOTMAGIC_KEY_DEBUG_MOUSE KC_M
53#endif
54#ifndef BOOTMAGIC_KEY_EE_HANDS_LEFT
55# define BOOTMAGIC_KEY_EE_HANDS_LEFT KC_L
56#endif
57#ifndef BOOTMAGIC_KEY_EE_HANDS_RIGHT
58# define BOOTMAGIC_KEY_EE_HANDS_RIGHT KC_R
59#endif
60
61/*
62 * keymap config
63 */
64#ifndef BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK
65# define BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK KC_LCTRL
66#endif
67#ifndef BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL
68# define BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL KC_CAPSLOCK
69#endif
70#ifndef BOOTMAGIC_KEY_SWAP_LALT_LGUI
71# define BOOTMAGIC_KEY_SWAP_LALT_LGUI KC_LALT
72#endif
73#ifndef BOOTMAGIC_KEY_SWAP_RALT_RGUI
74# define BOOTMAGIC_KEY_SWAP_RALT_RGUI KC_RALT
75#endif
76#ifndef BOOTMAGIC_KEY_NO_GUI
77# define BOOTMAGIC_KEY_NO_GUI KC_LGUI
78#endif
79#ifndef BOOTMAGIC_KEY_SWAP_GRAVE_ESC
80# define BOOTMAGIC_KEY_SWAP_GRAVE_ESC KC_GRAVE
81#endif
82#ifndef BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE
83# define BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE KC_BSLASH
84#endif
85#ifndef BOOTMAGIC_HOST_NKRO
86# define BOOTMAGIC_HOST_NKRO KC_N
87#endif
88
89/*
90 * change default layer
91 */
92#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_0
93# define BOOTMAGIC_KEY_DEFAULT_LAYER_0 KC_0
94#endif
95#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_1
96# define BOOTMAGIC_KEY_DEFAULT_LAYER_1 KC_1
97#endif
98#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_2
99# define BOOTMAGIC_KEY_DEFAULT_LAYER_2 KC_2
100#endif
101#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_3
102# define BOOTMAGIC_KEY_DEFAULT_LAYER_3 KC_3
103#endif
104#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_4
105# define BOOTMAGIC_KEY_DEFAULT_LAYER_4 KC_4
106#endif
107#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_5
108# define BOOTMAGIC_KEY_DEFAULT_LAYER_5 KC_5
109#endif
110#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_6
111# define BOOTMAGIC_KEY_DEFAULT_LAYER_6 KC_6
112#endif
113#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7
114# define BOOTMAGIC_KEY_DEFAULT_LAYER_7 KC_7
115#endif \ No newline at end of file
diff --git a/quantum/bootmagic/bootmagic_lite.c b/quantum/bootmagic/bootmagic_lite.c
new file mode 100644
index 000000000..9cbdcb0bb
--- /dev/null
+++ b/quantum/bootmagic/bootmagic_lite.c
@@ -0,0 +1,66 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include "quantum.h"
17
18/** \brief Reset eeprom
19 *
20 * ...just incase someone wants to only change the eeprom behaviour
21 */
22__attribute__((weak)) void bootmagic_lite_reset_eeprom(void) {
23#if defined(VIA_ENABLE)
24 via_eeprom_reset();
25#else
26 eeconfig_disable();
27#endif
28}
29
30/** \brief The lite version of TMK's bootmagic based on Wilba.
31 *
32 * 100% less potential for accidentally making the keyboard do stupid things.
33 */
34__attribute__((weak)) void bootmagic_lite(void) {
35 // We need multiple scans because debouncing can't be turned off.
36 matrix_scan();
37#if defined(DEBOUNCE) && DEBOUNCE > 0
38 wait_ms(DEBOUNCE * 2);
39#else
40 wait_ms(30);
41#endif
42 matrix_scan();
43
44 // If the configured key (commonly Esc) is held down on power up,
45 // reset the EEPROM valid state and jump to bootloader.
46 // This isn't very generalized, but we need something that doesn't
47 // rely on user's keymaps in firmware or EEPROM.
48 uint8_t row = BOOTMAGIC_LITE_ROW;
49 uint8_t col = BOOTMAGIC_LITE_COLUMN;
50
51#if defined(SPLIT_KEYBOARD) && defined(BOOTMAGIC_LITE_ROW_RIGHT) && defined(BOOTMAGIC_LITE_COLUMN_RIGHT)
52 if (!is_keyboard_left()) {
53 row = BOOTMAGIC_LITE_ROW_RIGHT;
54 col = BOOTMAGIC_LITE_COLUMN_RIGHT;
55 }
56#endif
57
58 if (matrix_get_row(row) & (1 << col)) {
59 bootmagic_lite_reset_eeprom();
60
61 // Jump to bootloader.
62 bootloader_jump();
63 }
64}
65
66void bootmagic(void) { bootmagic_lite(); }
diff --git a/quantum/bootmagic/bootmagic_lite.h b/quantum/bootmagic/bootmagic_lite.h
new file mode 100644
index 000000000..17777e6b4
--- /dev/null
+++ b/quantum/bootmagic/bootmagic_lite.h
@@ -0,0 +1,25 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#pragma once
17
18#ifndef BOOTMAGIC_LITE_COLUMN
19# define BOOTMAGIC_LITE_COLUMN 0
20#endif
21#ifndef BOOTMAGIC_LITE_ROW
22# define BOOTMAGIC_LITE_ROW 0
23#endif
24
25void bootmagic_lite(void);
diff --git a/quantum/bootmagic/magic.c b/quantum/bootmagic/magic.c
new file mode 100644
index 000000000..f1cb11c39
--- /dev/null
+++ b/quantum/bootmagic/magic.c
@@ -0,0 +1,54 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include <stdint.h>
17#include <stdbool.h>
18#include "wait.h"
19#include "matrix.h"
20#include "bootloader.h"
21#include "debug.h"
22#include "keymap.h"
23#include "host.h"
24#include "action_layer.h"
25#include "eeconfig.h"
26#include "bootmagic.h"
27
28keymap_config_t keymap_config;
29
30__attribute__((weak)) void bootmagic(void) {}
31
32/** \brief Magic
33 *
34 * FIXME: Needs doc
35 */
36void magic(void) {
37 /* check signature */
38 if (!eeconfig_is_enabled()) {
39 eeconfig_init();
40 }
41
42 /* init globals */
43 debug_config.raw = eeconfig_read_debug();
44 keymap_config.raw = eeconfig_read_keymap();
45
46 bootmagic();
47
48 /* read here just incase bootmagic process changed its value */
49 layer_state_t default_layer = (layer_state_t)eeconfig_read_default_layer();
50 default_layer_set(default_layer);
51
52 /* Also initialize layer state to trigger callback functions for layer_state */
53 layer_state_set_kb((layer_state_t)layer_state);
54}
diff --git a/quantum/bootmagic/magic.h b/quantum/bootmagic/magic.h
new file mode 100644
index 000000000..2c3969b85
--- /dev/null
+++ b/quantum/bootmagic/magic.h
@@ -0,0 +1,18 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#pragma once
17
18void magic(void);
diff --git a/quantum/config_common.h b/quantum/config_common.h
index d93477b27..661609ef2 100644
--- a/quantum/config_common.h
+++ b/quantum/config_common.h
@@ -24,4 +24,7 @@
24#define COL2ROW 0 24#define COL2ROW 0
25#define ROW2COL 1 25#define ROW2COL 1
26 26
27// Deprecated alias - avoid using
28#define KEYMAP LAYOUT
29
27#include "song_list.h" 30#include "song_list.h"
diff --git a/quantum/encoder.c b/quantum/encoder.c
index 2ed64c1e3..c30bf01cb 100644
--- a/quantum/encoder.c
+++ b/quantum/encoder.c
@@ -59,9 +59,9 @@ static uint8_t thisHand, thatHand;
59static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0}; 59static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
60#endif 60#endif
61 61
62__attribute__((weak)) void encoder_update_user(int8_t index, bool clockwise) {} 62__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; }
63 63
64__attribute__((weak)) void encoder_update_kb(int8_t index, bool clockwise) { encoder_update_user(index, clockwise); } 64__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); }
65 65
66void encoder_init(void) { 66void encoder_init(void) {
67#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) 67#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT)
@@ -94,14 +94,14 @@ void encoder_init(void) {
94#endif 94#endif
95} 95}
96 96
97static bool encoder_update(int8_t index, uint8_t state) { 97static bool encoder_update(uint8_t index, uint8_t state) {
98 bool changed = false; 98 bool changed = false;
99 uint8_t i = index; 99 uint8_t i = index;
100 100
101#ifdef ENCODER_RESOLUTIONS 101#ifdef ENCODER_RESOLUTIONS
102 int8_t resolution = encoder_resolutions[i]; 102 uint8_t resolution = encoder_resolutions[i];
103#else 103#else
104 int8_t resolution = ENCODER_RESOLUTION; 104 uint8_t resolution = ENCODER_RESOLUTION;
105#endif 105#endif
106 106
107#ifdef SPLIT_KEYBOARD 107#ifdef SPLIT_KEYBOARD
diff --git a/quantum/encoder.h b/quantum/encoder.h
index db6f220da..25dc77721 100644
--- a/quantum/encoder.h
+++ b/quantum/encoder.h
@@ -22,8 +22,8 @@
22void encoder_init(void); 22void encoder_init(void);
23bool encoder_read(void); 23bool encoder_read(void);
24 24
25void encoder_update_kb(int8_t index, bool clockwise); 25bool encoder_update_kb(uint8_t index, bool clockwise);
26void encoder_update_user(int8_t index, bool clockwise); 26bool encoder_update_user(uint8_t index, bool clockwise);
27 27
28#ifdef SPLIT_KEYBOARD 28#ifdef SPLIT_KEYBOARD
29void encoder_state_raw(uint8_t* slave_state); 29void encoder_state_raw(uint8_t* slave_state);
diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h
index f878168c5..d7e334fdc 100644
--- a/quantum/keycode_config.h
+++ b/quantum/keycode_config.h
@@ -37,6 +37,7 @@ typedef union {
37 bool nkro : 1; 37 bool nkro : 1;
38 bool swap_lctl_lgui : 1; 38 bool swap_lctl_lgui : 1;
39 bool swap_rctl_rgui : 1; 39 bool swap_rctl_rgui : 1;
40 bool oneshot_disable : 1;
40 }; 41 };
41} keymap_config_t; 42} keymap_config_t;
42 43
diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c
index 4f1f06c7a..d612fbfa9 100644
--- a/quantum/led_matrix.c
+++ b/quantum/led_matrix.c
@@ -17,79 +17,143 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20#include <stdint.h>
21#include <stdbool.h>
22#include "quantum.h"
23#include "led_matrix.h" 20#include "led_matrix.h"
24#include "progmem.h" 21#include "progmem.h"
25#include "config.h" 22#include "config.h"
26#include "eeprom.h" 23#include "eeprom.h"
27#include <string.h> 24#include <string.h>
28#include <math.h> 25#include <math.h>
26#include "led_tables.h"
29 27
30led_eeconfig_t led_matrix_eeconfig; 28#include <lib/lib8tion/lib8tion.h>
31 29
32#ifndef MAX 30#ifndef LED_MATRIX_CENTER
33# define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) 31const led_point_t k_led_matrix_center = {112, 32};
32#else
33const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
34#endif 34#endif
35 35
36#ifndef MIN 36// Generic effect runners
37# define MIN(a, b) ((a) < (b) ? (a) : (b)) 37#include "led_matrix_runners/effect_runner_dx_dy_dist.h"
38#include "led_matrix_runners/effect_runner_dx_dy.h"
39#include "led_matrix_runners/effect_runner_i.h"
40#include "led_matrix_runners/effect_runner_sin_cos_i.h"
41#include "led_matrix_runners/effect_runner_reactive.h"
42#include "led_matrix_runners/effect_runner_reactive_splash.h"
43
44// ------------------------------------------
45// -----Begin led effect includes macros-----
46#define LED_MATRIX_EFFECT(name)
47#define LED_MATRIX_CUSTOM_EFFECT_IMPLS
48
49#include "led_matrix_animations/led_matrix_effects.inc"
50#ifdef LED_MATRIX_CUSTOM_KB
51# include "led_matrix_kb.inc"
38#endif 52#endif
53#ifdef LED_MATRIX_CUSTOM_USER
54# include "led_matrix_user.inc"
55#endif
56
57#undef LED_MATRIX_CUSTOM_EFFECT_IMPLS
58#undef LED_MATRIX_EFFECT
59// -----End led effect includes macros-------
60// ------------------------------------------
39 61
40#ifndef LED_DISABLE_AFTER_TIMEOUT 62#if defined(LED_DISABLE_AFTER_TIMEOUT) && !defined(LED_DISABLE_TIMEOUT)
41# define LED_DISABLE_AFTER_TIMEOUT 0 63# define LED_DISABLE_TIMEOUT (LED_DISABLE_AFTER_TIMEOUT * 1200UL)
42#endif 64#endif
43 65
44#ifndef LED_DISABLE_WHEN_USB_SUSPENDED 66#ifndef LED_DISABLE_TIMEOUT
45# define LED_DISABLE_WHEN_USB_SUSPENDED false 67# define LED_DISABLE_TIMEOUT 0
46#endif 68#endif
47 69
48#ifndef EECONFIG_LED_MATRIX 70#if LED_DISABLE_WHEN_USB_SUSPENDED == false
49# define EECONFIG_LED_MATRIX EECONFIG_RGBLIGHT 71# undef LED_DISABLE_WHEN_USB_SUSPENDED
50#endif 72#endif
51 73
52#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > 255 74#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
53# define LED_MATRIX_MAXIMUM_BRIGHTNESS 255 75# undef LED_MATRIX_MAXIMUM_BRIGHTNESS
76# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
54#endif 77#endif
55 78
56bool g_suspend_state = false; 79#if !defined(LED_MATRIX_VAL_STEP)
80# define LED_MATRIX_VAL_STEP 8
81#endif
57 82
58// Global tick at 20 Hz 83#if !defined(LED_MATRIX_SPD_STEP)
59uint32_t g_tick = 0; 84# define LED_MATRIX_SPD_STEP 16
85#endif
60 86
61// Ticks since this key was last hit. 87#if !defined(LED_MATRIX_STARTUP_MODE)
62uint8_t g_key_hit[DRIVER_LED_TOTAL]; 88# define LED_MATRIX_STARTUP_MODE LED_MATRIX_SOLID
89#endif
63 90
64// Ticks since any key was last hit. 91#if !defined(LED_MATRIX_STARTUP_VAL)
65uint32_t g_any_key_hit = 0; 92# define LED_MATRIX_STARTUP_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS
93#endif
66 94
67uint32_t eeconfig_read_led_matrix(void) { return eeprom_read_dword(EECONFIG_LED_MATRIX); } 95#if !defined(LED_MATRIX_STARTUP_SPD)
96# define LED_MATRIX_STARTUP_SPD UINT8_MAX / 2
97#endif
68 98
69void eeconfig_update_led_matrix(uint32_t config_value) { eeprom_update_dword(EECONFIG_LED_MATRIX, config_value); } 99// globals
100led_eeconfig_t led_matrix_eeconfig; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr
101uint32_t g_led_timer;
102#ifdef LED_MATRIX_FRAMEBUFFER_EFFECTS
103uint8_t g_led_frame_buffer[MATRIX_ROWS][MATRIX_COLS] = {{0}};
104#endif // LED_MATRIX_FRAMEBUFFER_EFFECTS
105#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
106last_hit_t g_last_hit_tracker;
107#endif // LED_MATRIX_KEYREACTIVE_ENABLED
108
109// internals
110static bool suspend_state = false;
111static uint8_t led_last_enable = UINT8_MAX;
112static uint8_t led_last_effect = UINT8_MAX;
113static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false};
114static led_task_states led_task_state = SYNCING;
115#if LED_DISABLE_TIMEOUT > 0
116static uint32_t led_anykey_timer;
117#endif // LED_DISABLE_TIMEOUT > 0
118
119// double buffers
120static uint32_t led_timer_buffer;
121#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
122static last_hit_t last_hit_buffer;
123#endif // LED_MATRIX_KEYREACTIVE_ENABLED
124
125// split led matrix
126#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
127const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT;
128#endif
129
130void eeconfig_read_led_matrix(void) { eeprom_read_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); }
131
132void eeconfig_update_led_matrix(void) { eeprom_update_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); }
70 133
71void eeconfig_update_led_matrix_default(void) { 134void eeconfig_update_led_matrix_default(void) {
72 dprintf("eeconfig_update_led_matrix_default\n"); 135 dprintf("eeconfig_update_led_matrix_default\n");
73 led_matrix_eeconfig.enable = 1; 136 led_matrix_eeconfig.enable = 1;
74 led_matrix_eeconfig.mode = LED_MATRIX_UNIFORM_BRIGHTNESS; 137 led_matrix_eeconfig.mode = LED_MATRIX_STARTUP_MODE;
75 led_matrix_eeconfig.val = 128; 138 led_matrix_eeconfig.val = LED_MATRIX_STARTUP_VAL;
76 led_matrix_eeconfig.speed = 0; 139 led_matrix_eeconfig.speed = LED_MATRIX_STARTUP_SPD;
77 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); 140 led_matrix_eeconfig.flags = LED_FLAG_ALL;
141 eeconfig_update_led_matrix();
78} 142}
79 143
80void eeconfig_debug_led_matrix(void) { 144void eeconfig_debug_led_matrix(void) {
81 dprintf("led_matrix_eeconfig eeprom\n"); 145 dprintf("led_matrix_eeconfig EEPROM\n");
82 dprintf("led_matrix_eeconfig.enable = %d\n", led_matrix_eeconfig.enable); 146 dprintf("led_matrix_eeconfig.enable = %d\n", led_matrix_eeconfig.enable);
83 dprintf("led_matrix_eeconfig.mode = %d\n", led_matrix_eeconfig.mode); 147 dprintf("led_matrix_eeconfig.mode = %d\n", led_matrix_eeconfig.mode);
84 dprintf("led_matrix_eeconfig.val = %d\n", led_matrix_eeconfig.val); 148 dprintf("led_matrix_eeconfig.val = %d\n", led_matrix_eeconfig.val);
85 dprintf("led_matrix_eeconfig.speed = %d\n", led_matrix_eeconfig.speed); 149 dprintf("led_matrix_eeconfig.speed = %d\n", led_matrix_eeconfig.speed);
150 dprintf("led_matrix_eeconfig.flags = %d\n", led_matrix_eeconfig.flags);
86} 151}
87 152
88uint8_t g_last_led_hit[LED_HITS_TO_REMEMBER] = {255}; 153__attribute__((weak)) uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; }
89uint8_t g_last_led_count = 0;
90 154
91uint8_t map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) { 155uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) {
92 uint8_t led_count = 0; 156 uint8_t led_count = led_matrix_map_row_column_to_led_kb(row, column, led_i);
93 uint8_t led_index = g_led_config.matrix_co[row][column]; 157 uint8_t led_index = g_led_config.matrix_co[row][column];
94 if (led_index != NO_LED) { 158 if (led_index != NO_LED) {
95 led_i[led_count] = led_index; 159 led_i[led_count] = led_index;
@@ -100,88 +164,235 @@ uint8_t map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) {
100 164
101void led_matrix_update_pwm_buffers(void) { led_matrix_driver.flush(); } 165void led_matrix_update_pwm_buffers(void) { led_matrix_driver.flush(); }
102 166
103void led_matrix_set_index_value(int index, uint8_t value) { led_matrix_driver.set_value(index, value); } 167void led_matrix_set_value(int index, uint8_t value) {
104 168#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
105void led_matrix_set_index_value_all(uint8_t value) { led_matrix_driver.set_value_all(value); } 169 if (!is_keyboard_left() && index >= k_led_matrix_split[0])
106 170# ifdef USE_CIE1931_CURVE
107bool process_led_matrix(uint16_t keycode, keyrecord_t *record) { 171 led_matrix_driver.set_value(index - k_led_matrix_split[0], pgm_read_byte(&CIE1931_CURVE[value]));
108 if (record->event.pressed) { 172# else
109 uint8_t led[8]; 173 led_matrix_driver.set_value(index - k_led_matrix_split[0], value);
110 uint8_t led_count = map_row_column_to_led(record->event.key.row, record->event.key.col, led); 174# endif
111 if (led_count > 0) { 175 else if (is_keyboard_left() && index < k_led_matrix_split[0])
112 for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) { 176#endif
113 g_last_led_hit[i - 1] = g_last_led_hit[i - 2]; 177#ifdef USE_CIE1931_CURVE
114 } 178 led_matrix_driver.set_value(index, pgm_read_byte(&CIE1931_CURVE[value]));
115 g_last_led_hit[0] = led[0]; 179#else
116 g_last_led_count = MIN(LED_HITS_TO_REMEMBER, g_last_led_count + 1); 180 led_matrix_driver.set_value(index, value);
117 } 181#endif
118 for (uint8_t i = 0; i < led_count; i++) g_key_hit[led[i]] = 0; 182}
119 g_any_key_hit = 0;
120 } else {
121#ifdef LED_MATRIX_KEYRELEASES
122 uint8_t led[8];
123 uint8_t led_count = map_row_column_to_led(record->event.key.row, record->event.key.col, led);
124 for (uint8_t i = 0; i < led_count; i++) g_key_hit[led[i]] = 255;
125 183
126 g_any_key_hit = 255; 184void led_matrix_set_value_all(uint8_t value) {
185#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
186 for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) led_matrix_set_value(i, value);
187#else
188# ifdef USE_CIE1931_CURVE
189 led_matrix_driver.set_value_all(pgm_read_byte(&CIE1931_CURVE[value]));
190# else
191 led_matrix_driver.set_value_all(value);
192# endif
127#endif 193#endif
128 }
129 return true;
130} 194}
131 195
132void led_matrix_set_suspend_state(bool state) { g_suspend_state = state; } 196void process_led_matrix(uint8_t row, uint8_t col, bool pressed) {
197#ifndef LED_MATRIX_SPLIT
198 if (!is_keyboard_master()) return;
199#endif
200#if LED_DISABLE_TIMEOUT > 0
201 led_anykey_timer = 0;
202#endif // LED_DISABLE_TIMEOUT > 0
133 203
134// All LEDs off 204#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
135void led_matrix_all_off(void) { led_matrix_set_index_value_all(0); } 205 uint8_t led[LED_HITS_TO_REMEMBER];
206 uint8_t led_count = 0;
136 207
137// Uniform brightness 208# if defined(LED_MATRIX_KEYRELEASES)
138void led_matrix_uniform_brightness(void) { led_matrix_set_index_value_all(LED_MATRIX_MAXIMUM_BRIGHTNESS / BACKLIGHT_LEVELS * led_matrix_eeconfig.val); } 209 if (!pressed)
210# elif defined(LED_MATRIX_KEYPRESSES)
211 if (pressed)
212# endif // defined(LED_MATRIX_KEYRELEASES)
213 {
214 led_count = led_matrix_map_row_column_to_led(row, col, led);
215 }
139 216
140void led_matrix_custom(void) {} 217 if (last_hit_buffer.count + led_count > LED_HITS_TO_REMEMBER) {
218 memcpy(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count);
219 memcpy(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count);
220 memcpy(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit
221 memcpy(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count);
222 last_hit_buffer.count--;
223 }
141 224
142void led_matrix_task(void) { 225 for (uint8_t i = 0; i < led_count; i++) {
143 if (!led_matrix_eeconfig.enable) { 226 uint8_t index = last_hit_buffer.count;
144 led_matrix_all_off(); 227 last_hit_buffer.x[index] = g_led_config.point[led[i]].x;
145 led_matrix_indicators(); 228 last_hit_buffer.y[index] = g_led_config.point[led[i]].y;
146 return; 229 last_hit_buffer.index[index] = led[i];
230 last_hit_buffer.tick[index] = 0;
231 last_hit_buffer.count++;
147 } 232 }
233#endif // LED_MATRIX_KEYREACTIVE_ENABLED
148 234
149 g_tick++; 235#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP)
236 if (led_matrix_eeconfig.mode == LED_MATRIX_TYPING_HEATMAP) {
237 process_led_matrix_typing_heatmap(row, col);
238 }
239#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP)
240}
150 241
151 if (g_any_key_hit < 0xFFFFFFFF) { 242static bool led_matrix_none(effect_params_t *params) {
152 g_any_key_hit++; 243 if (!params->init) {
244 return false;
153 } 245 }
154 246
155 for (int led = 0; led < DRIVER_LED_TOTAL; led++) { 247 led_matrix_set_value_all(0);
156 if (g_key_hit[led] < 255) { 248 return false;
157 if (g_key_hit[led] == 254) g_last_led_count = MAX(g_last_led_count - 1, 0); 249}
158 g_key_hit[led]++; 250
251static void led_task_timers(void) {
252#if defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0
253 uint32_t deltaTime = sync_timer_elapsed32(led_timer_buffer);
254#endif // defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0
255 led_timer_buffer = sync_timer_read32();
256
257 // Update double buffer timers
258#if LED_DISABLE_TIMEOUT > 0
259 if (led_anykey_timer < UINT32_MAX) {
260 if (UINT32_MAX - deltaTime < led_anykey_timer) {
261 led_anykey_timer = UINT32_MAX;
262 } else {
263 led_anykey_timer += deltaTime;
159 } 264 }
160 } 265 }
266#endif // LED_DISABLE_TIMEOUT > 0
267
268 // Update double buffer last hit timers
269#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
270 uint8_t count = last_hit_buffer.count;
271 for (uint8_t i = 0; i < count; ++i) {
272 if (UINT16_MAX - deltaTime < last_hit_buffer.tick[i]) {
273 last_hit_buffer.count--;
274 continue;
275 }
276 last_hit_buffer.tick[i] += deltaTime;
277 }
278#endif // LED_MATRIX_KEYREACTIVE_ENABLED
279}
161 280
162 // Ideally we would also stop sending zeros to the LED driver PWM buffers 281static void led_task_sync(void) {
163 // while suspended and just do a software shutdown. This is a cheap hack for now. 282 // next task
164 bool suspend_backlight = ((g_suspend_state && LED_DISABLE_WHEN_USB_SUSPENDED) || (LED_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > LED_DISABLE_AFTER_TIMEOUT * 60 * 20)); 283 if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING;
165 uint8_t effect = suspend_backlight ? 0 : led_matrix_eeconfig.mode; 284}
285
286static void led_task_start(void) {
287 // reset iter
288 led_effect_params.iter = 0;
289
290 // update double buffers
291 g_led_timer = led_timer_buffer;
292#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
293 g_last_hit_tracker = last_hit_buffer;
294#endif // LED_MATRIX_KEYREACTIVE_ENABLED
295
296 // next task
297 led_task_state = RENDERING;
298}
299
300static void led_task_render(uint8_t effect) {
301 bool rendering = false;
302 led_effect_params.init = (effect != led_last_effect) || (led_matrix_eeconfig.enable != led_last_enable);
303 if (led_effect_params.flags != led_matrix_eeconfig.flags) {
304 led_effect_params.flags = led_matrix_eeconfig.flags;
305 led_matrix_set_value_all(0);
306 }
166 307
167 // this gets ticked at 20 Hz.
168 // each effect can opt to do calculations 308 // each effect can opt to do calculations
169 // and/or request PWM buffer updates. 309 // and/or request PWM buffer updates.
170 switch (effect) { 310 switch (effect) {
171 case LED_MATRIX_UNIFORM_BRIGHTNESS: 311 case LED_MATRIX_NONE:
172 led_matrix_uniform_brightness(); 312 rendering = led_matrix_none(&led_effect_params);
173 break; 313 break;
174 default: 314
175 led_matrix_custom(); 315// ---------------------------------------------
316// -----Begin led effect switch case macros-----
317#define LED_MATRIX_EFFECT(name, ...) \
318 case LED_MATRIX_##name: \
319 rendering = name(&led_effect_params); \
320 break;
321#include "led_matrix_animations/led_matrix_effects.inc"
322#undef LED_MATRIX_EFFECT
323
324#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
325# define LED_MATRIX_EFFECT(name, ...) \
326 case LED_MATRIX_CUSTOM_##name: \
327 rendering = name(&led_effect_params); \
176 break; 328 break;
329# ifdef LED_MATRIX_CUSTOM_KB
330# include "led_matrix_kb.inc"
331# endif
332# ifdef LED_MATRIX_CUSTOM_USER
333# include "led_matrix_user.inc"
334# endif
335# undef LED_MATRIX_EFFECT
336#endif
337 // -----End led effect switch case macros-------
338 // ---------------------------------------------
177 } 339 }
178 340
179 if (!suspend_backlight) { 341 led_effect_params.iter++;
180 led_matrix_indicators(); 342
343 // next task
344 if (!rendering) {
345 led_task_state = FLUSHING;
346 if (!led_effect_params.init && effect == LED_MATRIX_NONE) {
347 // We only need to flush once if we are LED_MATRIX_NONE
348 led_task_state = SYNCING;
349 }
181 } 350 }
351}
352
353static void led_task_flush(uint8_t effect) {
354 // update last trackers after the first full render so we can init over several frames
355 led_last_effect = effect;
356 led_last_enable = led_matrix_eeconfig.enable;
357
358 // update pwm buffers
359 led_matrix_update_pwm_buffers();
182 360
183 // Tell the LED driver to update its state 361 // next task
184 led_matrix_driver.flush(); 362 led_task_state = SYNCING;
363}
364
365void led_matrix_task(void) {
366 led_task_timers();
367
368 // Ideally we would also stop sending zeros to the LED driver PWM buffers
369 // while suspended and just do a software shutdown. This is a cheap hack for now.
370 bool suspend_backlight = suspend_state ||
371#if LED_DISABLE_TIMEOUT > 0
372 (led_anykey_timer > (uint32_t)LED_DISABLE_TIMEOUT) ||
373#endif // LED_DISABLE_TIMEOUT > 0
374 false;
375
376 uint8_t effect = suspend_backlight || !led_matrix_eeconfig.enable ? 0 : led_matrix_eeconfig.mode;
377
378 switch (led_task_state) {
379 case STARTING:
380 led_task_start();
381 break;
382 case RENDERING:
383 led_task_render(effect);
384 if (effect) {
385 led_matrix_indicators();
386 led_matrix_indicators_advanced(&led_effect_params);
387 }
388 break;
389 case FLUSHING:
390 led_task_flush(effect);
391 break;
392 case SYNCING:
393 led_task_sync();
394 break;
395 }
185} 396}
186 397
187void led_matrix_indicators(void) { 398void led_matrix_indicators(void) {
@@ -193,33 +404,42 @@ __attribute__((weak)) void led_matrix_indicators_kb(void) {}
193 404
194__attribute__((weak)) void led_matrix_indicators_user(void) {} 405__attribute__((weak)) void led_matrix_indicators_user(void) {}
195 406
196// void led_matrix_set_indicator_index(uint8_t *index, uint8_t row, uint8_t column) 407void led_matrix_indicators_advanced(effect_params_t *params) {
197// { 408 /* special handling is needed for "params->iter", since it's already been incremented.
198// if (row >= MATRIX_ROWS) 409 * Could move the invocations to led_task_render, but then it's missing a few checks
199// { 410 * and not sure which would be better. Otherwise, this should be called from
200// // Special value, 255=none, 254=all 411 * led_task_render, right before the iter++ line.
201// *index = row; 412 */
202// } 413#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL
203// else 414 uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * (params->iter - 1);
204// { 415 uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT;
205// // This needs updated to something like 416 if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
206// // uint8_t led[8]; 417#else
207// // uint8_t led_count = map_row_column_to_led(row, column, led); 418 uint8_t min = 0;
208// // for(uint8_t i = 0; i < led_count; i++) 419 uint8_t max = DRIVER_LED_TOTAL;
209// map_row_column_to_led(row, column, index); 420#endif
210// } 421 led_matrix_indicators_advanced_kb(min, max);
211// } 422 led_matrix_indicators_advanced_user(min, max);
423}
424
425__attribute__((weak)) void led_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max) {}
426
427__attribute__((weak)) void led_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {}
212 428
213void led_matrix_init(void) { 429void led_matrix_init(void) {
214 led_matrix_driver.init(); 430 led_matrix_driver.init();
215 431
216 // Wait half a second for the driver to finish initializing 432#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
217 wait_ms(500); 433 g_last_hit_tracker.count = 0;
434 for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) {
435 g_last_hit_tracker.tick[i] = UINT16_MAX;
436 }
218 437
219 // clear the key hits 438 last_hit_buffer.count = 0;
220 for (int led = 0; led < DRIVER_LED_TOTAL; led++) { 439 for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) {
221 g_key_hit[led] = 255; 440 last_hit_buffer.tick[i] = UINT16_MAX;
222 } 441 }
442#endif // LED_MATRIX_KEYREACTIVE_ENABLED
223 443
224 if (!eeconfig_is_enabled()) { 444 if (!eeconfig_is_enabled()) {
225 dprintf("led_matrix_init_drivers eeconfig is not enabled.\n"); 445 dprintf("led_matrix_init_drivers eeconfig is not enabled.\n");
@@ -227,122 +447,137 @@ void led_matrix_init(void) {
227 eeconfig_update_led_matrix_default(); 447 eeconfig_update_led_matrix_default();
228 } 448 }
229 449
230 led_matrix_eeconfig.raw = eeconfig_read_led_matrix(); 450 eeconfig_read_led_matrix();
231
232 if (!led_matrix_eeconfig.mode) { 451 if (!led_matrix_eeconfig.mode) {
233 dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n"); 452 dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n");
234 eeconfig_update_led_matrix_default(); 453 eeconfig_update_led_matrix_default();
235 led_matrix_eeconfig.raw = eeconfig_read_led_matrix();
236 } 454 }
237
238 eeconfig_debug_led_matrix(); // display current eeprom values 455 eeconfig_debug_led_matrix(); // display current eeprom values
239} 456}
240 457
241// Deals with the messy details of incrementing an integer 458void led_matrix_set_suspend_state(bool state) {
242static uint8_t increment(uint8_t value, uint8_t step, uint8_t min, uint8_t max) { 459#ifdef LED_DISABLE_WHEN_USB_SUSPENDED
243 int16_t new_value = value; 460 if (state) {
244 new_value += step; 461 led_matrix_set_value_all(0); // turn off all LEDs when suspending
245 return MIN(MAX(new_value, min), max); 462 }
463 suspend_state = state;
464#endif
246} 465}
247 466
248static uint8_t decrement(uint8_t value, uint8_t step, uint8_t min, uint8_t max) { 467bool led_matrix_get_suspend_state(void) { return suspend_state; }
249 int16_t new_value = value;
250 new_value -= step;
251 return MIN(MAX(new_value, min), max);
252}
253 468
254// void *backlight_get_custom_key_value_eeprom_address(uint8_t led) { 469void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
255// // 3 bytes per value
256// return EECONFIG_LED_MATRIX + (led * 3);
257// }
258
259// void backlight_get_key_value(uint8_t led, uint8_t *value) {
260// void *address = backlight_get_custom_key_value_eeprom_address(led);
261// value = eeprom_read_byte(address);
262// }
263
264// void backlight_set_key_value(uint8_t row, uint8_t column, uint8_t value) {
265// uint8_t led[8];
266// uint8_t led_count = map_row_column_to_led(row, column, led);
267// for(uint8_t i = 0; i < led_count; i++) {
268// if (led[i] < DRIVER_LED_TOTAL) {
269// void *address = backlight_get_custom_key_value_eeprom_address(led[i]);
270// eeprom_update_byte(address, value);
271// }
272// }
273// }
274
275uint32_t led_matrix_get_tick(void) { return g_tick; }
276
277void led_matrix_toggle(void) {
278 led_matrix_eeconfig.enable ^= 1; 470 led_matrix_eeconfig.enable ^= 1;
279 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); 471 led_task_state = STARTING;
472 if (write_to_eeprom) {
473 eeconfig_update_led_matrix();
474 }
475 dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable);
280} 476}
477void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); }
478void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); }
281 479
282void led_matrix_enable(void) { 480void led_matrix_enable(void) {
283 led_matrix_eeconfig.enable = 1; 481 led_matrix_enable_noeeprom();
284 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); 482 eeconfig_update_led_matrix();
285} 483}
286 484
287void led_matrix_enable_noeeprom(void) { led_matrix_eeconfig.enable = 1; } 485void led_matrix_enable_noeeprom(void) {
486 if (!led_matrix_eeconfig.enable) led_task_state = STARTING;
487 led_matrix_eeconfig.enable = 1;
488}
288 489
289void led_matrix_disable(void) { 490void led_matrix_disable(void) {
491 led_matrix_disable_noeeprom();
492 eeconfig_update_led_matrix();
493}
494
495void led_matrix_disable_noeeprom(void) {
496 if (led_matrix_eeconfig.enable) led_task_state = STARTING;
290 led_matrix_eeconfig.enable = 0; 497 led_matrix_eeconfig.enable = 0;
291 eeconfig_update_led_matrix(led_matrix_eeconfig.raw);
292} 498}
293 499
294void led_matrix_disable_noeeprom(void) { led_matrix_eeconfig.enable = 0; } 500uint8_t led_matrix_is_enabled(void) { return led_matrix_eeconfig.enable; }
295 501
296void led_matrix_step(void) { 502void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
297 led_matrix_eeconfig.mode++; 503 if (!led_matrix_eeconfig.enable) {
298 if (led_matrix_eeconfig.mode >= LED_MATRIX_EFFECT_MAX) { 504 return;
299 led_matrix_eeconfig.mode = 1;
300 } 505 }
301 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); 506 if (mode < 1) {
302} 507 led_matrix_eeconfig.mode = 1;
303 508 } else if (mode >= LED_MATRIX_EFFECT_MAX) {
304void led_matrix_step_reverse(void) {
305 led_matrix_eeconfig.mode--;
306 if (led_matrix_eeconfig.mode < 1) {
307 led_matrix_eeconfig.mode = LED_MATRIX_EFFECT_MAX - 1; 509 led_matrix_eeconfig.mode = LED_MATRIX_EFFECT_MAX - 1;
510 } else {
511 led_matrix_eeconfig.mode = mode;
512 }
513 led_task_state = STARTING;
514 if (write_to_eeprom) {
515 eeconfig_update_led_matrix();
308 } 516 }
309 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); 517 dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);
310} 518}
519void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); }
520void led_matrix_mode(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, true); }
311 521
312void led_matrix_increase_val(void) { 522uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; }
313 led_matrix_eeconfig.val = increment(led_matrix_eeconfig.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS);
314 eeconfig_update_led_matrix(led_matrix_eeconfig.raw);
315}
316 523
317void led_matrix_decrease_val(void) { 524void led_matrix_step_helper(bool write_to_eeprom) {
318 led_matrix_eeconfig.val = decrement(led_matrix_eeconfig.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); 525 uint8_t mode = led_matrix_eeconfig.mode + 1;
319 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); 526 led_matrix_mode_eeprom_helper((mode < LED_MATRIX_EFFECT_MAX) ? mode : 1, write_to_eeprom);
320} 527}
528void led_matrix_step_noeeprom(void) { led_matrix_step_helper(false); }
529void led_matrix_step(void) { led_matrix_step_helper(true); }
321 530
322void led_matrix_increase_speed(void) { 531void led_matrix_step_reverse_helper(bool write_to_eeprom) {
323 led_matrix_eeconfig.speed = increment(led_matrix_eeconfig.speed, 1, 0, 3); 532 uint8_t mode = led_matrix_eeconfig.mode - 1;
324 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); // EECONFIG needs to be increased to support this 533 led_matrix_mode_eeprom_helper((mode < 1) ? LED_MATRIX_EFFECT_MAX - 1 : mode, write_to_eeprom);
325} 534}
535void led_matrix_step_reverse_noeeprom(void) { led_matrix_step_reverse_helper(false); }
536void led_matrix_step_reverse(void) { led_matrix_step_reverse_helper(true); }
326 537
327void led_matrix_decrease_speed(void) { 538void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) {
328 led_matrix_eeconfig.speed = decrement(led_matrix_eeconfig.speed, 1, 0, 3); 539 if (!led_matrix_eeconfig.enable) {
329 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); // EECONFIG needs to be increased to support this 540 return;
541 }
542 led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val;
543 if (write_to_eeprom) {
544 eeconfig_update_led_matrix();
545 }
546 dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val);
330} 547}
548void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); }
549void led_matrix_set_val(uint8_t val) { led_matrix_set_val_eeprom_helper(val, true); }
331 550
332void led_matrix_mode(uint8_t mode, bool eeprom_write) { 551uint8_t led_matrix_get_val(void) { return led_matrix_eeconfig.val; }
333 led_matrix_eeconfig.mode = mode; 552
334 if (eeprom_write) { 553void led_matrix_increase_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qadd8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); }
335 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); 554void led_matrix_increase_val_noeeprom(void) { led_matrix_increase_val_helper(false); }
555void led_matrix_increase_val(void) { led_matrix_increase_val_helper(true); }
556
557void led_matrix_decrease_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qsub8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); }
558void led_matrix_decrease_val_noeeprom(void) { led_matrix_decrease_val_helper(false); }
559void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); }
560
561void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
562 led_matrix_eeconfig.speed = speed;
563 if (write_to_eeprom) {
564 eeconfig_update_led_matrix();
336 } 565 }
566 dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed);
337} 567}
568void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); }
569void led_matrix_set_speed(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, true); }
338 570
339uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; } 571uint8_t led_matrix_get_speed(void) { return led_matrix_eeconfig.speed; }
340 572
341void led_matrix_set_value_noeeprom(uint8_t val) { led_matrix_eeconfig.val = val; } 573void led_matrix_increase_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qadd8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); }
574void led_matrix_increase_speed_noeeprom(void) { led_matrix_increase_speed_helper(false); }
575void led_matrix_increase_speed(void) { led_matrix_increase_speed_helper(true); }
342 576
343void led_matrix_set_value(uint8_t val) { 577void led_matrix_decrease_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qsub8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); }
344 led_matrix_set_value_noeeprom(val); 578void led_matrix_decrease_speed_noeeprom(void) { led_matrix_decrease_speed_helper(false); }
345 eeconfig_update_led_matrix(led_matrix_eeconfig.raw); 579void led_matrix_decrease_speed(void) { led_matrix_decrease_speed_helper(true); }
346} 580
581led_flags_t led_matrix_get_flags(void) { return led_matrix_eeconfig.flags; }
347 582
348void backlight_set(uint8_t val) { led_matrix_set_value(val); } 583void led_matrix_set_flags(led_flags_t flags) { led_matrix_eeconfig.flags = flags; }
diff --git a/quantum/led_matrix.h b/quantum/led_matrix.h
index 85bae43c1..0984de73b 100644
--- a/quantum/led_matrix.h
+++ b/quantum/led_matrix.h
@@ -19,61 +19,120 @@
19 19
20#pragma once 20#pragma once
21 21
22#include <stdint.h>
23#include <stdbool.h>
22#include "led_matrix_types.h" 24#include "led_matrix_types.h"
25#include "quantum.h"
23 26
24#ifndef BACKLIGHT_ENABLE 27#ifdef IS31FL3731
25# error You must define BACKLIGHT_ENABLE with LED_MATRIX_ENABLE 28# include "is31fl3731-simple.h"
26#endif 29#endif
27 30
31#ifndef LED_MATRIX_LED_FLUSH_LIMIT
32# define LED_MATRIX_LED_FLUSH_LIMIT 16
33#endif
34
35#ifndef LED_MATRIX_LED_PROCESS_LIMIT
36# define LED_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5
37#endif
38
39#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL
40# define LED_MATRIX_USE_LIMITS(min, max) \
41 uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
42 uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
43 if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
44#else
45# define LED_MATRIX_USE_LIMITS(min, max) \
46 uint8_t min = 0; \
47 uint8_t max = DRIVER_LED_TOTAL;
48#endif
49
50#define LED_MATRIX_TEST_LED_FLAGS() \
51 if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) continue
52
28enum led_matrix_effects { 53enum led_matrix_effects {
29 LED_MATRIX_UNIFORM_BRIGHTNESS = 1, 54 LED_MATRIX_NONE = 0,
30 // All new effects go above this line 55
56// --------------------------------------
57// -----Begin led effect enum macros-----
58#define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name,
59#include "led_matrix_animations/led_matrix_effects.inc"
60#undef LED_MATRIX_EFFECT
61
62#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
63# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_CUSTOM_##name,
64# ifdef LED_MATRIX_CUSTOM_KB
65# include "led_matrix_kb.inc"
66# endif
67# ifdef LED_MATRIX_CUSTOM_USER
68# include "led_matrix_user.inc"
69# endif
70# undef LED_MATRIX_EFFECT
71#endif
72 // --------------------------------------
73 // -----End led effect enum macros-------
74
31 LED_MATRIX_EFFECT_MAX 75 LED_MATRIX_EFFECT_MAX
32}; 76};
33 77
34void led_matrix_set_index_value(int index, uint8_t value); 78void eeconfig_update_led_matrix_default(void);
35void led_matrix_set_index_value_all(uint8_t value); 79void eeconfig_update_led_matrix(void);
80void eeconfig_debug_led_matrix(void);
81
82uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i);
83uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i);
84
85void led_matrix_set_value(int index, uint8_t value);
86void led_matrix_set_value_all(uint8_t value);
87
88void process_led_matrix(uint8_t row, uint8_t col, bool pressed);
89
90void led_matrix_task(void);
36 91
37// This runs after another backlight effect and replaces 92// This runs after another backlight effect and replaces
38// colors already set 93// values already set
39void led_matrix_indicators(void); 94void led_matrix_indicators(void);
40void led_matrix_indicators_kb(void); 95void led_matrix_indicators_kb(void);
41void led_matrix_indicators_user(void); 96void led_matrix_indicators_user(void);
42 97
43void led_matrix_init(void); 98void led_matrix_indicators_advanced(effect_params_t *params);
44void led_matrix_setup_drivers(void); 99void led_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max);
45 100void led_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max);
46void led_matrix_set_suspend_state(bool state);
47void led_matrix_set_indicator_state(uint8_t state);
48 101
49void led_matrix_task(void); 102void led_matrix_init(void);
50 103
51// This should not be called from an interrupt 104void led_matrix_set_suspend_state(bool state);
52// (eg. from a timer interrupt). 105bool led_matrix_get_suspend_state(void);
53// Call this while idle (in between matrix scans). 106void led_matrix_toggle(void);
54// If the buffer is dirty, it will update the driver with the buffer. 107void led_matrix_toggle_noeeprom(void);
55void led_matrix_update_pwm_buffers(void); 108void led_matrix_enable(void);
56 109void led_matrix_enable_noeeprom(void);
57bool process_led_matrix(uint16_t keycode, keyrecord_t *record); 110void led_matrix_disable(void);
58 111void led_matrix_disable_noeeprom(void);
59uint32_t led_matrix_get_tick(void); 112uint8_t led_matrix_is_enabled(void);
60 113void led_matrix_mode(uint8_t mode);
61void led_matrix_toggle(void); 114void led_matrix_mode_noeeprom(uint8_t mode);
62void led_matrix_enable(void); 115uint8_t led_matrix_get_mode(void);
63void led_matrix_enable_noeeprom(void); 116void led_matrix_step(void);
64void led_matrix_disable(void); 117void led_matrix_step_noeeprom(void);
65void led_matrix_disable_noeeprom(void); 118void led_matrix_step_reverse(void);
66void led_matrix_step(void); 119void led_matrix_step_reverse_noeeprom(void);
67void led_matrix_step_reverse(void); 120void led_matrix_set_val(uint8_t val);
68void led_matrix_increase_val(void); 121void led_matrix_set_val_noeeprom(uint8_t val);
69void led_matrix_decrease_val(void); 122uint8_t led_matrix_get_val(void);
70void led_matrix_increase_speed(void); 123void led_matrix_increase_val(void);
71void led_matrix_decrease_speed(void); 124void led_matrix_increase_val_noeeprom(void);
72void led_matrix_mode(uint8_t mode, bool eeprom_write); 125void led_matrix_decrease_val(void);
73void led_matrix_mode_noeeprom(uint8_t mode); 126void led_matrix_decrease_val_noeeprom(void);
74uint8_t led_matrix_get_mode(void); 127void led_matrix_set_speed(uint8_t speed);
75void led_matrix_set_value(uint8_t mode); 128void led_matrix_set_speed_noeeprom(uint8_t speed);
76void led_matrix_set_value_noeeprom(uint8_t mode); 129uint8_t led_matrix_get_speed(void);
130void led_matrix_increase_speed(void);
131void led_matrix_increase_speed_noeeprom(void);
132void led_matrix_decrease_speed(void);
133void led_matrix_decrease_speed_noeeprom(void);
134led_flags_t led_matrix_get_flags(void);
135void led_matrix_set_flags(led_flags_t flags);
77 136
78typedef struct { 137typedef struct {
79 /* Perform any initialisation required for the other driver functions to work. */ 138 /* Perform any initialisation required for the other driver functions to work. */
@@ -91,4 +150,11 @@ extern const led_matrix_driver_t led_matrix_driver;
91 150
92extern led_eeconfig_t led_matrix_eeconfig; 151extern led_eeconfig_t led_matrix_eeconfig;
93 152
153extern uint32_t g_led_timer;
94extern led_config_t g_led_config; 154extern led_config_t g_led_config;
155#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
156extern last_hit_t g_last_hit_tracker;
157#endif
158#ifdef LED_MATRIX_FRAMEBUFFER_EFFECTS
159extern uint8_t g_led_frame_buffer[MATRIX_ROWS][MATRIX_COLS];
160#endif
diff --git a/quantum/led_matrix_animations/alpha_mods_anim.h b/quantum/led_matrix_animations/alpha_mods_anim.h
new file mode 100644
index 000000000..6f69f6892
--- /dev/null
+++ b/quantum/led_matrix_animations/alpha_mods_anim.h
@@ -0,0 +1,24 @@
1#ifndef DISABLE_LED_MATRIX_ALPHAS_MODS
2LED_MATRIX_EFFECT(ALPHAS_MODS)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5// alphas = val1, mods = val2
6bool ALPHAS_MODS(effect_params_t* params) {
7 LED_MATRIX_USE_LIMITS(led_min, led_max);
8
9 uint8_t val1 = led_matrix_eeconfig.val;
10 uint8_t val2 = val1 + led_matrix_eeconfig.speed;
11
12 for (uint8_t i = led_min; i < led_max; i++) {
13 LED_MATRIX_TEST_LED_FLAGS();
14 if (HAS_FLAGS(g_led_config.flags[i], LED_FLAG_MODIFIER)) {
15 led_matrix_set_value(i, val2);
16 } else {
17 led_matrix_set_value(i, val1);
18 }
19 }
20 return led_max < DRIVER_LED_TOTAL;
21}
22
23# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
24#endif // DISABLE_LED_MATRIX_ALPHAS_MODS
diff --git a/quantum/led_matrix_animations/band_anim.h b/quantum/led_matrix_animations/band_anim.h
new file mode 100644
index 000000000..523dba1b7
--- /dev/null
+++ b/quantum/led_matrix_animations/band_anim.h
@@ -0,0 +1,13 @@
1#ifndef DISABLE_LED_MATRIX_BAND
2LED_MATRIX_EFFECT(BAND)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) {
6 int16_t v = val - abs(scale8(g_led_config.point[i].x, 228) + 28 - time) * 8;
7 return scale8(v < 0 ? 0 : v, val);
8}
9
10bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); }
11
12# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
13#endif // DISABLE_LED_MATRIX_BAND
diff --git a/quantum/led_matrix_animations/band_pinwheel_anim.h b/quantum/led_matrix_animations/band_pinwheel_anim.h
new file mode 100644
index 000000000..fb3b835ca
--- /dev/null
+++ b/quantum/led_matrix_animations/band_pinwheel_anim.h
@@ -0,0 +1,10 @@
1#ifndef DISABLE_LED_MATRIX_BAND_PINWHEEL
2LED_MATRIX_EFFECT(BAND_PINWHEEL)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t time) { return scale8(val - time - atan2_8(dy, dx) * 3, val); }
6
7bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); }
8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL
diff --git a/quantum/led_matrix_animations/band_spiral_anim.h b/quantum/led_matrix_animations/band_spiral_anim.h
new file mode 100644
index 000000000..fca22aad9
--- /dev/null
+++ b/quantum/led_matrix_animations/band_spiral_anim.h
@@ -0,0 +1,10 @@
1#ifndef DISABLE_LED_MATRIX_BAND_SPIRAL
2LED_MATRIX_EFFECT(BAND_SPIRAL)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { return scale8(val + dist - time - atan2_8(dy, dx), val); }
6
7bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); }
8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_BAND_SPIRAL
diff --git a/quantum/led_matrix_animations/breathing_anim.h b/quantum/led_matrix_animations/breathing_anim.h
new file mode 100644
index 000000000..00310e3f6
--- /dev/null
+++ b/quantum/led_matrix_animations/breathing_anim.h
@@ -0,0 +1,19 @@
1#ifndef DISABLE_LED_MATRIX_BREATHING
2LED_MATRIX_EFFECT(BREATHING)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5bool BREATHING(effect_params_t* params) {
6 LED_MATRIX_USE_LIMITS(led_min, led_max);
7
8 uint8_t val = led_matrix_eeconfig.val;
9 uint16_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 8);
10 val = scale8(abs8(sin8(time) - 128) * 2, val);
11 for (uint8_t i = led_min; i < led_max; i++) {
12 LED_MATRIX_TEST_LED_FLAGS();
13 led_matrix_set_value(i, val);
14 }
15 return led_max < DRIVER_LED_TOTAL;
16}
17
18# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
19#endif // DISABLE_LED_MATRIX_BREATHING
diff --git a/quantum/led_matrix_animations/cycle_left_right_anim.h b/quantum/led_matrix_animations/cycle_left_right_anim.h
new file mode 100644
index 000000000..51e81d57c
--- /dev/null
+++ b/quantum/led_matrix_animations/cycle_left_right_anim.h
@@ -0,0 +1,10 @@
1#ifndef DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
2LED_MATRIX_EFFECT(CYCLE_LEFT_RIGHT)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(g_led_config.point[i].x - time, val); }
6
7bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }
8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
diff --git a/quantum/led_matrix_animations/cycle_out_in_anim.h b/quantum/led_matrix_animations/cycle_out_in_anim.h
new file mode 100644
index 000000000..f62061552
--- /dev/null
+++ b/quantum/led_matrix_animations/cycle_out_in_anim.h
@@ -0,0 +1,10 @@
1#ifndef DISABLE_LED_MATRIX_CYCLE_OUT_IN
2LED_MATRIX_EFFECT(CYCLE_OUT_IN)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { return scale8(3 * dist / 2 + time, val); }
6
7bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }
8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN
diff --git a/quantum/led_matrix_animations/cycle_up_down_anim.h b/quantum/led_matrix_animations/cycle_up_down_anim.h
new file mode 100644
index 000000000..bd1d12567
--- /dev/null
+++ b/quantum/led_matrix_animations/cycle_up_down_anim.h
@@ -0,0 +1,10 @@
1#ifndef DISABLE_LED_MATRIX_CYCLE_UP_DOWN
2LED_MATRIX_EFFECT(CYCLE_UP_DOWN)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(g_led_config.point[i].y - time, val); }
6
7bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }
8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN
diff --git a/quantum/led_matrix_animations/dual_beacon_anim.h b/quantum/led_matrix_animations/dual_beacon_anim.h
new file mode 100644
index 000000000..9b8a7877c
--- /dev/null
+++ b/quantum/led_matrix_animations/dual_beacon_anim.h
@@ -0,0 +1,10 @@
1#ifndef DISABLE_LED_MATRIX_DUAL_BEACON
2LED_MATRIX_EFFECT(DUAL_BEACON)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time) { return scale8(((g_led_config.point[i].y - k_led_matrix_center.y) * cos + (g_led_config.point[i].x - k_led_matrix_center.x) * sin) / 128, val); }
6
7bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }
8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_DUAL_BEACON
diff --git a/quantum/led_matrix_animations/led_matrix_effects.inc b/quantum/led_matrix_animations/led_matrix_effects.inc
new file mode 100644
index 000000000..67237c568
--- /dev/null
+++ b/quantum/led_matrix_animations/led_matrix_effects.inc
@@ -0,0 +1,18 @@
1// Add your new core led matrix effect here, order determins enum order, requires "led_matrix_animations/ directory
2#include "led_matrix_animations/solid_anim.h"
3#include "led_matrix_animations/alpha_mods_anim.h"
4#include "led_matrix_animations/breathing_anim.h"
5#include "led_matrix_animations/band_anim.h"
6#include "led_matrix_animations/band_pinwheel_anim.h"
7#include "led_matrix_animations/band_spiral_anim.h"
8#include "led_matrix_animations/cycle_left_right_anim.h"
9#include "led_matrix_animations/cycle_up_down_anim.h"
10#include "led_matrix_animations/cycle_out_in_anim.h"
11#include "led_matrix_animations/dual_beacon_anim.h"
12#include "led_matrix_animations/solid_reactive_simple_anim.h"
13#include "led_matrix_animations/solid_reactive_wide.h"
14#include "led_matrix_animations/solid_reactive_cross.h"
15#include "led_matrix_animations/solid_reactive_nexus.h"
16#include "led_matrix_animations/solid_splash_anim.h"
17#include "led_matrix_animations/wave_left_right_anim.h"
18#include "led_matrix_animations/wave_up_down_anim.h"
diff --git a/quantum/led_matrix_animations/solid_anim.h b/quantum/led_matrix_animations/solid_anim.h
new file mode 100644
index 000000000..4c9e43c58
--- /dev/null
+++ b/quantum/led_matrix_animations/solid_anim.h
@@ -0,0 +1,15 @@
1LED_MATRIX_EFFECT(SOLID)
2#ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
3
4bool SOLID(effect_params_t* params) {
5 LED_MATRIX_USE_LIMITS(led_min, led_max);
6
7 uint8_t val = led_matrix_eeconfig.val;
8 for (uint8_t i = led_min; i < led_max; i++) {
9 LED_MATRIX_TEST_LED_FLAGS();
10 led_matrix_set_value(i, val);
11 }
12 return led_max < DRIVER_LED_TOTAL;
13}
14
15#endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/led_matrix_animations/solid_reactive_cross.h b/quantum/led_matrix_animations/solid_reactive_cross.h
new file mode 100644
index 000000000..f402d99b3
--- /dev/null
+++ b/quantum/led_matrix_animations/solid_reactive_cross.h
@@ -0,0 +1,35 @@
1#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
2# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
3
4# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
5LED_MATRIX_EFFECT(SOLID_REACTIVE_CROSS)
6# endif
7
8# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS
9LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTICROSS)
10# endif
11
12# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
13
14static uint8_t SOLID_REACTIVE_CROSS_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
15 uint16_t effect = tick + dist;
16 dx = dx < 0 ? dx * -1 : dx;
17 dy = dy < 0 ? dy * -1 : dy;
18 dx = dx * 16 > 255 ? 255 : dx * 16;
19 dy = dy * 16 > 255 ? 255 : dy * 16;
20 effect += dx > dy ? dy : dx;
21 if (effect > 255) effect = 255;
22 return qadd8(val, 255 - effect);
23}
24
25# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
26bool SOLID_REACTIVE_CROSS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math); }
27# endif
28
29# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS
30bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math); }
31# endif
32
33# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
34# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
35#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix_animations/solid_reactive_nexus.h b/quantum/led_matrix_animations/solid_reactive_nexus.h
new file mode 100644
index 000000000..4d0d25226
--- /dev/null
+++ b/quantum/led_matrix_animations/solid_reactive_nexus.h
@@ -0,0 +1,32 @@
1#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
2# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
3
4# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS
5LED_MATRIX_EFFECT(SOLID_REACTIVE_NEXUS)
6# endif
7
8# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS
9LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTINEXUS)
10# endif
11
12# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
13
14static uint8_t SOLID_REACTIVE_NEXUS_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
15 uint16_t effect = tick - dist;
16 if (effect > 255) effect = 255;
17 if (dist > 72) effect = 255;
18 if ((dx > 8 || dx < -8) && (dy > 8 || dy < -8)) effect = 255;
19 return qadd8(val, 255 - effect);
20}
21
22# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS
23bool SOLID_REACTIVE_NEXUS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math); }
24# endif
25
26# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS
27bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math); }
28# endif
29
30# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
31# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
32#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix_animations/solid_reactive_simple_anim.h b/quantum/led_matrix_animations/solid_reactive_simple_anim.h
new file mode 100644
index 000000000..30e2527f6
--- /dev/null
+++ b/quantum/led_matrix_animations/solid_reactive_simple_anim.h
@@ -0,0 +1,12 @@
1#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
2# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
3LED_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE)
4# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
5
6static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return scale8(255 - offset, val); }
7
8bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }
9
10# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
11# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
12#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix_animations/solid_reactive_wide.h b/quantum/led_matrix_animations/solid_reactive_wide.h
new file mode 100644
index 000000000..34a230c25
--- /dev/null
+++ b/quantum/led_matrix_animations/solid_reactive_wide.h
@@ -0,0 +1,30 @@
1#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
2# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
3
4# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
5LED_MATRIX_EFFECT(SOLID_REACTIVE_WIDE)
6# endif
7
8# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE
9LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTIWIDE)
10# endif
11
12# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
13
14static uint8_t SOLID_REACTIVE_WIDE_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
15 uint16_t effect = tick + dist * 5;
16 if (effect > 255) effect = 255;
17 return qadd8(val, 255 - effect);
18}
19
20# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
21bool SOLID_REACTIVE_WIDE(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math); }
22# endif
23
24# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE
25bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math); }
26# endif
27
28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
29# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
30#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix_animations/solid_splash_anim.h b/quantum/led_matrix_animations/solid_splash_anim.h
new file mode 100644
index 000000000..4f6ba3d34
--- /dev/null
+++ b/quantum/led_matrix_animations/solid_splash_anim.h
@@ -0,0 +1,30 @@
1#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
2# if !defined(DISABLE_LED_MATRIX_SOLID_SPLASH) || !defined(DISABLE_LED_MATRIX_SOLID_MULTISPLASH)
3
4# ifndef DISABLE_LED_MATRIX_SOLID_SPLASH
5LED_MATRIX_EFFECT(SOLID_SPLASH)
6# endif
7
8# ifndef DISABLE_LED_MATRIX_SOLID_MULTISPLASH
9LED_MATRIX_EFFECT(SOLID_MULTISPLASH)
10# endif
11
12# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
13
14uint8_t SOLID_SPLASH_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
15 uint16_t effect = tick - dist;
16 if (effect > 255) effect = 255;
17 return qadd8(val, 255 - effect);
18}
19
20# ifndef DISABLE_LED_MATRIX_SOLID_SPLASH
21bool SOLID_SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math); }
22# endif
23
24# ifndef DISABLE_LED_MATRIX_SOLID_MULTISPLASH
25bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); }
26# endif
27
28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
29# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH)
30#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix_animations/wave_left_right_anim.h b/quantum/led_matrix_animations/wave_left_right_anim.h
new file mode 100644
index 000000000..736f22ddc
--- /dev/null
+++ b/quantum/led_matrix_animations/wave_left_right_anim.h
@@ -0,0 +1,10 @@
1#ifndef DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT
2LED_MATRIX_EFFECT(WAVE_LEFT_RIGHT)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(sin8(g_led_config.point[i].x - time), val); }
6
7bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); }
8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT
diff --git a/quantum/led_matrix_animations/wave_up_down_anim.h b/quantum/led_matrix_animations/wave_up_down_anim.h
new file mode 100644
index 000000000..3cab0597d
--- /dev/null
+++ b/quantum/led_matrix_animations/wave_up_down_anim.h
@@ -0,0 +1,10 @@
1#ifndef DISABLE_LED_MATRIX_WAVE_UP_DOWN
2LED_MATRIX_EFFECT(WAVE_UP_DOWN)
3# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
4
5static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(sin8(g_led_config.point[i].y - time), val); }
6
7bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); }
8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN
diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix_drivers.c
index eddf3f286..1d46b2c50 100644
--- a/quantum/led_matrix_drivers.c
+++ b/quantum/led_matrix_drivers.c
@@ -15,9 +15,6 @@
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18#include <stdint.h>
19#include <stdbool.h>
20#include "quantum.h"
21#include "led_matrix.h" 18#include "led_matrix.h"
22 19
23/* Each driver needs to define a struct: 20/* Each driver needs to define a struct:
@@ -30,10 +27,6 @@
30 27
31#if defined(IS31FL3731) || defined(IS31FL3733) 28#if defined(IS31FL3731) || defined(IS31FL3733)
32 29
33# if defined(IS31FL3731)
34# include "is31fl3731-simple.h"
35# endif
36
37# include "i2c_master.h" 30# include "i2c_master.h"
38 31
39static void init(void) { 32static void init(void) {
@@ -53,16 +46,28 @@ static void init(void) {
53# endif 46# endif
54# else 47# else
55# ifdef LED_DRIVER_ADDR_1 48# ifdef LED_DRIVER_ADDR_1
56 IS31FL3733_init(LED_DRIVER_ADDR_1, 0); 49# ifndef LED_DRIVER_SYNC_1
50# define LED_DRIVER_SYNC_1 0
51# endif
52 IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1);
57# endif 53# endif
58# ifdef LED_DRIVER_ADDR_2 54# ifdef LED_DRIVER_ADDR_2
59 IS31FL3733_init(LED_DRIVER_ADDR_2, 0); 55# ifndef LED_DRIVER_SYNC_2
56# define LED_DRIVER_SYNC_2 0
57# endif
58 IS31FL3733_init(LED_DRIVER_ADDR_2, LED_DRIVER_SYNC_2);
60# endif 59# endif
61# ifdef LED_DRIVER_ADDR_3 60# ifdef LED_DRIVER_ADDR_3
62 IS31FL3733_init(LED_DRIVER_ADDR_3, 0); 61# ifndef LED_DRIVER_SYNC_3
62# define LED_DRIVER_SYNC_3 0
63# endif
64 IS31FL3733_init(LED_DRIVER_ADDR_3, LED_DRIVER_SYNC_3);
63# endif 65# endif
64# ifdef LED_DRIVER_ADDR_4 66# ifdef LED_DRIVER_ADDR_4
65 IS31FL3733_init(LED_DRIVER_ADDR_4, 0); 67# ifndef LED_DRIVER_SYNC_4
68# define LED_DRIVER_SYNC_4 0
69# endif
70 IS31FL3733_init(LED_DRIVER_ADDR_4, LED_DRIVER_SYNC_4);
66# endif 71# endif
67# endif 72# endif
68 73
diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy.h b/quantum/led_matrix_runners/effect_runner_dx_dy.h
new file mode 100644
index 000000000..ef97631b9
--- /dev/null
+++ b/quantum/led_matrix_runners/effect_runner_dx_dy.h
@@ -0,0 +1,16 @@
1#pragma once
2
3typedef uint8_t (*dx_dy_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t time);
4
5bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) {
6 LED_MATRIX_USE_LIMITS(led_min, led_max);
7
8 uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 2);
9 for (uint8_t i = led_min; i < led_max; i++) {
10 LED_MATRIX_TEST_LED_FLAGS();
11 int16_t dx = g_led_config.point[i].x - k_led_matrix_center.x;
12 int16_t dy = g_led_config.point[i].y - k_led_matrix_center.y;
13 led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, time));
14 }
15 return led_max < DRIVER_LED_TOTAL;
16}
diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h
new file mode 100644
index 000000000..5ef5938be
--- /dev/null
+++ b/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h
@@ -0,0 +1,17 @@
1#pragma once
2
3typedef uint8_t (*dx_dy_dist_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time);
4
5bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func) {
6 LED_MATRIX_USE_LIMITS(led_min, led_max);
7
8 uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 2);
9 for (uint8_t i = led_min; i < led_max; i++) {
10 LED_MATRIX_TEST_LED_FLAGS();
11 int16_t dx = g_led_config.point[i].x - k_led_matrix_center.x;
12 int16_t dy = g_led_config.point[i].y - k_led_matrix_center.y;
13 uint8_t dist = sqrt16(dx * dx + dy * dy);
14 led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, dist, time));
15 }
16 return led_max < DRIVER_LED_TOTAL;
17}
diff --git a/quantum/led_matrix_runners/effect_runner_i.h b/quantum/led_matrix_runners/effect_runner_i.h
new file mode 100644
index 000000000..b3015759b
--- /dev/null
+++ b/quantum/led_matrix_runners/effect_runner_i.h
@@ -0,0 +1,14 @@
1#pragma once
2
3typedef uint8_t (*i_f)(uint8_t val, uint8_t i, uint8_t time);
4
5bool effect_runner_i(effect_params_t* params, i_f effect_func) {
6 LED_MATRIX_USE_LIMITS(led_min, led_max);
7
8 uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 4);
9 for (uint8_t i = led_min; i < led_max; i++) {
10 LED_MATRIX_TEST_LED_FLAGS();
11 led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, i, time));
12 }
13 return led_max < DRIVER_LED_TOTAL;
14}
diff --git a/quantum/led_matrix_runners/effect_runner_reactive.h b/quantum/led_matrix_runners/effect_runner_reactive.h
new file mode 100644
index 000000000..4369ea8c4
--- /dev/null
+++ b/quantum/led_matrix_runners/effect_runner_reactive.h
@@ -0,0 +1,28 @@
1#pragma once
2
3#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
4
5typedef uint8_t (*reactive_f)(uint8_t val, uint16_t offset);
6
7bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) {
8 LED_MATRIX_USE_LIMITS(led_min, led_max);
9
10 uint16_t max_tick = 65535 / led_matrix_eeconfig.speed;
11 for (uint8_t i = led_min; i < led_max; i++) {
12 LED_MATRIX_TEST_LED_FLAGS();
13 uint16_t tick = max_tick;
14 // Reverse search to find most recent key hit
15 for (int8_t j = g_last_hit_tracker.count - 1; j >= 0; j--) {
16 if (g_last_hit_tracker.index[j] == i && g_last_hit_tracker.tick[j] < tick) {
17 tick = g_last_hit_tracker.tick[j];
18 break;
19 }
20 }
21
22 uint16_t offset = scale16by8(tick, led_matrix_eeconfig.speed);
23 led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, offset));
24 }
25 return led_max < DRIVER_LED_TOTAL;
26}
27
28#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix_runners/effect_runner_reactive_splash.h b/quantum/led_matrix_runners/effect_runner_reactive_splash.h
new file mode 100644
index 000000000..d6eb9731e
--- /dev/null
+++ b/quantum/led_matrix_runners/effect_runner_reactive_splash.h
@@ -0,0 +1,26 @@
1#pragma once
2
3#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
4
5typedef uint8_t (*reactive_splash_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick);
6
7bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, reactive_splash_f effect_func) {
8 LED_MATRIX_USE_LIMITS(led_min, led_max);
9
10 uint8_t count = g_last_hit_tracker.count;
11 for (uint8_t i = led_min; i < led_max; i++) {
12 LED_MATRIX_TEST_LED_FLAGS();
13 uint8_t val = 0;
14 for (uint8_t j = start; j < count; j++) {
15 int16_t dx = g_led_config.point[i].x - g_last_hit_tracker.x[j];
16 int16_t dy = g_led_config.point[i].y - g_last_hit_tracker.y[j];
17 uint8_t dist = sqrt16(dx * dx + dy * dy);
18 uint16_t tick = scale16by8(g_last_hit_tracker.tick[j], led_matrix_eeconfig.speed);
19 val = effect_func(val, dx, dy, dist, tick);
20 }
21 led_matrix_set_value(i, scale8(val, led_matrix_eeconfig.val));
22 }
23 return led_max < DRIVER_LED_TOTAL;
24}
25
26#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h b/quantum/led_matrix_runners/effect_runner_sin_cos_i.h
new file mode 100644
index 000000000..4a5219abd
--- /dev/null
+++ b/quantum/led_matrix_runners/effect_runner_sin_cos_i.h
@@ -0,0 +1,16 @@
1#pragma once
2
3typedef uint8_t (*sin_cos_i_f)(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time);
4
5bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) {
6 LED_MATRIX_USE_LIMITS(led_min, led_max);
7
8 uint16_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 4);
9 int8_t cos_value = cos8(time) - 128;
10 int8_t sin_value = sin8(time) - 128;
11 for (uint8_t i = led_min; i < led_max; i++) {
12 LED_MATRIX_TEST_LED_FLAGS();
13 led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, cos_value, sin_value, i, time));
14 }
15 return led_max < DRIVER_LED_TOTAL;
16}
diff --git a/quantum/led_matrix_types.h b/quantum/led_matrix_types.h
index 669b67042..61cdbd9b8 100644
--- a/quantum/led_matrix_types.h
+++ b/quantum/led_matrix_types.h
@@ -29,15 +29,42 @@
29# pragma pack(push, 1) 29# pragma pack(push, 1)
30#endif 30#endif
31 31
32#if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES)
33# define LED_MATRIX_KEYREACTIVE_ENABLED
34#endif
35
32// Last led hit 36// Last led hit
33#ifndef LED_HITS_TO_REMEMBER 37#ifndef LED_HITS_TO_REMEMBER
34# define LED_HITS_TO_REMEMBER 8 38# define LED_HITS_TO_REMEMBER 8
35#endif // LED_HITS_TO_REMEMBER 39#endif // LED_HITS_TO_REMEMBER
36 40
41#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
42typedef struct PACKED {
43 uint8_t count;
44 uint8_t x[LED_HITS_TO_REMEMBER];
45 uint8_t y[LED_HITS_TO_REMEMBER];
46 uint8_t index[LED_HITS_TO_REMEMBER];
47 uint16_t tick[LED_HITS_TO_REMEMBER];
48} last_hit_t;
49#endif // LED_MATRIX_KEYREACTIVE_ENABLED
50
51typedef enum led_task_states { STARTING, RENDERING, FLUSHING, SYNCING } led_task_states;
52
53typedef uint8_t led_flags_t;
54
55typedef struct PACKED {
56 uint8_t iter;
57 led_flags_t flags;
58 bool init;
59} effect_params_t;
60
37typedef struct PACKED { 61typedef struct PACKED {
38 uint8_t x; 62 uint8_t x;
39 uint8_t y; 63 uint8_t y;
40} point_t; 64} led_point_t;
65
66#define HAS_FLAGS(bits, flags) ((bits & flags) == flags)
67#define HAS_ANY_FLAGS(bits, flags) ((bits & flags) != 0x00)
41 68
42#define LED_FLAG_ALL 0xFF 69#define LED_FLAG_ALL 0xFF
43#define LED_FLAG_NONE 0x00 70#define LED_FLAG_NONE 0x00
@@ -48,19 +75,20 @@ typedef struct PACKED {
48#define NO_LED 255 75#define NO_LED 255
49 76
50typedef struct PACKED { 77typedef struct PACKED {
51 uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS]; 78 uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS];
52 point_t point[DRIVER_LED_TOTAL]; 79 led_point_t point[DRIVER_LED_TOTAL];
53 uint8_t flags[DRIVER_LED_TOTAL]; 80 uint8_t flags[DRIVER_LED_TOTAL];
54} led_config_t; 81} led_config_t;
55 82
56typedef union { 83typedef union {
57 uint32_t raw; 84 uint32_t raw;
58 struct PACKED { 85 struct PACKED {
59 uint8_t enable : 2; 86 uint8_t enable : 2;
60 uint8_t mode : 6; 87 uint8_t mode : 6;
61 uint16_t reserved; 88 uint16_t reserved;
62 uint8_t val; 89 uint8_t val;
63 uint8_t speed; // EECONFIG needs to be increased to support this 90 uint8_t speed; // EECONFIG needs to be increased to support this
91 led_flags_t flags;
64 }; 92 };
65} led_eeconfig_t; 93} led_eeconfig_t;
66 94
diff --git a/quantum/matrix.c b/quantum/matrix.c
index c027b7bf2..34d6af2e6 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -116,9 +116,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
116 116
117 // Unselect row 117 // Unselect row
118 unselect_row(current_row); 118 unselect_row(current_row);
119 if (current_row + 1 < MATRIX_ROWS) { 119 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH
120 matrix_output_unselect_delay(); // wait for row signal to go HIGH
121 }
122 120
123 // If the row has changed, store the row and return the changed flag. 121 // If the row has changed, store the row and return the changed flag.
124 if (current_matrix[current_row] != current_row_value) { 122 if (current_matrix[current_row] != current_row_value) {
@@ -178,9 +176,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
178 176
179 // Unselect col 177 // Unselect col
180 unselect_col(current_col); 178 unselect_col(current_col);
181 if (current_col + 1 < MATRIX_COLS) { 179 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
182 matrix_output_unselect_delay(); // wait for col signal to go HIGH
183 }
184 180
185 return matrix_changed; 181 return matrix_changed;
186} 182}
diff --git a/quantum/matrix.h b/quantum/matrix.h
index ce57010a4..3fe691aae 100644
--- a/quantum/matrix.h
+++ b/quantum/matrix.h
@@ -74,6 +74,11 @@ void matrix_scan_kb(void);
74void matrix_init_user(void); 74void matrix_init_user(void);
75void matrix_scan_user(void); 75void matrix_scan_user(void);
76 76
77#ifdef SPLIT_KEYBOARD
78void matrix_slave_scan_kb(void);
79void matrix_slave_scan_user(void);
80#endif
81
77#ifdef __cplusplus 82#ifdef __cplusplus
78} 83}
79#endif 84#endif
diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk
index f7329fc4d..9268c4522 100644
--- a/quantum/mcu_selection.mk
+++ b/quantum/mcu_selection.mk
@@ -81,6 +81,33 @@ ifneq ($(findstring MK20DX256, $(MCU)),)
81 BOARD ?= PJRC_TEENSY_3_1 81 BOARD ?= PJRC_TEENSY_3_1
82endif 82endif
83 83
84ifneq ($(findstring MK66F18, $(MCU)),)
85 # Cortex version
86 MCU = cortex-m4
87
88 # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
89 ARMV = 7
90
91 ## chip/board settings
92 # - the next two should match the directories in
93 # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
94 MCU_FAMILY = KINETIS
95 MCU_SERIES = MK66F18
96
97 # Linker script to use
98 # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
99 # or <keyboard_dir>/ld/
100 MCU_LDSCRIPT ?= MK66FX1M0
101
102 # Startup code to use
103 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
104 MCU_STARTUP ?= MK66F18
105
106 # Board: it should exist either in <chibios>/os/hal/boards/,
107 # <keyboard_dir>/boards/, or drivers/boards/
108 BOARD ?= PJRC_TEENSY_3_6
109endif
110
84ifneq ($(findstring STM32F042, $(MCU)),) 111ifneq ($(findstring STM32F042, $(MCU)),)
85 # Cortex version 112 # Cortex version
86 MCU = cortex-m0 113 MCU = cortex-m0
@@ -112,6 +139,9 @@ ifneq ($(findstring STM32F042, $(MCU)),)
112 # Options to pass to dfu-util when flashing 139 # Options to pass to dfu-util when flashing
113 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 140 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
114 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 141 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
142
143 # UF2 settings
144 UF2_FAMILY ?= STM32F0
115endif 145endif
116 146
117ifneq ($(findstring STM32F072, $(MCU)),) 147ifneq ($(findstring STM32F072, $(MCU)),)
@@ -145,6 +175,9 @@ ifneq ($(findstring STM32F072, $(MCU)),)
145 # Options to pass to dfu-util when flashing 175 # Options to pass to dfu-util when flashing
146 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 176 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
147 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 177 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
178
179 # UF2 settings
180 UF2_FAMILY ?= STM32F0
148endif 181endif
149 182
150ifneq ($(findstring STM32F103, $(MCU)),) 183ifneq ($(findstring STM32F103, $(MCU)),)
@@ -178,6 +211,9 @@ ifneq ($(findstring STM32F103, $(MCU)),)
178 # Options to pass to dfu-util when flashing 211 # Options to pass to dfu-util when flashing
179 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 212 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
180 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 213 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
214
215 # UF2 settings
216 UF2_FAMILY ?= STM32F1
181endif 217endif
182 218
183ifneq ($(findstring STM32F303, $(MCU)),) 219ifneq ($(findstring STM32F303, $(MCU)),)
@@ -211,6 +247,9 @@ ifneq ($(findstring STM32F303, $(MCU)),)
211 # Options to pass to dfu-util when flashing 247 # Options to pass to dfu-util when flashing
212 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 248 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
213 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 249 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
250
251 # UF2 settings
252 UF2_FAMILY ?= STM32F3
214endif 253endif
215 254
216ifneq ($(findstring STM32F401, $(MCU)),) 255ifneq ($(findstring STM32F401, $(MCU)),)
@@ -244,6 +283,9 @@ ifneq ($(findstring STM32F401, $(MCU)),)
244 # Options to pass to dfu-util when flashing 283 # Options to pass to dfu-util when flashing
245 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 284 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
246 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 285 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
286
287 # UF2 settings
288 UF2_FAMILY ?= STM32F4
247endif 289endif
248 290
249ifneq ($(findstring STM32F411, $(MCU)),) 291ifneq ($(findstring STM32F411, $(MCU)),)
@@ -262,7 +304,12 @@ ifneq ($(findstring STM32F411, $(MCU)),)
262 # Linker script to use 304 # Linker script to use
263 # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ 305 # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
264 # or <keyboard_dir>/ld/ 306 # or <keyboard_dir>/ld/
265 MCU_LDSCRIPT ?= STM32F411xE 307 ifeq ($(strip $(BOOTLOADER)), tinyuf2)
308 MCU_LDSCRIPT ?= STM32F411xE_tinyuf2
309 FIRMWARE_FORMAT ?= uf2
310 else
311 MCU_LDSCRIPT ?= STM32F411xE
312 endif
266 313
267 # Startup code to use 314 # Startup code to use
268 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ 315 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
@@ -277,6 +324,43 @@ ifneq ($(findstring STM32F411, $(MCU)),)
277 # Options to pass to dfu-util when flashing 324 # Options to pass to dfu-util when flashing
278 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 325 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
279 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 326 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
327
328 # UF2 settings
329 UF2_FAMILY ?= STM32F4
330endif
331
332ifneq ($(findstring STM32F446, $(MCU)),)
333 # Cortex version
334 MCU = cortex-m4
335
336 # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
337 ARMV = 7
338
339 ## chip/board settings
340 # - the next two should match the directories in
341 # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
342 MCU_FAMILY = STM32
343 MCU_SERIES = STM32F4xx
344
345 # Linker script to use
346 # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
347 # or <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
348 # or <keyboard_dir>/ld/
349 MCU_LDSCRIPT ?= STM32F446xE
350
351 # Startup code to use
352 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
353 MCU_STARTUP ?= stm32f4xx
354
355 # Board: it should exist either in <chibios>/os/hal/boards/,
356 # <keyboard_dir>/boards/, or drivers/boards/
357 BOARD ?= GENERIC_STM32_F446XE
358
359 USE_FPU ?= yes
360
361 # Options to pass to dfu-util when flashing
362 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
363 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
280endif 364endif
281 365
282ifneq ($(findstring STM32G431, $(MCU)),) 366ifneq ($(findstring STM32G431, $(MCU)),)
@@ -310,6 +394,9 @@ ifneq ($(findstring STM32G431, $(MCU)),)
310 # Options to pass to dfu-util when flashing 394 # Options to pass to dfu-util when flashing
311 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 395 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
312 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 396 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
397
398 # UF2 settings
399 UF2_FAMILY ?= STM32G4
313endif 400endif
314 401
315ifneq ($(findstring STM32G474, $(MCU)),) 402ifneq ($(findstring STM32G474, $(MCU)),)
@@ -343,6 +430,47 @@ ifneq ($(findstring STM32G474, $(MCU)),)
343 # Options to pass to dfu-util when flashing 430 # Options to pass to dfu-util when flashing
344 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 431 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
345 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 432 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
433
434 # UF2 settings
435 UF2_FAMILY ?= STM32G4
436endif
437
438ifneq (,$(filter $(MCU),STM32L433 STM32L443))
439 # Cortex version
440 MCU = cortex-m4
441
442 # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
443 ARMV = 7
444
445 ## chip/board settings
446 # - the next two should match the directories in
447 # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
448 MCU_FAMILY = STM32
449 MCU_SERIES = STM32L4xx
450
451 # Linker script to use
452 # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
453 # or <keyboard_dir>/ld/
454 MCU_LDSCRIPT ?= STM32L432xC
455
456 # Startup code to use
457 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
458 MCU_STARTUP ?= stm32l4xx
459
460 # Board: it should exist either in <chibios>/os/hal/boards/,
461 # <keyboard_dir>/boards/, or drivers/boards/
462 BOARD ?= GENERIC_STM32_L433XC
463
464 PLATFORM_NAME ?= platform_l432
465
466 USE_FPU ?= yes
467
468 # Options to pass to dfu-util when flashing
469 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
470 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
471
472 # UF2 settings
473 UF2_FAMILY ?= STM32L4
346endif 474endif
347 475
348ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287)) 476ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287))
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index bf359e994..51b0efdb4 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -216,7 +216,18 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
216# endif 216# endif
217 } 217 }
218 } 218 }
219 if (get_auto_shifted_key(keycode, record)) {
220 if (record->event.pressed) {
221 return autoshift_press(keycode, now, record);
222 } else {
223 autoshift_end(keycode, now, false);
224 return false;
225 }
226 }
227 return true;
228}
219 229
230__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
220 switch (keycode) { 231 switch (keycode) {
221# ifndef NO_AUTO_SHIFT_ALPHA 232# ifndef NO_AUTO_SHIFT_ALPHA
222 case KC_A ... KC_Z: 233 case KC_A ... KC_Z:
@@ -229,14 +240,9 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
229 case KC_MINUS ... KC_SLASH: 240 case KC_MINUS ... KC_SLASH:
230 case KC_NONUS_BSLASH: 241 case KC_NONUS_BSLASH:
231# endif 242# endif
232 if (record->event.pressed) { 243 return true;
233 return autoshift_press(keycode, now, record);
234 } else {
235 autoshift_end(keycode, now, false);
236 return false;
237 }
238 } 244 }
239 return true; 245 return false;
240} 246}
241 247
242#endif 248#endif
diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
index 5b2718f11..00a9ab036 100644
--- a/quantum/process_keycode/process_auto_shift.h
+++ b/quantum/process_keycode/process_auto_shift.h
@@ -31,3 +31,4 @@ bool get_autoshift_state(void);
31uint16_t get_autoshift_timeout(void); 31uint16_t get_autoshift_timeout(void);
32void set_autoshift_timeout(uint16_t timeout); 32void set_autoshift_timeout(uint16_t timeout);
33void autoshift_matrix_scan(void); 33void autoshift_matrix_scan(void);
34bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_backlight.c b/quantum/process_keycode/process_backlight.c
index 4d12f6813..8b70339a5 100644
--- a/quantum/process_keycode/process_backlight.c
+++ b/quantum/process_keycode/process_backlight.c
@@ -16,11 +16,35 @@
16 16
17#include "process_backlight.h" 17#include "process_backlight.h"
18 18
19#include "backlight.h" 19#ifdef LED_MATRIX_ENABLE
20# include "led_matrix.h"
21#else
22# include "backlight.h"
23#endif
20 24
21bool process_backlight(uint16_t keycode, keyrecord_t *record) { 25bool process_backlight(uint16_t keycode, keyrecord_t *record) {
22 if (record->event.pressed) { 26 if (record->event.pressed) {
23 switch (keycode) { 27 switch (keycode) {
28#ifdef LED_MATRIX_ENABLE
29 case BL_ON:
30 led_matrix_enable();
31 return false;
32 case BL_OFF:
33 led_matrix_disable();
34 return false;
35 case BL_DEC:
36 led_matrix_decrease_val();
37 return false;
38 case BL_INC:
39 led_matrix_increase_val();
40 return false;
41 case BL_TOGG:
42 led_matrix_toggle();
43 return false;
44 case BL_STEP:
45 led_matrix_step();
46 return false;
47#else
24 case BL_ON: 48 case BL_ON:
25 backlight_level(BACKLIGHT_LEVELS); 49 backlight_level(BACKLIGHT_LEVELS);
26 return false; 50 return false;
@@ -39,10 +63,11 @@ bool process_backlight(uint16_t keycode, keyrecord_t *record) {
39 case BL_STEP: 63 case BL_STEP:
40 backlight_step(); 64 backlight_step();
41 return false; 65 return false;
42#ifdef BACKLIGHT_BREATHING 66# ifdef BACKLIGHT_BREATHING
43 case BL_BRTG: 67 case BL_BRTG:
44 backlight_toggle_breathing(); 68 backlight_toggle_breathing();
45 return false; 69 return false;
70# endif
46#endif 71#endif
47 } 72 }
48 } 73 }
diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c
index 58a615d85..cf63f2514 100644
--- a/quantum/process_keycode/process_leader.c
+++ b/quantum/process_keycode/process_leader.c
@@ -49,7 +49,10 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) {
49 // Leader key set-up 49 // Leader key set-up
50 if (record->event.pressed) { 50 if (record->event.pressed) {
51 if (leading) { 51 if (leading) {
52 if (timer_elapsed(leader_time) < LEADER_TIMEOUT) { 52# ifndef LEADER_NO_TIMEOUT
53 if (timer_elapsed(leader_time) < LEADER_TIMEOUT)
54# endif // LEADER_NO_TIMEOUT
55 {
53# ifndef LEADER_KEY_STRICT_KEY_PROCESSING 56# ifndef LEADER_KEY_STRICT_KEY_PROCESSING
54 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { 57 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
55 keycode = keycode & 0xFF; 58 keycode = keycode & 0xFF;
diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h
index 9844f27a1..f3fe14a43 100644
--- a/quantum/process_keycode/process_leader.h
+++ b/quantum/process_keycode/process_leader.h
@@ -35,4 +35,9 @@ void qk_leader_start(void);
35 extern uint16_t leader_time; \ 35 extern uint16_t leader_time; \
36 extern uint16_t leader_sequence[5]; \ 36 extern uint16_t leader_sequence[5]; \
37 extern uint8_t leader_sequence_size 37 extern uint8_t leader_sequence_size
38#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT) 38
39#ifdef LEADER_NO_TIMEOUT
40# define LEADER_DICTIONARY() if (leading && leader_sequence_size > 0 && timer_elapsed(leader_time) > LEADER_TIMEOUT)
41#else
42# define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT)
43#endif
diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c
index 5dd8e7809..167c0c03c 100644
--- a/quantum/process_keycode/process_rgb.c
+++ b/quantum/process_keycode/process_rgb.c
@@ -207,6 +207,11 @@ bool process_rgb(const uint16_t keycode, const keyrecord_t *record) {
207 rgblight_mode(RGBLIGHT_MODE_RGB_TEST); 207 rgblight_mode(RGBLIGHT_MODE_RGB_TEST);
208#endif 208#endif
209 return false; 209 return false;
210 case RGB_MODE_TWINKLE:
211#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_TWINKLE)
212 handleKeycodeRGBMode(RGBLIGHT_MODE_TWINKLE, RGBLIGHT_MODE_TWINKLE_end);
213#endif
214 return false;
210 } 215 }
211 } 216 }
212 217
diff --git a/quantum/quantum.c b/quantum/quantum.c
index b40b40544..8ccdb774b 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include "quantum.h" 17#include "quantum.h"
18#include "magic.h"
18 19
19#ifdef BLUETOOTH_ENABLE 20#ifdef BLUETOOTH_ENABLE
20# include "outputselect.h" 21# include "outputselect.h"
@@ -233,7 +234,7 @@ bool process_record_quantum(keyrecord_t *record) {
233#ifdef AUDIO_ENABLE 234#ifdef AUDIO_ENABLE
234 process_audio(keycode, record) && 235 process_audio(keycode, record) &&
235#endif 236#endif
236#ifdef BACKLIGHT_ENABLE 237#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE)
237 process_backlight(keycode, record) && 238 process_backlight(keycode, record) &&
238#endif 239#endif
239#ifdef STENO_ENABLE 240#ifdef STENO_ENABLE
@@ -318,6 +319,17 @@ bool process_record_quantum(keyrecord_t *record) {
318 set_output(OUTPUT_BLUETOOTH); 319 set_output(OUTPUT_BLUETOOTH);
319 return false; 320 return false;
320#endif 321#endif
322#ifndef NO_ACTION_ONESHOT
323 case ONESHOT_TOGGLE:
324 oneshot_toggle();
325 break;
326 case ONESHOT_ENABLE:
327 oneshot_enable();
328 break;
329 case ONESHOT_DISABLE:
330 oneshot_disable();
331 break;
332#endif
321 } 333 }
322 } 334 }
323 335
@@ -341,26 +353,20 @@ layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_
341void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3)); } 353void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3)); }
342 354
343void matrix_init_quantum() { 355void matrix_init_quantum() {
344#ifdef BOOTMAGIC_LITE 356 magic();
345 bootmagic_lite();
346#endif
347 if (!eeconfig_is_enabled()) {
348 eeconfig_init();
349 }
350#if defined(LED_NUM_LOCK_PIN) || defined(LED_CAPS_LOCK_PIN) || defined(LED_SCROLL_LOCK_PIN) || defined(LED_COMPOSE_PIN) || defined(LED_KANA_PIN) 357#if defined(LED_NUM_LOCK_PIN) || defined(LED_CAPS_LOCK_PIN) || defined(LED_SCROLL_LOCK_PIN) || defined(LED_COMPOSE_PIN) || defined(LED_KANA_PIN)
351 // TODO: remove calls to led_init_ports from keyboards and remove ifdef 358 // TODO: remove calls to led_init_ports from keyboards and remove ifdef
352 led_init_ports(); 359 led_init_ports();
353#endif 360#endif
354#ifdef BACKLIGHT_ENABLE 361#ifdef BACKLIGHT_ENABLE
355# ifdef LED_MATRIX_ENABLE
356 led_matrix_init();
357# else
358 backlight_init_ports(); 362 backlight_init_ports();
359# endif
360#endif 363#endif
361#ifdef AUDIO_ENABLE 364#ifdef AUDIO_ENABLE
362 audio_init(); 365 audio_init();
363#endif 366#endif
367#ifdef LED_MATRIX_ENABLE
368 led_matrix_init();
369#endif
364#ifdef RGB_MATRIX_ENABLE 370#ifdef RGB_MATRIX_ENABLE
365 rgb_matrix_init(); 371 rgb_matrix_init();
366#endif 372#endif
diff --git a/quantum/quantum.h b/quantum/quantum.h
index e24a4c43a..e4a7c5723 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -30,11 +30,11 @@
30#include "keymap.h" 30#include "keymap.h"
31 31
32#ifdef BACKLIGHT_ENABLE 32#ifdef BACKLIGHT_ENABLE
33# ifdef LED_MATRIX_ENABLE 33# include "backlight.h"
34# include "led_matrix.h" 34#endif
35# else 35
36# include "backlight.h" 36#ifdef LED_MATRIX_ENABLE
37# endif 37# include "led_matrix.h"
38#endif 38#endif
39 39
40#if defined(RGBLIGHT_ENABLE) 40#if defined(RGBLIGHT_ENABLE)
@@ -52,6 +52,7 @@
52#include "action_layer.h" 52#include "action_layer.h"
53#include "eeconfig.h" 53#include "eeconfig.h"
54#include "bootloader.h" 54#include "bootloader.h"
55#include "bootmagic.h"
55#include "timer.h" 56#include "timer.h"
56#include "sync_timer.h" 57#include "sync_timer.h"
57#include "config_common.h" 58#include "config_common.h"
@@ -97,7 +98,7 @@ extern layer_state_t layer_state;
97# include "process_music.h" 98# include "process_music.h"
98#endif 99#endif
99 100
100#ifdef BACKLIGHT_ENABLE 101#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE)
101# include "process_backlight.h" 102# include "process_backlight.h"
102#endif 103#endif
103 104
@@ -199,37 +200,8 @@ extern layer_state_t layer_state;
199# include "usbpd.h" 200# include "usbpd.h"
200#endif 201#endif
201 202
202// Function substitutions to ease GPIO manipulation 203#ifdef ENCODER_ENABLE
203#if defined(__AVR__) 204# include "encoder.h"
204
205/* The AVR series GPIOs have a one clock read delay for changes in the digital input signal.
206 * But here's more margin to make it two clocks. */
207# if !defined(GPIO_INPUT_PIN_DELAY)
208# define GPIO_INPUT_PIN_DELAY 2
209# endif
210# define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY)
211
212#elif defined(__ARMEL__) || defined(__ARMEB__)
213
214/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus
215 * to which the GPIO is connected.
216 * The connected buses differ depending on the various series of MCUs.
217 * And since the instruction execution clock of the CPU and the bus clock of GPIO are different,
218 * there is a delay of several clocks to read the change of the input signal.
219 *
220 * Define this delay with the GPIO_INPUT_PIN_DELAY macro.
221 * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used.
222 * (A fairly large value of 0.25 microseconds is set.)
223 */
224# if !defined(GPIO_INPUT_PIN_DELAY)
225# if defined(STM32_SYSCLK)
226# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4)
227# elif defined(KINETIS_SYSCLK_FREQUENCY)
228# define GPIO_INPUT_PIN_DELAY (KINETIS_SYSCLK_FREQUENCY / 1000000L / 4)
229# endif
230# endif
231# define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY)
232
233#endif 205#endif
234 206
235// For tri-layer 207// For tri-layer
@@ -256,15 +228,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record);
256void post_process_record_kb(uint16_t keycode, keyrecord_t *record); 228void post_process_record_kb(uint16_t keycode, keyrecord_t *record);
257void post_process_record_user(uint16_t keycode, keyrecord_t *record); 229void post_process_record_user(uint16_t keycode, keyrecord_t *record);
258 230
259#ifndef BOOTMAGIC_LITE_COLUMN
260# define BOOTMAGIC_LITE_COLUMN 0
261#endif
262#ifndef BOOTMAGIC_LITE_ROW
263# define BOOTMAGIC_LITE_ROW 0
264#endif
265
266void bootmagic_lite(void);
267
268void reset_keyboard(void); 231void reset_keyboard(void);
269 232
270void startup_user(void); 233void startup_user(void);
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index e49f8dcda..316c20fce 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -16,19 +16,7 @@
16 16
17#pragma once 17#pragma once
18 18
19#if defined(SEQUENCER_ENABLE) 19#include "sequencer.h"
20# include "sequencer.h"
21#endif
22
23#ifndef MIDI_ENABLE_STRICT
24# define MIDI_ENABLE_STRICT 0
25#endif
26
27#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED))
28# ifndef MIDI_TONE_KEYCODE_OCTAVES
29# define MIDI_TONE_KEYCODE_OCTAVES 3
30# endif
31#endif
32 20
33// Fillers to make layering more clear 21// Fillers to make layering more clear
34#define _______ KC_TRNS 22#define _______ KC_TRNS
@@ -67,6 +55,8 @@ enum quantum_keycodes {
67 QK_ONE_SHOT_LAYER_MAX = 0x54FF, 55 QK_ONE_SHOT_LAYER_MAX = 0x54FF,
68 QK_ONE_SHOT_MOD = 0x5500, 56 QK_ONE_SHOT_MOD = 0x5500,
69 QK_ONE_SHOT_MOD_MAX = 0x55FF, 57 QK_ONE_SHOT_MOD_MAX = 0x55FF,
58 QK_SWAP_HANDS = 0x5600,
59 QK_SWAP_HANDS_MAX = 0x56FF,
70 QK_TAP_DANCE = 0x5700, 60 QK_TAP_DANCE = 0x5700,
71 QK_TAP_DANCE_MAX = 0x57FF, 61 QK_TAP_DANCE_MAX = 0x57FF,
72 QK_LAYER_TAP_TOGGLE = 0x5800, 62 QK_LAYER_TAP_TOGGLE = 0x5800,
@@ -77,507 +67,458 @@ enum quantum_keycodes {
77 QK_STENO_BOLT = 0x5A30, 67 QK_STENO_BOLT = 0x5A30,
78 QK_STENO_GEMINI = 0x5A31, 68 QK_STENO_GEMINI = 0x5A31,
79 QK_STENO_MAX = 0x5A3F, 69 QK_STENO_MAX = 0x5A3F,
80 QK_SWAP_HANDS = 0x5B00, 70 // 0x5C00 - 0x5FFF are reserved, see below
81 QK_SWAP_HANDS_MAX = 0x5BFF, 71 QK_MOD_TAP = 0x6000,
82 QK_MOD_TAP = 0x6000, 72 QK_MOD_TAP_MAX = 0x7FFF,
83 QK_MOD_TAP_MAX = 0x7FFF, 73 QK_UNICODE = 0x8000,
84 QK_UNICODE = 0x8000, 74 QK_UNICODE_MAX = 0xFFFF,
85 QK_UNICODE_MAX = 0xFFFF, 75 QK_UNICODEMAP = 0x8000,
86 QK_UNICODEMAP = 0x8000, 76 QK_UNICODEMAP_MAX = 0xBFFF,
87 QK_UNICODEMAP_MAX = 0xBFFF, 77 QK_UNICODEMAP_PAIR = 0xC000,
88 QK_UNICODEMAP_PAIR = 0xC000, 78 QK_UNICODEMAP_PAIR_MAX = 0xFFFF,
89 QK_UNICODEMAP_PAIR_MAX = 0xFFFF,
90 79
91 // Loose keycodes - to be used directly 80 // Loose keycodes - to be used directly
92 RESET = 0x5C00, 81 RESET = 0x5C00,
93 DEBUG, 82 DEBUG, // 5C01
94 MAGIC_SWAP_CONTROL_CAPSLOCK, 83
95 MAGIC_CAPSLOCK_TO_CONTROL, 84 // Magic
96 MAGIC_SWAP_LALT_LGUI, 85 MAGIC_SWAP_CONTROL_CAPSLOCK, // 5C02
97 MAGIC_SWAP_RALT_RGUI, 86 MAGIC_CAPSLOCK_TO_CONTROL, // 5C03
98 MAGIC_NO_GUI, 87 MAGIC_SWAP_LALT_LGUI, // 5C04
99 MAGIC_SWAP_GRAVE_ESC, 88 MAGIC_SWAP_RALT_RGUI, // 5C05
100 MAGIC_SWAP_BACKSLASH_BACKSPACE, 89 MAGIC_NO_GUI, // 5C06
101 MAGIC_HOST_NKRO, 90 MAGIC_SWAP_GRAVE_ESC, // 5C07
102 MAGIC_SWAP_ALT_GUI, 91 MAGIC_SWAP_BACKSLASH_BACKSPACE, // 5C08
103 MAGIC_UNSWAP_CONTROL_CAPSLOCK, 92 MAGIC_HOST_NKRO, // 5C09
104 MAGIC_UNCAPSLOCK_TO_CONTROL, 93 MAGIC_SWAP_ALT_GUI, // 5C0A
105 MAGIC_UNSWAP_LALT_LGUI, 94 MAGIC_UNSWAP_CONTROL_CAPSLOCK, // 5C0B
106 MAGIC_UNSWAP_RALT_RGUI, 95 MAGIC_UNCAPSLOCK_TO_CONTROL, // 5C0C
107 MAGIC_UNNO_GUI, 96 MAGIC_UNSWAP_LALT_LGUI, // 5C0D
108 MAGIC_UNSWAP_GRAVE_ESC, 97 MAGIC_UNSWAP_RALT_RGUI, // 5C0E
109 MAGIC_UNSWAP_BACKSLASH_BACKSPACE, 98 MAGIC_UNNO_GUI, // 5C0F
110 MAGIC_UNHOST_NKRO, 99 MAGIC_UNSWAP_GRAVE_ESC, // 5C10
111 MAGIC_UNSWAP_ALT_GUI, 100 MAGIC_UNSWAP_BACKSLASH_BACKSPACE, // 5C11
112 MAGIC_TOGGLE_NKRO, 101 MAGIC_UNHOST_NKRO, // 5C12
113 MAGIC_TOGGLE_ALT_GUI, 102 MAGIC_UNSWAP_ALT_GUI, // 5C13
114 GRAVE_ESC, 103 MAGIC_TOGGLE_NKRO, // 5C14
115 104 MAGIC_TOGGLE_ALT_GUI, // 5C15
116// Leader key 105
117#ifdef LEADER_ENABLE 106 // Grave Escape
118 KC_LEAD, 107 GRAVE_ESC, // 5C16
119#endif 108
120 109 // Auto Shift
121// Auto Shift setup 110 KC_ASUP, // 5C17
122#ifndef AUTO_SHIFT_NO_SETUP 111 KC_ASDN, // 5C18
123 KC_ASUP, 112 KC_ASRP, // 5C19
124 KC_ASDN, 113 KC_ASTG, // 5C1A
125 KC_ASRP, 114 KC_ASON, // 5C1B
126#endif 115 KC_ASOFF, // 5C1C
127 KC_ASTG, 116
128 KC_ASON, 117 // Audio
129 KC_ASOFF, 118 AU_ON, // 5C1D
130 119 AU_OFF, // 5C1E
131 // Audio on/off/toggle 120 AU_TOG, // 5C1F
132 AU_ON, 121
133 AU_OFF, 122 // Audio Clicky
134 AU_TOG, 123 CLICKY_TOGGLE, // 5C20
135 124 CLICKY_ENABLE, // 5C21
136 // Faux clicky as part of main audio feature 125 CLICKY_DISABLE, // 5C22
137 CLICKY_TOGGLE, 126 CLICKY_UP, // 5C23
138 CLICKY_ENABLE, 127 CLICKY_DOWN, // 5C24
139 CLICKY_DISABLE, 128 CLICKY_RESET, // 5C25
140 CLICKY_UP, 129
141 CLICKY_DOWN, 130 // Music mode
142 CLICKY_RESET, 131 MU_ON, // 5C26
143 132 MU_OFF, // 5C27
144 // Music mode on/off/toggle 133 MU_TOG, // 5C28
145 MU_ON, 134 MU_MOD, // 5C29
146 MU_OFF, 135 MUV_IN, // 5C2A
147 MU_TOG, 136 MUV_DE, // 5C2B
148 137
149 // Music mode cycle 138 // MIDI
150 MU_MOD, 139 MI_ON, // 5C2C
151 140 MI_OFF, // 5C2D
152 // Music voice iterate 141 MI_TOG, // 5C2E
153 MUV_IN, 142
154 MUV_DE, 143 MI_C, // 5C2F
155 144 MI_Cs, // 5C30
156// Midi
157#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
158 MI_ON,
159 MI_OFF,
160 MI_TOG,
161#endif
162
163#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED))
164 MIDI_TONE_MIN,
165
166# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 0
167 MI_C = MIDI_TONE_MIN,
168 MI_Cs,
169 MI_Db = MI_Cs, 145 MI_Db = MI_Cs,
170 MI_D, 146 MI_D, // 5C31
171 MI_Ds, 147 MI_Ds, // 5C32
172 MI_Eb = MI_Ds, 148 MI_Eb = MI_Ds,
173 MI_E, 149 MI_E, // 5C33
174 MI_F, 150 MI_F, // 5C34
175 MI_Fs, 151 MI_Fs, // 5C35
176 MI_Gb = MI_Fs, 152 MI_Gb = MI_Fs,
177 MI_G, 153 MI_G, // 5C36
178 MI_Gs, 154 MI_Gs, // 5C37
179 MI_Ab = MI_Gs, 155 MI_Ab = MI_Gs,
180 MI_A, 156 MI_A, // 5C38
181 MI_As, 157 MI_As, // 5C39
182 MI_Bb = MI_As, 158 MI_Bb = MI_As,
183 MI_B, 159 MI_B, // 5C3A
184# endif
185 160
186# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 1 161 MI_C_1, // 5C3B
187 MI_C_1, 162 MI_Cs_1, // 5C3C
188 MI_Cs_1,
189 MI_Db_1 = MI_Cs_1, 163 MI_Db_1 = MI_Cs_1,
190 MI_D_1, 164 MI_D_1, // 5C3D
191 MI_Ds_1, 165 MI_Ds_1, // 5C3E
192 MI_Eb_1 = MI_Ds_1, 166 MI_Eb_1 = MI_Ds_1,
193 MI_E_1, 167 MI_E_1, // 5C3F
194 MI_F_1, 168 MI_F_1, // 5C40
195 MI_Fs_1, 169 MI_Fs_1, // 5C41
196 MI_Gb_1 = MI_Fs_1, 170 MI_Gb_1 = MI_Fs_1,
197 MI_G_1, 171 MI_G_1, // 5C42
198 MI_Gs_1, 172 MI_Gs_1, // 5C43
199 MI_Ab_1 = MI_Gs_1, 173 MI_Ab_1 = MI_Gs_1,
200 MI_A_1, 174 MI_A_1, // 5C44
201 MI_As_1, 175 MI_As_1, // 5C45
202 MI_Bb_1 = MI_As_1, 176 MI_Bb_1 = MI_As_1,
203 MI_B_1, 177 MI_B_1, // 5C46
204# endif
205 178
206# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 2 179 MI_C_2, // 5C47
207 MI_C_2, 180 MI_Cs_2, // 5C48
208 MI_Cs_2,
209 MI_Db_2 = MI_Cs_2, 181 MI_Db_2 = MI_Cs_2,
210 MI_D_2, 182 MI_D_2, // 5C49
211 MI_Ds_2, 183 MI_Ds_2, // 5C4A
212 MI_Eb_2 = MI_Ds_2, 184 MI_Eb_2 = MI_Ds_2,
213 MI_E_2, 185 MI_E_2, // 5C4B
214 MI_F_2, 186 MI_F_2, // 5C4C
215 MI_Fs_2, 187 MI_Fs_2, // 5C4D
216 MI_Gb_2 = MI_Fs_2, 188 MI_Gb_2 = MI_Fs_2,
217 MI_G_2, 189 MI_G_2, // 5C4E
218 MI_Gs_2, 190 MI_Gs_2, // 5C4F
219 MI_Ab_2 = MI_Gs_2, 191 MI_Ab_2 = MI_Gs_2,
220 MI_A_2, 192 MI_A_2, // 5C50
221 MI_As_2, 193 MI_As_2, // 5C51
222 MI_Bb_2 = MI_As_2, 194 MI_Bb_2 = MI_As_2,
223 MI_B_2, 195 MI_B_2, // 5C52
224# endif
225 196
226# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 3 197 MI_C_3, // 5C53
227 MI_C_3, 198 MI_Cs_3, // 5C54
228 MI_Cs_3,
229 MI_Db_3 = MI_Cs_3, 199 MI_Db_3 = MI_Cs_3,
230 MI_D_3, 200 MI_D_3, // 5C55
231 MI_Ds_3, 201 MI_Ds_3, // 5C56
232 MI_Eb_3 = MI_Ds_3, 202 MI_Eb_3 = MI_Ds_3,
233 MI_E_3, 203 MI_E_3, // 5C57
234 MI_F_3, 204 MI_F_3, // 5C58
235 MI_Fs_3, 205 MI_Fs_3, // 5C59
236 MI_Gb_3 = MI_Fs_3, 206 MI_Gb_3 = MI_Fs_3,
237 MI_G_3, 207 MI_G_3, // 5C5A
238 MI_Gs_3, 208 MI_Gs_3, // 5C5B
239 MI_Ab_3 = MI_Gs_3, 209 MI_Ab_3 = MI_Gs_3,
240 MI_A_3, 210 MI_A_3, // 5C5C
241 MI_As_3, 211 MI_As_3, // 5C5D
242 MI_Bb_3 = MI_As_3, 212 MI_Bb_3 = MI_As_3,
243 MI_B_3, 213 MI_B_3, // 5C5E
244# endif
245 214
246# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 4 215 MI_C_4, // 5C5F
247 MI_C_4, 216 MI_Cs_4, // 5C60
248 MI_Cs_4,
249 MI_Db_4 = MI_Cs_4, 217 MI_Db_4 = MI_Cs_4,
250 MI_D_4, 218 MI_D_4, // 5C61
251 MI_Ds_4, 219 MI_Ds_4, // 5C62
252 MI_Eb_4 = MI_Ds_4, 220 MI_Eb_4 = MI_Ds_4,
253 MI_E_4, 221 MI_E_4, // 5C63
254 MI_F_4, 222 MI_F_4, // 5C64
255 MI_Fs_4, 223 MI_Fs_4, // 5C65
256 MI_Gb_4 = MI_Fs_4, 224 MI_Gb_4 = MI_Fs_4,
257 MI_G_4, 225 MI_G_4, // 5C66
258 MI_Gs_4, 226 MI_Gs_4, // 5C67
259 MI_Ab_4 = MI_Gs_4, 227 MI_Ab_4 = MI_Gs_4,
260 MI_A_4, 228 MI_A_4, // 5C68
261 MI_As_4, 229 MI_As_4, // 5C69
262 MI_Bb_4 = MI_As_4, 230 MI_Bb_4 = MI_As_4,
263 MI_B_4, 231 MI_B_4, // 5C6A
264# endif
265 232
266# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5 233 MI_C_5, // 5C6B
267 MI_C_5, 234 MI_Cs_5, // 5C6C
268 MI_Cs_5,
269 MI_Db_5 = MI_Cs_5, 235 MI_Db_5 = MI_Cs_5,
270 MI_D_5, 236 MI_D_5, // 5C6D
271 MI_Ds_5, 237 MI_Ds_5, // 5C6E
272 MI_Eb_5 = MI_Ds_5, 238 MI_Eb_5 = MI_Ds_5,
273 MI_E_5, 239 MI_E_5, // 5C6F
274 MI_F_5, 240 MI_F_5, // 5C70
275 MI_Fs_5, 241 MI_Fs_5, // 5C71
276 MI_Gb_5 = MI_Fs_5, 242 MI_Gb_5 = MI_Fs_5,
277 MI_G_5, 243 MI_G_5, // 5C72
278 MI_Gs_5, 244 MI_Gs_5, // 5C73
279 MI_Ab_5 = MI_Gs_5, 245 MI_Ab_5 = MI_Gs_5,
280 MI_A_5, 246 MI_A_5, // 5C74
281 MI_As_5, 247 MI_As_5, // 5C75
282 MI_Bb_5 = MI_As_5, 248 MI_Bb_5 = MI_As_5,
283 MI_B_5, 249 MI_B_5, // 5C76
284# endif 250
285 251 MI_OCT_N2, // 5C77
286# if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5 252 MI_OCT_N1, // 5C78
287 MIDI_TONE_MAX = MI_B_5, 253 MI_OCT_0, // 5C79
288# elif MIDI_TONE_KEYCODE_OCTAVES > 4 254 MI_OCT_1, // 5C7A
289 MIDI_TONE_MAX = MI_B_4, 255 MI_OCT_2, // 5C7B
290# elif MIDI_TONE_KEYCODE_OCTAVES > 3 256 MI_OCT_3, // 5C7C
291 MIDI_TONE_MAX = MI_B_3, 257 MI_OCT_4, // 5C7D
292# elif MIDI_TONE_KEYCODE_OCTAVES > 2 258 MI_OCT_5, // 5C7E
293 MIDI_TONE_MAX = MI_B_2, 259 MI_OCT_6, // 5C7F
294# elif MIDI_TONE_KEYCODE_OCTAVES > 1 260 MI_OCT_7, // 5C80
295 MIDI_TONE_MAX = MI_B_1, 261 MI_OCTD, // 5C81
296# elif MIDI_TONE_KEYCODE_OCTAVES > 0 262 MI_OCTU, // 5C82
297 MIDI_TONE_MAX = MI_B, 263
298# endif 264 MI_TRNS_N6, // 5C83
299 265 MI_TRNS_N5, // 5C84
300 MIDI_OCTAVE_MIN, 266 MI_TRNS_N4, // 5C85
301 MI_OCT_N2 = MIDI_OCTAVE_MIN, 267 MI_TRNS_N3, // 5C86
302 MI_OCT_N1, 268 MI_TRNS_N2, // 5C87
303 MI_OCT_0, 269 MI_TRNS_N1, // 5C88
304 MI_OCT_1, 270 MI_TRNS_0, // 5C89
305 MI_OCT_2, 271 MI_TRNS_1, // 5C8A
306 MI_OCT_3, 272 MI_TRNS_2, // 5C8B
307 MI_OCT_4, 273 MI_TRNS_3, // 5C8C
308 MI_OCT_5, 274 MI_TRNS_4, // 5C8D
309 MI_OCT_6, 275 MI_TRNS_5, // 5C8E
310 MI_OCT_7, 276 MI_TRNS_6, // 5C8F
311 MIDI_OCTAVE_MAX = MI_OCT_7, 277 MI_TRNSD, // 5C90
312 MI_OCTD, // octave down 278 MI_TRNSU, // 5C91
313 MI_OCTU, // octave up 279
314 280 MI_VEL_0, // 5C92
315 MIDI_TRANSPOSE_MIN, 281#ifdef VIA_ENABLE
316 MI_TRNS_N6 = MIDI_TRANSPOSE_MIN, 282 MI_VEL_1 = MI_VEL_0,
317 MI_TRNS_N5, 283#else
318 MI_TRNS_N4, 284 MI_VEL_1, // 5C93
319 MI_TRNS_N3,
320 MI_TRNS_N2,
321 MI_TRNS_N1,
322 MI_TRNS_0,
323 MI_TRNS_1,
324 MI_TRNS_2,
325 MI_TRNS_3,
326 MI_TRNS_4,
327 MI_TRNS_5,
328 MI_TRNS_6,
329 MIDI_TRANSPOSE_MAX = MI_TRNS_6,
330 MI_TRNSD, // transpose down
331 MI_TRNSU, // transpose up
332
333 MIDI_VELOCITY_MIN,
334 MI_VEL_0 = MIDI_VELOCITY_MIN,
335# ifdef VIA_ENABLE
336 MI_VEL_1 = MIDI_VELOCITY_MIN,
337# else
338 MI_VEL_1,
339# endif
340 MI_VEL_2,
341 MI_VEL_3,
342 MI_VEL_4,
343 MI_VEL_5,
344 MI_VEL_6,
345 MI_VEL_7,
346 MI_VEL_8,
347 MI_VEL_9,
348 MI_VEL_10,
349 MIDI_VELOCITY_MAX = MI_VEL_10,
350 MI_VELD, // velocity down
351 MI_VELU, // velocity up
352
353 MIDI_CHANNEL_MIN,
354 MI_CH1 = MIDI_CHANNEL_MIN,
355 MI_CH2,
356 MI_CH3,
357 MI_CH4,
358 MI_CH5,
359 MI_CH6,
360 MI_CH7,
361 MI_CH8,
362 MI_CH9,
363 MI_CH10,
364 MI_CH11,
365 MI_CH12,
366 MI_CH13,
367 MI_CH14,
368 MI_CH15,
369 MI_CH16,
370 MIDI_CHANNEL_MAX = MI_CH16,
371 MI_CHD, // previous channel
372 MI_CHU, // next channel
373
374 MI_ALLOFF, // all notes off
375
376 MI_SUS, // sustain
377 MI_PORT, // portamento
378 MI_SOST, // sostenuto
379 MI_SOFT, // soft pedal
380 MI_LEG, // legato
381
382 MI_MOD, // modulation
383 MI_MODSD, // decrease modulation speed
384 MI_MODSU, // increase modulation speed
385
386 MI_BENDD, // Bend down
387 MI_BENDU, // Bend up
388#endif // MIDI_ADVANCED
389
390 // Backlight functionality
391 BL_ON,
392 BL_OFF,
393 BL_DEC,
394 BL_INC,
395 BL_TOGG,
396 BL_STEP,
397 BL_BRTG,
398
399 // RGB functionality
400 RGB_TOG,
401 RGB_MODE_FORWARD,
402 RGB_MODE_REVERSE,
403 RGB_HUI,
404 RGB_HUD,
405 RGB_SAI,
406 RGB_SAD,
407 RGB_VAI,
408 RGB_VAD,
409 RGB_SPI,
410 RGB_SPD,
411 RGB_MODE_PLAIN,
412 RGB_MODE_BREATHE,
413 RGB_MODE_RAINBOW,
414 RGB_MODE_SWIRL,
415 RGB_MODE_SNAKE,
416 RGB_MODE_KNIGHT,
417 RGB_MODE_XMAS,
418 RGB_MODE_GRADIENT,
419 RGB_MODE_RGBTEST,
420
421 // Momentum matching toggle
422 VLK_TOG,
423
424 // Left shift, open paren
425 KC_LSPO,
426
427 // Right shift, close paren
428 KC_RSPC,
429
430 // Shift, Enter
431 KC_SFTENT,
432
433 // Printing
434 PRINT_ON,
435 PRINT_OFF,
436
437 // output selection
438 OUT_AUTO,
439 OUT_USB,
440#ifdef BLUETOOTH_ENABLE
441 OUT_BT,
442#endif
443
444#ifdef KEY_LOCK_ENABLE
445 KC_LOCK,
446#endif 285#endif
447 286 MI_VEL_2, // 5C94
448#ifdef TERMINAL_ENABLE 287 MI_VEL_3, // 5C95
449 TERM_ON, 288 MI_VEL_4, // 5C96
450 TERM_OFF, 289 MI_VEL_5, // 5C97
451#endif 290 MI_VEL_6, // 5C98
452 291 MI_VEL_7, // 5C99
453 EEPROM_RESET, 292 MI_VEL_8, // 5C9A
454 293 MI_VEL_9, // 5C9B
455 UNICODE_MODE_FORWARD, 294 MI_VEL_10, // 5C9C
456 UNICODE_MODE_REVERSE, 295 MI_VELD, // 5C9D
457 UNICODE_MODE_MAC, 296 MI_VELU, // 5C9E
458 UNICODE_MODE_LNX, 297
459 UNICODE_MODE_WIN, 298 MI_CH1, // 5C9F
460 UNICODE_MODE_BSD, 299 MI_CH2, // 5CA0
461 UNICODE_MODE_WINC, 300 MI_CH3, // 5CA1
462 301 MI_CH4, // 5CA2
463 HPT_ON, 302 MI_CH5, // 5CA3
464 HPT_OFF, 303 MI_CH6, // 5CA4
465 HPT_TOG, 304 MI_CH7, // 5CA5
466 HPT_RST, 305 MI_CH8, // 5CA6
467 HPT_FBK, 306 MI_CH9, // 5CA7
468 HPT_BUZ, 307 MI_CH10, // 5CA8
469 HPT_MODI, 308 MI_CH11, // 5CA9
470 HPT_MODD, 309 MI_CH12, // 5CAA
471 HPT_CONT, 310 MI_CH13, // 5CAB
472 HPT_CONI, 311 MI_CH14, // 5CAC
473 HPT_COND, 312 MI_CH15, // 5CAD
474 HPT_DWLI, 313 MI_CH16, // 5CAE
475 HPT_DWLD, 314 MI_CHD, // 5CAF
476 315 MI_CHU, // 5CB0
477 // Left control, open paren 316
478 KC_LCPO, 317 MI_ALLOFF, // 5CB1
479 318
480 // Right control, close paren 319 MI_SUS, // 5CB2
481 KC_RCPC, 320 MI_PORT, // 5CB3
482 321 MI_SOST, // 5CB4
483 // Left control, open paren 322 MI_SOFT, // 5CB5
484 KC_LAPO, 323 MI_LEG, // 5CB6
485 324
486 // Right control, close paren 325 MI_MOD, // 5CB7
487 KC_RAPC, 326 MI_MODSD, // 5CB8
488 327 MI_MODSU, // 5CB9
489 CMB_ON, 328
490 CMB_OFF, 329 MI_BENDD, // 5CBA
491 CMB_TOG, 330 MI_BENDU, // 5CBB
492 331
493 MAGIC_SWAP_LCTL_LGUI, 332 // Backlight
494 MAGIC_SWAP_RCTL_RGUI, 333 BL_ON, // 5CBC
495 MAGIC_UNSWAP_LCTL_LGUI, 334 BL_OFF, // 5CBD
496 MAGIC_UNSWAP_RCTL_RGUI, 335 BL_DEC, // 5CBE
497 MAGIC_SWAP_CTL_GUI, 336 BL_INC, // 5CBF
498 MAGIC_UNSWAP_CTL_GUI, 337 BL_TOGG, // 5CC0
499 MAGIC_TOGGLE_CTL_GUI, 338 BL_STEP, // 5CC1
500 MAGIC_EE_HANDS_LEFT, 339 BL_BRTG, // 5CC2
501 MAGIC_EE_HANDS_RIGHT, 340
341 // RGB underglow/matrix
342 RGB_TOG, // 5CC3
343 RGB_MODE_FORWARD, // 5CC4
344 RGB_MODE_REVERSE, // 5CC5
345 RGB_HUI, // 5CC6
346 RGB_HUD, // 5CC7
347 RGB_SAI, // 5CC8
348 RGB_SAD, // 5CC9
349 RGB_VAI, // 5CCA
350 RGB_VAD, // 5CCB
351 RGB_SPI, // 5CCC
352 RGB_SPD, // 5CCD
353 RGB_MODE_PLAIN, // 5CCE
354 RGB_MODE_BREATHE, // 5CCF
355 RGB_MODE_RAINBOW, // 5CD0
356 RGB_MODE_SWIRL, // 5CD1
357 RGB_MODE_SNAKE, // 5CD2
358 RGB_MODE_KNIGHT, // 5CD3
359 RGB_MODE_XMAS, // 5CD4
360 RGB_MODE_GRADIENT, // 5CD5
361 RGB_MODE_RGBTEST, // 5CD6
362
363 // Velocikey
364 VLK_TOG, // 5CD7
365
366 // Space Cadet
367 KC_LSPO, // 5CD8
368 KC_RSPC, // 5CD9
369 KC_SFTENT, // 5CDA
370
371 // Thermal Printer
372 PRINT_ON, // 5CDB
373 PRINT_OFF, // 5CDC
374
375 // Bluetooth: output selection
376 OUT_AUTO, // 5CDD
377 OUT_USB, // 5CDE
378
379 // Clear EEPROM
380 EEPROM_RESET, // 5CDF
381
382 // Unicode
383 UNICODE_MODE_FORWARD, // 5CE0
384 UNICODE_MODE_REVERSE, // 5CE1
385 UNICODE_MODE_MAC, // 5CE2
386 UNICODE_MODE_LNX, // 5CE3
387 UNICODE_MODE_WIN, // 5CE4
388 UNICODE_MODE_BSD, // 5CE5
389 UNICODE_MODE_WINC, // 5CE6
390
391 // Haptic
392 HPT_ON, // 5CE7
393 HPT_OFF, // 5CE8
394 HPT_TOG, // 5CE9
395 HPT_RST, // 5CEA
396 HPT_FBK, // 5CEB
397 HPT_BUZ, // 5CEC
398 HPT_MODI, // 5CED
399 HPT_MODD, // 5CEE
400 HPT_CONT, // 5CEF
401 HPT_CONI, // 5CF0
402 HPT_COND, // 5CF1
403 HPT_DWLI, // 5CF2
404 HPT_DWLD, // 5CF3
405
406 // Space Cadet (continued)
407 KC_LCPO, // 5CF4
408 KC_RCPC, // 5CF5
409 KC_LAPO, // 5CF6
410 KC_RAPC, // 5CF7
411
412 // Combos
413 CMB_ON, // 5CF8
414 CMB_OFF, // 5CF9
415 CMB_TOG, // 5CFA
416
417 // Magic (continued)
418 MAGIC_SWAP_LCTL_LGUI, // 5CFB
419 MAGIC_SWAP_RCTL_RGUI, // 5CFC
420 MAGIC_UNSWAP_LCTL_LGUI, // 5CFD
421 MAGIC_UNSWAP_RCTL_RGUI, // 5CFE
422 MAGIC_SWAP_CTL_GUI, // 5CFF
423 MAGIC_UNSWAP_CTL_GUI, // 5D00
424 MAGIC_TOGGLE_CTL_GUI, // 5D01
425 MAGIC_EE_HANDS_LEFT, // 5D02
426 MAGIC_EE_HANDS_RIGHT, // 5D03
502 427
503 // Dynamic Macros 428 // Dynamic Macros
504 DYN_REC_START1, 429 DYN_REC_START1, // 5D04
505 DYN_REC_START2, 430 DYN_REC_START2, // 5D05
506 DYN_REC_STOP, 431 DYN_REC_STOP, // 5D06
507 DYN_MACRO_PLAY1, 432 DYN_MACRO_PLAY1, // 5D07
508 DYN_MACRO_PLAY2, 433 DYN_MACRO_PLAY2, // 5D08
509 434
510 JS_BUTTON0, 435 // Joystick
511 JS_BUTTON_MIN = JS_BUTTON0, 436 JS_BUTTON0, // 5D09
512 JS_BUTTON1, 437 JS_BUTTON1, // 5D0A
513 JS_BUTTON2, 438 JS_BUTTON2, // 5D0B
514 JS_BUTTON3, 439 JS_BUTTON3, // 5D0C
515 JS_BUTTON4, 440 JS_BUTTON4, // 5D0D
516 JS_BUTTON5, 441 JS_BUTTON5, // 5D0E
517 JS_BUTTON6, 442 JS_BUTTON6, // 5D0F
518 JS_BUTTON7, 443 JS_BUTTON7, // 5D10
519 JS_BUTTON8, 444 JS_BUTTON8, // 5D11
520 JS_BUTTON9, 445 JS_BUTTON9, // 5D12
521 JS_BUTTON10, 446 JS_BUTTON10, // 5D13
522 JS_BUTTON11, 447 JS_BUTTON11, // 5D14
523 JS_BUTTON12, 448 JS_BUTTON12, // 5D15
524 JS_BUTTON13, 449 JS_BUTTON13, // 5D16
525 JS_BUTTON14, 450 JS_BUTTON14, // 5D17
526 JS_BUTTON15, 451 JS_BUTTON15, // 5D18
527 JS_BUTTON16, 452 JS_BUTTON16, // 5D19
528 JS_BUTTON17, 453 JS_BUTTON17, // 5D1A
529 JS_BUTTON18, 454 JS_BUTTON18, // 5D1B
530 JS_BUTTON19, 455 JS_BUTTON19, // 5D1C
531 JS_BUTTON20, 456 JS_BUTTON20, // 5D1D
532 JS_BUTTON21, 457 JS_BUTTON21, // 5D1E
533 JS_BUTTON22, 458 JS_BUTTON22, // 5D1F
534 JS_BUTTON23, 459 JS_BUTTON23, // 5D20
535 JS_BUTTON24, 460 JS_BUTTON24, // 5D21
536 JS_BUTTON25, 461 JS_BUTTON25, // 5D22
537 JS_BUTTON26, 462 JS_BUTTON26, // 5D23
538 JS_BUTTON27, 463 JS_BUTTON27, // 5D24
539 JS_BUTTON28, 464 JS_BUTTON28, // 5D25
540 JS_BUTTON29, 465 JS_BUTTON29, // 5D26
541 JS_BUTTON30, 466 JS_BUTTON30, // 5D27
542 JS_BUTTON31, 467 JS_BUTTON31, // 5D28
543 JS_BUTTON_MAX = JS_BUTTON31, 468
544 469 // Leader Key
545#if defined(SEQUENCER_ENABLE) 470 KC_LEAD, // 5D29
546 SQ_ON, 471
547 SQ_OFF, 472 // Bluetooth: output selection (continued)
548 SQ_TOG, 473 OUT_BT, // 5D2A
549 474
550 SQ_TMPD, // Decrease tempo 475 // Lock Key
551 SQ_TMPU, // Increase tempo 476 KC_LOCK, // 5D2B
477
478 // Terminal
479 TERM_ON, // 5D2C
480 TERM_OFF, // 5D2D
481
482 // Sequencer
483 SQ_ON, // 5D2E
484 SQ_OFF, // 5D2F
485 SQ_TOG, // 5D30
486
487 SQ_TMPD, // 5D31
488 SQ_TMPU, // 5D32
489
490 SQ_RESD, // 5D33
491 SQ_RESU, // 5D34
492
493 SQ_SALL, // 5D35
494 SQ_SCLR, // 5D36
495
496 SEQUENCER_STEP_MIN, // 5D37
497 SEQUENCER_STEP_MAX = SEQUENCER_STEP_MIN + SEQUENCER_STEPS,
552 498
553 SEQUENCER_RESOLUTION_MIN, 499 SEQUENCER_RESOLUTION_MIN,
554 SEQUENCER_RESOLUTION_MAX = SEQUENCER_RESOLUTION_MIN + SEQUENCER_RESOLUTIONS, 500 SEQUENCER_RESOLUTION_MAX = SEQUENCER_RESOLUTION_MIN + SEQUENCER_RESOLUTIONS,
555 SQ_RESD, // Decrease resolution
556 SQ_RESU, // Increase resolution
557
558 SQ_SALL, // All steps on
559 SQ_SCLR, // All steps off
560 SEQUENCER_STEP_MIN,
561 SEQUENCER_STEP_MAX = SEQUENCER_STEP_MIN + SEQUENCER_STEPS,
562 501
563 SEQUENCER_TRACK_MIN, 502 SEQUENCER_TRACK_MIN,
564 SEQUENCER_TRACK_MAX = SEQUENCER_TRACK_MIN + SEQUENCER_TRACKS, 503 SEQUENCER_TRACK_MAX = SEQUENCER_TRACK_MIN + SEQUENCER_TRACKS,
565 504
566/** 505#define SQ_S(n) (n < SEQUENCER_STEPS ? SEQUENCER_STEP_MIN + n : KC_NO)
567 * Helpers to assign a keycode to a step, a resolution, or a track. 506#define SQ_R(n) (n < SEQUENCER_RESOLUTIONS ? SEQUENCER_RESOLUTION_MIN + n : KC_NO)
568 * Falls back to NOOP if n is out of range. 507#define SQ_T(n) (n < SEQUENCER_TRACKS ? SEQUENCER_TRACK_MIN + n : KC_NO)
569 */
570# define SQ_S(n) (n < SEQUENCER_STEPS ? SEQUENCER_STEP_MIN + n : XXXXXXX)
571# define SQ_R(n) (n < SEQUENCER_RESOLUTIONS ? SEQUENCER_RESOLUTION_MIN + n : XXXXXXX)
572# define SQ_T(n) (n < SEQUENCER_TRACKS ? SEQUENCER_TRACK_MIN + n : XXXXXXX)
573 508
574#endif 509 // One Shot
510 ONESHOT_ENABLE,
511 ONESHOT_DISABLE,
512 ONESHOT_TOGGLE,
513
514 // RGB underglow/matrix (continued)
515 RGB_MODE_TWINKLE,
575 516
576 // always leave at the end 517 // Start of custom keycode range for keyboards and keymaps - always leave at the end
577 SAFE_RANGE 518 SAFE_RANGE
578}; 519};
579 520
580// Ability to use mods in layouts 521// Keycode modifiers & aliases
581#define LCTL(kc) (QK_LCTL | (kc)) 522#define LCTL(kc) (QK_LCTL | (kc))
582#define LSFT(kc) (QK_LSFT | (kc)) 523#define LSFT(kc) (QK_LSFT | (kc))
583#define LALT(kc) (QK_LALT | (kc)) 524#define LALT(kc) (QK_LALT | (kc))
@@ -609,11 +550,7 @@ enum quantum_keycodes {
609#define MOD_HYPR 0xF 550#define MOD_HYPR 0xF
610#define MOD_MEH 0x7 551#define MOD_MEH 0x7
611 552
612// Aliases for shifted symbols 553// US ANSI shifted keycode aliases
613// Each key has a 4-letter code, and some have longer aliases too.
614// While the long aliases are descriptive, the 4-letter codes
615// make for nicer grid layouts (everything lines up), and are
616// the preferred style for Quantum.
617#define KC_TILD LSFT(KC_GRV) // ~ 554#define KC_TILD LSFT(KC_GRV) // ~
618#define KC_TILDE KC_TILD 555#define KC_TILDE KC_TILD
619 556
@@ -680,18 +617,15 @@ enum quantum_keycodes {
680 617
681#define KC_DELT KC_DELETE // Del key (four letter code) 618#define KC_DELT KC_DELETE // Del key (four letter code)
682 619
683// Alias for function layers than expand past FN31 620// Modified keycode aliases
684#define FUNC(kc) (QK_FUNCTION | (kc))
685
686// Aliases
687#define C(kc) LCTL(kc) 621#define C(kc) LCTL(kc)
688#define S(kc) LSFT(kc) 622#define S(kc) LSFT(kc)
689#define A(kc) LALT(kc) 623#define A(kc) LALT(kc)
690#define G(kc) LGUI(kc) 624#define G(kc) LGUI(kc)
691 625
692#define F(kc) FUNC(kc) 626// Deprecated - do not use
627#define F(kc) (QK_FUNCTION | (kc))
693#define M(kc) (QK_MACRO | (kc)) 628#define M(kc) (QK_MACRO | (kc))
694
695#define MACROTAP(kc) (QK_MACRO | (FUNC_TAP << 8) | (kc)) 629#define MACROTAP(kc) (QK_MACRO | (FUNC_TAP << 8) | (kc))
696#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE) 630#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
697 631
@@ -699,19 +633,21 @@ enum quantum_keycodes {
699 633
700#define EEP_RST EEPROM_RESET 634#define EEP_RST EEPROM_RESET
701 635
636// Audio Clicky aliases
702#define CK_TOGG CLICKY_TOGGLE 637#define CK_TOGG CLICKY_TOGGLE
703#define CK_RST CLICKY_RESET 638#define CK_RST CLICKY_RESET
704#define CK_UP CLICKY_UP 639#define CK_UP CLICKY_UP
705#define CK_DOWN CLICKY_DOWN 640#define CK_DOWN CLICKY_DOWN
706#define CK_ON CLICKY_ENABLE 641#define CK_ON CLICKY_ENABLE
707#define CK_OFF CLICKY_DISABLE 642#define CK_OFF CLICKY_DISABLE
643// Fauxclicky (deprecated) redirects to Audio Clicky
708#define FC_ON CLICKY_ENABLE 644#define FC_ON CLICKY_ENABLE
709#define FC_OFF CLICKY_DISABLE 645#define FC_OFF CLICKY_DISABLE
710#define FC_TOGG CLICKY_TOGGLE 646#define FC_TOGG CLICKY_TOGGLE
711 647
648// RGB aliases
712#define RGB_MOD RGB_MODE_FORWARD 649#define RGB_MOD RGB_MODE_FORWARD
713#define RGB_RMOD RGB_MODE_REVERSE 650#define RGB_RMOD RGB_MODE_REVERSE
714
715#define RGB_M_P RGB_MODE_PLAIN 651#define RGB_M_P RGB_MODE_PLAIN
716#define RGB_M_B RGB_MODE_BREATHE 652#define RGB_M_B RGB_MODE_BREATHE
717#define RGB_M_R RGB_MODE_RAINBOW 653#define RGB_M_R RGB_MODE_RAINBOW
@@ -721,10 +657,9 @@ enum quantum_keycodes {
721#define RGB_M_X RGB_MODE_XMAS 657#define RGB_M_X RGB_MODE_XMAS
722#define RGB_M_G RGB_MODE_GRADIENT 658#define RGB_M_G RGB_MODE_GRADIENT
723#define RGB_M_T RGB_MODE_RGBTEST 659#define RGB_M_T RGB_MODE_RGBTEST
660#define RGB_M_TW RGB_MODE_TWINKLE
724 661
725// L-ayer, T-ap - 256 keycode max, 16 layer max 662// Magic aliases
726#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF))
727
728#define CL_SWAP MAGIC_SWAP_CONTROL_CAPSLOCK 663#define CL_SWAP MAGIC_SWAP_CONTROL_CAPSLOCK
729#define CL_NORM MAGIC_UNSWAP_CONTROL_CAPSLOCK 664#define CL_NORM MAGIC_UNSWAP_CONTROL_CAPSLOCK
730#define CL_CTRL MAGIC_CAPSLOCK_TO_CONTROL 665#define CL_CTRL MAGIC_CAPSLOCK_TO_CONTROL
@@ -793,6 +728,9 @@ enum quantum_keycodes {
793// Layer tap-toggle 728// Layer tap-toggle
794#define TT(layer) (QK_LAYER_TAP_TOGGLE | ((layer)&0xFF)) 729#define TT(layer) (QK_LAYER_TAP_TOGGLE | ((layer)&0xFF))
795 730
731// L-ayer, T-ap - 256 keycode max, 16 layer max
732#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF))
733
796// M-od, T-ap - 256 keycode max 734// M-od, T-ap - 256 keycode max
797#define MT(mod, kc) (QK_MOD_TAP | (((mod)&0x1F) << 8) | ((kc)&0xFF)) 735#define MT(mod, kc) (QK_MOD_TAP | (((mod)&0x1F) << 8) | ((kc)&0xFF))
798 736
@@ -822,12 +760,12 @@ enum quantum_keycodes {
822#define CMD_T(kc) LCMD_T(kc) 760#define CMD_T(kc) LCMD_T(kc)
823#define WIN_T(kc) LWIN_T(kc) 761#define WIN_T(kc) LWIN_T(kc)
824 762
825#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal 763#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal
826#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt 764#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
827#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI 765#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI
828#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI 766#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI
829#define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/ 767#define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
830#define SGUI_T(kc) MT(MOD_LGUI | MOD_LSFT, kc) // Left Shift + GUI 768#define SGUI_T(kc) MT(MOD_LGUI | MOD_LSFT, kc) // Left Shift + GUI
831#define SCMD_T(kc) SGUI_T(kc) 769#define SCMD_T(kc) SGUI_T(kc)
832#define SWIN_T(kc) SGUI_T(kc) 770#define SWIN_T(kc) SGUI_T(kc)
833#define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc) // Left Control + Alt 771#define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc) // Left Control + Alt
@@ -842,6 +780,7 @@ enum quantum_keycodes {
842#define KC_HYPR HYPR(KC_NO) 780#define KC_HYPR HYPR(KC_NO)
843#define KC_MEH MEH(KC_NO) 781#define KC_MEH MEH(KC_NO)
844 782
783// Unicode aliases
845// UNICODE_ENABLE - Allows Unicode input up to 0x7FFF 784// UNICODE_ENABLE - Allows Unicode input up to 0x7FFF
846#define UC(c) (QK_UNICODE | (c)) 785#define UC(c) (QK_UNICODE | (c))
847// UNICODEMAP_ENABLE - Allows Unicode input up to 0x10FFFF, requires unicode_map 786// UNICODEMAP_ENABLE - Allows Unicode input up to 0x10FFFF, requires unicode_map
@@ -853,12 +792,13 @@ enum quantum_keycodes {
853 792
854#define UC_M_MA UNICODE_MODE_MAC 793#define UC_M_MA UNICODE_MODE_MAC
855#define UNICODE_MODE_OSX UNICODE_MODE_MAC // Deprecated alias 794#define UNICODE_MODE_OSX UNICODE_MODE_MAC // Deprecated alias
856#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias 795#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias
857#define UC_M_LN UNICODE_MODE_LNX 796#define UC_M_LN UNICODE_MODE_LNX
858#define UC_M_WI UNICODE_MODE_WIN 797#define UC_M_WI UNICODE_MODE_WIN
859#define UC_M_BS UNICODE_MODE_BSD 798#define UC_M_BS UNICODE_MODE_BSD
860#define UC_M_WC UNICODE_MODE_WINC 799#define UC_M_WC UNICODE_MODE_WINC
861 800
801// Swap Hands
862#define SH_T(kc) (QK_SWAP_HANDS | (kc)) 802#define SH_T(kc) (QK_SWAP_HANDS | (kc))
863#define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE) 803#define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE)
864#define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE) 804#define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE)
@@ -868,9 +808,30 @@ enum quantum_keycodes {
868#define SH_ON (QK_SWAP_HANDS | OP_SH_ON) 808#define SH_ON (QK_SWAP_HANDS | OP_SH_ON)
869#define SH_OFF (QK_SWAP_HANDS | OP_SH_OFF) 809#define SH_OFF (QK_SWAP_HANDS | OP_SH_OFF)
870 810
811// MIDI aliases
812#define MIDI_TONE_MIN MI_C
813#define MIDI_TONE_MAX MI_B_5
814#define MIDI_OCTAVE_MIN MI_OCT_N2
815#define MIDI_OCTAVE_MAX MI_OCT_7
816#define MIDI_TRANSPOSE_MIN MI_TRNS_N6
817#define MIDI_TRANSPOSE_MAX MI_TRNS_6
818#define MIDI_VELOCITY_MIN MI_VEL_0
819#define MIDI_VELOCITY_MAX MI_VEL_10
820#define MIDI_CHANNEL_MIN MI_CH1
821#define MIDI_CHANNEL_MAX MI_CH16
822
871// Dynamic Macros aliases 823// Dynamic Macros aliases
872#define DM_REC1 DYN_REC_START1 824#define DM_REC1 DYN_REC_START1
873#define DM_REC2 DYN_REC_START2 825#define DM_REC2 DYN_REC_START2
874#define DM_RSTP DYN_REC_STOP 826#define DM_RSTP DYN_REC_STOP
875#define DM_PLY1 DYN_MACRO_PLAY1 827#define DM_PLY1 DYN_MACRO_PLAY1
876#define DM_PLY2 DYN_MACRO_PLAY2 828#define DM_PLY2 DYN_MACRO_PLAY2
829
830// Joystick aliases
831#define JS_BUTTON_MIN JS_BUTTON0
832#define JS_BUTTON_MAX JS_BUTTON31
833
834// One Shot aliases
835#define OS_TOGG ONESHOT_TOGGLE
836#define OS_ON ONESHOT_ENABLE
837#define OS_OFF ONESHOT_DISABLE
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c
index ec17b4d72..e716c6aad 100644
--- a/quantum/rgb_matrix.c
+++ b/quantum/rgb_matrix.c
@@ -26,9 +26,9 @@
26#include <lib/lib8tion/lib8tion.h> 26#include <lib/lib8tion/lib8tion.h>
27 27
28#ifndef RGB_MATRIX_CENTER 28#ifndef RGB_MATRIX_CENTER
29const point_t k_rgb_matrix_center = {112, 32}; 29const led_point_t k_rgb_matrix_center = {112, 32};
30#else 30#else
31const point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; 31const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER;
32#endif 32#endif
33 33
34__attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } 34__attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); }
@@ -67,8 +67,8 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv
67# define RGB_DISABLE_TIMEOUT 0 67# define RGB_DISABLE_TIMEOUT 0
68#endif 68#endif
69 69
70#ifndef RGB_DISABLE_WHEN_USB_SUSPENDED 70#if RGB_DISABLE_WHEN_USB_SUSPENDED == false
71# define RGB_DISABLE_WHEN_USB_SUSPENDED false 71# undef RGB_DISABLE_WHEN_USB_SUSPENDED
72#endif 72#endif
73 73
74#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX 74#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
@@ -118,7 +118,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv
118#endif 118#endif
119 119
120// globals 120// globals
121bool g_suspend_state = false;
122rgb_config_t rgb_matrix_config; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr 121rgb_config_t rgb_matrix_config; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr
123uint32_t g_rgb_timer; 122uint32_t g_rgb_timer;
124#ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS 123#ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS
@@ -129,9 +128,10 @@ last_hit_t g_last_hit_tracker;
129#endif // RGB_MATRIX_KEYREACTIVE_ENABLED 128#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
130 129
131// internals 130// internals
131static bool suspend_state = false;
132static uint8_t rgb_last_enable = UINT8_MAX; 132static uint8_t rgb_last_enable = UINT8_MAX;
133static uint8_t rgb_last_effect = UINT8_MAX; 133static uint8_t rgb_last_effect = UINT8_MAX;
134static effect_params_t rgb_effect_params = {0, 0xFF}; 134static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false};
135static rgb_task_states rgb_task_state = SYNCING; 135static rgb_task_states rgb_task_state = SYNCING;
136#if RGB_DISABLE_TIMEOUT > 0 136#if RGB_DISABLE_TIMEOUT > 0
137static uint32_t rgb_anykey_timer; 137static uint32_t rgb_anykey_timer;
@@ -143,6 +143,11 @@ static uint32_t rgb_timer_buffer;
143static last_hit_t last_hit_buffer; 143static last_hit_t last_hit_buffer;
144#endif // RGB_MATRIX_KEYREACTIVE_ENABLED 144#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
145 145
146// split rgb matrix
147#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
148const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
149#endif
150
146void eeconfig_read_rgb_matrix(void) { eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } 151void eeconfig_read_rgb_matrix(void) { eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); }
147 152
148void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } 153void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); }
@@ -153,6 +158,7 @@ void eeconfig_update_rgb_matrix_default(void) {
153 rgb_matrix_config.mode = RGB_MATRIX_STARTUP_MODE; 158 rgb_matrix_config.mode = RGB_MATRIX_STARTUP_MODE;
154 rgb_matrix_config.hsv = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL}; 159 rgb_matrix_config.hsv = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL};
155 rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD; 160 rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD;
161 rgb_matrix_config.flags = LED_FLAG_ALL;
156 eeconfig_update_rgb_matrix(); 162 eeconfig_update_rgb_matrix();
157} 163}
158 164
@@ -164,6 +170,7 @@ void eeconfig_debug_rgb_matrix(void) {
164 dprintf("rgb_matrix_config.hsv.s = %d\n", rgb_matrix_config.hsv.s); 170 dprintf("rgb_matrix_config.hsv.s = %d\n", rgb_matrix_config.hsv.s);
165 dprintf("rgb_matrix_config.hsv.v = %d\n", rgb_matrix_config.hsv.v); 171 dprintf("rgb_matrix_config.hsv.v = %d\n", rgb_matrix_config.hsv.v);
166 dprintf("rgb_matrix_config.speed = %d\n", rgb_matrix_config.speed); 172 dprintf("rgb_matrix_config.speed = %d\n", rgb_matrix_config.speed);
173 dprintf("rgb_matrix_config.flags = %d\n", rgb_matrix_config.flags);
167} 174}
168 175
169__attribute__((weak)) uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; } 176__attribute__((weak)) uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; }
@@ -180,9 +187,22 @@ uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l
180 187
181void rgb_matrix_update_pwm_buffers(void) { rgb_matrix_driver.flush(); } 188void rgb_matrix_update_pwm_buffers(void) { rgb_matrix_driver.flush(); }
182 189
183void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color(index, red, green, blue); } 190void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
191#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
192 if (!is_keyboard_left() && index >= k_rgb_matrix_split[0])
193 rgb_matrix_driver.set_color(index - k_rgb_matrix_split[0], red, green, blue);
194 else if (is_keyboard_left() && index < k_rgb_matrix_split[0])
195#endif
196 rgb_matrix_driver.set_color(index, red, green, blue);
197}
184 198
185void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color_all(red, green, blue); } 199void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
200#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
201 for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) rgb_matrix_set_color(i, red, green, blue);
202#else
203 rgb_matrix_driver.set_color_all(red, green, blue);
204#endif
205}
186 206
187void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) { 207void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) {
188#ifndef RGB_MATRIX_SPLIT 208#ifndef RGB_MATRIX_SPLIT
@@ -315,6 +335,10 @@ static void rgb_task_start(void) {
315static void rgb_task_render(uint8_t effect) { 335static void rgb_task_render(uint8_t effect) {
316 bool rendering = false; 336 bool rendering = false;
317 rgb_effect_params.init = (effect != rgb_last_effect) || (rgb_matrix_config.enable != rgb_last_enable); 337 rgb_effect_params.init = (effect != rgb_last_effect) || (rgb_matrix_config.enable != rgb_last_enable);
338 if (rgb_effect_params.flags != rgb_matrix_config.flags) {
339 rgb_effect_params.flags = rgb_matrix_config.flags;
340 rgb_matrix_set_color_all(0, 0, 0);
341 }
318 342
319 // each effect can opt to do calculations 343 // each effect can opt to do calculations
320 // and/or request PWM buffer updates. 344 // and/or request PWM buffer updates.
@@ -385,14 +409,11 @@ void rgb_matrix_task(void) {
385 409
386 // Ideally we would also stop sending zeros to the LED driver PWM buffers 410 // Ideally we would also stop sending zeros to the LED driver PWM buffers
387 // while suspended and just do a software shutdown. This is a cheap hack for now. 411 // while suspended and just do a software shutdown. This is a cheap hack for now.
388 bool suspend_backlight = 412 bool suspend_backlight = suspend_state ||
389#if RGB_DISABLE_WHEN_USB_SUSPENDED == true
390 g_suspend_state ||
391#endif // RGB_DISABLE_WHEN_USB_SUSPENDED == true
392#if RGB_DISABLE_TIMEOUT > 0 413#if RGB_DISABLE_TIMEOUT > 0
393 (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) || 414 (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) ||
394#endif // RGB_DISABLE_TIMEOUT > 0 415#endif // RGB_DISABLE_TIMEOUT > 0
395 false; 416 false;
396 417
397 uint8_t effect = suspend_backlight || !rgb_matrix_config.enable ? 0 : rgb_matrix_config.mode; 418 uint8_t effect = suspend_backlight || !rgb_matrix_config.enable ? 0 : rgb_matrix_config.mode;
398 419
@@ -477,13 +498,15 @@ void rgb_matrix_init(void) {
477} 498}
478 499
479void rgb_matrix_set_suspend_state(bool state) { 500void rgb_matrix_set_suspend_state(bool state) {
480 if (RGB_DISABLE_WHEN_USB_SUSPENDED && state) { 501#ifdef RGB_DISABLE_WHEN_USB_SUSPENDED
502 if (state) {
481 rgb_matrix_set_color_all(0, 0, 0); // turn off all LEDs when suspending 503 rgb_matrix_set_color_all(0, 0, 0); // turn off all LEDs when suspending
482 } 504 }
483 g_suspend_state = state; 505 suspend_state = state;
506#endif
484} 507}
485 508
486bool rgb_matrix_get_suspend_state(void) { return g_suspend_state; } 509bool rgb_matrix_get_suspend_state(void) { return suspend_state; }
487 510
488void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { 511void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
489 rgb_matrix_config.enable ^= 1; 512 rgb_matrix_config.enable ^= 1;
@@ -618,6 +641,6 @@ void rgb_matrix_decrease_speed_helper(bool write_to_eeprom) { rgb_matrix_set_spe
618void rgb_matrix_decrease_speed_noeeprom(void) { rgb_matrix_decrease_speed_helper(false); } 641void rgb_matrix_decrease_speed_noeeprom(void) { rgb_matrix_decrease_speed_helper(false); }
619void rgb_matrix_decrease_speed(void) { rgb_matrix_decrease_speed_helper(true); } 642void rgb_matrix_decrease_speed(void) { rgb_matrix_decrease_speed_helper(true); }
620 643
621led_flags_t rgb_matrix_get_flags(void) { return rgb_effect_params.flags; } 644led_flags_t rgb_matrix_get_flags(void) { return rgb_matrix_config.flags; }
622 645
623void rgb_matrix_set_flags(led_flags_t flags) { rgb_effect_params.flags = flags; } 646void rgb_matrix_set_flags(led_flags_t flags) { rgb_matrix_config.flags = flags; }
diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h
index bb8bcfab6..a615b8422 100644
--- a/quantum/rgb_matrix.h
+++ b/quantum/rgb_matrix.h
@@ -216,7 +216,6 @@ extern const rgb_matrix_driver_t rgb_matrix_driver;
216 216
217extern rgb_config_t rgb_matrix_config; 217extern rgb_config_t rgb_matrix_config;
218 218
219extern bool g_suspend_state;
220extern uint32_t g_rgb_timer; 219extern uint32_t g_rgb_timer;
221extern led_config_t g_led_config; 220extern led_config_t g_led_config;
222#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED 221#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix_drivers.c
index 2978e7bed..896fa6d0e 100644
--- a/quantum/rgb_matrix_drivers.c
+++ b/quantum/rgb_matrix_drivers.c
@@ -41,7 +41,28 @@ static void init(void) {
41 IS31FL3731_init(DRIVER_ADDR_4); 41 IS31FL3731_init(DRIVER_ADDR_4);
42# endif 42# endif
43# elif defined(IS31FL3733) 43# elif defined(IS31FL3733)
44 IS31FL3733_init(DRIVER_ADDR_1, 0); 44# ifndef DRIVER_SYNC_1
45# define DRIVER_SYNC_1 0
46# endif
47 IS31FL3733_init(DRIVER_ADDR_1, DRIVER_SYNC_1);
48# if defined DRIVER_ADDR_2 && (DRIVER_ADDR_1 != DRIVER_ADDR_2)
49# ifndef DRIVER_SYNC_2
50# define DRIVER_SYNC_2 0
51# endif
52 IS31FL3733_init(DRIVER_ADDR_2, DRIVER_SYNC_2);
53# endif
54# ifdef DRIVER_ADDR_3
55# ifndef DRIVER_SYNC_3
56# define DRIVER_SYNC_3 0
57# endif
58 IS31FL3733_init(DRIVER_ADDR_3, DRIVER_SYNC_3);
59# endif
60# ifdef DRIVER_ADDR_4
61# ifndef DRIVER_SYNC_4
62# define DRIVER_SYNC_4 0
63# endif
64 IS31FL3733_init(DRIVER_ADDR_4, DRIVER_SYNC_4);
65# endif
45# elif defined(IS31FL3737) 66# elif defined(IS31FL3737)
46 IS31FL3737_init(DRIVER_ADDR_1); 67 IS31FL3737_init(DRIVER_ADDR_1);
47# else 68# else
@@ -74,7 +95,15 @@ static void init(void) {
74# endif 95# endif
75# elif defined(IS31FL3733) 96# elif defined(IS31FL3733)
76 IS31FL3733_update_led_control_registers(DRIVER_ADDR_1, 0); 97 IS31FL3733_update_led_control_registers(DRIVER_ADDR_1, 0);
98# ifdef DRIVER_ADDR_2
77 IS31FL3733_update_led_control_registers(DRIVER_ADDR_2, 1); 99 IS31FL3733_update_led_control_registers(DRIVER_ADDR_2, 1);
100# endif
101# ifdef DRIVER_ADDR_3
102 IS31FL3733_update_led_control_registers(DRIVER_ADDR_3, 2);
103# endif
104# ifdef DRIVER_ADDR_4
105 IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3);
106# endif
78# elif defined(IS31FL3737) 107# elif defined(IS31FL3737)
79 IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, DRIVER_ADDR_2); 108 IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, DRIVER_ADDR_2);
80# else 109# else
@@ -105,7 +134,15 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
105# elif defined(IS31FL3733) 134# elif defined(IS31FL3733)
106static void flush(void) { 135static void flush(void) {
107 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1, 0); 136 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1, 0);
137# ifdef DRIVER_ADDR_2
108 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2, 1); 138 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2, 1);
139# endif
140# ifdef DRIVER_ADDR_3
141 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_3, 2);
142# endif
143# ifdef DRIVER_ADDR_4
144 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_4, 3);
145# endif
109} 146}
110 147
111const rgb_matrix_driver_t rgb_matrix_driver = { 148const rgb_matrix_driver_t rgb_matrix_driver = {
diff --git a/quantum/rgb_matrix_types.h b/quantum/rgb_matrix_types.h
index 7b8171fb2..df575d657 100644
--- a/quantum/rgb_matrix_types.h
+++ b/quantum/rgb_matrix_types.h
@@ -62,7 +62,7 @@ typedef struct PACKED {
62typedef struct PACKED { 62typedef struct PACKED {
63 uint8_t x; 63 uint8_t x;
64 uint8_t y; 64 uint8_t y;
65} point_t; 65} led_point_t;
66 66
67#define HAS_FLAGS(bits, flags) ((bits & flags) == flags) 67#define HAS_FLAGS(bits, flags) ((bits & flags) == flags)
68#define HAS_ANY_FLAGS(bits, flags) ((bits & flags) != 0x00) 68#define HAS_ANY_FLAGS(bits, flags) ((bits & flags) != 0x00)
@@ -77,18 +77,19 @@ typedef struct PACKED {
77#define NO_LED 255 77#define NO_LED 255
78 78
79typedef struct PACKED { 79typedef struct PACKED {
80 uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS]; 80 uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS];
81 point_t point[DRIVER_LED_TOTAL]; 81 led_point_t point[DRIVER_LED_TOTAL];
82 uint8_t flags[DRIVER_LED_TOTAL]; 82 uint8_t flags[DRIVER_LED_TOTAL];
83} led_config_t; 83} led_config_t;
84 84
85typedef union { 85typedef union {
86 uint32_t raw; 86 uint32_t raw;
87 struct PACKED { 87 struct PACKED {
88 uint8_t enable : 2; 88 uint8_t enable : 2;
89 uint8_t mode : 6; 89 uint8_t mode : 6;
90 HSV hsv; 90 HSV hsv;
91 uint8_t speed; // EECONFIG needs to be increased to support this 91 uint8_t speed; // EECONFIG needs to be increased to support this
92 led_flags_t flags;
92 }; 93 };
93} rgb_config_t; 94} rgb_config_t;
94 95
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index 119d3eab2..baa10ec41 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -722,23 +722,39 @@ static void rgblight_layers_write(void) {
722} 722}
723 723
724# ifdef RGBLIGHT_LAYER_BLINK 724# ifdef RGBLIGHT_LAYER_BLINK
725rgblight_layer_mask_t _blinked_layer_mask = 0; 725rgblight_layer_mask_t _blinking_layer_mask = 0;
726static uint16_t _blink_timer; 726static uint16_t _repeat_timer;
727static uint8_t _times_remaining;
728static uint16_t _dur;
729
730void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { rgblight_blink_layer_repeat(layer, duration_ms, 1); }
731
732void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times) {
733 _times_remaining = times * 2;
734 _dur = duration_ms;
727 735
728void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {
729 rgblight_set_layer_state(layer, true); 736 rgblight_set_layer_state(layer, true);
730 _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; 737 _times_remaining--;
731 _blink_timer = sync_timer_read() + duration_ms; 738 _blinking_layer_mask |= (rgblight_layer_mask_t)1 << layer;
739 _repeat_timer = sync_timer_read() + duration_ms;
732} 740}
733 741
734void rgblight_unblink_layers(void) { 742void rgblight_blink_layer_repeat_helper(void) {
735 if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) { 743 if (_blinking_layer_mask != 0 && timer_expired(sync_timer_read(), _repeat_timer)) {
736 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { 744 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
737 if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { 745 if ((_blinking_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0 && _times_remaining > 0) {
738 rgblight_set_layer_state(layer, false); 746 if (_times_remaining % 2 == 1) {
747 rgblight_set_layer_state(layer, false);
748 } else {
749 rgblight_set_layer_state(layer, true);
750 }
751 _times_remaining--;
752 _repeat_timer = sync_timer_read() + _dur;
739 } 753 }
740 } 754 }
741 _blinked_layer_mask = 0; 755 if (_times_remaining <= 0) {
756 _blinking_layer_mask = 0;
757 }
742 } 758 }
743} 759}
744# endif 760# endif
@@ -755,8 +771,8 @@ void rgblight_suspend(void) {
755 771
756# ifdef RGBLIGHT_LAYER_BLINK 772# ifdef RGBLIGHT_LAYER_BLINK
757 // make sure any layer blinks don't come back after suspend 773 // make sure any layer blinks don't come back after suspend
758 rgblight_status.enabled_layer_mask &= ~_blinked_layer_mask; 774 rgblight_status.enabled_layer_mask &= ~_blinking_layer_mask;
759 _blinked_layer_mask = 0; 775 _blinking_layer_mask = 0;
760# endif 776# endif
761 777
762 rgblight_disable_noeeprom(); 778 rgblight_disable_noeeprom();
@@ -874,7 +890,7 @@ void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
874 animation_status.restart = true; 890 animation_status.restart = true;
875 } 891 }
876# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ 892# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */
877# endif /* RGBLIGHT_USE_TIMER */ 893# endif /* RGBLIGHT_USE_TIMER */
878} 894}
879#endif /* RGBLIGHT_SPLIT */ 895#endif /* RGBLIGHT_SPLIT */
880 896
@@ -1030,7 +1046,7 @@ void rgblight_task(void) {
1030 } 1046 }
1031 1047
1032# ifdef RGBLIGHT_LAYER_BLINK 1048# ifdef RGBLIGHT_LAYER_BLINK
1033 rgblight_unblink_layers(); 1049 rgblight_blink_layer_repeat_helper();
1034# endif 1050# endif
1035} 1051}
1036 1052
diff --git a/quantum/rgblight.h b/quantum/rgblight.h
index 6fb3ab938..bec2c6695 100644
--- a/quantum/rgblight.h
+++ b/quantum/rgblight.h
@@ -222,6 +222,7 @@ extern const rgblight_segment_t *const *rgblight_layers;
222# ifdef RGBLIGHT_LAYER_BLINK 222# ifdef RGBLIGHT_LAYER_BLINK
223# define RGBLIGHT_USE_TIMER 223# define RGBLIGHT_USE_TIMER
224void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms); 224void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms);
225void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times);
225# endif 226# endif
226 227
227# endif 228# endif
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index d6636b886..039e7d977 100644
--- a/quantum/split_common/matrix.c
+++ b/quantum/split_common/matrix.c
@@ -43,6 +43,7 @@ extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
43uint8_t thisHand, thatHand; 43uint8_t thisHand, thatHand;
44 44
45// user-defined overridable functions 45// user-defined overridable functions
46__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
46__attribute__((weak)) void matrix_slave_scan_user(void) {} 47__attribute__((weak)) void matrix_slave_scan_user(void) {}
47 48
48static inline void setPinOutput_writeLow(pin_t pin) { 49static inline void setPinOutput_writeLow(pin_t pin) {
@@ -129,9 +130,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
129 130
130 // Unselect row 131 // Unselect row
131 unselect_row(current_row); 132 unselect_row(current_row);
132 if (current_row + 1 < MATRIX_ROWS) { 133 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH
133 matrix_output_unselect_delay(); // wait for row signal to go HIGH
134 }
135 134
136 // If the row has changed, store the row and return the changed flag. 135 // If the row has changed, store the row and return the changed flag.
137 if (current_matrix[current_row] != current_row_value) { 136 if (current_matrix[current_row] != current_row_value) {
@@ -191,9 +190,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
191 190
192 // Unselect col 191 // Unselect col
193 unselect_col(current_col); 192 unselect_col(current_col);
194 if (current_col + 1 < MATRIX_COLS) { 193 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
195 matrix_output_unselect_delay(); // wait for col signal to go HIGH
196 }
197 194
198 return matrix_changed; 195 return matrix_changed;
199} 196}
@@ -284,7 +281,7 @@ bool matrix_post_scan(void) {
284 } else { 281 } else {
285 transport_slave(matrix + thatHand, matrix + thisHand); 282 transport_slave(matrix + thatHand, matrix + thisHand);
286 283
287 matrix_slave_scan_user(); 284 matrix_slave_scan_kb();
288 } 285 }
289 286
290 return changed; 287 return changed;
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 2ae44e6e1..9e75e19ce 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -1,3 +1,18 @@
1/* Copyright 2021 QMK
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
1#include "split_util.h" 16#include "split_util.h"
2#include "matrix.h" 17#include "matrix.h"
3#include "keyboard.h" 18#include "keyboard.h"
@@ -6,14 +21,7 @@
6#include "transport.h" 21#include "transport.h"
7#include "quantum.h" 22#include "quantum.h"
8#include "wait.h" 23#include "wait.h"
9 24#include "usb_util.h"
10#ifdef PROTOCOL_LUFA
11# include <LUFA/Drivers/USB/USB.h>
12#endif
13
14#ifdef PROTOCOL_VUSB
15# include <usbdrv/usbdrv.h>
16#endif
17 25
18#ifdef EE_HANDS 26#ifdef EE_HANDS
19# include "eeconfig.h" 27# include "eeconfig.h"
@@ -31,56 +39,21 @@
31# define SPLIT_USB_TIMEOUT_POLL 10 39# define SPLIT_USB_TIMEOUT_POLL 10
32#endif 40#endif
33 41
34#ifdef PROTOCOL_CHIBIOS
35# define SPLIT_USB_DETECT // Force this on for now
36#endif
37
38volatile bool isLeftHand = true; 42volatile bool isLeftHand = true;
39 43
40#if defined(SPLIT_USB_DETECT) 44#if defined(SPLIT_USB_DETECT)
41# if defined(PROTOCOL_LUFA) 45static bool usbIsActive(void) {
42static inline bool usbHasActiveConnection(void) { return USB_Device_IsAddressSet(); }
43static inline void usbDisable(void) {
44 USB_Disable();
45 USB_DeviceState = DEVICE_STATE_Unattached;
46}
47# elif defined(PROTOCOL_CHIBIOS)
48static inline bool usbHasActiveConnection(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; }
49static inline void usbDisable(void) { usbStop(&USBD1); }
50# elif defined(PROTOCOL_VUSB)
51static inline bool usbHasActiveConnection(void) {
52 usbPoll();
53 return usbConfiguration;
54}
55static inline void usbDisable(void) { usbDeviceDisconnect(); }
56# else
57static inline bool usbHasActiveConnection(void) { return true; }
58static inline void usbDisable(void) {}
59# endif
60
61bool usbIsActive(void) {
62 for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) { 46 for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {
63 // This will return true if a USB connection has been established 47 // This will return true if a USB connection has been established
64 if (usbHasActiveConnection()) { 48 if (usb_connected_state()) {
65 return true; 49 return true;
66 } 50 }
67 wait_ms(SPLIT_USB_TIMEOUT_POLL); 51 wait_ms(SPLIT_USB_TIMEOUT_POLL);
68 } 52 }
69
70 // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
71 usbDisable();
72
73 return false; 53 return false;
74} 54}
75#elif defined(PROTOCOL_LUFA) && defined(OTGPADE)
76static inline bool usbIsActive(void) {
77 USB_OTGPAD_On(); // enables VBUS pad
78 wait_us(5);
79
80 return USB_VBUS_GetStatus(); // checks state of VBUS
81}
82#else 55#else
83static inline bool usbIsActive(void) { return true; } 56static inline bool usbIsActive(void) { return usb_vbus_state(); }
84#endif 57#endif
85 58
86#ifdef SPLIT_HAND_MATRIX_GRID 59#ifdef SPLIT_HAND_MATRIX_GRID
@@ -126,6 +99,11 @@ __attribute__((weak)) bool is_keyboard_master(void) {
126 // only check once, as this is called often 99 // only check once, as this is called often
127 if (usbstate == UNKNOWN) { 100 if (usbstate == UNKNOWN) {
128 usbstate = usbIsActive() ? MASTER : SLAVE; 101 usbstate = usbIsActive() ? MASTER : SLAVE;
102
103 // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow
104 if (usbstate == SLAVE) {
105 usb_disable();
106 }
129 } 107 }
130 108
131 return (usbstate == MASTER); 109 return (usbstate == MASTER);
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
index 61b61ea08..9ed0f7591 100644
--- a/quantum/split_common/transport.c
+++ b/quantum/split_common/transport.c
@@ -22,6 +22,13 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A;
22# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) 22# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t))
23#endif 23#endif
24 24
25#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
26# include "led_matrix.h"
27#endif
28#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
29# include "rgb_matrix.h"
30#endif
31
25#if defined(USE_I2C) 32#if defined(USE_I2C)
26 33
27# include "i2c_master.h" 34# include "i2c_master.h"
@@ -54,6 +61,14 @@ typedef struct _I2C_slave_buffer_t {
54# ifdef WPM_ENABLE 61# ifdef WPM_ENABLE
55 uint8_t current_wpm; 62 uint8_t current_wpm;
56# endif 63# endif
64# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
65 led_eeconfig_t led_matrix;
66 bool led_suspend_state;
67# endif
68# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
69 rgb_config_t rgb_matrix;
70 bool rgb_suspend_state;
71# endif
57} I2C_slave_buffer_t; 72} I2C_slave_buffer_t;
58 73
59static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; 74static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg;
@@ -68,6 +83,10 @@ static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_re
68# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) 83# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)
69# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) 84# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)
70# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) 85# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm)
86# define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix)
87# define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state)
88# define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix)
89# define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state)
71 90
72# define TIMEOUT 100 91# define TIMEOUT 100
73 92
@@ -141,6 +160,17 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])
141# endif 160# endif
142# endif 161# endif
143 162
163# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
164 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT);
165 bool suspend_state = led_matrix_get_suspend_state();
166 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT);
167# endif
168# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
169 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT);
170 bool suspend_state = rgb_matrix_get_suspend_state();
171 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT);
172# endif
173
144# ifndef DISABLE_SYNC_TIMER 174# ifndef DISABLE_SYNC_TIMER
145 i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; 175 i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
146 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); 176 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT);
@@ -186,6 +216,15 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])
186 set_oneshot_mods(i2c_buffer->oneshot_mods); 216 set_oneshot_mods(i2c_buffer->oneshot_mods);
187# endif 217# endif
188# endif 218# endif
219
220# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
221 memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix));
222 led_matrix_set_suspend_state(i2c_buffer->led_suspend_state);
223# endif
224# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
225 memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix));
226 rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state);
227# endif
189} 228}
190 229
191void transport_master_init(void) { i2c_init(); } 230void transport_master_init(void) { i2c_init(); }
@@ -201,30 +240,38 @@ typedef struct _Serial_s2m_buffer_t {
201 matrix_row_t smatrix[ROWS_PER_HAND]; 240 matrix_row_t smatrix[ROWS_PER_HAND];
202 241
203# ifdef ENCODER_ENABLE 242# ifdef ENCODER_ENABLE
204 uint8_t encoder_state[NUMBER_OF_ENCODERS]; 243 uint8_t encoder_state[NUMBER_OF_ENCODERS];
205# endif 244# endif
206 245
207} Serial_s2m_buffer_t; 246} Serial_s2m_buffer_t;
208 247
209typedef struct _Serial_m2s_buffer_t { 248typedef struct _Serial_m2s_buffer_t {
210# ifdef SPLIT_MODS_ENABLE 249# ifdef SPLIT_MODS_ENABLE
211 uint8_t real_mods; 250 uint8_t real_mods;
212 uint8_t weak_mods; 251 uint8_t weak_mods;
213# ifndef NO_ACTION_ONESHOT 252# ifndef NO_ACTION_ONESHOT
214 uint8_t oneshot_mods; 253 uint8_t oneshot_mods;
215# endif 254# endif
216# endif 255# endif
217# ifndef DISABLE_SYNC_TIMER 256# ifndef DISABLE_SYNC_TIMER
218 uint32_t sync_timer; 257 uint32_t sync_timer;
219# endif 258# endif
220# ifdef SPLIT_TRANSPORT_MIRROR 259# ifdef SPLIT_TRANSPORT_MIRROR
221 matrix_row_t mmatrix[ROWS_PER_HAND]; 260 matrix_row_t mmatrix[ROWS_PER_HAND];
222# endif 261# endif
223# ifdef BACKLIGHT_ENABLE 262# ifdef BACKLIGHT_ENABLE
224 uint8_t backlight_level; 263 uint8_t backlight_level;
225# endif 264# endif
226# ifdef WPM_ENABLE 265# ifdef WPM_ENABLE
227 uint8_t current_wpm; 266 uint8_t current_wpm;
267# endif
268# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
269 led_eeconfig_t led_matrix;
270 bool led_suspend_state;
271# endif
272# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
273 rgb_config_t rgb_matrix;
274 bool rgb_suspend_state;
228# endif 275# endif
229} Serial_m2s_buffer_t; 276} Serial_m2s_buffer_t;
230 277
@@ -316,7 +363,7 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])
316 363
317 // TODO: if MATRIX_COLS > 8 change to unpack() 364 // TODO: if MATRIX_COLS > 8 change to unpack()
318 for (int i = 0; i < ROWS_PER_HAND; ++i) { 365 for (int i = 0; i < ROWS_PER_HAND; ++i) {
319 slave_matrix[i] = serial_s2m_buffer.smatrix[i]; 366 slave_matrix[i] = serial_s2m_buffer.smatrix[i];
320# ifdef SPLIT_TRANSPORT_MIRROR 367# ifdef SPLIT_TRANSPORT_MIRROR
321 serial_m2s_buffer.mmatrix[i] = master_matrix[i]; 368 serial_m2s_buffer.mmatrix[i] = master_matrix[i];
322# endif 369# endif
@@ -333,18 +380,28 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])
333 380
334# ifdef WPM_ENABLE 381# ifdef WPM_ENABLE
335 // Write wpm to slave 382 // Write wpm to slave
336 serial_m2s_buffer.current_wpm = get_current_wpm(); 383 serial_m2s_buffer.current_wpm = get_current_wpm();
337# endif 384# endif
338 385
339# ifdef SPLIT_MODS_ENABLE 386# ifdef SPLIT_MODS_ENABLE
340 serial_m2s_buffer.real_mods = get_mods(); 387 serial_m2s_buffer.real_mods = get_mods();
341 serial_m2s_buffer.weak_mods = get_weak_mods(); 388 serial_m2s_buffer.weak_mods = get_weak_mods();
342# ifndef NO_ACTION_ONESHOT 389# ifndef NO_ACTION_ONESHOT
343 serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); 390 serial_m2s_buffer.oneshot_mods = get_oneshot_mods();
344# endif 391# endif
345# endif 392# endif
393
394# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
395 serial_m2s_buffer.led_matrix = led_matrix_eeconfig;
396 serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state();
397# endif
398# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
399 serial_m2s_buffer.rgb_matrix = rgb_matrix_config;
400 serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state();
401# endif
402
346# ifndef DISABLE_SYNC_TIMER 403# ifndef DISABLE_SYNC_TIMER
347 serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; 404 serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
348# endif 405# endif
349 return true; 406 return true;
350} 407}
@@ -359,7 +416,7 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])
359 for (int i = 0; i < ROWS_PER_HAND; ++i) { 416 for (int i = 0; i < ROWS_PER_HAND; ++i) {
360 serial_s2m_buffer.smatrix[i] = slave_matrix[i]; 417 serial_s2m_buffer.smatrix[i] = slave_matrix[i];
361# ifdef SPLIT_TRANSPORT_MIRROR 418# ifdef SPLIT_TRANSPORT_MIRROR
362 master_matrix[i] = serial_m2s_buffer.mmatrix[i]; 419 master_matrix[i] = serial_m2s_buffer.mmatrix[i];
363# endif 420# endif
364 } 421 }
365# ifdef BACKLIGHT_ENABLE 422# ifdef BACKLIGHT_ENABLE
@@ -381,6 +438,15 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])
381 set_oneshot_mods(serial_m2s_buffer.oneshot_mods); 438 set_oneshot_mods(serial_m2s_buffer.oneshot_mods);
382# endif 439# endif
383# endif 440# endif
441
442# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
443 led_matrix_eeconfig = serial_m2s_buffer.led_matrix;
444 led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state);
445# endif
446# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
447 rgb_matrix_config = serial_m2s_buffer.rgb_matrix;
448 rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state);
449# endif
384} 450}
385 451
386#endif 452#endif
diff --git a/quantum/wpm.c b/quantum/wpm.c
index da30bd252..bec419a48 100644
--- a/quantum/wpm.c
+++ b/quantum/wpm.c
@@ -19,11 +19,10 @@
19 19
20// WPM Stuff 20// WPM Stuff
21static uint8_t current_wpm = 0; 21static uint8_t current_wpm = 0;
22static uint8_t latest_wpm = 0;
23static uint16_t wpm_timer = 0; 22static uint16_t wpm_timer = 0;
24 23
25// This smoothing is 40 keystrokes 24// This smoothing is 40 keystrokes
26static const float wpm_smoothing = 0.0487; 25static const float wpm_smoothing = WPM_SMOOTHING;
27 26
28void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; } 27void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; }
29 28
@@ -46,19 +45,46 @@ __attribute__((weak)) bool wpm_keycode_user(uint16_t keycode) {
46 return false; 45 return false;
47} 46}
48 47
48#ifdef WPM_ALLOW_COUNT_REGRESSION
49__attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) {
50 bool weak_modded = (keycode >= QK_LCTL && keycode < QK_LSFT) || (keycode >= QK_RCTL && keycode < QK_RSFT);
51
52 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)) {
53 keycode = keycode & 0xFF;
54 } else if (keycode > 0xFF) {
55 keycode = 0;
56 }
57 if (keycode == KC_DEL || keycode == KC_BSPC) {
58 if (((get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) || weak_modded) {
59 return WPM_ESTIMATED_WORD_SIZE;
60 } else {
61 return 1;
62 }
63 } else {
64 return 0;
65 }
66}
67#endif
68
49void update_wpm(uint16_t keycode) { 69void update_wpm(uint16_t keycode) {
50 if (wpm_keycode(keycode)) { 70 if (wpm_keycode(keycode)) {
51 if (wpm_timer > 0) { 71 if (wpm_timer > 0) {
52 latest_wpm = 60000 / timer_elapsed(wpm_timer) / 5; 72 current_wpm += ((60000 / timer_elapsed(wpm_timer) / WPM_ESTIMATED_WORD_SIZE) - current_wpm) * wpm_smoothing;
53 current_wpm = (latest_wpm - current_wpm) * wpm_smoothing + current_wpm;
54 } 73 }
55 wpm_timer = timer_read(); 74 wpm_timer = timer_read();
56 } 75 }
76#ifdef WPM_ALLOW_COUNT_REGRESSION
77 uint8_t regress = wpm_regress_count(keycode);
78 if (regress) {
79 current_wpm -= regress;
80 wpm_timer = timer_read();
81 }
82#endif
57} 83}
58 84
59void decay_wpm(void) { 85void decay_wpm(void) {
60 if (timer_elapsed(wpm_timer) > 1000) { 86 if (timer_elapsed(wpm_timer) > 1000) {
61 current_wpm = (0 - current_wpm) * wpm_smoothing + current_wpm; 87 current_wpm += (-current_wpm) * wpm_smoothing;
62 wpm_timer = timer_read(); 88 wpm_timer = timer_read();
63 } 89 }
64} 90}
diff --git a/quantum/wpm.h b/quantum/wpm.h
index 15ab4ffcd..4af52d2b9 100644
--- a/quantum/wpm.h
+++ b/quantum/wpm.h
@@ -19,10 +19,21 @@
19 19
20#include "quantum.h" 20#include "quantum.h"
21 21
22#ifndef WPM_ESTIMATED_WORD_SIZE
23# define WPM_ESTIMATED_WORD_SIZE 5
24#endif
25#ifndef WPM_SMOOTHING
26# define WPM_SMOOTHING 0.0487
27#endif
28
22bool wpm_keycode(uint16_t keycode); 29bool wpm_keycode(uint16_t keycode);
23bool wpm_keycode_kb(uint16_t keycode); 30bool wpm_keycode_kb(uint16_t keycode);
24bool wpm_keycode_user(uint16_t keycode); 31bool wpm_keycode_user(uint16_t keycode);
25 32
33#ifdef WPM_ALLOW_COUNT_REGRESSION
34uint8_t wpm_regress_count(uint16_t keycode);
35#endif
36
26void set_current_wpm(uint8_t); 37void set_current_wpm(uint8_t);
27uint8_t get_current_wpm(void); 38uint8_t get_current_wpm(void);
28void update_wpm(uint16_t); 39void update_wpm(uint16_t);