aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/color.h54
-rw-r--r--quantum/command.c2
-rw-r--r--quantum/crc.c59
-rw-r--r--quantum/crc.h (renamed from quantum/rgb.h)45
-rw-r--r--quantum/debounce.h2
-rw-r--r--quantum/debounce/asym_eager_defer_pk.c171
-rw-r--r--quantum/debounce/none.c31
-rw-r--r--quantum/debounce/sym_defer_g.c26
-rw-r--r--quantum/debounce/sym_defer_pk.c67
-rw-r--r--quantum/debounce/sym_eager_pk.c72
-rw-r--r--quantum/debounce/sym_eager_pr.c76
-rw-r--r--quantum/debounce/tests/asym_eager_defer_pk_tests.cpp374
-rw-r--r--quantum/debounce/tests/debounce_test_common.cpp229
-rw-r--r--quantum/debounce/tests/debounce_test_common.h83
-rw-r--r--quantum/debounce/tests/rules.mk44
-rw-r--r--quantum/debounce/tests/sym_defer_g_tests.cpp223
-rw-r--r--quantum/debounce/tests/sym_defer_pk_tests.cpp225
-rw-r--r--quantum/debounce/tests/sym_eager_pk_tests.cpp237
-rw-r--r--quantum/debounce/tests/sym_eager_pr_tests.cpp280
-rw-r--r--quantum/debounce/tests/testlist.mk6
-rw-r--r--quantum/dip_switch.c8
-rw-r--r--quantum/dip_switch.h8
-rw-r--r--quantum/keymap_extras/keymap_belgian.h13
-rw-r--r--quantum/keymap_extras/keymap_bepo.h167
-rw-r--r--quantum/keymap_extras/keymap_br_abnt2.h20
-rw-r--r--quantum/keymap_extras/keymap_canadian_multilingual.h179
-rw-r--r--quantum/keymap_extras/keymap_colemak.h32
-rw-r--r--quantum/keymap_extras/keymap_fr_ch.h79
-rw-r--r--quantum/keymap_extras/keymap_french.h11
-rw-r--r--quantum/keymap_extras/keymap_french_osx.h12
-rw-r--r--quantum/keymap_extras/keymap_german.h13
-rw-r--r--quantum/keymap_extras/keymap_german_ch.h18
-rw-r--r--quantum/keymap_extras/keymap_german_osx.h80
-rw-r--r--quantum/keymap_extras/keymap_hungarian.h19
-rw-r--r--quantum/keymap_extras/keymap_italian.h19
-rw-r--r--quantum/keymap_extras/keymap_italian_osx_ansi.h18
-rw-r--r--quantum/keymap_extras/keymap_italian_osx_iso.h18
-rw-r--r--quantum/keymap_extras/keymap_jp.h9
-rw-r--r--quantum/keymap_extras/keymap_neo2.h52
-rw-r--r--quantum/keymap_extras/keymap_norwegian.h23
-rw-r--r--quantum/keymap_extras/keymap_slovenian.h8
-rw-r--r--quantum/keymap_extras/keymap_spanish.h9
-rw-r--r--quantum/keymap_extras/keymap_swedish.h23
-rw-r--r--quantum/keymap_extras/keymap_uk.h75
-rw-r--r--quantum/keymap_extras/keymap_workman.h29
-rw-r--r--quantum/led_matrix/animations/alpha_mods_anim.h (renamed from quantum/led_matrix_animations/alpha_mods_anim.h)2
-rw-r--r--quantum/led_matrix/animations/band_anim.h (renamed from quantum/led_matrix_animations/band_anim.h)2
-rw-r--r--quantum/led_matrix/animations/band_pinwheel_anim.h (renamed from quantum/led_matrix_animations/band_pinwheel_anim.h)2
-rw-r--r--quantum/led_matrix/animations/band_spiral_anim.h (renamed from quantum/led_matrix_animations/band_spiral_anim.h)2
-rw-r--r--quantum/led_matrix/animations/breathing_anim.h (renamed from quantum/led_matrix_animations/breathing_anim.h)2
-rw-r--r--quantum/led_matrix/animations/cycle_left_right_anim.h (renamed from quantum/led_matrix_animations/cycle_left_right_anim.h)2
-rw-r--r--quantum/led_matrix/animations/cycle_out_in_anim.h (renamed from quantum/led_matrix_animations/cycle_out_in_anim.h)2
-rw-r--r--quantum/led_matrix/animations/cycle_up_down_anim.h (renamed from quantum/led_matrix_animations/cycle_up_down_anim.h)2
-rw-r--r--quantum/led_matrix/animations/dual_beacon_anim.h (renamed from quantum/led_matrix_animations/dual_beacon_anim.h)2
-rw-r--r--quantum/led_matrix/animations/led_matrix_effects.inc18
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_dx_dy.h (renamed from quantum/led_matrix_runners/effect_runner_dx_dy.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h (renamed from quantum/led_matrix_runners/effect_runner_dx_dy_dist.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_i.h (renamed from quantum/led_matrix_runners/effect_runner_i.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_reactive.h (renamed from quantum/led_matrix_runners/effect_runner_reactive.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h (renamed from quantum/led_matrix_runners/effect_runner_reactive_splash.h)0
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h (renamed from quantum/led_matrix_runners/effect_runner_sin_cos_i.h)0
-rw-r--r--quantum/led_matrix/animations/runners/led_matrix_runners.inc6
-rw-r--r--quantum/led_matrix/animations/solid_anim.h (renamed from quantum/led_matrix_animations/solid_anim.h)0
-rw-r--r--quantum/led_matrix/animations/solid_reactive_cross.h (renamed from quantum/led_matrix_animations/solid_reactive_cross.h)4
-rw-r--r--quantum/led_matrix/animations/solid_reactive_nexus.h (renamed from quantum/led_matrix_animations/solid_reactive_nexus.h)4
-rw-r--r--quantum/led_matrix/animations/solid_reactive_simple_anim.h (renamed from quantum/led_matrix_animations/solid_reactive_simple_anim.h)4
-rw-r--r--quantum/led_matrix/animations/solid_reactive_wide.h (renamed from quantum/led_matrix_animations/solid_reactive_wide.h)4
-rw-r--r--quantum/led_matrix/animations/solid_splash_anim.h (renamed from quantum/led_matrix_animations/solid_splash_anim.h)4
-rw-r--r--quantum/led_matrix/animations/wave_left_right_anim.h (renamed from quantum/led_matrix_animations/wave_left_right_anim.h)2
-rw-r--r--quantum/led_matrix/animations/wave_up_down_anim.h (renamed from quantum/led_matrix_animations/wave_up_down_anim.h)2
-rw-r--r--quantum/led_matrix/led_matrix.c (renamed from quantum/led_matrix.c)46
-rw-r--r--quantum/led_matrix/led_matrix.h (renamed from quantum/led_matrix.h)2
-rw-r--r--quantum/led_matrix/led_matrix_drivers.c (renamed from quantum/led_matrix_drivers.c)0
-rw-r--r--quantum/led_matrix/led_matrix_types.h (renamed from quantum/led_matrix_types.h)0
-rw-r--r--quantum/led_matrix_animations/led_matrix_effects.inc18
-rw-r--r--quantum/matrix.c274
-rw-r--r--quantum/mcu_selection.mk72
-rw-r--r--quantum/mousekey.c2
-rw-r--r--quantum/mousekey.h11
-rw-r--r--quantum/process_keycode/process_rgb.c1
-rw-r--r--quantum/quantum.c8
-rw-r--r--quantum/quantum.h4
-rw-r--r--quantum/rgb_matrix/animations/alpha_mods_anim.h (renamed from quantum/rgb_matrix_animations/alpha_mods_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/breathing_anim.h (renamed from quantum/rgb_matrix_animations/breathing_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h (renamed from quantum/rgb_matrix_animations/colorband_pinwheel_sat_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h (renamed from quantum/rgb_matrix_animations/colorband_pinwheel_val_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_sat_anim.h (renamed from quantum/rgb_matrix_animations/colorband_sat_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h (renamed from quantum/rgb_matrix_animations/colorband_spiral_sat_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_spiral_val_anim.h (renamed from quantum/rgb_matrix_animations/colorband_spiral_val_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/colorband_val_anim.h (renamed from quantum/rgb_matrix_animations/colorband_val_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_all_anim.h (renamed from quantum/rgb_matrix_animations/cycle_all_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_left_right_anim.h (renamed from quantum/rgb_matrix_animations/cycle_left_right_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_out_in_anim.h (renamed from quantum/rgb_matrix_animations/cycle_out_in_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h (renamed from quantum/rgb_matrix_animations/cycle_out_in_dual_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_pinwheel_anim.h (renamed from quantum/rgb_matrix_animations/cycle_pinwheel_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_spiral_anim.h (renamed from quantum/rgb_matrix_animations/cycle_spiral_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/cycle_up_down_anim.h (renamed from quantum/rgb_matrix_animations/cycle_up_down_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/digital_rain_anim.h (renamed from quantum/rgb_matrix_animations/digital_rain_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/dual_beacon_anim.h (renamed from quantum/rgb_matrix_animations/dual_beacon_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/gradient_left_right_anim.h (renamed from quantum/rgb_matrix_animations/gradient_left_right_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/gradient_up_down_anim.h (renamed from quantum/rgb_matrix_animations/gradient_up_down_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/hue_breathing_anim.h (renamed from quantum/rgb_matrix_animations/hue_breathing_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/hue_pendulum_anim.h (renamed from quantum/rgb_matrix_animations/hue_pendulum_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/hue_wave_anim.h (renamed from quantum/rgb_matrix_animations/hue_wave_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/jellybean_raindrops_anim.h (renamed from quantum/rgb_matrix_animations/jellybean_raindrops_anim.h)2
-rw-r--r--quantum/rgb_matrix/animations/rainbow_beacon_anim.h (renamed from quantum/rgb_matrix_animations/rainbow_beacon_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h (renamed from quantum/rgb_matrix_animations/rainbow_moving_chevron_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h (renamed from quantum/rgb_matrix_animations/rainbow_pinwheels_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/raindrops_anim.h (renamed from quantum/rgb_matrix_animations/raindrops_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/rgb_matrix_effects.inc37
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h (renamed from quantum/rgb_matrix_runners/effect_runner_dx_dy.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h (renamed from quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_i.h (renamed from quantum/rgb_matrix_runners/effect_runner_i.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_reactive.h (renamed from quantum/rgb_matrix_runners/effect_runner_reactive.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h (renamed from quantum/rgb_matrix_runners/effect_runner_reactive_splash.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h (renamed from quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h)0
-rw-r--r--quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc6
-rw-r--r--quantum/rgb_matrix/animations/solid_color_anim.h (renamed from quantum/rgb_matrix_animations/solid_color_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_anim.h (renamed from quantum/rgb_matrix_animations/solid_reactive_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_cross.h (renamed from quantum/rgb_matrix_animations/solid_reactive_cross.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_nexus.h (renamed from quantum/rgb_matrix_animations/solid_reactive_nexus.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_simple_anim.h (renamed from quantum/rgb_matrix_animations/solid_reactive_simple_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_wide.h (renamed from quantum/rgb_matrix_animations/solid_reactive_wide.h)0
-rw-r--r--quantum/rgb_matrix/animations/solid_splash_anim.h (renamed from quantum/rgb_matrix_animations/solid_splash_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/splash_anim.h (renamed from quantum/rgb_matrix_animations/splash_anim.h)0
-rw-r--r--quantum/rgb_matrix/animations/typing_heatmap_anim.h (renamed from quantum/rgb_matrix_animations/typing_heatmap_anim.h)0
-rw-r--r--quantum/rgb_matrix/rgb_matrix.c (renamed from quantum/rgb_matrix.c)46
-rw-r--r--quantum/rgb_matrix/rgb_matrix.h (renamed from quantum/rgb_matrix.h)4
-rw-r--r--quantum/rgb_matrix/rgb_matrix_drivers.c (renamed from quantum/rgb_matrix_drivers.c)16
-rw-r--r--quantum/rgb_matrix/rgb_matrix_types.h (renamed from quantum/rgb_matrix_types.h)0
-rw-r--r--quantum/rgb_matrix_animations/rgb_matrix_effects.inc37
-rw-r--r--quantum/rgblight/rgblight.c (renamed from quantum/rgblight.c)2
-rw-r--r--quantum/rgblight/rgblight.h (renamed from quantum/rgblight.h)0
-rw-r--r--quantum/rgblight/rgblight_breathe_table.h (renamed from quantum/rgblight_breathe_table.h)0
-rw-r--r--quantum/rgblight/rgblight_list.h (renamed from quantum/rgblight_list.h)46
-rw-r--r--quantum/rgblight/rgblight_modes.h (renamed from quantum/rgblight_modes.h)0
-rw-r--r--quantum/rgblight/rgblight_post_config.h (renamed from quantum/rgblight_post_config.h)0
-rw-r--r--quantum/serial_link/system/serial_link.c22
-rw-r--r--quantum/split_common/matrix.c309
-rw-r--r--quantum/split_common/post_config.h9
-rw-r--r--quantum/split_common/split_util.c4
-rw-r--r--quantum/split_common/transaction_id_define.h94
-rw-r--r--quantum/split_common/transactions.c655
-rw-r--r--quantum/split_common/transactions.h54
-rw-r--r--quantum/split_common/transport.c484
-rw-r--r--quantum/split_common/transport.h165
146 files changed, 3688 insertions, 2056 deletions
diff --git a/quantum/color.h b/quantum/color.h
index 4783f6839..e2cfc4692 100644
--- a/quantum/color.h
+++ b/quantum/color.h
@@ -19,6 +19,60 @@
19#include <stdint.h> 19#include <stdint.h>
20#include <stdbool.h> 20#include <stdbool.h>
21 21
22// clang-format off
23
24/*
25 * RGB Colors
26 */
27#define RGB_AZURE 0x99, 0xF5, 0xFF
28#define RGB_BLACK 0x00, 0x00, 0x00
29#define RGB_BLUE 0x00, 0x00, 0xFF
30#define RGB_CHARTREUSE 0x80, 0xFF, 0x00
31#define RGB_CORAL 0xFF, 0x7C, 0x4D
32#define RGB_CYAN 0x00, 0xFF, 0xFF
33#define RGB_GOLD 0xFF, 0xD9, 0x00
34#define RGB_GOLDENROD 0xD9, 0xA5, 0x21
35#define RGB_GREEN 0x00, 0xFF, 0x00
36#define RGB_MAGENTA 0xFF, 0x00, 0xFF
37#define RGB_ORANGE 0xFF, 0x80, 0x00
38#define RGB_PINK 0xFF, 0x80, 0xBF
39#define RGB_PURPLE 0x7A, 0x00, 0xFF
40#define RGB_RED 0xFF, 0x00, 0x00
41#define RGB_SPRINGGREEN 0x00, 0xFF, 0x80
42#define RGB_TEAL 0x00, 0x80, 0x80
43#define RGB_TURQUOISE 0x47, 0x6E, 0x6A
44#define RGB_WHITE 0xFF, 0xFF, 0xFF
45#define RGB_YELLOW 0xFF, 0xFF, 0x00
46#define RGB_OFF RGB_BLACK
47
48/*
49 * HSV Colors
50 *
51 * All values (including hue) are scaled to 0-255
52 */
53#define HSV_AZURE 132, 102, 255
54#define HSV_BLACK 0, 0, 0
55#define HSV_BLUE 170, 255, 255
56#define HSV_CHARTREUSE 64, 255, 255
57#define HSV_CORAL 11, 176, 255
58#define HSV_CYAN 128, 255, 255
59#define HSV_GOLD 36, 255, 255
60#define HSV_GOLDENROD 30, 218, 218
61#define HSV_GREEN 85, 255, 255
62#define HSV_MAGENTA 213, 255, 255
63#define HSV_ORANGE 28, 255, 255
64#define HSV_PINK 234, 128, 255
65#define HSV_PURPLE 191, 255, 255
66#define HSV_RED 0, 255, 255
67#define HSV_SPRINGGREEN 106, 255, 255
68#define HSV_TEAL 128, 255, 128
69#define HSV_TURQUOISE 123, 90, 112
70#define HSV_WHITE 0, 0, 255
71#define HSV_YELLOW 43, 255, 255
72#define HSV_OFF HSV_BLACK
73
74// clang-format on
75
22#if defined(__GNUC__) 76#if defined(__GNUC__)
23# define PACKED __attribute__((__packed__)) 77# define PACKED __attribute__((__packed__))
24#else 78#else
diff --git a/quantum/command.c b/quantum/command.c
index 34c4b36b1..3a7dc0f8c 100644
--- a/quantum/command.c
+++ b/quantum/command.c
@@ -781,6 +781,6 @@ uint8_t numkey2num(uint8_t code) {
781 781
782static void switch_default_layer(uint8_t layer) { 782static void switch_default_layer(uint8_t layer) {
783 xprintf("L%d\n", layer); 783 xprintf("L%d\n", layer);
784 default_layer_set(1UL << layer); 784 default_layer_set((layer_state_t)1 << layer);
785 clear_keyboard(); 785 clear_keyboard();
786} 786}
diff --git a/quantum/crc.c b/quantum/crc.c
new file mode 100644
index 000000000..0d8b9d601
--- /dev/null
+++ b/quantum/crc.c
@@ -0,0 +1,59 @@
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 2 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#include "crc.h"
18
19__attribute__((weak)) void crc_init(void){
20 /* Software implementation nothing todo here. */
21};
22
23#if defined(CRC8_USE_TABLE)
24/**
25 * Static table used for the table_driven implementation.
26 */
27static const crc_t crc_table[256] = {0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
28 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3};
29
30__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) {
31 const uint8_t *d = (const uint8_t *)data;
32 crc_t crc = 0xff;
33 size_t tbl_idx;
34
35 while (data_len--) {
36 tbl_idx = crc ^ *d;
37 crc = crc_table[tbl_idx] & 0xff;
38 d++;
39 }
40 return crc & 0xff;
41}
42#else
43__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) {
44 const uint8_t *d = (const uint8_t *)data;
45 crc_t crc = 0xff;
46 size_t i, j;
47
48 for (i = 0; i < data_len; i++) {
49 crc ^= d[i];
50 for (j = 0; j < 8; j++) {
51 if ((crc & 0x80) != 0)
52 crc = (crc_t)((crc << 1) ^ 0x31);
53 else
54 crc <<= 1;
55 }
56 }
57 return crc;
58}
59#endif \ No newline at end of file
diff --git a/quantum/rgb.h b/quantum/crc.h
index 2602fc0b2..c17f5888e 100644
--- a/quantum/rgb.h
+++ b/quantum/crc.h
@@ -1,4 +1,4 @@
1/* Copyright 2017 Jack Humbert 1/* Copyright 2021 QMK
2 * 2 *
3 * This program is free software: you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License as published by
@@ -16,24 +16,29 @@
16 16
17#pragma once 17#pragma once
18 18
19__attribute__((weak)) void rgblight_toggle(void){}; 19#include "quantum.h"
20 20
21__attribute__((weak)) void rgblight_step(void){}; 21/**
22 22 * The type of the CRC values.
23__attribute__((weak)) void rgblight_step_reverse(void){}; 23 *
24 24 * This type must be big enough to contain at least 8 bits.
25__attribute__((weak)) void rgblight_increase_hue(void){}; 25 */
26 26#if defined(CRC8_OPTIMIZE_SPEED)
27__attribute__((weak)) void rgblight_decrease_hue(void){}; 27typedef uint_fast8_t crc_t;
28 28#else
29__attribute__((weak)) void rgblight_increase_sat(void){}; 29typedef uint_least8_t crc_t;
30 30#endif
31__attribute__((weak)) void rgblight_decrease_sat(void){}; 31
32 32/**
33__attribute__((weak)) void rgblight_increase_val(void){}; 33 * Initialize crc subsystem.
34 34 */
35__attribute__((weak)) void rgblight_decrease_val(void){}; 35__attribute__((weak)) void crc_init(void);
36
37__attribute__((weak)) void rgblight_increase_speed(void){};
38 36
39__attribute__((weak)) void rgblight_decrease_speed(void){}; 37/**
38 * Generate CRC8 value from given data.
39 *
40 * \param[in] data Pointer to a buffer of \a data_len bytes.
41 * \param[in] data_len Number of bytes in the \a data buffer.
42 * \return The calculated crc value.
43 */
44__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len); \ No newline at end of file
diff --git a/quantum/debounce.h b/quantum/debounce.h
index 9ca05c682..504386828 100644
--- a/quantum/debounce.h
+++ b/quantum/debounce.h
@@ -9,3 +9,5 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
9bool debounce_active(void); 9bool debounce_active(void);
10 10
11void debounce_init(uint8_t num_rows); 11void debounce_init(uint8_t num_rows);
12
13void debounce_free(void);
diff --git a/quantum/debounce/asym_eager_defer_pk.c b/quantum/debounce/asym_eager_defer_pk.c
new file mode 100644
index 000000000..24380dc5e
--- /dev/null
+++ b/quantum/debounce/asym_eager_defer_pk.c
@@ -0,0 +1,171 @@
1/*
2 * Copyright 2017 Alex Ong <the.onga@gmail.com>
3 * Copyright 2020 Andrei Purdea <andrei@purdea.ro>
4 * Copyright 2021 Simon Arlott
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21Basic symmetric per-key algorithm. Uses an 8-bit counter per key.
22When no state changes have occured for DEBOUNCE milliseconds, we push the state.
23*/
24
25#include "matrix.h"
26#include "timer.h"
27#include "quantum.h"
28#include <stdlib.h>
29
30#ifdef PROTOCOL_CHIBIOS
31# if CH_CFG_USE_MEMCORE == FALSE
32# error ChibiOS is configured without a memory allocator. Your keyboard may have set `#define CH_CFG_USE_MEMCORE FALSE`, which is incompatible with this debounce algorithm.
33# endif
34#endif
35
36#ifndef DEBOUNCE
37# define DEBOUNCE 5
38#endif
39
40// Maximum debounce: 127ms
41#if DEBOUNCE > 127
42# undef DEBOUNCE
43# define DEBOUNCE 127
44#endif
45
46#define ROW_SHIFTER ((matrix_row_t)1)
47
48typedef struct {
49 bool pressed : 1;
50 uint8_t time : 7;
51} debounce_counter_t;
52
53#if DEBOUNCE > 0
54static debounce_counter_t *debounce_counters;
55static fast_timer_t last_time;
56static bool counters_need_update;
57static bool matrix_need_update;
58
59#define DEBOUNCE_ELAPSED 0
60
61static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
62static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
63
64// we use num_rows rather than MATRIX_ROWS to support split keyboards
65void debounce_init(uint8_t num_rows) {
66 debounce_counters = malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t));
67 int i = 0;
68 for (uint8_t r = 0; r < num_rows; r++) {
69 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
70 debounce_counters[i++].time = DEBOUNCE_ELAPSED;
71 }
72 }
73}
74
75void debounce_free(void) {
76 free(debounce_counters);
77 debounce_counters = NULL;
78}
79
80void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
81 bool updated_last = false;
82
83 if (counters_need_update) {
84 fast_timer_t now = timer_read_fast();
85 fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
86
87 last_time = now;
88 updated_last = true;
89 if (elapsed_time > UINT8_MAX) {
90 elapsed_time = UINT8_MAX;
91 }
92
93 if (elapsed_time > 0) {
94 update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time);
95 }
96 }
97
98 if (changed || matrix_need_update) {
99 if (!updated_last) {
100 last_time = timer_read_fast();
101 }
102
103 transfer_matrix_values(raw, cooked, num_rows);
104 }
105}
106
107static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) {
108 debounce_counter_t *debounce_pointer = debounce_counters;
109
110 counters_need_update = false;
111 matrix_need_update = false;
112
113 for (uint8_t row = 0; row < num_rows; row++) {
114 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
115 matrix_row_t col_mask = (ROW_SHIFTER << col);
116
117 if (debounce_pointer->time != DEBOUNCE_ELAPSED) {
118 if (debounce_pointer->time <= elapsed_time) {
119 debounce_pointer->time = DEBOUNCE_ELAPSED;
120
121 if (debounce_pointer->pressed) {
122 // key-down: eager
123 matrix_need_update = true;
124 } else {
125 // key-up: defer
126 cooked[row] = (cooked[row] & ~col_mask) | (raw[row] & col_mask);
127 }
128 } else {
129 debounce_pointer->time -= elapsed_time;
130 counters_need_update = true;
131 }
132 }
133 debounce_pointer++;
134 }
135 }
136}
137
138static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
139 debounce_counter_t *debounce_pointer = debounce_counters;
140
141 for (uint8_t row = 0; row < num_rows; row++) {
142 matrix_row_t delta = raw[row] ^ cooked[row];
143 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
144 matrix_row_t col_mask = (ROW_SHIFTER << col);
145
146 if (delta & col_mask) {
147 if (debounce_pointer->time == DEBOUNCE_ELAPSED) {
148 debounce_pointer->pressed = (raw[row] & col_mask);
149 debounce_pointer->time = DEBOUNCE;
150 counters_need_update = true;
151
152 if (debounce_pointer->pressed) {
153 // key-down: eager
154 cooked[row] ^= col_mask;
155 }
156 }
157 } else if (debounce_pointer->time != DEBOUNCE_ELAPSED) {
158 if (!debounce_pointer->pressed) {
159 // key-up: defer
160 debounce_pointer->time = DEBOUNCE_ELAPSED;
161 }
162 }
163 debounce_pointer++;
164 }
165 }
166}
167
168bool debounce_active(void) { return true; }
169#else
170# include "none.c"
171#endif
diff --git a/quantum/debounce/none.c b/quantum/debounce/none.c
new file mode 100644
index 000000000..b03892bc5
--- /dev/null
+++ b/quantum/debounce/none.c
@@ -0,0 +1,31 @@
1/* Copyright 2021 Simon Arlott
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 2 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#include "matrix.h"
18#include "quantum.h"
19#include <stdlib.h>
20
21void debounce_init(uint8_t num_rows) {}
22
23void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
24 for (int i = 0; i < num_rows; i++) {
25 cooked[i] = raw[i];
26 }
27}
28
29bool debounce_active(void) { return false; }
30
31void debounce_free(void) {}
diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c
index 3ed9055d2..fbefd55ed 100644
--- a/quantum/debounce/sym_defer_g.c
+++ b/quantum/debounce/sym_defer_g.c
@@ -1,5 +1,6 @@
1/* 1/*
2Copyright 2017 Alex Ong<the.onga@gmail.com> 2Copyright 2017 Alex Ong<the.onga@gmail.com>
3Copyright 2021 Simon Arlott
3This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or 6the Free Software Foundation, either version 2 of the License, or
@@ -23,30 +24,29 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
23# define DEBOUNCE 5 24# define DEBOUNCE 5
24#endif 25#endif
25 26
26void debounce_init(uint8_t num_rows) {} 27#if DEBOUNCE > 0
27static bool debouncing = false; 28static bool debouncing = false;
29static fast_timer_t debouncing_time;
28 30
29#if DEBOUNCE > 0 31void debounce_init(uint8_t num_rows) {}
30static uint16_t debouncing_time; 32
31void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { 33void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
32 if (changed) { 34 if (changed) {
33 debouncing = true; 35 debouncing = true;
34 debouncing_time = timer_read(); 36 debouncing_time = timer_read_fast();
35 } 37 }
36 38
37 if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { 39 if (debouncing && timer_elapsed_fast(debouncing_time) >= DEBOUNCE) {
38 for (int i = 0; i < num_rows; i++) { 40 for (int i = 0; i < num_rows; i++) {
39 cooked[i] = raw[i]; 41 cooked[i] = raw[i];
40 } 42 }
41 debouncing = false; 43 debouncing = false;
42 } 44 }
43} 45}
44#else // no debouncing.
45void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
46 for (int i = 0; i < num_rows; i++) {
47 cooked[i] = raw[i];
48 }
49}
50#endif
51 46
52bool debounce_active(void) { return debouncing; } 47bool debounce_active(void) { return debouncing; }
48
49void debounce_free(void) {}
50#else // no debouncing.
51# include "none.c"
52#endif
diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c
index 60513f98e..626a9be84 100644
--- a/quantum/debounce/sym_defer_pk.c
+++ b/quantum/debounce/sym_defer_pk.c
@@ -1,6 +1,7 @@
1/* 1/*
2Copyright 2017 Alex Ong<the.onga@gmail.com> 2Copyright 2017 Alex Ong<the.onga@gmail.com>
3Copyright 2020 Andrei Purdea<andrei@purdea.ro> 3Copyright 2020 Andrei Purdea<andrei@purdea.ro>
4Copyright 2021 Simon Arlott
4This program is free software: you can redistribute it and/or modify 5This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by 6it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or 7the Free Software Foundation, either version 2 of the License, or
@@ -33,28 +34,25 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
33# define DEBOUNCE 5 34# define DEBOUNCE 5
34#endif 35#endif
35 36
37// Maximum debounce: 255ms
38#if DEBOUNCE > UINT8_MAX
39# undef DEBOUNCE
40# define DEBOUNCE UINT8_MAX
41#endif
42
36#define ROW_SHIFTER ((matrix_row_t)1) 43#define ROW_SHIFTER ((matrix_row_t)1)
37 44
38#define debounce_counter_t uint8_t 45typedef uint8_t debounce_counter_t;
39 46
47#if DEBOUNCE > 0
40static debounce_counter_t *debounce_counters; 48static debounce_counter_t *debounce_counters;
49static fast_timer_t last_time;
41static bool counters_need_update; 50static bool counters_need_update;
42 51
43#define DEBOUNCE_ELAPSED 251 52#define DEBOUNCE_ELAPSED 0
44#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1)
45
46static uint8_t wrapping_timer_read(void) {
47 static uint16_t time = 0;
48 static uint8_t last_result = 0;
49 uint16_t new_time = timer_read();
50 uint16_t diff = new_time - time;
51 time = new_time;
52 last_result = (last_result + diff) % (MAX_DEBOUNCE + 1);
53 return last_result;
54}
55 53
56void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); 54static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
57void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); 55static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
58 56
59// we use num_rows rather than MATRIX_ROWS to support split keyboards 57// we use num_rows rather than MATRIX_ROWS to support split keyboards
60void debounce_init(uint8_t num_rows) { 58void debounce_init(uint8_t num_rows) {
@@ -67,27 +65,49 @@ void debounce_init(uint8_t num_rows) {
67 } 65 }
68} 66}
69 67
68void debounce_free(void) {
69 free(debounce_counters);
70 debounce_counters = NULL;
71}
72
70void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { 73void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
71 uint8_t current_time = wrapping_timer_read(); 74 bool updated_last = false;
75
72 if (counters_need_update) { 76 if (counters_need_update) {
73 update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, current_time); 77 fast_timer_t now = timer_read_fast();
78 fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
79
80 last_time = now;
81 updated_last = true;
82 if (elapsed_time > UINT8_MAX) {
83 elapsed_time = UINT8_MAX;
84 }
85
86 if (elapsed_time > 0) {
87 update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time);
88 }
74 } 89 }
75 90
76 if (changed) { 91 if (changed) {
77 start_debounce_counters(raw, cooked, num_rows, current_time); 92 if (!updated_last) {
93 last_time = timer_read_fast();
94 }
95
96 start_debounce_counters(raw, cooked, num_rows);
78 } 97 }
79} 98}
80 99
81void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { 100static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) {
82 counters_need_update = false; 101 counters_need_update = false;
83 debounce_counter_t *debounce_pointer = debounce_counters; 102 debounce_counter_t *debounce_pointer = debounce_counters;
84 for (uint8_t row = 0; row < num_rows; row++) { 103 for (uint8_t row = 0; row < num_rows; row++) {
85 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 104 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
86 if (*debounce_pointer != DEBOUNCE_ELAPSED) { 105 if (*debounce_pointer != DEBOUNCE_ELAPSED) {
87 if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { 106 if (*debounce_pointer <= elapsed_time) {
88 *debounce_pointer = DEBOUNCE_ELAPSED; 107 *debounce_pointer = DEBOUNCE_ELAPSED;
89 cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col)); 108 cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col));
90 } else { 109 } else {
110 *debounce_pointer -= elapsed_time;
91 counters_need_update = true; 111 counters_need_update = true;
92 } 112 }
93 } 113 }
@@ -96,14 +116,14 @@ void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix
96 } 116 }
97} 117}
98 118
99void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { 119static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
100 debounce_counter_t *debounce_pointer = debounce_counters; 120 debounce_counter_t *debounce_pointer = debounce_counters;
101 for (uint8_t row = 0; row < num_rows; row++) { 121 for (uint8_t row = 0; row < num_rows; row++) {
102 matrix_row_t delta = raw[row] ^ cooked[row]; 122 matrix_row_t delta = raw[row] ^ cooked[row];
103 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 123 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
104 if (delta & (ROW_SHIFTER << col)) { 124 if (delta & (ROW_SHIFTER << col)) {
105 if (*debounce_pointer == DEBOUNCE_ELAPSED) { 125 if (*debounce_pointer == DEBOUNCE_ELAPSED) {
106 *debounce_pointer = current_time; 126 *debounce_pointer = DEBOUNCE;
107 counters_need_update = true; 127 counters_need_update = true;
108 } 128 }
109 } else { 129 } else {
@@ -115,3 +135,6 @@ void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t
115} 135}
116 136
117bool debounce_active(void) { return true; } 137bool debounce_active(void) { return true; }
138#else
139# include "none.c"
140#endif
diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c
index e66cf92d7..15a3242e6 100644
--- a/quantum/debounce/sym_eager_pk.c
+++ b/quantum/debounce/sym_eager_pk.c
@@ -1,5 +1,6 @@
1/* 1/*
2Copyright 2017 Alex Ong<the.onga@gmail.com> 2Copyright 2017 Alex Ong<the.onga@gmail.com>
3Copyright 2021 Simon Arlott
3This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or 6the Free Software Foundation, either version 2 of the License, or
@@ -33,29 +34,26 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.
33# define DEBOUNCE 5 34# define DEBOUNCE 5
34#endif 35#endif
35 36
37// Maximum debounce: 255ms
38#if DEBOUNCE > UINT8_MAX
39# undef DEBOUNCE
40# define DEBOUNCE UINT8_MAX
41#endif
42
36#define ROW_SHIFTER ((matrix_row_t)1) 43#define ROW_SHIFTER ((matrix_row_t)1)
37 44
38#define debounce_counter_t uint8_t 45typedef uint8_t debounce_counter_t;
39 46
47#if DEBOUNCE > 0
40static debounce_counter_t *debounce_counters; 48static debounce_counter_t *debounce_counters;
49static fast_timer_t last_time;
41static bool counters_need_update; 50static bool counters_need_update;
42static bool matrix_need_update; 51static bool matrix_need_update;
43 52
44#define DEBOUNCE_ELAPSED 251 53#define DEBOUNCE_ELAPSED 0
45#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1)
46
47static uint8_t wrapping_timer_read(void) {
48 static uint16_t time = 0;
49 static uint8_t last_result = 0;
50 uint16_t new_time = timer_read();
51 uint16_t diff = new_time - time;
52 time = new_time;
53 last_result = (last_result + diff) % (MAX_DEBOUNCE + 1);
54 return last_result;
55}
56 54
57void update_debounce_counters(uint8_t num_rows, uint8_t current_time); 55static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
58void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); 56static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
59 57
60// we use num_rows rather than MATRIX_ROWS to support split keyboards 58// we use num_rows rather than MATRIX_ROWS to support split keyboards
61void debounce_init(uint8_t num_rows) { 59void debounce_init(uint8_t num_rows) {
@@ -68,27 +66,51 @@ void debounce_init(uint8_t num_rows) {
68 } 66 }
69} 67}
70 68
69void debounce_free(void) {
70 free(debounce_counters);
71 debounce_counters = NULL;
72}
73
71void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { 74void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
72 uint8_t current_time = wrapping_timer_read(); 75 bool updated_last = false;
76
73 if (counters_need_update) { 77 if (counters_need_update) {
74 update_debounce_counters(num_rows, current_time); 78 fast_timer_t now = timer_read_fast();
79 fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
80
81 last_time = now;
82 updated_last = true;
83 if (elapsed_time > UINT8_MAX) {
84 elapsed_time = UINT8_MAX;
85 }
86
87 if (elapsed_time > 0) {
88 update_debounce_counters(num_rows, elapsed_time);
89 }
75 } 90 }
76 91
77 if (changed || matrix_need_update) { 92 if (changed || matrix_need_update) {
78 transfer_matrix_values(raw, cooked, num_rows, current_time); 93 if (!updated_last) {
94 last_time = timer_read_fast();
95 }
96
97 transfer_matrix_values(raw, cooked, num_rows);
79 } 98 }
80} 99}
81 100
82// If the current time is > debounce counter, set the counter to enable input. 101// If the current time is > debounce counter, set the counter to enable input.
83void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { 102static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
84 counters_need_update = false; 103 counters_need_update = false;
104 matrix_need_update = false;
85 debounce_counter_t *debounce_pointer = debounce_counters; 105 debounce_counter_t *debounce_pointer = debounce_counters;
86 for (uint8_t row = 0; row < num_rows; row++) { 106 for (uint8_t row = 0; row < num_rows; row++) {
87 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 107 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
88 if (*debounce_pointer != DEBOUNCE_ELAPSED) { 108 if (*debounce_pointer != DEBOUNCE_ELAPSED) {
89 if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { 109 if (*debounce_pointer <= elapsed_time) {
90 *debounce_pointer = DEBOUNCE_ELAPSED; 110 *debounce_pointer = DEBOUNCE_ELAPSED;
111 matrix_need_update = true;
91 } else { 112 } else {
113 *debounce_pointer -= elapsed_time;
92 counters_need_update = true; 114 counters_need_update = true;
93 } 115 }
94 } 116 }
@@ -98,8 +120,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) {
98} 120}
99 121
100// upload from raw_matrix to final matrix; 122// upload from raw_matrix to final matrix;
101void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { 123static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
102 matrix_need_update = false;
103 debounce_counter_t *debounce_pointer = debounce_counters; 124 debounce_counter_t *debounce_pointer = debounce_counters;
104 for (uint8_t row = 0; row < num_rows; row++) { 125 for (uint8_t row = 0; row < num_rows; row++) {
105 matrix_row_t delta = raw[row] ^ cooked[row]; 126 matrix_row_t delta = raw[row] ^ cooked[row];
@@ -108,11 +129,9 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n
108 matrix_row_t col_mask = (ROW_SHIFTER << col); 129 matrix_row_t col_mask = (ROW_SHIFTER << col);
109 if (delta & col_mask) { 130 if (delta & col_mask) {
110 if (*debounce_pointer == DEBOUNCE_ELAPSED) { 131 if (*debounce_pointer == DEBOUNCE_ELAPSED) {
111 *debounce_pointer = current_time; 132 *debounce_pointer = DEBOUNCE;
112 counters_need_update = true; 133 counters_need_update = true;
113 existing_row ^= col_mask; // flip the bit. 134 existing_row ^= col_mask; // flip the bit.
114 } else {
115 matrix_need_update = true;
116 } 135 }
117 } 136 }
118 debounce_pointer++; 137 debounce_pointer++;
@@ -122,3 +141,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n
122} 141}
123 142
124bool debounce_active(void) { return true; } 143bool debounce_active(void) { return true; }
144#else
145# include "none.c"
146#endif
diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c
index 20ccb46f1..2ad592c5a 100644
--- a/quantum/debounce/sym_eager_pr.c
+++ b/quantum/debounce/sym_eager_pr.c
@@ -1,5 +1,6 @@
1/* 1/*
2Copyright 2019 Alex Ong<the.onga@gmail.com> 2Copyright 2019 Alex Ong<the.onga@gmail.com>
3Copyright 2021 Simon Arlott
3This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
4it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
5the Free Software Foundation, either version 2 of the License, or 6the Free Software Foundation, either version 2 of the License, or
@@ -33,27 +34,25 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.
33# define DEBOUNCE 5 34# define DEBOUNCE 5
34#endif 35#endif
35 36
36#define debounce_counter_t uint8_t 37// Maximum debounce: 255ms
38#if DEBOUNCE > UINT8_MAX
39# undef DEBOUNCE
40# define DEBOUNCE UINT8_MAX
41#endif
42
43typedef uint8_t debounce_counter_t;
44
45#if DEBOUNCE > 0
37static bool matrix_need_update; 46static bool matrix_need_update;
38 47
39static debounce_counter_t *debounce_counters; 48static debounce_counter_t *debounce_counters;
49static fast_timer_t last_time;
40static bool counters_need_update; 50static bool counters_need_update;
41 51
42#define DEBOUNCE_ELAPSED 251 52#define DEBOUNCE_ELAPSED 0
43#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1)
44
45static uint8_t wrapping_timer_read(void) {
46 static uint16_t time = 0;
47 static uint8_t last_result = 0;
48 uint16_t new_time = timer_read();
49 uint16_t diff = new_time - time;
50 time = new_time;
51 last_result = (last_result + diff) % (MAX_DEBOUNCE + 1);
52 return last_result;
53}
54 53
55void update_debounce_counters(uint8_t num_rows, uint8_t current_time); 54static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
56void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); 55static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
57 56
58// we use num_rows rather than MATRIX_ROWS to support split keyboards 57// we use num_rows rather than MATRIX_ROWS to support split keyboards
59void debounce_init(uint8_t num_rows) { 58void debounce_init(uint8_t num_rows) {
@@ -63,27 +62,50 @@ void debounce_init(uint8_t num_rows) {
63 } 62 }
64} 63}
65 64
65void debounce_free(void) {
66 free(debounce_counters);
67 debounce_counters = NULL;
68}
69
66void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { 70void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
67 uint8_t current_time = wrapping_timer_read(); 71 bool updated_last = false;
68 bool needed_update = counters_need_update; 72
69 if (counters_need_update) { 73 if (counters_need_update) {
70 update_debounce_counters(num_rows, current_time); 74 fast_timer_t now = timer_read_fast();
75 fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
76
77 last_time = now;
78 updated_last = true;
79 if (elapsed_time > UINT8_MAX) {
80 elapsed_time = UINT8_MAX;
81 }
82
83 if (elapsed_time > 0) {
84 update_debounce_counters(num_rows, elapsed_time);
85 }
71 } 86 }
72 87
73 if (changed || (needed_update && !counters_need_update) || matrix_need_update) { 88 if (changed || matrix_need_update) {
74 transfer_matrix_values(raw, cooked, num_rows, current_time); 89 if (!updated_last) {
90 last_time = timer_read_fast();
91 }
92
93 transfer_matrix_values(raw, cooked, num_rows);
75 } 94 }
76} 95}
77 96
78// If the current time is > debounce counter, set the counter to enable input. 97// If the current time is > debounce counter, set the counter to enable input.
79void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { 98static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
80 counters_need_update = false; 99 counters_need_update = false;
100 matrix_need_update = false;
81 debounce_counter_t *debounce_pointer = debounce_counters; 101 debounce_counter_t *debounce_pointer = debounce_counters;
82 for (uint8_t row = 0; row < num_rows; row++) { 102 for (uint8_t row = 0; row < num_rows; row++) {
83 if (*debounce_pointer != DEBOUNCE_ELAPSED) { 103 if (*debounce_pointer != DEBOUNCE_ELAPSED) {
84 if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { 104 if (*debounce_pointer <= elapsed_time) {
85 *debounce_pointer = DEBOUNCE_ELAPSED; 105 *debounce_pointer = DEBOUNCE_ELAPSED;
106 matrix_need_update = true;
86 } else { 107 } else {
108 *debounce_pointer -= elapsed_time;
87 counters_need_update = true; 109 counters_need_update = true;
88 } 110 }
89 } 111 }
@@ -92,8 +114,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) {
92} 114}
93 115
94// upload from raw_matrix to final matrix; 116// upload from raw_matrix to final matrix;
95void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { 117static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {
96 matrix_need_update = false;
97 debounce_counter_t *debounce_pointer = debounce_counters; 118 debounce_counter_t *debounce_pointer = debounce_counters;
98 for (uint8_t row = 0; row < num_rows; row++) { 119 for (uint8_t row = 0; row < num_rows; row++) {
99 matrix_row_t existing_row = cooked[row]; 120 matrix_row_t existing_row = cooked[row];
@@ -102,11 +123,9 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n
102 // determine new value basd on debounce pointer + raw value 123 // determine new value basd on debounce pointer + raw value
103 if (existing_row != raw_row) { 124 if (existing_row != raw_row) {
104 if (*debounce_pointer == DEBOUNCE_ELAPSED) { 125 if (*debounce_pointer == DEBOUNCE_ELAPSED) {
105 *debounce_pointer = current_time; 126 *debounce_pointer = DEBOUNCE;
106 cooked[row] = raw_row; 127 cooked[row] = raw_row;
107 counters_need_update = true; 128 counters_need_update = true;
108 } else {
109 matrix_need_update = true;
110 } 129 }
111 } 130 }
112 debounce_pointer++; 131 debounce_pointer++;
@@ -114,3 +133,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n
114} 133}
115 134
116bool debounce_active(void) { return true; } 135bool debounce_active(void) { return true; }
136#else
137# include "none.c"
138#endif
diff --git a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
new file mode 100644
index 000000000..fe374c3df
--- /dev/null
+++ b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
@@ -0,0 +1,374 @@
1/* Copyright 2021 Simon Arlott
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 2 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#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 /* Release key after 1ms delay */
25 {1, {{0, 1, UP}}, {}},
26
27 /*
28 * Until the eager timer on DOWN is observed to finish, the defer timer
29 * on UP can't start. There's no workaround for this because it's not
30 * possible to debounce an event that isn't being tracked.
31 *
32 * sym_defer_pk has the same problem but the test has to track that the
33 * key changed state so the DOWN timer is always allowed to finish
34 * before starting the UP timer.
35 */
36 {5, {}, {}},
37
38 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
39 /* Press key again after 1ms delay */
40 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
41 });
42 runEvents();
43}
44
45TEST_F(DebounceTest, OneKeyShort2) {
46 addEvents({ /* Time, Inputs, Outputs */
47 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
48 /* Release key after 2ms delay */
49 {2, {{0, 1, UP}}, {}},
50
51 {5, {}, {}}, /* See OneKeyShort1 */
52
53 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
54 /* Press key again after 1ms delay */
55 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort3) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 /* Release key after 3ms delay */
64 {3, {{0, 1, UP}}, {}},
65
66 {5, {}, {}}, /* See OneKeyShort1 */
67
68 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
69 /* Press key again after 1ms delay */
70 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
71 });
72 runEvents();
73}
74
75TEST_F(DebounceTest, OneKeyShort4) {
76 addEvents({ /* Time, Inputs, Outputs */
77 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
78 /* Release key after 4ms delay */
79 {4, {{0, 1, UP}}, {}},
80
81 {5, {}, {}}, /* See OneKeyShort1 */
82
83 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
84 /* Press key again after 1ms delay */
85 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
86 });
87 runEvents();
88}
89
90TEST_F(DebounceTest, OneKeyShort5) {
91 addEvents({ /* Time, Inputs, Outputs */
92 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93
94 /* Release key after 5ms delay */
95 {5, {{0, 1, UP}}, {}},
96
97 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
98 /* Press key again after 1ms delay */
99 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 });
101 runEvents();
102}
103
104TEST_F(DebounceTest, OneKeyShort6) {
105 addEvents({ /* Time, Inputs, Outputs */
106 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
107
108 /* Release key after 6ms delay */
109 {6, {{0, 1, UP}}, {}},
110
111 {11, {}, {{0, 1, UP}}}, /* 5ms after UP at time 6 */
112 /* Press key again after 1ms delay */
113 {12, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
114 });
115 runEvents();
116}
117
118TEST_F(DebounceTest, OneKeyShort7) {
119 addEvents({ /* Time, Inputs, Outputs */
120 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
121
122 /* Release key after 7ms delay */
123 {7, {{0, 1, UP}}, {}},
124
125 {12, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */
126 /* Press key again after 1ms delay */
127 {13, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
128 });
129 runEvents();
130}
131
132TEST_F(DebounceTest, OneKeyShort8) {
133 addEvents({ /* Time, Inputs, Outputs */
134 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
135 /* Release key after 1ms delay */
136 {1, {{0, 1, UP}}, {}},
137
138 {5, {}, {}}, /* See OneKeyShort1 */
139
140 {10, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */
141 /* Press key again after 0ms delay (scan 2) */
142 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
143 });
144 runEvents();
145}
146
147TEST_F(DebounceTest, OneKeyShort9) {
148 addEvents({ /* Time, Inputs, Outputs */
149 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
150 /* Release key after 1ms delay */
151 {1, {{0, 1, UP}}, {}},
152
153 {5, {}, {}}, /* See OneKeyShort1 */
154
155 /* Press key again after 0ms delay (same scan) before debounce finishes */
156 {10, {{0, 1, DOWN}}, {}},
157 });
158 runEvents();
159}
160
161TEST_F(DebounceTest, OneKeyBouncing1) {
162 addEvents({ /* Time, Inputs, Outputs */
163 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
164 {1, {{0, 1, UP}}, {}},
165 {2, {{0, 1, DOWN}}, {}},
166 {3, {{0, 1, UP}}, {}},
167 {4, {{0, 1, DOWN}}, {}},
168 {5, {{0, 1, UP}}, {}},
169 {6, {{0, 1, DOWN}}, {}},
170 {7, {{0, 1, UP}}, {}},
171 {8, {{0, 1, DOWN}}, {}},
172 {9, {{0, 1, UP}}, {}},
173 {10, {{0, 1, DOWN}}, {}},
174 {11, {{0, 1, UP}}, {}},
175 {12, {{0, 1, DOWN}}, {}},
176 {13, {{0, 1, UP}}, {}},
177 {14, {{0, 1, DOWN}}, {}},
178 {15, {{0, 1, UP}}, {}},
179
180 {20, {}, {{0, 1, UP}}},
181 /* Press key again after 1ms delay */
182 {21, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
183 });
184 runEvents();
185}
186
187TEST_F(DebounceTest, OneKeyBouncing2) {
188 addEvents({ /* Time, Inputs, Outputs */
189 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
190 /* Change twice in the same time period */
191 {1, {{0, 1, UP}}, {}},
192 {1, {{0, 1, DOWN}}, {}},
193 /* Change three times in the same time period */
194 {2, {{0, 1, UP}}, {}},
195 {2, {{0, 1, DOWN}}, {}},
196 {2, {{0, 1, UP}}, {}},
197 /* Change twice in the same time period */
198 {6, {{0, 1, DOWN}}, {}},
199 {6, {{0, 1, UP}}, {}},
200 /* Change three times in the same time period */
201 {7, {{0, 1, DOWN}}, {}},
202 {7, {{0, 1, UP}}, {}},
203 {7, {{0, 1, DOWN}}, {}},
204 /* Change twice in the same time period */
205 {8, {{0, 1, UP}}, {}},
206 {8, {{0, 1, DOWN}}, {}},
207 /* Change three times in the same time period */
208 {9, {{0, 1, UP}}, {}},
209 {9, {{0, 1, DOWN}}, {}},
210 {9, {{0, 1, UP}}, {}},
211
212 {14, {}, {{0, 1, UP}}},
213 /* Press key again after 1ms delay */
214 {15, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
215 });
216 runEvents();
217}
218
219TEST_F(DebounceTest, OneKeyLong) {
220 addEvents({ /* Time, Inputs, Outputs */
221 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
222
223 {25, {{0, 1, UP}}, {}},
224
225 {30, {}, {{0, 1, UP}}},
226
227 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
228
229 {75, {{0, 1, UP}}, {}},
230
231 {80, {}, {{0, 1, UP}}},
232
233 {100, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
234 });
235 runEvents();
236}
237
238TEST_F(DebounceTest, TwoKeysShort) {
239 addEvents({ /* Time, Inputs, Outputs */
240 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
241 {1, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
242 /* Release key after 2ms delay */
243 {2, {{0, 1, UP}}, {}},
244 {3, {{0, 2, UP}}, {}},
245
246 {5, {}, {}}, /* See OneKeyShort1 */
247 {6, {}, {}}, /* See OneKeyShort1 */
248
249 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
250 /* Press key again after 1ms delay */
251 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}, {0, 2, UP}}}, /* 5ms+5ms after DOWN at time 0 */
252 {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */
253 });
254 runEvents();
255}
256
257
258TEST_F(DebounceTest, OneKeyDelayedScan1) {
259 addEvents({ /* Time, Inputs, Outputs */
260 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
261
262 /* Processing is very late, immediately release key */
263 {300, {{0, 1, UP}}, {}},
264
265 {305, {}, {{0, 1, UP}}},
266 });
267 time_jumps_ = true;
268 runEvents();
269}
270
271TEST_F(DebounceTest, OneKeyDelayedScan2) {
272 addEvents({ /* Time, Inputs, Outputs */
273 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
274
275 /* Processing is very late, immediately release key */
276 {300, {{0, 1, UP}}, {}},
277
278 /* Processing is very late again */
279 {600, {}, {{0, 1, UP}}},
280 });
281 time_jumps_ = true;
282 runEvents();
283}
284
285TEST_F(DebounceTest, OneKeyDelayedScan3) {
286 addEvents({ /* Time, Inputs, Outputs */
287 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
288
289 /* Processing is very late */
290 {300, {}, {}},
291 /* Release key after 1ms */
292 {301, {{0, 1, UP}}, {}},
293
294 {306, {}, {{0, 1, UP}}},
295 });
296 time_jumps_ = true;
297 runEvents();
298}
299
300TEST_F(DebounceTest, OneKeyDelayedScan4) {
301 addEvents({ /* Time, Inputs, Outputs */
302 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
303
304 /* Processing is very late */
305 {300, {}, {}},
306 /* Release key after 1ms */
307 {301, {{0, 1, UP}}, {}},
308
309 /* Processing is very late again */
310 {600, {}, {{0, 1, UP}}},
311 });
312 time_jumps_ = true;
313 runEvents();
314}
315
316TEST_F(DebounceTest, OneKeyDelayedScan5) {
317 addEvents({ /* Time, Inputs, Outputs */
318 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
319
320 {5, {{0, 1, UP}}, {}},
321
322 /* Processing is very late */
323 {300, {}, {{0, 1, UP}}},
324 /* Immediately press key again */
325 {300, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
326 });
327 time_jumps_ = true;
328 runEvents();
329}
330
331TEST_F(DebounceTest, OneKeyDelayedScan6) {
332 addEvents({ /* Time, Inputs, Outputs */
333 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
334
335 {5, {{0, 1, UP}}, {}},
336
337 /* Processing is very late */
338 {300, {}, {{0, 1, UP}}},
339
340 /* Press key again after 1ms */
341 {301, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
342 });
343 time_jumps_ = true;
344 runEvents();
345}
346
347TEST_F(DebounceTest, OneKeyDelayedScan7) {
348 addEvents({ /* Time, Inputs, Outputs */
349 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
350
351 {5, {{0, 1, UP}}, {}},
352
353 /* Press key again before debounce expires */
354 {300, {{0, 1, DOWN}}, {}},
355 });
356 time_jumps_ = true;
357 runEvents();
358}
359
360TEST_F(DebounceTest, OneKeyDelayedScan8) {
361 addEvents({ /* Time, Inputs, Outputs */
362 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
363
364 /* Processing is a bit late */
365 {50, {}, {}},
366 /* Release key after 1ms */
367 {51, {{0, 1, UP}}, {}},
368
369 /* Processing is a bit late again */
370 {100, {}, {{0, 1, UP}}},
371 });
372 time_jumps_ = true;
373 runEvents();
374}
diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp
new file mode 100644
index 000000000..1c5e7c9f4
--- /dev/null
+++ b/quantum/debounce/tests/debounce_test_common.cpp
@@ -0,0 +1,229 @@
1/* Copyright 2021 Simon Arlott
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 2 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#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21#include <algorithm>
22#include <iomanip>
23#include <sstream>
24
25extern "C" {
26#include "quantum.h"
27#include "timer.h"
28#include "debounce.h"
29
30void set_time(uint32_t t);
31void advance_time(uint32_t ms);
32}
33
34void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) {
35 events_.insert(events_.end(), events.begin(), events.end());
36}
37
38void DebounceTest::runEvents() {
39 /* Run the test multiple times, from 1kHz to 10kHz scan rate */
40 for (extra_iterations_ = 0; extra_iterations_ < 10; extra_iterations_++) {
41 if (time_jumps_) {
42 /* Don't advance time smoothly, jump to the next event (some tests require this) */
43 auto_advance_time_ = false;
44 runEventsInternal();
45 } else {
46 /* Run the test with both smooth and irregular time; it must produce the same result */
47 auto_advance_time_ = true;
48 runEventsInternal();
49 auto_advance_time_ = false;
50 runEventsInternal();
51 }
52 }
53}
54
55void DebounceTest::runEventsInternal() {
56 fast_timer_t previous = 0;
57 bool first = true;
58
59 /* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */
60 debounce_init(MATRIX_ROWS);
61 set_time(time_offset_);
62 std::fill(std::begin(input_matrix_), std::end(input_matrix_), 0);
63 std::fill(std::begin(output_matrix_), std::end(output_matrix_), 0);
64
65 for (auto &event : events_) {
66 if (!auto_advance_time_) {
67 /* Jump to the next event */
68 set_time(time_offset_ + event.time_);
69 } else if (!first && event.time_ == previous + 1) {
70 /* This event immediately follows the previous one, don't make extra debounce() calls */
71 advance_time(1);
72 } else {
73 /* Fast forward to the time for this event, calling debounce() with no changes */
74 ASSERT_LT((time_offset_ + event.time_) - timer_read_fast(), 60000) << "Test tries to advance more than 1 minute of time";
75
76 while (timer_read_fast() != time_offset_ + event.time_) {
77 runDebounce(false);
78 checkCookedMatrix(false, "debounce() modified cooked matrix");
79 advance_time(1);
80 }
81 }
82
83 first = false;
84 previous = event.time_;
85
86 /* Prepare input matrix */
87 for (auto &input : event.inputs_) {
88 matrixUpdate(input_matrix_, "input", input);
89 }
90
91 /* Call debounce */
92 runDebounce(!event.inputs_.empty());
93
94 /* Prepare output matrix */
95 for (auto &output : event.outputs_) {
96 matrixUpdate(output_matrix_, "output", output);
97 }
98
99 /* Check output matrix has expected change events */
100 for (auto &output : event.outputs_) {
101 EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_))
102 << "Missing event at " << strTime()
103 << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_)
104 << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_)
105 << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
106 << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
107 }
108
109 /* Check output matrix has no other changes */
110 checkCookedMatrix(!event.inputs_.empty(), "debounce() cooked matrix does not match expected output matrix");
111
112 /* Perform some extra iterations of the matrix scan with no changes */
113 for (int i = 0; i < extra_iterations_; i++) {
114 runDebounce(false);
115 checkCookedMatrix(false, "debounce() modified cooked matrix");
116 }
117 }
118
119 /* Check that no further changes happen for 1 minute */
120 for (int i = 0; i < 60000; i++) {
121 runDebounce(false);
122 checkCookedMatrix(false, "debounce() modified cooked matrix");
123 advance_time(1);
124 }
125
126 debounce_free();
127}
128
129void DebounceTest::runDebounce(bool changed) {
130 std::copy(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_));
131 std::copy(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_));
132
133 debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
134
135 if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) {
136 FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime()
137 << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
138 << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
139 }
140}
141
142void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) {
143 if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) {
144 FAIL() << "Unexpected event: " << error_message << " at " << strTime()
145 << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
146 << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
147 << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
148 }
149}
150
151std::string DebounceTest::strTime() {
152 std::stringstream text;
153
154 text << "time " << (timer_read_fast() - time_offset_)
155 << " (extra_iterations=" << extra_iterations_
156 << ", auto_advance_time=" << auto_advance_time_ << ")";
157
158 return text.str();
159}
160
161std::string DebounceTest::strMatrix(matrix_row_t matrix[]) {
162 std::stringstream text;
163
164 text << "\t" << std::setw(3) << "";
165 for (int col = 0; col < MATRIX_COLS; col++) {
166 text << " " << std::setw(2) << col;
167 }
168 text << "\n";
169
170 for (int row = 0; row < MATRIX_ROWS; row++) {
171 text << "\t" << std::setw(2) << row << ":";
172 for (int col = 0; col < MATRIX_COLS; col++) {
173 text << ((matrix[row] & (1U << col)) ? " XX" : " __");
174 }
175
176 text << "\n";
177 }
178
179 return text.str();
180}
181
182bool DebounceTest::directionValue(Direction direction) {
183 switch (direction) {
184 case DOWN:
185 return true;
186
187 case UP:
188 return false;
189 }
190}
191
192std::string DebounceTest::directionLabel(Direction direction) {
193 switch (direction) {
194 case DOWN:
195 return "DOWN";
196
197 case UP:
198 return "UP";
199 }
200}
201
202/* Modify a matrix and verify that events always specify a change */
203void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) {
204 ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_))
205 << "Test " << name << " at " << strTime()
206 << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_)
207 << " but it is already " << directionLabel(event.direction_)
208 << "\n" << name << "_matrix:\n" << strMatrix(matrix);
209
210 switch (event.direction_) {
211 case DOWN:
212 matrix[event.row_] |= (1U << event.col_);
213 break;
214
215 case UP:
216 matrix[event.row_] &= ~(1U << event.col_);
217 break;
218 }
219}
220
221DebounceTestEvent::DebounceTestEvent(fast_timer_t time,
222 std::initializer_list<MatrixTestEvent> inputs,
223 std::initializer_list<MatrixTestEvent> outputs)
224 : time_(time), inputs_(inputs), outputs_(outputs) {
225}
226
227MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction)
228 : row_(row), col_(col), direction_(direction) {
229}
diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h
new file mode 100644
index 000000000..d87e31059
--- /dev/null
+++ b/quantum/debounce/tests/debounce_test_common.h
@@ -0,0 +1,83 @@
1/* Copyright 2021 Simon Arlott
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 2 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#include "gtest/gtest.h"
18
19#include <initializer_list>
20#include <list>
21#include <string>
22
23extern "C" {
24#include "quantum.h"
25#include "timer.h"
26}
27
28enum Direction {
29 DOWN,
30 UP,
31};
32
33class MatrixTestEvent {
34public:
35 MatrixTestEvent(int row, int col, Direction direction);
36
37 const int row_;
38 const int col_;
39 const Direction direction_;
40};
41
42class DebounceTestEvent {
43public:
44 // 0, {{0, 1, DOWN}}, {{0, 1, DOWN}})
45 DebounceTestEvent(fast_timer_t time,
46 std::initializer_list<MatrixTestEvent> inputs,
47 std::initializer_list<MatrixTestEvent> outputs);
48
49 const fast_timer_t time_;
50 const std::list<MatrixTestEvent> inputs_;
51 const std::list<MatrixTestEvent> outputs_;
52};
53
54class DebounceTest : public ::testing::Test {
55protected:
56 void addEvents(std::initializer_list<DebounceTestEvent> events);
57 void runEvents();
58
59 fast_timer_t time_offset_ = 7777;
60 bool time_jumps_ = false;
61
62private:
63 static bool directionValue(Direction direction);
64 static std::string directionLabel(Direction direction);
65
66 void runEventsInternal();
67 void runDebounce(bool changed);
68 void checkCookedMatrix(bool changed, const std::string &error_message);
69 void matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event);
70
71 std::string strTime();
72 std::string strMatrix(matrix_row_t matrix[]);
73
74 std::list<DebounceTestEvent> events_;
75
76 matrix_row_t input_matrix_[MATRIX_ROWS];
77 matrix_row_t raw_matrix_[MATRIX_ROWS];
78 matrix_row_t cooked_matrix_[MATRIX_ROWS];
79 matrix_row_t output_matrix_[MATRIX_ROWS];
80
81 int extra_iterations_;
82 bool auto_advance_time_;
83};
diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk
new file mode 100644
index 000000000..66928d7eb
--- /dev/null
+++ b/quantum/debounce/tests/rules.mk
@@ -0,0 +1,44 @@
1# Copyright 2021 Simon Arlott
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 2 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
16DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5
17
18DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \
19 $(TMK_PATH)/common/test/timer.c
20
21debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS)
22debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \
23 $(QUANTUM_PATH)/debounce/sym_defer_g.c \
24 $(QUANTUM_PATH)/debounce/tests/sym_defer_g_tests.cpp
25
26debounce_sym_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
27debounce_sym_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
28 $(QUANTUM_PATH)/debounce/sym_defer_pk.c \
29 $(QUANTUM_PATH)/debounce/tests/sym_defer_pk_tests.cpp
30
31debounce_sym_eager_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
32debounce_sym_eager_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
33 $(QUANTUM_PATH)/debounce/sym_eager_pk.c \
34 $(QUANTUM_PATH)/debounce/tests/sym_eager_pk_tests.cpp
35
36debounce_sym_eager_pr_DEFS := $(DEBOUNCE_COMMON_DEFS)
37debounce_sym_eager_pr_SRC := $(DEBOUNCE_COMMON_SRC) \
38 $(QUANTUM_PATH)/debounce/sym_eager_pr.c \
39 $(QUANTUM_PATH)/debounce/tests/sym_eager_pr_tests.cpp
40
41debounce_asym_eager_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
42debounce_asym_eager_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
43 $(QUANTUM_PATH)/debounce/asym_eager_defer_pk.c \
44 $(QUANTUM_PATH)/debounce/tests/asym_eager_defer_pk_tests.cpp
diff --git a/quantum/debounce/tests/sym_defer_g_tests.cpp b/quantum/debounce/tests/sym_defer_g_tests.cpp
new file mode 100644
index 000000000..a56aecd8f
--- /dev/null
+++ b/quantum/debounce/tests/sym_defer_g_tests.cpp
@@ -0,0 +1,223 @@
1/* Copyright 2021 Simon Arlott
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 2 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#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {}},
24
25 {5, {}, {{0, 1, DOWN}}},
26 /* 0ms delay (fast scan rate) */
27 {5, {{0, 1, UP}}, {}},
28
29 {10, {}, {{0, 1, UP}}},
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {}},
37
38 {5, {}, {{0, 1, DOWN}}},
39 /* 1ms delay */
40 {6, {{0, 1, UP}}, {}},
41
42 {11, {}, {{0, 1, UP}}},
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {}},
50
51 {5, {}, {{0, 1, DOWN}}},
52 /* 2ms delay */
53 {7, {{0, 1, UP}}, {}},
54
55 {12, {}, {{0, 1, UP}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyTooQuick1) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {}},
63 /* Release key exactly on the debounce time */
64 {5, {{0, 1, UP}}, {}},
65 });
66 runEvents();
67}
68
69TEST_F(DebounceTest, OneKeyTooQuick2) {
70 addEvents({ /* Time, Inputs, Outputs */
71 {0, {{0, 1, DOWN}}, {}},
72
73 {5, {}, {{0, 1, DOWN}}},
74 {6, {{0, 1, UP}}, {}},
75
76 /* Press key exactly on the debounce time */
77 {11, {{0, 1, DOWN}}, {}},
78 });
79 runEvents();
80}
81
82TEST_F(DebounceTest, OneKeyBouncing1) {
83 addEvents({ /* Time, Inputs, Outputs */
84 {0, {{0, 1, DOWN}}, {}},
85 {1, {{0, 1, UP}}, {}},
86 {2, {{0, 1, DOWN}}, {}},
87 {3, {{0, 1, UP}}, {}},
88 {4, {{0, 1, DOWN}}, {}},
89 {5, {{0, 1, UP}}, {}},
90 {6, {{0, 1, DOWN}}, {}},
91 {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */
92 });
93 runEvents();
94}
95
96TEST_F(DebounceTest, OneKeyBouncing2) {
97 addEvents({ /* Time, Inputs, Outputs */
98 {0, {{0, 1, DOWN}}, {}},
99 {5, {}, {{0, 1, DOWN}}},
100 {6, {{0, 1, UP}}, {}},
101 {7, {{0, 1, DOWN}}, {}},
102 {8, {{0, 1, UP}}, {}},
103 {9, {{0, 1, DOWN}}, {}},
104 {10, {{0, 1, UP}}, {}},
105 {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */
106 });
107 runEvents();
108}
109
110TEST_F(DebounceTest, OneKeyLong) {
111 addEvents({ /* Time, Inputs, Outputs */
112 {0, {{0, 1, DOWN}}, {}},
113
114 {5, {}, {{0, 1, DOWN}}},
115
116 {25, {{0, 1, UP}}, {}},
117
118 {30, {}, {{0, 1, UP}}},
119
120 {50, {{0, 1, DOWN}}, {}},
121
122 {55, {}, {{0, 1, DOWN}}},
123 });
124 runEvents();
125}
126
127TEST_F(DebounceTest, TwoKeysShort) {
128 addEvents({ /* Time, Inputs, Outputs */
129 {0, {{0, 1, DOWN}}, {}},
130 {1, {{0, 2, DOWN}}, {}},
131
132 {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
133
134 {7, {{0, 1, UP}}, {}},
135 {8, {{0, 2, UP}}, {}},
136
137 {13, {}, {{0, 1, UP}, {0, 2, UP}}},
138 });
139 runEvents();
140}
141
142TEST_F(DebounceTest, TwoKeysSimultaneous1) {
143 addEvents({ /* Time, Inputs, Outputs */
144 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
145
146 {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
147 {6, {{0, 1, UP}, {0, 2, UP}}, {}},
148
149 {11, {}, {{0, 1, UP}, {0, 2, UP}}},
150 });
151 runEvents();
152}
153
154TEST_F(DebounceTest, TwoKeysSimultaneous2) {
155 addEvents({ /* Time, Inputs, Outputs */
156 {0, {{0, 1, DOWN}}, {}},
157 {1, {{0, 2, DOWN}}, {}},
158
159 {5, {}, {}},
160 {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
161 {7, {{0, 1, UP}}, {}},
162 {8, {{0, 2, UP}}, {}},
163
164 {13, {}, {{0, 1, UP}, {0, 2, UP}}},
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, OneKeyDelayedScan1) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {}},
172
173 /* Processing is very late */
174 {300, {}, {{0, 1, DOWN}}},
175 /* Immediately release key */
176 {300, {{0, 1, UP}}, {}},
177
178 {305, {}, {{0, 1, UP}}},
179 });
180 time_jumps_ = true;
181 runEvents();
182}
183
184TEST_F(DebounceTest, OneKeyDelayedScan2) {
185 addEvents({ /* Time, Inputs, Outputs */
186 {0, {{0, 1, DOWN}}, {}},
187
188 /* Processing is very late */
189 {300, {}, {{0, 1, DOWN}}},
190 /* Release key after 1ms */
191 {301, {{0, 1, UP}}, {}},
192
193 {306, {}, {{0, 1, UP}}},
194 });
195 time_jumps_ = true;
196 runEvents();
197}
198
199TEST_F(DebounceTest, OneKeyDelayedScan3) {
200 addEvents({ /* Time, Inputs, Outputs */
201 {0, {{0, 1, DOWN}}, {}},
202
203 /* Release key before debounce expires */
204 {300, {{0, 1, UP}}, {}},
205 });
206 time_jumps_ = true;
207 runEvents();
208}
209
210TEST_F(DebounceTest, OneKeyDelayedScan4) {
211 addEvents({ /* Time, Inputs, Outputs */
212 {0, {{0, 1, DOWN}}, {}},
213
214 /* Processing is a bit late */
215 {50, {}, {{0, 1, DOWN}}},
216 /* Release key after 1ms */
217 {51, {{0, 1, UP}}, {}},
218
219 {56, {}, {{0, 1, UP}}},
220 });
221 time_jumps_ = true;
222 runEvents();
223}
diff --git a/quantum/debounce/tests/sym_defer_pk_tests.cpp b/quantum/debounce/tests/sym_defer_pk_tests.cpp
new file mode 100644
index 000000000..1f3061e59
--- /dev/null
+++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp
@@ -0,0 +1,225 @@
1/* Copyright 2021 Simon Arlott
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 2 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#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {}},
24
25 {5, {}, {{0, 1, DOWN}}},
26 /* 0ms delay (fast scan rate) */
27 {5, {{0, 1, UP}}, {}},
28
29 {10, {}, {{0, 1, UP}}},
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {}},
37
38 {5, {}, {{0, 1, DOWN}}},
39 /* 1ms delay */
40 {6, {{0, 1, UP}}, {}},
41
42 {11, {}, {{0, 1, UP}}},
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {}},
50
51 {5, {}, {{0, 1, DOWN}}},
52 /* 2ms delay */
53 {7, {{0, 1, UP}}, {}},
54
55 {12, {}, {{0, 1, UP}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyTooQuick1) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {}},
63 /* Release key exactly on the debounce time */
64 {5, {{0, 1, UP}}, {}},
65 });
66 runEvents();
67}
68
69TEST_F(DebounceTest, OneKeyTooQuick2) {
70 addEvents({ /* Time, Inputs, Outputs */
71 {0, {{0, 1, DOWN}}, {}},
72
73 {5, {}, {{0, 1, DOWN}}},
74 {6, {{0, 1, UP}}, {}},
75
76 /* Press key exactly on the debounce time */
77 {11, {{0, 1, DOWN}}, {}},
78 });
79 runEvents();
80}
81
82TEST_F(DebounceTest, OneKeyBouncing1) {
83 addEvents({ /* Time, Inputs, Outputs */
84 {0, {{0, 1, DOWN}}, {}},
85 {1, {{0, 1, UP}}, {}},
86 {2, {{0, 1, DOWN}}, {}},
87 {3, {{0, 1, UP}}, {}},
88 {4, {{0, 1, DOWN}}, {}},
89 {5, {{0, 1, UP}}, {}},
90 {6, {{0, 1, DOWN}}, {}},
91 {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */
92 });
93 runEvents();
94}
95
96TEST_F(DebounceTest, OneKeyBouncing2) {
97 addEvents({ /* Time, Inputs, Outputs */
98 {0, {{0, 1, DOWN}}, {}},
99 {5, {}, {{0, 1, DOWN}}},
100 {6, {{0, 1, UP}}, {}},
101 {7, {{0, 1, DOWN}}, {}},
102 {8, {{0, 1, UP}}, {}},
103 {9, {{0, 1, DOWN}}, {}},
104 {10, {{0, 1, UP}}, {}},
105 {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */
106 });
107 runEvents();
108}
109
110TEST_F(DebounceTest, OneKeyLong) {
111 addEvents({ /* Time, Inputs, Outputs */
112 {0, {{0, 1, DOWN}}, {}},
113
114 {5, {}, {{0, 1, DOWN}}},
115
116 {25, {{0, 1, UP}}, {}},
117
118 {30, {}, {{0, 1, UP}}},
119
120 {50, {{0, 1, DOWN}}, {}},
121
122 {55, {}, {{0, 1, DOWN}}},
123 });
124 runEvents();
125}
126
127TEST_F(DebounceTest, TwoKeysShort) {
128 addEvents({ /* Time, Inputs, Outputs */
129 {0, {{0, 1, DOWN}}, {}},
130 {1, {{0, 2, DOWN}}, {}},
131
132 {5, {}, {{0, 1, DOWN}}},
133 {6, {}, {{0, 2, DOWN}}},
134
135 {7, {{0, 1, UP}}, {}},
136 {8, {{0, 2, UP}}, {}},
137
138 {12, {}, {{0, 1, UP}}},
139 {13, {}, {{0, 2, UP}}},
140 });
141 runEvents();
142}
143
144TEST_F(DebounceTest, TwoKeysSimultaneous1) {
145 addEvents({ /* Time, Inputs, Outputs */
146 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
147
148 {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
149 {6, {{0, 1, UP}, {0, 2, UP}}, {}},
150
151 {11, {}, {{0, 1, UP}, {0, 2, UP}}},
152 });
153 runEvents();
154}
155
156TEST_F(DebounceTest, TwoKeysSimultaneous2) {
157 addEvents({ /* Time, Inputs, Outputs */
158 {0, {{0, 1, DOWN}}, {}},
159 {1, {{0, 2, DOWN}}, {}},
160
161 {5, {}, {{0, 1, DOWN}}},
162 {6, {{0, 1, UP}}, {{0, 2, DOWN}}},
163 {7, {{0, 2, UP}}, {}},
164
165 {11, {}, {{0, 1, UP}}},
166 {12, {}, {{0, 2, UP}}},
167 });
168 runEvents();
169}
170
171TEST_F(DebounceTest, OneKeyDelayedScan1) {
172 addEvents({ /* Time, Inputs, Outputs */
173 {0, {{0, 1, DOWN}}, {}},
174
175 /* Processing is very late */
176 {300, {}, {{0, 1, DOWN}}},
177 /* Immediately release key */
178 {300, {{0, 1, UP}}, {}},
179
180 {305, {}, {{0, 1, UP}}},
181 });
182 time_jumps_ = true;
183 runEvents();
184}
185
186TEST_F(DebounceTest, OneKeyDelayedScan2) {
187 addEvents({ /* Time, Inputs, Outputs */
188 {0, {{0, 1, DOWN}}, {}},
189
190 /* Processing is very late */
191 {300, {}, {{0, 1, DOWN}}},
192 /* Release key after 1ms */
193 {301, {{0, 1, UP}}, {}},
194
195 {306, {}, {{0, 1, UP}}},
196 });
197 time_jumps_ = true;
198 runEvents();
199}
200
201TEST_F(DebounceTest, OneKeyDelayedScan3) {
202 addEvents({ /* Time, Inputs, Outputs */
203 {0, {{0, 1, DOWN}}, {}},
204
205 /* Release key before debounce expires */
206 {300, {{0, 1, UP}}, {}},
207 });
208 time_jumps_ = true;
209 runEvents();
210}
211
212TEST_F(DebounceTest, OneKeyDelayedScan4) {
213 addEvents({ /* Time, Inputs, Outputs */
214 {0, {{0, 1, DOWN}}, {}},
215
216 /* Processing is a bit late */
217 {50, {}, {{0, 1, DOWN}}},
218 /* Release key after 1ms */
219 {51, {{0, 1, UP}}, {}},
220
221 {56, {}, {{0, 1, UP}}},
222 });
223 time_jumps_ = true;
224 runEvents();
225}
diff --git a/quantum/debounce/tests/sym_eager_pk_tests.cpp b/quantum/debounce/tests/sym_eager_pk_tests.cpp
new file mode 100644
index 000000000..e0fc205e3
--- /dev/null
+++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp
@@ -0,0 +1,237 @@
1/* Copyright 2021 Simon Arlott
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 2 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#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 {1, {{0, 1, UP}}, {}},
25
26 {5, {}, {{0, 1, UP}}},
27 /* Press key again after 1ms delay (debounce has not yet finished) */
28 {6, {{0, 1, DOWN}}, {}},
29 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
37 {1, {{0, 1, UP}}, {}},
38
39 {5, {}, {{0, 1, UP}}},
40 /* Press key again after 2ms delay (debounce has not yet finished) */
41 {7, {{0, 1, DOWN}}, {}},
42 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
50 {1, {{0, 1, UP}}, {}},
51
52 {5, {}, {{0, 1, UP}}},
53 /* Press key again after 3ms delay (debounce has not yet finished) */
54 {8, {{0, 1, DOWN}}, {}},
55 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort4) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 {1, {{0, 1, UP}}, {}},
64
65 {5, {}, {{0, 1, UP}}},
66 /* Press key again after 4ms delay (debounce has not yet finished) */
67 {9, {{0, 1, DOWN}}, {}},
68 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
69 });
70 runEvents();
71}
72
73TEST_F(DebounceTest, OneKeyShort5) {
74 addEvents({ /* Time, Inputs, Outputs */
75 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
76 {1, {{0, 1, UP}}, {}},
77
78 {5, {}, {{0, 1, UP}}},
79 /* Press key again after 5ms delay (debounce has finished) */
80 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
81 });
82 runEvents();
83}
84
85TEST_F(DebounceTest, OneKeyShort6) {
86 addEvents({ /* Time, Inputs, Outputs */
87 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
88 {1, {{0, 1, UP}}, {}},
89
90 {5, {}, {{0, 1, UP}}},
91 /* Press key after after 6ms delay (debounce has finished) */
92 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93 });
94 runEvents();
95}
96
97TEST_F(DebounceTest, OneKeyBouncing1) {
98 addEvents({ /* Time, Inputs, Outputs */
99 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 {1, {{0, 1, UP}}, {}},
101 {2, {{0, 1, DOWN}}, {}},
102 {3, {{0, 1, UP}}, {}},
103 {4, {{0, 1, DOWN}}, {}},
104 {5, {{0, 1, UP}}, {{0, 1, UP}}},
105 /* Press key again after 1ms delay (debounce has not yet finished) */
106 {6, {{0, 1, DOWN}}, {}},
107 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
108 });
109 runEvents();
110}
111
112TEST_F(DebounceTest, OneKeyBouncing2) {
113 addEvents({ /* Time, Inputs, Outputs */
114 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
115 /* Change twice in the same time period */
116 {1, {{0, 1, UP}}, {}},
117 {1, {{0, 1, DOWN}}, {}},
118 /* Change three times in the same time period */
119 {2, {{0, 1, UP}}, {}},
120 {2, {{0, 1, DOWN}}, {}},
121 {2, {{0, 1, UP}}, {}},
122 /* Change three times in the same time period */
123 {3, {{0, 1, DOWN}}, {}},
124 {3, {{0, 1, UP}}, {}},
125 {3, {{0, 1, DOWN}}, {}},
126 /* Change twice in the same time period */
127 {4, {{0, 1, UP}}, {}},
128 {4, {{0, 1, DOWN}}, {}},
129 {5, {{0, 1, UP}}, {{0, 1, UP}}},
130 /* Press key again after 1ms delay (debounce has not yet finished) */
131 {6, {{0, 1, DOWN}}, {}},
132 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
133 });
134 runEvents();
135}
136
137TEST_F(DebounceTest, OneKeyLong) {
138 addEvents({ /* Time, Inputs, Outputs */
139 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
140
141 {25, {{0, 1, UP}}, {{0, 1, UP}}},
142
143 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
144 });
145 runEvents();
146}
147
148TEST_F(DebounceTest, TwoKeysShort) {
149 addEvents({ /* Time, Inputs, Outputs */
150 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
151 {1, {{0, 1, UP}}, {}},
152 {2, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
153 {3, {{0, 2, UP}}, {}},
154
155 {5, {}, {{0, 1, UP}}},
156 /* Press key again after 1ms delay (debounce has not yet finished) */
157 {6, {{0, 1, DOWN}}, {}},
158 {7, {}, {{0, 2, UP}}},
159
160 /* Press key again after 1ms delay (debounce has not yet finished) */
161 {9, {{0, 2, DOWN}}, {}},
162 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
163
164 {12, {}, {{0, 2, DOWN}}}, /* 5ms after UP at time 7 */
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, OneKeyDelayedScan1) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
172
173 /* Processing is very late but the change will now be accepted */
174 {300, {{0, 1, UP}}, {{0, 1, UP}}},
175 });
176 time_jumps_ = true;
177 runEvents();
178}
179
180TEST_F(DebounceTest, OneKeyDelayedScan2) {
181 addEvents({ /* Time, Inputs, Outputs */
182 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
183
184 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
185 {300, {}, {}},
186 {300, {{0, 1, UP}}, {{0, 1, UP}}},
187 });
188 time_jumps_ = true;
189 runEvents();
190}
191
192TEST_F(DebounceTest, OneKeyDelayedScan3) {
193 addEvents({ /* Time, Inputs, Outputs */
194 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
195
196 /* Processing is very late but the change will now be accepted even with a 1ms delay */
197 {300, {}, {}},
198 {301, {{0, 1, UP}}, {{0, 1, UP}}},
199 });
200 time_jumps_ = true;
201 runEvents();
202}
203
204TEST_F(DebounceTest, OneKeyDelayedScan4) {
205 addEvents({ /* Time, Inputs, Outputs */
206 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
207
208 /* Processing is a bit late but the change will now be accepted */
209 {50, {{0, 1, UP}}, {{0, 1, UP}}},
210 });
211 time_jumps_ = true;
212 runEvents();
213}
214
215TEST_F(DebounceTest, OneKeyDelayedScan5) {
216 addEvents({ /* Time, Inputs, Outputs */
217 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
218
219 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
220 {50, {}, {}},
221 {50, {{0, 1, UP}}, {{0, 1, UP}}},
222 });
223 time_jumps_ = true;
224 runEvents();
225}
226
227TEST_F(DebounceTest, OneKeyDelayedScan6) {
228 addEvents({ /* Time, Inputs, Outputs */
229 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
230
231 /* Processing is very late but the change will now be accepted even with a 1ms delay */
232 {50, {}, {}},
233 {51, {{0, 1, UP}}, {{0, 1, UP}}},
234 });
235 time_jumps_ = true;
236 runEvents();
237}
diff --git a/quantum/debounce/tests/sym_eager_pr_tests.cpp b/quantum/debounce/tests/sym_eager_pr_tests.cpp
new file mode 100644
index 000000000..2c4bca127
--- /dev/null
+++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp
@@ -0,0 +1,280 @@
1/* Copyright 2021 Simon Arlott
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 2 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#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 {1, {{0, 1, UP}}, {}},
25
26 {5, {}, {{0, 1, UP}}},
27 /* Press key again after 1ms delay (debounce has not yet finished) */
28 {6, {{0, 1, DOWN}}, {}},
29 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
37 {1, {{0, 1, UP}}, {}},
38
39 {5, {}, {{0, 1, UP}}},
40 /* Press key again after 2ms delay (debounce has not yet finished) */
41 {7, {{0, 1, DOWN}}, {}},
42 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
50 {1, {{0, 1, UP}}, {}},
51
52 {5, {}, {{0, 1, UP}}},
53 /* Press key again after 3ms delay (debounce has not yet finished) */
54 {8, {{0, 1, DOWN}}, {}},
55 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort4) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 {1, {{0, 1, UP}}, {}},
64
65 {5, {}, {{0, 1, UP}}},
66 /* Press key again after 4ms delay (debounce has not yet finished) */
67 {9, {{0, 1, DOWN}}, {}},
68 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
69 });
70 runEvents();
71}
72
73TEST_F(DebounceTest, OneKeyShort5) {
74 addEvents({ /* Time, Inputs, Outputs */
75 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
76 {1, {{0, 1, UP}}, {}},
77
78 {5, {}, {{0, 1, UP}}},
79 /* Press key again after 5ms delay (debounce has finished) */
80 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
81 });
82 runEvents();
83}
84
85TEST_F(DebounceTest, OneKeyShort6) {
86 addEvents({ /* Time, Inputs, Outputs */
87 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
88 {1, {{0, 1, UP}}, {}},
89
90 {5, {}, {{0, 1, UP}}},
91 /* Press key after after 6ms delay (debounce has finished) */
92 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93 });
94 runEvents();
95}
96
97TEST_F(DebounceTest, OneKeyBouncing1) {
98 addEvents({ /* Time, Inputs, Outputs */
99 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 {1, {{0, 1, UP}}, {}},
101 {2, {{0, 1, DOWN}}, {}},
102 {3, {{0, 1, UP}}, {}},
103 {4, {{0, 1, DOWN}}, {}},
104 {5, {{0, 1, UP}}, {{0, 1, UP}}},
105 /* Press key again after 1ms delay (debounce has not yet finished) */
106 {6, {{0, 1, DOWN}}, {}},
107 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
108 });
109 runEvents();
110}
111
112TEST_F(DebounceTest, OneKeyBouncing2) {
113 addEvents({ /* Time, Inputs, Outputs */
114 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
115 /* Change twice in the same time period */
116 {1, {{0, 1, UP}}, {}},
117 {1, {{0, 1, DOWN}}, {}},
118 /* Change three times in the same time period */
119 {2, {{0, 1, UP}}, {}},
120 {2, {{0, 1, DOWN}}, {}},
121 {2, {{0, 1, UP}}, {}},
122 /* Change three times in the same time period */
123 {3, {{0, 1, DOWN}}, {}},
124 {3, {{0, 1, UP}}, {}},
125 {3, {{0, 1, DOWN}}, {}},
126 /* Change twice in the same time period */
127 {4, {{0, 1, UP}}, {}},
128 {4, {{0, 1, DOWN}}, {}},
129 {5, {{0, 1, UP}}, {{0, 1, UP}}},
130 /* Press key again after 1ms delay (debounce has not yet finished) */
131 {6, {{0, 1, DOWN}}, {}},
132 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
133 });
134 runEvents();
135}
136
137TEST_F(DebounceTest, OneKeyLong) {
138 addEvents({ /* Time, Inputs, Outputs */
139 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
140
141 {25, {{0, 1, UP}}, {{0, 1, UP}}},
142
143 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
144 });
145 runEvents();
146}
147
148TEST_F(DebounceTest, TwoRowsShort) {
149 addEvents({ /* Time, Inputs, Outputs */
150 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
151 {1, {{0, 1, UP}}, {}},
152 {2, {{2, 0, DOWN}}, {{2, 0, DOWN}}},
153 {3, {{2, 0, UP}}, {}},
154
155 {5, {}, {{0, 1, UP}}},
156 /* Press key again after 1ms delay (debounce has not yet finished) */
157 {6, {{0, 1, DOWN}}, {}},
158 {7, {}, {{2, 0, UP}}},
159
160 /* Press key again after 1ms delay (debounce has not yet finished) */
161 {9, {{2, 0, DOWN}}, {}},
162 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
163
164 {12, {}, {{2, 0, DOWN}}}, /* 5ms after UP at time 7 */
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, TwoKeysOverlap) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
172 {1, {{0, 1, UP}}, {}},
173 /* Press a second key during the first debounce */
174 {2, {{0, 2, DOWN}}, {}},
175
176 /* Key registers as soon as debounce finishes, 5ms after time 0 */
177 {5, {}, {{0, 1, UP}, {0, 2, DOWN}}},
178 {6, {{0, 1, DOWN}}, {}},
179
180 /* Key registers as soon as debounce finishes, 5ms after time 5 */
181 {10, {}, {{0, 1, DOWN}}},
182 /* Release both keys */
183 {11, {{0, 1, UP}}, {}},
184 {12, {{0, 2, UP}}, {}},
185
186 /* Keys register as soon as debounce finishes, 5ms after time 10 */
187 {15, {}, {{0, 1, UP}, {0, 2, UP}}},
188 });
189 runEvents();
190}
191
192TEST_F(DebounceTest, TwoKeysSimultaneous1) {
193 addEvents({ /* Time, Inputs, Outputs */
194 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
195 {20, {{0, 1, UP}}, {{0, 1, UP}}},
196 {21, {{0, 2, UP}}, {}},
197
198 /* Key registers as soon as debounce finishes, 5ms after time 20 */
199 {25, {}, {{0, 2, UP}}},
200 });
201 runEvents();
202}
203
204TEST_F(DebounceTest, TwoKeysSimultaneous2) {
205 addEvents({ /* Time, Inputs, Outputs */
206 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
207 {20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}},
208 });
209 runEvents();
210}
211
212TEST_F(DebounceTest, OneKeyDelayedScan1) {
213 addEvents({ /* Time, Inputs, Outputs */
214 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
215
216 /* Processing is very late but the change will now be accepted */
217 {300, {{0, 1, UP}}, {{0, 1, UP}}},
218 });
219 time_jumps_ = true;
220 runEvents();
221}
222
223TEST_F(DebounceTest, OneKeyDelayedScan2) {
224 addEvents({ /* Time, Inputs, Outputs */
225 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
226
227 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
228 {300, {}, {}},
229 {300, {{0, 1, UP}}, {{0, 1, UP}}},
230 });
231 time_jumps_ = true;
232 runEvents();
233}
234
235TEST_F(DebounceTest, OneKeyDelayedScan3) {
236 addEvents({ /* Time, Inputs, Outputs */
237 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
238
239 /* Processing is very late but the change will now be accepted even with a 1ms delay */
240 {300, {}, {}},
241 {301, {{0, 1, UP}}, {{0, 1, UP}}},
242 });
243 time_jumps_ = true;
244 runEvents();
245}
246
247TEST_F(DebounceTest, OneKeyDelayedScan4) {
248 addEvents({ /* Time, Inputs, Outputs */
249 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
250
251 /* Processing is a bit late but the change will now be accepted */
252 {50, {{0, 1, UP}}, {{0, 1, UP}}},
253 });
254 time_jumps_ = true;
255 runEvents();
256}
257
258TEST_F(DebounceTest, OneKeyDelayedScan5) {
259 addEvents({ /* Time, Inputs, Outputs */
260 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
261
262 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
263 {50, {}, {}},
264 {50, {{0, 1, UP}}, {{0, 1, UP}}},
265 });
266 time_jumps_ = true;
267 runEvents();
268}
269
270TEST_F(DebounceTest, OneKeyDelayedScan6) {
271 addEvents({ /* Time, Inputs, Outputs */
272 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
273
274 /* Processing is very late but the change will now be accepted even with a 1ms delay */
275 {50, {}, {}},
276 {51, {{0, 1, UP}}, {{0, 1, UP}}},
277 });
278 time_jumps_ = true;
279 runEvents();
280}
diff --git a/quantum/debounce/tests/testlist.mk b/quantum/debounce/tests/testlist.mk
new file mode 100644
index 000000000..c54c45aa6
--- /dev/null
+++ b/quantum/debounce/tests/testlist.mk
@@ -0,0 +1,6 @@
1TEST_LIST += \
2 debounce_sym_defer_g \
3 debounce_sym_defer_pk \
4 debounce_sym_eager_pk \
5 debounce_sym_eager_pr \
6 debounce_asym_eager_defer_pk
diff --git a/quantum/dip_switch.c b/quantum/dip_switch.c
index cda69bd0e..72789ca8e 100644
--- a/quantum/dip_switch.c
+++ b/quantum/dip_switch.c
@@ -49,13 +49,13 @@ static uint16_t scan_count;
49static bool dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0}; 49static bool dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0};
50static bool last_dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0}; 50static bool last_dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0};
51 51
52__attribute__((weak)) void dip_switch_update_user(uint8_t index, bool active) {} 52__attribute__((weak)) bool dip_switch_update_user(uint8_t index, bool active) { return true; }
53 53
54__attribute__((weak)) void dip_switch_update_kb(uint8_t index, bool active) { dip_switch_update_user(index, active); } 54__attribute__((weak)) bool dip_switch_update_kb(uint8_t index, bool active) { return dip_switch_update_user(index, active); }
55 55
56__attribute__((weak)) void dip_switch_update_mask_user(uint32_t state) {} 56__attribute__((weak)) bool dip_switch_update_mask_user(uint32_t state) { return true; }
57 57
58__attribute__((weak)) void dip_switch_update_mask_kb(uint32_t state) { dip_switch_update_mask_user(state); } 58__attribute__((weak)) bool dip_switch_update_mask_kb(uint32_t state) { return dip_switch_update_mask_user(state); }
59 59
60void dip_switch_init(void) { 60void dip_switch_init(void) {
61#ifdef DIP_SWITCH_PINS 61#ifdef DIP_SWITCH_PINS
diff --git a/quantum/dip_switch.h b/quantum/dip_switch.h
index 61ef1cc19..058a10f41 100644
--- a/quantum/dip_switch.h
+++ b/quantum/dip_switch.h
@@ -20,10 +20,10 @@
20 20
21#include "quantum.h" 21#include "quantum.h"
22 22
23void dip_switch_update_kb(uint8_t index, bool active); 23bool dip_switch_update_kb(uint8_t index, bool active);
24void dip_switch_update_user(uint8_t index, bool active); 24bool dip_switch_update_user(uint8_t index, bool active);
25void dip_switch_update_mask_user(uint32_t state); 25bool dip_switch_update_mask_user(uint32_t state);
26void dip_switch_update_mask_kb(uint32_t state); 26bool dip_switch_update_mask_kb(uint32_t state);
27 27
28void dip_switch_init(void); 28void dip_switch_init(void);
29void dip_switch_read(bool forced); 29void dip_switch_read(bool forced);
diff --git a/quantum/keymap_extras/keymap_belgian.h b/quantum/keymap_extras/keymap_belgian.h
index 6aaadf978..207905b29 100644
--- a/quantum/keymap_extras/keymap_belgian.h
+++ b/quantum/keymap_extras/keymap_belgian.h
@@ -156,16 +156,3 @@
156// Row 4 156// Row 4
157#define BE_BSLS ALGR(BE_LABK) // (backslash) 157#define BE_BSLS ALGR(BE_LABK) // (backslash)
158#define BE_TILD ALGR(BE_EQL) // ~ 158#define BE_TILD ALGR(BE_EQL) // ~
159
160// DEPRECATED
161#define BE_AMP BE_AMPR
162#define BE_APOS BE_QUOT
163#define BE_PARA BE_SECT
164#define BE_MU BE_MICR
165#define BE_LESS BE_LABK
166#define BE_OVRR BE_DEG
167#define BE_UMLT BE_DIAE
168#define BE_GRTR BE_RABK
169#define BE_LSBR BE_LBRC
170#define BE_RSBR BE_RBRC
171#define BE_TILT BE_TILD
diff --git a/quantum/keymap_extras/keymap_bepo.h b/quantum/keymap_extras/keymap_bepo.h
index b6244898a..72d5b81f3 100644
--- a/quantum/keymap_extras/keymap_bepo.h
+++ b/quantum/keymap_extras/keymap_bepo.h
@@ -181,7 +181,7 @@
181#define BP_RCBR ALGR(BP_X) // } 181#define BP_RCBR ALGR(BP_X) // }
182#define BP_ELLP ALGR(BP_DOT) // … 182#define BP_ELLP ALGR(BP_DOT) // …
183#define BP_TILD ALGR(BP_K) // ~ 183#define BP_TILD ALGR(BP_K) // ~
184#define BP_IQUE ALGR(BP_QEST) // ¿ 184#define BP_IQUE ALGR(BP_QUES) // ¿
185#define BP_RNGA ALGR(BP_Q) // ° (dead) 185#define BP_RNGA ALGR(BP_Q) // ° (dead)
186#define BP_DGRK ALGR(BP_G) // µ (dead Greek key) 186#define BP_DGRK ALGR(BP_G) // µ (dead Greek key)
187#define BP_DAGG ALGR(BP_H) // † 187#define BP_DAGG ALGR(BP_H) // †
@@ -238,168 +238,3 @@
238#define BP_FORD S(ALGR(BP_F)) // ª 238#define BP_FORD S(ALGR(BP_F)) // ª
239// Row 5 239// Row 5
240#define BP_NNBS S(ALGR(BP_)) //   (narrow non-breaking space) 240#define BP_NNBS S(ALGR(BP_)) //   (narrow non-breaking space)
241
242// DEPRECATED
243#define BP_DOLLAR BP_DLR
244#define BP_DOUBLE_QUOTE BP_DQUO
245#define BP_DQOT BP_DQUO
246#define BP_LEFT_GUILLEMET BP_LDAQ
247#define BP_LGIL BP_LDAQ
248#define BP_RIGHT_GUILLEMET BP_RDAQ
249#define BP_RGIL BP_RDAQ
250#define BP_LEFT_PAREN BP_LPRN
251#define BP_RIGHT_PAREN BP_RPRN
252#define BP_MINUS BP_MINS
253#define BP_SLASH BP_SLSH
254#define BP_ASTERISK BP_ASTR
255#define BP_EQUAL BP_EQL
256#define BP_PERCENT BP_PERC
257#define BP_E_ACUTE BP_EACU
258#define BP_ECUT BP_EACU
259#define BP_E_GRAVE BP_EGRV
260#define BP_DEAD_CIRCUMFLEX BP_DCIR
261#define BP_DCRC BP_DCIR
262#define BP_COMMA BP_COMM
263#define BP_C_CEDILLA BP_CCED
264#define BP_E_CIRCUMFLEX BP_ECIR
265#define BP_ECRC BP_ECIR
266#define BP_A_GRAVE BP_AGRV
267#define BP_APOSTROPHE BP_QUOT
268#define BP_APOS BP_QUOT
269#define BP_DEGREE BP_DEG
270#define BP_DEGR BP_DEG
271#define BP_GRAVE BP_GRV
272#define BP_EXCLAIM BP_EXLM
273#define BP_SCOLON BP_SCLN
274#define BP_COLON BP_COLN
275#define BP_QUESTION BP_QUES
276#define BP_QEST BP_QUES
277#define BP_NON_BREAKING_SPACE BP_NBSP
278#define BP_EN_DASH BP_NDSH
279#define BP_EM_DASH BP_MDSH
280#define BP_LESS BP_LABK
281#define BP_GREATER BP_RABK
282#define BP_GRTR BP_RABK
283#define BP_LBRACKET BP_LBRC
284#define BP_RBRACKET BP_RBRC
285#define BP_CIRCUMFLEX CIRC
286#define BP_PLUS_MINUS BP_PLMN
287#define BP_PSMS BP_PLMN
288#define BP_MATH_MINUS BP_MMNS
289#define BP_OBELUS BP_DIV
290#define BP_OBEL BP_DIV
291#define BP_DIVISION_SIGN BP_DIV
292#define BP_DVSN BP_DIV
293#define BP_TIMES BP_MUL
294#define BP_TIMS BP_MUL
295#define BP_DIFFERENT BP_NEQL
296#define BP_DIFF BP_NEQL
297#define BP_PERMILLE BP_PERM
298#define BP_PMIL BP_PERM
299#define BP_DEAD_ACUTE BP_ACUT
300#define BP_DACT BP_ACUT
301#define BP_AMPERSAND BP_AMPR
302#define BP_OE_LIGATURE BP_OE
303#define BP_DEAD_GRAVE BP_DGRV
304#define BP_INVERTED_EXCLAIM BP_IEXL
305#define BP_IXLM BP_IEXL
306#define BP_DEAD_CARON BP_CARN
307#define BP_DCAR BP_CARN
308#define BP_DEAD_SLASH BP_DSLS
309#define BP_DSLH BP_DSLS
310#define BP_IJ_LIGATURE BP_IJ
311#define BP_SCHWA BP_SCHW
312#define BP_SCWA BP_SCHW
313#define BP_DEAD_BREVE BP_BREV
314#define BP_DBRV BP_BREV
315#define BP_AE_LIGATURE BP_AE
316#define BP_U_GRAVE BP_UGRV
317#define BP_DEAD_TREMA BP_DIAE
318#define BP_DTRM BP_DIAE
319#define BP_TYPOGRAPHICAL_APOSTROPHE BP_COMM
320#define BP_TAPO BP_COMM
321#define BP_COPYRIGHT BP_COPY
322#define BP_CPRT BP_COPY
323#define BP_THORN BP_THRN
324#define BP_SHARP_S BP_SS
325#define BP_SRPS BP_SS
326#define BP_REGISTERED_TRADEMARK BP_REGD
327#define BP_RTM BP_REGD
328#define BP_DEAD_TILDE BP_DTIL
329#define BP_DTLD BP_DTIL
330#define BP_DEAD_MACRON BP_MACR
331#define BP_DMCR BP_MACR
332#define BP_DEAD_CEDILLA BP_CEDL
333#define BP_DCED BP_CEDL
334#define BP_NONUS_SLASH BP_SLSH
335#define BP_NUSL BP_SLSH
336#define BP_BACKSLASH BP_BSLS
337#define BP_LEFT_CURLY_BRACE BP_LCBR
338#define BP_RIGHT_CURLY_BRACE BP_RCBR
339#define BP_ELLIPSIS BP_ELLP
340#define BP_ELPS BP_ELLP
341#define BP_TILDE BP_TILD
342#define BP_INVERTED_QUESTION BP_IQUE
343#define BP_IQST BP_IQUE
344#define BP_DEAD_RING BP_RNGA
345#define BP_DRNG BP_RNGA
346#define BP_DEAD_GREEK BP_DGRK
347#define BP_DAGGER BP_DAGG
348#define BP_DAGR BP_DAGG
349#define BP_DEAD_OGONEK BP_OGON
350#define BP_DOGO BP_OGON
351#define BP_UNDERSCORE BP_UNDS
352#define BP_PARAGRAPH BP_PARA
353#define BP_PARG BP_PARA
354#define BP_LOW_DOUBLE_QUOTE BP_DLQU
355#define BP_LWQT BP_DLQU
356#define BP_LEFT_DOUBLE_QUOTE BP_RDQU
357#define BP_RIGHT_DOUBLE_QUOTE BP_RDQU
358#define BP_LESS_OR_EQUAL BP_LEQL
359#define BP_GREATER_OR_EQUAL BP_GEQL
360#define BP_NEGATION BP_NOT
361#define BP_NEGT BP_NOT
362#define BP_ONE_QUARTER BP_QRTR
363#define BP_1QRT BP_QRTR
364#define BP_ONE_HALF BP_HALF
365#define BP_1HLF BP_HALF
366#define BP_THREE_QUARTERS TQTR
367#define BP_3QRT BP_TQTR
368#define BP_MINUTES BP_PRIM
369#define BP_MNUT BP_PRIM
370#define BP_SECONDS BP_DPRM
371#define BP_SCND BP_DPRM
372#define BP_BROKEN_PIPE BP_BRKP
373#define BP_BPIP BP_BRKP
374#define BP_DEAD_DOUBLE_ACUTE BP_DACU
375#define BP_DDCT BP_DACU
376#define BP_SECTION BP_SECT
377#define BP_GRAVE_BIS BP_GRV
378#define BP_GRVB BP_GRV
379#define BP_DEAD_DOT_ABOVE BP_DOTA
380#define BP_DDTA BP_DOTA
381#define BP_DEAD_CURRENCY BP_CURR
382#define BP_DCUR BP_CURR
383#define BP_DEAD_HORN BP_HORN
384#define BP_DHRN BP_HORN
385#define BP_LONG_S BP_LNGS
386#define BP_TRADEMARK BP_TM
387#define BP_ORDINAL_INDICATOR_O MORD
388#define BP_ORDO BP_MORD
389#define BP_DEAD_COMMA BP_DCMM
390#define BP_DCOM BP_DCMM
391#define BP_LEFT_QUOTE BP_LSQU
392#define BP_LQOT BP_LSQU
393#define BP_RIGHT_QUOTE BP_RSQU
394#define BP_RQOT BP_RSQU
395#define BP_INTERPUNCT BP_MDDT
396#define BP_IPCT BP_MDDT
397#define BP_DEAD_HOOK_ABOVE BP_HOKA
398#define BP_DHKA BP_HOKA
399#define BP_DEAD_UNDERDOT BP_DOTB
400#define BP_DUDT BP_DOTB
401#define BP_DOUBLE_DAGGER BP_DDAG
402#define BP_DDGR BP_DDAG
403#define BP_ORDINAL_INDICATOR_A BP_FORD
404#define BP_ORDA BP_FORD
405#define BP_NARROW_NON_BREAKING_SPACE BP_NNBS
diff --git a/quantum/keymap_extras/keymap_br_abnt2.h b/quantum/keymap_extras/keymap_br_abnt2.h
index 310950d49..e91718013 100644
--- a/quantum/keymap_extras/keymap_br_abnt2.h
+++ b/quantum/keymap_extras/keymap_br_abnt2.h
@@ -158,23 +158,3 @@
158#define BR_MORD ALGR(BR_RBRC) // º 158#define BR_MORD ALGR(BR_RBRC) // º
159// Row 4 159// Row 4
160#define BR_CRUZ ALGR(BR_C) // ₢ 160#define BR_CRUZ ALGR(BR_C) // ₢
161
162// DEPRECATED
163#define BR_CCDL BR_CCED
164#define BR_DQT BR_DQUO
165#define BR_TRMA BR_DIAE
166#define BR_GRAV BR_GRV
167#define BR_KPDT BR_PDOT
168#define BR_KPCM BR_PCMM
169#define BR_1UP BR_SUP1
170#define BR_2UP BR_SUP2
171#define BR_3UP BR_SUP3
172#define BR_ASLS BR_SLSH
173#define BR_AQST BR_QUES
174
175// Not present on Windows 10?
176#define BR_NDTD ALGR(BR_TILD) // ~
177#define BR_NDAC ALGR(BR_ACUT) // ´
178#define BR_NDGV ALGR(BR_QUOT) // `
179#define BR_NDCR ALGR(BR_CIRC) // ^
180#define BR_NDTR ALGR(BR_DIAE) // ¨
diff --git a/quantum/keymap_extras/keymap_canadian_multilingual.h b/quantum/keymap_extras/keymap_canadian_multilingual.h
index d72ea3979..e328cf65e 100644
--- a/quantum/keymap_extras/keymap_canadian_multilingual.h
+++ b/quantum/keymap_extras/keymap_canadian_multilingual.h
@@ -252,182 +252,3 @@
252#define CA_MORD RCTL(S(CA_M)) // º 252#define CA_MORD RCTL(S(CA_M)) // º
253#define CA_MUL RCTL(S(CA_COMM)) // × 253#define CA_MUL RCTL(S(CA_COMM)) // ×
254#define CA_DIV RCTL(S(CA_DOT)) // ÷ 254#define CA_DIV RCTL(S(CA_DOT)) // ÷
255
256// DEPRECATED
257#define GR2A(kc) RCTL(kc)
258#define CSA_SLASH CA_SLSH
259#define CSA_SLSH CA_SLSH
260#define CSA_DEAD_CIRCUMFLEX CA_CIRC
261#define CSA_DCRC CA_CIRC
262#define CSA_C_CEDILLA CA_CCED
263#define CSA_CCED CA_CCED
264#define CSA_E_GRAVE CA_EGRV
265#define CSA_EGRV CA_EGRV
266#define CSA_A_GRAVE CA_AGRV
267#define CSA_AGRV CA_AGRV
268#define CSA_U_GRAVE CA_UGRV
269#define CSA_UGRV CA_UGRV
270#define CSA_E_ACUTE CA_EACU
271#define CSA_ECUT CA_EACU
272#define CSA_BACKSLASH CA_BSLS
273#define CSA_BSLS CA_BSLS
274#define CSA_QUESTION CA_QUES
275#define CSA_QEST CA_QUES
276#define CSA_DEAD_TREMA CA_DIAE
277#define CSA_DTRM CA_DIAE
278#define CSA_APOSTROPHE CA_QUOT
279#define CSA_APOS CA_QUOT
280#define CSA_DOUBLE_QUOTE CA_DQUO
281#define CSA_DQOT CA_DQUO
282#define CSA_PIPE CA_PIPE
283#define CSA_CURRENCY CA_CURR
284#define CSA_CURR CA_CURR
285#define CSA_LEFT_CURLY_BRACE CA_LCBR
286#define CSA_LCBR CA_LCBR
287#define CSA_RIGHT_CURLY_BRACE CA_RCBR
288#define CSA_RCBR CA_RCBR
289#define CSA_LBRACKET CA_LBRC
290#define CSA_LBRC CA_LBRC
291#define CSA_RBRACKET CA_RBRC
292#define CSA_RBRC CA_RBRC
293#define CSA_NEGATION CA_NOT
294#define CSA_NEGT CA_NOT
295#define CSA_EURO CA_EURO
296#define CSA_DEAD_GRAVE CA_GRV
297#define CSA_DGRV CA_GRV
298#define CSA_DEAD_TILDE CA_DTIL
299#define CSA_DTLD CA_DTIL
300#define CSA_DEGREE CA_DEG
301#define CSA_DEGR CA_DEG
302#define CSA_LEFT_GUILLEMET CA_LDAQ
303#define CSA_LGIL CA_LDAQ
304#define CSA_RIGHT_GUILLEMET CA_RDAQ
305#define CSA_RGIL CA_RDAQ
306#define CSA_LESS CA_LABK
307#define CSA_GREATER CA_RABK
308#define CSA_GRTR CA_RABK
309#define CSA_NON_BREAKING_SPACE ALGR(KC_SPC)
310#define CSA_NBSP ALGR(KC_SPC)
311#define CSA_SUPERSCRIPT_ONE CA_SUP1
312#define CSA_SUP1 CA_SUP1
313#define CSA_SUPERSCRIPT_TWO CA_SUP2
314#define CSA_SUP2 CA_SUP2
315#define CSA_SUPERSCRIPT_THREE CA_SUP3
316#define CSA_SUP3 CA_SUP3
317#define CSA_ONE_QUARTER CA_QRTR
318#define CSA_1QRT CA_QRTR
319#define CSA_ONE_HALF CA_HALF
320#define CSA_1HLF CA_HALF
321#define CSA_THREE_QUARTERS CA_TQTR
322#define CSA_3QRT CA_TQTR
323#define CSA_DEAD_CEDILLA CA_CEDL
324#define CSA_DCED CA_CEDL
325#define CSA_OMEGA CA_OMEG
326#define CSA_OMEG CA_OMEG
327#define CSA_L_STROKE CA_LSTR
328#define CSA_LSTK CA_LSTR
329#define CSA_OE_LIGATURE CA_OE
330#define CSA_OE CA_OE
331#define CSA_PARAGRAPH CA_PARA
332#define CSA_PARG CA_PARA
333#define CSA_T_STROKE CA_TSTR
334#define CSA_LEFT_ARROW CA_LARR
335#define CSA_LARW CA_LARR
336#define CSA_DOWN_ARROW CA_DARR
337#define CSA_DARW CA_DARR
338#define CSA_RIGHT_ARROW CA_RARR
339#define CSA_RARW CA_RARR
340#define CSA_O_STROKE CA_OSTR
341#define CSA_OSTK CA_OSTR
342#define CSA_THORN CA_THRN
343#define CSA_THRN CA_THRN
344#define CSA_TILDE CA_TILD
345#define CSA_TILD CA_TILD
346#define CSA_AE_LIGATURE CA_AE
347#define CSA_AE CA_AE
348#define CSA_SHARP_S CA_SS
349#define CSA_SRPS CA_SS
350#define CSA_ETH CA_ETH
351#define CSA_ENG CA_ENG
352#define CSA_H_SRTOKE CA_HSTR
353#define CSA_HSTK CA_HSTR
354#define CSA_IJ_LIGATURE CA_IJ
355#define CSA_IJ CA_IJ
356#define CSA_KRA CA_KRA
357#define CSA_L_FLOWN_DOT CA_LMDT
358#define CSA_LFLD CA_LMDT
359#define CSA_DEAD_ACUTE CA_ACUT
360#define CSA_DACT CA_ACUT
361#define CSA_CENT CA_CENT
362#define CSA_LEFT_DOUBLE_QUOTE CA_LDQU
363#define CSA_LDQT CA_LDQU
364#define CSA_RIGHT_DOUBLE_QUOTE CA_RDQU
365#define CSA_RDQT CA_RDQU
366#define CSA_N_APOSTROPHE CA_APSN
367#define CSA_NAPO CA_APSN
368#define CSA_MU CA_MICR
369#define CSA_HORIZONTAL_BAR CA_HRZB
370#define CSA_HZBR CA_HRZB
371#define CSA_DEAD_DOT_ABOVE CA_DOTA
372#define CSA_DDTA CA_DOTA
373#define CSA_SOFT_HYPHEN CA_SHYP
374#define CSA_SHYP CA_SHYP
375#define CSA_INVERTED_EXCLAIM CA_IEXL
376#define CSA_IXLM CA_IEXL
377#define CSA_POUND CA_PND
378#define CSA_GBP CA_PND
379#define CSA_EURO_BIS CA_EURO
380#define CSA_EURB CA_EURO
381#define CSA_THREE_EIGHTHS CA_TEIG
382#define CSA_3ON8 CA_TEIG
383#define CSA_FIVE_EIGHTHS CA_FEIG
384#define CSA_5ON8 CA_FEIG
385#define CSA_SEVEN_EIGHTHS CA_SEIG
386#define CSA_7ON8 CA_SEIG
387#define CSA_TRADEMARK CA_TM
388#define CSA_TM CA_TM
389#define CSA_PLUS_MINUS CA_PLMN
390#define CSA_PSMS CA_PLMN
391#define CSA_INVERTED_QUESTION CA_IQUE
392#define CSA_IQST CA_IQUE
393#define CSA_DEAD_OGONEK CA_OGON
394#define CSA_DOGO CA_OGON
395#define CSA_REGISTERED_TRADEMARK CA_REGD
396#define CSA_RTM CA_REGD
397#define CSA_YEN CA_YEN
398#define CSA_YUAN CA_YEN
399#define CSA_UP_ARROW CA_UARR
400#define CSA_DOTLESS_I CA_DLSI
401#define CSA_DLSI CA_DLSI
402#define CSA_DEAD_RING CA_RNGA
403#define CSA_DRNG CA_RNGA
404#define CSA_DEAD_MACRON CA_MACR
405#define CSA_DMCR CA_MACR
406#define CSA_SECTION CA_SECT
407#define CSA_SECT CA_SECT
408#define CSA_ORDINAL_INDICATOR_A CA_FORD
409#define CSA_ORDA CA_FORD
410#define CSA_DEAD_DOUBLE_ACUTE CA_DACU
411#define CSA_DDCT CA_DACU
412#define CSA_DEAD_CARON CA_CARN
413#define CSA_DCAR CA_CARN
414#define CSA_DEAD_BREVE CA_BREV
415#define CSA_DBRV CA_BREV
416#define CSA_BROKEN_PIPE CA_BRKP
417#define CSA_BPIP CA_BRKP
418#define CSA_COPYRIGHT CA_COPY
419#define CSA_CPRT CA_COPY
420#define CSA_LEFT_QUOTE CA_LSQU
421#define CSA_LQOT CA_LSQU
422#define CSA_RIGHT_QUOTE CA_RSQU
423#define CSA_RQOT CA_RSQU
424#define CSA_EIGHTH_NOTE CA_ENOT
425#define CSA_8NOT CA_ENOT
426#define CSA_ORDINAL_INDICATOR_O CA_MORD
427#define CSA_ORDO CA_MORD
428#define CSA_TIMES CA_MUL
429#define CSA_TIMS CA_MUL
430#define CSA_OBELUS CA_DIV
431#define CSA_OBEL CA_DIV
432#define CSA_DIVISION_SIGN CA_DIV
433#define CSA_DVSN CA_DIV
diff --git a/quantum/keymap_extras/keymap_colemak.h b/quantum/keymap_extras/keymap_colemak.h
index a97be9ad5..6658cc130 100644
--- a/quantum/keymap_extras/keymap_colemak.h
+++ b/quantum/keymap_extras/keymap_colemak.h
@@ -123,35 +123,3 @@
123#define CM_LABK S(CM_COMM) // < 123#define CM_LABK S(CM_COMM) // <
124#define CM_RABK S(CM_DOT) // > 124#define CM_RABK S(CM_DOT) // >
125#define CM_QUES S(CM_SLSH) // / 125#define CM_QUES S(CM_SLSH) // /
126
127// DEPRECATED
128#define KC_CM_Q CM_Q
129#define KC_CM_W CM_W
130#define KC_CM_F CM_F
131#define KC_CM_P CM_P
132#define KC_CM_G CM_G
133#define KC_CM_J CM_J
134#define KC_CM_L CM_L
135#define KC_CM_U CM_U
136#define KC_CM_Y CM_Y
137#define KC_CM_SCLN CM_SCLN
138#define KC_CM_A CM_A
139#define KC_CM_R CM_R
140#define KC_CM_S CM_S
141#define KC_CM_T CM_T
142#define KC_CM_D CM_D
143#define KC_CM_H CM_H
144#define KC_CM_N CM_N
145#define KC_CM_E CM_E
146#define KC_CM_I CM_I
147#define KC_CM_O CM_O
148#define KC_CM_Z CM_Z
149#define KC_CM_X CM_X
150#define KC_CM_C CM_C
151#define KC_CM_V CM_V
152#define KC_CM_B CM_B
153#define KC_CM_K CM_K
154#define KC_CM_M CM_M
155#define KC_CM_COMM CM_COMM
156#define KC_CM_DOT CM_DOT
157#define KC_CM_SLSH CM_SLSH
diff --git a/quantum/keymap_extras/keymap_fr_ch.h b/quantum/keymap_extras/keymap_fr_ch.h
index fea44324b..b1f2455a6 100644
--- a/quantum/keymap_extras/keymap_fr_ch.h
+++ b/quantum/keymap_extras/keymap_fr_ch.h
@@ -162,82 +162,3 @@
162#define CH_RCBR ALGR(CH_DLR) // } 162#define CH_RCBR ALGR(CH_DLR) // }
163// Row 4 163// Row 4
164#define CH_BSLS ALGR(CH_LABK) // (backslash) 164#define CH_BSLS ALGR(CH_LABK) // (backslash)
165
166// DEPRECATED
167#define FR_CH_Z CH_Z
168#define FR_CH_Y CH_Y
169#define FR_CH_A CH_A
170#define FR_CH_B CH_B
171#define FR_CH_C CH_C
172#define FR_CH_D CH_D
173#define FR_CH_E CH_E
174#define FR_CH_F CH_F
175#define FR_CH_G CH_G
176#define FR_CH_H CH_H
177#define FR_CH_I CH_I
178#define FR_CH_J CH_J
179#define FR_CH_K CH_K
180#define FR_CH_L CH_L
181#define FR_CH_M CH_M
182#define FR_CH_N CH_N
183#define FR_CH_O CH_O
184#define FR_CH_P CH_P
185#define FR_CH_Q CH_Q
186#define FR_CH_R CH_R
187#define FR_CH_S CH_S
188#define FR_CH_T CH_T
189#define FR_CH_U CH_U
190#define FR_CH_V CH_V
191#define FR_CH_W CH_W
192#define FR_CH_X CH_X
193#define FR_CH_0 CH_0
194#define FR_CH_1 CH_1
195#define FR_CH_2 CH_2
196#define FR_CH_3 CH_3
197#define FR_CH_4 CH_4
198#define FR_CH_5 CH_5
199#define FR_CH_6 CH_6
200#define FR_CH_7 CH_7
201#define FR_CH_8 CH_8
202#define FR_CH_9 CH_9
203#define FR_CH_DOT CH_DOT
204#define FR_CH_COMM CH_COMM
205#define FR_CH_QUOT CH_QUOT
206#define FR_CH_AE CH_AGRV
207#define FR_CH_UE CH_EGRV
208#define FR_CH_OE CH_EACU
209#define FR_CH_CIRC CH_CIRC
210#define FR_CH_LESS CH_LABK
211#define FR_CH_MINS CH_MINS
212#define FR_CH_DLR CH_DLR
213#define FR_CH_PARA CH_SECT
214#define FR_CH_DIAE CH_DIAE
215#define FR_CH_RING CH_DEG
216#define FR_CH_EXLM CH_EXLM
217#define FR_CH_PLUS CH_PLUS
218#define FR_CH_DQOT CH_DQUO
219#define FR_CH_ASTR CH_ASTR
220#define FR_CH_PERC CH_PERC
221#define FR_CH_AMPR CH_AMPR
222#define FR_CH_SLSH CH_SLSH
223#define FR_CH_LPRN CH_LPRN
224#define FR_CH_RPRN CH_RPRN
225#define FR_CH_EQL CH_EQL
226#define FR_CH_QST CH_QUES
227#define FR_CH_MORE CH_RABK
228#define FR_CH_COLN CH_COLN
229#define FR_CH_SCLN CH_SCLN
230#define FR_CH_UNDS CH_UNDS
231#define FR_CH_CCED CH_CCED
232#define FR_CH_GRV CH_GRV
233#define FR_CH_LCBR CH_LCBR
234#define FR_CH_LBRC CH_LBRC
235#define FR_CH_RBRC CH_RBRC
236#define FR_CH_RCBR CH_RCBR
237#define FR_CH_BSLS CH_BSLS
238#define FR_CH_AT CH_AT
239#define FR_CH_EURO CH_EURO
240#define FR_CH_TILD CH_TILD
241#define FR_CH_PIPE CH_PIPE
242#define FR_CH_HASH CH_HASH
243#define FR_CH_ACUT CH_ACUT
diff --git a/quantum/keymap_extras/keymap_french.h b/quantum/keymap_extras/keymap_french.h
index c62f2c403..0be53f0a9 100644
--- a/quantum/keymap_extras/keymap_french.h
+++ b/quantum/keymap_extras/keymap_french.h
@@ -152,14 +152,3 @@
152// Row 2 152// Row 2
153#define FR_EURO ALGR(KC_E) // € 153#define FR_EURO ALGR(KC_E) // €
154#define FR_CURR ALGR(FR_DLR) // ¤ 154#define FR_CURR ALGR(FR_DLR) // ¤
155
156// DEPRECATED
157#define FR_AMP FR_AMPR
158#define FR_APOS FR_QUOT
159#define FR_LESS FR_LABK
160#define FR_OVRR FR_DEG
161#define FR_UMLT FR_DIAE
162#define FR_MU FR_MICR
163#define FR_GRTR FR_RABK
164#define FR_CCIRC FR_CIRC
165#define FR_BULT FR_CURR
diff --git a/quantum/keymap_extras/keymap_french_osx.h b/quantum/keymap_extras/keymap_french_osx.h
index 76eb22191..590a57e55 100644
--- a/quantum/keymap_extras/keymap_french_osx.h
+++ b/quantum/keymap_extras/keymap_french_osx.h
@@ -246,15 +246,3 @@
246#define FR_IQUE S(A(FR_COMM)) // ¿ 246#define FR_IQUE S(A(FR_COMM)) // ¿
247#define FR_BSLS S(A(FR_COLN)) // (backslash) 247#define FR_BSLS S(A(FR_COLN)) // (backslash)
248#define FR_PLMN S(A(FR_EQL)) // ± 248#define FR_PLMN S(A(FR_EQL)) // ±
249
250// DEPRECATED
251#define FR_AMP FR_AMPR
252#define FR_EACU FR_LEAC
253#define FR_APOS FR_QUOT
254#define FR_EGRV FR_LEGR
255#define FR_CCED FR_LCCE
256#define FR_AGRV FR_LAGR
257#define FR_UGRV FR_LUGR
258#define FR_LESS FR_LABK
259#define FR_UMLT FR_DIAE
260#define FR_GRTR FR_RABK
diff --git a/quantum/keymap_extras/keymap_german.h b/quantum/keymap_extras/keymap_german.h
index 924bde6d3..085995b0c 100644
--- a/quantum/keymap_extras/keymap_german.h
+++ b/quantum/keymap_extras/keymap_german.h
@@ -151,16 +151,3 @@
151// Row 4 151// Row 4
152#define DE_PIPE ALGR(DE_LABK) // | 152#define DE_PIPE ALGR(DE_LABK) // |
153#define DE_MICR ALGR(DE_M) // µ 153#define DE_MICR ALGR(DE_M) // µ
154
155// DEPRECATED
156#define DE_UE DE_UDIA
157#define DE_OE DE_ODIA
158#define DE_AE DE_ADIA
159#define DE_LESS DE_LABK
160#define DE_RING DE_DEG
161#define DE_DQOT DE_DQUO
162#define DE_PARA DE_SECT
163#define DE_QST DE_QUES
164#define DE_MORE DE_RABK
165#define DE_SQ2 DE_SUP2
166#define DE_SQ3 DE_SUP3
diff --git a/quantum/keymap_extras/keymap_german_ch.h b/quantum/keymap_extras/keymap_german_ch.h
index fee37eabb..672383687 100644
--- a/quantum/keymap_extras/keymap_german_ch.h
+++ b/quantum/keymap_extras/keymap_german_ch.h
@@ -162,21 +162,3 @@
162#define CH_RCBR ALGR(CH_DLR) // } 162#define CH_RCBR ALGR(CH_DLR) // }
163// Row 4 163// Row 4
164#define CH_BSLS ALGR(CH_LABK) // (backslash) 164#define CH_BSLS ALGR(CH_LABK) // (backslash)
165
166// DEPRECATED
167#define CH_AE CH_ADIA
168#define CH_UE CH_UDIA
169#define CH_OE CH_ODIA
170#define CH_PARA CH_SECT
171#define CH_CARR CH_CIRC
172#define CH_DIER CH_DIAE
173#define CH_LESS CH_LABK
174#define CH_RING CH_DEG
175#define CH_DQOT CH_DQUO
176#define CH_PAST CH_ASTR
177#define CH_CELA CH_CCED
178#define CH_QST CH_QUES
179#define CH_POND CH_PND
180#define CH_MORE CH_RABK
181#define CH_BRBR CH_BRKP
182#define CH_NOTL CH_NOT
diff --git a/quantum/keymap_extras/keymap_german_osx.h b/quantum/keymap_extras/keymap_german_osx.h
index be109a721..82404fa5f 100644
--- a/quantum/keymap_extras/keymap_german_osx.h
+++ b/quantum/keymap_extras/keymap_german_osx.h
@@ -241,83 +241,3 @@
241#define DE_OGON S(A(DE_COMM)) // ˛ 241#define DE_OGON S(A(DE_COMM)) // ˛
242#define DE_DIV S(A(DE_DOT)) // ÷ 242#define DE_DIV S(A(DE_DOT)) // ÷
243#define DE_MDSH S(A(DE_MINS)) // — 243#define DE_MDSH S(A(DE_MINS)) // —
244
245// DEPRECATED
246#define DE_OSX_CIRC DE_CIRC
247#define DE_OSX_1 DE_1
248#define DE_OSX_2 DE_2
249#define DE_OSX_3 DE_3
250#define DE_OSX_4 DE_4
251#define DE_OSX_5 DE_5
252#define DE_OSX_6 DE_6
253#define DE_OSX_7 DE_7
254#define DE_OSX_8 DE_8
255#define DE_OSX_9 DE_9
256#define DE_OSX_0 DE_0
257#define DE_OSX_SS DE_SS
258#define DE_OSX_ACUT DE_ACUT
259#define DE_OSX_Q DE_Q
260#define DE_OSX_W DE_W
261#define DE_OSX_E DE_E
262#define DE_OSX_R DE_R
263#define DE_OSX_T DE_T
264#define DE_OSX_Z DE_Z
265#define DE_OSX_U DE_U
266#define DE_OSX_I DE_I
267#define DE_OSX_O DE_O
268#define DE_OSX_P DE_P
269#define DE_OSX_UE DE_UDIA
270#define DE_OSX_PLUS DE_PLUS
271#define DE_OSX_A DE_A
272#define DE_OSX_S DE_S
273#define DE_OSX_D DE_D
274#define DE_OSX_F DE_F
275#define DE_OSX_G DE_G
276#define DE_OSX_H DE_H
277#define DE_OSX_J DE_J
278#define DE_OSX_K DE_K
279#define DE_OSX_L DE_L
280#define DE_OSX_OE DE_ODIA
281#define DE_OSX_AE DE_ADIA
282#define DE_OSX_HASH DE_HASH
283#define DE_OSX_LESS DE_LABK
284#define DE_OSX_Y DE_Y
285#define DE_OSX_X DE_X
286#define DE_OSX_C DE_C
287#define DE_OSX_V DE_V
288#define DE_OSX_B DE_B
289#define DE_OSX_N DE_N
290#define DE_OSX_M DE_M
291#define DE_OSX_COMM DE_COMM
292#define DE_OSX_DOT DE_DOT
293#define DE_OSX_MINS DE_MINS
294
295#define DE_OSX_RING DE_DEG
296#define DE_OSX_EXLM DE_EXLM
297#define DE_OSX_DQOT DE_DQUO
298#define DE_OSX_PARA DE_SECT
299#define DE_OSX_DLR DE_DLR
300#define DE_OSX_PERC DE_PERC
301#define DE_OSX_AMPR DE_AMPR
302#define DE_OSX_SLSH DE_SLSH
303#define DE_OSX_LPRN DE_LPRN
304#define DE_OSX_RPRN DE_RPRN
305#define DE_OSX_EQL DE_EQL
306#define DE_OSX_QST DE_QUES
307#define DE_OSX_GRV DE_GRV
308#define DE_OSX_ASTR DE_ASTR
309#define DE_OSX_QUOT DE_QUOT
310#define DE_OSX_MORE DE_RABK
311#define DE_OSX_COLN DE_COLN
312#define DE_OSX_SCLN DE_SCLN
313#define DE_OSX_UNDS DE_UNDS
314
315#define DE_OSX_LBRC DE_LBRC
316#define DE_OSX_RBRC DE_RBRC
317#define DE_OSX_PIPE DE_PIPE
318#define DE_OSX_LCBR DE_LCBR
319#define DE_OSX_RCBR DE_RCBR
320#define DE_OSX_AT DE_AT
321#define DE_OSX_EURO DE_EURO
322#define DE_OSX_TILD DE_TILD
323#define DE_OSX_BSLS DE_BSLS
diff --git a/quantum/keymap_extras/keymap_hungarian.h b/quantum/keymap_extras/keymap_hungarian.h
index 1b282a461..a4e4b1a52 100644
--- a/quantum/keymap_extras/keymap_hungarian.h
+++ b/quantum/keymap_extras/keymap_hungarian.h
@@ -169,22 +169,3 @@
169#define HU_RCBR ALGR(HU_N) // } 169#define HU_RCBR ALGR(HU_N) // }
170#define HU_SCLN ALGR(HU_COMM) // ; 170#define HU_SCLN ALGR(HU_COMM) // ;
171#define HU_ASTR ALGR(HU_MINS) // * 171#define HU_ASTR ALGR(HU_MINS) // *
172
173// DEPRECATED
174#define HU_OE HU_ODIA
175#define HU_UE HU_UDIA
176#define HU_OO HU_OACU
177#define HU_OEE HU_ODAC
178#define HU_UU HU_UACU
179#define HU_EE HU_EACU
180#define HU_AA HU_AACU
181#define HU_UEE HU_UDAC
182#define HU_II HU_IACU
183#define HU_PARA HU_SECT
184#define HU_DQOT HU_DQUO
185#define HU_QST HU_QUES
186#define HU_BRV HU_BREV
187#define HU_RING HU_RNGA
188#define HU_CRSS HU_MUL
189#define HU_LESS HU_LABK
190#define HU_MORE HU_RABK
diff --git a/quantum/keymap_extras/keymap_italian.h b/quantum/keymap_extras/keymap_italian.h
index 5d19e56d3..be495f85b 100644
--- a/quantum/keymap_extras/keymap_italian.h
+++ b/quantum/keymap_extras/keymap_italian.h
@@ -163,22 +163,3 @@
163// Row 2 163// Row 2
164#define IT_LCBR S(ALGR(IT_EGRV)) // { 164#define IT_LCBR S(ALGR(IT_EGRV)) // {
165#define IT_RCBR S(ALGR(IT_PLUS)) // } 165#define IT_RCBR S(ALGR(IT_PLUS)) // }
166
167// DEPRECATED
168#define IT_BKSL IT_BSLS
169#define IT_APOS IT_QUOT
170#define IT_IACC IT_IGRV
171#define IT_EACC IT_EGRV
172#define IT_OACC IT_OGRV
173#define IT_AACC IT_AGRV
174#define IT_UACC IT_UGRV
175#define IT_LESS IT_LABK
176#define IT_DQOT IT_DQUO
177#define IT_STRL IT_PND
178#define IT_QST IT_QUES
179#define IT_CRC IT_CIRC
180#define IT_MORE IT_RABK
181#define IT_SHRP IT_HASH
182
183#define IT_X_PLUS X_RBRACKET
184#define IT_ACUT
diff --git a/quantum/keymap_extras/keymap_italian_osx_ansi.h b/quantum/keymap_extras/keymap_italian_osx_ansi.h
index 488a6561e..c2b8e3cad 100644
--- a/quantum/keymap_extras/keymap_italian_osx_ansi.h
+++ b/quantum/keymap_extras/keymap_italian_osx_ansi.h
@@ -248,21 +248,3 @@
248#define IT_CUAC S(A(IT_M)) // Ú 248#define IT_CUAC S(A(IT_M)) // Ú
249#define IT_MDDT S(A(IT_DOT)) // · 249#define IT_MDDT S(A(IT_DOT)) // ·
250#define IT_MDSH S(A(IT_MINS)) // — 250#define IT_MDSH S(A(IT_MINS)) // —
251
252// DEPRECATED
253#define IT_LESS IT_LABK
254#define IT_APOS IT_QUOT
255#define IT_IACC IT_IGRV
256#define IT_EACC IT_EGRV
257#define IT_UACC IT_UGRV
258#define IT_OACC IT_OGRV
259#define IT_AACC IT_AGRV
260#define IT_MORE IT_RABK
261#define IT_DQOT IT_DQUO
262#define IT_STRL IT_PND
263#define IT_QST IT_QUES
264#define IT_CRC IT_CIRC
265#define IT_DEGR IT_DEG
266#define IT_TILDE IT_TILD
267#define IT_GRAVE IT_GRV
268#define IT_SHRP IT_HASH
diff --git a/quantum/keymap_extras/keymap_italian_osx_iso.h b/quantum/keymap_extras/keymap_italian_osx_iso.h
index e4fb03acf..61f76ddba 100644
--- a/quantum/keymap_extras/keymap_italian_osx_iso.h
+++ b/quantum/keymap_extras/keymap_italian_osx_iso.h
@@ -249,21 +249,3 @@
249#define IT_CUAC S(A(IT_M)) // Ú 249#define IT_CUAC S(A(IT_M)) // Ú
250#define IT_MDDT S(A(IT_DOT)) // · 250#define IT_MDDT S(A(IT_DOT)) // ·
251#define IT_MDSH S(A(IT_MINS)) // — 251#define IT_MDSH S(A(IT_MINS)) // —
252
253// DEPRECATED
254#define IT_APOS IT_QUOT
255#define IT_IACC IT_IGRV
256#define IT_EACC IT_EGRV
257#define IT_OACC IT_OGRV
258#define IT_AACC IT_AGRV
259#define IT_UACC IT_UGRV
260#define IT_LESS IT_LABK
261#define IT_DQOT IT_DQUO
262#define IT_STRL IT_PND
263#define IT_QST IT_QUES
264#define IT_CRC IT_CIRC
265#define IT_DEGR IT_DEG
266#define IT_MORE IT_RABK
267#define IT_TILDE IT_TILD
268#define IT_GRAVE IT_GRV
269#define IT_SHRP IT_HASH
diff --git a/quantum/keymap_extras/keymap_jp.h b/quantum/keymap_extras/keymap_jp.h
index cd3c08f9f..d10feb585 100644
--- a/quantum/keymap_extras/keymap_jp.h
+++ b/quantum/keymap_extras/keymap_jp.h
@@ -137,12 +137,3 @@
137#define JP_RABK S(JP_DOT) // > 137#define JP_RABK S(JP_DOT) // >
138#define JP_QUES S(JP_SLSH) // ? 138#define JP_QUES S(JP_SLSH) // ?
139#define JP_UNDS S(JP_BSLS) // _ 139#define JP_UNDS S(JP_BSLS) // _
140
141// DEPRECATED
142#define JP_ZHTG JP_ZKHK
143#define JP_DQT JP_DQUO
144#define JP_LT JP_LABK
145#define JP_GT JP_RABK
146
147#define JP_MEISU KC_LANG2 // Eisū (英数) on macOS
148#define JP_MKANA KC_LANG1 // Kana (かな) on macOS
diff --git a/quantum/keymap_extras/keymap_neo2.h b/quantum/keymap_extras/keymap_neo2.h
index 8d5323c6a..f9fc00d79 100644
--- a/quantum/keymap_extras/keymap_neo2.h
+++ b/quantum/keymap_extras/keymap_neo2.h
@@ -88,55 +88,3 @@
88#define NE_J KC_SLSH // J 88#define NE_J KC_SLSH // J
89// Row 5 89// Row 5
90#define NE_L4R KC_ALGR // (layer 4) 90#define NE_L4R KC_ALGR // (layer 4)
91
92// DEPRECATED
93#define NEO_A NE_A
94#define NEO_B NE_B
95#define NEO_C NE_C
96#define NEO_D NE_D
97#define NEO_E NE_E
98#define NEO_F NE_F
99#define NEO_G NE_G
100#define NEO_H NE_H
101#define NEO_I NE_I
102#define NEO_J NE_J
103#define NEO_K NE_K
104#define NEO_L NE_L
105#define NEO_M NE_M
106#define NEO_N NE_N
107#define NEO_O NE_O
108#define NEO_P NE_P
109#define NEO_Q NE_Q
110#define NEO_R NE_R
111#define NEO_S NE_S
112#define NEO_T NE_T
113#define NEO_U NE_U
114#define NEO_V NE_V
115#define NEO_W NE_W
116#define NEO_X NE_X
117#define NEO_Y NE_Y
118#define NEO_Z NE_Z
119#define NEO_AE NE_ADIA
120#define NEO_OE NE_ODIA
121#define NEO_UE NE_UDIA
122#define NEO_SS NE_SS
123#define NEO_DOT NE_DOT
124#define NEO_COMM NE_COMM
125#define NEO_1 NE_1
126#define NEO_2 NE_2
127#define NEO_3 NE_3
128#define NEO_4 NE_4
129#define NEO_5 NE_5
130#define NEO_6 NE_6
131#define NEO_7 NE_7
132#define NEO_8 NE_8
133#define NEO_9 NE_9
134#define NEO_0 NE_0
135#define NEO_MINS NE_MINS
136#define NEO_ACUT NE_ACUT
137#define NEO_GRV NE_GRV
138#define NEO_CIRC NE_CIRC
139#define NEO_L1_L NE_L3L
140#define NEO_L1_R NE_L3R
141#define NEO_L2_L NE_L4L
142#define NEO_L2_R NE_L4R
diff --git a/quantum/keymap_extras/keymap_norwegian.h b/quantum/keymap_extras/keymap_norwegian.h
index 74c0c1ae2..b2499f4fd 100644
--- a/quantum/keymap_extras/keymap_norwegian.h
+++ b/quantum/keymap_extras/keymap_norwegian.h
@@ -150,26 +150,3 @@
150#define NO_TILD ALGR(NO_DIAE) // ~ (dead) 150#define NO_TILD ALGR(NO_DIAE) // ~ (dead)
151// Row 4 151// Row 4
152#define NO_MICR ALGR(NO_M) // µ 152#define NO_MICR ALGR(NO_M) // µ
153
154// DEPRECATED
155#define NO_AM NO_ARNG
156#define NO_AA NO_ARNG
157#define NO_OSLH NO_OSTR
158#define NO_APOS NO_QUOT
159#define NO_LESS NO_LABK
160#define NO_QUO2 NO_DQUO
161#define NO_BULT NO_CURR
162#define NO_GRTR NO_RABK
163#define NO_MU NO_MICR
164// Norwegian macOS symbols
165#define NO_ACUT_MAC NO_BSLS // ´
166#define NO_APOS_MAC NO_LABK // '
167#define NO_AT_MAC NO_QUOT // @
168#define NO_BSLS_MAC S(ALGR(NO_7)) // (backslash)
169#define NO_DLR_MAC S(NO_4) // $
170#define NO_GRV_MAC ALGR(NO_BSLS) // `
171#define NO_GRTR_MAC S(NO_PIPE) // >
172#define NO_LCBR_MAC S(ALGR(NO_8)) // {
173#define NO_LESS_MAC NO_PIPE // <
174#define NO_PIPE_MAC ALGR(NO_7) // |
175#define NO_RCBR_MAC S(ALGR(NO_9)) // }
diff --git a/quantum/keymap_extras/keymap_slovenian.h b/quantum/keymap_extras/keymap_slovenian.h
index 06be62cf3..827fa06c2 100644
--- a/quantum/keymap_extras/keymap_slovenian.h
+++ b/quantum/keymap_extras/keymap_slovenian.h
@@ -161,11 +161,3 @@
161#define SI_LCBR ALGR(SI_B) // { 161#define SI_LCBR ALGR(SI_B) // {
162#define SI_RCBR ALGR(SI_N) // } 162#define SI_RCBR ALGR(SI_N) // }
163#define SI_SECT ALGR(SI_M) // § 163#define SI_SECT ALGR(SI_M) // §
164
165// DEPRECATED
166#define SI_QOT SI_QUOT
167#define SI_SV SI_SCAR
168#define SI_CV SI_CCAR
169#define SI_ZV SI_ZCAR
170#define SI_DQOT SI_DQUO
171#define SI_QST SI_QUES
diff --git a/quantum/keymap_extras/keymap_spanish.h b/quantum/keymap_extras/keymap_spanish.h
index 4e888c513..8432c56e9 100644
--- a/quantum/keymap_extras/keymap_spanish.h
+++ b/quantum/keymap_extras/keymap_spanish.h
@@ -151,12 +151,3 @@
151// Row 3 151// Row 3
152#define ES_LCBR ALGR(ES_ACUT) // { 152#define ES_LCBR ALGR(ES_ACUT) // {
153#define ES_RCBR ALGR(ES_CCED) // } 153#define ES_RCBR ALGR(ES_CCED) // }
154
155// DEPRECATED
156#define ES_OVRR ES_MORD
157#define ES_APOS ES_QUOT
158#define ES_LESS ES_LABK
159#define ES_ASML ES_FORD
160#define ES_OVDT ES_BULT
161#define ES_UMLT ES_DIAE
162#define ES_GRTR ES_RABK
diff --git a/quantum/keymap_extras/keymap_swedish.h b/quantum/keymap_extras/keymap_swedish.h
index aef8d003d..cadb66d3b 100644
--- a/quantum/keymap_extras/keymap_swedish.h
+++ b/quantum/keymap_extras/keymap_swedish.h
@@ -154,26 +154,3 @@
154 154
155// DEPRECATED 155// DEPRECATED
156#include "keymap_nordic.h" 156#include "keymap_nordic.h"
157
158#define SE_OSLH SE_ODIA
159#define SE_APOS SE_QUOT
160#define SE_LESS SE_LABK
161#define SE_QUO2 SE_DQUO
162#define SE_BULT SE_CURR
163#define SE_GRTR SE_RABK
164#define SE_AA SE_ARNG
165#define SE_AE SE_ADIA
166#define SE_AM SE_ARNG
167#define SE_MU SE_MICR
168// Swedish macOS symbols (not vetted)
169#define SE_ACUT_MAC SE_ACUT
170#define SE_APOS_MAC SE_LABK
171#define SE_AT_MAC SE_ADIA
172#define SE_BSLS_MAC S(SE_LCBR)
173#define SE_DLR_MAC SE_CURR
174#define SE_GRV_MAC SE_BSLS
175#define SE_GRTR_MAC SE_HALF
176#define SE_LCBR_MAC S(SE_LBRC)
177#define SE_LESS_MAC SE_SECT
178#define SE_PIPE_MAC SE_LCBR
179#define SE_RCBR_MAC S(SE_RBRC)
diff --git a/quantum/keymap_extras/keymap_uk.h b/quantum/keymap_extras/keymap_uk.h
index 1eba0ed2f..03fe8149f 100644
--- a/quantum/keymap_extras/keymap_uk.h
+++ b/quantum/keymap_extras/keymap_uk.h
@@ -149,78 +149,3 @@
149#define UK_OACU ALGR(KC_O) // Ó 149#define UK_OACU ALGR(KC_O) // Ó
150// Row 3 150// Row 3
151#define UK_AACU ALGR(KC_A) // Á 151#define UK_AACU ALGR(KC_A) // Á
152
153// DEPRECATED
154#define UK_ESC KC_ESC
155#define UK_F1 KC_F1
156#define UK_F2 KC_F2
157#define UK_F3 KC_F3
158#define UK_F4 KC_F4
159#define UK_F5 KC_F5
160#define UK_F6 KC_F6
161#define UK_F7 KC_F7
162#define UK_F8 KC_F8
163#define UK_F9 KC_F9
164#define UK_F10 KC_F10
165#define UK_F11 KC_F11
166#define UK_F12 KC_F12
167#define UK_PSCR KC_PSCR
168#define UK_SLCK KC_SLCK
169#define UK_PAUS KC_PAUS
170#define UK_BSPC KC_BSPC
171#define UK_TAB KC_TAB
172#define UK_ENT KC_ENT
173#define UK_LSFT KC_LSFT
174#define UK_RSFT KC_RSFT
175#define UK_LCTL KC_LCTL
176#define UK_LGUI KC_LGUI
177#define UK_LALT KC_LALT
178#define UK_SPC KC_SPC
179#define UK_RALT KC_RALT
180#define UK_RGUI KC_RGUI
181#define UK_RCTL KC_RCTL
182#define UK_INS KC_INS
183#define UK_DEL KC_DEL
184#define UK_HOME KC_HOME
185#define UK_END KC_END
186#define UK_PGUP KC_PGUP
187#define UK_PGDN KC_PGDN
188#define UK_UP KC_UP
189#define UK_LEFT KC_LEFT
190#define UK_DOWN KC_DOWN
191#define UK_RGHT KC_RGHT
192#define UK_PSLS KC_PSLS
193#define UK_PAST KC_PAST
194#define UK_PMNS KC_PMNS
195#define UK_PPLS KC_PPLS
196#define UK_PENT KC_PENT
197#define UK_P1 KC_P1
198#define UK_P2 KC_P2
199#define UK_P3 KC_P3
200#define UK_P4 KC_P4
201#define UK_P5 KC_P5
202#define UK_P6 KC_P6
203#define UK_P7 KC_P7
204#define UK_P8 KC_P8
205#define UK_P9 KC_P9
206#define UK_P0 KC_P0
207#define UK_PDOT KC_PDOT
208#define UK_PEQL KC_PEQL
209#define UK_PCMM KC_PCMM
210#define UK_F13 KC_F13
211#define UK_F14 KC_F14
212#define UK_F15 KC_F15
213#define UK_F16 KC_F16
214#define UK_F17 KC_F17
215#define UK_F18 KC_F18
216#define UK_F19 KC_F19
217#define UK_F20 KC_F20
218#define UK_F21 KC_F21
219#define UK_F22 KC_F22
220#define UK_F23 KC_F23
221#define UK_F24 KC_F24
222#define UK_EACT UK_EACU
223#define UK_UACT UK_UACU
224#define UK_IACT UK_IACU
225#define UK_OACT UK_OACU
226#define UK_AACT UK_OACU
diff --git a/quantum/keymap_extras/keymap_workman.h b/quantum/keymap_extras/keymap_workman.h
index 4c7530aa0..6367d6835 100644
--- a/quantum/keymap_extras/keymap_workman.h
+++ b/quantum/keymap_extras/keymap_workman.h
@@ -123,32 +123,3 @@
123#define WK_LABK S(WK_COMM) // < 123#define WK_LABK S(WK_COMM) // <
124#define WK_RABK S(WK_DOT) // > 124#define WK_RABK S(WK_DOT) // >
125#define WK_QUES S(WK_SLSH) // ? 125#define WK_QUES S(WK_SLSH) // ?
126
127// DEPRECATED
128#define KC_WK_Q WK_Q
129#define KC_WK_D WK_D
130#define KC_WK_R WK_R
131#define KC_WK_W WK_W
132#define KC_WK_B WK_B
133#define KC_WK_J WK_J
134#define KC_WK_F WK_F
135#define KC_WK_U WK_U
136#define KC_WK_P WK_P
137#define KC_WK_SCLN WK_SCLN
138#define KC_WK_A WK_A
139#define KC_WK_S WK_S
140#define KC_WK_H WK_H
141#define KC_WK_T WK_T
142#define KC_WK_G WK_G
143#define KC_WK_Y WK_Y
144#define KC_WK_N WK_N
145#define KC_WK_E WK_E
146#define KC_WK_O WK_O
147#define KC_WK_I WK_I
148#define KC_WK_Z WK_Z
149#define KC_WK_X WK_X
150#define KC_WK_M WK_M
151#define KC_WK_C WK_C
152#define KC_WK_V WK_V
153#define KC_WK_K WK_K
154#define KC_WK_L WK_L
diff --git a/quantum/led_matrix_animations/alpha_mods_anim.h b/quantum/led_matrix/animations/alpha_mods_anim.h
index 6f69f6892..a4638fde6 100644
--- a/quantum/led_matrix_animations/alpha_mods_anim.h
+++ b/quantum/led_matrix/animations/alpha_mods_anim.h
@@ -21,4 +21,4 @@ bool ALPHAS_MODS(effect_params_t* params) {
21} 21}
22 22
23# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 23# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
24#endif // DISABLE_LED_MATRIX_ALPHAS_MODS 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
index 523dba1b7..f9cb85dc4 100644
--- a/quantum/led_matrix_animations/band_anim.h
+++ b/quantum/led_matrix/animations/band_anim.h
@@ -10,4 +10,4 @@ static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) {
10bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); } 10bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); }
11 11
12# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 12# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
13#endif // DISABLE_LED_MATRIX_BAND 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
index fb3b835ca..d3144bffb 100644
--- a/quantum/led_matrix_animations/band_pinwheel_anim.h
+++ b/quantum/led_matrix/animations/band_pinwheel_anim.h
@@ -7,4 +7,4 @@ static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t t
7bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); } 7bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL 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
index fca22aad9..defbe6967 100644
--- a/quantum/led_matrix_animations/band_spiral_anim.h
+++ b/quantum/led_matrix/animations/band_spiral_anim.h
@@ -7,4 +7,4 @@ static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dis
7bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); } 7bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_BAND_SPIRAL 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
index 00310e3f6..4f49f5069 100644
--- a/quantum/led_matrix_animations/breathing_anim.h
+++ b/quantum/led_matrix/animations/breathing_anim.h
@@ -16,4 +16,4 @@ bool BREATHING(effect_params_t* params) {
16} 16}
17 17
18# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 18# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
19#endif // DISABLE_LED_MATRIX_BREATHING 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
index 51e81d57c..c426d02fd 100644
--- a/quantum/led_matrix_animations/cycle_left_right_anim.h
+++ b/quantum/led_matrix/animations/cycle_left_right_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { ret
7bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); } 7bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT 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
index f62061552..55527556f 100644
--- a/quantum/led_matrix_animations/cycle_out_in_anim.h
+++ b/quantum/led_matrix/animations/cycle_out_in_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t di
7bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); } 7bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN 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
index bd1d12567..d97de0d1e 100644
--- a/quantum/led_matrix_animations/cycle_up_down_anim.h
+++ b/quantum/led_matrix/animations/cycle_up_down_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return
7bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); } 7bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN 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
index 9b8a7877c..e1bc5ae46 100644
--- a/quantum/led_matrix_animations/dual_beacon_anim.h
+++ b/quantum/led_matrix/animations/dual_beacon_anim.h
@@ -7,4 +7,4 @@ static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i,
7bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); } 7bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_DUAL_BEACON 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..ad1f46b24
--- /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 determines enum order
2#include "solid_anim.h"
3#include "alpha_mods_anim.h"
4#include "breathing_anim.h"
5#include "band_anim.h"
6#include "band_pinwheel_anim.h"
7#include "band_spiral_anim.h"
8#include "cycle_left_right_anim.h"
9#include "cycle_up_down_anim.h"
10#include "cycle_out_in_anim.h"
11#include "dual_beacon_anim.h"
12#include "solid_reactive_simple_anim.h"
13#include "solid_reactive_wide.h"
14#include "solid_reactive_cross.h"
15#include "solid_reactive_nexus.h"
16#include "solid_splash_anim.h"
17#include "wave_left_right_anim.h"
18#include "wave_up_down_anim.h"
diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
index ef97631b9..ef97631b9 100644
--- a/quantum/led_matrix_runners/effect_runner_dx_dy.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
index 5ef5938be..5ef5938be 100644
--- a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
diff --git a/quantum/led_matrix_runners/effect_runner_i.h b/quantum/led_matrix/animations/runners/effect_runner_i.h
index b3015759b..b3015759b 100644
--- a/quantum/led_matrix_runners/effect_runner_i.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_i.h
diff --git a/quantum/led_matrix_runners/effect_runner_reactive.h b/quantum/led_matrix/animations/runners/effect_runner_reactive.h
index 4369ea8c4..4369ea8c4 100644
--- a/quantum/led_matrix_runners/effect_runner_reactive.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_reactive.h
diff --git a/quantum/led_matrix_runners/effect_runner_reactive_splash.h b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
index d6eb9731e..d6eb9731e 100644
--- a/quantum/led_matrix_runners/effect_runner_reactive_splash.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
diff --git a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
index 4a5219abd..4a5219abd 100644
--- a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
diff --git a/quantum/led_matrix/animations/runners/led_matrix_runners.inc b/quantum/led_matrix/animations/runners/led_matrix_runners.inc
new file mode 100644
index 000000000..c09022bb0
--- /dev/null
+++ b/quantum/led_matrix/animations/runners/led_matrix_runners.inc
@@ -0,0 +1,6 @@
1#include "effect_runner_dx_dy_dist.h"
2#include "effect_runner_dx_dy.h"
3#include "effect_runner_i.h"
4#include "effect_runner_sin_cos_i.h"
5#include "effect_runner_reactive.h"
6#include "effect_runner_reactive_splash.h"
diff --git a/quantum/led_matrix_animations/solid_anim.h b/quantum/led_matrix/animations/solid_anim.h
index 4c9e43c58..4c9e43c58 100644
--- a/quantum/led_matrix_animations/solid_anim.h
+++ b/quantum/led_matrix/animations/solid_anim.h
diff --git a/quantum/led_matrix_animations/solid_reactive_cross.h b/quantum/led_matrix/animations/solid_reactive_cross.h
index f402d99b3..94425c959 100644
--- a/quantum/led_matrix_animations/solid_reactive_cross.h
+++ b/quantum/led_matrix/animations/solid_reactive_cross.h
@@ -31,5 +31,5 @@ bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_r
31# endif 31# endif
32 32
33# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 33# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
34# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) 34# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
35#endif // LED_MATRIX_KEYREACTIVE_ENABLED 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
index 4d0d25226..504b1104f 100644
--- a/quantum/led_matrix_animations/solid_reactive_nexus.h
+++ b/quantum/led_matrix/animations/solid_reactive_nexus.h
@@ -28,5 +28,5 @@ bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_r
28# endif 28# endif
29 29
30# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 30# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
31# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) 31# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
32#endif // LED_MATRIX_KEYREACTIVE_ENABLED 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
index 30e2527f6..4752a8416 100644
--- a/quantum/led_matrix_animations/solid_reactive_simple_anim.h
+++ b/quantum/led_matrix/animations/solid_reactive_simple_anim.h
@@ -8,5 +8,5 @@ static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return
8bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); } 8bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }
9 9
10# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 10# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
11# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE 11# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
12#endif // LED_MATRIX_KEYREACTIVE_ENABLED 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
index 34a230c25..922e32fe5 100644
--- a/quantum/led_matrix_animations/solid_reactive_wide.h
+++ b/quantum/led_matrix/animations/solid_reactive_wide.h
@@ -26,5 +26,5 @@ bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_re
26# endif 26# endif
27 27
28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
29# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) 29# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
30#endif // LED_MATRIX_KEYREACTIVE_ENABLED 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
index 4f6ba3d34..d95889b81 100644
--- a/quantum/led_matrix_animations/solid_splash_anim.h
+++ b/quantum/led_matrix/animations/solid_splash_anim.h
@@ -26,5 +26,5 @@ bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_
26# endif 26# endif
27 27
28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 28# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
29# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) 29# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH)
30#endif // LED_MATRIX_KEYREACTIVE_ENABLED 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
index 736f22ddc..8579f1b45 100644
--- a/quantum/led_matrix_animations/wave_left_right_anim.h
+++ b/quantum/led_matrix/animations/wave_left_right_anim.h
@@ -7,4 +7,4 @@ static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { retu
7bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); } 7bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT 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
index 3cab0597d..635c60841 100644
--- a/quantum/led_matrix_animations/wave_up_down_anim.h
+++ b/quantum/led_matrix/animations/wave_up_down_anim.h
@@ -7,4 +7,4 @@ static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return
7bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); } 7bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); }
8 8
9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS 9# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
10#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN 10#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN
diff --git a/quantum/led_matrix.c b/quantum/led_matrix/led_matrix.c
index 7e0fdf896..32788866c 100644
--- a/quantum/led_matrix.c
+++ b/quantum/led_matrix/led_matrix.c
@@ -33,20 +33,23 @@ const led_point_t k_led_matrix_center = {112, 32};
33const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; 33const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
34#endif 34#endif
35 35
36// clang-format off
37#ifndef LED_MATRIX_IMMEDIATE_EEPROM
38# define led_eeconfig_update(v) led_update_eeprom |= v
39#else
40# define led_eeconfig_update(v) if (v) eeconfig_update_led_matrix()
41#endif
42// clang-format on
43
36// Generic effect runners 44// Generic effect runners
37#include "led_matrix_runners/effect_runner_dx_dy_dist.h" 45#include "led_matrix_runners.inc"
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 46
44// ------------------------------------------ 47// ------------------------------------------
45// -----Begin led effect includes macros----- 48// -----Begin led effect includes macros-----
46#define LED_MATRIX_EFFECT(name) 49#define LED_MATRIX_EFFECT(name)
47#define LED_MATRIX_CUSTOM_EFFECT_IMPLS 50#define LED_MATRIX_CUSTOM_EFFECT_IMPLS
48 51
49#include "led_matrix_animations/led_matrix_effects.inc" 52#include "led_matrix_effects.inc"
50#ifdef LED_MATRIX_CUSTOM_KB 53#ifdef LED_MATRIX_CUSTOM_KB
51# include "led_matrix_kb.inc" 54# include "led_matrix_kb.inc"
52#endif 55#endif
@@ -67,10 +70,6 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
67# define LED_DISABLE_TIMEOUT 0 70# define LED_DISABLE_TIMEOUT 0
68#endif 71#endif
69 72
70#if LED_DISABLE_WHEN_USB_SUSPENDED != 1
71# undef LED_DISABLE_WHEN_USB_SUSPENDED
72#endif
73
74#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX 73#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
75# undef LED_MATRIX_MAXIMUM_BRIGHTNESS 74# undef LED_MATRIX_MAXIMUM_BRIGHTNESS
76# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX 75# define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
@@ -108,6 +107,7 @@ last_hit_t g_last_hit_tracker;
108 107
109// internals 108// internals
110static bool suspend_state = false; 109static bool suspend_state = false;
110static bool led_update_eeprom = false;
111static uint8_t led_last_enable = UINT8_MAX; 111static uint8_t led_last_enable = UINT8_MAX;
112static uint8_t led_last_effect = UINT8_MAX; 112static uint8_t led_last_effect = UINT8_MAX;
113static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; 113static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false};
@@ -280,6 +280,8 @@ static void led_task_timers(void) {
280 280
281static void led_task_sync(void) { 281static void led_task_sync(void) {
282 // next task 282 // next task
283 if (led_update_eeprom) eeconfig_update_led_matrix();
284 led_update_eeprom = false;
283 if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING; 285 if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING;
284} 286}
285 287
@@ -318,7 +320,7 @@ static void led_task_render(uint8_t effect) {
318 case LED_MATRIX_##name: \ 320 case LED_MATRIX_##name: \
319 rendering = name(&led_effect_params); \ 321 rendering = name(&led_effect_params); \
320 break; 322 break;
321#include "led_matrix_animations/led_matrix_effects.inc" 323#include "led_matrix_effects.inc"
322#undef LED_MATRIX_EFFECT 324#undef LED_MATRIX_EFFECT
323 325
324#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) 326#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
@@ -469,9 +471,7 @@ bool led_matrix_get_suspend_state(void) { return suspend_state; }
469void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { 471void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
470 led_matrix_eeconfig.enable ^= 1; 472 led_matrix_eeconfig.enable ^= 1;
471 led_task_state = STARTING; 473 led_task_state = STARTING;
472 if (write_to_eeprom) { 474 led_eeconfig_update(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); 475 dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable);
476} 476}
477void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); } 477void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); }
@@ -479,7 +479,7 @@ void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); }
479 479
480void led_matrix_enable(void) { 480void led_matrix_enable(void) {
481 led_matrix_enable_noeeprom(); 481 led_matrix_enable_noeeprom();
482 eeconfig_update_led_matrix(); 482 led_eeconfig_update(true);
483} 483}
484 484
485void led_matrix_enable_noeeprom(void) { 485void led_matrix_enable_noeeprom(void) {
@@ -489,7 +489,7 @@ void led_matrix_enable_noeeprom(void) {
489 489
490void led_matrix_disable(void) { 490void led_matrix_disable(void) {
491 led_matrix_disable_noeeprom(); 491 led_matrix_disable_noeeprom();
492 eeconfig_update_led_matrix(); 492 led_eeconfig_update(true);
493} 493}
494 494
495void led_matrix_disable_noeeprom(void) { 495void led_matrix_disable_noeeprom(void) {
@@ -511,9 +511,7 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
511 led_matrix_eeconfig.mode = mode; 511 led_matrix_eeconfig.mode = mode;
512 } 512 }
513 led_task_state = STARTING; 513 led_task_state = STARTING;
514 if (write_to_eeprom) { 514 led_eeconfig_update(write_to_eeprom);
515 eeconfig_update_led_matrix();
516 }
517 dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode); 515 dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);
518} 516}
519void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); } 517void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); }
@@ -540,9 +538,7 @@ void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) {
540 return; 538 return;
541 } 539 }
542 led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; 540 led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val;
543 if (write_to_eeprom) { 541 led_eeconfig_update(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); 542 dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val);
547} 543}
548void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); } 544void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); }
@@ -560,9 +556,7 @@ void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); }
560 556
561void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { 557void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
562 led_matrix_eeconfig.speed = speed; 558 led_matrix_eeconfig.speed = speed;
563 if (write_to_eeprom) { 559 led_eeconfig_update(write_to_eeprom);
564 eeconfig_update_led_matrix();
565 }
566 dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed); 560 dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed);
567} 561}
568void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); } 562void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); }
diff --git a/quantum/led_matrix.h b/quantum/led_matrix/led_matrix.h
index 0984de73b..6f85854fb 100644
--- a/quantum/led_matrix.h
+++ b/quantum/led_matrix/led_matrix.h
@@ -56,7 +56,7 @@ enum led_matrix_effects {
56// -------------------------------------- 56// --------------------------------------
57// -----Begin led effect enum macros----- 57// -----Begin led effect enum macros-----
58#define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name, 58#define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name,
59#include "led_matrix_animations/led_matrix_effects.inc" 59#include "led_matrix_effects.inc"
60#undef LED_MATRIX_EFFECT 60#undef LED_MATRIX_EFFECT
61 61
62#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) 62#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c
index 1d46b2c50..1d46b2c50 100644
--- a/quantum/led_matrix_drivers.c
+++ b/quantum/led_matrix/led_matrix_drivers.c
diff --git a/quantum/led_matrix_types.h b/quantum/led_matrix/led_matrix_types.h
index 61cdbd9b8..61cdbd9b8 100644
--- a/quantum/led_matrix_types.h
+++ b/quantum/led_matrix/led_matrix_types.h
diff --git a/quantum/led_matrix_animations/led_matrix_effects.inc b/quantum/led_matrix_animations/led_matrix_effects.inc
deleted file mode 100644
index 67237c568..000000000
--- a/quantum/led_matrix_animations/led_matrix_effects.inc
+++ /dev/null
@@ -1,18 +0,0 @@
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/matrix.c b/quantum/matrix.c
index 34d6af2e6..ed4643f81 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -16,22 +16,69 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17#include <stdint.h> 17#include <stdint.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <string.h>
19#include "util.h" 20#include "util.h"
20#include "matrix.h" 21#include "matrix.h"
21#include "debounce.h" 22#include "debounce.h"
22#include "quantum.h" 23#include "quantum.h"
24#ifdef SPLIT_KEYBOARD
25# include "split_common/split_util.h"
26# include "split_common/transactions.h"
27
28# ifndef ERROR_DISCONNECT_COUNT
29# define ERROR_DISCONNECT_COUNT 5
30# endif // ERROR_DISCONNECT_COUNT
31
32# define ROWS_PER_HAND (MATRIX_ROWS / 2)
33#else
34# define ROWS_PER_HAND (MATRIX_ROWS)
35#endif
36
37#ifdef DIRECT_PINS_RIGHT
38# define SPLIT_MUTABLE
39#else
40# define SPLIT_MUTABLE const
41#endif
42#ifdef MATRIX_ROW_PINS_RIGHT
43# define SPLIT_MUTABLE_ROW
44#else
45# define SPLIT_MUTABLE_ROW const
46#endif
47#ifdef MATRIX_COL_PINS_RIGHT
48# define SPLIT_MUTABLE_COL
49#else
50# define SPLIT_MUTABLE_COL const
51#endif
23 52
24#ifdef DIRECT_PINS 53#ifdef DIRECT_PINS
25static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; 54static SPLIT_MUTABLE pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
26#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 55#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
27static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 56# ifdef MATRIX_ROW_PINS
28static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 57static SPLIT_MUTABLE_ROW pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
58# endif // MATRIX_ROW_PINS
59# ifdef MATRIX_COL_PINS
60static SPLIT_MUTABLE_COL pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
61# endif // MATRIX_COL_PINS
29#endif 62#endif
30 63
31/* matrix state(1:on, 0:off) */ 64/* matrix state(1:on, 0:off) */
32extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values 65extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
33extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values 66extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
34 67
68#ifdef SPLIT_KEYBOARD
69// row offsets for each hand
70uint8_t thisHand, thatHand;
71#endif
72
73// user-defined overridable functions
74__attribute__((weak)) void matrix_init_pins(void);
75__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
76__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
77#ifdef SPLIT_KEYBOARD
78__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
79__attribute__((weak)) void matrix_slave_scan_user(void) {}
80#endif
81
35static inline void setPinOutput_writeLow(pin_t pin) { 82static inline void setPinOutput_writeLow(pin_t pin) {
36 ATOMIC_BLOCK_FORCEON { 83 ATOMIC_BLOCK_FORCEON {
37 setPinOutput(pin); 84 setPinOutput(pin);
@@ -43,11 +90,19 @@ static inline void setPinInputHigh_atomic(pin_t pin) {
43 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); } 90 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }
44} 91}
45 92
93static inline uint8_t readMatrixPin(pin_t pin) {
94 if (pin != NO_PIN) {
95 return readPin(pin);
96 } else {
97 return 1;
98 }
99}
100
46// matrix code 101// matrix code
47 102
48#ifdef DIRECT_PINS 103#ifdef DIRECT_PINS
49 104
50static void init_pins(void) { 105__attribute__((weak)) void matrix_init_pins(void) {
51 for (int row = 0; row < MATRIX_ROWS; row++) { 106 for (int row = 0; row < MATRIX_ROWS; row++) {
52 for (int col = 0; col < MATRIX_COLS; col++) { 107 for (int col = 0; col < MATRIX_COLS; col++) {
53 pin_t pin = direct_pins[row][col]; 108 pin_t pin = direct_pins[row][col];
@@ -58,7 +113,7 @@ static void init_pins(void) {
58 } 113 }
59} 114}
60 115
61static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 116__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
62 // Start with a clear matrix row 117 // Start with a clear matrix row
63 matrix_row_t current_row_value = 0; 118 matrix_row_t current_row_value = 0;
64 119
@@ -69,46 +124,57 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
69 } 124 }
70 } 125 }
71 126
72 // If the row has changed, store the row and return the changed flag. 127 // Update the matrix
73 if (current_matrix[current_row] != current_row_value) { 128 current_matrix[current_row] = current_row_value;
74 current_matrix[current_row] = current_row_value;
75 return true;
76 }
77 return false;
78} 129}
79 130
80#elif defined(DIODE_DIRECTION) 131#elif defined(DIODE_DIRECTION)
81# if (DIODE_DIRECTION == COL2ROW) 132# if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
133# if (DIODE_DIRECTION == COL2ROW)
82 134
83static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } 135static bool select_row(uint8_t row) {
136 pin_t pin = row_pins[row];
137 if (pin != NO_PIN) {
138 setPinOutput_writeLow(pin);
139 return true;
140 }
141 return false;
142}
84 143
85static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); } 144static void unselect_row(uint8_t row) {
145 pin_t pin = row_pins[row];
146 if (pin != NO_PIN) {
147 setPinInputHigh_atomic(pin);
148 }
149}
86 150
87static void unselect_rows(void) { 151static void unselect_rows(void) {
88 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 152 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
89 setPinInputHigh_atomic(row_pins[x]); 153 unselect_row(x);
90 } 154 }
91} 155}
92 156
93static void init_pins(void) { 157__attribute__((weak)) void matrix_init_pins(void) {
94 unselect_rows(); 158 unselect_rows();
95 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 159 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
96 setPinInputHigh_atomic(col_pins[x]); 160 if (col_pins[x] != NO_PIN) {
161 setPinInputHigh_atomic(col_pins[x]);
162 }
97 } 163 }
98} 164}
99 165
100static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 166__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
101 // Start with a clear matrix row 167 // Start with a clear matrix row
102 matrix_row_t current_row_value = 0; 168 matrix_row_t current_row_value = 0;
103 169
104 // Select row 170 if (!select_row(current_row)) { // Select row
105 select_row(current_row); 171 return; // skip NO_PIN row
172 }
106 matrix_output_select_delay(); 173 matrix_output_select_delay();
107 174
108 // For each col... 175 // For each col...
109 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 176 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
110 // Select the col pin to read (active low) 177 uint8_t pin_state = readMatrixPin(col_pins[col_index]);
111 uint8_t pin_state = readPin(col_pins[col_index]);
112 178
113 // Populate the matrix row with the state of the col pin 179 // Populate the matrix row with the state of the col pin
114 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); 180 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
@@ -118,79 +184,109 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
118 unselect_row(current_row); 184 unselect_row(current_row);
119 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH 185 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH
120 186
121 // If the row has changed, store the row and return the changed flag. 187 // Update the matrix
122 if (current_matrix[current_row] != current_row_value) { 188 current_matrix[current_row] = current_row_value;
123 current_matrix[current_row] = current_row_value; 189}
190
191# elif (DIODE_DIRECTION == ROW2COL)
192
193static bool select_col(uint8_t col) {
194 pin_t pin = col_pins[col];
195 if (pin != NO_PIN) {
196 setPinOutput_writeLow(pin);
124 return true; 197 return true;
125 } 198 }
126 return false; 199 return false;
127} 200}
128 201
129# elif (DIODE_DIRECTION == ROW2COL) 202static void unselect_col(uint8_t col) {
130 203 pin_t pin = col_pins[col];
131static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } 204 if (pin != NO_PIN) {
132 205 setPinInputHigh_atomic(pin);
133static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); } 206 }
207}
134 208
135static void unselect_cols(void) { 209static void unselect_cols(void) {
136 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 210 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
137 setPinInputHigh_atomic(col_pins[x]); 211 unselect_col(x);
138 } 212 }
139} 213}
140 214
141static void init_pins(void) { 215__attribute__((weak)) void matrix_init_pins(void) {
142 unselect_cols(); 216 unselect_cols();
143 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 217 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
144 setPinInputHigh_atomic(row_pins[x]); 218 if (row_pins[x] != NO_PIN) {
219 setPinInputHigh_atomic(row_pins[x]);
220 }
145 } 221 }
146} 222}
147 223
148static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 224__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
149 bool matrix_changed = false;
150
151 // Select col 225 // Select col
152 select_col(current_col); 226 if (!select_col(current_col)) { // select col
227 return; // skip NO_PIN col
228 }
153 matrix_output_select_delay(); 229 matrix_output_select_delay();
154 230
155 // For each row... 231 // For each row...
156 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 232 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
157 // Store last value of row prior to reading
158 matrix_row_t last_row_value = current_matrix[row_index];
159 matrix_row_t current_row_value = last_row_value;
160
161 // Check row pin state 233 // Check row pin state
162 if (readPin(row_pins[row_index]) == 0) { 234 if (readMatrixPin(row_pins[row_index]) == 0) {
163 // Pin LO, set col bit 235 // Pin LO, set col bit
164 current_row_value |= (MATRIX_ROW_SHIFTER << current_col); 236 current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
165 } else { 237 } else {
166 // Pin HI, clear col bit 238 // Pin HI, clear col bit
167 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); 239 current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
168 }
169
170 // Determine if the matrix changed state
171 if ((last_row_value != current_row_value)) {
172 matrix_changed |= true;
173 current_matrix[row_index] = current_row_value;
174 } 240 }
175 } 241 }
176 242
177 // Unselect col 243 // Unselect col
178 unselect_col(current_col); 244 unselect_col(current_col);
179 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH 245 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
180
181 return matrix_changed;
182} 246}
183 247
184# else 248# else
185# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! 249# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
186# endif 250# endif
251# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
187#else 252#else
188# error DIODE_DIRECTION is not defined! 253# error DIODE_DIRECTION is not defined!
189#endif 254#endif
190 255
191void matrix_init(void) { 256void matrix_init(void) {
257#ifdef SPLIT_KEYBOARD
258 split_pre_init();
259
260 // Set pinout for right half if pinout for that half is defined
261 if (!isLeftHand) {
262# ifdef DIRECT_PINS_RIGHT
263 const pin_t direct_pins_right[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS_RIGHT;
264 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
265 for (uint8_t j = 0; j < MATRIX_COLS; j++) {
266 direct_pins[i][j] = direct_pins_right[i][j];
267 }
268 }
269# endif
270# ifdef MATRIX_ROW_PINS_RIGHT
271 const pin_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
272 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
273 row_pins[i] = row_pins_right[i];
274 }
275# endif
276# ifdef MATRIX_COL_PINS_RIGHT
277 const pin_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
278 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
279 col_pins[i] = col_pins_right[i];
280 }
281# endif
282 }
283
284 thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
285 thatHand = ROWS_PER_HAND - thisHand;
286#endif
287
192 // initialize key pins 288 // initialize key pins
193 init_pins(); 289 matrix_init_pins();
194 290
195 // initialize matrix state: all keys off 291 // initialize matrix state: all keys off
196 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 292 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
@@ -198,28 +294,80 @@ void matrix_init(void) {
198 matrix[i] = 0; 294 matrix[i] = 0;
199 } 295 }
200 296
201 debounce_init(MATRIX_ROWS); 297 debounce_init(ROWS_PER_HAND);
202 298
203 matrix_init_quantum(); 299 matrix_init_quantum();
300
301#ifdef SPLIT_KEYBOARD
302 split_post_init();
303#endif
204} 304}
205 305
206uint8_t matrix_scan(void) { 306#ifdef SPLIT_KEYBOARD
307bool matrix_post_scan(void) {
207 bool changed = false; 308 bool changed = false;
309 if (is_keyboard_master()) {
310 static uint8_t error_count;
311
312 matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
313 if (!transport_master(matrix + thisHand, slave_matrix)) {
314 error_count++;
315
316 if (error_count > ERROR_DISCONNECT_COUNT) {
317 // reset other half if disconnected
318 for (int i = 0; i < ROWS_PER_HAND; ++i) {
319 matrix[thatHand + i] = 0;
320 slave_matrix[i] = 0;
321 }
322
323 changed = true;
324 }
325 } else {
326 error_count = 0;
327
328 for (int i = 0; i < ROWS_PER_HAND; ++i) {
329 if (matrix[thatHand + i] != slave_matrix[i]) {
330 matrix[thatHand + i] = slave_matrix[i];
331 changed = true;
332 }
333 }
334 }
335
336 matrix_scan_quantum();
337 } else {
338 transport_slave(matrix + thatHand, matrix + thisHand);
339
340 matrix_slave_scan_kb();
341 }
342
343 return changed;
344}
345#endif
346
347uint8_t matrix_scan(void) {
348 matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
208 349
209#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 350#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
210 // Set row, read cols 351 // Set row, read cols
211 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 352 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
212 changed |= read_cols_on_row(raw_matrix, current_row); 353 matrix_read_cols_on_row(curr_matrix, current_row);
213 } 354 }
214#elif (DIODE_DIRECTION == ROW2COL) 355#elif (DIODE_DIRECTION == ROW2COL)
215 // Set col, read rows 356 // Set col, read rows
216 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 357 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
217 changed |= read_rows_on_col(raw_matrix, current_col); 358 matrix_read_rows_on_col(curr_matrix, current_col);
218 } 359 }
219#endif 360#endif
220 361
221 debounce(raw_matrix, matrix, MATRIX_ROWS, changed); 362 bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
363 if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix));
222 364
365#ifdef SPLIT_KEYBOARD
366 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
367 changed = (changed || matrix_post_scan());
368#else
369 debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
223 matrix_scan_quantum(); 370 matrix_scan_quantum();
371#endif
224 return (uint8_t)changed; 372 return (uint8_t)changed;
225} 373}
diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk
index 9268c4522..ca0accd71 100644
--- a/quantum/mcu_selection.mk
+++ b/quantum/mcu_selection.mk
@@ -136,10 +136,6 @@ ifneq ($(findstring STM32F042, $(MCU)),)
136 136
137 USE_FPU ?= no 137 USE_FPU ?= no
138 138
139 # Options to pass to dfu-util when flashing
140 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
141 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
142
143 # UF2 settings 139 # UF2 settings
144 UF2_FAMILY ?= STM32F0 140 UF2_FAMILY ?= STM32F0
145endif 141endif
@@ -172,10 +168,6 @@ ifneq ($(findstring STM32F072, $(MCU)),)
172 168
173 USE_FPU ?= no 169 USE_FPU ?= no
174 170
175 # Options to pass to dfu-util when flashing
176 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
177 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
178
179 # UF2 settings 171 # UF2 settings
180 UF2_FAMILY ?= STM32F0 172 UF2_FAMILY ?= STM32F0
181endif 173endif
@@ -208,10 +200,6 @@ ifneq ($(findstring STM32F103, $(MCU)),)
208 200
209 USE_FPU ?= no 201 USE_FPU ?= no
210 202
211 # Options to pass to dfu-util when flashing
212 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
213 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
214
215 # UF2 settings 203 # UF2 settings
216 UF2_FAMILY ?= STM32F1 204 UF2_FAMILY ?= STM32F1
217endif 205endif
@@ -244,10 +232,6 @@ ifneq ($(findstring STM32F303, $(MCU)),)
244 232
245 USE_FPU ?= yes 233 USE_FPU ?= yes
246 234
247 # Options to pass to dfu-util when flashing
248 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
249 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
250
251 # UF2 settings 235 # UF2 settings
252 UF2_FAMILY ?= STM32F3 236 UF2_FAMILY ?= STM32F3
253endif 237endif
@@ -280,10 +264,6 @@ ifneq ($(findstring STM32F401, $(MCU)),)
280 264
281 USE_FPU ?= yes 265 USE_FPU ?= yes
282 266
283 # Options to pass to dfu-util when flashing
284 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
285 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
286
287 # UF2 settings 267 # UF2 settings
288 UF2_FAMILY ?= STM32F4 268 UF2_FAMILY ?= STM32F4
289endif 269endif
@@ -321,10 +301,6 @@ ifneq ($(findstring STM32F411, $(MCU)),)
321 301
322 USE_FPU ?= yes 302 USE_FPU ?= yes
323 303
324 # Options to pass to dfu-util when flashing
325 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
326 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
327
328 # UF2 settings 304 # UF2 settings
329 UF2_FAMILY ?= STM32F4 305 UF2_FAMILY ?= STM32F4
330endif 306endif
@@ -357,10 +333,6 @@ ifneq ($(findstring STM32F446, $(MCU)),)
357 BOARD ?= GENERIC_STM32_F446XE 333 BOARD ?= GENERIC_STM32_F446XE
358 334
359 USE_FPU ?= yes 335 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
364endif 336endif
365 337
366ifneq ($(findstring STM32G431, $(MCU)),) 338ifneq ($(findstring STM32G431, $(MCU)),)
@@ -391,10 +363,6 @@ ifneq ($(findstring STM32G431, $(MCU)),)
391 363
392 USE_FPU ?= yes 364 USE_FPU ?= yes
393 365
394 # Options to pass to dfu-util when flashing
395 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
396 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
397
398 # UF2 settings 366 # UF2 settings
399 UF2_FAMILY ?= STM32G4 367 UF2_FAMILY ?= STM32G4
400endif 368endif
@@ -427,10 +395,6 @@ ifneq ($(findstring STM32G474, $(MCU)),)
427 395
428 USE_FPU ?= yes 396 USE_FPU ?= yes
429 397
430 # Options to pass to dfu-util when flashing
431 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
432 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
433
434 # UF2 settings 398 # UF2 settings
435 UF2_FAMILY ?= STM32G4 399 UF2_FAMILY ?= STM32G4
436endif 400endif
@@ -465,9 +429,39 @@ ifneq (,$(filter $(MCU),STM32L433 STM32L443))
465 429
466 USE_FPU ?= yes 430 USE_FPU ?= yes
467 431
468 # Options to pass to dfu-util when flashing 432 # UF2 settings
469 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave 433 UF2_FAMILY ?= STM32L4
470 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 434endif
435
436ifneq (,$(filter $(MCU),STM32L412 STM32L422))
437 # Cortex version
438 MCU = cortex-m4
439
440 # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
441 ARMV = 7
442
443 ## chip/board settings
444 # - the next two should match the directories in
445 # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
446 MCU_FAMILY = STM32
447 MCU_SERIES = STM32L4xx
448
449 # Linker script to use
450 # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
451 # or <keyboard_dir>/ld/
452 MCU_LDSCRIPT ?= STM32L412xB
453
454 # Startup code to use
455 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
456 MCU_STARTUP ?= stm32l4xx
457
458 # Board: it should exist either in <chibios>/os/hal/boards/,
459 # <keyboard_dir>/boards/, or drivers/boards/
460 BOARD ?= GENERIC_STM32_L412XB
461
462 PLATFORM_NAME ?= platform_l432
463
464 USE_FPU ?= yes
471 465
472 # UF2 settings 466 # UF2 settings
473 UF2_FAMILY ?= STM32L4 467 UF2_FAMILY ?= STM32L4
diff --git a/quantum/mousekey.c b/quantum/mousekey.c
index 99bfd6b96..c2291fb39 100644
--- a/quantum/mousekey.c
+++ b/quantum/mousekey.c
@@ -486,3 +486,5 @@ static void mousekey_debug(void) {
486 print_dec(mousekey_accel); 486 print_dec(mousekey_accel);
487 print(")\n"); 487 print(")\n");
488} 488}
489
490report_mouse_t mousekey_get_report(void) { return mouse_report; }
diff --git a/quantum/mousekey.h b/quantum/mousekey.h
index 70dc4bb5c..56c91b5f1 100644
--- a/quantum/mousekey.h
+++ b/quantum/mousekey.h
@@ -168,11 +168,12 @@ extern uint8_t mk_time_to_max;
168extern uint8_t mk_wheel_max_speed; 168extern uint8_t mk_wheel_max_speed;
169extern uint8_t mk_wheel_time_to_max; 169extern uint8_t mk_wheel_time_to_max;
170 170
171void mousekey_task(void); 171void mousekey_task(void);
172void mousekey_on(uint8_t code); 172void mousekey_on(uint8_t code);
173void mousekey_off(uint8_t code); 173void mousekey_off(uint8_t code);
174void mousekey_clear(void); 174void mousekey_clear(void);
175void mousekey_send(void); 175void mousekey_send(void);
176report_mouse_t mousekey_get_report(void);
176 177
177#ifdef __cplusplus 178#ifdef __cplusplus
178} 179}
diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c
index 167c0c03c..b9fee1ca5 100644
--- a/quantum/process_keycode/process_rgb.c
+++ b/quantum/process_keycode/process_rgb.c
@@ -14,7 +14,6 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 15 */
16#include "process_rgb.h" 16#include "process_rgb.h"
17#include "rgb.h"
18 17
19typedef void (*rgb_func_pointer)(void); 18typedef void (*rgb_func_pointer)(void);
20 19
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 8ccdb774b..b4cfa28d7 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -340,13 +340,13 @@ void set_single_persistent_default_layer(uint8_t default_layer) {
340#if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS) 340#if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS)
341 PLAY_SONG(default_layer_songs[default_layer]); 341 PLAY_SONG(default_layer_songs[default_layer]);
342#endif 342#endif
343 eeconfig_update_default_layer(1U << default_layer); 343 eeconfig_update_default_layer((layer_state_t)1 << default_layer);
344 default_layer_set(1U << default_layer); 344 default_layer_set((layer_state_t)1 << default_layer);
345} 345}
346 346
347layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) { 347layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) {
348 layer_state_t mask12 = (1UL << layer1) | (1UL << layer2); 348 layer_state_t mask12 = ((layer_state_t)1 << layer1) | ((layer_state_t)1 << layer2);
349 layer_state_t mask3 = 1UL << layer3; 349 layer_state_t mask3 = (layer_state_t)1 << layer3;
350 return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3); 350 return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);
351} 351}
352 352
diff --git a/quantum/quantum.h b/quantum/quantum.h
index e4a7c5723..66ba96fde 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -176,6 +176,10 @@ extern layer_state_t layer_state;
176# include "oled_driver.h" 176# include "oled_driver.h"
177#endif 177#endif
178 178
179#ifdef ST7565_ENABLE
180# include "st7565.h"
181#endif
182
179#ifdef DIP_SWITCH_ENABLE 183#ifdef DIP_SWITCH_ENABLE
180# include "dip_switch.h" 184# include "dip_switch.h"
181#endif 185#endif
diff --git a/quantum/rgb_matrix_animations/alpha_mods_anim.h b/quantum/rgb_matrix/animations/alpha_mods_anim.h
index 426d88ef3..426d88ef3 100644
--- a/quantum/rgb_matrix_animations/alpha_mods_anim.h
+++ b/quantum/rgb_matrix/animations/alpha_mods_anim.h
diff --git a/quantum/rgb_matrix_animations/breathing_anim.h b/quantum/rgb_matrix/animations/breathing_anim.h
index 340bd93e5..340bd93e5 100644
--- a/quantum/rgb_matrix_animations/breathing_anim.h
+++ b/quantum/rgb_matrix/animations/breathing_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_pinwheel_sat_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
index 3df3cfda7..3df3cfda7 100644
--- a/quantum/rgb_matrix_animations/colorband_pinwheel_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_pinwheel_val_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
index 7d80074fd..7d80074fd 100644
--- a/quantum/rgb_matrix_animations/colorband_pinwheel_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_sat_anim.h b/quantum/rgb_matrix/animations/colorband_sat_anim.h
index 35b830af6..35b830af6 100644
--- a/quantum/rgb_matrix_animations/colorband_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_sat_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_spiral_sat_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
index 048157aa1..048157aa1 100644
--- a/quantum/rgb_matrix_animations/colorband_spiral_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_spiral_val_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
index bff2da161..bff2da161 100644
--- a/quantum/rgb_matrix_animations/colorband_spiral_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
diff --git a/quantum/rgb_matrix_animations/colorband_val_anim.h b/quantum/rgb_matrix/animations/colorband_val_anim.h
index f1aaf1d06..f1aaf1d06 100644
--- a/quantum/rgb_matrix_animations/colorband_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_val_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_all_anim.h b/quantum/rgb_matrix/animations/cycle_all_anim.h
index faf8598a3..faf8598a3 100644
--- a/quantum/rgb_matrix_animations/cycle_all_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_all_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_left_right_anim.h b/quantum/rgb_matrix/animations/cycle_left_right_anim.h
index cf911eb93..cf911eb93 100644
--- a/quantum/rgb_matrix_animations/cycle_left_right_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_left_right_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_out_in_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_anim.h
index d66acd4b2..d66acd4b2 100644
--- a/quantum/rgb_matrix_animations/cycle_out_in_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_out_in_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_out_in_dual_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h
index fe8396140..fe8396140 100644
--- a/quantum/rgb_matrix_animations/cycle_out_in_dual_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_pinwheel_anim.h b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
index 779988709..779988709 100644
--- a/quantum/rgb_matrix_animations/cycle_pinwheel_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_spiral_anim.h b/quantum/rgb_matrix/animations/cycle_spiral_anim.h
index 80cfb0dbc..80cfb0dbc 100644
--- a/quantum/rgb_matrix_animations/cycle_spiral_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_spiral_anim.h
diff --git a/quantum/rgb_matrix_animations/cycle_up_down_anim.h b/quantum/rgb_matrix/animations/cycle_up_down_anim.h
index 5016f739d..5016f739d 100644
--- a/quantum/rgb_matrix_animations/cycle_up_down_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_up_down_anim.h
diff --git a/quantum/rgb_matrix_animations/digital_rain_anim.h b/quantum/rgb_matrix/animations/digital_rain_anim.h
index 1de45f8e8..1de45f8e8 100644
--- a/quantum/rgb_matrix_animations/digital_rain_anim.h
+++ b/quantum/rgb_matrix/animations/digital_rain_anim.h
diff --git a/quantum/rgb_matrix_animations/dual_beacon_anim.h b/quantum/rgb_matrix/animations/dual_beacon_anim.h
index ce9487168..ce9487168 100644
--- a/quantum/rgb_matrix_animations/dual_beacon_anim.h
+++ b/quantum/rgb_matrix/animations/dual_beacon_anim.h
diff --git a/quantum/rgb_matrix_animations/gradient_left_right_anim.h b/quantum/rgb_matrix/animations/gradient_left_right_anim.h
index 53dfd04e2..53dfd04e2 100644
--- a/quantum/rgb_matrix_animations/gradient_left_right_anim.h
+++ b/quantum/rgb_matrix/animations/gradient_left_right_anim.h
diff --git a/quantum/rgb_matrix_animations/gradient_up_down_anim.h b/quantum/rgb_matrix/animations/gradient_up_down_anim.h
index 7e0d2898c..7e0d2898c 100644
--- a/quantum/rgb_matrix_animations/gradient_up_down_anim.h
+++ b/quantum/rgb_matrix/animations/gradient_up_down_anim.h
diff --git a/quantum/rgb_matrix_animations/hue_breathing_anim.h b/quantum/rgb_matrix/animations/hue_breathing_anim.h
index 54dea958a..54dea958a 100644
--- a/quantum/rgb_matrix_animations/hue_breathing_anim.h
+++ b/quantum/rgb_matrix/animations/hue_breathing_anim.h
diff --git a/quantum/rgb_matrix_animations/hue_pendulum_anim.h b/quantum/rgb_matrix/animations/hue_pendulum_anim.h
index 2d8d36174..2d8d36174 100644
--- a/quantum/rgb_matrix_animations/hue_pendulum_anim.h
+++ b/quantum/rgb_matrix/animations/hue_pendulum_anim.h
diff --git a/quantum/rgb_matrix_animations/hue_wave_anim.h b/quantum/rgb_matrix/animations/hue_wave_anim.h
index fd9026fc9..fd9026fc9 100644
--- a/quantum/rgb_matrix_animations/hue_wave_anim.h
+++ b/quantum/rgb_matrix/animations/hue_wave_anim.h
diff --git a/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
index 9493b3850..a17e954b1 100644
--- a/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h
+++ b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
@@ -4,7 +4,7 @@ RGB_MATRIX_EFFECT(JELLYBEAN_RAINDROPS)
4 4
5static void jellybean_raindrops_set_color(int i, effect_params_t* params) { 5static void jellybean_raindrops_set_color(int i, effect_params_t* params) {
6 if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) return; 6 if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) return;
7 HSV hsv = {rand() & 0xFF, rand() & 0xFF, rgb_matrix_config.hsv.v}; 7 HSV hsv = {rand() & 0xFF, qadd8(rand() & 0x7F, 0x80), rgb_matrix_config.hsv.v};
8 RGB rgb = rgb_matrix_hsv_to_rgb(hsv); 8 RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
9 rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); 9 rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
10} 10}
diff --git a/quantum/rgb_matrix_animations/rainbow_beacon_anim.h b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
index 977261182..977261182 100644
--- a/quantum/rgb_matrix_animations/rainbow_beacon_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
diff --git a/quantum/rgb_matrix_animations/rainbow_moving_chevron_anim.h b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
index e51e7b251..e51e7b251 100644
--- a/quantum/rgb_matrix_animations/rainbow_moving_chevron_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
diff --git a/quantum/rgb_matrix_animations/rainbow_pinwheels_anim.h b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
index 1cd4ed2ac..1cd4ed2ac 100644
--- a/quantum/rgb_matrix_animations/rainbow_pinwheels_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
diff --git a/quantum/rgb_matrix_animations/raindrops_anim.h b/quantum/rgb_matrix/animations/raindrops_anim.h
index 38359cdca..38359cdca 100644
--- a/quantum/rgb_matrix_animations/raindrops_anim.h
+++ b/quantum/rgb_matrix/animations/raindrops_anim.h
diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
new file mode 100644
index 000000000..302ad79c0
--- /dev/null
+++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
@@ -0,0 +1,37 @@
1// Add your new core rgb matrix effect here, order determines enum order
2#include "solid_color_anim.h"
3#include "alpha_mods_anim.h"
4#include "gradient_up_down_anim.h"
5#include "gradient_left_right_anim.h"
6#include "breathing_anim.h"
7#include "colorband_sat_anim.h"
8#include "colorband_val_anim.h"
9#include "colorband_pinwheel_sat_anim.h"
10#include "colorband_pinwheel_val_anim.h"
11#include "colorband_spiral_sat_anim.h"
12#include "colorband_spiral_val_anim.h"
13#include "cycle_all_anim.h"
14#include "cycle_left_right_anim.h"
15#include "cycle_up_down_anim.h"
16#include "rainbow_moving_chevron_anim.h"
17#include "cycle_out_in_anim.h"
18#include "cycle_out_in_dual_anim.h"
19#include "cycle_pinwheel_anim.h"
20#include "cycle_spiral_anim.h"
21#include "dual_beacon_anim.h"
22#include "rainbow_beacon_anim.h"
23#include "rainbow_pinwheels_anim.h"
24#include "raindrops_anim.h"
25#include "jellybean_raindrops_anim.h"
26#include "hue_breathing_anim.h"
27#include "hue_pendulum_anim.h"
28#include "hue_wave_anim.h"
29#include "typing_heatmap_anim.h"
30#include "digital_rain_anim.h"
31#include "solid_reactive_simple_anim.h"
32#include "solid_reactive_anim.h"
33#include "solid_reactive_wide.h"
34#include "solid_reactive_cross.h"
35#include "solid_reactive_nexus.h"
36#include "splash_anim.h"
37#include "solid_splash_anim.h"
diff --git a/quantum/rgb_matrix_runners/effect_runner_dx_dy.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
index 4867609c8..4867609c8 100644
--- a/quantum/rgb_matrix_runners/effect_runner_dx_dy.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
index 9545b418d..9545b418d 100644
--- a/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_i.h
index 1881cd6c6..1881cd6c6 100644
--- a/quantum/rgb_matrix_runners/effect_runner_i.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_i.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_reactive.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
index 75b7c0df4..75b7c0df4 100644
--- a/quantum/rgb_matrix_runners/effect_runner_reactive.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
index 2e46ffb35..2e46ffb35 100644
--- a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
diff --git a/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
index 02351de51..02351de51 100644
--- a/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
diff --git a/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc b/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc
new file mode 100644
index 000000000..c09022bb0
--- /dev/null
+++ b/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc
@@ -0,0 +1,6 @@
1#include "effect_runner_dx_dy_dist.h"
2#include "effect_runner_dx_dy.h"
3#include "effect_runner_i.h"
4#include "effect_runner_sin_cos_i.h"
5#include "effect_runner_reactive.h"
6#include "effect_runner_reactive_splash.h"
diff --git a/quantum/rgb_matrix_animations/solid_color_anim.h b/quantum/rgb_matrix/animations/solid_color_anim.h
index 79d63cf13..79d63cf13 100644
--- a/quantum/rgb_matrix_animations/solid_color_anim.h
+++ b/quantum/rgb_matrix/animations/solid_color_anim.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_anim.h b/quantum/rgb_matrix/animations/solid_reactive_anim.h
index d45bb961b..d45bb961b 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_anim.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_anim.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_cross.h b/quantum/rgb_matrix/animations/solid_reactive_cross.h
index f76c68e8c..f76c68e8c 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_cross.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_cross.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_nexus.h b/quantum/rgb_matrix/animations/solid_reactive_nexus.h
index 17f94e3c1..17f94e3c1 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_nexus.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_nexus.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_simple_anim.h b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
index 12eb248cc..12eb248cc 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_simple_anim.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
diff --git a/quantum/rgb_matrix_animations/solid_reactive_wide.h b/quantum/rgb_matrix/animations/solid_reactive_wide.h
index 1cc4dca72..1cc4dca72 100644
--- a/quantum/rgb_matrix_animations/solid_reactive_wide.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_wide.h
diff --git a/quantum/rgb_matrix_animations/solid_splash_anim.h b/quantum/rgb_matrix/animations/solid_splash_anim.h
index 99efb4996..99efb4996 100644
--- a/quantum/rgb_matrix_animations/solid_splash_anim.h
+++ b/quantum/rgb_matrix/animations/solid_splash_anim.h
diff --git a/quantum/rgb_matrix_animations/splash_anim.h b/quantum/rgb_matrix/animations/splash_anim.h
index 1415bcc0f..1415bcc0f 100644
--- a/quantum/rgb_matrix_animations/splash_anim.h
+++ b/quantum/rgb_matrix/animations/splash_anim.h
diff --git a/quantum/rgb_matrix_animations/typing_heatmap_anim.h b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
index e7dda11a2..e7dda11a2 100644
--- a/quantum/rgb_matrix_animations/typing_heatmap_anim.h
+++ b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index ab8dbd849..789cd2860 100644
--- a/quantum/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -31,22 +31,25 @@ const led_point_t k_rgb_matrix_center = {112, 32};
31const led_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// clang-format off
35#ifndef RGB_MATRIX_IMMEDIATE_EEPROM
36# define rgb_eeconfig_update(v) rgb_update_eeprom |= v
37#else
38# define rgb_eeconfig_update(v) if (v) eeconfig_update_rgb_matrix()
39#endif
40// clang-format on
41
34__attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } 42__attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); }
35 43
36// Generic effect runners 44// Generic effect runners
37#include "rgb_matrix_runners/effect_runner_dx_dy_dist.h" 45#include "rgb_matrix_runners.inc"
38#include "rgb_matrix_runners/effect_runner_dx_dy.h"
39#include "rgb_matrix_runners/effect_runner_i.h"
40#include "rgb_matrix_runners/effect_runner_sin_cos_i.h"
41#include "rgb_matrix_runners/effect_runner_reactive.h"
42#include "rgb_matrix_runners/effect_runner_reactive_splash.h"
43 46
44// ------------------------------------------ 47// ------------------------------------------
45// -----Begin rgb effect includes macros----- 48// -----Begin rgb effect includes macros-----
46#define RGB_MATRIX_EFFECT(name) 49#define RGB_MATRIX_EFFECT(name)
47#define RGB_MATRIX_CUSTOM_EFFECT_IMPLS 50#define RGB_MATRIX_CUSTOM_EFFECT_IMPLS
48 51
49#include "rgb_matrix_animations/rgb_matrix_effects.inc" 52#include "rgb_matrix_effects.inc"
50#ifdef RGB_MATRIX_CUSTOM_KB 53#ifdef RGB_MATRIX_CUSTOM_KB
51# include "rgb_matrix_kb.inc" 54# include "rgb_matrix_kb.inc"
52#endif 55#endif
@@ -67,10 +70,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv
67# define RGB_DISABLE_TIMEOUT 0 70# define RGB_DISABLE_TIMEOUT 0
68#endif 71#endif
69 72
70#if RGB_DISABLE_WHEN_USB_SUSPENDED != 1
71# undef RGB_DISABLE_WHEN_USB_SUSPENDED
72#endif
73
74#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX 73#if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX
75# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS 74# undef RGB_MATRIX_MAXIMUM_BRIGHTNESS
76# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX 75# define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX
@@ -129,6 +128,7 @@ last_hit_t g_last_hit_tracker;
129 128
130// internals 129// internals
131static bool suspend_state = false; 130static bool suspend_state = false;
131static bool rgb_update_eeprom = 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, LED_FLAG_ALL, false}; 134static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false};
@@ -315,6 +315,8 @@ static void rgb_task_timers(void) {
315 315
316static void rgb_task_sync(void) { 316static void rgb_task_sync(void) {
317 // next task 317 // next task
318 if (rgb_update_eeprom) eeconfig_update_rgb_matrix();
319 rgb_update_eeprom = false;
318 if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; 320 if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;
319} 321}
320 322
@@ -353,7 +355,7 @@ static void rgb_task_render(uint8_t effect) {
353 case RGB_MATRIX_##name: \ 355 case RGB_MATRIX_##name: \
354 rendering = name(&rgb_effect_params); \ 356 rendering = name(&rgb_effect_params); \
355 break; 357 break;
356#include "rgb_matrix_animations/rgb_matrix_effects.inc" 358#include "rgb_matrix_effects.inc"
357#undef RGB_MATRIX_EFFECT 359#undef RGB_MATRIX_EFFECT
358 360
359#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) 361#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
@@ -511,9 +513,7 @@ bool rgb_matrix_get_suspend_state(void) { return suspend_state; }
511void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { 513void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
512 rgb_matrix_config.enable ^= 1; 514 rgb_matrix_config.enable ^= 1;
513 rgb_task_state = STARTING; 515 rgb_task_state = STARTING;
514 if (write_to_eeprom) { 516 rgb_eeconfig_update(write_to_eeprom);
515 eeconfig_update_rgb_matrix();
516 }
517 dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable); 517 dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable);
518} 518}
519void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); } 519void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); }
@@ -521,7 +521,7 @@ void rgb_matrix_toggle(void) { rgb_matrix_toggle_eeprom_helper(true); }
521 521
522void rgb_matrix_enable(void) { 522void rgb_matrix_enable(void) {
523 rgb_matrix_enable_noeeprom(); 523 rgb_matrix_enable_noeeprom();
524 eeconfig_update_rgb_matrix(); 524 rgb_eeconfig_update(true);
525} 525}
526 526
527void rgb_matrix_enable_noeeprom(void) { 527void rgb_matrix_enable_noeeprom(void) {
@@ -531,7 +531,7 @@ void rgb_matrix_enable_noeeprom(void) {
531 531
532void rgb_matrix_disable(void) { 532void rgb_matrix_disable(void) {
533 rgb_matrix_disable_noeeprom(); 533 rgb_matrix_disable_noeeprom();
534 eeconfig_update_rgb_matrix(); 534 rgb_eeconfig_update(true);
535} 535}
536 536
537void rgb_matrix_disable_noeeprom(void) { 537void rgb_matrix_disable_noeeprom(void) {
@@ -553,9 +553,7 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
553 rgb_matrix_config.mode = mode; 553 rgb_matrix_config.mode = mode;
554 } 554 }
555 rgb_task_state = STARTING; 555 rgb_task_state = STARTING;
556 if (write_to_eeprom) { 556 rgb_eeconfig_update(write_to_eeprom);
557 eeconfig_update_rgb_matrix();
558 }
559 dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode); 557 dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode);
560} 558}
561void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); } 559void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); }
@@ -584,9 +582,7 @@ void rgb_matrix_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, boo
584 rgb_matrix_config.hsv.h = hue; 582 rgb_matrix_config.hsv.h = hue;
585 rgb_matrix_config.hsv.s = sat; 583 rgb_matrix_config.hsv.s = sat;
586 rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val; 584 rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val;
587 if (write_to_eeprom) { 585 rgb_eeconfig_update(write_to_eeprom);
588 eeconfig_update_rgb_matrix();
589 }
590 dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v); 586 dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v);
591} 587}
592void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); } 588void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); }
@@ -623,9 +619,7 @@ void rgb_matrix_decrease_val(void) { rgb_matrix_decrease_val_helper(true); }
623 619
624void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { 620void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
625 rgb_matrix_config.speed = speed; 621 rgb_matrix_config.speed = speed;
626 if (write_to_eeprom) { 622 rgb_eeconfig_update(write_to_eeprom);
627 eeconfig_update_rgb_matrix();
628 }
629 dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed); 623 dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed);
630} 624}
631void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); } 625void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); }
diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h
index a615b8422..28f07c84d 100644
--- a/quantum/rgb_matrix.h
+++ b/quantum/rgb_matrix/rgb_matrix.h
@@ -33,6 +33,8 @@
33# include "is31fl3737.h" 33# include "is31fl3737.h"
34#elif defined(IS31FL3741) 34#elif defined(IS31FL3741)
35# include "is31fl3741.h" 35# include "is31fl3741.h"
36#elif defined(AW20216)
37# include "aw20216.h"
36#elif defined(WS2812) 38#elif defined(WS2812)
37# include "ws2812.h" 39# include "ws2812.h"
38#endif 40#endif
@@ -70,7 +72,7 @@ enum rgb_matrix_effects {
70// -------------------------------------- 72// --------------------------------------
71// -----Begin rgb effect enum macros----- 73// -----Begin rgb effect enum macros-----
72#define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_##name, 74#define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_##name,
73#include "rgb_matrix_animations/rgb_matrix_effects.inc" 75#include "rgb_matrix_effects.inc"
74#undef RGB_MATRIX_EFFECT 76#undef RGB_MATRIX_EFFECT
75 77
76#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) 78#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c
index 896fa6d0e..6a11d4791 100644
--- a/quantum/rgb_matrix_drivers.c
+++ b/quantum/rgb_matrix/rgb_matrix_drivers.c
@@ -171,6 +171,22 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
171}; 171};
172# endif 172# endif
173 173
174#elif defined(AW20216)
175# include "spi_master.h"
176static void init(void) {
177 spi_init();
178 AW20216_init();
179}
180
181static void flush(void) { AW20216_update_pwm_buffers(); }
182
183const rgb_matrix_driver_t rgb_matrix_driver = {
184 .init = init,
185 .flush = flush,
186 .set_color = AW20216_set_color,
187 .set_color_all = AW20216_set_color_all,
188};
189
174#elif defined(WS2812) 190#elif defined(WS2812)
175# if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_CUSTOM_DRIVER) 191# if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_CUSTOM_DRIVER)
176# pragma message "Cannot use RGBLIGHT and RGB Matrix using WS2812 at the same time." 192# pragma message "Cannot use RGBLIGHT and RGB Matrix using WS2812 at the same time."
diff --git a/quantum/rgb_matrix_types.h b/quantum/rgb_matrix/rgb_matrix_types.h
index df575d657..df575d657 100644
--- a/quantum/rgb_matrix_types.h
+++ b/quantum/rgb_matrix/rgb_matrix_types.h
diff --git a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc b/quantum/rgb_matrix_animations/rgb_matrix_effects.inc
deleted file mode 100644
index 053d44150..000000000
--- a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc
+++ /dev/null
@@ -1,37 +0,0 @@
1// Add your new core rgb matrix effect here, order determins enum order, requires "rgb_matrix_animations/ directory
2#include "rgb_matrix_animations/solid_color_anim.h"
3#include "rgb_matrix_animations/alpha_mods_anim.h"
4#include "rgb_matrix_animations/gradient_up_down_anim.h"
5#include "rgb_matrix_animations/gradient_left_right_anim.h"
6#include "rgb_matrix_animations/breathing_anim.h"
7#include "rgb_matrix_animations/colorband_sat_anim.h"
8#include "rgb_matrix_animations/colorband_val_anim.h"
9#include "rgb_matrix_animations/colorband_pinwheel_sat_anim.h"
10#include "rgb_matrix_animations/colorband_pinwheel_val_anim.h"
11#include "rgb_matrix_animations/colorband_spiral_sat_anim.h"
12#include "rgb_matrix_animations/colorband_spiral_val_anim.h"
13#include "rgb_matrix_animations/cycle_all_anim.h"
14#include "rgb_matrix_animations/cycle_left_right_anim.h"
15#include "rgb_matrix_animations/cycle_up_down_anim.h"
16#include "rgb_matrix_animations/rainbow_moving_chevron_anim.h"
17#include "rgb_matrix_animations/cycle_out_in_anim.h"
18#include "rgb_matrix_animations/cycle_out_in_dual_anim.h"
19#include "rgb_matrix_animations/cycle_pinwheel_anim.h"
20#include "rgb_matrix_animations/cycle_spiral_anim.h"
21#include "rgb_matrix_animations/dual_beacon_anim.h"
22#include "rgb_matrix_animations/rainbow_beacon_anim.h"
23#include "rgb_matrix_animations/rainbow_pinwheels_anim.h"
24#include "rgb_matrix_animations/raindrops_anim.h"
25#include "rgb_matrix_animations/jellybean_raindrops_anim.h"
26#include "rgb_matrix_animations/hue_breathing_anim.h"
27#include "rgb_matrix_animations/hue_pendulum_anim.h"
28#include "rgb_matrix_animations/hue_wave_anim.h"
29#include "rgb_matrix_animations/typing_heatmap_anim.h"
30#include "rgb_matrix_animations/digital_rain_anim.h"
31#include "rgb_matrix_animations/solid_reactive_simple_anim.h"
32#include "rgb_matrix_animations/solid_reactive_anim.h"
33#include "rgb_matrix_animations/solid_reactive_wide.h"
34#include "rgb_matrix_animations/solid_reactive_cross.h"
35#include "rgb_matrix_animations/solid_reactive_nexus.h"
36#include "rgb_matrix_animations/splash_anim.h"
37#include "rgb_matrix_animations/solid_splash_anim.h"
diff --git a/quantum/rgblight.c b/quantum/rgblight/rgblight.c
index baa10ec41..54face173 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight/rgblight.c
@@ -890,7 +890,7 @@ void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
890 animation_status.restart = true; 890 animation_status.restart = true;
891 } 891 }
892# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ 892# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */
893# endif /* RGBLIGHT_USE_TIMER */ 893# endif /* RGBLIGHT_USE_TIMER */
894} 894}
895#endif /* RGBLIGHT_SPLIT */ 895#endif /* RGBLIGHT_SPLIT */
896 896
diff --git a/quantum/rgblight.h b/quantum/rgblight/rgblight.h
index bec2c6695..bec2c6695 100644
--- a/quantum/rgblight.h
+++ b/quantum/rgblight/rgblight.h
diff --git a/quantum/rgblight_breathe_table.h b/quantum/rgblight/rgblight_breathe_table.h
index 30245318b..30245318b 100644
--- a/quantum/rgblight_breathe_table.h
+++ b/quantum/rgblight/rgblight_breathe_table.h
diff --git a/quantum/rgblight_list.h b/quantum/rgblight/rgblight_list.h
index f29a646b6..0fd68b75f 100644
--- a/quantum/rgblight_list.h
+++ b/quantum/rgblight/rgblight_list.h
@@ -15,49 +15,7 @@
15 */ 15 */
16#pragma once 16#pragma once
17 17
18/* RGB COLORS */ 18#include "color.h"
19#define RGB_WHITE 0xFF, 0xFF, 0xFF
20#define RGB_RED 0xFF, 0x00, 0x00
21#define RGB_CORAL 0xFF, 0x7C, 0x4D
22#define RGB_ORANGE 0xFF, 0x80, 0x00
23#define RGB_GOLDENROD 0xD9, 0xA5, 0x21
24#define RGB_GOLD 0xFF, 0xD9, 0x00
25#define RGB_YELLOW 0xFF, 0xFF, 0x00
26#define RGB_CHARTREUSE 0x80, 0xFF, 0x00
27#define RGB_GREEN 0x00, 0xFF, 0x00
28#define RGB_SPRINGGREEN 0x00, 0xFF, 0x80
29#define RGB_TURQUOISE 0x47, 0x6E, 0x6A
30#define RGB_TEAL 0x00, 0x80, 0x80
31#define RGB_CYAN 0x00, 0xFF, 0xFF
32#define RGB_AZURE 0x99, 0xf5, 0xFF
33#define RGB_BLUE 0x00, 0x00, 0xFF
34#define RGB_PURPLE 0x7A, 0x00, 0xFF
35#define RGB_MAGENTA 0xFF, 0x00, 0xFF
36#define RGB_PINK 0xFF, 0x80, 0xBF
37#define RGB_BLACK 0x00, 0x00, 0x00
38#define RGB_OFF RGB_BLACK
39
40/* HSV COLORS */
41#define HSV_WHITE 0, 0, 255
42#define HSV_RED 0, 255, 255
43#define HSV_CORAL 11, 176, 255
44#define HSV_ORANGE 28, 255, 255
45#define HSV_GOLDENROD 30, 218, 218
46#define HSV_GOLD 36, 255, 255
47#define HSV_YELLOW 43, 255, 255
48#define HSV_CHARTREUSE 64, 255, 255
49#define HSV_GREEN 85, 255, 255
50#define HSV_SPRINGGREEN 106, 255, 255
51#define HSV_TURQUOISE 123, 90, 112
52#define HSV_TEAL 128, 255, 128
53#define HSV_CYAN 128, 255, 255
54#define HSV_AZURE 132, 102, 255
55#define HSV_BLUE 170, 255, 255
56#define HSV_PURPLE 191, 255, 255
57#define HSV_MAGENTA 213, 255, 255
58#define HSV_PINK 234, 128, 255
59#define HSV_BLACK 0, 0, 0
60#define HSV_OFF HSV_BLACK
61 19
62/* 20/*
63######################################################################################## 21########################################################################################
@@ -66,7 +24,7 @@
66## ## 24## ##
67## The functions below have been deprecated and may be removed in a future release. ## 25## The functions below have been deprecated and may be removed in a future release. ##
68## ## 26## ##
69## Please use the values above with the RGB functions. ## 27## Please use the values in color.h with the RGB functions. ##
70## ## 28## ##
71## ## 29## ##
72## ## 30## ##
diff --git a/quantum/rgblight_modes.h b/quantum/rgblight/rgblight_modes.h
index 7abdb87bc..7abdb87bc 100644
--- a/quantum/rgblight_modes.h
+++ b/quantum/rgblight/rgblight_modes.h
diff --git a/quantum/rgblight_post_config.h b/quantum/rgblight/rgblight_post_config.h
index 3c14cb610..3c14cb610 100644
--- a/quantum/rgblight_post_config.h
+++ b/quantum/rgblight/rgblight_post_config.h
diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c
index f77483ad8..6363f8ff3 100644
--- a/quantum/serial_link/system/serial_link.c
+++ b/quantum/serial_link/system/serial_link.c
@@ -29,10 +29,13 @@ SOFTWARE.
29#include "serial_link/protocol/transport.h" 29#include "serial_link/protocol/transport.h"
30#include "serial_link/protocol/frame_router.h" 30#include "serial_link/protocol/frame_router.h"
31#include "matrix.h" 31#include "matrix.h"
32#include "sync_timer.h"
32#include <stdbool.h> 33#include <stdbool.h>
33#include "print.h" 34#include "print.h"
34#include "config.h" 35#include "config.h"
35 36
37#define SYNC_TIMER_OFFSET 2
38
36static event_source_t new_data_event; 39static event_source_t new_data_event;
37static bool serial_link_connected; 40static bool serial_link_connected;
38static bool is_master = false; 41static bool is_master = false;
@@ -159,10 +162,16 @@ static matrix_object_t last_matrix = {};
159 162
160SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t); 163SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);
161MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool); 164MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool);
165#ifndef DISABLE_SYNC_TIMER
166MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t);
167#endif
162 168
163static remote_object_t* remote_objects[] = { 169static remote_object_t* remote_objects[] = {
164 REMOTE_OBJECT(serial_link_connected), 170 REMOTE_OBJECT(serial_link_connected),
165 REMOTE_OBJECT(keyboard_matrix), 171 REMOTE_OBJECT(keyboard_matrix),
172#ifndef DISABLE_SYNC_TIMER
173 REMOTE_OBJECT(sync_timer),
174#endif
166}; 175};
167 176
168void init_serial_link(void) { 177void init_serial_link(void) {
@@ -200,14 +209,27 @@ void serial_link_update(void) {
200 m->rows[i] = matrix.rows[i]; 209 m->rows[i] = matrix.rows[i];
201 } 210 }
202 end_write_keyboard_matrix(); 211 end_write_keyboard_matrix();
212
203 *begin_write_serial_link_connected() = true; 213 *begin_write_serial_link_connected() = true;
204 end_write_serial_link_connected(); 214 end_write_serial_link_connected();
215
216#ifndef DISABLE_SYNC_TIMER
217 *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET;
218 end_write_sync_timer();
219#endif
205 } 220 }
206 221
207 matrix_object_t* m = read_keyboard_matrix(0); 222 matrix_object_t* m = read_keyboard_matrix(0);
208 if (m) { 223 if (m) {
209 matrix_set_remote(m->rows, 0); 224 matrix_set_remote(m->rows, 0);
210 } 225 }
226
227#ifndef DISABLE_SYNC_TIMER
228 uint32_t* t = read_sync_timer();
229 if (t) {
230 sync_timer_update(*t);
231 }
232#endif
211} 233}
212 234
213void signal_data_written(void) { chEvtBroadcast(&new_data_event); } 235void signal_data_written(void) { chEvtBroadcast(&new_data_event); }
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
deleted file mode 100644
index 039e7d977..000000000
--- a/quantum/split_common/matrix.c
+++ /dev/null
@@ -1,309 +0,0 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17#include <stdint.h>
18#include <stdbool.h>
19#include "util.h"
20#include "matrix.h"
21#include "debounce.h"
22#include "quantum.h"
23#include "split_util.h"
24#include "config.h"
25#include "transport.h"
26
27#define ERROR_DISCONNECT_COUNT 5
28
29#define ROWS_PER_HAND (MATRIX_ROWS / 2)
30
31#ifdef DIRECT_PINS
32static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
33#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
34static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
35static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
36#endif
37
38/* matrix state(1:on, 0:off) */
39extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
40extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
41
42// row offsets for each hand
43uint8_t thisHand, thatHand;
44
45// user-defined overridable functions
46__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
47__attribute__((weak)) void matrix_slave_scan_user(void) {}
48
49static inline void setPinOutput_writeLow(pin_t pin) {
50 ATOMIC_BLOCK_FORCEON {
51 setPinOutput(pin);
52 writePinLow(pin);
53 }
54}
55
56static inline void setPinInputHigh_atomic(pin_t pin) {
57 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }
58}
59
60// matrix code
61
62#ifdef DIRECT_PINS
63
64static void init_pins(void) {
65 for (int row = 0; row < MATRIX_ROWS; row++) {
66 for (int col = 0; col < MATRIX_COLS; col++) {
67 pin_t pin = direct_pins[row][col];
68 if (pin != NO_PIN) {
69 setPinInputHigh(pin);
70 }
71 }
72 }
73}
74
75static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
76 // Start with a clear matrix row
77 matrix_row_t current_row_value = 0;
78
79 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
80 pin_t pin = direct_pins[current_row][col_index];
81 if (pin != NO_PIN) {
82 current_row_value |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
83 }
84 }
85
86 // If the row has changed, store the row and return the changed flag.
87 if (current_matrix[current_row] != current_row_value) {
88 current_matrix[current_row] = current_row_value;
89 return true;
90 }
91 return false;
92}
93
94#elif defined(DIODE_DIRECTION)
95# if (DIODE_DIRECTION == COL2ROW)
96
97static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); }
98
99static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); }
100
101static void unselect_rows(void) {
102 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
103 setPinInputHigh_atomic(row_pins[x]);
104 }
105}
106
107static void init_pins(void) {
108 unselect_rows();
109 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
110 setPinInputHigh_atomic(col_pins[x]);
111 }
112}
113
114static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
115 // Start with a clear matrix row
116 matrix_row_t current_row_value = 0;
117
118 // Select row
119 select_row(current_row);
120 matrix_output_select_delay();
121
122 // For each col...
123 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
124 // Select the col pin to read (active low)
125 uint8_t pin_state = readPin(col_pins[col_index]);
126
127 // Populate the matrix row with the state of the col pin
128 current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
129 }
130
131 // Unselect row
132 unselect_row(current_row);
133 matrix_output_unselect_delay(); // wait for all Col signals to go HIGH
134
135 // If the row has changed, store the row and return the changed flag.
136 if (current_matrix[current_row] != current_row_value) {
137 current_matrix[current_row] = current_row_value;
138 return true;
139 }
140 return false;
141}
142
143# elif (DIODE_DIRECTION == ROW2COL)
144
145static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); }
146
147static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); }
148
149static void unselect_cols(void) {
150 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
151 setPinInputHigh_atomic(col_pins[x]);
152 }
153}
154
155static void init_pins(void) {
156 unselect_cols();
157 for (uint8_t x = 0; x < ROWS_PER_HAND; x++) {
158 setPinInputHigh_atomic(row_pins[x]);
159 }
160}
161
162static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
163 bool matrix_changed = false;
164
165 // Select col
166 select_col(current_col);
167 matrix_output_select_delay();
168
169 // For each row...
170 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {
171 // Store last value of row prior to reading
172 matrix_row_t last_row_value = current_matrix[row_index];
173 matrix_row_t current_row_value = last_row_value;
174
175 // Check row pin state
176 if (readPin(row_pins[row_index]) == 0) {
177 // Pin LO, set col bit
178 current_row_value |= (MATRIX_ROW_SHIFTER << current_col);
179 } else {
180 // Pin HI, clear col bit
181 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col);
182 }
183
184 // Determine if the matrix changed state
185 if ((last_row_value != current_row_value)) {
186 matrix_changed |= true;
187 current_matrix[row_index] = current_row_value;
188 }
189 }
190
191 // Unselect col
192 unselect_col(current_col);
193 matrix_output_unselect_delay(); // wait for all Row signals to go HIGH
194
195 return matrix_changed;
196}
197
198# else
199# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
200# endif
201#else
202# error DIODE_DIRECTION is not defined!
203#endif
204
205void matrix_init(void) {
206 split_pre_init();
207
208 // Set pinout for right half if pinout for that half is defined
209 if (!isLeftHand) {
210#ifdef DIRECT_PINS_RIGHT
211 const pin_t direct_pins_right[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS_RIGHT;
212 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
213 for (uint8_t j = 0; j < MATRIX_COLS; j++) {
214 direct_pins[i][j] = direct_pins_right[i][j];
215 }
216 }
217#endif
218#ifdef MATRIX_ROW_PINS_RIGHT
219 const pin_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
220 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
221 row_pins[i] = row_pins_right[i];
222 }
223#endif
224#ifdef MATRIX_COL_PINS_RIGHT
225 const pin_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
226 for (uint8_t i = 0; i < MATRIX_COLS; i++) {
227 col_pins[i] = col_pins_right[i];
228 }
229#endif
230 }
231
232 thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
233 thatHand = ROWS_PER_HAND - thisHand;
234
235 // initialize key pins
236 init_pins();
237
238 // initialize matrix state: all keys off
239 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
240 raw_matrix[i] = 0;
241 matrix[i] = 0;
242 }
243
244 debounce_init(ROWS_PER_HAND);
245
246 matrix_init_quantum();
247
248 split_post_init();
249}
250
251bool matrix_post_scan(void) {
252 bool changed = false;
253 if (is_keyboard_master()) {
254 static uint8_t error_count;
255
256 matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
257 if (!transport_master(matrix + thisHand, slave_matrix)) {
258 error_count++;
259
260 if (error_count > ERROR_DISCONNECT_COUNT) {
261 // reset other half if disconnected
262 for (int i = 0; i < ROWS_PER_HAND; ++i) {
263 matrix[thatHand + i] = 0;
264 slave_matrix[i] = 0;
265 }
266
267 changed = true;
268 }
269 } else {
270 error_count = 0;
271
272 for (int i = 0; i < ROWS_PER_HAND; ++i) {
273 if (matrix[thatHand + i] != slave_matrix[i]) {
274 matrix[thatHand + i] = slave_matrix[i];
275 changed = true;
276 }
277 }
278 }
279
280 matrix_scan_quantum();
281 } else {
282 transport_slave(matrix + thatHand, matrix + thisHand);
283
284 matrix_slave_scan_kb();
285 }
286
287 return changed;
288}
289
290uint8_t matrix_scan(void) {
291 bool local_changed = false;
292
293#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
294 // Set row, read cols
295 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
296 local_changed |= read_cols_on_row(raw_matrix, current_row);
297 }
298#elif (DIODE_DIRECTION == ROW2COL)
299 // Set col, read rows
300 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
301 local_changed |= read_rows_on_col(raw_matrix, current_col);
302 }
303#endif
304
305 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed);
306
307 bool remote_changed = matrix_post_scan();
308 return (uint8_t)(local_changed || remote_changed);
309}
diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h
index 4ae1d5273..a4c0a1956 100644
--- a/quantum/split_common/post_config.h
+++ b/quantum/split_common/post_config.h
@@ -7,13 +7,4 @@
7# ifndef F_SCL 7# ifndef F_SCL
8# define F_SCL 100000UL // SCL frequency 8# define F_SCL 100000UL // SCL frequency
9# endif 9# endif
10
11#else // use serial
12// When using serial, the user must define RGBLIGHT_SPLIT explicitly
13// in config.h as needed.
14// see quantum/rgblight_post_config.h
15# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
16// When using serial and RGBLIGHT_SPLIT need separate transaction
17# define SERIAL_USE_MULTI_TRANSACTION
18# endif
19#endif 10#endif
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 9e75e19ce..989829d2d 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -77,7 +77,11 @@ __attribute__((weak)) bool is_keyboard_left(void) {
77#if defined(SPLIT_HAND_PIN) 77#if defined(SPLIT_HAND_PIN)
78 // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand 78 // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
79 setPinInput(SPLIT_HAND_PIN); 79 setPinInput(SPLIT_HAND_PIN);
80# ifdef SPLIT_HAND_PIN_LOW_IS_LEFT
81 return !readPin(SPLIT_HAND_PIN);
82# else
80 return readPin(SPLIT_HAND_PIN); 83 return readPin(SPLIT_HAND_PIN);
84# endif
81#elif defined(SPLIT_HAND_MATRIX_GRID) 85#elif defined(SPLIT_HAND_MATRIX_GRID)
82# ifdef SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT 86# ifdef SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT
83 return peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID); 87 return peek_matrix_intersection(SPLIT_HAND_MATRIX_GRID);
diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h
new file mode 100644
index 000000000..464c73478
--- /dev/null
+++ b/quantum/split_common/transaction_id_define.h
@@ -0,0 +1,94 @@
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 2 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
19enum serial_transaction_id {
20#ifdef USE_I2C
21 I2C_EXECUTE_CALLBACK,
22#endif // USE_I2C
23
24 GET_SLAVE_MATRIX_CHECKSUM,
25 GET_SLAVE_MATRIX_DATA,
26
27#ifdef SPLIT_TRANSPORT_MIRROR
28 PUT_MASTER_MATRIX,
29#endif // SPLIT_TRANSPORT_MIRROR
30
31#ifdef ENCODER_ENABLE
32 GET_ENCODERS_CHECKSUM,
33 GET_ENCODERS_DATA,
34#endif // ENCODER_ENABLE
35
36#ifndef DISABLE_SYNC_TIMER
37 PUT_SYNC_TIMER,
38#endif // DISABLE_SYNC_TIMER
39
40#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
41 PUT_LAYER_STATE,
42 PUT_DEFAULT_LAYER_STATE,
43#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
44
45#ifdef SPLIT_LED_STATE_ENABLE
46 PUT_LED_STATE,
47#endif // SPLIT_LED_STATE_ENABLE
48
49#ifdef SPLIT_MODS_ENABLE
50 PUT_MODS,
51#endif // SPLIT_MODS_ENABLE
52
53#ifdef BACKLIGHT_ENABLE
54 PUT_BACKLIGHT,
55#endif // BACKLIGHT_ENABLE
56
57#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
58 PUT_RGBLIGHT,
59#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
60
61#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
62 PUT_LED_MATRIX,
63#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
64
65#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
66 PUT_RGB_MATRIX,
67#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
68
69#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
70 PUT_WPM,
71#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
72
73#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
74 PUT_RPC_INFO,
75 PUT_RPC_REQ_DATA,
76 EXECUTE_RPC,
77 GET_RPC_RESP_DATA,
78#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
79
80// keyboard-specific
81#ifdef SPLIT_TRANSACTION_IDS_KB
82 SPLIT_TRANSACTION_IDS_KB,
83#endif // SPLIT_TRANSACTION_IDS_KB
84
85// user/keymap-specific
86#ifdef SPLIT_TRANSACTION_IDS_USER
87 SPLIT_TRANSACTION_IDS_USER,
88#endif // SPLIT_TRANSACTION_IDS_USER
89
90 NUM_TOTAL_TRANSACTIONS
91};
92
93// Ensure we only use 5 bits for transaction
94_Static_assert(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded");
diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c
new file mode 100644
index 000000000..abad626e0
--- /dev/null
+++ b/quantum/split_common/transactions.c
@@ -0,0 +1,655 @@
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 2 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#include <string.h>
18#include <stddef.h>
19
20#include "crc.h"
21#include "debug.h"
22#include "matrix.h"
23#include "quantum.h"
24#include "transactions.h"
25#include "transport.h"
26#include "transaction_id_define.h"
27
28#define SYNC_TIMER_OFFSET 2
29
30#ifndef FORCED_SYNC_THROTTLE_MS
31# define FORCED_SYNC_THROTTLE_MS 100
32#endif // FORCED_SYNC_THROTTLE_MS
33
34#define sizeof_member(type, member) sizeof(((type *)NULL)->member)
35
36#define trans_initiator2target_initializer_cb(member, cb) \
37 { &dummy, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), 0, 0, cb }
38#define trans_initiator2target_initializer(member) trans_initiator2target_initializer_cb(member, NULL)
39
40#define trans_target2initiator_initializer_cb(member, cb) \
41 { &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb }
42#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL)
43
44#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
45#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
46
47#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
48// Forward-declare the RPC callback handlers
49void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
50void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
51#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
52
53////////////////////////////////////////////////////
54// Helpers
55
56bool transaction_handler_master(bool okay, matrix_row_t master_matrix[], matrix_row_t slave_matrix[], const char *prefix, bool (*handler)(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])) {
57 if (okay) {
58 bool this_okay = true;
59 for (int iter = 1; iter <= 10; ++iter) {
60 if (!this_okay) {
61 for (int i = 0; i < iter * iter; ++i) {
62 wait_us(10);
63 }
64 }
65 ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix); };
66 if (this_okay) break;
67 }
68 okay &= this_okay;
69 if (!okay) {
70 dprintf("Failed to execute %s\n", prefix);
71 }
72 }
73 return okay;
74}
75
76#define TRANSACTION_HANDLER_MASTER(prefix) \
77 do { \
78 okay &= transaction_handler_master(okay, master_matrix, slave_matrix, #prefix, &prefix##_master); \
79 } while (0)
80
81#define TRANSACTION_HANDLER_SLAVE(prefix) \
82 do { \
83 ATOMIC_BLOCK_FORCEON { prefix##_slave(master_matrix, slave_matrix); }; \
84 } while (0)
85
86inline static bool read_if_checksum_mismatch(int8_t trans_id_checksum, int8_t trans_id_retrieve, uint32_t *last_update, void *destination, const void *equiv_shmem, size_t length) {
87 uint8_t curr_checksum;
88 bool okay = transport_read(trans_id_checksum, &curr_checksum, sizeof(curr_checksum));
89 if (okay && (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || curr_checksum != crc8(equiv_shmem, length))) {
90 okay &= transport_read(trans_id_retrieve, destination, length);
91 okay &= curr_checksum == crc8(equiv_shmem, length);
92 if (okay) {
93 *last_update = timer_read32();
94 }
95 } else {
96 memcpy(destination, equiv_shmem, length);
97 }
98 return okay;
99}
100
101inline static bool send_if_condition(int8_t trans_id, uint32_t *last_update, bool condition, void *source, size_t length) {
102 bool okay = true;
103 if (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || condition) {
104 okay &= transport_write(trans_id, source, length);
105 if (okay) {
106 *last_update = timer_read32();
107 }
108 }
109 return okay;
110}
111
112inline static bool send_if_data_mismatch(int8_t trans_id, uint32_t *last_update, void *source, const void *equiv_shmem, size_t length) {
113 // Just run a memcmp to compare the source and equivalent shmem location
114 return send_if_condition(trans_id, last_update, (memcmp(source, equiv_shmem, length) != 0), source, length);
115}
116
117////////////////////////////////////////////////////
118// Slave matrix
119
120static bool slave_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
121 static uint32_t last_update = 0;
122 static matrix_row_t last_matrix[(MATRIX_ROWS) / 2] = {0}; // last successfully-read matrix, so we can replicate if there are checksum errors
123 matrix_row_t temp_matrix[(MATRIX_ROWS) / 2]; // holding area while we test whether or not checksum is correct
124
125 bool okay = read_if_checksum_mismatch(GET_SLAVE_MATRIX_CHECKSUM, GET_SLAVE_MATRIX_DATA, &last_update, temp_matrix, split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix));
126 if (okay) {
127 // Checksum matches the received data, save as the last matrix state
128 memcpy(last_matrix, temp_matrix, sizeof(temp_matrix));
129 }
130 // Copy out the last-known-good matrix state to the slave matrix
131 memcpy(slave_matrix, last_matrix, sizeof(last_matrix));
132 return okay;
133}
134
135static void slave_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
136 memcpy(split_shmem->smatrix.matrix, slave_matrix, sizeof(split_shmem->smatrix.matrix));
137 split_shmem->smatrix.checksum = crc8(split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix));
138}
139
140// clang-format off
141#define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix_handlers)
142#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix_handlers)
143#define TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS \
144 [GET_SLAVE_MATRIX_CHECKSUM] = trans_target2initiator_initializer(smatrix.checksum), \
145 [GET_SLAVE_MATRIX_DATA] = trans_target2initiator_initializer(smatrix.matrix),
146// clang-format on
147
148////////////////////////////////////////////////////
149// Master matrix
150
151#ifdef SPLIT_TRANSPORT_MIRROR
152
153static bool master_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
154 static uint32_t last_update = 0;
155 return send_if_data_mismatch(PUT_MASTER_MATRIX, &last_update, master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix));
156}
157
158static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
159 // Always copy to the master matrix
160 memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix));
161}
162
163# define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix_handlers)
164# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix_handlers)
165# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix),
166
167#else // SPLIT_TRANSPORT_MIRROR
168
169# define TRANSACTIONS_MASTER_MATRIX_MASTER()
170# define TRANSACTIONS_MASTER_MATRIX_SLAVE()
171# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS
172
173#endif // SPLIT_TRANSPORT_MIRROR
174
175////////////////////////////////////////////////////
176// Encoders
177
178#ifdef ENCODER_ENABLE
179
180static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
181 static uint32_t last_update = 0;
182 uint8_t temp_state[NUMBER_OF_ENCODERS];
183
184 bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, temp_state, split_shmem->encoders.state, sizeof(temp_state));
185 if (okay) encoder_update_raw(temp_state);
186 return okay;
187}
188
189static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
190 uint8_t encoder_state[NUMBER_OF_ENCODERS];
191 encoder_state_raw(encoder_state);
192 // Always prepare the encoder state for read.
193 memcpy(split_shmem->encoders.state, encoder_state, sizeof(encoder_state));
194 // Now update the checksum given that the encoders has been written to
195 split_shmem->encoders.checksum = crc8(encoder_state, sizeof(encoder_state));
196}
197
198// clang-format off
199# define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder_handlers)
200# define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder_handlers)
201# define TRANSACTIONS_ENCODERS_REGISTRATIONS \
202 [GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \
203 [GET_ENCODERS_DATA] = trans_target2initiator_initializer(encoders.state),
204// clang-format on
205
206#else // ENCODER_ENABLE
207
208# define TRANSACTIONS_ENCODERS_MASTER()
209# define TRANSACTIONS_ENCODERS_SLAVE()
210# define TRANSACTIONS_ENCODERS_REGISTRATIONS
211
212#endif // ENCODER_ENABLE
213
214////////////////////////////////////////////////////
215// Sync timer
216
217#ifndef DISABLE_SYNC_TIMER
218
219static bool sync_timer_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
220 static uint32_t last_update = 0;
221
222 bool okay = true;
223 if (timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS) {
224 uint32_t sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
225 okay &= transport_write(PUT_SYNC_TIMER, &sync_timer, sizeof(sync_timer));
226 if (okay) {
227 last_update = timer_read32();
228 }
229 }
230 return okay;
231}
232
233static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
234 static uint32_t last_sync_timer = 0;
235 if (last_sync_timer != split_shmem->sync_timer) {
236 last_sync_timer = split_shmem->sync_timer;
237 sync_timer_update(last_sync_timer);
238 }
239}
240
241# define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer_handlers)
242# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer_handlers)
243# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer),
244
245#else // DISABLE_SYNC_TIMER
246
247# define TRANSACTIONS_SYNC_TIMER_MASTER()
248# define TRANSACTIONS_SYNC_TIMER_SLAVE()
249# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS
250
251#endif // DISABLE_SYNC_TIMER
252
253////////////////////////////////////////////////////
254// Layer state
255
256#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
257
258static bool layer_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
259 static uint32_t last_layer_state_update = 0;
260 static uint32_t last_default_layer_state_update = 0;
261
262 bool okay = send_if_condition(PUT_LAYER_STATE, &last_layer_state_update, (layer_state != split_shmem->layers.layer_state), &layer_state, sizeof(layer_state));
263 if (okay) {
264 okay &= send_if_condition(PUT_DEFAULT_LAYER_STATE, &last_default_layer_state_update, (default_layer_state != split_shmem->layers.default_layer_state), &default_layer_state, sizeof(default_layer_state));
265 }
266 return okay;
267}
268
269static void layer_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
270 layer_state = split_shmem->layers.layer_state;
271 default_layer_state = split_shmem->layers.default_layer_state;
272}
273
274// clang-format off
275# define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state_handlers)
276# define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state_handlers)
277# define TRANSACTIONS_LAYER_STATE_REGISTRATIONS \
278 [PUT_LAYER_STATE] = trans_initiator2target_initializer(layers.layer_state), \
279 [PUT_DEFAULT_LAYER_STATE] = trans_initiator2target_initializer(layers.default_layer_state),
280// clang-format on
281
282#else // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
283
284# define TRANSACTIONS_LAYER_STATE_MASTER()
285# define TRANSACTIONS_LAYER_STATE_SLAVE()
286# define TRANSACTIONS_LAYER_STATE_REGISTRATIONS
287
288#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
289
290////////////////////////////////////////////////////
291// LED state
292
293#ifdef SPLIT_LED_STATE_ENABLE
294
295static bool led_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
296 static uint32_t last_update = 0;
297 uint8_t led_state = host_keyboard_leds();
298 return send_if_data_mismatch(PUT_LED_STATE, &last_update, &led_state, &split_shmem->led_state, sizeof(led_state));
299}
300
301static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
302 void set_split_host_keyboard_leds(uint8_t led_state);
303 set_split_host_keyboard_leds(split_shmem->led_state);
304}
305
306# define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state_handlers)
307# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state_handlers)
308# define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state),
309
310#else // SPLIT_LED_STATE_ENABLE
311
312# define TRANSACTIONS_LED_STATE_MASTER()
313# define TRANSACTIONS_LED_STATE_SLAVE()
314# define TRANSACTIONS_LED_STATE_REGISTRATIONS
315
316#endif // SPLIT_LED_STATE_ENABLE
317
318////////////////////////////////////////////////////
319// Mods
320
321#ifdef SPLIT_MODS_ENABLE
322
323static bool mods_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
324 static uint32_t last_update = 0;
325 bool mods_need_sync = timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS;
326 split_mods_sync_t new_mods;
327 new_mods.real_mods = get_mods();
328 if (!mods_need_sync && new_mods.real_mods != split_shmem->mods.real_mods) {
329 mods_need_sync = true;
330 }
331
332 new_mods.weak_mods = get_weak_mods();
333 if (!mods_need_sync && new_mods.weak_mods != split_shmem->mods.weak_mods) {
334 mods_need_sync = true;
335 }
336
337# ifndef NO_ACTION_ONESHOT
338 new_mods.oneshot_mods = get_oneshot_mods();
339 if (!mods_need_sync && new_mods.oneshot_mods != split_shmem->mods.oneshot_mods) {
340 mods_need_sync = true;
341 }
342# endif // NO_ACTION_ONESHOT
343
344 bool okay = true;
345 if (mods_need_sync) {
346 okay &= transport_write(PUT_MODS, &new_mods, sizeof(new_mods));
347 if (okay) {
348 last_update = timer_read32();
349 }
350 }
351
352 return okay;
353}
354
355static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
356 set_mods(split_shmem->mods.real_mods);
357 set_weak_mods(split_shmem->mods.weak_mods);
358# ifndef NO_ACTION_ONESHOT
359 set_oneshot_mods(split_shmem->mods.oneshot_mods);
360# endif
361}
362
363# define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods_handlers)
364# define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods_handlers)
365# define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods),
366
367#else // SPLIT_MODS_ENABLE
368
369# define TRANSACTIONS_MODS_MASTER()
370# define TRANSACTIONS_MODS_SLAVE()
371# define TRANSACTIONS_MODS_REGISTRATIONS
372
373#endif // SPLIT_MODS_ENABLE
374
375////////////////////////////////////////////////////
376// Backlight
377
378#ifdef BACKLIGHT_ENABLE
379
380static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
381 static uint32_t last_update = 0;
382 uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0;
383 return send_if_condition(PUT_BACKLIGHT, &last_update, (level != split_shmem->backlight_level), &level, sizeof(level));
384}
385
386static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); }
387
388# define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight_handlers)
389# define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight_handlers)
390# define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level),
391
392#else // BACKLIGHT_ENABLE
393
394# define TRANSACTIONS_BACKLIGHT_MASTER()
395# define TRANSACTIONS_BACKLIGHT_SLAVE()
396# define TRANSACTIONS_BACKLIGHT_REGISTRATIONS
397
398#endif // BACKLIGHT_ENABLE
399
400////////////////////////////////////////////////////
401// RGBLIGHT
402
403#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
404
405static bool rgblight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
406 static uint32_t last_update = 0;
407 rgblight_syncinfo_t rgblight_sync;
408 rgblight_get_syncinfo(&rgblight_sync);
409 if (send_if_condition(PUT_RGBLIGHT, &last_update, (rgblight_sync.status.change_flags != 0), &rgblight_sync, sizeof(rgblight_sync))) {
410 rgblight_clear_change_flags();
411 } else {
412 return false;
413 }
414 return true;
415}
416
417static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
418 // Update the RGB with the new data
419 if (split_shmem->rgblight_sync.status.change_flags != 0) {
420 rgblight_update_sync(&split_shmem->rgblight_sync, false);
421 split_shmem->rgblight_sync.status.change_flags = 0;
422 }
423}
424
425# define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight_handlers)
426# define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight_handlers)
427# define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync),
428
429#else // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
430
431# define TRANSACTIONS_RGBLIGHT_MASTER()
432# define TRANSACTIONS_RGBLIGHT_SLAVE()
433# define TRANSACTIONS_RGBLIGHT_REGISTRATIONS
434
435#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
436
437////////////////////////////////////////////////////
438// LED Matrix
439
440#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
441
442static bool led_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
443 static uint32_t last_update = 0;
444 led_matrix_sync_t led_matrix_sync;
445 memcpy(&led_matrix_sync.led_matrix, &led_matrix_eeconfig, sizeof(led_eeconfig_t));
446 led_matrix_sync.led_suspend_state = led_matrix_get_suspend_state();
447 return send_if_data_mismatch(PUT_LED_MATRIX, &last_update, &led_matrix_sync, &split_shmem->led_matrix_sync, sizeof(led_matrix_sync));
448}
449
450static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
451 memcpy(&led_matrix_eeconfig, &split_shmem->led_matrix_sync.led_matrix, sizeof(led_eeconfig_t));
452 led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state);
453}
454
455# define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix_handlers)
456# define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix_handlers)
457# define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync),
458
459#else // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
460
461# define TRANSACTIONS_LED_MATRIX_MASTER()
462# define TRANSACTIONS_LED_MATRIX_SLAVE()
463# define TRANSACTIONS_LED_MATRIX_REGISTRATIONS
464
465#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
466
467////////////////////////////////////////////////////
468// RGB Matrix
469
470#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
471
472static bool rgb_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
473 static uint32_t last_update = 0;
474 rgb_matrix_sync_t rgb_matrix_sync;
475 memcpy(&rgb_matrix_sync.rgb_matrix, &rgb_matrix_config, sizeof(rgb_config_t));
476 rgb_matrix_sync.rgb_suspend_state = rgb_matrix_get_suspend_state();
477 return send_if_data_mismatch(PUT_RGB_MATRIX, &last_update, &rgb_matrix_sync, &split_shmem->rgb_matrix_sync, sizeof(rgb_matrix_sync));
478}
479
480static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
481 memcpy(&rgb_matrix_config, &split_shmem->rgb_matrix_sync.rgb_matrix, sizeof(rgb_config_t));
482 rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state);
483}
484
485# define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix_handlers)
486# define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix_handlers)
487# define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync),
488
489#else // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
490
491# define TRANSACTIONS_RGB_MATRIX_MASTER()
492# define TRANSACTIONS_RGB_MATRIX_SLAVE()
493# define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS
494
495#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
496
497////////////////////////////////////////////////////
498// WPM
499
500#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
501
502static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
503 static uint32_t last_update = 0;
504 uint8_t current_wpm = get_current_wpm();
505 return send_if_condition(PUT_WPM, &last_update, (current_wpm != split_shmem->current_wpm), &current_wpm, sizeof(current_wpm));
506}
507
508static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); }
509
510# define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm_handlers)
511# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm_handlers)
512# define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm),
513
514#else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
515
516# define TRANSACTIONS_WPM_MASTER()
517# define TRANSACTIONS_WPM_SLAVE()
518# define TRANSACTIONS_WPM_REGISTRATIONS
519
520#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
521
522////////////////////////////////////////////////////
523
524uint8_t dummy;
525split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
526 // Set defaults
527 [0 ...(NUM_TOTAL_TRANSACTIONS - 1)] = {NULL, 0, 0, 0, 0, 0},
528
529#ifdef USE_I2C
530 [I2C_EXECUTE_CALLBACK] = trans_initiator2target_initializer(transaction_id),
531#endif // USE_I2C
532
533 // clang-format off
534 TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS
535 TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS
536 TRANSACTIONS_ENCODERS_REGISTRATIONS
537 TRANSACTIONS_SYNC_TIMER_REGISTRATIONS
538 TRANSACTIONS_LAYER_STATE_REGISTRATIONS
539 TRANSACTIONS_LED_STATE_REGISTRATIONS
540 TRANSACTIONS_MODS_REGISTRATIONS
541 TRANSACTIONS_BACKLIGHT_REGISTRATIONS
542 TRANSACTIONS_RGBLIGHT_REGISTRATIONS
543 TRANSACTIONS_LED_MATRIX_REGISTRATIONS
544 TRANSACTIONS_RGB_MATRIX_REGISTRATIONS
545 TRANSACTIONS_WPM_REGISTRATIONS
546// clang-format on
547
548#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
549 [PUT_RPC_INFO] = trans_initiator2target_initializer_cb(rpc_info, slave_rpc_info_callback),
550 [PUT_RPC_REQ_DATA] = trans_initiator2target_initializer(rpc_m2s_buffer),
551 [EXECUTE_RPC] = trans_initiator2target_initializer_cb(rpc_info.transaction_id, slave_rpc_exec_callback),
552 [GET_RPC_RESP_DATA] = trans_target2initiator_initializer(rpc_s2m_buffer),
553#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
554};
555
556bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
557 bool okay = true;
558 TRANSACTIONS_SLAVE_MATRIX_MASTER();
559 TRANSACTIONS_MASTER_MATRIX_MASTER();
560 TRANSACTIONS_ENCODERS_MASTER();
561 TRANSACTIONS_SYNC_TIMER_MASTER();
562 TRANSACTIONS_LAYER_STATE_MASTER();
563 TRANSACTIONS_LED_STATE_MASTER();
564 TRANSACTIONS_MODS_MASTER();
565 TRANSACTIONS_BACKLIGHT_MASTER();
566 TRANSACTIONS_RGBLIGHT_MASTER();
567 TRANSACTIONS_LED_MATRIX_MASTER();
568 TRANSACTIONS_RGB_MATRIX_MASTER();
569 TRANSACTIONS_WPM_MASTER();
570 return okay;
571}
572
573void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
574 TRANSACTIONS_SLAVE_MATRIX_SLAVE();
575 TRANSACTIONS_MASTER_MATRIX_SLAVE();
576 TRANSACTIONS_ENCODERS_SLAVE();
577 TRANSACTIONS_SYNC_TIMER_SLAVE();
578 TRANSACTIONS_LAYER_STATE_SLAVE();
579 TRANSACTIONS_LED_STATE_SLAVE();
580 TRANSACTIONS_MODS_SLAVE();
581 TRANSACTIONS_BACKLIGHT_SLAVE();
582 TRANSACTIONS_RGBLIGHT_SLAVE();
583 TRANSACTIONS_LED_MATRIX_SLAVE();
584 TRANSACTIONS_RGB_MATRIX_SLAVE();
585 TRANSACTIONS_WPM_SLAVE();
586}
587
588#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
589
590void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback) {
591 // Prevent invoking RPC on QMK core sync data
592 if (transaction_id <= GET_RPC_RESP_DATA) return;
593
594 // Set the callback
595 split_transaction_table[transaction_id].slave_callback = callback;
596 split_transaction_table[transaction_id].initiator2target_offset = offsetof(split_shared_memory_t, rpc_m2s_buffer);
597 split_transaction_table[transaction_id].target2initiator_offset = offsetof(split_shared_memory_t, rpc_s2m_buffer);
598}
599
600bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
601 // Prevent invoking RPC on QMK core sync data
602 if (transaction_id <= GET_RPC_RESP_DATA) return false;
603 // Prevent sizing issues
604 if (initiator2target_buffer_size > RPC_M2S_BUFFER_SIZE) return false;
605 if (target2initiator_buffer_size > RPC_S2M_BUFFER_SIZE) return false;
606
607 // Prepare the metadata block
608 rpc_sync_info_t info = {.transaction_id = transaction_id, .m2s_length = initiator2target_buffer_size, .s2m_length = target2initiator_buffer_size};
609
610 // Make sure the local side knows that we're not sending the full block of data
611 split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = initiator2target_buffer_size;
612 split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = target2initiator_buffer_size;
613
614 // Run through the sequence:
615 // * set the transaction ID and lengths
616 // * send the request data
617 // * execute RPC callback
618 // * retrieve the response data
619 if (!transport_write(PUT_RPC_INFO, &info, sizeof(info))) {
620 return false;
621 }
622 if (!transport_write(PUT_RPC_REQ_DATA, initiator2target_buffer, initiator2target_buffer_size)) {
623 return false;
624 }
625 if (!transport_write(EXECUTE_RPC, &transaction_id, sizeof(transaction_id))) {
626 return false;
627 }
628 if (!transport_read(GET_RPC_RESP_DATA, target2initiator_buffer, target2initiator_buffer_size)) {
629 return false;
630 }
631 return true;
632}
633
634void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
635 // The RPC info block contains the intended transaction ID, as well as the sizes for both inbound and outbound data.
636 // Ignore the args -- the `split_shmem` already has the info, we just need to act upon it.
637 // We must keep the `split_transaction_table` non-const, so that it is able to be modified at runtime.
638
639 split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = split_shmem->rpc_info.m2s_length;
640 split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = split_shmem->rpc_info.s2m_length;
641}
642
643void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
644 // We can assume that the buffer lengths are correctly set, now, given that sequentially the rpc_info callback was already executed.
645 // Go through the rpc_info and execute _that_ transaction's callback, with the scratch buffers as inputs.
646 int8_t transaction_id = split_shmem->rpc_info.transaction_id;
647 if (transaction_id < NUM_TOTAL_TRANSACTIONS) {
648 split_transaction_desc_t *trans = &split_transaction_table[transaction_id];
649 if (trans->slave_callback) {
650 trans->slave_callback(split_shmem->rpc_info.m2s_length, split_shmem->rpc_m2s_buffer, split_shmem->rpc_info.s2m_length, split_shmem->rpc_s2m_buffer);
651 }
652 }
653}
654
655#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
diff --git a/quantum/split_common/transactions.h b/quantum/split_common/transactions.h
new file mode 100644
index 000000000..4306ba1d8
--- /dev/null
+++ b/quantum/split_common/transactions.h
@@ -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 2 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#include "stdint.h"
20#include "stdbool.h"
21
22#include "matrix.h"
23#include "transaction_id_define.h"
24#include "transport.h"
25
26typedef void (*slave_callback_t)(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
27
28// Split transaction Descriptor
29typedef struct _split_transaction_desc_t {
30 uint8_t * status;
31 uint8_t initiator2target_buffer_size;
32 uint16_t initiator2target_offset;
33 uint8_t target2initiator_buffer_size;
34 uint16_t target2initiator_offset;
35 slave_callback_t slave_callback;
36} split_transaction_desc_t;
37
38// Forward declaration for the split transactions
39extern split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS];
40
41#define split_shmem_offset_ptr(offset) ((void *)(((uint8_t *)split_shmem) + (offset)))
42#define split_trans_initiator2target_buffer(trans) (split_shmem_offset_ptr((trans)->initiator2target_offset))
43#define split_trans_target2initiator_buffer(trans) (split_shmem_offset_ptr((trans)->target2initiator_offset))
44
45// returns false if valid data not received from slave
46bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
47void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
48
49void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback);
50
51bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer);
52
53#define transaction_rpc_send(transaction_id, initiator2target_buffer_size, initiator2target_buffer) transaction_rpc_exec(transaction_id, initiator2target_buffer_size, initiator2target_buffer, 0, NULL)
54#define transaction_rpc_recv(transaction_id, target2initiator_buffer_size, target2initiator_buffer) transaction_rpc_exec(transaction_id, 0, NULL, target2initiator_buffer_size, target2initiator_buffer)
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
index 9ed0f7591..a711ef85f 100644
--- a/quantum/split_common/transport.c
+++ b/quantum/split_common/transport.c
@@ -1,452 +1,118 @@
1#include <string.h> 1/* Copyright 2021 QMK
2#include <stddef.h> 2 *
3 3 * This program is free software: you can redistribute it and/or modify
4#include "config.h" 4 * it under the terms of the GNU General Public License as published by
5#include "matrix.h" 5 * the Free Software Foundation, either version 2 of the License, or
6#include "quantum.h" 6 * (at your option) any later version.
7 7 *
8#define ROWS_PER_HAND (MATRIX_ROWS / 2) 8 * This program is distributed in the hope that it will be useful,
9#define SYNC_TIMER_OFFSET 2 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11#ifdef RGBLIGHT_ENABLE 11 * GNU General Public License for more details.
12# include "rgblight.h" 12 *
13#endif 13 * You should have received a copy of the GNU General Public License
14 14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15#ifdef BACKLIGHT_ENABLE 15 */
16# include "backlight.h"
17#endif
18
19#ifdef ENCODER_ENABLE
20# include "encoder.h"
21static pin_t encoders_pad[] = ENCODERS_PAD_A;
22# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t))
23#endif
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
32#if defined(USE_I2C)
33 16
34# include "i2c_master.h" 17#include <string.h>
35# include "i2c_slave.h" 18#include <debug.h>
36
37typedef struct _I2C_slave_buffer_t {
38# ifndef DISABLE_SYNC_TIMER
39 uint32_t sync_timer;
40# endif
41# ifdef SPLIT_TRANSPORT_MIRROR
42 matrix_row_t mmatrix[ROWS_PER_HAND];
43# endif
44 matrix_row_t smatrix[ROWS_PER_HAND];
45# ifdef SPLIT_MODS_ENABLE
46 uint8_t real_mods;
47 uint8_t weak_mods;
48# ifndef NO_ACTION_ONESHOT
49 uint8_t oneshot_mods;
50# endif
51# endif
52# ifdef BACKLIGHT_ENABLE
53 uint8_t backlight_level;
54# endif
55# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
56 rgblight_syncinfo_t rgblight_sync;
57# endif
58# ifdef ENCODER_ENABLE
59 uint8_t encoder_state[NUMBER_OF_ENCODERS];
60# endif
61# ifdef WPM_ENABLE
62 uint8_t current_wpm;
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
72} I2C_slave_buffer_t;
73 19
74static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; 20#include "transactions.h"
21#include "transport.h"
22#include "transaction_id_define.h"
23#include "atomic_util.h"
75 24
76# define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer) 25#ifdef USE_I2C
77# define I2C_KEYMAP_MASTER_START offsetof(I2C_slave_buffer_t, mmatrix)
78# define I2C_KEYMAP_SLAVE_START offsetof(I2C_slave_buffer_t, smatrix)
79# define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods)
80# define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods)
81# define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods)
82# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level)
83# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)
84# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)
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)
90 26
91# define TIMEOUT 100 27# ifndef SLAVE_I2C_TIMEOUT
28# define SLAVE_I2C_TIMEOUT 100
29# endif // SLAVE_I2C_TIMEOUT
92 30
93# ifndef SLAVE_I2C_ADDRESS 31# ifndef SLAVE_I2C_ADDRESS
94# define SLAVE_I2C_ADDRESS 0x32 32# define SLAVE_I2C_ADDRESS 0x32
95# endif 33# endif
96 34
97// Get rows from other half over i2c 35# include "i2c_master.h"
98bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { 36# include "i2c_slave.h"
99 i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_SLAVE_START, (void *)slave_matrix, sizeof(i2c_buffer->smatrix), TIMEOUT);
100# ifdef SPLIT_TRANSPORT_MIRROR
101 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_MASTER_START, (void *)master_matrix, sizeof(i2c_buffer->mmatrix), TIMEOUT);
102# endif
103 37
104 // write backlight info 38// Ensure the I2C buffer has enough space
105# ifdef BACKLIGHT_ENABLE 39_Static_assert(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT");
106 uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0;
107 if (level != i2c_buffer->backlight_level) {
108 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) {
109 i2c_buffer->backlight_level = level;
110 }
111 }
112# endif
113 40
114# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) 41split_shared_memory_t *const split_shmem = (split_shared_memory_t *)i2c_slave_reg;
115 if (rgblight_get_change_flags()) {
116 rgblight_syncinfo_t rgblight_sync;
117 rgblight_get_syncinfo(&rgblight_sync);
118 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) {
119 rgblight_clear_change_flags();
120 }
121 }
122# endif
123 42
124# ifdef ENCODER_ENABLE 43void transport_master_init(void) { i2c_init(); }
125 i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT); 44void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }
126 encoder_update_raw(i2c_buffer->encoder_state);
127# endif
128 45
129# ifdef WPM_ENABLE 46i2c_status_t transport_trigger_callback(int8_t id) {
130 uint8_t current_wpm = get_current_wpm(); 47 // If there's no callback, indicate that we were successful
131 if (current_wpm != i2c_buffer->current_wpm) { 48 if (!split_transaction_table[id].slave_callback) {
132 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)&current_wpm, sizeof(current_wpm), TIMEOUT) >= 0) { 49 return I2C_STATUS_SUCCESS;
133 i2c_buffer->current_wpm = current_wpm;
134 }
135 } 50 }
136# endif
137 51
138# ifdef SPLIT_MODS_ENABLE 52 // Kick off the "callback executor", now that data has been written to the slave
139 uint8_t real_mods = get_mods(); 53 split_shmem->transaction_id = id;
140 if (real_mods != i2c_buffer->real_mods) { 54 split_transaction_desc_t *trans = &split_transaction_table[I2C_EXECUTE_CALLBACK];
141 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) { 55 return i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, SLAVE_I2C_TIMEOUT);
142 i2c_buffer->real_mods = real_mods; 56}
57
58bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) {
59 i2c_status_t status;
60 split_transaction_desc_t *trans = &split_transaction_table[id];
61 if (initiator2target_length > 0) {
62 size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length;
63 memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len);
64 if ((status = i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) {
65 return false;
143 } 66 }
144 } 67 }
145 68
146 uint8_t weak_mods = get_weak_mods(); 69 // If we need to execute a callback on the slave, do so
147 if (weak_mods != i2c_buffer->weak_mods) { 70 if ((status = transport_trigger_callback(id)) < 0) {
148 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) { 71 return false;
149 i2c_buffer->weak_mods = weak_mods;
150 }
151 } 72 }
152 73
153# ifndef NO_ACTION_ONESHOT 74 if (target2initiator_length > 0) {
154 uint8_t oneshot_mods = get_oneshot_mods(); 75 size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length;
155 if (oneshot_mods != i2c_buffer->oneshot_mods) { 76 if ((status = i2c_readReg(SLAVE_I2C_ADDRESS, trans->target2initiator_offset, split_trans_target2initiator_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) {
156 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) { 77 return false;
157 i2c_buffer->oneshot_mods = oneshot_mods;
158 } 78 }
79 memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len);
159 } 80 }
160# endif
161# endif
162 81
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
174# ifndef DISABLE_SYNC_TIMER
175 i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
176 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT);
177# endif
178 return true; 82 return true;
179} 83}
180 84
181void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { 85#else // USE_I2C
182# ifndef DISABLE_SYNC_TIMER
183 sync_timer_update(i2c_buffer->sync_timer);
184# endif
185 // Copy matrix to I2C buffer
186 memcpy((void *)i2c_buffer->smatrix, (void *)slave_matrix, sizeof(i2c_buffer->smatrix));
187# ifdef SPLIT_TRANSPORT_MIRROR
188 memcpy((void *)master_matrix, (void *)i2c_buffer->mmatrix, sizeof(i2c_buffer->mmatrix));
189# endif
190
191// Read Backlight Info
192# ifdef BACKLIGHT_ENABLE
193 backlight_set(i2c_buffer->backlight_level);
194# endif
195
196# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
197 // Update the RGB with the new data
198 if (i2c_buffer->rgblight_sync.status.change_flags != 0) {
199 rgblight_update_sync(&i2c_buffer->rgblight_sync, false);
200 i2c_buffer->rgblight_sync.status.change_flags = 0;
201 }
202# endif
203
204# ifdef ENCODER_ENABLE
205 encoder_state_raw(i2c_buffer->encoder_state);
206# endif
207
208# ifdef WPM_ENABLE
209 set_current_wpm(i2c_buffer->current_wpm);
210# endif
211
212# ifdef SPLIT_MODS_ENABLE
213 set_mods(i2c_buffer->real_mods);
214 set_weak_mods(i2c_buffer->weak_mods);
215# ifndef NO_ACTION_ONESHOT
216 set_oneshot_mods(i2c_buffer->oneshot_mods);
217# 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
228}
229
230void transport_master_init(void) { i2c_init(); }
231
232void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }
233
234#else // USE_SERIAL
235 86
236# include "serial.h" 87# include "serial.h"
237 88
238typedef struct _Serial_s2m_buffer_t { 89static split_shared_memory_t shared_memory;
239 // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack 90split_shared_memory_t *const split_shmem = &shared_memory;
240 matrix_row_t smatrix[ROWS_PER_HAND];
241
242# ifdef ENCODER_ENABLE
243 uint8_t encoder_state[NUMBER_OF_ENCODERS];
244# endif
245
246} Serial_s2m_buffer_t;
247
248typedef struct _Serial_m2s_buffer_t {
249# ifdef SPLIT_MODS_ENABLE
250 uint8_t real_mods;
251 uint8_t weak_mods;
252# ifndef NO_ACTION_ONESHOT
253 uint8_t oneshot_mods;
254# endif
255# endif
256# ifndef DISABLE_SYNC_TIMER
257 uint32_t sync_timer;
258# endif
259# ifdef SPLIT_TRANSPORT_MIRROR
260 matrix_row_t mmatrix[ROWS_PER_HAND];
261# endif
262# ifdef BACKLIGHT_ENABLE
263 uint8_t backlight_level;
264# endif
265# ifdef WPM_ENABLE
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;
275# endif
276} Serial_m2s_buffer_t;
277
278# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
279// When MCUs on both sides drive their respective RGB LED chains,
280// it is necessary to synchronize, so it is necessary to communicate RGB
281// information. In that case, define RGBLIGHT_SPLIT with info on the number
282// of LEDs on each half.
283//
284// Otherwise, if the master side MCU drives both sides RGB LED chains,
285// there is no need to communicate.
286
287typedef struct _Serial_rgblight_t {
288 rgblight_syncinfo_t rgblight_sync;
289} Serial_rgblight_t;
290 91
291volatile Serial_rgblight_t serial_rgblight = {}; 92void transport_master_init(void) { soft_serial_initiator_init(); }
292uint8_t volatile status_rgblight = 0; 93void transport_slave_init(void) { soft_serial_target_init(); }
293# endif
294
295volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
296volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
297uint8_t volatile status0 = 0;
298
299enum serial_transaction_id {
300 GET_SLAVE_MATRIX = 0,
301# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
302 PUT_RGBLIGHT,
303# endif
304};
305
306SSTD_t transactions[] = {
307 [GET_SLAVE_MATRIX] =
308 {
309 (uint8_t *)&status0,
310 sizeof(serial_m2s_buffer),
311 (uint8_t *)&serial_m2s_buffer,
312 sizeof(serial_s2m_buffer),
313 (uint8_t *)&serial_s2m_buffer,
314 },
315# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
316 [PUT_RGBLIGHT] =
317 {
318 (uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer
319 },
320# endif
321};
322
323void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
324
325void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
326 94
327# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) 95bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) {
328 96 split_transaction_desc_t *trans = &split_transaction_table[id];
329// rgblight synchronization information communication. 97 if (initiator2target_length > 0) {
330 98 size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length;
331void transport_rgblight_master(void) { 99 memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len);
332 if (rgblight_get_change_flags()) {
333 rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync);
334 if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) {
335 rgblight_clear_change_flags();
336 }
337 }
338}
339
340void transport_rgblight_slave(void) {
341 if (status_rgblight == TRANSACTION_ACCEPTED) {
342 rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false);
343 status_rgblight = TRANSACTION_END;
344 } 100 }
345}
346 101
347# else 102 if (soft_serial_transaction(id) != TRANSACTION_END) {
348# define transport_rgblight_master()
349# define transport_rgblight_slave()
350# endif
351
352bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
353# ifndef SERIAL_USE_MULTI_TRANSACTION
354 if (soft_serial_transaction() != TRANSACTION_END) {
355 return false;
356 }
357# else
358 transport_rgblight_master();
359 if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) {
360 return false; 103 return false;
361 } 104 }
362# endif
363 105
364 // TODO: if MATRIX_COLS > 8 change to unpack() 106 if (target2initiator_length > 0) {
365 for (int i = 0; i < ROWS_PER_HAND; ++i) { 107 size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length;
366 slave_matrix[i] = serial_s2m_buffer.smatrix[i]; 108 memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len);
367# ifdef SPLIT_TRANSPORT_MIRROR
368 serial_m2s_buffer.mmatrix[i] = master_matrix[i];
369# endif
370 } 109 }
371 110
372# ifdef BACKLIGHT_ENABLE
373 // Write backlight level for slave to read
374 serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0;
375# endif
376
377# ifdef ENCODER_ENABLE
378 encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state);
379# endif
380
381# ifdef WPM_ENABLE
382 // Write wpm to slave
383 serial_m2s_buffer.current_wpm = get_current_wpm();
384# endif
385
386# ifdef SPLIT_MODS_ENABLE
387 serial_m2s_buffer.real_mods = get_mods();
388 serial_m2s_buffer.weak_mods = get_weak_mods();
389# ifndef NO_ACTION_ONESHOT
390 serial_m2s_buffer.oneshot_mods = get_oneshot_mods();
391# 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
403# ifndef DISABLE_SYNC_TIMER
404 serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
405# endif
406 return true; 111 return true;
407} 112}
408 113
409void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { 114#endif // USE_I2C
410 transport_rgblight_slave();
411# ifndef DISABLE_SYNC_TIMER
412 sync_timer_update(serial_m2s_buffer.sync_timer);
413# endif
414
415 // TODO: if MATRIX_COLS > 8 change to pack()
416 for (int i = 0; i < ROWS_PER_HAND; ++i) {
417 serial_s2m_buffer.smatrix[i] = slave_matrix[i];
418# ifdef SPLIT_TRANSPORT_MIRROR
419 master_matrix[i] = serial_m2s_buffer.mmatrix[i];
420# endif
421 }
422# ifdef BACKLIGHT_ENABLE
423 backlight_set(serial_m2s_buffer.backlight_level);
424# endif
425
426# ifdef ENCODER_ENABLE
427 encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state);
428# endif
429 115
430# ifdef WPM_ENABLE 116bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { return transactions_master(master_matrix, slave_matrix); }
431 set_current_wpm(serial_m2s_buffer.current_wpm);
432# endif
433
434# ifdef SPLIT_MODS_ENABLE
435 set_mods(serial_m2s_buffer.real_mods);
436 set_weak_mods(serial_m2s_buffer.weak_mods);
437# ifndef NO_ACTION_ONESHOT
438 set_oneshot_mods(serial_m2s_buffer.oneshot_mods);
439# 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
450}
451 117
452#endif 118void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { transactions_slave(master_matrix, slave_matrix); } \ No newline at end of file
diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h
index a9f66301b..2e07f6b25 100644
--- a/quantum/split_common/transport.h
+++ b/quantum/split_common/transport.h
@@ -1,10 +1,175 @@
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 2 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
1#pragma once 17#pragma once
2 18
19#include "stdint.h"
20#include "stdbool.h"
21
22#include "progmem.h"
23#include "action_layer.h"
3#include "matrix.h" 24#include "matrix.h"
4 25
26#ifndef RPC_M2S_BUFFER_SIZE
27# define RPC_M2S_BUFFER_SIZE 32
28#endif // RPC_M2S_BUFFER_SIZE
29
30#ifndef RPC_S2M_BUFFER_SIZE
31# define RPC_S2M_BUFFER_SIZE 32
32#endif // RPC_S2M_BUFFER_SIZE
33
5void transport_master_init(void); 34void transport_master_init(void);
6void transport_slave_init(void); 35void transport_slave_init(void);
7 36
8// returns false if valid data not received from slave 37// returns false if valid data not received from slave
9bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); 38bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
10void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); 39void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
40
41bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length);
42
43#ifdef ENCODER_ENABLE
44# include "encoder.h"
45# define NUMBER_OF_ENCODERS (sizeof((pin_t[])ENCODERS_PAD_A) / sizeof(pin_t))
46#endif // ENCODER_ENABLE
47
48#ifdef BACKLIGHT_ENABLE
49# include "backlight.h"
50#endif // BACKLIGHT_ENABLE
51
52#ifdef RGBLIGHT_ENABLE
53# include "rgblight.h"
54#endif // RGBLIGHT_ENABLE
55
56typedef struct _split_slave_matrix_sync_t {
57 uint8_t checksum;
58 matrix_row_t matrix[(MATRIX_ROWS) / 2];
59} split_slave_matrix_sync_t;
60
61#ifdef SPLIT_TRANSPORT_MIRROR
62typedef struct _split_master_matrix_sync_t {
63 matrix_row_t matrix[(MATRIX_ROWS) / 2];
64} split_master_matrix_sync_t;
65#endif // SPLIT_TRANSPORT_MIRROR
66
67#ifdef ENCODER_ENABLE
68typedef struct _split_slave_encoder_sync_t {
69 uint8_t checksum;
70 uint8_t state[NUMBER_OF_ENCODERS];
71} split_slave_encoder_sync_t;
72#endif // ENCODER_ENABLE
73
74#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
75typedef struct _split_layers_sync_t {
76 layer_state_t layer_state;
77 layer_state_t default_layer_state;
78} split_layers_sync_t;
79#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
80
81#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
82# include "led_matrix.h"
83
84typedef struct _led_matrix_sync_t {
85 led_eeconfig_t led_matrix;
86 bool led_suspend_state;
87} led_matrix_sync_t;
88#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
89
90#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
91# include "rgb_matrix.h"
92
93typedef struct _rgb_matrix_sync_t {
94 rgb_config_t rgb_matrix;
95 bool rgb_suspend_state;
96} rgb_matrix_sync_t;
97#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
98
99#ifdef SPLIT_MODS_ENABLE
100typedef struct _split_mods_sync_t {
101 uint8_t real_mods;
102 uint8_t weak_mods;
103# ifndef NO_ACTION_ONESHOT
104 uint8_t oneshot_mods;
105# endif // NO_ACTION_ONESHOT
106} split_mods_sync_t;
107#endif // SPLIT_MODS_ENABLE
108
109#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
110typedef struct _rpc_sync_info_t {
111 int8_t transaction_id;
112 uint8_t m2s_length;
113 uint8_t s2m_length;
114} rpc_sync_info_t;
115#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
116
117typedef struct _split_shared_memory_t {
118#ifdef USE_I2C
119 int8_t transaction_id;
120#endif // USE_I2C
121
122 split_slave_matrix_sync_t smatrix;
123
124#ifdef SPLIT_TRANSPORT_MIRROR
125 split_master_matrix_sync_t mmatrix;
126#endif // SPLIT_TRANSPORT_MIRROR
127
128#ifdef ENCODER_ENABLE
129 split_slave_encoder_sync_t encoders;
130#endif // ENCODER_ENABLE
131
132#ifndef DISABLE_SYNC_TIMER
133 uint32_t sync_timer;
134#endif // DISABLE_SYNC_TIMER
135
136#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
137 split_layers_sync_t layers;
138#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)
139
140#ifdef SPLIT_LED_STATE_ENABLE
141 uint8_t led_state;
142#endif // SPLIT_LED_STATE_ENABLE
143
144#ifdef SPLIT_MODS_ENABLE
145 split_mods_sync_t mods;
146#endif // SPLIT_MODS_ENABLE
147
148#ifdef BACKLIGHT_ENABLE
149 uint8_t backlight_level;
150#endif // BACKLIGHT_ENABLE
151
152#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
153 rgblight_syncinfo_t rgblight_sync;
154#endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
155
156#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
157 led_matrix_sync_t led_matrix_sync;
158#endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
159
160#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
161 rgb_matrix_sync_t rgb_matrix_sync;
162#endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
163
164#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
165 uint8_t current_wpm;
166#endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
167
168#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
169 rpc_sync_info_t rpc_info;
170 uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];
171 uint8_t rpc_s2m_buffer[RPC_S2M_BUFFER_SIZE];
172#endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
173} split_shared_memory_t;
174
175extern split_shared_memory_t *const split_shmem; \ No newline at end of file