diff options
Diffstat (limited to 'quantum')
| -rw-r--r-- | quantum/crc.c | 59 | ||||
| -rw-r--r-- | quantum/crc.h | 44 | ||||
| -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/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 | 79 | ||||
| -rw-r--r-- | quantum/mcu_selection.mk | 40 | ||||
| -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/serial_link/system/serial_link.c | 22 | ||||
| -rw-r--r-- | quantum/split_common/matrix.c | 83 | ||||
| -rw-r--r-- | quantum/split_common/post_config.h | 9 | ||||
| -rw-r--r-- | quantum/split_common/transaction_id_define.h | 94 | ||||
| -rw-r--r-- | quantum/split_common/transactions.c | 670 | ||||
| -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 |
108 files changed, 3469 insertions, 764 deletions
diff --git a/quantum/crc.c b/quantum/crc.c new file mode 100644 index 000000000..0d8b9d601 --- /dev/null +++ b/quantum/crc.c | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "crc.h" | ||
| 18 | |||
| 19 | __attribute__((weak)) void crc_init(void){ | ||
| 20 | /* Software implementation nothing todo here. */ | ||
| 21 | }; | ||
| 22 | |||
| 23 | #if defined(CRC8_USE_TABLE) | ||
| 24 | /** | ||
| 25 | * Static table used for the table_driven implementation. | ||
| 26 | */ | ||
| 27 | 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, | ||
| 28 | 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3}; | ||
| 29 | |||
| 30 | __attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) { | ||
| 31 | const uint8_t *d = (const uint8_t *)data; | ||
| 32 | crc_t crc = 0xff; | ||
| 33 | size_t tbl_idx; | ||
| 34 | |||
| 35 | while (data_len--) { | ||
| 36 | tbl_idx = crc ^ *d; | ||
| 37 | crc = crc_table[tbl_idx] & 0xff; | ||
| 38 | d++; | ||
| 39 | } | ||
| 40 | return crc & 0xff; | ||
| 41 | } | ||
| 42 | #else | ||
| 43 | __attribute__((weak)) uint8_t crc8(const void *data, size_t data_len) { | ||
| 44 | const uint8_t *d = (const uint8_t *)data; | ||
| 45 | crc_t crc = 0xff; | ||
| 46 | size_t i, j; | ||
| 47 | |||
| 48 | for (i = 0; i < data_len; i++) { | ||
| 49 | crc ^= d[i]; | ||
| 50 | for (j = 0; j < 8; j++) { | ||
| 51 | if ((crc & 0x80) != 0) | ||
| 52 | crc = (crc_t)((crc << 1) ^ 0x31); | ||
| 53 | else | ||
| 54 | crc <<= 1; | ||
| 55 | } | ||
| 56 | } | ||
| 57 | return crc; | ||
| 58 | } | ||
| 59 | #endif \ No newline at end of file | ||
diff --git a/quantum/crc.h b/quantum/crc.h new file mode 100644 index 000000000..c17f5888e --- /dev/null +++ b/quantum/crc.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #pragma once | ||
| 18 | |||
| 19 | #include "quantum.h" | ||
| 20 | |||
| 21 | /** | ||
| 22 | * The type of the CRC values. | ||
| 23 | * | ||
| 24 | * This type must be big enough to contain at least 8 bits. | ||
| 25 | */ | ||
| 26 | #if defined(CRC8_OPTIMIZE_SPEED) | ||
| 27 | typedef uint_fast8_t crc_t; | ||
| 28 | #else | ||
| 29 | typedef uint_least8_t crc_t; | ||
| 30 | #endif | ||
| 31 | |||
| 32 | /** | ||
| 33 | * Initialize crc subsystem. | ||
| 34 | */ | ||
| 35 | __attribute__((weak)) void crc_init(void); | ||
| 36 | |||
| 37 | /** | ||
| 38 | * Generate CRC8 value from given data. | ||
| 39 | * | ||
| 40 | * \param[in] data Pointer to a buffer of \a data_len bytes. | ||
| 41 | * \param[in] data_len Number of bytes in the \a data buffer. | ||
| 42 | * \return The calculated crc value. | ||
| 43 | */ | ||
| 44 | __attribute__((weak)) uint8_t crc8(const void *data, size_t data_len); \ No newline at end of file | ||
diff --git a/quantum/debounce.h b/quantum/debounce.h index 9ca05c682..504386828 100644 --- a/quantum/debounce.h +++ b/quantum/debounce.h | |||
| @@ -9,3 +9,5 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool | |||
| 9 | bool debounce_active(void); | 9 | bool debounce_active(void); |
| 10 | 10 | ||
| 11 | void debounce_init(uint8_t num_rows); | 11 | void debounce_init(uint8_t num_rows); |
| 12 | |||
| 13 | 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 000000000..24380dc5e --- /dev/null +++ b/quantum/debounce/asym_eager_defer_pk.c | |||
| @@ -0,0 +1,171 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2017 Alex Ong <the.onga@gmail.com> | ||
| 3 | * Copyright 2020 Andrei Purdea <andrei@purdea.ro> | ||
| 4 | * Copyright 2021 Simon Arlott | ||
| 5 | * | ||
| 6 | * This program is free software: you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation, either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* | ||
| 21 | Basic symmetric per-key algorithm. Uses an 8-bit counter per key. | ||
| 22 | When no state changes have occured for DEBOUNCE milliseconds, we push the state. | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include "matrix.h" | ||
| 26 | #include "timer.h" | ||
| 27 | #include "quantum.h" | ||
| 28 | #include <stdlib.h> | ||
| 29 | |||
| 30 | #ifdef PROTOCOL_CHIBIOS | ||
| 31 | # if CH_CFG_USE_MEMCORE == FALSE | ||
| 32 | # error ChibiOS is configured without a memory allocator. Your keyboard may have set `#define CH_CFG_USE_MEMCORE FALSE`, which is incompatible with this debounce algorithm. | ||
| 33 | # endif | ||
| 34 | #endif | ||
| 35 | |||
| 36 | #ifndef DEBOUNCE | ||
| 37 | # define DEBOUNCE 5 | ||
| 38 | #endif | ||
| 39 | |||
| 40 | // Maximum debounce: 127ms | ||
| 41 | #if DEBOUNCE > 127 | ||
| 42 | # undef DEBOUNCE | ||
| 43 | # define DEBOUNCE 127 | ||
| 44 | #endif | ||
| 45 | |||
| 46 | #define ROW_SHIFTER ((matrix_row_t)1) | ||
| 47 | |||
| 48 | typedef struct { | ||
| 49 | bool pressed : 1; | ||
| 50 | uint8_t time : 7; | ||
| 51 | } debounce_counter_t; | ||
| 52 | |||
| 53 | #if DEBOUNCE > 0 | ||
| 54 | static debounce_counter_t *debounce_counters; | ||
| 55 | static fast_timer_t last_time; | ||
| 56 | static bool counters_need_update; | ||
| 57 | static bool matrix_need_update; | ||
| 58 | |||
| 59 | #define DEBOUNCE_ELAPSED 0 | ||
| 60 | |||
| 61 | 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); | ||
| 62 | static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); | ||
| 63 | |||
| 64 | // we use num_rows rather than MATRIX_ROWS to support split keyboards | ||
| 65 | void debounce_init(uint8_t num_rows) { | ||
| 66 | debounce_counters = malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t)); | ||
| 67 | int i = 0; | ||
| 68 | for (uint8_t r = 0; r < num_rows; r++) { | ||
| 69 | for (uint8_t c = 0; c < MATRIX_COLS; c++) { | ||
| 70 | debounce_counters[i++].time = DEBOUNCE_ELAPSED; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | void debounce_free(void) { | ||
| 76 | free(debounce_counters); | ||
| 77 | debounce_counters = NULL; | ||
| 78 | } | ||
| 79 | |||
| 80 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | ||
| 81 | bool updated_last = false; | ||
| 82 | |||
| 83 | if (counters_need_update) { | ||
| 84 | fast_timer_t now = timer_read_fast(); | ||
| 85 | fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); | ||
| 86 | |||
| 87 | last_time = now; | ||
| 88 | updated_last = true; | ||
| 89 | if (elapsed_time > UINT8_MAX) { | ||
| 90 | elapsed_time = UINT8_MAX; | ||
| 91 | } | ||
| 92 | |||
| 93 | if (elapsed_time > 0) { | ||
| 94 | update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | if (changed || matrix_need_update) { | ||
| 99 | if (!updated_last) { | ||
| 100 | last_time = timer_read_fast(); | ||
| 101 | } | ||
| 102 | |||
| 103 | transfer_matrix_values(raw, cooked, num_rows); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | 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) { | ||
| 108 | debounce_counter_t *debounce_pointer = debounce_counters; | ||
| 109 | |||
| 110 | counters_need_update = false; | ||
| 111 | matrix_need_update = false; | ||
| 112 | |||
| 113 | for (uint8_t row = 0; row < num_rows; row++) { | ||
| 114 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { | ||
| 115 | matrix_row_t col_mask = (ROW_SHIFTER << col); | ||
| 116 | |||
| 117 | if (debounce_pointer->time != DEBOUNCE_ELAPSED) { | ||
| 118 | if (debounce_pointer->time <= elapsed_time) { | ||
| 119 | debounce_pointer->time = DEBOUNCE_ELAPSED; | ||
| 120 | |||
| 121 | if (debounce_pointer->pressed) { | ||
| 122 | // key-down: eager | ||
| 123 | matrix_need_update = true; | ||
| 124 | } else { | ||
| 125 | // key-up: defer | ||
| 126 | cooked[row] = (cooked[row] & ~col_mask) | (raw[row] & col_mask); | ||
| 127 | } | ||
| 128 | } else { | ||
| 129 | debounce_pointer->time -= elapsed_time; | ||
| 130 | counters_need_update = true; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | debounce_pointer++; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { | ||
| 139 | debounce_counter_t *debounce_pointer = debounce_counters; | ||
| 140 | |||
| 141 | for (uint8_t row = 0; row < num_rows; row++) { | ||
| 142 | matrix_row_t delta = raw[row] ^ cooked[row]; | ||
| 143 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { | ||
| 144 | matrix_row_t col_mask = (ROW_SHIFTER << col); | ||
| 145 | |||
| 146 | if (delta & col_mask) { | ||
| 147 | if (debounce_pointer->time == DEBOUNCE_ELAPSED) { | ||
| 148 | debounce_pointer->pressed = (raw[row] & col_mask); | ||
| 149 | debounce_pointer->time = DEBOUNCE; | ||
| 150 | counters_need_update = true; | ||
| 151 | |||
| 152 | if (debounce_pointer->pressed) { | ||
| 153 | // key-down: eager | ||
| 154 | cooked[row] ^= col_mask; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | } else if (debounce_pointer->time != DEBOUNCE_ELAPSED) { | ||
| 158 | if (!debounce_pointer->pressed) { | ||
| 159 | // key-up: defer | ||
| 160 | debounce_pointer->time = DEBOUNCE_ELAPSED; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | debounce_pointer++; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | bool debounce_active(void) { return true; } | ||
| 169 | #else | ||
| 170 | # include "none.c" | ||
| 171 | #endif | ||
diff --git a/quantum/debounce/none.c b/quantum/debounce/none.c new file mode 100644 index 000000000..b03892bc5 --- /dev/null +++ b/quantum/debounce/none.c | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | /* Copyright 2021 Simon Arlott | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "matrix.h" | ||
| 18 | #include "quantum.h" | ||
| 19 | #include <stdlib.h> | ||
| 20 | |||
| 21 | void debounce_init(uint8_t num_rows) {} | ||
| 22 | |||
| 23 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | ||
| 24 | for (int i = 0; i < num_rows; i++) { | ||
| 25 | cooked[i] = raw[i]; | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | bool debounce_active(void) { return false; } | ||
| 30 | |||
| 31 | void debounce_free(void) {} | ||
diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c index 3ed9055d2..fbefd55ed 100644 --- a/quantum/debounce/sym_defer_g.c +++ b/quantum/debounce/sym_defer_g.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | Copyright 2017 Alex Ong<the.onga@gmail.com> | 2 | Copyright 2017 Alex Ong<the.onga@gmail.com> |
| 3 | Copyright 2021 Simon Arlott | ||
| 3 | This program is free software: you can redistribute it and/or modify | 4 | This program is free software: you can redistribute it and/or modify |
| 4 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
| 5 | the Free Software Foundation, either version 2 of the License, or | 6 | 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. | |||
| 23 | # define DEBOUNCE 5 | 24 | # define DEBOUNCE 5 |
| 24 | #endif | 25 | #endif |
| 25 | 26 | ||
| 26 | void debounce_init(uint8_t num_rows) {} | 27 | #if DEBOUNCE > 0 |
| 27 | static bool debouncing = false; | 28 | static bool debouncing = false; |
| 29 | static fast_timer_t debouncing_time; | ||
| 28 | 30 | ||
| 29 | #if DEBOUNCE > 0 | 31 | void debounce_init(uint8_t num_rows) {} |
| 30 | static uint16_t debouncing_time; | 32 | |
| 31 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | 33 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { |
| 32 | if (changed) { | 34 | if (changed) { |
| 33 | debouncing = true; | 35 | debouncing = true; |
| 34 | debouncing_time = timer_read(); | 36 | debouncing_time = timer_read_fast(); |
| 35 | } | 37 | } |
| 36 | 38 | ||
| 37 | if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { | 39 | if (debouncing && timer_elapsed_fast(debouncing_time) >= DEBOUNCE) { |
| 38 | for (int i = 0; i < num_rows; i++) { | 40 | for (int i = 0; i < num_rows; i++) { |
| 39 | cooked[i] = raw[i]; | 41 | cooked[i] = raw[i]; |
| 40 | } | 42 | } |
| 41 | debouncing = false; | 43 | debouncing = false; |
| 42 | } | 44 | } |
| 43 | } | 45 | } |
| 44 | #else // no debouncing. | ||
| 45 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | ||
| 46 | for (int i = 0; i < num_rows; i++) { | ||
| 47 | cooked[i] = raw[i]; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | #endif | ||
| 51 | 46 | ||
| 52 | bool debounce_active(void) { return debouncing; } | 47 | bool debounce_active(void) { return debouncing; } |
| 48 | |||
| 49 | void debounce_free(void) {} | ||
| 50 | #else // no debouncing. | ||
| 51 | # include "none.c" | ||
| 52 | #endif | ||
diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c index 60513f98e..626a9be84 100644 --- a/quantum/debounce/sym_defer_pk.c +++ b/quantum/debounce/sym_defer_pk.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | Copyright 2017 Alex Ong<the.onga@gmail.com> | 2 | Copyright 2017 Alex Ong<the.onga@gmail.com> |
| 3 | Copyright 2020 Andrei Purdea<andrei@purdea.ro> | 3 | Copyright 2020 Andrei Purdea<andrei@purdea.ro> |
| 4 | Copyright 2021 Simon Arlott | ||
| 4 | This program is free software: you can redistribute it and/or modify | 5 | This program is free software: you can redistribute it and/or modify |
| 5 | it under the terms of the GNU General Public License as published by | 6 | it under the terms of the GNU General Public License as published by |
| 6 | the Free Software Foundation, either version 2 of the License, or | 7 | 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. | |||
| 33 | # define DEBOUNCE 5 | 34 | # define DEBOUNCE 5 |
| 34 | #endif | 35 | #endif |
| 35 | 36 | ||
| 37 | // Maximum debounce: 255ms | ||
| 38 | #if DEBOUNCE > UINT8_MAX | ||
| 39 | # undef DEBOUNCE | ||
| 40 | # define DEBOUNCE UINT8_MAX | ||
| 41 | #endif | ||
| 42 | |||
| 36 | #define ROW_SHIFTER ((matrix_row_t)1) | 43 | #define ROW_SHIFTER ((matrix_row_t)1) |
| 37 | 44 | ||
| 38 | #define debounce_counter_t uint8_t | 45 | typedef uint8_t debounce_counter_t; |
| 39 | 46 | ||
| 47 | #if DEBOUNCE > 0 | ||
| 40 | static debounce_counter_t *debounce_counters; | 48 | static debounce_counter_t *debounce_counters; |
| 49 | static fast_timer_t last_time; | ||
| 41 | static bool counters_need_update; | 50 | static bool counters_need_update; |
| 42 | 51 | ||
| 43 | #define DEBOUNCE_ELAPSED 251 | 52 | #define DEBOUNCE_ELAPSED 0 |
| 44 | #define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) | ||
| 45 | |||
| 46 | static uint8_t wrapping_timer_read(void) { | ||
| 47 | static uint16_t time = 0; | ||
| 48 | static uint8_t last_result = 0; | ||
| 49 | uint16_t new_time = timer_read(); | ||
| 50 | uint16_t diff = new_time - time; | ||
| 51 | time = new_time; | ||
| 52 | last_result = (last_result + diff) % (MAX_DEBOUNCE + 1); | ||
| 53 | return last_result; | ||
| 54 | } | ||
| 55 | 53 | ||
| 56 | void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); | 54 | 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); |
| 57 | void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); | 55 | static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); |
| 58 | 56 | ||
| 59 | // we use num_rows rather than MATRIX_ROWS to support split keyboards | 57 | // we use num_rows rather than MATRIX_ROWS to support split keyboards |
| 60 | void debounce_init(uint8_t num_rows) { | 58 | void debounce_init(uint8_t num_rows) { |
| @@ -67,27 +65,49 @@ void debounce_init(uint8_t num_rows) { | |||
| 67 | } | 65 | } |
| 68 | } | 66 | } |
| 69 | 67 | ||
| 68 | void debounce_free(void) { | ||
| 69 | free(debounce_counters); | ||
| 70 | debounce_counters = NULL; | ||
| 71 | } | ||
| 72 | |||
| 70 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | 73 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { |
| 71 | uint8_t current_time = wrapping_timer_read(); | 74 | bool updated_last = false; |
| 75 | |||
| 72 | if (counters_need_update) { | 76 | if (counters_need_update) { |
| 73 | update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, current_time); | 77 | fast_timer_t now = timer_read_fast(); |
| 78 | fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); | ||
| 79 | |||
| 80 | last_time = now; | ||
| 81 | updated_last = true; | ||
| 82 | if (elapsed_time > UINT8_MAX) { | ||
| 83 | elapsed_time = UINT8_MAX; | ||
| 84 | } | ||
| 85 | |||
| 86 | if (elapsed_time > 0) { | ||
| 87 | update_debounce_counters_and_transfer_if_expired(raw, cooked, num_rows, elapsed_time); | ||
| 88 | } | ||
| 74 | } | 89 | } |
| 75 | 90 | ||
| 76 | if (changed) { | 91 | if (changed) { |
| 77 | start_debounce_counters(raw, cooked, num_rows, current_time); | 92 | if (!updated_last) { |
| 93 | last_time = timer_read_fast(); | ||
| 94 | } | ||
| 95 | |||
| 96 | start_debounce_counters(raw, cooked, num_rows); | ||
| 78 | } | 97 | } |
| 79 | } | 98 | } |
| 80 | 99 | ||
| 81 | void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { | 100 | 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) { |
| 82 | counters_need_update = false; | 101 | counters_need_update = false; |
| 83 | debounce_counter_t *debounce_pointer = debounce_counters; | 102 | debounce_counter_t *debounce_pointer = debounce_counters; |
| 84 | for (uint8_t row = 0; row < num_rows; row++) { | 103 | for (uint8_t row = 0; row < num_rows; row++) { |
| 85 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { | 104 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { |
| 86 | if (*debounce_pointer != DEBOUNCE_ELAPSED) { | 105 | if (*debounce_pointer != DEBOUNCE_ELAPSED) { |
| 87 | if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { | 106 | if (*debounce_pointer <= elapsed_time) { |
| 88 | *debounce_pointer = DEBOUNCE_ELAPSED; | 107 | *debounce_pointer = DEBOUNCE_ELAPSED; |
| 89 | cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col)); | 108 | cooked[row] = (cooked[row] & ~(ROW_SHIFTER << col)) | (raw[row] & (ROW_SHIFTER << col)); |
| 90 | } else { | 109 | } else { |
| 110 | *debounce_pointer -= elapsed_time; | ||
| 91 | counters_need_update = true; | 111 | counters_need_update = true; |
| 92 | } | 112 | } |
| 93 | } | 113 | } |
| @@ -96,14 +116,14 @@ void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix | |||
| 96 | } | 116 | } |
| 97 | } | 117 | } |
| 98 | 118 | ||
| 99 | void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { | 119 | static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { |
| 100 | debounce_counter_t *debounce_pointer = debounce_counters; | 120 | debounce_counter_t *debounce_pointer = debounce_counters; |
| 101 | for (uint8_t row = 0; row < num_rows; row++) { | 121 | for (uint8_t row = 0; row < num_rows; row++) { |
| 102 | matrix_row_t delta = raw[row] ^ cooked[row]; | 122 | matrix_row_t delta = raw[row] ^ cooked[row]; |
| 103 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { | 123 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { |
| 104 | if (delta & (ROW_SHIFTER << col)) { | 124 | if (delta & (ROW_SHIFTER << col)) { |
| 105 | if (*debounce_pointer == DEBOUNCE_ELAPSED) { | 125 | if (*debounce_pointer == DEBOUNCE_ELAPSED) { |
| 106 | *debounce_pointer = current_time; | 126 | *debounce_pointer = DEBOUNCE; |
| 107 | counters_need_update = true; | 127 | counters_need_update = true; |
| 108 | } | 128 | } |
| 109 | } else { | 129 | } else { |
| @@ -115,3 +135,6 @@ void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t | |||
| 115 | } | 135 | } |
| 116 | 136 | ||
| 117 | bool debounce_active(void) { return true; } | 137 | bool debounce_active(void) { return true; } |
| 138 | #else | ||
| 139 | # include "none.c" | ||
| 140 | #endif | ||
diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c index e66cf92d7..15a3242e6 100644 --- a/quantum/debounce/sym_eager_pk.c +++ b/quantum/debounce/sym_eager_pk.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | Copyright 2017 Alex Ong<the.onga@gmail.com> | 2 | Copyright 2017 Alex Ong<the.onga@gmail.com> |
| 3 | Copyright 2021 Simon Arlott | ||
| 3 | This program is free software: you can redistribute it and/or modify | 4 | This program is free software: you can redistribute it and/or modify |
| 4 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
| 5 | the Free Software Foundation, either version 2 of the License, or | 6 | 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. | |||
| 33 | # define DEBOUNCE 5 | 34 | # define DEBOUNCE 5 |
| 34 | #endif | 35 | #endif |
| 35 | 36 | ||
| 37 | // Maximum debounce: 255ms | ||
| 38 | #if DEBOUNCE > UINT8_MAX | ||
| 39 | # undef DEBOUNCE | ||
| 40 | # define DEBOUNCE UINT8_MAX | ||
| 41 | #endif | ||
| 42 | |||
| 36 | #define ROW_SHIFTER ((matrix_row_t)1) | 43 | #define ROW_SHIFTER ((matrix_row_t)1) |
| 37 | 44 | ||
| 38 | #define debounce_counter_t uint8_t | 45 | typedef uint8_t debounce_counter_t; |
| 39 | 46 | ||
| 47 | #if DEBOUNCE > 0 | ||
| 40 | static debounce_counter_t *debounce_counters; | 48 | static debounce_counter_t *debounce_counters; |
| 49 | static fast_timer_t last_time; | ||
| 41 | static bool counters_need_update; | 50 | static bool counters_need_update; |
| 42 | static bool matrix_need_update; | 51 | static bool matrix_need_update; |
| 43 | 52 | ||
| 44 | #define DEBOUNCE_ELAPSED 251 | 53 | #define DEBOUNCE_ELAPSED 0 |
| 45 | #define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) | ||
| 46 | |||
| 47 | static uint8_t wrapping_timer_read(void) { | ||
| 48 | static uint16_t time = 0; | ||
| 49 | static uint8_t last_result = 0; | ||
| 50 | uint16_t new_time = timer_read(); | ||
| 51 | uint16_t diff = new_time - time; | ||
| 52 | time = new_time; | ||
| 53 | last_result = (last_result + diff) % (MAX_DEBOUNCE + 1); | ||
| 54 | return last_result; | ||
| 55 | } | ||
| 56 | 54 | ||
| 57 | void update_debounce_counters(uint8_t num_rows, uint8_t current_time); | 55 | static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time); |
| 58 | void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); | 56 | static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); |
| 59 | 57 | ||
| 60 | // we use num_rows rather than MATRIX_ROWS to support split keyboards | 58 | // we use num_rows rather than MATRIX_ROWS to support split keyboards |
| 61 | void debounce_init(uint8_t num_rows) { | 59 | void debounce_init(uint8_t num_rows) { |
| @@ -68,27 +66,51 @@ void debounce_init(uint8_t num_rows) { | |||
| 68 | } | 66 | } |
| 69 | } | 67 | } |
| 70 | 68 | ||
| 69 | void debounce_free(void) { | ||
| 70 | free(debounce_counters); | ||
| 71 | debounce_counters = NULL; | ||
| 72 | } | ||
| 73 | |||
| 71 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | 74 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { |
| 72 | uint8_t current_time = wrapping_timer_read(); | 75 | bool updated_last = false; |
| 76 | |||
| 73 | if (counters_need_update) { | 77 | if (counters_need_update) { |
| 74 | update_debounce_counters(num_rows, current_time); | 78 | fast_timer_t now = timer_read_fast(); |
| 79 | fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); | ||
| 80 | |||
| 81 | last_time = now; | ||
| 82 | updated_last = true; | ||
| 83 | if (elapsed_time > UINT8_MAX) { | ||
| 84 | elapsed_time = UINT8_MAX; | ||
| 85 | } | ||
| 86 | |||
| 87 | if (elapsed_time > 0) { | ||
| 88 | update_debounce_counters(num_rows, elapsed_time); | ||
| 89 | } | ||
| 75 | } | 90 | } |
| 76 | 91 | ||
| 77 | if (changed || matrix_need_update) { | 92 | if (changed || matrix_need_update) { |
| 78 | transfer_matrix_values(raw, cooked, num_rows, current_time); | 93 | if (!updated_last) { |
| 94 | last_time = timer_read_fast(); | ||
| 95 | } | ||
| 96 | |||
| 97 | transfer_matrix_values(raw, cooked, num_rows); | ||
| 79 | } | 98 | } |
| 80 | } | 99 | } |
| 81 | 100 | ||
| 82 | // If the current time is > debounce counter, set the counter to enable input. | 101 | // If the current time is > debounce counter, set the counter to enable input. |
| 83 | void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { | 102 | static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) { |
| 84 | counters_need_update = false; | 103 | counters_need_update = false; |
| 104 | matrix_need_update = false; | ||
| 85 | debounce_counter_t *debounce_pointer = debounce_counters; | 105 | debounce_counter_t *debounce_pointer = debounce_counters; |
| 86 | for (uint8_t row = 0; row < num_rows; row++) { | 106 | for (uint8_t row = 0; row < num_rows; row++) { |
| 87 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { | 107 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { |
| 88 | if (*debounce_pointer != DEBOUNCE_ELAPSED) { | 108 | if (*debounce_pointer != DEBOUNCE_ELAPSED) { |
| 89 | if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { | 109 | if (*debounce_pointer <= elapsed_time) { |
| 90 | *debounce_pointer = DEBOUNCE_ELAPSED; | 110 | *debounce_pointer = DEBOUNCE_ELAPSED; |
| 111 | matrix_need_update = true; | ||
| 91 | } else { | 112 | } else { |
| 113 | *debounce_pointer -= elapsed_time; | ||
| 92 | counters_need_update = true; | 114 | counters_need_update = true; |
| 93 | } | 115 | } |
| 94 | } | 116 | } |
| @@ -98,8 +120,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { | |||
| 98 | } | 120 | } |
| 99 | 121 | ||
| 100 | // upload from raw_matrix to final matrix; | 122 | // upload from raw_matrix to final matrix; |
| 101 | void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { | 123 | static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { |
| 102 | matrix_need_update = false; | ||
| 103 | debounce_counter_t *debounce_pointer = debounce_counters; | 124 | debounce_counter_t *debounce_pointer = debounce_counters; |
| 104 | for (uint8_t row = 0; row < num_rows; row++) { | 125 | for (uint8_t row = 0; row < num_rows; row++) { |
| 105 | matrix_row_t delta = raw[row] ^ cooked[row]; | 126 | matrix_row_t delta = raw[row] ^ cooked[row]; |
| @@ -108,11 +129,9 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n | |||
| 108 | matrix_row_t col_mask = (ROW_SHIFTER << col); | 129 | matrix_row_t col_mask = (ROW_SHIFTER << col); |
| 109 | if (delta & col_mask) { | 130 | if (delta & col_mask) { |
| 110 | if (*debounce_pointer == DEBOUNCE_ELAPSED) { | 131 | if (*debounce_pointer == DEBOUNCE_ELAPSED) { |
| 111 | *debounce_pointer = current_time; | 132 | *debounce_pointer = DEBOUNCE; |
| 112 | counters_need_update = true; | 133 | counters_need_update = true; |
| 113 | existing_row ^= col_mask; // flip the bit. | 134 | existing_row ^= col_mask; // flip the bit. |
| 114 | } else { | ||
| 115 | matrix_need_update = true; | ||
| 116 | } | 135 | } |
| 117 | } | 136 | } |
| 118 | debounce_pointer++; | 137 | debounce_pointer++; |
| @@ -122,3 +141,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n | |||
| 122 | } | 141 | } |
| 123 | 142 | ||
| 124 | bool debounce_active(void) { return true; } | 143 | bool debounce_active(void) { return true; } |
| 144 | #else | ||
| 145 | # include "none.c" | ||
| 146 | #endif | ||
diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c index 20ccb46f1..2ad592c5a 100644 --- a/quantum/debounce/sym_eager_pr.c +++ b/quantum/debounce/sym_eager_pr.c | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | Copyright 2019 Alex Ong<the.onga@gmail.com> | 2 | Copyright 2019 Alex Ong<the.onga@gmail.com> |
| 3 | Copyright 2021 Simon Arlott | ||
| 3 | This program is free software: you can redistribute it and/or modify | 4 | This program is free software: you can redistribute it and/or modify |
| 4 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
| 5 | the Free Software Foundation, either version 2 of the License, or | 6 | 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. | |||
| 33 | # define DEBOUNCE 5 | 34 | # define DEBOUNCE 5 |
| 34 | #endif | 35 | #endif |
| 35 | 36 | ||
| 36 | #define debounce_counter_t uint8_t | 37 | // Maximum debounce: 255ms |
| 38 | #if DEBOUNCE > UINT8_MAX | ||
| 39 | # undef DEBOUNCE | ||
| 40 | # define DEBOUNCE UINT8_MAX | ||
| 41 | #endif | ||
| 42 | |||
| 43 | typedef uint8_t debounce_counter_t; | ||
| 44 | |||
| 45 | #if DEBOUNCE > 0 | ||
| 37 | static bool matrix_need_update; | 46 | static bool matrix_need_update; |
| 38 | 47 | ||
| 39 | static debounce_counter_t *debounce_counters; | 48 | static debounce_counter_t *debounce_counters; |
| 49 | static fast_timer_t last_time; | ||
| 40 | static bool counters_need_update; | 50 | static bool counters_need_update; |
| 41 | 51 | ||
| 42 | #define DEBOUNCE_ELAPSED 251 | 52 | #define DEBOUNCE_ELAPSED 0 |
| 43 | #define MAX_DEBOUNCE (DEBOUNCE_ELAPSED - 1) | ||
| 44 | |||
| 45 | static uint8_t wrapping_timer_read(void) { | ||
| 46 | static uint16_t time = 0; | ||
| 47 | static uint8_t last_result = 0; | ||
| 48 | uint16_t new_time = timer_read(); | ||
| 49 | uint16_t diff = new_time - time; | ||
| 50 | time = new_time; | ||
| 51 | last_result = (last_result + diff) % (MAX_DEBOUNCE + 1); | ||
| 52 | return last_result; | ||
| 53 | } | ||
| 54 | 53 | ||
| 55 | void update_debounce_counters(uint8_t num_rows, uint8_t current_time); | 54 | static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time); |
| 56 | void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time); | 55 | static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); |
| 57 | 56 | ||
| 58 | // we use num_rows rather than MATRIX_ROWS to support split keyboards | 57 | // we use num_rows rather than MATRIX_ROWS to support split keyboards |
| 59 | void debounce_init(uint8_t num_rows) { | 58 | void debounce_init(uint8_t num_rows) { |
| @@ -63,27 +62,50 @@ void debounce_init(uint8_t num_rows) { | |||
| 63 | } | 62 | } |
| 64 | } | 63 | } |
| 65 | 64 | ||
| 65 | void debounce_free(void) { | ||
| 66 | free(debounce_counters); | ||
| 67 | debounce_counters = NULL; | ||
| 68 | } | ||
| 69 | |||
| 66 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { | 70 | void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { |
| 67 | uint8_t current_time = wrapping_timer_read(); | 71 | bool updated_last = false; |
| 68 | bool needed_update = counters_need_update; | 72 | |
| 69 | if (counters_need_update) { | 73 | if (counters_need_update) { |
| 70 | update_debounce_counters(num_rows, current_time); | 74 | fast_timer_t now = timer_read_fast(); |
| 75 | fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); | ||
| 76 | |||
| 77 | last_time = now; | ||
| 78 | updated_last = true; | ||
| 79 | if (elapsed_time > UINT8_MAX) { | ||
| 80 | elapsed_time = UINT8_MAX; | ||
| 81 | } | ||
| 82 | |||
| 83 | if (elapsed_time > 0) { | ||
| 84 | update_debounce_counters(num_rows, elapsed_time); | ||
| 85 | } | ||
| 71 | } | 86 | } |
| 72 | 87 | ||
| 73 | if (changed || (needed_update && !counters_need_update) || matrix_need_update) { | 88 | if (changed || matrix_need_update) { |
| 74 | transfer_matrix_values(raw, cooked, num_rows, current_time); | 89 | if (!updated_last) { |
| 90 | last_time = timer_read_fast(); | ||
| 91 | } | ||
| 92 | |||
| 93 | transfer_matrix_values(raw, cooked, num_rows); | ||
| 75 | } | 94 | } |
| 76 | } | 95 | } |
| 77 | 96 | ||
| 78 | // If the current time is > debounce counter, set the counter to enable input. | 97 | // If the current time is > debounce counter, set the counter to enable input. |
| 79 | void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { | 98 | static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) { |
| 80 | counters_need_update = false; | 99 | counters_need_update = false; |
| 100 | matrix_need_update = false; | ||
| 81 | debounce_counter_t *debounce_pointer = debounce_counters; | 101 | debounce_counter_t *debounce_pointer = debounce_counters; |
| 82 | for (uint8_t row = 0; row < num_rows; row++) { | 102 | for (uint8_t row = 0; row < num_rows; row++) { |
| 83 | if (*debounce_pointer != DEBOUNCE_ELAPSED) { | 103 | if (*debounce_pointer != DEBOUNCE_ELAPSED) { |
| 84 | if (TIMER_DIFF(current_time, *debounce_pointer, MAX_DEBOUNCE) >= DEBOUNCE) { | 104 | if (*debounce_pointer <= elapsed_time) { |
| 85 | *debounce_pointer = DEBOUNCE_ELAPSED; | 105 | *debounce_pointer = DEBOUNCE_ELAPSED; |
| 106 | matrix_need_update = true; | ||
| 86 | } else { | 107 | } else { |
| 108 | *debounce_pointer -= elapsed_time; | ||
| 87 | counters_need_update = true; | 109 | counters_need_update = true; |
| 88 | } | 110 | } |
| 89 | } | 111 | } |
| @@ -92,8 +114,7 @@ void update_debounce_counters(uint8_t num_rows, uint8_t current_time) { | |||
| 92 | } | 114 | } |
| 93 | 115 | ||
| 94 | // upload from raw_matrix to final matrix; | 116 | // upload from raw_matrix to final matrix; |
| 95 | void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) { | 117 | static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { |
| 96 | matrix_need_update = false; | ||
| 97 | debounce_counter_t *debounce_pointer = debounce_counters; | 118 | debounce_counter_t *debounce_pointer = debounce_counters; |
| 98 | for (uint8_t row = 0; row < num_rows; row++) { | 119 | for (uint8_t row = 0; row < num_rows; row++) { |
| 99 | matrix_row_t existing_row = cooked[row]; | 120 | matrix_row_t existing_row = cooked[row]; |
| @@ -102,11 +123,9 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n | |||
| 102 | // determine new value basd on debounce pointer + raw value | 123 | // determine new value basd on debounce pointer + raw value |
| 103 | if (existing_row != raw_row) { | 124 | if (existing_row != raw_row) { |
| 104 | if (*debounce_pointer == DEBOUNCE_ELAPSED) { | 125 | if (*debounce_pointer == DEBOUNCE_ELAPSED) { |
| 105 | *debounce_pointer = current_time; | 126 | *debounce_pointer = DEBOUNCE; |
| 106 | cooked[row] = raw_row; | 127 | cooked[row] = raw_row; |
| 107 | counters_need_update = true; | 128 | counters_need_update = true; |
| 108 | } else { | ||
| 109 | matrix_need_update = true; | ||
| 110 | } | 129 | } |
| 111 | } | 130 | } |
| 112 | debounce_pointer++; | 131 | debounce_pointer++; |
| @@ -114,3 +133,6 @@ void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t n | |||
| 114 | } | 133 | } |
| 115 | 134 | ||
| 116 | bool debounce_active(void) { return true; } | 135 | bool debounce_active(void) { return true; } |
| 136 | #else | ||
| 137 | # include "none.c" | ||
| 138 | #endif | ||
diff --git a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp new file mode 100644 index 000000000..fe374c3df --- /dev/null +++ b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp | |||
| @@ -0,0 +1,374 @@ | |||
| 1 | /* Copyright 2021 Simon Arlott | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "gtest/gtest.h" | ||
| 18 | |||
| 19 | #include "debounce_test_common.h" | ||
| 20 | |||
| 21 | TEST_F(DebounceTest, OneKeyShort1) { | ||
| 22 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 23 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 24 | /* Release key after 1ms delay */ | ||
| 25 | {1, {{0, 1, UP}}, {}}, | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Until the eager timer on DOWN is observed to finish, the defer timer | ||
| 29 | * on UP can't start. There's no workaround for this because it's not | ||
| 30 | * possible to debounce an event that isn't being tracked. | ||
| 31 | * | ||
| 32 | * sym_defer_pk has the same problem but the test has to track that the | ||
| 33 | * key changed state so the DOWN timer is always allowed to finish | ||
| 34 | * before starting the UP timer. | ||
| 35 | */ | ||
| 36 | {5, {}, {}}, | ||
| 37 | |||
| 38 | {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ | ||
| 39 | /* Press key again after 1ms delay */ | ||
| 40 | {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 41 | }); | ||
| 42 | runEvents(); | ||
| 43 | } | ||
| 44 | |||
| 45 | TEST_F(DebounceTest, OneKeyShort2) { | ||
| 46 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 47 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 48 | /* Release key after 2ms delay */ | ||
| 49 | {2, {{0, 1, UP}}, {}}, | ||
| 50 | |||
| 51 | {5, {}, {}}, /* See OneKeyShort1 */ | ||
| 52 | |||
| 53 | {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ | ||
| 54 | /* Press key again after 1ms delay */ | ||
| 55 | {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 56 | }); | ||
| 57 | runEvents(); | ||
| 58 | } | ||
| 59 | |||
| 60 | TEST_F(DebounceTest, OneKeyShort3) { | ||
| 61 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 62 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 63 | /* Release key after 3ms delay */ | ||
| 64 | {3, {{0, 1, UP}}, {}}, | ||
| 65 | |||
| 66 | {5, {}, {}}, /* See OneKeyShort1 */ | ||
| 67 | |||
| 68 | {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ | ||
| 69 | /* Press key again after 1ms delay */ | ||
| 70 | {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 71 | }); | ||
| 72 | runEvents(); | ||
| 73 | } | ||
| 74 | |||
| 75 | TEST_F(DebounceTest, OneKeyShort4) { | ||
| 76 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 77 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 78 | /* Release key after 4ms delay */ | ||
| 79 | {4, {{0, 1, UP}}, {}}, | ||
| 80 | |||
| 81 | {5, {}, {}}, /* See OneKeyShort1 */ | ||
| 82 | |||
| 83 | {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ | ||
| 84 | /* Press key again after 1ms delay */ | ||
| 85 | {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 86 | }); | ||
| 87 | runEvents(); | ||
| 88 | } | ||
| 89 | |||
| 90 | TEST_F(DebounceTest, OneKeyShort5) { | ||
| 91 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 92 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 93 | |||
| 94 | /* Release key after 5ms delay */ | ||
| 95 | {5, {{0, 1, UP}}, {}}, | ||
| 96 | |||
| 97 | {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ | ||
| 98 | /* Press key again after 1ms delay */ | ||
| 99 | {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 100 | }); | ||
| 101 | runEvents(); | ||
| 102 | } | ||
| 103 | |||
| 104 | TEST_F(DebounceTest, OneKeyShort6) { | ||
| 105 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 106 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 107 | |||
| 108 | /* Release key after 6ms delay */ | ||
| 109 | {6, {{0, 1, UP}}, {}}, | ||
| 110 | |||
| 111 | {11, {}, {{0, 1, UP}}}, /* 5ms after UP at time 6 */ | ||
| 112 | /* Press key again after 1ms delay */ | ||
| 113 | {12, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 114 | }); | ||
| 115 | runEvents(); | ||
| 116 | } | ||
| 117 | |||
| 118 | TEST_F(DebounceTest, OneKeyShort7) { | ||
| 119 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 120 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 121 | |||
| 122 | /* Release key after 7ms delay */ | ||
| 123 | {7, {{0, 1, UP}}, {}}, | ||
| 124 | |||
| 125 | {12, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */ | ||
| 126 | /* Press key again after 1ms delay */ | ||
| 127 | {13, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 128 | }); | ||
| 129 | runEvents(); | ||
| 130 | } | ||
| 131 | |||
| 132 | TEST_F(DebounceTest, OneKeyShort8) { | ||
| 133 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 134 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 135 | /* Release key after 1ms delay */ | ||
| 136 | {1, {{0, 1, UP}}, {}}, | ||
| 137 | |||
| 138 | {5, {}, {}}, /* See OneKeyShort1 */ | ||
| 139 | |||
| 140 | {10, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */ | ||
| 141 | /* Press key again after 0ms delay (scan 2) */ | ||
| 142 | {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 143 | }); | ||
| 144 | runEvents(); | ||
| 145 | } | ||
| 146 | |||
| 147 | TEST_F(DebounceTest, OneKeyShort9) { | ||
| 148 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 149 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 150 | /* Release key after 1ms delay */ | ||
| 151 | {1, {{0, 1, UP}}, {}}, | ||
| 152 | |||
| 153 | {5, {}, {}}, /* See OneKeyShort1 */ | ||
| 154 | |||
| 155 | /* Press key again after 0ms delay (same scan) before debounce finishes */ | ||
| 156 | {10, {{0, 1, DOWN}}, {}}, | ||
| 157 | }); | ||
| 158 | runEvents(); | ||
| 159 | } | ||
| 160 | |||
| 161 | TEST_F(DebounceTest, OneKeyBouncing1) { | ||
| 162 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 163 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 164 | {1, {{0, 1, UP}}, {}}, | ||
| 165 | {2, {{0, 1, DOWN}}, {}}, | ||
| 166 | {3, {{0, 1, UP}}, {}}, | ||
| 167 | {4, {{0, 1, DOWN}}, {}}, | ||
| 168 | {5, {{0, 1, UP}}, {}}, | ||
| 169 | {6, {{0, 1, DOWN}}, {}}, | ||
| 170 | {7, {{0, 1, UP}}, {}}, | ||
| 171 | {8, {{0, 1, DOWN}}, {}}, | ||
| 172 | {9, {{0, 1, UP}}, {}}, | ||
| 173 | {10, {{0, 1, DOWN}}, {}}, | ||
| 174 | {11, {{0, 1, UP}}, {}}, | ||
| 175 | {12, {{0, 1, DOWN}}, {}}, | ||
| 176 | {13, {{0, 1, UP}}, {}}, | ||
| 177 | {14, {{0, 1, DOWN}}, {}}, | ||
| 178 | {15, {{0, 1, UP}}, {}}, | ||
| 179 | |||
| 180 | {20, {}, {{0, 1, UP}}}, | ||
| 181 | /* Press key again after 1ms delay */ | ||
| 182 | {21, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 183 | }); | ||
| 184 | runEvents(); | ||
| 185 | } | ||
| 186 | |||
| 187 | TEST_F(DebounceTest, OneKeyBouncing2) { | ||
| 188 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 189 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 190 | /* Change twice in the same time period */ | ||
| 191 | {1, {{0, 1, UP}}, {}}, | ||
| 192 | {1, {{0, 1, DOWN}}, {}}, | ||
| 193 | /* Change three times in the same time period */ | ||
| 194 | {2, {{0, 1, UP}}, {}}, | ||
| 195 | {2, {{0, 1, DOWN}}, {}}, | ||
| 196 | {2, {{0, 1, UP}}, {}}, | ||
| 197 | /* Change twice in the same time period */ | ||
| 198 | {6, {{0, 1, DOWN}}, {}}, | ||
| 199 | {6, {{0, 1, UP}}, {}}, | ||
| 200 | /* Change three times in the same time period */ | ||
| 201 | {7, {{0, 1, DOWN}}, {}}, | ||
| 202 | {7, {{0, 1, UP}}, {}}, | ||
| 203 | {7, {{0, 1, DOWN}}, {}}, | ||
| 204 | /* Change twice in the same time period */ | ||
| 205 | {8, {{0, 1, UP}}, {}}, | ||
| 206 | {8, {{0, 1, DOWN}}, {}}, | ||
| 207 | /* Change three times in the same time period */ | ||
| 208 | {9, {{0, 1, UP}}, {}}, | ||
| 209 | {9, {{0, 1, DOWN}}, {}}, | ||
| 210 | {9, {{0, 1, UP}}, {}}, | ||
| 211 | |||
| 212 | {14, {}, {{0, 1, UP}}}, | ||
| 213 | /* Press key again after 1ms delay */ | ||
| 214 | {15, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 215 | }); | ||
| 216 | runEvents(); | ||
| 217 | } | ||
| 218 | |||
| 219 | TEST_F(DebounceTest, OneKeyLong) { | ||
| 220 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 221 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 222 | |||
| 223 | {25, {{0, 1, UP}}, {}}, | ||
| 224 | |||
| 225 | {30, {}, {{0, 1, UP}}}, | ||
| 226 | |||
| 227 | {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 228 | |||
| 229 | {75, {{0, 1, UP}}, {}}, | ||
| 230 | |||
| 231 | {80, {}, {{0, 1, UP}}}, | ||
| 232 | |||
| 233 | {100, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 234 | }); | ||
| 235 | runEvents(); | ||
| 236 | } | ||
| 237 | |||
| 238 | TEST_F(DebounceTest, TwoKeysShort) { | ||
| 239 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 240 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 241 | {1, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, | ||
| 242 | /* Release key after 2ms delay */ | ||
| 243 | {2, {{0, 1, UP}}, {}}, | ||
| 244 | {3, {{0, 2, UP}}, {}}, | ||
| 245 | |||
| 246 | {5, {}, {}}, /* See OneKeyShort1 */ | ||
| 247 | {6, {}, {}}, /* See OneKeyShort1 */ | ||
| 248 | |||
| 249 | {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */ | ||
| 250 | /* Press key again after 1ms delay */ | ||
| 251 | {11, {{0, 1, DOWN}}, {{0, 1, DOWN}, {0, 2, UP}}}, /* 5ms+5ms after DOWN at time 0 */ | ||
| 252 | {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */ | ||
| 253 | }); | ||
| 254 | runEvents(); | ||
| 255 | } | ||
| 256 | |||
| 257 | |||
| 258 | TEST_F(DebounceTest, OneKeyDelayedScan1) { | ||
| 259 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 260 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 261 | |||
| 262 | /* Processing is very late, immediately release key */ | ||
| 263 | {300, {{0, 1, UP}}, {}}, | ||
| 264 | |||
| 265 | {305, {}, {{0, 1, UP}}}, | ||
| 266 | }); | ||
| 267 | time_jumps_ = true; | ||
| 268 | runEvents(); | ||
| 269 | } | ||
| 270 | |||
| 271 | TEST_F(DebounceTest, OneKeyDelayedScan2) { | ||
| 272 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 273 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 274 | |||
| 275 | /* Processing is very late, immediately release key */ | ||
| 276 | {300, {{0, 1, UP}}, {}}, | ||
| 277 | |||
| 278 | /* Processing is very late again */ | ||
| 279 | {600, {}, {{0, 1, UP}}}, | ||
| 280 | }); | ||
| 281 | time_jumps_ = true; | ||
| 282 | runEvents(); | ||
| 283 | } | ||
| 284 | |||
| 285 | TEST_F(DebounceTest, OneKeyDelayedScan3) { | ||
| 286 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 287 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 288 | |||
| 289 | /* Processing is very late */ | ||
| 290 | {300, {}, {}}, | ||
| 291 | /* Release key after 1ms */ | ||
| 292 | {301, {{0, 1, UP}}, {}}, | ||
| 293 | |||
| 294 | {306, {}, {{0, 1, UP}}}, | ||
| 295 | }); | ||
| 296 | time_jumps_ = true; | ||
| 297 | runEvents(); | ||
| 298 | } | ||
| 299 | |||
| 300 | TEST_F(DebounceTest, OneKeyDelayedScan4) { | ||
| 301 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 302 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 303 | |||
| 304 | /* Processing is very late */ | ||
| 305 | {300, {}, {}}, | ||
| 306 | /* Release key after 1ms */ | ||
| 307 | {301, {{0, 1, UP}}, {}}, | ||
| 308 | |||
| 309 | /* Processing is very late again */ | ||
| 310 | {600, {}, {{0, 1, UP}}}, | ||
| 311 | }); | ||
| 312 | time_jumps_ = true; | ||
| 313 | runEvents(); | ||
| 314 | } | ||
| 315 | |||
| 316 | TEST_F(DebounceTest, OneKeyDelayedScan5) { | ||
| 317 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 318 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 319 | |||
| 320 | {5, {{0, 1, UP}}, {}}, | ||
| 321 | |||
| 322 | /* Processing is very late */ | ||
| 323 | {300, {}, {{0, 1, UP}}}, | ||
| 324 | /* Immediately press key again */ | ||
| 325 | {300, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 326 | }); | ||
| 327 | time_jumps_ = true; | ||
| 328 | runEvents(); | ||
| 329 | } | ||
| 330 | |||
| 331 | TEST_F(DebounceTest, OneKeyDelayedScan6) { | ||
| 332 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 333 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 334 | |||
| 335 | {5, {{0, 1, UP}}, {}}, | ||
| 336 | |||
| 337 | /* Processing is very late */ | ||
| 338 | {300, {}, {{0, 1, UP}}}, | ||
| 339 | |||
| 340 | /* Press key again after 1ms */ | ||
| 341 | {301, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 342 | }); | ||
| 343 | time_jumps_ = true; | ||
| 344 | runEvents(); | ||
| 345 | } | ||
| 346 | |||
| 347 | TEST_F(DebounceTest, OneKeyDelayedScan7) { | ||
| 348 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 349 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 350 | |||
| 351 | {5, {{0, 1, UP}}, {}}, | ||
| 352 | |||
| 353 | /* Press key again before debounce expires */ | ||
| 354 | {300, {{0, 1, DOWN}}, {}}, | ||
| 355 | }); | ||
| 356 | time_jumps_ = true; | ||
| 357 | runEvents(); | ||
| 358 | } | ||
| 359 | |||
| 360 | TEST_F(DebounceTest, OneKeyDelayedScan8) { | ||
| 361 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 362 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 363 | |||
| 364 | /* Processing is a bit late */ | ||
| 365 | {50, {}, {}}, | ||
| 366 | /* Release key after 1ms */ | ||
| 367 | {51, {{0, 1, UP}}, {}}, | ||
| 368 | |||
| 369 | /* Processing is a bit late again */ | ||
| 370 | {100, {}, {{0, 1, UP}}}, | ||
| 371 | }); | ||
| 372 | time_jumps_ = true; | ||
| 373 | runEvents(); | ||
| 374 | } | ||
diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp new file mode 100644 index 000000000..1c5e7c9f4 --- /dev/null +++ b/quantum/debounce/tests/debounce_test_common.cpp | |||
| @@ -0,0 +1,229 @@ | |||
| 1 | /* Copyright 2021 Simon Arlott | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "gtest/gtest.h" | ||
| 18 | |||
| 19 | #include "debounce_test_common.h" | ||
| 20 | |||
| 21 | #include <algorithm> | ||
| 22 | #include <iomanip> | ||
| 23 | #include <sstream> | ||
| 24 | |||
| 25 | extern "C" { | ||
| 26 | #include "quantum.h" | ||
| 27 | #include "timer.h" | ||
| 28 | #include "debounce.h" | ||
| 29 | |||
| 30 | void set_time(uint32_t t); | ||
| 31 | void advance_time(uint32_t ms); | ||
| 32 | } | ||
| 33 | |||
| 34 | void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) { | ||
| 35 | events_.insert(events_.end(), events.begin(), events.end()); | ||
| 36 | } | ||
| 37 | |||
| 38 | void DebounceTest::runEvents() { | ||
| 39 | /* Run the test multiple times, from 1kHz to 10kHz scan rate */ | ||
| 40 | for (extra_iterations_ = 0; extra_iterations_ < 10; extra_iterations_++) { | ||
| 41 | if (time_jumps_) { | ||
| 42 | /* Don't advance time smoothly, jump to the next event (some tests require this) */ | ||
| 43 | auto_advance_time_ = false; | ||
| 44 | runEventsInternal(); | ||
| 45 | } else { | ||
| 46 | /* Run the test with both smooth and irregular time; it must produce the same result */ | ||
| 47 | auto_advance_time_ = true; | ||
| 48 | runEventsInternal(); | ||
| 49 | auto_advance_time_ = false; | ||
| 50 | runEventsInternal(); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | void DebounceTest::runEventsInternal() { | ||
| 56 | fast_timer_t previous = 0; | ||
| 57 | bool first = true; | ||
| 58 | |||
| 59 | /* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */ | ||
| 60 | debounce_init(MATRIX_ROWS); | ||
| 61 | set_time(time_offset_); | ||
| 62 | std::fill(std::begin(input_matrix_), std::end(input_matrix_), 0); | ||
| 63 | std::fill(std::begin(output_matrix_), std::end(output_matrix_), 0); | ||
| 64 | |||
| 65 | for (auto &event : events_) { | ||
| 66 | if (!auto_advance_time_) { | ||
| 67 | /* Jump to the next event */ | ||
| 68 | set_time(time_offset_ + event.time_); | ||
| 69 | } else if (!first && event.time_ == previous + 1) { | ||
| 70 | /* This event immediately follows the previous one, don't make extra debounce() calls */ | ||
| 71 | advance_time(1); | ||
| 72 | } else { | ||
| 73 | /* Fast forward to the time for this event, calling debounce() with no changes */ | ||
| 74 | ASSERT_LT((time_offset_ + event.time_) - timer_read_fast(), 60000) << "Test tries to advance more than 1 minute of time"; | ||
| 75 | |||
| 76 | while (timer_read_fast() != time_offset_ + event.time_) { | ||
| 77 | runDebounce(false); | ||
| 78 | checkCookedMatrix(false, "debounce() modified cooked matrix"); | ||
| 79 | advance_time(1); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | first = false; | ||
| 84 | previous = event.time_; | ||
| 85 | |||
| 86 | /* Prepare input matrix */ | ||
| 87 | for (auto &input : event.inputs_) { | ||
| 88 | matrixUpdate(input_matrix_, "input", input); | ||
| 89 | } | ||
| 90 | |||
| 91 | /* Call debounce */ | ||
| 92 | runDebounce(!event.inputs_.empty()); | ||
| 93 | |||
| 94 | /* Prepare output matrix */ | ||
| 95 | for (auto &output : event.outputs_) { | ||
| 96 | matrixUpdate(output_matrix_, "output", output); | ||
| 97 | } | ||
| 98 | |||
| 99 | /* Check output matrix has expected change events */ | ||
| 100 | for (auto &output : event.outputs_) { | ||
| 101 | EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_)) | ||
| 102 | << "Missing event at " << strTime() | ||
| 103 | << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_) | ||
| 104 | << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_) | ||
| 105 | << "\nexpected_matrix:\n" << strMatrix(output_matrix_) | ||
| 106 | << "\nactual_matrix:\n" << strMatrix(cooked_matrix_); | ||
| 107 | } | ||
| 108 | |||
| 109 | /* Check output matrix has no other changes */ | ||
| 110 | checkCookedMatrix(!event.inputs_.empty(), "debounce() cooked matrix does not match expected output matrix"); | ||
| 111 | |||
| 112 | /* Perform some extra iterations of the matrix scan with no changes */ | ||
| 113 | for (int i = 0; i < extra_iterations_; i++) { | ||
| 114 | runDebounce(false); | ||
| 115 | checkCookedMatrix(false, "debounce() modified cooked matrix"); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | /* Check that no further changes happen for 1 minute */ | ||
| 120 | for (int i = 0; i < 60000; i++) { | ||
| 121 | runDebounce(false); | ||
| 122 | checkCookedMatrix(false, "debounce() modified cooked matrix"); | ||
| 123 | advance_time(1); | ||
| 124 | } | ||
| 125 | |||
| 126 | debounce_free(); | ||
| 127 | } | ||
| 128 | |||
| 129 | void DebounceTest::runDebounce(bool changed) { | ||
| 130 | std::copy(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_)); | ||
| 131 | std::copy(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_)); | ||
| 132 | |||
| 133 | debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed); | ||
| 134 | |||
| 135 | if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) { | ||
| 136 | FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime() | ||
| 137 | << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) | ||
| 138 | << "\nraw_matrix:\n" << strMatrix(raw_matrix_); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) { | ||
| 143 | if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) { | ||
| 144 | FAIL() << "Unexpected event: " << error_message << " at " << strTime() | ||
| 145 | << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) | ||
| 146 | << "\nexpected_matrix:\n" << strMatrix(output_matrix_) | ||
| 147 | << "\nactual_matrix:\n" << strMatrix(cooked_matrix_); | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | std::string DebounceTest::strTime() { | ||
| 152 | std::stringstream text; | ||
| 153 | |||
| 154 | text << "time " << (timer_read_fast() - time_offset_) | ||
| 155 | << " (extra_iterations=" << extra_iterations_ | ||
| 156 | << ", auto_advance_time=" << auto_advance_time_ << ")"; | ||
| 157 | |||
| 158 | return text.str(); | ||
| 159 | } | ||
| 160 | |||
| 161 | std::string DebounceTest::strMatrix(matrix_row_t matrix[]) { | ||
| 162 | std::stringstream text; | ||
| 163 | |||
| 164 | text << "\t" << std::setw(3) << ""; | ||
| 165 | for (int col = 0; col < MATRIX_COLS; col++) { | ||
| 166 | text << " " << std::setw(2) << col; | ||
| 167 | } | ||
| 168 | text << "\n"; | ||
| 169 | |||
| 170 | for (int row = 0; row < MATRIX_ROWS; row++) { | ||
| 171 | text << "\t" << std::setw(2) << row << ":"; | ||
| 172 | for (int col = 0; col < MATRIX_COLS; col++) { | ||
| 173 | text << ((matrix[row] & (1U << col)) ? " XX" : " __"); | ||
| 174 | } | ||
| 175 | |||
| 176 | text << "\n"; | ||
| 177 | } | ||
| 178 | |||
| 179 | return text.str(); | ||
| 180 | } | ||
| 181 | |||
| 182 | bool DebounceTest::directionValue(Direction direction) { | ||
| 183 | switch (direction) { | ||
| 184 | case DOWN: | ||
| 185 | return true; | ||
| 186 | |||
| 187 | case UP: | ||
| 188 | return false; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | std::string DebounceTest::directionLabel(Direction direction) { | ||
| 193 | switch (direction) { | ||
| 194 | case DOWN: | ||
| 195 | return "DOWN"; | ||
| 196 | |||
| 197 | case UP: | ||
| 198 | return "UP"; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | /* Modify a matrix and verify that events always specify a change */ | ||
| 203 | void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) { | ||
| 204 | ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_)) | ||
| 205 | << "Test " << name << " at " << strTime() | ||
| 206 | << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_) | ||
| 207 | << " but it is already " << directionLabel(event.direction_) | ||
| 208 | << "\n" << name << "_matrix:\n" << strMatrix(matrix); | ||
| 209 | |||
| 210 | switch (event.direction_) { | ||
| 211 | case DOWN: | ||
| 212 | matrix[event.row_] |= (1U << event.col_); | ||
| 213 | break; | ||
| 214 | |||
| 215 | case UP: | ||
| 216 | matrix[event.row_] &= ~(1U << event.col_); | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | DebounceTestEvent::DebounceTestEvent(fast_timer_t time, | ||
| 222 | std::initializer_list<MatrixTestEvent> inputs, | ||
| 223 | std::initializer_list<MatrixTestEvent> outputs) | ||
| 224 | : time_(time), inputs_(inputs), outputs_(outputs) { | ||
| 225 | } | ||
| 226 | |||
| 227 | MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction) | ||
| 228 | : row_(row), col_(col), direction_(direction) { | ||
| 229 | } | ||
diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h new file mode 100644 index 000000000..d87e31059 --- /dev/null +++ b/quantum/debounce/tests/debounce_test_common.h | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | /* Copyright 2021 Simon Arlott | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "gtest/gtest.h" | ||
| 18 | |||
| 19 | #include <initializer_list> | ||
| 20 | #include <list> | ||
| 21 | #include <string> | ||
| 22 | |||
| 23 | extern "C" { | ||
| 24 | #include "quantum.h" | ||
| 25 | #include "timer.h" | ||
| 26 | } | ||
| 27 | |||
| 28 | enum Direction { | ||
| 29 | DOWN, | ||
| 30 | UP, | ||
| 31 | }; | ||
| 32 | |||
| 33 | class MatrixTestEvent { | ||
| 34 | public: | ||
| 35 | MatrixTestEvent(int row, int col, Direction direction); | ||
| 36 | |||
| 37 | const int row_; | ||
| 38 | const int col_; | ||
| 39 | const Direction direction_; | ||
| 40 | }; | ||
| 41 | |||
| 42 | class DebounceTestEvent { | ||
| 43 | public: | ||
| 44 | // 0, {{0, 1, DOWN}}, {{0, 1, DOWN}}) | ||
| 45 | DebounceTestEvent(fast_timer_t time, | ||
| 46 | std::initializer_list<MatrixTestEvent> inputs, | ||
| 47 | std::initializer_list<MatrixTestEvent> outputs); | ||
| 48 | |||
| 49 | const fast_timer_t time_; | ||
| 50 | const std::list<MatrixTestEvent> inputs_; | ||
| 51 | const std::list<MatrixTestEvent> outputs_; | ||
| 52 | }; | ||
| 53 | |||
| 54 | class DebounceTest : public ::testing::Test { | ||
| 55 | protected: | ||
| 56 | void addEvents(std::initializer_list<DebounceTestEvent> events); | ||
| 57 | void runEvents(); | ||
| 58 | |||
| 59 | fast_timer_t time_offset_ = 7777; | ||
| 60 | bool time_jumps_ = false; | ||
| 61 | |||
| 62 | private: | ||
| 63 | static bool directionValue(Direction direction); | ||
| 64 | static std::string directionLabel(Direction direction); | ||
| 65 | |||
| 66 | void runEventsInternal(); | ||
| 67 | void runDebounce(bool changed); | ||
| 68 | void checkCookedMatrix(bool changed, const std::string &error_message); | ||
| 69 | void matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event); | ||
| 70 | |||
| 71 | std::string strTime(); | ||
| 72 | std::string strMatrix(matrix_row_t matrix[]); | ||
| 73 | |||
| 74 | std::list<DebounceTestEvent> events_; | ||
| 75 | |||
| 76 | matrix_row_t input_matrix_[MATRIX_ROWS]; | ||
| 77 | matrix_row_t raw_matrix_[MATRIX_ROWS]; | ||
| 78 | matrix_row_t cooked_matrix_[MATRIX_ROWS]; | ||
| 79 | matrix_row_t output_matrix_[MATRIX_ROWS]; | ||
| 80 | |||
| 81 | int extra_iterations_; | ||
| 82 | bool auto_advance_time_; | ||
| 83 | }; | ||
diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk new file mode 100644 index 000000000..66928d7eb --- /dev/null +++ b/quantum/debounce/tests/rules.mk | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | # Copyright 2021 Simon Arlott | ||
| 2 | # | ||
| 3 | # This program is free software: you can redistribute it and/or modify | ||
| 4 | # it under the terms of the GNU General Public License as published by | ||
| 5 | # the Free Software Foundation, either version 2 of the License, or | ||
| 6 | # (at your option) any later version. | ||
| 7 | # | ||
| 8 | # This program is distributed in the hope that it will be useful, | ||
| 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | # GNU General Public License for more details. | ||
| 12 | # | ||
| 13 | # You should have received a copy of the GNU General Public License | ||
| 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | |||
| 16 | DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5 | ||
| 17 | |||
| 18 | DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \ | ||
| 19 | $(TMK_PATH)/common/test/timer.c | ||
| 20 | |||
| 21 | debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS) | ||
| 22 | debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \ | ||
| 23 | $(QUANTUM_PATH)/debounce/sym_defer_g.c \ | ||
| 24 | $(QUANTUM_PATH)/debounce/tests/sym_defer_g_tests.cpp | ||
| 25 | |||
| 26 | debounce_sym_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS) | ||
| 27 | debounce_sym_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \ | ||
| 28 | $(QUANTUM_PATH)/debounce/sym_defer_pk.c \ | ||
| 29 | $(QUANTUM_PATH)/debounce/tests/sym_defer_pk_tests.cpp | ||
| 30 | |||
| 31 | debounce_sym_eager_pk_DEFS := $(DEBOUNCE_COMMON_DEFS) | ||
| 32 | debounce_sym_eager_pk_SRC := $(DEBOUNCE_COMMON_SRC) \ | ||
| 33 | $(QUANTUM_PATH)/debounce/sym_eager_pk.c \ | ||
| 34 | $(QUANTUM_PATH)/debounce/tests/sym_eager_pk_tests.cpp | ||
| 35 | |||
| 36 | debounce_sym_eager_pr_DEFS := $(DEBOUNCE_COMMON_DEFS) | ||
| 37 | debounce_sym_eager_pr_SRC := $(DEBOUNCE_COMMON_SRC) \ | ||
| 38 | $(QUANTUM_PATH)/debounce/sym_eager_pr.c \ | ||
| 39 | $(QUANTUM_PATH)/debounce/tests/sym_eager_pr_tests.cpp | ||
| 40 | |||
| 41 | debounce_asym_eager_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS) | ||
| 42 | debounce_asym_eager_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \ | ||
| 43 | $(QUANTUM_PATH)/debounce/asym_eager_defer_pk.c \ | ||
| 44 | $(QUANTUM_PATH)/debounce/tests/asym_eager_defer_pk_tests.cpp | ||
diff --git a/quantum/debounce/tests/sym_defer_g_tests.cpp b/quantum/debounce/tests/sym_defer_g_tests.cpp new file mode 100644 index 000000000..a56aecd8f --- /dev/null +++ b/quantum/debounce/tests/sym_defer_g_tests.cpp | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | /* Copyright 2021 Simon Arlott | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "gtest/gtest.h" | ||
| 18 | |||
| 19 | #include "debounce_test_common.h" | ||
| 20 | |||
| 21 | TEST_F(DebounceTest, OneKeyShort1) { | ||
| 22 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 23 | {0, {{0, 1, DOWN}}, {}}, | ||
| 24 | |||
| 25 | {5, {}, {{0, 1, DOWN}}}, | ||
| 26 | /* 0ms delay (fast scan rate) */ | ||
| 27 | {5, {{0, 1, UP}}, {}}, | ||
| 28 | |||
| 29 | {10, {}, {{0, 1, UP}}}, | ||
| 30 | }); | ||
| 31 | runEvents(); | ||
| 32 | } | ||
| 33 | |||
| 34 | TEST_F(DebounceTest, OneKeyShort2) { | ||
| 35 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 36 | {0, {{0, 1, DOWN}}, {}}, | ||
| 37 | |||
| 38 | {5, {}, {{0, 1, DOWN}}}, | ||
| 39 | /* 1ms delay */ | ||
| 40 | {6, {{0, 1, UP}}, {}}, | ||
| 41 | |||
| 42 | {11, {}, {{0, 1, UP}}}, | ||
| 43 | }); | ||
| 44 | runEvents(); | ||
| 45 | } | ||
| 46 | |||
| 47 | TEST_F(DebounceTest, OneKeyShort3) { | ||
| 48 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 49 | {0, {{0, 1, DOWN}}, {}}, | ||
| 50 | |||
| 51 | {5, {}, {{0, 1, DOWN}}}, | ||
| 52 | /* 2ms delay */ | ||
| 53 | {7, {{0, 1, UP}}, {}}, | ||
| 54 | |||
| 55 | {12, {}, {{0, 1, UP}}}, | ||
| 56 | }); | ||
| 57 | runEvents(); | ||
| 58 | } | ||
| 59 | |||
| 60 | TEST_F(DebounceTest, OneKeyTooQuick1) { | ||
| 61 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 62 | {0, {{0, 1, DOWN}}, {}}, | ||
| 63 | /* Release key exactly on the debounce time */ | ||
| 64 | {5, {{0, 1, UP}}, {}}, | ||
| 65 | }); | ||
| 66 | runEvents(); | ||
| 67 | } | ||
| 68 | |||
| 69 | TEST_F(DebounceTest, OneKeyTooQuick2) { | ||
| 70 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 71 | {0, {{0, 1, DOWN}}, {}}, | ||
| 72 | |||
| 73 | {5, {}, {{0, 1, DOWN}}}, | ||
| 74 | {6, {{0, 1, UP}}, {}}, | ||
| 75 | |||
| 76 | /* Press key exactly on the debounce time */ | ||
| 77 | {11, {{0, 1, DOWN}}, {}}, | ||
| 78 | }); | ||
| 79 | runEvents(); | ||
| 80 | } | ||
| 81 | |||
| 82 | TEST_F(DebounceTest, OneKeyBouncing1) { | ||
| 83 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 84 | {0, {{0, 1, DOWN}}, {}}, | ||
| 85 | {1, {{0, 1, UP}}, {}}, | ||
| 86 | {2, {{0, 1, DOWN}}, {}}, | ||
| 87 | {3, {{0, 1, UP}}, {}}, | ||
| 88 | {4, {{0, 1, DOWN}}, {}}, | ||
| 89 | {5, {{0, 1, UP}}, {}}, | ||
| 90 | {6, {{0, 1, DOWN}}, {}}, | ||
| 91 | {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */ | ||
| 92 | }); | ||
| 93 | runEvents(); | ||
| 94 | } | ||
| 95 | |||
| 96 | TEST_F(DebounceTest, OneKeyBouncing2) { | ||
| 97 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 98 | {0, {{0, 1, DOWN}}, {}}, | ||
| 99 | {5, {}, {{0, 1, DOWN}}}, | ||
| 100 | {6, {{0, 1, UP}}, {}}, | ||
| 101 | {7, {{0, 1, DOWN}}, {}}, | ||
| 102 | {8, {{0, 1, UP}}, {}}, | ||
| 103 | {9, {{0, 1, DOWN}}, {}}, | ||
| 104 | {10, {{0, 1, UP}}, {}}, | ||
| 105 | {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */ | ||
| 106 | }); | ||
| 107 | runEvents(); | ||
| 108 | } | ||
| 109 | |||
| 110 | TEST_F(DebounceTest, OneKeyLong) { | ||
| 111 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 112 | {0, {{0, 1, DOWN}}, {}}, | ||
| 113 | |||
| 114 | {5, {}, {{0, 1, DOWN}}}, | ||
| 115 | |||
| 116 | {25, {{0, 1, UP}}, {}}, | ||
| 117 | |||
| 118 | {30, {}, {{0, 1, UP}}}, | ||
| 119 | |||
| 120 | {50, {{0, 1, DOWN}}, {}}, | ||
| 121 | |||
| 122 | {55, {}, {{0, 1, DOWN}}}, | ||
| 123 | }); | ||
| 124 | runEvents(); | ||
| 125 | } | ||
| 126 | |||
| 127 | TEST_F(DebounceTest, TwoKeysShort) { | ||
| 128 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 129 | {0, {{0, 1, DOWN}}, {}}, | ||
| 130 | {1, {{0, 2, DOWN}}, {}}, | ||
| 131 | |||
| 132 | {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, | ||
| 133 | |||
| 134 | {7, {{0, 1, UP}}, {}}, | ||
| 135 | {8, {{0, 2, UP}}, {}}, | ||
| 136 | |||
| 137 | {13, {}, {{0, 1, UP}, {0, 2, UP}}}, | ||
| 138 | }); | ||
| 139 | runEvents(); | ||
| 140 | } | ||
| 141 | |||
| 142 | TEST_F(DebounceTest, TwoKeysSimultaneous1) { | ||
| 143 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 144 | {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}}, | ||
| 145 | |||
| 146 | {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, | ||
| 147 | {6, {{0, 1, UP}, {0, 2, UP}}, {}}, | ||
| 148 | |||
| 149 | {11, {}, {{0, 1, UP}, {0, 2, UP}}}, | ||
| 150 | }); | ||
| 151 | runEvents(); | ||
| 152 | } | ||
| 153 | |||
| 154 | TEST_F(DebounceTest, TwoKeysSimultaneous2) { | ||
| 155 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 156 | {0, {{0, 1, DOWN}}, {}}, | ||
| 157 | {1, {{0, 2, DOWN}}, {}}, | ||
| 158 | |||
| 159 | {5, {}, {}}, | ||
| 160 | {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, | ||
| 161 | {7, {{0, 1, UP}}, {}}, | ||
| 162 | {8, {{0, 2, UP}}, {}}, | ||
| 163 | |||
| 164 | {13, {}, {{0, 1, UP}, {0, 2, UP}}}, | ||
| 165 | }); | ||
| 166 | runEvents(); | ||
| 167 | } | ||
| 168 | |||
| 169 | TEST_F(DebounceTest, OneKeyDelayedScan1) { | ||
| 170 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 171 | {0, {{0, 1, DOWN}}, {}}, | ||
| 172 | |||
| 173 | /* Processing is very late */ | ||
| 174 | {300, {}, {{0, 1, DOWN}}}, | ||
| 175 | /* Immediately release key */ | ||
| 176 | {300, {{0, 1, UP}}, {}}, | ||
| 177 | |||
| 178 | {305, {}, {{0, 1, UP}}}, | ||
| 179 | }); | ||
| 180 | time_jumps_ = true; | ||
| 181 | runEvents(); | ||
| 182 | } | ||
| 183 | |||
| 184 | TEST_F(DebounceTest, OneKeyDelayedScan2) { | ||
| 185 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 186 | {0, {{0, 1, DOWN}}, {}}, | ||
| 187 | |||
| 188 | /* Processing is very late */ | ||
| 189 | {300, {}, {{0, 1, DOWN}}}, | ||
| 190 | /* Release key after 1ms */ | ||
| 191 | {301, {{0, 1, UP}}, {}}, | ||
| 192 | |||
| 193 | {306, {}, {{0, 1, UP}}}, | ||
| 194 | }); | ||
| 195 | time_jumps_ = true; | ||
| 196 | runEvents(); | ||
| 197 | } | ||
| 198 | |||
| 199 | TEST_F(DebounceTest, OneKeyDelayedScan3) { | ||
| 200 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 201 | {0, {{0, 1, DOWN}}, {}}, | ||
| 202 | |||
| 203 | /* Release key before debounce expires */ | ||
| 204 | {300, {{0, 1, UP}}, {}}, | ||
| 205 | }); | ||
| 206 | time_jumps_ = true; | ||
| 207 | runEvents(); | ||
| 208 | } | ||
| 209 | |||
| 210 | TEST_F(DebounceTest, OneKeyDelayedScan4) { | ||
| 211 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 212 | {0, {{0, 1, DOWN}}, {}}, | ||
| 213 | |||
| 214 | /* Processing is a bit late */ | ||
| 215 | {50, {}, {{0, 1, DOWN}}}, | ||
| 216 | /* Release key after 1ms */ | ||
| 217 | {51, {{0, 1, UP}}, {}}, | ||
| 218 | |||
| 219 | {56, {}, {{0, 1, UP}}}, | ||
| 220 | }); | ||
| 221 | time_jumps_ = true; | ||
| 222 | runEvents(); | ||
| 223 | } | ||
diff --git a/quantum/debounce/tests/sym_defer_pk_tests.cpp b/quantum/debounce/tests/sym_defer_pk_tests.cpp new file mode 100644 index 000000000..1f3061e59 --- /dev/null +++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp | |||
| @@ -0,0 +1,225 @@ | |||
| 1 | /* Copyright 2021 Simon Arlott | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "gtest/gtest.h" | ||
| 18 | |||
| 19 | #include "debounce_test_common.h" | ||
| 20 | |||
| 21 | TEST_F(DebounceTest, OneKeyShort1) { | ||
| 22 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 23 | {0, {{0, 1, DOWN}}, {}}, | ||
| 24 | |||
| 25 | {5, {}, {{0, 1, DOWN}}}, | ||
| 26 | /* 0ms delay (fast scan rate) */ | ||
| 27 | {5, {{0, 1, UP}}, {}}, | ||
| 28 | |||
| 29 | {10, {}, {{0, 1, UP}}}, | ||
| 30 | }); | ||
| 31 | runEvents(); | ||
| 32 | } | ||
| 33 | |||
| 34 | TEST_F(DebounceTest, OneKeyShort2) { | ||
| 35 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 36 | {0, {{0, 1, DOWN}}, {}}, | ||
| 37 | |||
| 38 | {5, {}, {{0, 1, DOWN}}}, | ||
| 39 | /* 1ms delay */ | ||
| 40 | {6, {{0, 1, UP}}, {}}, | ||
| 41 | |||
| 42 | {11, {}, {{0, 1, UP}}}, | ||
| 43 | }); | ||
| 44 | runEvents(); | ||
| 45 | } | ||
| 46 | |||
| 47 | TEST_F(DebounceTest, OneKeyShort3) { | ||
| 48 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 49 | {0, {{0, 1, DOWN}}, {}}, | ||
| 50 | |||
| 51 | {5, {}, {{0, 1, DOWN}}}, | ||
| 52 | /* 2ms delay */ | ||
| 53 | {7, {{0, 1, UP}}, {}}, | ||
| 54 | |||
| 55 | {12, {}, {{0, 1, UP}}}, | ||
| 56 | }); | ||
| 57 | runEvents(); | ||
| 58 | } | ||
| 59 | |||
| 60 | TEST_F(DebounceTest, OneKeyTooQuick1) { | ||
| 61 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 62 | {0, {{0, 1, DOWN}}, {}}, | ||
| 63 | /* Release key exactly on the debounce time */ | ||
| 64 | {5, {{0, 1, UP}}, {}}, | ||
| 65 | }); | ||
| 66 | runEvents(); | ||
| 67 | } | ||
| 68 | |||
| 69 | TEST_F(DebounceTest, OneKeyTooQuick2) { | ||
| 70 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 71 | {0, {{0, 1, DOWN}}, {}}, | ||
| 72 | |||
| 73 | {5, {}, {{0, 1, DOWN}}}, | ||
| 74 | {6, {{0, 1, UP}}, {}}, | ||
| 75 | |||
| 76 | /* Press key exactly on the debounce time */ | ||
| 77 | {11, {{0, 1, DOWN}}, {}}, | ||
| 78 | }); | ||
| 79 | runEvents(); | ||
| 80 | } | ||
| 81 | |||
| 82 | TEST_F(DebounceTest, OneKeyBouncing1) { | ||
| 83 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 84 | {0, {{0, 1, DOWN}}, {}}, | ||
| 85 | {1, {{0, 1, UP}}, {}}, | ||
| 86 | {2, {{0, 1, DOWN}}, {}}, | ||
| 87 | {3, {{0, 1, UP}}, {}}, | ||
| 88 | {4, {{0, 1, DOWN}}, {}}, | ||
| 89 | {5, {{0, 1, UP}}, {}}, | ||
| 90 | {6, {{0, 1, DOWN}}, {}}, | ||
| 91 | {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */ | ||
| 92 | }); | ||
| 93 | runEvents(); | ||
| 94 | } | ||
| 95 | |||
| 96 | TEST_F(DebounceTest, OneKeyBouncing2) { | ||
| 97 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 98 | {0, {{0, 1, DOWN}}, {}}, | ||
| 99 | {5, {}, {{0, 1, DOWN}}}, | ||
| 100 | {6, {{0, 1, UP}}, {}}, | ||
| 101 | {7, {{0, 1, DOWN}}, {}}, | ||
| 102 | {8, {{0, 1, UP}}, {}}, | ||
| 103 | {9, {{0, 1, DOWN}}, {}}, | ||
| 104 | {10, {{0, 1, UP}}, {}}, | ||
| 105 | {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */ | ||
| 106 | }); | ||
| 107 | runEvents(); | ||
| 108 | } | ||
| 109 | |||
| 110 | TEST_F(DebounceTest, OneKeyLong) { | ||
| 111 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 112 | {0, {{0, 1, DOWN}}, {}}, | ||
| 113 | |||
| 114 | {5, {}, {{0, 1, DOWN}}}, | ||
| 115 | |||
| 116 | {25, {{0, 1, UP}}, {}}, | ||
| 117 | |||
| 118 | {30, {}, {{0, 1, UP}}}, | ||
| 119 | |||
| 120 | {50, {{0, 1, DOWN}}, {}}, | ||
| 121 | |||
| 122 | {55, {}, {{0, 1, DOWN}}}, | ||
| 123 | }); | ||
| 124 | runEvents(); | ||
| 125 | } | ||
| 126 | |||
| 127 | TEST_F(DebounceTest, TwoKeysShort) { | ||
| 128 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 129 | {0, {{0, 1, DOWN}}, {}}, | ||
| 130 | {1, {{0, 2, DOWN}}, {}}, | ||
| 131 | |||
| 132 | {5, {}, {{0, 1, DOWN}}}, | ||
| 133 | {6, {}, {{0, 2, DOWN}}}, | ||
| 134 | |||
| 135 | {7, {{0, 1, UP}}, {}}, | ||
| 136 | {8, {{0, 2, UP}}, {}}, | ||
| 137 | |||
| 138 | {12, {}, {{0, 1, UP}}}, | ||
| 139 | {13, {}, {{0, 2, UP}}}, | ||
| 140 | }); | ||
| 141 | runEvents(); | ||
| 142 | } | ||
| 143 | |||
| 144 | TEST_F(DebounceTest, TwoKeysSimultaneous1) { | ||
| 145 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 146 | {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}}, | ||
| 147 | |||
| 148 | {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}}, | ||
| 149 | {6, {{0, 1, UP}, {0, 2, UP}}, {}}, | ||
| 150 | |||
| 151 | {11, {}, {{0, 1, UP}, {0, 2, UP}}}, | ||
| 152 | }); | ||
| 153 | runEvents(); | ||
| 154 | } | ||
| 155 | |||
| 156 | TEST_F(DebounceTest, TwoKeysSimultaneous2) { | ||
| 157 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 158 | {0, {{0, 1, DOWN}}, {}}, | ||
| 159 | {1, {{0, 2, DOWN}}, {}}, | ||
| 160 | |||
| 161 | {5, {}, {{0, 1, DOWN}}}, | ||
| 162 | {6, {{0, 1, UP}}, {{0, 2, DOWN}}}, | ||
| 163 | {7, {{0, 2, UP}}, {}}, | ||
| 164 | |||
| 165 | {11, {}, {{0, 1, UP}}}, | ||
| 166 | {12, {}, {{0, 2, UP}}}, | ||
| 167 | }); | ||
| 168 | runEvents(); | ||
| 169 | } | ||
| 170 | |||
| 171 | TEST_F(DebounceTest, OneKeyDelayedScan1) { | ||
| 172 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 173 | {0, {{0, 1, DOWN}}, {}}, | ||
| 174 | |||
| 175 | /* Processing is very late */ | ||
| 176 | {300, {}, {{0, 1, DOWN}}}, | ||
| 177 | /* Immediately release key */ | ||
| 178 | {300, {{0, 1, UP}}, {}}, | ||
| 179 | |||
| 180 | {305, {}, {{0, 1, UP}}}, | ||
| 181 | }); | ||
| 182 | time_jumps_ = true; | ||
| 183 | runEvents(); | ||
| 184 | } | ||
| 185 | |||
| 186 | TEST_F(DebounceTest, OneKeyDelayedScan2) { | ||
| 187 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 188 | {0, {{0, 1, DOWN}}, {}}, | ||
| 189 | |||
| 190 | /* Processing is very late */ | ||
| 191 | {300, {}, {{0, 1, DOWN}}}, | ||
| 192 | /* Release key after 1ms */ | ||
| 193 | {301, {{0, 1, UP}}, {}}, | ||
| 194 | |||
| 195 | {306, {}, {{0, 1, UP}}}, | ||
| 196 | }); | ||
| 197 | time_jumps_ = true; | ||
| 198 | runEvents(); | ||
| 199 | } | ||
| 200 | |||
| 201 | TEST_F(DebounceTest, OneKeyDelayedScan3) { | ||
| 202 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 203 | {0, {{0, 1, DOWN}}, {}}, | ||
| 204 | |||
| 205 | /* Release key before debounce expires */ | ||
| 206 | {300, {{0, 1, UP}}, {}}, | ||
| 207 | }); | ||
| 208 | time_jumps_ = true; | ||
| 209 | runEvents(); | ||
| 210 | } | ||
| 211 | |||
| 212 | TEST_F(DebounceTest, OneKeyDelayedScan4) { | ||
| 213 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 214 | {0, {{0, 1, DOWN}}, {}}, | ||
| 215 | |||
| 216 | /* Processing is a bit late */ | ||
| 217 | {50, {}, {{0, 1, DOWN}}}, | ||
| 218 | /* Release key after 1ms */ | ||
| 219 | {51, {{0, 1, UP}}, {}}, | ||
| 220 | |||
| 221 | {56, {}, {{0, 1, UP}}}, | ||
| 222 | }); | ||
| 223 | time_jumps_ = true; | ||
| 224 | runEvents(); | ||
| 225 | } | ||
diff --git a/quantum/debounce/tests/sym_eager_pk_tests.cpp b/quantum/debounce/tests/sym_eager_pk_tests.cpp new file mode 100644 index 000000000..e0fc205e3 --- /dev/null +++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp | |||
| @@ -0,0 +1,237 @@ | |||
| 1 | /* Copyright 2021 Simon Arlott | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "gtest/gtest.h" | ||
| 18 | |||
| 19 | #include "debounce_test_common.h" | ||
| 20 | |||
| 21 | TEST_F(DebounceTest, OneKeyShort1) { | ||
| 22 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 23 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 24 | {1, {{0, 1, UP}}, {}}, | ||
| 25 | |||
| 26 | {5, {}, {{0, 1, UP}}}, | ||
| 27 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 28 | {6, {{0, 1, DOWN}}, {}}, | ||
| 29 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 30 | }); | ||
| 31 | runEvents(); | ||
| 32 | } | ||
| 33 | |||
| 34 | TEST_F(DebounceTest, OneKeyShort2) { | ||
| 35 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 36 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 37 | {1, {{0, 1, UP}}, {}}, | ||
| 38 | |||
| 39 | {5, {}, {{0, 1, UP}}}, | ||
| 40 | /* Press key again after 2ms delay (debounce has not yet finished) */ | ||
| 41 | {7, {{0, 1, DOWN}}, {}}, | ||
| 42 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 43 | }); | ||
| 44 | runEvents(); | ||
| 45 | } | ||
| 46 | |||
| 47 | TEST_F(DebounceTest, OneKeyShort3) { | ||
| 48 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 49 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 50 | {1, {{0, 1, UP}}, {}}, | ||
| 51 | |||
| 52 | {5, {}, {{0, 1, UP}}}, | ||
| 53 | /* Press key again after 3ms delay (debounce has not yet finished) */ | ||
| 54 | {8, {{0, 1, DOWN}}, {}}, | ||
| 55 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 56 | }); | ||
| 57 | runEvents(); | ||
| 58 | } | ||
| 59 | |||
| 60 | TEST_F(DebounceTest, OneKeyShort4) { | ||
| 61 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 62 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 63 | {1, {{0, 1, UP}}, {}}, | ||
| 64 | |||
| 65 | {5, {}, {{0, 1, UP}}}, | ||
| 66 | /* Press key again after 4ms delay (debounce has not yet finished) */ | ||
| 67 | {9, {{0, 1, DOWN}}, {}}, | ||
| 68 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 69 | }); | ||
| 70 | runEvents(); | ||
| 71 | } | ||
| 72 | |||
| 73 | TEST_F(DebounceTest, OneKeyShort5) { | ||
| 74 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 75 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 76 | {1, {{0, 1, UP}}, {}}, | ||
| 77 | |||
| 78 | {5, {}, {{0, 1, UP}}}, | ||
| 79 | /* Press key again after 5ms delay (debounce has finished) */ | ||
| 80 | {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 81 | }); | ||
| 82 | runEvents(); | ||
| 83 | } | ||
| 84 | |||
| 85 | TEST_F(DebounceTest, OneKeyShort6) { | ||
| 86 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 87 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 88 | {1, {{0, 1, UP}}, {}}, | ||
| 89 | |||
| 90 | {5, {}, {{0, 1, UP}}}, | ||
| 91 | /* Press key after after 6ms delay (debounce has finished) */ | ||
| 92 | {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 93 | }); | ||
| 94 | runEvents(); | ||
| 95 | } | ||
| 96 | |||
| 97 | TEST_F(DebounceTest, OneKeyBouncing1) { | ||
| 98 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 99 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 100 | {1, {{0, 1, UP}}, {}}, | ||
| 101 | {2, {{0, 1, DOWN}}, {}}, | ||
| 102 | {3, {{0, 1, UP}}, {}}, | ||
| 103 | {4, {{0, 1, DOWN}}, {}}, | ||
| 104 | {5, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 105 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 106 | {6, {{0, 1, DOWN}}, {}}, | ||
| 107 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 108 | }); | ||
| 109 | runEvents(); | ||
| 110 | } | ||
| 111 | |||
| 112 | TEST_F(DebounceTest, OneKeyBouncing2) { | ||
| 113 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 114 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 115 | /* Change twice in the same time period */ | ||
| 116 | {1, {{0, 1, UP}}, {}}, | ||
| 117 | {1, {{0, 1, DOWN}}, {}}, | ||
| 118 | /* Change three times in the same time period */ | ||
| 119 | {2, {{0, 1, UP}}, {}}, | ||
| 120 | {2, {{0, 1, DOWN}}, {}}, | ||
| 121 | {2, {{0, 1, UP}}, {}}, | ||
| 122 | /* Change three times in the same time period */ | ||
| 123 | {3, {{0, 1, DOWN}}, {}}, | ||
| 124 | {3, {{0, 1, UP}}, {}}, | ||
| 125 | {3, {{0, 1, DOWN}}, {}}, | ||
| 126 | /* Change twice in the same time period */ | ||
| 127 | {4, {{0, 1, UP}}, {}}, | ||
| 128 | {4, {{0, 1, DOWN}}, {}}, | ||
| 129 | {5, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 130 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 131 | {6, {{0, 1, DOWN}}, {}}, | ||
| 132 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 133 | }); | ||
| 134 | runEvents(); | ||
| 135 | } | ||
| 136 | |||
| 137 | TEST_F(DebounceTest, OneKeyLong) { | ||
| 138 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 139 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 140 | |||
| 141 | {25, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 142 | |||
| 143 | {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 144 | }); | ||
| 145 | runEvents(); | ||
| 146 | } | ||
| 147 | |||
| 148 | TEST_F(DebounceTest, TwoKeysShort) { | ||
| 149 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 150 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 151 | {1, {{0, 1, UP}}, {}}, | ||
| 152 | {2, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, | ||
| 153 | {3, {{0, 2, UP}}, {}}, | ||
| 154 | |||
| 155 | {5, {}, {{0, 1, UP}}}, | ||
| 156 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 157 | {6, {{0, 1, DOWN}}, {}}, | ||
| 158 | {7, {}, {{0, 2, UP}}}, | ||
| 159 | |||
| 160 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 161 | {9, {{0, 2, DOWN}}, {}}, | ||
| 162 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 163 | |||
| 164 | {12, {}, {{0, 2, DOWN}}}, /* 5ms after UP at time 7 */ | ||
| 165 | }); | ||
| 166 | runEvents(); | ||
| 167 | } | ||
| 168 | |||
| 169 | TEST_F(DebounceTest, OneKeyDelayedScan1) { | ||
| 170 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 171 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 172 | |||
| 173 | /* Processing is very late but the change will now be accepted */ | ||
| 174 | {300, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 175 | }); | ||
| 176 | time_jumps_ = true; | ||
| 177 | runEvents(); | ||
| 178 | } | ||
| 179 | |||
| 180 | TEST_F(DebounceTest, OneKeyDelayedScan2) { | ||
| 181 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 182 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 183 | |||
| 184 | /* Processing is very late but the change will now be accepted even with a 1 scan delay */ | ||
| 185 | {300, {}, {}}, | ||
| 186 | {300, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 187 | }); | ||
| 188 | time_jumps_ = true; | ||
| 189 | runEvents(); | ||
| 190 | } | ||
| 191 | |||
| 192 | TEST_F(DebounceTest, OneKeyDelayedScan3) { | ||
| 193 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 194 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 195 | |||
| 196 | /* Processing is very late but the change will now be accepted even with a 1ms delay */ | ||
| 197 | {300, {}, {}}, | ||
| 198 | {301, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 199 | }); | ||
| 200 | time_jumps_ = true; | ||
| 201 | runEvents(); | ||
| 202 | } | ||
| 203 | |||
| 204 | TEST_F(DebounceTest, OneKeyDelayedScan4) { | ||
| 205 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 206 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 207 | |||
| 208 | /* Processing is a bit late but the change will now be accepted */ | ||
| 209 | {50, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 210 | }); | ||
| 211 | time_jumps_ = true; | ||
| 212 | runEvents(); | ||
| 213 | } | ||
| 214 | |||
| 215 | TEST_F(DebounceTest, OneKeyDelayedScan5) { | ||
| 216 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 217 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 218 | |||
| 219 | /* Processing is very late but the change will now be accepted even with a 1 scan delay */ | ||
| 220 | {50, {}, {}}, | ||
| 221 | {50, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 222 | }); | ||
| 223 | time_jumps_ = true; | ||
| 224 | runEvents(); | ||
| 225 | } | ||
| 226 | |||
| 227 | TEST_F(DebounceTest, OneKeyDelayedScan6) { | ||
| 228 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 229 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 230 | |||
| 231 | /* Processing is very late but the change will now be accepted even with a 1ms delay */ | ||
| 232 | {50, {}, {}}, | ||
| 233 | {51, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 234 | }); | ||
| 235 | time_jumps_ = true; | ||
| 236 | runEvents(); | ||
| 237 | } | ||
diff --git a/quantum/debounce/tests/sym_eager_pr_tests.cpp b/quantum/debounce/tests/sym_eager_pr_tests.cpp new file mode 100644 index 000000000..2c4bca127 --- /dev/null +++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp | |||
| @@ -0,0 +1,280 @@ | |||
| 1 | /* Copyright 2021 Simon Arlott | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "gtest/gtest.h" | ||
| 18 | |||
| 19 | #include "debounce_test_common.h" | ||
| 20 | |||
| 21 | TEST_F(DebounceTest, OneKeyShort1) { | ||
| 22 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 23 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 24 | {1, {{0, 1, UP}}, {}}, | ||
| 25 | |||
| 26 | {5, {}, {{0, 1, UP}}}, | ||
| 27 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 28 | {6, {{0, 1, DOWN}}, {}}, | ||
| 29 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 30 | }); | ||
| 31 | runEvents(); | ||
| 32 | } | ||
| 33 | |||
| 34 | TEST_F(DebounceTest, OneKeyShort2) { | ||
| 35 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 36 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 37 | {1, {{0, 1, UP}}, {}}, | ||
| 38 | |||
| 39 | {5, {}, {{0, 1, UP}}}, | ||
| 40 | /* Press key again after 2ms delay (debounce has not yet finished) */ | ||
| 41 | {7, {{0, 1, DOWN}}, {}}, | ||
| 42 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 43 | }); | ||
| 44 | runEvents(); | ||
| 45 | } | ||
| 46 | |||
| 47 | TEST_F(DebounceTest, OneKeyShort3) { | ||
| 48 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 49 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 50 | {1, {{0, 1, UP}}, {}}, | ||
| 51 | |||
| 52 | {5, {}, {{0, 1, UP}}}, | ||
| 53 | /* Press key again after 3ms delay (debounce has not yet finished) */ | ||
| 54 | {8, {{0, 1, DOWN}}, {}}, | ||
| 55 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 56 | }); | ||
| 57 | runEvents(); | ||
| 58 | } | ||
| 59 | |||
| 60 | TEST_F(DebounceTest, OneKeyShort4) { | ||
| 61 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 62 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 63 | {1, {{0, 1, UP}}, {}}, | ||
| 64 | |||
| 65 | {5, {}, {{0, 1, UP}}}, | ||
| 66 | /* Press key again after 4ms delay (debounce has not yet finished) */ | ||
| 67 | {9, {{0, 1, DOWN}}, {}}, | ||
| 68 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 69 | }); | ||
| 70 | runEvents(); | ||
| 71 | } | ||
| 72 | |||
| 73 | TEST_F(DebounceTest, OneKeyShort5) { | ||
| 74 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 75 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 76 | {1, {{0, 1, UP}}, {}}, | ||
| 77 | |||
| 78 | {5, {}, {{0, 1, UP}}}, | ||
| 79 | /* Press key again after 5ms delay (debounce has finished) */ | ||
| 80 | {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 81 | }); | ||
| 82 | runEvents(); | ||
| 83 | } | ||
| 84 | |||
| 85 | TEST_F(DebounceTest, OneKeyShort6) { | ||
| 86 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 87 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 88 | {1, {{0, 1, UP}}, {}}, | ||
| 89 | |||
| 90 | {5, {}, {{0, 1, UP}}}, | ||
| 91 | /* Press key after after 6ms delay (debounce has finished) */ | ||
| 92 | {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 93 | }); | ||
| 94 | runEvents(); | ||
| 95 | } | ||
| 96 | |||
| 97 | TEST_F(DebounceTest, OneKeyBouncing1) { | ||
| 98 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 99 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 100 | {1, {{0, 1, UP}}, {}}, | ||
| 101 | {2, {{0, 1, DOWN}}, {}}, | ||
| 102 | {3, {{0, 1, UP}}, {}}, | ||
| 103 | {4, {{0, 1, DOWN}}, {}}, | ||
| 104 | {5, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 105 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 106 | {6, {{0, 1, DOWN}}, {}}, | ||
| 107 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 108 | }); | ||
| 109 | runEvents(); | ||
| 110 | } | ||
| 111 | |||
| 112 | TEST_F(DebounceTest, OneKeyBouncing2) { | ||
| 113 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 114 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 115 | /* Change twice in the same time period */ | ||
| 116 | {1, {{0, 1, UP}}, {}}, | ||
| 117 | {1, {{0, 1, DOWN}}, {}}, | ||
| 118 | /* Change three times in the same time period */ | ||
| 119 | {2, {{0, 1, UP}}, {}}, | ||
| 120 | {2, {{0, 1, DOWN}}, {}}, | ||
| 121 | {2, {{0, 1, UP}}, {}}, | ||
| 122 | /* Change three times in the same time period */ | ||
| 123 | {3, {{0, 1, DOWN}}, {}}, | ||
| 124 | {3, {{0, 1, UP}}, {}}, | ||
| 125 | {3, {{0, 1, DOWN}}, {}}, | ||
| 126 | /* Change twice in the same time period */ | ||
| 127 | {4, {{0, 1, UP}}, {}}, | ||
| 128 | {4, {{0, 1, DOWN}}, {}}, | ||
| 129 | {5, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 130 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 131 | {6, {{0, 1, DOWN}}, {}}, | ||
| 132 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 133 | }); | ||
| 134 | runEvents(); | ||
| 135 | } | ||
| 136 | |||
| 137 | TEST_F(DebounceTest, OneKeyLong) { | ||
| 138 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 139 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 140 | |||
| 141 | {25, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 142 | |||
| 143 | {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 144 | }); | ||
| 145 | runEvents(); | ||
| 146 | } | ||
| 147 | |||
| 148 | TEST_F(DebounceTest, TwoRowsShort) { | ||
| 149 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 150 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 151 | {1, {{0, 1, UP}}, {}}, | ||
| 152 | {2, {{2, 0, DOWN}}, {{2, 0, DOWN}}}, | ||
| 153 | {3, {{2, 0, UP}}, {}}, | ||
| 154 | |||
| 155 | {5, {}, {{0, 1, UP}}}, | ||
| 156 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 157 | {6, {{0, 1, DOWN}}, {}}, | ||
| 158 | {7, {}, {{2, 0, UP}}}, | ||
| 159 | |||
| 160 | /* Press key again after 1ms delay (debounce has not yet finished) */ | ||
| 161 | {9, {{2, 0, DOWN}}, {}}, | ||
| 162 | {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */ | ||
| 163 | |||
| 164 | {12, {}, {{2, 0, DOWN}}}, /* 5ms after UP at time 7 */ | ||
| 165 | }); | ||
| 166 | runEvents(); | ||
| 167 | } | ||
| 168 | |||
| 169 | TEST_F(DebounceTest, TwoKeysOverlap) { | ||
| 170 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 171 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 172 | {1, {{0, 1, UP}}, {}}, | ||
| 173 | /* Press a second key during the first debounce */ | ||
| 174 | {2, {{0, 2, DOWN}}, {}}, | ||
| 175 | |||
| 176 | /* Key registers as soon as debounce finishes, 5ms after time 0 */ | ||
| 177 | {5, {}, {{0, 1, UP}, {0, 2, DOWN}}}, | ||
| 178 | {6, {{0, 1, DOWN}}, {}}, | ||
| 179 | |||
| 180 | /* Key registers as soon as debounce finishes, 5ms after time 5 */ | ||
| 181 | {10, {}, {{0, 1, DOWN}}}, | ||
| 182 | /* Release both keys */ | ||
| 183 | {11, {{0, 1, UP}}, {}}, | ||
| 184 | {12, {{0, 2, UP}}, {}}, | ||
| 185 | |||
| 186 | /* Keys register as soon as debounce finishes, 5ms after time 10 */ | ||
| 187 | {15, {}, {{0, 1, UP}, {0, 2, UP}}}, | ||
| 188 | }); | ||
| 189 | runEvents(); | ||
| 190 | } | ||
| 191 | |||
| 192 | TEST_F(DebounceTest, TwoKeysSimultaneous1) { | ||
| 193 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 194 | {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}}, | ||
| 195 | {20, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 196 | {21, {{0, 2, UP}}, {}}, | ||
| 197 | |||
| 198 | /* Key registers as soon as debounce finishes, 5ms after time 20 */ | ||
| 199 | {25, {}, {{0, 2, UP}}}, | ||
| 200 | }); | ||
| 201 | runEvents(); | ||
| 202 | } | ||
| 203 | |||
| 204 | TEST_F(DebounceTest, TwoKeysSimultaneous2) { | ||
| 205 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 206 | {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}}, | ||
| 207 | {20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}}, | ||
| 208 | }); | ||
| 209 | runEvents(); | ||
| 210 | } | ||
| 211 | |||
| 212 | TEST_F(DebounceTest, OneKeyDelayedScan1) { | ||
| 213 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 214 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 215 | |||
| 216 | /* Processing is very late but the change will now be accepted */ | ||
| 217 | {300, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 218 | }); | ||
| 219 | time_jumps_ = true; | ||
| 220 | runEvents(); | ||
| 221 | } | ||
| 222 | |||
| 223 | TEST_F(DebounceTest, OneKeyDelayedScan2) { | ||
| 224 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 225 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 226 | |||
| 227 | /* Processing is very late but the change will now be accepted even with a 1 scan delay */ | ||
| 228 | {300, {}, {}}, | ||
| 229 | {300, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 230 | }); | ||
| 231 | time_jumps_ = true; | ||
| 232 | runEvents(); | ||
| 233 | } | ||
| 234 | |||
| 235 | TEST_F(DebounceTest, OneKeyDelayedScan3) { | ||
| 236 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 237 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 238 | |||
| 239 | /* Processing is very late but the change will now be accepted even with a 1ms delay */ | ||
| 240 | {300, {}, {}}, | ||
| 241 | {301, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 242 | }); | ||
| 243 | time_jumps_ = true; | ||
| 244 | runEvents(); | ||
| 245 | } | ||
| 246 | |||
| 247 | TEST_F(DebounceTest, OneKeyDelayedScan4) { | ||
| 248 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 249 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 250 | |||
| 251 | /* Processing is a bit late but the change will now be accepted */ | ||
| 252 | {50, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 253 | }); | ||
| 254 | time_jumps_ = true; | ||
| 255 | runEvents(); | ||
| 256 | } | ||
| 257 | |||
| 258 | TEST_F(DebounceTest, OneKeyDelayedScan5) { | ||
| 259 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 260 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 261 | |||
| 262 | /* Processing is very late but the change will now be accepted even with a 1 scan delay */ | ||
| 263 | {50, {}, {}}, | ||
| 264 | {50, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 265 | }); | ||
| 266 | time_jumps_ = true; | ||
| 267 | runEvents(); | ||
| 268 | } | ||
| 269 | |||
| 270 | TEST_F(DebounceTest, OneKeyDelayedScan6) { | ||
| 271 | addEvents({ /* Time, Inputs, Outputs */ | ||
| 272 | {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}}, | ||
| 273 | |||
| 274 | /* Processing is very late but the change will now be accepted even with a 1ms delay */ | ||
| 275 | {50, {}, {}}, | ||
| 276 | {51, {{0, 1, UP}}, {{0, 1, UP}}}, | ||
| 277 | }); | ||
| 278 | time_jumps_ = true; | ||
| 279 | runEvents(); | ||
| 280 | } | ||
diff --git a/quantum/debounce/tests/testlist.mk b/quantum/debounce/tests/testlist.mk new file mode 100644 index 000000000..c54c45aa6 --- /dev/null +++ b/quantum/debounce/tests/testlist.mk | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | TEST_LIST += \ | ||
| 2 | debounce_sym_defer_g \ | ||
| 3 | debounce_sym_defer_pk \ | ||
| 4 | debounce_sym_eager_pk \ | ||
| 5 | debounce_sym_eager_pr \ | ||
| 6 | debounce_asym_eager_defer_pk | ||
diff --git a/quantum/led_matrix_animations/alpha_mods_anim.h b/quantum/led_matrix/animations/alpha_mods_anim.h index 6f69f6892..a4638fde6 100644 --- a/quantum/led_matrix_animations/alpha_mods_anim.h +++ b/quantum/led_matrix/animations/alpha_mods_anim.h | |||
| @@ -21,4 +21,4 @@ bool ALPHAS_MODS(effect_params_t* params) { | |||
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 23 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 24 | #endif // DISABLE_LED_MATRIX_ALPHAS_MODS | 24 | #endif // DISABLE_LED_MATRIX_ALPHAS_MODS |
diff --git a/quantum/led_matrix_animations/band_anim.h b/quantum/led_matrix/animations/band_anim.h index 523dba1b7..f9cb85dc4 100644 --- a/quantum/led_matrix_animations/band_anim.h +++ b/quantum/led_matrix/animations/band_anim.h | |||
| @@ -10,4 +10,4 @@ static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) { | |||
| 10 | bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); } | 10 | bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); } |
| 11 | 11 | ||
| 12 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 12 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 13 | #endif // DISABLE_LED_MATRIX_BAND | 13 | #endif // DISABLE_LED_MATRIX_BAND |
diff --git a/quantum/led_matrix_animations/band_pinwheel_anim.h b/quantum/led_matrix/animations/band_pinwheel_anim.h index fb3b835ca..d3144bffb 100644 --- a/quantum/led_matrix_animations/band_pinwheel_anim.h +++ b/quantum/led_matrix/animations/band_pinwheel_anim.h | |||
| @@ -7,4 +7,4 @@ static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t t | |||
| 7 | bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); } | 7 | bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); } |
| 8 | 8 | ||
| 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 10 | #endif // DISABLE_LED_MATRIX_BAND_PINWHEEL | 10 | #endif // DISABLE_LED_MATRIX_BAND_PINWHEEL |
diff --git a/quantum/led_matrix_animations/band_spiral_anim.h b/quantum/led_matrix/animations/band_spiral_anim.h index fca22aad9..defbe6967 100644 --- a/quantum/led_matrix_animations/band_spiral_anim.h +++ b/quantum/led_matrix/animations/band_spiral_anim.h | |||
| @@ -7,4 +7,4 @@ static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dis | |||
| 7 | bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); } | 7 | bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); } |
| 8 | 8 | ||
| 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 10 | #endif // DISABLE_LED_MATRIX_BAND_SPIRAL | 10 | #endif // DISABLE_LED_MATRIX_BAND_SPIRAL |
diff --git a/quantum/led_matrix_animations/breathing_anim.h b/quantum/led_matrix/animations/breathing_anim.h index 00310e3f6..4f49f5069 100644 --- a/quantum/led_matrix_animations/breathing_anim.h +++ b/quantum/led_matrix/animations/breathing_anim.h | |||
| @@ -16,4 +16,4 @@ bool BREATHING(effect_params_t* params) { | |||
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 18 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 19 | #endif // DISABLE_LED_MATRIX_BREATHING | 19 | #endif // DISABLE_LED_MATRIX_BREATHING |
diff --git a/quantum/led_matrix_animations/cycle_left_right_anim.h b/quantum/led_matrix/animations/cycle_left_right_anim.h index 51e81d57c..c426d02fd 100644 --- a/quantum/led_matrix_animations/cycle_left_right_anim.h +++ b/quantum/led_matrix/animations/cycle_left_right_anim.h | |||
| @@ -7,4 +7,4 @@ static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { ret | |||
| 7 | bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); } | 7 | bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); } |
| 8 | 8 | ||
| 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 10 | #endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT | 10 | #endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT |
diff --git a/quantum/led_matrix_animations/cycle_out_in_anim.h b/quantum/led_matrix/animations/cycle_out_in_anim.h index f62061552..55527556f 100644 --- a/quantum/led_matrix_animations/cycle_out_in_anim.h +++ b/quantum/led_matrix/animations/cycle_out_in_anim.h | |||
| @@ -7,4 +7,4 @@ static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t di | |||
| 7 | bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); } | 7 | bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); } |
| 8 | 8 | ||
| 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 10 | #endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN | 10 | #endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN |
diff --git a/quantum/led_matrix_animations/cycle_up_down_anim.h b/quantum/led_matrix/animations/cycle_up_down_anim.h index bd1d12567..d97de0d1e 100644 --- a/quantum/led_matrix_animations/cycle_up_down_anim.h +++ b/quantum/led_matrix/animations/cycle_up_down_anim.h | |||
| @@ -7,4 +7,4 @@ static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return | |||
| 7 | bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); } | 7 | bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); } |
| 8 | 8 | ||
| 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 10 | #endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN | 10 | #endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN |
diff --git a/quantum/led_matrix_animations/dual_beacon_anim.h b/quantum/led_matrix/animations/dual_beacon_anim.h index 9b8a7877c..e1bc5ae46 100644 --- a/quantum/led_matrix_animations/dual_beacon_anim.h +++ b/quantum/led_matrix/animations/dual_beacon_anim.h | |||
| @@ -7,4 +7,4 @@ static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, | |||
| 7 | bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); } | 7 | bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); } |
| 8 | 8 | ||
| 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 10 | #endif // DISABLE_LED_MATRIX_DUAL_BEACON | 10 | #endif // DISABLE_LED_MATRIX_DUAL_BEACON |
diff --git a/quantum/led_matrix/animations/led_matrix_effects.inc b/quantum/led_matrix/animations/led_matrix_effects.inc new file mode 100644 index 000000000..ad1f46b24 --- /dev/null +++ b/quantum/led_matrix/animations/led_matrix_effects.inc | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Add your new core led matrix effect here, order determines enum order | ||
| 2 | #include "solid_anim.h" | ||
| 3 | #include "alpha_mods_anim.h" | ||
| 4 | #include "breathing_anim.h" | ||
| 5 | #include "band_anim.h" | ||
| 6 | #include "band_pinwheel_anim.h" | ||
| 7 | #include "band_spiral_anim.h" | ||
| 8 | #include "cycle_left_right_anim.h" | ||
| 9 | #include "cycle_up_down_anim.h" | ||
| 10 | #include "cycle_out_in_anim.h" | ||
| 11 | #include "dual_beacon_anim.h" | ||
| 12 | #include "solid_reactive_simple_anim.h" | ||
| 13 | #include "solid_reactive_wide.h" | ||
| 14 | #include "solid_reactive_cross.h" | ||
| 15 | #include "solid_reactive_nexus.h" | ||
| 16 | #include "solid_splash_anim.h" | ||
| 17 | #include "wave_left_right_anim.h" | ||
| 18 | #include "wave_up_down_anim.h" | ||
diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h index ef97631b9..ef97631b9 100644 --- a/quantum/led_matrix_runners/effect_runner_dx_dy.h +++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h | |||
diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h index 5ef5938be..5ef5938be 100644 --- a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h +++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h | |||
diff --git a/quantum/led_matrix_runners/effect_runner_i.h b/quantum/led_matrix/animations/runners/effect_runner_i.h index b3015759b..b3015759b 100644 --- a/quantum/led_matrix_runners/effect_runner_i.h +++ b/quantum/led_matrix/animations/runners/effect_runner_i.h | |||
diff --git a/quantum/led_matrix_runners/effect_runner_reactive.h b/quantum/led_matrix/animations/runners/effect_runner_reactive.h index 4369ea8c4..4369ea8c4 100644 --- a/quantum/led_matrix_runners/effect_runner_reactive.h +++ b/quantum/led_matrix/animations/runners/effect_runner_reactive.h | |||
diff --git a/quantum/led_matrix_runners/effect_runner_reactive_splash.h b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h index d6eb9731e..d6eb9731e 100644 --- a/quantum/led_matrix_runners/effect_runner_reactive_splash.h +++ b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h | |||
diff --git a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h index 4a5219abd..4a5219abd 100644 --- a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h +++ b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h | |||
diff --git a/quantum/led_matrix/animations/runners/led_matrix_runners.inc b/quantum/led_matrix/animations/runners/led_matrix_runners.inc new file mode 100644 index 000000000..c09022bb0 --- /dev/null +++ b/quantum/led_matrix/animations/runners/led_matrix_runners.inc | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #include "effect_runner_dx_dy_dist.h" | ||
| 2 | #include "effect_runner_dx_dy.h" | ||
| 3 | #include "effect_runner_i.h" | ||
| 4 | #include "effect_runner_sin_cos_i.h" | ||
| 5 | #include "effect_runner_reactive.h" | ||
| 6 | #include "effect_runner_reactive_splash.h" | ||
diff --git a/quantum/led_matrix_animations/solid_anim.h b/quantum/led_matrix/animations/solid_anim.h index 4c9e43c58..4c9e43c58 100644 --- a/quantum/led_matrix_animations/solid_anim.h +++ b/quantum/led_matrix/animations/solid_anim.h | |||
diff --git a/quantum/led_matrix_animations/solid_reactive_cross.h b/quantum/led_matrix/animations/solid_reactive_cross.h index f402d99b3..94425c959 100644 --- a/quantum/led_matrix_animations/solid_reactive_cross.h +++ b/quantum/led_matrix/animations/solid_reactive_cross.h | |||
| @@ -31,5 +31,5 @@ bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_r | |||
| 31 | # endif | 31 | # endif |
| 32 | 32 | ||
| 33 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 33 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 34 | # endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) | 34 | # endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) |
| 35 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED | 35 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED |
diff --git a/quantum/led_matrix_animations/solid_reactive_nexus.h b/quantum/led_matrix/animations/solid_reactive_nexus.h index 4d0d25226..504b1104f 100644 --- a/quantum/led_matrix_animations/solid_reactive_nexus.h +++ b/quantum/led_matrix/animations/solid_reactive_nexus.h | |||
| @@ -28,5 +28,5 @@ bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_r | |||
| 28 | # endif | 28 | # endif |
| 29 | 29 | ||
| 30 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 30 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 31 | # endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) | 31 | # endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) |
| 32 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED | 32 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED |
diff --git a/quantum/led_matrix_animations/solid_reactive_simple_anim.h b/quantum/led_matrix/animations/solid_reactive_simple_anim.h index 30e2527f6..4752a8416 100644 --- a/quantum/led_matrix_animations/solid_reactive_simple_anim.h +++ b/quantum/led_matrix/animations/solid_reactive_simple_anim.h | |||
| @@ -8,5 +8,5 @@ static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return | |||
| 8 | bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); } | 8 | bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); } |
| 9 | 9 | ||
| 10 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 10 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 11 | # endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE | 11 | # endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE |
| 12 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED | 12 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED |
diff --git a/quantum/led_matrix_animations/solid_reactive_wide.h b/quantum/led_matrix/animations/solid_reactive_wide.h index 34a230c25..922e32fe5 100644 --- a/quantum/led_matrix_animations/solid_reactive_wide.h +++ b/quantum/led_matrix/animations/solid_reactive_wide.h | |||
| @@ -26,5 +26,5 @@ bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_re | |||
| 26 | # endif | 26 | # endif |
| 27 | 27 | ||
| 28 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 28 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 29 | # endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) | 29 | # endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) |
| 30 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED | 30 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED |
diff --git a/quantum/led_matrix_animations/solid_splash_anim.h b/quantum/led_matrix/animations/solid_splash_anim.h index 4f6ba3d34..d95889b81 100644 --- a/quantum/led_matrix_animations/solid_splash_anim.h +++ b/quantum/led_matrix/animations/solid_splash_anim.h | |||
| @@ -26,5 +26,5 @@ bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_ | |||
| 26 | # endif | 26 | # endif |
| 27 | 27 | ||
| 28 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 28 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 29 | # endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) | 29 | # endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) |
| 30 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED | 30 | #endif // LED_MATRIX_KEYREACTIVE_ENABLED |
diff --git a/quantum/led_matrix_animations/wave_left_right_anim.h b/quantum/led_matrix/animations/wave_left_right_anim.h index 736f22ddc..8579f1b45 100644 --- a/quantum/led_matrix_animations/wave_left_right_anim.h +++ b/quantum/led_matrix/animations/wave_left_right_anim.h | |||
| @@ -7,4 +7,4 @@ static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { retu | |||
| 7 | bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); } | 7 | bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); } |
| 8 | 8 | ||
| 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 10 | #endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT | 10 | #endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT |
diff --git a/quantum/led_matrix_animations/wave_up_down_anim.h b/quantum/led_matrix/animations/wave_up_down_anim.h index 3cab0597d..635c60841 100644 --- a/quantum/led_matrix_animations/wave_up_down_anim.h +++ b/quantum/led_matrix/animations/wave_up_down_anim.h | |||
| @@ -7,4 +7,4 @@ static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return | |||
| 7 | bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); } | 7 | bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); } |
| 8 | 8 | ||
| 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS | 9 | # endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 10 | #endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN | 10 | #endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN |
diff --git a/quantum/led_matrix.c b/quantum/led_matrix/led_matrix.c index 7e0fdf896..32788866c 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix/led_matrix.c | |||
| @@ -33,20 +33,23 @@ const led_point_t k_led_matrix_center = {112, 32}; | |||
| 33 | const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; | 33 | const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | // clang-format off | ||
| 37 | #ifndef LED_MATRIX_IMMEDIATE_EEPROM | ||
| 38 | # define led_eeconfig_update(v) led_update_eeprom |= v | ||
| 39 | #else | ||
| 40 | # define led_eeconfig_update(v) if (v) eeconfig_update_led_matrix() | ||
| 41 | #endif | ||
| 42 | // clang-format on | ||
| 43 | |||
| 36 | // Generic effect runners | 44 | // Generic effect runners |
| 37 | #include "led_matrix_runners/effect_runner_dx_dy_dist.h" | 45 | #include "led_matrix_runners.inc" |
| 38 | #include "led_matrix_runners/effect_runner_dx_dy.h" | ||
| 39 | #include "led_matrix_runners/effect_runner_i.h" | ||
| 40 | #include "led_matrix_runners/effect_runner_sin_cos_i.h" | ||
| 41 | #include "led_matrix_runners/effect_runner_reactive.h" | ||
| 42 | #include "led_matrix_runners/effect_runner_reactive_splash.h" | ||
| 43 | 46 | ||
| 44 | // ------------------------------------------ | 47 | // ------------------------------------------ |
| 45 | // -----Begin led effect includes macros----- | 48 | // -----Begin led effect includes macros----- |
| 46 | #define LED_MATRIX_EFFECT(name) | 49 | #define LED_MATRIX_EFFECT(name) |
| 47 | #define LED_MATRIX_CUSTOM_EFFECT_IMPLS | 50 | #define LED_MATRIX_CUSTOM_EFFECT_IMPLS |
| 48 | 51 | ||
| 49 | #include "led_matrix_animations/led_matrix_effects.inc" | 52 | #include "led_matrix_effects.inc" |
| 50 | #ifdef LED_MATRIX_CUSTOM_KB | 53 | #ifdef LED_MATRIX_CUSTOM_KB |
| 51 | # include "led_matrix_kb.inc" | 54 | # include "led_matrix_kb.inc" |
| 52 | #endif | 55 | #endif |
| @@ -67,10 +70,6 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER; | |||
| 67 | # define LED_DISABLE_TIMEOUT 0 | 70 | # define LED_DISABLE_TIMEOUT 0 |
| 68 | #endif | 71 | #endif |
| 69 | 72 | ||
| 70 | #if LED_DISABLE_WHEN_USB_SUSPENDED != 1 | ||
| 71 | # undef LED_DISABLE_WHEN_USB_SUSPENDED | ||
| 72 | #endif | ||
| 73 | |||
| 74 | #if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX | 73 | #if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX |
| 75 | # undef LED_MATRIX_MAXIMUM_BRIGHTNESS | 74 | # undef LED_MATRIX_MAXIMUM_BRIGHTNESS |
| 76 | # define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX | 75 | # define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX |
| @@ -108,6 +107,7 @@ last_hit_t g_last_hit_tracker; | |||
| 108 | 107 | ||
| 109 | // internals | 108 | // internals |
| 110 | static bool suspend_state = false; | 109 | static bool suspend_state = false; |
| 110 | static bool led_update_eeprom = false; | ||
| 111 | static uint8_t led_last_enable = UINT8_MAX; | 111 | static uint8_t led_last_enable = UINT8_MAX; |
| 112 | static uint8_t led_last_effect = UINT8_MAX; | 112 | static uint8_t led_last_effect = UINT8_MAX; |
| 113 | static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; | 113 | static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; |
| @@ -280,6 +280,8 @@ static void led_task_timers(void) { | |||
| 280 | 280 | ||
| 281 | static void led_task_sync(void) { | 281 | static void led_task_sync(void) { |
| 282 | // next task | 282 | // next task |
| 283 | if (led_update_eeprom) eeconfig_update_led_matrix(); | ||
| 284 | led_update_eeprom = false; | ||
| 283 | if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING; | 285 | if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING; |
| 284 | } | 286 | } |
| 285 | 287 | ||
| @@ -318,7 +320,7 @@ static void led_task_render(uint8_t effect) { | |||
| 318 | case LED_MATRIX_##name: \ | 320 | case LED_MATRIX_##name: \ |
| 319 | rendering = name(&led_effect_params); \ | 321 | rendering = name(&led_effect_params); \ |
| 320 | break; | 322 | break; |
| 321 | #include "led_matrix_animations/led_matrix_effects.inc" | 323 | #include "led_matrix_effects.inc" |
| 322 | #undef LED_MATRIX_EFFECT | 324 | #undef LED_MATRIX_EFFECT |
| 323 | 325 | ||
| 324 | #if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) | 326 | #if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) |
| @@ -469,9 +471,7 @@ bool led_matrix_get_suspend_state(void) { return suspend_state; } | |||
| 469 | void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { | 471 | void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) { |
| 470 | led_matrix_eeconfig.enable ^= 1; | 472 | led_matrix_eeconfig.enable ^= 1; |
| 471 | led_task_state = STARTING; | 473 | led_task_state = STARTING; |
| 472 | if (write_to_eeprom) { | 474 | led_eeconfig_update(write_to_eeprom); |
| 473 | eeconfig_update_led_matrix(); | ||
| 474 | } | ||
| 475 | dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable); | 475 | dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable); |
| 476 | } | 476 | } |
| 477 | void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); } | 477 | 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); } | |||
| 479 | 479 | ||
| 480 | void led_matrix_enable(void) { | 480 | void led_matrix_enable(void) { |
| 481 | led_matrix_enable_noeeprom(); | 481 | led_matrix_enable_noeeprom(); |
| 482 | eeconfig_update_led_matrix(); | 482 | led_eeconfig_update(true); |
| 483 | } | 483 | } |
| 484 | 484 | ||
| 485 | void led_matrix_enable_noeeprom(void) { | 485 | void led_matrix_enable_noeeprom(void) { |
| @@ -489,7 +489,7 @@ void led_matrix_enable_noeeprom(void) { | |||
| 489 | 489 | ||
| 490 | void led_matrix_disable(void) { | 490 | void led_matrix_disable(void) { |
| 491 | led_matrix_disable_noeeprom(); | 491 | led_matrix_disable_noeeprom(); |
| 492 | eeconfig_update_led_matrix(); | 492 | led_eeconfig_update(true); |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | void led_matrix_disable_noeeprom(void) { | 495 | void led_matrix_disable_noeeprom(void) { |
| @@ -511,9 +511,7 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { | |||
| 511 | led_matrix_eeconfig.mode = mode; | 511 | led_matrix_eeconfig.mode = mode; |
| 512 | } | 512 | } |
| 513 | led_task_state = STARTING; | 513 | led_task_state = STARTING; |
| 514 | if (write_to_eeprom) { | 514 | led_eeconfig_update(write_to_eeprom); |
| 515 | eeconfig_update_led_matrix(); | ||
| 516 | } | ||
| 517 | dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode); | 515 | dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode); |
| 518 | } | 516 | } |
| 519 | void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); } | 517 | 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) { | |||
| 540 | return; | 538 | return; |
| 541 | } | 539 | } |
| 542 | led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; | 540 | led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; |
| 543 | if (write_to_eeprom) { | 541 | led_eeconfig_update(write_to_eeprom); |
| 544 | eeconfig_update_led_matrix(); | ||
| 545 | } | ||
| 546 | dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val); | 542 | dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val); |
| 547 | } | 543 | } |
| 548 | void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); } | 544 | 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); } | |||
| 560 | 556 | ||
| 561 | void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { | 557 | void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { |
| 562 | led_matrix_eeconfig.speed = speed; | 558 | led_matrix_eeconfig.speed = speed; |
| 563 | if (write_to_eeprom) { | 559 | led_eeconfig_update(write_to_eeprom); |
| 564 | eeconfig_update_led_matrix(); | ||
| 565 | } | ||
| 566 | dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed); | 560 | dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed); |
| 567 | } | 561 | } |
| 568 | void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); } | 562 | 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 0984de73b..6f85854fb 100644 --- a/quantum/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h | |||
| @@ -56,7 +56,7 @@ enum led_matrix_effects { | |||
| 56 | // -------------------------------------- | 56 | // -------------------------------------- |
| 57 | // -----Begin led effect enum macros----- | 57 | // -----Begin led effect enum macros----- |
| 58 | #define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name, | 58 | #define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name, |
| 59 | #include "led_matrix_animations/led_matrix_effects.inc" | 59 | #include "led_matrix_effects.inc" |
| 60 | #undef LED_MATRIX_EFFECT | 60 | #undef LED_MATRIX_EFFECT |
| 61 | 61 | ||
| 62 | #if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) | 62 | #if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) |
diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c index 1d46b2c50..1d46b2c50 100644 --- a/quantum/led_matrix_drivers.c +++ b/quantum/led_matrix/led_matrix_drivers.c | |||
diff --git a/quantum/led_matrix_types.h b/quantum/led_matrix/led_matrix_types.h index 61cdbd9b8..61cdbd9b8 100644 --- a/quantum/led_matrix_types.h +++ b/quantum/led_matrix/led_matrix_types.h | |||
diff --git a/quantum/led_matrix_animations/led_matrix_effects.inc b/quantum/led_matrix_animations/led_matrix_effects.inc deleted file mode 100644 index 67237c568..000000000 --- a/quantum/led_matrix_animations/led_matrix_effects.inc +++ /dev/null | |||
| @@ -1,18 +0,0 @@ | |||
| 1 | // Add your new core led matrix effect here, order determins enum order, requires "led_matrix_animations/ directory | ||
| 2 | #include "led_matrix_animations/solid_anim.h" | ||
| 3 | #include "led_matrix_animations/alpha_mods_anim.h" | ||
| 4 | #include "led_matrix_animations/breathing_anim.h" | ||
| 5 | #include "led_matrix_animations/band_anim.h" | ||
| 6 | #include "led_matrix_animations/band_pinwheel_anim.h" | ||
| 7 | #include "led_matrix_animations/band_spiral_anim.h" | ||
| 8 | #include "led_matrix_animations/cycle_left_right_anim.h" | ||
| 9 | #include "led_matrix_animations/cycle_up_down_anim.h" | ||
| 10 | #include "led_matrix_animations/cycle_out_in_anim.h" | ||
| 11 | #include "led_matrix_animations/dual_beacon_anim.h" | ||
| 12 | #include "led_matrix_animations/solid_reactive_simple_anim.h" | ||
| 13 | #include "led_matrix_animations/solid_reactive_wide.h" | ||
| 14 | #include "led_matrix_animations/solid_reactive_cross.h" | ||
| 15 | #include "led_matrix_animations/solid_reactive_nexus.h" | ||
| 16 | #include "led_matrix_animations/solid_splash_anim.h" | ||
| 17 | #include "led_matrix_animations/wave_left_right_anim.h" | ||
| 18 | #include "led_matrix_animations/wave_up_down_anim.h" | ||
diff --git a/quantum/matrix.c b/quantum/matrix.c index 34d6af2e6..71ef27089 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/>. | |||
| 16 | */ | 16 | */ |
| 17 | #include <stdint.h> | 17 | #include <stdint.h> |
| 18 | #include <stdbool.h> | 18 | #include <stdbool.h> |
| 19 | #include <string.h> | ||
| 19 | #include "util.h" | 20 | #include "util.h" |
| 20 | #include "matrix.h" | 21 | #include "matrix.h" |
| 21 | #include "debounce.h" | 22 | #include "debounce.h" |
| @@ -24,14 +25,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 24 | #ifdef DIRECT_PINS | 25 | #ifdef DIRECT_PINS |
| 25 | static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; | 26 | static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; |
| 26 | #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) | 27 | #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) |
| 28 | # ifdef MATRIX_ROW_PINS | ||
| 27 | static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | 29 | static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; |
| 30 | # endif // MATRIX_ROW_PINS | ||
| 31 | # ifdef MATRIX_COL_PINS | ||
| 28 | static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; | 32 | static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; |
| 33 | # endif // MATRIX_COL_PINS | ||
| 29 | #endif | 34 | #endif |
| 30 | 35 | ||
| 31 | /* matrix state(1:on, 0:off) */ | 36 | /* matrix state(1:on, 0:off) */ |
| 32 | extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values | 37 | extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values |
| 33 | extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values | 38 | extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values |
| 34 | 39 | ||
| 40 | // user-defined overridable functions | ||
| 41 | __attribute__((weak)) void matrix_init_pins(void); | ||
| 42 | __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); | ||
| 43 | __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); | ||
| 44 | |||
| 35 | static inline void setPinOutput_writeLow(pin_t pin) { | 45 | static inline void setPinOutput_writeLow(pin_t pin) { |
| 36 | ATOMIC_BLOCK_FORCEON { | 46 | ATOMIC_BLOCK_FORCEON { |
| 37 | setPinOutput(pin); | 47 | setPinOutput(pin); |
| @@ -47,7 +57,7 @@ static inline void setPinInputHigh_atomic(pin_t pin) { | |||
| 47 | 57 | ||
| 48 | #ifdef DIRECT_PINS | 58 | #ifdef DIRECT_PINS |
| 49 | 59 | ||
| 50 | static void init_pins(void) { | 60 | __attribute__((weak)) void matrix_init_pins(void) { |
| 51 | for (int row = 0; row < MATRIX_ROWS; row++) { | 61 | for (int row = 0; row < MATRIX_ROWS; row++) { |
| 52 | for (int col = 0; col < MATRIX_COLS; col++) { | 62 | for (int col = 0; col < MATRIX_COLS; col++) { |
| 53 | pin_t pin = direct_pins[row][col]; | 63 | pin_t pin = direct_pins[row][col]; |
| @@ -58,7 +68,7 @@ static void init_pins(void) { | |||
| 58 | } | 68 | } |
| 59 | } | 69 | } |
| 60 | 70 | ||
| 61 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { | 71 | __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { |
| 62 | // Start with a clear matrix row | 72 | // Start with a clear matrix row |
| 63 | matrix_row_t current_row_value = 0; | 73 | matrix_row_t current_row_value = 0; |
| 64 | 74 | ||
| @@ -69,16 +79,13 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) | |||
| 69 | } | 79 | } |
| 70 | } | 80 | } |
| 71 | 81 | ||
| 72 | // If the row has changed, store the row and return the changed flag. | 82 | // Update the matrix |
| 73 | if (current_matrix[current_row] != current_row_value) { | 83 | current_matrix[current_row] = current_row_value; |
| 74 | current_matrix[current_row] = current_row_value; | ||
| 75 | return true; | ||
| 76 | } | ||
| 77 | return false; | ||
| 78 | } | 84 | } |
| 79 | 85 | ||
| 80 | #elif defined(DIODE_DIRECTION) | 86 | #elif defined(DIODE_DIRECTION) |
| 81 | # if (DIODE_DIRECTION == COL2ROW) | 87 | # if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS) |
| 88 | # if (DIODE_DIRECTION == COL2ROW) | ||
| 82 | 89 | ||
| 83 | static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } | 90 | static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } |
| 84 | 91 | ||
| @@ -90,14 +97,14 @@ static void unselect_rows(void) { | |||
| 90 | } | 97 | } |
| 91 | } | 98 | } |
| 92 | 99 | ||
| 93 | static void init_pins(void) { | 100 | __attribute__((weak)) void matrix_init_pins(void) { |
| 94 | unselect_rows(); | 101 | unselect_rows(); |
| 95 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | 102 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { |
| 96 | setPinInputHigh_atomic(col_pins[x]); | 103 | setPinInputHigh_atomic(col_pins[x]); |
| 97 | } | 104 | } |
| 98 | } | 105 | } |
| 99 | 106 | ||
| 100 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { | 107 | __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { |
| 101 | // Start with a clear matrix row | 108 | // Start with a clear matrix row |
| 102 | matrix_row_t current_row_value = 0; | 109 | matrix_row_t current_row_value = 0; |
| 103 | 110 | ||
| @@ -118,15 +125,11 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) | |||
| 118 | unselect_row(current_row); | 125 | unselect_row(current_row); |
| 119 | matrix_output_unselect_delay(); // wait for all Col signals to go HIGH | 126 | matrix_output_unselect_delay(); // wait for all Col signals to go HIGH |
| 120 | 127 | ||
| 121 | // If the row has changed, store the row and return the changed flag. | 128 | // Update the matrix |
| 122 | if (current_matrix[current_row] != current_row_value) { | 129 | current_matrix[current_row] = current_row_value; |
| 123 | current_matrix[current_row] = current_row_value; | ||
| 124 | return true; | ||
| 125 | } | ||
| 126 | return false; | ||
| 127 | } | 130 | } |
| 128 | 131 | ||
| 129 | # elif (DIODE_DIRECTION == ROW2COL) | 132 | # elif (DIODE_DIRECTION == ROW2COL) |
| 130 | 133 | ||
| 131 | static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } | 134 | static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } |
| 132 | 135 | ||
| @@ -138,59 +141,46 @@ static void unselect_cols(void) { | |||
| 138 | } | 141 | } |
| 139 | } | 142 | } |
| 140 | 143 | ||
| 141 | static void init_pins(void) { | 144 | __attribute__((weak)) void matrix_init_pins(void) { |
| 142 | unselect_cols(); | 145 | unselect_cols(); |
| 143 | for (uint8_t x = 0; x < MATRIX_ROWS; x++) { | 146 | for (uint8_t x = 0; x < MATRIX_ROWS; x++) { |
| 144 | setPinInputHigh_atomic(row_pins[x]); | 147 | setPinInputHigh_atomic(row_pins[x]); |
| 145 | } | 148 | } |
| 146 | } | 149 | } |
| 147 | 150 | ||
| 148 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { | 151 | __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { |
| 149 | bool matrix_changed = false; | ||
| 150 | |||
| 151 | // Select col | 152 | // Select col |
| 152 | select_col(current_col); | 153 | select_col(current_col); |
| 153 | matrix_output_select_delay(); | 154 | matrix_output_select_delay(); |
| 154 | 155 | ||
| 155 | // For each row... | 156 | // For each row... |
| 156 | for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { | 157 | for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { |
| 157 | // Store last value of row prior to reading | ||
| 158 | matrix_row_t last_row_value = current_matrix[row_index]; | ||
| 159 | matrix_row_t current_row_value = last_row_value; | ||
| 160 | |||
| 161 | // Check row pin state | 158 | // Check row pin state |
| 162 | if (readPin(row_pins[row_index]) == 0) { | 159 | if (readPin(row_pins[row_index]) == 0) { |
| 163 | // Pin LO, set col bit | 160 | // Pin LO, set col bit |
| 164 | current_row_value |= (MATRIX_ROW_SHIFTER << current_col); | 161 | current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col); |
| 165 | } else { | 162 | } else { |
| 166 | // Pin HI, clear col bit | 163 | // Pin HI, clear col bit |
| 167 | current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); | 164 | current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col); |
| 168 | } | ||
| 169 | |||
| 170 | // Determine if the matrix changed state | ||
| 171 | if ((last_row_value != current_row_value)) { | ||
| 172 | matrix_changed |= true; | ||
| 173 | current_matrix[row_index] = current_row_value; | ||
| 174 | } | 165 | } |
| 175 | } | 166 | } |
| 176 | 167 | ||
| 177 | // Unselect col | 168 | // Unselect col |
| 178 | unselect_col(current_col); | 169 | unselect_col(current_col); |
| 179 | matrix_output_unselect_delay(); // wait for all Row signals to go HIGH | 170 | matrix_output_unselect_delay(); // wait for all Row signals to go HIGH |
| 180 | |||
| 181 | return matrix_changed; | ||
| 182 | } | 171 | } |
| 183 | 172 | ||
| 184 | # else | 173 | # else |
| 185 | # error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! | 174 | # error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! |
| 186 | # endif | 175 | # endif |
| 176 | # endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS) | ||
| 187 | #else | 177 | #else |
| 188 | # error DIODE_DIRECTION is not defined! | 178 | # error DIODE_DIRECTION is not defined! |
| 189 | #endif | 179 | #endif |
| 190 | 180 | ||
| 191 | void matrix_init(void) { | 181 | void matrix_init(void) { |
| 192 | // initialize key pins | 182 | // initialize key pins |
| 193 | init_pins(); | 183 | matrix_init_pins(); |
| 194 | 184 | ||
| 195 | // initialize matrix state: all keys off | 185 | // initialize matrix state: all keys off |
| 196 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | 186 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| @@ -204,20 +194,23 @@ void matrix_init(void) { | |||
| 204 | } | 194 | } |
| 205 | 195 | ||
| 206 | uint8_t matrix_scan(void) { | 196 | uint8_t matrix_scan(void) { |
| 207 | bool changed = false; | 197 | matrix_row_t curr_matrix[MATRIX_ROWS] = {0}; |
| 208 | 198 | ||
| 209 | #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) | 199 | #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) |
| 210 | // Set row, read cols | 200 | // Set row, read cols |
| 211 | for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { | 201 | for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { |
| 212 | changed |= read_cols_on_row(raw_matrix, current_row); | 202 | matrix_read_cols_on_row(curr_matrix, current_row); |
| 213 | } | 203 | } |
| 214 | #elif (DIODE_DIRECTION == ROW2COL) | 204 | #elif (DIODE_DIRECTION == ROW2COL) |
| 215 | // Set col, read rows | 205 | // Set col, read rows |
| 216 | for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { | 206 | for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { |
| 217 | changed |= read_rows_on_col(raw_matrix, current_col); | 207 | matrix_read_rows_on_col(curr_matrix, current_col); |
| 218 | } | 208 | } |
| 219 | #endif | 209 | #endif |
| 220 | 210 | ||
| 211 | bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0; | ||
| 212 | if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix)); | ||
| 213 | |||
| 221 | debounce(raw_matrix, matrix, MATRIX_ROWS, changed); | 214 | debounce(raw_matrix, matrix, MATRIX_ROWS, changed); |
| 222 | 215 | ||
| 223 | matrix_scan_quantum(); | 216 | matrix_scan_quantum(); |
diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index 9268c4522..f8def7f67 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk | |||
| @@ -136,10 +136,6 @@ ifneq ($(findstring STM32F042, $(MCU)),) | |||
| 136 | 136 | ||
| 137 | USE_FPU ?= no | 137 | USE_FPU ?= no |
| 138 | 138 | ||
| 139 | # Options to pass to dfu-util when flashing | ||
| 140 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 141 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 142 | |||
| 143 | # UF2 settings | 139 | # UF2 settings |
| 144 | UF2_FAMILY ?= STM32F0 | 140 | UF2_FAMILY ?= STM32F0 |
| 145 | endif | 141 | endif |
| @@ -172,10 +168,6 @@ ifneq ($(findstring STM32F072, $(MCU)),) | |||
| 172 | 168 | ||
| 173 | USE_FPU ?= no | 169 | USE_FPU ?= no |
| 174 | 170 | ||
| 175 | # Options to pass to dfu-util when flashing | ||
| 176 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 177 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 178 | |||
| 179 | # UF2 settings | 171 | # UF2 settings |
| 180 | UF2_FAMILY ?= STM32F0 | 172 | UF2_FAMILY ?= STM32F0 |
| 181 | endif | 173 | endif |
| @@ -208,10 +200,6 @@ ifneq ($(findstring STM32F103, $(MCU)),) | |||
| 208 | 200 | ||
| 209 | USE_FPU ?= no | 201 | USE_FPU ?= no |
| 210 | 202 | ||
| 211 | # Options to pass to dfu-util when flashing | ||
| 212 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 213 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 214 | |||
| 215 | # UF2 settings | 203 | # UF2 settings |
| 216 | UF2_FAMILY ?= STM32F1 | 204 | UF2_FAMILY ?= STM32F1 |
| 217 | endif | 205 | endif |
| @@ -244,10 +232,6 @@ ifneq ($(findstring STM32F303, $(MCU)),) | |||
| 244 | 232 | ||
| 245 | USE_FPU ?= yes | 233 | USE_FPU ?= yes |
| 246 | 234 | ||
| 247 | # Options to pass to dfu-util when flashing | ||
| 248 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 249 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 250 | |||
| 251 | # UF2 settings | 235 | # UF2 settings |
| 252 | UF2_FAMILY ?= STM32F3 | 236 | UF2_FAMILY ?= STM32F3 |
| 253 | endif | 237 | endif |
| @@ -280,10 +264,6 @@ ifneq ($(findstring STM32F401, $(MCU)),) | |||
| 280 | 264 | ||
| 281 | USE_FPU ?= yes | 265 | USE_FPU ?= yes |
| 282 | 266 | ||
| 283 | # Options to pass to dfu-util when flashing | ||
| 284 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 285 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 286 | |||
| 287 | # UF2 settings | 267 | # UF2 settings |
| 288 | UF2_FAMILY ?= STM32F4 | 268 | UF2_FAMILY ?= STM32F4 |
| 289 | endif | 269 | endif |
| @@ -321,10 +301,6 @@ ifneq ($(findstring STM32F411, $(MCU)),) | |||
| 321 | 301 | ||
| 322 | USE_FPU ?= yes | 302 | USE_FPU ?= yes |
| 323 | 303 | ||
| 324 | # Options to pass to dfu-util when flashing | ||
| 325 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 326 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 327 | |||
| 328 | # UF2 settings | 304 | # UF2 settings |
| 329 | UF2_FAMILY ?= STM32F4 | 305 | UF2_FAMILY ?= STM32F4 |
| 330 | endif | 306 | endif |
| @@ -357,10 +333,6 @@ ifneq ($(findstring STM32F446, $(MCU)),) | |||
| 357 | BOARD ?= GENERIC_STM32_F446XE | 333 | BOARD ?= GENERIC_STM32_F446XE |
| 358 | 334 | ||
| 359 | USE_FPU ?= yes | 335 | USE_FPU ?= yes |
| 360 | |||
| 361 | # Options to pass to dfu-util when flashing | ||
| 362 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 363 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 364 | endif | 336 | endif |
| 365 | 337 | ||
| 366 | ifneq ($(findstring STM32G431, $(MCU)),) | 338 | ifneq ($(findstring STM32G431, $(MCU)),) |
| @@ -391,10 +363,6 @@ ifneq ($(findstring STM32G431, $(MCU)),) | |||
| 391 | 363 | ||
| 392 | USE_FPU ?= yes | 364 | USE_FPU ?= yes |
| 393 | 365 | ||
| 394 | # Options to pass to dfu-util when flashing | ||
| 395 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 396 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 397 | |||
| 398 | # UF2 settings | 366 | # UF2 settings |
| 399 | UF2_FAMILY ?= STM32G4 | 367 | UF2_FAMILY ?= STM32G4 |
| 400 | endif | 368 | endif |
| @@ -427,10 +395,6 @@ ifneq ($(findstring STM32G474, $(MCU)),) | |||
| 427 | 395 | ||
| 428 | USE_FPU ?= yes | 396 | USE_FPU ?= yes |
| 429 | 397 | ||
| 430 | # Options to pass to dfu-util when flashing | ||
| 431 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 432 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 433 | |||
| 434 | # UF2 settings | 398 | # UF2 settings |
| 435 | UF2_FAMILY ?= STM32G4 | 399 | UF2_FAMILY ?= STM32G4 |
| 436 | endif | 400 | endif |
| @@ -465,10 +429,6 @@ ifneq (,$(filter $(MCU),STM32L433 STM32L443)) | |||
| 465 | 429 | ||
| 466 | USE_FPU ?= yes | 430 | USE_FPU ?= yes |
| 467 | 431 | ||
| 468 | # Options to pass to dfu-util when flashing | ||
| 469 | DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave | ||
| 470 | DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 | ||
| 471 | |||
| 472 | # UF2 settings | 432 | # UF2 settings |
| 473 | UF2_FAMILY ?= STM32L4 | 433 | UF2_FAMILY ?= STM32L4 |
| 474 | endif | 434 | endif |
diff --git a/quantum/quantum.h b/quantum/quantum.h index e4a7c5723..66ba96fde 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h | |||
| @@ -176,6 +176,10 @@ extern layer_state_t layer_state; | |||
| 176 | # include "oled_driver.h" | 176 | # include "oled_driver.h" |
| 177 | #endif | 177 | #endif |
| 178 | 178 | ||
| 179 | #ifdef ST7565_ENABLE | ||
| 180 | # include "st7565.h" | ||
| 181 | #endif | ||
| 182 | |||
| 179 | #ifdef DIP_SWITCH_ENABLE | 183 | #ifdef DIP_SWITCH_ENABLE |
| 180 | # include "dip_switch.h" | 184 | # include "dip_switch.h" |
| 181 | #endif | 185 | #endif |
diff --git a/quantum/rgb_matrix_animations/alpha_mods_anim.h b/quantum/rgb_matrix/animations/alpha_mods_anim.h index 426d88ef3..426d88ef3 100644 --- a/quantum/rgb_matrix_animations/alpha_mods_anim.h +++ b/quantum/rgb_matrix/animations/alpha_mods_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/breathing_anim.h b/quantum/rgb_matrix/animations/breathing_anim.h index 340bd93e5..340bd93e5 100644 --- a/quantum/rgb_matrix_animations/breathing_anim.h +++ b/quantum/rgb_matrix/animations/breathing_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/colorband_pinwheel_sat_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h index 3df3cfda7..3df3cfda7 100644 --- a/quantum/rgb_matrix_animations/colorband_pinwheel_sat_anim.h +++ b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/colorband_pinwheel_val_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h index 7d80074fd..7d80074fd 100644 --- a/quantum/rgb_matrix_animations/colorband_pinwheel_val_anim.h +++ b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/colorband_sat_anim.h b/quantum/rgb_matrix/animations/colorband_sat_anim.h index 35b830af6..35b830af6 100644 --- a/quantum/rgb_matrix_animations/colorband_sat_anim.h +++ b/quantum/rgb_matrix/animations/colorband_sat_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/colorband_spiral_sat_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h index 048157aa1..048157aa1 100644 --- a/quantum/rgb_matrix_animations/colorband_spiral_sat_anim.h +++ b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/colorband_spiral_val_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h index bff2da161..bff2da161 100644 --- a/quantum/rgb_matrix_animations/colorband_spiral_val_anim.h +++ b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/colorband_val_anim.h b/quantum/rgb_matrix/animations/colorband_val_anim.h index f1aaf1d06..f1aaf1d06 100644 --- a/quantum/rgb_matrix_animations/colorband_val_anim.h +++ b/quantum/rgb_matrix/animations/colorband_val_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/cycle_all_anim.h b/quantum/rgb_matrix/animations/cycle_all_anim.h index faf8598a3..faf8598a3 100644 --- a/quantum/rgb_matrix_animations/cycle_all_anim.h +++ b/quantum/rgb_matrix/animations/cycle_all_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/cycle_left_right_anim.h b/quantum/rgb_matrix/animations/cycle_left_right_anim.h index cf911eb93..cf911eb93 100644 --- a/quantum/rgb_matrix_animations/cycle_left_right_anim.h +++ b/quantum/rgb_matrix/animations/cycle_left_right_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/cycle_out_in_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_anim.h index d66acd4b2..d66acd4b2 100644 --- a/quantum/rgb_matrix_animations/cycle_out_in_anim.h +++ b/quantum/rgb_matrix/animations/cycle_out_in_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/cycle_out_in_dual_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h index fe8396140..fe8396140 100644 --- a/quantum/rgb_matrix_animations/cycle_out_in_dual_anim.h +++ b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/cycle_pinwheel_anim.h b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h index 779988709..779988709 100644 --- a/quantum/rgb_matrix_animations/cycle_pinwheel_anim.h +++ b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/cycle_spiral_anim.h b/quantum/rgb_matrix/animations/cycle_spiral_anim.h index 80cfb0dbc..80cfb0dbc 100644 --- a/quantum/rgb_matrix_animations/cycle_spiral_anim.h +++ b/quantum/rgb_matrix/animations/cycle_spiral_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/cycle_up_down_anim.h b/quantum/rgb_matrix/animations/cycle_up_down_anim.h index 5016f739d..5016f739d 100644 --- a/quantum/rgb_matrix_animations/cycle_up_down_anim.h +++ b/quantum/rgb_matrix/animations/cycle_up_down_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/digital_rain_anim.h b/quantum/rgb_matrix/animations/digital_rain_anim.h index 1de45f8e8..1de45f8e8 100644 --- a/quantum/rgb_matrix_animations/digital_rain_anim.h +++ b/quantum/rgb_matrix/animations/digital_rain_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/dual_beacon_anim.h b/quantum/rgb_matrix/animations/dual_beacon_anim.h index ce9487168..ce9487168 100644 --- a/quantum/rgb_matrix_animations/dual_beacon_anim.h +++ b/quantum/rgb_matrix/animations/dual_beacon_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/gradient_left_right_anim.h b/quantum/rgb_matrix/animations/gradient_left_right_anim.h index 53dfd04e2..53dfd04e2 100644 --- a/quantum/rgb_matrix_animations/gradient_left_right_anim.h +++ b/quantum/rgb_matrix/animations/gradient_left_right_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/gradient_up_down_anim.h b/quantum/rgb_matrix/animations/gradient_up_down_anim.h index 7e0d2898c..7e0d2898c 100644 --- a/quantum/rgb_matrix_animations/gradient_up_down_anim.h +++ b/quantum/rgb_matrix/animations/gradient_up_down_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/hue_breathing_anim.h b/quantum/rgb_matrix/animations/hue_breathing_anim.h index 54dea958a..54dea958a 100644 --- a/quantum/rgb_matrix_animations/hue_breathing_anim.h +++ b/quantum/rgb_matrix/animations/hue_breathing_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/hue_pendulum_anim.h b/quantum/rgb_matrix/animations/hue_pendulum_anim.h index 2d8d36174..2d8d36174 100644 --- a/quantum/rgb_matrix_animations/hue_pendulum_anim.h +++ b/quantum/rgb_matrix/animations/hue_pendulum_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/hue_wave_anim.h b/quantum/rgb_matrix/animations/hue_wave_anim.h index fd9026fc9..fd9026fc9 100644 --- a/quantum/rgb_matrix_animations/hue_wave_anim.h +++ b/quantum/rgb_matrix/animations/hue_wave_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h index 9493b3850..a17e954b1 100644 --- a/quantum/rgb_matrix_animations/jellybean_raindrops_anim.h +++ b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h | |||
| @@ -4,7 +4,7 @@ RGB_MATRIX_EFFECT(JELLYBEAN_RAINDROPS) | |||
| 4 | 4 | ||
| 5 | static void jellybean_raindrops_set_color(int i, effect_params_t* params) { | 5 | static void jellybean_raindrops_set_color(int i, effect_params_t* params) { |
| 6 | if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) return; | 6 | if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) return; |
| 7 | HSV hsv = {rand() & 0xFF, rand() & 0xFF, rgb_matrix_config.hsv.v}; | 7 | HSV hsv = {rand() & 0xFF, qadd8(rand() & 0x7F, 0x80), rgb_matrix_config.hsv.v}; |
| 8 | RGB rgb = rgb_matrix_hsv_to_rgb(hsv); | 8 | RGB rgb = rgb_matrix_hsv_to_rgb(hsv); |
| 9 | rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); | 9 | rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); |
| 10 | } | 10 | } |
diff --git a/quantum/rgb_matrix_animations/rainbow_beacon_anim.h b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h index 977261182..977261182 100644 --- a/quantum/rgb_matrix_animations/rainbow_beacon_anim.h +++ b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/rainbow_moving_chevron_anim.h b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h index e51e7b251..e51e7b251 100644 --- a/quantum/rgb_matrix_animations/rainbow_moving_chevron_anim.h +++ b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/rainbow_pinwheels_anim.h b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h index 1cd4ed2ac..1cd4ed2ac 100644 --- a/quantum/rgb_matrix_animations/rainbow_pinwheels_anim.h +++ b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/raindrops_anim.h b/quantum/rgb_matrix/animations/raindrops_anim.h index 38359cdca..38359cdca 100644 --- a/quantum/rgb_matrix_animations/raindrops_anim.h +++ b/quantum/rgb_matrix/animations/raindrops_anim.h | |||
diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc new file mode 100644 index 000000000..302ad79c0 --- /dev/null +++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | // Add your new core rgb matrix effect here, order determines enum order | ||
| 2 | #include "solid_color_anim.h" | ||
| 3 | #include "alpha_mods_anim.h" | ||
| 4 | #include "gradient_up_down_anim.h" | ||
| 5 | #include "gradient_left_right_anim.h" | ||
| 6 | #include "breathing_anim.h" | ||
| 7 | #include "colorband_sat_anim.h" | ||
| 8 | #include "colorband_val_anim.h" | ||
| 9 | #include "colorband_pinwheel_sat_anim.h" | ||
| 10 | #include "colorband_pinwheel_val_anim.h" | ||
| 11 | #include "colorband_spiral_sat_anim.h" | ||
| 12 | #include "colorband_spiral_val_anim.h" | ||
| 13 | #include "cycle_all_anim.h" | ||
| 14 | #include "cycle_left_right_anim.h" | ||
| 15 | #include "cycle_up_down_anim.h" | ||
| 16 | #include "rainbow_moving_chevron_anim.h" | ||
| 17 | #include "cycle_out_in_anim.h" | ||
| 18 | #include "cycle_out_in_dual_anim.h" | ||
| 19 | #include "cycle_pinwheel_anim.h" | ||
| 20 | #include "cycle_spiral_anim.h" | ||
| 21 | #include "dual_beacon_anim.h" | ||
| 22 | #include "rainbow_beacon_anim.h" | ||
| 23 | #include "rainbow_pinwheels_anim.h" | ||
| 24 | #include "raindrops_anim.h" | ||
| 25 | #include "jellybean_raindrops_anim.h" | ||
| 26 | #include "hue_breathing_anim.h" | ||
| 27 | #include "hue_pendulum_anim.h" | ||
| 28 | #include "hue_wave_anim.h" | ||
| 29 | #include "typing_heatmap_anim.h" | ||
| 30 | #include "digital_rain_anim.h" | ||
| 31 | #include "solid_reactive_simple_anim.h" | ||
| 32 | #include "solid_reactive_anim.h" | ||
| 33 | #include "solid_reactive_wide.h" | ||
| 34 | #include "solid_reactive_cross.h" | ||
| 35 | #include "solid_reactive_nexus.h" | ||
| 36 | #include "splash_anim.h" | ||
| 37 | #include "solid_splash_anim.h" | ||
diff --git a/quantum/rgb_matrix_runners/effect_runner_dx_dy.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h index 4867609c8..4867609c8 100644 --- a/quantum/rgb_matrix_runners/effect_runner_dx_dy.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h | |||
diff --git a/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h index 9545b418d..9545b418d 100644 --- a/quantum/rgb_matrix_runners/effect_runner_dx_dy_dist.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h | |||
diff --git a/quantum/rgb_matrix_runners/effect_runner_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_i.h index 95bfe8b39..95bfe8b39 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 8485b61f3..8485b61f3 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 5c69d0fbb..5c69d0fbb 100644 --- a/quantum/rgb_matrix_runners/effect_runner_reactive_splash.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h | |||
diff --git a/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h index 02351de51..02351de51 100644 --- a/quantum/rgb_matrix_runners/effect_runner_sin_cos_i.h +++ b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h | |||
diff --git a/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc b/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc new file mode 100644 index 000000000..c09022bb0 --- /dev/null +++ b/quantum/rgb_matrix/animations/runners/rgb_matrix_runners.inc | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #include "effect_runner_dx_dy_dist.h" | ||
| 2 | #include "effect_runner_dx_dy.h" | ||
| 3 | #include "effect_runner_i.h" | ||
| 4 | #include "effect_runner_sin_cos_i.h" | ||
| 5 | #include "effect_runner_reactive.h" | ||
| 6 | #include "effect_runner_reactive_splash.h" | ||
diff --git a/quantum/rgb_matrix_animations/solid_color_anim.h b/quantum/rgb_matrix/animations/solid_color_anim.h index 79d63cf13..79d63cf13 100644 --- a/quantum/rgb_matrix_animations/solid_color_anim.h +++ b/quantum/rgb_matrix/animations/solid_color_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/solid_reactive_anim.h b/quantum/rgb_matrix/animations/solid_reactive_anim.h index d45bb961b..d45bb961b 100644 --- a/quantum/rgb_matrix_animations/solid_reactive_anim.h +++ b/quantum/rgb_matrix/animations/solid_reactive_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/solid_reactive_cross.h b/quantum/rgb_matrix/animations/solid_reactive_cross.h index f76c68e8c..f76c68e8c 100644 --- a/quantum/rgb_matrix_animations/solid_reactive_cross.h +++ b/quantum/rgb_matrix/animations/solid_reactive_cross.h | |||
diff --git a/quantum/rgb_matrix_animations/solid_reactive_nexus.h b/quantum/rgb_matrix/animations/solid_reactive_nexus.h index 17f94e3c1..17f94e3c1 100644 --- a/quantum/rgb_matrix_animations/solid_reactive_nexus.h +++ b/quantum/rgb_matrix/animations/solid_reactive_nexus.h | |||
diff --git a/quantum/rgb_matrix_animations/solid_reactive_simple_anim.h b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h index 12eb248cc..12eb248cc 100644 --- a/quantum/rgb_matrix_animations/solid_reactive_simple_anim.h +++ b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/solid_reactive_wide.h b/quantum/rgb_matrix/animations/solid_reactive_wide.h index 1cc4dca72..1cc4dca72 100644 --- a/quantum/rgb_matrix_animations/solid_reactive_wide.h +++ b/quantum/rgb_matrix/animations/solid_reactive_wide.h | |||
diff --git a/quantum/rgb_matrix_animations/solid_splash_anim.h b/quantum/rgb_matrix/animations/solid_splash_anim.h index 99efb4996..99efb4996 100644 --- a/quantum/rgb_matrix_animations/solid_splash_anim.h +++ b/quantum/rgb_matrix/animations/solid_splash_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/splash_anim.h b/quantum/rgb_matrix/animations/splash_anim.h index 1415bcc0f..1415bcc0f 100644 --- a/quantum/rgb_matrix_animations/splash_anim.h +++ b/quantum/rgb_matrix/animations/splash_anim.h | |||
diff --git a/quantum/rgb_matrix_animations/typing_heatmap_anim.h b/quantum/rgb_matrix/animations/typing_heatmap_anim.h index e7dda11a2..e7dda11a2 100644 --- a/quantum/rgb_matrix_animations/typing_heatmap_anim.h +++ b/quantum/rgb_matrix/animations/typing_heatmap_anim.h | |||
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c index ab8dbd849..789cd2860 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix/rgb_matrix.c | |||
| @@ -31,22 +31,25 @@ const led_point_t k_rgb_matrix_center = {112, 32}; | |||
| 31 | const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; | 31 | const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | // clang-format off | ||
| 35 | #ifndef RGB_MATRIX_IMMEDIATE_EEPROM | ||
| 36 | # define rgb_eeconfig_update(v) rgb_update_eeprom |= v | ||
| 37 | #else | ||
| 38 | # define rgb_eeconfig_update(v) if (v) eeconfig_update_rgb_matrix() | ||
| 39 | #endif | ||
| 40 | // clang-format on | ||
| 41 | |||
| 34 | __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } | 42 | __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } |
| 35 | 43 | ||
| 36 | // Generic effect runners | 44 | // Generic effect runners |
| 37 | #include "rgb_matrix_runners/effect_runner_dx_dy_dist.h" | 45 | #include "rgb_matrix_runners.inc" |
| 38 | #include "rgb_matrix_runners/effect_runner_dx_dy.h" | ||
| 39 | #include "rgb_matrix_runners/effect_runner_i.h" | ||
| 40 | #include "rgb_matrix_runners/effect_runner_sin_cos_i.h" | ||
| 41 | #include "rgb_matrix_runners/effect_runner_reactive.h" | ||
| 42 | #include "rgb_matrix_runners/effect_runner_reactive_splash.h" | ||
| 43 | 46 | ||
| 44 | // ------------------------------------------ | 47 | // ------------------------------------------ |
| 45 | // -----Begin rgb effect includes macros----- | 48 | // -----Begin rgb effect includes macros----- |
| 46 | #define RGB_MATRIX_EFFECT(name) | 49 | #define RGB_MATRIX_EFFECT(name) |
| 47 | #define RGB_MATRIX_CUSTOM_EFFECT_IMPLS | 50 | #define RGB_MATRIX_CUSTOM_EFFECT_IMPLS |
| 48 | 51 | ||
| 49 | #include "rgb_matrix_animations/rgb_matrix_effects.inc" | 52 | #include "rgb_matrix_effects.inc" |
| 50 | #ifdef RGB_MATRIX_CUSTOM_KB | 53 | #ifdef RGB_MATRIX_CUSTOM_KB |
| 51 | # include "rgb_matrix_kb.inc" | 54 | # include "rgb_matrix_kb.inc" |
| 52 | #endif | 55 | #endif |
| @@ -67,10 +70,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv | |||
| 67 | # define RGB_DISABLE_TIMEOUT 0 | 70 | # define RGB_DISABLE_TIMEOUT 0 |
| 68 | #endif | 71 | #endif |
| 69 | 72 | ||
| 70 | #if RGB_DISABLE_WHEN_USB_SUSPENDED != 1 | ||
| 71 | # undef RGB_DISABLE_WHEN_USB_SUSPENDED | ||
| 72 | #endif | ||
| 73 | |||
| 74 | #if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX | 73 | #if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX |
| 75 | # undef RGB_MATRIX_MAXIMUM_BRIGHTNESS | 74 | # undef RGB_MATRIX_MAXIMUM_BRIGHTNESS |
| 76 | # define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX | 75 | # define RGB_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX |
| @@ -129,6 +128,7 @@ last_hit_t g_last_hit_tracker; | |||
| 129 | 128 | ||
| 130 | // internals | 129 | // internals |
| 131 | static bool suspend_state = false; | 130 | static bool suspend_state = false; |
| 131 | static bool rgb_update_eeprom = false; | ||
| 132 | static uint8_t rgb_last_enable = UINT8_MAX; | 132 | static uint8_t rgb_last_enable = UINT8_MAX; |
| 133 | static uint8_t rgb_last_effect = UINT8_MAX; | 133 | static uint8_t rgb_last_effect = UINT8_MAX; |
| 134 | static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; | 134 | static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; |
| @@ -315,6 +315,8 @@ static void rgb_task_timers(void) { | |||
| 315 | 315 | ||
| 316 | static void rgb_task_sync(void) { | 316 | static void rgb_task_sync(void) { |
| 317 | // next task | 317 | // next task |
| 318 | if (rgb_update_eeprom) eeconfig_update_rgb_matrix(); | ||
| 319 | rgb_update_eeprom = false; | ||
| 318 | if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; | 320 | if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; |
| 319 | } | 321 | } |
| 320 | 322 | ||
| @@ -353,7 +355,7 @@ static void rgb_task_render(uint8_t effect) { | |||
| 353 | case RGB_MATRIX_##name: \ | 355 | case RGB_MATRIX_##name: \ |
| 354 | rendering = name(&rgb_effect_params); \ | 356 | rendering = name(&rgb_effect_params); \ |
| 355 | break; | 357 | break; |
| 356 | #include "rgb_matrix_animations/rgb_matrix_effects.inc" | 358 | #include "rgb_matrix_effects.inc" |
| 357 | #undef RGB_MATRIX_EFFECT | 359 | #undef RGB_MATRIX_EFFECT |
| 358 | 360 | ||
| 359 | #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) | 361 | #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) |
| @@ -511,9 +513,7 @@ bool rgb_matrix_get_suspend_state(void) { return suspend_state; } | |||
| 511 | void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { | 513 | void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { |
| 512 | rgb_matrix_config.enable ^= 1; | 514 | rgb_matrix_config.enable ^= 1; |
| 513 | rgb_task_state = STARTING; | 515 | rgb_task_state = STARTING; |
| 514 | if (write_to_eeprom) { | 516 | rgb_eeconfig_update(write_to_eeprom); |
| 515 | eeconfig_update_rgb_matrix(); | ||
| 516 | } | ||
| 517 | dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable); | 517 | dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable); |
| 518 | } | 518 | } |
| 519 | void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); } | 519 | 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); } | |||
| 521 | 521 | ||
| 522 | void rgb_matrix_enable(void) { | 522 | void rgb_matrix_enable(void) { |
| 523 | rgb_matrix_enable_noeeprom(); | 523 | rgb_matrix_enable_noeeprom(); |
| 524 | eeconfig_update_rgb_matrix(); | 524 | rgb_eeconfig_update(true); |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | void rgb_matrix_enable_noeeprom(void) { | 527 | void rgb_matrix_enable_noeeprom(void) { |
| @@ -531,7 +531,7 @@ void rgb_matrix_enable_noeeprom(void) { | |||
| 531 | 531 | ||
| 532 | void rgb_matrix_disable(void) { | 532 | void rgb_matrix_disable(void) { |
| 533 | rgb_matrix_disable_noeeprom(); | 533 | rgb_matrix_disable_noeeprom(); |
| 534 | eeconfig_update_rgb_matrix(); | 534 | rgb_eeconfig_update(true); |
| 535 | } | 535 | } |
| 536 | 536 | ||
| 537 | void rgb_matrix_disable_noeeprom(void) { | 537 | void rgb_matrix_disable_noeeprom(void) { |
| @@ -553,9 +553,7 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { | |||
| 553 | rgb_matrix_config.mode = mode; | 553 | rgb_matrix_config.mode = mode; |
| 554 | } | 554 | } |
| 555 | rgb_task_state = STARTING; | 555 | rgb_task_state = STARTING; |
| 556 | if (write_to_eeprom) { | 556 | rgb_eeconfig_update(write_to_eeprom); |
| 557 | eeconfig_update_rgb_matrix(); | ||
| 558 | } | ||
| 559 | dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode); | 557 | dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode); |
| 560 | } | 558 | } |
| 561 | void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); } | 559 | 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 | |||
| 584 | rgb_matrix_config.hsv.h = hue; | 582 | rgb_matrix_config.hsv.h = hue; |
| 585 | rgb_matrix_config.hsv.s = sat; | 583 | rgb_matrix_config.hsv.s = sat; |
| 586 | rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val; | 584 | rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val; |
| 587 | if (write_to_eeprom) { | 585 | rgb_eeconfig_update(write_to_eeprom); |
| 588 | eeconfig_update_rgb_matrix(); | ||
| 589 | } | ||
| 590 | dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v); | 586 | dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v); |
| 591 | } | 587 | } |
| 592 | void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); } | 588 | 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); } | |||
| 623 | 619 | ||
| 624 | void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { | 620 | void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { |
| 625 | rgb_matrix_config.speed = speed; | 621 | rgb_matrix_config.speed = speed; |
| 626 | if (write_to_eeprom) { | 622 | rgb_eeconfig_update(write_to_eeprom); |
| 627 | eeconfig_update_rgb_matrix(); | ||
| 628 | } | ||
| 629 | dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed); | 623 | dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed); |
| 630 | } | 624 | } |
| 631 | void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); } | 625 | 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 a615b8422..28f07c84d 100644 --- a/quantum/rgb_matrix.h +++ b/quantum/rgb_matrix/rgb_matrix.h | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | # include "is31fl3737.h" | 33 | # include "is31fl3737.h" |
| 34 | #elif defined(IS31FL3741) | 34 | #elif defined(IS31FL3741) |
| 35 | # include "is31fl3741.h" | 35 | # include "is31fl3741.h" |
| 36 | #elif defined(AW20216) | ||
| 37 | # include "aw20216.h" | ||
| 36 | #elif defined(WS2812) | 38 | #elif defined(WS2812) |
| 37 | # include "ws2812.h" | 39 | # include "ws2812.h" |
| 38 | #endif | 40 | #endif |
| @@ -70,7 +72,7 @@ enum rgb_matrix_effects { | |||
| 70 | // -------------------------------------- | 72 | // -------------------------------------- |
| 71 | // -----Begin rgb effect enum macros----- | 73 | // -----Begin rgb effect enum macros----- |
| 72 | #define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_##name, | 74 | #define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_##name, |
| 73 | #include "rgb_matrix_animations/rgb_matrix_effects.inc" | 75 | #include "rgb_matrix_effects.inc" |
| 74 | #undef RGB_MATRIX_EFFECT | 76 | #undef RGB_MATRIX_EFFECT |
| 75 | 77 | ||
| 76 | #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) | 78 | #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) |
diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c index 896fa6d0e..6a11d4791 100644 --- a/quantum/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix/rgb_matrix_drivers.c | |||
| @@ -171,6 +171,22 @@ const rgb_matrix_driver_t rgb_matrix_driver = { | |||
| 171 | }; | 171 | }; |
| 172 | # endif | 172 | # endif |
| 173 | 173 | ||
| 174 | #elif defined(AW20216) | ||
| 175 | # include "spi_master.h" | ||
| 176 | static void init(void) { | ||
| 177 | spi_init(); | ||
| 178 | AW20216_init(); | ||
| 179 | } | ||
| 180 | |||
| 181 | static void flush(void) { AW20216_update_pwm_buffers(); } | ||
| 182 | |||
| 183 | const rgb_matrix_driver_t rgb_matrix_driver = { | ||
| 184 | .init = init, | ||
| 185 | .flush = flush, | ||
| 186 | .set_color = AW20216_set_color, | ||
| 187 | .set_color_all = AW20216_set_color_all, | ||
| 188 | }; | ||
| 189 | |||
| 174 | #elif defined(WS2812) | 190 | #elif defined(WS2812) |
| 175 | # if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_CUSTOM_DRIVER) | 191 | # if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_CUSTOM_DRIVER) |
| 176 | # pragma message "Cannot use RGBLIGHT and RGB Matrix using WS2812 at the same time." | 192 | # pragma message "Cannot use RGBLIGHT and RGB Matrix using WS2812 at the same time." |
diff --git a/quantum/rgb_matrix_types.h b/quantum/rgb_matrix/rgb_matrix_types.h index df575d657..df575d657 100644 --- a/quantum/rgb_matrix_types.h +++ b/quantum/rgb_matrix/rgb_matrix_types.h | |||
diff --git a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc b/quantum/rgb_matrix_animations/rgb_matrix_effects.inc deleted file mode 100644 index 053d44150..000000000 --- a/quantum/rgb_matrix_animations/rgb_matrix_effects.inc +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | // Add your new core rgb matrix effect here, order determins enum order, requires "rgb_matrix_animations/ directory | ||
| 2 | #include "rgb_matrix_animations/solid_color_anim.h" | ||
| 3 | #include "rgb_matrix_animations/alpha_mods_anim.h" | ||
| 4 | #include "rgb_matrix_animations/gradient_up_down_anim.h" | ||
| 5 | #include "rgb_matrix_animations/gradient_left_right_anim.h" | ||
| 6 | #include "rgb_matrix_animations/breathing_anim.h" | ||
| 7 | #include "rgb_matrix_animations/colorband_sat_anim.h" | ||
| 8 | #include "rgb_matrix_animations/colorband_val_anim.h" | ||
| 9 | #include "rgb_matrix_animations/colorband_pinwheel_sat_anim.h" | ||
| 10 | #include "rgb_matrix_animations/colorband_pinwheel_val_anim.h" | ||
| 11 | #include "rgb_matrix_animations/colorband_spiral_sat_anim.h" | ||
| 12 | #include "rgb_matrix_animations/colorband_spiral_val_anim.h" | ||
| 13 | #include "rgb_matrix_animations/cycle_all_anim.h" | ||
| 14 | #include "rgb_matrix_animations/cycle_left_right_anim.h" | ||
| 15 | #include "rgb_matrix_animations/cycle_up_down_anim.h" | ||
| 16 | #include "rgb_matrix_animations/rainbow_moving_chevron_anim.h" | ||
| 17 | #include "rgb_matrix_animations/cycle_out_in_anim.h" | ||
| 18 | #include "rgb_matrix_animations/cycle_out_in_dual_anim.h" | ||
| 19 | #include "rgb_matrix_animations/cycle_pinwheel_anim.h" | ||
| 20 | #include "rgb_matrix_animations/cycle_spiral_anim.h" | ||
| 21 | #include "rgb_matrix_animations/dual_beacon_anim.h" | ||
| 22 | #include "rgb_matrix_animations/rainbow_beacon_anim.h" | ||
| 23 | #include "rgb_matrix_animations/rainbow_pinwheels_anim.h" | ||
| 24 | #include "rgb_matrix_animations/raindrops_anim.h" | ||
| 25 | #include "rgb_matrix_animations/jellybean_raindrops_anim.h" | ||
| 26 | #include "rgb_matrix_animations/hue_breathing_anim.h" | ||
| 27 | #include "rgb_matrix_animations/hue_pendulum_anim.h" | ||
| 28 | #include "rgb_matrix_animations/hue_wave_anim.h" | ||
| 29 | #include "rgb_matrix_animations/typing_heatmap_anim.h" | ||
| 30 | #include "rgb_matrix_animations/digital_rain_anim.h" | ||
| 31 | #include "rgb_matrix_animations/solid_reactive_simple_anim.h" | ||
| 32 | #include "rgb_matrix_animations/solid_reactive_anim.h" | ||
| 33 | #include "rgb_matrix_animations/solid_reactive_wide.h" | ||
| 34 | #include "rgb_matrix_animations/solid_reactive_cross.h" | ||
| 35 | #include "rgb_matrix_animations/solid_reactive_nexus.h" | ||
| 36 | #include "rgb_matrix_animations/splash_anim.h" | ||
| 37 | #include "rgb_matrix_animations/solid_splash_anim.h" | ||
diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c index f77483ad8..6363f8ff3 100644 --- a/quantum/serial_link/system/serial_link.c +++ b/quantum/serial_link/system/serial_link.c | |||
| @@ -29,10 +29,13 @@ SOFTWARE. | |||
| 29 | #include "serial_link/protocol/transport.h" | 29 | #include "serial_link/protocol/transport.h" |
| 30 | #include "serial_link/protocol/frame_router.h" | 30 | #include "serial_link/protocol/frame_router.h" |
| 31 | #include "matrix.h" | 31 | #include "matrix.h" |
| 32 | #include "sync_timer.h" | ||
| 32 | #include <stdbool.h> | 33 | #include <stdbool.h> |
| 33 | #include "print.h" | 34 | #include "print.h" |
| 34 | #include "config.h" | 35 | #include "config.h" |
| 35 | 36 | ||
| 37 | #define SYNC_TIMER_OFFSET 2 | ||
| 38 | |||
| 36 | static event_source_t new_data_event; | 39 | static event_source_t new_data_event; |
| 37 | static bool serial_link_connected; | 40 | static bool serial_link_connected; |
| 38 | static bool is_master = false; | 41 | static bool is_master = false; |
| @@ -159,10 +162,16 @@ static matrix_object_t last_matrix = {}; | |||
| 159 | 162 | ||
| 160 | SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t); | 163 | SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t); |
| 161 | MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool); | 164 | MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool); |
| 165 | #ifndef DISABLE_SYNC_TIMER | ||
| 166 | MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t); | ||
| 167 | #endif | ||
| 162 | 168 | ||
| 163 | static remote_object_t* remote_objects[] = { | 169 | static remote_object_t* remote_objects[] = { |
| 164 | REMOTE_OBJECT(serial_link_connected), | 170 | REMOTE_OBJECT(serial_link_connected), |
| 165 | REMOTE_OBJECT(keyboard_matrix), | 171 | REMOTE_OBJECT(keyboard_matrix), |
| 172 | #ifndef DISABLE_SYNC_TIMER | ||
| 173 | REMOTE_OBJECT(sync_timer), | ||
| 174 | #endif | ||
| 166 | }; | 175 | }; |
| 167 | 176 | ||
| 168 | void init_serial_link(void) { | 177 | void init_serial_link(void) { |
| @@ -200,14 +209,27 @@ void serial_link_update(void) { | |||
| 200 | m->rows[i] = matrix.rows[i]; | 209 | m->rows[i] = matrix.rows[i]; |
| 201 | } | 210 | } |
| 202 | end_write_keyboard_matrix(); | 211 | end_write_keyboard_matrix(); |
| 212 | |||
| 203 | *begin_write_serial_link_connected() = true; | 213 | *begin_write_serial_link_connected() = true; |
| 204 | end_write_serial_link_connected(); | 214 | end_write_serial_link_connected(); |
| 215 | |||
| 216 | #ifndef DISABLE_SYNC_TIMER | ||
| 217 | *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET; | ||
| 218 | end_write_sync_timer(); | ||
| 219 | #endif | ||
| 205 | } | 220 | } |
| 206 | 221 | ||
| 207 | matrix_object_t* m = read_keyboard_matrix(0); | 222 | matrix_object_t* m = read_keyboard_matrix(0); |
| 208 | if (m) { | 223 | if (m) { |
| 209 | matrix_set_remote(m->rows, 0); | 224 | matrix_set_remote(m->rows, 0); |
| 210 | } | 225 | } |
| 226 | |||
| 227 | #ifndef DISABLE_SYNC_TIMER | ||
| 228 | uint32_t* t = read_sync_timer(); | ||
| 229 | if (t) { | ||
| 230 | sync_timer_update(*t); | ||
| 231 | } | ||
| 232 | #endif | ||
| 211 | } | 233 | } |
| 212 | 234 | ||
| 213 | void signal_data_written(void) { chEvtBroadcast(&new_data_event); } | 235 | void signal_data_written(void) { chEvtBroadcast(&new_data_event); } |
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 039e7d977..56d91b07f 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/>. | |||
| 16 | */ | 16 | */ |
| 17 | #include <stdint.h> | 17 | #include <stdint.h> |
| 18 | #include <stdbool.h> | 18 | #include <stdbool.h> |
| 19 | #include <string.h> | ||
| 19 | #include "util.h" | 20 | #include "util.h" |
| 20 | #include "matrix.h" | 21 | #include "matrix.h" |
| 21 | #include "debounce.h" | 22 | #include "debounce.h" |
| 22 | #include "quantum.h" | 23 | #include "quantum.h" |
| 23 | #include "split_util.h" | 24 | #include "split_util.h" |
| 24 | #include "config.h" | 25 | #include "config.h" |
| 25 | #include "transport.h" | 26 | #include "transactions.h" |
| 26 | 27 | ||
| 27 | #define ERROR_DISCONNECT_COUNT 5 | 28 | #ifndef ERROR_DISCONNECT_COUNT |
| 29 | # define ERROR_DISCONNECT_COUNT 5 | ||
| 30 | #endif // ERROR_DISCONNECT_COUNT | ||
| 28 | 31 | ||
| 29 | #define ROWS_PER_HAND (MATRIX_ROWS / 2) | 32 | #define ROWS_PER_HAND (MATRIX_ROWS / 2) |
| 30 | 33 | ||
| 31 | #ifdef DIRECT_PINS | 34 | #ifdef DIRECT_PINS |
| 32 | static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; | 35 | static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; |
| 33 | #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) | 36 | #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) |
| 37 | # ifdef MATRIX_ROW_PINS | ||
| 34 | static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | 38 | static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; |
| 39 | # endif // MATRIX_ROW_PINS | ||
| 40 | # ifdef MATRIX_COL_PINS | ||
| 35 | static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; | 41 | static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; |
| 42 | # endif // MATRIX_COL_PINS | ||
| 36 | #endif | 43 | #endif |
| 37 | 44 | ||
| 38 | /* matrix state(1:on, 0:off) */ | 45 | /* matrix state(1:on, 0:off) */ |
| @@ -45,6 +52,9 @@ uint8_t thisHand, thatHand; | |||
| 45 | // user-defined overridable functions | 52 | // user-defined overridable functions |
| 46 | __attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); } | 53 | __attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); } |
| 47 | __attribute__((weak)) void matrix_slave_scan_user(void) {} | 54 | __attribute__((weak)) void matrix_slave_scan_user(void) {} |
| 55 | __attribute__((weak)) void matrix_init_pins(void); | ||
| 56 | __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); | ||
| 57 | __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); | ||
| 48 | 58 | ||
| 49 | static inline void setPinOutput_writeLow(pin_t pin) { | 59 | static inline void setPinOutput_writeLow(pin_t pin) { |
| 50 | ATOMIC_BLOCK_FORCEON { | 60 | ATOMIC_BLOCK_FORCEON { |
| @@ -61,7 +71,7 @@ static inline void setPinInputHigh_atomic(pin_t pin) { | |||
| 61 | 71 | ||
| 62 | #ifdef DIRECT_PINS | 72 | #ifdef DIRECT_PINS |
| 63 | 73 | ||
| 64 | static void init_pins(void) { | 74 | __attribute__((weak)) void matrix_init_pins(void) { |
| 65 | for (int row = 0; row < MATRIX_ROWS; row++) { | 75 | for (int row = 0; row < MATRIX_ROWS; row++) { |
| 66 | for (int col = 0; col < MATRIX_COLS; col++) { | 76 | for (int col = 0; col < MATRIX_COLS; col++) { |
| 67 | pin_t pin = direct_pins[row][col]; | 77 | pin_t pin = direct_pins[row][col]; |
| @@ -72,7 +82,7 @@ static void init_pins(void) { | |||
| 72 | } | 82 | } |
| 73 | } | 83 | } |
| 74 | 84 | ||
| 75 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { | 85 | __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { |
| 76 | // Start with a clear matrix row | 86 | // Start with a clear matrix row |
| 77 | matrix_row_t current_row_value = 0; | 87 | matrix_row_t current_row_value = 0; |
| 78 | 88 | ||
| @@ -83,16 +93,13 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) | |||
| 83 | } | 93 | } |
| 84 | } | 94 | } |
| 85 | 95 | ||
| 86 | // If the row has changed, store the row and return the changed flag. | 96 | // Update the matrix |
| 87 | if (current_matrix[current_row] != current_row_value) { | 97 | current_matrix[current_row] = current_row_value; |
| 88 | current_matrix[current_row] = current_row_value; | ||
| 89 | return true; | ||
| 90 | } | ||
| 91 | return false; | ||
| 92 | } | 98 | } |
| 93 | 99 | ||
| 94 | #elif defined(DIODE_DIRECTION) | 100 | #elif defined(DIODE_DIRECTION) |
| 95 | # if (DIODE_DIRECTION == COL2ROW) | 101 | # if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS) |
| 102 | # if (DIODE_DIRECTION == COL2ROW) | ||
| 96 | 103 | ||
| 97 | static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } | 104 | static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } |
| 98 | 105 | ||
| @@ -104,14 +111,14 @@ static void unselect_rows(void) { | |||
| 104 | } | 111 | } |
| 105 | } | 112 | } |
| 106 | 113 | ||
| 107 | static void init_pins(void) { | 114 | __attribute__((weak)) void matrix_init_pins(void) { |
| 108 | unselect_rows(); | 115 | unselect_rows(); |
| 109 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | 116 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { |
| 110 | setPinInputHigh_atomic(col_pins[x]); | 117 | setPinInputHigh_atomic(col_pins[x]); |
| 111 | } | 118 | } |
| 112 | } | 119 | } |
| 113 | 120 | ||
| 114 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { | 121 | __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { |
| 115 | // Start with a clear matrix row | 122 | // Start with a clear matrix row |
| 116 | matrix_row_t current_row_value = 0; | 123 | matrix_row_t current_row_value = 0; |
| 117 | 124 | ||
| @@ -132,15 +139,11 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) | |||
| 132 | unselect_row(current_row); | 139 | unselect_row(current_row); |
| 133 | matrix_output_unselect_delay(); // wait for all Col signals to go HIGH | 140 | matrix_output_unselect_delay(); // wait for all Col signals to go HIGH |
| 134 | 141 | ||
| 135 | // If the row has changed, store the row and return the changed flag. | 142 | // Update the matrix |
| 136 | if (current_matrix[current_row] != current_row_value) { | 143 | current_matrix[current_row] = current_row_value; |
| 137 | current_matrix[current_row] = current_row_value; | ||
| 138 | return true; | ||
| 139 | } | ||
| 140 | return false; | ||
| 141 | } | 144 | } |
| 142 | 145 | ||
| 143 | # elif (DIODE_DIRECTION == ROW2COL) | 146 | # elif (DIODE_DIRECTION == ROW2COL) |
| 144 | 147 | ||
| 145 | static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } | 148 | static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } |
| 146 | 149 | ||
| @@ -152,52 +155,39 @@ static void unselect_cols(void) { | |||
| 152 | } | 155 | } |
| 153 | } | 156 | } |
| 154 | 157 | ||
| 155 | static void init_pins(void) { | 158 | __attribute__((weak)) void matrix_init_pins(void) { |
| 156 | unselect_cols(); | 159 | unselect_cols(); |
| 157 | for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { | 160 | for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { |
| 158 | setPinInputHigh_atomic(row_pins[x]); | 161 | setPinInputHigh_atomic(row_pins[x]); |
| 159 | } | 162 | } |
| 160 | } | 163 | } |
| 161 | 164 | ||
| 162 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { | 165 | __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { |
| 163 | bool matrix_changed = false; | ||
| 164 | |||
| 165 | // Select col | 166 | // Select col |
| 166 | select_col(current_col); | 167 | select_col(current_col); |
| 167 | matrix_output_select_delay(); | 168 | matrix_output_select_delay(); |
| 168 | 169 | ||
| 169 | // For each row... | 170 | // For each row... |
| 170 | for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { | 171 | for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { |
| 171 | // Store last value of row prior to reading | ||
| 172 | matrix_row_t last_row_value = current_matrix[row_index]; | ||
| 173 | matrix_row_t current_row_value = last_row_value; | ||
| 174 | |||
| 175 | // Check row pin state | 172 | // Check row pin state |
| 176 | if (readPin(row_pins[row_index]) == 0) { | 173 | if (readPin(row_pins[row_index]) == 0) { |
| 177 | // Pin LO, set col bit | 174 | // Pin LO, set col bit |
| 178 | current_row_value |= (MATRIX_ROW_SHIFTER << current_col); | 175 | current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col); |
| 179 | } else { | 176 | } else { |
| 180 | // Pin HI, clear col bit | 177 | // Pin HI, clear col bit |
| 181 | current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); | 178 | current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col); |
| 182 | } | ||
| 183 | |||
| 184 | // Determine if the matrix changed state | ||
| 185 | if ((last_row_value != current_row_value)) { | ||
| 186 | matrix_changed |= true; | ||
| 187 | current_matrix[row_index] = current_row_value; | ||
| 188 | } | 179 | } |
| 189 | } | 180 | } |
| 190 | 181 | ||
| 191 | // Unselect col | 182 | // Unselect col |
| 192 | unselect_col(current_col); | 183 | unselect_col(current_col); |
| 193 | matrix_output_unselect_delay(); // wait for all Row signals to go HIGH | 184 | matrix_output_unselect_delay(); // wait for all Row signals to go HIGH |
| 194 | |||
| 195 | return matrix_changed; | ||
| 196 | } | 185 | } |
| 197 | 186 | ||
| 198 | # else | 187 | # else |
| 199 | # error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! | 188 | # error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! |
| 200 | # endif | 189 | # endif |
| 190 | # endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS) | ||
| 201 | #else | 191 | #else |
| 202 | # error DIODE_DIRECTION is not defined! | 192 | # error DIODE_DIRECTION is not defined! |
| 203 | #endif | 193 | #endif |
| @@ -233,7 +223,7 @@ void matrix_init(void) { | |||
| 233 | thatHand = ROWS_PER_HAND - thisHand; | 223 | thatHand = ROWS_PER_HAND - thisHand; |
| 234 | 224 | ||
| 235 | // initialize key pins | 225 | // initialize key pins |
| 236 | init_pins(); | 226 | matrix_init_pins(); |
| 237 | 227 | ||
| 238 | // initialize matrix state: all keys off | 228 | // initialize matrix state: all keys off |
| 239 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | 229 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| @@ -288,20 +278,23 @@ bool matrix_post_scan(void) { | |||
| 288 | } | 278 | } |
| 289 | 279 | ||
| 290 | uint8_t matrix_scan(void) { | 280 | uint8_t matrix_scan(void) { |
| 291 | bool local_changed = false; | 281 | matrix_row_t curr_matrix[MATRIX_ROWS] = {0}; |
| 292 | 282 | ||
| 293 | #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) | 283 | #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) |
| 294 | // Set row, read cols | 284 | // Set row, read cols |
| 295 | for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { | 285 | for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { |
| 296 | local_changed |= read_cols_on_row(raw_matrix, current_row); | 286 | matrix_read_cols_on_row(curr_matrix, current_row); |
| 297 | } | 287 | } |
| 298 | #elif (DIODE_DIRECTION == ROW2COL) | 288 | #elif (DIODE_DIRECTION == ROW2COL) |
| 299 | // Set col, read rows | 289 | // Set col, read rows |
| 300 | for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { | 290 | for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { |
| 301 | local_changed |= read_rows_on_col(raw_matrix, current_col); | 291 | matrix_read_rows_on_col(curr_matrix, current_col); |
| 302 | } | 292 | } |
| 303 | #endif | 293 | #endif |
| 304 | 294 | ||
| 295 | bool local_changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0; | ||
| 296 | if (local_changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix)); | ||
| 297 | |||
| 305 | debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed); | 298 | debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed); |
| 306 | 299 | ||
| 307 | bool remote_changed = matrix_post_scan(); | 300 | bool remote_changed = matrix_post_scan(); |
diff --git a/quantum/split_common/post_config.h b/quantum/split_common/post_config.h index 4ae1d5273..a4c0a1956 100644 --- a/quantum/split_common/post_config.h +++ b/quantum/split_common/post_config.h | |||
| @@ -7,13 +7,4 @@ | |||
| 7 | # ifndef F_SCL | 7 | # ifndef F_SCL |
| 8 | # define F_SCL 100000UL // SCL frequency | 8 | # define F_SCL 100000UL // SCL frequency |
| 9 | # endif | 9 | # endif |
| 10 | |||
| 11 | #else // use serial | ||
| 12 | // When using serial, the user must define RGBLIGHT_SPLIT explicitly | ||
| 13 | // in config.h as needed. | ||
| 14 | // see quantum/rgblight_post_config.h | ||
| 15 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 16 | // When using serial and RGBLIGHT_SPLIT need separate transaction | ||
| 17 | # define SERIAL_USE_MULTI_TRANSACTION | ||
| 18 | # endif | ||
| 19 | #endif | 10 | #endif |
diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h new file mode 100644 index 000000000..464c73478 --- /dev/null +++ b/quantum/split_common/transaction_id_define.h | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #pragma once | ||
| 18 | |||
| 19 | enum serial_transaction_id { | ||
| 20 | #ifdef USE_I2C | ||
| 21 | I2C_EXECUTE_CALLBACK, | ||
| 22 | #endif // USE_I2C | ||
| 23 | |||
| 24 | GET_SLAVE_MATRIX_CHECKSUM, | ||
| 25 | GET_SLAVE_MATRIX_DATA, | ||
| 26 | |||
| 27 | #ifdef SPLIT_TRANSPORT_MIRROR | ||
| 28 | PUT_MASTER_MATRIX, | ||
| 29 | #endif // SPLIT_TRANSPORT_MIRROR | ||
| 30 | |||
| 31 | #ifdef ENCODER_ENABLE | ||
| 32 | GET_ENCODERS_CHECKSUM, | ||
| 33 | GET_ENCODERS_DATA, | ||
| 34 | #endif // ENCODER_ENABLE | ||
| 35 | |||
| 36 | #ifndef DISABLE_SYNC_TIMER | ||
| 37 | PUT_SYNC_TIMER, | ||
| 38 | #endif // DISABLE_SYNC_TIMER | ||
| 39 | |||
| 40 | #if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 41 | PUT_LAYER_STATE, | ||
| 42 | PUT_DEFAULT_LAYER_STATE, | ||
| 43 | #endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 44 | |||
| 45 | #ifdef SPLIT_LED_STATE_ENABLE | ||
| 46 | PUT_LED_STATE, | ||
| 47 | #endif // SPLIT_LED_STATE_ENABLE | ||
| 48 | |||
| 49 | #ifdef SPLIT_MODS_ENABLE | ||
| 50 | PUT_MODS, | ||
| 51 | #endif // SPLIT_MODS_ENABLE | ||
| 52 | |||
| 53 | #ifdef BACKLIGHT_ENABLE | ||
| 54 | PUT_BACKLIGHT, | ||
| 55 | #endif // BACKLIGHT_ENABLE | ||
| 56 | |||
| 57 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 58 | PUT_RGBLIGHT, | ||
| 59 | #endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 60 | |||
| 61 | #if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 62 | PUT_LED_MATRIX, | ||
| 63 | #endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 64 | |||
| 65 | #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 66 | PUT_RGB_MATRIX, | ||
| 67 | #endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 68 | |||
| 69 | #if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 70 | PUT_WPM, | ||
| 71 | #endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 72 | |||
| 73 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 74 | PUT_RPC_INFO, | ||
| 75 | PUT_RPC_REQ_DATA, | ||
| 76 | EXECUTE_RPC, | ||
| 77 | GET_RPC_RESP_DATA, | ||
| 78 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 79 | |||
| 80 | // keyboard-specific | ||
| 81 | #ifdef SPLIT_TRANSACTION_IDS_KB | ||
| 82 | SPLIT_TRANSACTION_IDS_KB, | ||
| 83 | #endif // SPLIT_TRANSACTION_IDS_KB | ||
| 84 | |||
| 85 | // user/keymap-specific | ||
| 86 | #ifdef SPLIT_TRANSACTION_IDS_USER | ||
| 87 | SPLIT_TRANSACTION_IDS_USER, | ||
| 88 | #endif // SPLIT_TRANSACTION_IDS_USER | ||
| 89 | |||
| 90 | NUM_TOTAL_TRANSACTIONS | ||
| 91 | }; | ||
| 92 | |||
| 93 | // Ensure we only use 5 bits for transaction | ||
| 94 | _Static_assert(NUM_TOTAL_TRANSACTIONS <= (1 << 5), "Max number of usable transactions exceeded"); | ||
diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c new file mode 100644 index 000000000..99a8623b3 --- /dev/null +++ b/quantum/split_common/transactions.c | |||
| @@ -0,0 +1,670 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <string.h> | ||
| 18 | #include <stddef.h> | ||
| 19 | |||
| 20 | #include "debug.h" | ||
| 21 | #include "matrix.h" | ||
| 22 | #include "quantum.h" | ||
| 23 | #include "transactions.h" | ||
| 24 | #include "transport.h" | ||
| 25 | #include "transaction_id_define.h" | ||
| 26 | |||
| 27 | #define SYNC_TIMER_OFFSET 2 | ||
| 28 | |||
| 29 | #ifndef FORCED_SYNC_THROTTLE_MS | ||
| 30 | # define FORCED_SYNC_THROTTLE_MS 100 | ||
| 31 | #endif // FORCED_SYNC_THROTTLE_MS | ||
| 32 | |||
| 33 | #define sizeof_member(type, member) sizeof(((type *)NULL)->member) | ||
| 34 | |||
| 35 | #define trans_initiator2target_initializer_cb(member, cb) \ | ||
| 36 | { &dummy, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), 0, 0, cb } | ||
| 37 | #define trans_initiator2target_initializer(member) trans_initiator2target_initializer_cb(member, NULL) | ||
| 38 | |||
| 39 | #define trans_target2initiator_initializer_cb(member, cb) \ | ||
| 40 | { &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb } | ||
| 41 | #define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL) | ||
| 42 | |||
| 43 | #define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0) | ||
| 44 | #define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length) | ||
| 45 | |||
| 46 | static uint8_t crc8(const void *data, size_t len) { | ||
| 47 | const uint8_t *p = (const uint8_t *)data; | ||
| 48 | uint8_t crc = 0xff; | ||
| 49 | size_t i, j; | ||
| 50 | for (i = 0; i < len; i++) { | ||
| 51 | crc ^= p[i]; | ||
| 52 | for (j = 0; j < 8; j++) { | ||
| 53 | if ((crc & 0x80) != 0) | ||
| 54 | crc = (uint8_t)((crc << 1) ^ 0x31); | ||
| 55 | else | ||
| 56 | crc <<= 1; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | return crc; | ||
| 60 | } | ||
| 61 | |||
| 62 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 63 | // Forward-declare the RPC callback handlers | ||
| 64 | void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); | ||
| 65 | void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); | ||
| 66 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 67 | |||
| 68 | //////////////////////////////////////////////////// | ||
| 69 | // Helpers | ||
| 70 | |||
| 71 | 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[])) { | ||
| 72 | if (okay) { | ||
| 73 | bool this_okay = true; | ||
| 74 | for (int iter = 1; iter <= 10; ++iter) { | ||
| 75 | if (!this_okay) { | ||
| 76 | for (int i = 0; i < iter * iter; ++i) { | ||
| 77 | wait_us(10); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | ATOMIC_BLOCK_FORCEON { this_okay = handler(master_matrix, slave_matrix); }; | ||
| 81 | if (this_okay) break; | ||
| 82 | } | ||
| 83 | okay &= this_okay; | ||
| 84 | if (!okay) { | ||
| 85 | dprintf("Failed to execute %s\n", prefix); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | return okay; | ||
| 89 | } | ||
| 90 | |||
| 91 | #define TRANSACTION_HANDLER_MASTER(prefix) \ | ||
| 92 | do { \ | ||
| 93 | okay &= transaction_handler_master(okay, master_matrix, slave_matrix, #prefix, &prefix##_master); \ | ||
| 94 | } while (0) | ||
| 95 | |||
| 96 | #define TRANSACTION_HANDLER_SLAVE(prefix) \ | ||
| 97 | do { \ | ||
| 98 | ATOMIC_BLOCK_FORCEON { prefix##_slave(master_matrix, slave_matrix); }; \ | ||
| 99 | } while (0) | ||
| 100 | |||
| 101 | 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) { | ||
| 102 | uint8_t curr_checksum; | ||
| 103 | bool okay = transport_read(trans_id_checksum, &curr_checksum, sizeof(curr_checksum)); | ||
| 104 | if (okay && (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || curr_checksum != crc8(equiv_shmem, length))) { | ||
| 105 | okay &= transport_read(trans_id_retrieve, destination, length); | ||
| 106 | okay &= curr_checksum == crc8(equiv_shmem, length); | ||
| 107 | if (okay) { | ||
| 108 | *last_update = timer_read32(); | ||
| 109 | } | ||
| 110 | } else { | ||
| 111 | memcpy(destination, equiv_shmem, length); | ||
| 112 | } | ||
| 113 | return okay; | ||
| 114 | } | ||
| 115 | |||
| 116 | inline static bool send_if_condition(int8_t trans_id, uint32_t *last_update, bool condition, void *source, size_t length) { | ||
| 117 | bool okay = true; | ||
| 118 | if (timer_elapsed32(*last_update) >= FORCED_SYNC_THROTTLE_MS || condition) { | ||
| 119 | okay &= transport_write(trans_id, source, length); | ||
| 120 | if (okay) { | ||
| 121 | *last_update = timer_read32(); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | return okay; | ||
| 125 | } | ||
| 126 | |||
| 127 | inline static bool send_if_data_mismatch(int8_t trans_id, uint32_t *last_update, void *source, const void *equiv_shmem, size_t length) { | ||
| 128 | // Just run a memcmp to compare the source and equivalent shmem location | ||
| 129 | return send_if_condition(trans_id, last_update, (memcmp(source, equiv_shmem, length) != 0), source, length); | ||
| 130 | } | ||
| 131 | |||
| 132 | //////////////////////////////////////////////////// | ||
| 133 | // Slave matrix | ||
| 134 | |||
| 135 | static bool slave_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 136 | static uint32_t last_update = 0; | ||
| 137 | static matrix_row_t last_matrix[(MATRIX_ROWS) / 2] = {0}; // last successfully-read matrix, so we can replicate if there are checksum errors | ||
| 138 | matrix_row_t temp_matrix[(MATRIX_ROWS) / 2]; // holding area while we test whether or not checksum is correct | ||
| 139 | |||
| 140 | 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)); | ||
| 141 | if (okay) { | ||
| 142 | // Checksum matches the received data, save as the last matrix state | ||
| 143 | memcpy(last_matrix, temp_matrix, sizeof(temp_matrix)); | ||
| 144 | } | ||
| 145 | // Copy out the last-known-good matrix state to the slave matrix | ||
| 146 | memcpy(slave_matrix, last_matrix, sizeof(last_matrix)); | ||
| 147 | return okay; | ||
| 148 | } | ||
| 149 | |||
| 150 | static void slave_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 151 | memcpy(split_shmem->smatrix.matrix, slave_matrix, sizeof(split_shmem->smatrix.matrix)); | ||
| 152 | split_shmem->smatrix.checksum = crc8(split_shmem->smatrix.matrix, sizeof(split_shmem->smatrix.matrix)); | ||
| 153 | } | ||
| 154 | |||
| 155 | // clang-format off | ||
| 156 | #define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix_handlers) | ||
| 157 | #define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix_handlers) | ||
| 158 | #define TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS \ | ||
| 159 | [GET_SLAVE_MATRIX_CHECKSUM] = trans_target2initiator_initializer(smatrix.checksum), \ | ||
| 160 | [GET_SLAVE_MATRIX_DATA] = trans_target2initiator_initializer(smatrix.matrix), | ||
| 161 | // clang-format on | ||
| 162 | |||
| 163 | //////////////////////////////////////////////////// | ||
| 164 | // Master matrix | ||
| 165 | |||
| 166 | #ifdef SPLIT_TRANSPORT_MIRROR | ||
| 167 | |||
| 168 | static bool master_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 169 | static uint32_t last_update = 0; | ||
| 170 | return send_if_data_mismatch(PUT_MASTER_MATRIX, &last_update, master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix)); | ||
| 171 | } | ||
| 172 | |||
| 173 | static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 174 | // Always copy to the master matrix | ||
| 175 | memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix)); | ||
| 176 | } | ||
| 177 | |||
| 178 | # define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix_handlers) | ||
| 179 | # define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix_handlers) | ||
| 180 | # define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix), | ||
| 181 | |||
| 182 | #else // SPLIT_TRANSPORT_MIRROR | ||
| 183 | |||
| 184 | # define TRANSACTIONS_MASTER_MATRIX_MASTER() | ||
| 185 | # define TRANSACTIONS_MASTER_MATRIX_SLAVE() | ||
| 186 | # define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS | ||
| 187 | |||
| 188 | #endif // SPLIT_TRANSPORT_MIRROR | ||
| 189 | |||
| 190 | //////////////////////////////////////////////////// | ||
| 191 | // Encoders | ||
| 192 | |||
| 193 | #ifdef ENCODER_ENABLE | ||
| 194 | |||
| 195 | static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 196 | static uint32_t last_update = 0; | ||
| 197 | uint8_t temp_state[NUMBER_OF_ENCODERS]; | ||
| 198 | |||
| 199 | bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, temp_state, split_shmem->encoders.state, sizeof(temp_state)); | ||
| 200 | if (okay) encoder_update_raw(temp_state); | ||
| 201 | return okay; | ||
| 202 | } | ||
| 203 | |||
| 204 | static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 205 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; | ||
| 206 | encoder_state_raw(encoder_state); | ||
| 207 | // Always prepare the encoder state for read. | ||
| 208 | memcpy(split_shmem->encoders.state, encoder_state, sizeof(encoder_state)); | ||
| 209 | // Now update the checksum given that the encoders has been written to | ||
| 210 | split_shmem->encoders.checksum = crc8(encoder_state, sizeof(encoder_state)); | ||
| 211 | } | ||
| 212 | |||
| 213 | // clang-format off | ||
| 214 | # define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder_handlers) | ||
| 215 | # define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder_handlers) | ||
| 216 | # define TRANSACTIONS_ENCODERS_REGISTRATIONS \ | ||
| 217 | [GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \ | ||
| 218 | [GET_ENCODERS_DATA] = trans_target2initiator_initializer(encoders.state), | ||
| 219 | // clang-format on | ||
| 220 | |||
| 221 | #else // ENCODER_ENABLE | ||
| 222 | |||
| 223 | # define TRANSACTIONS_ENCODERS_MASTER() | ||
| 224 | # define TRANSACTIONS_ENCODERS_SLAVE() | ||
| 225 | # define TRANSACTIONS_ENCODERS_REGISTRATIONS | ||
| 226 | |||
| 227 | #endif // ENCODER_ENABLE | ||
| 228 | |||
| 229 | //////////////////////////////////////////////////// | ||
| 230 | // Sync timer | ||
| 231 | |||
| 232 | #ifndef DISABLE_SYNC_TIMER | ||
| 233 | |||
| 234 | static bool sync_timer_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 235 | static uint32_t last_update = 0; | ||
| 236 | |||
| 237 | bool okay = true; | ||
| 238 | if (timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS) { | ||
| 239 | uint32_t sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; | ||
| 240 | okay &= transport_write(PUT_SYNC_TIMER, &sync_timer, sizeof(sync_timer)); | ||
| 241 | if (okay) { | ||
| 242 | last_update = timer_read32(); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | return okay; | ||
| 246 | } | ||
| 247 | |||
| 248 | static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 249 | static uint32_t last_sync_timer = 0; | ||
| 250 | if (last_sync_timer != split_shmem->sync_timer) { | ||
| 251 | last_sync_timer = split_shmem->sync_timer; | ||
| 252 | sync_timer_update(last_sync_timer); | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | # define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer_handlers) | ||
| 257 | # define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer_handlers) | ||
| 258 | # define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer), | ||
| 259 | |||
| 260 | #else // DISABLE_SYNC_TIMER | ||
| 261 | |||
| 262 | # define TRANSACTIONS_SYNC_TIMER_MASTER() | ||
| 263 | # define TRANSACTIONS_SYNC_TIMER_SLAVE() | ||
| 264 | # define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS | ||
| 265 | |||
| 266 | #endif // DISABLE_SYNC_TIMER | ||
| 267 | |||
| 268 | //////////////////////////////////////////////////// | ||
| 269 | // Layer state | ||
| 270 | |||
| 271 | #if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 272 | |||
| 273 | static bool layer_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 274 | static uint32_t last_layer_state_update = 0; | ||
| 275 | static uint32_t last_default_layer_state_update = 0; | ||
| 276 | |||
| 277 | bool okay = send_if_condition(PUT_LAYER_STATE, &last_layer_state_update, (layer_state != split_shmem->layers.layer_state), &layer_state, sizeof(layer_state)); | ||
| 278 | if (okay) { | ||
| 279 | 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)); | ||
| 280 | } | ||
| 281 | return okay; | ||
| 282 | } | ||
| 283 | |||
| 284 | static void layer_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 285 | layer_state = split_shmem->layers.layer_state; | ||
| 286 | default_layer_state = split_shmem->layers.default_layer_state; | ||
| 287 | } | ||
| 288 | |||
| 289 | // clang-format off | ||
| 290 | # define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state_handlers) | ||
| 291 | # define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state_handlers) | ||
| 292 | # define TRANSACTIONS_LAYER_STATE_REGISTRATIONS \ | ||
| 293 | [PUT_LAYER_STATE] = trans_initiator2target_initializer(layers.layer_state), \ | ||
| 294 | [PUT_DEFAULT_LAYER_STATE] = trans_initiator2target_initializer(layers.default_layer_state), | ||
| 295 | // clang-format on | ||
| 296 | |||
| 297 | #else // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 298 | |||
| 299 | # define TRANSACTIONS_LAYER_STATE_MASTER() | ||
| 300 | # define TRANSACTIONS_LAYER_STATE_SLAVE() | ||
| 301 | # define TRANSACTIONS_LAYER_STATE_REGISTRATIONS | ||
| 302 | |||
| 303 | #endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 304 | |||
| 305 | //////////////////////////////////////////////////// | ||
| 306 | // LED state | ||
| 307 | |||
| 308 | #ifdef SPLIT_LED_STATE_ENABLE | ||
| 309 | |||
| 310 | static bool led_state_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 311 | static uint32_t last_update = 0; | ||
| 312 | uint8_t led_state = host_keyboard_leds(); | ||
| 313 | return send_if_data_mismatch(PUT_LED_STATE, &last_update, &led_state, &split_shmem->led_state, sizeof(led_state)); | ||
| 314 | } | ||
| 315 | |||
| 316 | static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 317 | void set_split_host_keyboard_leds(uint8_t led_state); | ||
| 318 | set_split_host_keyboard_leds(split_shmem->led_state); | ||
| 319 | } | ||
| 320 | |||
| 321 | # define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state_handlers) | ||
| 322 | # define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state_handlers) | ||
| 323 | # define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state), | ||
| 324 | |||
| 325 | #else // SPLIT_LED_STATE_ENABLE | ||
| 326 | |||
| 327 | # define TRANSACTIONS_LED_STATE_MASTER() | ||
| 328 | # define TRANSACTIONS_LED_STATE_SLAVE() | ||
| 329 | # define TRANSACTIONS_LED_STATE_REGISTRATIONS | ||
| 330 | |||
| 331 | #endif // SPLIT_LED_STATE_ENABLE | ||
| 332 | |||
| 333 | //////////////////////////////////////////////////// | ||
| 334 | // Mods | ||
| 335 | |||
| 336 | #ifdef SPLIT_MODS_ENABLE | ||
| 337 | |||
| 338 | static bool mods_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 339 | static uint32_t last_update = 0; | ||
| 340 | bool mods_need_sync = timer_elapsed32(last_update) >= FORCED_SYNC_THROTTLE_MS; | ||
| 341 | split_mods_sync_t new_mods; | ||
| 342 | new_mods.real_mods = get_mods(); | ||
| 343 | if (!mods_need_sync && new_mods.real_mods != split_shmem->mods.real_mods) { | ||
| 344 | mods_need_sync = true; | ||
| 345 | } | ||
| 346 | |||
| 347 | new_mods.weak_mods = get_weak_mods(); | ||
| 348 | if (!mods_need_sync && new_mods.weak_mods != split_shmem->mods.weak_mods) { | ||
| 349 | mods_need_sync = true; | ||
| 350 | } | ||
| 351 | |||
| 352 | # ifndef NO_ACTION_ONESHOT | ||
| 353 | new_mods.oneshot_mods = get_oneshot_mods(); | ||
| 354 | if (!mods_need_sync && new_mods.oneshot_mods != split_shmem->mods.oneshot_mods) { | ||
| 355 | mods_need_sync = true; | ||
| 356 | } | ||
| 357 | # endif // NO_ACTION_ONESHOT | ||
| 358 | |||
| 359 | bool okay = true; | ||
| 360 | if (mods_need_sync) { | ||
| 361 | okay &= transport_write(PUT_MODS, &new_mods, sizeof(new_mods)); | ||
| 362 | if (okay) { | ||
| 363 | last_update = timer_read32(); | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | return okay; | ||
| 368 | } | ||
| 369 | |||
| 370 | static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 371 | set_mods(split_shmem->mods.real_mods); | ||
| 372 | set_weak_mods(split_shmem->mods.weak_mods); | ||
| 373 | # ifndef NO_ACTION_ONESHOT | ||
| 374 | set_oneshot_mods(split_shmem->mods.oneshot_mods); | ||
| 375 | # endif | ||
| 376 | } | ||
| 377 | |||
| 378 | # define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods_handlers) | ||
| 379 | # define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods_handlers) | ||
| 380 | # define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods), | ||
| 381 | |||
| 382 | #else // SPLIT_MODS_ENABLE | ||
| 383 | |||
| 384 | # define TRANSACTIONS_MODS_MASTER() | ||
| 385 | # define TRANSACTIONS_MODS_SLAVE() | ||
| 386 | # define TRANSACTIONS_MODS_REGISTRATIONS | ||
| 387 | |||
| 388 | #endif // SPLIT_MODS_ENABLE | ||
| 389 | |||
| 390 | //////////////////////////////////////////////////// | ||
| 391 | // Backlight | ||
| 392 | |||
| 393 | #ifdef BACKLIGHT_ENABLE | ||
| 394 | |||
| 395 | static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 396 | static uint32_t last_update = 0; | ||
| 397 | uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; | ||
| 398 | return send_if_condition(PUT_BACKLIGHT, &last_update, (level != split_shmem->backlight_level), &level, sizeof(level)); | ||
| 399 | } | ||
| 400 | |||
| 401 | static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); } | ||
| 402 | |||
| 403 | # define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight_handlers) | ||
| 404 | # define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight_handlers) | ||
| 405 | # define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level), | ||
| 406 | |||
| 407 | #else // BACKLIGHT_ENABLE | ||
| 408 | |||
| 409 | # define TRANSACTIONS_BACKLIGHT_MASTER() | ||
| 410 | # define TRANSACTIONS_BACKLIGHT_SLAVE() | ||
| 411 | # define TRANSACTIONS_BACKLIGHT_REGISTRATIONS | ||
| 412 | |||
| 413 | #endif // BACKLIGHT_ENABLE | ||
| 414 | |||
| 415 | //////////////////////////////////////////////////// | ||
| 416 | // RGBLIGHT | ||
| 417 | |||
| 418 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 419 | |||
| 420 | static bool rgblight_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 421 | static uint32_t last_update = 0; | ||
| 422 | rgblight_syncinfo_t rgblight_sync; | ||
| 423 | rgblight_get_syncinfo(&rgblight_sync); | ||
| 424 | if (send_if_condition(PUT_RGBLIGHT, &last_update, (rgblight_sync.status.change_flags != 0), &rgblight_sync, sizeof(rgblight_sync))) { | ||
| 425 | rgblight_clear_change_flags(); | ||
| 426 | } else { | ||
| 427 | return false; | ||
| 428 | } | ||
| 429 | return true; | ||
| 430 | } | ||
| 431 | |||
| 432 | static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 433 | // Update the RGB with the new data | ||
| 434 | if (split_shmem->rgblight_sync.status.change_flags != 0) { | ||
| 435 | rgblight_update_sync(&split_shmem->rgblight_sync, false); | ||
| 436 | split_shmem->rgblight_sync.status.change_flags = 0; | ||
| 437 | } | ||
| 438 | } | ||
| 439 | |||
| 440 | # define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight_handlers) | ||
| 441 | # define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight_handlers) | ||
| 442 | # define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync), | ||
| 443 | |||
| 444 | #else // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 445 | |||
| 446 | # define TRANSACTIONS_RGBLIGHT_MASTER() | ||
| 447 | # define TRANSACTIONS_RGBLIGHT_SLAVE() | ||
| 448 | # define TRANSACTIONS_RGBLIGHT_REGISTRATIONS | ||
| 449 | |||
| 450 | #endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 451 | |||
| 452 | //////////////////////////////////////////////////// | ||
| 453 | // LED Matrix | ||
| 454 | |||
| 455 | #if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 456 | |||
| 457 | static bool led_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 458 | static uint32_t last_update = 0; | ||
| 459 | led_matrix_sync_t led_matrix_sync; | ||
| 460 | memcpy(&led_matrix_sync.led_matrix, &led_matrix_eeconfig, sizeof(led_eeconfig_t)); | ||
| 461 | led_matrix_sync.led_suspend_state = led_matrix_get_suspend_state(); | ||
| 462 | return send_if_data_mismatch(PUT_LED_MATRIX, &last_update, &led_matrix_sync, &split_shmem->led_matrix_sync, sizeof(led_matrix_sync)); | ||
| 463 | } | ||
| 464 | |||
| 465 | static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 466 | memcpy(&led_matrix_eeconfig, &split_shmem->led_matrix_sync.led_matrix, sizeof(led_eeconfig_t)); | ||
| 467 | led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state); | ||
| 468 | } | ||
| 469 | |||
| 470 | # define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix_handlers) | ||
| 471 | # define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix_handlers) | ||
| 472 | # define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync), | ||
| 473 | |||
| 474 | #else // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 475 | |||
| 476 | # define TRANSACTIONS_LED_MATRIX_MASTER() | ||
| 477 | # define TRANSACTIONS_LED_MATRIX_SLAVE() | ||
| 478 | # define TRANSACTIONS_LED_MATRIX_REGISTRATIONS | ||
| 479 | |||
| 480 | #endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 481 | |||
| 482 | //////////////////////////////////////////////////// | ||
| 483 | // RGB Matrix | ||
| 484 | |||
| 485 | #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 486 | |||
| 487 | static bool rgb_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 488 | static uint32_t last_update = 0; | ||
| 489 | rgb_matrix_sync_t rgb_matrix_sync; | ||
| 490 | memcpy(&rgb_matrix_sync.rgb_matrix, &rgb_matrix_config, sizeof(rgb_config_t)); | ||
| 491 | rgb_matrix_sync.rgb_suspend_state = rgb_matrix_get_suspend_state(); | ||
| 492 | return send_if_data_mismatch(PUT_RGB_MATRIX, &last_update, &rgb_matrix_sync, &split_shmem->rgb_matrix_sync, sizeof(rgb_matrix_sync)); | ||
| 493 | } | ||
| 494 | |||
| 495 | static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 496 | memcpy(&rgb_matrix_config, &split_shmem->rgb_matrix_sync.rgb_matrix, sizeof(rgb_config_t)); | ||
| 497 | rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state); | ||
| 498 | } | ||
| 499 | |||
| 500 | # define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix_handlers) | ||
| 501 | # define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix_handlers) | ||
| 502 | # define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync), | ||
| 503 | |||
| 504 | #else // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 505 | |||
| 506 | # define TRANSACTIONS_RGB_MATRIX_MASTER() | ||
| 507 | # define TRANSACTIONS_RGB_MATRIX_SLAVE() | ||
| 508 | # define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS | ||
| 509 | |||
| 510 | #endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 511 | |||
| 512 | //////////////////////////////////////////////////// | ||
| 513 | // WPM | ||
| 514 | |||
| 515 | #if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 516 | |||
| 517 | static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 518 | static uint32_t last_update = 0; | ||
| 519 | uint8_t current_wpm = get_current_wpm(); | ||
| 520 | return send_if_condition(PUT_WPM, &last_update, (current_wpm != split_shmem->current_wpm), ¤t_wpm, sizeof(current_wpm)); | ||
| 521 | } | ||
| 522 | |||
| 523 | static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); } | ||
| 524 | |||
| 525 | # define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm_handlers) | ||
| 526 | # define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm_handlers) | ||
| 527 | # define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm), | ||
| 528 | |||
| 529 | #else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 530 | |||
| 531 | # define TRANSACTIONS_WPM_MASTER() | ||
| 532 | # define TRANSACTIONS_WPM_SLAVE() | ||
| 533 | # define TRANSACTIONS_WPM_REGISTRATIONS | ||
| 534 | |||
| 535 | #endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 536 | |||
| 537 | //////////////////////////////////////////////////// | ||
| 538 | |||
| 539 | uint8_t dummy; | ||
| 540 | split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { | ||
| 541 | // Set defaults | ||
| 542 | [0 ...(NUM_TOTAL_TRANSACTIONS - 1)] = {NULL, 0, 0, 0, 0, 0}, | ||
| 543 | |||
| 544 | #ifdef USE_I2C | ||
| 545 | [I2C_EXECUTE_CALLBACK] = trans_initiator2target_initializer(transaction_id), | ||
| 546 | #endif // USE_I2C | ||
| 547 | |||
| 548 | // clang-format off | ||
| 549 | TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS | ||
| 550 | TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS | ||
| 551 | TRANSACTIONS_ENCODERS_REGISTRATIONS | ||
| 552 | TRANSACTIONS_SYNC_TIMER_REGISTRATIONS | ||
| 553 | TRANSACTIONS_LAYER_STATE_REGISTRATIONS | ||
| 554 | TRANSACTIONS_LED_STATE_REGISTRATIONS | ||
| 555 | TRANSACTIONS_MODS_REGISTRATIONS | ||
| 556 | TRANSACTIONS_BACKLIGHT_REGISTRATIONS | ||
| 557 | TRANSACTIONS_RGBLIGHT_REGISTRATIONS | ||
| 558 | TRANSACTIONS_LED_MATRIX_REGISTRATIONS | ||
| 559 | TRANSACTIONS_RGB_MATRIX_REGISTRATIONS | ||
| 560 | TRANSACTIONS_WPM_REGISTRATIONS | ||
| 561 | // clang-format on | ||
| 562 | |||
| 563 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 564 | [PUT_RPC_INFO] = trans_initiator2target_initializer_cb(rpc_info, slave_rpc_info_callback), | ||
| 565 | [PUT_RPC_REQ_DATA] = trans_initiator2target_initializer(rpc_m2s_buffer), | ||
| 566 | [EXECUTE_RPC] = trans_initiator2target_initializer_cb(rpc_info.transaction_id, slave_rpc_exec_callback), | ||
| 567 | [GET_RPC_RESP_DATA] = trans_target2initiator_initializer(rpc_s2m_buffer), | ||
| 568 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 569 | }; | ||
| 570 | |||
| 571 | bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 572 | bool okay = true; | ||
| 573 | TRANSACTIONS_SLAVE_MATRIX_MASTER(); | ||
| 574 | TRANSACTIONS_MASTER_MATRIX_MASTER(); | ||
| 575 | TRANSACTIONS_ENCODERS_MASTER(); | ||
| 576 | TRANSACTIONS_SYNC_TIMER_MASTER(); | ||
| 577 | TRANSACTIONS_LAYER_STATE_MASTER(); | ||
| 578 | TRANSACTIONS_LED_STATE_MASTER(); | ||
| 579 | TRANSACTIONS_MODS_MASTER(); | ||
| 580 | TRANSACTIONS_BACKLIGHT_MASTER(); | ||
| 581 | TRANSACTIONS_RGBLIGHT_MASTER(); | ||
| 582 | TRANSACTIONS_LED_MATRIX_MASTER(); | ||
| 583 | TRANSACTIONS_RGB_MATRIX_MASTER(); | ||
| 584 | TRANSACTIONS_WPM_MASTER(); | ||
| 585 | return okay; | ||
| 586 | } | ||
| 587 | |||
| 588 | void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 589 | TRANSACTIONS_SLAVE_MATRIX_SLAVE(); | ||
| 590 | TRANSACTIONS_MASTER_MATRIX_SLAVE(); | ||
| 591 | TRANSACTIONS_ENCODERS_SLAVE(); | ||
| 592 | TRANSACTIONS_SYNC_TIMER_SLAVE(); | ||
| 593 | TRANSACTIONS_LAYER_STATE_SLAVE(); | ||
| 594 | TRANSACTIONS_LED_STATE_SLAVE(); | ||
| 595 | TRANSACTIONS_MODS_SLAVE(); | ||
| 596 | TRANSACTIONS_BACKLIGHT_SLAVE(); | ||
| 597 | TRANSACTIONS_RGBLIGHT_SLAVE(); | ||
| 598 | TRANSACTIONS_LED_MATRIX_SLAVE(); | ||
| 599 | TRANSACTIONS_RGB_MATRIX_SLAVE(); | ||
| 600 | TRANSACTIONS_WPM_SLAVE(); | ||
| 601 | } | ||
| 602 | |||
| 603 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 604 | |||
| 605 | void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback) { | ||
| 606 | // Prevent invoking RPC on QMK core sync data | ||
| 607 | if (transaction_id <= GET_RPC_RESP_DATA) return; | ||
| 608 | |||
| 609 | // Set the callback | ||
| 610 | split_transaction_table[transaction_id].slave_callback = callback; | ||
| 611 | split_transaction_table[transaction_id].initiator2target_offset = offsetof(split_shared_memory_t, rpc_m2s_buffer); | ||
| 612 | split_transaction_table[transaction_id].target2initiator_offset = offsetof(split_shared_memory_t, rpc_s2m_buffer); | ||
| 613 | } | ||
| 614 | |||
| 615 | 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) { | ||
| 616 | // Prevent invoking RPC on QMK core sync data | ||
| 617 | if (transaction_id <= GET_RPC_RESP_DATA) return false; | ||
| 618 | // Prevent sizing issues | ||
| 619 | if (initiator2target_buffer_size > RPC_M2S_BUFFER_SIZE) return false; | ||
| 620 | if (target2initiator_buffer_size > RPC_S2M_BUFFER_SIZE) return false; | ||
| 621 | |||
| 622 | // Prepare the metadata block | ||
| 623 | rpc_sync_info_t info = {.transaction_id = transaction_id, .m2s_length = initiator2target_buffer_size, .s2m_length = target2initiator_buffer_size}; | ||
| 624 | |||
| 625 | // Make sure the local side knows that we're not sending the full block of data | ||
| 626 | split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = initiator2target_buffer_size; | ||
| 627 | split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = target2initiator_buffer_size; | ||
| 628 | |||
| 629 | // Run through the sequence: | ||
| 630 | // * set the transaction ID and lengths | ||
| 631 | // * send the request data | ||
| 632 | // * execute RPC callback | ||
| 633 | // * retrieve the response data | ||
| 634 | if (!transport_write(PUT_RPC_INFO, &info, sizeof(info))) { | ||
| 635 | return false; | ||
| 636 | } | ||
| 637 | if (!transport_write(PUT_RPC_REQ_DATA, initiator2target_buffer, initiator2target_buffer_size)) { | ||
| 638 | return false; | ||
| 639 | } | ||
| 640 | if (!transport_write(EXECUTE_RPC, &transaction_id, sizeof(transaction_id))) { | ||
| 641 | return false; | ||
| 642 | } | ||
| 643 | if (!transport_read(GET_RPC_RESP_DATA, target2initiator_buffer, target2initiator_buffer_size)) { | ||
| 644 | return false; | ||
| 645 | } | ||
| 646 | return true; | ||
| 647 | } | ||
| 648 | |||
| 649 | void slave_rpc_info_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { | ||
| 650 | // The RPC info block contains the intended transaction ID, as well as the sizes for both inbound and outbound data. | ||
| 651 | // Ignore the args -- the `split_shmem` already has the info, we just need to act upon it. | ||
| 652 | // We must keep the `split_transaction_table` non-const, so that it is able to be modified at runtime. | ||
| 653 | |||
| 654 | split_transaction_table[PUT_RPC_REQ_DATA].initiator2target_buffer_size = split_shmem->rpc_info.m2s_length; | ||
| 655 | split_transaction_table[GET_RPC_RESP_DATA].target2initiator_buffer_size = split_shmem->rpc_info.s2m_length; | ||
| 656 | } | ||
| 657 | |||
| 658 | void slave_rpc_exec_callback(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) { | ||
| 659 | // We can assume that the buffer lengths are correctly set, now, given that sequentially the rpc_info callback was already executed. | ||
| 660 | // Go through the rpc_info and execute _that_ transaction's callback, with the scratch buffers as inputs. | ||
| 661 | int8_t transaction_id = split_shmem->rpc_info.transaction_id; | ||
| 662 | if (transaction_id < NUM_TOTAL_TRANSACTIONS) { | ||
| 663 | split_transaction_desc_t *trans = &split_transaction_table[transaction_id]; | ||
| 664 | if (trans->slave_callback) { | ||
| 665 | 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); | ||
| 666 | } | ||
| 667 | } | ||
| 668 | } | ||
| 669 | |||
| 670 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
diff --git a/quantum/split_common/transactions.h b/quantum/split_common/transactions.h new file mode 100644 index 000000000..4306ba1d8 --- /dev/null +++ b/quantum/split_common/transactions.h | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #pragma once | ||
| 18 | |||
| 19 | #include "stdint.h" | ||
| 20 | #include "stdbool.h" | ||
| 21 | |||
| 22 | #include "matrix.h" | ||
| 23 | #include "transaction_id_define.h" | ||
| 24 | #include "transport.h" | ||
| 25 | |||
| 26 | typedef void (*slave_callback_t)(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer); | ||
| 27 | |||
| 28 | // Split transaction Descriptor | ||
| 29 | typedef struct _split_transaction_desc_t { | ||
| 30 | uint8_t * status; | ||
| 31 | uint8_t initiator2target_buffer_size; | ||
| 32 | uint16_t initiator2target_offset; | ||
| 33 | uint8_t target2initiator_buffer_size; | ||
| 34 | uint16_t target2initiator_offset; | ||
| 35 | slave_callback_t slave_callback; | ||
| 36 | } split_transaction_desc_t; | ||
| 37 | |||
| 38 | // Forward declaration for the split transactions | ||
| 39 | extern split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS]; | ||
| 40 | |||
| 41 | #define split_shmem_offset_ptr(offset) ((void *)(((uint8_t *)split_shmem) + (offset))) | ||
| 42 | #define split_trans_initiator2target_buffer(trans) (split_shmem_offset_ptr((trans)->initiator2target_offset)) | ||
| 43 | #define split_trans_target2initiator_buffer(trans) (split_shmem_offset_ptr((trans)->target2initiator_offset)) | ||
| 44 | |||
| 45 | // returns false if valid data not received from slave | ||
| 46 | bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); | ||
| 47 | void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); | ||
| 48 | |||
| 49 | void transaction_register_rpc(int8_t transaction_id, slave_callback_t callback); | ||
| 50 | |||
| 51 | 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); | ||
| 52 | |||
| 53 | #define transaction_rpc_send(transaction_id, initiator2target_buffer_size, initiator2target_buffer) transaction_rpc_exec(transaction_id, initiator2target_buffer_size, initiator2target_buffer, 0, NULL) | ||
| 54 | #define transaction_rpc_recv(transaction_id, target2initiator_buffer_size, target2initiator_buffer) transaction_rpc_exec(transaction_id, 0, NULL, target2initiator_buffer_size, target2initiator_buffer) | ||
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 9ed0f7591..a711ef85f 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c | |||
| @@ -1,452 +1,118 @@ | |||
| 1 | #include <string.h> | 1 | /* Copyright 2021 QMK |
| 2 | #include <stddef.h> | 2 | * |
| 3 | 3 | * This program is free software: you can redistribute it and/or modify | |
| 4 | #include "config.h" | 4 | * it under the terms of the GNU General Public License as published by |
| 5 | #include "matrix.h" | 5 | * the Free Software Foundation, either version 2 of the License, or |
| 6 | #include "quantum.h" | 6 | * (at your option) any later version. |
| 7 | 7 | * | |
| 8 | #define ROWS_PER_HAND (MATRIX_ROWS / 2) | 8 | * This program is distributed in the hope that it will be useful, |
| 9 | #define SYNC_TIMER_OFFSET 2 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 11 | #ifdef RGBLIGHT_ENABLE | 11 | * GNU General Public License for more details. |
| 12 | # include "rgblight.h" | 12 | * |
| 13 | #endif | 13 | * You should have received a copy of the GNU General Public License |
| 14 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 15 | #ifdef BACKLIGHT_ENABLE | 15 | */ |
| 16 | # include "backlight.h" | ||
| 17 | #endif | ||
| 18 | |||
| 19 | #ifdef ENCODER_ENABLE | ||
| 20 | # include "encoder.h" | ||
| 21 | static pin_t encoders_pad[] = ENCODERS_PAD_A; | ||
| 22 | # define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t)) | ||
| 23 | #endif | ||
| 24 | |||
| 25 | #if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 26 | # include "led_matrix.h" | ||
| 27 | #endif | ||
| 28 | #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 29 | # include "rgb_matrix.h" | ||
| 30 | #endif | ||
| 31 | |||
| 32 | #if defined(USE_I2C) | ||
| 33 | 16 | ||
| 34 | # include "i2c_master.h" | 17 | #include <string.h> |
| 35 | # include "i2c_slave.h" | 18 | #include <debug.h> |
| 36 | |||
| 37 | typedef struct _I2C_slave_buffer_t { | ||
| 38 | # ifndef DISABLE_SYNC_TIMER | ||
| 39 | uint32_t sync_timer; | ||
| 40 | # endif | ||
| 41 | # ifdef SPLIT_TRANSPORT_MIRROR | ||
| 42 | matrix_row_t mmatrix[ROWS_PER_HAND]; | ||
| 43 | # endif | ||
| 44 | matrix_row_t smatrix[ROWS_PER_HAND]; | ||
| 45 | # ifdef SPLIT_MODS_ENABLE | ||
| 46 | uint8_t real_mods; | ||
| 47 | uint8_t weak_mods; | ||
| 48 | # ifndef NO_ACTION_ONESHOT | ||
| 49 | uint8_t oneshot_mods; | ||
| 50 | # endif | ||
| 51 | # endif | ||
| 52 | # ifdef BACKLIGHT_ENABLE | ||
| 53 | uint8_t backlight_level; | ||
| 54 | # endif | ||
| 55 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 56 | rgblight_syncinfo_t rgblight_sync; | ||
| 57 | # endif | ||
| 58 | # ifdef ENCODER_ENABLE | ||
| 59 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; | ||
| 60 | # endif | ||
| 61 | # ifdef WPM_ENABLE | ||
| 62 | uint8_t current_wpm; | ||
| 63 | # endif | ||
| 64 | # if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 65 | led_eeconfig_t led_matrix; | ||
| 66 | bool led_suspend_state; | ||
| 67 | # endif | ||
| 68 | # if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 69 | rgb_config_t rgb_matrix; | ||
| 70 | bool rgb_suspend_state; | ||
| 71 | # endif | ||
| 72 | } I2C_slave_buffer_t; | ||
| 73 | 19 | ||
| 74 | static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; | 20 | #include "transactions.h" |
| 21 | #include "transport.h" | ||
| 22 | #include "transaction_id_define.h" | ||
| 23 | #include "atomic_util.h" | ||
| 75 | 24 | ||
| 76 | # define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer) | 25 | #ifdef USE_I2C |
| 77 | # define I2C_KEYMAP_MASTER_START offsetof(I2C_slave_buffer_t, mmatrix) | ||
| 78 | # define I2C_KEYMAP_SLAVE_START offsetof(I2C_slave_buffer_t, smatrix) | ||
| 79 | # define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods) | ||
| 80 | # define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods) | ||
| 81 | # define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods) | ||
| 82 | # define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) | ||
| 83 | # define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) | ||
| 84 | # define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) | ||
| 85 | # define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) | ||
| 86 | # define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix) | ||
| 87 | # define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state) | ||
| 88 | # define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix) | ||
| 89 | # define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state) | ||
| 90 | 26 | ||
| 91 | # define TIMEOUT 100 | 27 | # ifndef SLAVE_I2C_TIMEOUT |
| 28 | # define SLAVE_I2C_TIMEOUT 100 | ||
| 29 | # endif // SLAVE_I2C_TIMEOUT | ||
| 92 | 30 | ||
| 93 | # ifndef SLAVE_I2C_ADDRESS | 31 | # ifndef SLAVE_I2C_ADDRESS |
| 94 | # define SLAVE_I2C_ADDRESS 0x32 | 32 | # define SLAVE_I2C_ADDRESS 0x32 |
| 95 | # endif | 33 | # endif |
| 96 | 34 | ||
| 97 | // Get rows from other half over i2c | 35 | # include "i2c_master.h" |
| 98 | bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | 36 | # include "i2c_slave.h" |
| 99 | i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_SLAVE_START, (void *)slave_matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); | ||
| 100 | # ifdef SPLIT_TRANSPORT_MIRROR | ||
| 101 | i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_MASTER_START, (void *)master_matrix, sizeof(i2c_buffer->mmatrix), TIMEOUT); | ||
| 102 | # endif | ||
| 103 | 37 | ||
| 104 | // write backlight info | 38 | // Ensure the I2C buffer has enough space |
| 105 | # ifdef BACKLIGHT_ENABLE | 39 | _Static_assert(sizeof(split_shared_memory_t) <= I2C_SLAVE_REG_COUNT, "split_shared_memory_t too large for I2C_SLAVE_REG_COUNT"); |
| 106 | uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0; | ||
| 107 | if (level != i2c_buffer->backlight_level) { | ||
| 108 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { | ||
| 109 | i2c_buffer->backlight_level = level; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | # endif | ||
| 113 | 40 | ||
| 114 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | 41 | split_shared_memory_t *const split_shmem = (split_shared_memory_t *)i2c_slave_reg; |
| 115 | if (rgblight_get_change_flags()) { | ||
| 116 | rgblight_syncinfo_t rgblight_sync; | ||
| 117 | rgblight_get_syncinfo(&rgblight_sync); | ||
| 118 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) { | ||
| 119 | rgblight_clear_change_flags(); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | # endif | ||
| 123 | 42 | ||
| 124 | # ifdef ENCODER_ENABLE | 43 | void transport_master_init(void) { i2c_init(); } |
| 125 | i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT); | 44 | void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } |
| 126 | encoder_update_raw(i2c_buffer->encoder_state); | ||
| 127 | # endif | ||
| 128 | 45 | ||
| 129 | # ifdef WPM_ENABLE | 46 | i2c_status_t transport_trigger_callback(int8_t id) { |
| 130 | uint8_t current_wpm = get_current_wpm(); | 47 | // If there's no callback, indicate that we were successful |
| 131 | if (current_wpm != i2c_buffer->current_wpm) { | 48 | if (!split_transaction_table[id].slave_callback) { |
| 132 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)¤t_wpm, sizeof(current_wpm), TIMEOUT) >= 0) { | 49 | return I2C_STATUS_SUCCESS; |
| 133 | i2c_buffer->current_wpm = current_wpm; | ||
| 134 | } | ||
| 135 | } | 50 | } |
| 136 | # endif | ||
| 137 | 51 | ||
| 138 | # ifdef SPLIT_MODS_ENABLE | 52 | // Kick off the "callback executor", now that data has been written to the slave |
| 139 | uint8_t real_mods = get_mods(); | 53 | split_shmem->transaction_id = id; |
| 140 | if (real_mods != i2c_buffer->real_mods) { | 54 | split_transaction_desc_t *trans = &split_transaction_table[I2C_EXECUTE_CALLBACK]; |
| 141 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) { | 55 | return i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, SLAVE_I2C_TIMEOUT); |
| 142 | i2c_buffer->real_mods = real_mods; | 56 | } |
| 57 | |||
| 58 | bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) { | ||
| 59 | i2c_status_t status; | ||
| 60 | split_transaction_desc_t *trans = &split_transaction_table[id]; | ||
| 61 | if (initiator2target_length > 0) { | ||
| 62 | size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length; | ||
| 63 | memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len); | ||
| 64 | if ((status = i2c_writeReg(SLAVE_I2C_ADDRESS, trans->initiator2target_offset, split_trans_initiator2target_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { | ||
| 65 | return false; | ||
| 143 | } | 66 | } |
| 144 | } | 67 | } |
| 145 | 68 | ||
| 146 | uint8_t weak_mods = get_weak_mods(); | 69 | // If we need to execute a callback on the slave, do so |
| 147 | if (weak_mods != i2c_buffer->weak_mods) { | 70 | if ((status = transport_trigger_callback(id)) < 0) { |
| 148 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) { | 71 | return false; |
| 149 | i2c_buffer->weak_mods = weak_mods; | ||
| 150 | } | ||
| 151 | } | 72 | } |
| 152 | 73 | ||
| 153 | # ifndef NO_ACTION_ONESHOT | 74 | if (target2initiator_length > 0) { |
| 154 | uint8_t oneshot_mods = get_oneshot_mods(); | 75 | size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length; |
| 155 | if (oneshot_mods != i2c_buffer->oneshot_mods) { | 76 | if ((status = i2c_readReg(SLAVE_I2C_ADDRESS, trans->target2initiator_offset, split_trans_target2initiator_buffer(trans), len, SLAVE_I2C_TIMEOUT)) < 0) { |
| 156 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) { | 77 | return false; |
| 157 | i2c_buffer->oneshot_mods = oneshot_mods; | ||
| 158 | } | 78 | } |
| 79 | memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len); | ||
| 159 | } | 80 | } |
| 160 | # endif | ||
| 161 | # endif | ||
| 162 | 81 | ||
| 163 | # if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 164 | i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT); | ||
| 165 | bool suspend_state = led_matrix_get_suspend_state(); | ||
| 166 | i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT); | ||
| 167 | # endif | ||
| 168 | # if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 169 | i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT); | ||
| 170 | bool suspend_state = rgb_matrix_get_suspend_state(); | ||
| 171 | i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT); | ||
| 172 | # endif | ||
| 173 | |||
| 174 | # ifndef DISABLE_SYNC_TIMER | ||
| 175 | i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; | ||
| 176 | i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); | ||
| 177 | # endif | ||
| 178 | return true; | 82 | return true; |
| 179 | } | 83 | } |
| 180 | 84 | ||
| 181 | void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | 85 | #else // USE_I2C |
| 182 | # ifndef DISABLE_SYNC_TIMER | ||
| 183 | sync_timer_update(i2c_buffer->sync_timer); | ||
| 184 | # endif | ||
| 185 | // Copy matrix to I2C buffer | ||
| 186 | memcpy((void *)i2c_buffer->smatrix, (void *)slave_matrix, sizeof(i2c_buffer->smatrix)); | ||
| 187 | # ifdef SPLIT_TRANSPORT_MIRROR | ||
| 188 | memcpy((void *)master_matrix, (void *)i2c_buffer->mmatrix, sizeof(i2c_buffer->mmatrix)); | ||
| 189 | # endif | ||
| 190 | |||
| 191 | // Read Backlight Info | ||
| 192 | # ifdef BACKLIGHT_ENABLE | ||
| 193 | backlight_set(i2c_buffer->backlight_level); | ||
| 194 | # endif | ||
| 195 | |||
| 196 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 197 | // Update the RGB with the new data | ||
| 198 | if (i2c_buffer->rgblight_sync.status.change_flags != 0) { | ||
| 199 | rgblight_update_sync(&i2c_buffer->rgblight_sync, false); | ||
| 200 | i2c_buffer->rgblight_sync.status.change_flags = 0; | ||
| 201 | } | ||
| 202 | # endif | ||
| 203 | |||
| 204 | # ifdef ENCODER_ENABLE | ||
| 205 | encoder_state_raw(i2c_buffer->encoder_state); | ||
| 206 | # endif | ||
| 207 | |||
| 208 | # ifdef WPM_ENABLE | ||
| 209 | set_current_wpm(i2c_buffer->current_wpm); | ||
| 210 | # endif | ||
| 211 | |||
| 212 | # ifdef SPLIT_MODS_ENABLE | ||
| 213 | set_mods(i2c_buffer->real_mods); | ||
| 214 | set_weak_mods(i2c_buffer->weak_mods); | ||
| 215 | # ifndef NO_ACTION_ONESHOT | ||
| 216 | set_oneshot_mods(i2c_buffer->oneshot_mods); | ||
| 217 | # endif | ||
| 218 | # endif | ||
| 219 | |||
| 220 | # if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 221 | memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix)); | ||
| 222 | led_matrix_set_suspend_state(i2c_buffer->led_suspend_state); | ||
| 223 | # endif | ||
| 224 | # if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 225 | memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix)); | ||
| 226 | rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state); | ||
| 227 | # endif | ||
| 228 | } | ||
| 229 | |||
| 230 | void transport_master_init(void) { i2c_init(); } | ||
| 231 | |||
| 232 | void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } | ||
| 233 | |||
| 234 | #else // USE_SERIAL | ||
| 235 | 86 | ||
| 236 | # include "serial.h" | 87 | # include "serial.h" |
| 237 | 88 | ||
| 238 | typedef struct _Serial_s2m_buffer_t { | 89 | static split_shared_memory_t shared_memory; |
| 239 | // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack | 90 | split_shared_memory_t *const split_shmem = &shared_memory; |
| 240 | matrix_row_t smatrix[ROWS_PER_HAND]; | ||
| 241 | |||
| 242 | # ifdef ENCODER_ENABLE | ||
| 243 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; | ||
| 244 | # endif | ||
| 245 | |||
| 246 | } Serial_s2m_buffer_t; | ||
| 247 | |||
| 248 | typedef struct _Serial_m2s_buffer_t { | ||
| 249 | # ifdef SPLIT_MODS_ENABLE | ||
| 250 | uint8_t real_mods; | ||
| 251 | uint8_t weak_mods; | ||
| 252 | # ifndef NO_ACTION_ONESHOT | ||
| 253 | uint8_t oneshot_mods; | ||
| 254 | # endif | ||
| 255 | # endif | ||
| 256 | # ifndef DISABLE_SYNC_TIMER | ||
| 257 | uint32_t sync_timer; | ||
| 258 | # endif | ||
| 259 | # ifdef SPLIT_TRANSPORT_MIRROR | ||
| 260 | matrix_row_t mmatrix[ROWS_PER_HAND]; | ||
| 261 | # endif | ||
| 262 | # ifdef BACKLIGHT_ENABLE | ||
| 263 | uint8_t backlight_level; | ||
| 264 | # endif | ||
| 265 | # ifdef WPM_ENABLE | ||
| 266 | uint8_t current_wpm; | ||
| 267 | # endif | ||
| 268 | # if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 269 | led_eeconfig_t led_matrix; | ||
| 270 | bool led_suspend_state; | ||
| 271 | # endif | ||
| 272 | # if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 273 | rgb_config_t rgb_matrix; | ||
| 274 | bool rgb_suspend_state; | ||
| 275 | # endif | ||
| 276 | } Serial_m2s_buffer_t; | ||
| 277 | |||
| 278 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 279 | // When MCUs on both sides drive their respective RGB LED chains, | ||
| 280 | // it is necessary to synchronize, so it is necessary to communicate RGB | ||
| 281 | // information. In that case, define RGBLIGHT_SPLIT with info on the number | ||
| 282 | // of LEDs on each half. | ||
| 283 | // | ||
| 284 | // Otherwise, if the master side MCU drives both sides RGB LED chains, | ||
| 285 | // there is no need to communicate. | ||
| 286 | |||
| 287 | typedef struct _Serial_rgblight_t { | ||
| 288 | rgblight_syncinfo_t rgblight_sync; | ||
| 289 | } Serial_rgblight_t; | ||
| 290 | 91 | ||
| 291 | volatile Serial_rgblight_t serial_rgblight = {}; | 92 | void transport_master_init(void) { soft_serial_initiator_init(); } |
| 292 | uint8_t volatile status_rgblight = 0; | 93 | void transport_slave_init(void) { soft_serial_target_init(); } |
| 293 | # endif | ||
| 294 | |||
| 295 | volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; | ||
| 296 | volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; | ||
| 297 | uint8_t volatile status0 = 0; | ||
| 298 | |||
| 299 | enum serial_transaction_id { | ||
| 300 | GET_SLAVE_MATRIX = 0, | ||
| 301 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 302 | PUT_RGBLIGHT, | ||
| 303 | # endif | ||
| 304 | }; | ||
| 305 | |||
| 306 | SSTD_t transactions[] = { | ||
| 307 | [GET_SLAVE_MATRIX] = | ||
| 308 | { | ||
| 309 | (uint8_t *)&status0, | ||
| 310 | sizeof(serial_m2s_buffer), | ||
| 311 | (uint8_t *)&serial_m2s_buffer, | ||
| 312 | sizeof(serial_s2m_buffer), | ||
| 313 | (uint8_t *)&serial_s2m_buffer, | ||
| 314 | }, | ||
| 315 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 316 | [PUT_RGBLIGHT] = | ||
| 317 | { | ||
| 318 | (uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer | ||
| 319 | }, | ||
| 320 | # endif | ||
| 321 | }; | ||
| 322 | |||
| 323 | void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } | ||
| 324 | |||
| 325 | void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } | ||
| 326 | 94 | ||
| 327 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | 95 | bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length) { |
| 328 | 96 | split_transaction_desc_t *trans = &split_transaction_table[id]; | |
| 329 | // rgblight synchronization information communication. | 97 | if (initiator2target_length > 0) { |
| 330 | 98 | size_t len = trans->initiator2target_buffer_size < initiator2target_length ? trans->initiator2target_buffer_size : initiator2target_length; | |
| 331 | void transport_rgblight_master(void) { | 99 | memcpy(split_trans_initiator2target_buffer(trans), initiator2target_buf, len); |
| 332 | if (rgblight_get_change_flags()) { | ||
| 333 | rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync); | ||
| 334 | if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) { | ||
| 335 | rgblight_clear_change_flags(); | ||
| 336 | } | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | void transport_rgblight_slave(void) { | ||
| 341 | if (status_rgblight == TRANSACTION_ACCEPTED) { | ||
| 342 | rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false); | ||
| 343 | status_rgblight = TRANSACTION_END; | ||
| 344 | } | 100 | } |
| 345 | } | ||
| 346 | 101 | ||
| 347 | # else | 102 | if (soft_serial_transaction(id) != TRANSACTION_END) { |
| 348 | # define transport_rgblight_master() | ||
| 349 | # define transport_rgblight_slave() | ||
| 350 | # endif | ||
| 351 | |||
| 352 | bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
| 353 | # ifndef SERIAL_USE_MULTI_TRANSACTION | ||
| 354 | if (soft_serial_transaction() != TRANSACTION_END) { | ||
| 355 | return false; | ||
| 356 | } | ||
| 357 | # else | ||
| 358 | transport_rgblight_master(); | ||
| 359 | if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) { | ||
| 360 | return false; | 103 | return false; |
| 361 | } | 104 | } |
| 362 | # endif | ||
| 363 | 105 | ||
| 364 | // TODO: if MATRIX_COLS > 8 change to unpack() | 106 | if (target2initiator_length > 0) { |
| 365 | for (int i = 0; i < ROWS_PER_HAND; ++i) { | 107 | size_t len = trans->target2initiator_buffer_size < target2initiator_length ? trans->target2initiator_buffer_size : target2initiator_length; |
| 366 | slave_matrix[i] = serial_s2m_buffer.smatrix[i]; | 108 | memcpy(target2initiator_buf, split_trans_target2initiator_buffer(trans), len); |
| 367 | # ifdef SPLIT_TRANSPORT_MIRROR | ||
| 368 | serial_m2s_buffer.mmatrix[i] = master_matrix[i]; | ||
| 369 | # endif | ||
| 370 | } | 109 | } |
| 371 | 110 | ||
| 372 | # ifdef BACKLIGHT_ENABLE | ||
| 373 | // Write backlight level for slave to read | ||
| 374 | serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0; | ||
| 375 | # endif | ||
| 376 | |||
| 377 | # ifdef ENCODER_ENABLE | ||
| 378 | encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state); | ||
| 379 | # endif | ||
| 380 | |||
| 381 | # ifdef WPM_ENABLE | ||
| 382 | // Write wpm to slave | ||
| 383 | serial_m2s_buffer.current_wpm = get_current_wpm(); | ||
| 384 | # endif | ||
| 385 | |||
| 386 | # ifdef SPLIT_MODS_ENABLE | ||
| 387 | serial_m2s_buffer.real_mods = get_mods(); | ||
| 388 | serial_m2s_buffer.weak_mods = get_weak_mods(); | ||
| 389 | # ifndef NO_ACTION_ONESHOT | ||
| 390 | serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); | ||
| 391 | # endif | ||
| 392 | # endif | ||
| 393 | |||
| 394 | # if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 395 | serial_m2s_buffer.led_matrix = led_matrix_eeconfig; | ||
| 396 | serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state(); | ||
| 397 | # endif | ||
| 398 | # if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 399 | serial_m2s_buffer.rgb_matrix = rgb_matrix_config; | ||
| 400 | serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state(); | ||
| 401 | # endif | ||
| 402 | |||
| 403 | # ifndef DISABLE_SYNC_TIMER | ||
| 404 | serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; | ||
| 405 | # endif | ||
| 406 | return true; | 111 | return true; |
| 407 | } | 112 | } |
| 408 | 113 | ||
| 409 | void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | 114 | #endif // USE_I2C |
| 410 | transport_rgblight_slave(); | ||
| 411 | # ifndef DISABLE_SYNC_TIMER | ||
| 412 | sync_timer_update(serial_m2s_buffer.sync_timer); | ||
| 413 | # endif | ||
| 414 | |||
| 415 | // TODO: if MATRIX_COLS > 8 change to pack() | ||
| 416 | for (int i = 0; i < ROWS_PER_HAND; ++i) { | ||
| 417 | serial_s2m_buffer.smatrix[i] = slave_matrix[i]; | ||
| 418 | # ifdef SPLIT_TRANSPORT_MIRROR | ||
| 419 | master_matrix[i] = serial_m2s_buffer.mmatrix[i]; | ||
| 420 | # endif | ||
| 421 | } | ||
| 422 | # ifdef BACKLIGHT_ENABLE | ||
| 423 | backlight_set(serial_m2s_buffer.backlight_level); | ||
| 424 | # endif | ||
| 425 | |||
| 426 | # ifdef ENCODER_ENABLE | ||
| 427 | encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state); | ||
| 428 | # endif | ||
| 429 | 115 | ||
| 430 | # ifdef WPM_ENABLE | 116 | bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { return transactions_master(master_matrix, slave_matrix); } |
| 431 | set_current_wpm(serial_m2s_buffer.current_wpm); | ||
| 432 | # endif | ||
| 433 | |||
| 434 | # ifdef SPLIT_MODS_ENABLE | ||
| 435 | set_mods(serial_m2s_buffer.real_mods); | ||
| 436 | set_weak_mods(serial_m2s_buffer.weak_mods); | ||
| 437 | # ifndef NO_ACTION_ONESHOT | ||
| 438 | set_oneshot_mods(serial_m2s_buffer.oneshot_mods); | ||
| 439 | # endif | ||
| 440 | # endif | ||
| 441 | |||
| 442 | # if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 443 | led_matrix_eeconfig = serial_m2s_buffer.led_matrix; | ||
| 444 | led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state); | ||
| 445 | # endif | ||
| 446 | # if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 447 | rgb_matrix_config = serial_m2s_buffer.rgb_matrix; | ||
| 448 | rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state); | ||
| 449 | # endif | ||
| 450 | } | ||
| 451 | 117 | ||
| 452 | #endif | 118 | 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 a9f66301b..2e07f6b25 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h | |||
| @@ -1,10 +1,175 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 1 | #pragma once | 17 | #pragma once |
| 2 | 18 | ||
| 19 | #include "stdint.h" | ||
| 20 | #include "stdbool.h" | ||
| 21 | |||
| 22 | #include "progmem.h" | ||
| 23 | #include "action_layer.h" | ||
| 3 | #include "matrix.h" | 24 | #include "matrix.h" |
| 4 | 25 | ||
| 26 | #ifndef RPC_M2S_BUFFER_SIZE | ||
| 27 | # define RPC_M2S_BUFFER_SIZE 32 | ||
| 28 | #endif // RPC_M2S_BUFFER_SIZE | ||
| 29 | |||
| 30 | #ifndef RPC_S2M_BUFFER_SIZE | ||
| 31 | # define RPC_S2M_BUFFER_SIZE 32 | ||
| 32 | #endif // RPC_S2M_BUFFER_SIZE | ||
| 33 | |||
| 5 | void transport_master_init(void); | 34 | void transport_master_init(void); |
| 6 | void transport_slave_init(void); | 35 | void transport_slave_init(void); |
| 7 | 36 | ||
| 8 | // returns false if valid data not received from slave | 37 | // returns false if valid data not received from slave |
| 9 | bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); | 38 | bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); |
| 10 | void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); | 39 | void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); |
| 40 | |||
| 41 | bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length); | ||
| 42 | |||
| 43 | #ifdef ENCODER_ENABLE | ||
| 44 | # include "encoder.h" | ||
| 45 | # define NUMBER_OF_ENCODERS (sizeof((pin_t[])ENCODERS_PAD_A) / sizeof(pin_t)) | ||
| 46 | #endif // ENCODER_ENABLE | ||
| 47 | |||
| 48 | #ifdef BACKLIGHT_ENABLE | ||
| 49 | # include "backlight.h" | ||
| 50 | #endif // BACKLIGHT_ENABLE | ||
| 51 | |||
| 52 | #ifdef RGBLIGHT_ENABLE | ||
| 53 | # include "rgblight.h" | ||
| 54 | #endif // RGBLIGHT_ENABLE | ||
| 55 | |||
| 56 | typedef struct _split_slave_matrix_sync_t { | ||
| 57 | uint8_t checksum; | ||
| 58 | matrix_row_t matrix[(MATRIX_ROWS) / 2]; | ||
| 59 | } split_slave_matrix_sync_t; | ||
| 60 | |||
| 61 | #ifdef SPLIT_TRANSPORT_MIRROR | ||
| 62 | typedef struct _split_master_matrix_sync_t { | ||
| 63 | matrix_row_t matrix[(MATRIX_ROWS) / 2]; | ||
| 64 | } split_master_matrix_sync_t; | ||
| 65 | #endif // SPLIT_TRANSPORT_MIRROR | ||
| 66 | |||
| 67 | #ifdef ENCODER_ENABLE | ||
| 68 | typedef struct _split_slave_encoder_sync_t { | ||
| 69 | uint8_t checksum; | ||
| 70 | uint8_t state[NUMBER_OF_ENCODERS]; | ||
| 71 | } split_slave_encoder_sync_t; | ||
| 72 | #endif // ENCODER_ENABLE | ||
| 73 | |||
| 74 | #if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 75 | typedef struct _split_layers_sync_t { | ||
| 76 | layer_state_t layer_state; | ||
| 77 | layer_state_t default_layer_state; | ||
| 78 | } split_layers_sync_t; | ||
| 79 | #endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 80 | |||
| 81 | #if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 82 | # include "led_matrix.h" | ||
| 83 | |||
| 84 | typedef struct _led_matrix_sync_t { | ||
| 85 | led_eeconfig_t led_matrix; | ||
| 86 | bool led_suspend_state; | ||
| 87 | } led_matrix_sync_t; | ||
| 88 | #endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 89 | |||
| 90 | #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 91 | # include "rgb_matrix.h" | ||
| 92 | |||
| 93 | typedef struct _rgb_matrix_sync_t { | ||
| 94 | rgb_config_t rgb_matrix; | ||
| 95 | bool rgb_suspend_state; | ||
| 96 | } rgb_matrix_sync_t; | ||
| 97 | #endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 98 | |||
| 99 | #ifdef SPLIT_MODS_ENABLE | ||
| 100 | typedef struct _split_mods_sync_t { | ||
| 101 | uint8_t real_mods; | ||
| 102 | uint8_t weak_mods; | ||
| 103 | # ifndef NO_ACTION_ONESHOT | ||
| 104 | uint8_t oneshot_mods; | ||
| 105 | # endif // NO_ACTION_ONESHOT | ||
| 106 | } split_mods_sync_t; | ||
| 107 | #endif // SPLIT_MODS_ENABLE | ||
| 108 | |||
| 109 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 110 | typedef struct _rpc_sync_info_t { | ||
| 111 | int8_t transaction_id; | ||
| 112 | uint8_t m2s_length; | ||
| 113 | uint8_t s2m_length; | ||
| 114 | } rpc_sync_info_t; | ||
| 115 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 116 | |||
| 117 | typedef struct _split_shared_memory_t { | ||
| 118 | #ifdef USE_I2C | ||
| 119 | int8_t transaction_id; | ||
| 120 | #endif // USE_I2C | ||
| 121 | |||
| 122 | split_slave_matrix_sync_t smatrix; | ||
| 123 | |||
| 124 | #ifdef SPLIT_TRANSPORT_MIRROR | ||
| 125 | split_master_matrix_sync_t mmatrix; | ||
| 126 | #endif // SPLIT_TRANSPORT_MIRROR | ||
| 127 | |||
| 128 | #ifdef ENCODER_ENABLE | ||
| 129 | split_slave_encoder_sync_t encoders; | ||
| 130 | #endif // ENCODER_ENABLE | ||
| 131 | |||
| 132 | #ifndef DISABLE_SYNC_TIMER | ||
| 133 | uint32_t sync_timer; | ||
| 134 | #endif // DISABLE_SYNC_TIMER | ||
| 135 | |||
| 136 | #if !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 137 | split_layers_sync_t layers; | ||
| 138 | #endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE) | ||
| 139 | |||
| 140 | #ifdef SPLIT_LED_STATE_ENABLE | ||
| 141 | uint8_t led_state; | ||
| 142 | #endif // SPLIT_LED_STATE_ENABLE | ||
| 143 | |||
| 144 | #ifdef SPLIT_MODS_ENABLE | ||
| 145 | split_mods_sync_t mods; | ||
| 146 | #endif // SPLIT_MODS_ENABLE | ||
| 147 | |||
| 148 | #ifdef BACKLIGHT_ENABLE | ||
| 149 | uint8_t backlight_level; | ||
| 150 | #endif // BACKLIGHT_ENABLE | ||
| 151 | |||
| 152 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 153 | rgblight_syncinfo_t rgblight_sync; | ||
| 154 | #endif // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 155 | |||
| 156 | #if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 157 | led_matrix_sync_t led_matrix_sync; | ||
| 158 | #endif // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) | ||
| 159 | |||
| 160 | #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 161 | rgb_matrix_sync_t rgb_matrix_sync; | ||
| 162 | #endif // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) | ||
| 163 | |||
| 164 | #if defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 165 | uint8_t current_wpm; | ||
| 166 | #endif // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
| 167 | |||
| 168 | #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 169 | rpc_sync_info_t rpc_info; | ||
| 170 | uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE]; | ||
| 171 | uint8_t rpc_s2m_buffer[RPC_S2M_BUFFER_SIZE]; | ||
| 172 | #endif // defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) | ||
| 173 | } split_shared_memory_t; | ||
| 174 | |||
| 175 | extern split_shared_memory_t *const split_shmem; \ No newline at end of file | ||
