diff options
Diffstat (limited to 'quantum')
| -rw-r--r-- | quantum/color.h | 54 | ||||
| -rw-r--r-- | quantum/command.c | 2 | ||||
| -rw-r--r-- | quantum/crc.c | 59 | ||||
| -rw-r--r-- | quantum/crc.h (renamed from quantum/rgb.h) | 45 | ||||
| -rw-r--r-- | quantum/debounce.h | 2 | ||||
| -rw-r--r-- | quantum/debounce/asym_eager_defer_pk.c | 171 | ||||
| -rw-r--r-- | quantum/debounce/none.c | 31 | ||||
| -rw-r--r-- | quantum/debounce/sym_defer_g.c | 26 | ||||
| -rw-r--r-- | quantum/debounce/sym_defer_pk.c | 67 | ||||
| -rw-r--r-- | quantum/debounce/sym_eager_pk.c | 72 | ||||
| -rw-r--r-- | quantum/debounce/sym_eager_pr.c | 76 | ||||
| -rw-r--r-- | quantum/debounce/tests/asym_eager_defer_pk_tests.cpp | 374 | ||||
| -rw-r--r-- | quantum/debounce/tests/debounce_test_common.cpp | 229 | ||||
| -rw-r--r-- | quantum/debounce/tests/debounce_test_common.h | 83 | ||||
| -rw-r--r-- | quantum/debounce/tests/rules.mk | 44 | ||||
| -rw-r--r-- | quantum/debounce/tests/sym_defer_g_tests.cpp | 223 | ||||
| -rw-r--r-- | quantum/debounce/tests/sym_defer_pk_tests.cpp | 225 | ||||
| -rw-r--r-- | quantum/debounce/tests/sym_eager_pk_tests.cpp | 237 | ||||
| -rw-r--r-- | quantum/debounce/tests/sym_eager_pr_tests.cpp | 280 | ||||
| -rw-r--r-- | quantum/debounce/tests/testlist.mk | 6 | ||||
| -rw-r--r-- | quantum/dip_switch.c | 8 | ||||
| -rw-r--r-- | quantum/dip_switch.h | 8 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_belgian.h | 13 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_bepo.h | 167 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_br_abnt2.h | 20 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_canadian_multilingual.h | 179 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_colemak.h | 32 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_fr_ch.h | 79 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_french.h | 11 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_french_osx.h | 12 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_german.h | 13 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_german_ch.h | 18 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_german_osx.h | 80 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_hungarian.h | 19 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_italian.h | 19 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_italian_osx_ansi.h | 18 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_italian_osx_iso.h | 18 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_jp.h | 9 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_neo2.h | 52 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_norwegian.h | 23 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_slovenian.h | 8 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_spanish.h | 9 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_swedish.h | 23 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_uk.h | 75 | ||||
| -rw-r--r-- | quantum/keymap_extras/keymap_workman.h | 29 | ||||
| -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.inc | 18 | ||||
| -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.inc | 6 | ||||
| -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.inc | 18 | ||||
| -rw-r--r-- | quantum/matrix.c | 143 | ||||
| -rw-r--r-- | quantum/mcu_selection.mk | 72 | ||||
| -rw-r--r-- | quantum/mousekey.c | 2 | ||||
| -rw-r--r-- | quantum/mousekey.h | 11 | ||||
| -rw-r--r-- | quantum/process_keycode/process_rgb.c | 1 | ||||
| -rw-r--r-- | quantum/quantum.c | 8 | ||||
| -rw-r--r-- | quantum/quantum.h | 4 | ||||
| -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.inc | 37 | ||||
| -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.inc | 6 | ||||
| -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.inc | 37 | ||||
| -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.c | 22 | ||||
| -rw-r--r-- | quantum/split_common/matrix.c | 147 | ||||
| -rw-r--r-- | quantum/split_common/post_config.h | 9 | ||||
| -rw-r--r-- | quantum/split_common/split_util.c | 4 | ||||
| -rw-r--r-- | quantum/split_common/transaction_id_define.h | 94 | ||||
| -rw-r--r-- | quantum/split_common/transactions.c | 655 | ||||
| -rw-r--r-- | quantum/split_common/transactions.h | 54 | ||||
| -rw-r--r-- | quantum/split_common/transport.c | 484 | ||||
| -rw-r--r-- | quantum/split_common/transport.h | 165 | 
146 files changed, 3653 insertions, 1798 deletions
| diff --git a/quantum/color.h b/quantum/color.h index 4783f6839c..e2cfc46927 100644 --- a/quantum/color.h +++ b/quantum/color.h @@ -19,6 +19,60 @@  #include <stdint.h>  #include <stdbool.h> +// clang-format off + +/* + * RGB Colors + */ +#define RGB_AZURE       0x99, 0xF5, 0xFF +#define RGB_BLACK       0x00, 0x00, 0x00 +#define RGB_BLUE        0x00, 0x00, 0xFF +#define RGB_CHARTREUSE  0x80, 0xFF, 0x00 +#define RGB_CORAL       0xFF, 0x7C, 0x4D +#define RGB_CYAN        0x00, 0xFF, 0xFF +#define RGB_GOLD        0xFF, 0xD9, 0x00 +#define RGB_GOLDENROD   0xD9, 0xA5, 0x21 +#define RGB_GREEN       0x00, 0xFF, 0x00 +#define RGB_MAGENTA     0xFF, 0x00, 0xFF +#define RGB_ORANGE      0xFF, 0x80, 0x00 +#define RGB_PINK        0xFF, 0x80, 0xBF +#define RGB_PURPLE      0x7A, 0x00, 0xFF +#define RGB_RED         0xFF, 0x00, 0x00 +#define RGB_SPRINGGREEN 0x00, 0xFF, 0x80 +#define RGB_TEAL        0x00, 0x80, 0x80 +#define RGB_TURQUOISE   0x47, 0x6E, 0x6A +#define RGB_WHITE       0xFF, 0xFF, 0xFF +#define RGB_YELLOW      0xFF, 0xFF, 0x00 +#define RGB_OFF         RGB_BLACK + +/* + * HSV Colors + * + * All values (including hue) are scaled to 0-255 + */ +#define HSV_AZURE       132, 102, 255 +#define HSV_BLACK         0,   0,   0 +#define HSV_BLUE        170, 255, 255 +#define HSV_CHARTREUSE   64, 255, 255 +#define HSV_CORAL        11, 176, 255 +#define HSV_CYAN        128, 255, 255 +#define HSV_GOLD         36, 255, 255 +#define HSV_GOLDENROD    30, 218, 218 +#define HSV_GREEN        85, 255, 255 +#define HSV_MAGENTA     213, 255, 255 +#define HSV_ORANGE       28, 255, 255 +#define HSV_PINK        234, 128, 255 +#define HSV_PURPLE      191, 255, 255 +#define HSV_RED           0, 255, 255 +#define HSV_SPRINGGREEN 106, 255, 255 +#define HSV_TEAL        128, 255, 128 +#define HSV_TURQUOISE   123,  90, 112 +#define HSV_WHITE         0,   0, 255 +#define HSV_YELLOW       43, 255, 255 +#define HSV_OFF         HSV_BLACK + +// clang-format on +  #if defined(__GNUC__)  #    define PACKED __attribute__((__packed__))  #else diff --git a/quantum/command.c b/quantum/command.c index 34c4b36b1c..3a7dc0f8ca 100644 --- a/quantum/command.c +++ b/quantum/command.c @@ -781,6 +781,6 @@ uint8_t numkey2num(uint8_t code) {  static void switch_default_layer(uint8_t layer) {      xprintf("L%d\n", layer); -    default_layer_set(1UL << layer); +    default_layer_set((layer_state_t)1 << layer);      clear_keyboard();  } diff --git a/quantum/crc.c b/quantum/crc.c new file mode 100644 index 0000000000..0d8b9d6017 --- /dev/null +++ b/quantum/crc.c @@ -0,0 +1,59 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "crc.h" + +__attribute__((weak)) void crc_init(void){ +    /* Software implementation nothing todo here. */ +}; + +#if defined(CRC8_USE_TABLE) +/** + * Static table used for the table_driven implementation. + */ +static 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, +                                     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}; + +__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) { +    const uint8_t *d   = (const uint8_t *)data; +    crc_t          crc = 0xff; +    size_t         tbl_idx; + +    while (data_len--) { +        tbl_idx = crc ^ *d; +        crc     = crc_table[tbl_idx] & 0xff; +        d++; +    } +    return crc & 0xff; +} +#else +__attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) { +    const uint8_t *d   = (const uint8_t *)data; +    crc_t          crc = 0xff; +    size_t         i, j; + +    for (i = 0; i < data_len; i++) { +        crc ^= d[i]; +        for (j = 0; j < 8; j++) { +            if ((crc & 0x80) != 0) +                crc = (crc_t)((crc << 1) ^ 0x31); +            else +                crc <<= 1; +        } +    } +    return crc; +} +#endif
\ No newline at end of file diff --git a/quantum/rgb.h b/quantum/crc.h index 2602fc0b20..c17f5888e2 100644 --- a/quantum/rgb.h +++ b/quantum/crc.h @@ -1,4 +1,4 @@ -/* Copyright 2017 Jack Humbert +/* Copyright 2021 QMK   *   * This program is free software: you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -16,24 +16,29 @@  #pragma once -__attribute__((weak)) void rgblight_toggle(void){}; +#include "quantum.h" -__attribute__((weak)) void rgblight_step(void){}; - -__attribute__((weak)) void rgblight_step_reverse(void){}; - -__attribute__((weak)) void rgblight_increase_hue(void){}; - -__attribute__((weak)) void rgblight_decrease_hue(void){}; - -__attribute__((weak)) void rgblight_increase_sat(void){}; - -__attribute__((weak)) void rgblight_decrease_sat(void){}; - -__attribute__((weak)) void rgblight_increase_val(void){}; - -__attribute__((weak)) void rgblight_decrease_val(void){}; - -__attribute__((weak)) void rgblight_increase_speed(void){}; +/** + * The type of the CRC values. + * + * This type must be big enough to contain at least 8 bits. + */ +#if defined(CRC8_OPTIMIZE_SPEED) +typedef uint_fast8_t crc_t; +#else +typedef uint_least8_t crc_t; +#endif + +/** + * Initialize crc subsystem. + */ +__attribute__((weak)) void crc_init(void); -__attribute__((weak)) void rgblight_decrease_speed(void){}; +/** + * Generate CRC8 value from given data. + * + * \param[in] data     Pointer to a buffer of \a data_len bytes. + * \param[in] data_len Number of bytes in the \a data buffer. + * \return             The calculated crc value. + */ +__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 9ca05c6824..5043868289 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  bool debounce_active(void);  void debounce_init(uint8_t num_rows); + +void 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 0000000000..24380dc5e5 --- /dev/null +++ b/quantum/debounce/asym_eager_defer_pk.c @@ -0,0 +1,171 @@ +/* + * Copyright 2017 Alex Ong <the.onga@gmail.com> + * Copyright 2020 Andrei Purdea <andrei@purdea.ro> + * Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +/* +Basic symmetric per-key algorithm. Uses an 8-bit counter per key. +When no state changes have occured for DEBOUNCE milliseconds, we push the state. +*/ + +#include "matrix.h" +#include "timer.h" +#include "quantum.h" +#include <stdlib.h> + +#ifdef PROTOCOL_CHIBIOS +#    if CH_CFG_USE_MEMCORE == FALSE +#        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. +#    endif +#endif + +#ifndef DEBOUNCE +#    define DEBOUNCE 5 +#endif + +// Maximum debounce: 127ms +#if DEBOUNCE > 127 +#    undef DEBOUNCE +#    define DEBOUNCE 127 +#endif + +#define ROW_SHIFTER ((matrix_row_t)1) + +typedef struct { +    bool pressed : 1; +    uint8_t time : 7; +} debounce_counter_t; + +#if DEBOUNCE > 0 +static debounce_counter_t *debounce_counters; +static fast_timer_t last_time; +static bool counters_need_update; +static bool matrix_need_update; + +#define DEBOUNCE_ELAPSED 0 + +static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time); +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); + +// we use num_rows rather than MATRIX_ROWS to support split keyboards +void debounce_init(uint8_t num_rows) { +    debounce_counters = malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t)); +    int i = 0; +    for (uint8_t r = 0; r < num_rows; r++) { +        for (uint8_t c = 0; c < MATRIX_COLS; c++) { +            debounce_counters[i++].time = DEBOUNCE_ELAPSED; +        } +    } +} + +void debounce_free(void) { +    free(debounce_counters); +    debounce_counters = NULL; +} + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { +    bool updated_last = false; + +    if (counters_need_update) { +        fast_timer_t now = timer_read_fast(); +        fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); + +        last_time = now; +        updated_last = true; +        if (elapsed_time > UINT8_MAX) { +            elapsed_time = UINT8_MAX; +        } + +        if (elapsed_time > 0) { +            update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time); +        } +    } + +    if (changed || matrix_need_update) { +        if (!updated_last) { +            last_time = timer_read_fast(); +        } + +        transfer_matrix_values(raw, cooked, num_rows); +    } +} + +static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) { +    debounce_counter_t *debounce_pointer = debounce_counters; + +    counters_need_update = false; +    matrix_need_update = false; + +    for (uint8_t row = 0; row < num_rows; row++) { +        for (uint8_t col = 0; col < MATRIX_COLS; col++) { +            matrix_row_t col_mask = (ROW_SHIFTER << col); + +            if (debounce_pointer->time != DEBOUNCE_ELAPSED) { +                if (debounce_pointer->time <= elapsed_time) { +                    debounce_pointer->time = DEBOUNCE_ELAPSED; + +                    if (debounce_pointer->pressed) { +                        // key-down: eager +                        matrix_need_update = true; +                    } else { +                        // key-up: defer +                        cooked[row] = (cooked[row] & ~col_mask) | (raw[row] & col_mask); +                    } +                } else { +                    debounce_pointer->time -= elapsed_time; +                    counters_need_update = true; +                } +            } +            debounce_pointer++; +        } +    } +} + +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { +    debounce_counter_t *debounce_pointer = debounce_counters; + +    for (uint8_t row = 0; row < num_rows; row++) { +        matrix_row_t delta = raw[row] ^ cooked[row]; +        for (uint8_t col = 0; col < MATRIX_COLS; col++) { +            matrix_row_t col_mask = (ROW_SHIFTER << col); + +            if (delta & col_mask) { +                if (debounce_pointer->time == DEBOUNCE_ELAPSED) { +                    debounce_pointer->pressed = (raw[row] & col_mask); +                    debounce_pointer->time = DEBOUNCE; +                    counters_need_update = true; + +                    if (debounce_pointer->pressed) { +                        // key-down: eager +                        cooked[row] ^= col_mask; +                    } +                } +            } else if (debounce_pointer->time != DEBOUNCE_ELAPSED) { +                if (!debounce_pointer->pressed) { +                    // key-up: defer +                    debounce_pointer->time = DEBOUNCE_ELAPSED; +                } +            } +            debounce_pointer++; +        } +    } +} + +bool debounce_active(void) { return true; } +#else +#    include "none.c" +#endif diff --git a/quantum/debounce/none.c b/quantum/debounce/none.c new file mode 100644 index 0000000000..b03892bc5b --- /dev/null +++ b/quantum/debounce/none.c @@ -0,0 +1,31 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "matrix.h" +#include "quantum.h" +#include <stdlib.h> + +void debounce_init(uint8_t num_rows) {} + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { +    for (int i = 0; i < num_rows; i++) { +        cooked[i] = raw[i]; +    } +} + +bool debounce_active(void) { return false; } + +void debounce_free(void) {} diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c index 3ed9055d2a..fbefd55ede 100644 --- a/quantum/debounce/sym_defer_g.c +++ b/quantum/debounce/sym_defer_g.c @@ -1,5 +1,6 @@  /*  Copyright 2017 Alex Ong<the.onga@gmail.com> +Copyright 2021 Simon Arlott  This program is free software: you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the 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.  #    define DEBOUNCE 5  #endif -void        debounce_init(uint8_t num_rows) {} +#if DEBOUNCE > 0  static bool debouncing = false; +static fast_timer_t debouncing_time; -#if DEBOUNCE > 0 -static uint16_t debouncing_time; -void            debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { +void debounce_init(uint8_t num_rows) {} + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {      if (changed) {          debouncing      = true; -        debouncing_time = timer_read(); +        debouncing_time = timer_read_fast();      } -    if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { +    if (debouncing && timer_elapsed_fast(debouncing_time) >= DEBOUNCE) {          for (int i = 0; i < num_rows; i++) {              cooked[i] = raw[i];          }          debouncing = false;      }  } -#else  // no debouncing. -void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { -    for (int i = 0; i < num_rows; i++) { -        cooked[i] = raw[i]; -    } -} -#endif  bool debounce_active(void) { return debouncing; } + +void debounce_free(void) {} +#else  // no debouncing. +#    include "none.c" +#endif diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c index 60513f98e1..626a9be841 100644 --- a/quantum/debounce/sym_defer_pk.c +++ b/quantum/debounce/sym_defer_pk.c @@ -1,6 +1,7 @@  /*  Copyright 2017 Alex Ong<the.onga@gmail.com>  Copyright 2020 Andrei Purdea<andrei@purdea.ro> +Copyright 2021 Simon Arlott  This program is free software: you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the 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.  #    define DEBOUNCE 5  #endif +// Maximum debounce: 255ms +#if DEBOUNCE > UINT8_MAX +#    undef DEBOUNCE +#    define DEBOUNCE UINT8_MAX +#endif +  #define ROW_SHIFTER ((matrix_row_t)1) -#define debounce_counter_t uint8_t +typedef uint8_t debounce_counter_t; +#if DEBOUNCE > 0  static debounce_counter_t *debounce_counters; +static fast_timer_t        last_time;  static bool                counters_need_update; -#define DEBOUNCE_ELAPSED 251 -#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) - -static uint8_t wrapping_timer_read(void) { -    static uint16_t time        = 0; -    static uint8_t  last_result = 0; -    uint16_t        new_time    = timer_read(); -    uint16_t        diff        = new_time - time; -    time                        = new_time; -    last_result                 = (last_result + diff) % (MAX_DEBOUNCE + 1); -    return last_result; -} +#define DEBOUNCE_ELAPSED 0 -void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); -void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); +static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time); +static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);  // we use num_rows rather than MATRIX_ROWS to support split keyboards  void debounce_init(uint8_t num_rows) { @@ -67,27 +65,49 @@ void debounce_init(uint8_t num_rows) {      }  } +void debounce_free(void) { +    free(debounce_counters); +    debounce_counters = NULL; +} +  void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { -    uint8_t current_time = wrapping_timer_read(); +    bool updated_last = false; +      if (counters_need_update) { -        update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, current_time); +        fast_timer_t now = timer_read_fast(); +        fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); + +        last_time = now; +        updated_last = true; +        if (elapsed_time > UINT8_MAX) { +            elapsed_time = UINT8_MAX; +        } + +        if (elapsed_time > 0) { +            update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time); +        }      }      if (changed) { -        start_debounce_counters(raw, cooked, num_rows, current_time); +        if (!updated_last) { +            last_time = timer_read_fast(); +        } + +        start_debounce_counters(raw, cooked, num_rows);      }  } -void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { +static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time) {      counters_need_update                 = false;      debounce_counter_t *debounce_pointer = debounce_counters;      for (uint8_t row = 0; row < num_rows; row++) {          for (uint8_t col = 0; col < MATRIX_COLS; col++) {              if (*debounce_pointer != DEBOUNCE_ELAPSED) { -                if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { +                if (*debounce_pointer <= elapsed_time) {                      *debounce_pointer = DEBOUNCE_ELAPSED;                      cooked[row]       = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col));                  } else { +                    *debounce_pointer -= elapsed_time;                      counters_need_update = true;                  }              } @@ -96,14 +116,14 @@ void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix      }  } -void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { +static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {      debounce_counter_t *debounce_pointer = debounce_counters;      for (uint8_t row = 0; row < num_rows; row++) {          matrix_row_t delta = raw[row] ^ cooked[row];          for (uint8_t col = 0; col < MATRIX_COLS; col++) {              if (delta & (ROW_SHIFTER << col)) {                  if (*debounce_pointer == DEBOUNCE_ELAPSED) { -                    *debounce_pointer    = current_time; +                    *debounce_pointer    = DEBOUNCE;                      counters_need_update = true;                  }              } else { @@ -115,3 +135,6 @@ void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t  }  bool debounce_active(void) { return true; } +#else +#    include "none.c" +#endif diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c index e66cf92d79..15a3242e68 100644 --- a/quantum/debounce/sym_eager_pk.c +++ b/quantum/debounce/sym_eager_pk.c @@ -1,5 +1,6 @@  /*  Copyright 2017 Alex Ong<the.onga@gmail.com> +Copyright 2021 Simon Arlott  This program is free software: you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation, either version 2 of the License, or @@ -33,29 +34,26 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.  #    define DEBOUNCE 5  #endif +// Maximum debounce: 255ms +#if DEBOUNCE > UINT8_MAX +#    undef DEBOUNCE +#    define DEBOUNCE UINT8_MAX +#endif +  #define ROW_SHIFTER ((matrix_row_t)1) -#define debounce_counter_t uint8_t +typedef uint8_t debounce_counter_t; +#if DEBOUNCE > 0  static debounce_counter_t *debounce_counters; +static fast_timer_t        last_time;  static bool                counters_need_update;  static bool                matrix_need_update; -#define DEBOUNCE_ELAPSED 251 -#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) - -static uint8_t wrapping_timer_read(void) { -    static uint16_t time        = 0; -    static uint8_t  last_result = 0; -    uint16_t        new_time    = timer_read(); -    uint16_t        diff        = new_time - time; -    time                        = new_time; -    last_result                 = (last_result + diff) % (MAX_DEBOUNCE + 1); -    return last_result; -} +#define DEBOUNCE_ELAPSED 0 -void update_debounce_counters(uint8_t num_rows, uint8_t current_time); -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); +static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time); +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);  // we use num_rows rather than MATRIX_ROWS to support split keyboards  void debounce_init(uint8_t num_rows) { @@ -68,27 +66,51 @@ void debounce_init(uint8_t num_rows) {      }  } +void debounce_free(void) { +    free(debounce_counters); +    debounce_counters = NULL; +} +  void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { -    uint8_t current_time = wrapping_timer_read(); +    bool updated_last = false; +      if (counters_need_update) { -        update_debounce_counters(num_rows, current_time); +        fast_timer_t now = timer_read_fast(); +        fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); + +        last_time = now; +        updated_last = true; +        if (elapsed_time > UINT8_MAX) { +            elapsed_time = UINT8_MAX; +        } + +        if (elapsed_time > 0) { +            update_debounce_counters(num_rows, elapsed_time); +        }      }      if (changed || matrix_need_update) { -        transfer_matrix_values(raw, cooked, num_rows, current_time); +        if (!updated_last) { +            last_time = timer_read_fast(); +        } + +        transfer_matrix_values(raw, cooked, num_rows);      }  }  // If the current time is > debounce counter, set the counter to enable input. -void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { +static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {      counters_need_update                 = false; +    matrix_need_update                   = false;      debounce_counter_t *debounce_pointer = debounce_counters;      for (uint8_t row = 0; row < num_rows; row++) {          for (uint8_t col = 0; col < MATRIX_COLS; col++) {              if (*debounce_pointer != DEBOUNCE_ELAPSED) { -                if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { +                if (*debounce_pointer <= elapsed_time) {                      *debounce_pointer = DEBOUNCE_ELAPSED; +                    matrix_need_update = true;                  } else { +                    *debounce_pointer -= elapsed_time;                      counters_need_update = true;                  }              } @@ -98,8 +120,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) {  }  // upload from raw_matrix to final matrix; -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { -    matrix_need_update                   = false; +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {      debounce_counter_t *debounce_pointer = debounce_counters;      for (uint8_t row = 0; row < num_rows; row++) {          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              matrix_row_t col_mask = (ROW_SHIFTER << col);              if (delta & col_mask) {                  if (*debounce_pointer == DEBOUNCE_ELAPSED) { -                    *debounce_pointer    = current_time; +                    *debounce_pointer    = DEBOUNCE;                      counters_need_update = true;                      existing_row ^= col_mask;  // flip the bit. -                } else { -                    matrix_need_update = true;                  }              }              debounce_pointer++; @@ -122,3 +141,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n  }  bool debounce_active(void) { return true; } +#else +#    include "none.c" +#endif diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c index 20ccb46f1d..2ad592c5a6 100644 --- a/quantum/debounce/sym_eager_pr.c +++ b/quantum/debounce/sym_eager_pr.c @@ -1,5 +1,6 @@  /*  Copyright 2019 Alex Ong<the.onga@gmail.com> +Copyright 2021 Simon Arlott  This program is free software: you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation, either version 2 of the License, or @@ -33,27 +34,25 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.  #    define DEBOUNCE 5  #endif -#define debounce_counter_t uint8_t +// Maximum debounce: 255ms +#if DEBOUNCE > UINT8_MAX +#    undef DEBOUNCE +#    define DEBOUNCE UINT8_MAX +#endif + +typedef uint8_t debounce_counter_t; + +#if DEBOUNCE > 0  static bool matrix_need_update;  static debounce_counter_t *debounce_counters; +static fast_timer_t        last_time;  static bool                counters_need_update; -#define DEBOUNCE_ELAPSED 251 -#define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) - -static uint8_t wrapping_timer_read(void) { -    static uint16_t time        = 0; -    static uint8_t  last_result = 0; -    uint16_t        new_time    = timer_read(); -    uint16_t        diff        = new_time - time; -    time                        = new_time; -    last_result                 = (last_result + diff) % (MAX_DEBOUNCE + 1); -    return last_result; -} +#define DEBOUNCE_ELAPSED 0 -void update_debounce_counters(uint8_t num_rows, uint8_t current_time); -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); +static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time); +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);  // we use num_rows rather than MATRIX_ROWS to support split keyboards  void debounce_init(uint8_t num_rows) { @@ -63,27 +62,50 @@ void debounce_init(uint8_t num_rows) {      }  } +void debounce_free(void) { +    free(debounce_counters); +    debounce_counters = NULL; +} +  void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { -    uint8_t current_time  = wrapping_timer_read(); -    bool    needed_update = counters_need_update; +    bool updated_last = false; +      if (counters_need_update) { -        update_debounce_counters(num_rows, current_time); +        fast_timer_t now = timer_read_fast(); +        fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); + +        last_time = now; +        updated_last = true; +        if (elapsed_time > UINT8_MAX) { +            elapsed_time = UINT8_MAX; +        } + +        if (elapsed_time > 0) { +            update_debounce_counters(num_rows, elapsed_time); +        }      } -    if (changed || (needed_update && !counters_need_update) || matrix_need_update) { -        transfer_matrix_values(raw, cooked, num_rows, current_time); +    if (changed || matrix_need_update) { +        if (!updated_last) { +            last_time = timer_read_fast(); +        } + +        transfer_matrix_values(raw, cooked, num_rows);      }  }  // If the current time is > debounce counter, set the counter to enable input. -void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { +static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {      counters_need_update                 = false; +    matrix_need_update                   = false;      debounce_counter_t *debounce_pointer = debounce_counters;      for (uint8_t row = 0; row < num_rows; row++) {          if (*debounce_pointer != DEBOUNCE_ELAPSED) { -            if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { +            if (*debounce_pointer <= elapsed_time) {                  *debounce_pointer = DEBOUNCE_ELAPSED; +                matrix_need_update = true;              } else { +                *debounce_pointer -= elapsed_time;                  counters_need_update = true;              }          } @@ -92,8 +114,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) {  }  // upload from raw_matrix to final matrix; -void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { -    matrix_need_update                   = false; +static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {      debounce_counter_t *debounce_pointer = debounce_counters;      for (uint8_t row = 0; row < num_rows; row++) {          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          // determine new value basd on debounce pointer + raw value          if (existing_row != raw_row) {              if (*debounce_pointer == DEBOUNCE_ELAPSED) { -                *debounce_pointer    = current_time; +                *debounce_pointer    = DEBOUNCE;                  cooked[row]          = raw_row;                  counters_need_update = true; -            } else { -                matrix_need_update = true;              }          }          debounce_pointer++; @@ -114,3 +133,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n  }  bool debounce_active(void) { return true; } +#else +#    include "none.c" +#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 0000000000..fe374c3dfa --- /dev/null +++ b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp @@ -0,0 +1,374 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Release key after 1ms delay */ +        {1, {{0, 1, UP}}, {}}, + +        /* +         * Until the eager timer on DOWN is observed to finish, the defer timer +         * on UP can't start. There's no workaround for this because it's not +         * possible to debounce an event that isn't being tracked. +         * +         * sym_defer_pk has the same problem but the test has to track that the +         * key changed state so the DOWN timer is always allowed to finish +         * before starting the UP timer. +         */ +        {5, {}, {}}, + +        {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ +        /* Press key again after 1ms delay */ +        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Release key after 2ms delay */ +        {2, {{0, 1, UP}}, {}}, + +        {5, {}, {}}, /* See OneKeyShort1 */ + +        {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ +        /* Press key again after 1ms delay */ +        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Release key after 3ms delay */ +        {3, {{0, 1, UP}}, {}}, + +        {5, {}, {}}, /* See OneKeyShort1 */ + +        {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ +        /* Press key again after 1ms delay */ +        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort4) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Release key after 4ms delay */ +        {4, {{0, 1, UP}}, {}}, + +        {5, {}, {}}, /* See OneKeyShort1 */ + +        {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ +        /* Press key again after 1ms delay */ +        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort5) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Release key after 5ms delay */ +        {5, {{0, 1, UP}}, {}}, + +        {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ +        /* Press key again after 1ms delay */ +        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort6) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Release key after 6ms delay */ +        {6, {{0, 1, UP}}, {}}, + +        {11, {}, {{0, 1, UP}}}, /* 5ms after UP at time 6 */ +        /* Press key again after 1ms delay */ +        {12, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort7) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Release key after 7ms delay */ +        {7, {{0, 1, UP}}, {}}, + +        {12, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */ +        /* Press key again after 1ms delay */ +        {13, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort8) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Release key after 1ms delay */ +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {}}, /* See OneKeyShort1 */ + +        {10, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */ +        /* Press key again after 0ms delay (scan 2) */ +        {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort9) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Release key after 1ms delay */ +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {}}, /* See OneKeyShort1 */ + +        /* Press key again after 0ms delay (same scan) before debounce finishes */ +        {10, {{0, 1, DOWN}}, {}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, +        {2, {{0, 1, DOWN}}, {}}, +        {3, {{0, 1, UP}}, {}}, +        {4, {{0, 1, DOWN}}, {}}, +        {5, {{0, 1, UP}}, {}}, +        {6, {{0, 1, DOWN}}, {}}, +        {7, {{0, 1, UP}}, {}}, +        {8, {{0, 1, DOWN}}, {}}, +        {9, {{0, 1, UP}}, {}}, +        {10, {{0, 1, DOWN}}, {}}, +        {11, {{0, 1, UP}}, {}}, +        {12, {{0, 1, DOWN}}, {}}, +        {13, {{0, 1, UP}}, {}}, +        {14, {{0, 1, DOWN}}, {}}, +        {15, {{0, 1, UP}}, {}}, + +        {20, {}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay */ +        {21, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Change twice in the same time period */ +        {1, {{0, 1, UP}}, {}}, +        {1, {{0, 1, DOWN}}, {}}, +        /* Change three times in the same time period */ +        {2, {{0, 1, UP}}, {}}, +        {2, {{0, 1, DOWN}}, {}}, +        {2, {{0, 1, UP}}, {}}, +        /* Change twice in the same time period */ +        {6, {{0, 1, DOWN}}, {}}, +        {6, {{0, 1, UP}}, {}}, +        /* Change three times in the same time period */ +        {7, {{0, 1, DOWN}}, {}}, +        {7, {{0, 1, UP}}, {}}, +        {7, {{0, 1, DOWN}}, {}}, +        /* Change twice in the same time period */ +        {8, {{0, 1, UP}}, {}}, +        {8, {{0, 1, DOWN}}, {}}, +        /* Change three times in the same time period */ +        {9, {{0, 1, UP}}, {}}, +        {9, {{0, 1, DOWN}}, {}}, +        {9, {{0, 1, UP}}, {}}, + +        {14, {}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay */ +        {15, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        {25, {{0, 1, UP}}, {}}, + +        {30, {}, {{0, 1, UP}}}, + +        {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        {75, {{0, 1, UP}}, {}}, + +        {80, {}, {{0, 1, UP}}}, + +        {100, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysShort) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, +        /* Release key after 2ms delay */ +        {2, {{0, 1, UP}}, {}}, +        {3, {{0, 2, UP}}, {}}, + +        {5, {}, {}}, /* See OneKeyShort1 */ +        {6, {}, {}}, /* See OneKeyShort1 */ + +        {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ +        /* Press key again after 1ms delay */ +        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}, {0, 2, UP}}}, /* 5ms+5ms after DOWN at time 0 */ +        {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */ +    }); +    runEvents(); +} + + +TEST_F(DebounceTest, OneKeyDelayedScan1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late, immediately release key */ +        {300, {{0, 1, UP}}, {}}, + +        {305, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late, immediately release key */ +        {300, {{0, 1, UP}}, {}}, + +        /* Processing is very late again */ +        {600, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late */ +        {300, {}, {}}, +        /* Release key after 1ms */ +        {301, {{0, 1, UP}}, {}}, + +        {306, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late */ +        {300, {}, {}}, +        /* Release key after 1ms */ +        {301, {{0, 1, UP}}, {}}, + +        /* Processing is very late again */ +        {600, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan5) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        {5, {{0, 1, UP}}, {}}, + +        /* Processing is very late */ +        {300, {}, {{0, 1, UP}}}, +        /* Immediately press key again */ +        {300, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan6) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        {5, {{0, 1, UP}}, {}}, + +        /* Processing is very late */ +        {300, {}, {{0, 1, UP}}}, + +        /* Press key again after 1ms */ +        {301, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan7) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        {5, {{0, 1, UP}}, {}}, + +        /* Press key again before debounce expires */ +        {300, {{0, 1, DOWN}}, {}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan8) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is a bit late */ +        {50, {}, {}}, +        /* Release key after 1ms */ +        {51, {{0, 1, UP}}, {}}, + +        /* Processing is a bit late again */ +        {100, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp new file mode 100644 index 0000000000..1c5e7c9f4e --- /dev/null +++ b/quantum/debounce/tests/debounce_test_common.cpp @@ -0,0 +1,229 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +#include <algorithm> +#include <iomanip> +#include <sstream> + +extern "C" { +#include "quantum.h" +#include "timer.h" +#include "debounce.h" + +void set_time(uint32_t t); +void advance_time(uint32_t ms); +} + +void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) { +    events_.insert(events_.end(), events.begin(), events.end()); +} + +void DebounceTest::runEvents() { +    /* Run the test multiple times, from 1kHz to 10kHz scan rate */ +    for (extra_iterations_ = 0; extra_iterations_ < 10; extra_iterations_++) { +        if (time_jumps_) { +            /* Don't advance time smoothly, jump to the next event (some tests require this) */ +            auto_advance_time_ = false; +            runEventsInternal(); +        } else { +            /* Run the test with both smooth and irregular time; it must produce the same result */ +            auto_advance_time_ = true; +            runEventsInternal(); +            auto_advance_time_ = false; +            runEventsInternal(); +        } +    } +} + +void DebounceTest::runEventsInternal() { +    fast_timer_t previous = 0; +    bool first = true; + +    /* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */ +    debounce_init(MATRIX_ROWS); +    set_time(time_offset_); +    std::fill(std::begin(input_matrix_), std::end(input_matrix_), 0); +    std::fill(std::begin(output_matrix_), std::end(output_matrix_), 0); + +    for (auto &event : events_) { +        if (!auto_advance_time_) { +            /* Jump to the next event */ +            set_time(time_offset_ + event.time_); +        } else if (!first && event.time_ == previous + 1) { +            /* This event immediately follows the previous one, don't make extra debounce() calls */ +            advance_time(1); +        } else { +            /* Fast forward to the time for this event, calling debounce() with no changes */ +            ASSERT_LT((time_offset_ + event.time_) - timer_read_fast(), 60000) << "Test tries to advance more than 1 minute of time"; + +            while (timer_read_fast() != time_offset_ + event.time_) { +                runDebounce(false); +                checkCookedMatrix(false, "debounce() modified cooked matrix"); +                advance_time(1); +            } +        } + +        first = false; +        previous = event.time_; + +        /* Prepare input matrix */ +        for (auto &input : event.inputs_) { +            matrixUpdate(input_matrix_, "input", input); +        } + +        /* Call debounce */ +        runDebounce(!event.inputs_.empty()); + +        /* Prepare output matrix */ +        for (auto &output : event.outputs_) { +            matrixUpdate(output_matrix_, "output", output); +        } + +        /* Check output matrix has expected change events */ +        for (auto &output : event.outputs_) { +            EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_)) +                    << "Missing event at " << strTime() +                    << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_) +                    << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_) +                    << "\nexpected_matrix:\n" << strMatrix(output_matrix_) +                    << "\nactual_matrix:\n" << strMatrix(cooked_matrix_); +        } + +        /* Check output matrix has no other changes */ +        checkCookedMatrix(!event.inputs_.empty(), "debounce() cooked matrix does not match expected output matrix"); + +        /* Perform some extra iterations of the matrix scan with no changes */ +        for (int i = 0; i < extra_iterations_; i++) { +            runDebounce(false); +            checkCookedMatrix(false, "debounce() modified cooked matrix"); +        } +    } + +    /* Check that no further changes happen for 1 minute */ +    for (int i = 0; i < 60000; i++) { +        runDebounce(false); +        checkCookedMatrix(false, "debounce() modified cooked matrix"); +        advance_time(1); +    } + +    debounce_free(); +} + +void DebounceTest::runDebounce(bool changed) { +    std::copy(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_)); +    std::copy(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_)); + +    debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed); + +    if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) { +        FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime() +            << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) +            << "\nraw_matrix:\n" << strMatrix(raw_matrix_); +    } +} + +void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) { +    if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) { +        FAIL() << "Unexpected event: " << error_message << " at " << strTime() +            << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) +            << "\nexpected_matrix:\n" << strMatrix(output_matrix_) +            << "\nactual_matrix:\n" << strMatrix(cooked_matrix_); +    } +} + +std::string DebounceTest::strTime() { +    std::stringstream text; + +    text << "time " << (timer_read_fast() - time_offset_) +        << " (extra_iterations=" << extra_iterations_ +        << ", auto_advance_time=" << auto_advance_time_ << ")"; + +    return text.str(); +} + +std::string DebounceTest::strMatrix(matrix_row_t matrix[]) { +    std::stringstream text; + +    text << "\t" << std::setw(3) << ""; +    for (int col = 0; col < MATRIX_COLS; col++) { +        text << " " << std::setw(2) << col; +    } +    text << "\n"; + +    for (int row = 0; row < MATRIX_ROWS; row++) { +        text << "\t" << std::setw(2) << row << ":"; +        for (int col = 0; col < MATRIX_COLS; col++) { +            text << ((matrix[row] & (1U << col)) ? " XX" : " __"); +        } + +        text << "\n"; +    } + +    return text.str(); +} + +bool DebounceTest::directionValue(Direction direction) { +    switch (direction) { +    case DOWN: +        return true; + +    case UP: +        return false; +    } +} + +std::string DebounceTest::directionLabel(Direction direction) { +    switch (direction) { +    case DOWN: +        return "DOWN"; + +    case UP: +        return "UP"; +    } +} + +/* Modify a matrix and verify that events always specify a change */ +void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) { +    ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_)) +        << "Test " << name << " at " << strTime() +        << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_) +        << " but it is already " << directionLabel(event.direction_) +        << "\n" << name << "_matrix:\n" << strMatrix(matrix); + +    switch (event.direction_) { +    case DOWN: +        matrix[event.row_] |= (1U << event.col_); +        break; + +    case UP: +        matrix[event.row_] &= ~(1U << event.col_); +        break; +    } +} + +DebounceTestEvent::DebounceTestEvent(fast_timer_t time, +        std::initializer_list<MatrixTestEvent> inputs, +        std::initializer_list<MatrixTestEvent> outputs) +        : time_(time), inputs_(inputs), outputs_(outputs) { +} + +MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction) +        : row_(row), col_(col), direction_(direction) { +} diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h new file mode 100644 index 0000000000..d87e310594 --- /dev/null +++ b/quantum/debounce/tests/debounce_test_common.h @@ -0,0 +1,83 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gtest/gtest.h" + +#include <initializer_list> +#include <list> +#include <string> + +extern "C" { +#include "quantum.h" +#include "timer.h" +} + +enum Direction { +    DOWN, +    UP, +}; + +class MatrixTestEvent { +public: +    MatrixTestEvent(int row, int col, Direction direction); + +    const int row_; +    const int col_; +    const Direction direction_; +}; + +class DebounceTestEvent { +public: +    // 0, {{0, 1, DOWN}}, {{0, 1, DOWN}}) +    DebounceTestEvent(fast_timer_t time, +        std::initializer_list<MatrixTestEvent> inputs, +        std::initializer_list<MatrixTestEvent> outputs); + +    const fast_timer_t time_; +    const std::list<MatrixTestEvent> inputs_; +    const std::list<MatrixTestEvent> outputs_; +}; + +class DebounceTest : public ::testing::Test { +protected: +    void addEvents(std::initializer_list<DebounceTestEvent> events); +    void runEvents(); + +    fast_timer_t time_offset_ = 7777; +    bool time_jumps_ = false; + +private: +    static bool directionValue(Direction direction); +    static std::string directionLabel(Direction direction); + +    void runEventsInternal(); +    void runDebounce(bool changed); +    void checkCookedMatrix(bool changed, const std::string &error_message); +    void matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event); + +    std::string strTime(); +    std::string strMatrix(matrix_row_t matrix[]); + +    std::list<DebounceTestEvent> events_; + +    matrix_row_t input_matrix_[MATRIX_ROWS]; +    matrix_row_t raw_matrix_[MATRIX_ROWS]; +    matrix_row_t cooked_matrix_[MATRIX_ROWS]; +    matrix_row_t output_matrix_[MATRIX_ROWS]; + +    int extra_iterations_; +    bool auto_advance_time_; +}; diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk new file mode 100644 index 0000000000..66928d7eb6 --- /dev/null +++ b/quantum/debounce/tests/rules.mk @@ -0,0 +1,44 @@ +# Copyright 2021 Simon Arlott +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + +DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5 + +DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \ +	$(TMK_PATH)/common/test/timer.c + +debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \ +	$(QUANTUM_PATH)/debounce/sym_defer_g.c \ +	$(QUANTUM_PATH)/debounce/tests/sym_defer_g_tests.cpp + +debounce_sym_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_sym_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \ +	$(QUANTUM_PATH)/debounce/sym_defer_pk.c \ +	$(QUANTUM_PATH)/debounce/tests/sym_defer_pk_tests.cpp + +debounce_sym_eager_pk_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_sym_eager_pk_SRC := $(DEBOUNCE_COMMON_SRC) \ +	$(QUANTUM_PATH)/debounce/sym_eager_pk.c \ +	$(QUANTUM_PATH)/debounce/tests/sym_eager_pk_tests.cpp + +debounce_sym_eager_pr_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_sym_eager_pr_SRC := $(DEBOUNCE_COMMON_SRC) \ +	$(QUANTUM_PATH)/debounce/sym_eager_pr.c \ +	$(QUANTUM_PATH)/debounce/tests/sym_eager_pr_tests.cpp + +debounce_asym_eager_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS) +debounce_asym_eager_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \ +	$(QUANTUM_PATH)/debounce/asym_eager_defer_pk.c \ +	$(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 0000000000..a56aecd8f3 --- /dev/null +++ b/quantum/debounce/tests/sym_defer_g_tests.cpp @@ -0,0 +1,223 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        /* 0ms delay (fast scan rate) */ +        {5, {{0, 1, UP}}, {}}, + +        {10, {}, {{0, 1, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        /* 1ms delay */ +        {6, {{0, 1, UP}}, {}}, + +        {11, {}, {{0, 1, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        /* 2ms delay */ +        {7, {{0, 1, UP}}, {}}, + +        {12, {}, {{0, 1, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyTooQuick1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        /* Release key exactly on the debounce time */ +        {5, {{0, 1, UP}}, {}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyTooQuick2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        {6, {{0, 1, UP}}, {}}, + +        /* Press key exactly on the debounce time */ +        {11, {{0, 1, DOWN}}, {}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        {1, {{0, 1, UP}}, {}}, +        {2, {{0, 1, DOWN}}, {}}, +        {3, {{0, 1, UP}}, {}}, +        {4, {{0, 1, DOWN}}, {}}, +        {5, {{0, 1, UP}}, {}}, +        {6, {{0, 1, DOWN}}, {}}, +        {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        {5, {}, {{0, 1, DOWN}}}, +        {6, {{0, 1, UP}}, {}}, +        {7, {{0, 1, DOWN}}, {}}, +        {8, {{0, 1, UP}}, {}}, +        {9, {{0, 1, DOWN}}, {}}, +        {10, {{0, 1, UP}}, {}}, +        {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, + +        {25, {{0, 1, UP}}, {}}, + +        {30, {}, {{0, 1, UP}}}, + +        {50, {{0, 1, DOWN}}, {}}, + +        {55, {}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysShort) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        {1, {{0, 2, DOWN}}, {}}, + +        {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, + +        {7, {{0, 1, UP}}, {}}, +        {8, {{0, 2, UP}}, {}}, + +        {13, {}, {{0, 1, UP}, {0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, +        {6, {{0, 1, UP}, {0, 2, UP}}, {}}, + +        {11, {}, {{0, 1, UP}, {0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        {1, {{0, 2, DOWN}}, {}}, + +        {5, {}, {}}, +        {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, +        {7, {{0, 1, UP}}, {}}, +        {8, {{0, 2, UP}}, {}}, + +        {13, {}, {{0, 1, UP}, {0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        /* Processing is very late */ +        {300, {}, {{0, 1, DOWN}}}, +        /* Immediately release key */ +        {300, {{0, 1, UP}}, {}}, + +        {305, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        /* Processing is very late */ +        {300, {}, {{0, 1, DOWN}}}, +        /* Release key after 1ms */ +        {301, {{0, 1, UP}}, {}}, + +        {306, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        /* Release key before debounce expires */ +        {300, {{0, 1, UP}}, {}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        /* Processing is a bit late */ +        {50, {}, {{0, 1, DOWN}}}, +        /* Release key after 1ms */ +        {51, {{0, 1, UP}}, {}}, + +        {56, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} 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 0000000000..1f3061e59c --- /dev/null +++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp @@ -0,0 +1,225 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        /* 0ms delay (fast scan rate) */ +        {5, {{0, 1, UP}}, {}}, + +        {10, {}, {{0, 1, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        /* 1ms delay */ +        {6, {{0, 1, UP}}, {}}, + +        {11, {}, {{0, 1, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        /* 2ms delay */ +        {7, {{0, 1, UP}}, {}}, + +        {12, {}, {{0, 1, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyTooQuick1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        /* Release key exactly on the debounce time */ +        {5, {{0, 1, UP}}, {}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyTooQuick2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        {6, {{0, 1, UP}}, {}}, + +        /* Press key exactly on the debounce time */ +        {11, {{0, 1, DOWN}}, {}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        {1, {{0, 1, UP}}, {}}, +        {2, {{0, 1, DOWN}}, {}}, +        {3, {{0, 1, UP}}, {}}, +        {4, {{0, 1, DOWN}}, {}}, +        {5, {{0, 1, UP}}, {}}, +        {6, {{0, 1, DOWN}}, {}}, +        {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        {5, {}, {{0, 1, DOWN}}}, +        {6, {{0, 1, UP}}, {}}, +        {7, {{0, 1, DOWN}}, {}}, +        {8, {{0, 1, UP}}, {}}, +        {9, {{0, 1, DOWN}}, {}}, +        {10, {{0, 1, UP}}, {}}, +        {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, + +        {25, {{0, 1, UP}}, {}}, + +        {30, {}, {{0, 1, UP}}}, + +        {50, {{0, 1, DOWN}}, {}}, + +        {55, {}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysShort) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        {1, {{0, 2, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        {6, {}, {{0, 2, DOWN}}}, + +        {7, {{0, 1, UP}}, {}}, +        {8, {{0, 2, UP}}, {}}, + +        {12, {}, {{0, 1, UP}}}, +        {13, {}, {{0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, +        {6, {{0, 1, UP}, {0, 2, UP}}, {}}, + +        {11, {}, {{0, 1, UP}, {0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, +        {1, {{0, 2, DOWN}}, {}}, + +        {5, {}, {{0, 1, DOWN}}}, +        {6, {{0, 1, UP}}, {{0, 2, DOWN}}}, +        {7, {{0, 2, UP}}, {}}, + +        {11, {}, {{0, 1, UP}}}, +        {12, {}, {{0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        /* Processing is very late */ +        {300, {}, {{0, 1, DOWN}}}, +        /* Immediately release key */ +        {300, {{0, 1, UP}}, {}}, + +        {305, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        /* Processing is very late */ +        {300, {}, {{0, 1, DOWN}}}, +        /* Release key after 1ms */ +        {301, {{0, 1, UP}}, {}}, + +        {306, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        /* Release key before debounce expires */ +        {300, {{0, 1, UP}}, {}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {}}, + +        /* Processing is a bit late */ +        {50, {}, {{0, 1, DOWN}}}, +        /* Release key after 1ms */ +        {51, {{0, 1, UP}}, {}}, + +        {56, {}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} 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 0000000000..e0fc205e33 --- /dev/null +++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp @@ -0,0 +1,237 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {6, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 2ms delay (debounce has not yet finished) */ +        {7, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 3ms delay (debounce has not yet finished) */ +        {8, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort4) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 4ms delay (debounce has not yet finished) */ +        {9, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort5) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 5ms delay (debounce has finished) */ +        {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort6) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key after after 6ms delay (debounce has finished) */ +        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, +        {2, {{0, 1, DOWN}}, {}}, +        {3, {{0, 1, UP}}, {}}, +        {4, {{0, 1, DOWN}}, {}}, +        {5, {{0, 1, UP}}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {6, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Change twice in the same time period */ +        {1, {{0, 1, UP}}, {}}, +        {1, {{0, 1, DOWN}}, {}}, +        /* Change three times in the same time period */ +        {2, {{0, 1, UP}}, {}}, +        {2, {{0, 1, DOWN}}, {}}, +        {2, {{0, 1, UP}}, {}}, +        /* Change three times in the same time period */ +        {3, {{0, 1, DOWN}}, {}}, +        {3, {{0, 1, UP}}, {}}, +        {3, {{0, 1, DOWN}}, {}}, +        /* Change twice in the same time period */ +        {4, {{0, 1, UP}}, {}}, +        {4, {{0, 1, DOWN}}, {}}, +        {5, {{0, 1, UP}}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {6, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        {25, {{0, 1, UP}}, {{0, 1, UP}}}, + +        {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysShort) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, +        {2, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, +        {3, {{0, 2, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {6, {{0, 1, DOWN}}, {}}, +        {7, {}, {{0, 2, UP}}}, + +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {9, {{0, 2, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + +        {12, {}, {{0, 2, DOWN}}}, /* 5ms after UP at time 7 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted */ +        {300, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted even with a 1 scan delay */ +        {300, {}, {}}, +        {300, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted even with a 1ms delay */ +        {300, {}, {}}, +        {301, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is a bit late but the change will now be accepted */ +        {50, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan5) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted even with a 1 scan delay */ +        {50, {}, {}}, +        {50, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan6) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted even with a 1ms delay */ +        {50, {}, {}}, +        {51, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} 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 0000000000..2c4bca127e --- /dev/null +++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp @@ -0,0 +1,280 @@ +/* Copyright 2021 Simon Arlott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gtest/gtest.h" + +#include "debounce_test_common.h" + +TEST_F(DebounceTest, OneKeyShort1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {6, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 2ms delay (debounce has not yet finished) */ +        {7, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 3ms delay (debounce has not yet finished) */ +        {8, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort4) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 4ms delay (debounce has not yet finished) */ +        {9, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort5) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 5ms delay (debounce has finished) */ +        {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyShort6) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key after after 6ms delay (debounce has finished) */ +        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, +        {2, {{0, 1, DOWN}}, {}}, +        {3, {{0, 1, UP}}, {}}, +        {4, {{0, 1, DOWN}}, {}}, +        {5, {{0, 1, UP}}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {6, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyBouncing2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        /* Change twice in the same time period */ +        {1, {{0, 1, UP}}, {}}, +        {1, {{0, 1, DOWN}}, {}}, +        /* Change three times in the same time period */ +        {2, {{0, 1, UP}}, {}}, +        {2, {{0, 1, DOWN}}, {}}, +        {2, {{0, 1, UP}}, {}}, +        /* Change three times in the same time period */ +        {3, {{0, 1, DOWN}}, {}}, +        {3, {{0, 1, UP}}, {}}, +        {3, {{0, 1, DOWN}}, {}}, +        /* Change twice in the same time period */ +        {4, {{0, 1, UP}}, {}}, +        {4, {{0, 1, DOWN}}, {}}, +        {5, {{0, 1, UP}}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {6, {{0, 1, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyLong) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        {25, {{0, 1, UP}}, {{0, 1, UP}}}, + +        {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoRowsShort) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, +        {2, {{2, 0, DOWN}}, {{2, 0, DOWN}}}, +        {3, {{2, 0, UP}}, {}}, + +        {5, {}, {{0, 1, UP}}}, +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {6, {{0, 1, DOWN}}, {}}, +        {7, {}, {{2, 0, UP}}}, + +        /* Press key again after 1ms delay (debounce has not yet finished) */ +        {9, {{2, 0, DOWN}}, {}}, +        {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ + +        {12, {}, {{2, 0, DOWN}}}, /* 5ms after UP at time 7 */ +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysOverlap) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, +        {1, {{0, 1, UP}}, {}}, +        /* Press a second key during the first debounce */ +        {2, {{0, 2, DOWN}}, {}}, + +        /* Key registers as soon as debounce finishes, 5ms after time 0 */ +        {5, {}, {{0, 1, UP}, {0, 2, DOWN}}}, +        {6, {{0, 1, DOWN}}, {}}, + +        /* Key registers as soon as debounce finishes, 5ms after time 5 */ +        {10, {}, {{0, 1, DOWN}}}, +        /* Release both keys */ +        {11, {{0, 1, UP}}, {}}, +        {12, {{0, 2, UP}}, {}}, + +        /* Keys register as soon as debounce finishes, 5ms after time 10 */ +        {15, {}, {{0, 1, UP}, {0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}}, +        {20, {{0, 1, UP}}, {{0, 1, UP}}}, +        {21, {{0, 2, UP}}, {}}, + +        /* Key registers as soon as debounce finishes, 5ms after time 20 */ +        {25, {}, {{0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, TwoKeysSimultaneous2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}}, +        {20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}}, +    }); +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan1) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted */ +        {300, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan2) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted even with a 1 scan delay */ +        {300, {}, {}}, +        {300, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan3) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted even with a 1ms delay */ +        {300, {}, {}}, +        {301, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan4) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is a bit late but the change will now be accepted */ +        {50, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan5) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted even with a 1 scan delay */ +        {50, {}, {}}, +        {50, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} + +TEST_F(DebounceTest, OneKeyDelayedScan6) { +    addEvents({ /* Time, Inputs, Outputs */ +        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, + +        /* Processing is very late but the change will now be accepted even with a 1ms delay */ +        {50, {}, {}}, +        {51, {{0, 1, UP}}, {{0, 1, UP}}}, +    }); +    time_jumps_ = true; +    runEvents(); +} diff --git a/quantum/debounce/tests/testlist.mk b/quantum/debounce/tests/testlist.mk new file mode 100644 index 0000000000..c54c45aa63 --- /dev/null +++ b/quantum/debounce/tests/testlist.mk @@ -0,0 +1,6 @@ +TEST_LIST += \ +	debounce_sym_defer_g \ +	debounce_sym_defer_pk \ +	debounce_sym_eager_pk \ +	debounce_sym_eager_pr \ +	debounce_asym_eager_defer_pk diff --git a/quantum/dip_switch.c b/quantum/dip_switch.c index cda69bd0ef..72789ca8e8 100644 --- a/quantum/dip_switch.c +++ b/quantum/dip_switch.c @@ -49,13 +49,13 @@ static uint16_t       scan_count;  static bool dip_switch_state[NUMBER_OF_DIP_SWITCHES]      = {0};  static bool last_dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0}; -__attribute__((weak)) void dip_switch_update_user(uint8_t index, bool active) {} +__attribute__((weak)) bool dip_switch_update_user(uint8_t index, bool active) { return true; } -__attribute__((weak)) void dip_switch_update_kb(uint8_t index, bool active) { dip_switch_update_user(index, active); } +__attribute__((weak)) bool dip_switch_update_kb(uint8_t index, bool active) { return dip_switch_update_user(index, active); } -__attribute__((weak)) void dip_switch_update_mask_user(uint32_t state) {} +__attribute__((weak)) bool dip_switch_update_mask_user(uint32_t state) { return true; } -__attribute__((weak)) void dip_switch_update_mask_kb(uint32_t state) { dip_switch_update_mask_user(state); } +__attribute__((weak)) bool dip_switch_update_mask_kb(uint32_t state) { return dip_switch_update_mask_user(state); }  void dip_switch_init(void) {  #ifdef DIP_SWITCH_PINS diff --git a/quantum/dip_switch.h b/quantum/dip_switch.h index 61ef1cc19d..058a10f41f 100644 --- a/quantum/dip_switch.h +++ b/quantum/dip_switch.h @@ -20,10 +20,10 @@  #include "quantum.h" -void dip_switch_update_kb(uint8_t index, bool active); -void dip_switch_update_user(uint8_t index, bool active); -void dip_switch_update_mask_user(uint32_t state); -void dip_switch_update_mask_kb(uint32_t state); +bool dip_switch_update_kb(uint8_t index, bool active); +bool dip_switch_update_user(uint8_t index, bool active); +bool dip_switch_update_mask_user(uint32_t state); +bool dip_switch_update_mask_kb(uint32_t state);  void dip_switch_init(void);  void dip_switch_read(bool forced); diff --git a/quantum/keymap_extras/keymap_belgian.h b/quantum/keymap_extras/keymap_belgian.h index 6aaadf9787..207905b291 100644 --- a/quantum/keymap_extras/keymap_belgian.h +++ b/quantum/keymap_extras/keymap_belgian.h @@ -156,16 +156,3 @@  // Row 4  #define BE_BSLS ALGR(BE_LABK) // (backslash)  #define BE_TILD ALGR(BE_EQL)  // ~ - -// DEPRECATED -#define BE_AMP  BE_AMPR -#define BE_APOS BE_QUOT -#define BE_PARA BE_SECT -#define BE_MU   BE_MICR -#define BE_LESS BE_LABK -#define BE_OVRR BE_DEG -#define BE_UMLT BE_DIAE -#define BE_GRTR BE_RABK -#define BE_LSBR BE_LBRC -#define BE_RSBR BE_RBRC -#define BE_TILT BE_TILD diff --git a/quantum/keymap_extras/keymap_bepo.h b/quantum/keymap_extras/keymap_bepo.h index b6244898aa..72d5b81f32 100644 --- a/quantum/keymap_extras/keymap_bepo.h +++ b/quantum/keymap_extras/keymap_bepo.h @@ -181,7 +181,7 @@  #define BP_RCBR ALGR(BP_X)    // }  #define BP_ELLP ALGR(BP_DOT)  // …  #define BP_TILD ALGR(BP_K)    // ~ -#define BP_IQUE ALGR(BP_QEST) // ¿ +#define BP_IQUE ALGR(BP_QUES) // ¿  #define BP_RNGA ALGR(BP_Q)    // ° (dead)  #define BP_DGRK ALGR(BP_G)    // µ (dead Greek key)  #define BP_DAGG ALGR(BP_H)    // † @@ -238,168 +238,3 @@  #define BP_FORD S(ALGR(BP_F))    // ª  // Row 5  #define BP_NNBS S(ALGR(BP_))     //   (narrow non-breaking space) - -// DEPRECATED -#define BP_DOLLAR BP_DLR -#define BP_DOUBLE_QUOTE BP_DQUO -#define BP_DQOT BP_DQUO -#define BP_LEFT_GUILLEMET BP_LDAQ -#define BP_LGIL BP_LDAQ -#define BP_RIGHT_GUILLEMET BP_RDAQ -#define BP_RGIL BP_RDAQ -#define BP_LEFT_PAREN BP_LPRN -#define BP_RIGHT_PAREN BP_RPRN -#define BP_MINUS BP_MINS -#define BP_SLASH BP_SLSH -#define BP_ASTERISK BP_ASTR -#define BP_EQUAL BP_EQL -#define BP_PERCENT BP_PERC -#define BP_E_ACUTE BP_EACU -#define BP_ECUT BP_EACU -#define BP_E_GRAVE BP_EGRV -#define BP_DEAD_CIRCUMFLEX BP_DCIR -#define BP_DCRC BP_DCIR -#define BP_COMMA BP_COMM -#define BP_C_CEDILLA BP_CCED -#define BP_E_CIRCUMFLEX BP_ECIR -#define BP_ECRC BP_ECIR -#define BP_A_GRAVE BP_AGRV -#define BP_APOSTROPHE BP_QUOT -#define BP_APOS BP_QUOT -#define BP_DEGREE BP_DEG -#define BP_DEGR BP_DEG -#define BP_GRAVE BP_GRV -#define BP_EXCLAIM BP_EXLM -#define BP_SCOLON BP_SCLN -#define BP_COLON BP_COLN -#define BP_QUESTION BP_QUES -#define BP_QEST BP_QUES -#define BP_NON_BREAKING_SPACE BP_NBSP -#define BP_EN_DASH BP_NDSH -#define BP_EM_DASH BP_MDSH -#define BP_LESS BP_LABK -#define BP_GREATER BP_RABK -#define BP_GRTR BP_RABK -#define BP_LBRACKET BP_LBRC -#define BP_RBRACKET BP_RBRC -#define BP_CIRCUMFLEX CIRC -#define BP_PLUS_MINUS BP_PLMN -#define BP_PSMS BP_PLMN -#define BP_MATH_MINUS BP_MMNS -#define BP_OBELUS BP_DIV -#define BP_OBEL BP_DIV -#define BP_DIVISION_SIGN BP_DIV -#define BP_DVSN BP_DIV -#define BP_TIMES BP_MUL -#define BP_TIMS BP_MUL -#define BP_DIFFERENT BP_NEQL -#define BP_DIFF BP_NEQL -#define BP_PERMILLE BP_PERM -#define BP_PMIL BP_PERM -#define BP_DEAD_ACUTE BP_ACUT -#define BP_DACT BP_ACUT -#define BP_AMPERSAND BP_AMPR -#define BP_OE_LIGATURE BP_OE -#define BP_DEAD_GRAVE BP_DGRV -#define BP_INVERTED_EXCLAIM BP_IEXL -#define BP_IXLM BP_IEXL -#define BP_DEAD_CARON BP_CARN -#define BP_DCAR BP_CARN -#define BP_DEAD_SLASH BP_DSLS -#define BP_DSLH BP_DSLS -#define BP_IJ_LIGATURE BP_IJ -#define BP_SCHWA BP_SCHW -#define BP_SCWA BP_SCHW -#define BP_DEAD_BREVE BP_BREV -#define BP_DBRV BP_BREV -#define BP_AE_LIGATURE BP_AE -#define BP_U_GRAVE BP_UGRV -#define BP_DEAD_TREMA BP_DIAE -#define BP_DTRM BP_DIAE -#define BP_TYPOGRAPHICAL_APOSTROPHE BP_COMM -#define BP_TAPO BP_COMM -#define BP_COPYRIGHT BP_COPY -#define BP_CPRT BP_COPY -#define BP_THORN BP_THRN -#define BP_SHARP_S BP_SS -#define BP_SRPS BP_SS -#define BP_REGISTERED_TRADEMARK BP_REGD -#define BP_RTM BP_REGD -#define BP_DEAD_TILDE BP_DTIL -#define BP_DTLD BP_DTIL -#define BP_DEAD_MACRON BP_MACR -#define BP_DMCR BP_MACR -#define BP_DEAD_CEDILLA BP_CEDL -#define BP_DCED BP_CEDL -#define BP_NONUS_SLASH BP_SLSH -#define BP_NUSL BP_SLSH -#define BP_BACKSLASH BP_BSLS -#define BP_LEFT_CURLY_BRACE BP_LCBR -#define BP_RIGHT_CURLY_BRACE BP_RCBR -#define BP_ELLIPSIS BP_ELLP -#define BP_ELPS BP_ELLP -#define BP_TILDE BP_TILD -#define BP_INVERTED_QUESTION BP_IQUE -#define BP_IQST BP_IQUE -#define BP_DEAD_RING BP_RNGA -#define BP_DRNG BP_RNGA -#define BP_DEAD_GREEK BP_DGRK -#define BP_DAGGER BP_DAGG -#define BP_DAGR BP_DAGG -#define BP_DEAD_OGONEK BP_OGON -#define BP_DOGO BP_OGON -#define BP_UNDERSCORE BP_UNDS -#define BP_PARAGRAPH BP_PARA -#define BP_PARG BP_PARA -#define BP_LOW_DOUBLE_QUOTE BP_DLQU -#define BP_LWQT BP_DLQU -#define BP_LEFT_DOUBLE_QUOTE BP_RDQU -#define BP_RIGHT_DOUBLE_QUOTE BP_RDQU -#define BP_LESS_OR_EQUAL BP_LEQL -#define BP_GREATER_OR_EQUAL BP_GEQL -#define BP_NEGATION BP_NOT -#define BP_NEGT BP_NOT -#define BP_ONE_QUARTER BP_QRTR -#define BP_1QRT BP_QRTR -#define BP_ONE_HALF BP_HALF -#define BP_1HLF BP_HALF -#define BP_THREE_QUARTERS TQTR -#define BP_3QRT BP_TQTR -#define BP_MINUTES BP_PRIM -#define BP_MNUT BP_PRIM -#define BP_SECONDS BP_DPRM -#define BP_SCND BP_DPRM -#define BP_BROKEN_PIPE BP_BRKP -#define BP_BPIP BP_BRKP -#define BP_DEAD_DOUBLE_ACUTE BP_DACU -#define BP_DDCT BP_DACU -#define BP_SECTION BP_SECT -#define BP_GRAVE_BIS BP_GRV -#define BP_GRVB BP_GRV -#define BP_DEAD_DOT_ABOVE BP_DOTA -#define BP_DDTA BP_DOTA -#define BP_DEAD_CURRENCY BP_CURR -#define BP_DCUR BP_CURR -#define BP_DEAD_HORN BP_HORN -#define BP_DHRN BP_HORN -#define BP_LONG_S BP_LNGS -#define BP_TRADEMARK BP_TM -#define BP_ORDINAL_INDICATOR_O MORD -#define BP_ORDO BP_MORD -#define BP_DEAD_COMMA BP_DCMM -#define BP_DCOM BP_DCMM -#define BP_LEFT_QUOTE BP_LSQU -#define BP_LQOT BP_LSQU -#define BP_RIGHT_QUOTE BP_RSQU -#define BP_RQOT BP_RSQU -#define BP_INTERPUNCT BP_MDDT -#define BP_IPCT BP_MDDT -#define BP_DEAD_HOOK_ABOVE BP_HOKA -#define BP_DHKA BP_HOKA -#define BP_DEAD_UNDERDOT BP_DOTB -#define BP_DUDT BP_DOTB -#define BP_DOUBLE_DAGGER BP_DDAG -#define BP_DDGR BP_DDAG -#define BP_ORDINAL_INDICATOR_A BP_FORD -#define BP_ORDA BP_FORD -#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 310950d49d..e91718013a 100644 --- a/quantum/keymap_extras/keymap_br_abnt2.h +++ b/quantum/keymap_extras/keymap_br_abnt2.h @@ -158,23 +158,3 @@  #define BR_MORD ALGR(BR_RBRC) // º  // Row 4  #define BR_CRUZ ALGR(BR_C)    // ₢ - -// DEPRECATED -#define BR_CCDL BR_CCED -#define BR_DQT  BR_DQUO -#define BR_TRMA BR_DIAE -#define BR_GRAV BR_GRV -#define BR_KPDT BR_PDOT -#define BR_KPCM BR_PCMM -#define BR_1UP  BR_SUP1 -#define BR_2UP  BR_SUP2 -#define BR_3UP  BR_SUP3 -#define BR_ASLS BR_SLSH -#define BR_AQST BR_QUES - -// Not present on Windows 10? -#define BR_NDTD ALGR(BR_TILD)   // ~ -#define BR_NDAC ALGR(BR_ACUT)   // ´ -#define BR_NDGV ALGR(BR_QUOT)   // ` -#define BR_NDCR ALGR(BR_CIRC)   // ^ -#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 d72ea3979f..e328cf65e6 100644 --- a/quantum/keymap_extras/keymap_canadian_multilingual.h +++ b/quantum/keymap_extras/keymap_canadian_multilingual.h @@ -252,182 +252,3 @@  #define CA_MORD RCTL(S(CA_M))    // º  #define CA_MUL  RCTL(S(CA_COMM)) // ×  #define CA_DIV  RCTL(S(CA_DOT))  // ÷ - -// DEPRECATED -#define GR2A(kc) RCTL(kc) -#define CSA_SLASH CA_SLSH -#define CSA_SLSH CA_SLSH -#define CSA_DEAD_CIRCUMFLEX CA_CIRC -#define CSA_DCRC CA_CIRC -#define CSA_C_CEDILLA CA_CCED -#define CSA_CCED CA_CCED -#define CSA_E_GRAVE CA_EGRV -#define CSA_EGRV CA_EGRV -#define CSA_A_GRAVE CA_AGRV -#define CSA_AGRV CA_AGRV -#define CSA_U_GRAVE CA_UGRV -#define CSA_UGRV CA_UGRV -#define CSA_E_ACUTE CA_EACU -#define CSA_ECUT CA_EACU -#define CSA_BACKSLASH CA_BSLS -#define CSA_BSLS CA_BSLS -#define CSA_QUESTION CA_QUES -#define CSA_QEST CA_QUES -#define CSA_DEAD_TREMA CA_DIAE -#define CSA_DTRM CA_DIAE -#define CSA_APOSTROPHE CA_QUOT -#define CSA_APOS CA_QUOT -#define CSA_DOUBLE_QUOTE CA_DQUO -#define CSA_DQOT CA_DQUO -#define CSA_PIPE CA_PIPE -#define CSA_CURRENCY CA_CURR -#define CSA_CURR CA_CURR -#define CSA_LEFT_CURLY_BRACE CA_LCBR -#define CSA_LCBR CA_LCBR -#define CSA_RIGHT_CURLY_BRACE CA_RCBR -#define CSA_RCBR CA_RCBR -#define CSA_LBRACKET CA_LBRC -#define CSA_LBRC CA_LBRC -#define CSA_RBRACKET CA_RBRC -#define CSA_RBRC CA_RBRC -#define CSA_NEGATION CA_NOT -#define CSA_NEGT CA_NOT -#define CSA_EURO CA_EURO -#define CSA_DEAD_GRAVE CA_GRV -#define CSA_DGRV CA_GRV -#define CSA_DEAD_TILDE CA_DTIL -#define CSA_DTLD CA_DTIL -#define CSA_DEGREE CA_DEG -#define CSA_DEGR CA_DEG -#define CSA_LEFT_GUILLEMET CA_LDAQ -#define CSA_LGIL CA_LDAQ -#define CSA_RIGHT_GUILLEMET CA_RDAQ -#define CSA_RGIL CA_RDAQ -#define CSA_LESS CA_LABK -#define CSA_GREATER CA_RABK -#define CSA_GRTR CA_RABK -#define CSA_NON_BREAKING_SPACE ALGR(KC_SPC) -#define CSA_NBSP ALGR(KC_SPC) -#define CSA_SUPERSCRIPT_ONE CA_SUP1 -#define CSA_SUP1 CA_SUP1 -#define CSA_SUPERSCRIPT_TWO CA_SUP2 -#define CSA_SUP2 CA_SUP2 -#define CSA_SUPERSCRIPT_THREE CA_SUP3 -#define CSA_SUP3 CA_SUP3 -#define CSA_ONE_QUARTER CA_QRTR -#define CSA_1QRT CA_QRTR -#define CSA_ONE_HALF CA_HALF -#define CSA_1HLF CA_HALF -#define CSA_THREE_QUARTERS CA_TQTR -#define CSA_3QRT CA_TQTR -#define CSA_DEAD_CEDILLA CA_CEDL -#define CSA_DCED CA_CEDL -#define CSA_OMEGA CA_OMEG -#define CSA_OMEG CA_OMEG -#define CSA_L_STROKE CA_LSTR -#define CSA_LSTK CA_LSTR -#define CSA_OE_LIGATURE CA_OE -#define CSA_OE CA_OE -#define CSA_PARAGRAPH CA_PARA -#define CSA_PARG CA_PARA -#define CSA_T_STROKE CA_TSTR -#define CSA_LEFT_ARROW CA_LARR -#define CSA_LARW CA_LARR -#define CSA_DOWN_ARROW CA_DARR -#define CSA_DARW CA_DARR -#define CSA_RIGHT_ARROW CA_RARR -#define CSA_RARW CA_RARR -#define CSA_O_STROKE CA_OSTR -#define CSA_OSTK CA_OSTR -#define CSA_THORN CA_THRN -#define CSA_THRN CA_THRN -#define CSA_TILDE CA_TILD -#define CSA_TILD CA_TILD -#define CSA_AE_LIGATURE CA_AE -#define CSA_AE CA_AE -#define CSA_SHARP_S CA_SS -#define CSA_SRPS CA_SS -#define CSA_ETH CA_ETH -#define CSA_ENG CA_ENG -#define CSA_H_SRTOKE CA_HSTR -#define CSA_HSTK CA_HSTR -#define CSA_IJ_LIGATURE CA_IJ -#define CSA_IJ CA_IJ -#define CSA_KRA CA_KRA -#define CSA_L_FLOWN_DOT CA_LMDT -#define CSA_LFLD CA_LMDT -#define CSA_DEAD_ACUTE CA_ACUT -#define CSA_DACT CA_ACUT -#define CSA_CENT CA_CENT -#define CSA_LEFT_DOUBLE_QUOTE CA_LDQU -#define CSA_LDQT CA_LDQU -#define CSA_RIGHT_DOUBLE_QUOTE CA_RDQU -#define CSA_RDQT CA_RDQU -#define CSA_N_APOSTROPHE CA_APSN -#define CSA_NAPO CA_APSN -#define CSA_MU CA_MICR -#define CSA_HORIZONTAL_BAR CA_HRZB -#define CSA_HZBR CA_HRZB -#define CSA_DEAD_DOT_ABOVE CA_DOTA -#define CSA_DDTA CA_DOTA -#define CSA_SOFT_HYPHEN CA_SHYP -#define CSA_SHYP CA_SHYP -#define CSA_INVERTED_EXCLAIM CA_IEXL -#define CSA_IXLM CA_IEXL -#define CSA_POUND CA_PND -#define CSA_GBP CA_PND -#define CSA_EURO_BIS CA_EURO -#define CSA_EURB CA_EURO -#define CSA_THREE_EIGHTHS CA_TEIG -#define CSA_3ON8 CA_TEIG -#define CSA_FIVE_EIGHTHS CA_FEIG -#define CSA_5ON8 CA_FEIG -#define CSA_SEVEN_EIGHTHS CA_SEIG -#define CSA_7ON8 CA_SEIG -#define CSA_TRADEMARK CA_TM -#define CSA_TM CA_TM -#define CSA_PLUS_MINUS CA_PLMN -#define CSA_PSMS CA_PLMN -#define CSA_INVERTED_QUESTION CA_IQUE -#define CSA_IQST CA_IQUE -#define CSA_DEAD_OGONEK CA_OGON -#define CSA_DOGO CA_OGON -#define CSA_REGISTERED_TRADEMARK CA_REGD -#define CSA_RTM CA_REGD -#define CSA_YEN CA_YEN -#define CSA_YUAN CA_YEN -#define CSA_UP_ARROW CA_UARR -#define CSA_DOTLESS_I CA_DLSI -#define CSA_DLSI CA_DLSI -#define CSA_DEAD_RING CA_RNGA -#define CSA_DRNG CA_RNGA -#define CSA_DEAD_MACRON CA_MACR -#define CSA_DMCR CA_MACR -#define CSA_SECTION CA_SECT -#define CSA_SECT CA_SECT -#define CSA_ORDINAL_INDICATOR_A CA_FORD -#define CSA_ORDA CA_FORD -#define CSA_DEAD_DOUBLE_ACUTE CA_DACU -#define CSA_DDCT CA_DACU -#define CSA_DEAD_CARON CA_CARN -#define CSA_DCAR CA_CARN -#define CSA_DEAD_BREVE CA_BREV -#define CSA_DBRV CA_BREV -#define CSA_BROKEN_PIPE CA_BRKP -#define CSA_BPIP CA_BRKP -#define CSA_COPYRIGHT CA_COPY -#define CSA_CPRT CA_COPY -#define CSA_LEFT_QUOTE CA_LSQU -#define CSA_LQOT CA_LSQU -#define CSA_RIGHT_QUOTE CA_RSQU -#define CSA_RQOT CA_RSQU -#define CSA_EIGHTH_NOTE CA_ENOT -#define CSA_8NOT CA_ENOT -#define CSA_ORDINAL_INDICATOR_O CA_MORD -#define CSA_ORDO CA_MORD -#define CSA_TIMES CA_MUL -#define CSA_TIMS CA_MUL -#define CSA_OBELUS CA_DIV -#define CSA_OBEL CA_DIV -#define CSA_DIVISION_SIGN CA_DIV -#define CSA_DVSN CA_DIV diff --git a/quantum/keymap_extras/keymap_colemak.h b/quantum/keymap_extras/keymap_colemak.h index a97be9ad5d..6658cc1301 100644 --- a/quantum/keymap_extras/keymap_colemak.h +++ b/quantum/keymap_extras/keymap_colemak.h @@ -123,35 +123,3 @@  #define CM_LABK S(CM_COMM) // <  #define CM_RABK S(CM_DOT)  // >  #define CM_QUES S(CM_SLSH) // / - -// DEPRECATED -#define KC_CM_Q    CM_Q -#define KC_CM_W    CM_W -#define KC_CM_F    CM_F -#define KC_CM_P    CM_P -#define KC_CM_G    CM_G -#define KC_CM_J    CM_J -#define KC_CM_L    CM_L -#define KC_CM_U    CM_U -#define KC_CM_Y    CM_Y -#define KC_CM_SCLN CM_SCLN -#define KC_CM_A    CM_A -#define KC_CM_R    CM_R -#define KC_CM_S    CM_S -#define KC_CM_T    CM_T -#define KC_CM_D    CM_D -#define KC_CM_H    CM_H -#define KC_CM_N    CM_N -#define KC_CM_E    CM_E -#define KC_CM_I    CM_I -#define KC_CM_O    CM_O -#define KC_CM_Z    CM_Z -#define KC_CM_X    CM_X -#define KC_CM_C    CM_C -#define KC_CM_V    CM_V -#define KC_CM_B    CM_B -#define KC_CM_K    CM_K -#define KC_CM_M    CM_M -#define KC_CM_COMM CM_COMM -#define KC_CM_DOT  CM_DOT -#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 fea44324b1..b1f2455a68 100644 --- a/quantum/keymap_extras/keymap_fr_ch.h +++ b/quantum/keymap_extras/keymap_fr_ch.h @@ -162,82 +162,3 @@  #define CH_RCBR ALGR(CH_DLR)  // }  // Row 4  #define CH_BSLS ALGR(CH_LABK) // (backslash) - -// DEPRECATED -#define FR_CH_Z    CH_Z -#define FR_CH_Y    CH_Y -#define FR_CH_A    CH_A -#define FR_CH_B    CH_B -#define FR_CH_C    CH_C -#define FR_CH_D    CH_D -#define FR_CH_E    CH_E -#define FR_CH_F    CH_F -#define FR_CH_G    CH_G -#define FR_CH_H    CH_H -#define FR_CH_I    CH_I -#define FR_CH_J    CH_J -#define FR_CH_K    CH_K -#define FR_CH_L    CH_L -#define FR_CH_M    CH_M -#define FR_CH_N    CH_N -#define FR_CH_O    CH_O -#define FR_CH_P    CH_P -#define FR_CH_Q    CH_Q -#define FR_CH_R    CH_R -#define FR_CH_S    CH_S -#define FR_CH_T    CH_T -#define FR_CH_U    CH_U -#define FR_CH_V    CH_V -#define FR_CH_W    CH_W -#define FR_CH_X    CH_X -#define FR_CH_0    CH_0 -#define FR_CH_1    CH_1 -#define FR_CH_2    CH_2 -#define FR_CH_3    CH_3 -#define FR_CH_4    CH_4 -#define FR_CH_5    CH_5 -#define FR_CH_6    CH_6 -#define FR_CH_7    CH_7 -#define FR_CH_8    CH_8 -#define FR_CH_9    CH_9 -#define FR_CH_DOT  CH_DOT -#define FR_CH_COMM CH_COMM -#define FR_CH_QUOT CH_QUOT -#define FR_CH_AE   CH_AGRV -#define FR_CH_UE   CH_EGRV -#define FR_CH_OE   CH_EACU -#define FR_CH_CIRC CH_CIRC -#define FR_CH_LESS CH_LABK -#define FR_CH_MINS CH_MINS -#define FR_CH_DLR  CH_DLR -#define FR_CH_PARA CH_SECT -#define FR_CH_DIAE CH_DIAE -#define FR_CH_RING CH_DEG -#define FR_CH_EXLM CH_EXLM -#define FR_CH_PLUS CH_PLUS -#define FR_CH_DQOT CH_DQUO -#define FR_CH_ASTR CH_ASTR -#define FR_CH_PERC CH_PERC -#define FR_CH_AMPR CH_AMPR -#define FR_CH_SLSH CH_SLSH -#define FR_CH_LPRN CH_LPRN -#define FR_CH_RPRN CH_RPRN -#define FR_CH_EQL  CH_EQL -#define FR_CH_QST  CH_QUES -#define FR_CH_MORE CH_RABK -#define FR_CH_COLN CH_COLN -#define FR_CH_SCLN CH_SCLN -#define FR_CH_UNDS CH_UNDS -#define FR_CH_CCED CH_CCED -#define FR_CH_GRV  CH_GRV -#define FR_CH_LCBR CH_LCBR -#define FR_CH_LBRC CH_LBRC -#define FR_CH_RBRC CH_RBRC -#define FR_CH_RCBR CH_RCBR -#define FR_CH_BSLS CH_BSLS -#define FR_CH_AT   CH_AT -#define FR_CH_EURO CH_EURO -#define FR_CH_TILD CH_TILD -#define FR_CH_PIPE CH_PIPE -#define FR_CH_HASH CH_HASH -#define FR_CH_ACUT CH_ACUT diff --git a/quantum/keymap_extras/keymap_french.h b/quantum/keymap_extras/keymap_french.h index c62f2c4036..0be53f0a9c 100644 --- a/quantum/keymap_extras/keymap_french.h +++ b/quantum/keymap_extras/keymap_french.h @@ -152,14 +152,3 @@  // Row 2  #define FR_EURO ALGR(KC_E)   // €  #define FR_CURR ALGR(FR_DLR) // ¤ - -// DEPRECATED -#define FR_AMP   FR_AMPR -#define FR_APOS  FR_QUOT -#define FR_LESS  FR_LABK -#define FR_OVRR  FR_DEG -#define FR_UMLT  FR_DIAE -#define FR_MU    FR_MICR -#define FR_GRTR  FR_RABK -#define FR_CCIRC FR_CIRC -#define FR_BULT  FR_CURR diff --git a/quantum/keymap_extras/keymap_french_osx.h b/quantum/keymap_extras/keymap_french_osx.h index 76eb221918..590a57e55c 100644 --- a/quantum/keymap_extras/keymap_french_osx.h +++ b/quantum/keymap_extras/keymap_french_osx.h @@ -246,15 +246,3 @@  #define FR_IQUE S(A(FR_COMM)) // ¿  #define FR_BSLS S(A(FR_COLN)) // (backslash)  #define FR_PLMN S(A(FR_EQL))  // ± - -// DEPRECATED -#define FR_AMP  FR_AMPR -#define FR_EACU FR_LEAC -#define FR_APOS FR_QUOT -#define FR_EGRV FR_LEGR -#define FR_CCED FR_LCCE -#define FR_AGRV FR_LAGR -#define FR_UGRV FR_LUGR -#define FR_LESS FR_LABK -#define FR_UMLT FR_DIAE -#define FR_GRTR FR_RABK diff --git a/quantum/keymap_extras/keymap_german.h b/quantum/keymap_extras/keymap_german.h index 924bde6d36..085995b0c6 100644 --- a/quantum/keymap_extras/keymap_german.h +++ b/quantum/keymap_extras/keymap_german.h @@ -151,16 +151,3 @@  // Row 4  #define DE_PIPE ALGR(DE_LABK) // |  #define DE_MICR ALGR(DE_M)    // µ - -// DEPRECATED -#define DE_UE   DE_UDIA -#define DE_OE   DE_ODIA -#define DE_AE   DE_ADIA -#define DE_LESS DE_LABK -#define DE_RING DE_DEG -#define DE_DQOT DE_DQUO -#define DE_PARA DE_SECT -#define DE_QST  DE_QUES -#define DE_MORE DE_RABK -#define DE_SQ2  DE_SUP2 -#define DE_SQ3  DE_SUP3 diff --git a/quantum/keymap_extras/keymap_german_ch.h b/quantum/keymap_extras/keymap_german_ch.h index fee37eabb8..6723836870 100644 --- a/quantum/keymap_extras/keymap_german_ch.h +++ b/quantum/keymap_extras/keymap_german_ch.h @@ -162,21 +162,3 @@  #define CH_RCBR ALGR(CH_DLR)  // }  // Row 4  #define CH_BSLS ALGR(CH_LABK) // (backslash) - -// DEPRECATED -#define CH_AE   CH_ADIA -#define CH_UE   CH_UDIA -#define CH_OE   CH_ODIA -#define CH_PARA CH_SECT -#define CH_CARR CH_CIRC -#define CH_DIER CH_DIAE -#define CH_LESS CH_LABK -#define CH_RING CH_DEG -#define CH_DQOT CH_DQUO -#define CH_PAST CH_ASTR -#define CH_CELA CH_CCED -#define CH_QST  CH_QUES -#define CH_POND CH_PND -#define CH_MORE CH_RABK -#define CH_BRBR CH_BRKP -#define CH_NOTL CH_NOT diff --git a/quantum/keymap_extras/keymap_german_osx.h b/quantum/keymap_extras/keymap_german_osx.h index be109a721e..82404fa5fd 100644 --- a/quantum/keymap_extras/keymap_german_osx.h +++ b/quantum/keymap_extras/keymap_german_osx.h @@ -241,83 +241,3 @@  #define DE_OGON S(A(DE_COMM)) // ˛  #define DE_DIV  S(A(DE_DOT))  // ÷  #define DE_MDSH S(A(DE_MINS)) // — - -// DEPRECATED -#define DE_OSX_CIRC DE_CIRC -#define DE_OSX_1    DE_1 -#define DE_OSX_2    DE_2 -#define DE_OSX_3    DE_3 -#define DE_OSX_4    DE_4 -#define DE_OSX_5    DE_5 -#define DE_OSX_6    DE_6 -#define DE_OSX_7    DE_7 -#define DE_OSX_8    DE_8 -#define DE_OSX_9    DE_9 -#define DE_OSX_0    DE_0 -#define DE_OSX_SS   DE_SS -#define DE_OSX_ACUT DE_ACUT -#define DE_OSX_Q    DE_Q -#define DE_OSX_W    DE_W -#define DE_OSX_E    DE_E -#define DE_OSX_R    DE_R -#define DE_OSX_T    DE_T -#define DE_OSX_Z    DE_Z -#define DE_OSX_U    DE_U -#define DE_OSX_I    DE_I -#define DE_OSX_O    DE_O -#define DE_OSX_P    DE_P -#define DE_OSX_UE   DE_UDIA -#define DE_OSX_PLUS DE_PLUS -#define DE_OSX_A    DE_A -#define DE_OSX_S    DE_S -#define DE_OSX_D    DE_D -#define DE_OSX_F    DE_F -#define DE_OSX_G    DE_G -#define DE_OSX_H    DE_H -#define DE_OSX_J    DE_J -#define DE_OSX_K    DE_K -#define DE_OSX_L    DE_L -#define DE_OSX_OE   DE_ODIA -#define DE_OSX_AE   DE_ADIA -#define DE_OSX_HASH DE_HASH -#define DE_OSX_LESS DE_LABK -#define DE_OSX_Y    DE_Y -#define DE_OSX_X    DE_X -#define DE_OSX_C    DE_C -#define DE_OSX_V    DE_V -#define DE_OSX_B    DE_B -#define DE_OSX_N    DE_N -#define DE_OSX_M    DE_M -#define DE_OSX_COMM DE_COMM -#define DE_OSX_DOT  DE_DOT -#define DE_OSX_MINS DE_MINS - -#define DE_OSX_RING DE_DEG -#define DE_OSX_EXLM DE_EXLM -#define DE_OSX_DQOT DE_DQUO -#define DE_OSX_PARA DE_SECT -#define DE_OSX_DLR  DE_DLR -#define DE_OSX_PERC DE_PERC -#define DE_OSX_AMPR DE_AMPR -#define DE_OSX_SLSH DE_SLSH -#define DE_OSX_LPRN DE_LPRN -#define DE_OSX_RPRN DE_RPRN -#define DE_OSX_EQL  DE_EQL -#define DE_OSX_QST  DE_QUES -#define DE_OSX_GRV  DE_GRV -#define DE_OSX_ASTR DE_ASTR -#define DE_OSX_QUOT DE_QUOT -#define DE_OSX_MORE DE_RABK -#define DE_OSX_COLN DE_COLN -#define DE_OSX_SCLN DE_SCLN -#define DE_OSX_UNDS DE_UNDS - -#define DE_OSX_LBRC DE_LBRC -#define DE_OSX_RBRC DE_RBRC -#define DE_OSX_PIPE DE_PIPE -#define DE_OSX_LCBR DE_LCBR -#define DE_OSX_RCBR DE_RCBR -#define DE_OSX_AT   DE_AT -#define DE_OSX_EURO DE_EURO -#define DE_OSX_TILD DE_TILD -#define DE_OSX_BSLS DE_BSLS diff --git a/quantum/keymap_extras/keymap_hungarian.h b/quantum/keymap_extras/keymap_hungarian.h index 1b282a4615..a4e4b1a522 100644 --- a/quantum/keymap_extras/keymap_hungarian.h +++ b/quantum/keymap_extras/keymap_hungarian.h @@ -169,22 +169,3 @@  #define HU_RCBR ALGR(HU_N)    // }  #define HU_SCLN ALGR(HU_COMM) // ;  #define HU_ASTR ALGR(HU_MINS) // * - -// DEPRECATED -#define HU_OE   HU_ODIA -#define HU_UE   HU_UDIA -#define HU_OO   HU_OACU -#define HU_OEE  HU_ODAC -#define HU_UU   HU_UACU -#define HU_EE   HU_EACU -#define HU_AA   HU_AACU -#define HU_UEE  HU_UDAC -#define HU_II   HU_IACU -#define HU_PARA HU_SECT -#define HU_DQOT HU_DQUO -#define HU_QST  HU_QUES -#define HU_BRV  HU_BREV -#define HU_RING HU_RNGA -#define HU_CRSS HU_MUL -#define HU_LESS HU_LABK -#define HU_MORE HU_RABK diff --git a/quantum/keymap_extras/keymap_italian.h b/quantum/keymap_extras/keymap_italian.h index 5d19e56d38..be495f85ba 100644 --- a/quantum/keymap_extras/keymap_italian.h +++ b/quantum/keymap_extras/keymap_italian.h @@ -163,22 +163,3 @@  // Row 2  #define IT_LCBR S(ALGR(IT_EGRV)) // {  #define IT_RCBR S(ALGR(IT_PLUS)) // } - -// DEPRECATED -#define IT_BKSL IT_BSLS -#define IT_APOS IT_QUOT -#define IT_IACC IT_IGRV -#define IT_EACC IT_EGRV -#define IT_OACC IT_OGRV -#define IT_AACC IT_AGRV -#define IT_UACC IT_UGRV -#define IT_LESS IT_LABK -#define IT_DQOT IT_DQUO -#define IT_STRL IT_PND -#define IT_QST  IT_QUES -#define IT_CRC  IT_CIRC -#define IT_MORE IT_RABK -#define IT_SHRP IT_HASH - -#define IT_X_PLUS X_RBRACKET -#define IT_ACUT diff --git a/quantum/keymap_extras/keymap_italian_osx_ansi.h b/quantum/keymap_extras/keymap_italian_osx_ansi.h index 488a6561ee..c2b8e3cad6 100644 --- a/quantum/keymap_extras/keymap_italian_osx_ansi.h +++ b/quantum/keymap_extras/keymap_italian_osx_ansi.h @@ -248,21 +248,3 @@  #define IT_CUAC S(A(IT_M))    // Ú  #define IT_MDDT S(A(IT_DOT))  // ·  #define IT_MDSH S(A(IT_MINS)) // — - -// DEPRECATED -#define IT_LESS IT_LABK -#define IT_APOS IT_QUOT -#define IT_IACC IT_IGRV -#define IT_EACC IT_EGRV -#define IT_UACC IT_UGRV -#define IT_OACC IT_OGRV -#define IT_AACC IT_AGRV -#define IT_MORE IT_RABK -#define IT_DQOT IT_DQUO -#define IT_STRL IT_PND -#define IT_QST  IT_QUES -#define IT_CRC  IT_CIRC -#define IT_DEGR IT_DEG -#define IT_TILDE IT_TILD -#define IT_GRAVE IT_GRV -#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 e4fb03acf7..61f76ddba7 100644 --- a/quantum/keymap_extras/keymap_italian_osx_iso.h +++ b/quantum/keymap_extras/keymap_italian_osx_iso.h @@ -249,21 +249,3 @@  #define IT_CUAC S(A(IT_M))    // Ú  #define IT_MDDT S(A(IT_DOT))  // ·  #define IT_MDSH S(A(IT_MINS)) // — - -// DEPRECATED -#define IT_APOS IT_QUOT -#define IT_IACC IT_IGRV -#define IT_EACC IT_EGRV -#define IT_OACC IT_OGRV -#define IT_AACC IT_AGRV -#define IT_UACC IT_UGRV -#define IT_LESS IT_LABK -#define IT_DQOT IT_DQUO -#define IT_STRL IT_PND -#define IT_QST  IT_QUES -#define IT_CRC  IT_CIRC -#define IT_DEGR IT_DEG -#define IT_MORE IT_RABK -#define IT_TILDE IT_TILD -#define IT_GRAVE IT_GRV -#define IT_SHRP IT_HASH diff --git a/quantum/keymap_extras/keymap_jp.h b/quantum/keymap_extras/keymap_jp.h index cd3c08f9f0..d10feb5856 100644 --- a/quantum/keymap_extras/keymap_jp.h +++ b/quantum/keymap_extras/keymap_jp.h @@ -137,12 +137,3 @@  #define JP_RABK S(JP_DOT)  // >  #define JP_QUES S(JP_SLSH) // ?  #define JP_UNDS S(JP_BSLS) // _ - -// DEPRECATED -#define JP_ZHTG JP_ZKHK -#define JP_DQT  JP_DQUO -#define JP_LT   JP_LABK -#define JP_GT   JP_RABK - -#define JP_MEISU KC_LANG2 // Eisū (英数) on macOS -#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 8d5323c6a8..f9fc00d794 100644 --- a/quantum/keymap_extras/keymap_neo2.h +++ b/quantum/keymap_extras/keymap_neo2.h @@ -88,55 +88,3 @@  #define NE_J    KC_SLSH // J  // Row 5  #define NE_L4R  KC_ALGR // (layer 4) - -// DEPRECATED -#define NEO_A NE_A -#define NEO_B NE_B -#define NEO_C NE_C -#define NEO_D NE_D -#define NEO_E NE_E -#define NEO_F NE_F -#define NEO_G NE_G -#define NEO_H NE_H -#define NEO_I NE_I -#define NEO_J NE_J -#define NEO_K NE_K -#define NEO_L NE_L -#define NEO_M NE_M -#define NEO_N NE_N -#define NEO_O NE_O -#define NEO_P NE_P -#define NEO_Q NE_Q -#define NEO_R NE_R -#define NEO_S NE_S -#define NEO_T NE_T -#define NEO_U NE_U -#define NEO_V NE_V -#define NEO_W NE_W -#define NEO_X NE_X -#define NEO_Y NE_Y -#define NEO_Z NE_Z -#define NEO_AE NE_ADIA -#define NEO_OE NE_ODIA -#define NEO_UE NE_UDIA -#define NEO_SS NE_SS -#define NEO_DOT NE_DOT -#define NEO_COMM NE_COMM -#define NEO_1 NE_1 -#define NEO_2 NE_2 -#define NEO_3 NE_3 -#define NEO_4 NE_4 -#define NEO_5 NE_5 -#define NEO_6 NE_6 -#define NEO_7 NE_7 -#define NEO_8 NE_8 -#define NEO_9 NE_9 -#define NEO_0 NE_0 -#define NEO_MINS NE_MINS -#define NEO_ACUT NE_ACUT -#define NEO_GRV NE_GRV -#define NEO_CIRC NE_CIRC -#define NEO_L1_L NE_L3L -#define NEO_L1_R NE_L3R -#define NEO_L2_L NE_L4L -#define NEO_L2_R NE_L4R diff --git a/quantum/keymap_extras/keymap_norwegian.h b/quantum/keymap_extras/keymap_norwegian.h index 74c0c1ae27..b2499f4fda 100644 --- a/quantum/keymap_extras/keymap_norwegian.h +++ b/quantum/keymap_extras/keymap_norwegian.h @@ -150,26 +150,3 @@  #define NO_TILD ALGR(NO_DIAE) // ~ (dead)  // Row 4  #define NO_MICR ALGR(NO_M)    // µ - -// DEPRECATED -#define NO_AM       NO_ARNG -#define NO_AA       NO_ARNG -#define NO_OSLH     NO_OSTR -#define NO_APOS     NO_QUOT -#define NO_LESS     NO_LABK -#define NO_QUO2     NO_DQUO -#define NO_BULT     NO_CURR -#define NO_GRTR     NO_RABK -#define NO_MU       NO_MICR -// Norwegian macOS symbols -#define NO_ACUT_MAC NO_BSLS       // ´ -#define NO_APOS_MAC NO_LABK       // ' -#define NO_AT_MAC   NO_QUOT       // @ -#define NO_BSLS_MAC S(ALGR(NO_7)) // (backslash) -#define NO_DLR_MAC  S(NO_4)       // $ -#define NO_GRV_MAC  ALGR(NO_BSLS) // ` -#define NO_GRTR_MAC S(NO_PIPE)    // > -#define NO_LCBR_MAC S(ALGR(NO_8)) // { -#define NO_LESS_MAC NO_PIPE       // < -#define NO_PIPE_MAC ALGR(NO_7)    // | -#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 06be62cf33..827fa06c25 100644 --- a/quantum/keymap_extras/keymap_slovenian.h +++ b/quantum/keymap_extras/keymap_slovenian.h @@ -161,11 +161,3 @@  #define SI_LCBR ALGR(SI_B)    // {  #define SI_RCBR ALGR(SI_N)    // }  #define SI_SECT ALGR(SI_M)    // § - -// DEPRECATED -#define SI_QOT  SI_QUOT -#define SI_SV   SI_SCAR -#define SI_CV   SI_CCAR -#define SI_ZV   SI_ZCAR -#define SI_DQOT SI_DQUO -#define SI_QST  SI_QUES diff --git a/quantum/keymap_extras/keymap_spanish.h b/quantum/keymap_extras/keymap_spanish.h index 4e888c5133..8432c56e99 100644 --- a/quantum/keymap_extras/keymap_spanish.h +++ b/quantum/keymap_extras/keymap_spanish.h @@ -151,12 +151,3 @@  // Row 3  #define ES_LCBR ALGR(ES_ACUT) // {  #define ES_RCBR ALGR(ES_CCED) // } - -// DEPRECATED -#define ES_OVRR ES_MORD -#define ES_APOS ES_QUOT -#define ES_LESS ES_LABK -#define ES_ASML ES_FORD -#define ES_OVDT ES_BULT -#define ES_UMLT ES_DIAE -#define ES_GRTR ES_RABK diff --git a/quantum/keymap_extras/keymap_swedish.h b/quantum/keymap_extras/keymap_swedish.h index aef8d003d6..cadb66d3bd 100644 --- a/quantum/keymap_extras/keymap_swedish.h +++ b/quantum/keymap_extras/keymap_swedish.h @@ -154,26 +154,3 @@  // DEPRECATED  #include "keymap_nordic.h" - -#define SE_OSLH SE_ODIA -#define SE_APOS SE_QUOT -#define SE_LESS SE_LABK -#define SE_QUO2 SE_DQUO -#define SE_BULT SE_CURR -#define SE_GRTR SE_RABK -#define SE_AA   SE_ARNG -#define SE_AE   SE_ADIA -#define SE_AM   SE_ARNG -#define SE_MU   SE_MICR -// Swedish macOS symbols (not vetted) -#define SE_ACUT_MAC SE_ACUT -#define SE_APOS_MAC SE_LABK -#define SE_AT_MAC   SE_ADIA -#define SE_BSLS_MAC S(SE_LCBR) -#define SE_DLR_MAC  SE_CURR -#define SE_GRV_MAC  SE_BSLS -#define SE_GRTR_MAC SE_HALF -#define SE_LCBR_MAC S(SE_LBRC) -#define SE_LESS_MAC SE_SECT -#define SE_PIPE_MAC SE_LCBR -#define SE_RCBR_MAC S(SE_RBRC) diff --git a/quantum/keymap_extras/keymap_uk.h b/quantum/keymap_extras/keymap_uk.h index 1eba0ed2f4..03fe8149f0 100644 --- a/quantum/keymap_extras/keymap_uk.h +++ b/quantum/keymap_extras/keymap_uk.h @@ -149,78 +149,3 @@  #define UK_OACU ALGR(KC_O)    // Ó  // Row 3  #define UK_AACU ALGR(KC_A)    // Á - -// DEPRECATED -#define UK_ESC  KC_ESC -#define UK_F1   KC_F1 -#define UK_F2   KC_F2 -#define UK_F3   KC_F3 -#define UK_F4   KC_F4 -#define UK_F5   KC_F5 -#define UK_F6   KC_F6 -#define UK_F7   KC_F7 -#define UK_F8   KC_F8 -#define UK_F9   KC_F9 -#define UK_F10  KC_F10 -#define UK_F11  KC_F11 -#define UK_F12  KC_F12 -#define UK_PSCR KC_PSCR -#define UK_SLCK KC_SLCK -#define UK_PAUS KC_PAUS -#define UK_BSPC KC_BSPC -#define UK_TAB  KC_TAB -#define UK_ENT  KC_ENT -#define UK_LSFT KC_LSFT -#define UK_RSFT KC_RSFT -#define UK_LCTL KC_LCTL -#define UK_LGUI KC_LGUI -#define UK_LALT KC_LALT -#define UK_SPC  KC_SPC -#define UK_RALT KC_RALT -#define UK_RGUI KC_RGUI -#define UK_RCTL KC_RCTL -#define UK_INS  KC_INS -#define UK_DEL  KC_DEL -#define UK_HOME KC_HOME -#define UK_END  KC_END -#define UK_PGUP KC_PGUP -#define UK_PGDN KC_PGDN -#define UK_UP   KC_UP -#define UK_LEFT KC_LEFT -#define UK_DOWN KC_DOWN -#define UK_RGHT KC_RGHT -#define UK_PSLS KC_PSLS -#define UK_PAST KC_PAST -#define UK_PMNS KC_PMNS -#define UK_PPLS KC_PPLS -#define UK_PENT KC_PENT -#define UK_P1   KC_P1 -#define UK_P2   KC_P2 -#define UK_P3   KC_P3 -#define UK_P4   KC_P4 -#define UK_P5   KC_P5 -#define UK_P6   KC_P6 -#define UK_P7   KC_P7 -#define UK_P8   KC_P8 -#define UK_P9   KC_P9 -#define UK_P0   KC_P0 -#define UK_PDOT KC_PDOT -#define UK_PEQL KC_PEQL -#define UK_PCMM KC_PCMM -#define UK_F13  KC_F13 -#define UK_F14  KC_F14 -#define UK_F15  KC_F15 -#define UK_F16  KC_F16 -#define UK_F17  KC_F17 -#define UK_F18  KC_F18 -#define UK_F19  KC_F19 -#define UK_F20  KC_F20 -#define UK_F21  KC_F21 -#define UK_F22  KC_F22 -#define UK_F23  KC_F23 -#define UK_F24  KC_F24 -#define UK_EACT UK_EACU -#define UK_UACT UK_UACU -#define UK_IACT UK_IACU -#define UK_OACT UK_OACU -#define UK_AACT UK_OACU diff --git a/quantum/keymap_extras/keymap_workman.h b/quantum/keymap_extras/keymap_workman.h index 4c7530aa07..6367d68351 100644 --- a/quantum/keymap_extras/keymap_workman.h +++ b/quantum/keymap_extras/keymap_workman.h @@ -123,32 +123,3 @@  #define WK_LABK S(WK_COMM) // <  #define WK_RABK S(WK_DOT)  // >  #define WK_QUES S(WK_SLSH) // ? - -// DEPRECATED -#define KC_WK_Q    WK_Q -#define KC_WK_D    WK_D -#define KC_WK_R    WK_R -#define KC_WK_W    WK_W -#define KC_WK_B    WK_B -#define KC_WK_J    WK_J -#define KC_WK_F    WK_F -#define KC_WK_U    WK_U -#define KC_WK_P    WK_P -#define KC_WK_SCLN WK_SCLN -#define KC_WK_A    WK_A -#define KC_WK_S    WK_S -#define KC_WK_H    WK_H -#define KC_WK_T    WK_T -#define KC_WK_G    WK_G -#define KC_WK_Y    WK_Y -#define KC_WK_N    WK_N -#define KC_WK_E    WK_E -#define KC_WK_O    WK_O -#define KC_WK_I    WK_I -#define KC_WK_Z    WK_Z -#define KC_WK_X    WK_X -#define KC_WK_M    WK_M -#define KC_WK_C    WK_C -#define KC_WK_V    WK_V -#define KC_WK_K    WK_K -#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 6f69f6892b..a4638fde69 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) {  }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_ALPHAS_MODS +#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 523dba1b78..f9cb85dc4f 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) {  bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_BAND +#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 fb3b835cad..d3144bffbf 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  bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_BAND_PINWHEEL +#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 fca22aad9c..defbe69676 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  bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_BAND_SPIRAL +#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 00310e3f65..4f49f50690 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) {  }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_BREATHING +#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 51e81d57ca..c426d02fd5 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  bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT +#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 f62061552c..55527556fd 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  bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_CYCLE_OUT_IN +#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 bd1d125672..d97de0d1ec 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  bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_CYCLE_UP_DOWN +#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 9b8a7877c9..e1bc5ae464 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,  bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_DUAL_BEACON +#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 0000000000..ad1f46b242 --- /dev/null +++ b/quantum/led_matrix/animations/led_matrix_effects.inc @@ -0,0 +1,18 @@ +// Add your new core led matrix effect here, order determines enum order +#include "solid_anim.h" +#include "alpha_mods_anim.h" +#include "breathing_anim.h" +#include "band_anim.h" +#include "band_pinwheel_anim.h" +#include "band_spiral_anim.h" +#include "cycle_left_right_anim.h" +#include "cycle_up_down_anim.h" +#include "cycle_out_in_anim.h" +#include "dual_beacon_anim.h" +#include "solid_reactive_simple_anim.h" +#include "solid_reactive_wide.h" +#include "solid_reactive_cross.h" +#include "solid_reactive_nexus.h" +#include "solid_splash_anim.h" +#include "wave_left_right_anim.h" +#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 ef97631b90..ef97631b90 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 5ef5938be0..5ef5938be0 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 b3015759be..b3015759be 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 4369ea8c49..4369ea8c49 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 d6eb9731ee..d6eb9731ee 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 4a5219abd1..4a5219abd1 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 0000000000..c09022bb0f --- /dev/null +++ b/quantum/led_matrix/animations/runners/led_matrix_runners.inc @@ -0,0 +1,6 @@ +#include "effect_runner_dx_dy_dist.h" +#include "effect_runner_dx_dy.h" +#include "effect_runner_i.h" +#include "effect_runner_sin_cos_i.h" +#include "effect_runner_reactive.h" +#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 4c9e43c581..4c9e43c581 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 f402d99b37..94425c959f 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  #            endif  #        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#    endif  // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) -#endif  // LED_MATRIX_KEYREACTIVE_ENABLED +#    endif      // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) +#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 4d0d252263..504b1104f1 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  #            endif  #        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#    endif  // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) -#endif  // LED_MATRIX_KEYREACTIVE_ENABLED +#    endif      // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) +#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 30e2527f60..4752a84162 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  bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }  #        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#    endif  // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE -#endif  // LED_MATRIX_KEYREACTIVE_ENABLED +#    endif      // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE +#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 34a230c259..922e32fe5f 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  #            endif  #        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#    endif  // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) -#endif  // LED_MATRIX_KEYREACTIVE_ENABLED +#    endif      // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) +#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 4f6ba3d343..d95889b813 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_  #            endif  #        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#    endif  // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) -#endif  // LED_MATRIX_KEYREACTIVE_ENABLED +#    endif      // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) +#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 736f22ddc5..8579f1b45f 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  bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT +#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 3cab0597d4..635c608414 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  bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); }  #    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS -#endif  // DISABLE_LED_MATRIX_WAVE_UP_DOWN +#endif      // DISABLE_LED_MATRIX_WAVE_UP_DOWN diff --git a/quantum/led_matrix.c b/quantum/led_matrix/led_matrix.c index 7e0fdf896a..32788866c5 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};  const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;  #endif +// clang-format off +#ifndef LED_MATRIX_IMMEDIATE_EEPROM +#    define led_eeconfig_update(v) led_update_eeprom |= v +#else +#    define led_eeconfig_update(v) if (v) eeconfig_update_led_matrix() +#endif +// clang-format on +  // Generic effect runners -#include "led_matrix_runners/effect_runner_dx_dy_dist.h" -#include "led_matrix_runners/effect_runner_dx_dy.h" -#include "led_matrix_runners/effect_runner_i.h" -#include "led_matrix_runners/effect_runner_sin_cos_i.h" -#include "led_matrix_runners/effect_runner_reactive.h" -#include "led_matrix_runners/effect_runner_reactive_splash.h" +#include "led_matrix_runners.inc"  // ------------------------------------------  // -----Begin led effect includes macros-----  #define LED_MATRIX_EFFECT(name)  #define LED_MATRIX_CUSTOM_EFFECT_IMPLS -#include "led_matrix_animations/led_matrix_effects.inc" +#include "led_matrix_effects.inc"  #ifdef LED_MATRIX_CUSTOM_KB  #    include "led_matrix_kb.inc"  #endif @@ -67,10 +70,6 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;  #    define LED_DISABLE_TIMEOUT 0  #endif -#if LED_DISABLE_WHEN_USB_SUSPENDED != 1 -#    undef LED_DISABLE_WHEN_USB_SUSPENDED -#endif -  #if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX  #    undef LED_MATRIX_MAXIMUM_BRIGHTNESS  #    define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX @@ -108,6 +107,7 @@ last_hit_t g_last_hit_tracker;  // internals  static bool            suspend_state     = false; +static bool            led_update_eeprom = false;  static uint8_t         led_last_enable   = UINT8_MAX;  static uint8_t         led_last_effect   = UINT8_MAX;  static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; @@ -280,6 +280,8 @@ static void led_task_timers(void) {  static void led_task_sync(void) {      // next task +    if (led_update_eeprom) eeconfig_update_led_matrix(); +    led_update_eeprom = false;      if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING;  } @@ -318,7 +320,7 @@ static void led_task_render(uint8_t effect) {      case LED_MATRIX_##name:                   \          rendering = name(&led_effect_params); \          break; -#include "led_matrix_animations/led_matrix_effects.inc" +#include "led_matrix_effects.inc"  #undef LED_MATRIX_EFFECT  #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; }  void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {      led_matrix_eeconfig.enable ^= 1;      led_task_state = STARTING; -    if (write_to_eeprom) { -        eeconfig_update_led_matrix(); -    } +    led_eeconfig_update(write_to_eeprom);      dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable);  }  void 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); }  void led_matrix_enable(void) {      led_matrix_enable_noeeprom(); -    eeconfig_update_led_matrix(); +    led_eeconfig_update(true);  }  void led_matrix_enable_noeeprom(void) { @@ -489,7 +489,7 @@ void led_matrix_enable_noeeprom(void) {  void led_matrix_disable(void) {      led_matrix_disable_noeeprom(); -    eeconfig_update_led_matrix(); +    led_eeconfig_update(true);  }  void led_matrix_disable_noeeprom(void) { @@ -511,9 +511,7 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {          led_matrix_eeconfig.mode = mode;      }      led_task_state = STARTING; -    if (write_to_eeprom) { -        eeconfig_update_led_matrix(); -    } +    led_eeconfig_update(write_to_eeprom);      dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);  }  void 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) {          return;      }      led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; -    if (write_to_eeprom) { -        eeconfig_update_led_matrix(); -    } +    led_eeconfig_update(write_to_eeprom);      dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val);  }  void 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); }  void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {      led_matrix_eeconfig.speed = speed; -    if (write_to_eeprom) { -        eeconfig_update_led_matrix(); -    } +    led_eeconfig_update(write_to_eeprom);      dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed);  }  void 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 0984de73b3..6f85854fbe 100644 --- a/quantum/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h @@ -56,7 +56,7 @@ enum led_matrix_effects {  // --------------------------------------  // -----Begin led effect enum macros-----  #define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name, -#include "led_matrix_animations/led_matrix_effects.inc" +#include "led_matrix_effects.inc"  #undef LED_MATRIX_EFFECT  #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 1d46b2c506..1d46b2c506 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 61cdbd9b8e..61cdbd9b8e 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 67237c5683..0000000000 --- a/quantum/led_matrix_animations/led_matrix_effects.inc +++ /dev/null @@ -1,18 +0,0 @@ -// Add your new core led matrix effect here, order determins enum order, requires "led_matrix_animations/ directory -#include "led_matrix_animations/solid_anim.h" -#include "led_matrix_animations/alpha_mods_anim.h" -#include "led_matrix_animations/breathing_anim.h" -#include "led_matrix_animations/band_anim.h" -#include "led_matrix_animations/band_pinwheel_anim.h" -#include "led_matrix_animations/band_spiral_anim.h" -#include "led_matrix_animations/cycle_left_right_anim.h" -#include "led_matrix_animations/cycle_up_down_anim.h" -#include "led_matrix_animations/cycle_out_in_anim.h" -#include "led_matrix_animations/dual_beacon_anim.h" -#include "led_matrix_animations/solid_reactive_simple_anim.h" -#include "led_matrix_animations/solid_reactive_wide.h" -#include "led_matrix_animations/solid_reactive_cross.h" -#include "led_matrix_animations/solid_reactive_nexus.h" -#include "led_matrix_animations/solid_splash_anim.h" -#include "led_matrix_animations/wave_left_right_anim.h" -#include "led_matrix_animations/wave_up_down_anim.h" diff --git a/quantum/matrix.c b/quantum/matrix.c index 34d6af2e6d..566d9ff340 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -16,6 +16,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */  #include <stdint.h>  #include <stdbool.h> +#include <string.h>  #include "util.h"  #include "matrix.h"  #include "debounce.h" @@ -24,14 +25,23 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #ifdef DIRECT_PINS  static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;  #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) +#    ifdef MATRIX_ROW_PINS  static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; +#    endif  // MATRIX_ROW_PINS +#    ifdef MATRIX_COL_PINS  static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +#    endif  // MATRIX_COL_PINS  #endif  /* matrix state(1:on, 0:off) */  extern matrix_row_t raw_matrix[MATRIX_ROWS];  // raw values  extern matrix_row_t matrix[MATRIX_ROWS];      // debounced values +// user-defined overridable functions +__attribute__((weak)) void matrix_init_pins(void); +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); +__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); +  static inline void setPinOutput_writeLow(pin_t pin) {      ATOMIC_BLOCK_FORCEON {          setPinOutput(pin); @@ -43,11 +53,19 @@ static inline void setPinInputHigh_atomic(pin_t pin) {      ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }  } +static inline uint8_t readMatrixPin(pin_t pin) { +    if (pin != NO_PIN) { +        return readPin(pin); +    } else { +        return 1; +    } +} +  // matrix code  #ifdef DIRECT_PINS -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      for (int row = 0; row < MATRIX_ROWS; row++) {          for (int col = 0; col < MATRIX_COLS; col++) {              pin_t pin = direct_pins[row][col]; @@ -58,7 +76,7 @@ static void init_pins(void) {      }  } -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {      // Start with a clear matrix row      matrix_row_t current_row_value = 0; @@ -69,46 +87,57 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)          }      } -    // If the row has changed, store the row and return the changed flag. -    if (current_matrix[current_row] != current_row_value) { -        current_matrix[current_row] = current_row_value; -        return true; -    } -    return false; +    // Update the matrix +    current_matrix[current_row] = current_row_value;  }  #elif defined(DIODE_DIRECTION) -#    if (DIODE_DIRECTION == COL2ROW) +#    if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS) +#        if (DIODE_DIRECTION == COL2ROW) -static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } +static bool select_row(uint8_t row) { +    pin_t pin = row_pins[row]; +    if (pin != NO_PIN) { +        setPinOutput_writeLow(pin); +        return true; +    } +    return false; +} -static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); } +static void unselect_row(uint8_t row) { +    pin_t pin = row_pins[row]; +    if (pin != NO_PIN) { +        setPinInputHigh_atomic(pin); +    } +}  static void unselect_rows(void) {      for (uint8_t x = 0; x < MATRIX_ROWS; x++) { -        setPinInputHigh_atomic(row_pins[x]); +        unselect_row(x);      }  } -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      unselect_rows();      for (uint8_t x = 0; x < MATRIX_COLS; x++) { -        setPinInputHigh_atomic(col_pins[x]); +        if (col_pins[x] != NO_PIN) { +            setPinInputHigh_atomic(col_pins[x]); +        }      }  } -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {      // Start with a clear matrix row      matrix_row_t current_row_value = 0; -    // Select row -    select_row(current_row); +    if (!select_row(current_row)) {  // Select row +        return;                      // skip NO_PIN row +    }      matrix_output_select_delay();      // For each col...      for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { -        // Select the col pin to read (active low) -        uint8_t pin_state = readPin(col_pins[col_index]); +        uint8_t pin_state = readMatrixPin(col_pins[col_index]);          // Populate the matrix row with the state of the col pin          current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); @@ -118,79 +147,78 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)      unselect_row(current_row);      matrix_output_unselect_delay();  // wait for all Col signals to go HIGH -    // If the row has changed, store the row and return the changed flag. -    if (current_matrix[current_row] != current_row_value) { -        current_matrix[current_row] = current_row_value; +    // Update the matrix +    current_matrix[current_row] = current_row_value; +} + +#        elif (DIODE_DIRECTION == ROW2COL) + +static bool select_col(uint8_t col) { +    pin_t pin = col_pins[col]; +    if (pin != NO_PIN) { +        setPinOutput_writeLow(pin);          return true;      }      return false;  } -#    elif (DIODE_DIRECTION == ROW2COL) - -static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } - -static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); } +static void unselect_col(uint8_t col) { +    pin_t pin = col_pins[col]; +    if (pin != NO_PIN) { +        setPinInputHigh_atomic(pin); +    } +}  static void unselect_cols(void) {      for (uint8_t x = 0; x < MATRIX_COLS; x++) { -        setPinInputHigh_atomic(col_pins[x]); +        unselect_col(x);      }  } -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      unselect_cols();      for (uint8_t x = 0; x < MATRIX_ROWS; x++) { -        setPinInputHigh_atomic(row_pins[x]); +        if (row_pins[x] != NO_PIN) { +            setPinInputHigh_atomic(row_pins[x]); +        }      }  } -static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { -    bool matrix_changed = false; - +__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {      // Select col -    select_col(current_col); +    if (!select_col(current_col)) {  // select col +        return;                      // skip NO_PIN col +    }      matrix_output_select_delay();      // For each row...      for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { -        // Store last value of row prior to reading -        matrix_row_t last_row_value    = current_matrix[row_index]; -        matrix_row_t current_row_value = last_row_value; -          // Check row pin state -        if (readPin(row_pins[row_index]) == 0) { +        if (readMatrixPin(row_pins[row_index]) == 0) {              // Pin LO, set col bit -            current_row_value |= (MATRIX_ROW_SHIFTER << current_col); +            current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);          } else {              // Pin HI, clear col bit -            current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); -        } - -        // Determine if the matrix changed state -        if ((last_row_value != current_row_value)) { -            matrix_changed |= true; -            current_matrix[row_index] = current_row_value; +            current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);          }      }      // Unselect col      unselect_col(current_col);      matrix_output_unselect_delay();  // wait for all Row signals to go HIGH - -    return matrix_changed;  } -#    else -#        error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! -#    endif +#        else +#            error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! +#        endif +#    endif  // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)  #else  #    error DIODE_DIRECTION is not defined!  #endif  void matrix_init(void) {      // initialize key pins -    init_pins(); +    matrix_init_pins();      // initialize matrix state: all keys off      for (uint8_t i = 0; i < MATRIX_ROWS; i++) { @@ -204,20 +232,23 @@ void matrix_init(void) {  }  uint8_t matrix_scan(void) { -    bool changed = false; +    matrix_row_t curr_matrix[MATRIX_ROWS] = {0};  #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)      // Set row, read cols      for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { -        changed |= read_cols_on_row(raw_matrix, current_row); +        matrix_read_cols_on_row(curr_matrix, current_row);      }  #elif (DIODE_DIRECTION == ROW2COL)      // Set col, read rows      for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { -        changed |= read_rows_on_col(raw_matrix, current_col); +        matrix_read_rows_on_col(curr_matrix, current_col);      }  #endif +    bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0; +    if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix)); +      debounce(raw_matrix, matrix, MATRIX_ROWS, changed);      matrix_scan_quantum(); diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index 9268c4522e..ca0accd719 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -136,10 +136,6 @@ ifneq ($(findstring STM32F042, $(MCU)),)    USE_FPU ?= no -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 -    # UF2 settings    UF2_FAMILY ?= STM32F0  endif @@ -172,10 +168,6 @@ ifneq ($(findstring STM32F072, $(MCU)),)    USE_FPU ?= no -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 -    # UF2 settings    UF2_FAMILY ?= STM32F0  endif @@ -208,10 +200,6 @@ ifneq ($(findstring STM32F103, $(MCU)),)    USE_FPU ?= no -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 -    # UF2 settings    UF2_FAMILY ?= STM32F1  endif @@ -244,10 +232,6 @@ ifneq ($(findstring STM32F303, $(MCU)),)    USE_FPU ?= yes -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 -    # UF2 settings    UF2_FAMILY ?= STM32F3  endif @@ -280,10 +264,6 @@ ifneq ($(findstring STM32F401, $(MCU)),)    USE_FPU ?= yes -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 -    # UF2 settings    UF2_FAMILY ?= STM32F4  endif @@ -321,10 +301,6 @@ ifneq ($(findstring STM32F411, $(MCU)),)    USE_FPU ?= yes -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 -    # UF2 settings    UF2_FAMILY ?= STM32F4  endif @@ -357,10 +333,6 @@ ifneq ($(findstring STM32F446, $(MCU)),)    BOARD ?= GENERIC_STM32_F446XE    USE_FPU ?= yes - -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11  endif  ifneq ($(findstring STM32G431, $(MCU)),) @@ -391,10 +363,6 @@ ifneq ($(findstring STM32G431, $(MCU)),)    USE_FPU ?= yes -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 -    # UF2 settings    UF2_FAMILY ?= STM32G4  endif @@ -427,10 +395,6 @@ ifneq ($(findstring STM32G474, $(MCU)),)    USE_FPU ?= yes -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 -    # UF2 settings    UF2_FAMILY ?= STM32G4  endif @@ -465,9 +429,39 @@ ifneq (,$(filter $(MCU),STM32L433 STM32L443))    USE_FPU ?= yes -  # Options to pass to dfu-util when flashing -  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave -  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 +  # UF2 settings +  UF2_FAMILY ?= STM32L4 +endif + +ifneq (,$(filter $(MCU),STM32L412 STM32L422)) +  # Cortex version +  MCU = cortex-m4 + +  # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +  ARMV = 7 + +  ## chip/board settings +  # - the next two should match the directories in +  #   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +  MCU_FAMILY = STM32 +  MCU_SERIES = STM32L4xx + +  # Linker script to use +  # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ +  #   or <keyboard_dir>/ld/ +  MCU_LDSCRIPT ?= STM32L412xB + +  # Startup code to use +  #  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ +  MCU_STARTUP ?= stm32l4xx + +  # Board: it should exist either in <chibios>/os/hal/boards/, +  # <keyboard_dir>/boards/, or drivers/boards/ +  BOARD ?= GENERIC_STM32_L412XB + +  PLATFORM_NAME ?= platform_l432 + +  USE_FPU ?= yes    # UF2 settings    UF2_FAMILY ?= STM32L4 diff --git a/quantum/mousekey.c b/quantum/mousekey.c index 99bfd6b96f..c2291fb397 100644 --- a/quantum/mousekey.c +++ b/quantum/mousekey.c @@ -486,3 +486,5 @@ static void mousekey_debug(void) {      print_dec(mousekey_accel);      print(")\n");  } + +report_mouse_t mousekey_get_report(void) { return mouse_report; } diff --git a/quantum/mousekey.h b/quantum/mousekey.h index 70dc4bb5c5..56c91b5f1b 100644 --- a/quantum/mousekey.h +++ b/quantum/mousekey.h @@ -168,11 +168,12 @@ extern uint8_t mk_time_to_max;  extern uint8_t mk_wheel_max_speed;  extern uint8_t mk_wheel_time_to_max; -void mousekey_task(void); -void mousekey_on(uint8_t code); -void mousekey_off(uint8_t code); -void mousekey_clear(void); -void mousekey_send(void); +void           mousekey_task(void); +void           mousekey_on(uint8_t code); +void           mousekey_off(uint8_t code); +void           mousekey_clear(void); +void           mousekey_send(void); +report_mouse_t mousekey_get_report(void);  #ifdef __cplusplus  } diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c index 167c0c03c9..b9fee1ca59 100644 --- a/quantum/process_keycode/process_rgb.c +++ b/quantum/process_keycode/process_rgb.c @@ -14,7 +14,6 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #include "process_rgb.h" -#include "rgb.h"  typedef void (*rgb_func_pointer)(void); diff --git a/quantum/quantum.c b/quantum/quantum.c index 8ccdb774bd..b4cfa28d7d 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -340,13 +340,13 @@ void set_single_persistent_default_layer(uint8_t default_layer) {  #if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS)      PLAY_SONG(default_layer_songs[default_layer]);  #endif -    eeconfig_update_default_layer(1U << default_layer); -    default_layer_set(1U << default_layer); +    eeconfig_update_default_layer((layer_state_t)1 << default_layer); +    default_layer_set((layer_state_t)1 << default_layer);  }  layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) { -    layer_state_t mask12 = (1UL << layer1) | (1UL << layer2); -    layer_state_t mask3  = 1UL << layer3; +    layer_state_t mask12 = ((layer_state_t)1 << layer1) | ((layer_state_t)1 << layer2); +    layer_state_t mask3  = (layer_state_t)1 << layer3;      return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);  } diff --git a/quantum/quantum.h b/quantum/quantum.h index e4a7c5723c..66ba96fde8 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -176,6 +176,10 @@ extern layer_state_t layer_state;  #    include "oled_driver.h"  #endif +#ifdef ST7565_ENABLE +#    include "st7565.h" +#endif +  #ifdef DIP_SWITCH_ENABLE  #    include "dip_switch.h"  #endif diff --git a/quantum/rgb_matrix_animations/alpha_mods_anim.h b/quantum/rgb_matrix/animations/alpha_mods_anim.h index 426d88ef35..426d88ef35 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 340bd93e5d..340bd93e5d 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 3df3cfda7d..3df3cfda7d 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 7d80074fd5..7d80074fd5 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 35b830af6b..35b830af6b 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 048157aa1b..048157aa1b 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 bff2da1616..bff2da1616 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 f1aaf1d067..f1aaf1d067 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 faf8598a39..faf8598a39 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 cf911eb937..cf911eb937 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 d66acd4b2b..d66acd4b2b 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 fe8396140f..fe8396140f 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 7799887099..7799887099 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 80cfb0dbc7..80cfb0dbc7 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 5016f739d6..5016f739d6 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 1de45f8e8d..1de45f8e8d 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 ce94871681..ce94871681 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 53dfd04e2c..53dfd04e2c 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 7e0d2898cf..7e0d2898cf 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 54dea958af..54dea958af 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 2d8d36174f..2d8d36174f 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 fd9026fc90..fd9026fc90 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 9493b38508..a17e954b1b 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)  static void jellybean_raindrops_set_color(int i, effect_params_t* params) {      if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) return; -    HSV hsv = {rand() & 0xFF, rand() & 0xFF, rgb_matrix_config.hsv.v}; +    HSV hsv = {rand() & 0xFF, qadd8(rand() & 0x7F, 0x80), rgb_matrix_config.hsv.v};      RGB rgb = rgb_matrix_hsv_to_rgb(hsv);      rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);  } diff --git a/quantum/rgb_matrix_animations/rainbow_beacon_anim.h b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h index 977261182f..977261182f 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 e51e7b2516..e51e7b2516 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 1cd4ed2acf..1cd4ed2acf 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 38359cdca7..38359cdca7 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 0000000000..302ad79c04 --- /dev/null +++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc @@ -0,0 +1,37 @@ +// Add your new core rgb matrix effect here, order determines enum order +#include "solid_color_anim.h" +#include "alpha_mods_anim.h" +#include "gradient_up_down_anim.h" +#include "gradient_left_right_anim.h" +#include "breathing_anim.h" +#include "colorband_sat_anim.h" +#include "colorband_val_anim.h" +#include "colorband_pinwheel_sat_anim.h" +#include "colorband_pinwheel_val_anim.h" +#include "colorband_spiral_sat_anim.h" +#include "colorband_spiral_val_anim.h" +#include "cycle_all_anim.h" +#include "cycle_left_right_anim.h" +#include "cycle_up_down_anim.h" +#include "rainbow_moving_chevron_anim.h" +#include "cycle_out_in_anim.h" +#include "cycle_out_in_dual_anim.h" +#include "cycle_pinwheel_anim.h" +#include "cycle_spiral_anim.h" +#include "dual_beacon_anim.h" +#include "rainbow_beacon_anim.h" +#include "rainbow_pinwheels_anim.h" +#include "raindrops_anim.h" +#include "jellybean_raindrops_anim.h" +#include "hue_breathing_anim.h" +#include "hue_pendulum_anim.h" +#include "hue_wave_anim.h" +#include "typing_heatmap_anim.h" +#include "digital_rain_anim.h" +#include "solid_reactive_simple_anim.h" +#include "solid_reactive_anim.h" +#include "solid_reactive_wide.h" +#include "solid_reactive_cross.h" +#include "solid_reactive_nexus.h" +#include "splash_anim.h" +#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 4867609c81..4867609c81 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 9545b418d9..9545b418d9 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 1881cd6c60..1881cd6c60 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 75b7c0df4e..75b7c0df4e 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 2e46ffb350..2e46ffb350 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 02351de51e..02351de51e 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 0000000000..c09022bb0f --- /dev/null +++ b/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc @@ -0,0 +1,6 @@ +#include "effect_runner_dx_dy_dist.h" +#include "effect_runner_dx_dy.h" +#include "effect_runner_i.h" +#include "effect_runner_sin_cos_i.h" +#include "effect_runner_reactive.h" +#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 79d63cf133..79d63cf133 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 d45bb961bc..d45bb961bc 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 f76c68e8c7..f76c68e8c7 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 17f94e3c18..17f94e3c18 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 12eb248cc0..12eb248cc0 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 1cc4dca728..1cc4dca728 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 99efb4996a..99efb4996a 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 1415bcc0fa..1415bcc0fa 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 e7dda11a2f..e7dda11a2f 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 ab8dbd849b..789cd28605 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};  const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER;  #endif +// clang-format off +#ifndef RGB_MATRIX_IMMEDIATE_EEPROM +#    define rgb_eeconfig_update(v) rgb_update_eeprom |= v +#else +#    define rgb_eeconfig_update(v) if (v) eeconfig_update_rgb_matrix() +#endif +// clang-format on +  __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); }  // Generic effect runners -#include "rgb_matrix_runners/effect_runner_dx_dy_dist.h" -#include "rgb_matrix_runners/effect_runner_dx_dy.h" -#include "rgb_matrix_runners/effect_runner_i.h" -#include "rgb_matrix_runners/effect_runner_sin_cos_i.h" -#include "rgb_matrix_runners/effect_runner_reactive.h" -#include "rgb_matrix_runners/effect_runner_reactive_splash.h" +#include "rgb_matrix_runners.inc"  // ------------------------------------------  // -----Begin rgb effect includes macros-----  #define RGB_MATRIX_EFFECT(name)  #define RGB_MATRIX_CUSTOM_EFFECT_IMPLS -#include "rgb_matrix_animations/rgb_matrix_effects.inc" +#include "rgb_matrix_effects.inc"  #ifdef RGB_MATRIX_CUSTOM_KB  #    include "rgb_matrix_kb.inc"  #endif @@ -67,10 +70,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv  #    define RGB_DISABLE_TIMEOUT 0  #endif -#if RGB_DISABLE_WHEN_USB_SUSPENDED != 1 -#    undef RGB_DISABLE_WHEN_USB_SUSPENDED -#endif -  #if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX  #    undef RGB_MATRIX_MAXIMUM_BRIGHTNESS  #    define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX @@ -129,6 +128,7 @@ last_hit_t g_last_hit_tracker;  // internals  static bool            suspend_state     = false; +static bool            rgb_update_eeprom = false;  static uint8_t         rgb_last_enable   = UINT8_MAX;  static uint8_t         rgb_last_effect   = UINT8_MAX;  static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; @@ -315,6 +315,8 @@ static void rgb_task_timers(void) {  static void rgb_task_sync(void) {      // next task +    if (rgb_update_eeprom) eeconfig_update_rgb_matrix(); +    rgb_update_eeprom = false;      if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;  } @@ -353,7 +355,7 @@ static void rgb_task_render(uint8_t effect) {      case RGB_MATRIX_##name:                   \          rendering = name(&rgb_effect_params); \          break; -#include "rgb_matrix_animations/rgb_matrix_effects.inc" +#include "rgb_matrix_effects.inc"  #undef RGB_MATRIX_EFFECT  #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; }  void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) {      rgb_matrix_config.enable ^= 1;      rgb_task_state = STARTING; -    if (write_to_eeprom) { -        eeconfig_update_rgb_matrix(); -    } +    rgb_eeconfig_update(write_to_eeprom);      dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable);  }  void 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); }  void rgb_matrix_enable(void) {      rgb_matrix_enable_noeeprom(); -    eeconfig_update_rgb_matrix(); +    rgb_eeconfig_update(true);  }  void rgb_matrix_enable_noeeprom(void) { @@ -531,7 +531,7 @@ void rgb_matrix_enable_noeeprom(void) {  void rgb_matrix_disable(void) {      rgb_matrix_disable_noeeprom(); -    eeconfig_update_rgb_matrix(); +    rgb_eeconfig_update(true);  }  void rgb_matrix_disable_noeeprom(void) { @@ -553,9 +553,7 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {          rgb_matrix_config.mode = mode;      }      rgb_task_state = STARTING; -    if (write_to_eeprom) { -        eeconfig_update_rgb_matrix(); -    } +    rgb_eeconfig_update(write_to_eeprom);      dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode);  }  void 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      rgb_matrix_config.hsv.h = hue;      rgb_matrix_config.hsv.s = sat;      rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val; -    if (write_to_eeprom) { -        eeconfig_update_rgb_matrix(); -    } +    rgb_eeconfig_update(write_to_eeprom);      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);  }  void 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); }  void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {      rgb_matrix_config.speed = speed; -    if (write_to_eeprom) { -        eeconfig_update_rgb_matrix(); -    } +    rgb_eeconfig_update(write_to_eeprom);      dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed);  }  void 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 a615b8422c..28f07c84d6 100644 --- a/quantum/rgb_matrix.h +++ b/quantum/rgb_matrix/rgb_matrix.h @@ -33,6 +33,8 @@  #    include "is31fl3737.h"  #elif defined(IS31FL3741)  #    include "is31fl3741.h" +#elif defined(AW20216) +#    include "aw20216.h"  #elif defined(WS2812)  #    include "ws2812.h"  #endif @@ -70,7 +72,7 @@ enum rgb_matrix_effects {  // --------------------------------------  // -----Begin rgb effect enum macros-----  #define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_##name, -#include "rgb_matrix_animations/rgb_matrix_effects.inc" +#include "rgb_matrix_effects.inc"  #undef RGB_MATRIX_EFFECT  #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 896fa6d0ef..6a11d4791e 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 = {  };  #    endif +#elif defined(AW20216) +#    include "spi_master.h" +static void init(void) { +    spi_init(); +    AW20216_init(); +} + +static void flush(void) { AW20216_update_pwm_buffers(); } + +const rgb_matrix_driver_t rgb_matrix_driver = { +    .init          = init, +    .flush         = flush, +    .set_color     = AW20216_set_color, +    .set_color_all = AW20216_set_color_all, +}; +  #elif defined(WS2812)  #    if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_CUSTOM_DRIVER)  #        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 df575d6577..df575d6577 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 053d441506..0000000000 --- a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc +++ /dev/null @@ -1,37 +0,0 @@ -// Add your new core rgb matrix effect here, order determins enum order, requires "rgb_matrix_animations/ directory -#include "rgb_matrix_animations/solid_color_anim.h" -#include "rgb_matrix_animations/alpha_mods_anim.h" -#include "rgb_matrix_animations/gradient_up_down_anim.h" -#include "rgb_matrix_animations/gradient_left_right_anim.h" -#include "rgb_matrix_animations/breathing_anim.h" -#include "rgb_matrix_animations/colorband_sat_anim.h" -#include "rgb_matrix_animations/colorband_val_anim.h" -#include "rgb_matrix_animations/colorband_pinwheel_sat_anim.h" -#include "rgb_matrix_animations/colorband_pinwheel_val_anim.h" -#include "rgb_matrix_animations/colorband_spiral_sat_anim.h" -#include "rgb_matrix_animations/colorband_spiral_val_anim.h" -#include "rgb_matrix_animations/cycle_all_anim.h" -#include "rgb_matrix_animations/cycle_left_right_anim.h" -#include "rgb_matrix_animations/cycle_up_down_anim.h" -#include "rgb_matrix_animations/rainbow_moving_chevron_anim.h" -#include "rgb_matrix_animations/cycle_out_in_anim.h" -#include "rgb_matrix_animations/cycle_out_in_dual_anim.h" -#include "rgb_matrix_animations/cycle_pinwheel_anim.h" -#include "rgb_matrix_animations/cycle_spiral_anim.h" -#include "rgb_matrix_animations/dual_beacon_anim.h" -#include "rgb_matrix_animations/rainbow_beacon_anim.h" -#include "rgb_matrix_animations/rainbow_pinwheels_anim.h" -#include "rgb_matrix_animations/raindrops_anim.h" -#include "rgb_matrix_animations/jellybean_raindrops_anim.h" -#include "rgb_matrix_animations/hue_breathing_anim.h" -#include "rgb_matrix_animations/hue_pendulum_anim.h" -#include "rgb_matrix_animations/hue_wave_anim.h" -#include "rgb_matrix_animations/typing_heatmap_anim.h" -#include "rgb_matrix_animations/digital_rain_anim.h" -#include "rgb_matrix_animations/solid_reactive_simple_anim.h" -#include "rgb_matrix_animations/solid_reactive_anim.h" -#include "rgb_matrix_animations/solid_reactive_wide.h" -#include "rgb_matrix_animations/solid_reactive_cross.h" -#include "rgb_matrix_animations/solid_reactive_nexus.h" -#include "rgb_matrix_animations/splash_anim.h" -#include "rgb_matrix_animations/solid_splash_anim.h" diff --git a/quantum/rgblight.c b/quantum/rgblight/rgblight.c index baa10ec416..54face173c 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) {          animation_status.restart = true;      }  #        endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ -#    endif /* RGBLIGHT_USE_TIMER */ +#    endif     /* RGBLIGHT_USE_TIMER */  }  #endif /* RGBLIGHT_SPLIT */ diff --git a/quantum/rgblight.h b/quantum/rgblight/rgblight.h index bec2c66955..bec2c66955 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 30245318b6..30245318b6 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 f29a646b66..0fd68b75f3 100644 --- a/quantum/rgblight_list.h +++ b/quantum/rgblight/rgblight_list.h @@ -15,49 +15,7 @@   */  #pragma once -/*              RGB COLORS             */ -#define RGB_WHITE 0xFF, 0xFF, 0xFF -#define RGB_RED 0xFF, 0x00, 0x00 -#define RGB_CORAL 0xFF, 0x7C, 0x4D -#define RGB_ORANGE 0xFF, 0x80, 0x00 -#define RGB_GOLDENROD 0xD9, 0xA5, 0x21 -#define RGB_GOLD 0xFF, 0xD9, 0x00 -#define RGB_YELLOW 0xFF, 0xFF, 0x00 -#define RGB_CHARTREUSE 0x80, 0xFF, 0x00 -#define RGB_GREEN 0x00, 0xFF, 0x00 -#define RGB_SPRINGGREEN 0x00, 0xFF, 0x80 -#define RGB_TURQUOISE 0x47, 0x6E, 0x6A -#define RGB_TEAL 0x00, 0x80, 0x80 -#define RGB_CYAN 0x00, 0xFF, 0xFF -#define RGB_AZURE 0x99, 0xf5, 0xFF -#define RGB_BLUE 0x00, 0x00, 0xFF -#define RGB_PURPLE 0x7A, 0x00, 0xFF -#define RGB_MAGENTA 0xFF, 0x00, 0xFF -#define RGB_PINK 0xFF, 0x80, 0xBF -#define RGB_BLACK 0x00, 0x00, 0x00 -#define RGB_OFF RGB_BLACK - -/*            HSV COLORS            */ -#define HSV_WHITE 0, 0, 255 -#define HSV_RED 0, 255, 255 -#define HSV_CORAL 11, 176, 255 -#define HSV_ORANGE 28, 255, 255 -#define HSV_GOLDENROD 30, 218, 218 -#define HSV_GOLD 36, 255, 255 -#define HSV_YELLOW 43, 255, 255 -#define HSV_CHARTREUSE 64, 255, 255 -#define HSV_GREEN 85, 255, 255 -#define HSV_SPRINGGREEN 106, 255, 255 -#define HSV_TURQUOISE 123, 90, 112 -#define HSV_TEAL 128, 255, 128 -#define HSV_CYAN 128, 255, 255 -#define HSV_AZURE 132, 102, 255 -#define HSV_BLUE 170, 255, 255 -#define HSV_PURPLE 191, 255, 255 -#define HSV_MAGENTA 213, 255, 255 -#define HSV_PINK 234, 128, 255 -#define HSV_BLACK 0, 0, 0 -#define HSV_OFF HSV_BLACK +#include "color.h"  /*  ######################################################################################## @@ -66,7 +24,7 @@  ##                                                                                    ##  ##  The functions below have been deprecated and may be removed in a future release.  ##  ##                                                                                    ## -##                Please use the values above with the RGB functions.                 ## +##              Please use the values in color.h with the RGB functions.              ##  ##                                                                                    ##  ##                                                                                    ##  ##                                                                                    ## diff --git a/quantum/rgblight_modes.h b/quantum/rgblight/rgblight_modes.h index 7abdb87bc6..7abdb87bc6 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 3c14cb6109..3c14cb6109 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 f77483ad8c..6363f8ff3b 100644 --- a/quantum/serial_link/system/serial_link.c +++ b/quantum/serial_link/system/serial_link.c @@ -29,10 +29,13 @@ SOFTWARE.  #include "serial_link/protocol/transport.h"  #include "serial_link/protocol/frame_router.h"  #include "matrix.h" +#include "sync_timer.h"  #include <stdbool.h>  #include "print.h"  #include "config.h" +#define SYNC_TIMER_OFFSET 2 +  static event_source_t new_data_event;  static bool           serial_link_connected;  static bool           is_master = false; @@ -159,10 +162,16 @@ static matrix_object_t last_matrix = {};  SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);  MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool); +#ifndef DISABLE_SYNC_TIMER +MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t); +#endif  static remote_object_t* remote_objects[] = {      REMOTE_OBJECT(serial_link_connected),      REMOTE_OBJECT(keyboard_matrix), +#ifndef DISABLE_SYNC_TIMER +    REMOTE_OBJECT(sync_timer), +#endif  };  void init_serial_link(void) { @@ -200,14 +209,27 @@ void serial_link_update(void) {              m->rows[i] = matrix.rows[i];          }          end_write_keyboard_matrix(); +          *begin_write_serial_link_connected() = true;          end_write_serial_link_connected(); + +#ifndef DISABLE_SYNC_TIMER +        *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET; +        end_write_sync_timer(); +#endif      }      matrix_object_t* m = read_keyboard_matrix(0);      if (m) {          matrix_set_remote(m->rows, 0);      } + +#ifndef DISABLE_SYNC_TIMER +    uint32_t* t = read_sync_timer(); +    if (t) { +        sync_timer_update(*t); +    } +#endif  }  void signal_data_written(void) { chEvtBroadcast(&new_data_event); } diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 039e7d9773..d8e078e9bb 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -16,23 +16,30 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */  #include <stdint.h>  #include <stdbool.h> +#include <string.h>  #include "util.h"  #include "matrix.h"  #include "debounce.h"  #include "quantum.h"  #include "split_util.h"  #include "config.h" -#include "transport.h" +#include "transactions.h" -#define ERROR_DISCONNECT_COUNT 5 +#ifndef ERROR_DISCONNECT_COUNT +#    define ERROR_DISCONNECT_COUNT 5 +#endif  // ERROR_DISCONNECT_COUNT  #define ROWS_PER_HAND (MATRIX_ROWS / 2)  #ifdef DIRECT_PINS  static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;  #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) +#    ifdef MATRIX_ROW_PINS  static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; +#    endif  // MATRIX_ROW_PINS +#    ifdef MATRIX_COL_PINS  static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +#    endif  // MATRIX_COL_PINS  #endif  /* matrix state(1:on, 0:off) */ @@ -45,6 +52,9 @@ uint8_t thisHand, thatHand;  // user-defined overridable functions  __attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }  __attribute__((weak)) void matrix_slave_scan_user(void) {} +__attribute__((weak)) void matrix_init_pins(void); +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); +__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);  static inline void setPinOutput_writeLow(pin_t pin) {      ATOMIC_BLOCK_FORCEON { @@ -57,11 +67,19 @@ static inline void setPinInputHigh_atomic(pin_t pin) {      ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }  } +static inline uint8_t readMatrixPin(pin_t pin) { +    if (pin != NO_PIN) { +        return readPin(pin); +    } else { +        return 1; +    } +} +  // matrix code  #ifdef DIRECT_PINS -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      for (int row = 0; row < MATRIX_ROWS; row++) {          for (int col = 0; col < MATRIX_COLS; col++) {              pin_t pin = direct_pins[row][col]; @@ -72,7 +90,7 @@ static void init_pins(void) {      }  } -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {      // Start with a clear matrix row      matrix_row_t current_row_value = 0; @@ -83,46 +101,57 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)          }      } -    // If the row has changed, store the row and return the changed flag. -    if (current_matrix[current_row] != current_row_value) { -        current_matrix[current_row] = current_row_value; -        return true; -    } -    return false; +    // Update the matrix +    current_matrix[current_row] = current_row_value;  }  #elif defined(DIODE_DIRECTION) -#    if (DIODE_DIRECTION == COL2ROW) +#    if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS) +#        if (DIODE_DIRECTION == COL2ROW) -static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } +static bool select_row(uint8_t row) { +    pin_t pin = row_pins[row]; +    if (pin != NO_PIN) { +        setPinOutput_writeLow(pin); +        return true; +    } +    return false; +} -static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); } +static void unselect_row(uint8_t row) { +    pin_t pin = row_pins[row]; +    if (pin != NO_PIN) { +        setPinInputHigh_atomic(pin); +    } +}  static void unselect_rows(void) {      for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { -        setPinInputHigh_atomic(row_pins[x]); +        unselect_row(x);      }  } -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      unselect_rows();      for (uint8_t x = 0; x < MATRIX_COLS; x++) { -        setPinInputHigh_atomic(col_pins[x]); +        if (col_pins[x] != NO_PIN) { +            setPinInputHigh_atomic(col_pins[x]); +        }      }  } -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {      // Start with a clear matrix row      matrix_row_t current_row_value = 0; -    // Select row -    select_row(current_row); +    if (!select_row(current_row)) {  // Select row +        return;                      // skip NO_PIN row +    }      matrix_output_select_delay();      // For each col...      for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { -        // Select the col pin to read (active low) -        uint8_t pin_state = readPin(col_pins[col_index]); +        uint8_t pin_state = readMatrixPin(col_pins[col_index]);          // Populate the matrix row with the state of the col pin          current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); @@ -132,72 +161,71 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)      unselect_row(current_row);      matrix_output_unselect_delay();  // wait for all Col signals to go HIGH -    // If the row has changed, store the row and return the changed flag. -    if (current_matrix[current_row] != current_row_value) { -        current_matrix[current_row] = current_row_value; +    // Update the matrix +    current_matrix[current_row] = current_row_value; +} + +#        elif (DIODE_DIRECTION == ROW2COL) + +static bool select_col(uint8_t col) { +    pin_t pin = col_pins[col]; +    if (pin != NO_PIN) { +        setPinOutput_writeLow(pin);          return true;      }      return false;  } -#    elif (DIODE_DIRECTION == ROW2COL) - -static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } - -static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); } +static void unselect_col(uint8_t col) { +    pin_t pin = col_pins[col]; +    if (pin != NO_PIN) { +        setPinInputHigh_atomic(pin); +    } +}  static void unselect_cols(void) {      for (uint8_t x = 0; x < MATRIX_COLS; x++) { -        setPinInputHigh_atomic(col_pins[x]); +        unselect_col(x);      }  } -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      unselect_cols();      for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { -        setPinInputHigh_atomic(row_pins[x]); +        if (row_pins[x] != NO_PIN) { +            setPinInputHigh_atomic(row_pins[x]); +        }      }  } -static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { -    bool matrix_changed = false; - +__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {      // Select col -    select_col(current_col); +    if (!select_col(current_col)) {  // select col +        return;                      // skip NO_PIN col +    }      matrix_output_select_delay();      // For each row...      for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { -        // Store last value of row prior to reading -        matrix_row_t last_row_value    = current_matrix[row_index]; -        matrix_row_t current_row_value = last_row_value; -          // Check row pin state -        if (readPin(row_pins[row_index]) == 0) { +        if (readMatrixPin(row_pins[row_index]) == 0) {              // Pin LO, set col bit -            current_row_value |= (MATRIX_ROW_SHIFTER << current_col); +            current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);          } else {              // Pin HI, clear col bit -            current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); -        } - -        // Determine if the matrix changed state -        if ((last_row_value != current_row_value)) { -            matrix_changed |= true; -            current_matrix[row_index] = current_row_value; +            current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);          }      }      // Unselect col      unselect_col(current_col);      matrix_output_unselect_delay();  // wait for all Row signals to go HIGH - -    return matrix_changed;  } -#    else -#        error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! -#    endif +#        else +#            error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! +#        endif +#    endif  // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)  #else  #    error DIODE_DIRECTION is not defined!  #endif @@ -233,7 +261,7 @@ void matrix_init(void) {      thatHand = ROWS_PER_HAND - thisHand;      // initialize key pins -    init_pins(); +    matrix_init_pins();      // initialize matrix state: all keys off      for (uint8_t i = 0; i < MATRIX_ROWS; i++) { @@ -288,20 +316,23 @@ bool matrix_post_scan(void) {  }  uint8_t matrix_scan(void) { -    bool local_changed = false; +    matrix_row_t curr_matrix[MATRIX_ROWS] = {0};  #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)      // Set row, read cols      for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { -        local_changed |= read_cols_on_row(raw_matrix, current_row); +        matrix_read_cols_on_row(curr_matrix, current_row);      }  #elif (DIODE_DIRECTION == ROW2COL)      // Set col, read rows      for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { -        local_changed |= read_rows_on_col(raw_matrix, current_col); +        matrix_read_rows_on_col(curr_matrix, current_col);      }  #endif +    bool local_changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0; +    if (local_changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix)); +      debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed);      bool remote_changed = matrix_post_scan(); diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h index 4ae1d52732..a4c0a1956b 100644 --- a/quantum/split_common/post_config.h +++ b/quantum/split_common/post_config.h @@ -7,13 +7,4 @@  #    ifndef F_SCL  #        define F_SCL 100000UL  // SCL frequency  #    endif - -#else  // use serial -// When using serial, the user must define RGBLIGHT_SPLIT explicitly -//  in config.h as needed. -//      see quantum/rgblight_post_config.h -#    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -// When using serial and RGBLIGHT_SPLIT need separate transaction -#        define SERIAL_USE_MULTI_TRANSACTION -#    endif  #endif diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 9e75e19ce0..989829d2dc 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) {  #if defined(SPLIT_HAND_PIN)      // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand      setPinInput(SPLIT_HAND_PIN); +#    ifdef SPLIT_HAND_PIN_LOW_IS_LEFT +    return !readPin(SPLIT_HAND_PIN); +#    else      return readPin(SPLIT_HAND_PIN); +#    endif  #elif defined(SPLIT_HAND_MATRIX_GRID)  #    ifdef SPLIT_HAND_MATRIX_GRID_LOW_IS_RIGHT      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 0000000000..464c73478a --- /dev/null +++ b/quantum/split_common/transaction_id_define.h @@ -0,0 +1,94 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +enum serial_transaction_id { +#ifdef USE_I2C +    I2C_EXECUTE_CALLBACK, +#endif  // USE_I2C + +    GET_SLAVE_MATRIX_CHECKSUM, +    GET_SLAVE_MATRIX_DATA, + +#ifdef SPLIT_TRANSPORT_MIRROR +    PUT_MASTER_MATRIX, +#endif  // SPLIT_TRANSPORT_MIRROR + +#ifdef ENCODER_ENABLE +    GET_ENCODERS_CHECKSUM, +    GET_ENCODERS_DATA, +#endif  // ENCODER_ENABLE + +#ifndef DISABLE_SYNC_TIMER +    PUT_SYNC_TIMER, +#endif  // DISABLE_SYNC_TIMER + +#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) +    PUT_LAYER_STATE, +    PUT_DEFAULT_LAYER_STATE, +#endif  // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +#ifdef SPLIT_LED_STATE_ENABLE +    PUT_LED_STATE, +#endif  // SPLIT_LED_STATE_ENABLE + +#ifdef SPLIT_MODS_ENABLE +    PUT_MODS, +#endif  // SPLIT_MODS_ENABLE + +#ifdef BACKLIGHT_ENABLE +    PUT_BACKLIGHT, +#endif  // BACKLIGHT_ENABLE + +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) +    PUT_RGBLIGHT, +#endif  // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    PUT_LED_MATRIX, +#endif  // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    PUT_RGB_MATRIX, +#endif  // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) +    PUT_WPM, +#endif  // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +    PUT_RPC_INFO, +    PUT_RPC_REQ_DATA, +    EXECUTE_RPC, +    GET_RPC_RESP_DATA, +#endif  // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + +// keyboard-specific +#ifdef SPLIT_TRANSACTION_IDS_KB +    SPLIT_TRANSACTION_IDS_KB, +#endif  // SPLIT_TRANSACTION_IDS_KB + +// user/keymap-specific +#ifdef SPLIT_TRANSACTION_IDS_USER +    SPLIT_TRANSACTION_IDS_USER, +#endif  // SPLIT_TRANSACTION_IDS_USER + +    NUM_TOTAL_TRANSACTIONS +}; + +// Ensure we only use 5 bits for transaction +_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 0000000000..abad626e00 --- /dev/null +++ b/quantum/split_common/transactions.c @@ -0,0 +1,655 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stddef.h> + +#include "crc.h" +#include "debug.h" +#include "matrix.h" +#include "quantum.h" +#include "transactions.h" +#include "transport.h" +#include "transaction_id_define.h" + +#define SYNC_TIMER_OFFSET 2 + +#ifndef FORCED_SYNC_THROTTLE_MS +#    define FORCED_SYNC_THROTTLE_MS 100 +#endif  // FORCED_SYNC_THROTTLE_MS + +#define sizeof_member(type, member) sizeof(((type *)NULL)->member) + +#define trans_initiator2target_initializer_cb(member, cb) \ +    { &dummy, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), 0, 0, cb } +#define trans_initiator2target_initializer(member) trans_initiator2target_initializer_cb(member, NULL) + +#define trans_target2initiator_initializer_cb(member, cb) \ +    { &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb } +#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL) + +#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0) +#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length) + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +// Forward-declare the RPC callback handlers +void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); +void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); +#endif  // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + +//////////////////////////////////////////////////// +// Helpers + +bool 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[])) { +    if (okay) { +        bool this_okay = true; +        for (int iter = 1; iter <= 10; ++iter) { +            if (!this_okay) { +                for (int i = 0; i < iter * iter; ++i) { +                    wait_us(10); +                } +            } +            ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix); }; +            if (this_okay) break; +        } +        okay &= this_okay; +        if (!okay) { +            dprintf("Failed to execute %s\n", prefix); +        } +    } +    return okay; +} + +#define TRANSACTION_HANDLER_MASTER(prefix)                                                                \ +    do {                                                                                                  \ +        okay &= transaction_handler_master(okay, master_matrix, slave_matrix, #prefix, &prefix##_master); \ +    } while (0) + +#define TRANSACTION_HANDLER_SLAVE(prefix)                                      \ +    do {                                                                       \ +        ATOMIC_BLOCK_FORCEON { prefix##_slave(master_matrix, slave_matrix); }; \ +    } while (0) + +inline 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) { +    uint8_t curr_checksum; +    bool    okay = transport_read(trans_id_checksum, &curr_checksum, sizeof(curr_checksum)); +    if (okay && (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || curr_checksum != crc8(equiv_shmem, length))) { +        okay &= transport_read(trans_id_retrieve, destination, length); +        okay &= curr_checksum == crc8(equiv_shmem, length); +        if (okay) { +            *last_update = timer_read32(); +        } +    } else { +        memcpy(destination, equiv_shmem, length); +    } +    return okay; +} + +inline static bool send_if_condition(int8_t trans_id, uint32_t *last_update, bool condition, void *source, size_t length) { +    bool okay = true; +    if (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || condition) { +        okay &= transport_write(trans_id, source, length); +        if (okay) { +            *last_update = timer_read32(); +        } +    } +    return okay; +} + +inline static bool send_if_data_mismatch(int8_t trans_id, uint32_t *last_update, void *source, const void *equiv_shmem, size_t length) { +    // Just run a memcmp to compare the source and equivalent shmem location +    return send_if_condition(trans_id, last_update, (memcmp(source, equiv_shmem, length) != 0), source, length); +} + +//////////////////////////////////////////////////// +// Slave matrix + +static bool slave_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t     last_update                    = 0; +    static matrix_row_t last_matrix[(MATRIX_ROWS) / 2] = {0};  // last successfully-read matrix, so we can replicate if there are checksum errors +    matrix_row_t        temp_matrix[(MATRIX_ROWS) / 2];        // holding area while we test whether or not checksum is correct + +    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)); +    if (okay) { +        // Checksum matches the received data, save as the last matrix state +        memcpy(last_matrix, temp_matrix, sizeof(temp_matrix)); +    } +    // Copy out the last-known-good matrix state to the slave matrix +    memcpy(slave_matrix, last_matrix, sizeof(last_matrix)); +    return okay; +} + +static void slave_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    memcpy(split_shmem->smatrix.matrix, slave_matrix, sizeof(split_shmem->smatrix.matrix)); +    split_shmem->smatrix.checksum = crc8(split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix)); +} + +// clang-format off +#define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix_handlers) +#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix_handlers) +#define TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS \ +    [GET_SLAVE_MATRIX_CHECKSUM] = trans_target2initiator_initializer(smatrix.checksum), \ +    [GET_SLAVE_MATRIX_DATA]     = trans_target2initiator_initializer(smatrix.matrix), +// clang-format on + +//////////////////////////////////////////////////// +// Master matrix + +#ifdef SPLIT_TRANSPORT_MIRROR + +static bool master_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t last_update = 0; +    return send_if_data_mismatch(PUT_MASTER_MATRIX, &last_update, master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix)); +} + +static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    // Always copy to the master matrix +    memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix)); +} + +#    define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix_handlers) +#    define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix_handlers) +#    define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix), + +#else  // SPLIT_TRANSPORT_MIRROR + +#    define TRANSACTIONS_MASTER_MATRIX_MASTER() +#    define TRANSACTIONS_MASTER_MATRIX_SLAVE() +#    define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS + +#endif  // SPLIT_TRANSPORT_MIRROR + +//////////////////////////////////////////////////// +// Encoders + +#ifdef ENCODER_ENABLE + +static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t last_update = 0; +    uint8_t         temp_state[NUMBER_OF_ENCODERS]; + +    bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, temp_state, split_shmem->encoders.state, sizeof(temp_state)); +    if (okay) encoder_update_raw(temp_state); +    return okay; +} + +static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    uint8_t encoder_state[NUMBER_OF_ENCODERS]; +    encoder_state_raw(encoder_state); +    // Always prepare the encoder state for read. +    memcpy(split_shmem->encoders.state, encoder_state, sizeof(encoder_state)); +    // Now update the checksum given that the encoders has been written to +    split_shmem->encoders.checksum = crc8(encoder_state, sizeof(encoder_state)); +} + +// clang-format off +#    define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder_handlers) +#    define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder_handlers) +#    define TRANSACTIONS_ENCODERS_REGISTRATIONS \ +    [GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \ +    [GET_ENCODERS_DATA]     = trans_target2initiator_initializer(encoders.state), +// clang-format on + +#else  // ENCODER_ENABLE + +#    define TRANSACTIONS_ENCODERS_MASTER() +#    define TRANSACTIONS_ENCODERS_SLAVE() +#    define TRANSACTIONS_ENCODERS_REGISTRATIONS + +#endif  // ENCODER_ENABLE + +//////////////////////////////////////////////////// +// Sync timer + +#ifndef DISABLE_SYNC_TIMER + +static bool sync_timer_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t last_update = 0; + +    bool okay = true; +    if (timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS) { +        uint32_t sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; +        okay &= transport_write(PUT_SYNC_TIMER, &sync_timer, sizeof(sync_timer)); +        if (okay) { +            last_update = timer_read32(); +        } +    } +    return okay; +} + +static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t last_sync_timer = 0; +    if (last_sync_timer != split_shmem->sync_timer) { +        last_sync_timer = split_shmem->sync_timer; +        sync_timer_update(last_sync_timer); +    } +} + +#    define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer_handlers) +#    define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer_handlers) +#    define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer), + +#else  // DISABLE_SYNC_TIMER + +#    define TRANSACTIONS_SYNC_TIMER_MASTER() +#    define TRANSACTIONS_SYNC_TIMER_SLAVE() +#    define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS + +#endif  // DISABLE_SYNC_TIMER + +//////////////////////////////////////////////////// +// Layer state + +#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +static bool layer_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t last_layer_state_update         = 0; +    static uint32_t last_default_layer_state_update = 0; + +    bool okay = send_if_condition(PUT_LAYER_STATE, &last_layer_state_update, (layer_state != split_shmem->layers.layer_state), &layer_state, sizeof(layer_state)); +    if (okay) { +        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)); +    } +    return okay; +} + +static void layer_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    layer_state         = split_shmem->layers.layer_state; +    default_layer_state = split_shmem->layers.default_layer_state; +} + +// clang-format off +#    define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state_handlers) +#    define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state_handlers) +#    define TRANSACTIONS_LAYER_STATE_REGISTRATIONS \ +    [PUT_LAYER_STATE]         = trans_initiator2target_initializer(layers.layer_state), \ +    [PUT_DEFAULT_LAYER_STATE] = trans_initiator2target_initializer(layers.default_layer_state), +// clang-format on + +#else  // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +#    define TRANSACTIONS_LAYER_STATE_MASTER() +#    define TRANSACTIONS_LAYER_STATE_SLAVE() +#    define TRANSACTIONS_LAYER_STATE_REGISTRATIONS + +#endif  // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +//////////////////////////////////////////////////// +// LED state + +#ifdef SPLIT_LED_STATE_ENABLE + +static bool led_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t last_update = 0; +    uint8_t         led_state   = host_keyboard_leds(); +    return send_if_data_mismatch(PUT_LED_STATE, &last_update, &led_state, &split_shmem->led_state, sizeof(led_state)); +} + +static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    void set_split_host_keyboard_leds(uint8_t led_state); +    set_split_host_keyboard_leds(split_shmem->led_state); +} + +#    define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state_handlers) +#    define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state_handlers) +#    define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state), + +#else  // SPLIT_LED_STATE_ENABLE + +#    define TRANSACTIONS_LED_STATE_MASTER() +#    define TRANSACTIONS_LED_STATE_SLAVE() +#    define TRANSACTIONS_LED_STATE_REGISTRATIONS + +#endif  // SPLIT_LED_STATE_ENABLE + +//////////////////////////////////////////////////// +// Mods + +#ifdef SPLIT_MODS_ENABLE + +static bool mods_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t   last_update    = 0; +    bool              mods_need_sync = timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS; +    split_mods_sync_t new_mods; +    new_mods.real_mods = get_mods(); +    if (!mods_need_sync && new_mods.real_mods != split_shmem->mods.real_mods) { +        mods_need_sync = true; +    } + +    new_mods.weak_mods = get_weak_mods(); +    if (!mods_need_sync && new_mods.weak_mods != split_shmem->mods.weak_mods) { +        mods_need_sync = true; +    } + +#    ifndef NO_ACTION_ONESHOT +    new_mods.oneshot_mods = get_oneshot_mods(); +    if (!mods_need_sync && new_mods.oneshot_mods != split_shmem->mods.oneshot_mods) { +        mods_need_sync = true; +    } +#    endif  // NO_ACTION_ONESHOT + +    bool okay = true; +    if (mods_need_sync) { +        okay &= transport_write(PUT_MODS, &new_mods, sizeof(new_mods)); +        if (okay) { +            last_update = timer_read32(); +        } +    } + +    return okay; +} + +static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    set_mods(split_shmem->mods.real_mods); +    set_weak_mods(split_shmem->mods.weak_mods); +#    ifndef NO_ACTION_ONESHOT +    set_oneshot_mods(split_shmem->mods.oneshot_mods); +#    endif +} + +#    define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods_handlers) +#    define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods_handlers) +#    define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods), + +#else  // SPLIT_MODS_ENABLE + +#    define TRANSACTIONS_MODS_MASTER() +#    define TRANSACTIONS_MODS_SLAVE() +#    define TRANSACTIONS_MODS_REGISTRATIONS + +#endif  // SPLIT_MODS_ENABLE + +//////////////////////////////////////////////////// +// Backlight + +#ifdef BACKLIGHT_ENABLE + +static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t last_update = 0; +    uint8_t         level       = is_backlight_enabled() ? get_backlight_level() : 0; +    return send_if_condition(PUT_BACKLIGHT, &last_update, (level != split_shmem->backlight_level), &level, sizeof(level)); +} + +static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); } + +#    define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight_handlers) +#    define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight_handlers) +#    define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level), + +#else  // BACKLIGHT_ENABLE + +#    define TRANSACTIONS_BACKLIGHT_MASTER() +#    define TRANSACTIONS_BACKLIGHT_SLAVE() +#    define TRANSACTIONS_BACKLIGHT_REGISTRATIONS + +#endif  // BACKLIGHT_ENABLE + +//////////////////////////////////////////////////// +// RGBLIGHT + +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +static bool rgblight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t     last_update = 0; +    rgblight_syncinfo_t rgblight_sync; +    rgblight_get_syncinfo(&rgblight_sync); +    if (send_if_condition(PUT_RGBLIGHT, &last_update, (rgblight_sync.status.change_flags != 0), &rgblight_sync, sizeof(rgblight_sync))) { +        rgblight_clear_change_flags(); +    } else { +        return false; +    } +    return true; +} + +static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    // Update the RGB with the new data +    if (split_shmem->rgblight_sync.status.change_flags != 0) { +        rgblight_update_sync(&split_shmem->rgblight_sync, false); +        split_shmem->rgblight_sync.status.change_flags = 0; +    } +} + +#    define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight_handlers) +#    define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight_handlers) +#    define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync), + +#else  // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +#    define TRANSACTIONS_RGBLIGHT_MASTER() +#    define TRANSACTIONS_RGBLIGHT_SLAVE() +#    define TRANSACTIONS_RGBLIGHT_REGISTRATIONS + +#endif  // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +//////////////////////////////////////////////////// +// LED Matrix + +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +static bool led_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t   last_update = 0; +    led_matrix_sync_t led_matrix_sync; +    memcpy(&led_matrix_sync.led_matrix, &led_matrix_eeconfig, sizeof(led_eeconfig_t)); +    led_matrix_sync.led_suspend_state = led_matrix_get_suspend_state(); +    return send_if_data_mismatch(PUT_LED_MATRIX, &last_update, &led_matrix_sync, &split_shmem->led_matrix_sync, sizeof(led_matrix_sync)); +} + +static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    memcpy(&led_matrix_eeconfig, &split_shmem->led_matrix_sync.led_matrix, sizeof(led_eeconfig_t)); +    led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state); +} + +#    define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix_handlers) +#    define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix_handlers) +#    define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync), + +#else  // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +#    define TRANSACTIONS_LED_MATRIX_MASTER() +#    define TRANSACTIONS_LED_MATRIX_SLAVE() +#    define TRANSACTIONS_LED_MATRIX_REGISTRATIONS + +#endif  // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +//////////////////////////////////////////////////// +// RGB Matrix + +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +static bool rgb_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t   last_update = 0; +    rgb_matrix_sync_t rgb_matrix_sync; +    memcpy(&rgb_matrix_sync.rgb_matrix, &rgb_matrix_config, sizeof(rgb_config_t)); +    rgb_matrix_sync.rgb_suspend_state = rgb_matrix_get_suspend_state(); +    return send_if_data_mismatch(PUT_RGB_MATRIX, &last_update, &rgb_matrix_sync, &split_shmem->rgb_matrix_sync, sizeof(rgb_matrix_sync)); +} + +static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    memcpy(&rgb_matrix_config, &split_shmem->rgb_matrix_sync.rgb_matrix, sizeof(rgb_config_t)); +    rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state); +} + +#    define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix_handlers) +#    define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix_handlers) +#    define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync), + +#else  // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +#    define TRANSACTIONS_RGB_MATRIX_MASTER() +#    define TRANSACTIONS_RGB_MATRIX_SLAVE() +#    define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS + +#endif  // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +//////////////////////////////////////////////////// +// WPM + +#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    static uint32_t last_update = 0; +    uint8_t         current_wpm = get_current_wpm(); +    return send_if_condition(PUT_WPM, &last_update, (current_wpm != split_shmem->current_wpm), ¤t_wpm, sizeof(current_wpm)); +} + +static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); } + +#    define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm_handlers) +#    define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm_handlers) +#    define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm), + +#else  // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +#    define TRANSACTIONS_WPM_MASTER() +#    define TRANSACTIONS_WPM_SLAVE() +#    define TRANSACTIONS_WPM_REGISTRATIONS + +#endif  // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +//////////////////////////////////////////////////// + +uint8_t                  dummy; +split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { +    // Set defaults +    [0 ...(NUM_TOTAL_TRANSACTIONS - 1)] = {NULL, 0, 0, 0, 0, 0}, + +#ifdef USE_I2C +    [I2C_EXECUTE_CALLBACK] = trans_initiator2target_initializer(transaction_id), +#endif  // USE_I2C + +    // clang-format off +    TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS +    TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS +    TRANSACTIONS_ENCODERS_REGISTRATIONS +    TRANSACTIONS_SYNC_TIMER_REGISTRATIONS +    TRANSACTIONS_LAYER_STATE_REGISTRATIONS +    TRANSACTIONS_LED_STATE_REGISTRATIONS +    TRANSACTIONS_MODS_REGISTRATIONS +    TRANSACTIONS_BACKLIGHT_REGISTRATIONS +    TRANSACTIONS_RGBLIGHT_REGISTRATIONS +    TRANSACTIONS_LED_MATRIX_REGISTRATIONS +    TRANSACTIONS_RGB_MATRIX_REGISTRATIONS +    TRANSACTIONS_WPM_REGISTRATIONS +// clang-format on + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +        [PUT_RPC_INFO]  = trans_initiator2target_initializer_cb(rpc_info, slave_rpc_info_callback), +    [PUT_RPC_REQ_DATA]  = trans_initiator2target_initializer(rpc_m2s_buffer), +    [EXECUTE_RPC]       = trans_initiator2target_initializer_cb(rpc_info.transaction_id, slave_rpc_exec_callback), +    [GET_RPC_RESP_DATA] = trans_target2initiator_initializer(rpc_s2m_buffer), +#endif  // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +}; + +bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    bool okay = true; +    TRANSACTIONS_SLAVE_MATRIX_MASTER(); +    TRANSACTIONS_MASTER_MATRIX_MASTER(); +    TRANSACTIONS_ENCODERS_MASTER(); +    TRANSACTIONS_SYNC_TIMER_MASTER(); +    TRANSACTIONS_LAYER_STATE_MASTER(); +    TRANSACTIONS_LED_STATE_MASTER(); +    TRANSACTIONS_MODS_MASTER(); +    TRANSACTIONS_BACKLIGHT_MASTER(); +    TRANSACTIONS_RGBLIGHT_MASTER(); +    TRANSACTIONS_LED_MATRIX_MASTER(); +    TRANSACTIONS_RGB_MATRIX_MASTER(); +    TRANSACTIONS_WPM_MASTER(); +    return okay; +} + +void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { +    TRANSACTIONS_SLAVE_MATRIX_SLAVE(); +    TRANSACTIONS_MASTER_MATRIX_SLAVE(); +    TRANSACTIONS_ENCODERS_SLAVE(); +    TRANSACTIONS_SYNC_TIMER_SLAVE(); +    TRANSACTIONS_LAYER_STATE_SLAVE(); +    TRANSACTIONS_LED_STATE_SLAVE(); +    TRANSACTIONS_MODS_SLAVE(); +    TRANSACTIONS_BACKLIGHT_SLAVE(); +    TRANSACTIONS_RGBLIGHT_SLAVE(); +    TRANSACTIONS_LED_MATRIX_SLAVE(); +    TRANSACTIONS_RGB_MATRIX_SLAVE(); +    TRANSACTIONS_WPM_SLAVE(); +} + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + +void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback) { +    // Prevent invoking RPC on QMK core sync data +    if (transaction_id <= GET_RPC_RESP_DATA) return; + +    // Set the callback +    split_transaction_table[transaction_id].slave_callback          = callback; +    split_transaction_table[transaction_id].initiator2target_offset = offsetof(split_shared_memory_t, rpc_m2s_buffer); +    split_transaction_table[transaction_id].target2initiator_offset = offsetof(split_shared_memory_t, rpc_s2m_buffer); +} + +bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { +    // Prevent invoking RPC on QMK core sync data +    if (transaction_id <= GET_RPC_RESP_DATA) return false; +    // Prevent sizing issues +    if (initiator2target_buffer_size > RPC_M2S_BUFFER_SIZE) return false; +    if (target2initiator_buffer_size > RPC_S2M_BUFFER_SIZE) return false; + +    // Prepare the metadata block +    rpc_sync_info_t info = {.transaction_id = transaction_id, .m2s_length = initiator2target_buffer_size, .s2m_length = target2initiator_buffer_size}; + +    // Make sure the local side knows that we're not sending the full block of data +    split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size  = initiator2target_buffer_size; +    split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = target2initiator_buffer_size; + +    // Run through the sequence: +    // * set the transaction ID and lengths +    // * send the request data +    // * execute RPC callback +    // * retrieve the response data +    if (!transport_write(PUT_RPC_INFO, &info, sizeof(info))) { +        return false; +    } +    if (!transport_write(PUT_RPC_REQ_DATA, initiator2target_buffer, initiator2target_buffer_size)) { +        return false; +    } +    if (!transport_write(EXECUTE_RPC, &transaction_id, sizeof(transaction_id))) { +        return false; +    } +    if (!transport_read(GET_RPC_RESP_DATA, target2initiator_buffer, target2initiator_buffer_size)) { +        return false; +    } +    return true; +} + +void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { +    // The RPC info block contains the intended transaction ID, as well as the sizes for both inbound and outbound data. +    // Ignore the args -- the `split_shmem` already has the info, we just need to act upon it. +    // We must keep the `split_transaction_table` non-const, so that it is able to be modified at runtime. + +    split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size  = split_shmem->rpc_info.m2s_length; +    split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = split_shmem->rpc_info.s2m_length; +} + +void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { +    // We can assume that the buffer lengths are correctly set, now, given that sequentially the rpc_info callback was already executed. +    // Go through the rpc_info and execute _that_ transaction's callback, with the scratch buffers as inputs. +    int8_t transaction_id = split_shmem->rpc_info.transaction_id; +    if (transaction_id < NUM_TOTAL_TRANSACTIONS) { +        split_transaction_desc_t *trans = &split_transaction_table[transaction_id]; +        if (trans->slave_callback) { +            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); +        } +    } +} + +#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 0000000000..4306ba1d87 --- /dev/null +++ b/quantum/split_common/transactions.h @@ -0,0 +1,54 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "stdint.h" +#include "stdbool.h" + +#include "matrix.h" +#include "transaction_id_define.h" +#include "transport.h" + +typedef void (*slave_callback_t)(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); + +// Split transaction Descriptor +typedef struct _split_transaction_desc_t { +    uint8_t *        status; +    uint8_t          initiator2target_buffer_size; +    uint16_t         initiator2target_offset; +    uint8_t          target2initiator_buffer_size; +    uint16_t         target2initiator_offset; +    slave_callback_t slave_callback; +} split_transaction_desc_t; + +// Forward declaration for the split transactions +extern split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS]; + +#define split_shmem_offset_ptr(offset) ((void *)(((uint8_t *)split_shmem) + (offset))) +#define split_trans_initiator2target_buffer(trans) (split_shmem_offset_ptr((trans)->initiator2target_offset)) +#define split_trans_target2initiator_buffer(trans) (split_shmem_offset_ptr((trans)->target2initiator_offset)) + +// returns false if valid data not received from slave +bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); +void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); + +void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback); + +bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); + +#define transaction_rpc_send(transaction_id, initiator2target_buffer_size, initiator2target_buffer) transaction_rpc_exec(transaction_id, initiator2target_buffer_size, initiator2target_buffer, 0, NULL) +#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 9ed0f7591b..a711ef85f0 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -1,452 +1,118 @@ -#include <string.h> -#include <stddef.h> - -#include "config.h" -#include "matrix.h" -#include "quantum.h" - -#define ROWS_PER_HAND (MATRIX_ROWS / 2) -#define SYNC_TIMER_OFFSET 2 - -#ifdef RGBLIGHT_ENABLE -#    include "rgblight.h" -#endif - -#ifdef BACKLIGHT_ENABLE -#    include "backlight.h" -#endif - -#ifdef ENCODER_ENABLE -#    include "encoder.h" -static pin_t encoders_pad[] = ENCODERS_PAD_A; -#    define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) -#endif - -#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) -#    include "led_matrix.h" -#endif -#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) -#    include "rgb_matrix.h" -#endif - -#if defined(USE_I2C) +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ -#    include "i2c_master.h" -#    include "i2c_slave.h" - -typedef struct _I2C_slave_buffer_t { -#    ifndef DISABLE_SYNC_TIMER -    uint32_t sync_timer; -#    endif -#    ifdef SPLIT_TRANSPORT_MIRROR -    matrix_row_t mmatrix[ROWS_PER_HAND]; -#    endif -    matrix_row_t smatrix[ROWS_PER_HAND]; -#    ifdef SPLIT_MODS_ENABLE -    uint8_t real_mods; -    uint8_t weak_mods; -#        ifndef NO_ACTION_ONESHOT -    uint8_t oneshot_mods; -#        endif -#    endif -#    ifdef BACKLIGHT_ENABLE -    uint8_t backlight_level; -#    endif -#    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -    rgblight_syncinfo_t rgblight_sync; -#    endif -#    ifdef ENCODER_ENABLE -    uint8_t encoder_state[NUMBER_OF_ENCODERS]; -#    endif -#    ifdef WPM_ENABLE -    uint8_t current_wpm; -#    endif -#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) -    led_eeconfig_t led_matrix; -    bool           led_suspend_state; -#    endif -#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) -    rgb_config_t rgb_matrix; -    bool         rgb_suspend_state; -#    endif -} I2C_slave_buffer_t; +#include <string.h> +#include <debug.h> -static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; +#include "transactions.h" +#include "transport.h" +#include "transaction_id_define.h" +#include "atomic_util.h" -#    define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer) -#    define I2C_KEYMAP_MASTER_START offsetof(I2C_slave_buffer_t, mmatrix) -#    define I2C_KEYMAP_SLAVE_START offsetof(I2C_slave_buffer_t, smatrix) -#    define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods) -#    define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods) -#    define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods) -#    define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) -#    define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) -#    define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) -#    define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) -#    define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix) -#    define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state) -#    define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix) -#    define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state) +#ifdef USE_I2C -#    define TIMEOUT 100 +#    ifndef SLAVE_I2C_TIMEOUT +#        define SLAVE_I2C_TIMEOUT 100 +#    endif  // SLAVE_I2C_TIMEOUT  #    ifndef SLAVE_I2C_ADDRESS  #        define SLAVE_I2C_ADDRESS 0x32  #    endif -// Get rows from other half over i2c -bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { -    i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_SLAVE_START, (void *)slave_matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); -#    ifdef SPLIT_TRANSPORT_MIRROR -    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_MASTER_START, (void *)master_matrix, sizeof(i2c_buffer->mmatrix), TIMEOUT); -#    endif +#    include "i2c_master.h" +#    include "i2c_slave.h" -    // write backlight info -#    ifdef BACKLIGHT_ENABLE -    uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; -    if (level != i2c_buffer->backlight_level) { -        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { -            i2c_buffer->backlight_level = level; -        } -    } -#    endif +// Ensure the I2C buffer has enough space +_Static_assert(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT"); -#    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -    if (rgblight_get_change_flags()) { -        rgblight_syncinfo_t rgblight_sync; -        rgblight_get_syncinfo(&rgblight_sync); -        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) { -            rgblight_clear_change_flags(); -        } -    } -#    endif +split_shared_memory_t *const split_shmem = (split_shared_memory_t *)i2c_slave_reg; -#    ifdef ENCODER_ENABLE -    i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT); -    encoder_update_raw(i2c_buffer->encoder_state); -#    endif +void transport_master_init(void) { i2c_init(); } +void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } -#    ifdef WPM_ENABLE -    uint8_t current_wpm = get_current_wpm(); -    if (current_wpm != i2c_buffer->current_wpm) { -        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)¤t_wpm, sizeof(current_wpm), TIMEOUT) >= 0) { -            i2c_buffer->current_wpm = current_wpm; -        } +i2c_status_t transport_trigger_callback(int8_t id) { +    // If there's no callback, indicate that we were successful +    if (!split_transaction_table[id].slave_callback) { +        return I2C_STATUS_SUCCESS;      } -#    endif -#    ifdef SPLIT_MODS_ENABLE -    uint8_t real_mods = get_mods(); -    if (real_mods != i2c_buffer->real_mods) { -        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) { -            i2c_buffer->real_mods = real_mods; +    // Kick off the "callback executor", now that data has been written to the slave +    split_shmem->transaction_id     = id; +    split_transaction_desc_t *trans = &split_transaction_table[I2C_EXECUTE_CALLBACK]; +    return i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, SLAVE_I2C_TIMEOUT); +} + +bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) { +    i2c_status_t              status; +    split_transaction_desc_t *trans = &split_transaction_table[id]; +    if (initiator2target_length > 0) { +        size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length; +        memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len); +        if ((status = i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { +            return false;          }      } -    uint8_t weak_mods = get_weak_mods(); -    if (weak_mods != i2c_buffer->weak_mods) { -        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) { -            i2c_buffer->weak_mods = weak_mods; -        } +    // If we need to execute a callback on the slave, do so +    if ((status = transport_trigger_callback(id)) < 0) { +        return false;      } -#        ifndef NO_ACTION_ONESHOT -    uint8_t oneshot_mods = get_oneshot_mods(); -    if (oneshot_mods != i2c_buffer->oneshot_mods) { -        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) { -            i2c_buffer->oneshot_mods = oneshot_mods; +    if (target2initiator_length > 0) { +        size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length; +        if ((status = i2c_readReg(SLAVE_I2C_ADDRESS, trans->target2initiator_offset, split_trans_target2initiator_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { +            return false;          } +        memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len);      } -#        endif -#    endif -#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) -    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT); -    bool suspend_state = led_matrix_get_suspend_state(); -    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT); -#    endif -#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) -    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT); -    bool suspend_state = rgb_matrix_get_suspend_state(); -    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT); -#    endif - -#    ifndef DISABLE_SYNC_TIMER -    i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; -    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); -#    endif      return true;  } -void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { -#    ifndef DISABLE_SYNC_TIMER -    sync_timer_update(i2c_buffer->sync_timer); -#    endif -    // Copy matrix to I2C buffer -    memcpy((void *)i2c_buffer->smatrix, (void *)slave_matrix, sizeof(i2c_buffer->smatrix)); -#    ifdef SPLIT_TRANSPORT_MIRROR -    memcpy((void *)master_matrix, (void *)i2c_buffer->mmatrix, sizeof(i2c_buffer->mmatrix)); -#    endif - -// Read Backlight Info -#    ifdef BACKLIGHT_ENABLE -    backlight_set(i2c_buffer->backlight_level); -#    endif - -#    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -    // Update the RGB with the new data -    if (i2c_buffer->rgblight_sync.status.change_flags != 0) { -        rgblight_update_sync(&i2c_buffer->rgblight_sync, false); -        i2c_buffer->rgblight_sync.status.change_flags = 0; -    } -#    endif - -#    ifdef ENCODER_ENABLE -    encoder_state_raw(i2c_buffer->encoder_state); -#    endif - -#    ifdef WPM_ENABLE -    set_current_wpm(i2c_buffer->current_wpm); -#    endif - -#    ifdef SPLIT_MODS_ENABLE -    set_mods(i2c_buffer->real_mods); -    set_weak_mods(i2c_buffer->weak_mods); -#        ifndef NO_ACTION_ONESHOT -    set_oneshot_mods(i2c_buffer->oneshot_mods); -#        endif -#    endif - -#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) -    memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix)); -    led_matrix_set_suspend_state(i2c_buffer->led_suspend_state); -#    endif -#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) -    memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix)); -    rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state); -#    endif -} - -void transport_master_init(void) { i2c_init(); } - -void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } - -#else  // USE_SERIAL +#else  // USE_I2C  #    include "serial.h" -typedef struct _Serial_s2m_buffer_t { -    // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack -    matrix_row_t smatrix[ROWS_PER_HAND]; - -#    ifdef ENCODER_ENABLE -    uint8_t encoder_state[NUMBER_OF_ENCODERS]; -#    endif - -} Serial_s2m_buffer_t; - -typedef struct _Serial_m2s_buffer_t { -#    ifdef SPLIT_MODS_ENABLE -    uint8_t real_mods; -    uint8_t weak_mods; -#        ifndef NO_ACTION_ONESHOT -    uint8_t oneshot_mods; -#        endif -#    endif -#    ifndef DISABLE_SYNC_TIMER -    uint32_t sync_timer; -#    endif -#    ifdef SPLIT_TRANSPORT_MIRROR -    matrix_row_t mmatrix[ROWS_PER_HAND]; -#    endif -#    ifdef BACKLIGHT_ENABLE -    uint8_t backlight_level; -#    endif -#    ifdef WPM_ENABLE -    uint8_t current_wpm; -#    endif -#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) -    led_eeconfig_t led_matrix; -    bool           led_suspend_state; -#    endif -#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) -    rgb_config_t rgb_matrix; -    bool         rgb_suspend_state; -#    endif -} Serial_m2s_buffer_t; - -#    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -// When MCUs on both sides drive their respective RGB LED chains, -// it is necessary to synchronize, so it is necessary to communicate RGB -// information. In that case, define RGBLIGHT_SPLIT with info on the number -// of LEDs on each half. -// -// Otherwise, if the master side MCU drives both sides RGB LED chains, -// there is no need to communicate. - -typedef struct _Serial_rgblight_t { -    rgblight_syncinfo_t rgblight_sync; -} Serial_rgblight_t; +static split_shared_memory_t shared_memory; +split_shared_memory_t *const split_shmem = &shared_memory; -volatile Serial_rgblight_t serial_rgblight = {}; -uint8_t volatile status_rgblight           = 0; -#    endif - -volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; -volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; -uint8_t volatile status0                       = 0; - -enum serial_transaction_id { -    GET_SLAVE_MATRIX = 0, -#    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -    PUT_RGBLIGHT, -#    endif -}; - -SSTD_t transactions[] = { -    [GET_SLAVE_MATRIX] = -        { -            (uint8_t *)&status0, -            sizeof(serial_m2s_buffer), -            (uint8_t *)&serial_m2s_buffer, -            sizeof(serial_s2m_buffer), -            (uint8_t *)&serial_s2m_buffer, -        }, -#    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) -    [PUT_RGBLIGHT] = -        { -            (uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL  // no slave to master transfer -        }, -#    endif -}; - -void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } - -void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } +void transport_master_init(void) { soft_serial_initiator_init(); } +void transport_slave_init(void) { soft_serial_target_init(); } -#    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - -// rgblight synchronization information communication. - -void transport_rgblight_master(void) { -    if (rgblight_get_change_flags()) { -        rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync); -        if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) { -            rgblight_clear_change_flags(); -        } -    } -} - -void transport_rgblight_slave(void) { -    if (status_rgblight == TRANSACTION_ACCEPTED) { -        rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false); -        status_rgblight = TRANSACTION_END; +bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) { +    split_transaction_desc_t *trans = &split_transaction_table[id]; +    if (initiator2target_length > 0) { +        size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length; +        memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len);      } -} -#    else -#        define transport_rgblight_master() -#        define transport_rgblight_slave() -#    endif - -bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { -#    ifndef SERIAL_USE_MULTI_TRANSACTION -    if (soft_serial_transaction() != TRANSACTION_END) { -        return false; -    } -#    else -    transport_rgblight_master(); -    if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) { +    if (soft_serial_transaction(id) != TRANSACTION_END) {          return false;      } -#    endif -    // TODO:  if MATRIX_COLS > 8 change to unpack() -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        slave_matrix[i] = serial_s2m_buffer.smatrix[i]; -#    ifdef SPLIT_TRANSPORT_MIRROR -        serial_m2s_buffer.mmatrix[i] = master_matrix[i]; -#    endif +    if (target2initiator_length > 0) { +        size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length; +        memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len);      } -#    ifdef BACKLIGHT_ENABLE -    // Write backlight level for slave to read -    serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0; -#    endif - -#    ifdef ENCODER_ENABLE -    encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state); -#    endif - -#    ifdef WPM_ENABLE -    // Write wpm to slave -    serial_m2s_buffer.current_wpm = get_current_wpm(); -#    endif - -#    ifdef SPLIT_MODS_ENABLE -    serial_m2s_buffer.real_mods = get_mods(); -    serial_m2s_buffer.weak_mods = get_weak_mods(); -#        ifndef NO_ACTION_ONESHOT -    serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); -#        endif -#    endif - -#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) -    serial_m2s_buffer.led_matrix        = led_matrix_eeconfig; -    serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state(); -#    endif -#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) -    serial_m2s_buffer.rgb_matrix        = rgb_matrix_config; -    serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state(); -#    endif - -#    ifndef DISABLE_SYNC_TIMER -    serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; -#    endif      return true;  } -void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { -    transport_rgblight_slave(); -#    ifndef DISABLE_SYNC_TIMER -    sync_timer_update(serial_m2s_buffer.sync_timer); -#    endif - -    // TODO: if MATRIX_COLS > 8 change to pack() -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        serial_s2m_buffer.smatrix[i] = slave_matrix[i]; -#    ifdef SPLIT_TRANSPORT_MIRROR -        master_matrix[i] = serial_m2s_buffer.mmatrix[i]; -#    endif -    } -#    ifdef BACKLIGHT_ENABLE -    backlight_set(serial_m2s_buffer.backlight_level); -#    endif - -#    ifdef ENCODER_ENABLE -    encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state); -#    endif +#endif  // USE_I2C -#    ifdef WPM_ENABLE -    set_current_wpm(serial_m2s_buffer.current_wpm); -#    endif - -#    ifdef SPLIT_MODS_ENABLE -    set_mods(serial_m2s_buffer.real_mods); -    set_weak_mods(serial_m2s_buffer.weak_mods); -#        ifndef NO_ACTION_ONESHOT -    set_oneshot_mods(serial_m2s_buffer.oneshot_mods); -#        endif -#    endif - -#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) -    led_matrix_eeconfig = serial_m2s_buffer.led_matrix; -    led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state); -#    endif -#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) -    rgb_matrix_config = serial_m2s_buffer.rgb_matrix; -    rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state); -#    endif -} +bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { return transactions_master(master_matrix, slave_matrix); } -#endif +void 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 a9f66301bf..2e07f6b25c 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h @@ -1,10 +1,175 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +  #pragma once +#include "stdint.h" +#include "stdbool.h" + +#include "progmem.h" +#include "action_layer.h"  #include "matrix.h" +#ifndef RPC_M2S_BUFFER_SIZE +#    define RPC_M2S_BUFFER_SIZE 32 +#endif  // RPC_M2S_BUFFER_SIZE + +#ifndef RPC_S2M_BUFFER_SIZE +#    define RPC_S2M_BUFFER_SIZE 32 +#endif  // RPC_S2M_BUFFER_SIZE +  void transport_master_init(void);  void transport_slave_init(void);  // returns false if valid data not received from slave  bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);  void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); + +bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length); + +#ifdef ENCODER_ENABLE +#    include "encoder.h" +#    define NUMBER_OF_ENCODERS (sizeof((pin_t[])ENCODERS_PAD_A) / sizeof(pin_t)) +#endif  // ENCODER_ENABLE + +#ifdef BACKLIGHT_ENABLE +#    include "backlight.h" +#endif  // BACKLIGHT_ENABLE + +#ifdef RGBLIGHT_ENABLE +#    include "rgblight.h" +#endif  // RGBLIGHT_ENABLE + +typedef struct _split_slave_matrix_sync_t { +    uint8_t      checksum; +    matrix_row_t matrix[(MATRIX_ROWS) / 2]; +} split_slave_matrix_sync_t; + +#ifdef SPLIT_TRANSPORT_MIRROR +typedef struct _split_master_matrix_sync_t { +    matrix_row_t matrix[(MATRIX_ROWS) / 2]; +} split_master_matrix_sync_t; +#endif  // SPLIT_TRANSPORT_MIRROR + +#ifdef ENCODER_ENABLE +typedef struct _split_slave_encoder_sync_t { +    uint8_t checksum; +    uint8_t state[NUMBER_OF_ENCODERS]; +} split_slave_encoder_sync_t; +#endif  // ENCODER_ENABLE + +#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) +typedef struct _split_layers_sync_t { +    layer_state_t layer_state; +    layer_state_t default_layer_state; +} split_layers_sync_t; +#endif  // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +#    include "led_matrix.h" + +typedef struct _led_matrix_sync_t { +    led_eeconfig_t led_matrix; +    bool           led_suspend_state; +} led_matrix_sync_t; +#endif  // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +#    include "rgb_matrix.h" + +typedef struct _rgb_matrix_sync_t { +    rgb_config_t rgb_matrix; +    bool         rgb_suspend_state; +} rgb_matrix_sync_t; +#endif  // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +#ifdef SPLIT_MODS_ENABLE +typedef struct _split_mods_sync_t { +    uint8_t real_mods; +    uint8_t weak_mods; +#    ifndef NO_ACTION_ONESHOT +    uint8_t oneshot_mods; +#    endif  // NO_ACTION_ONESHOT +} split_mods_sync_t; +#endif  // SPLIT_MODS_ENABLE + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +typedef struct _rpc_sync_info_t { +    int8_t  transaction_id; +    uint8_t m2s_length; +    uint8_t s2m_length; +} rpc_sync_info_t; +#endif  // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) + +typedef struct _split_shared_memory_t { +#ifdef USE_I2C +    int8_t transaction_id; +#endif  // USE_I2C + +    split_slave_matrix_sync_t smatrix; + +#ifdef SPLIT_TRANSPORT_MIRROR +    split_master_matrix_sync_t mmatrix; +#endif  // SPLIT_TRANSPORT_MIRROR + +#ifdef ENCODER_ENABLE +    split_slave_encoder_sync_t encoders; +#endif  // ENCODER_ENABLE + +#ifndef DISABLE_SYNC_TIMER +    uint32_t sync_timer; +#endif  // DISABLE_SYNC_TIMER + +#if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) +    split_layers_sync_t layers; +#endif  // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) + +#ifdef SPLIT_LED_STATE_ENABLE +    uint8_t led_state; +#endif  // SPLIT_LED_STATE_ENABLE + +#ifdef SPLIT_MODS_ENABLE +    split_mods_sync_t mods; +#endif  // SPLIT_MODS_ENABLE + +#ifdef BACKLIGHT_ENABLE +    uint8_t backlight_level; +#endif  // BACKLIGHT_ENABLE + +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) +    rgblight_syncinfo_t rgblight_sync; +#endif  // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    led_matrix_sync_t led_matrix_sync; +#endif  // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) + +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    rgb_matrix_sync_t rgb_matrix_sync; +#endif  // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) + +#if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) +    uint8_t current_wpm; +#endif  // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) + +#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +    rpc_sync_info_t rpc_info; +    uint8_t         rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE]; +    uint8_t         rpc_s2m_buffer[RPC_S2M_BUFFER_SIZE]; +#endif  // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) +} split_shared_memory_t; + +extern split_shared_memory_t *const split_shmem;
\ No newline at end of file | 
