summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/action.c325
-rw-r--r--quantum/action.h2
-rw-r--r--quantum/action_tapping.c150
-rw-r--r--quantum/action_tapping.h4
-rw-r--r--quantum/action_util.c3
-rw-r--r--quantum/api.c182
-rw-r--r--quantum/api.h55
-rw-r--r--quantum/api/api_sysex.c72
-rw-r--r--quantum/audio/audio.h13
-rw-r--r--quantum/audio/driver_avr_pwm.h17
-rw-r--r--quantum/audio/driver_avr_pwm_hardware.c332
-rw-r--r--quantum/audio/driver_chibios_dac.h126
-rw-r--r--quantum/audio/driver_chibios_dac_additive.c335
-rw-r--r--quantum/audio/driver_chibios_dac_basic.c245
-rw-r--r--quantum/audio/driver_chibios_pwm.h40
-rw-r--r--quantum/audio/driver_chibios_pwm_hardware.c144
-rw-r--r--quantum/audio/driver_chibios_pwm_software.c164
-rw-r--r--quantum/audio/song_list.h8
-rw-r--r--quantum/backlight/backlight_avr.c88
-rw-r--r--quantum/backlight/backlight_chibios.c10
-rw-r--r--quantum/config_common.h3
-rw-r--r--quantum/debounce/asym_eager_defer_pk.c22
-rw-r--r--quantum/debounce/sym_defer_g.c2
-rw-r--r--quantum/debounce/sym_defer_pk.c6
-rw-r--r--quantum/debounce/sym_eager_pk.c8
-rw-r--r--quantum/debounce/sym_eager_pr.c8
-rw-r--r--quantum/debounce/tests/asym_eager_defer_pk_tests.cpp66
-rw-r--r--quantum/debounce/tests/debounce_test_common.cpp72
-rw-r--r--quantum/debounce/tests/debounce_test_common.h24
-rw-r--r--quantum/debounce/tests/rules.mk2
-rw-r--r--quantum/debounce/tests/sym_defer_g_tests.cpp45
-rw-r--r--quantum/debounce/tests/sym_defer_pk_tests.cpp45
-rw-r--r--quantum/debounce/tests/sym_eager_pk_tests.cpp48
-rw-r--r--quantum/debounce/tests/sym_eager_pr_tests.cpp57
-rw-r--r--quantum/deferred_exec.c152
-rw-r--r--quantum/deferred_exec.h38
-rw-r--r--quantum/dynamic_keymap.c6
-rw-r--r--quantum/eeconfig.c11
-rw-r--r--quantum/eeconfig.h26
-rw-r--r--quantum/encoder/tests/encoder_tests.cpp144
-rw-r--r--quantum/encoder/tests/encoder_tests_split.cpp143
-rw-r--r--quantum/encoder/tests/mock.c (renamed from quantum/api/api_sysex.h)21
-rw-r--r--quantum/encoder/tests/mock.h (renamed from quantum/visualizer/default_animations.h)29
-rw-r--r--quantum/encoder/tests/mock_split.c (renamed from quantum/visualizer/visualizer_keyframes.c)25
-rw-r--r--quantum/encoder/tests/mock_split.h48
-rw-r--r--quantum/encoder/tests/rules.mk13
-rw-r--r--quantum/encoder/tests/testlist.mk3
-rw-r--r--quantum/haptic.c51
-rw-r--r--quantum/haptic.h27
-rw-r--r--quantum/keyboard.c70
-rw-r--r--quantum/keycode.h272
-rw-r--r--quantum/keycode_config.c66
-rw-r--r--quantum/keycode_legacy.h53
-rw-r--r--quantum/keymap_common.c4
-rw-r--r--quantum/keymap_extras/keymap_korean.h4
-rw-r--r--quantum/keymap_extras/keymap_steno.h3
-rw-r--r--quantum/keymap_extras/keymap_turkish_f.h2
-rw-r--r--quantum/led_matrix/animations/alpha_mods_anim.h4
-rw-r--r--quantum/led_matrix/animations/band_anim.h2
-rw-r--r--quantum/led_matrix/animations/band_pinwheel_anim.h2
-rw-r--r--quantum/led_matrix/animations/band_spiral_anim.h2
-rw-r--r--quantum/led_matrix/animations/breathing_anim.h4
-rw-r--r--quantum/led_matrix/animations/cycle_left_right_anim.h2
-rw-r--r--quantum/led_matrix/animations/cycle_out_in_anim.h2
-rw-r--r--quantum/led_matrix/animations/cycle_up_down_anim.h2
-rw-r--r--quantum/led_matrix/animations/dual_beacon_anim.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_dx_dy.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_i.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_reactive.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h2
-rw-r--r--quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h2
-rw-r--r--quantum/led_matrix/animations/solid_anim.h2
-rw-r--r--quantum/led_matrix/animations/solid_reactive_cross.h4
-rw-r--r--quantum/led_matrix/animations/solid_reactive_nexus.h2
-rw-r--r--quantum/led_matrix/animations/solid_reactive_simple_anim.h2
-rw-r--r--quantum/led_matrix/animations/solid_reactive_wide.h4
-rw-r--r--quantum/led_matrix/animations/solid_splash_anim.h4
-rw-r--r--quantum/led_matrix/animations/wave_left_right_anim.h2
-rw-r--r--quantum/led_matrix/animations/wave_up_down_anim.h2
-rw-r--r--quantum/led_matrix/led_matrix.c50
-rw-r--r--quantum/led_matrix/led_matrix.h46
-rw-r--r--quantum/led_matrix/led_matrix_drivers.c133
-rw-r--r--quantum/led_matrix/led_matrix_legacy_enables.h82
-rw-r--r--quantum/main.c36
-rw-r--r--quantum/matrix.c51
-rw-r--r--quantum/mcu_selection.mk601
-rw-r--r--quantum/pointing_device.c124
-rw-r--r--quantum/pointing_device.h59
-rw-r--r--quantum/pointing_device_drivers.c262
-rw-r--r--quantum/process_keycode/process_auto_shift.c427
-rw-r--r--quantum/process_keycode/process_auto_shift.h22
-rw-r--r--quantum/process_keycode/process_combo.c184
-rw-r--r--quantum/process_keycode/process_combo.h4
-rw-r--r--quantum/process_keycode/process_dynamic_tapping_term.c50
-rw-r--r--quantum/process_keycode/process_dynamic_tapping_term.h (renamed from quantum/visualizer/resources/resources.h)11
-rw-r--r--quantum/process_keycode/process_haptic.c30
-rw-r--r--quantum/process_keycode/process_music.c6
-rw-r--r--quantum/process_keycode/process_printer.c32
-rw-r--r--quantum/process_keycode/process_printer_bb.c32
-rw-r--r--quantum/process_keycode/process_programmable_button.c31
-rw-r--r--quantum/process_keycode/process_programmable_button.h23
-rw-r--r--quantum/process_keycode/process_space_cadet.c24
-rw-r--r--quantum/process_keycode/process_steno.c9
-rw-r--r--quantum/process_keycode/process_terminal.c10
-rw-r--r--quantum/process_keycode/process_ucis.c18
-rw-r--r--quantum/process_keycode/process_unicode_common.c54
-rw-r--r--quantum/process_keycode/process_unicode_common.h4
-rw-r--r--quantum/programmable_button.c37
-rw-r--r--quantum/programmable_button.h30
-rw-r--r--quantum/quantum.c205
-rw-r--r--quantum/quantum.h22
-rw-r--r--quantum/quantum_keycodes.h203
-rw-r--r--quantum/raw_hid.h5
-rw-r--r--quantum/rgb_matrix/animations/alpha_mods_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/breathing_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_sat_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_spiral_val_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/colorband_val_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_all_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_left_right_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_out_in_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_pinwheel_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_spiral_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/cycle_up_down_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/digital_rain_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/dual_beacon_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/gradient_left_right_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/gradient_up_down_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/hue_breathing_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/jellybean_raindrops_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/pixel_fractal_anim.h74
-rw-r--r--quantum/rgb_matrix/animations/pixel_rain_anim.h48
-rw-r--r--quantum/rgb_matrix/animations/rainbow_beacon_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/raindrops_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/rgb_matrix_effects.inc2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_i.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_reactive.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h2
-rw-r--r--quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h2
-rw-r--r--quantum/rgb_matrix/animations/solid_color_anim.h2
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_cross.h12
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_nexus.h12
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_simple_anim.h4
-rw-r--r--quantum/rgb_matrix/animations/solid_reactive_wide.h12
-rw-r--r--quantum/rgb_matrix/animations/solid_splash_anim.h12
-rw-r--r--quantum/rgb_matrix/animations/splash_anim.h12
-rw-r--r--quantum/rgb_matrix/animations/typing_heatmap_anim.h2
-rw-r--r--quantum/rgb_matrix/rgb_matrix.c41
-rw-r--r--quantum/rgb_matrix/rgb_matrix.h48
-rw-r--r--quantum/rgb_matrix/rgb_matrix_drivers.c184
-rw-r--r--quantum/rgb_matrix/rgb_matrix_legacy_enables.h153
-rw-r--r--quantum/sequencer/tests/rules.mk4
-rw-r--r--quantum/serial_link/LICENSE19
-rw-r--r--quantum/serial_link/README.md1
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.c135
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.h34
-rw-r--r--quantum/serial_link/protocol/frame_router.c64
-rw-r--r--quantum/serial_link/protocol/frame_router.h35
-rw-r--r--quantum/serial_link/protocol/frame_validator.c57
-rw-r--r--quantum/serial_link/protocol/frame_validator.h31
-rw-r--r--quantum/serial_link/protocol/physical.h27
-rw-r--r--quantum/serial_link/protocol/transport.c121
-rw-r--r--quantum/serial_link/protocol/transport.h139
-rw-r--r--quantum/serial_link/protocol/triple_buffered_object.c77
-rw-r--r--quantum/serial_link/protocol/triple_buffered_object.h44
-rw-r--r--quantum/serial_link/system/serial_link.c250
-rw-r--r--quantum/serial_link/system/serial_link.h54
-rw-r--r--quantum/serial_link/tests/Makefile61
-rw-r--r--quantum/serial_link/tests/byte_stuffer_tests.cpp450
-rw-r--r--quantum/serial_link/tests/frame_router_tests.cpp204
-rw-r--r--quantum/serial_link/tests/frame_validator_tests.cpp100
-rw-r--r--quantum/serial_link/tests/rules.mk22
-rw-r--r--quantum/serial_link/tests/testlist.mk6
-rw-r--r--quantum/serial_link/tests/transport_tests.cpp184
-rw-r--r--quantum/serial_link/tests/triple_buffered_object_tests.cpp80
-rw-r--r--quantum/split_common/transactions.c48
-rw-r--r--quantum/sync_timer.c58
-rw-r--r--quantum/sync_timer.h54
-rw-r--r--quantum/via.c2
-rw-r--r--quantum/via_ensure_keycode.h670
-rw-r--r--quantum/virtser.h9
-rw-r--r--quantum/visualizer/LICENSE.md29
-rw-r--r--quantum/visualizer/common_gfxconf.h354
-rw-r--r--quantum/visualizer/default_animations.c177
-rw-r--r--quantum/visualizer/lcd_backlight.c87
-rw-r--r--quantum/visualizer/lcd_backlight.h43
-rw-r--r--quantum/visualizer/lcd_backlight_keyframes.c69
-rw-r--r--quantum/visualizer/lcd_backlight_keyframes.h27
-rw-r--r--quantum/visualizer/lcd_keyframes.c184
-rw-r--r--quantum/visualizer/lcd_keyframes.h35
-rw-r--r--quantum/visualizer/led_backlight_keyframes.c143
-rw-r--r--quantum/visualizer/led_backlight_keyframes.h40
-rw-r--r--quantum/visualizer/readme.md18
-rw-r--r--quantum/visualizer/resources/lcd_logo.c45
-rw-r--r--quantum/visualizer/resources/lcd_logo.pngbin271 -> 0 bytes
-rw-r--r--quantum/visualizer/visualizer.c483
-rw-r--r--quantum/visualizer/visualizer.h154
-rw-r--r--quantum/visualizer/visualizer.mk123
-rw-r--r--quantum/visualizer/visualizer_keyframes.h23
-rw-r--r--quantum/wpm.c100
-rw-r--r--quantum/wpm.h7
211 files changed, 4243 insertions, 8543 deletions
diff --git a/quantum/action.c b/quantum/action.c
index 0946b0ca1a..a6568f8b38 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keycode.h"
#include "keyboard.h"
#include "mousekey.h"
+#include "programmable_button.h"
#include "command.h"
#include "led.h"
#include "action_layer.h"
@@ -26,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_util.h"
#include "action.h"
#include "wait.h"
+#include "keycode_config.h"
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
@@ -43,10 +45,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
int tp_buttons;
-#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY)
+#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
int retro_tapping_counter = 0;
#endif
+#if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+# include "process_auto_shift.h"
+#endif
+
#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; }
#endif
@@ -67,7 +73,7 @@ void action_exec(keyevent_t event) {
dprint("EVENT: ");
debug_event(event);
dprintln();
-#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY)
+#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
retro_tapping_counter++;
#endif
}
@@ -86,22 +92,29 @@ void action_exec(keyevent_t event) {
keyrecord_t record = {.event = event};
#ifndef NO_ACTION_ONESHOT
+ if (!keymap_config.oneshot_disable) {
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
- if (has_oneshot_layer_timed_out()) {
- clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
- }
- if (has_oneshot_mods_timed_out()) {
- clear_oneshot_mods();
- }
+ if (has_oneshot_layer_timed_out()) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
+ if (has_oneshot_mods_timed_out()) {
+ clear_oneshot_mods();
+ }
# ifdef SWAP_HANDS_ENABLE
- if (has_oneshot_swaphands_timed_out()) {
- clear_oneshot_swaphands();
- }
+ if (has_oneshot_swaphands_timed_out()) {
+ clear_oneshot_swaphands();
+ }
# endif
# endif
+ }
#endif
#ifndef NO_ACTION_TAPPING
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ if (event.pressed) {
+ retroshift_poll_time(&event);
+ }
+# endif
if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) {
action_tapping_process(record);
}
@@ -194,7 +207,7 @@ void process_record(keyrecord_t *record) {
if (!process_record_quantum(record)) {
#ifndef NO_ACTION_ONESHOT
- if (is_oneshot_layer_active() && record->event.pressed) {
+ if (is_oneshot_layer_active() && record->event.pressed && !keymap_config.oneshot_disable) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
#endif
@@ -259,7 +272,7 @@ void process_action(keyrecord_t *record, action_t action) {
# ifdef SWAP_HANDS_ENABLE
&& !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)
# endif
- ) {
+ && !keymap_config.oneshot_disable) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
do_release_oneshot = !is_oneshot_layer_active();
}
@@ -273,8 +286,8 @@ void process_action(keyrecord_t *record, action_t action) {
if (event.pressed) {
if (mods) {
if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
- // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
- // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT).
+ // e.g. LSFT(KC_LEFT_GUI): we don't want the LSFT to be weak as it would make it useless.
+ // This also makes LSFT(KC_LEFT_GUI) behave exactly the same as LGUI(KC_LEFT_SHIFT).
// Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
add_mods(mods);
} else {
@@ -303,41 +316,68 @@ void process_action(keyrecord_t *record, action_t action) {
# ifndef NO_ACTION_ONESHOT
case MODS_ONESHOT:
// Oneshot modifier
- if (event.pressed) {
- if (tap_count == 0) {
- dprint("MODS_TAP: Oneshot: 0\n");
- register_mods(mods | get_oneshot_mods());
- } else if (tap_count == 1) {
- dprint("MODS_TAP: Oneshot: start\n");
- set_oneshot_mods(mods | get_oneshot_mods());
-# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
- } else if (tap_count == ONESHOT_TAP_TOGGLE) {
- dprint("MODS_TAP: Toggling oneshot");
- clear_oneshot_mods();
- set_oneshot_locked_mods(mods);
- register_mods(mods);
-# endif
+ if (keymap_config.oneshot_disable) {
+ if (event.pressed) {
+ if (mods) {
+ if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
+ // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
+ // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT).
+ // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
+ add_mods(mods);
+ } else {
+ add_weak_mods(mods);
+ }
+ send_keyboard_report();
+ }
+ register_code(action.key.code);
} else {
- register_mods(mods | get_oneshot_mods());
+ unregister_code(action.key.code);
+ if (mods) {
+ if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
+ del_mods(mods);
+ } else {
+ del_weak_mods(mods);
+ }
+ send_keyboard_report();
+ }
}
} else {
- if (tap_count == 0) {
- clear_oneshot_mods();
- unregister_mods(mods);
- } else if (tap_count == 1) {
- // Retain Oneshot mods
+ if (event.pressed) {
+ if (tap_count == 0) {
+ dprint("MODS_TAP: Oneshot: 0\n");
+ register_mods(mods | get_oneshot_mods());
+ } else if (tap_count == 1) {
+ dprint("MODS_TAP: Oneshot: start\n");
+ set_oneshot_mods(mods | get_oneshot_mods());
# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
- if (mods & get_mods()) {
- clear_oneshot_locked_mods();
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ dprint("MODS_TAP: Toggling oneshot");
clear_oneshot_mods();
- unregister_mods(mods);
- }
- } else if (tap_count == ONESHOT_TAP_TOGGLE) {
- // Toggle Oneshot Layer
+ set_oneshot_locked_mods(mods);
+ register_mods(mods);
# endif
+ } else {
+ register_mods(mods | get_oneshot_mods());
+ }
} else {
- clear_oneshot_mods();
- unregister_mods(mods);
+ if (tap_count == 0) {
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ } else if (tap_count == 1) {
+ // Retain Oneshot mods
+# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ if (mods & get_mods()) {
+ clear_oneshot_locked_mods();
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ }
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ // Toggle Oneshot Layer
+# endif
+ } else {
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ }
}
}
break;
@@ -379,7 +419,7 @@ void process_action(keyrecord_t *record, action_t action) {
} else {
if (tap_count > 0) {
dprint("MODS_TAP: Tap: unregister_code\n");
- if (action.layer_tap.code == KC_CAPS) {
+ if (action.layer_tap.code == KC_CAPS_LOCK) {
wait_ms(TAP_HOLD_CAPS_DELAY);
} else {
wait_ms(TAP_CODE_DELAY);
@@ -522,39 +562,47 @@ void process_action(keyrecord_t *record, action_t action) {
# ifndef NO_ACTION_ONESHOT
case OP_ONESHOT:
// Oneshot modifier
-# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
- do_release_oneshot = false;
- if (event.pressed) {
- del_mods(get_oneshot_locked_mods());
- if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
- reset_oneshot_layer();
- layer_off(action.layer_tap.val);
- break;
- } else if (tap_count < ONESHOT_TAP_TOGGLE) {
+ if (keymap_config.oneshot_disable) {
+ if (event.pressed) {
layer_on(action.layer_tap.val);
- set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ } else {
+ layer_off(action.layer_tap.val);
}
} else {
- add_mods(get_oneshot_locked_mods());
- if (tap_count >= ONESHOT_TAP_TOGGLE) {
- reset_oneshot_layer();
- clear_oneshot_locked_mods();
- set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
+# if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ do_release_oneshot = false;
+ if (event.pressed) {
+ del_mods(get_oneshot_locked_mods());
+ if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
+ reset_oneshot_layer();
+ layer_off(action.layer_tap.val);
+ break;
+ } else if (tap_count < ONESHOT_TAP_TOGGLE) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ }
} else {
- clear_oneshot_layer_state(ONESHOT_PRESSED);
+ add_mods(get_oneshot_locked_mods());
+ if (tap_count >= ONESHOT_TAP_TOGGLE) {
+ reset_oneshot_layer();
+ clear_oneshot_locked_mods();
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ }
}
- }
# else
- if (event.pressed) {
- layer_on(action.layer_tap.val);
- set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
- } else {
- clear_oneshot_layer_state(ONESHOT_PRESSED);
- if (tap_count > 1) {
- clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ if (event.pressed) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ if (tap_count > 1) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
}
- }
# endif
+ }
break;
# endif
default:
@@ -570,7 +618,7 @@ void process_action(keyrecord_t *record, action_t action) {
} else {
if (tap_count > 0) {
dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
- if (action.layer_tap.code == KC_CAPS) {
+ if (action.layer_tap.code == KC_CAPS_LOCK) {
wait_ms(TAP_HOLD_CAPS_DELAY);
} else {
wait_ms(TAP_CODE_DELAY);
@@ -691,7 +739,7 @@ void process_action(keyrecord_t *record, action_t action) {
#endif
#ifndef NO_ACTION_TAPPING
-# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY)
+# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
if (!is_tap_action(action)) {
retro_tapping_counter = 0;
} else {
@@ -708,7 +756,11 @@ void process_action(keyrecord_t *record, action_t action) {
get_retro_tapping(get_event_keycode(record->event, false), record) &&
# endif
retro_tapping_counter == 2) {
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ process_auto_shift(action.layer_tap.code, record);
+# else
tap_code(action.layer_tap.code);
+# endif
}
retro_tapping_counter = 0;
}
@@ -747,44 +799,45 @@ void register_code(uint8_t code) {
return;
}
#ifdef LOCKING_SUPPORT_ENABLE
- else if (KC_LOCKING_CAPS == code) {
+ else if (KC_LOCKING_CAPS_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
// Resync: ignore if caps lock already is on
if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) return;
# endif
- add_key(KC_CAPSLOCK);
+ add_key(KC_CAPS_LOCK);
send_keyboard_report();
wait_ms(100);
- del_key(KC_CAPSLOCK);
+ del_key(KC_CAPS_LOCK);
send_keyboard_report();
}
- else if (KC_LOCKING_NUM == code) {
+ else if (KC_LOCKING_NUM_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
if (host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)) return;
# endif
- add_key(KC_NUMLOCK);
+ add_key(KC_NUM_LOCK);
send_keyboard_report();
wait_ms(100);
- del_key(KC_NUMLOCK);
+ del_key(KC_NUM_LOCK);
send_keyboard_report();
}
- else if (KC_LOCKING_SCROLL == code) {
+ else if (KC_LOCKING_SCROLL_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
if (host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK)) return;
# endif
- add_key(KC_SCROLLLOCK);
+ add_key(KC_SCROLL_LOCK);
send_keyboard_report();
wait_ms(100);
- del_key(KC_SCROLLLOCK);
+ del_key(KC_SCROLL_LOCK);
send_keyboard_report();
}
#endif
- else if IS_KEY (code) {
- // TODO: should push command_proc out of this block?
- if (command_proc(code)) return;
+ else if
+ IS_KEY(code) {
+ // TODO: should push command_proc out of this block?
+ if (command_proc(code)) return;
#ifndef NO_ACTION_ONESHOT
/* TODO: remove
@@ -801,33 +854,35 @@ void register_code(uint8_t code) {
} else
*/
#endif
- {
- // Force a new key press if the key is already pressed
- // without this, keys with the same keycode, but different
- // modifiers will be reported incorrectly, see issue #1708
- if (is_key_pressed(keyboard_report, code)) {
- del_key(code);
+ {
+ // Force a new key press if the key is already pressed
+ // without this, keys with the same keycode, but different
+ // modifiers will be reported incorrectly, see issue #1708
+ if (is_key_pressed(keyboard_report, code)) {
+ del_key(code);
+ send_keyboard_report();
+ }
+ add_key(code);
send_keyboard_report();
}
- add_key(code);
+ }
+ else if
+ IS_MOD(code) {
+ add_mods(MOD_BIT(code));
send_keyboard_report();
}
- } else if IS_MOD (code) {
- add_mods(MOD_BIT(code));
- send_keyboard_report();
- }
#ifdef EXTRAKEY_ENABLE
- else if IS_SYSTEM (code) {
- host_system_send(KEYCODE2SYSTEM(code));
- } else if IS_CONSUMER (code) {
- host_consumer_send(KEYCODE2CONSUMER(code));
- }
+ else if
+ IS_SYSTEM(code) { host_system_send(KEYCODE2SYSTEM(code)); }
+ else if
+ IS_CONSUMER(code) { host_consumer_send(KEYCODE2CONSUMER(code)); }
#endif
#ifdef MOUSEKEY_ENABLE
- else if IS_MOUSEKEY (code) {
- mousekey_on(code);
- mousekey_send();
- }
+ else if
+ IS_MOUSEKEY(code) {
+ mousekey_on(code);
+ mousekey_send();
+ }
#endif
}
@@ -840,54 +895,58 @@ void unregister_code(uint8_t code) {
return;
}
#ifdef LOCKING_SUPPORT_ENABLE
- else if (KC_LOCKING_CAPS == code) {
+ else if (KC_LOCKING_CAPS_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
// Resync: ignore if caps lock already is off
if (!(host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK))) return;
# endif
- add_key(KC_CAPSLOCK);
+ add_key(KC_CAPS_LOCK);
send_keyboard_report();
- del_key(KC_CAPSLOCK);
+ del_key(KC_CAPS_LOCK);
send_keyboard_report();
}
- else if (KC_LOCKING_NUM == code) {
+ else if (KC_LOCKING_NUM_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
if (!(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK))) return;
# endif
- add_key(KC_NUMLOCK);
+ add_key(KC_NUM_LOCK);
send_keyboard_report();
- del_key(KC_NUMLOCK);
+ del_key(KC_NUM_LOCK);
send_keyboard_report();
}
- else if (KC_LOCKING_SCROLL == code) {
+ else if (KC_LOCKING_SCROLL_LOCK == code) {
# ifdef LOCKING_RESYNC_ENABLE
if (!(host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK))) return;
# endif
- add_key(KC_SCROLLLOCK);
+ add_key(KC_SCROLL_LOCK);
send_keyboard_report();
- del_key(KC_SCROLLLOCK);
+ del_key(KC_SCROLL_LOCK);
send_keyboard_report();
}
#endif
- else if IS_KEY (code) {
- del_key(code);
- send_keyboard_report();
- } else if IS_MOD (code) {
- del_mods(MOD_BIT(code));
- send_keyboard_report();
- } else if IS_SYSTEM (code) {
- host_system_send(0);
- } else if IS_CONSUMER (code) {
- host_consumer_send(0);
- }
+ else if
+ IS_KEY(code) {
+ del_key(code);
+ send_keyboard_report();
+ }
+ else if
+ IS_MOD(code) {
+ del_mods(MOD_BIT(code));
+ send_keyboard_report();
+ }
+ else if
+ IS_SYSTEM(code) { host_system_send(0); }
+ else if
+ IS_CONSUMER(code) { host_consumer_send(0); }
#ifdef MOUSEKEY_ENABLE
- else if IS_MOUSEKEY (code) {
- mousekey_off(code);
- mousekey_send();
- }
+ else if
+ IS_MOUSEKEY(code) {
+ mousekey_off(code);
+ mousekey_send();
+ }
#endif
}
@@ -906,9 +965,9 @@ void tap_code_delay(uint8_t code, uint16_t delay) {
/** \brief Tap a keycode with the default delay.
*
- * \param code The basic keycode to tap. If `code` is `KC_CAPS`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
+ * \param code The basic keycode to tap. If `code` is `KC_CAPS_LOCK`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
*/
-void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); }
+void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS_LOCK ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); }
/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately.
*
@@ -989,6 +1048,10 @@ void clear_keyboard_but_mods_and_keys() {
mousekey_clear();
mousekey_send();
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ programmable_button_clear();
+ programmable_button_send();
+#endif
}
/** \brief Utilities for actions. (FIXME: Needs better description)
@@ -1029,7 +1092,7 @@ bool is_tap_action(action_t action) {
case ACT_LAYER_TAP:
case ACT_LAYER_TAP_EXT:
switch (action.layer_tap.code) {
- case KC_NO ... KC_RGUI:
+ case KC_NO ... KC_RIGHT_GUI:
case OP_TAP_TOGGLE:
case OP_ONESHOT:
return true;
@@ -1037,7 +1100,7 @@ bool is_tap_action(action_t action) {
return false;
case ACT_SWAP_HANDS:
switch (action.swap.code) {
- case KC_NO ... KC_RGUI:
+ case KC_NO ... KC_RIGHT_GUI:
case OP_SH_TAP_TOGGLE:
return true;
}
diff --git a/quantum/action.h b/quantum/action.h
index 8a357ded87..b562f18c5b 100644
--- a/quantum/action.h
+++ b/quantum/action.h
@@ -88,7 +88,7 @@ extern bool disable_action_cache;
/* Code for handling one-handed key modifiers. */
#ifdef SWAP_HANDS_ENABLE
-extern bool swap_hands;
+extern bool swap_hands;
extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS];
# if (MATRIX_COLS <= 8)
typedef uint8_t swap_state_row_t;
diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
index 36839f9faf..d2c93f85e3 100644
--- a/quantum/action_tapping.c
+++ b/quantum/action_tapping.c
@@ -18,18 +18,20 @@
# define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
# define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
# define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
-#ifndef COMBO_ENABLE
-# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)))
-#else
-# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
-#endif
+# ifndef COMBO_ENABLE
+# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)))
+# else
+# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
+# endif
+
+uint16_t g_tapping_term = TAPPING_TERM;
-__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; }
+__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return g_tapping_term; }
# ifdef TAPPING_TERM_PER_KEY
# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_record_keycode(&tapping_key, false), &tapping_key))
# else
-# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
+# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < g_tapping_term)
# endif
# ifdef TAPPING_FORCE_HOLD_PER_KEY
@@ -44,6 +46,10 @@ __attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *re
__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; }
# endif
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+# include "process_auto_shift.h"
+# endif
+
static keyrecord_t tapping_key = {};
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
static uint8_t waiting_buffer_head = 0;
@@ -107,12 +113,29 @@ void action_tapping_process(keyrecord_t record) {
/* return true when key event is processed or consumed. */
bool process_tapping(keyrecord_t *keyp) {
keyevent_t event = keyp->event;
+# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(TAPPING_TERM_PER_KEY) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
+ uint16_t tapping_keycode = get_record_keycode(&tapping_key, false);
+# endif
// if tapping
if (IS_TAPPING_PRESSED()) {
- if (WITHIN_TAPPING_TERM(event)) {
+ // clang-format off
+ if (WITHIN_TAPPING_TERM(event)
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ || (
+# ifdef RETRO_TAPPING_PER_KEY
+ get_retro_tapping(tapping_keycode, keyp) &&
+# endif
+ (RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16(event.time, tapping_key.event.time) < (RETRO_SHIFT + 0)
+ )
+# endif
+ ) {
+ // clang-format on
if (tapping_key.tap.count == 0) {
if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ retroshift_swap_times();
+# endif
// first tap!
debug("Tapping: First tap(0->1).\n");
tapping_key.tap.count = 1;
@@ -128,22 +151,70 @@ bool process_tapping(keyrecord_t *keyp) {
* This can register the key before settlement of tapping,
* useful for long TAPPING_TERM but may prevent fast typing.
*/
-# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY)
- else if (((
+ // clang-format off
+# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
+ else if (
+ (
+ (
+ (
# ifdef TAPPING_TERM_PER_KEY
- get_tapping_term(get_record_keycode(&tapping_key, false), keyp)
+ get_tapping_term(tapping_keycode, keyp)
# else
- TAPPING_TERM
+ g_tapping_term
# endif
- >= 500)
+ >= 500
+ )
# ifdef PERMISSIVE_HOLD_PER_KEY
- || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp)
+ || get_permissive_hold(tapping_keycode, keyp)
# elif defined(PERMISSIVE_HOLD)
- || true
+ || true
+# endif
+ ) && IS_RELEASED(event) && waiting_buffer_typed(event)
+ )
+ // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
+ // unnecessarily and fixes them for Layer Taps.
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ || (
+# ifdef RETRO_TAPPING_PER_KEY
+ get_retro_tapping(tapping_keycode, keyp) &&
+# endif
+ (
+ // Rolled over the two keys.
+ (
+ (
+ false
+# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
+ || (
+ IS_LT(tapping_keycode)
+# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
+ && get_hold_on_other_key_press(tapping_keycode, keyp)
+# endif
+ )
+# endif
+# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
+ || (
+ IS_MT(tapping_keycode)
+# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
+ && !get_ignore_mod_tap_interrupt(tapping_keycode, keyp)
+# endif
+ )
+# endif
+ ) && tapping_key.tap.interrupted == true
+ )
+ // Makes Retro Shift ignore [IGNORE_MOD_TAP_INTERRUPT's
+ // effects on nested taps for MTs and the default
+ // behavior of LTs] below TAPPING_TERM or RETRO_SHIFT.
+ || (
+ IS_RETRO(tapping_keycode)
+ && (event.key.col != tapping_key.event.key.col || event.key.row != tapping_key.event.key.row)
+ && IS_RELEASED(event) && waiting_buffer_typed(event)
+ )
+ )
+ )
# endif
- ) &&
- IS_RELEASED(event) && waiting_buffer_typed(event)) {
+ ) {
+ // clang-format on
debug("Tapping: End. No tap. Interfered by typing key\n");
process_record(&tapping_key);
tapping_key = (keyrecord_t){};
@@ -181,7 +252,7 @@ bool process_tapping(keyrecord_t *keyp) {
tapping_key.tap.interrupted = true;
# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
- if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp))
+ if (get_hold_on_other_key_press(tapping_keycode, keyp))
# endif
{
debug("Tapping: End. No tap. Interfered by pressed key\n");
@@ -212,11 +283,15 @@ bool process_tapping(keyrecord_t *keyp) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last tap(>1).\n");
// unregister key
- process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false,
-#ifdef COMBO_ENABLE
- .keycode = tapping_key.keycode,
-#endif
- });
+ process_record(&(keyrecord_t){
+ .tap = tapping_key.tap,
+ .event.key = tapping_key.event.key,
+ .event.time = event.time,
+ .event.pressed = false,
+# ifdef COMBO_ENABLE
+ .keycode = tapping_key.keycode,
+# endif
+ });
} else {
debug("Tapping: Start while last tap(1).\n");
}
@@ -254,11 +329,15 @@ bool process_tapping(keyrecord_t *keyp) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
// unregister key
- process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false,
-#ifdef COMBO_ENABLE
- .keycode = tapping_key.keycode,
-#endif
- });
+ process_record(&(keyrecord_t){
+ .tap = tapping_key.tap,
+ .event.key = tapping_key.event.key,
+ .event.time = event.time,
+ .event.pressed = false,
+# ifdef COMBO_ENABLE
+ .keycode = tapping_key.keycode,
+# endif
+ });
} else {
debug("Tapping: Start while last timeout tap(1).\n");
}
@@ -276,14 +355,25 @@ bool process_tapping(keyrecord_t *keyp) {
}
}
} else if (IS_TAPPING_RELEASED()) {
- if (WITHIN_TAPPING_TERM(event)) {
+ // clang-format off
+ if (WITHIN_TAPPING_TERM(event)
+# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
+ || (
+# ifdef RETRO_TAPPING_PER_KEY
+ get_retro_tapping(tapping_keycode, keyp) &&
+# endif
+ (RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16(event.time, tapping_key.event.time) < (RETRO_SHIFT + 0)
+ )
+# endif
+ ) {
+ // clang-format on
if (event.pressed) {
if (IS_TAPPING_RECORD(keyp)) {
//# ifndef TAPPING_FORCE_HOLD
# if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY)
if (
# ifdef TAPPING_FORCE_HOLD_PER_KEY
- !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) &&
+ !get_tapping_force_hold(tapping_keycode, keyp) &&
# endif
!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
// sequential tap.
diff --git a/quantum/action_tapping.h b/quantum/action_tapping.h
index 7de8049c7f..b2feb6850c 100644
--- a/quantum/action_tapping.h
+++ b/quantum/action_tapping.h
@@ -33,10 +33,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache);
uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache);
void action_tapping_process(keyrecord_t record);
+#endif
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record);
bool get_permissive_hold(uint16_t keycode, keyrecord_t *record);
bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record);
bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record);
bool get_retro_tapping(uint16_t keycode, keyrecord_t *record);
+
+#ifdef DYNAMIC_TAPPING_TERM_ENABLE
+extern uint16_t g_tapping_term;
#endif
diff --git a/quantum/action_util.c b/quantum/action_util.c
index 9a85bd5040..78e02aec18 100644
--- a/quantum/action_util.c
+++ b/quantum/action_util.c
@@ -170,7 +170,7 @@ void reset_oneshot_layer(void) {
void clear_oneshot_layer_state(oneshot_fullfillment_t state) {
uint8_t start_state = oneshot_layer_data;
oneshot_layer_data &= ~state;
- if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) {
+ if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) && !keymap_config.oneshot_disable) {
layer_off(get_oneshot_layer());
reset_oneshot_layer();
}
@@ -189,6 +189,7 @@ void oneshot_set(bool active) {
if (keymap_config.oneshot_disable != active) {
keymap_config.oneshot_disable = active;
eeconfig_update_keymap(keymap_config.raw);
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
dprintf("Oneshot: active: %d\n", active);
}
}
diff --git a/quantum/api.c b/quantum/api.c
deleted file mode 100644
index 1685744589..0000000000
--- a/quantum/api.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Copyright 2016 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "api.h"
-#include "quantum.h"
-
-void dword_to_bytes(uint32_t dword, uint8_t* bytes) {
- bytes[0] = (dword >> 24) & 0xFF;
- bytes[1] = (dword >> 16) & 0xFF;
- bytes[2] = (dword >> 8) & 0xFF;
- bytes[3] = (dword >> 0) & 0xFF;
-}
-
-uint32_t bytes_to_dword(uint8_t* bytes, uint8_t index) { return ((uint32_t)bytes[index + 0] << 24) | ((uint32_t)bytes[index + 1] << 16) | ((uint32_t)bytes[index + 2] << 8) | (uint32_t)bytes[index + 3]; }
-
-__attribute__((weak)) bool process_api_quantum(uint8_t length, uint8_t* data) { return process_api_keyboard(length, data); }
-
-__attribute__((weak)) bool process_api_keyboard(uint8_t length, uint8_t* data) { return process_api_user(length, data); }
-
-__attribute__((weak)) bool process_api_user(uint8_t length, uint8_t* data) { return true; }
-
-void process_api(uint16_t length, uint8_t* data) {
- // SEND_STRING("\nRX: ");
- // for (uint8_t i = 0; i < length; i++) {
- // send_byte(data[i]);
- // SEND_STRING(" ");
- // }
- if (!process_api_quantum(length, data)) return;
-
- switch (data[0]) {
- case MT_SET_DATA:
- switch (data[1]) {
- case DT_DEFAULT_LAYER: {
- eeconfig_update_default_layer(data[2]);
- default_layer_set((uint32_t)(data[2]));
- break;
- }
- case DT_KEYMAP_OPTIONS: {
- eeconfig_update_keymap(data[2]);
- break;
- }
- case DT_RGBLIGHT: {
-#ifdef RGBLIGHT_ENABLE
- uint32_t rgblight = bytes_to_dword(data, 2);
- eeconfig_update_rgblight(rgblight);
-#endif
- break;
- }
- }
- case MT_GET_DATA:
- switch (data[1]) {
- case DT_HANDSHAKE: {
- MT_GET_DATA_ACK(DT_HANDSHAKE, NULL, 0);
- break;
- }
- case DT_DEBUG: {
- uint8_t debug_bytes[1] = {eeprom_read_byte(EECONFIG_DEBUG)};
- MT_GET_DATA_ACK(DT_DEBUG, debug_bytes, 1);
- break;
- }
- case DT_DEFAULT_LAYER: {
- uint8_t default_bytes[1] = {eeprom_read_byte(EECONFIG_DEFAULT_LAYER)};
- MT_GET_DATA_ACK(DT_DEFAULT_LAYER, default_bytes, 1);
- break;
- }
- case DT_CURRENT_LAYER: {
- uint8_t layer_state_bytes[4];
- dword_to_bytes(layer_state, layer_state_bytes);
- MT_GET_DATA_ACK(DT_CURRENT_LAYER, layer_state_bytes, 4);
- break;
- }
- case DT_AUDIO: {
-#ifdef AUDIO_ENABLE
- uint8_t audio_bytes[1] = {eeprom_read_byte(EECONFIG_AUDIO)};
- MT_GET_DATA_ACK(DT_AUDIO, audio_bytes, 1);
-#else
- MT_GET_DATA_ACK(DT_AUDIO, NULL, 0);
-#endif
- break;
- }
- case DT_BACKLIGHT: {
-#ifdef BACKLIGHT_ENABLE
- uint8_t backlight_bytes[1] = {eeprom_read_byte(EECONFIG_BACKLIGHT)};
- MT_GET_DATA_ACK(DT_BACKLIGHT, backlight_bytes, 1);
-#else
- MT_GET_DATA_ACK(DT_BACKLIGHT, NULL, 0);
-#endif
- break;
- }
- case DT_RGBLIGHT: {
-#ifdef RGBLIGHT_ENABLE
- uint8_t rgblight_bytes[4];
- dword_to_bytes(eeconfig_read_rgblight(), rgblight_bytes);
- MT_GET_DATA_ACK(DT_RGBLIGHT, rgblight_bytes, 4);
-#else
- MT_GET_DATA_ACK(DT_RGBLIGHT, NULL, 0);
-#endif
- break;
- }
- case DT_KEYMAP_OPTIONS: {
- uint8_t keymap_bytes[1] = {eeconfig_read_keymap()};
- MT_GET_DATA_ACK(DT_KEYMAP_OPTIONS, keymap_bytes, 1);
- break;
- }
- case DT_KEYMAP_SIZE: {
- uint8_t keymap_size[2] = {MATRIX_ROWS, MATRIX_COLS};
- MT_GET_DATA_ACK(DT_KEYMAP_SIZE, keymap_size, 2);
- break;
- }
- // This may be too much
- // case DT_KEYMAP: {
- // uint8_t keymap_data[MATRIX_ROWS * MATRIX_COLS * 4 + 3];
- // keymap_data[0] = data[2];
- // keymap_data[1] = MATRIX_ROWS;
- // keymap_data[2] = MATRIX_COLS;
- // for (int i = 0; i < MATRIX_ROWS; i++) {
- // for (int j = 0; j < MATRIX_COLS; j++) {
- // keymap_data[3 + (i*MATRIX_COLS*2) + (j*2)] = pgm_read_word(&keymaps[data[2]][i][j]) >> 8;
- // keymap_data[3 + (i*MATRIX_COLS*2) + (j*2) + 1] = pgm_read_word(&keymaps[data[2]][i][j]) & 0xFF;
- // }
- // }
- // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, MATRIX_ROWS * MATRIX_COLS * 4 + 3);
- // // uint8_t keymap_data[5];
- // // keymap_data[0] = data[2];
- // // keymap_data[1] = data[3];
- // // keymap_data[2] = data[4];
- // // keymap_data[3] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) >> 8;
- // // keymap_data[4] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) & 0xFF;
-
- // // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, 5);
- // break;
- // }
- default:
- break;
- }
- break;
- case MT_SET_DATA_ACK:
- case MT_GET_DATA_ACK:
- break;
- case MT_SEND_DATA:
- break;
- case MT_SEND_DATA_ACK:
- break;
- case MT_EXE_ACTION:
- break;
- case MT_EXE_ACTION_ACK:
- break;
- case MT_TYPE_ERROR:
- break;
- default:; // command not recognised
- SEND_BYTES(MT_TYPE_ERROR, DT_NONE, data, length);
- break;
-
- // #ifdef RGBLIGHT_ENABLE
- // case 0x27: ; // RGB LED functions
- // switch (*data++) {
- // case 0x00: ; // Update HSV
- // rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]);
- // break;
- // case 0x01: ; // Update RGB
- // break;
- // case 0x02: ; // Update mode
- // rgblight_mode(data[0]);
- // break;
- // }
- // break;
- // #endif
- }
-}
diff --git a/quantum/api.h b/quantum/api.h
deleted file mode 100644
index 0a30e9d6cc..0000000000
--- a/quantum/api.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright 2016 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#ifdef __AVR__
-# include "lufa.h"
-#endif
-
-enum MESSAGE_TYPE {
- MT_GET_DATA = 0x10, // Get data from keyboard
- MT_GET_DATA_ACK = 0x11, // returned data to process (ACK)
- MT_SET_DATA = 0x20, // Set data on keyboard
- MT_SET_DATA_ACK = 0x21, // returned data to confirm (ACK)
- MT_SEND_DATA = 0x30, // Sending data/action from keyboard
- MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK)
- MT_EXE_ACTION = 0x40, // executing actions on keyboard
- MT_EXE_ACTION_ACK = 0x41, // return confirmation/value (ACK)
- MT_TYPE_ERROR = 0x80 // type not recognised (ACK)
-};
-
-enum DATA_TYPE { DT_NONE = 0x00, DT_HANDSHAKE, DT_DEFAULT_LAYER, DT_CURRENT_LAYER, DT_KEYMAP_OPTIONS, DT_BACKLIGHT, DT_RGBLIGHT, DT_UNICODE, DT_DEBUG, DT_AUDIO, DT_QUANTUM_ACTION, DT_KEYBOARD_ACTION, DT_USER_ACTION, DT_KEYMAP_SIZE, DT_KEYMAP };
-
-void dword_to_bytes(uint32_t dword, uint8_t* bytes);
-uint32_t bytes_to_dword(uint8_t* bytes, uint8_t index);
-
-#define MT_GET_DATA(data_type, data, length) SEND_BYTES(MT_GET_DATA, data_type, data, length)
-#define MT_GET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_GET_DATA_ACK, data_type, data, length)
-#define MT_SET_DATA(data_type, data, length) SEND_BYTES(MT_SET_DATA, data_type, data, length)
-#define MT_SET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SET_DATA_ACK, data_type, data, length)
-#define MT_SEND_DATA(data_type, data, length) SEND_BYTES(MT_SEND_DATA, data_type, data, length)
-#define MT_SEND_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SEND_DATA_ACK, data_type, data, length)
-#define MT_EXE_ACTION(data_type, data, length) SEND_BYTES(MT_EXE_ACTION, data_type, data, length)
-#define MT_EXE_ACTION_ACK(data_type, data, length) SEND_BYTES(MT_EXE_ACTION_ACK, data_type, data, length)
-
-void process_api(uint16_t length, uint8_t* data);
-
-__attribute__((weak)) bool process_api_quantum(uint8_t length, uint8_t* data);
-
-__attribute__((weak)) bool process_api_keyboard(uint8_t length, uint8_t* data);
-
-__attribute__((weak)) bool process_api_user(uint8_t length, uint8_t* data);
diff --git a/quantum/api/api_sysex.c b/quantum/api/api_sysex.c
deleted file mode 100644
index 07c90cf804..0000000000
--- a/quantum/api/api_sysex.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Copyright 2016 Jack Humbert, Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#include "api_sysex.h"
-#include "sysex_tools.h"
-#include "print.h"
-#include "qmk_midi.h"
-
-void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t* bytes, uint16_t length) {
- // SEND_STRING("\nTX: ");
- // for (uint8_t i = 0; i < length; i++) {
- // send_byte(bytes[i]);
- // SEND_STRING(" ");
- // }
- if (length > API_SYSEX_MAX_SIZE) {
- xprintf("Sysex msg too big %d %d %d", message_type, data_type, length);
- return;
- }
-
- // The buffer size required is calculated as the following
- // API_SYSEX_MAX_SIZE is the maximum length
- // In addition to that we have a two byte message header consisting of the message_type and data_type
- // This has to be encoded with an additional overhead of one byte for every starting 7 bytes
- // We just add one extra byte in case it's not divisible by 7
- // Then we have an unencoded header consisting of 4 bytes
- // Plus a one byte terminator
- const unsigned message_header = 2;
- const unsigned unencoded_message = API_SYSEX_MAX_SIZE + message_header;
- const unsigned encoding_overhead = unencoded_message / 7 + 1;
- const unsigned encoded_size = unencoded_message + encoding_overhead;
- const unsigned unencoded_header = 4;
- const unsigned terminator = 1;
- const unsigned buffer_size = encoded_size + unencoded_header + terminator;
- uint8_t buffer[encoded_size + unencoded_header + terminator];
- // The unencoded header
- buffer[0] = 0xF0;
- buffer[1] = 0x00;
- buffer[2] = 0x00;
- buffer[3] = 0x00;
-
- // We copy the message to the end of the array, this way we can do an inplace encoding, using the same
- // buffer for both input and output
- const unsigned message_size = length + message_header;
- uint8_t* unencoded_start = buffer + buffer_size - message_size;
- uint8_t* ptr = unencoded_start;
- *(ptr++) = message_type;
- *(ptr++) = data_type;
- memcpy(ptr, bytes, length);
-
- unsigned encoded_length = sysex_encode(buffer + unencoded_header, unencoded_start, message_size);
- unsigned final_size = unencoded_header + encoded_length + terminator;
- buffer[final_size - 1] = 0xF7;
- midi_send_array(&midi_device, final_size, buffer);
-
- // SEND_STRING("\nTD: ");
- // for (uint8_t i = 0; i < encoded_length + 5; i++) {
- // send_byte(buffer[i]);
- // SEND_STRING(" ");
- // }
-}
diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h
index 56b9158a1a..290d461f5a 100644
--- a/quantum/audio/audio.h
+++ b/quantum/audio/audio.h
@@ -26,17 +26,12 @@
#if defined(__AVR__)
# include <avr/io.h>
-# if defined(AUDIO_DRIVER_PWM)
-# include "driver_avr_pwm.h"
-# endif
#endif
-#if defined(PROTOCOL_CHIBIOS)
-# if defined(AUDIO_DRIVER_PWM)
-# include "driver_chibios_pwm.h"
-# elif defined(AUDIO_DRIVER_DAC)
-# include "driver_chibios_dac.h"
-# endif
+#if defined(AUDIO_DRIVER_PWM)
+# include "audio_pwm.h"
+#elif defined(AUDIO_DRIVER_DAC)
+# include "audio_dac.h"
#endif
typedef union {
diff --git a/quantum/audio/driver_avr_pwm.h b/quantum/audio/driver_avr_pwm.h
deleted file mode 100644
index d6eb3571da..0000000000
--- a/quantum/audio/driver_avr_pwm.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Copyright 2020 Jack Humbert
- * Copyright 2020 JohSchneider
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
diff --git a/quantum/audio/driver_avr_pwm_hardware.c b/quantum/audio/driver_avr_pwm_hardware.c
deleted file mode 100644
index df03a4558c..0000000000
--- a/quantum/audio/driver_avr_pwm_hardware.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/* Copyright 2016 Jack Humbert
- * Copyright 2020 JohSchneider
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#if defined(__AVR__)
-# include <avr/pgmspace.h>
-# include <avr/interrupt.h>
-# include <avr/io.h>
-#endif
-
-#include "audio.h"
-
-extern bool playing_note;
-extern bool playing_melody;
-extern uint8_t note_timbre;
-
-#define CPU_PRESCALER 8
-
-/*
- Audio Driver: PWM
-
- drive up to two speakers through the AVR PWM hardware-peripheral, using timer1 and/or timer3 on Atmega32U4.
-
- the primary channel_1 can be connected to either pin PC4 PC5 or PC6 (the later being used by most AVR based keyboards) with a PMW signal generated by timer3
- and an optional secondary channel_2 on either pin PB5, PB6 or PB7, with a PWM signal from timer1
-
- alternatively, the PWM pins on PORTB can be used as only/primary speaker
-*/
-
-#if defined(AUDIO_PIN) && (AUDIO_PIN != C4) && (AUDIO_PIN != C5) && (AUDIO_PIN != C6) && (AUDIO_PIN != B5) && (AUDIO_PIN != B6) && (AUDIO_PIN != B7) && (AUDIO_PIN != D5)
-# error "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under the AVR settings for available options."
-#endif
-
-#if (AUDIO_PIN == C4) || (AUDIO_PIN == C5) || (AUDIO_PIN == C6)
-# define AUDIO1_PIN_SET
-# define AUDIO1_TIMSKx TIMSK3
-# define AUDIO1_TCCRxA TCCR3A
-# define AUDIO1_TCCRxB TCCR3B
-# define AUDIO1_ICRx ICR3
-# define AUDIO1_WGMx0 WGM30
-# define AUDIO1_WGMx1 WGM31
-# define AUDIO1_WGMx2 WGM32
-# define AUDIO1_WGMx3 WGM33
-# define AUDIO1_CSx0 CS30
-# define AUDIO1_CSx1 CS31
-# define AUDIO1_CSx2 CS32
-
-# if (AUDIO_PIN == C6)
-# define AUDIO1_COMxy0 COM3A0
-# define AUDIO1_COMxy1 COM3A1
-# define AUDIO1_OCIExy OCIE3A
-# define AUDIO1_OCRxy OCR3A
-# define AUDIO1_PIN C6
-# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPA_vect
-# elif (AUDIO_PIN == C5)
-# define AUDIO1_COMxy0 COM3B0
-# define AUDIO1_COMxy1 COM3B1
-# define AUDIO1_OCIExy OCIE3B
-# define AUDIO1_OCRxy OCR3B
-# define AUDIO1_PIN C5
-# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPB_vect
-# elif (AUDIO_PIN == C4)
-# define AUDIO1_COMxy0 COM3C0
-# define AUDIO1_COMxy1 COM3C1
-# define AUDIO1_OCIExy OCIE3C
-# define AUDIO1_OCRxy OCR3C
-# define AUDIO1_PIN C4
-# define AUDIO1_TIMERx_COMPy_vect TIMER3_COMPC_vect
-# endif
-#endif
-
-#if defined(AUDIO_PIN) && defined(AUDIO_PIN_ALT) && (AUDIO_PIN == AUDIO_PIN_ALT)
-# error "Audio feature: AUDIO_PIN and AUDIO_PIN_ALT on the same pin makes no sense."
-#endif
-
-#if ((AUDIO_PIN == B5) && ((AUDIO_PIN_ALT == B6) || (AUDIO_PIN_ALT == B7))) || ((AUDIO_PIN == B6) && ((AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B7))) || ((AUDIO_PIN == B7) && ((AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B6)))
-# error "Audio feature: PORTB as AUDIO_PIN and AUDIO_PIN_ALT at the same time is not supported."
-#endif
-
-#if defined(AUDIO_PIN_ALT) && (AUDIO_PIN_ALT != B5) && (AUDIO_PIN_ALT != B6) && (AUDIO_PIN_ALT != B7)
-# error "Audio feature: the pin selected as AUDIO_PIN_ALT is not supported."
-#endif
-
-#if (AUDIO_PIN == B5) || (AUDIO_PIN == B6) || (AUDIO_PIN == B7) || (AUDIO_PIN_ALT == B5) || (AUDIO_PIN_ALT == B6) || (AUDIO_PIN_ALT == B7) || (AUDIO_PIN == D5)
-# define AUDIO2_PIN_SET
-# define AUDIO2_TIMSKx TIMSK1
-# define AUDIO2_TCCRxA TCCR1A
-# define AUDIO2_TCCRxB TCCR1B
-# define AUDIO2_ICRx ICR1
-# define AUDIO2_WGMx0 WGM10
-# define AUDIO2_WGMx1 WGM11
-# define AUDIO2_WGMx2 WGM12
-# define AUDIO2_WGMx3 WGM13
-# define AUDIO2_CSx0 CS10
-# define AUDIO2_CSx1 CS11
-# define AUDIO2_CSx2 CS12
-
-# if (AUDIO_PIN == B5) || (AUDIO_PIN_ALT == B5)
-# define AUDIO2_COMxy0 COM1A0
-# define AUDIO2_COMxy1 COM1A1
-# define AUDIO2_OCIExy OCIE1A
-# define AUDIO2_OCRxy OCR1A
-# define AUDIO2_PIN B5
-# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPA_vect
-# elif (AUDIO_PIN == B6) || (AUDIO_PIN_ALT == B6)
-# define AUDIO2_COMxy0 COM1B0
-# define AUDIO2_COMxy1 COM1B1
-# define AUDIO2_OCIExy OCIE1B
-# define AUDIO2_OCRxy OCR1B
-# define AUDIO2_PIN B6
-# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPB_vect
-# elif (AUDIO_PIN == B7) || (AUDIO_PIN_ALT == B7)
-# define AUDIO2_COMxy0 COM1C0
-# define AUDIO2_COMxy1 COM1C1
-# define AUDIO2_OCIExy OCIE1C
-# define AUDIO2_OCRxy OCR1C
-# define AUDIO2_PIN B7
-# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPC_vect
-# elif (AUDIO_PIN == D5) && defined(__AVR_ATmega32A__)
-# pragma message "Audio support for ATmega32A is experimental and can cause crashes."
-# undef AUDIO2_TIMSKx
-# define AUDIO2_TIMSKx TIMSK
-# define AUDIO2_COMxy0 COM1A0
-# define AUDIO2_COMxy1 COM1A1
-# define AUDIO2_OCIExy OCIE1A
-# define AUDIO2_OCRxy OCR1A
-# define AUDIO2_PIN D5
-# define AUDIO2_TIMERx_COMPy_vect TIMER1_COMPA_vect
-# endif
-#endif
-
-// C6 seems to be the assumed default by many existing keyboard - but sill warn the user
-#if !defined(AUDIO1_PIN_SET) && !defined(AUDIO2_PIN_SET)
-# pragma message "Audio feature enabled, but no suitable pin selected - see docs/feature_audio under the AVR settings for available options. Don't expect to hear anything... :-)"
-// TODO: make this an error - go through the breaking-change-process and change all keyboards to the new define
-#endif
-// -----------------------------------------------------------------------------
-
-#ifdef AUDIO1_PIN_SET
-static float channel_1_frequency = 0.0f;
-void channel_1_set_frequency(float freq) {
- if (freq == 0.0f) // a pause/rest is a valid "note" with freq=0
- {
- // disable the output, but keep the pwm-ISR going (with the previous
- // frequency) so the audio-state keeps getting updated
- // Note: setting the duty-cycle 0 is not possible on non-inverting PWM mode - see the AVR data-sheet
- AUDIO1_TCCRxA &= ~(_BV(AUDIO1_COMxy1) | _BV(AUDIO1_COMxy0));
- return;
- } else {
- AUDIO1_TCCRxA |= _BV(AUDIO1_COMxy1); // enable output, PWM mode
- }
-
- channel_1_frequency = freq;
-
- // set pwm period
- AUDIO1_ICRx = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
- // and duty cycle
- AUDIO1_OCRxy = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre / 100);
-}
-
-void channel_1_start(void) {
- // enable timer-counter ISR
- AUDIO1_TIMSKx |= _BV(AUDIO1_OCIExy);
- // enable timer-counter output
- AUDIO1_TCCRxA |= _BV(AUDIO1_COMxy1);
-}
-
-void channel_1_stop(void) {
- // disable timer-counter ISR
- AUDIO1_TIMSKx &= ~_BV(AUDIO1_OCIExy);
- // disable timer-counter output
- AUDIO1_TCCRxA &= ~(_BV(AUDIO1_COMxy1) | _BV(AUDIO1_COMxy0));
-}
-#endif
-
-#ifdef AUDIO2_PIN_SET
-static float channel_2_frequency = 0.0f;
-void channel_2_set_frequency(float freq) {
- if (freq == 0.0f) {
- AUDIO2_TCCRxA &= ~(_BV(AUDIO2_COMxy1) | _BV(AUDIO2_COMxy0));
- return;
- } else {
- AUDIO2_TCCRxA |= _BV(AUDIO2_COMxy1);
- }
-
- channel_2_frequency = freq;
-
- AUDIO2_ICRx = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
- AUDIO2_OCRxy = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre / 100);
-}
-
-float channel_2_get_frequency(void) { return channel_2_frequency; }
-
-void channel_2_start(void) {
- AUDIO2_TIMSKx |= _BV(AUDIO2_OCIExy);
- AUDIO2_TCCRxA |= _BV(AUDIO2_COMxy1);
-}
-
-void channel_2_stop(void) {
- AUDIO2_TIMSKx &= ~_BV(AUDIO2_OCIExy);
- AUDIO2_TCCRxA &= ~(_BV(AUDIO2_COMxy1) | _BV(AUDIO2_COMxy0));
-}
-#endif
-
-void audio_driver_initialize() {
-#ifdef AUDIO1_PIN_SET
- channel_1_stop();
- setPinOutput(AUDIO1_PIN);
-#endif
-
-#ifdef AUDIO2_PIN_SET
- channel_2_stop();
- setPinOutput(AUDIO2_PIN);
-#endif
-
- // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers TCCR3A/TCCR3B, TCCR1A/TCCR1B
- // Compare Output Mode (COM3An and COM1An) = 0b00 = Normal port operation
- // OC3A -- PC6
- // OC3B -- PC5
- // OC3C -- PC4
- // OC1A -- PB5
- // OC1B -- PB6
- // OC1C -- PB7
-
- // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14. Period = ICR3, Duty Cycle OCR3A)
- // OCR3A - PC6
- // OCR3B - PC5
- // OCR3C - PC4
- // OCR1A - PB5
- // OCR1B - PB6
- // OCR1C - PB7
-
- // Clock Select (CS3n) = 0b010 = Clock / 8
-#ifdef AUDIO1_PIN_SET
- // initialize timer-counter
- AUDIO1_TCCRxA = (0 << AUDIO1_COMxy1) | (0 << AUDIO1_COMxy0) | (1 << AUDIO1_WGMx1) | (0 << AUDIO1_WGMx0);
- AUDIO1_TCCRxB = (1 << AUDIO1_WGMx3) | (1 << AUDIO1_WGMx2) | (0 << AUDIO1_CSx2) | (1 << AUDIO1_CSx1) | (0 << AUDIO1_CSx0);
-#endif
-
-#ifdef AUDIO2_PIN_SET
- AUDIO2_TCCRxA = (0 << AUDIO2_COMxy1) | (0 << AUDIO2_COMxy0) | (1 << AUDIO2_WGMx1) | (0 << AUDIO2_WGMx0);
- AUDIO2_TCCRxB = (1 << AUDIO2_WGMx3) | (1 << AUDIO2_WGMx2) | (0 << AUDIO2_CSx2) | (1 << AUDIO2_CSx1) | (0 << AUDIO2_CSx0);
-#endif
-}
-
-void audio_driver_stop() {
-#ifdef AUDIO1_PIN_SET
- channel_1_stop();
-#endif
-
-#ifdef AUDIO2_PIN_SET
- channel_2_stop();
-#endif
-}
-
-void audio_driver_start(void) {
-#ifdef AUDIO1_PIN_SET
- channel_1_start();
- if (playing_note) {
- channel_1_set_frequency(audio_get_processed_frequency(0));
- }
-#endif
-
-#if !defined(AUDIO1_PIN_SET) && defined(AUDIO2_PIN_SET)
- channel_2_start();
- if (playing_note) {
- channel_2_set_frequency(audio_get_processed_frequency(0));
- }
-#endif
-}
-
-static volatile uint32_t isr_counter = 0;
-#ifdef AUDIO1_PIN_SET
-ISR(AUDIO1_TIMERx_COMPy_vect) {
- isr_counter++;
- if (isr_counter < channel_1_frequency / (CPU_PRESCALER * 8)) return;
-
- isr_counter = 0;
- bool state_changed = audio_update_state();
-
- if (!playing_note && !playing_melody) {
- channel_1_stop();
-# ifdef AUDIO2_PIN_SET
- channel_2_stop();
-# endif
- return;
- }
-
- if (state_changed) {
- channel_1_set_frequency(audio_get_processed_frequency(0));
-# ifdef AUDIO2_PIN_SET
- if (audio_get_number_of_active_tones() > 1) {
- channel_2_set_frequency(audio_get_processed_frequency(1));
- } else {
- channel_2_stop();
- }
-# endif
- }
-}
-#endif
-
-#if !defined(AUDIO1_PIN_SET) && defined(AUDIO2_PIN_SET)
-ISR(AUDIO2_TIMERx_COMPy_vect) {
- isr_counter++;
- if (isr_counter < channel_2_frequency / (CPU_PRESCALER * 8)) return;
-
- isr_counter = 0;
- bool state_changed = audio_update_state();
-
- if (!playing_note && !playing_melody) {
- channel_2_stop();
- return;
- }
-
- if (state_changed) {
- channel_2_set_frequency(audio_get_processed_frequency(0));
- }
-}
-#endif
diff --git a/quantum/audio/driver_chibios_dac.h b/quantum/audio/driver_chibios_dac.h
deleted file mode 100644
index 07cd622ead..0000000000
--- a/quantum/audio/driver_chibios_dac.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Copyright 2019 Jack Humbert
- * Copyright 2020 JohSchneider
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#ifndef A4
-# define A4 PAL_LINE(GPIOA, 4)
-#endif
-#ifndef A5
-# define A5 PAL_LINE(GPIOA, 5)
-#endif
-
-/**
- * Size of the dac_buffer arrays. All must be the same size.
- */
-#define AUDIO_DAC_BUFFER_SIZE 256U
-
-/**
- * Highest value allowed sample value.
-
- * since the DAC is limited to 12 bit, the absolute max is 0xfff = 4095U;
- * lower values adjust the peak-voltage aka volume down.
- * adjusting this value has only an effect on a sample-buffer whose values are
- * are NOT pregenerated - see square-wave
- */
-#ifndef AUDIO_DAC_SAMPLE_MAX
-# define AUDIO_DAC_SAMPLE_MAX 4095U
-#endif
-
-#if !defined(AUDIO_DAC_SAMPLE_RATE) && !defined(AUDIO_MAX_SIMULTANEOUS_TONES) && !defined(AUDIO_DAC_QUALITY_VERY_LOW) && !defined(AUDIO_DAC_QUALITY_LOW) && !defined(AUDIO_DAC_QUALITY_HIGH) && !defined(AUDIO_DAC_QUALITY_VERY_HIGH)
-# define AUDIO_DAC_QUALITY_SANE_MINIMUM
-#endif
-
-/**
- * These presets allow you to quickly switch between quality settings for
- * the DAC. The sample rate and maximum number of simultaneous tones roughly
- * has an inverse relationship - slightly higher sample rates may be possible.
- *
- * NOTE: a high sample-rate results in a higher cpu-load, which might lead to
- * (audible) discontinuities and/or starve other processes of cpu-time
- * (like RGB-led back-lighting, ...)
- */
-#ifdef AUDIO_DAC_QUALITY_VERY_LOW
-# define AUDIO_DAC_SAMPLE_RATE 11025U
-# define AUDIO_MAX_SIMULTANEOUS_TONES 8
-#endif
-
-#ifdef AUDIO_DAC_QUALITY_LOW
-# define AUDIO_DAC_SAMPLE_RATE 22050U
-# define AUDIO_MAX_SIMULTANEOUS_TONES 4
-#endif
-
-#ifdef AUDIO_DAC_QUALITY_HIGH
-# define AUDIO_DAC_SAMPLE_RATE 44100U
-# define AUDIO_MAX_SIMULTANEOUS_TONES 2
-#endif
-
-#ifdef AUDIO_DAC_QUALITY_VERY_HIGH
-# define AUDIO_DAC_SAMPLE_RATE 88200U
-# define AUDIO_MAX_SIMULTANEOUS_TONES 1
-#endif
-
-#ifdef AUDIO_DAC_QUALITY_SANE_MINIMUM
-/* a sane-minimum config: with a trade-off between cpu-load and tone-range
- *
- * the (currently) highest defined note is NOTE_B8 with 7902Hz; if we now
- * aim for an even even multiple of the buffer-size, we end up with:
- * ( roundUptoPow2(highest note / AUDIO_DAC_BUFFER_SIZE) * nyquist-rate * AUDIO_DAC_BUFFER_SIZE)
- * 7902/256 = 30.867 * 2 * 256 ~= 16384
- * which works out (but the 'scope shows some sampling artifacts with lower harmonics :-P)
- */
-# define AUDIO_DAC_SAMPLE_RATE 16384U
-# define AUDIO_MAX_SIMULTANEOUS_TONES 8
-#endif
-
-/**
- * Effective bit-rate of the DAC. 44.1khz is the standard for most audio - any
- * lower will sacrifice perceptible audio quality. Any higher will limit the
- * number of simultaneous tones. In most situations, a tenth (1/10) of the
- * sample rate is where notes become unbearable.
- */
-#ifndef AUDIO_DAC_SAMPLE_RATE
-# define AUDIO_DAC_SAMPLE_RATE 44100U
-#endif
-
-/**
- * The number of tones that can be played simultaneously. If too high a value
- * is used here, the keyboard will freeze and glitch-out when that many tones
- * are being played.
- */
-#ifndef AUDIO_MAX_SIMULTANEOUS_TONES
-# define AUDIO_MAX_SIMULTANEOUS_TONES 2
-#endif
-
-/**
- * The default value of the DAC when not playing anything. Certain hardware
- * setups may require a high (AUDIO_DAC_SAMPLE_MAX) or low (0) value here.
- * Since multiple added sine waves tend to oscillate around the midpoint,
- * and possibly never/rarely reach either 0 of MAX, 1/2 MAX can be a
- * reasonable default value.
- */
-#ifndef AUDIO_DAC_OFF_VALUE
-# define AUDIO_DAC_OFF_VALUE AUDIO_DAC_SAMPLE_MAX / 2
-#endif
-
-#if AUDIO_DAC_OFF_VALUE > AUDIO_DAC_SAMPLE_MAX
-# error "AUDIO_DAC: OFF_VALUE may not be larger than SAMPLE_MAX"
-#endif
-
-/**
- *user overridable sample generation/processing
- */
-uint16_t dac_value_generate(void);
diff --git a/quantum/audio/driver_chibios_dac_additive.c b/quantum/audio/driver_chibios_dac_additive.c
deleted file mode 100644
index db304adb87..0000000000
--- a/quantum/audio/driver_chibios_dac_additive.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/* Copyright 2016-2019 Jack Humbert
- * Copyright 2020 JohSchneider
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "audio.h"
-#include <ch.h>
-#include <hal.h>
-
-/*
- Audio Driver: DAC
-
- which utilizes the dac unit many STM32 are equipped with, to output a modulated waveform from samples stored in the dac_buffer_* array who are passed to the hardware through DMA
-
- it is also possible to have a custom sample-LUT by implementing/overriding 'dac_value_generate'
-
- this driver allows for multiple simultaneous tones to be played through one single channel by doing additive wave-synthesis
-*/
-
-#if !defined(AUDIO_PIN)
-# error "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under 'ARM (DAC additive)' for available options."
-#endif
-#if defined(AUDIO_PIN_ALT) && !defined(AUDIO_PIN_ALT_AS_NEGATIVE)
-# pragma message "Audio feature: AUDIO_PIN_ALT set, but not AUDIO_PIN_ALT_AS_NEGATIVE - pin will be left unused; audio might still work though."
-#endif
-
-#if !defined(AUDIO_PIN_ALT)
-// no ALT pin defined is valid, but the c-ifs below need some value set
-# define AUDIO_PIN_ALT PAL_NOLINE
-#endif
-
-#if !defined(AUDIO_DAC_SAMPLE_WAVEFORM_SINE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE) && !defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID)
-# define AUDIO_DAC_SAMPLE_WAVEFORM_SINE
-#endif
-
-#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SINE
-/* one full sine wave over [0,2*pi], but shifted up one amplitude and left pi/4; for the samples to start at 0
- */
-static const dacsample_t dac_buffer_sine[AUDIO_DAC_BUFFER_SIZE] = {
- // 256 values, max 4095
- 0x0, 0x1, 0x2, 0x6, 0xa, 0xf, 0x16, 0x1e, 0x27, 0x32, 0x3d, 0x4a, 0x58, 0x67, 0x78, 0x89, 0x9c, 0xb0, 0xc5, 0xdb, 0xf2, 0x10a, 0x123, 0x13e, 0x159, 0x175, 0x193, 0x1b1, 0x1d1, 0x1f1, 0x212, 0x235, 0x258, 0x27c, 0x2a0, 0x2c6, 0x2ed, 0x314, 0x33c, 0x365, 0x38e, 0x3b8, 0x3e3, 0x40e, 0x43a, 0x467, 0x494, 0x4c2, 0x4f0, 0x51f, 0x54e, 0x57d, 0x5ad, 0x5dd, 0x60e, 0x63f, 0x670, 0x6a1, 0x6d3, 0x705, 0x737, 0x769, 0x79b, 0x7cd, 0x800, 0x832, 0x864, 0x896, 0x8c8, 0x8fa, 0x92c, 0x95e, 0x98f, 0x9c0, 0x9f1, 0xa22, 0xa52, 0xa82, 0xab1, 0xae0, 0xb0f, 0xb3d, 0xb6b, 0xb98, 0xbc5, 0xbf1, 0xc1c, 0xc47, 0xc71, 0xc9a, 0xcc3, 0xceb, 0xd12, 0xd39, 0xd5f, 0xd83, 0xda7, 0xdca, 0xded, 0xe0e, 0xe2e, 0xe4e, 0xe6c, 0xe8a, 0xea6, 0xec1, 0xedc, 0xef5, 0xf0d, 0xf24, 0xf3a, 0xf4f, 0xf63, 0xf76, 0xf87, 0xf98, 0xfa7, 0xfb5, 0xfc2, 0xfcd, 0xfd8, 0xfe1, 0xfe9, 0xff0, 0xff5, 0xff9, 0xffd, 0xffe,
- 0xfff, 0xffe, 0xffd, 0xff9, 0xff5, 0xff0, 0xfe9, 0xfe1, 0xfd8, 0xfcd, 0xfc2, 0xfb5, 0xfa7, 0xf98, 0xf87, 0xf76, 0xf63, 0xf4f, 0xf3a, 0xf24, 0xf0d, 0xef5, 0xedc, 0xec1, 0xea6, 0xe8a, 0xe6c, 0xe4e, 0xe2e, 0xe0e, 0xded, 0xdca, 0xda7, 0xd83, 0xd5f, 0xd39, 0xd12, 0xceb, 0xcc3, 0xc9a, 0xc71, 0xc47, 0xc1c, 0xbf1, 0xbc5, 0xb98, 0xb6b, 0xb3d, 0xb0f, 0xae0, 0xab1, 0xa82, 0xa52, 0xa22, 0x9f1, 0x9c0, 0x98f, 0x95e, 0x92c, 0x8fa, 0x8c8, 0x896, 0x864, 0x832, 0x800, 0x7cd, 0x79b, 0x769, 0x737, 0x705, 0x6d3, 0x6a1, 0x670, 0x63f, 0x60e, 0x5dd, 0x5ad, 0x57d, 0x54e, 0x51f, 0x4f0, 0x4c2, 0x494, 0x467, 0x43a, 0x40e, 0x3e3, 0x3b8, 0x38e, 0x365, 0x33c, 0x314, 0x2ed, 0x2c6, 0x2a0, 0x27c, 0x258, 0x235, 0x212, 0x1f1, 0x1d1, 0x1b1, 0x193, 0x175, 0x159, 0x13e, 0x123, 0x10a, 0xf2, 0xdb, 0xc5, 0xb0, 0x9c, 0x89, 0x78, 0x67, 0x58, 0x4a, 0x3d, 0x32, 0x27, 0x1e, 0x16, 0xf, 0xa, 0x6, 0x2, 0x1};
-#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SINE
-#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE
-static const dacsample_t dac_buffer_triangle[AUDIO_DAC_BUFFER_SIZE] = {
- // 256 values, max 4095
- 0x0, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4a0, 0x4c0, 0x4e0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5a0, 0x5c0, 0x5e0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6a0, 0x6c0, 0x6e0, 0x700, 0x720, 0x740, 0x760, 0x780, 0x7a0, 0x7c0, 0x7e0, 0x800, 0x81f, 0x83f, 0x85f, 0x87f, 0x89f, 0x8bf, 0x8df, 0x8ff, 0x91f, 0x93f, 0x95f, 0x97f, 0x99f, 0x9bf, 0x9df, 0x9ff, 0xa1f, 0xa3f, 0xa5f, 0xa7f, 0xa9f, 0xabf, 0xadf, 0xaff, 0xb1f, 0xb3f, 0xb5f, 0xb7f, 0xb9f, 0xbbf, 0xbdf, 0xbff, 0xc1f, 0xc3f, 0xc5f, 0xc7f, 0xc9f, 0xcbf, 0xcdf, 0xcff, 0xd1f, 0xd3f, 0xd5f, 0xd7f, 0xd9f, 0xdbf, 0xddf, 0xdff, 0xe1f, 0xe3f, 0xe5f, 0xe7f, 0xe9f, 0xebf, 0xedf, 0xeff, 0xf1f, 0xf3f, 0xf5f, 0xf7f, 0xf9f, 0xfbf, 0xfdf,
- 0xfff, 0xfdf, 0xfbf, 0xf9f, 0xf7f, 0xf5f, 0xf3f, 0xf1f, 0xeff, 0xedf, 0xebf, 0xe9f, 0xe7f, 0xe5f, 0xe3f, 0xe1f, 0xdff, 0xddf, 0xdbf, 0xd9f, 0xd7f, 0xd5f, 0xd3f, 0xd1f, 0xcff, 0xcdf, 0xcbf, 0xc9f, 0xc7f, 0xc5f, 0xc3f, 0xc1f, 0xbff, 0xbdf, 0xbbf, 0xb9f, 0xb7f, 0xb5f, 0xb3f, 0xb1f, 0xaff, 0xadf, 0xabf, 0xa9f, 0xa7f, 0xa5f, 0xa3f, 0xa1f, 0x9ff, 0x9df, 0x9bf, 0x99f, 0x97f, 0x95f, 0x93f, 0x91f, 0x8ff, 0x8df, 0x8bf, 0x89f, 0x87f, 0x85f, 0x83f, 0x81f, 0x800, 0x7e0, 0x7c0, 0x7a0, 0x780, 0x760, 0x740, 0x720, 0x700, 0x6e0, 0x6c0, 0x6a0, 0x680, 0x660, 0x640, 0x620, 0x600, 0x5e0, 0x5c0, 0x5a0, 0x580, 0x560, 0x540, 0x520, 0x500, 0x4e0, 0x4c0, 0x4a0, 0x480, 0x460, 0x440, 0x420, 0x400, 0x3e0, 0x3c0, 0x3a0, 0x380, 0x360, 0x340, 0x320, 0x300, 0x2e0, 0x2c0, 0x2a0, 0x280, 0x260, 0x240, 0x220, 0x200, 0x1e0, 0x1c0, 0x1a0, 0x180, 0x160, 0x140, 0x120, 0x100, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20};
-#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE
-#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE
-static const dacsample_t dac_buffer_square[AUDIO_DAC_BUFFER_SIZE] = {
- [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = 0, // first and
- [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, // second half
-};
-#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE
-/*
-// four steps: 0, 1/3, 2/3 and 1
-static const dacsample_t dac_buffer_staircase[AUDIO_DAC_BUFFER_SIZE] = {
- [0 ... AUDIO_DAC_BUFFER_SIZE/3 -1 ] = 0,
- [AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE / 2 -1 ] = AUDIO_DAC_SAMPLE_MAX / 3,
- [AUDIO_DAC_BUFFER_SIZE / 2 ... 3 * AUDIO_DAC_BUFFER_SIZE / 4 -1 ] = 2 * AUDIO_DAC_SAMPLE_MAX / 3,
- [3 * AUDIO_DAC_BUFFER_SIZE / 4 ... AUDIO_DAC_BUFFER_SIZE -1 ] = AUDIO_DAC_SAMPLE_MAX,
-}
-*/
-#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID
-static const dacsample_t dac_buffer_trapezoid[AUDIO_DAC_BUFFER_SIZE] = {0x0, 0x1f, 0x7f, 0xdf, 0x13f, 0x19f, 0x1ff, 0x25f, 0x2bf, 0x31f, 0x37f, 0x3df, 0x43f, 0x49f, 0x4ff, 0x55f, 0x5bf, 0x61f, 0x67f, 0x6df, 0x73f, 0x79f, 0x7ff, 0x85f, 0x8bf, 0x91f, 0x97f, 0x9df, 0xa3f, 0xa9f, 0xaff, 0xb5f, 0xbbf, 0xc1f, 0xc7f, 0xcdf, 0xd3f, 0xd9f, 0xdff, 0xe5f, 0xebf, 0xf1f, 0xf7f, 0xfdf, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
- 0xfff, 0xfdf, 0xf7f, 0xf1f, 0xebf, 0xe5f, 0xdff, 0xd9f, 0xd3f, 0xcdf, 0xc7f, 0xc1f, 0xbbf, 0xb5f, 0xaff, 0xa9f, 0xa3f, 0x9df, 0x97f, 0x91f, 0x8bf, 0x85f, 0x7ff, 0x79f, 0x73f, 0x6df, 0x67f, 0x61f, 0x5bf, 0x55f, 0x4ff, 0x49f, 0x43f, 0x3df, 0x37f, 0x31f, 0x2bf, 0x25f, 0x1ff, 0x19f, 0x13f, 0xdf, 0x7f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID
-
-static dacsample_t dac_buffer_empty[AUDIO_DAC_BUFFER_SIZE] = {AUDIO_DAC_OFF_VALUE};
-
-/* keep track of the sample position for for each frequency */
-static float dac_if[AUDIO_MAX_SIMULTANEOUS_TONES] = {0.0};
-
-static float active_tones_snapshot[AUDIO_MAX_SIMULTANEOUS_TONES] = {0, 0};
-static uint8_t active_tones_snapshot_length = 0;
-
-typedef enum {
- OUTPUT_SHOULD_START,
- OUTPUT_RUN_NORMALLY,
- // path 1: wait for zero, then change/update active tones
- OUTPUT_TONES_CHANGED,
- OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE,
- // path 2: hardware should stop, wait for zero then turn output off = stop the timer
- OUTPUT_SHOULD_STOP,
- OUTPUT_REACHED_ZERO_BEFORE_OFF,
- OUTPUT_OFF,
- OUTPUT_OFF_1,
- OUTPUT_OFF_2, // trailing off: giving the DAC two more conversion cycles until the AUDIO_DAC_OFF_VALUE reaches the output, then turn the timer off, which leaves the output at that level
- number_of_output_states
-} output_states_t;
-output_states_t state = OUTPUT_OFF_2;
-
-/**
- * Generation of the waveform being passed to the callback. Declared weak so users
- * can override it with their own wave-forms/noises.
- */
-__attribute__((weak)) uint16_t dac_value_generate(void) {
- // DAC is running/asking for values but snapshot length is zero -> must be playing a pause
- if (active_tones_snapshot_length == 0) {
- return AUDIO_DAC_OFF_VALUE;
- }
-
- /* doing additive wave synthesis over all currently playing tones = adding up
- * sine-wave-samples for each frequency, scaled by the number of active tones
- */
- uint16_t value = 0;
- float frequency = 0.0f;
-
- for (uint8_t i = 0; i < active_tones_snapshot_length; i++) {
- /* Note: a user implementation does not have to rely on the active_tones_snapshot, but
- * could directly query the active frequencies through audio_get_processed_frequency */
- frequency = active_tones_snapshot[i];
-
- dac_if[i] = dac_if[i] + ((frequency * AUDIO_DAC_BUFFER_SIZE) / AUDIO_DAC_SAMPLE_RATE) * 2 / 3;
- /*Note: the 2/3 are necessary to get the correct frequencies on the
- * DAC output (as measured with an oscilloscope), since the gpt
- * timer runs with 3*AUDIO_DAC_SAMPLE_RATE; and the DAC callback
- * is called twice per conversion.*/
-
- dac_if[i] = fmod(dac_if[i], AUDIO_DAC_BUFFER_SIZE);
-
- // Wavetable generation/lookup
- uint16_t dac_i = (uint16_t)dac_if[i];
-
-#if defined(AUDIO_DAC_SAMPLE_WAVEFORM_SINE)
- value += dac_buffer_sine[dac_i] / active_tones_snapshot_length;
-#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE)
- value += dac_buffer_triangle[dac_i] / active_tones_snapshot_length;
-#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID)
- value += dac_buffer_trapezoid[dac_i] / active_tones_snapshot_length;
-#elif defined(AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE)
- value += dac_buffer_square[dac_i] / active_tones_snapshot_length;
-#endif
- /*
- // SINE
- value += dac_buffer_sine[dac_i] / active_tones_snapshot_length / 3;
- // TRIANGLE
- value += dac_buffer_triangle[dac_i] / active_tones_snapshot_length / 3;
- // SQUARE
- value += dac_buffer_square[dac_i] / active_tones_snapshot_length / 3;
- //NOTE: combination of these three wave-forms is more exemplary - and doesn't sound particularly good :-P
- */
-
- // STAIRS (mostly usefully as test-pattern)
- // value_avg = dac_buffer_staircase[dac_i] / active_tones_snapshot_length;
- }
-
- return value;
-}
-
-/**
- * DAC streaming callback. Does all of the main computing for playing songs.
- *
- * Note: chibios calls this CB twice: during the 'half buffer event', and the 'full buffer event'.
- */
-static void dac_end(DACDriver *dacp) {
- dacsample_t *sample_p = (dacp)->samples;
-
- // work on the other half of the buffer
- if (dacIsBufferComplete(dacp)) {
- sample_p += AUDIO_DAC_BUFFER_SIZE / 2; // 'half_index'
- }
-
- for (uint8_t s = 0; s < AUDIO_DAC_BUFFER_SIZE / 2; s++) {
- if (OUTPUT_OFF <= state) {
- sample_p[s] = AUDIO_DAC_OFF_VALUE;
- continue;
- } else {
- sample_p[s] = dac_value_generate();
- }
-
- /* zero crossing (or approach, whereas zero == DAC_OFF_VALUE, which can be configured to anything from 0 to DAC_SAMPLE_MAX)
- * ============================*=*========================== AUDIO_DAC_SAMPLE_MAX
- * * *
- * * *
- * ---------------------------------------------------------
- * * * } AUDIO_DAC_SAMPLE_MAX/100
- * --------------------------------------------------------- AUDIO_DAC_OFF_VALUE
- * * * } AUDIO_DAC_SAMPLE_MAX/100
- * ---------------------------------------------------------
- * *
- * * *
- * * *
- * =====*=*================================================= 0x0
- */
- if (((sample_p[s] + (AUDIO_DAC_SAMPLE_MAX / 100)) > AUDIO_DAC_OFF_VALUE) && // value approaches from below
- (sample_p[s] < (AUDIO_DAC_OFF_VALUE + (AUDIO_DAC_SAMPLE_MAX / 100))) // or above
- ) {
- if ((OUTPUT_SHOULD_START == state) && (active_tones_snapshot_length > 0)) {
- state = OUTPUT_RUN_NORMALLY;
- } else if (OUTPUT_TONES_CHANGED == state) {
- state = OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE;
- } else if (OUTPUT_SHOULD_STOP == state) {
- state = OUTPUT_REACHED_ZERO_BEFORE_OFF;
- }
- }
-
- // still 'ramping up', reset the output to OFF_VALUE until the generated values reach that value, to do a smooth handover
- if (OUTPUT_SHOULD_START == state) {
- sample_p[s] = AUDIO_DAC_OFF_VALUE;
- }
-
- if ((OUTPUT_SHOULD_START == state) || (OUTPUT_REACHED_ZERO_BEFORE_OFF == state) || (OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE == state)) {
- uint8_t active_tones = MIN(AUDIO_MAX_SIMULTANEOUS_TONES, audio_get_number_of_active_tones());
- active_tones_snapshot_length = 0;
- // update the snapshot - once, and only on occasion that something changed;
- // -> saves cpu cycles (?)
- for (uint8_t i = 0; i < active_tones; i++) {
- float freq = audio_get_processed_frequency(i);
- if (freq > 0) { // disregard 'rest' notes, with valid frequency 0.0f; which would only lower the resulting waveform volume during the additive synthesis step
- active_tones_snapshot[active_tones_snapshot_length++] = freq;
- }
- }
-
- if ((0 == active_tones_snapshot_length) && (OUTPUT_REACHED_ZERO_BEFORE_OFF == state)) {
- state = OUTPUT_OFF;
- }
- if (OUTPUT_REACHED_ZERO_BEFORE_TONE_CHANGE == state) {
- state = OUTPUT_RUN_NORMALLY;
- }
- }
- }
-
- // update audio internal state (note position, current_note, ...)
- if (audio_update_state()) {
- if (OUTPUT_SHOULD_STOP != state) {
- state = OUTPUT_TONES_CHANGED;
- }
- }
-
- if (OUTPUT_OFF <= state) {
- if (OUTPUT_OFF_2 == state) {
- // stopping timer6 = stopping the DAC at whatever value it is currently pushing to the output = AUDIO_DAC_OFF_VALUE
- gptStopTimer(&GPTD6);
- } else {
- state++;
- }
- }
-}
-
-static void dac_error(DACDriver *dacp, dacerror_t err) {
- (void)dacp;
- (void)err;
-
- chSysHalt("DAC failure. halp");
-}
-
-static const GPTConfig gpt6cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE * 3,
- .callback = NULL,
- .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */
- .dier = 0U};
-
-static const DACConfig dac_conf = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT};
-
-/**
- * @note The DAC_TRG(0) here selects the Timer 6 TRGO event, which is triggered
- * on the rising edge after 3 APB1 clock cycles, causing our gpt6cfg1.frequency
- * to be a third of what we expect.
- *
- * Here are all the values for DAC_TRG (TSEL in the ref manual)
- * TIM15_TRGO 0b011
- * TIM2_TRGO 0b100
- * TIM3_TRGO 0b001
- * TIM6_TRGO 0b000
- * TIM7_TRGO 0b010
- * EXTI9 0b110
- * SWTRIG 0b111
- */
-static const DACConversionGroup dac_conv_cfg = {.num_channels = 1U, .end_cb = dac_end, .error_cb = dac_error, .trigger = DAC_TRG(0b000)};
-
-void audio_driver_initialize() {
- if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) {
- palSetLineMode(A4, PAL_MODE_INPUT_ANALOG);
- dacStart(&DACD1, &dac_conf);
- }
- if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) {
- palSetLineMode(A5, PAL_MODE_INPUT_ANALOG);
- dacStart(&DACD2, &dac_conf);
- }
-
- /* enable the output buffer, to directly drive external loads with no additional circuitry
- *
- * see: AN4566 Application note: Extending the DAC performance of STM32 microcontrollers
- * Note: Buffer-Off bit -> has to be set 0 to enable the output buffer
- * Note: enabling the output buffer imparts an additional dc-offset of a couple mV
- *
- * this is done here, reaching directly into the stm32 registers since chibios has not implemented BOFF handling yet
- * (see: chibios/os/hal/ports/STM32/todo.txt '- BOFF handling in DACv1.'
- */
- DACD1.params->dac->CR &= ~DAC_CR_BOFF1;
- DACD2.params->dac->CR &= ~DAC_CR_BOFF2;
-
- if (AUDIO_PIN == A4) {
- dacStartConversion(&DACD1, &dac_conv_cfg, dac_buffer_empty, AUDIO_DAC_BUFFER_SIZE);
- } else if (AUDIO_PIN == A5) {
- dacStartConversion(&DACD2, &dac_conv_cfg, dac_buffer_empty, AUDIO_DAC_BUFFER_SIZE);
- }
-
- // no inverted/out-of-phase waveform (yet?), only pulling AUDIO_PIN_ALT to AUDIO_DAC_OFF_VALUE
-#if defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- if (AUDIO_PIN_ALT == A4) {
- dacPutChannelX(&DACD1, 0, AUDIO_DAC_OFF_VALUE);
- } else if (AUDIO_PIN_ALT == A5) {
- dacPutChannelX(&DACD2, 0, AUDIO_DAC_OFF_VALUE);
- }
-#endif
-
- gptStart(&GPTD6, &gpt6cfg1);
-}
-
-void audio_driver_stop(void) { state = OUTPUT_SHOULD_STOP; }
-
-void audio_driver_start(void) {
- gptStartContinuous(&GPTD6, 2U);
-
- for (uint8_t i = 0; i < AUDIO_MAX_SIMULTANEOUS_TONES; i++) {
- dac_if[i] = 0.0f;
- active_tones_snapshot[i] = 0.0f;
- }
- active_tones_snapshot_length = 0;
- state = OUTPUT_SHOULD_START;
-}
diff --git a/quantum/audio/driver_chibios_dac_basic.c b/quantum/audio/driver_chibios_dac_basic.c
deleted file mode 100644
index fac6513506..0000000000
--- a/quantum/audio/driver_chibios_dac_basic.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/* Copyright 2016-2020 Jack Humbert
- * Copyright 2020 JohSchneider
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "audio.h"
-#include "ch.h"
-#include "hal.h"
-
-/*
- Audio Driver: DAC
-
- which utilizes both channels of the DAC unit many STM32 are equipped with to output a modulated square-wave, from precomputed samples stored in a buffer, which is passed to the hardware through DMA
-
- this driver can either be used to drive to separate speakers, wired to A4+Gnd and A5+Gnd, which allows two tones to be played simultaneously
- OR
- one speaker wired to A4+A5 with the AUDIO_PIN_ALT_AS_NEGATIVE define set - see docs/feature_audio
-
-*/
-
-#if !defined(AUDIO_PIN)
-# pragma message "Audio feature enabled, but no suitable pin selected as AUDIO_PIN - see docs/feature_audio under 'ARM (DAC basic)' for available options."
-// TODO: make this an 'error' instead; go through a breaking change, and add AUDIO_PIN A5 to all keyboards currently using AUDIO on STM32 based boards? - for now: set the define here
-# define AUDIO_PIN A5
-#endif
-// check configuration for ONE speaker, connected to both DAC pins
-#if defined(AUDIO_PIN_ALT_AS_NEGATIVE) && !defined(AUDIO_PIN_ALT)
-# error "Audio feature: AUDIO_PIN_ALT_AS_NEGATIVE set, but no pin configured as AUDIO_PIN_ALT"
-#endif
-
-#ifndef AUDIO_PIN_ALT
-// no ALT pin defined is valid, but the c-ifs below need some value set
-# define AUDIO_PIN_ALT -1
-#endif
-
-#if !defined(AUDIO_STATE_TIMER)
-# define AUDIO_STATE_TIMER GPTD8
-#endif
-
-// square-wave
-static const dacsample_t dac_buffer_1[AUDIO_DAC_BUFFER_SIZE] = {
- // First half is max, second half is 0
- [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = AUDIO_DAC_SAMPLE_MAX,
- [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = 0,
-};
-
-// square-wave
-static const dacsample_t dac_buffer_2[AUDIO_DAC_BUFFER_SIZE] = {
- // opposite of dac_buffer above
- [0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = 0,
- [AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX,
-};
-
-GPTConfig gpt6cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE,
- .callback = NULL,
- .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */
- .dier = 0U};
-GPTConfig gpt7cfg1 = {.frequency = AUDIO_DAC_SAMPLE_RATE,
- .callback = NULL,
- .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */
- .dier = 0U};
-
-static void gpt_audio_state_cb(GPTDriver *gptp);
-GPTConfig gptStateUpdateCfg = {.frequency = 10,
- .callback = gpt_audio_state_cb,
- .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */
- .dier = 0U};
-
-static const DACConfig dac_conf_ch1 = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT};
-static const DACConfig dac_conf_ch2 = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_DHRM_12BIT_RIGHT};
-
-/**
- * @note The DAC_TRG(0) here selects the Timer 6 TRGO event, which is triggered
- * on the rising edge after 3 APB1 clock cycles, causing our gpt6cfg1.frequency
- * to be a third of what we expect.
- *
- * Here are all the values for DAC_TRG (TSEL in the ref manual)
- * TIM15_TRGO 0b011
- * TIM2_TRGO 0b100
- * TIM3_TRGO 0b001
- * TIM6_TRGO 0b000
- * TIM7_TRGO 0b010
- * EXTI9 0b110
- * SWTRIG 0b111
- */
-static const DACConversionGroup dac_conv_grp_ch1 = {.num_channels = 1U, .trigger = DAC_TRG(0b000)};
-static const DACConversionGroup dac_conv_grp_ch2 = {.num_channels = 1U, .trigger = DAC_TRG(0b010)};
-
-void channel_1_start(void) {
- gptStart(&GPTD6, &gpt6cfg1);
- gptStartContinuous(&GPTD6, 2U);
- palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG);
-}
-
-void channel_1_stop(void) {
- gptStopTimer(&GPTD6);
- palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL);
- palSetPad(GPIOA, 4);
-}
-
-static float channel_1_frequency = 0.0f;
-void channel_1_set_frequency(float freq) {
- channel_1_frequency = freq;
-
- channel_1_stop();
- if (freq <= 0.0) // a pause/rest has freq=0
- return;
-
- gpt6cfg1.frequency = 2 * freq * AUDIO_DAC_BUFFER_SIZE;
- channel_1_start();
-}
-float channel_1_get_frequency(void) { return channel_1_frequency; }
-
-void channel_2_start(void) {
- gptStart(&GPTD7, &gpt7cfg1);
- gptStartContinuous(&GPTD7, 2U);
- palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG);
-}
-
-void channel_2_stop(void) {
- gptStopTimer(&GPTD7);
- palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL);
- palSetPad(GPIOA, 5);
-}
-
-static float channel_2_frequency = 0.0f;
-void channel_2_set_frequency(float freq) {
- channel_2_frequency = freq;
-
- channel_2_stop();
- if (freq <= 0.0) // a pause/rest has freq=0
- return;
-
- gpt7cfg1.frequency = 2 * freq * AUDIO_DAC_BUFFER_SIZE;
- channel_2_start();
-}
-float channel_2_get_frequency(void) { return channel_2_frequency; }
-
-static void gpt_audio_state_cb(GPTDriver *gptp) {
- if (audio_update_state()) {
-#if defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- // one piezo/speaker connected to both audio pins, the generated square-waves are inverted
- channel_1_set_frequency(audio_get_processed_frequency(0));
- channel_2_set_frequency(audio_get_processed_frequency(0));
-
-#else // two separate audio outputs/speakers
- // primary speaker on A4, optional secondary on A5
- if (AUDIO_PIN == A4) {
- channel_1_set_frequency(audio_get_processed_frequency(0));
- if (AUDIO_PIN_ALT == A5) {
- if (audio_get_number_of_active_tones() > 1) {
- channel_2_set_frequency(audio_get_processed_frequency(1));
- } else {
- channel_2_stop();
- }
- }
- }
-
- // primary speaker on A5, optional secondary on A4
- if (AUDIO_PIN == A5) {
- channel_2_set_frequency(audio_get_processed_frequency(0));
- if (AUDIO_PIN_ALT == A4) {
- if (audio_get_number_of_active_tones() > 1) {
- channel_1_set_frequency(audio_get_processed_frequency(1));
- } else {
- channel_1_stop();
- }
- }
- }
-#endif
- }
-}
-
-void audio_driver_initialize() {
- if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) {
- palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG);
- dacStart(&DACD1, &dac_conf_ch1);
-
- // initial setup of the dac-triggering timer is still required, even
- // though it gets reconfigured and restarted later on
- gptStart(&GPTD6, &gpt6cfg1);
- }
-
- if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) {
- palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG);
- dacStart(&DACD2, &dac_conf_ch2);
-
- gptStart(&GPTD7, &gpt7cfg1);
- }
-
- /* enable the output buffer, to directly drive external loads with no additional circuitry
- *
- * see: AN4566 Application note: Extending the DAC performance of STM32 microcontrollers
- * Note: Buffer-Off bit -> has to be set 0 to enable the output buffer
- * Note: enabling the output buffer imparts an additional dc-offset of a couple mV
- *
- * this is done here, reaching directly into the stm32 registers since chibios has not implemented BOFF handling yet
- * (see: chibios/os/hal/ports/STM32/todo.txt '- BOFF handling in DACv1.'
- */
- DACD1.params->dac->CR &= ~DAC_CR_BOFF1;
- DACD2.params->dac->CR &= ~DAC_CR_BOFF2;
-
- // start state-updater
- gptStart(&AUDIO_STATE_TIMER, &gptStateUpdateCfg);
-}
-
-void audio_driver_stop(void) {
- if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) {
- gptStopTimer(&GPTD6);
-
- // stop the ongoing conversion and put the output in a known state
- dacStopConversion(&DACD1);
- dacPutChannelX(&DACD1, 0, AUDIO_DAC_OFF_VALUE);
- }
-
- if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) {
- gptStopTimer(&GPTD7);
-
- dacStopConversion(&DACD2);
- dacPutChannelX(&DACD2, 0, AUDIO_DAC_OFF_VALUE);
- }
- gptStopTimer(&AUDIO_STATE_TIMER);
-}
-
-void audio_driver_start(void) {
- if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) {
- dacStartConversion(&DACD1, &dac_conv_grp_ch1, (dacsample_t *)dac_buffer_1, AUDIO_DAC_BUFFER_SIZE);
- }
- if ((AUDIO_PIN == A5) || (AUDIO_PIN_ALT == A5)) {
- dacStartConversion(&DACD2, &dac_conv_grp_ch2, (dacsample_t *)dac_buffer_2, AUDIO_DAC_BUFFER_SIZE);
- }
- gptStartContinuous(&AUDIO_STATE_TIMER, 2U);
-}
diff --git a/quantum/audio/driver_chibios_pwm.h b/quantum/audio/driver_chibios_pwm.h
deleted file mode 100644
index 86cab916e1..0000000000
--- a/quantum/audio/driver_chibios_pwm.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright 2020 Jack Humbert
- * Copyright 2020 JohSchneider
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-
-#if !defined(AUDIO_PWM_DRIVER)
-// NOTE: Timer2 seems to be used otherwise in QMK, otherwise we could default to A5 (= TIM2_CH1, with PWMD2 and alternate-function(1))
-# define AUDIO_PWM_DRIVER PWMD1
-#endif
-
-#if !defined(AUDIO_PWM_CHANNEL)
-// NOTE: sticking to the STM data-sheet numbering: TIMxCH1 to TIMxCH4
-// default: STM32F303CC PA8+TIM1_CH1 -> 1
-# define AUDIO_PWM_CHANNEL 1
-#endif
-
-#if !defined(AUDIO_PWM_PAL_MODE)
-// pin-alternate function: see the data-sheet for which pin needs what AF to connect to TIMx_CHy
-// default: STM32F303CC PA8+TIM1_CH1 -> 6
-# define AUDIO_PWM_PAL_MODE 6
-#endif
-
-#if !defined(AUDIO_STATE_TIMER)
-// timer used to trigger updates in the audio-system, configured/enabled in chibios mcuconf.
-// Tim6 is the default for "larger" STMs, smaller ones might not have this one (enabled) and need to switch to a different one (e.g.: STM32F103 has only Tim1-Tim4)
-# define AUDIO_STATE_TIMER GPTD6
-#endif
diff --git a/quantum/audio/driver_chibios_pwm_hardware.c b/quantum/audio/driver_chibios_pwm_hardware.c
deleted file mode 100644
index 3c7d89b290..0000000000
--- a/quantum/audio/driver_chibios_pwm_hardware.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Copyright 2020 Jack Humbert
- * Copyright 2020 JohSchneider
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-Audio Driver: PWM
-
-the duty-cycle is always kept at 50%, and the pwm-period is adjusted to match the frequency of a note to be played back.
-
-this driver uses the chibios-PWM system to produce a square-wave on specific output pins that are connected to the PWM hardware.
-The hardware directly toggles the pin via its alternate function. see your MCUs data-sheet for which pin can be driven by what timer - looking for TIMx_CHy and the corresponding alternate function.
-
- */
-
-#include "audio.h"
-#include "ch.h"
-#include "hal.h"
-
-#if !defined(AUDIO_PIN)
-# error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings"
-#endif
-
-extern bool playing_note;
-extern bool playing_melody;
-extern uint8_t note_timbre;
-
-static PWMConfig pwmCFG = {
- .frequency = 100000, /* PWM clock frequency */
- // CHIBIOS-BUG? can't set the initial period to <2, or the pwm (hard or software) takes ~130ms with .frequency=500000 for a pwmChangePeriod to take effect; with no output=silence in the meantime
- .period = 2, /* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */
- .callback = NULL, /* no callback, the hardware directly toggles the pin */
- .channels =
- {
-#if AUDIO_PWM_CHANNEL == 4
- {PWM_OUTPUT_DISABLED, NULL}, /* channel 0 -> TIMx_CH1 */
- {PWM_OUTPUT_DISABLED, NULL}, /* channel 1 -> TIMx_CH2 */
- {PWM_OUTPUT_DISABLED, NULL}, /* channel 2 -> TIMx_CH3 */
- {PWM_OUTPUT_ACTIVE_HIGH, NULL} /* channel 3 -> TIMx_CH4 */
-#elif AUDIO_PWM_CHANNEL == 3
- {PWM_OUTPUT_DISABLED, NULL},
- {PWM_OUTPUT_DISABLED, NULL},
- {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH3 */
- {PWM_OUTPUT_DISABLED, NULL}
-#elif AUDIO_PWM_CHANNEL == 2
- {PWM_OUTPUT_DISABLED, NULL},
- {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH2 */
- {PWM_OUTPUT_DISABLED, NULL},
- {PWM_OUTPUT_DISABLED, NULL}
-#else /*fallback to CH1 */
- {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH1 */
- {PWM_OUTPUT_DISABLED, NULL},
- {PWM_OUTPUT_DISABLED, NULL},
- {PWM_OUTPUT_DISABLED, NULL}
-#endif
- },
-};
-
-static float channel_1_frequency = 0.0f;
-void channel_1_set_frequency(float freq) {
- channel_1_frequency = freq;
-
- if (freq <= 0.0) // a pause/rest has freq=0
- return;
-
- pwmcnt_t period = (pwmCFG.frequency / freq);
- pwmChangePeriod(&AUDIO_PWM_DRIVER, period);
- pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1,
- // adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH
- PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100));
-}
-
-float channel_1_get_frequency(void) { return channel_1_frequency; }
-
-void channel_1_start(void) {
- pwmStop(&AUDIO_PWM_DRIVER);
- pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
-}
-
-void channel_1_stop(void) { pwmStop(&AUDIO_PWM_DRIVER); }
-
-static void gpt_callback(GPTDriver *gptp);
-GPTConfig gptCFG = {
- /* a whole note is one beat, which is - per definition in musical_notes.h - set to 64
- the longest note is BREAVE_DOT=128+64=192, the shortest SIXTEENTH=4
- the tempo (which might vary!) is in bpm (beats per minute)
- therefore: if the timer ticks away at .frequency = (60*64)Hz,
- and the .interval counts from 64 downwards - audio_update_state is
- called just often enough to not miss any notes
- */
- .frequency = 60 * 64,
- .callback = gpt_callback,
-};
-
-void audio_driver_initialize(void) {
- pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
-
- // connect the AUDIO_PIN to the PWM hardware
-#if defined(USE_GPIOV1) // STM32F103C8
- palSetLineMode(AUDIO_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-#else // GPIOv2 (or GPIOv3 for f4xx, which is the same/compatible at this command)
- palSetLineMode(AUDIO_PIN, PAL_STM32_MODE_ALTERNATE | PAL_STM32_ALTERNATE(AUDIO_PWM_PAL_MODE));
-#endif
-
- gptStart(&AUDIO_STATE_TIMER, &gptCFG);
-}
-
-void audio_driver_start(void) {
- channel_1_stop();
- channel_1_start();
-
- if (playing_note || playing_melody) {
- gptStartContinuous(&AUDIO_STATE_TIMER, 64);
- }
-}
-
-void audio_driver_stop(void) {
- channel_1_stop();
- gptStopTimer(&AUDIO_STATE_TIMER);
-}
-
-/* a regular timer task, that checks the note to be currently played
- * and updates the pwm to output that frequency
- */
-static void gpt_callback(GPTDriver *gptp) {
- float freq; // TODO: freq_alt
-
- if (audio_update_state()) {
- freq = audio_get_processed_frequency(0); // freq_alt would be index=1
- channel_1_set_frequency(freq);
- }
-}
diff --git a/quantum/audio/driver_chibios_pwm_software.c b/quantum/audio/driver_chibios_pwm_software.c
deleted file mode 100644
index 15c3e98b6a..0000000000
--- a/quantum/audio/driver_chibios_pwm_software.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Copyright 2020 Jack Humbert
- * Copyright 2020 JohSchneider
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-Audio Driver: PWM
-
-the duty-cycle is always kept at 50%, and the pwm-period is adjusted to match the frequency of a note to be played back.
-
-this driver uses the chibios-PWM system to produce a square-wave on any given output pin in software
-- a pwm callback is used to set/clear the configured pin.
-
- */
-#include "audio.h"
-#include "ch.h"
-#include "hal.h"
-
-#if !defined(AUDIO_PIN)
-# error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings"
-#endif
-extern bool playing_note;
-extern bool playing_melody;
-extern uint8_t note_timbre;
-
-static void pwm_audio_period_callback(PWMDriver *pwmp);
-static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp);
-
-static PWMConfig pwmCFG = {
- .frequency = 100000, /* PWM clock frequency */
- // CHIBIOS-BUG? can't set the initial period to <2, or the pwm (hard or software) takes ~130ms with .frequency=500000 for a pwmChangePeriod to take effect; with no output=silence in the meantime
- .period = 2, /* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */
- .callback = pwm_audio_period_callback,
- .channels =
- {
- // software-PWM just needs another callback on any channel
- {PWM_OUTPUT_ACTIVE_HIGH, pwm_audio_channel_interrupt_callback}, /* channel 0 -> TIMx_CH1 */
- {PWM_OUTPUT_DISABLED, NULL}, /* channel 1 -> TIMx_CH2 */
- {PWM_OUTPUT_DISABLED, NULL}, /* channel 2 -> TIMx_CH3 */
- {PWM_OUTPUT_DISABLED, NULL} /* channel 3 -> TIMx_CH4 */
- },
-};
-
-static float channel_1_frequency = 0.0f;
-void channel_1_set_frequency(float freq) {
- channel_1_frequency = freq;
-
- if (freq <= 0.0) // a pause/rest has freq=0
- return;
-
- pwmcnt_t period = (pwmCFG.frequency / freq);
- pwmChangePeriod(&AUDIO_PWM_DRIVER, period);
-
- pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1,
- // adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH
- PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100));
-}
-
-float channel_1_get_frequency(void) { return channel_1_frequency; }
-
-void channel_1_start(void) {
- pwmStop(&AUDIO_PWM_DRIVER);
- pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
-
- pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER);
- pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1);
-}
-
-void channel_1_stop(void) {
- pwmStop(&AUDIO_PWM_DRIVER);
-
- palClearLine(AUDIO_PIN); // leave the line low, after last note was played
-
-#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- palClearLine(AUDIO_PIN_ALT); // leave the line low, after last note was played
-#endif
-}
-
-// generate a PWM signal on any pin, not necessarily the one connected to the timer
-static void pwm_audio_period_callback(PWMDriver *pwmp) {
- (void)pwmp;
- palClearLine(AUDIO_PIN);
-
-#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- palSetLine(AUDIO_PIN_ALT);
-#endif
-}
-static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp) {
- (void)pwmp;
- if (channel_1_frequency > 0) {
- palSetLine(AUDIO_PIN); // generate a PWM signal on any pin, not necessarily the one connected to the timer
-#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- palClearLine(AUDIO_PIN_ALT);
-#endif
- }
-}
-
-static void gpt_callback(GPTDriver *gptp);
-GPTConfig gptCFG = {
- /* a whole note is one beat, which is - per definition in musical_notes.h - set to 64
- the longest note is BREAVE_DOT=128+64=192, the shortest SIXTEENTH=4
- the tempo (which might vary!) is in bpm (beats per minute)
- therefore: if the timer ticks away at .frequency = (60*64)Hz,
- and the .interval counts from 64 downwards - audio_update_state is
- called just often enough to not miss anything
- */
- .frequency = 60 * 64,
- .callback = gpt_callback,
-};
-
-void audio_driver_initialize(void) {
- pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
-
- palSetLineMode(AUDIO_PIN, PAL_MODE_OUTPUT_PUSHPULL);
- palClearLine(AUDIO_PIN);
-
-#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- palSetLineMode(AUDIO_PIN_ALT, PAL_MODE_OUTPUT_PUSHPULL);
- palClearLine(AUDIO_PIN_ALT);
-#endif
-
- pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER); // enable pwm callbacks
- pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1);
-
- gptStart(&AUDIO_STATE_TIMER, &gptCFG);
-}
-
-void audio_driver_start(void) {
- channel_1_stop();
- channel_1_start();
-
- if (playing_note || playing_melody) {
- gptStartContinuous(&AUDIO_STATE_TIMER, 64);
- }
-}
-
-void audio_driver_stop(void) {
- channel_1_stop();
- gptStopTimer(&AUDIO_STATE_TIMER);
-}
-
-/* a regular timer task, that checks the note to be currently played
- * and updates the pwm to output that frequency
- */
-static void gpt_callback(GPTDriver *gptp) {
- float freq; // TODO: freq_alt
-
- if (audio_update_state()) {
- freq = audio_get_processed_frequency(0); // freq_alt would be index=1
- channel_1_set_frequency(freq);
- }
-}
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h
index b54b397e1c..8e80a016aa 100644
--- a/quantum/audio/song_list.h
+++ b/quantum/audio/song_list.h
@@ -20,11 +20,9 @@
#include "musical_notes.h"
-#if __GNUC__ > 5 // don't use for older gcc compilers since check isn't supported.
-# if __has_include("user_song_list.h")
-# include "user_song_list.h"
-# endif // if file exists
-#endif // __GNUC__
+#if __has_include("user_song_list.h")
+# include "user_song_list.h"
+#endif // if file exists
#define NO_SOUND
diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c
index e47192de34..9c972ae02e 100644
--- a/quantum/backlight/backlight_avr.c
+++ b/quantum/backlight/backlight_avr.c
@@ -199,13 +199,14 @@ static inline void disable_pwm(void) {
// reaches the backlight level, where we turn off the LEDs,
// but also an overflow interrupt when the counter rolls back to 0,
// in which we're going to turn on the LEDs.
-// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz.
+// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz,
+// or F_CPU/BACKLIGHT_CUSTOM_RESOLUTION if used.
// Triggered when the counter reaches the OCRx value
ISR(TIMERx_COMPA_vect) { backlight_pins_off(); }
// Triggered when the counter reaches the TOP value
-// this one triggers at F_CPU/65536 =~ 244 Hz
+// this one triggers at F_CPU/ICRx = 16MHz/65536 =~ 244 Hz
ISR(TIMERx_OVF_vect) {
# ifdef BACKLIGHT_BREATHING
if (is_breathing()) {
@@ -220,7 +221,7 @@ ISR(TIMERx_OVF_vect) {
// artifacts (especially while breathing, because breathing_task
// takes many computation cycles).
// so better not turn them on while the counter TOP is very low.
- if (OCRxx > 256) {
+ if (OCRxx > ICRx / 250 + 5) {
backlight_pins_on();
}
}
@@ -231,24 +232,26 @@ ISR(TIMERx_OVF_vect) {
// See http://jared.geek.nz/2013/feb/linear-led-pwm
static uint16_t cie_lightness(uint16_t v) {
- if (v <= 5243) // if below 8% of max
- return v / 9; // same as dividing by 900%
- else {
- uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
- // to get a useful result with integer division, we shift left in the expression above
- // and revert what we've done again after squaring.
- y = y * y * y >> 8;
- if (y > 0xFFFFUL) // prevent overflow
- return 0xFFFFU;
- else
- return (uint16_t)y;
+ if (v <= (uint32_t)ICRx / 12) // If the value is less than or equal to ~8% of max
+ {
+ return v / 9; // Same as dividing by 900%
+ } else {
+ // In the next two lines values are bit-shifted. This is to avoid loosing decimals in integer math.
+ uint32_t y = (((uint32_t)v + (uint32_t)ICRx / 6) << 5) / ((uint32_t)ICRx / 6 + ICRx); // If above 8%, add ~16% of max, and normalize with (max + ~16% max)
+ uint32_t out = (y * y * y * ICRx) >> 15; // Cube it and undo the bit-shifting. (which is now three times as much due to the cubing)
+
+ if (out > ICRx) // Avoid overflows
+ {
+ out = ICRx;
+ }
+ return (uint16_t)out;
}
}
-// rescale the supplied backlight value to be in terms of the value limit
+// rescale the supplied backlight value to be in terms of the value limit // range for val is [0..ICRx]. PWM pin is high while the timer count is below val.
static uint32_t rescale_limit_val(uint32_t val) { return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256; }
-// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
+// range for val is [0..ICRx]. PWM pin is high while the timer count is below val.
static inline void set_pwm(uint16_t val) { OCRxx = val; }
void backlight_set(uint8_t level) {
@@ -277,7 +280,7 @@ void backlight_set(uint8_t level) {
#endif
}
// Set the brightness
- set_pwm(cie_lightness(rescale_limit_val(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS)));
+ set_pwm(cie_lightness(rescale_limit_val(ICRx * (uint32_t)level / BACKLIGHT_LEVELS)));
}
void backlight_task(void) {}
@@ -292,6 +295,11 @@ void backlight_task(void) {}
static uint8_t breathing_halt = BREATHING_NO_HALT;
static uint16_t breathing_counter = 0;
+static uint8_t breath_scale_counter = 1;
+/* Run the breathing loop at ~120Hz*/
+const uint8_t breathing_ISR_frequency = 120;
+static uint16_t breathing_freq_scale_factor = 2;
+
# ifdef BACKLIGHT_PWM_TIMER
static bool breathing = false;
@@ -323,9 +331,9 @@ bool is_breathing(void) { return !!(TIMSKx & _BV(TOIEx)); }
do { \
breathing_counter = 0; \
} while (0)
-# define breathing_max() \
- do { \
- breathing_counter = get_breathing_period() * 244 / 2; \
+# define breathing_max() \
+ do { \
+ breathing_counter = get_breathing_period() * breathing_ISR_frequency / 2; \
} while (0)
void breathing_enable(void) {
@@ -369,21 +377,30 @@ void breathing_task(void)
# else
/* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
* about 244 times per second.
+ *
+ * The following ISR runs at F_CPU/ISRx. With a 16MHz clock and default pwm resolution, that means 244Hz
*/
ISR(TIMERx_OVF_vect)
# endif
{
- uint8_t breathing_period = get_breathing_period();
- uint16_t interval = (uint16_t)breathing_period * 244 / BREATHING_STEPS;
+
+ // Only run this ISR at ~120 Hz
+ if (breath_scale_counter++ == breathing_freq_scale_factor) {
+ breath_scale_counter = 1;
+ } else {
+ return;
+ }
+ uint16_t interval = (uint16_t)get_breathing_period() * breathing_ISR_frequency / BREATHING_STEPS;
// resetting after one period to prevent ugly reset at overflow.
- breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
+ breathing_counter = (breathing_counter + 1) % (get_breathing_period() * breathing_ISR_frequency);
uint8_t index = breathing_counter / interval % BREATHING_STEPS;
if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) {
breathing_interrupt_disable();
}
- set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * 0x0101U))));
+ // Set PWM to a brightnessvalue scaled to the configured resolution
+ set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * ICRx / 255))));
}
#endif // BACKLIGHT_BREATHING
@@ -413,16 +430,23 @@ void backlight_init_ports(void) {
"In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]."
"In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)."
*/
-# if BACKLIGHT_ON_STATE == 1
- TCCRxA = _BV(COMxx1) | _BV(WGM11);
-# else
- TCCRxA = _BV(COMxx1) | _BV(COMxx0) | _BV(WGM11);
-# endif
-
- TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
+ TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
+ TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
#endif
- // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
+
+#ifdef BACKLIGHT_CUSTOM_RESOLUTION
+# if (BACKLIGHT_CUSTOM_RESOLUTION > 0xFFFF || BACKLIGHT_CUSTOM_RESOLUTION < 1)
+# error "This out of range of the timer capabilities"
+# elif (BACKLIGHT_CUSTOM_RESOLUTION < 0xFF)
+# warning "Resolution lower than 0xFF isn't recommended"
+# endif
+# ifdef BACKLIGHT_BREATHING
+ breathing_freq_scale_factor = F_CPU / BACKLIGHT_CUSTOM_RESOLUTION / 120;
+# endif
+ ICRx = BACKLIGHT_CUSTOM_RESOLUTION;
+#else
ICRx = TIMER_TOP;
+#endif
backlight_init();
#ifdef BACKLIGHT_BREATHING
diff --git a/quantum/backlight/backlight_chibios.c b/quantum/backlight/backlight_chibios.c
index 4d5a69e14e..7c6edd10d6 100644
--- a/quantum/backlight/backlight_chibios.c
+++ b/quantum/backlight/backlight_chibios.c
@@ -8,9 +8,13 @@
# define BACKLIGHT_LIMIT_VAL 255
#endif
-// GPIOV2 && GPIOV3
#ifndef BACKLIGHT_PAL_MODE
-# define BACKLIGHT_PAL_MODE 2
+# if defined(USE_GPIOV1)
+# define BACKLIGHT_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
+# else
+// GPIOV2 && GPIOV3
+# define BACKLIGHT_PAL_MODE 5
+# endif
#endif
// GENERIC
@@ -70,7 +74,7 @@ static uint32_t rescale_limit_val(uint32_t val) {
void backlight_init_ports(void) {
#ifdef USE_GPIOV1
- palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+ palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), BACKLIGHT_PAL_MODE);
#else
palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_ALTERNATE(BACKLIGHT_PAL_MODE));
#endif
diff --git a/quantum/config_common.h b/quantum/config_common.h
index 661609ef2a..d93477b27e 100644
--- a/quantum/config_common.h
+++ b/quantum/config_common.h
@@ -24,7 +24,4 @@
#define COL2ROW 0
#define ROW2COL 1
-// Deprecated alias - avoid using
-#define KEYMAP LAYOUT
-
#include "song_list.h"
diff --git a/quantum/debounce/asym_eager_defer_pk.c b/quantum/debounce/asym_eager_defer_pk.c
index 24380dc5e5..81f39383c4 100644
--- a/quantum/debounce/asym_eager_defer_pk.c
+++ b/quantum/debounce/asym_eager_defer_pk.c
@@ -46,17 +46,17 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
#define ROW_SHIFTER ((matrix_row_t)1)
typedef struct {
- bool pressed : 1;
+ bool pressed : 1;
uint8_t time : 7;
} debounce_counter_t;
#if DEBOUNCE > 0
static debounce_counter_t *debounce_counters;
-static fast_timer_t last_time;
-static bool counters_need_update;
-static bool matrix_need_update;
+static fast_timer_t last_time;
+static bool counters_need_update;
+static bool matrix_need_update;
-#define DEBOUNCE_ELAPSED 0
+# define DEBOUNCE_ELAPSED 0
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
@@ -64,7 +64,7 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
// we use num_rows rather than MATRIX_ROWS to support split keyboards
void debounce_init(uint8_t num_rows) {
debounce_counters = malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t));
- int i = 0;
+ int i = 0;
for (uint8_t r = 0; r < num_rows; r++) {
for (uint8_t c = 0; c < MATRIX_COLS; c++) {
debounce_counters[i++].time = DEBOUNCE_ELAPSED;
@@ -81,10 +81,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
bool updated_last = false;
if (counters_need_update) {
- fast_timer_t now = timer_read_fast();
+ fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
- last_time = now;
+ last_time = now;
updated_last = true;
if (elapsed_time > UINT8_MAX) {
elapsed_time = UINT8_MAX;
@@ -108,7 +108,7 @@ static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[],
debounce_counter_t *debounce_pointer = debounce_counters;
counters_need_update = false;
- matrix_need_update = false;
+ matrix_need_update = false;
for (uint8_t row = 0; row < num_rows; row++) {
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
@@ -146,8 +146,8 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
if (delta & col_mask) {
if (debounce_pointer->time == DEBOUNCE_ELAPSED) {
debounce_pointer->pressed = (raw[row] & col_mask);
- debounce_pointer->time = DEBOUNCE;
- counters_need_update = true;
+ debounce_pointer->time = DEBOUNCE;
+ counters_need_update = true;
if (debounce_pointer->pressed) {
// key-down: eager
diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c
index fbefd55ede..9155eb914c 100644
--- a/quantum/debounce/sym_defer_g.c
+++ b/quantum/debounce/sym_defer_g.c
@@ -25,7 +25,7 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
#endif
#if DEBOUNCE > 0
-static bool debouncing = false;
+static bool debouncing = false;
static fast_timer_t debouncing_time;
void debounce_init(uint8_t num_rows) {}
diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c
index 626a9be841..1b698ba347 100644
--- a/quantum/debounce/sym_defer_pk.c
+++ b/quantum/debounce/sym_defer_pk.c
@@ -49,7 +49,7 @@ static debounce_counter_t *debounce_counters;
static fast_timer_t last_time;
static bool counters_need_update;
-#define DEBOUNCE_ELAPSED 0
+# define DEBOUNCE_ELAPSED 0
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
@@ -74,10 +74,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
bool updated_last = false;
if (counters_need_update) {
- fast_timer_t now = timer_read_fast();
+ fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
- last_time = now;
+ last_time = now;
updated_last = true;
if (elapsed_time > UINT8_MAX) {
elapsed_time = UINT8_MAX;
diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c
index 15a3242e68..9da000ea9a 100644
--- a/quantum/debounce/sym_eager_pk.c
+++ b/quantum/debounce/sym_eager_pk.c
@@ -50,7 +50,7 @@ static fast_timer_t last_time;
static bool counters_need_update;
static bool matrix_need_update;
-#define DEBOUNCE_ELAPSED 0
+# define DEBOUNCE_ELAPSED 0
static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
@@ -75,10 +75,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
bool updated_last = false;
if (counters_need_update) {
- fast_timer_t now = timer_read_fast();
+ fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
- last_time = now;
+ last_time = now;
updated_last = true;
if (elapsed_time > UINT8_MAX) {
elapsed_time = UINT8_MAX;
@@ -107,7 +107,7 @@ static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
if (*debounce_pointer != DEBOUNCE_ELAPSED) {
if (*debounce_pointer <= elapsed_time) {
- *debounce_pointer = DEBOUNCE_ELAPSED;
+ *debounce_pointer = DEBOUNCE_ELAPSED;
matrix_need_update = true;
} else {
*debounce_pointer -= elapsed_time;
diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c
index 2ad592c5a6..eda92a263b 100644
--- a/quantum/debounce/sym_eager_pr.c
+++ b/quantum/debounce/sym_eager_pr.c
@@ -49,7 +49,7 @@ static debounce_counter_t *debounce_counters;
static fast_timer_t last_time;
static bool counters_need_update;
-#define DEBOUNCE_ELAPSED 0
+# define DEBOUNCE_ELAPSED 0
static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
@@ -71,10 +71,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
bool updated_last = false;
if (counters_need_update) {
- fast_timer_t now = timer_read_fast();
+ fast_timer_t now = timer_read_fast();
fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
- last_time = now;
+ last_time = now;
updated_last = true;
if (elapsed_time > UINT8_MAX) {
elapsed_time = UINT8_MAX;
@@ -102,7 +102,7 @@ static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
for (uint8_t row = 0; row < num_rows; row++) {
if (*debounce_pointer != DEBOUNCE_ELAPSED) {
if (*debounce_pointer <= elapsed_time) {
- *debounce_pointer = DEBOUNCE_ELAPSED;
+ *debounce_pointer = DEBOUNCE_ELAPSED;
matrix_need_update = true;
} else {
*debounce_pointer -= elapsed_time;
diff --git a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
index fe374c3dfa..44b4fe1956 100644
--- a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
+++ b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 1ms delay */
{1, {{0, 1, UP}}, {}},
@@ -43,7 +44,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 2ms delay */
{2, {{0, 1, UP}}, {}},
@@ -58,7 +60,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 3ms delay */
{3, {{0, 1, UP}}, {}},
@@ -73,7 +76,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyShort4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 4ms delay */
{4, {{0, 1, UP}}, {}},
@@ -88,7 +92,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
}
TEST_F(DebounceTest, OneKeyShort5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 5ms delay */
@@ -102,7 +107,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
}
TEST_F(DebounceTest, OneKeyShort6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 6ms delay */
@@ -116,7 +122,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
}
TEST_F(DebounceTest, OneKeyShort7) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 7ms delay */
@@ -130,7 +137,8 @@ TEST_F(DebounceTest, OneKeyShort7) {
}
TEST_F(DebounceTest, OneKeyShort8) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 1ms delay */
{1, {{0, 1, UP}}, {}},
@@ -145,7 +153,8 @@ TEST_F(DebounceTest, OneKeyShort8) {
}
TEST_F(DebounceTest, OneKeyShort9) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Release key after 1ms delay */
{1, {{0, 1, UP}}, {}},
@@ -159,7 +168,8 @@ TEST_F(DebounceTest, OneKeyShort9) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -185,7 +195,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Change twice in the same time period */
{1, {{0, 1, UP}}, {}},
@@ -217,7 +228,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{25, {{0, 1, UP}}, {}},
@@ -236,7 +248,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoKeysShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
/* Release key after 2ms delay */
@@ -249,14 +262,14 @@ TEST_F(DebounceTest, TwoKeysShort) {
{10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
/* Press key again after 1ms delay */
{11, {{0, 1, DOWN}}, {{0, 1, DOWN}, {0, 2, UP}}}, /* 5ms+5ms after DOWN at time 0 */
- {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */
+ {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */
});
runEvents();
}
-
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late, immediately release key */
@@ -269,7 +282,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late, immediately release key */
@@ -283,7 +297,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late */
@@ -298,7 +313,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late */
@@ -314,7 +330,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
}
TEST_F(DebounceTest, OneKeyDelayedScan5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{5, {{0, 1, UP}}, {}},
@@ -329,7 +346,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
}
TEST_F(DebounceTest, OneKeyDelayedScan6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{5, {{0, 1, UP}}, {}},
@@ -345,7 +363,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan6) {
}
TEST_F(DebounceTest, OneKeyDelayedScan7) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{5, {{0, 1, UP}}, {}},
@@ -358,7 +377,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan7) {
}
TEST_F(DebounceTest, OneKeyDelayedScan8) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is a bit late */
diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp
index 1c5e7c9f4e..f9414e571d 100644
--- a/quantum/debounce/tests/debounce_test_common.cpp
+++ b/quantum/debounce/tests/debounce_test_common.cpp
@@ -31,9 +31,7 @@ void set_time(uint32_t t);
void advance_time(uint32_t ms);
}
-void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) {
- events_.insert(events_.end(), events.begin(), events.end());
-}
+void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) { events_.insert(events_.end(), events.begin(), events.end()); }
void DebounceTest::runEvents() {
/* Run the test multiple times, from 1kHz to 10kHz scan rate */
@@ -54,7 +52,7 @@ void DebounceTest::runEvents() {
void DebounceTest::runEventsInternal() {
fast_timer_t previous = 0;
- bool first = true;
+ bool first = true;
/* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */
debounce_init(MATRIX_ROWS);
@@ -80,7 +78,7 @@ void DebounceTest::runEventsInternal() {
}
}
- first = false;
+ first = false;
previous = event.time_;
/* Prepare input matrix */
@@ -98,12 +96,7 @@ void DebounceTest::runEventsInternal() {
/* Check output matrix has expected change events */
for (auto &output : event.outputs_) {
- EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_))
- << "Missing event at " << strTime()
- << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_)
- << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_)
- << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
- << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
+ EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_)) << "Missing event at " << strTime() << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_) << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_) << "\nexpected_matrix:\n" << strMatrix(output_matrix_) << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
}
/* Check output matrix has no other changes */
@@ -133,27 +126,20 @@ void DebounceTest::runDebounce(bool changed) {
debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) {
- FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime()
- << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
- << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
+ FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime() << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
}
}
void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) {
if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) {
- FAIL() << "Unexpected event: " << error_message << " at " << strTime()
- << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
- << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
- << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
+ FAIL() << "Unexpected event: " << error_message << " at " << strTime() << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) << "\nexpected_matrix:\n" << strMatrix(output_matrix_) << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
}
}
std::string DebounceTest::strTime() {
std::stringstream text;
- text << "time " << (timer_read_fast() - time_offset_)
- << " (extra_iterations=" << extra_iterations_
- << ", auto_advance_time=" << auto_advance_time_ << ")";
+ text << "time " << (timer_read_fast() - time_offset_) << " (extra_iterations=" << extra_iterations_ << ", auto_advance_time=" << auto_advance_time_ << ")";
return text.str();
}
@@ -181,49 +167,39 @@ std::string DebounceTest::strMatrix(matrix_row_t matrix[]) {
bool DebounceTest::directionValue(Direction direction) {
switch (direction) {
- case DOWN:
- return true;
+ case DOWN:
+ return true;
- case UP:
- return false;
+ case UP:
+ return false;
}
}
std::string DebounceTest::directionLabel(Direction direction) {
switch (direction) {
- case DOWN:
- return "DOWN";
+ case DOWN:
+ return "DOWN";
- case UP:
- return "UP";
+ case UP:
+ return "UP";
}
}
/* Modify a matrix and verify that events always specify a change */
void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) {
- ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_))
- << "Test " << name << " at " << strTime()
- << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_)
- << " but it is already " << directionLabel(event.direction_)
- << "\n" << name << "_matrix:\n" << strMatrix(matrix);
+ ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_)) << "Test " << name << " at " << strTime() << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_) << " but it is already " << directionLabel(event.direction_) << "\n" << name << "_matrix:\n" << strMatrix(matrix);
switch (event.direction_) {
- case DOWN:
- matrix[event.row_] |= (1U << event.col_);
- break;
+ case DOWN:
+ matrix[event.row_] |= (1U << event.col_);
+ break;
- case UP:
- matrix[event.row_] &= ~(1U << event.col_);
- break;
+ case UP:
+ matrix[event.row_] &= ~(1U << event.col_);
+ break;
}
}
-DebounceTestEvent::DebounceTestEvent(fast_timer_t time,
- std::initializer_list<MatrixTestEvent> inputs,
- std::initializer_list<MatrixTestEvent> outputs)
- : time_(time), inputs_(inputs), outputs_(outputs) {
-}
+DebounceTestEvent::DebounceTestEvent(fast_timer_t time, std::initializer_list<MatrixTestEvent> inputs, std::initializer_list<MatrixTestEvent> outputs) : time_(time), inputs_(inputs), outputs_(outputs) {}
-MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction)
- : row_(row), col_(col), direction_(direction) {
-}
+MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction) : row_(row), col_(col), direction_(direction) {}
diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h
index d87e310594..b7becb3782 100644
--- a/quantum/debounce/tests/debounce_test_common.h
+++ b/quantum/debounce/tests/debounce_test_common.h
@@ -31,36 +31,34 @@ enum Direction {
};
class MatrixTestEvent {
-public:
+ public:
MatrixTestEvent(int row, int col, Direction direction);
- const int row_;
- const int col_;
+ const int row_;
+ const int col_;
const Direction direction_;
};
class DebounceTestEvent {
-public:
+ public:
// 0, {{0, 1, DOWN}}, {{0, 1, DOWN}})
- DebounceTestEvent(fast_timer_t time,
- std::initializer_list<MatrixTestEvent> inputs,
- std::initializer_list<MatrixTestEvent> outputs);
+ DebounceTestEvent(fast_timer_t time, std::initializer_list<MatrixTestEvent> inputs, std::initializer_list<MatrixTestEvent> outputs);
- const fast_timer_t time_;
+ const fast_timer_t time_;
const std::list<MatrixTestEvent> inputs_;
const std::list<MatrixTestEvent> outputs_;
};
class DebounceTest : public ::testing::Test {
-protected:
+ protected:
void addEvents(std::initializer_list<DebounceTestEvent> events);
void runEvents();
fast_timer_t time_offset_ = 7777;
- bool time_jumps_ = false;
+ bool time_jumps_ = false;
-private:
- static bool directionValue(Direction direction);
+ private:
+ static bool directionValue(Direction direction);
static std::string directionLabel(Direction direction);
void runEventsInternal();
@@ -78,6 +76,6 @@ private:
matrix_row_t cooked_matrix_[MATRIX_ROWS];
matrix_row_t output_matrix_[MATRIX_ROWS];
- int extra_iterations_;
+ int extra_iterations_;
bool auto_advance_time_;
};
diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk
index 66928d7eb6..e908dd6f67 100644
--- a/quantum/debounce/tests/rules.mk
+++ b/quantum/debounce/tests/rules.mk
@@ -16,7 +16,7 @@
DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5
DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \
- $(TMK_PATH)/common/test/timer.c
+ $(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c
debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS)
debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \
diff --git a/quantum/debounce/tests/sym_defer_g_tests.cpp b/quantum/debounce/tests/sym_defer_g_tests.cpp
index a56aecd8f3..73d3d45e30 100644
--- a/quantum/debounce/tests/sym_defer_g_tests.cpp
+++ b/quantum/debounce/tests/sym_defer_g_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyTooQuick1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Release key exactly on the debounce time */
{5, {{0, 1, UP}}, {}},
@@ -67,7 +71,8 @@ TEST_F(DebounceTest, OneKeyTooQuick1) {
}
TEST_F(DebounceTest, OneKeyTooQuick2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -80,7 +85,8 @@ TEST_F(DebounceTest, OneKeyTooQuick2) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -94,7 +100,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
{6, {{0, 1, UP}}, {}},
@@ -108,7 +115,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -125,7 +133,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoKeysShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 2, DOWN}}, {}},
@@ -140,7 +149,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
@@ -152,7 +162,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 2, DOWN}}, {}},
@@ -167,7 +178,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is very late */
@@ -182,7 +194,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is very late */
@@ -197,7 +210,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Release key before debounce expires */
@@ -208,7 +222,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is a bit late */
diff --git a/quantum/debounce/tests/sym_defer_pk_tests.cpp b/quantum/debounce/tests/sym_defer_pk_tests.cpp
index 1f3061e59c..7542c2dad4 100644
--- a/quantum/debounce/tests/sym_defer_pk_tests.cpp
+++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyTooQuick1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Release key exactly on the debounce time */
{5, {{0, 1, UP}}, {}},
@@ -67,7 +71,8 @@ TEST_F(DebounceTest, OneKeyTooQuick1) {
}
TEST_F(DebounceTest, OneKeyTooQuick2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -80,7 +85,8 @@ TEST_F(DebounceTest, OneKeyTooQuick2) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -94,7 +100,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
{6, {{0, 1, UP}}, {}},
@@ -108,7 +115,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}}},
@@ -125,7 +133,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoKeysShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 2, DOWN}}, {}},
@@ -142,7 +151,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
{5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
@@ -154,7 +164,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
{1, {{0, 2, DOWN}}, {}},
@@ -169,7 +180,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is very late */
@@ -184,7 +196,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is very late */
@@ -199,7 +212,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Release key before debounce expires */
@@ -210,7 +224,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {}},
/* Processing is a bit late */
diff --git a/quantum/debounce/tests/sym_eager_pk_tests.cpp b/quantum/debounce/tests/sym_eager_pk_tests.cpp
index e0fc205e33..d9a02fe33c 100644
--- a/quantum/debounce/tests/sym_eager_pk_tests.cpp
+++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyShort4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -71,7 +75,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
}
TEST_F(DebounceTest, OneKeyShort5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -83,7 +88,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
}
TEST_F(DebounceTest, OneKeyShort6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -95,7 +101,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -110,7 +117,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Change twice in the same time period */
{1, {{0, 1, UP}}, {}},
@@ -135,7 +143,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{25, {{0, 1, UP}}, {{0, 1, UP}}},
@@ -146,7 +155,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoKeysShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
@@ -167,7 +177,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
}
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted */
@@ -178,7 +189,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1 scan delay */
@@ -190,7 +202,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1ms delay */
@@ -202,7 +215,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is a bit late but the change will now be accepted */
@@ -213,7 +227,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
}
TEST_F(DebounceTest, OneKeyDelayedScan5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1 scan delay */
@@ -225,7 +240,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
}
TEST_F(DebounceTest, OneKeyDelayedScan6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1ms delay */
diff --git a/quantum/debounce/tests/sym_eager_pr_tests.cpp b/quantum/debounce/tests/sym_eager_pr_tests.cpp
index 2c4bca127e..e91dd9cb87 100644
--- a/quantum/debounce/tests/sym_eager_pr_tests.cpp
+++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp
@@ -19,7 +19,8 @@
#include "debounce_test_common.h"
TEST_F(DebounceTest, OneKeyShort1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
}
TEST_F(DebounceTest, OneKeyShort2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
}
TEST_F(DebounceTest, OneKeyShort3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
}
TEST_F(DebounceTest, OneKeyShort4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -71,7 +75,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
}
TEST_F(DebounceTest, OneKeyShort5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -83,7 +88,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
}
TEST_F(DebounceTest, OneKeyShort6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
@@ -95,7 +101,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
}
TEST_F(DebounceTest, OneKeyBouncing1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{0, 1, DOWN}}, {}},
@@ -110,7 +117,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
}
TEST_F(DebounceTest, OneKeyBouncing2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Change twice in the same time period */
{1, {{0, 1, UP}}, {}},
@@ -135,7 +143,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
}
TEST_F(DebounceTest, OneKeyLong) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{25, {{0, 1, UP}}, {{0, 1, UP}}},
@@ -146,7 +155,8 @@ TEST_F(DebounceTest, OneKeyLong) {
}
TEST_F(DebounceTest, TwoRowsShort) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
{2, {{2, 0, DOWN}}, {{2, 0, DOWN}}},
@@ -167,7 +177,8 @@ TEST_F(DebounceTest, TwoRowsShort) {
}
TEST_F(DebounceTest, TwoKeysOverlap) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
{1, {{0, 1, UP}}, {}},
/* Press a second key during the first debounce */
@@ -190,7 +201,8 @@ TEST_F(DebounceTest, TwoKeysOverlap) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
{20, {{0, 1, UP}}, {{0, 1, UP}}},
{21, {{0, 2, UP}}, {}},
@@ -202,7 +214,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
}
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
{20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}},
});
@@ -210,7 +223,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan1) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted */
@@ -221,7 +235,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
}
TEST_F(DebounceTest, OneKeyDelayedScan2) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1 scan delay */
@@ -233,7 +248,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
}
TEST_F(DebounceTest, OneKeyDelayedScan3) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1ms delay */
@@ -245,7 +261,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
}
TEST_F(DebounceTest, OneKeyDelayedScan4) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is a bit late but the change will now be accepted */
@@ -256,7 +273,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
}
TEST_F(DebounceTest, OneKeyDelayedScan5) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1 scan delay */
@@ -268,7 +286,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
}
TEST_F(DebounceTest, OneKeyDelayedScan6) {
- addEvents({ /* Time, Inputs, Outputs */
+ addEvents({
+ /* Time, Inputs, Outputs */
{0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
/* Processing is very late but the change will now be accepted even with a 1ms delay */
diff --git a/quantum/deferred_exec.c b/quantum/deferred_exec.c
new file mode 100644
index 0000000000..5b0a5b1425
--- /dev/null
+++ b/quantum/deferred_exec.c
@@ -0,0 +1,152 @@
+// Copyright 2021 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <stddef.h>
+#include <timer.h>
+#include <deferred_exec.h>
+
+#ifndef MAX_DEFERRED_EXECUTORS
+# define MAX_DEFERRED_EXECUTORS 8
+#endif
+
+typedef struct deferred_executor_t {
+ deferred_token token;
+ uint32_t trigger_time;
+ deferred_exec_callback callback;
+ void * cb_arg;
+} deferred_executor_t;
+
+static deferred_token current_token = 0;
+static uint32_t last_deferred_exec_check = 0;
+static deferred_executor_t executors[MAX_DEFERRED_EXECUTORS] = {0};
+
+static inline bool token_can_be_used(deferred_token token) {
+ if (token == INVALID_DEFERRED_TOKEN) {
+ return false;
+ }
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ if (executors[i].token == token) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static inline deferred_token allocate_token(void) {
+ deferred_token first = ++current_token;
+ while (!token_can_be_used(current_token)) {
+ ++current_token;
+ if (current_token == first) {
+ // If we've looped back around to the first, everything is already allocated (yikes!). Need to exit with a failure.
+ return INVALID_DEFERRED_TOKEN;
+ }
+ }
+ return current_token;
+}
+
+deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) {
+ // Ignore queueing if it's a zero-time delay, or invalid callback
+ if (delay_ms == 0 || !callback) {
+ return INVALID_DEFERRED_TOKEN;
+ }
+
+ // Find an unused slot and claim it
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ deferred_executor_t *entry = &executors[i];
+ if (entry->token == INVALID_DEFERRED_TOKEN) {
+ // Work out the new token value, dropping out if none were available
+ deferred_token token = allocate_token();
+ if (token == INVALID_DEFERRED_TOKEN) {
+ return false;
+ }
+
+ // Set up the executor table entry
+ entry->token = current_token;
+ entry->trigger_time = timer_read32() + delay_ms;
+ entry->callback = callback;
+ entry->cb_arg = cb_arg;
+ return current_token;
+ }
+ }
+
+ // None available
+ return INVALID_DEFERRED_TOKEN;
+}
+
+bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) {
+ // Ignore queueing if it's a zero-time delay, or the token is not valid
+ if (delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) {
+ return false;
+ }
+
+ // Find the entry corresponding to the token
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ deferred_executor_t *entry = &executors[i];
+ if (entry->token == token) {
+ // Found it, extend the delay
+ entry->trigger_time = timer_read32() + delay_ms;
+ return true;
+ }
+ }
+
+ // Not found
+ return false;
+}
+
+bool cancel_deferred_exec(deferred_token token) {
+ // Ignore request if the token is not valid
+ if (token == INVALID_DEFERRED_TOKEN) {
+ return false;
+ }
+
+ // Find the entry corresponding to the token
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ deferred_executor_t *entry = &executors[i];
+ if (entry->token == token) {
+ // Found it, cancel and clear the table entry
+ entry->token = INVALID_DEFERRED_TOKEN;
+ entry->trigger_time = 0;
+ entry->callback = NULL;
+ entry->cb_arg = NULL;
+ return true;
+ }
+ }
+
+ // Not found
+ return false;
+}
+
+void deferred_exec_task(void) {
+ uint32_t now = timer_read32();
+
+ // Throttle only once per millisecond
+ if (((int32_t)TIMER_DIFF_32(now, last_deferred_exec_check)) > 0) {
+ last_deferred_exec_check = now;
+
+ // Run through each of the executors
+ for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
+ deferred_executor_t *entry = &executors[i];
+
+ // Check if we're supposed to execute this entry
+ if (entry->token != INVALID_DEFERRED_TOKEN && ((int32_t)TIMER_DIFF_32(entry->trigger_time, now)) <= 0) {
+ // Invoke the callback and work work out if we should be requeued
+ uint32_t delay_ms = entry->callback(entry->trigger_time, entry->cb_arg);
+
+ // Update the trigger time if we have to repeat, otherwise clear it out
+ if (delay_ms > 0) {
+ // Intentionally add just the delay to the existing trigger time -- this ensures the next
+ // invocation is with respect to the previous trigger, rather than when it got to execution. Under
+ // normal circumstances this won't cause issue, but if another executor is invoked that takes a
+ // considerable length of time, then this ensures best-effort timing between invocations.
+ entry->trigger_time += delay_ms;
+ } else {
+ // If it was zero, then the callback is cancelling repeated execution. Free up the slot.
+ entry->token = INVALID_DEFERRED_TOKEN;
+ entry->trigger_time = 0;
+ entry->callback = NULL;
+ entry->cb_arg = NULL;
+ }
+ }
+ }
+ }
+}
diff --git a/quantum/deferred_exec.h b/quantum/deferred_exec.h
new file mode 100644
index 0000000000..f80d353169
--- /dev/null
+++ b/quantum/deferred_exec.h
@@ -0,0 +1,38 @@
+// Copyright 2021 Nick Brassel (@tzarc)
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+// A token that can be used to cancel an existing deferred execution.
+typedef uint8_t deferred_token;
+#define INVALID_DEFERRED_TOKEN 0
+
+// Callback to execute.
+// -- Parameter trigger_time: the intended trigger time to execute the callback -- equivalent time-space as timer_read32()
+// cb_arg: the callback argument specified when enqueueing the deferred executor
+// -- Return value: Non-zero re-queues the callback to execute after the returned number of milliseconds. Zero cancels repeated execution.
+typedef uint32_t (*deferred_exec_callback)(uint32_t trigger_time, void *cb_arg);
+
+// Configures the supplied deferred executor to be executed after the required number of milliseconds.
+// -- Parameter delay_ms: the number of milliseconds before executing the callback
+// -- callback: the executor to invoke
+// -- cb_arg: the argument to pass to the executor, may be NULL if unused by the executor
+// -- Return value: a token usable for cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
+deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg);
+
+// Allows for extending the timeframe before an existing deferred execution is invoked.
+// -- Parameter token: the returned value from defer_exec for the deferred execution you wish to extend.
+// -- delay_ms: the new delay (with respect to the current time)
+// -- Return value: if the token was found, and the delay was extended
+bool extend_deferred_exec(deferred_token token, uint32_t delay_ms);
+
+// Allows for cancellation of an existing deferred execution.
+// -- Parameter token: the returned value from defer_exec for the deferred execution you wish to cancel.
+// -- Return value: if the token was found, and the executor was cancelled
+bool cancel_deferred_exec(deferred_token token);
+
+// Forward declaration for the main loop in order to execute any deferred executors. Should not be invoked by keyboard/user code.
+void deferred_exec_task(void);
diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c
index f76f37f997..8c2d2f5dce 100644
--- a/quantum/dynamic_keymap.c
+++ b/quantum/dynamic_keymap.c
@@ -14,8 +14,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-#include "tmk_core/common/eeprom.h"
+#include "config.h"
+#include "keymap.h" // to get keymaps[][][]
+#include "eeprom.h"
+#include "progmem.h" // to read default from flash
#include "quantum.h" // for send_string()
#include "eeconfig.h"
diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c
index e571309a05..7c1a1f3cb2 100644
--- a/quantum/eeconfig.c
+++ b/quantum/eeconfig.c
@@ -7,11 +7,6 @@
# include "oryx.h"
#endif
-#ifdef STM32_EEPROM_ENABLE
-# include <hal.h>
-# include "eeprom_stm32.h"
-#endif
-
#if defined(EEPROM_DRIVER)
# include "eeprom_driver.h"
#endif
@@ -46,9 +41,6 @@ __attribute__((weak)) void eeconfig_init_kb(void) {
* FIXME: needs doc
*/
void eeconfig_init_quantum(void) {
-#ifdef STM32_EEPROM_ENABLE
- EEPROM_Erase();
-#endif
#if defined(EEPROM_DRIVER)
eeprom_driver_erase();
#endif
@@ -118,9 +110,6 @@ void eeconfig_enable(void) { eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_N
* FIXME: needs doc
*/
void eeconfig_disable(void) {
-#ifdef STM32_EEPROM_ENABLE
- EEPROM_Erase();
-#endif
#if defined(EEPROM_DRIVER)
eeprom_driver_erase();
#endif
diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h
index bd39971b2c..22d874273c 100644
--- a/quantum/eeconfig.h
+++ b/quantum/eeconfig.h
@@ -111,3 +111,29 @@ void eeconfig_update_haptic(uint32_t val);
bool eeconfig_read_handedness(void);
void eeconfig_update_handedness(bool val);
+
+#define EECONFIG_DEBOUNCE_HELPER(name, offset, config) \
+ static uint8_t dirty_##name = false; \
+ \
+ static inline void eeconfig_init_##name(void) { \
+ eeprom_read_block(&config, offset, sizeof(config)); \
+ dirty_##name = false; \
+ } \
+ static inline void eeconfig_flush_##name(bool force) { \
+ if (force || dirty_##name) { \
+ eeprom_update_block(&config, offset, sizeof(config)); \
+ dirty_##name = false; \
+ } \
+ } \
+ static inline void eeconfig_flush_##name##_task(uint16_t timeout) { \
+ static uint16_t flush_timer = 0; \
+ if (timer_elapsed(flush_timer) > timeout) { \
+ eeconfig_flush_##name(false); \
+ flush_timer = timer_read(); \
+ } \
+ } \
+ static inline void eeconfig_flag_##name(bool v) { dirty_##name |= v; } \
+ static inline void eeconfig_write_##name(typeof(config) conf) { \
+ memcpy(&config, &conf, sizeof(config)); \
+ eeconfig_flag_##name(true); \
+ }
diff --git a/quantum/encoder/tests/encoder_tests.cpp b/quantum/encoder/tests/encoder_tests.cpp
new file mode 100644
index 0000000000..1888fdab8d
--- /dev/null
+++ b/quantum/encoder/tests/encoder_tests.cpp
@@ -0,0 +1,144 @@
+/* Copyright 2021 Balz Guenat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include <vector>
+#include <algorithm>
+#include <stdio.h>
+
+extern "C" {
+#include "encoder.h"
+#include "encoder/tests/mock.h"
+}
+
+struct update {
+ int8_t index;
+ bool clockwise;
+};
+
+uint8_t uidx = 0;
+update updates[32];
+
+bool encoder_update_kb(uint8_t index, bool clockwise) {
+ updates[uidx % 32] = {index, clockwise};
+ uidx++;
+ return true;
+}
+
+bool setAndRead(pin_t pin, bool val) {
+ setPin(pin, val);
+ return encoder_read();
+}
+
+class EncoderTest : public ::testing::Test {};
+
+TEST_F(EncoderTest, TestInit) {
+ uidx = 0;
+ encoder_init();
+ EXPECT_EQ(pinIsInputHigh[0], true);
+ EXPECT_EQ(pinIsInputHigh[1], true);
+ EXPECT_EQ(uidx, 0);
+}
+
+TEST_F(EncoderTest, TestOneClockwise) {
+ uidx = 0;
+ encoder_init();
+ // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+}
+
+TEST_F(EncoderTest, TestOneCounterClockwise) {
+ uidx = 0;
+ encoder_init();
+ setAndRead(1, false);
+ setAndRead(0, false);
+ setAndRead(1, true);
+ setAndRead(0, true);
+
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, false);
+}
+
+TEST_F(EncoderTest, TestTwoClockwiseOneCC) {
+ uidx = 0;
+ encoder_init();
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+ setAndRead(1, false);
+ setAndRead(0, false);
+ setAndRead(1, true);
+ setAndRead(0, true);
+
+ EXPECT_EQ(uidx, 3);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+ EXPECT_EQ(updates[1].index, 0);
+ EXPECT_EQ(updates[1].clockwise, true);
+ EXPECT_EQ(updates[2].index, 0);
+ EXPECT_EQ(updates[2].clockwise, false);
+}
+
+TEST_F(EncoderTest, TestNoEarly) {
+ uidx = 0;
+ encoder_init();
+ // send 3 pulses. with resolution 4, that's not enough for a step.
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ EXPECT_EQ(uidx, 0);
+ // now send last pulse
+ setAndRead(1, true);
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+}
+
+TEST_F(EncoderTest, TestHalfway) {
+ uidx = 0;
+ encoder_init();
+ // go halfway
+ setAndRead(0, false);
+ setAndRead(1, false);
+ EXPECT_EQ(uidx, 0);
+ // back off
+ setAndRead(1, true);
+ setAndRead(0, true);
+ EXPECT_EQ(uidx, 0);
+ // go all the way
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+ // should result in 1 update
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+}
diff --git a/quantum/encoder/tests/encoder_tests_split.cpp b/quantum/encoder/tests/encoder_tests_split.cpp
new file mode 100644
index 0000000000..25e52c83f9
--- /dev/null
+++ b/quantum/encoder/tests/encoder_tests_split.cpp
@@ -0,0 +1,143 @@
+/* Copyright 2021 Balz Guenat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include <vector>
+#include <algorithm>
+#include <stdio.h>
+
+extern "C" {
+#include "encoder.h"
+#include "encoder/tests/mock_split.h"
+}
+
+struct update {
+ int8_t index;
+ bool clockwise;
+};
+
+uint8_t uidx = 0;
+update updates[32];
+
+bool isLeftHand;
+
+bool encoder_update_kb(uint8_t index, bool clockwise) {
+ if (!isLeftHand) {
+ // this method has no effect on slave half
+ printf("ignoring update on right hand (%d,%s)\n", index, clockwise ? "CW" : "CC");
+ return true;
+ }
+ updates[uidx % 32] = {index, clockwise};
+ uidx++;
+ return true;
+}
+
+bool setAndRead(pin_t pin, bool val) {
+ setPin(pin, val);
+ return encoder_read();
+}
+
+class EncoderTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ uidx = 0;
+ for (int i = 0; i < 32; i++) {
+ pinIsInputHigh[i] = 0;
+ pins[i] = 0;
+ }
+ }
+};
+
+TEST_F(EncoderTest, TestInitLeft) {
+ isLeftHand = true;
+ encoder_init();
+ EXPECT_EQ(pinIsInputHigh[0], true);
+ EXPECT_EQ(pinIsInputHigh[1], true);
+ EXPECT_EQ(pinIsInputHigh[2], false);
+ EXPECT_EQ(pinIsInputHigh[3], false);
+ EXPECT_EQ(uidx, 0);
+}
+
+TEST_F(EncoderTest, TestInitRight) {
+ isLeftHand = false;
+ encoder_init();
+ EXPECT_EQ(pinIsInputHigh[0], false);
+ EXPECT_EQ(pinIsInputHigh[1], false);
+ EXPECT_EQ(pinIsInputHigh[2], true);
+ EXPECT_EQ(pinIsInputHigh[3], true);
+ EXPECT_EQ(uidx, 0);
+}
+
+TEST_F(EncoderTest, TestOneClockwiseLeft) {
+ isLeftHand = true;
+ encoder_init();
+ // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
+ setAndRead(0, false);
+ setAndRead(1, false);
+ setAndRead(0, true);
+ setAndRead(1, true);
+
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 0);
+ EXPECT_EQ(updates[0].clockwise, true);
+}
+
+TEST_F(EncoderTest, TestOneClockwiseRightSent) {
+ isLeftHand = false;
+ encoder_init();
+ // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
+ setAndRead(2, false);
+ setAndRead(3, false);
+ setAndRead(2, true);
+ setAndRead(3, true);
+
+ uint8_t slave_state[2] = {0};
+ encoder_state_raw(slave_state);
+
+ EXPECT_EQ((int8_t)slave_state[0], -1);
+}
+
+/* this test will not work after the previous test.
+ * this is due to encoder_value[1] already being set to -1 when simulating the right half.
+ * When we now receive this update acting as the left half, there is no change.
+ * This is hard to mock, as the static values inside encoder.c normally exist twice, once on each half,
+ * but here, they only exist once.
+ */
+
+// TEST_F(EncoderTest, TestOneClockwiseRightReceived) {
+// isLeftHand = true;
+// encoder_init();
+
+// uint8_t slave_state[2] = {255, 0};
+// encoder_update_raw(slave_state);
+
+// EXPECT_EQ(uidx, 1);
+// EXPECT_EQ(updates[0].index, 1);
+// EXPECT_EQ(updates[0].clockwise, true);
+// }
+
+TEST_F(EncoderTest, TestOneCounterClockwiseRightReceived) {
+ isLeftHand = true;
+ encoder_init();
+
+ uint8_t slave_state[2] = {0, 0};
+ encoder_update_raw(slave_state);
+
+ EXPECT_EQ(uidx, 1);
+ EXPECT_EQ(updates[0].index, 1);
+ EXPECT_EQ(updates[0].clockwise, false);
+}
diff --git a/quantum/api/api_sysex.h b/quantum/encoder/tests/mock.c
index eb0a18848d..d0506a938f 100644
--- a/quantum/api/api_sysex.h
+++ b/quantum/encoder/tests/mock.c
@@ -1,4 +1,4 @@
-/* Copyright 2016 Jack Humbert
+/* Copyright 2021 Balz Guenat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,12 +14,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#pragma once
+#include "mock.h"
-#include "api.h"
+bool pins[32] = {0};
+bool pinIsInputHigh[32] = {0};
-#define API_SYSEX_MAX_SIZE 32
+uint8_t mockSetPinInputHigh(pin_t pin) {
+ // dprintf("Setting pin %d input high.", pin);
+ pins[pin] = true;
+ pinIsInputHigh[pin] = true;
+ return 0;
+}
-void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t* bytes, uint16_t length);
+bool mockReadPin(pin_t pin) { return pins[pin]; }
-#define SEND_BYTES(mt, dt, b, l) send_bytes_sysex(mt, dt, b, l)
+bool setPin(pin_t pin, bool val) {
+ pins[pin] = val;
+ return val;
+}
diff --git a/quantum/visualizer/default_animations.h b/quantum/encoder/tests/mock.h
index 9accd89774..dbc25a0846 100644
--- a/quantum/visualizer/default_animations.h
+++ b/quantum/encoder/tests/mock.h
@@ -1,4 +1,4 @@
-/* Copyright 2017 Fred Sundvik
+/* Copyright 2021 Balz Guenat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,12 +16,25 @@
#pragma once
-#include "visualizer.h"
+#include <stdint.h>
+#include <stdbool.h>
-// You can use these default animations, but of course you can also write your own custom ones instead
-extern keyframe_animation_t default_startup_animation;
-extern keyframe_animation_t default_suspend_animation;
+/* Here, "pins" from 0 to 31 are allowed. */
+#define ENCODERS_PAD_A \
+ { 0 }
+#define ENCODERS_PAD_B \
+ { 1 }
-// An animation for testing and demonstrating the led support, should probably not be used for real world
-// cases
-extern keyframe_animation_t led_test_animation;
+typedef uint8_t pin_t;
+
+extern bool pins[];
+extern bool pinIsInputHigh[];
+
+#define setPinInputHigh(pin) (mockSetPinInputHigh(pin))
+#define readPin(pin) (mockReadPin(pin))
+
+uint8_t mockSetPinInputHigh(pin_t pin);
+
+bool mockReadPin(pin_t pin);
+
+bool setPin(pin_t pin, bool val);
diff --git a/quantum/visualizer/visualizer_keyframes.c b/quantum/encoder/tests/mock_split.c
index 8f6a7e15a4..68bf3af599 100644
--- a/quantum/visualizer/visualizer_keyframes.c
+++ b/quantum/encoder/tests/mock_split.c
@@ -1,4 +1,4 @@
-/* Copyright 2017 Fred Sundvik
+/* Copyright 2021 Balz Guenat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,10 +14,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "visualizer_keyframes.h"
+#include "mock_split.h"
-bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- return false;
+bool pins[32] = {0};
+bool pinIsInputHigh[32] = {0};
+
+uint8_t mockSetPinInputHigh(pin_t pin) {
+ // dprintf("Setting pin %d input high.", pin);
+ pins[pin] = true;
+ pinIsInputHigh[pin] = true;
+ return 0;
}
+
+bool mockReadPin(pin_t pin) { return pins[pin]; }
+
+bool setPin(pin_t pin, bool val) {
+ pins[pin] = val;
+ return val;
+}
+
+void last_encoder_activity_trigger(void) {}
diff --git a/quantum/encoder/tests/mock_split.h b/quantum/encoder/tests/mock_split.h
new file mode 100644
index 0000000000..0ae62652f9
--- /dev/null
+++ b/quantum/encoder/tests/mock_split.h
@@ -0,0 +1,48 @@
+/* Copyright 2021 Balz Guenat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define SPLIT_KEYBOARD
+/* Here, "pins" from 0 to 31 are allowed. */
+#define ENCODERS_PAD_A \
+ { 0 }
+#define ENCODERS_PAD_B \
+ { 1 }
+#define ENCODERS_PAD_A_RIGHT \
+ { 2 }
+#define ENCODERS_PAD_B_RIGHT \
+ { 3 }
+
+typedef uint8_t pin_t;
+extern bool isLeftHand;
+void encoder_state_raw(uint8_t* slave_state);
+void encoder_update_raw(uint8_t* slave_state);
+
+extern bool pins[];
+extern bool pinIsInputHigh[];
+
+#define setPinInputHigh(pin) (mockSetPinInputHigh(pin))
+#define readPin(pin) (mockReadPin(pin))
+
+uint8_t mockSetPinInputHigh(pin_t pin);
+
+bool mockReadPin(pin_t pin);
+
+bool setPin(pin_t pin, bool val);
diff --git a/quantum/encoder/tests/rules.mk b/quantum/encoder/tests/rules.mk
new file mode 100644
index 0000000000..b826ce3aed
--- /dev/null
+++ b/quantum/encoder/tests/rules.mk
@@ -0,0 +1,13 @@
+encoder_DEFS := -DENCODER_MOCK_SINGLE
+
+encoder_SRC := \
+ $(QUANTUM_PATH)/encoder/tests/mock.c \
+ $(QUANTUM_PATH)/encoder/tests/encoder_tests.cpp \
+ $(QUANTUM_PATH)/encoder.c
+
+encoder_split_DEFS := -DENCODER_MOCK_SPLIT
+
+encoder_split_SRC := \
+ $(QUANTUM_PATH)/encoder/tests/mock_split.c \
+ $(QUANTUM_PATH)/encoder/tests/encoder_tests_split.cpp \
+ $(QUANTUM_PATH)/encoder.c
diff --git a/quantum/encoder/tests/testlist.mk b/quantum/encoder/tests/testlist.mk
new file mode 100644
index 0000000000..1be9f4a054
--- /dev/null
+++ b/quantum/encoder/tests/testlist.mk
@@ -0,0 +1,3 @@
+TEST_LIST += \
+ encoder \
+ encoder_split
diff --git a/quantum/haptic.c b/quantum/haptic.c
index 65abcc15fa..f915acf946 100644
--- a/quantum/haptic.c
+++ b/quantum/haptic.c
@@ -17,6 +17,8 @@
#include "haptic.h"
#include "eeconfig.h"
#include "debug.h"
+#include "usb_device_state.h"
+#include "gpio.h"
#ifdef DRV2605L
# include "DRV2605L.h"
#endif
@@ -26,6 +28,29 @@
haptic_config_t haptic_config;
+static void update_haptic_enable_gpios(void) {
+ if (haptic_config.enable && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) {
+#if defined(HAPTIC_ENABLE_PIN)
+ HAPTIC_ENABLE_PIN_WRITE_ACTIVE();
+#endif
+#if defined(HAPTIC_ENABLE_STATUS_LED)
+ HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE();
+#endif
+ } else {
+#if defined(HAPTIC_ENABLE_PIN)
+ HAPTIC_ENABLE_PIN_WRITE_INACTIVE();
+#endif
+#if defined(HAPTIC_ENABLE_STATUS_LED)
+ HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE();
+#endif
+ }
+}
+
+static void set_haptic_config_enable(bool enabled) {
+ haptic_config.enable = enabled;
+ update_haptic_enable_gpios();
+}
+
void haptic_init(void) {
if (!eeconfig_is_enabled()) {
eeconfig_init();
@@ -44,6 +69,10 @@ void haptic_init(void) {
// or the previous firmware didn't have solenoid enabled,
// and the current one has solenoid enabled.
haptic_reset();
+ } else {
+ // Haptic configuration has been loaded through the "raw" union item.
+ // This is to execute any side effects of the configuration.
+ set_haptic_config_enable(haptic_config.enable);
}
#ifdef SOLENOID_ENABLE
solenoid_setup();
@@ -54,6 +83,12 @@ void haptic_init(void) {
dprintf("DRV2605 driver initialized\n");
#endif
eeconfig_debug_haptic();
+#ifdef HAPTIC_ENABLE_PIN
+ setPinOutput(HAPTIC_ENABLE_PIN);
+#endif
+#ifdef HAPTIC_ENABLE_STATUS_LED
+ setPinOutput(HAPTIC_ENABLE_STATUS_LED);
+#endif
}
void haptic_task(void) {
@@ -69,13 +104,13 @@ void eeconfig_debug_haptic(void) {
}
void haptic_enable(void) {
- haptic_config.enable = 1;
+ set_haptic_config_enable(true);
xprintf("haptic_config.enable = %u\n", haptic_config.enable);
eeconfig_update_haptic(haptic_config.raw);
}
void haptic_disable(void) {
- haptic_config.enable = 0;
+ set_haptic_config_enable(false);
xprintf("haptic_config.enable = %u\n", haptic_config.enable);
eeconfig_update_haptic(haptic_config.raw);
}
@@ -157,7 +192,7 @@ void haptic_dwell_decrease(void) {
}
void haptic_reset(void) {
- haptic_config.enable = true;
+ set_haptic_config_enable(true);
uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT;
haptic_config.feedback = feedback;
#ifdef DRV2605L
@@ -293,3 +328,13 @@ void haptic_shutdown(void) {
solenoid_shutdown();
#endif
}
+
+void haptic_notify_usb_device_state_change(void) {
+ update_haptic_enable_gpios();
+#if defined(HAPTIC_ENABLE_PIN)
+ setPinOutput(HAPTIC_ENABLE_PIN);
+#endif
+#if defined(HAPTIC_ENABLE_STATUS_LED)
+ setPinOutput(HAPTIC_ENABLE_STATUS_LED);
+#endif
+}
diff --git a/quantum/haptic.h b/quantum/haptic.h
index fc7ca2f3e6..7d70a01333 100644
--- a/quantum/haptic.h
+++ b/quantum/haptic.h
@@ -75,3 +75,30 @@ void haptic_cont_decrease(void);
void haptic_play(void);
void haptic_shutdown(void);
+void haptic_notify_usb_device_state_change(void);
+
+#ifdef HAPTIC_ENABLE_PIN_ACTIVE_LOW
+# ifndef HAPTIC_ENABLE_PIN
+# error HAPTIC_ENABLE_PIN not defined
+# endif
+# define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_PIN)
+# define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_PIN)
+#else
+# define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_PIN)
+# define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_PIN)
+#endif
+
+#ifdef HAPTIC_ENABLE_STATUS_LED_ACTIVE_LOW
+# ifndef HAPTIC_ENABLE_STATUS_LED
+# error HAPTIC_ENABLE_STATUS_LED not defined
+# endif
+# define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED)
+# define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED)
+#else
+# define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED)
+# define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED)
+#endif
+
+#ifndef HAPTIC_OFF_IN_LOW_POWER
+# define HAPTIC_OFF_IN_LOW_POWER 0
+#endif
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
index b98fc64e45..3bca05aab7 100644
--- a/quantum/keyboard.c
+++ b/quantum/keyboard.c
@@ -40,12 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef PS2_MOUSE_ENABLE
# include "ps2_mouse.h"
#endif
-#ifdef SERIAL_MOUSE_ENABLE
-# include "serial_mouse.h"
-#endif
-#ifdef ADB_MOUSE_ENABLE
-# include "adb.h"
-#endif
#ifdef RGBLIGHT_ENABLE
# include "rgblight.h"
#endif
@@ -61,12 +55,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef STENO_ENABLE
# include "process_steno.h"
#endif
-#ifdef SERIAL_LINK_ENABLE
-# include "serial_link/system/serial_link.h"
-#endif
-#ifdef VISUALIZER_ENABLE
-# include "visualizer/visualizer.h"
-#endif
#ifdef POINTING_DEVICE_ENABLE
# include "pointing_device.h"
#endif
@@ -76,12 +64,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef JOYSTICK_ENABLE
# include "process_joystick.h"
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+# include "programmable_button.h"
+#endif
#ifdef HD44780_ENABLE
# include "hd44780.h"
#endif
-#ifdef QWIIC_ENABLE
-# include "qwiic.h"
-#endif
#ifdef OLED_ENABLE
# include "oled_driver.h"
#endif
@@ -97,9 +85,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef DIP_SWITCH_ENABLE
# include "dip_switch.h"
#endif
-#ifdef STM32_EEPROM_ENABLE
-# include "eeprom_stm32.h"
-#endif
#ifdef EEPROM_DRIVER
# include "eeprom_driver.h"
#endif
@@ -109,6 +94,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef DIGITIZER_ENABLE
# include "digitizer.h"
#endif
+#ifdef VIRTSER_ENABLE
+# include "virtser.h"
+#endif
+#ifdef SLEEP_LED_ENABLE
+# include "sleep_led.h"
+#endif
static uint32_t last_input_modification_time = 0;
uint32_t last_input_activity_time(void) { return last_input_modification_time; }
@@ -246,9 +237,6 @@ void keyboard_setup(void) {
disable_jtag();
#endif
print_set_sendchar(sendchar);
-#ifdef STM32_EEPROM_ENABLE
- EEPROM_Init();
-#endif
#ifdef EEPROM_DRIVER
eeprom_driver_init();
#endif
@@ -316,9 +304,6 @@ void keyboard_init(void) {
#if defined(CRC_ENABLE)
crc_init();
#endif
-#ifdef QWIIC_ENABLE
- qwiic_init();
-#endif
#ifdef OLED_ENABLE
oled_init(OLED_ROTATION_0);
#endif
@@ -328,12 +313,6 @@ void keyboard_init(void) {
#ifdef PS2_MOUSE_ENABLE
ps2_mouse_init();
#endif
-#ifdef SERIAL_MOUSE_ENABLE
- serial_mouse_init();
-#endif
-#ifdef ADB_MOUSE_ENABLE
- adb_mouse_init();
-#endif
#ifdef BACKLIGHT_ENABLE
backlight_init();
#endif
@@ -356,6 +335,12 @@ void keyboard_init(void) {
#ifdef DIP_SWITCH_ENABLE
dip_switch_init();
#endif
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+#ifdef VIRTSER_ENABLE
+ virtser_init();
+#endif
#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)
debug_enable = true;
@@ -384,7 +369,6 @@ void switch_events(uint8_t row, uint8_t col, bool pressed) {
*
* * scan matrix
* * handle mouse movements
- * * run visualizer code
* * handle midi commands
* * light LEDs
*
@@ -473,10 +457,6 @@ MATRIX_LOOP_END:
if (encoders_changed) last_encoder_activity_trigger();
#endif
-#ifdef QWIIC_ENABLE
- qwiic_task();
-#endif
-
#ifdef OLED_ENABLE
oled_task();
# if OLED_TIMEOUT > 0
@@ -510,22 +490,6 @@ MATRIX_LOOP_END:
ps2_mouse_task();
#endif
-#ifdef SERIAL_MOUSE_ENABLE
- serial_mouse_task();
-#endif
-
-#ifdef ADB_MOUSE_ENABLE
- adb_mouse_task();
-#endif
-
-#ifdef SERIAL_LINK_ENABLE
- serial_link_update();
-#endif
-
-#ifdef VISUALIZER_ENABLE
- visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds());
-#endif
-
#ifdef POINTING_DEVICE_ENABLE
pointing_device_task();
#endif
@@ -548,6 +512,10 @@ MATRIX_LOOP_END:
digitizer_task();
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ programmable_button_send();
+#endif
+
// update LED
if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds();
diff --git a/quantum/keycode.h b/quantum/keycode.h
index 8facabd818..38a29b439b 100644
--- a/quantum/keycode.h
+++ b/quantum/keycode.h
@@ -29,7 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED)
#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF)
#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL)
-#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI)
+#define IS_MOD(code) (KC_LEFT_CTRL <= (code) && (code) <= KC_RIGHT_GUI)
#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
@@ -46,10 +46,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MOD_BIT(code) (1 << MOD_INDEX(code))
#define MOD_INDEX(code) ((code)&0x07)
-#define MOD_MASK_CTRL (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL))
-#define MOD_MASK_SHIFT (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))
-#define MOD_MASK_ALT (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT))
-#define MOD_MASK_GUI (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))
+#define MOD_MASK_CTRL (MOD_BIT(KC_LEFT_CTRL) | MOD_BIT(KC_RIGHT_CTRL))
+#define MOD_MASK_SHIFT (MOD_BIT(KC_LEFT_SHIFT) | MOD_BIT(KC_RIGHT_SHIFT))
+#define MOD_MASK_ALT (MOD_BIT(KC_LEFT_ALT) | MOD_BIT(KC_RIGHT_ALT))
+#define MOD_MASK_GUI (MOD_BIT(KC_LEFT_GUI) | MOD_BIT(KC_RIGHT_GUI))
#define MOD_MASK_CS (MOD_MASK_CTRL | MOD_MASK_SHIFT)
#define MOD_MASK_CA (MOD_MASK_CTRL | MOD_MASK_ALT)
#define MOD_MASK_CG (MOD_MASK_CTRL | MOD_MASK_GUI)
@@ -67,6 +67,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define FN_MIN KC_FN0
#define FN_MAX KC_FN31
+// clang-format off
+
/*
* Short names for ease of definition of keymap
*/
@@ -75,47 +77,55 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_TRNS KC_TRANSPARENT
/* Punctuation */
-#define KC_ENT KC_ENTER
-#define KC_ESC KC_ESCAPE
-#define KC_BSPC KC_BSPACE
-#define KC_SPC KC_SPACE
+#define KC_ENT KC_ENTER
+#define KC_ESC KC_ESCAPE
+#define KC_BSPC KC_BACKSPACE
+#define KC_SPC KC_SPACE
#define KC_MINS KC_MINUS
-#define KC_EQL KC_EQUAL
-#define KC_LBRC KC_LBRACKET
-#define KC_RBRC KC_RBRACKET
-#define KC_BSLS KC_BSLASH
+#define KC_EQL KC_EQUAL
+#define KC_LBRC KC_LEFT_BRACKET
+#define KC_RBRC KC_RIGHT_BRACKET
+#define KC_BSLS KC_BACKSLASH
#define KC_NUHS KC_NONUS_HASH
-#define KC_SCLN KC_SCOLON
+#define KC_SCLN KC_SEMICOLON
#define KC_QUOT KC_QUOTE
-#define KC_GRV KC_GRAVE
+#define KC_GRV KC_GRAVE
#define KC_COMM KC_COMMA
#define KC_SLSH KC_SLASH
-#define KC_NUBS KC_NONUS_BSLASH
+#define KC_NUBS KC_NONUS_BACKSLASH
/* Lock Keys */
-#define KC_CLCK KC_CAPSLOCK
-#define KC_CAPS KC_CAPSLOCK
-#define KC_SLCK KC_SCROLLLOCK
-#define KC_NLCK KC_NUMLOCK
-#define KC_LCAP KC_LOCKING_CAPS
-#define KC_LNUM KC_LOCKING_NUM
-#define KC_LSCR KC_LOCKING_SCROLL
+#define KC_CAPS KC_CAPS_LOCK
+#define KC_SCRL KC_SCROLL_LOCK
+#define KC_NUM KC_NUM_LOCK
+#define KC_LCAP KC_LOCKING_CAPS_LOCK
+#define KC_LNUM KC_LOCKING_NUM_LOCK
+#define KC_LSCR KC_LOCKING_SCROLL_LOCK
/* Commands */
-#define KC_PSCR KC_PSCREEN
+#define KC_PSCR KC_PRINT_SCREEN
#define KC_PAUS KC_PAUSE
-#define KC_BRK KC_PAUSE
-#define KC_INS KC_INSERT
-#define KC_DEL KC_DELETE
-#define KC_PGDN KC_PGDOWN
+#define KC_BRK KC_PAUSE
+#define KC_INS KC_INSERT
+#define KC_PGUP KC_PAGE_UP
+#define KC_DEL KC_DELETE
+#define KC_PGDN KC_PAGE_DOWN
#define KC_RGHT KC_RIGHT
-#define KC_APP KC_APPLICATION
+#define KC_APP KC_APPLICATION
#define KC_EXEC KC_EXECUTE
#define KC_SLCT KC_SELECT
#define KC_AGIN KC_AGAIN
#define KC_PSTE KC_PASTE
-#define KC_ERAS KC_ALT_ERASE
-#define KC_CLR KC_CLEAR
+#define KC_ERAS KC_ALTERNATE_ERASE
+#define KC_SYRQ KC_SYSTEM_REQUEST
+#define KC_CNCL KC_CANCEL
+#define KC_CLR KC_CLEAR
+#define KC_PRIR KC_PRIOR
+#define KC_RETN KC_RETURN
+#define KC_SEPR KC_SEPARATOR
+#define KC_CLAG KC_CLEAR_AGAIN
+#define KC_CRSL KC_CRSEL
+#define KC_EXSL KC_EXSEL
/* Keypad */
#define KC_PSLS KC_KP_SLASH
@@ -123,47 +133,59 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_PMNS KC_KP_MINUS
#define KC_PPLS KC_KP_PLUS
#define KC_PENT KC_KP_ENTER
-#define KC_P1 KC_KP_1
-#define KC_P2 KC_KP_2
-#define KC_P3 KC_KP_3
-#define KC_P4 KC_KP_4
-#define KC_P5 KC_KP_5
-#define KC_P6 KC_KP_6
-#define KC_P7 KC_KP_7
-#define KC_P8 KC_KP_8
-#define KC_P9 KC_KP_9
-#define KC_P0 KC_KP_0
+#define KC_P1 KC_KP_1
+#define KC_P2 KC_KP_2
+#define KC_P3 KC_KP_3
+#define KC_P4 KC_KP_4
+#define KC_P5 KC_KP_5
+#define KC_P6 KC_KP_6
+#define KC_P7 KC_KP_7
+#define KC_P8 KC_KP_8
+#define KC_P9 KC_KP_9
+#define KC_P0 KC_KP_0
#define KC_PDOT KC_KP_DOT
#define KC_PEQL KC_KP_EQUAL
#define KC_PCMM KC_KP_COMMA
-/* Japanese specific */
-#define KC_ZKHK KC_GRAVE
-#define KC_RO KC_INT1
-#define KC_KANA KC_INT2
-#define KC_JYEN KC_INT3
-#define KC_HENK KC_INT4
-#define KC_MHEN KC_INT5
-
-/* Korean specific */
-#define KC_HAEN KC_LANG1
-#define KC_HANJ KC_LANG2
+/* Language Specific */
+#define KC_INT1 KC_INTERNATIONAL_1
+#define KC_INT2 KC_INTERNATIONAL_2
+#define KC_INT3 KC_INTERNATIONAL_3
+#define KC_INT4 KC_INTERNATIONAL_4
+#define KC_INT5 KC_INTERNATIONAL_5
+#define KC_INT6 KC_INTERNATIONAL_6
+#define KC_INT7 KC_INTERNATIONAL_7
+#define KC_INT8 KC_INTERNATIONAL_8
+#define KC_INT9 KC_INTERNATIONAL_9
+#define KC_LNG1 KC_LANGUAGE_1
+#define KC_LNG2 KC_LANGUAGE_2
+#define KC_LNG3 KC_LANGUAGE_3
+#define KC_LNG4 KC_LANGUAGE_4
+#define KC_LNG5 KC_LANGUAGE_5
+#define KC_LNG6 KC_LANGUAGE_6
+#define KC_LNG7 KC_LANGUAGE_7
+#define KC_LNG8 KC_LANGUAGE_8
+#define KC_LNG9 KC_LANGUAGE_9
/* Modifiers */
-#define KC_LCTL KC_LCTRL
-#define KC_LSFT KC_LSHIFT
-#define KC_LOPT KC_LALT
-#define KC_LCMD KC_LGUI
-#define KC_LWIN KC_LGUI
-#define KC_RCTL KC_RCTRL
-#define KC_RSFT KC_RSHIFT
-#define KC_ALGR KC_RALT
-#define KC_ROPT KC_RALT
-#define KC_RCMD KC_RGUI
-#define KC_RWIN KC_RGUI
+#define KC_LCTL KC_LEFT_CTRL
+#define KC_LSFT KC_LEFT_SHIFT
+#define KC_LALT KC_LEFT_ALT
+#define KC_LOPT KC_LEFT_ALT
+#define KC_LGUI KC_LEFT_GUI
+#define KC_LCMD KC_LEFT_GUI
+#define KC_LWIN KC_LEFT_GUI
+#define KC_RCTL KC_RIGHT_CTRL
+#define KC_RSFT KC_RIGHT_SHIFT
+#define KC_RALT KC_RIGHT_ALT
+#define KC_ALGR KC_RIGHT_ALT
+#define KC_ROPT KC_RIGHT_ALT
+#define KC_RGUI KC_RIGHT_GUI
+#define KC_RCMD KC_RIGHT_GUI
+#define KC_RWIN KC_RIGHT_GUI
/* Generic Desktop Page (0x01) */
-#define KC_PWR KC_SYSTEM_POWER
+#define KC_PWR KC_SYSTEM_POWER
#define KC_SLEP KC_SYSTEM_SLEEP
#define KC_WAKE KC_SYSTEM_WAKE
@@ -193,7 +215,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* System Specific */
#define KC_BRMU KC_PAUSE
-#define KC_BRMD KC_SCROLLLOCK
+#define KC_BRMD KC_SCROLL_LOCK
/* Mouse Keys */
#define KC_MS_U KC_MS_UP
@@ -216,6 +238,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_ACL1 KC_MS_ACCEL1
#define KC_ACL2 KC_MS_ACCEL2
+// clang-format on
+
/* Keyboard/Keypad Page (0x07) */
enum hid_keyboard_keypad_usage {
KC_NO = 0x00,
@@ -260,22 +284,22 @@ enum hid_keyboard_keypad_usage {
KC_0,
KC_ENTER,
KC_ESCAPE,
- KC_BSPACE,
+ KC_BACKSPACE,
KC_TAB,
KC_SPACE,
KC_MINUS,
KC_EQUAL,
- KC_LBRACKET,
- KC_RBRACKET, // 0x30
- KC_BSLASH,
+ KC_LEFT_BRACKET,
+ KC_RIGHT_BRACKET, // 0x30
+ KC_BACKSLASH,
KC_NONUS_HASH,
- KC_SCOLON,
+ KC_SEMICOLON,
KC_QUOTE,
KC_GRAVE,
KC_COMMA,
KC_DOT,
KC_SLASH,
- KC_CAPSLOCK,
+ KC_CAPS_LOCK,
KC_F1,
KC_F2,
KC_F3,
@@ -288,20 +312,20 @@ enum hid_keyboard_keypad_usage {
KC_F10,
KC_F11,
KC_F12,
- KC_PSCREEN,
- KC_SCROLLLOCK,
+ KC_PRINT_SCREEN,
+ KC_SCROLL_LOCK,
KC_PAUSE,
KC_INSERT,
KC_HOME,
- KC_PGUP,
+ KC_PAGE_UP,
KC_DELETE,
KC_END,
- KC_PGDOWN,
+ KC_PAGE_DOWN,
KC_RIGHT,
KC_LEFT, // 0x50
KC_DOWN,
KC_UP,
- KC_NUMLOCK,
+ KC_NUM_LOCK,
KC_KP_SLASH,
KC_KP_ASTERISK,
KC_KP_MINUS,
@@ -318,9 +342,9 @@ enum hid_keyboard_keypad_usage {
KC_KP_9,
KC_KP_0,
KC_KP_DOT,
- KC_NONUS_BSLASH,
+ KC_NONUS_BACKSLASH,
KC_APPLICATION,
- KC_POWER,
+ KC_KB_POWER,
KC_KP_EQUAL,
KC_F13,
KC_F14,
@@ -345,34 +369,34 @@ enum hid_keyboard_keypad_usage {
KC_COPY,
KC_PASTE,
KC_FIND,
- KC__MUTE,
- KC__VOLUP, // 0x80
- KC__VOLDOWN,
- KC_LOCKING_CAPS,
- KC_LOCKING_NUM,
- KC_LOCKING_SCROLL,
+ KC_KB_MUTE,
+ KC_KB_VOLUME_UP, // 0x80
+ KC_KB_VOLUME_DOWN,
+ KC_LOCKING_CAPS_LOCK,
+ KC_LOCKING_NUM_LOCK,
+ KC_LOCKING_SCROLL_LOCK,
KC_KP_COMMA,
KC_KP_EQUAL_AS400,
- KC_INT1,
- KC_INT2,
- KC_INT3,
- KC_INT4,
- KC_INT5,
- KC_INT6,
- KC_INT7,
- KC_INT8,
- KC_INT9,
- KC_LANG1, // 0x90
- KC_LANG2,
- KC_LANG3,
- KC_LANG4,
- KC_LANG5,
- KC_LANG6,
- KC_LANG7,
- KC_LANG8,
- KC_LANG9,
- KC_ALT_ERASE,
- KC_SYSREQ,
+ KC_INTERNATIONAL_1,
+ KC_INTERNATIONAL_2,
+ KC_INTERNATIONAL_3,
+ KC_INTERNATIONAL_4,
+ KC_INTERNATIONAL_5,
+ KC_INTERNATIONAL_6,
+ KC_INTERNATIONAL_7,
+ KC_INTERNATIONAL_8,
+ KC_INTERNATIONAL_9,
+ KC_LANGUAGE_1, // 0x90
+ KC_LANGUAGE_2,
+ KC_LANGUAGE_3,
+ KC_LANGUAGE_4,
+ KC_LANGUAGE_5,
+ KC_LANGUAGE_6,
+ KC_LANGUAGE_7,
+ KC_LANGUAGE_8,
+ KC_LANGUAGE_9,
+ KC_ALTERNATE_ERASE,
+ KC_SYSTEM_REQUEST,
KC_CANCEL,
KC_CLEAR,
KC_PRIOR,
@@ -397,12 +421,12 @@ enum hid_keyboard_keypad_usage {
KC_DECIMAL_SEPARATOR,
KC_CURRENCY_UNIT,
KC_CURRENCY_SUB_UNIT,
- KC_KP_LPAREN,
- KC_KP_RPAREN,
- KC_KP_LCBRACKET,
- KC_KP_RCBRACKET,
+ KC_KP_LEFT_PARENTHESIS,
+ KC_KP_RIGHT_PARENTHESIS,
+ KC_KP_LEFT_BRACE,
+ KC_KP_RIGHT_BRACE,
KC_KP_TAB,
- KC_KP_BSPACE,
+ KC_KP_BACKSPACE,
KC_KP_A,
KC_KP_B,
KC_KP_C,
@@ -411,17 +435,17 @@ enum hid_keyboard_keypad_usage {
KC_KP_F,
KC_KP_XOR,
KC_KP_HAT,
- KC_KP_PERC,
- KC_KP_LT,
- KC_KP_GT,
+ KC_KP_PERCENT,
+ KC_KP_LESS_THAN,
+ KC_KP_GREATER_THAN,
KC_KP_AND,
- KC_KP_LAZYAND,
+ KC_KP_LAZY_AND,
KC_KP_OR,
- KC_KP_LAZYOR,
+ KC_KP_LAZY_OR,
KC_KP_COLON,
KC_KP_HASH,
KC_KP_SPACE,
- KC_KP_ATMARK,
+ KC_KP_AT,
KC_KP_EXCLAMATION,
KC_KP_MEM_STORE, //0xD0
KC_KP_MEM_RECALL,
@@ -440,14 +464,14 @@ enum hid_keyboard_keypad_usage {
#endif
/* Modifiers */
- KC_LCTRL = 0xE0,
- KC_LSHIFT,
- KC_LALT,
- KC_LGUI,
- KC_RCTRL,
- KC_RSHIFT,
- KC_RALT,
- KC_RGUI
+ KC_LEFT_CTRL = 0xE0,
+ KC_LEFT_SHIFT,
+ KC_LEFT_ALT,
+ KC_LEFT_GUI,
+ KC_RIGHT_CTRL,
+ KC_RIGHT_SHIFT,
+ KC_RIGHT_ALT,
+ KC_RIGHT_GUI
// **********************************************
// * 0xF0-0xFF are unallocated in the HID spec. *
@@ -558,3 +582,5 @@ enum mouse_keys {
KC_MS_ACCEL1,
KC_MS_ACCEL2 // 0xFF
};
+
+#include "keycode_legacy.h"
diff --git a/quantum/keycode_config.c b/quantum/keycode_config.c
index f340905eab..dd2a17e242 100644
--- a/quantum/keycode_config.c
+++ b/quantum/keycode_config.c
@@ -25,89 +25,89 @@ extern keymap_config_t keymap_config;
*/
uint16_t keycode_config(uint16_t keycode) {
switch (keycode) {
- case KC_CAPSLOCK:
- case KC_LOCKING_CAPS:
+ case KC_CAPS_LOCK:
+ case KC_LOCKING_CAPS_LOCK:
if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
- return KC_LCTL;
+ return KC_LEFT_CTRL;
}
return keycode;
- case KC_LCTL:
+ case KC_LEFT_CTRL:
if (keymap_config.swap_control_capslock) {
- return KC_CAPSLOCK;
+ return KC_CAPS_LOCK;
}
if (keymap_config.swap_lctl_lgui) {
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_LGUI;
+ return KC_LEFT_GUI;
}
- return KC_LCTL;
- case KC_LALT:
+ return KC_LEFT_CTRL;
+ case KC_LEFT_ALT:
if (keymap_config.swap_lalt_lgui) {
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_LGUI;
+ return KC_LEFT_GUI;
}
- return KC_LALT;
- case KC_LGUI:
+ return KC_LEFT_ALT;
+ case KC_LEFT_GUI:
if (keymap_config.swap_lalt_lgui) {
- return KC_LALT;
+ return KC_LEFT_ALT;
}
if (keymap_config.swap_lctl_lgui) {
- return KC_LCTRL;
+ return KC_LEFT_CTRL;
}
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_LGUI;
- case KC_RCTL:
+ return KC_LEFT_GUI;
+ case KC_RIGHT_CTRL:
if (keymap_config.swap_rctl_rgui) {
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_RGUI;
+ return KC_RIGHT_GUI;
}
- return KC_RCTL;
- case KC_RALT:
+ return KC_RIGHT_CTRL;
+ case KC_RIGHT_ALT:
if (keymap_config.swap_ralt_rgui) {
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_RGUI;
+ return KC_RIGHT_GUI;
}
- return KC_RALT;
- case KC_RGUI:
+ return KC_RIGHT_ALT;
+ case KC_RIGHT_GUI:
if (keymap_config.swap_ralt_rgui) {
- return KC_RALT;
+ return KC_RIGHT_ALT;
}
if (keymap_config.swap_rctl_rgui) {
- return KC_RCTL;
+ return KC_RIGHT_CTRL;
}
if (keymap_config.no_gui) {
return KC_NO;
}
- return KC_RGUI;
+ return KC_RIGHT_GUI;
case KC_GRAVE:
if (keymap_config.swap_grave_esc) {
- return KC_ESC;
+ return KC_ESCAPE;
}
return KC_GRAVE;
- case KC_ESC:
+ case KC_ESCAPE:
if (keymap_config.swap_grave_esc) {
return KC_GRAVE;
}
- return KC_ESC;
- case KC_BSLASH:
+ return KC_ESCAPE;
+ case KC_BACKSLASH:
if (keymap_config.swap_backslash_backspace) {
- return KC_BSPACE;
+ return KC_BACKSPACE;
}
- return KC_BSLASH;
- case KC_BSPACE:
+ return KC_BACKSLASH;
+ case KC_BACKSPACE:
if (keymap_config.swap_backslash_backspace) {
- return KC_BSLASH;
+ return KC_BACKSLASH;
}
- return KC_BSPACE;
+ return KC_BACKSPACE;
default:
return keycode;
}
diff --git a/quantum/keycode_legacy.h b/quantum/keycode_legacy.h
new file mode 100644
index 0000000000..0317a05534
--- /dev/null
+++ b/quantum/keycode_legacy.h
@@ -0,0 +1,53 @@
+#pragma once
+
+// clang-format off
+
+// These keycode names have been deprecated
+
+#define KC_BSPACE KC_BACKSPACE
+#define KC_LBRACKET KC_LEFT_BRACKET
+#define KC_RBRACKET KC_RIGHT_BRACKET
+#define KC_BSLASH KC_BACKSLASH
+#define KC_SCOLON KC_SEMICOLON
+#define KC_CAPSLOCK KC_CAPS_LOCK
+#define KC_PSCREEN KC_PRINT_SCREEN
+#define KC_SCROLLLOCK KC_SCROLL_LOCK
+#define KC_PGDOWN KC_PAGE_DOWN
+#define KC_NUMLOCK KC_NUM_LOCK
+#define KC_NONUS_BSLASH KC_NONUS_BACKSLASH
+#define KC_POWER KC_KB_POWER
+#define KC__MUTE KC_KB_MUTE
+#define KC__VOLUP KC_KB_VOLUME_UP
+#define KC__VOLDOWN KC_KB_VOLUME_DOWN
+#define KC_LOCKING_CAPS KC_LOCKING_CAPS_LOCK
+#define KC_LOCKING_NUM KC_LOCKING_NUM_LOCK
+#define KC_LOCKING_SCROLL KC_LOCKING_SCROLL_LOCK
+#define KC_LANG1 KC_LANGUAGE_1
+#define KC_LANG2 KC_LANGUAGE_2
+#define KC_LANG3 KC_LANGUAGE_3
+#define KC_LANG4 KC_LANGUAGE_4
+#define KC_LANG5 KC_LANGUAGE_5
+#define KC_LANG6 KC_LANGUAGE_6
+#define KC_LANG7 KC_LANGUAGE_7
+#define KC_LANG8 KC_LANGUAGE_8
+#define KC_LANG9 KC_LANGUAGE_9
+#define KC_ALT_ERASE KC_ALTERNATE_ERASE
+#define KC_SYSREQ KC_SYSTEM_REQUEST
+
+#define KC_LCTRL KC_LEFT_CTRL
+#define KC_LSHIFT KC_LEFT_SHIFT
+#define KC_RCTRL KC_RIGHT_CTRL
+#define KC_RSHIFT KC_RIGHT_SHIFT
+
+#define KC_ZKHK KC_GRAVE
+#define KC_RO KC_INTERNATIONAL_1
+#define KC_KANA KC_INTERNATIONAL_2
+#define KC_JYEN KC_INTERNATIONAL_3
+#define KC_HENK KC_INTERNATIONAL_4
+#define KC_MHEN KC_INTERNATIONAL_5
+#define KC_HAEN KC_LANGUAGE_1
+#define KC_HANJ KC_LANGUAGE_2
+
+#define KC_CLCK KC_CAPS_LOCK
+#define KC_SLCK KC_SCROLL_LOCK
+#define KC_NLCK KC_NUM_LOCK
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index 780c71ab9b..5007f15f11 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -56,7 +56,7 @@ action_t action_for_keycode(uint16_t keycode) {
switch (keycode) {
case KC_A ... KC_EXSEL:
- case KC_LCTRL ... KC_RGUI:
+ case KC_LEFT_CTRL ... KC_RIGHT_GUI:
action.code = ACTION_KEY(keycode);
break;
#ifdef EXTRAKEY_ENABLE
@@ -72,7 +72,7 @@ action_t action_for_keycode(uint16_t keycode) {
action.code = ACTION_MOUSEKEY(keycode);
break;
#endif
- case KC_TRNS:
+ case KC_TRANSPARENT:
action.code = ACTION_TRANSPARENT;
break;
case QK_MODS ... QK_MODS_MAX:;
diff --git a/quantum/keymap_extras/keymap_korean.h b/quantum/keymap_extras/keymap_korean.h
index 23d235ef09..74be122dad 100644
--- a/quantum/keymap_extras/keymap_korean.h
+++ b/quantum/keymap_extras/keymap_korean.h
@@ -85,8 +85,8 @@
#define KR_DOT KC_DOT // .
#define KR_SLSH KC_SLSH // /
// Row 5
-#define KR_HANJ KC_LANG2 // Hanja (한자)
-#define KR_HAEN KC_LANG1 // Han ↔ Yeong (한 ↔ 영)
+#define KR_HANJ KC_LNG2 // Hanja (한자)
+#define KR_HAEN KC_LNG1 // Han ↔ Yeong (한 ↔ 영)
/* Shifted symbols
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
diff --git a/quantum/keymap_extras/keymap_steno.h b/quantum/keymap_extras/keymap_steno.h
index ab95b43fdd..310aa07409 100644
--- a/quantum/keymap_extras/keymap_steno.h
+++ b/quantum/keymap_extras/keymap_steno.h
@@ -74,8 +74,7 @@ enum steno_keycodes {
};
#ifdef STENO_COMBINEDMAP
-enum steno_combined_keycodes
-{
+enum steno_combined_keycodes {
STN_S3 = QK_STENO_COMB,
STN_TKL,
STN_PWL,
diff --git a/quantum/keymap_extras/keymap_turkish_f.h b/quantum/keymap_extras/keymap_turkish_f.h
index 226f8cbeb0..f86ef21546 100644
--- a/quantum/keymap_extras/keymap_turkish_f.h
+++ b/quantum/keymap_extras/keymap_turkish_f.h
@@ -111,7 +111,7 @@
#define TR_LPRN S(TR_8) // (
#define TR_RPRN S(TR_9) // )
#define TR_EQL S(TR_0) // =
-#define TR_QUES S(TR_ASTR) // ?
+#define TR_QUES S(TR_SLSH) // ?
#define TR_UNDS S(TR_MINS) // _
// Row 4
#define TR_RABK S(TR_LABK) // >
diff --git a/quantum/led_matrix/animations/alpha_mods_anim.h b/quantum/led_matrix/animations/alpha_mods_anim.h
index 14038cd082..4d017894a1 100644
--- a/quantum/led_matrix/animations/alpha_mods_anim.h
+++ b/quantum/led_matrix/animations/alpha_mods_anim.h
@@ -17,8 +17,8 @@ bool ALPHAS_MODS(effect_params_t* params) {
led_matrix_set_value(i, val1);
}
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_ALPHAS_MODS
+#endif // ENABLE_LED_MATRIX_ALPHAS_MODS
diff --git a/quantum/led_matrix/animations/band_anim.h b/quantum/led_matrix/animations/band_anim.h
index 5548787b88..293be4f67a 100644
--- a/quantum/led_matrix/animations/band_anim.h
+++ b/quantum/led_matrix/animations/band_anim.h
@@ -10,4 +10,4 @@ static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) {
bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_BAND
+#endif // ENABLE_LED_MATRIX_BAND
diff --git a/quantum/led_matrix/animations/band_pinwheel_anim.h b/quantum/led_matrix/animations/band_pinwheel_anim.h
index 89651582d5..f47a3869ce 100644
--- a/quantum/led_matrix/animations/band_pinwheel_anim.h
+++ b/quantum/led_matrix/animations/band_pinwheel_anim.h
@@ -7,4 +7,4 @@ static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t t
bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_BAND_PINWHEEL
+#endif // ENABLE_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 70b0ffaea9..a4bd382181 100644
--- a/quantum/led_matrix/animations/band_spiral_anim.h
+++ b/quantum/led_matrix/animations/band_spiral_anim.h
@@ -7,4 +7,4 @@ static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dis
bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_BAND_SPIRAL
+#endif // ENABLE_LED_MATRIX_BAND_SPIRAL
diff --git a/quantum/led_matrix/animations/breathing_anim.h b/quantum/led_matrix/animations/breathing_anim.h
index e3f600c45c..899925f516 100644
--- a/quantum/led_matrix/animations/breathing_anim.h
+++ b/quantum/led_matrix/animations/breathing_anim.h
@@ -12,8 +12,8 @@ bool BREATHING(effect_params_t* params) {
LED_MATRIX_TEST_LED_FLAGS();
led_matrix_set_value(i, val);
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_BREATHING
+#endif // ENABLE_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 769e6d7942..1a8999b831 100644
--- a/quantum/led_matrix/animations/cycle_left_right_anim.h
+++ b/quantum/led_matrix/animations/cycle_left_right_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { ret
bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
+#endif // ENABLE_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 6adf9c25ff..77d3a14b6f 100644
--- a/quantum/led_matrix/animations/cycle_out_in_anim.h
+++ b/quantum/led_matrix/animations/cycle_out_in_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t di
bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_CYCLE_OUT_IN
+#endif // ENABLE_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 7a5868ac26..b25947199c 100644
--- a/quantum/led_matrix/animations/cycle_up_down_anim.h
+++ b/quantum/led_matrix/animations/cycle_up_down_anim.h
@@ -7,4 +7,4 @@ static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return
bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_CYCLE_UP_DOWN
+#endif // ENABLE_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 3552c9fc39..81735e323c 100644
--- a/quantum/led_matrix/animations/dual_beacon_anim.h
+++ b/quantum/led_matrix/animations/dual_beacon_anim.h
@@ -7,4 +7,4 @@ static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i,
bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_DUAL_BEACON
+#endif // ENABLE_LED_MATRIX_DUAL_BEACON
diff --git a/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
index ef97631b90..fa9b7dbbfa 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy.h
@@ -12,5 +12,5 @@ bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) {
int16_t dy = g_led_config.point[i].y - k_led_matrix_center.y;
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, time));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
index 5ef5938be0..061a5f07fe 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_dx_dy_dist.h
@@ -13,5 +13,5 @@ bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func)
uint8_t dist = sqrt16(dx * dx + dy * dy);
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, dist, time));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/led_matrix/animations/runners/effect_runner_i.h b/quantum/led_matrix/animations/runners/effect_runner_i.h
index b3015759be..f6f8c0dee0 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_i.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_i.h
@@ -10,5 +10,5 @@ bool effect_runner_i(effect_params_t* params, i_f effect_func) {
LED_MATRIX_TEST_LED_FLAGS();
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, i, time));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/led_matrix/animations/runners/effect_runner_reactive.h b/quantum/led_matrix/animations/runners/effect_runner_reactive.h
index 4369ea8c49..be3090aa53 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_reactive.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_reactive.h
@@ -22,7 +22,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) {
uint16_t offset = scale16by8(tick, led_matrix_eeconfig.speed);
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, offset));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
index d6eb9731ee..f6ffc825a1 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_reactive_splash.h
@@ -20,7 +20,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react
}
led_matrix_set_value(i, scale8(val, led_matrix_eeconfig.val));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
index 4a5219abd1..3145e27139 100644
--- a/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
+++ b/quantum/led_matrix/animations/runners/effect_runner_sin_cos_i.h
@@ -12,5 +12,5 @@ bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) {
LED_MATRIX_TEST_LED_FLAGS();
led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, cos_value, sin_value, i, time));
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/led_matrix/animations/solid_anim.h b/quantum/led_matrix/animations/solid_anim.h
index 4c9e43c581..c728dbcc98 100644
--- a/quantum/led_matrix/animations/solid_anim.h
+++ b/quantum/led_matrix/animations/solid_anim.h
@@ -9,7 +9,7 @@ bool SOLID(effect_params_t* params) {
LED_MATRIX_TEST_LED_FLAGS();
led_matrix_set_value(i, val);
}
- return led_max < DRIVER_LED_TOTAL;
+ return led_matrix_check_finished_leds(led_max);
}
#endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/led_matrix/animations/solid_reactive_cross.h b/quantum/led_matrix/animations/solid_reactive_cross.h
index 3a3c46be13..a149e9a929 100644
--- a/quantum/led_matrix/animations/solid_reactive_cross.h
+++ b/quantum/led_matrix/animations/solid_reactive_cross.h
@@ -1,5 +1,5 @@
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
+# if defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
LED_MATRIX_EFFECT(SOLID_REACTIVE_CROSS)
@@ -31,5 +31,5 @@ bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_r
# endif
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
+# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/solid_reactive_nexus.h b/quantum/led_matrix/animations/solid_reactive_nexus.h
index 2520b8e1df..5a86e48c6c 100644
--- a/quantum/led_matrix/animations/solid_reactive_nexus.h
+++ b/quantum/led_matrix/animations/solid_reactive_nexus.h
@@ -28,5 +28,5 @@ bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_r
# endif
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
+# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/solid_reactive_simple_anim.h b/quantum/led_matrix/animations/solid_reactive_simple_anim.h
index 43f6ad9ab4..14f5e90730 100644
--- a/quantum/led_matrix/animations/solid_reactive_simple_anim.h
+++ b/quantum/led_matrix/animations/solid_reactive_simple_anim.h
@@ -8,5 +8,5 @@ static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return
bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
+# endif // ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/solid_reactive_wide.h b/quantum/led_matrix/animations/solid_reactive_wide.h
index d683b02510..3aa88063a7 100644
--- a/quantum/led_matrix/animations/solid_reactive_wide.h
+++ b/quantum/led_matrix/animations/solid_reactive_wide.h
@@ -1,5 +1,5 @@
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
+# if !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
LED_MATRIX_EFFECT(SOLID_REACTIVE_WIDE)
@@ -26,5 +26,5 @@ bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_re
# endif
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
+# endif // !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/solid_splash_anim.h b/quantum/led_matrix/animations/solid_splash_anim.h
index cf599c8fe6..17b692a09a 100644
--- a/quantum/led_matrix/animations/solid_splash_anim.h
+++ b/quantum/led_matrix/animations/solid_splash_anim.h
@@ -1,5 +1,5 @@
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_LED_MATRIX_SOLID_SPLASH) || !defined(DISABLE_LED_MATRIX_SOLID_MULTISPLASH)
+# if defined(ENABLE_LED_MATRIX_SOLID_SPLASH) || defined(ENABLE_LED_MATRIX_SOLID_MULTISPLASH)
# ifdef ENABLE_LED_MATRIX_SOLID_SPLASH
LED_MATRIX_EFFECT(SOLID_SPLASH)
@@ -26,5 +26,5 @@ bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_
# endif
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH)
+# endif // defined(ENABLE_LED_MATRIX_SPLASH) || defined(ENABLE_LED_MATRIX_MULTISPLASH)
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/led_matrix/animations/wave_left_right_anim.h b/quantum/led_matrix/animations/wave_left_right_anim.h
index c062cf968e..76487f8515 100644
--- a/quantum/led_matrix/animations/wave_left_right_anim.h
+++ b/quantum/led_matrix/animations/wave_left_right_anim.h
@@ -7,4 +7,4 @@ static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { retu
bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT
+#endif // ENABLE_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 5e612f6b6d..94710f5c6e 100644
--- a/quantum/led_matrix/animations/wave_up_down_anim.h
+++ b/quantum/led_matrix/animations/wave_up_down_anim.h
@@ -7,4 +7,4 @@ static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return
bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); }
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_LED_MATRIX_WAVE_UP_DOWN
+#endif // ENABLE_LED_MATRIX_WAVE_UP_DOWN
diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c
index 50510e49aa..be1494e884 100644
--- a/quantum/led_matrix/led_matrix.c
+++ b/quantum/led_matrix/led_matrix.c
@@ -33,14 +33,6 @@ const led_point_t k_led_matrix_center = {112, 32};
const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
#endif
-// clang-format off
-#ifndef LED_MATRIX_IMMEDIATE_EEPROM
-# define led_eeconfig_update(v) led_update_eeprom |= v
-#else
-# define led_eeconfig_update(v) if (v) eeconfig_update_led_matrix()
-#endif
-// clang-format on
-
// Generic effect runners
#include "led_matrix_runners.inc"
@@ -107,7 +99,6 @@ last_hit_t g_last_hit_tracker;
// internals
static bool suspend_state = false;
-static bool led_update_eeprom = false;
static uint8_t led_last_enable = UINT8_MAX;
static uint8_t led_last_effect = UINT8_MAX;
static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false};
@@ -127,9 +118,9 @@ static last_hit_t last_hit_buffer;
const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT;
#endif
-void eeconfig_read_led_matrix(void) { eeprom_read_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); }
+EECONFIG_DEBOUNCE_HELPER(led_matrix, EECONFIG_LED_MATRIX, led_matrix_eeconfig);
-void eeconfig_update_led_matrix(void) { eeprom_update_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); }
+void eeconfig_update_led_matrix(void) { eeconfig_flush_led_matrix(true); }
void eeconfig_update_led_matrix_default(void) {
dprintf("eeconfig_update_led_matrix_default\n");
@@ -138,7 +129,7 @@ void eeconfig_update_led_matrix_default(void) {
led_matrix_eeconfig.val = LED_MATRIX_STARTUP_VAL;
led_matrix_eeconfig.speed = LED_MATRIX_STARTUP_SPD;
led_matrix_eeconfig.flags = LED_FLAG_ALL;
- eeconfig_update_led_matrix();
+ eeconfig_flush_led_matrix(true);
}
void eeconfig_debug_led_matrix(void) {
@@ -165,20 +156,10 @@ uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l
void led_matrix_update_pwm_buffers(void) { led_matrix_driver.flush(); }
void led_matrix_set_value(int index, uint8_t value) {
-#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
- if (!is_keyboard_left() && index >= k_led_matrix_split[0])
-# ifdef USE_CIE1931_CURVE
- led_matrix_driver.set_value(index - k_led_matrix_split[0], pgm_read_byte(&CIE1931_CURVE[value]));
-# else
- led_matrix_driver.set_value(index - k_led_matrix_split[0], value);
-# endif
- else if (is_keyboard_left() && index < k_led_matrix_split[0])
-#endif
#ifdef USE_CIE1931_CURVE
- led_matrix_driver.set_value(index, pgm_read_byte(&CIE1931_CURVE[value]));
-#else
- led_matrix_driver.set_value(index, value);
+ value = pgm_read_byte(&CIE1931_CURVE[value]);
#endif
+ led_matrix_driver.set_value(index, value);
}
void led_matrix_set_value_all(uint8_t value) {
@@ -232,11 +213,11 @@ void process_led_matrix(uint8_t row, uint8_t col, bool pressed) {
}
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
-#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP)
+#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
if (led_matrix_eeconfig.mode == LED_MATRIX_TYPING_HEATMAP) {
process_led_matrix_typing_heatmap(row, col);
}
-#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP)
+#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
}
static bool led_matrix_none(effect_params_t *params) {
@@ -279,9 +260,8 @@ static void led_task_timers(void) {
}
static void led_task_sync(void) {
+ eeconfig_flush_led_matrix(false);
// next task
- if (led_update_eeprom) eeconfig_update_led_matrix();
- led_update_eeprom = false;
if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING;
}
@@ -449,7 +429,7 @@ void led_matrix_init(void) {
eeconfig_update_led_matrix_default();
}
- eeconfig_read_led_matrix();
+ eeconfig_init_led_matrix();
if (!led_matrix_eeconfig.mode) {
dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n");
eeconfig_update_led_matrix_default();
@@ -472,7 +452,7 @@ bool led_matrix_get_suspend_state(void) { return suspend_state; }
void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
led_matrix_eeconfig.enable ^= 1;
led_task_state = STARTING;
- led_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_led_matrix(write_to_eeprom);
dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable);
}
void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); }
@@ -480,7 +460,7 @@ void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); }
void led_matrix_enable(void) {
led_matrix_enable_noeeprom();
- led_eeconfig_update(true);
+ eeconfig_flag_led_matrix(true);
}
void led_matrix_enable_noeeprom(void) {
@@ -490,7 +470,7 @@ void led_matrix_enable_noeeprom(void) {
void led_matrix_disable(void) {
led_matrix_disable_noeeprom();
- led_eeconfig_update(true);
+ eeconfig_flag_led_matrix(true);
}
void led_matrix_disable_noeeprom(void) {
@@ -512,7 +492,7 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
led_matrix_eeconfig.mode = mode;
}
led_task_state = STARTING;
- led_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_led_matrix(write_to_eeprom);
dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);
}
void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); }
@@ -539,7 +519,7 @@ void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) {
return;
}
led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val;
- led_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_led_matrix(write_to_eeprom);
dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val);
}
void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); }
@@ -557,7 +537,7 @@ void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); }
void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
led_matrix_eeconfig.speed = speed;
- led_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_led_matrix(write_to_eeprom);
dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed);
}
void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); }
diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h
index a7a1c983f7..e42be64661 100644
--- a/quantum/led_matrix/led_matrix.h
+++ b/quantum/led_matrix/led_matrix.h
@@ -23,7 +23,6 @@
#include <stdbool.h>
#include "led_matrix_types.h"
#include "quantum.h"
-#include "led_matrix_legacy_enables.h"
#ifdef IS31FL3731
# include "is31fl3731-simple.h"
@@ -38,14 +37,33 @@
#endif
#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL
-# define LED_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
- uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
- if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
+# if defined(LED_MATRIX_SPLIT)
+# define LED_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
+ uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
+ if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; \
+ uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; \
+ if (is_keyboard_left() && (max > k_led_matrix_split[0])) max = k_led_matrix_split[0]; \
+ if (!(is_keyboard_left()) && (min < k_led_matrix_split[0])) min = k_led_matrix_split[0];
+# else
+# define LED_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \
+ uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; \
+ if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
+# endif
#else
-# define LED_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = 0; \
- uint8_t max = DRIVER_LED_TOTAL;
+# if defined(LED_MATRIX_SPLIT)
+# define LED_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = 0; \
+ uint8_t max = DRIVER_LED_TOTAL; \
+ const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; \
+ if (is_keyboard_left() && (max > k_led_matrix_split[0])) max = k_led_matrix_split[0]; \
+ if (!(is_keyboard_left()) && (min < k_led_matrix_split[0])) min = k_led_matrix_split[0];
+# else
+# define LED_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = 0; \
+ uint8_t max = DRIVER_LED_TOTAL;
+# endif
#endif
#define LED_MATRIX_TEST_LED_FLAGS() \
@@ -147,6 +165,18 @@ typedef struct {
void (*flush)(void);
} led_matrix_driver_t;
+static inline bool led_matrix_check_finished_leds(uint8_t led_idx) {
+#if defined(LED_MATRIX_SPLIT)
+ if (is_keyboard_left()) {
+ uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT;
+ return led_idx < k_led_matrix_split[0];
+ } else
+ return led_idx < DRIVER_LED_TOTAL;
+#else
+ return led_idx < DRIVER_LED_TOTAL;
+#endif
+}
+
extern const led_matrix_driver_t led_matrix_driver;
extern led_eeconfig_t led_matrix_eeconfig;
diff --git a/quantum/led_matrix/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c
index 1d46b2c506..2157619a0b 100644
--- a/quantum/led_matrix/led_matrix_drivers.c
+++ b/quantum/led_matrix/led_matrix_drivers.c
@@ -26,128 +26,123 @@
*/
#if defined(IS31FL3731) || defined(IS31FL3733)
-
# include "i2c_master.h"
static void init(void) {
i2c_init();
-# ifdef IS31FL3731
-# ifdef LED_DRIVER_ADDR_1
+
+# if defined(IS31FL3731)
IS31FL3731_init(LED_DRIVER_ADDR_1);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3731_init(LED_DRIVER_ADDR_2);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3731_init(LED_DRIVER_ADDR_3);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3731_init(LED_DRIVER_ADDR_4);
-# endif
-# else
-# ifdef LED_DRIVER_ADDR_1
-# ifndef LED_DRIVER_SYNC_1
-# define LED_DRIVER_SYNC_1 0
+# endif
# endif
- IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1);
# endif
-# ifdef LED_DRIVER_ADDR_2
-# ifndef LED_DRIVER_SYNC_2
+
+# elif defined(IS31FL3733)
+# if !defined(LED_DRIVER_SYNC_1)
+# define LED_DRIVER_SYNC_1 0
+# endif
+ IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1);
+# if defined(LED_DRIVER_ADDR_2)
+# if !defined(LED_DRIVER_SYNC_2)
# define LED_DRIVER_SYNC_2 0
# endif
IS31FL3733_init(LED_DRIVER_ADDR_2, LED_DRIVER_SYNC_2);
-# endif
-# ifdef LED_DRIVER_ADDR_3
-# ifndef LED_DRIVER_SYNC_3
-# define LED_DRIVER_SYNC_3 0
-# endif
+# if defined(LED_DRIVER_ADDR_3)
+# if !defined(LED_DRIVER_SYNC_3)
+# define LED_DRIVER_SYNC_3 0
+# endif
IS31FL3733_init(LED_DRIVER_ADDR_3, LED_DRIVER_SYNC_3);
-# endif
-# ifdef LED_DRIVER_ADDR_4
-# ifndef LED_DRIVER_SYNC_4
-# define LED_DRIVER_SYNC_4 0
-# endif
+# if defined(LED_DRIVER_ADDR_4)
+# if !defined(LED_DRIVER_SYNC_4)
+# define LED_DRIVER_SYNC_4 0
+# endif
IS31FL3733_init(LED_DRIVER_ADDR_4, LED_DRIVER_SYNC_4);
+# endif
+# endif
# endif
# endif
for (int index = 0; index < DRIVER_LED_TOTAL; index++) {
-# ifdef IS31FL3731
+# if defined(IS31FL3731)
IS31FL3731_set_led_control_register(index, true);
-# else
+# elif defined(IS31FL3733)
IS31FL3733_set_led_control_register(index, true);
# endif
}
+
// This actually updates the LED drivers
-# ifdef IS31FL3731
-# ifdef LED_DRIVER_ADDR_1
+# if defined(IS31FL3731)
IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_2, 1);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_3, 2);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3731_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
-# else
-# ifdef LED_DRIVER_ADDR_1
+
+# elif defined(IS31FL3733)
IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_1, 0);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_2, 1);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_3, 2);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3733_update_led_control_registers(LED_DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
# endif
}
+# if defined(IS31FL3731)
static void flush(void) {
-# ifdef IS31FL3731
-# ifdef LED_DRIVER_ADDR_1
IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3731_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
-# else
-# ifdef LED_DRIVER_ADDR_1
+}
+
+const led_matrix_driver_t led_matrix_driver = {
+ .init = init,
+ .flush = flush,
+ .set_value = IS31FL3731_set_value,
+ .set_value_all = IS31FL3731_set_value_all,
+};
+
+# elif defined(IS31FL3733)
+static void flush(void) {
IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_1, 0);
-# endif
-# ifdef LED_DRIVER_ADDR_2
+# if defined(LED_DRIVER_ADDR_2)
IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_2, 1);
-# endif
-# ifdef LED_DRIVER_ADDR_3
+# if defined(LED_DRIVER_ADDR_3)
IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_3, 2);
-# endif
-# ifdef LED_DRIVER_ADDR_4
+# if defined(LED_DRIVER_ADDR_4)
IS31FL3733_update_pwm_buffers(LED_DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
-# endif
}
const led_matrix_driver_t led_matrix_driver = {
- .init = init,
+ .init = init,
.flush = flush,
-# ifdef IS31FL3731
- .set_value = IS31FL3731_set_value,
- .set_value_all = IS31FL3731_set_value_all,
-# else
.set_value = IS31FL3733_set_value,
.set_value_all = IS31FL3733_set_value_all,
-# endif
};
-
+# endif
#endif
diff --git a/quantum/led_matrix/led_matrix_legacy_enables.h b/quantum/led_matrix/led_matrix_legacy_enables.h
deleted file mode 100644
index 7738d2f34e..0000000000
--- a/quantum/led_matrix/led_matrix_legacy_enables.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Copyright 2021 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-// to-do: remove this
-
-#pragma once
-
-#ifndef DISABLE_LED_MATRIX_ALPHAS_MODS
-# define ENABLE_LED_MATRIX_ALPHAS_MODS
-#endif
-#ifndef DISABLE_LED_MATRIX_BREATHING
-# define ENABLE_LED_MATRIX_BREATHING
-#endif
-#ifndef DISABLE_LED_MATRIX_BAND
-# define ENABLE_LED_MATRIX_BAND
-#endif
-#ifndef DISABLE_LED_MATRIX_BAND_PINWHEEL
-# define ENABLE_LED_MATRIX_BAND_PINWHEEL
-#endif
-#ifndef DISABLE_LED_MATRIX_BAND_SPIRAL
-# define ENABLE_LED_MATRIX_BAND_SPIRAL
-#endif
-#ifndef DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
-# define ENABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
-#endif
-#ifndef DISABLE_LED_MATRIX_CYCLE_UP_DOWN
-# define ENABLE_LED_MATRIX_CYCLE_UP_DOWN
-#endif
-#ifndef DISABLE_LED_MATRIX_CYCLE_OUT_IN
-# define ENABLE_LED_MATRIX_CYCLE_OUT_IN
-#endif
-#ifndef DISABLE_LED_MATRIX_DUAL_BEACON
-# define ENABLE_LED_MATRIX_DUAL_BEACON
-#endif
-#if defined(LED_MATRIX_KEYREACTIVE_ENABLED)
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS
-# endif
-# ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS
-# define ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS
-# endif
-# ifndef DISABLE_LED_MATRIX_SPLASH
-# define ENABLE_LED_MATRIX_SPLASH
-# endif
-# ifndef DISABLE_LED_MATRIX_MULTISPLASH
-# define ENABLE_LED_MATRIX_MULTISPLASH
-# endif
-#endif
-#ifndef DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT
-# define ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT
-#endif
-#ifndef DISABLE_LED_MATRIX_WAVE_UP_DOWN
-# define ENABLE_LED_MATRIX_WAVE_UP_DOWN
-#endif
diff --git a/quantum/main.c b/quantum/main.c
index 2cbcd73d8f..6ed6b95741 100644
--- a/quantum/main.c
+++ b/quantum/main.c
@@ -19,8 +19,33 @@
void platform_setup(void);
void protocol_setup(void);
-void protocol_init(void);
-void protocol_task(void);
+void protocol_pre_init(void);
+void protocol_post_init(void);
+void protocol_pre_task(void);
+void protocol_post_task(void);
+
+// Bodge as refactoring this area sucks....
+void protocol_init(void) __attribute__((weak));
+void protocol_init(void) {
+ protocol_pre_init();
+
+ keyboard_init();
+
+ protocol_post_init();
+}
+
+void protocol_task(void) __attribute__((weak));
+void protocol_task(void) {
+ protocol_pre_task();
+
+ keyboard_task();
+
+ protocol_post_task();
+}
+
+#ifdef DEFERRED_EXEC_ENABLE
+void deferred_exec_task(void);
+#endif // DEFERRED_EXEC_ENABLE
/** \brief Main
*
@@ -30,12 +55,19 @@ int main(void) __attribute__((weak));
int main(void) {
platform_setup();
protocol_setup();
+ keyboard_setup();
protocol_init();
/* Main loop */
while (true) {
protocol_task();
+
+#ifdef DEFERRED_EXEC_ENABLE
+ // Run deferred executions
+ deferred_exec_task();
+#endif // DEFERRED_EXEC_ENABLE
+
housekeeping_task();
}
}
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 33586c431b..483d518ecc 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -69,7 +69,7 @@ uint8_t thisHand, thatHand;
// user-defined overridable functions
__attribute__((weak)) void matrix_init_pins(void);
__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
-__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
+__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter);
#ifdef SPLIT_KEYBOARD
__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
__attribute__((weak)) void matrix_slave_scan_user(void) {}
@@ -113,10 +113,11 @@ __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[]
// Start with a clear matrix row
matrix_row_t current_row_value = 0;
- for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
+ matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
+ for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) {
pin_t pin = direct_pins[current_row][col_index];
if (pin != NO_PIN) {
- current_row_value |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
+ current_row_value |= readPin(pin) ? 0 : row_shifter;
}
}
@@ -169,11 +170,12 @@ __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[]
matrix_output_select_delay();
// For each col...
- for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
+ matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
+ for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) {
uint8_t pin_state = readMatrixPin(col_pins[col_index]);
// Populate the matrix row with the state of the col pin
- current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
+ current_row_value |= pin_state ? 0 : row_shifter;
}
// Unselect row
@@ -217,7 +219,7 @@ __attribute__((weak)) void matrix_init_pins(void) {
}
}
-__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
+__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter) {
bool key_pressed = false;
// Select col
@@ -231,11 +233,11 @@ __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[]
// Check row pin state
if (readMatrixPin(row_pins[row_index]) == 0) {
// Pin LO, set col bit
- current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
+ current_matrix[row_index] |= row_shifter;
key_pressed = true;
} else {
// Pin HI, clear col bit
- current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
+ current_matrix[row_index] &= ~row_shifter;
}
}
@@ -288,10 +290,8 @@ void matrix_init(void) {
matrix_init_pins();
// initialize matrix state: all keys off
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- raw_matrix[i] = 0;
- matrix[i] = 0;
- }
+ memset(matrix, 0, sizeof(matrix));
+ memset(raw_matrix, 0, sizeof(raw_matrix));
debounce_init(ROWS_PER_HAND);
@@ -312,24 +312,22 @@ __attribute__((weak)) bool transport_master_if_connected(matrix_row_t master_mat
bool matrix_post_scan(void) {
bool changed = false;
if (is_keyboard_master()) {
+ static bool last_connected = false;
matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
if (transport_master_if_connected(matrix + thisHand, slave_matrix)) {
- for (int i = 0; i < ROWS_PER_HAND; ++i) {
- if (matrix[thatHand + i] != slave_matrix[i]) {
- matrix[thatHand + i] = slave_matrix[i];
- changed = true;
- }
- }
- } else {
- // reset other half if disconnected
- for (int i = 0; i < ROWS_PER_HAND; ++i) {
- matrix[thatHand + i] = 0;
- slave_matrix[i] = 0;
- }
+ changed = memcmp(matrix + thatHand, slave_matrix, sizeof(slave_matrix)) != 0;
+ last_connected = true;
+ } else if (last_connected) {
+ // reset other half when disconnected
+ memset(slave_matrix, 0, sizeof(slave_matrix));
changed = true;
+
+ last_connected = false;
}
+ if (changed) memcpy(matrix + thatHand, slave_matrix, sizeof(slave_matrix));
+
matrix_scan_quantum();
} else {
transport_slave(matrix + thatHand, matrix + thisHand);
@@ -351,8 +349,9 @@ uint8_t matrix_scan(void) {
}
#elif (DIODE_DIRECTION == ROW2COL)
// Set col, read rows
- for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
- matrix_read_rows_on_col(curr_matrix, current_col);
+ matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
+ for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++, row_shifter <<= 1) {
+ matrix_read_rows_on_col(curr_matrix, current_col, row_shifter);
}
#endif
diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk
deleted file mode 100644
index f7eaeec8ac..0000000000
--- a/quantum/mcu_selection.mk
+++ /dev/null
@@ -1,601 +0,0 @@
-MCU_ORIG := $(MCU)
-
-ifneq ($(findstring MKL26Z64, $(MCU)),)
- # Cortex version
- MCU = cortex-m0plus
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 6
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = KINETIS
- MCU_SERIES = KL2x
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= MKL26Z64
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= kl2x
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= PJRC_TEENSY_LC
-endif
-
-ifneq ($(findstring MK20DX128, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = KINETIS
- MCU_SERIES = K20x
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= MK20DX128
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= k20x5
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= PJRC_TEENSY_3
-endif
-
-ifneq ($(findstring MK20DX256, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = KINETIS
- MCU_SERIES = K20x
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= MK20DX256
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= k20x7
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= PJRC_TEENSY_3_1
-endif
-
-ifneq ($(findstring MK66F18, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = KINETIS
- MCU_SERIES = MK66F18
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= MK66FX1M0
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= MK66F18
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= PJRC_TEENSY_3_6
-endif
-
-ifneq ($(findstring STM32F042, $(MCU)),)
- # Cortex version
- MCU = cortex-m0
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 6
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32F0xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32F042x6
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32f0xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_F042X6
-
- USE_FPU ?= no
-
- # UF2 settings
- UF2_FAMILY ?= STM32F0
-endif
-
-ifneq ($(findstring STM32F072, $(MCU)),)
- # Cortex version
- MCU = cortex-m0
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 6
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32F0xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32F072xB
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32f0xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_F072XB
-
- USE_FPU ?= no
-
- # UF2 settings
- UF2_FAMILY ?= STM32F0
-endif
-
-ifneq ($(findstring STM32F103, $(MCU)),)
- # Cortex version
- MCU = cortex-m3
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32F1xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32F103x8
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32f1xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_F103
-
- USE_FPU ?= no
-
- # UF2 settings
- UF2_FAMILY ?= STM32F1
-endif
-
-ifneq ($(findstring STM32F303, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32F3xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32F303xC
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32f3xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_F303XC
-
- USE_FPU ?= yes
-
- # UF2 settings
- UF2_FAMILY ?= STM32F3
-endif
-
-ifneq ($(findstring STM32F401, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32F4xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- ifeq ($(strip $(BOOTLOADER)), tinyuf2)
- MCU_LDSCRIPT ?= STM32F401xC_tinyuf2
- FIRMWARE_FORMAT ?= uf2
- else
- MCU_LDSCRIPT ?= STM32F401xC
- endif
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32f4xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= BLACKPILL_STM32_F401
-
- USE_FPU ?= yes
-
- # UF2 settings
- UF2_FAMILY ?= STM32F4
-endif
-
-ifneq ($(findstring STM32F407, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32F4xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32F407xE
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32f4xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_F407XE
-
- USE_FPU ?= yes
-
- # UF2 settings
- UF2_FAMILY ?= STM32F4
-endif
-
-ifneq ($(findstring STM32F411, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32F4xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- ifeq ($(strip $(BOOTLOADER)), tinyuf2)
- MCU_LDSCRIPT ?= STM32F411xE_tinyuf2
- FIRMWARE_FORMAT ?= uf2
- else
- MCU_LDSCRIPT ?= STM32F411xE
- endif
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32f4xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= BLACKPILL_STM32_F411
-
- USE_FPU ?= yes
-
- # UF2 settings
- UF2_FAMILY ?= STM32F4
-endif
-
-ifneq ($(findstring STM32F446, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32F4xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32F446xE
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32f4xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_F446XE
-
- USE_FPU ?= yes
-endif
-
-ifneq ($(findstring STM32G431, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32G4xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32G431xB
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32g4xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_G431XB
-
- USE_FPU ?= yes
-
- # UF2 settings
- UF2_FAMILY ?= STM32G4
-endif
-
-ifneq ($(findstring STM32G474, $(MCU)),)
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32G4xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32G474xE
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32g4xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_G474XE
-
- USE_FPU ?= yes
-
- # UF2 settings
- UF2_FAMILY ?= STM32G4
-endif
-
-ifneq (,$(filter $(MCU),STM32L433 STM32L443))
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32L4xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32L432xC
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32l4xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_L433XC
-
- PLATFORM_NAME ?= platform_l432
-
- USE_FPU ?= yes
-
- # UF2 settings
- UF2_FAMILY ?= STM32L4
-endif
-
-ifneq (,$(filter $(MCU),STM32L412 STM32L422))
- # Cortex version
- MCU = cortex-m4
-
- # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
- ARMV = 7
-
- ## chip/board settings
- # - the next two should match the directories in
- # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
- MCU_FAMILY = STM32
- MCU_SERIES = STM32L4xx
-
- # Linker script to use
- # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
- # or <keyboard_dir>/ld/
- MCU_LDSCRIPT ?= STM32L412xB
-
- # Startup code to use
- # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
- MCU_STARTUP ?= stm32l4xx
-
- # Board: it should exist either in <chibios>/os/hal/boards/,
- # <keyboard_dir>/boards/, or drivers/boards/
- BOARD ?= GENERIC_STM32_L412XB
-
- PLATFORM_NAME ?= platform_l432
-
- USE_FPU ?= yes
-
- # UF2 settings
- UF2_FAMILY ?= STM32L4
-endif
-
-ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287))
- PROTOCOL = LUFA
-
- # Processor frequency.
- # This will define a symbol, F_CPU, in all source code files equal to the
- # processor frequency in Hz. You can then use this symbol in your source code to
- # calculate timings. Do NOT tack on a 'UL' at the end, this will be done
- # automatically to create a 32-bit value in your source code.
- #
- # This will be an integer division of F_USB below, as it is sourced by
- # F_USB after it has run through any CPU prescalers. Note that this value
- # does not *change* the processor frequency - it should merely be updated to
- # reflect the processor speed set externally so that the code can use accurate
- # software delays.
- F_CPU ?= 16000000
-
- # LUFA specific
- #
- # Target architecture (see library "Board Types" documentation).
- ARCH = AVR8
-
- # Input clock frequency.
- # This will define a symbol, F_USB, in all source code files equal to the
- # input clock frequency (before any prescaling is performed) in Hz. This value may
- # differ from F_CPU if prescaling is used on the latter, and is required as the
- # raw input clock is fed directly to the PLL sections of the AVR for high speed
- # clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
- # at the end, this will be done automatically to create a 32-bit value in your
- # source code.
- #
- # If no clock division is performed on the input clock inside the AVR (via the
- # CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
- F_USB ?= $(F_CPU)
-
- # Interrupt driven control endpoint task
- ifeq (,$(filter $(NO_INTERRUPT_CONTROL_ENDPOINT),yes))
- OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
- endif
- ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2))
- NO_I2C = yes
- endif
-endif
-
-ifneq (,$(filter $(MCU),atmega32a))
- # MCU name for avrdude
- AVRDUDE_MCU = m32
-
- PROTOCOL = VUSB
-
- # Processor frequency.
- # This will define a symbol, F_CPU, in all source code files equal to the
- # processor frequency in Hz. You can then use this symbol in your source code to
- # calculate timings. Do NOT tack on a 'UL' at the end, this will be done
- # automatically to create a 32-bit value in your source code.
- F_CPU ?= 12000000
-endif
-
-ifneq (,$(filter $(MCU),atmega328p))
- # MCU name for avrdude
- AVRDUDE_MCU = m328p
-
- PROTOCOL = VUSB
-
- # Processor frequency.
- # This will define a symbol, F_CPU, in all source code files equal to the
- # processor frequency in Hz. You can then use this symbol in your source code to
- # calculate timings. Do NOT tack on a 'UL' at the end, this will be done
- # automatically to create a 32-bit value in your source code.
- F_CPU ?= 16000000
-endif
-
-ifneq (,$(filter $(MCU),atmega328))
- # MCU name for avrdude
- AVRDUDE_MCU = m328
-
- PROTOCOL = VUSB
-
- # Processor frequency.
- # This will define a symbol, F_CPU, in all source code files equal to the
- # processor frequency in Hz. You can then use this symbol in your source code to
- # calculate timings. Do NOT tack on a 'UL' at the end, this will be done
- # automatically to create a 32-bit value in your source code.
- F_CPU ?= 16000000
-endif
-
-ifneq (,$(filter $(MCU),attiny85))
- PROTOCOL = VUSB
-
- # Processor frequency.
- # This will define a symbol, F_CPU, in all source code files equal to the
- # processor frequency in Hz. You can then use this symbol in your source code to
- # calculate timings. Do NOT tack on a 'UL' at the end, this will be done
- # automatically to create a 32-bit value in your source code.
- F_CPU ?= 16500000
-endif
diff --git a/quantum/pointing_device.c b/quantum/pointing_device.c
index 09d889f697..2fefdb67b6 100644
--- a/quantum/pointing_device.c
+++ b/quantum/pointing_device.c
@@ -1,34 +1,57 @@
-/*
-Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <stdint.h>
-#include "report.h"
-#include "host.h"
-#include "timer.h"
-#include "print.h"
-#include "debug.h"
+/* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
+ * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2021 Dasky (@daskygit)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#include "pointing_device.h"
+#include <string.h>
+#ifdef MOUSEKEY_ENABLE
+# include "mousekey.h"
+#endif
+#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
+# error More than one rotation selected. This is not supported.
+#endif
static report_mouse_t mouseReport = {};
-__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return (new.buttons != old.buttons) || (new.x&& new.x != old.x) || (new.y&& new.y != old.y) || (new.h&& new.h != old.h) || (new.v&& new.v != old.v); }
+extern const pointing_device_driver_t pointing_device_driver;
+
+__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return memcmp(&new, &old, sizeof(new)); }
+
+__attribute__((weak)) void pointing_device_init_kb(void) {}
+__attribute__((weak)) void pointing_device_init_user(void) {}
+__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { return pointing_device_task_user(mouse_report); }
+__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return mouse_report; }
+
+__attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) {
+ if (pressed) {
+ buttons |= 1 << (button);
+ } else {
+ buttons &= ~(1 << (button));
+ }
+ return buttons;
+}
__attribute__((weak)) void pointing_device_init(void) {
- // initialize device, if that needs to be done.
+ pointing_device_driver.init();
+#ifdef POINTING_DEVICE_MOTION_PIN
+ setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
+#endif
+ pointing_device_init_kb();
+ pointing_device_init_user();
}
__attribute__((weak)) void pointing_device_send(void) {
@@ -43,20 +66,55 @@ __attribute__((weak)) void pointing_device_send(void) {
mouseReport.y = 0;
mouseReport.v = 0;
mouseReport.h = 0;
- old_report = mouseReport;
+
+ memcpy(&old_report, &mouseReport, sizeof(mouseReport));
}
__attribute__((weak)) void pointing_device_task(void) {
- // gather info and put it in:
- // mouseReport.x = 127 max -127 min
- // mouseReport.y = 127 max -127 min
- // mouseReport.v = 127 max -127 min (scroll vertical)
- // mouseReport.h = 127 max -127 min (scroll horizontal)
- // mouseReport.buttons = 0x1F (decimal 31, binary 00011111) max (bitmask for mouse buttons 1-5, 1 is rightmost, 5 is leftmost) 0x00 min
- // send the report
+ // Gather report info
+#ifdef POINTING_DEVICE_MOTION_PIN
+ if (!readPin(POINTING_DEVICE_MOTION_PIN))
+#endif
+ mouseReport = pointing_device_driver.get_report(mouseReport);
+
+ // Support rotation of the sensor data
+#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270)
+ int8_t x = mouseReport.x, y = mouseReport.y;
+# if defined(POINTING_DEVICE_ROTATION_90)
+ mouseReport.x = y;
+ mouseReport.y = -x;
+# elif defined(POINTING_DEVICE_ROTATION_180)
+ mouseReport.x = -x;
+ mouseReport.y = -y;
+# elif defined(POINTING_DEVICE_ROTATION_270)
+ mouseReport.x = -y;
+ mouseReport.y = x;
+# else
+# error "How the heck did you get here?!"
+# endif
+#endif
+ // Support Inverting the X and Y Axises
+#if defined(POINTING_DEVICE_INVERT_X)
+ mouseReport.x = -mouseReport.x;
+#endif
+#if defined(POINTING_DEVICE_INVERT_Y)
+ mouseReport.y = -mouseReport.y;
+#endif
+
+ // allow kb to intercept and modify report
+ mouseReport = pointing_device_task_kb(mouseReport);
+ // combine with mouse report to ensure that the combined is sent correctly
+#ifdef MOUSEKEY_ENABLE
+ report_mouse_t mousekey_report = mousekey_get_report();
+ mouseReport.buttons = mouseReport.buttons | mousekey_report.buttons;
+#endif
pointing_device_send();
}
report_mouse_t pointing_device_get_report(void) { return mouseReport; }
void pointing_device_set_report(report_mouse_t newMouseReport) { mouseReport = newMouseReport; }
+
+uint16_t pointing_device_get_cpi(void) { return pointing_device_driver.get_cpi(); }
+
+void pointing_device_set_cpi(uint16_t cpi) { pointing_device_driver.set_cpi(cpi); }
diff --git a/quantum/pointing_device.h b/quantum/pointing_device.h
index 56a542d545..5106c26660 100644
--- a/quantum/pointing_device.h
+++ b/quantum/pointing_device.h
@@ -21,9 +21,68 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "host.h"
#include "report.h"
+#if defined(POINTING_DEVICE_DRIVER_adns5050)
+# include "drivers/sensors/adns5050.h"
+#elif defined(POINTING_DEVICE_DRIVER_adns9800)
+# include "spi_master.h"
+# include "drivers/sensors/adns9800.h"
+#elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
+# include "analog.h"
+# include "drivers/sensors/analog_joystick.h"
+#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
+# include "drivers/sensors/cirque_pinnacle.h"
+#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
+# include "i2c_master.h"
+# include "drivers/sensors/pimoroni_trackball.h"
+// support for legacy pimoroni defines
+# ifdef PIMORONI_TRACKBALL_INVERT_X
+# define POINTING_DEVICE_INVERT_X
+# endif
+# ifdef PIMORONI_TRACKBALL_INVERT_Y
+# define POINTING_DEVICE_INVERT_Y
+# endif
+# ifdef PIMORONI_TRACKBALL_ROTATE
+# define POINTING_DEVICE_ROTATION_90
+# endif
+#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
+# include "spi_master.h"
+# include "drivers/sensors/pmw3360.h"
+#else
+void pointing_device_driver_init(void);
+report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report);
+uint16_t pointing_device_driver_get_cpi(void);
+void pointing_device_driver_set_cpi(uint16_t cpi);
+#endif
+
+typedef struct {
+ void (*init)(void);
+ report_mouse_t (*get_report)(report_mouse_t mouse_report);
+ void (*set_cpi)(uint16_t);
+ uint16_t (*get_cpi)(void);
+} pointing_device_driver_t;
+
+typedef enum {
+ POINTING_DEVICE_BUTTON1,
+ POINTING_DEVICE_BUTTON2,
+ POINTING_DEVICE_BUTTON3,
+ POINTING_DEVICE_BUTTON4,
+ POINTING_DEVICE_BUTTON5,
+ POINTING_DEVICE_BUTTON6,
+ POINTING_DEVICE_BUTTON7,
+ POINTING_DEVICE_BUTTON8,
+} pointing_device_buttons_t;
+
void pointing_device_init(void);
void pointing_device_task(void);
void pointing_device_send(void);
report_mouse_t pointing_device_get_report(void);
void pointing_device_set_report(report_mouse_t newMouseReport);
bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old);
+uint16_t pointing_device_get_cpi(void);
+void pointing_device_set_cpi(uint16_t cpi);
+
+void pointing_device_init_kb(void);
+void pointing_device_init_user(void);
+report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report);
+report_mouse_t pointing_device_task_user(report_mouse_t mouse_report);
+uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button);
diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c
new file mode 100644
index 0000000000..9ad5e76ba6
--- /dev/null
+++ b/quantum/pointing_device_drivers.c
@@ -0,0 +1,262 @@
+/* Copyright 2017 Joshua Broekhuijsen <snipeye+qmk@gmail.com>
+ * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ * Copyright 2021 Dasky (@daskygit)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pointing_device.h"
+#include "debug.h"
+#include "wait.h"
+#include "timer.h"
+#include <stddef.h>
+
+// hid mouse reports cannot exceed -127 to 127, so constrain to that value
+#define constrain_hid(amt) ((amt) < -127 ? -127 : ((amt) > 127 ? 127 : (amt)))
+
+// get_report functions should probably be moved to their respective drivers.
+#if defined(POINTING_DEVICE_DRIVER_adns5050)
+report_mouse_t adns5050_get_report(report_mouse_t mouse_report) {
+ report_adns5050_t data = adns5050_read_burst();
+
+ if (data.dx != 0 || data.dy != 0) {
+# ifdef CONSOLE_ENABLE
+ if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
+# endif
+
+ mouse_report.x = data.dx;
+ mouse_report.y = data.dy;
+ }
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = adns5050_init,
+ .get_report = adns5050_get_report,
+ .set_cpi = adns5050_set_cpi,
+ .get_cpi = adns5050_get_cpi,
+};
+// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_adns9800)
+
+report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) {
+ report_adns9800_t sensor_report = adns9800_get_report();
+
+ int8_t clamped_x = constrain_hid(sensor_report.x);
+ int8_t clamped_y = constrain_hid(sensor_report.y);
+
+ mouse_report.x = clamped_x;
+ mouse_report.y = clamped_y;
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = adns9800_init,
+ .get_report = adns9800_get_report_driver,
+ .set_cpi = adns9800_set_cpi,
+ .get_cpi = adns9800_get_cpi
+};
+// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_analog_joystick)
+report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) {
+ report_analog_joystick_t data = analog_joystick_read();
+
+# ifdef CONSOLE_ENABLE
+ if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.x, data.y);
+# endif
+
+ mouse_report.x = data.x;
+ mouse_report.y = data.y;
+
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, data.button, POINTING_DEVICE_BUTTON1);
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = analog_joystick_init,
+ .get_report = analog_joystick_get_report,
+ .set_cpi = NULL,
+ .get_cpi = NULL
+};
+// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi)
+# ifndef CIRQUE_PINNACLE_TAPPING_TERM
+# ifdef TAPPING_TERM_PER_KEY
+# include "action.h"
+# include "action_tapping.h"
+# define CIRQUE_PINNACLE_TAPPING_TERM get_tapping_term(KC_BTN1, NULL)
+# else
+# ifdef TAPPING_TERM
+# define CIRQUE_PINNACLE_TAPPING_TERM TAPPING_TERM
+# else
+# define CIRQUE_PINNACLE_TAPPING_TERM 200
+# endif
+# endif
+# endif
+# ifndef CIRQUE_PINNACLE_TOUCH_DEBOUNCE
+# define CIRQUE_PINNACLE_TOUCH_DEBOUNCE (CIRQUE_PINNACLE_TAPPING_TERM * 8)
+# endif
+
+report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) {
+ pinnacle_data_t touchData = cirque_pinnacle_read_data();
+ static uint16_t x = 0, y = 0, mouse_timer = 0;
+ int8_t report_x = 0, report_y = 0;
+ static bool is_z_down = false;
+
+ cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); // Scale coordinates to arbitrary X, Y resolution
+
+ if (x && y && touchData.xValue && touchData.yValue) {
+ report_x = (int8_t)(touchData.xValue - x);
+ report_y = (int8_t)(touchData.yValue - y);
+ }
+ x = touchData.xValue;
+ y = touchData.yValue;
+
+ if ((bool)touchData.zValue != is_z_down) {
+ is_z_down = (bool)touchData.zValue;
+ if (!touchData.zValue) {
+ if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) {
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
+ pointing_device_set_report(mouse_report);
+ pointing_device_send();
+# if TAP_CODE_DELAY > 0
+ wait_ms(TAP_CODE_DELAY);
+# endif
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
+ pointing_device_set_report(mouse_report);
+ pointing_device_send();
+ }
+ }
+ mouse_timer = timer_read();
+ }
+ if (timer_elapsed(mouse_timer) > (CIRQUE_PINNACLE_TOUCH_DEBOUNCE)) {
+ mouse_timer = 0;
+ }
+ mouse_report.x = report_x;
+ mouse_report.y = report_y;
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = cirque_pinnacle_init,
+ .get_report = cirque_pinnacle_get_report,
+ .set_cpi = cirque_pinnacle_set_scale,
+ .get_cpi = cirque_pinnacle_get_scale
+};
+// clang-format on
+
+#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
+report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) {
+ static fast_timer_t throttle = 0;
+ static uint16_t debounce = 0;
+ static uint8_t error_count = 0;
+ pimoroni_data_t pimoroni_data = {0};
+ static int16_t x_offset = 0, y_offset = 0;
+
+ if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) {
+ i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
+
+ if (status == I2C_STATUS_SUCCESS) {
+ error_count = 0;
+
+ if (!(pimoroni_data.click & 128)) {
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, false, POINTING_DEVICE_BUTTON1);
+ if (!debounce) {
+ x_offset += pimoroni_trackball_get_offsets(pimoroni_data.right, pimoroni_data.left, PIMORONI_TRACKBALL_SCALE);
+ y_offset += pimoroni_trackball_get_offsets(pimoroni_data.down, pimoroni_data.up, PIMORONI_TRACKBALL_SCALE);
+ pimoroni_trackball_adapt_values(&mouse_report.x, &x_offset);
+ pimoroni_trackball_adapt_values(&mouse_report.y, &y_offset);
+ } else {
+ debounce--;
+ }
+ } else {
+ mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1);
+ debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES;
+ }
+ } else {
+ error_count++;
+ }
+ throttle = timer_read_fast();
+ }
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = pimironi_trackball_device_init,
+ .get_report = pimorono_trackball_get_report,
+ .set_cpi = NULL,
+ .get_cpi = NULL
+};
+// clang-format on
+#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
+
+static void init(void) { pmw3360_init(); }
+
+report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) {
+ report_pmw3360_t data = pmw3360_read_burst();
+ static uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
+
+ if (data.isOnSurface && data.isMotion) {
+ // Reset timer if stopped moving
+ if (!data.isMotion) {
+ if (MotionStart != 0) MotionStart = 0;
+ return mouse_report;
+ }
+
+ // Set timer if new motion
+ if ((MotionStart == 0) && data.isMotion) {
+# ifdef CONSOLE_ENABLE
+ if (debug_mouse) dprintf("Starting motion.\n");
+# endif
+ MotionStart = timer_read();
+ }
+ mouse_report.x = constrain_hid(data.dx);
+ mouse_report.y = constrain_hid(data.dy);
+ }
+
+ return mouse_report;
+}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = init,
+ .get_report = pmw3360_get_report,
+ .set_cpi = pmw3360_set_cpi,
+ .get_cpi = pmw3360_get_cpi
+};
+// clang-format on
+#else
+__attribute__((weak)) void pointing_device_driver_init(void) {}
+__attribute__((weak)) report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { return mouse_report; }
+__attribute__((weak)) uint16_t pointing_device_driver_get_cpi(void) { return 0; }
+__attribute__((weak)) void pointing_device_driver_set_cpi(uint16_t cpi) {}
+
+// clang-format off
+const pointing_device_driver_t pointing_device_driver = {
+ .init = pointing_device_driver_init,
+ .get_report = pointing_device_driver_get_report,
+ .get_cpi = pointing_device_driver_get_cpi,
+ .set_cpi = pointing_device_driver_set_cpi
+};
+// clang-format on
+#endif
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index 5d8de56a37..bbc6367ff1 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -18,14 +18,33 @@
# include <stdbool.h>
# include <stdio.h>
-
# include "process_auto_shift.h"
-static uint16_t autoshift_time = 0;
-static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
-static uint16_t autoshift_lastkey = KC_NO;
+# ifndef AUTO_SHIFT_DISABLED_AT_STARTUP
+# define AUTO_SHIFT_STARTUP_STATE true /* enabled */
+# else
+# define AUTO_SHIFT_STARTUP_STATE false /* disabled */
+# endif
+
+// Stores the last Auto Shift key's up or down time, for evaluation or keyrepeat.
+static uint16_t autoshift_time = 0;
+# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+// Stores the last key's up or down time, to replace autoshift_time so that Tap Hold times are accurate.
+static uint16_t retroshift_time = 0;
+// Stores a possibly Retro Shift key's up or down time, as retroshift_time needs
+// to be set before the Retro Shift key is evaluated if it is interrupted by an
+// Auto Shifted key.
+static uint16_t last_retroshift_time;
+# endif
+static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
+static uint16_t autoshift_lastkey = KC_NO;
+static keyrecord_t autoshift_lastrecord;
+// Keys take 8 bits if modifiers are excluded. This records the shift state
+// when pressed for each key, so that can be passed to the release function
+// and it knows which key needs to be released (if shifted is different base).
+static uint16_t autoshift_shift_states[((1 << 8) + 15) / 16];
static struct {
- // Whether autoshift is enabled.
+ // Whether Auto Shift is enabled.
bool enabled : 1;
// Whether the last auto-shifted key was released after the timeout. This
// is used to replicate the last key for a tap-then-hold.
@@ -34,43 +53,157 @@ static struct {
bool in_progress : 1;
// Whether the auto-shifted keypress has been registered.
bool holding_shift : 1;
-} autoshift_flags = {true, false, false, false};
+ // Whether the user is holding a shift and we removed it.
+ bool cancelling_lshift : 1;
+ bool cancelling_rshift : 1;
+ // clang-format wants to remove the true for some reason.
+ // clang-format off
+} autoshift_flags = {AUTO_SHIFT_STARTUP_STATE, false, false, false, false, false};
+// clang-format on
+
+/** \brief Called on physical press, returns whether key should be added to Auto Shift */
+__attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { return false; }
+
+/** \brief Called on physical press, returns whether is Auto Shift key */
+__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+# ifndef NO_AUTO_SHIFT_ALPHA
+ case AUTO_SHIFT_ALPHA:
+# endif
+# ifndef NO_AUTO_SHIFT_NUMERIC
+ case AUTO_SHIFT_NUMERIC:
+# endif
+# ifndef NO_AUTO_SHIFT_SPECIAL
+ case AUTO_SHIFT_SPECIAL:
+# endif
+ return true;
+ }
+ return get_custom_auto_shifted_key(keycode, record);
+}
+
+/** \brief Called to check whether defines should apply if PER_KEY is set for it */
+__attribute__((weak)) bool get_auto_shift_repeat(uint16_t keycode, keyrecord_t *record) { return true; }
+__attribute__((weak)) bool get_auto_shift_no_auto_repeat(uint16_t keycode, keyrecord_t *record) { return true; }
+
+/** \brief Called when an Auto Shift key needs to be pressed */
+__attribute__((weak)) void autoshift_press_user(uint16_t keycode, bool shifted, keyrecord_t *record) {
+ if (shifted) {
+ add_weak_mods(MOD_BIT(KC_LSFT));
+ }
+ register_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode);
+}
+
+/** \brief Called when an Auto Shift key needs to be released */
+__attribute__((weak)) void autoshift_release_user(uint16_t keycode, bool shifted, keyrecord_t *record) { unregister_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode); }
+
+/** \brief Sets the shift state to use when keyrepeating, required by custom shifts */
+void set_autoshift_shift_state(uint16_t keycode, bool shifted) {
+ keycode = keycode & 0xFF;
+ if (shifted) {
+ autoshift_shift_states[keycode / 16] |= (uint16_t)1 << keycode % 16;
+ } else {
+ autoshift_shift_states[keycode / 16] &= ~((uint16_t)1 << keycode % 16);
+ }
+}
+
+/** \brief Gets the shift state to use when keyrepeating, required by custom shifts */
+bool get_autoshift_shift_state(uint16_t keycode) {
+ keycode = keycode & 0xFF;
+ return (autoshift_shift_states[keycode / 16] & (uint16_t)1 << keycode % 16) != (uint16_t)0;
+}
+
+/** \brief Restores the shift key if it was cancelled by Auto Shift */
+static void autoshift_flush_shift(void) {
+ autoshift_flags.holding_shift = false;
+ del_weak_mods(MOD_BIT(KC_LSFT));
+ if (autoshift_flags.cancelling_lshift) {
+ autoshift_flags.cancelling_lshift = false;
+ add_mods(MOD_BIT(KC_LSFT));
+ }
+ if (autoshift_flags.cancelling_rshift) {
+ autoshift_flags.cancelling_rshift = false;
+ add_mods(MOD_BIT(KC_RSFT));
+ }
+ send_keyboard_report();
+}
/** \brief Record the press of an autoshiftable key
*
* \return Whether the record should be further processed.
*/
static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) {
- if (!autoshift_flags.enabled) {
- return true;
- }
-
+ // clang-format off
+ if ((get_mods()
+# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
+ | get_oneshot_mods()
+# endif
+ ) & (~MOD_BIT(KC_LSFT))
+ ) {
+ // clang-format on
+ // Prevents keyrepeating unshifted value of key after using it in a key combo.
+ autoshift_lastkey = KC_NO;
# ifndef AUTO_SHIFT_MODIFIERS
- if (get_mods()) {
- return true;
- }
+ // We can't return true here anymore because custom unshifted values are
+ // possible and there's no good way to tell whether the press returned
+ // true upon release.
+ set_autoshift_shift_state(keycode, false);
+ autoshift_press_user(keycode, false, record);
+# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
+ set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT)));
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+# endif
+ return false;
# endif
-# ifdef AUTO_SHIFT_REPEAT
- const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
-# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
- if (!autoshift_flags.lastshifted) {
+ }
+
+ // Store record to be sent to user functions if there's no release record then.
+ autoshift_lastrecord = *record;
+ autoshift_lastrecord.event.pressed = false;
+ autoshift_lastrecord.event.time = 0;
+ // clang-format off
+# if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)
+ if (keycode == autoshift_lastkey &&
+# ifdef AUTO_SHIFT_REPEAT_PER_KEY
+ get_auto_shift_repeat(autoshift_lastkey, record) &&
# endif
- if (elapsed < TAPPING_TERM && keycode == autoshift_lastkey) {
- // Allow a tap-then-hold for keyrepeat.
- if (!autoshift_flags.lastshifted) {
- register_code(autoshift_lastkey);
- } else {
- // Simulate pressing the shift key.
- add_weak_mods(MOD_BIT(KC_LSFT));
- register_code(autoshift_lastkey);
- }
- return false;
+# if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY)
+ (
+ !autoshift_flags.lastshifted
+# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY
+ || get_auto_shift_no_auto_repeat(autoshift_lastkey, record)
+# endif
+ ) &&
+# endif
+ TIMER_DIFF_16(now, autoshift_time) <
+# ifdef TAPPING_TERM_PER_KEY
+ get_tapping_term(autoshift_lastkey, record)
+# else
+ TAPPING_TERM
+# endif
+ ) {
+ // clang-format on
+ // Allow a tap-then-hold for keyrepeat.
+ if (get_mods() & MOD_BIT(KC_LSFT)) {
+ autoshift_flags.cancelling_lshift = true;
+ del_mods(MOD_BIT(KC_LSFT));
+ }
+ if (get_mods() & MOD_BIT(KC_RSFT)) {
+ autoshift_flags.cancelling_rshift = true;
+ del_mods(MOD_BIT(KC_RSFT));
}
-# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
+ // autoshift_shift_state doesn't need to be changed.
+ autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
+ return false;
}
-# endif
# endif
+ // Use physical shift state of press event to be more like normal typing.
+# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
+ autoshift_flags.lastshifted = (get_mods() | get_oneshot_mods()) & MOD_BIT(KC_LSFT);
+ set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT)));
+# else
+ autoshift_flags.lastshifted = get_mods() & MOD_BIT(KC_LSFT);
+# endif
// Record the keycode so we can simulate it later.
autoshift_lastkey = keycode;
autoshift_time = now;
@@ -84,51 +217,70 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)
/** \brief Registers an autoshiftable key under the right conditions
*
- * If the autoshift delay has elapsed, register a shift and the key.
+ * If autoshift_timeout has elapsed, register a shift and the key.
*
- * If the autoshift key is released before the delay has elapsed, register the
+ * If the Auto Shift key is released before the delay has elapsed, register the
* key without a shift.
+ *
+ * Called on key down with keycode=KC_NO, auto-shifted key up, and timeout.
*/
-static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) {
- // Called on key down with KC_NO, auto-shifted key up, and timeout.
- if (autoshift_flags.in_progress) {
+static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, keyrecord_t *record) {
+ if (autoshift_flags.in_progress && (keycode == autoshift_lastkey || keycode == KC_NO)) {
// Process the auto-shiftable key.
autoshift_flags.in_progress = false;
-
- // Time since the initial press was recorded.
- const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
- if (elapsed < autoshift_timeout) {
- register_code(autoshift_lastkey);
- autoshift_flags.lastshifted = false;
- } else {
- // Simulate pressing the shift key.
- add_weak_mods(MOD_BIT(KC_LSFT));
- register_code(autoshift_lastkey);
- autoshift_flags.lastshifted = true;
-# if defined(AUTO_SHIFT_REPEAT) && !defined(AUTO_SHIFT_NO_AUTO_REPEAT)
- if (matrix_trigger) {
- // Prevents release.
- return;
- }
+ // clang-format off
+ autoshift_flags.lastshifted =
+ autoshift_flags.lastshifted
+ || TIMER_DIFF_16(now, autoshift_time) >=
+# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY
+ get_autoshift_timeout(autoshift_lastkey, record)
+# else
+ autoshift_timeout
# endif
+ ;
+ // clang-format on
+ set_autoshift_shift_state(autoshift_lastkey, autoshift_flags.lastshifted);
+ if (get_mods() & MOD_BIT(KC_LSFT)) {
+ autoshift_flags.cancelling_lshift = true;
+ del_mods(MOD_BIT(KC_LSFT));
+ }
+ if (get_mods() & MOD_BIT(KC_RSFT)) {
+ autoshift_flags.cancelling_rshift = true;
+ del_mods(MOD_BIT(KC_RSFT));
}
+ autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
+ // clang-format off
+# if (defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)) && (!defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY))
+ if (matrix_trigger
+# ifdef AUTO_SHIFT_REPEAT_PER_KEY
+ && get_auto_shift_repeat(autoshift_lastkey, record)
+# endif
+# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY
+ && !get_auto_shift_no_auto_repeat(autoshift_lastkey, record)
+# endif
+ ) {
+ // Prevents release.
+ return;
+ }
+# endif
+ // clang-format on
# if TAP_CODE_DELAY > 0
wait_ms(TAP_CODE_DELAY);
# endif
- unregister_code(autoshift_lastkey);
- del_weak_mods(MOD_BIT(KC_LSFT));
+
+ autoshift_release_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
+ autoshift_flush_shift();
} else {
// Release after keyrepeat.
- unregister_code(keycode);
+ autoshift_release_user(keycode, get_autoshift_shift_state(keycode), record);
if (keycode == autoshift_lastkey) {
// This will only fire when the key was the last auto-shiftable
- // pressed. That prevents aaaaBBBB then releasing a from unshifting
- // later Bs (if B wasn't auto-shiftable).
- del_weak_mods(MOD_BIT(KC_LSFT));
+ // pressed. That prevents 'aaaaBBBB' then releasing a from unshifting
+ // later 'B's (if 'B' wasn't auto-shiftable).
+ autoshift_flush_shift();
}
}
- send_keyboard_report(); // del_weak_mods doesn't send one.
// Roll the autoshift_time forward for detecting tap-and-hold.
autoshift_time = now;
}
@@ -141,24 +293,29 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) {
*/
void autoshift_matrix_scan(void) {
if (autoshift_flags.in_progress) {
- const uint16_t now = timer_read();
- const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
- if (elapsed >= autoshift_timeout) {
- autoshift_end(autoshift_lastkey, now, true);
+ const uint16_t now = timer_read();
+ if (TIMER_DIFF_16(now, autoshift_time) >=
+# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY
+ get_autoshift_timeout(autoshift_lastkey, &autoshift_lastrecord)
+# else
+ autoshift_timeout
+# endif
+ ) {
+ autoshift_end(autoshift_lastkey, now, true, &autoshift_lastrecord);
}
}
}
void autoshift_toggle(void) {
autoshift_flags.enabled = !autoshift_flags.enabled;
- del_weak_mods(MOD_BIT(KC_LSFT));
+ autoshift_flush_shift();
}
void autoshift_enable(void) { autoshift_flags.enabled = true; }
void autoshift_disable(void) {
autoshift_flags.enabled = false;
- del_weak_mods(MOD_BIT(KC_LSFT));
+ autoshift_flush_shift();
}
# ifndef AUTO_SHIFT_NO_SETUP
@@ -173,78 +330,158 @@ void autoshift_timer_report(void) {
bool get_autoshift_state(void) { return autoshift_flags.enabled; }
-uint16_t get_autoshift_timeout(void) { return autoshift_timeout; }
+uint16_t get_generic_autoshift_timeout() { return autoshift_timeout; }
+__attribute__((weak)) uint16_t get_autoshift_timeout(uint16_t keycode, keyrecord_t *record) { return autoshift_timeout; }
void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; }
bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
// Note that record->event.time isn't reliable, see:
// https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550
- const uint16_t now = timer_read();
+ // clang-format off
+ const uint16_t now =
+# if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING)
+ timer_read()
+# else
+ (record->event.pressed) ? retroshift_time : timer_read()
+# endif
+ ;
+ // clang-format on
if (record->event.pressed) {
if (autoshift_flags.in_progress) {
- // Evaluate previous key if there is one. Doing this elsewhere is
- // more complicated and easier to break.
- autoshift_end(KC_NO, now, false);
+ // Evaluate previous key if there is one.
+ autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
}
- // For pressing another key while keyrepeating shifted autoshift.
- del_weak_mods(MOD_BIT(KC_LSFT));
switch (keycode) {
case KC_ASTG:
autoshift_toggle();
- return true;
+ break;
case KC_ASON:
autoshift_enable();
- return true;
+ break;
case KC_ASOFF:
autoshift_disable();
- return true;
+ break;
# ifndef AUTO_SHIFT_NO_SETUP
case KC_ASUP:
autoshift_timeout += 5;
- return true;
+ break;
case KC_ASDN:
autoshift_timeout -= 5;
- return true;
-
+ break;
case KC_ASRP:
autoshift_timer_report();
- return true;
+ break;
# endif
}
+ // If Retro Shift is disabled, possible custom actions shouldn't happen.
+ // clang-format off
+ if (IS_RETRO(keycode)
+# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+ // Not tapped or #defines mean that rolls should use hold action.
+ && (
+ record->tap.count == 0
+# ifdef RETRO_TAPPING_PER_KEY
+ || !get_retro_tapping(keycode, record)
+# endif
+ || (record->tap.interrupted && (IS_LT(keycode)
+# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
+# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
+ ? get_hold_on_other_key_press(keycode, record)
+# else
+ ? true
+# endif
+# else
+ ? false
+# endif
+# if defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
+# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
+ : !get_ignore_mod_tap_interrupt(keycode, record)
+# else
+ : false
+# endif
+# else
+ : true
+# endif
+ ))
+ )
+# endif
+ ) {
+ // clang-format on
+ autoshift_lastkey = KC_NO;
+ return true;
+ }
+ } else {
+ if (keycode == KC_LSFT) {
+ autoshift_flags.cancelling_lshift = false;
+ } else if (keycode == KC_RSFT) {
+ autoshift_flags.cancelling_rshift = false;
+ }
+ // Same as above (for pressed), additional checks are not needed because
+ // tap.count gets set to 0 in process_action
+ // clang-format off
+ else if (IS_RETRO(keycode)
+# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+ && (
+ record->tap.count == 0
+# ifdef RETRO_TAPPING_PER_KEY
+ || !get_retro_tapping(keycode, record)
+# endif
+ )
+# endif
+ ) {
+ // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set.
+# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
+ if (autoshift_flags.in_progress
+# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
+ && !get_ignore_mod_tap_interrupt(keycode, record)
+# endif
+ ) {
+ autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
+ }
+# endif
+ // clang-format on
+ return true;
+ }
+ }
+
+ if (!autoshift_flags.enabled) {
+ return true;
}
if (get_auto_shifted_key(keycode, record)) {
if (record->event.pressed) {
return autoshift_press(keycode, now, record);
} else {
- autoshift_end(keycode, now, false);
+ autoshift_end(keycode, now, false, record);
return false;
}
}
+
+ // Prevent keyrepeating of older keys upon non-AS key event.
+ // Not commented at above returns but they serve the same function.
+ if (record->event.pressed) {
+ autoshift_lastkey = KC_NO;
+ }
return true;
}
-__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
- switch (keycode) {
-# ifndef NO_AUTO_SHIFT_ALPHA
- case KC_A ... KC_Z:
-# endif
-# ifndef NO_AUTO_SHIFT_NUMERIC
- case KC_1 ... KC_0:
-# endif
-# ifndef NO_AUTO_SHIFT_SPECIAL
-# ifndef NO_AUTO_SHIFT_TAB
- case KC_TAB:
-# endif
- case KC_MINUS ... KC_SLASH:
- case KC_NONUS_BSLASH:
-# endif
- return true;
+# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
+// Called to record time before possible delays by action_tapping_process.
+void retroshift_poll_time(keyevent_t *event) {
+ last_retroshift_time = retroshift_time;
+ retroshift_time = timer_read();
+}
+// Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it.
+void retroshift_swap_times() {
+ if (last_retroshift_time != 0 && autoshift_flags.in_progress) {
+ uint16_t temp = retroshift_time;
+ retroshift_time = last_retroshift_time;
+ last_retroshift_time = temp;
}
- return false;
}
+# endif
#endif
diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
index 00a9ab036f..ac6a143746 100644
--- a/quantum/process_keycode/process_auto_shift.h
+++ b/quantum/process_keycode/process_auto_shift.h
@@ -22,13 +22,31 @@
# define AUTO_SHIFT_TIMEOUT 175
#endif
+#define IS_LT(kc) ((kc) >= QK_LAYER_TAP && (kc) <= QK_LAYER_TAP_MAX)
+#define IS_MT(kc) ((kc) >= QK_MOD_TAP && (kc) <= QK_MOD_TAP_MAX)
+#define IS_RETRO(kc) (IS_MT(kc) || IS_LT(kc))
+#define DO_GET_AUTOSHIFT_TIMEOUT(keycode, record, ...) record
+// clang-format off
+#define AUTO_SHIFT_ALPHA KC_A ... KC_Z
+#define AUTO_SHIFT_NUMERIC KC_1 ... KC_0
+#define AUTO_SHIFT_SPECIAL \
+ KC_TAB: \
+ case KC_MINUS ... KC_SLASH: \
+ case KC_NONUS_BSLASH
+// clang-format on
+
bool process_auto_shift(uint16_t keycode, keyrecord_t *record);
+void retroshift_poll_time(keyevent_t *event);
+void retroshift_swap_times(void);
void autoshift_enable(void);
void autoshift_disable(void);
void autoshift_toggle(void);
bool get_autoshift_state(void);
-uint16_t get_autoshift_timeout(void);
+uint16_t get_generic_autoshift_timeout(void);
+// clang-format off
+uint16_t (get_autoshift_timeout)(uint16_t keycode, keyrecord_t *record);
void set_autoshift_timeout(uint16_t timeout);
void autoshift_matrix_scan(void);
-bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
+bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
+// clang-format on
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c
index e8661839c7..a050161edf 100644
--- a/quantum/process_keycode/process_combo.c
+++ b/quantum/process_keycode/process_combo.c
@@ -18,10 +18,9 @@
#include "process_combo.h"
#include "action_tapping.h"
-
#ifdef COMBO_COUNT
-__attribute__((weak)) combo_t key_combos[COMBO_COUNT];
-uint16_t COMBO_LEN = COMBO_COUNT;
+__attribute__((weak)) combo_t key_combos[COMBO_COUNT];
+uint16_t COMBO_LEN = COMBO_COUNT;
#else
extern combo_t key_combos[];
extern uint16_t COMBO_LEN;
@@ -46,64 +45,86 @@ __attribute__((weak)) bool process_combo_key_release(uint16_t combo_index, combo
#endif
#ifndef COMBO_NO_TIMER
-static uint16_t timer = 0;
+static uint16_t timer = 0;
#endif
-static bool b_combo_enable = true; // defaults to enabled
-static uint16_t longest_term = 0;
+static bool b_combo_enable = true; // defaults to enabled
+static uint16_t longest_term = 0;
typedef struct {
keyrecord_t record;
- uint16_t combo_index;
- uint16_t keycode;
+ uint16_t combo_index;
+ uint16_t keycode;
} queued_record_t;
-static uint8_t key_buffer_size = 0;
+static uint8_t key_buffer_size = 0;
static queued_record_t key_buffer[COMBO_KEY_BUFFER_LENGTH];
typedef struct {
uint16_t combo_index;
} queued_combo_t;
-static uint8_t combo_buffer_write= 0;
-static uint8_t combo_buffer_read = 0;
+static uint8_t combo_buffer_write = 0;
+static uint8_t combo_buffer_read = 0;
static queued_combo_t combo_buffer[COMBO_BUFFER_LENGTH];
#define INCREMENT_MOD(i) i = (i + 1) % COMBO_BUFFER_LENGTH
-#define COMBO_KEY_POS ((keypos_t){.col=254, .row=254})
-
+#define COMBO_KEY_POS ((keypos_t){.col = 254, .row = 254})
#ifndef EXTRA_SHORT_COMBOS
/* flags are their own elements in combo_t struct. */
-# define COMBO_ACTIVE(combo) (combo->active)
+# define COMBO_ACTIVE(combo) (combo->active)
# define COMBO_DISABLED(combo) (combo->disabled)
-# define COMBO_STATE(combo) (combo->state)
-
-# define ACTIVATE_COMBO(combo) do {combo->active = true;}while(0)
-# define DEACTIVATE_COMBO(combo) do {combo->active = false;}while(0)
-# define DISABLE_COMBO(combo) do {combo->disabled = true;}while(0)
-# define RESET_COMBO_STATE(combo) do { \
- combo->disabled = false; \
- combo->state = 0; \
-}while(0)
+# define COMBO_STATE(combo) (combo->state)
+
+# define ACTIVATE_COMBO(combo) \
+ do { \
+ combo->active = true; \
+ } while (0)
+# define DEACTIVATE_COMBO(combo) \
+ do { \
+ combo->active = false; \
+ } while (0)
+# define DISABLE_COMBO(combo) \
+ do { \
+ combo->disabled = true; \
+ } while (0)
+# define RESET_COMBO_STATE(combo) \
+ do { \
+ combo->disabled = false; \
+ combo->state = 0; \
+ } while (0)
#else
/* flags are at the two high bits of state. */
-# define COMBO_ACTIVE(combo) (combo->state & 0x80)
+# define COMBO_ACTIVE(combo) (combo->state & 0x80)
# define COMBO_DISABLED(combo) (combo->state & 0x40)
-# define COMBO_STATE(combo) (combo->state & 0x3F)
-
-# define ACTIVATE_COMBO(combo) do {combo->state |= 0x80;}while(0)
-# define DEACTIVATE_COMBO(combo) do {combo->state &= ~0x80;}while(0)
-# define DISABLE_COMBO(combo) do {combo->state |= 0x40;}while(0)
-# define RESET_COMBO_STATE(combo) do {combo->state &= ~0x7F;}while(0)
+# define COMBO_STATE(combo) (combo->state & 0x3F)
+
+# define ACTIVATE_COMBO(combo) \
+ do { \
+ combo->state |= 0x80; \
+ } while (0)
+# define DEACTIVATE_COMBO(combo) \
+ do { \
+ combo->state &= ~0x80; \
+ } while (0)
+# define DISABLE_COMBO(combo) \
+ do { \
+ combo->state |= 0x40; \
+ } while (0)
+# define RESET_COMBO_STATE(combo) \
+ do { \
+ combo->state &= ~0x7F; \
+ } while (0)
#endif
static inline void release_combo(uint16_t combo_index, combo_t *combo) {
if (combo->keycode) {
keyrecord_t record = {
- .event = {
- .key = COMBO_KEY_POS,
- .time = timer_read()|1,
- .pressed = false,
- },
+ .event =
+ {
+ .key = COMBO_KEY_POS,
+ .time = timer_read() | 1,
+ .pressed = false,
+ },
.keycode = combo->keycode,
};
#ifndef NO_ACTION_TAPPING
@@ -123,18 +144,17 @@ static inline bool _get_combo_must_hold(uint16_t combo_index, combo_t *combo) {
#elif defined(COMBO_MUST_HOLD_PER_COMBO)
return get_combo_must_hold(combo_index, combo);
#elif defined(COMBO_MUST_HOLD_MODS)
- return (KEYCODE_IS_MOD(combo->keycode) ||
- (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX));
+ return (KEYCODE_IS_MOD(combo->keycode) || (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX));
#endif
return false;
}
-static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) {
+static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo) {
if (_get_combo_must_hold(combo_index, combo)
#ifdef COMBO_MUST_TAP_PER_COMBO
- || get_combo_must_tap(combo_index, combo)
+ || get_combo_must_tap(combo_index, combo)
#endif
- ) {
+ ) {
if (longest_term < COMBO_HOLD_TERM) {
return COMBO_HOLD_TERM;
}
@@ -144,9 +164,8 @@ static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) {
}
static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) {
-
#if defined(COMBO_TERM_PER_COMBO)
- return get_combo_term(combo_index, combo);
+ return get_combo_term(combo_index, combo);
#endif
return COMBO_TERM;
@@ -154,7 +173,7 @@ static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) {
void clear_combos(void) {
uint16_t index = 0;
- longest_term = 0;
+ longest_term = 0;
for (index = 0; index < COMBO_LEN; ++index) {
combo_t *combo = &key_combos[index];
if (!COMBO_ACTIVE(combo)) {
@@ -175,7 +194,7 @@ static inline void dump_key_buffer(void) {
key_buffer_next = key_buffer_i + 1;
queued_record_t *qrecord = &key_buffer[key_buffer_i];
- keyrecord_t *record = &qrecord->record;
+ keyrecord_t * record = &qrecord->record;
if (IS_NOEVENT(record->event)) {
continue;
@@ -185,9 +204,9 @@ static inline void dump_key_buffer(void) {
process_combo_event(qrecord->combo_index, true);
} else {
#ifndef NO_ACTION_TAPPING
- action_tapping_process(*record);
+ action_tapping_process(*record);
#else
- process_record(record);
+ process_record(record);
#endif
}
record->event.time = 0;
@@ -242,7 +261,9 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
/* Apply combo's result keycode to the last chord key of the combo and
* disable the other keys. */
- if (COMBO_DISABLED(combo)) { return; }
+ if (COMBO_DISABLED(combo)) {
+ return;
+ }
// state to check against so we find the last key of the combo from the buffer
#if defined(EXTRA_EXTRA_LONG_COMBOS)
@@ -254,12 +275,11 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
#endif
for (uint8_t key_buffer_i = 0; key_buffer_i < key_buffer_size; key_buffer_i++) {
-
queued_record_t *qrecord = &key_buffer[key_buffer_i];
- keyrecord_t *record = &qrecord->record;
- uint16_t keycode = qrecord->keycode;
+ keyrecord_t * record = &qrecord->record;
+ uint16_t keycode = qrecord->keycode;
- uint8_t key_count = 0;
+ uint8_t key_count = 0;
uint16_t key_index = -1;
_find_key_index_and_count(combo->keys, keycode, &key_index, &key_count);
@@ -271,7 +291,7 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
KEY_STATE_DOWN(state, key_index);
if (ALL_COMBO_KEYS_ARE_DOWN(state, key_count)) {
// this in the end executes the combo when the key_buffer is dumped.
- record->keycode = combo->keycode;
+ record->keycode = combo->keycode;
record->event.key = COMBO_KEY_POS;
qrecord->combo_index = combo_index;
@@ -283,19 +303,15 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
// by making it a TICK event.
record->event.time = 0;
}
-
}
drop_combo_from_buffer(combo_index);
}
static inline void apply_combos(void) {
// Apply all buffered normal combos.
- for (uint8_t i = combo_buffer_read;
- i != combo_buffer_write;
- INCREMENT_MOD(i)) {
-
+ for (uint8_t i = combo_buffer_read; i != combo_buffer_write; INCREMENT_MOD(i)) {
queued_combo_t *buffered_combo = &combo_buffer[i];
- combo_t *combo = &key_combos[buffered_combo->combo_index];
+ combo_t * combo = &key_combos[buffered_combo->combo_index];
#ifdef COMBO_MUST_TAP_PER_COMBO
if (get_combo_must_tap(buffered_combo->combo_index, combo)) {
@@ -310,15 +326,15 @@ static inline void apply_combos(void) {
clear_combos();
}
-combo_t* overlaps(combo_t *combo1, combo_t *combo2) {
+combo_t *overlaps(combo_t *combo1, combo_t *combo2) {
/* Checks if the combos overlap and returns the combo that should be
* dropped from the combo buffer.
* The combo that has less keys will be dropped. If they have the same
* amount of keys, drop combo1. */
- uint8_t idx1 = 0, idx2 = 0;
+ uint8_t idx1 = 0, idx2 = 0;
uint16_t key1, key2;
- bool overlaps = false;
+ bool overlaps = false;
while ((key1 = pgm_read_word(&combo1->keys[idx1])) != COMBO_END) {
idx2 = 0;
@@ -335,7 +351,7 @@ combo_t* overlaps(combo_t *combo1, combo_t *combo2) {
}
static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record, uint16_t combo_index) {
- uint8_t key_count = 0;
+ uint8_t key_count = 0;
uint16_t key_index = -1;
_find_key_index_and_count(combo->keys, keycode, &key_index, &key_count);
@@ -369,12 +385,9 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
// disable readied combos that overlap with this combo
combo_t *drop = NULL;
- for (uint8_t combo_buffer_i = combo_buffer_read;
- combo_buffer_i != combo_buffer_write;
- INCREMENT_MOD(combo_buffer_i)) {
-
- queued_combo_t *qcombo = &combo_buffer[combo_buffer_i];
- combo_t *buffered_combo = &key_combos[qcombo->combo_index];
+ for (uint8_t combo_buffer_i = combo_buffer_read; combo_buffer_i != combo_buffer_write; INCREMENT_MOD(combo_buffer_i)) {
+ queued_combo_t *qcombo = &combo_buffer[combo_buffer_i];
+ combo_t * buffered_combo = &key_combos[qcombo->combo_index];
if ((drop = overlaps(buffered_combo, combo))) {
DISABLE_COMBO(drop);
@@ -387,21 +400,19 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
INCREMENT_MOD(combo_buffer_read);
}
}
-
}
if (drop != combo) {
// save this combo to buffer
combo_buffer[combo_buffer_write] = (queued_combo_t){
- .combo_index=combo_index,
+ .combo_index = combo_index,
};
INCREMENT_MOD(combo_buffer_write);
// get possible longer waiting time for tap-/hold-only combos.
longest_term = _get_wait_time(combo_index, combo);
}
- } // if timer elapsed end
-
+ } // if timer elapsed end
}
} else {
// chord releases
@@ -416,7 +427,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
else if (get_combo_must_tap(combo_index, combo)) {
// immediately apply tap-only combo
apply_combo(combo_index, combo);
- apply_combos(); // also apply other prepared combos and dump key buffer
+ apply_combos(); // also apply other prepared combos and dump key buffer
# ifdef COMBO_PROCESS_KEY_RELEASE
if (process_combo_key_release(combo_index, combo, key_index, keycode)) {
release_combo(combo_index, combo);
@@ -424,10 +435,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
# endif
}
#endif
- } else if (COMBO_ACTIVE(combo)
- && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo))
- && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)
- ) {
+ } else if (COMBO_ACTIVE(combo) && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo)) && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)) {
/* last key released */
release_combo(combo_index, combo);
key_is_part_of_combo = true;
@@ -435,9 +443,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
#ifdef COMBO_PROCESS_KEY_RELEASE
process_combo_key_release(combo_index, combo, key_index, keycode);
#endif
- } else if (COMBO_ACTIVE(combo)
- && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)
- ) {
+ } else if (COMBO_ACTIVE(combo) && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)) {
/* first or middle key released */
key_is_part_of_combo = true;
@@ -489,21 +495,21 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed && is_combo_key) {
#ifndef COMBO_NO_TIMER
-# ifdef COMBO_STRICT_TIMER
+# ifdef COMBO_STRICT_TIMER
if (!timer) {
// timer is set only on the first key
timer = timer_read();
}
-# else
+# else
timer = timer_read();
-# endif
+# endif
#endif
if (key_buffer_size < COMBO_KEY_BUFFER_LENGTH) {
key_buffer[key_buffer_size++] = (queued_record_t){
- .record = *record,
- .keycode = keycode,
- .combo_index = -1, // this will be set when applying combos
+ .record = *record,
+ .keycode = keycode,
+ .combo_index = -1, // this will be set when applying combos
};
}
} else {
@@ -532,7 +538,7 @@ void combo_task(void) {
if (combo_buffer_read != combo_buffer_write) {
apply_combos();
longest_term = 0;
- timer = 0;
+ timer = 0;
} else {
dump_key_buffer();
timer = 0;
@@ -546,9 +552,9 @@ void combo_enable(void) { b_combo_enable = true; }
void combo_disable(void) {
#ifndef COMBO_NO_TIMER
- timer = 0;
+ timer = 0;
#endif
- b_combo_enable = false;
+ b_combo_enable = false;
combo_buffer_read = combo_buffer_write;
clear_combos();
dump_key_buffer();
diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h
index 43c36d79e6..4c4e574e34 100644
--- a/quantum/process_keycode/process_combo.h
+++ b/quantum/process_keycode/process_combo.h
@@ -43,8 +43,8 @@ typedef struct {
#ifdef EXTRA_SHORT_COMBOS
uint8_t state;
#else
- bool disabled;
- bool active;
+ bool disabled;
+ bool active;
# if defined(EXTRA_EXTRA_LONG_COMBOS)
uint32_t state;
# elif defined(EXTRA_LONG_COMBOS)
diff --git a/quantum/process_keycode/process_dynamic_tapping_term.c b/quantum/process_keycode/process_dynamic_tapping_term.c
new file mode 100644
index 0000000000..bdc5529e33
--- /dev/null
+++ b/quantum/process_keycode/process_dynamic_tapping_term.c
@@ -0,0 +1,50 @@
+/* Copyright 2020 Vladislav Kucheriavykh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "quantum.h"
+#include "process_dynamic_tapping_term.h"
+
+#ifndef DYNAMIC_TAPPING_TERM_INCREMENT
+# define DYNAMIC_TAPPING_TERM_INCREMENT 5
+#endif
+
+static void tapping_term_report(void) {
+ const char *tapping_term_str = get_u16_str(g_tapping_term, ' ');
+ // Skip padding spaces
+ while (*tapping_term_str == ' ') {
+ tapping_term_str++;
+ }
+ send_string(tapping_term_str);
+}
+
+bool process_dynamic_tapping_term(uint16_t keycode, keyrecord_t *record) {
+ if (record->event.pressed) {
+ switch (keycode) {
+ case DT_PRNT:
+ tapping_term_report();
+ return false;
+
+ case DT_UP:
+ g_tapping_term += DYNAMIC_TAPPING_TERM_INCREMENT;
+ return false;
+
+ case DT_DOWN:
+ g_tapping_term -= DYNAMIC_TAPPING_TERM_INCREMENT;
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/quantum/visualizer/resources/resources.h b/quantum/process_keycode/process_dynamic_tapping_term.h
index 5178fbe55a..85e83ee73b 100644
--- a/quantum/visualizer/resources/resources.h
+++ b/quantum/process_keycode/process_dynamic_tapping_term.h
@@ -1,4 +1,4 @@
-/* Copyright 2017 Fred Sundvik
+/* Copyright 2020 Vladislav Kucheriavykh
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,8 +16,11 @@
#pragma once
-#include <stdint.h>
+#include <stdbool.h>
+#include "action.h"
-#ifdef LCD_ENABLE
-extern const uint8_t resource_lcd_logo[];
+#ifndef DYNAMIC_TAPPING_TERM_INCREMENT
+# define DYNAMIC_TAPPING_TERM_INCREMENT 5
#endif
+
+bool process_dynamic_tapping_term(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_haptic.c b/quantum/process_keycode/process_haptic.c
index 64d455d009..85b2ffcddd 100644
--- a/quantum/process_keycode/process_haptic.c
+++ b/quantum/process_keycode/process_haptic.c
@@ -17,6 +17,7 @@
#include "process_haptic.h"
#include "quantum_keycodes.h"
#include "action_tapping.h"
+#include "usb_device_state.h"
__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
@@ -30,8 +31,9 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
if (record->tap.count == 0) return false;
break;
- case KC_LCTRL ... KC_RGUI:
+ case KC_LEFT_CTRL ... KC_RIGHT_GUI:
case QK_MOMENTARY ... QK_MOMENTARY_MAX:
+ case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
#endif
#ifdef NO_HAPTIC_FN
case KC_FN0 ... KC_FN31:
@@ -42,34 +44,34 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t
#ifdef NO_HAPTIC_PUNCTUATION
case KC_ENTER:
case KC_ESCAPE:
- case KC_BSPACE:
+ case KC_BACKSPACE:
case KC_SPACE:
case KC_MINUS:
case KC_EQUAL:
- case KC_LBRACKET:
- case KC_RBRACKET:
- case KC_BSLASH:
+ case KC_LEFT_BRACKET:
+ case KC_RIGHT_BRACKET:
+ case KC_BACKSLASH:
case KC_NONUS_HASH:
- case KC_SCOLON:
+ case KC_SEMICOLON:
case KC_QUOTE:
case KC_GRAVE:
case KC_COMMA:
case KC_SLASH:
case KC_DOT:
- case KC_NONUS_BSLASH:
+ case KC_NONUS_BACKSLASH:
#endif
#ifdef NO_HAPTIC_LOCKKEYS
- case KC_CAPSLOCK:
- case KC_SCROLLLOCK:
- case KC_NUMLOCK:
+ case KC_CAPS_LOCK:
+ case KC_SCROLL_LOCK:
+ case KC_NUM_LOCK:
#endif
#ifdef NO_HAPTIC_NAV
- case KC_PSCREEN:
+ case KC_PRINT_SCREEN:
case KC_PAUSE:
case KC_INSERT:
case KC_DELETE:
- case KC_PGDOWN:
- case KC_PGUP:
+ case KC_PAGE_DOWN:
+ case KC_PAGE_UP:
case KC_LEFT:
case KC_UP:
case KC_RIGHT:
@@ -130,7 +132,7 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) {
}
}
- if (haptic_get_enable()) {
+ if (haptic_get_enable() && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) {
if (record->event.pressed) {
// keypress
if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) {
diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c
index 2beccbd8f9..6822c5e289 100644
--- a/quantum/process_keycode/process_music.c
+++ b/quantum/process_keycode/process_music.c
@@ -146,7 +146,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
if (music_activated || midi_activated) {
if (record->event.pressed) {
- if (keycode == KC_LCTL) { // Start recording
+ if (keycode == KC_LEFT_CTRL) { // Start recording
music_all_notes_off();
music_sequence_recording = true;
music_sequence_recorded = false;
@@ -155,7 +155,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
return false;
}
- if (keycode == KC_LALT) { // Stop recording/playing
+ if (keycode == KC_LEFT_ALT) { // Stop recording/playing
music_all_notes_off();
if (music_sequence_recording) { // was recording
music_sequence_recorded = true;
@@ -165,7 +165,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
return false;
}
- if (keycode == KC_LGUI && music_sequence_recorded) { // Start playing
+ if (keycode == KC_LEFT_GUI && music_sequence_recorded) { // Start playing
music_all_notes_off();
music_sequence_recording = false;
music_sequence_playing = true;
diff --git a/quantum/process_keycode/process_printer.c b/quantum/process_keycode/process_printer.c
index 7c5e4169a6..82528cc680 100644
--- a/quantum/process_keycode/process_printer.c
+++ b/quantum/process_keycode/process_printer.c
@@ -31,7 +31,7 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0
// uint8_t keycode_to_ascii[0xFF][2];
-// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
+// keycode_to_ascii[KC_MINUS] = {0x2D, 0x5F};
void print_char(char c) {
USB_Disable();
@@ -90,8 +90,8 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
case KC_PIPE:
case KC_TILD:
keycode &= 0xFF;
- case KC_LSFT:
- case KC_RSFT:
+ case KC_LEFT_SHIFT:
+ case KC_RIGHT_SHIFT:
if (record->event.pressed) {
character_shift++;
} else {
@@ -107,13 +107,13 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
print_box_string("This is a line of text!");
}
return false;
- case KC_ESC:
+ case KC_ESCAPE:
if (record->event.pressed) {
print_char(0x1B);
}
return false;
break;
- case KC_SPC:
+ case KC_SPACE:
if (record->event.pressed) {
print_char(0x20);
}
@@ -139,7 +139,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_ENT:
+ case KC_ENTER:
if (record->event.pressed) {
if (character_shift) {
print_char(0x0C);
@@ -149,7 +149,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_BSPC:
+ case KC_BACKSPACE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x18);
@@ -169,7 +169,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_COMM:
+ case KC_COMMA:
if (record->event.pressed) {
if (character_shift) {
print_char(0x3C);
@@ -179,7 +179,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_SLSH:
+ case KC_SLASH:
if (record->event.pressed) {
if (character_shift) {
print_char(0x3F);
@@ -189,7 +189,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_QUOT:
+ case KC_QUOTE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x22);
@@ -199,7 +199,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_GRV:
+ case KC_GRAVE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7E);
@@ -209,7 +209,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_MINS:
+ case KC_MINUS:
if (record->event.pressed) {
if (character_shift) {
print_char(0x5F);
@@ -219,7 +219,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_EQL:
+ case KC_EQUAL:
if (record->event.pressed) {
if (character_shift) {
print_char(0x2B);
@@ -229,7 +229,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_LBRC:
+ case KC_LEFT_BRACKET:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7B);
@@ -239,7 +239,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_RBRC:
+ case KC_RIGHT_BRACKET:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7D);
@@ -249,7 +249,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_BSLS:
+ case KC_BACKSLASH:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7C);
diff --git a/quantum/process_keycode/process_printer_bb.c b/quantum/process_keycode/process_printer_bb.c
index e482d82591..6c91bd27ef 100644
--- a/quantum/process_keycode/process_printer_bb.c
+++ b/quantum/process_keycode/process_printer_bb.c
@@ -45,7 +45,7 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0
// uint8_t keycode_to_ascii[0xFF][2];
-// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
+// keycode_to_ascii[KC_MINUS] = {0x2D, 0x5F};
void print_char(char c) {
uint8_t b = 8;
@@ -84,8 +84,8 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
case KC_PIPE:
case KC_TILD:
keycode &= 0xFF;
- case KC_LSFT:
- case KC_RSFT:
+ case KC_LEFT_SHIFT:
+ case KC_RIGHT_SHIFT:
if (record->event.pressed) {
character_shift++;
} else {
@@ -101,13 +101,13 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
print_string("This is a line of text!\n\n\n");
}
return false;
- case KC_ESC:
+ case KC_ESCAPE:
if (record->event.pressed) {
print_char(0x1B);
}
return false;
break;
- case KC_SPC:
+ case KC_SPACE:
if (record->event.pressed) {
print_char(0x20);
}
@@ -133,7 +133,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_ENT:
+ case KC_ENTER:
if (record->event.pressed) {
if (character_shift) {
print_char(0x0C);
@@ -143,7 +143,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_BSPC:
+ case KC_BACKSPACE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x18);
@@ -163,7 +163,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_COMM:
+ case KC_COMMA:
if (record->event.pressed) {
if (character_shift) {
print_char(0x3C);
@@ -173,7 +173,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_SLSH:
+ case KC_SLASH:
if (record->event.pressed) {
if (character_shift) {
print_char(0x3F);
@@ -183,7 +183,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_QUOT:
+ case KC_QUOTE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x22);
@@ -193,7 +193,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_GRV:
+ case KC_GRAVE:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7E);
@@ -203,7 +203,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_MINS:
+ case KC_MINUS:
if (record->event.pressed) {
if (character_shift) {
print_char(0x5F);
@@ -213,7 +213,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_EQL:
+ case KC_EQUAL:
if (record->event.pressed) {
if (character_shift) {
print_char(0x2B);
@@ -223,7 +223,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_LBRC:
+ case KC_LEFT_BRACKET:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7B);
@@ -233,7 +233,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_RBRC:
+ case KC_RIGHT_BRACKET:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7D);
@@ -243,7 +243,7 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
}
return false;
break;
- case KC_BSLS:
+ case KC_BACKSLASH:
if (record->event.pressed) {
if (character_shift) {
print_char(0x7C);
diff --git a/quantum/process_keycode/process_programmable_button.c b/quantum/process_keycode/process_programmable_button.c
new file mode 100644
index 0000000000..c6e77faacc
--- /dev/null
+++ b/quantum/process_keycode/process_programmable_button.c
@@ -0,0 +1,31 @@
+/*
+Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "process_programmable_button.h"
+#include "programmable_button.h"
+
+bool process_programmable_button(uint16_t keycode, keyrecord_t *record) {
+ if (keycode >= PROGRAMMABLE_BUTTON_MIN && keycode <= PROGRAMMABLE_BUTTON_MAX) {
+ uint8_t button = keycode - PROGRAMMABLE_BUTTON_MIN + 1;
+ if (record->event.pressed) {
+ programmable_button_on(button);
+ } else {
+ programmable_button_off(button);
+ }
+ }
+ return true;
+}
diff --git a/quantum/process_keycode/process_programmable_button.h b/quantum/process_keycode/process_programmable_button.h
new file mode 100644
index 0000000000..47c6ce5614
--- /dev/null
+++ b/quantum/process_keycode/process_programmable_button.h
@@ -0,0 +1,23 @@
+/*
+Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include <stdint.h>
+#include "quantum.h"
+
+bool process_programmable_button(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_space_cadet.c b/quantum/process_keycode/process_space_cadet.c
index f99db2a87b..46b2648c35 100644
--- a/quantum/process_keycode/process_space_cadet.c
+++ b/quantum/process_keycode/process_space_cadet.c
@@ -27,53 +27,53 @@
// Shift / Enter setup
#ifndef SFTENT_KEY
-# define SFTENT_KEY KC_ENT
+# define SFTENT_KEY KC_ENTER
#endif
#ifdef DISABLE_SPACE_CADET_MODIFIER
# ifndef LSPO_MOD
-# define LSPO_MOD KC_TRNS
+# define LSPO_MOD KC_TRANSPARENT
# endif
# ifndef RSPC_MOD
-# define RSPC_MOD KC_TRNS
+# define RSPC_MOD KC_TRANSPARENT
# endif
#else
# ifndef LSPO_MOD
-# define LSPO_MOD KC_LSFT
+# define LSPO_MOD KC_LEFT_SHIFT
# endif
# ifndef RSPC_MOD
-# define RSPC_MOD KC_RSFT
+# define RSPC_MOD KC_RIGHT_SHIFT
# endif
#endif
// **********************************************************
// Shift / paren setup
#ifndef LSPO_KEYS
-# define LSPO_KEYS KC_LSFT, LSPO_MOD, LSPO_KEY
+# define LSPO_KEYS KC_LEFT_SHIFT, LSPO_MOD, LSPO_KEY
#endif
#ifndef RSPC_KEYS
-# define RSPC_KEYS KC_RSFT, RSPC_MOD, RSPC_KEY
+# define RSPC_KEYS KC_RIGHT_SHIFT, RSPC_MOD, RSPC_KEY
#endif
// Control / paren setup
#ifndef LCPO_KEYS
-# define LCPO_KEYS KC_LCTL, KC_LSFT, KC_9
+# define LCPO_KEYS KC_LEFT_CTRL, KC_LEFT_SHIFT, KC_9
#endif
#ifndef RCPC_KEYS
-# define RCPC_KEYS KC_RCTL, KC_RSFT, KC_0
+# define RCPC_KEYS KC_RIGHT_CTRL, KC_RIGHT_SHIFT, KC_0
#endif
// Alt / paren setup
#ifndef LAPO_KEYS
-# define LAPO_KEYS KC_LALT, KC_LSFT, KC_9
+# define LAPO_KEYS KC_LEFT_ALT, KC_LEFT_SHIFT, KC_9
#endif
#ifndef RAPC_KEYS
-# define RAPC_KEYS KC_RALT, KC_RSFT, KC_0
+# define RAPC_KEYS KC_RIGHT_ALT, KC_RIGHT_SHIFT, KC_0
#endif
// Shift / Enter setup
#ifndef SFTENT_KEYS
-# define SFTENT_KEYS KC_RSFT, KC_TRNS, SFTENT_KEY
+# define SFTENT_KEYS KC_RIGHT_SHIFT, KC_TRANSPARENT, SFTENT_KEY
#endif
static uint8_t sc_last = 0;
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index a964aead35..5d0bb313b4 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -67,7 +67,7 @@ static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM,
#ifdef STENO_COMBINEDMAP
/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */
-static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
+static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U};
#endif
@@ -174,11 +174,10 @@ bool process_steno(uint16_t keycode, keyrecord_t *record) {
return false;
#ifdef STENO_COMBINEDMAP
- case QK_STENO_COMB ... QK_STENO_COMB_MAX:
- {
+ case QK_STENO_COMB ... QK_STENO_COMB_MAX: {
uint8_t result;
- result = process_steno(combinedmap_first[keycode-QK_STENO_COMB], record);
- result &= process_steno(combinedmap_second[keycode-QK_STENO_COMB], record);
+ result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
+ result &= process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
return result;
}
#endif
diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c
index 7d1eefa9ed..a059f3a521 100644
--- a/quantum/process_keycode/process_terminal.c
+++ b/quantum/process_keycode/process_terminal.c
@@ -257,12 +257,12 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
process_terminal_command();
return false;
break;
- case KC_ESC:
+ case KC_ESCAPE:
SEND_STRING("\n");
enable_terminal();
return false;
break;
- case KC_BSPC:
+ case KC_BACKSPACE:
str_len = strlen(buffer);
if (str_len > 0) {
buffer[str_len - 1] = 0;
@@ -284,7 +284,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
str_len = strlen(buffer);
for (int i = 0; i < str_len; ++i) {
send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
- // process_terminal(KC_BSPC,record);
+ // process_terminal(KC_BACKSPACE,record);
}
strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 80);
@@ -299,7 +299,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
str_len = strlen(buffer);
for (int i = 0; i < str_len; ++i) {
send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
- // process_terminal(KC_BSPC,record);
+ // process_terminal(KC_BACKSPACE,record);
}
strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 79);
@@ -311,7 +311,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
default:
if (keycode <= 58) {
char_to_add = 0;
- if (get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) {
+ if (get_mods() & (MOD_BIT(KC_LEFT_SHIFT) | MOD_BIT(KC_RIGHT_SHIFT))) {
char_to_add = shifted_keycode_to_ascii_lut[keycode];
} else if (get_mods() == 0) {
char_to_add = keycode_to_ascii_lut[keycode];
diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c
index 12b0aba9bf..d084d2b66c 100644
--- a/quantum/process_keycode/process_ucis.c
+++ b/quantum/process_keycode/process_ucis.c
@@ -46,7 +46,7 @@ static bool is_uni_seq(char *seq) {
return false;
}
}
- return qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC;
+ return qk_ucis_state.codes[i] == KC_ENTER || qk_ucis_state.codes[i] == KC_SPACE;
}
__attribute__((weak)) void qk_ucis_symbol_fallback(void) {
@@ -72,7 +72,7 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
return true;
}
- bool special = keycode == KC_SPC || keycode == KC_ENT || keycode == KC_ESC || keycode == KC_BSPC;
+ bool special = keycode == KC_SPACE || keycode == KC_ENTER || keycode == KC_ESCAPE || keycode == KC_BACKSPACE;
if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) {
return false;
}
@@ -81,7 +81,7 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
qk_ucis_state.count++;
switch (keycode) {
- case KC_BSPC:
+ case KC_BACKSPACE:
if (qk_ucis_state.count >= 2) {
qk_ucis_state.count -= 2;
return true;
@@ -90,16 +90,16 @@ bool process_ucis(uint16_t keycode, keyrecord_t *record) {
return false;
}
- case KC_SPC:
- case KC_ENT:
- case KC_ESC:
+ case KC_SPACE:
+ case KC_ENTER:
+ case KC_ESCAPE:
for (uint8_t i = 0; i < qk_ucis_state.count; i++) {
- register_code(KC_BSPC);
- unregister_code(KC_BSPC);
+ register_code(KC_BACKSPACE);
+ unregister_code(KC_BACKSPACE);
wait_ms(UNICODE_TYPE_DELAY);
}
- if (keycode == KC_ESC) {
+ if (keycode == KC_ESCAPE) {
qk_ucis_state.in_progress = false;
qk_ucis_cancel();
return false;
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
index 46fcaaa86b..7685bb1c99 100644
--- a/quantum/process_keycode/process_unicode_common.c
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -22,6 +22,7 @@
unicode_config_t unicode_config;
uint8_t unicode_saved_mods;
bool unicode_saved_caps_lock;
+bool unicode_saved_num_lock;
#if UNICODE_SELECTED_MODES != -1
static uint8_t selected[] = {UNICODE_SELECTED_MODES};
@@ -79,13 +80,14 @@ void persist_unicode_input_mode(void) { eeprom_update_byte(EECONFIG_UNICODEMODE,
__attribute__((weak)) void unicode_input_start(void) {
unicode_saved_caps_lock = host_keyboard_led_state().caps_lock;
+ unicode_saved_num_lock = host_keyboard_led_state().num_lock;
// Note the order matters here!
// Need to do this before we mess around with the mods, or else
// UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work
// correctly in the shifted case.
if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) {
- tap_code(KC_CAPS);
+ tap_code(KC_CAPS_LOCK);
}
unicode_saved_mods = get_mods(); // Save current mods
@@ -99,8 +101,13 @@ __attribute__((weak)) void unicode_input_start(void) {
tap_code16(UNICODE_KEY_LNX);
break;
case UC_WIN:
- register_code(KC_LALT);
- tap_code(KC_PPLS);
+ // For increased reliability, use numpad keys for inputting digits
+ if (!unicode_saved_num_lock) {
+ tap_code(KC_NUM_LOCK);
+ }
+ register_code(KC_LEFT_ALT);
+ wait_ms(UNICODE_TYPE_DELAY);
+ tap_code(KC_KP_PLUS);
break;
case UC_WINC:
tap_code(UNICODE_KEY_WINC);
@@ -117,13 +124,16 @@ __attribute__((weak)) void unicode_input_finish(void) {
unregister_code(UNICODE_KEY_MAC);
break;
case UC_LNX:
- tap_code(KC_SPC);
+ tap_code(KC_SPACE);
if (unicode_saved_caps_lock) {
- tap_code(KC_CAPS);
+ tap_code(KC_CAPS_LOCK);
}
break;
case UC_WIN:
- unregister_code(KC_LALT);
+ unregister_code(KC_LEFT_ALT);
+ if (!unicode_saved_num_lock) {
+ tap_code(KC_NUM_LOCK);
+ }
break;
case UC_WINC:
tap_code(KC_ENTER);
@@ -139,26 +149,44 @@ __attribute__((weak)) void unicode_input_cancel(void) {
unregister_code(UNICODE_KEY_MAC);
break;
case UC_LNX:
- tap_code(KC_ESC);
+ tap_code(KC_ESCAPE);
if (unicode_saved_caps_lock) {
- tap_code(KC_CAPS);
+ tap_code(KC_CAPS_LOCK);
}
break;
case UC_WINC:
- tap_code(KC_ESC);
+ tap_code(KC_ESCAPE);
break;
case UC_WIN:
- unregister_code(KC_LALT);
+ unregister_code(KC_LEFT_ALT);
+ if (!unicode_saved_num_lock) {
+ tap_code(KC_NUM_LOCK);
+ }
break;
}
set_mods(unicode_saved_mods); // Reregister previously set mods
}
+// clang-format off
+
+static void send_nibble_wrapper(uint8_t digit) {
+ if (unicode_config.input_mode == UC_WIN) {
+ uint8_t kc = digit < 10
+ ? KC_KP_1 + (10 + digit - 1) % 10
+ : KC_A + (digit - 10);
+ tap_code(kc);
+ return;
+ }
+ send_nibble(digit);
+}
+
+// clang-format on
+
void register_hex(uint16_t hex) {
for (int i = 3; i >= 0; i--) {
uint8_t digit = ((hex >> (i * 4)) & 0xF);
- send_nibble(digit);
+ send_nibble_wrapper(digit);
}
}
@@ -171,10 +199,10 @@ void register_hex32(uint32_t hex) {
uint8_t digit = ((hex >> (i * 4)) & 0xF);
if (digit == 0) {
if (!onzerostart) {
- send_nibble(digit);
+ send_nibble_wrapper(digit);
}
} else {
- send_nibble(digit);
+ send_nibble_wrapper(digit);
onzerostart = false;
}
}
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
index c10e171ec3..72defb445e 100644
--- a/quantum/process_keycode/process_unicode_common.h
+++ b/quantum/process_keycode/process_unicode_common.h
@@ -24,13 +24,13 @@
// Keycodes used for starting Unicode input on different platforms
#ifndef UNICODE_KEY_MAC
-# define UNICODE_KEY_MAC KC_LALT
+# define UNICODE_KEY_MAC KC_LEFT_ALT
#endif
#ifndef UNICODE_KEY_LNX
# define UNICODE_KEY_LNX LCTL(LSFT(KC_U))
#endif
#ifndef UNICODE_KEY_WINC
-# define UNICODE_KEY_WINC KC_RALT
+# define UNICODE_KEY_WINC KC_RIGHT_ALT
#endif
// Comma-delimited, ordered list of input modes selected for use (e.g. in cycle)
diff --git a/quantum/programmable_button.c b/quantum/programmable_button.c
new file mode 100644
index 0000000000..be828fd17c
--- /dev/null
+++ b/quantum/programmable_button.c
@@ -0,0 +1,37 @@
+/*
+Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "programmable_button.h"
+#include "host.h"
+
+#define REPORT_BIT(index) (((uint32_t)1) << (index - 1))
+
+static uint32_t programmable_button_report = 0;
+
+void programmable_button_clear(void) { programmable_button_report = 0; }
+
+void programmable_button_send(void) { host_programmable_button_send(programmable_button_report); }
+
+void programmable_button_on(uint8_t index) { programmable_button_report |= REPORT_BIT(index); }
+
+void programmable_button_off(uint8_t index) { programmable_button_report &= ~REPORT_BIT(index); }
+
+bool programmable_button_is_on(uint8_t index) { return !!(programmable_button_report & REPORT_BIT(index)); };
+
+uint32_t programmable_button_get_report(void) { return programmable_button_report; };
+
+void programmable_button_set_report(uint32_t report) { programmable_button_report = report; }
diff --git a/quantum/programmable_button.h b/quantum/programmable_button.h
new file mode 100644
index 0000000000..e89b8b9fd6
--- /dev/null
+++ b/quantum/programmable_button.h
@@ -0,0 +1,30 @@
+/*
+Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "report.h"
+
+void programmable_button_clear(void);
+void programmable_button_send(void);
+void programmable_button_on(uint8_t index);
+void programmable_button_off(uint8_t index);
+bool programmable_button_is_on(uint8_t index);
+uint32_t programmable_button_get_report(void);
+void programmable_button_set_report(uint32_t report);
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 14f25597ca..5568c54703 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -26,10 +26,6 @@
# include "backlight.h"
#endif
-#ifdef API_ENABLE
-# include "api.h"
-#endif
-
#ifdef MIDI_ENABLE
# include "process_midi.h"
#endif
@@ -67,15 +63,15 @@ uint8_t extract_mod_bits(uint16_t code) {
uint8_t mods_to_send = 0;
if (code & QK_RMODS_MIN) { // Right mod flag is set
- if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RCTL);
- if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RSFT);
- if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RALT);
- if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RGUI);
+ if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RIGHT_CTRL);
+ if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RIGHT_SHIFT);
+ if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RIGHT_ALT);
+ if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RIGHT_GUI);
} else {
- if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LCTL);
- if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LSFT);
- if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LALT);
- if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LGUI);
+ if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LEFT_CTRL);
+ if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LEFT_SHIFT);
+ if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LEFT_ALT);
+ if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LEFT_GUI);
}
return mods_to_send;
@@ -146,12 +142,13 @@ void reset_keyboard(void) {
/* Convert record into usable keycode via the contained event. */
uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) {
#ifdef COMBO_ENABLE
- if (record->keycode) { return record->keycode; }
+ if (record->keycode) {
+ return record->keycode;
+ }
#endif
return get_event_keycode(record->event, update_layer_cache);
}
-
/* Convert event into usable keycode. Checks the layer cache to ensure that it
* retains the correct keycode after a layer change, if the key is still pressed.
* "update_layer_cache" is to ensure that it only updates the layer cache when
@@ -180,12 +177,12 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) {
bool pre_process_record_quantum(keyrecord_t *record) {
if (!(
#ifdef COMBO_ENABLE
- process_combo(get_record_keycode(record, true), record) &&
+ process_combo(get_record_keycode(record, true), record) &&
#endif
- true)) {
+ true)) {
return false;
}
- return true; // continue processing
+ return true; // continue processing
}
/* Get keycode, and then call keyboard function */
@@ -282,6 +279,9 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef AUTO_SHIFT_ENABLE
process_auto_shift(keycode, record) &&
#endif
+#ifdef DYNAMIC_TAPPING_TERM_ENABLE
+ process_dynamic_tapping_term(keycode, record) &&
+#endif
#ifdef TERMINAL_ENABLE
process_terminal(keycode, record) &&
#endif
@@ -300,6 +300,9 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef JOYSTICK_ENABLE
process_joystick(keycode, record) &&
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+ process_programmable_button(keycode, record) &&
+#endif
true)) {
return false;
}
@@ -479,14 +482,6 @@ void matrix_scan_quantum() {
# include "hd44780.h"
#endif
-void api_send_unicode(uint32_t unicode) {
-#ifdef API_ENABLE
- uint8_t chunk[4];
- dword_to_bytes(unicode, chunk);
- MT_SEND_DATA(DT_UNICODE, chunk, 5);
-#endif
-}
-
//------------------------------------------------------------------------------
// Override these functions in your keymap file to play different tunes on
// different events such as startup and bootloader jump
@@ -500,10 +495,166 @@ __attribute__((weak)) bool webusb_receive_user(uint8_t *data, uint8_t length) {
__attribute__((weak)) bool webusb_receive_kb(uint8_t *data, uint8_t length) { return webusb_receive_user(data, length); }
bool webusb_receive_quantum(uint8_t *data, uint8_t length) {
-#ifdef ORYX_ENABLE
+# ifdef ORYX_ENABLE
return webusb_receive_oryx(data, length);
-#else
+# else
return webusb_receive_kb(data, length);
+# endif
+}
+#endif
+
+/** \brief Run keyboard level Power down
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_power_down_user(void) {}
+/** \brief Run keyboard level Power down
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
+
+void suspend_power_down_quantum(void) {
+#ifndef NO_SUSPEND_POWER_DOWN
+// Turn off backlight
+# ifdef BACKLIGHT_ENABLE
+ backlight_set(0);
+# endif
+
+# ifdef LED_MATRIX_ENABLE
+ led_matrix_task();
+# endif
+# ifdef RGB_MATRIX_ENABLE
+ rgb_matrix_task();
+# endif
+
+ // Turn off LED indicators
+ uint8_t leds_off = 0;
+# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
+ if (is_backlight_enabled()) {
+ // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
+ leds_off |= (1 << USB_LED_CAPS_LOCK);
+ }
+# endif
+ led_set(leds_off);
+
+// Turn off audio
+# ifdef AUDIO_ENABLE
+ stop_all_notes();
+# endif
+
+// Turn off underglow
+# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
+ rgblight_suspend();
+# endif
+
+# if defined(LED_MATRIX_ENABLE)
+ led_matrix_set_suspend_state(true);
+# endif
+# if defined(RGB_MATRIX_ENABLE)
+ rgb_matrix_set_suspend_state(true);
+# endif
+
+# ifdef OLED_ENABLE
+ oled_off();
+# endif
+# ifdef ST7565_ENABLE
+ st7565_off();
+# endif
+# if defined(POINTING_DEVICE_ENABLE)
+ // run to ensure scanning occurs while suspended
+ pointing_device_task();
+# endif
#endif
}
+
+/** \brief run user level code immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_wakeup_init_user(void) {}
+
+/** \brief run keyboard level code immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
+
+__attribute__((weak)) void suspend_wakeup_init_quantum(void) {
+// Turn on backlight
+#ifdef BACKLIGHT_ENABLE
+ backlight_init();
+#endif
+
+ // Restore LED indicators
+ led_set(host_keyboard_leds());
+
+// Wake up underglow
+#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
+ rgblight_wakeup();
#endif
+
+#if defined(LED_MATRIX_ENABLE)
+ led_matrix_set_suspend_state(false);
+#endif
+#if defined(RGB_MATRIX_ENABLE)
+ rgb_matrix_set_suspend_state(false);
+#endif
+ suspend_wakeup_init_kb();
+}
+
+/** \brief converts unsigned integers into char arrays
+ *
+ * Takes an unsigned integer and converts that value into an equivalent char array
+ * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
+ */
+
+const char *get_numeric_str(char *buf, size_t buf_len, uint32_t curr_num, char curr_pad) {
+ buf[buf_len - 1] = '\0';
+ for (size_t i = 0; i < buf_len - 1; ++i) {
+ char c = '0' + curr_num % 10;
+ buf[buf_len - 2 - i] = (c == '0' && i == 0) ? '0' : (curr_num > 0 ? c : curr_pad);
+ curr_num /= 10;
+ }
+ return buf;
+}
+
+/** \brief converts uint8_t into char array
+ *
+ * Takes an uint8_t, and uses an internal static buffer to render that value into a char array
+ * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
+ *
+ * NOTE: Subsequent invocations will reuse the same static buffer and overwrite the previous
+ * contents. Use the result immediately, instead of caching it.
+ */
+const char *get_u8_str(uint8_t curr_num, char curr_pad) {
+ static char buf[4] = {0};
+ static uint8_t last_num = 0xFF;
+ static char last_pad = '\0';
+ if (last_num == curr_num && last_pad == curr_pad) {
+ return buf;
+ }
+ last_num = curr_num;
+ last_pad = curr_pad;
+ return get_numeric_str(buf, sizeof(buf), curr_num, curr_pad);
+}
+
+/** \brief converts uint16_t into char array
+ *
+ * Takes an uint16_t, and uses an internal static buffer to render that value into a char array
+ * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
+ *
+ * NOTE: Subsequent invocations will reuse the same static buffer and overwrite the previous
+ * contents. Use the result immediately, instead of caching it.
+ */
+const char *get_u16_str(uint16_t curr_num, char curr_pad) {
+ static char buf[6] = {0};
+ static uint16_t last_num = 0xFF;
+ static char last_pad = '\0';
+ if (last_num == curr_num && last_pad == curr_pad) {
+ return buf;
+ }
+ last_num = curr_num;
+ last_pad = curr_pad;
+ return get_numeric_str(buf, sizeof(buf), curr_num, curr_pad);
+}
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 22afacec0d..d0829629f5 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -54,6 +54,10 @@
#include <stddef.h>
#include <stdlib.h>
+#ifdef DEFERRED_EXEC_ENABLE
+# include "deferred_exec.h"
+#endif
+
extern layer_state_t default_layer_state;
#ifndef NO_ACTION_LAYER
@@ -121,6 +125,10 @@ extern layer_state_t layer_state;
# include "process_auto_shift.h"
#endif
+#ifdef DYNAMIC_TAPPING_TERM_ENABLE
+# include "process_dynamic_tapping_term.h"
+#endif
+
#ifdef COMBO_ENABLE
# include "process_combo.h"
#endif
@@ -147,6 +155,10 @@ extern layer_state_t layer_state;
# include "process_joystick.h"
#endif
+#ifdef PROGRAMMABLE_BUTTON_ENABLE
+# include "process_programmable_button.h"
+#endif
+
#ifdef GRAVE_ESC_ENABLE
# include "process_grave_esc.h"
#endif
@@ -210,6 +222,10 @@ extern layer_state_t layer_state;
# include "encoder.h"
#endif
+#ifdef POINTING_DEVICE_ENABLE
+# include "pointing_device.h"
+#endif
+
// For tri-layer
void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3);
@@ -244,7 +260,9 @@ void led_set_kb(uint8_t usb_led);
bool led_update_user(led_t led_state);
bool led_update_kb(led_t led_state);
-void api_send_unicode(uint32_t unicode);
-
bool webusb_receive_kb(uint8_t *data, uint8_t length);
bool webusb_receive_user(uint8_t *data, uint8_t length);
+
+const char *get_numeric_str(char *buf, size_t buf_len, uint32_t curr_num, char curr_pad);
+const char *get_u8_str(uint8_t curr_num, char curr_pad);
+const char *get_u16_str(uint16_t curr_num, char curr_pad);
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 6cce7808f1..7093d46f87 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -19,7 +19,7 @@
#include "sequencer.h"
// Fillers to make layering more clear
-#define _______ KC_TRNS
+#define _______ KC_TRANSPARENT
#define XXXXXXX KC_NO
enum quantum_keycodes {
@@ -526,6 +526,79 @@ enum quantum_keycodes {
// Additional magic key
MAGIC_TOGGLE_GUI,
+ // Adjust tapping term on the fly
+ DT_PRNT,
+ DT_UP,
+ DT_DOWN,
+
+ // Programmable Button
+ PROGRAMMABLE_BUTTON_1,
+ PROGRAMMABLE_BUTTON_2,
+ PROGRAMMABLE_BUTTON_3,
+ PROGRAMMABLE_BUTTON_4,
+ PROGRAMMABLE_BUTTON_5,
+ PROGRAMMABLE_BUTTON_6,
+ PROGRAMMABLE_BUTTON_7,
+ PROGRAMMABLE_BUTTON_8,
+ PROGRAMMABLE_BUTTON_9,
+ PROGRAMMABLE_BUTTON_10,
+ PROGRAMMABLE_BUTTON_11,
+ PROGRAMMABLE_BUTTON_12,
+ PROGRAMMABLE_BUTTON_13,
+ PROGRAMMABLE_BUTTON_14,
+ PROGRAMMABLE_BUTTON_15,
+ PROGRAMMABLE_BUTTON_16,
+ PROGRAMMABLE_BUTTON_17,
+ PROGRAMMABLE_BUTTON_18,
+ PROGRAMMABLE_BUTTON_19,
+ PROGRAMMABLE_BUTTON_20,
+ PROGRAMMABLE_BUTTON_21,
+ PROGRAMMABLE_BUTTON_22,
+ PROGRAMMABLE_BUTTON_23,
+ PROGRAMMABLE_BUTTON_24,
+ PROGRAMMABLE_BUTTON_25,
+ PROGRAMMABLE_BUTTON_26,
+ PROGRAMMABLE_BUTTON_27,
+ PROGRAMMABLE_BUTTON_28,
+ PROGRAMMABLE_BUTTON_29,
+ PROGRAMMABLE_BUTTON_30,
+ PROGRAMMABLE_BUTTON_31,
+ PROGRAMMABLE_BUTTON_32,
+
+ // Dedicated macro keys for Configurator and VIA
+ MACRO_0,
+ MACRO_1,
+ MACRO_2,
+ MACRO_3,
+ MACRO_4,
+ MACRO_5,
+ MACRO_6,
+ MACRO_7,
+ MACRO_8,
+ MACRO_9,
+ MACRO_10,
+ MACRO_11,
+ MACRO_12,
+ MACRO_13,
+ MACRO_14,
+ MACRO_15,
+ MACRO_16,
+ MACRO_17,
+ MACRO_18,
+ MACRO_19,
+ MACRO_20,
+ MACRO_21,
+ MACRO_22,
+ MACRO_23,
+ MACRO_24,
+ MACRO_25,
+ MACRO_26,
+ MACRO_27,
+ MACRO_28,
+ MACRO_29,
+ MACRO_30,
+ MACRO_31,
+
// Start of custom keycode range for keyboards and keymaps - always leave at the end
SAFE_RANGE
};
@@ -567,69 +640,67 @@ enum quantum_keycodes {
#define MOD_MEH 0x7
// US ANSI shifted keycode aliases
-#define KC_TILD LSFT(KC_GRV) // ~
-#define KC_TILDE KC_TILD
+#define KC_TILDE LSFT(KC_GRAVE) // ~
+#define KC_TILD KC_TILDE
-#define KC_EXLM LSFT(KC_1) // !
-#define KC_EXCLAIM KC_EXLM
+#define KC_EXCLAIM LSFT(KC_1) // !
+#define KC_EXLM KC_EXCLAIM
#define KC_AT LSFT(KC_2) // @
#define KC_HASH LSFT(KC_3) // #
-#define KC_DLR LSFT(KC_4) // $
-#define KC_DOLLAR KC_DLR
-
-#define KC_PERC LSFT(KC_5) // %
-#define KC_PERCENT KC_PERC
+#define KC_DOLLAR LSFT(KC_4) // $
+#define KC_DLR KC_DOLLAR
-#define KC_CIRC LSFT(KC_6) // ^
-#define KC_CIRCUMFLEX KC_CIRC
+#define KC_PERCENT LSFT(KC_5) // %
+#define KC_PERC KC_PERCENT
-#define KC_AMPR LSFT(KC_7) // &
-#define KC_AMPERSAND KC_AMPR
+#define KC_CIRCUMFLEX LSFT(KC_6) // ^
+#define KC_CIRC KC_CIRCUMFLEX
-#define KC_ASTR LSFT(KC_8) // *
-#define KC_ASTERISK KC_ASTR
+#define KC_AMPERSAND LSFT(KC_7) // &
+#define KC_AMPR KC_AMPERSAND
-#define KC_LPRN LSFT(KC_9) // (
-#define KC_LEFT_PAREN KC_LPRN
+#define KC_ASTERISK LSFT(KC_8) // *
+#define KC_ASTR KC_ASTERISK
-#define KC_RPRN LSFT(KC_0) // )
-#define KC_RIGHT_PAREN KC_RPRN
+#define KC_LEFT_PAREN LSFT(KC_9) // (
+#define KC_LPRN KC_LEFT_PAREN
-#define KC_UNDS LSFT(KC_MINS) // _
-#define KC_UNDERSCORE KC_UNDS
+#define KC_RIGHT_PAREN LSFT(KC_0) // )
+#define KC_RPRN KC_RIGHT_PAREN
-#define KC_PLUS LSFT(KC_EQL) // +
+#define KC_UNDERSCORE LSFT(KC_MINUS) // _
+#define KC_UNDS KC_UNDERSCORE
-#define KC_LCBR LSFT(KC_LBRC) // {
-#define KC_LEFT_CURLY_BRACE KC_LCBR
+#define KC_PLUS LSFT(KC_EQUAL) // +
-#define KC_RCBR LSFT(KC_RBRC) // }
-#define KC_RIGHT_CURLY_BRACE KC_RCBR
+#define KC_LEFT_CURLY_BRACE LSFT(KC_LEFT_BRACKET) // {
+#define KC_LCBR KC_LEFT_CURLY_BRACE
-#define KC_LABK LSFT(KC_COMM) // <
-#define KC_LEFT_ANGLE_BRACKET KC_LABK
+#define KC_RIGHT_CURLY_BRACE LSFT(KC_RIGHT_BRACKET) // }
+#define KC_RCBR KC_RIGHT_CURLY_BRACE
-#define KC_RABK LSFT(KC_DOT) // >
-#define KC_RIGHT_ANGLE_BRACKET KC_RABK
+#define KC_LEFT_ANGLE_BRACKET LSFT(KC_COMMA) // <
+#define KC_LABK KC_LEFT_ANGLE_BRACKET
+#define KC_LT KC_LEFT_ANGLE_BRACKET
-#define KC_COLN LSFT(KC_SCLN) // :
-#define KC_COLON KC_COLN
+#define KC_RIGHT_ANGLE_BRACKET LSFT(KC_DOT) // >
+#define KC_RABK KC_RIGHT_ANGLE_BRACKET
+#define KC_GT KC_RIGHT_ANGLE_BRACKET
-#define KC_PIPE LSFT(KC_BSLS) // |
+#define KC_COLON LSFT(KC_SEMICOLON) // :
+#define KC_COLN KC_COLON
-#define KC_LT LSFT(KC_COMM) // <
+#define KC_PIPE LSFT(KC_BACKSLASH) // |
-#define KC_GT LSFT(KC_DOT) // >
+#define KC_QUESTION LSFT(KC_SLASH) // ?
+#define KC_QUES KC_QUESTION
-#define KC_QUES LSFT(KC_SLSH) // ?
-#define KC_QUESTION KC_QUES
-
-#define KC_DQT LSFT(KC_QUOT) // "
-#define KC_DOUBLE_QUOTE KC_DQT
-#define KC_DQUO KC_DQT
+#define KC_DOUBLE_QUOTE LSFT(KC_QUOTE) // "
+#define KC_DQUO KC_DOUBLE_QUOTE
+#define KC_DQT KC_DOUBLE_QUOTE
#define KC_DELT KC_DELETE // Del key (four letter code)
@@ -777,12 +848,12 @@ enum quantum_keycodes {
#define CMD_T(kc) LCMD_T(kc)
#define WIN_T(kc) LWIN_T(kc)
-#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal
-#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
-#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI
-#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI
+#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Left Control + Shift e.g. for gnome-terminal
+#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
+#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left Control + Alt + GUI
+#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right Control + Alt + GUI
#define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
-#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc) // Left Shift + GUI
+#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc) // Left Shift + GUI
#define SGUI_T(kc) LSG_T(kc)
#define SCMD_T(kc) LSG_T(kc)
#define SWIN_T(kc) LSG_T(kc)
@@ -813,7 +884,7 @@ enum quantum_keycodes {
#define UC_M_MA UNICODE_MODE_MAC
#define UNICODE_MODE_OSX UNICODE_MODE_MAC // Deprecated alias
-#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias
+#define UC_M_OS UNICODE_MODE_MAC // Deprecated alias
#define UC_M_LN UNICODE_MODE_LNX
#define UC_M_WI UNICODE_MODE_WIN
#define UC_M_BS UNICODE_MODE_BSD
@@ -856,3 +927,39 @@ enum quantum_keycodes {
#define OS_TOGG ONESHOT_TOGGLE
#define OS_ON ONESHOT_ENABLE
#define OS_OFF ONESHOT_DISABLE
+
+// Programmable Button aliases
+#define PB_1 PROGRAMMABLE_BUTTON_1
+#define PB_2 PROGRAMMABLE_BUTTON_2
+#define PB_3 PROGRAMMABLE_BUTTON_3
+#define PB_4 PROGRAMMABLE_BUTTON_4
+#define PB_5 PROGRAMMABLE_BUTTON_5
+#define PB_6 PROGRAMMABLE_BUTTON_6
+#define PB_7 PROGRAMMABLE_BUTTON_7
+#define PB_8 PROGRAMMABLE_BUTTON_8
+#define PB_9 PROGRAMMABLE_BUTTON_9
+#define PB_10 PROGRAMMABLE_BUTTON_10
+#define PB_11 PROGRAMMABLE_BUTTON_11
+#define PB_12 PROGRAMMABLE_BUTTON_12
+#define PB_13 PROGRAMMABLE_BUTTON_13
+#define PB_14 PROGRAMMABLE_BUTTON_14
+#define PB_15 PROGRAMMABLE_BUTTON_15
+#define PB_16 PROGRAMMABLE_BUTTON_16
+#define PB_17 PROGRAMMABLE_BUTTON_17
+#define PB_18 PROGRAMMABLE_BUTTON_18
+#define PB_19 PROGRAMMABLE_BUTTON_19
+#define PB_20 PROGRAMMABLE_BUTTON_20
+#define PB_21 PROGRAMMABLE_BUTTON_21
+#define PB_22 PROGRAMMABLE_BUTTON_22
+#define PB_23 PROGRAMMABLE_BUTTON_23
+#define PB_24 PROGRAMMABLE_BUTTON_24
+#define PB_25 PROGRAMMABLE_BUTTON_25
+#define PB_26 PROGRAMMABLE_BUTTON_26
+#define PB_27 PROGRAMMABLE_BUTTON_27
+#define PB_28 PROGRAMMABLE_BUTTON_28
+#define PB_29 PROGRAMMABLE_BUTTON_29
+#define PB_30 PROGRAMMABLE_BUTTON_30
+#define PB_31 PROGRAMMABLE_BUTTON_31
+#define PB_32 PROGRAMMABLE_BUTTON_32
+#define PROGRAMMABLE_BUTTON_MIN PROGRAMMABLE_BUTTON_1
+#define PROGRAMMABLE_BUTTON_MAX PROGRAMMABLE_BUTTON_32
diff --git a/quantum/raw_hid.h b/quantum/raw_hid.h
new file mode 100644
index 0000000000..6d60ab2bff
--- /dev/null
+++ b/quantum/raw_hid.h
@@ -0,0 +1,5 @@
+#pragma once
+
+void raw_hid_receive(uint8_t *data, uint8_t length);
+
+void raw_hid_send(uint8_t *data, uint8_t length);
diff --git a/quantum/rgb_matrix/animations/alpha_mods_anim.h b/quantum/rgb_matrix/animations/alpha_mods_anim.h
index 3f2c9b799a..d6136f1ba4 100644
--- a/quantum/rgb_matrix/animations/alpha_mods_anim.h
+++ b/quantum/rgb_matrix/animations/alpha_mods_anim.h
@@ -19,8 +19,8 @@ bool ALPHAS_MODS(effect_params_t* params) {
rgb_matrix_set_color(i, rgb1.r, rgb1.g, rgb1.b);
}
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_ALPHAS_MODS
+#endif // ENABLE_RGB_MATRIX_ALPHAS_MODS
diff --git a/quantum/rgb_matrix/animations/breathing_anim.h b/quantum/rgb_matrix/animations/breathing_anim.h
index a00ccb83a2..29187e1543 100644
--- a/quantum/rgb_matrix/animations/breathing_anim.h
+++ b/quantum/rgb_matrix/animations/breathing_anim.h
@@ -13,8 +13,8 @@ bool BREATHING(effect_params_t* params) {
RGB_MATRIX_TEST_LED_FLAGS();
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BREATHING
+#endif // ENABLE_RGB_MATRIX_BREATHING
diff --git a/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
index ac95789228..0375d4937d 100644
--- a/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_pinwheel_sat_anim.h
@@ -10,4 +10,4 @@ static HSV BAND_PINWHEEL_SAT_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time)
bool BAND_PINWHEEL_SAT(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_SAT_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
+#endif // ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
diff --git a/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
index f7fe4b76e9..e40bf4cd1f 100644
--- a/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_pinwheel_val_anim.h
@@ -10,4 +10,4 @@ static HSV BAND_PINWHEEL_VAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time)
bool BAND_PINWHEEL_VAL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_VAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
+#endif // ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
diff --git a/quantum/rgb_matrix/animations/colorband_sat_anim.h b/quantum/rgb_matrix/animations/colorband_sat_anim.h
index 96a6cbf5cd..1c4f7de575 100644
--- a/quantum/rgb_matrix/animations/colorband_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_sat_anim.h
@@ -11,4 +11,4 @@ static HSV BAND_SAT_math(HSV hsv, uint8_t i, uint8_t time) {
bool BAND_SAT(effect_params_t* params) { return effect_runner_i(params, &BAND_SAT_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_SAT
+#endif // ENABLE_RGB_MATRIX_BAND_SAT
diff --git a/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
index 52f6040d81..cdd02b3797 100644
--- a/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_spiral_sat_anim.h
@@ -10,4 +10,4 @@ static HSV BAND_SPIRAL_SAT_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, u
bool BAND_SPIRAL_SAT(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_SAT_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
+#endif // ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
diff --git a/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
index d5752e27fb..e1331eaebe 100644
--- a/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_spiral_val_anim.h
@@ -10,4 +10,4 @@ static HSV BAND_SPIRAL_VAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, u
bool BAND_SPIRAL_VAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_VAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL
+#endif // ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
diff --git a/quantum/rgb_matrix/animations/colorband_val_anim.h b/quantum/rgb_matrix/animations/colorband_val_anim.h
index 32bc6f52a5..02ee4add67 100644
--- a/quantum/rgb_matrix/animations/colorband_val_anim.h
+++ b/quantum/rgb_matrix/animations/colorband_val_anim.h
@@ -11,4 +11,4 @@ static HSV BAND_VAL_math(HSV hsv, uint8_t i, uint8_t time) {
bool BAND_VAL(effect_params_t* params) { return effect_runner_i(params, &BAND_VAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_BAND_VAL
+#endif // ENABLE_RGB_MATRIX_BAND_VAL
diff --git a/quantum/rgb_matrix/animations/cycle_all_anim.h b/quantum/rgb_matrix/animations/cycle_all_anim.h
index 20af94b6ba..3b73b9d385 100644
--- a/quantum/rgb_matrix/animations/cycle_all_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_all_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_ALL_math(HSV hsv, uint8_t i, uint8_t time) {
bool CYCLE_ALL(effect_params_t* params) { return effect_runner_i(params, &CYCLE_ALL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_ALL
+#endif // ENABLE_RGB_MATRIX_CYCLE_ALL
diff --git a/quantum/rgb_matrix/animations/cycle_left_right_anim.h b/quantum/rgb_matrix/animations/cycle_left_right_anim.h
index 7f84f4bd59..bf6a574069 100644
--- a/quantum/rgb_matrix/animations/cycle_left_right_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_left_right_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_LEFT_RIGHT_math(HSV hsv, uint8_t i, uint8_t time) {
bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+#endif // ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
diff --git a/quantum/rgb_matrix/animations/cycle_out_in_anim.h b/quantum/rgb_matrix/animations/cycle_out_in_anim.h
index 2277f16a2f..2bdb9d9375 100644
--- a/quantum/rgb_matrix/animations/cycle_out_in_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_out_in_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_OUT_IN_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint
bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_OUT_IN
+#endif // ENABLE_RGB_MATRIX_CYCLE_OUT_IN
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 981c0afd05..51979c44fe 100644
--- a/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_out_in_dual_anim.h
@@ -12,4 +12,4 @@ static HSV CYCLE_OUT_IN_DUAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time)
bool CYCLE_OUT_IN_DUAL(effect_params_t* params) { return effect_runner_dx_dy(params, &CYCLE_OUT_IN_DUAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
+#endif // ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
diff --git a/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
index 1a7db4a4c7..10ba2b7c2c 100644
--- a/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_pinwheel_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_PINWHEEL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t time) {
bool CYCLE_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &CYCLE_PINWHEEL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_PINWHEEL
+#endif // ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
diff --git a/quantum/rgb_matrix/animations/cycle_spiral_anim.h b/quantum/rgb_matrix/animations/cycle_spiral_anim.h
index 245cdc237f..482c7e7da6 100644
--- a/quantum/rgb_matrix/animations/cycle_spiral_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_spiral_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_SPIRAL_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint
bool CYCLE_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_SPIRAL_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_SPIRAL
+#endif // ENABLE_RGB_MATRIX_CYCLE_SPIRAL
diff --git a/quantum/rgb_matrix/animations/cycle_up_down_anim.h b/quantum/rgb_matrix/animations/cycle_up_down_anim.h
index c9b5a54133..277edccb2f 100644
--- a/quantum/rgb_matrix/animations/cycle_up_down_anim.h
+++ b/quantum/rgb_matrix/animations/cycle_up_down_anim.h
@@ -10,4 +10,4 @@ static HSV CYCLE_UP_DOWN_math(HSV hsv, uint8_t i, uint8_t time) {
bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_CYCLE_UP_DOWN
+#endif // ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
diff --git a/quantum/rgb_matrix/animations/digital_rain_anim.h b/quantum/rgb_matrix/animations/digital_rain_anim.h
index 1de45f8e8d..8ce8fd7039 100644
--- a/quantum/rgb_matrix/animations/digital_rain_anim.h
+++ b/quantum/rgb_matrix/animations/digital_rain_anim.h
@@ -1,4 +1,4 @@
-#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN)
+#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_DIGITAL_RAIN)
RGB_MATRIX_EFFECT(DIGITAL_RAIN)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
@@ -72,4 +72,4 @@ bool DIGITAL_RAIN(effect_params_t* params) {
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN)
+#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(ENABLE_RGB_MATRIX_DIGITAL_RAIN)
diff --git a/quantum/rgb_matrix/animations/dual_beacon_anim.h b/quantum/rgb_matrix/animations/dual_beacon_anim.h
index 5c06080a26..dbe9b3ecf1 100644
--- a/quantum/rgb_matrix/animations/dual_beacon_anim.h
+++ b/quantum/rgb_matrix/animations/dual_beacon_anim.h
@@ -10,4 +10,4 @@ static HSV DUAL_BEACON_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, uint8_t
bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_DUAL_BEACON
+#endif // ENABLE_RGB_MATRIX_DUAL_BEACON
diff --git a/quantum/rgb_matrix/animations/gradient_left_right_anim.h b/quantum/rgb_matrix/animations/gradient_left_right_anim.h
index b4f2752ff7..8bb5e570bd 100644
--- a/quantum/rgb_matrix/animations/gradient_left_right_anim.h
+++ b/quantum/rgb_matrix/animations/gradient_left_right_anim.h
@@ -15,8 +15,8 @@ bool GRADIENT_LEFT_RIGHT(effect_params_t* params) {
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
+#endif // ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
diff --git a/quantum/rgb_matrix/animations/gradient_up_down_anim.h b/quantum/rgb_matrix/animations/gradient_up_down_anim.h
index 3fd45cf99b..a5674583e3 100644
--- a/quantum/rgb_matrix/animations/gradient_up_down_anim.h
+++ b/quantum/rgb_matrix/animations/gradient_up_down_anim.h
@@ -15,8 +15,8 @@ bool GRADIENT_UP_DOWN(effect_params_t* params) {
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+#endif // ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
diff --git a/quantum/rgb_matrix/animations/hue_breathing_anim.h b/quantum/rgb_matrix/animations/hue_breathing_anim.h
index 6d974b8c39..82be1a4424 100644
--- a/quantum/rgb_matrix/animations/hue_breathing_anim.h
+++ b/quantum/rgb_matrix/animations/hue_breathing_anim.h
@@ -15,7 +15,7 @@ bool HUE_BREATHING(effect_params_t* params) {
RGB_MATRIX_TEST_LED_FLAGS();
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
index 7d8eafffb9..3ffb57eb35 100644
--- a/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
+++ b/quantum/rgb_matrix/animations/jellybean_raindrops_anim.h
@@ -22,8 +22,8 @@ bool JELLYBEAN_RAINDROPS(effect_params_t* params) {
for (int i = led_min; i < led_max; i++) {
jellybean_raindrops_set_color(i, params);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+#endif // ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
diff --git a/quantum/rgb_matrix/animations/pixel_fractal_anim.h b/quantum/rgb_matrix/animations/pixel_fractal_anim.h
new file mode 100644
index 0000000000..8e25ec402c
--- /dev/null
+++ b/quantum/rgb_matrix/animations/pixel_fractal_anim.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2021 @filterpaper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Inspired from 4x12 fractal created by @schwarzgrau
+
+#ifdef ENABLE_RGB_MATRIX_PIXEL_FRACTAL
+RGB_MATRIX_EFFECT(PIXEL_FRACTAL)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+static bool PIXEL_FRACTAL(effect_params_t* params) {
+# define MID_COL MATRIX_COLS / 2
+ static bool led[MATRIX_ROWS][MATRIX_COLS];
+
+ static uint32_t wait_timer = 0;
+ if (wait_timer > g_rgb_timer) {
+ return false;
+ }
+
+ inline uint32_t interval(void) { return 3000 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16); }
+
+ RGB rgb = rgb_matrix_hsv_to_rgb(rgb_matrix_config.hsv);
+ for (uint8_t h = 0; h < MATRIX_ROWS; ++h) {
+ for (uint8_t l = 0; l < MID_COL - 1; ++l) { // Light and move left columns outwards
+ if (led[h][l]) {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][l], rgb.r, rgb.g, rgb.b);
+ } else {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][l], 0, 0, 0);
+ }
+ led[h][l] = led[h][l + 1];
+ }
+
+ for (uint8_t r = MATRIX_COLS - 1; r > MID_COL; --r) { // Light and move right columns outwards
+ if (led[h][r]) {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][r], rgb.r, rgb.g, rgb.b);
+ } else {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][r], 0, 0, 0);
+ }
+ led[h][r] = led[h][r - 1];
+ }
+
+ // Light both middle columns
+ if (led[h][MID_COL]) {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL], rgb.r, rgb.g, rgb.b);
+ } else {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL], 0, 0, 0);
+ }
+ if (led[h][MID_COL - 1]) {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], rgb.r, rgb.g, rgb.b);
+ } else {
+ rgb_matrix_set_color(g_led_config.matrix_co[h][MID_COL - 1], 0, 0, 0);
+ }
+
+ // Generate new random fractal columns
+ led[h][MID_COL] = led[h][MID_COL - 1] = (random8() & 3) ? false : true;
+ }
+
+ wait_timer = g_rgb_timer + interval();
+ return false;
+}
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_PIXEL_FRACTAL
diff --git a/quantum/rgb_matrix/animations/pixel_rain_anim.h b/quantum/rgb_matrix/animations/pixel_rain_anim.h
new file mode 100644
index 0000000000..001649aa6e
--- /dev/null
+++ b/quantum/rgb_matrix/animations/pixel_rain_anim.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2021 @filterpaper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef ENABLE_RGB_MATRIX_PIXEL_RAIN
+RGB_MATRIX_EFFECT(PIXEL_RAIN)
+# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+
+static bool PIXEL_RAIN(effect_params_t* params) {
+ static uint32_t wait_timer = 0;
+ if (wait_timer > g_rgb_timer) {
+ return false;
+ }
+
+ inline uint32_t interval(void) { return 500 / scale16by8(qadd8(rgb_matrix_config.speed, 16), 16); }
+
+ bool rain_pixel(uint8_t i, effect_params_t * params, bool off) {
+ if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) {
+ return true;
+ }
+ if (off) {
+ rgb_matrix_set_color(i, 0, 0, 0);
+ } else {
+ HSV hsv = {random8(), qadd8(random8() >> 1, 127), rgb_matrix_config.hsv.v};
+ RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
+ rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
+ }
+ wait_timer = g_rgb_timer + interval();
+ return false;
+ }
+
+ return rain_pixel(mod8(random8(), DRIVER_LED_TOTAL), params, random8() & 2);
+}
+
+# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
+#endif // ENABLE_RGB_MATRIX_PIXEL_RAIN
diff --git a/quantum/rgb_matrix/animations/rainbow_beacon_anim.h b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
index b54d997f63..cd529958db 100644
--- a/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_beacon_anim.h
@@ -10,4 +10,4 @@ static HSV RAINBOW_BEACON_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, uint8
bool RAINBOW_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &RAINBOW_BEACON_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_RAINBOW_BEACON
+#endif // ENABLE_RGB_MATRIX_RAINBOW_BEACON
diff --git a/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
index 50db922014..2f3de64e9d 100644
--- a/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_moving_chevron_anim.h
@@ -10,4 +10,4 @@ static HSV RAINBOW_MOVING_CHEVRON_math(HSV hsv, uint8_t i, uint8_t time) {
bool RAINBOW_MOVING_CHEVRON(effect_params_t* params) { return effect_runner_i(params, &RAINBOW_MOVING_CHEVRON_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+#endif // ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
diff --git a/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
index 3299f15df1..dae2b5d190 100644
--- a/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
+++ b/quantum/rgb_matrix/animations/rainbow_pinwheels_anim.h
@@ -10,4 +10,4 @@ static HSV RAINBOW_PINWHEELS_math(HSV hsv, int8_t sin, int8_t cos, uint8_t i, ui
bool RAINBOW_PINWHEELS(effect_params_t* params) { return effect_runner_sin_cos_i(params, &RAINBOW_PINWHEELS_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+#endif // ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
diff --git a/quantum/rgb_matrix/animations/raindrops_anim.h b/quantum/rgb_matrix/animations/raindrops_anim.h
index c01688e2c7..4b1b9dd9ec 100644
--- a/quantum/rgb_matrix/animations/raindrops_anim.h
+++ b/quantum/rgb_matrix/animations/raindrops_anim.h
@@ -32,8 +32,8 @@ bool RAINDROPS(effect_params_t* params) {
for (int i = led_min; i < led_max; i++) {
raindrops_set_color(i, params);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // DISABLE_RGB_MATRIX_RAINDROPS
+#endif // ENABLE_RGB_MATRIX_RAINDROPS
diff --git a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
index 302ad79c04..27ce347235 100644
--- a/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
+++ b/quantum/rgb_matrix/animations/rgb_matrix_effects.inc
@@ -26,6 +26,8 @@
#include "hue_breathing_anim.h"
#include "hue_pendulum_anim.h"
#include "hue_wave_anim.h"
+#include "pixel_rain_anim.h"
+#include "pixel_fractal_anim.h"
#include "typing_heatmap_anim.h"
#include "digital_rain_anim.h"
#include "solid_reactive_simple_anim.h"
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
index 4867609c81..2ad0f22c28 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy.h
@@ -13,5 +13,5 @@ bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) {
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, time));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
index 9545b418d9..bcae7c79b6 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_dx_dy_dist.h
@@ -14,5 +14,5 @@ bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func)
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, dx, dy, dist, time));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_i.h
index 1881cd6c60..b4de2992b6 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_i.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_i.h
@@ -11,5 +11,5 @@ bool effect_runner_i(effect_params_t* params, i_f effect_func) {
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
index 75b7c0df4e..d5c1a26cef 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive.h
@@ -23,7 +23,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) {
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, offset));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
index 2e46ffb350..d3a6e4e72f 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_reactive_splash.h
@@ -23,7 +23,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react
RGB rgb = rgb_matrix_hsv_to_rgb(hsv);
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
index 02351de51e..7776491d51 100644
--- a/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
+++ b/quantum/rgb_matrix/animations/runners/effect_runner_sin_cos_i.h
@@ -13,5 +13,5 @@ bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) {
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, cos_value, sin_value, i, time));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
diff --git a/quantum/rgb_matrix/animations/solid_color_anim.h b/quantum/rgb_matrix/animations/solid_color_anim.h
index 79d63cf133..4209959468 100644
--- a/quantum/rgb_matrix/animations/solid_color_anim.h
+++ b/quantum/rgb_matrix/animations/solid_color_anim.h
@@ -9,7 +9,7 @@ bool SOLID_COLOR(effect_params_t* params) {
RGB_MATRIX_TEST_LED_FLAGS();
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
- return led_max < DRIVER_LED_TOTAL;
+ return rgb_matrix_check_finished_leds(led_max);
}
#endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/rgb_matrix/animations/solid_reactive_anim.h b/quantum/rgb_matrix/animations/solid_reactive_anim.h
index d45bb961bc..360d05a67a 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_anim.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_anim.h
@@ -1,5 +1,5 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE
RGB_MATRIX_EFFECT(SOLID_REACTIVE)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
@@ -11,5 +11,5 @@ static HSV SOLID_REACTIVE_math(HSV hsv, uint16_t offset) {
bool SOLID_REACTIVE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // DISABLE_RGB_MATRIX_SOLID_REACTIVE
+# endif // ENABLE_RGB_MATRIX_SOLID_REACTIVE
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_reactive_cross.h b/quantum/rgb_matrix/animations/solid_reactive_cross.h
index f76c68e8c7..496651f8a5 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_cross.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_cross.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
+# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_CROSS)
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTICROSS)
# endif
@@ -23,14 +23,14 @@ static HSV SOLID_REACTIVE_CROSS_math(HSV hsv, int16_t dx, int16_t dy, uint8_t di
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
bool SOLID_REACTIVE_CROSS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
+# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_reactive_nexus.h b/quantum/rgb_matrix/animations/solid_reactive_nexus.h
index 17f94e3c18..3562e74a72 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_nexus.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_nexus.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
+# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_NEXUS)
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTINEXUS)
# endif
@@ -21,14 +21,14 @@ static HSV SOLID_REACTIVE_NEXUS_math(HSV hsv, int16_t dx, int16_t dy, uint8_t di
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
bool SOLID_REACTIVE_NEXUS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
+# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
index 12eb248cc0..69189f636b 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_simple_anim.h
@@ -1,5 +1,5 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE)
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
@@ -11,5 +11,5 @@ static HSV SOLID_REACTIVE_SIMPLE_math(HSV hsv, uint16_t offset) {
bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
+# endif // ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_reactive_wide.h b/quantum/rgb_matrix/animations/solid_reactive_wide.h
index 1cc4dca728..a613c7ff5f 100644
--- a/quantum/rgb_matrix/animations/solid_reactive_wide.h
+++ b/quantum/rgb_matrix/animations/solid_reactive_wide.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
+# if defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_WIDE)
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
RGB_MATRIX_EFFECT(SOLID_REACTIVE_MULTIWIDE)
# endif
@@ -18,14 +18,14 @@ static HSV SOLID_REACTIVE_WIDE_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dis
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
bool SOLID_REACTIVE_WIDE(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
+# ifdef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
+# endif // !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE) || !defined(ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/solid_splash_anim.h b/quantum/rgb_matrix/animations/solid_splash_anim.h
index 99efb4996a..bd9c1cfe2b 100644
--- a/quantum/rgb_matrix/animations/solid_splash_anim.h
+++ b/quantum/rgb_matrix/animations/solid_splash_anim.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SOLID_SPLASH) || !defined(DISABLE_RGB_MATRIX_SOLID_MULTISPLASH)
+# if defined(ENABLE_RGB_MATRIX_SOLID_SPLASH) || defined(ENABLE_RGB_MATRIX_SOLID_MULTISPLASH)
-# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
+# ifdef ENABLE_RGB_MATRIX_SOLID_SPLASH
RGB_MATRIX_EFFECT(SOLID_SPLASH)
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
+# ifdef ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
RGB_MATRIX_EFFECT(SOLID_MULTISPLASH)
# endif
@@ -18,14 +18,14 @@ HSV SOLID_SPLASH_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t ti
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
+# ifdef ENABLE_RGB_MATRIX_SOLID_SPLASH
bool SOLID_SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
+# ifdef ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SPLASH) && !defined(DISABLE_RGB_MATRIX_MULTISPLASH)
+# endif // !defined(ENABLE_RGB_MATRIX_SPLASH) && !defined(ENABLE_RGB_MATRIX_MULTISPLASH)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/splash_anim.h b/quantum/rgb_matrix/animations/splash_anim.h
index 1415bcc0fa..382355e9ed 100644
--- a/quantum/rgb_matrix/animations/splash_anim.h
+++ b/quantum/rgb_matrix/animations/splash_anim.h
@@ -1,11 +1,11 @@
#ifdef RGB_MATRIX_KEYREACTIVE_ENABLED
-# if !defined(DISABLE_RGB_MATRIX_SPLASH) || !defined(DISABLE_RGB_MATRIX_MULTISPLASH)
+# if defined(ENABLE_RGB_MATRIX_SPLASH) || defined(ENABLE_RGB_MATRIX_MULTISPLASH)
-# ifndef DISABLE_RGB_MATRIX_SPLASH
+# ifdef ENABLE_RGB_MATRIX_SPLASH
RGB_MATRIX_EFFECT(SPLASH)
# endif
-# ifndef DISABLE_RGB_MATRIX_MULTISPLASH
+# ifdef ENABLE_RGB_MATRIX_MULTISPLASH
RGB_MATRIX_EFFECT(MULTISPLASH)
# endif
@@ -19,14 +19,14 @@ HSV SPLASH_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
return hsv;
}
-# ifndef DISABLE_RGB_MATRIX_SPLASH
+# ifdef ENABLE_RGB_MATRIX_SPLASH
bool SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SPLASH_math); }
# endif
-# ifndef DISABLE_RGB_MATRIX_MULTISPLASH
+# ifdef ENABLE_RGB_MATRIX_MULTISPLASH
bool MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SPLASH_math); }
# endif
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-# endif // !defined(DISABLE_RGB_MATRIX_SPLASH) || !defined(DISABLE_RGB_MATRIX_MULTISPLASH)
+# endif // !defined(ENABLE_RGB_MATRIX_SPLASH) || !defined(ENABLE_RGB_MATRIX_MULTISPLASH)
#endif // RGB_MATRIX_KEYREACTIVE_ENABLED
diff --git a/quantum/rgb_matrix/animations/typing_heatmap_anim.h b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
index 28f040109d..b66667b9b8 100644
--- a/quantum/rgb_matrix/animations/typing_heatmap_anim.h
+++ b/quantum/rgb_matrix/animations/typing_heatmap_anim.h
@@ -83,4 +83,4 @@ bool TYPING_HEATMAP(effect_params_t* params) {
}
# endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
-#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_TYPING_HEATMAP)
+#endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP)
diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index 8f00b40877..558c7bd41a 100644
--- a/quantum/rgb_matrix/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -31,14 +31,6 @@ const led_point_t k_rgb_matrix_center = {112, 32};
const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER;
#endif
-// clang-format off
-#ifndef RGB_MATRIX_IMMEDIATE_EEPROM
-# define rgb_eeconfig_update(v) rgb_update_eeprom |= v
-#else
-# define rgb_eeconfig_update(v) if (v) eeconfig_update_rgb_matrix()
-#endif
-// clang-format on
-
__attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); }
// Generic effect runners
@@ -128,7 +120,6 @@ last_hit_t g_last_hit_tracker;
// internals
static bool suspend_state = false;
-static bool rgb_update_eeprom = false;
static uint8_t rgb_last_enable = UINT8_MAX;
static uint8_t rgb_last_effect = UINT8_MAX;
static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false};
@@ -148,9 +139,9 @@ static last_hit_t last_hit_buffer;
const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
#endif
-void eeconfig_read_rgb_matrix(void) { eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); }
+EECONFIG_DEBOUNCE_HELPER(rgb_matrix, EECONFIG_RGB_MATRIX, rgb_matrix_config);
-void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); }
+void eeconfig_update_rgb_matrix(void) { eeconfig_flush_rgb_matrix(true); }
void eeconfig_update_rgb_matrix_default(void) {
dprintf("eeconfig_update_rgb_matrix_default\n");
@@ -159,7 +150,7 @@ void eeconfig_update_rgb_matrix_default(void) {
rgb_matrix_config.hsv = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL};
rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD;
rgb_matrix_config.flags = LED_FLAG_ALL;
- eeconfig_update_rgb_matrix();
+ eeconfig_flush_rgb_matrix(true);
}
void eeconfig_debug_rgb_matrix(void) {
@@ -187,14 +178,7 @@ uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l
void rgb_matrix_update_pwm_buffers(void) { rgb_matrix_driver.flush(); }
-void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
-#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
- if (!is_keyboard_left() && index >= k_rgb_matrix_split[0])
- rgb_matrix_driver.set_color(index - k_rgb_matrix_split[0], red, green, blue);
- else if (is_keyboard_left() && index < k_rgb_matrix_split[0])
-#endif
- rgb_matrix_driver.set_color(index, red, green, blue);
-}
+void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color(index, red, green, blue); }
void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
@@ -314,9 +298,8 @@ static void rgb_task_timers(void) {
}
static void rgb_task_sync(void) {
+ eeconfig_flush_rgb_matrix(false);
// next task
- if (rgb_update_eeprom) eeconfig_update_rgb_matrix();
- rgb_update_eeprom = false;
if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;
}
@@ -491,7 +474,7 @@ void rgb_matrix_init(void) {
eeconfig_update_rgb_matrix_default();
}
- eeconfig_read_rgb_matrix();
+ eeconfig_init_rgb_matrix();
if (!rgb_matrix_config.mode) {
dprintf("rgb_matrix_init_drivers rgb_matrix_config.mode = 0. Write default values to EEPROM.\n");
eeconfig_update_rgb_matrix_default();
@@ -514,7 +497,7 @@ bool rgb_matrix_get_suspend_state(void) { return suspend_state; }
void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
rgb_matrix_config.enable ^= 1;
rgb_task_state = STARTING;
- rgb_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_rgb_matrix(write_to_eeprom);
dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable);
}
void rgb_matrix_toggle_noeeprom(void) { rgb_matrix_toggle_eeprom_helper(false); }
@@ -522,7 +505,7 @@ void rgb_matrix_toggle(void) { rgb_matrix_toggle_eeprom_helper(true); }
void rgb_matrix_enable(void) {
rgb_matrix_enable_noeeprom();
- rgb_eeconfig_update(true);
+ eeconfig_flag_rgb_matrix(true);
}
void rgb_matrix_enable_noeeprom(void) {
@@ -532,7 +515,7 @@ void rgb_matrix_enable_noeeprom(void) {
void rgb_matrix_disable(void) {
rgb_matrix_disable_noeeprom();
- rgb_eeconfig_update(true);
+ eeconfig_flag_rgb_matrix(true);
}
void rgb_matrix_disable_noeeprom(void) {
@@ -554,7 +537,7 @@ void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
rgb_matrix_config.mode = mode;
}
rgb_task_state = STARTING;
- rgb_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_rgb_matrix(write_to_eeprom);
dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.mode);
}
void rgb_matrix_mode_noeeprom(uint8_t mode) { rgb_matrix_mode_eeprom_helper(mode, false); }
@@ -583,7 +566,7 @@ void rgb_matrix_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, boo
rgb_matrix_config.hsv.h = hue;
rgb_matrix_config.hsv.s = sat;
rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val;
- rgb_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_rgb_matrix(write_to_eeprom);
dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v);
}
void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); }
@@ -620,7 +603,7 @@ void rgb_matrix_decrease_val(void) { rgb_matrix_decrease_val_helper(true); }
void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
rgb_matrix_config.speed = speed;
- rgb_eeconfig_update(write_to_eeprom);
+ eeconfig_flag_rgb_matrix(write_to_eeprom);
dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed);
}
void rgb_matrix_set_speed_noeeprom(uint8_t speed) { rgb_matrix_set_speed_eeprom_helper(speed, false); }
diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h
index f53e011c1b..a804d99abc 100644
--- a/quantum/rgb_matrix/rgb_matrix.h
+++ b/quantum/rgb_matrix/rgb_matrix.h
@@ -23,7 +23,6 @@
#include "rgb_matrix_types.h"
#include "color.h"
#include "quantum.h"
-#include "rgb_matrix_legacy_enables.h"
#ifdef IS31FL3731
# include "is31fl3731.h"
@@ -33,6 +32,8 @@
# include "is31fl3737.h"
#elif defined(IS31FL3741)
# include "is31fl3741.h"
+#elif defined(CKLED2001)
+# include "ckled2001.h"
#elif defined(AW20216)
# include "aw20216.h"
#elif defined(WS2812)
@@ -48,14 +49,33 @@
#endif
#if defined(RGB_MATRIX_LED_PROCESS_LIMIT) && RGB_MATRIX_LED_PROCESS_LIMIT > 0 && RGB_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL
-# define RGB_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \
- uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \
- if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
+# if defined(RGB_MATRIX_SPLIT)
+# define RGB_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \
+ uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \
+ if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; \
+ uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; \
+ if (is_keyboard_left() && (max > k_rgb_matrix_split[0])) max = k_rgb_matrix_split[0]; \
+ if (!(is_keyboard_left()) && (min < k_rgb_matrix_split[0])) min = k_rgb_matrix_split[0];
+# else
+# define RGB_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = RGB_MATRIX_LED_PROCESS_LIMIT * params->iter; \
+ uint8_t max = min + RGB_MATRIX_LED_PROCESS_LIMIT; \
+ if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL;
+# endif
#else
-# define RGB_MATRIX_USE_LIMITS(min, max) \
- uint8_t min = 0; \
- uint8_t max = DRIVER_LED_TOTAL;
+# if defined(RGB_MATRIX_SPLIT)
+# define RGB_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = 0; \
+ uint8_t max = DRIVER_LED_TOTAL; \
+ const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; \
+ if (is_keyboard_left() && (max > k_rgb_matrix_split[0])) max = k_rgb_matrix_split[0]; \
+ if (!(is_keyboard_left()) && (min < k_rgb_matrix_split[0])) min = k_rgb_matrix_split[0];
+# else
+# define RGB_MATRIX_USE_LIMITS(min, max) \
+ uint8_t min = 0; \
+ uint8_t max = DRIVER_LED_TOTAL;
+# endif
#endif
#define RGB_MATRIX_INDICATOR_SET_COLOR(i, r, g, b) \
@@ -214,6 +234,18 @@ typedef struct {
void (*flush)(void);
} rgb_matrix_driver_t;
+static inline bool rgb_matrix_check_finished_leds(uint8_t led_idx) {
+#if defined(RGB_MATRIX_SPLIT)
+ if (is_keyboard_left()) {
+ uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
+ return led_idx < k_rgb_matrix_split[0];
+ } else
+ return led_idx < DRIVER_LED_TOTAL;
+#else
+ return led_idx < DRIVER_LED_TOTAL;
+#endif
+}
+
extern const rgb_matrix_driver_t rgb_matrix_driver;
extern rgb_config_t rgb_matrix_config;
diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c
index 2cec162e22..130ca47a63 100644
--- a/quantum/rgb_matrix/rgb_matrix_drivers.c
+++ b/quantum/rgb_matrix/rgb_matrix_drivers.c
@@ -23,111 +23,153 @@
* be here if shared between boards.
*/
-#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3737) || defined(IS31FL3741)
-
+#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3737) || defined(IS31FL3741) || defined(CKLED2001)
# include "i2c_master.h"
+// TODO: Remove this at some later date
+# if defined(DRIVER_ADDR_1) && defined(DRIVER_ADDR_2)
+# if DRIVER_ADDR_1 == DRIVER_ADDR_2
+# error "Setting DRIVER_ADDR_2 == DRIVER_ADDR_1 is obsolete. If you are only using one ISSI driver, set DRIVER_COUNT to 1 and remove DRIVER_ADDR_2"
+# endif
+# endif
+
static void init(void) {
i2c_init();
-# ifdef IS31FL3731
+
+# if defined(IS31FL3731)
IS31FL3731_init(DRIVER_ADDR_1);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3731_init(DRIVER_ADDR_2);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3731_init(DRIVER_ADDR_3);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3731_init(DRIVER_ADDR_4);
+# endif
+# endif
# endif
+
# elif defined(IS31FL3733)
-# ifndef DRIVER_SYNC_1
+# if !defined(DRIVER_SYNC_1)
# define DRIVER_SYNC_1 0
# endif
IS31FL3733_init(DRIVER_ADDR_1, DRIVER_SYNC_1);
-# if defined DRIVER_ADDR_2 && (DRIVER_ADDR_1 != DRIVER_ADDR_2)
-# ifndef DRIVER_SYNC_2
+# if defined(DRIVER_ADDR_2)
+# if !defined(DRIVER_SYNC_2)
# define DRIVER_SYNC_2 0
# endif
IS31FL3733_init(DRIVER_ADDR_2, DRIVER_SYNC_2);
-# endif
-# ifdef DRIVER_ADDR_3
-# ifndef DRIVER_SYNC_3
-# define DRIVER_SYNC_3 0
-# endif
+# if defined(DRIVER_ADDR_3)
+# if !defined(DRIVER_SYNC_3)
+# define DRIVER_SYNC_3 0
+# endif
IS31FL3733_init(DRIVER_ADDR_3, DRIVER_SYNC_3);
-# endif
-# ifdef DRIVER_ADDR_4
-# ifndef DRIVER_SYNC_4
-# define DRIVER_SYNC_4 0
-# endif
+# if defined(DRIVER_ADDR_4)
+# if !defined(DRIVER_SYNC_4)
+# define DRIVER_SYNC_4 0
+# endif
IS31FL3733_init(DRIVER_ADDR_4, DRIVER_SYNC_4);
+# endif
+# endif
# endif
+
# elif defined(IS31FL3737)
IS31FL3737_init(DRIVER_ADDR_1);
-# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
+# if defined(DRIVER_ADDR_2)
IS31FL3737_init(DRIVER_ADDR_2);
# endif
-# else
+
+# elif defined(IS31FL3741)
IS31FL3741_init(DRIVER_ADDR_1);
+
+# elif defined(CKLED2001)
+ CKLED2001_init(DRIVER_ADDR_1);
+# if defined(DRIVER_ADDR_2)
+ CKLED2001_init(DRIVER_ADDR_2);
+# if defined(DRIVER_ADDR_3)
+ CKLED2001_init(DRIVER_ADDR_3);
+# if defined(DRIVER_ADDR_4)
+ CKLED2001_init(DRIVER_ADDR_4);
+# endif
+# endif
+# endif
# endif
+
for (int index = 0; index < DRIVER_LED_TOTAL; index++) {
bool enabled = true;
+
// This only caches it for later
-# ifdef IS31FL3731
+# if defined(IS31FL3731)
IS31FL3731_set_led_control_register(index, enabled, enabled, enabled);
# elif defined(IS31FL3733)
IS31FL3733_set_led_control_register(index, enabled, enabled, enabled);
# elif defined(IS31FL3737)
IS31FL3737_set_led_control_register(index, enabled, enabled, enabled);
-# else
+# elif defined(IS31FL3741)
IS31FL3741_set_led_control_register(index, enabled, enabled, enabled);
+# elif defined(CKLED2001)
+ CKLED2001_set_led_control_register(index, enabled, enabled, enabled);
# endif
}
+
// This actually updates the LED drivers
-# ifdef IS31FL3731
+# if defined(IS31FL3731)
IS31FL3731_update_led_control_registers(DRIVER_ADDR_1, 0);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3731_update_led_control_registers(DRIVER_ADDR_2, 1);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3731_update_led_control_registers(DRIVER_ADDR_3, 2);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3731_update_led_control_registers(DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
+
# elif defined(IS31FL3733)
IS31FL3733_update_led_control_registers(DRIVER_ADDR_1, 0);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3733_update_led_control_registers(DRIVER_ADDR_2, 1);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3733_update_led_control_registers(DRIVER_ADDR_3, 2);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
+
# elif defined(IS31FL3737)
IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
+# if defined(DRIVER_ADDR_2)
IS31FL3737_update_led_control_registers(DRIVER_ADDR_2, 1);
# endif
-# else
+
+# elif defined(IS31FL3741)
IS31FL3741_update_led_control_registers(DRIVER_ADDR_1, 0);
+
+# elif defined(CKLED2001)
+ CKLED2001_update_led_control_registers(DRIVER_ADDR_1, 0);
+# if defined(DRIVER_ADDR_2)
+ CKLED2001_update_led_control_registers(DRIVER_ADDR_2, 1);
+# if defined(DRIVER_ADDR_3)
+ CKLED2001_update_led_control_registers(DRIVER_ADDR_3, 2);
+# if defined(DRIVER_ADDR_4)
+ CKLED2001_update_led_control_registers(DRIVER_ADDR_4, 3);
+# endif
+# endif
+# endif
# endif
}
-# ifdef IS31FL3731
+# if defined(IS31FL3731)
static void flush(void) {
IS31FL3731_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3731_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3731_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3731_update_pwm_buffers(DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
}
@@ -137,17 +179,18 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = IS31FL3731_set_color,
.set_color_all = IS31FL3731_set_color_all,
};
+
# elif defined(IS31FL3733)
static void flush(void) {
IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# ifdef DRIVER_ADDR_2
+# if defined(DRIVER_ADDR_2)
IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2, 1);
-# endif
-# ifdef DRIVER_ADDR_3
+# if defined(DRIVER_ADDR_3)
IS31FL3733_update_pwm_buffers(DRIVER_ADDR_3, 2);
-# endif
-# ifdef DRIVER_ADDR_4
+# if defined(DRIVER_ADDR_4)
IS31FL3733_update_pwm_buffers(DRIVER_ADDR_4, 3);
+# endif
+# endif
# endif
}
@@ -157,10 +200,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = IS31FL3733_set_color,
.set_color_all = IS31FL3733_set_color_all,
};
+
# elif defined(IS31FL3737)
static void flush(void) {
IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
+# if defined(DRIVER_ADDR_2)
IS31FL3737_update_pwm_buffers(DRIVER_ADDR_2, 1);
# endif
}
@@ -171,10 +215,11 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = IS31FL3737_set_color,
.set_color_all = IS31FL3737_set_color_all,
};
-# else
+
+# elif defined(IS31FL3741)
static void flush(void) {
IS31FL3741_update_pwm_buffers(DRIVER_ADDR_1, 0);
-# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
+# if defined(DRIVER_ADDR_2)
IS31FL3741_update_pwm_buffers(DRIVER_ADDR_2, 1);
# endif
}
@@ -185,21 +230,44 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color = IS31FL3741_set_color,
.set_color_all = IS31FL3741_set_color_all,
};
+
+# elif defined(CKLED2001)
+static void flush(void) {
+ CKLED2001_update_pwm_buffers(DRIVER_ADDR_1, 0);
+# if defined(DRIVER_ADDR_2)
+ CKLED2001_update_pwm_buffers(DRIVER_ADDR_2, 1);
+# if defined(DRIVER_ADDR_3)
+ CKLED2001_update_pwm_buffers(DRIVER_ADDR_3, 2);
+# if defined(DRIVER_ADDR_4)
+ CKLED2001_update_pwm_buffers(DRIVER_ADDR_4, 3);
+# endif
+# endif
+# endif
+}
+
+const rgb_matrix_driver_t rgb_matrix_driver = {
+ .init = init,
+ .flush = flush,
+ .set_color = CKLED2001_set_color,
+ .set_color_all = CKLED2001_set_color_all,
+};
# endif
#elif defined(AW20216)
# include "spi_master.h"
+
static void init(void) {
spi_init();
+
AW20216_init(DRIVER_1_CS, DRIVER_1_EN);
-# ifdef DRIVER_2_CS
+# if defined(DRIVER_2_CS)
AW20216_init(DRIVER_2_CS, DRIVER_2_EN);
# endif
}
static void flush(void) {
AW20216_update_pwm_buffers(DRIVER_1_CS, 0);
-# ifdef DRIVER_2_CS
+# if defined(DRIVER_2_CS)
AW20216_update_pwm_buffers(DRIVER_2_CS, 1);
# endif
}
@@ -229,6 +297,14 @@ static void flush(void) {
// Set an led in the buffer to a color
static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) {
+# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
+ const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT;
+ if (!is_keyboard_left() && (i >= k_rgb_matrix_split[0])) {
+ i -= k_rgb_matrix_split[0];
+ } else if (is_keyboard_left() && (i >= k_rgb_matrix_split[0]))
+ return;
+# endif
+
rgb_matrix_ws2812_array[i].r = r;
rgb_matrix_ws2812_array[i].g = g;
rgb_matrix_ws2812_array[i].b = b;
diff --git a/quantum/rgb_matrix/rgb_matrix_legacy_enables.h b/quantum/rgb_matrix/rgb_matrix_legacy_enables.h
deleted file mode 100644
index 398858ebc8..0000000000
--- a/quantum/rgb_matrix/rgb_matrix_legacy_enables.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Copyright 2021 QMK
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-// to-do: remove this
-
-#pragma once
-
-#ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS
-# define ENABLE_RGB_MATRIX_ALPHAS_MODS
-#endif
-#ifndef DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
-# define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
-#endif
-#ifndef DISABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
-# define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
-#endif
-#ifndef DISABLE_RGB_MATRIX_BREATHING
-# define ENABLE_RGB_MATRIX_BREATHING
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_SAT
-# define ENABLE_RGB_MATRIX_BAND_SAT
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_VAL
-# define ENABLE_RGB_MATRIX_BAND_VAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
-# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
-# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
-# define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
-#endif
-#ifndef DISABLE_RGB_MATRIX_BAND_SPIRAL_VAL
-# define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_ALL
-# define ENABLE_RGB_MATRIX_CYCLE_ALL
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
-# define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_UP_DOWN
-# define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
-#endif
-#ifndef DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
-# define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_OUT_IN
-# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
-# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_PINWHEEL
-# define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
-#endif
-#ifndef DISABLE_RGB_MATRIX_CYCLE_SPIRAL
-# define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
-#endif
-#ifndef DISABLE_RGB_MATRIX_DUAL_BEACON
-# define ENABLE_RGB_MATRIX_DUAL_BEACON
-#endif
-#ifndef DISABLE_RGB_MATRIX_RAINBOW_BEACON
-# define ENABLE_RGB_MATRIX_RAINBOW_BEACON
-#endif
-#ifndef DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS
-# define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
-#endif
-#ifndef DISABLE_RGB_MATRIX_RAINDROPS
-# define ENABLE_RGB_MATRIX_RAINDROPS
-#endif
-#ifndef DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
-# define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
-#endif
-#ifndef DISABLE_RGB_MATRIX_HUE_BREATHING
-# define ENABLE_RGB_MATRIX_HUE_BREATHING
-#endif
-#ifndef DISABLE_RGB_MATRIX_HUE_PENDULUM
-# define ENABLE_RGB_MATRIX_HUE_PENDULUM
-#endif
-#ifndef DISABLE_RGB_MATRIX_HUE_WAVE
-# define ENABLE_RGB_MATRIX_HUE_WAVE
-#endif
-#ifndef DISABLE_RGB_MATRIX_PIXEL_RAIN
-# define ENABLE_RGB_MATRIX_PIXEL_RAIN
-#endif
-#ifndef DISABLE_RGB_MATRIX_PIXEL_FLOW
-# define ENABLE_RGB_MATRIX_PIXEL_FLOW
-#endif
-#ifndef DISABLE_RGB_MATRIX_PIXEL_FRACTAL
-# define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
-#endif
-#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
-# ifndef DISABLE_RGB_MATRIX_TYPING_HEATMAP
-# define ENABLE_RGB_MATRIX_TYPING_HEATMAP
-# endif
-# ifndef DISABLE_RGB_MATRIX_DIGITAL_RAIN
-# define ENABLE_RGB_MATRIX_DIGITAL_RAIN
-# endif
-#endif
-#if defined(RGB_MATRIX_KEYREACTIVE_ENABLED)
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
-# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
-# endif
-# ifndef DISABLE_RGB_MATRIX_SPLASH
-# define ENABLE_RGB_MATRIX_SPLASH
-# endif
-# ifndef DISABLE_RGB_MATRIX_MULTISPLASH
-# define ENABLE_RGB_MATRIX_MULTISPLASH
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
-# define ENABLE_RGB_MATRIX_SOLID_SPLASH
-# endif
-# ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
-# define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
-# endif
-#endif
diff --git a/quantum/sequencer/tests/rules.mk b/quantum/sequencer/tests/rules.mk
index 76c221cf92..a3bbd80513 100644
--- a/quantum/sequencer/tests/rules.mk
+++ b/quantum/sequencer/tests/rules.mk
@@ -1,5 +1,5 @@
# The letter case of these variables might seem odd. However:
-# - it is consistent with the serial_link example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features)
+# - it is consistent with the example that is used as a reference in the Unit Testing article (https://docs.qmk.fm/#/unit_testing?id=adding-tests-for-new-or-existing-features)
# - Neither `make test:sequencer` or `make test:SEQUENCER` work when using SCREAMING_SNAKE_CASE
sequencer_DEFS := -DNO_DEBUG -DMIDI_MOCKED
@@ -8,4 +8,4 @@ sequencer_SRC := \
$(QUANTUM_PATH)/sequencer/tests/midi_mock.c \
$(QUANTUM_PATH)/sequencer/tests/sequencer_tests.cpp \
$(QUANTUM_PATH)/sequencer/sequencer.c \
- $(TMK_PATH)/common/test/timer.c
+ $(PLATFORM_PATH)/$(PLATFORM_KEY)/timer.c
diff --git a/quantum/serial_link/LICENSE b/quantum/serial_link/LICENSE
deleted file mode 100644
index d13cc4b26a..0000000000
--- a/quantum/serial_link/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-The MIT License (MIT)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/quantum/serial_link/README.md b/quantum/serial_link/README.md
deleted file mode 100644
index 05871dbdf7..0000000000
--- a/quantum/serial_link/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# qmk_serial_link
diff --git a/quantum/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/protocol/byte_stuffer.c
deleted file mode 100644
index d3a91d8286..0000000000
--- a/quantum/serial_link/protocol/byte_stuffer.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/frame_validator.h"
-#include "serial_link/protocol/physical.h"
-#include <stdbool.h>
-
-// This implements the "Consistent overhead byte stuffing protocol"
-// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
-// http://www.stuartcheshire.org/papers/COBSforToN.pdf
-
-typedef struct byte_stuffer_state {
- uint16_t next_zero;
- uint16_t data_pos;
- bool long_frame;
- uint8_t data[MAX_FRAME_SIZE];
-} byte_stuffer_state_t;
-
-static byte_stuffer_state_t states[NUM_LINKS];
-
-void init_byte_stuffer_state(byte_stuffer_state_t* state) {
- state->next_zero = 0;
- state->data_pos = 0;
- state->long_frame = false;
-}
-
-void init_byte_stuffer(void) {
- int i;
- for (i = 0; i < NUM_LINKS; i++) {
- init_byte_stuffer_state(&states[i]);
- }
-}
-
-void byte_stuffer_recv_byte(uint8_t link, uint8_t data) {
- byte_stuffer_state_t* state = &states[link];
- // Start of a new frame
- if (state->next_zero == 0) {
- state->next_zero = data;
- state->long_frame = data == 0xFF;
- state->data_pos = 0;
- return;
- }
-
- state->next_zero--;
- if (data == 0) {
- if (state->next_zero == 0) {
- // The frame is completed
- if (state->data_pos > 0) {
- validator_recv_frame(link, state->data, state->data_pos);
- }
- } else {
- // The frame is invalid, so reset
- init_byte_stuffer_state(state);
- }
- } else {
- if (state->data_pos == MAX_FRAME_SIZE) {
- // We exceeded our maximum frame size
- // therefore there's nothing else to do than reset to a new frame
- state->next_zero = data;
- state->long_frame = data == 0xFF;
- state->data_pos = 0;
- } else if (state->next_zero == 0) {
- if (state->long_frame) {
- // This is part of a long frame, so continue
- state->next_zero = data;
- state->long_frame = data == 0xFF;
- } else {
- // Special case for zeroes
- state->next_zero = data;
- state->data[state->data_pos++] = 0;
- }
- } else {
- state->data[state->data_pos++] = data;
- }
- }
-}
-
-static void send_block(uint8_t link, uint8_t* start, uint8_t* end, uint8_t num_non_zero) {
- send_data(link, &num_non_zero, 1);
- if (end > start) {
- send_data(link, start, end - start);
- }
-}
-
-void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
- const uint8_t zero = 0;
- if (size > 0) {
- uint16_t num_non_zero = 1;
- uint8_t* end = data + size;
- uint8_t* start = data;
- while (data < end) {
- if (num_non_zero == 0xFF) {
- // There's more data after big non-zero block
- // So send it, and start a new block
- send_block(link, start, data, num_non_zero);
- start = data;
- num_non_zero = 1;
- } else {
- if (*data == 0) {
- // A zero encountered, so send the block
- send_block(link, start, data, num_non_zero);
- start = data + 1;
- num_non_zero = 1;
- } else {
- num_non_zero++;
- }
- ++data;
- }
- }
- send_block(link, start, data, num_non_zero);
- send_data(link, &zero, 1);
- }
-}
diff --git a/quantum/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/protocol/byte_stuffer.h
deleted file mode 100644
index 397ed3baae..0000000000
--- a/quantum/serial_link/protocol/byte_stuffer.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-
-#define MAX_FRAME_SIZE 1024
-#define NUM_LINKS 2
-
-void init_byte_stuffer(void);
-void byte_stuffer_recv_byte(uint8_t link, uint8_t data);
-void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/frame_router.c b/quantum/serial_link/protocol/frame_router.c
deleted file mode 100644
index 5292673700..0000000000
--- a/quantum/serial_link/protocol/frame_router.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/frame_router.h"
-#include "serial_link/protocol/transport.h"
-#include "serial_link/protocol/frame_validator.h"
-
-static bool is_master;
-
-void router_set_master(bool master) { is_master = master; }
-
-void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) {
- if (is_master) {
- if (link == DOWN_LINK) {
- transport_recv_frame(data[size - 1], data, size - 1);
- }
- } else {
- if (link == UP_LINK) {
- if (data[size - 1] & 1) {
- transport_recv_frame(0, data, size - 1);
- }
- data[size - 1] >>= 1;
- validator_send_frame(DOWN_LINK, data, size);
- } else {
- data[size - 1]++;
- validator_send_frame(UP_LINK, data, size);
- }
- }
-}
-
-void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
- if (destination == 0) {
- if (!is_master) {
- data[size] = 1;
- validator_send_frame(UP_LINK, data, size + 1);
- }
- } else {
- if (is_master) {
- data[size] = destination;
- validator_send_frame(DOWN_LINK, data, size + 1);
- }
- }
-}
diff --git a/quantum/serial_link/protocol/frame_router.h b/quantum/serial_link/protocol/frame_router.h
deleted file mode 100644
index 9325fe4eed..0000000000
--- a/quantum/serial_link/protocol/frame_router.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#define UP_LINK 0
-#define DOWN_LINK 1
-
-void router_set_master(bool master);
-void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size);
-void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/frame_validator.c b/quantum/serial_link/protocol/frame_validator.c
deleted file mode 100644
index bc9136f70b..0000000000
--- a/quantum/serial_link/protocol/frame_validator.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/frame_validator.h"
-#include "serial_link/protocol/frame_router.h"
-#include "serial_link/protocol/byte_stuffer.h"
-#include <string.h>
-
-const uint32_t poly8_lookup[256] = {0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
- 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
- 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
- 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
-
-static uint32_t crc32_byte(uint8_t* p, uint32_t bytelength) {
- uint32_t crc = 0xffffffff;
- while (bytelength-- != 0) crc = poly8_lookup[((uint8_t)crc ^ *(p++))] ^ (crc >> 8);
- // return (~crc); also works
- return (crc ^ 0xffffffff);
-}
-
-void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) {
- if (size > 4) {
- uint32_t frame_crc;
- memcpy(&frame_crc, data + size - 4, 4);
- uint32_t expected_crc = crc32_byte(data, size - 4);
- if (frame_crc == expected_crc) {
- route_incoming_frame(link, data, size - 4);
- }
- }
-}
-
-void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
- uint32_t crc = crc32_byte(data, size);
- memcpy(data + size, &crc, 4);
- byte_stuffer_send_frame(link, data, size + 4);
-}
diff --git a/quantum/serial_link/protocol/frame_validator.h b/quantum/serial_link/protocol/frame_validator.h
deleted file mode 100644
index 0f78768a00..0000000000
--- a/quantum/serial_link/protocol/frame_validator.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-
-void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size);
-// The buffer pointed to by the data needs 4 additional bytes
-void validator_send_frame(uint8_t link, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/physical.h b/quantum/serial_link/protocol/physical.h
deleted file mode 100644
index 399c9d1f76..0000000000
--- a/quantum/serial_link/protocol/physical.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-void send_data(uint8_t link, const uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c
deleted file mode 100644
index 73b8dc62e9..0000000000
--- a/quantum/serial_link/protocol/transport.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/transport.h"
-#include "serial_link/protocol/frame_router.h"
-#include "serial_link/protocol/triple_buffered_object.h"
-#include <string.h>
-
-#define MAX_REMOTE_OBJECTS 16
-static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS];
-static uint32_t num_remote_objects = 0;
-
-void reinitialize_serial_link_transport(void) { num_remote_objects = 0; }
-
-void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) {
- unsigned int i;
- for (i = 0; i < _num_remote_objects; i++) {
- remote_object_t* obj = _remote_objects[i];
- remote_objects[num_remote_objects++] = obj;
- if (obj->object_type == MASTER_TO_ALL_SLAVES) {
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer;
- triple_buffer_init(tb);
- uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
- tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- } else if (obj->object_type == MASTER_TO_SINGLE_SLAVE) {
- uint8_t* start = obj->buffer;
- unsigned int j;
- for (j = 0; j < NUM_SLAVES; j++) {
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- start += LOCAL_OBJECT_SIZE(obj->object_size);
- }
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- } else {
- uint8_t* start = obj->buffer;
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- start += LOCAL_OBJECT_SIZE(obj->object_size);
- unsigned int j;
- for (j = 0; j < NUM_SLAVES; j++) {
- tb = (triple_buffer_object_t*)start;
- triple_buffer_init(tb);
- start += REMOTE_OBJECT_SIZE(obj->object_size);
- }
- }
- }
-}
-
-void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) {
- uint8_t id = data[size - 1];
- if (id < num_remote_objects) {
- remote_object_t* obj = remote_objects[id];
- if (obj->object_size == size - 1) {
- uint8_t* start;
- if (obj->object_type == MASTER_TO_ALL_SLAVES) {
- start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
- } else if (obj->object_type == SLAVE_TO_MASTER) {
- start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);
- start += (from - 1) * REMOTE_OBJECT_SIZE(obj->object_size);
- } else {
- start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);
- }
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- void* ptr = triple_buffer_begin_write_internal(obj->object_size, tb);
- memcpy(ptr, data, size - 1);
- triple_buffer_end_write_internal(tb);
- }
- }
-}
-
-void update_transport(void) {
- unsigned int i;
- for (i = 0; i < num_remote_objects; i++) {
- remote_object_t* obj = remote_objects[i];
- if (obj->object_type == MASTER_TO_ALL_SLAVES || obj->object_type == SLAVE_TO_MASTER) {
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer;
- uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb);
- if (ptr) {
- ptr[obj->object_size] = i;
- uint8_t dest = obj->object_type == MASTER_TO_ALL_SLAVES ? 0xFF : 0;
- router_send_frame(dest, ptr, obj->object_size + 1);
- }
- } else {
- uint8_t* start = obj->buffer;
- unsigned int j;
- for (j = 0; j < NUM_SLAVES; j++) {
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start;
- uint8_t* ptr = (uint8_t*)triple_buffer_read_internal(obj->object_size + LOCAL_OBJECT_EXTRA, tb);
- if (ptr) {
- ptr[obj->object_size] = i;
- uint8_t dest = j + 1;
- router_send_frame(dest, ptr, obj->object_size + 1);
- }
- start += LOCAL_OBJECT_SIZE(obj->object_size);
- }
- }
- }
-}
diff --git a/quantum/serial_link/protocol/transport.h b/quantum/serial_link/protocol/transport.h
deleted file mode 100644
index 3ce0c9fe4e..0000000000
--- a/quantum/serial_link/protocol/transport.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include "serial_link/protocol/triple_buffered_object.h"
-#include "serial_link/system/serial_link.h"
-
-#define NUM_SLAVES 8
-#define LOCAL_OBJECT_EXTRA 16
-
-// master -> slave = 1 local(target all), 1 remote object
-// slave -> master = 1 local(target 0), multiple remote objects
-// master -> single slave (multiple local, target id), 1 remote object
-typedef enum {
- MASTER_TO_ALL_SLAVES,
- MASTER_TO_SINGLE_SLAVE,
- SLAVE_TO_MASTER,
-} remote_object_type;
-
-typedef struct {
- remote_object_type object_type;
- uint16_t object_size;
- uint8_t buffer[] __attribute__((aligned(4)));
-} remote_object_t;
-
-#define REMOTE_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + objectsize * 3)
-#define LOCAL_OBJECT_SIZE(objectsize) (sizeof(triple_buffer_object_t) + (objectsize + LOCAL_OBJECT_EXTRA) * 3)
-
-#define REMOTE_OBJECT_HELPER(name, type, num_local, num_remote) \
- typedef struct { \
- remote_object_t object; \
- uint8_t buffer[num_remote * REMOTE_OBJECT_SIZE(sizeof(type)) + num_local * LOCAL_OBJECT_SIZE(sizeof(type))]; \
- } remote_object_##name##_t;
-
-#define MASTER_TO_ALL_SLAVES_OBJECT(name, type) \
- REMOTE_OBJECT_HELPER(name, type, 1, 1) \
- remote_object_##name##_t remote_object_##name = {.object = { \
- .object_type = MASTER_TO_ALL_SLAVES, \
- .object_size = sizeof(type), \
- }}; \
- type* begin_write_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
- return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
- } \
- void end_write_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
- triple_buffer_end_write_internal(tb); \
- signal_data_written(); \
- } \
- type* read_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return (type*)triple_buffer_read_internal(obj->object_size, tb); \
- }
-
-#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \
- REMOTE_OBJECT_HELPER(name, type, NUM_SLAVES, 1) \
- remote_object_##name##_t remote_object_##name = {.object = { \
- .object_type = MASTER_TO_SINGLE_SLAVE, \
- .object_size = sizeof(type), \
- }}; \
- type* begin_write_##name(uint8_t slave) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer; \
- start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
- } \
- void end_write_##name(uint8_t slave) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer; \
- start += slave * LOCAL_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- triple_buffer_end_write_internal(tb); \
- signal_data_written(); \
- } \
- type* read_##name() { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return (type*)triple_buffer_read_internal(obj->object_size, tb); \
- }
-
-#define SLAVE_TO_MASTER_OBJECT(name, type) \
- REMOTE_OBJECT_HELPER(name, type, 1, NUM_SLAVES) \
- remote_object_##name##_t remote_object_##name = {.object = { \
- .object_type = SLAVE_TO_MASTER, \
- .object_size = sizeof(type), \
- }}; \
- type* begin_write_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
- return (type*)triple_buffer_begin_write_internal(sizeof(type) + LOCAL_OBJECT_EXTRA, tb); \
- } \
- void end_write_##name(void) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)obj->buffer; \
- triple_buffer_end_write_internal(tb); \
- signal_data_written(); \
- } \
- type* read_##name(uint8_t slave) { \
- remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
- uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size); \
- start += slave * REMOTE_OBJECT_SIZE(obj->object_size); \
- triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return (type*)triple_buffer_read_internal(obj->object_size, tb); \
- }
-
-#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name
-
-void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects);
-void reinitialize_serial_link_transport(void);
-void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size);
-void update_transport(void);
diff --git a/quantum/serial_link/protocol/triple_buffered_object.c b/quantum/serial_link/protocol/triple_buffered_object.c
deleted file mode 100644
index e0c6d702a5..0000000000
--- a/quantum/serial_link/protocol/triple_buffered_object.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "serial_link/protocol/triple_buffered_object.h"
-#include "serial_link/system/serial_link.h"
-#include <stdbool.h>
-#include <stddef.h>
-
-#define GET_READ_INDEX() object->state & 3
-#define GET_WRITE_INDEX() (object->state >> 2) & 3
-#define GET_SHARED_INDEX() (object->state >> 4) & 3
-#define GET_DATA_AVAILABLE() (object->state >> 6) & 1
-
-#define SET_READ_INDEX(i) object->state = ((object->state & ~3) | i)
-#define SET_WRITE_INDEX(i) object->state = ((object->state & ~(3 << 2)) | (i << 2))
-#define SET_SHARED_INDEX(i) object->state = ((object->state & ~(3 << 4)) | (i << 4))
-#define SET_DATA_AVAILABLE(i) object->state = ((object->state & ~(1 << 6)) | (i << 6))
-
-void triple_buffer_init(triple_buffer_object_t* object) {
- object->state = 0;
- SET_WRITE_INDEX(0);
- SET_READ_INDEX(1);
- SET_SHARED_INDEX(2);
- SET_DATA_AVAILABLE(0);
-}
-
-void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object) {
- serial_link_lock();
- if (GET_DATA_AVAILABLE()) {
- uint8_t shared_index = GET_SHARED_INDEX();
- uint8_t read_index = GET_READ_INDEX();
- SET_READ_INDEX(shared_index);
- SET_SHARED_INDEX(read_index);
- SET_DATA_AVAILABLE(false);
- serial_link_unlock();
- return object->buffer + object_size * shared_index;
- } else {
- serial_link_unlock();
- return NULL;
- }
-}
-
-void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object) {
- uint8_t write_index = GET_WRITE_INDEX();
- return object->buffer + object_size * write_index;
-}
-
-void triple_buffer_end_write_internal(triple_buffer_object_t* object) {
- serial_link_lock();
- uint8_t shared_index = GET_SHARED_INDEX();
- uint8_t write_index = GET_WRITE_INDEX();
- SET_SHARED_INDEX(write_index);
- SET_WRITE_INDEX(shared_index);
- SET_DATA_AVAILABLE(true);
- serial_link_unlock();
-}
diff --git a/quantum/serial_link/protocol/triple_buffered_object.h b/quantum/serial_link/protocol/triple_buffered_object.h
deleted file mode 100644
index 717d6d7b8b..0000000000
--- a/quantum/serial_link/protocol/triple_buffered_object.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-
-typedef struct {
- uint8_t state;
- uint8_t buffer[] __attribute__((aligned(4)));
-} triple_buffer_object_t;
-
-void triple_buffer_init(triple_buffer_object_t* object);
-
-#define triple_buffer_begin_write(object) (typeof(*object.buffer[0])*)triple_buffer_begin_write_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object)
-
-#define triple_buffer_end_write(object) triple_buffer_end_write_internal((triple_buffer_object_t*)object)
-
-#define triple_buffer_read(object) (typeof(*object.buffer[0])*)triple_buffer_read_internal(sizeof(*object.buffer[0]), (triple_buffer_object_t*)object)
-
-void* triple_buffer_begin_write_internal(uint16_t object_size, triple_buffer_object_t* object);
-void triple_buffer_end_write_internal(triple_buffer_object_t* object);
-void* triple_buffer_read_internal(uint16_t object_size, triple_buffer_object_t* object);
diff --git a/quantum/serial_link/system/serial_link.c b/quantum/serial_link/system/serial_link.c
deleted file mode 100644
index 6363f8ff3b..0000000000
--- a/quantum/serial_link/system/serial_link.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-#include "report.h"
-#include "host_driver.h"
-#include "serial_link/system/serial_link.h"
-#include <hal.h>
-#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/transport.h"
-#include "serial_link/protocol/frame_router.h"
-#include "matrix.h"
-#include "sync_timer.h"
-#include <stdbool.h>
-#include "print.h"
-#include "config.h"
-
-#define SYNC_TIMER_OFFSET 2
-
-static event_source_t new_data_event;
-static bool serial_link_connected;
-static bool is_master = false;
-
-static uint8_t keyboard_leds(void);
-static void send_keyboard(report_keyboard_t* report);
-static void send_mouse(report_mouse_t* report);
-static void send_system(uint16_t data);
-static void send_consumer(uint16_t data);
-
-host_driver_t serial_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
-
-// Define these in your Config.h file
-#ifndef SERIAL_LINK_BAUD
-# error "Serial link baud is not set"
-#endif
-
-#ifndef SERIAL_LINK_THREAD_PRIORITY
-# error "Serial link thread priority not set"
-#endif
-
-static SerialConfig config = {.sc_speed = SERIAL_LINK_BAUD};
-
-//#define DEBUG_LINK_ERRORS
-
-static uint32_t read_from_serial(SerialDriver* driver, uint8_t link) {
- const uint32_t buffer_size = 16;
- uint8_t buffer[buffer_size];
- uint32_t bytes_read = sdAsynchronousRead(driver, buffer, buffer_size);
- uint8_t* current = buffer;
- uint8_t* end = current + bytes_read;
- while (current < end) {
- byte_stuffer_recv_byte(link, *current);
- current++;
- }
- return bytes_read;
-}
-
-static void print_error(char* str, eventflags_t flags, SerialDriver* driver) {
-#ifdef DEBUG_LINK_ERRORS
- if (flags & SD_PARITY_ERROR) {
- print(str);
- print(" Parity error\n");
- }
- if (flags & SD_FRAMING_ERROR) {
- print(str);
- print(" Framing error\n");
- }
- if (flags & SD_OVERRUN_ERROR) {
- print(str);
- uint32_t size = qSpaceI(&(driver->iqueue));
- xprintf(" Overrun error, queue size %d\n", size);
- }
- if (flags & SD_NOISE_ERROR) {
- print(str);
- print(" Noise error\n");
- }
- if (flags & SD_BREAK_DETECTED) {
- print(str);
- print(" Break detected\n");
- }
-#else
- (void)str;
- (void)flags;
- (void)driver;
-#endif
-}
-
-bool is_serial_link_master(void) { return is_master; }
-
-// TODO: Optimize the stack size, this is probably way too big
-static THD_WORKING_AREA(serialThreadStack, 1024);
-static THD_FUNCTION(serialThread, arg) {
- (void)arg;
- event_listener_t new_data_listener;
- event_listener_t sd1_listener;
- event_listener_t sd2_listener;
- chEvtRegister(&new_data_event, &new_data_listener, 0);
- eventflags_t events = CHN_INPUT_AVAILABLE | SD_PARITY_ERROR | SD_FRAMING_ERROR | SD_OVERRUN_ERROR | SD_NOISE_ERROR | SD_BREAK_DETECTED;
- chEvtRegisterMaskWithFlags(chnGetEventSource(&SD1), &sd1_listener, EVENT_MASK(1), events);
- chEvtRegisterMaskWithFlags(chnGetEventSource(&SD2), &sd2_listener, EVENT_MASK(2), events);
- bool need_wait = false;
- while (true) {
- eventflags_t flags1 = 0;
- eventflags_t flags2 = 0;
- if (need_wait) {
- eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(1000));
- if (mask & EVENT_MASK(1)) {
- flags1 = chEvtGetAndClearFlags(&sd1_listener);
- print_error("DOWNLINK", flags1, &SD1);
- }
- if (mask & EVENT_MASK(2)) {
- flags2 = chEvtGetAndClearFlags(&sd2_listener);
- print_error("UPLINK", flags2, &SD2);
- }
- }
-
- // Always stay as master, even if the USB goes into sleep mode
- is_master |= usbGetDriverStateI(&USBD1) == USB_ACTIVE;
- router_set_master(is_master);
-
- need_wait = true;
- need_wait &= read_from_serial(&SD2, UP_LINK) == 0;
- need_wait &= read_from_serial(&SD1, DOWN_LINK) == 0;
- update_transport();
- }
-}
-
-void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
- if (link == DOWN_LINK) {
- sdWrite(&SD1, data, size);
- } else {
- sdWrite(&SD2, data, size);
- }
-}
-
-static systime_t last_update = 0;
-
-typedef struct {
- matrix_row_t rows[MATRIX_ROWS];
-} matrix_object_t;
-
-static matrix_object_t last_matrix = {};
-
-SLAVE_TO_MASTER_OBJECT(keyboard_matrix, matrix_object_t);
-MASTER_TO_ALL_SLAVES_OBJECT(serial_link_connected, bool);
-#ifndef DISABLE_SYNC_TIMER
-MASTER_TO_ALL_SLAVES_OBJECT(sync_timer, uint32_t);
-#endif
-
-static remote_object_t* remote_objects[] = {
- REMOTE_OBJECT(serial_link_connected),
- REMOTE_OBJECT(keyboard_matrix),
-#ifndef DISABLE_SYNC_TIMER
- REMOTE_OBJECT(sync_timer),
-#endif
-};
-
-void init_serial_link(void) {
- serial_link_connected = false;
- init_serial_link_hal();
- add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*));
- init_byte_stuffer();
- sdStart(&SD1, &config);
- sdStart(&SD2, &config);
- chEvtObjectInit(&new_data_event);
- (void)chThdCreateStatic(serialThreadStack, sizeof(serialThreadStack), SERIAL_LINK_THREAD_PRIORITY, serialThread, NULL);
-}
-
-void matrix_set_remote(matrix_row_t* rows, uint8_t index);
-
-void serial_link_update(void) {
- if (read_serial_link_connected()) {
- serial_link_connected = true;
- }
-
- matrix_object_t matrix;
- bool changed = false;
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- matrix.rows[i] = matrix_get_row(i);
- changed |= matrix.rows[i] != last_matrix.rows[i];
- }
-
- systime_t current_time = chVTGetSystemTimeX();
- systime_t delta = current_time - last_update;
- if (changed || delta > TIME_US2I(5000)) {
- last_update = current_time;
- last_matrix = matrix;
- matrix_object_t* m = begin_write_keyboard_matrix();
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- m->rows[i] = matrix.rows[i];
- }
- end_write_keyboard_matrix();
-
- *begin_write_serial_link_connected() = true;
- end_write_serial_link_connected();
-
-#ifndef DISABLE_SYNC_TIMER
- *begin_write_sync_timer() = sync_timer_read32() + SYNC_TIMER_OFFSET;
- end_write_sync_timer();
-#endif
- }
-
- matrix_object_t* m = read_keyboard_matrix(0);
- if (m) {
- matrix_set_remote(m->rows, 0);
- }
-
-#ifndef DISABLE_SYNC_TIMER
- uint32_t* t = read_sync_timer();
- if (t) {
- sync_timer_update(*t);
- }
-#endif
-}
-
-void signal_data_written(void) { chEvtBroadcast(&new_data_event); }
-
-bool is_serial_link_connected(void) { return serial_link_connected; }
-
-host_driver_t* get_serial_link_driver(void) { return &serial_driver; }
-
-// NOTE: The driver does nothing, because the master handles everything
-uint8_t keyboard_leds(void) { return 0; }
-
-void send_keyboard(report_keyboard_t* report) { (void)report; }
-
-void send_mouse(report_mouse_t* report) { (void)report; }
-
-void send_system(uint16_t data) { (void)data; }
-
-void send_consumer(uint16_t data) { (void)data; }
diff --git a/quantum/serial_link/system/serial_link.h b/quantum/serial_link/system/serial_link.h
deleted file mode 100644
index adc1f6e93d..0000000000
--- a/quantum/serial_link/system/serial_link.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include "host_driver.h"
-#include <stdbool.h>
-
-void init_serial_link(void);
-void init_serial_link_hal(void);
-bool is_serial_link_connected(void);
-bool is_serial_link_master(void);
-host_driver_t* get_serial_link_driver(void);
-void serial_link_update(void);
-
-#if defined(PROTOCOL_CHIBIOS)
-# include <ch.h>
-
-static inline void serial_link_lock(void) { chSysLock(); }
-
-static inline void serial_link_unlock(void) { chSysUnlock(); }
-
-void signal_data_written(void);
-
-#else
-
-inline void serial_link_lock(void) {}
-
-inline void serial_link_unlock(void) {}
-
-void signal_data_written(void);
-
-#endif
diff --git a/quantum/serial_link/tests/Makefile b/quantum/serial_link/tests/Makefile
deleted file mode 100644
index 11dd355b22..0000000000
--- a/quantum/serial_link/tests/Makefile
+++ /dev/null
@@ -1,61 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2016 Fred Sundvik
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-CC = gcc
-CFLAGS =
-INCLUDES = -I. -I../../
-LDFLAGS = -L$(BUILDDIR)/cgreen/build-c/src -shared
-LDLIBS = -lcgreen
-UNITOBJ = $(BUILDDIR)/serialtest/unitobj
-DEPDIR = $(BUILDDIR)/serialtest/unit.d
-UNITTESTS = $(BUILDDIR)/serialtest/unittests
-DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
-EXT = .so
-UNAME := $(shell uname)
-ifneq (, $(findstring MINGW, $(UNAME)))
- EXT = .dll
-endif
-ifneq (, $(findstring CYGWIN, $(UNAME)))
- EXT = .dll
-endif
-
-SRC = $(wildcard *.c)
-TESTFILES = $(patsubst %.c, $(UNITTESTS)/%$(EXT), $(SRC))
-$(shell mkdir -p $(DEPDIR) >/dev/null)
-
-test: $(TESTFILES)
- @$(BUILDDIR)/cgreen/build-c/tools/cgreen-runner --color $(TESTFILES)
-
-$(UNITTESTS)/%$(EXT): $(UNITOBJ)/%.o
- @mkdir -p $(UNITTESTS)
- $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
-
-$(UNITOBJ)/%.o : %.c
-$(UNITOBJ)/%.o: %.c $(DEPDIR)/%.d
- @mkdir -p $(UNITOBJ)
- $(CC) $(CFLAGS) $(DEPFLAGS) $(INCLUDES) -c $< -o $@
- @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
-
-$(DEPDIR)/%.d: ;
-.PRECIOUS: $(DEPDIR)/%.d
-
--include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC)))
diff --git a/quantum/serial_link/tests/byte_stuffer_tests.cpp b/quantum/serial_link/tests/byte_stuffer_tests.cpp
deleted file mode 100644
index 9e4e1768f4..0000000000
--- a/quantum/serial_link/tests/byte_stuffer_tests.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-#include <vector>
-#include <algorithm>
-extern "C" {
-#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/frame_validator.h"
-#include "serial_link/protocol/physical.h"
-}
-
-using testing::_;
-using testing::Args;
-using testing::ElementsAreArray;
-
-class ByteStuffer : public ::testing::Test {
- public:
- ByteStuffer() {
- Instance = this;
- init_byte_stuffer();
- }
-
- ~ByteStuffer() { Instance = nullptr; }
-
- MOCK_METHOD3(validator_recv_frame, void(uint8_t link, uint8_t* data, uint16_t size));
-
- void send_data(uint8_t link, const uint8_t* data, uint16_t size) { std::copy(data, data + size, std::back_inserter(sent_data)); }
- std::vector<uint8_t> sent_data;
-
- static ByteStuffer* Instance;
-};
-
-ByteStuffer* ByteStuffer::Instance = nullptr;
-
-extern "C" {
-void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) { ByteStuffer::Instance->validator_recv_frame(link, data, size); }
-
-void send_data(uint8_t link, const uint8_t* data, uint16_t size) { ByteStuffer::Instance->send_data(link, data, size); }
-}
-
-TEST_F(ByteStuffer, receives_no_frame_for_a_single_zero_byte) {
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_no_frame_for_a_single_FF_byte) {
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- byte_stuffer_recv_byte(0, 0xFF);
-}
-
-TEST_F(ByteStuffer, receives_no_frame_for_a_single_random_byte) {
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- byte_stuffer_recv_byte(0, 0x4A);
-}
-
-TEST_F(ByteStuffer, receives_no_frame_for_a_zero_length_frame) {
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_single_byte_valid_frame) {
- uint8_t expected[] = {0x37};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 0x37);
- byte_stuffer_recv_byte(0, 0);
-}
-TEST_F(ByteStuffer, receives_three_bytes_valid_frame) {
- uint8_t expected[] = {0x37, 0x99, 0xFF};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 4);
- byte_stuffer_recv_byte(0, 0x37);
- byte_stuffer_recv_byte(0, 0x99);
- byte_stuffer_recv_byte(0, 0xFF);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_single_zero_valid_frame) {
- uint8_t expected[] = {0};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_valid_frame_with_zeroes) {
- uint8_t expected[] = {5, 0, 3, 0};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 5);
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 3);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_two_valid_frames) {
- uint8_t expected1[] = {5, 0};
- uint8_t expected2[] = {3};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected1)));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected2)));
- byte_stuffer_recv_byte(1, 2);
- byte_stuffer_recv_byte(1, 5);
- byte_stuffer_recv_byte(1, 1);
- byte_stuffer_recv_byte(1, 0);
- byte_stuffer_recv_byte(1, 2);
- byte_stuffer_recv_byte(1, 3);
- byte_stuffer_recv_byte(1, 0);
-}
-
-TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_zero) {
- uint8_t expected[] = {5, 7};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(1, 3);
- byte_stuffer_recv_byte(1, 1);
- byte_stuffer_recv_byte(1, 0);
- byte_stuffer_recv_byte(1, 3);
- byte_stuffer_recv_byte(1, 5);
- byte_stuffer_recv_byte(1, 7);
- byte_stuffer_recv_byte(1, 0);
-}
-
-TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) {
- uint8_t expected[] = {5, 7};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 9);
- byte_stuffer_recv_byte(0, 4); // This should have been zero
- byte_stuffer_recv_byte(0, 0);
- byte_stuffer_recv_byte(0, 3);
- byte_stuffer_recv_byte(0, 5);
- byte_stuffer_recv_byte(0, 7);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) {
- uint8_t expected[254];
- int i;
- for (i = 0; i < 254; i++) {
- expected[i] = i + 1;
- }
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) {
- uint8_t expected[255];
- int i;
- for (i = 0; i < 254; i++) {
- expected[i] = i + 1;
- }
- expected[254] = 7;
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 7);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) {
- uint8_t expected[255];
- int i;
- for (i = 0; i < 254; i++) {
- expected[i] = i + 1;
- }
- expected[254] = 0;
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_two_long_frames_and_some_more) {
- uint8_t expected[515];
- int i;
- int j;
- for (j = 0; j < 2; j++) {
- for (i = 0; i < 254; i++) {
- expected[i + 254 * j] = i + 1;
- }
- }
- for (i = 0; i < 7; i++) {
- expected[254 * 2 + i] = i + 1;
- }
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 0xFF);
- for (i = 0; i < 254; i++) {
- byte_stuffer_recv_byte(0, i + 1);
- }
- byte_stuffer_recv_byte(0, 8);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 3);
- byte_stuffer_recv_byte(0, 4);
- byte_stuffer_recv_byte(0, 5);
- byte_stuffer_recv_byte(0, 6);
- byte_stuffer_recv_byte(0, 7);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) {
- uint8_t expected[MAX_FRAME_SIZE] = {};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- int i;
- byte_stuffer_recv_byte(0, 1);
- for (i = 0; i < MAX_FRAME_SIZE; i++) {
- byte_stuffer_recv_byte(0, 1);
- }
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) {
- uint8_t expected[1] = {0};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).Times(0);
- int i;
- byte_stuffer_recv_byte(0, 1);
- for (i = 0; i < MAX_FRAME_SIZE; i++) {
- byte_stuffer_recv_byte(0, 1);
- }
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, received_frame_is_aborted_when_its_too_long) {
- uint8_t expected[1] = {1};
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- int i;
- byte_stuffer_recv_byte(0, 1);
- for (i = 0; i < MAX_FRAME_SIZE; i++) {
- byte_stuffer_recv_byte(0, 1);
- }
- byte_stuffer_recv_byte(0, 2);
- byte_stuffer_recv_byte(0, 1);
- byte_stuffer_recv_byte(0, 0);
-}
-
-TEST_F(ByteStuffer, does_nothing_when_sending_zero_size_frame) {
- EXPECT_EQ(sent_data.size(), 0);
- byte_stuffer_send_frame(0, NULL, 0);
-}
-
-TEST_F(ByteStuffer, send_one_byte_frame) {
- uint8_t data[] = {5};
- byte_stuffer_send_frame(1, data, 1);
- uint8_t expected[] = {2, 5, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_two_byte_frame) {
- uint8_t data[] = {5, 0x77};
- byte_stuffer_send_frame(0, data, 2);
- uint8_t expected[] = {3, 5, 0x77, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_one_byte_frame_with_zero) {
- uint8_t data[] = {0};
- byte_stuffer_send_frame(0, data, 1);
- uint8_t expected[] = {1, 1, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_zero) {
- uint8_t data[] = {0, 9};
- byte_stuffer_send_frame(1, data, 2);
- uint8_t expected[] = {1, 2, 9, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) {
- uint8_t data[] = {9, 0};
- byte_stuffer_send_frame(1, data, 2);
- uint8_t expected[] = {2, 9, 1, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) {
- uint8_t data[] = {9, 0, 0x68};
- byte_stuffer_send_frame(0, data, 3);
- uint8_t expected[] = {2, 9, 2, 0x68, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_three_byte_frame_data_in_the_middle) {
- uint8_t data[] = {0, 0x55, 0};
- byte_stuffer_send_frame(0, data, 3);
- uint8_t expected[] = {1, 2, 0x55, 1, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_three_byte_frame_with_all_zeroes) {
- uint8_t data[] = {0, 0, 0};
- byte_stuffer_send_frame(0, data, 3);
- uint8_t expected[] = {1, 1, 1, 1, 0};
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes) {
- uint8_t data[254];
- int i;
- for (i = 0; i < 254; i++) {
- data[i] = i + 1;
- }
- byte_stuffer_send_frame(0, data, 254);
- uint8_t expected[256];
- expected[0] = 0xFF;
- for (i = 1; i < 255; i++) {
- expected[i] = i;
- }
- expected[255] = 0;
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_frame_with_255_non_zeroes) {
- uint8_t data[255];
- int i;
- for (i = 0; i < 255; i++) {
- data[i] = i + 1;
- }
- byte_stuffer_send_frame(0, data, 255);
- uint8_t expected[258];
- expected[0] = 0xFF;
- for (i = 1; i < 255; i++) {
- expected[i] = i;
- }
- expected[255] = 2;
- expected[256] = 255;
- expected[257] = 0;
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) {
- uint8_t data[255];
- int i;
- for (i = 0; i < 254; i++) {
- data[i] = i + 1;
- }
- data[254] = 0;
- byte_stuffer_send_frame(0, data, 255);
- uint8_t expected[258];
- expected[0] = 0xFF;
- for (i = 1; i < 255; i++) {
- expected[i] = i;
- }
- expected[255] = 1;
- expected[256] = 1;
- expected[257] = 0;
- EXPECT_THAT(sent_data, ElementsAreArray(expected));
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) {
- uint8_t original_data[] = {1, 2, 3};
- byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- int i;
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) {
- uint8_t original_data[] = {1, 0, 3, 0, 0, 9};
- byte_stuffer_send_frame(1, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- int i;
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) {
- uint8_t original_data[254];
- int i;
- for (i = 0; i < 254; i++) {
- original_data[i] = i + 1;
- }
- byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) {
- uint8_t original_data[256];
- int i;
- for (i = 0; i < 254; i++) {
- original_data[i] = i + 1;
- }
- original_data[254] = 22;
- original_data[255] = 23;
- byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
-
-TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) {
- uint8_t original_data[255];
- int i;
- for (i = 0; i < 254; i++) {
- original_data[i] = i + 1;
- }
- original_data[254] = 0;
- byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- EXPECT_CALL(*this, validator_recv_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(original_data)));
- for (auto& d : sent_data) {
- byte_stuffer_recv_byte(1, d);
- }
-}
diff --git a/quantum/serial_link/tests/frame_router_tests.cpp b/quantum/serial_link/tests/frame_router_tests.cpp
deleted file mode 100644
index f76dfb33d6..0000000000
--- a/quantum/serial_link/tests/frame_router_tests.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-#include <array>
-extern "C" {
-#include "serial_link/protocol/transport.h"
-#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/frame_router.h"
-}
-
-using testing::_;
-using testing::Args;
-using testing::ElementsAreArray;
-
-class FrameRouter : public testing::Test {
- public:
- FrameRouter() : current_router_buffer(nullptr) {
- Instance = this;
- init_byte_stuffer();
- }
-
- ~FrameRouter() { Instance = nullptr; }
-
- void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
- auto& buffer = current_router_buffer->send_buffers[link];
- std::copy(data, data + size, std::back_inserter(buffer));
- }
-
- void receive_data(uint8_t link, uint8_t* data, uint16_t size) {
- int i;
- for (i = 0; i < size; i++) {
- byte_stuffer_recv_byte(link, data[i]);
- }
- }
-
- void activate_router(uint8_t num) {
- current_router_buffer = router_buffers + num;
- router_set_master(num == 0);
- }
-
- void simulate_transport(uint8_t from, uint8_t to) {
- activate_router(to);
- if (from > to) {
- receive_data(DOWN_LINK, router_buffers[from].send_buffers[UP_LINK].data(), router_buffers[from].send_buffers[UP_LINK].size());
- } else if (to > from) {
- receive_data(UP_LINK, router_buffers[from].send_buffers[DOWN_LINK].data(), router_buffers[from].send_buffers[DOWN_LINK].size());
- }
- }
-
- MOCK_METHOD3(transport_recv_frame, void(uint8_t from, uint8_t* data, uint16_t size));
-
- std::vector<uint8_t> received_data;
-
- struct router_buffer {
- std::vector<uint8_t> send_buffers[2];
- };
-
- router_buffer router_buffers[8];
- router_buffer* current_router_buffer;
-
- static FrameRouter* Instance;
-};
-
-FrameRouter* FrameRouter::Instance = nullptr;
-
-typedef struct {
- std::array<uint8_t, 4> data;
- uint8_t extra[16];
-} frame_buffer_t;
-
-extern "C" {
-void send_data(uint8_t link, const uint8_t* data, uint16_t size) { FrameRouter::Instance->send_data(link, data, size); }
-
-void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) { FrameRouter::Instance->transport_recv_frame(from, data, size); }
-}
-
-TEST_F(FrameRouter, master_broadcast_is_received_by_everyone) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(0);
- router_send_frame(0xFF, (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
- EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(0, 1);
- EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(1, 2);
- EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, master_send_is_received_by_targets) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(0);
- router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
-
- simulate_transport(0, 1);
- EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(1, 2);
- EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(0, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(2, 3);
- EXPECT_GT(router_buffers[3].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[3].send_buffers[UP_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, first_link_sends_to_master) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(1);
- router_send_frame(0, (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(1, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(1, 0);
- EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, second_link_sends_to_master) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(2);
- router_send_frame(0, (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[2].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
-
- simulate_transport(2, 1);
- EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(2, _, _)).With(Args<1, 2>(ElementsAreArray(data.data)));
- simulate_transport(1, 0);
- EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, master_sends_to_master_does_nothing) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(0);
- router_send_frame(0, (uint8_t*)&data, 4);
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, link_sends_to_other_link_does_nothing) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(1);
- router_send_frame(2, (uint8_t*)&data, 4);
- EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
-}
-
-TEST_F(FrameRouter, master_receives_on_uplink_does_nothing) {
- frame_buffer_t data;
- data.data = {0xAB, 0x70, 0x55, 0xBB};
- activate_router(1);
- router_send_frame(0, (uint8_t*)&data, 4);
- EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
-
- EXPECT_CALL(*this, transport_recv_frame(_, _, _)).Times(0);
- activate_router(0);
- receive_data(UP_LINK, router_buffers[1].send_buffers[UP_LINK].data(), router_buffers[1].send_buffers[UP_LINK].size());
- EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
- EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
-}
diff --git a/quantum/serial_link/tests/frame_validator_tests.cpp b/quantum/serial_link/tests/frame_validator_tests.cpp
deleted file mode 100644
index 43dc57b633..0000000000
--- a/quantum/serial_link/tests/frame_validator_tests.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-extern "C" {
-#include "serial_link/protocol/frame_validator.h"
-}
-
-using testing::_;
-using testing::Args;
-using testing::ElementsAreArray;
-
-class FrameValidator : public testing::Test {
- public:
- FrameValidator() { Instance = this; }
-
- ~FrameValidator() { Instance = nullptr; }
-
- MOCK_METHOD3(route_incoming_frame, void(uint8_t link, uint8_t* data, uint16_t size));
- MOCK_METHOD3(byte_stuffer_send_frame, void(uint8_t link, uint8_t* data, uint16_t size));
-
- static FrameValidator* Instance;
-};
-
-FrameValidator* FrameValidator::Instance = nullptr;
-
-extern "C" {
-void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->route_incoming_frame(link, data, size); }
-
-void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) { FrameValidator::Instance->byte_stuffer_send_frame(link, data, size); }
-}
-
-TEST_F(FrameValidator, doesnt_validate_frames_under_5_bytes) {
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0);
- uint8_t data[] = {1, 2};
- validator_recv_frame(0, 0, 1);
- validator_recv_frame(0, data, 2);
- validator_recv_frame(0, data, 3);
- validator_recv_frame(0, data, 4);
-}
-
-TEST_F(FrameValidator, validates_one_byte_frame_with_correct_crc) {
- uint8_t data[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 1)));
- validator_recv_frame(0, data, 5);
-}
-
-TEST_F(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) {
- uint8_t data[] = {0x44, 0, 0, 0, 0};
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).Times(0);
- validator_recv_frame(1, data, 5);
-}
-
-TEST_F(FrameValidator, validates_four_byte_frame_with_correct_crc) {
- uint8_t data[] = {0x44, 0x10, 0xFF, 0x00, 0x74, 0x4E, 0x30, 0xBA};
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 4)));
- validator_recv_frame(1, data, 8);
-}
-
-TEST_F(FrameValidator, validates_five_byte_frame_with_correct_crc) {
- uint8_t data[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
- EXPECT_CALL(*this, route_incoming_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(data, 5)));
- validator_recv_frame(0, data, 9);
-}
-
-TEST_F(FrameValidator, sends_one_byte_with_correct_crc) {
- uint8_t original[] = {0x44, 0, 0, 0, 0};
- uint8_t expected[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
- EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- validator_send_frame(0, original, 1);
-}
-
-TEST_F(FrameValidator, sends_five_bytes_with_correct_crc) {
- uint8_t original[] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
- uint8_t expected[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
- EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _)).With(Args<1, 2>(ElementsAreArray(expected)));
- validator_send_frame(0, original, 5);
-}
diff --git a/quantum/serial_link/tests/rules.mk b/quantum/serial_link/tests/rules.mk
deleted file mode 100644
index b81515bc55..0000000000
--- a/quantum/serial_link/tests/rules.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-serial_link_byte_stuffer_SRC :=\
- $(SERIAL_PATH)/tests/byte_stuffer_tests.cpp \
- $(SERIAL_PATH)/protocol/byte_stuffer.c
-
-serial_link_frame_validator_SRC := \
- $(SERIAL_PATH)/tests/frame_validator_tests.cpp \
- $(SERIAL_PATH)/protocol/frame_validator.c
-
-serial_link_frame_router_SRC := \
- $(SERIAL_PATH)/tests/frame_router_tests.cpp \
- $(SERIAL_PATH)/protocol/byte_stuffer.c \
- $(SERIAL_PATH)/protocol/frame_validator.c \
- $(SERIAL_PATH)/protocol/frame_router.c
-
-serial_link_triple_buffered_object_SRC := \
- $(SERIAL_PATH)/tests/triple_buffered_object_tests.cpp \
- $(SERIAL_PATH)/protocol/triple_buffered_object.c
-
-serial_link_transport_SRC := \
- $(SERIAL_PATH)/tests/transport_tests.cpp \
- $(SERIAL_PATH)/protocol/transport.c \
- $(SERIAL_PATH)/protocol/triple_buffered_object.c
diff --git a/quantum/serial_link/tests/testlist.mk b/quantum/serial_link/tests/testlist.mk
deleted file mode 100644
index c5edaf478f..0000000000
--- a/quantum/serial_link/tests/testlist.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-TEST_LIST +=\
- serial_link_byte_stuffer\
- serial_link_frame_validator\
- serial_link_frame_router\
- serial_link_triple_buffered_object\
- serial_link_transport
diff --git a/quantum/serial_link/tests/transport_tests.cpp b/quantum/serial_link/tests/transport_tests.cpp
deleted file mode 100644
index cfd1110460..0000000000
--- a/quantum/serial_link/tests/transport_tests.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-#include "gmock/gmock.h"
-
-using testing::_;
-using testing::Args;
-using testing::ElementsAreArray;
-
-extern "C" {
-#include "serial_link/protocol/transport.h"
-}
-
-struct test_object1 {
- uint32_t test;
-};
-
-struct test_object2 {
- uint32_t test1;
- uint32_t test2;
-};
-
-MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1);
-MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1);
-SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1);
-
-static remote_object_t* test_remote_objects[] = {
- REMOTE_OBJECT(master_to_slave),
- REMOTE_OBJECT(master_to_single_slave),
- REMOTE_OBJECT(slave_to_master),
-};
-
-class Transport : public testing::Test {
- public:
- Transport() {
- Instance = this;
- add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
- }
-
- ~Transport() {
- Instance = nullptr;
- reinitialize_serial_link_transport();
- }
-
- MOCK_METHOD0(signal_data_written, void());
- MOCK_METHOD1(router_send_frame, void(uint8_t destination));
-
- void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
- router_send_frame(destination);
- std::copy(data, data + size, std::back_inserter(sent_data));
- }
-
- static Transport* Instance;
-
- std::vector<uint8_t> sent_data;
-};
-
-Transport* Transport::Instance = nullptr;
-
-extern "C" {
-void signal_data_written(void) { Transport::Instance->signal_data_written(); }
-
-void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) { Transport::Instance->router_send_frame(destination, data, size); }
-}
-
-TEST_F(Transport, write_to_local_signals_an_event) {
- begin_write_master_to_slave();
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_slave();
- begin_write_slave_to_master();
- EXPECT_CALL(*this, signal_data_written());
- end_write_slave_to_master();
- begin_write_master_to_single_slave(1);
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_single_slave(1);
-}
-
-TEST_F(Transport, writes_from_master_to_all_slaves) {
- update_transport();
- test_object1* obj = begin_write_master_to_slave();
- obj->test = 5;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_slave();
- EXPECT_CALL(*this, router_send_frame(0xFF));
- update_transport();
- transport_recv_frame(0, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_master_to_slave();
- EXPECT_NE(obj2, nullptr);
- EXPECT_EQ(obj2->test, 5);
-}
-
-TEST_F(Transport, writes_from_slave_to_master) {
- update_transport();
- test_object1* obj = begin_write_slave_to_master();
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_slave_to_master();
- EXPECT_CALL(*this, router_send_frame(0));
- update_transport();
- transport_recv_frame(3, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_slave_to_master(2);
- EXPECT_EQ(read_slave_to_master(0), nullptr);
- EXPECT_NE(obj2, nullptr);
- EXPECT_EQ(obj2->test, 7);
-}
-
-TEST_F(Transport, writes_from_master_to_single_slave) {
- update_transport();
- test_object1* obj = begin_write_master_to_single_slave(3);
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_single_slave(3);
- EXPECT_CALL(*this, router_send_frame(4));
- update_transport();
- transport_recv_frame(0, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_master_to_single_slave();
- EXPECT_NE(obj2, nullptr);
- EXPECT_EQ(obj2->test, 7);
-}
-
-TEST_F(Transport, ignores_object_with_invalid_id) {
- update_transport();
- test_object1* obj = begin_write_master_to_single_slave(3);
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_single_slave(3);
- EXPECT_CALL(*this, router_send_frame(4));
- update_transport();
- sent_data[sent_data.size() - 1] = 44;
- transport_recv_frame(0, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_master_to_single_slave();
- EXPECT_EQ(obj2, nullptr);
-}
-
-TEST_F(Transport, ignores_object_with_size_too_small) {
- update_transport();
- test_object1* obj = begin_write_master_to_slave();
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_slave();
- EXPECT_CALL(*this, router_send_frame(_));
- update_transport();
- sent_data[sent_data.size() - 2] = 0;
- transport_recv_frame(0, sent_data.data(), sent_data.size() - 1);
- test_object1* obj2 = read_master_to_slave();
- EXPECT_EQ(obj2, nullptr);
-}
-
-TEST_F(Transport, ignores_object_with_size_too_big) {
- update_transport();
- test_object1* obj = begin_write_master_to_slave();
- obj->test = 7;
- EXPECT_CALL(*this, signal_data_written());
- end_write_master_to_slave();
- EXPECT_CALL(*this, router_send_frame(_));
- update_transport();
- sent_data.resize(sent_data.size() + 22);
- sent_data[sent_data.size() - 1] = 0;
- transport_recv_frame(0, sent_data.data(), sent_data.size());
- test_object1* obj2 = read_master_to_slave();
- EXPECT_EQ(obj2, nullptr);
-}
diff --git a/quantum/serial_link/tests/triple_buffered_object_tests.cpp b/quantum/serial_link/tests/triple_buffered_object_tests.cpp
deleted file mode 100644
index 8de9bfdebf..0000000000
--- a/quantum/serial_link/tests/triple_buffered_object_tests.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "gtest/gtest.h"
-extern "C" {
-#include "serial_link/protocol/triple_buffered_object.h"
-}
-
-struct test_object {
- uint8_t state;
- uint32_t buffer[3];
-};
-
-test_object test_object;
-
-class TripleBufferedObject : public testing::Test {
- public:
- TripleBufferedObject() { triple_buffer_init((triple_buffer_object_t*)&test_object); }
-};
-
-TEST_F(TripleBufferedObject, writes_and_reads_object) {
- *triple_buffer_begin_write(&test_object) = 0x3456ABCC;
- triple_buffer_end_write(&test_object);
- EXPECT_EQ(*triple_buffer_read(&test_object), 0x3456ABCC);
-}
-
-TEST_F(TripleBufferedObject, does_not_read_empty) { EXPECT_EQ(triple_buffer_read(&test_object), nullptr); }
-
-TEST_F(TripleBufferedObject, writes_twice_and_reads_object) {
- *triple_buffer_begin_write(&test_object) = 0x3456ABCC;
- triple_buffer_end_write(&test_object);
- *triple_buffer_begin_write(&test_object) = 0x44778899;
- triple_buffer_end_write(&test_object);
- EXPECT_EQ(*triple_buffer_read(&test_object), 0x44778899);
-}
-
-TEST_F(TripleBufferedObject, performs_another_write_in_the_middle_of_read) {
- *triple_buffer_begin_write(&test_object) = 1;
- triple_buffer_end_write(&test_object);
- uint32_t* read = triple_buffer_read(&test_object);
- *triple_buffer_begin_write(&test_object) = 2;
- triple_buffer_end_write(&test_object);
- EXPECT_EQ(*read, 1);
- EXPECT_EQ(*triple_buffer_read(&test_object), 2);
- EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
-}
-
-TEST_F(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) {
- *triple_buffer_begin_write(&test_object) = 1;
- triple_buffer_end_write(&test_object);
- uint32_t* read = triple_buffer_read(&test_object);
- *triple_buffer_begin_write(&test_object) = 2;
- triple_buffer_end_write(&test_object);
- *triple_buffer_begin_write(&test_object) = 3;
- triple_buffer_end_write(&test_object);
- EXPECT_EQ(*read, 1);
- EXPECT_EQ(*triple_buffer_read(&test_object), 3);
- EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
-}
diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c
index fd676f0729..3ff87710e7 100644
--- a/quantum/split_common/transactions.c
+++ b/quantum/split_common/transactions.c
@@ -42,8 +42,8 @@
{ &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb }
#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL)
-#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
-#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
+#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
+#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
// Forward-declare the RPC callback handlers
@@ -157,8 +157,8 @@ static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_ro
memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix));
}
-# define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix)
-# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix)
+# define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix)
+# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix)
# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix),
#else // SPLIT_TRANSPORT_MIRROR
@@ -235,8 +235,8 @@ static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
}
}
-# define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer)
-# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer)
+# define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer)
+# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer)
# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer),
#else // DISABLE_SYNC_TIMER
@@ -300,8 +300,8 @@ static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
set_split_host_keyboard_leds(split_shmem->led_state);
}
-# define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state)
-# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state)
+# define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state)
+# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state)
# define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state),
#else // SPLIT_LED_STATE_ENABLE
@@ -357,8 +357,8 @@ static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave
# endif
}
-# define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods)
-# define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods)
+# define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods)
+# define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods)
# define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods),
#else // SPLIT_MODS_ENABLE
@@ -382,8 +382,8 @@ static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t
static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); }
-# define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight)
-# define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight)
+# define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight)
+# define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight)
# define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level),
#else // BACKLIGHT_ENABLE
@@ -419,8 +419,8 @@ static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s
}
}
-# define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight)
-# define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight)
+# define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight)
+# define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight)
# define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync),
#else // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
@@ -449,8 +449,8 @@ static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state);
}
-# define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix)
-# define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix)
+# define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix)
+# define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix)
# define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync),
#else // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
@@ -479,8 +479,8 @@ static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state);
}
-# define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix)
-# define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix)
+# define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix)
+# define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix)
# define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync),
#else // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
@@ -504,8 +504,8 @@ static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave
static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); }
-# define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm)
-# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm)
+# define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm)
+# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm)
# define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm),
#else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
@@ -535,8 +535,8 @@ static void oled_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave
}
}
-# define TRANSACTIONS_OLED_MASTER() TRANSACTION_HANDLER_MASTER(oled)
-# define TRANSACTIONS_OLED_SLAVE() TRANSACTION_HANDLER_SLAVE(oled)
+# define TRANSACTIONS_OLED_MASTER() TRANSACTION_HANDLER_MASTER(oled)
+# define TRANSACTIONS_OLED_SLAVE() TRANSACTION_HANDLER_SLAVE(oled)
# define TRANSACTIONS_OLED_REGISTRATIONS [PUT_OLED] = trans_initiator2target_initializer(current_oled_state),
#else // defined(OLED_ENABLE) && defined(SPLIT_OLED_ENABLE)
@@ -566,8 +566,8 @@ static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla
}
}
-# define TRANSACTIONS_ST7565_MASTER() TRANSACTION_HANDLER_MASTER(st7565)
-# define TRANSACTIONS_ST7565_SLAVE() TRANSACTION_HANDLER_SLAVE(st7565)
+# define TRANSACTIONS_ST7565_MASTER() TRANSACTION_HANDLER_MASTER(st7565)
+# define TRANSACTIONS_ST7565_SLAVE() TRANSACTION_HANDLER_SLAVE(st7565)
# define TRANSACTIONS_ST7565_REGISTRATIONS [PUT_ST7565] = trans_initiator2target_initializer(current_st7565_state),
#else // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
diff --git a/quantum/sync_timer.c b/quantum/sync_timer.c
new file mode 100644
index 0000000000..de24b463b6
--- /dev/null
+++ b/quantum/sync_timer.c
@@ -0,0 +1,58 @@
+/*
+Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+If you happen to meet one of the copyright holders in a bar you are obligated
+to buy them one pint of beer.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include "sync_timer.h"
+#include "keyboard.h"
+
+#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
+volatile int32_t sync_timer_ms;
+
+void sync_timer_init(void) { sync_timer_ms = 0; }
+
+void sync_timer_update(uint32_t time) {
+ if (is_keyboard_master()) return;
+ sync_timer_ms = time - timer_read32();
+}
+
+uint16_t sync_timer_read(void) {
+ if (is_keyboard_master()) return timer_read();
+ return sync_timer_read32();
+}
+
+uint32_t sync_timer_read32(void) {
+ if (is_keyboard_master()) return timer_read32();
+ return sync_timer_ms + timer_read32();
+}
+
+uint16_t sync_timer_elapsed(uint16_t last) {
+ if (is_keyboard_master()) return timer_elapsed(last);
+ return TIMER_DIFF_16(sync_timer_read(), last);
+}
+
+uint32_t sync_timer_elapsed32(uint32_t last) {
+ if (is_keyboard_master()) return timer_elapsed32(last);
+ return TIMER_DIFF_32(sync_timer_read32(), last);
+}
+#endif
diff --git a/quantum/sync_timer.h b/quantum/sync_timer.h
new file mode 100644
index 0000000000..9ddef45bb2
--- /dev/null
+++ b/quantum/sync_timer.h
@@ -0,0 +1,54 @@
+/*
+Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+If you happen to meet one of the copyright holders in a bar you are obligated
+to buy them one pint of beer.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#pragma once
+
+#include <stdint.h>
+#include "timer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
+void sync_timer_init(void);
+void sync_timer_update(uint32_t time);
+uint16_t sync_timer_read(void);
+uint32_t sync_timer_read32(void);
+uint16_t sync_timer_elapsed(uint16_t last);
+uint32_t sync_timer_elapsed32(uint32_t last);
+#else
+# define sync_timer_init()
+# define sync_timer_clear()
+# define sync_timer_update(t)
+# define sync_timer_read() timer_read()
+# define sync_timer_read32() timer_read32()
+# define sync_timer_elapsed(t) timer_elapsed(t)
+# define sync_timer_elapsed32(t) timer_elapsed32(t)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/quantum/via.c b/quantum/via.c
index 1b2dbcf08d..7c8aa753e7 100644
--- a/quantum/via.c
+++ b/quantum/via.c
@@ -44,7 +44,7 @@
#include "raw_hid.h"
#include "dynamic_keymap.h"
-#include "tmk_core/common/eeprom.h"
+#include "eeprom.h"
#include "version.h" // for QMK_BUILDDATE used in EEPROM magic
#include "via_ensure_keycode.h"
diff --git a/quantum/via_ensure_keycode.h b/quantum/via_ensure_keycode.h
index a9c1b8ba5d..1aba0cdd2a 100644
--- a/quantum/via_ensure_keycode.h
+++ b/quantum/via_ensure_keycode.h
@@ -5,362 +5,338 @@
#ifndef VIA_HAS_BROKEN_KEYCODES
-_Static_assert(KC_NO == 0, "");
-_Static_assert(KC_TRNS == 1, "");
+// clang-format off
-_Static_assert(KC_A == 0x04, "");
-_Static_assert(KC_B == 0x05, "");
-_Static_assert(KC_C == 0x06, "");
-_Static_assert(KC_D == 0x07, "");
-_Static_assert(KC_E == 0x08, "");
-_Static_assert(KC_F == 0x09, "");
-_Static_assert(KC_G == 0x0A, "");
-_Static_assert(KC_H == 0x0B, "");
-_Static_assert(KC_I == 0x0C, "");
-_Static_assert(KC_J == 0x0D, "");
-_Static_assert(KC_K == 0x0E, "");
-_Static_assert(KC_L == 0x0F, "");
-_Static_assert(KC_M == 0x10, "");
-_Static_assert(KC_N == 0x11, "");
-_Static_assert(KC_O == 0x12, "");
-_Static_assert(KC_P == 0x13, "");
-_Static_assert(KC_Q == 0x14, "");
-_Static_assert(KC_R == 0x15, "");
-_Static_assert(KC_S == 0x16, "");
-_Static_assert(KC_T == 0x17, "");
-_Static_assert(KC_U == 0x18, "");
-_Static_assert(KC_V == 0x19, "");
-_Static_assert(KC_W == 0x1A, "");
-_Static_assert(KC_X == 0x1B, "");
-_Static_assert(KC_Y == 0x1C, "");
-_Static_assert(KC_Z == 0x1D, "");
-_Static_assert(KC_1 == 0x1E, "");
-_Static_assert(KC_2 == 0x1F, "");
-_Static_assert(KC_3 == 0x20, "");
-_Static_assert(KC_4 == 0x21, "");
-_Static_assert(KC_5 == 0x22, "");
-_Static_assert(KC_6 == 0x23, "");
-_Static_assert(KC_7 == 0x24, "");
-_Static_assert(KC_8 == 0x25, "");
-_Static_assert(KC_9 == 0x26, "");
-_Static_assert(KC_0 == 0x27, "");
-_Static_assert(KC_ENTER == 0x28, "");
-_Static_assert(KC_ESCAPE == 0x29, "");
-_Static_assert(KC_BSPACE == 0x2A, "");
-_Static_assert(KC_TAB == 0x2B, "");
-_Static_assert(KC_SPACE == 0x2C, "");
-_Static_assert(KC_MINUS == 0x2D, "");
-_Static_assert(KC_EQUAL == 0x2E, "");
-_Static_assert(KC_LBRACKET == 0x2F, "");
-_Static_assert(KC_RBRACKET == 0x30, "");
-_Static_assert(KC_BSLASH == 0x31, "");
-_Static_assert(KC_SCOLON == 0x33, "");
-_Static_assert(KC_QUOTE == 0x34, "");
-_Static_assert(KC_GRAVE == 0x35, "");
-_Static_assert(KC_COMMA == 0x36, "");
-_Static_assert(KC_DOT == 0x37, "");
-_Static_assert(KC_SLASH == 0x38, "");
-_Static_assert(KC_CAPSLOCK == 0x39, "");
-_Static_assert(KC_F1 == 0x3A, "");
-_Static_assert(KC_F2 == 0x3B, "");
-_Static_assert(KC_F3 == 0x3C, "");
-_Static_assert(KC_F4 == 0x3D, "");
-_Static_assert(KC_F5 == 0x3E, "");
-_Static_assert(KC_F6 == 0x3F, "");
-_Static_assert(KC_F7 == 0x40, "");
-_Static_assert(KC_F8 == 0x41, "");
-_Static_assert(KC_F9 == 0x42, "");
-_Static_assert(KC_F10 == 0x43, "");
-_Static_assert(KC_F11 == 0x44, "");
-_Static_assert(KC_F12 == 0x45, "");
-_Static_assert(KC_PSCREEN == 0x46, "");
-_Static_assert(KC_SCROLLLOCK == 0x47, "");
-_Static_assert(KC_PAUSE == 0x48, "");
-_Static_assert(KC_INSERT == 0x49, "");
-_Static_assert(KC_HOME == 0x4A, "");
-_Static_assert(KC_PGUP == 0x4B, "");
-_Static_assert(KC_DELETE == 0x4C, "");
-_Static_assert(KC_END == 0x4D, "");
-_Static_assert(KC_PGDOWN == 0x4E, "");
-_Static_assert(KC_RIGHT == 0x4F, "");
-_Static_assert(KC_LEFT == 0x50, "");
-_Static_assert(KC_DOWN == 0x51, "");
-_Static_assert(KC_UP == 0x52, "");
-_Static_assert(KC_NUMLOCK == 0x53, "");
-_Static_assert(KC_KP_SLASH == 0x54, "");
-_Static_assert(KC_KP_ASTERISK == 0x55, "");
-_Static_assert(KC_KP_MINUS == 0x56, "");
-_Static_assert(KC_KP_PLUS == 0x57, "");
-_Static_assert(KC_KP_ENTER == 0x58, "");
-_Static_assert(KC_KP_1 == 0x59, "");
-_Static_assert(KC_KP_2 == 0x5A, "");
-_Static_assert(KC_KP_3 == 0x5B, "");
-_Static_assert(KC_KP_4 == 0x5C, "");
-_Static_assert(KC_KP_5 == 0x5D, "");
-_Static_assert(KC_KP_6 == 0x5E, "");
-_Static_assert(KC_KP_7 == 0x5F, "");
-_Static_assert(KC_KP_8 == 0x60, "");
-_Static_assert(KC_KP_9 == 0x61, "");
-_Static_assert(KC_KP_0 == 0x62, "");
-_Static_assert(KC_KP_DOT == 0x63, "");
-_Static_assert(KC_APPLICATION == 0x65, "");
-_Static_assert(KC_KP_EQUAL == 0x67, "");
-_Static_assert(KC_KP_COMMA == 0x85, "");
-_Static_assert(KC_LCTRL == 0xE0, "");
-_Static_assert(KC_LSHIFT == 0xE1, "");
-_Static_assert(KC_LALT == 0xE2, "");
-_Static_assert(KC_LGUI == 0xE3, "");
-_Static_assert(KC_RCTRL == 0xE4, "");
-_Static_assert(KC_RSHIFT == 0xE5, "");
-_Static_assert(KC_RALT == 0xE6, "");
-_Static_assert(KC_RGUI == 0xE7, "");
+_Static_assert(KC_NO == 0x0000, "");
+_Static_assert(KC_TRANSPARENT == 0x0001, "");
-_Static_assert(KC_TILD == 0x235, "");
-_Static_assert(KC_EXLM == 0x21E, "");
-_Static_assert(KC_AT == 0x21F, "");
-_Static_assert(KC_HASH == 0x220, "");
-_Static_assert(KC_DLR == 0x221, "");
-_Static_assert(KC_PERC == 0x222, "");
-_Static_assert(KC_CIRC == 0x223, "");
-_Static_assert(KC_AMPR == 0x224, "");
-_Static_assert(KC_ASTR == 0x225, "");
-_Static_assert(KC_LPRN == 0x226, "");
-_Static_assert(KC_RPRN == 0x227, "");
-_Static_assert(KC_UNDS == 0x22D, "");
-_Static_assert(KC_PLUS == 0x22E, "");
-_Static_assert(KC_LCBR == 0x22F, "");
-_Static_assert(KC_RCBR == 0x230, "");
-_Static_assert(KC_LT == 0x236, "");
-_Static_assert(KC_GT == 0x237, "");
-_Static_assert(KC_COLN == 0x233, "");
-_Static_assert(KC_PIPE == 0x231, "");
-_Static_assert(KC_QUES == 0x238, "");
-_Static_assert(KC_DQUO == 0x234, "");
+_Static_assert(KC_A == 0x0004, "");
+_Static_assert(KC_B == 0x0005, "");
+_Static_assert(KC_C == 0x0006, "");
+_Static_assert(KC_D == 0x0007, "");
+_Static_assert(KC_E == 0x0008, "");
+_Static_assert(KC_F == 0x0009, "");
+_Static_assert(KC_G == 0x000A, "");
+_Static_assert(KC_H == 0x000B, "");
+_Static_assert(KC_I == 0x000C, "");
+_Static_assert(KC_J == 0x000D, "");
+_Static_assert(KC_K == 0x000E, "");
+_Static_assert(KC_L == 0x000F, "");
+_Static_assert(KC_M == 0x0010, "");
+_Static_assert(KC_N == 0x0011, "");
+_Static_assert(KC_O == 0x0012, "");
+_Static_assert(KC_P == 0x0013, "");
+_Static_assert(KC_Q == 0x0014, "");
+_Static_assert(KC_R == 0x0015, "");
+_Static_assert(KC_S == 0x0016, "");
+_Static_assert(KC_T == 0x0017, "");
+_Static_assert(KC_U == 0x0018, "");
+_Static_assert(KC_V == 0x0019, "");
+_Static_assert(KC_W == 0x001A, "");
+_Static_assert(KC_X == 0x001B, "");
+_Static_assert(KC_Y == 0x001C, "");
+_Static_assert(KC_Z == 0x001D, "");
+_Static_assert(KC_1 == 0x001E, "");
+_Static_assert(KC_2 == 0x001F, "");
+_Static_assert(KC_3 == 0x0020, "");
+_Static_assert(KC_4 == 0x0021, "");
+_Static_assert(KC_5 == 0x0022, "");
+_Static_assert(KC_6 == 0x0023, "");
+_Static_assert(KC_7 == 0x0024, "");
+_Static_assert(KC_8 == 0x0025, "");
+_Static_assert(KC_9 == 0x0026, "");
+_Static_assert(KC_0 == 0x0027, "");
+_Static_assert(KC_ENTER == 0x0028, "");
+_Static_assert(KC_ESCAPE == 0x0029, "");
+_Static_assert(KC_BACKSPACE == 0x002A, "");
+_Static_assert(KC_TAB == 0x002B, "");
+_Static_assert(KC_SPACE == 0x002C, "");
+_Static_assert(KC_MINUS == 0x002D, "");
+_Static_assert(KC_EQUAL == 0x002E, "");
+_Static_assert(KC_LEFT_BRACKET == 0x002F, "");
+_Static_assert(KC_RIGHT_BRACKET == 0x0030, "");
+_Static_assert(KC_BACKSLASH == 0x0031, "");
+_Static_assert(KC_NONUS_HASH == 0x0032, "");
+_Static_assert(KC_SEMICOLON == 0x0033, "");
+_Static_assert(KC_QUOTE == 0x0034, "");
+_Static_assert(KC_GRAVE == 0x0035, "");
+_Static_assert(KC_COMMA == 0x0036, "");
+_Static_assert(KC_DOT == 0x0037, "");
+_Static_assert(KC_SLASH == 0x0038, "");
+_Static_assert(KC_CAPS_LOCK == 0x0039, "");
+_Static_assert(KC_F1 == 0x003A, "");
+_Static_assert(KC_F2 == 0x003B, "");
+_Static_assert(KC_F3 == 0x003C, "");
+_Static_assert(KC_F4 == 0x003D, "");
+_Static_assert(KC_F5 == 0x003E, "");
+_Static_assert(KC_F6 == 0x003F, "");
+_Static_assert(KC_F7 == 0x0040, "");
+_Static_assert(KC_F8 == 0x0041, "");
+_Static_assert(KC_F9 == 0x0042, "");
+_Static_assert(KC_F10 == 0x0043, "");
+_Static_assert(KC_F11 == 0x0044, "");
+_Static_assert(KC_F12 == 0x0045, "");
+_Static_assert(KC_PRINT_SCREEN == 0x0046, "");
+_Static_assert(KC_SCROLL_LOCK == 0x0047, "");
+_Static_assert(KC_PAUSE == 0x0048, "");
+_Static_assert(KC_INSERT == 0x0049, "");
+_Static_assert(KC_HOME == 0x004A, "");
+_Static_assert(KC_PAGE_UP == 0x004B, "");
+_Static_assert(KC_DELETE == 0x004C, "");
+_Static_assert(KC_END == 0x004D, "");
+_Static_assert(KC_PAGE_DOWN == 0x004E, "");
+_Static_assert(KC_RIGHT == 0x004F, "");
+_Static_assert(KC_LEFT == 0x0050, "");
+_Static_assert(KC_DOWN == 0x0051, "");
+_Static_assert(KC_UP == 0x0052, "");
+_Static_assert(KC_NUM_LOCK == 0x0053, "");
+_Static_assert(KC_KP_SLASH == 0x0054, "");
+_Static_assert(KC_KP_ASTERISK == 0x0055, "");
+_Static_assert(KC_KP_MINUS == 0x0056, "");
+_Static_assert(KC_KP_PLUS == 0x0057, "");
+_Static_assert(KC_KP_ENTER == 0x0058, "");
+_Static_assert(KC_KP_1 == 0x0059, "");
+_Static_assert(KC_KP_2 == 0x005A, "");
+_Static_assert(KC_KP_3 == 0x005B, "");
+_Static_assert(KC_KP_4 == 0x005C, "");
+_Static_assert(KC_KP_5 == 0x005D, "");
+_Static_assert(KC_KP_6 == 0x005E, "");
+_Static_assert(KC_KP_7 == 0x005F, "");
+_Static_assert(KC_KP_8 == 0x0060, "");
+_Static_assert(KC_KP_9 == 0x0061, "");
+_Static_assert(KC_KP_0 == 0x0062, "");
+_Static_assert(KC_KP_DOT == 0x0063, "");
+_Static_assert(KC_NONUS_BACKSLASH == 0x0064, "");
+_Static_assert(KC_APPLICATION == 0x0065, "");
+_Static_assert(KC_KB_POWER == 0x0066, "");
+_Static_assert(KC_KP_EQUAL == 0x0067, "");
+_Static_assert(KC_F13 == 0x0068, "");
+_Static_assert(KC_F14 == 0x0069, "");
+_Static_assert(KC_F15 == 0x006A, "");
+_Static_assert(KC_F16 == 0x006B, "");
+_Static_assert(KC_F17 == 0x006C, "");
+_Static_assert(KC_F18 == 0x006D, "");
+_Static_assert(KC_F19 == 0x006E, "");
+_Static_assert(KC_F20 == 0x006F, "");
+_Static_assert(KC_F21 == 0x0070, "");
+_Static_assert(KC_F22 == 0x0071, "");
+_Static_assert(KC_F23 == 0x0072, "");
+_Static_assert(KC_F24 == 0x0073, "");
+_Static_assert(KC_EXECUTE == 0x0074, "");
+_Static_assert(KC_HELP == 0x0075, "");
+_Static_assert(KC_MENU == 0x0076, "");
+_Static_assert(KC_SELECT == 0x0077, "");
+_Static_assert(KC_STOP == 0x0078, "");
+_Static_assert(KC_AGAIN == 0x0079, "");
+_Static_assert(KC_UNDO == 0x007A, "");
+_Static_assert(KC_CUT == 0x007B, "");
+_Static_assert(KC_COPY == 0x007C, "");
+_Static_assert(KC_PASTE == 0x007D, "");
+_Static_assert(KC_FIND == 0x007E, "");
-_Static_assert(KC_NONUS_HASH == 0x32, "");
-_Static_assert(KC_NONUS_BSLASH == 0x64, "");
-_Static_assert(KC_RO == 0x87, "");
-_Static_assert(KC_KANA == 0x88, "");
-_Static_assert(KC_JYEN == 0x89, "");
-_Static_assert(KC_HENK == 0x8A, "");
-_Static_assert(KC_MHEN == 0x8B, "");
-_Static_assert(KC_LANG1 == 0x90, "");
-_Static_assert(KC_LANG2 == 0x91, "");
+_Static_assert(KC_LOCKING_CAPS_LOCK == 0x0082, "");
+_Static_assert(KC_LOCKING_NUM_LOCK == 0x0083, "");
+_Static_assert(KC_LOCKING_SCROLL_LOCK == 0x0084, "");
+_Static_assert(KC_KP_COMMA == 0x0085, "");
+_Static_assert(KC_KP_EQUAL_AS400 == 0x0086, "");
+_Static_assert(KC_INTERNATIONAL_1 == 0x0087, "");
+_Static_assert(KC_INTERNATIONAL_2 == 0x0088, "");
+_Static_assert(KC_INTERNATIONAL_3 == 0x0089, "");
+_Static_assert(KC_INTERNATIONAL_4 == 0x008A, "");
+_Static_assert(KC_INTERNATIONAL_5 == 0x008B, "");
+_Static_assert(KC_INTERNATIONAL_6 == 0x008C, "");
+_Static_assert(KC_INTERNATIONAL_7 == 0x008D, "");
+_Static_assert(KC_INTERNATIONAL_8 == 0x008E, "");
+_Static_assert(KC_INTERNATIONAL_9 == 0x008F, "");
+_Static_assert(KC_LANGUAGE_1 == 0x0090, "");
+_Static_assert(KC_LANGUAGE_2 == 0x0091, "");
+_Static_assert(KC_LANGUAGE_3 == 0x0092, "");
+_Static_assert(KC_LANGUAGE_4 == 0x0093, "");
+_Static_assert(KC_LANGUAGE_5 == 0x0094, "");
+_Static_assert(KC_LANGUAGE_6 == 0x0095, "");
+_Static_assert(KC_LANGUAGE_7 == 0x0096, "");
+_Static_assert(KC_LANGUAGE_8 == 0x0097, "");
+_Static_assert(KC_LANGUAGE_9 == 0x0098, "");
+_Static_assert(KC_ALTERNATE_ERASE == 0x0099, "");
+_Static_assert(KC_SYSTEM_REQUEST == 0x009A, "");
+_Static_assert(KC_CANCEL == 0x009B, "");
+_Static_assert(KC_CLEAR == 0x009C, "");
+_Static_assert(KC_PRIOR == 0x009D, "");
-_Static_assert(KC_GESC == 0x5C16, "");
-_Static_assert(KC_LSPO == 0x5CD7, "");
-_Static_assert(KC_RSPC == 0x5CD8, "");
-_Static_assert(KC_LCPO == 0x5CF3, "");
-_Static_assert(KC_RCPC == 0x5CF4, "");
-_Static_assert(KC_LAPO == 0x5CF5, "");
-_Static_assert(KC_RAPC == 0x5CF6, "");
-_Static_assert(KC_SFTENT == 0x5CD9, "");
+_Static_assert(KC_OUT == 0x00A0, "");
+_Static_assert(KC_OPER == 0x00A1, "");
+_Static_assert(KC_CLEAR_AGAIN == 0x00A2, "");
+_Static_assert(KC_CRSEL == 0x00A3, "");
+_Static_assert(KC_EXSEL == 0x00A4, "");
-_Static_assert(BL_TOGG == 23743, "");
-_Static_assert(BL_STEP == 23744, "");
-_Static_assert(BL_BRTG == 23745, "");
-_Static_assert(BL_ON == 23739, "");
-_Static_assert(BL_OFF == 23740, "");
-_Static_assert(BL_INC == 23742, "");
-_Static_assert(BL_DEC == 23741, "");
-_Static_assert(RGB_TOG == 23746, "");
-_Static_assert(RGB_MOD == 23747, "");
-_Static_assert(RGB_RMOD == 23748, "");
-_Static_assert(RGB_HUI == 23749, "");
-_Static_assert(RGB_HUD == 23750, "");
-_Static_assert(RGB_SAI == 23751, "");
-_Static_assert(RGB_SAD == 23752, "");
-_Static_assert(RGB_VAI == 23753, "");
-_Static_assert(RGB_VAD == 23754, "");
-_Static_assert(RGB_SPI == 23755, "");
-_Static_assert(RGB_SPD == 23756, "");
-_Static_assert(RGB_M_P == 23757, "");
-_Static_assert(RGB_M_B == 23758, "");
-_Static_assert(RGB_M_R == 23759, "");
-_Static_assert(RGB_M_SW == 23760, "");
-_Static_assert(RGB_M_SN == 23761, "");
-_Static_assert(RGB_M_K == 23762, "");
-_Static_assert(RGB_M_X == 23763, "");
-_Static_assert(RGB_M_G == 23764, "");
-_Static_assert(RGB_M_T == 23765, "");
+_Static_assert(KC_PWR == 0x00A5, "");
+_Static_assert(KC_SLEP == 0x00A6, "");
+_Static_assert(KC_WAKE == 0x00A7, "");
+_Static_assert(KC_MUTE == 0x00A8, "");
+_Static_assert(KC_VOLU == 0x00A9, "");
+_Static_assert(KC_VOLD == 0x00AA, "");
+_Static_assert(KC_MNXT == 0x00AB, "");
+_Static_assert(KC_MPRV == 0x00AC, "");
+_Static_assert(KC_MSTP == 0x00AD, "");
+_Static_assert(KC_MPLY == 0x00AE, "");
+_Static_assert(KC_MSEL == 0x00AF, "");
+_Static_assert(KC_EJCT == 0x00B0, "");
+_Static_assert(KC_MAIL == 0x00B1, "");
+_Static_assert(KC_CALC == 0x00B2, "");
+_Static_assert(KC_MYCM == 0x00B3, "");
+_Static_assert(KC_WSCH == 0x00B4, "");
+_Static_assert(KC_WHOM == 0x00B5, "");
+_Static_assert(KC_WBAK == 0x00B6, "");
+_Static_assert(KC_WFWD == 0x00B7, "");
+_Static_assert(KC_WSTP == 0x00B8, "");
+_Static_assert(KC_WREF == 0x00B9, "");
+_Static_assert(KC_WFAV == 0x00BA, "");
+_Static_assert(KC_MFFD == 0x00BB, "");
+_Static_assert(KC_MRWD == 0x00BC, "");
+_Static_assert(KC_BRIU == 0x00BD, "");
+_Static_assert(KC_BRID == 0x00BE, "");
-_Static_assert(KC_F13 == 104, "");
-_Static_assert(KC_F14 == 105, "");
-_Static_assert(KC_F15 == 106, "");
-_Static_assert(KC_F16 == 107, "");
-_Static_assert(KC_F17 == 108, "");
-_Static_assert(KC_F18 == 109, "");
-_Static_assert(KC_F19 == 110, "");
-_Static_assert(KC_F20 == 111, "");
-_Static_assert(KC_F21 == 112, "");
-_Static_assert(KC_F22 == 113, "");
-_Static_assert(KC_F23 == 114, "");
-_Static_assert(KC_F24 == 115, "");
-_Static_assert(KC_PWR == 165, "");
-_Static_assert(KC_SLEP == 166, "");
-_Static_assert(KC_WAKE == 167, "");
-_Static_assert(KC_EXEC == 116, "");
-_Static_assert(KC_HELP == 117, "");
-_Static_assert(KC_SLCT == 119, "");
-_Static_assert(KC_STOP == 120, "");
-_Static_assert(KC_AGIN == 121, "");
-_Static_assert(KC_UNDO == 122, "");
-_Static_assert(KC_CUT == 123, "");
-_Static_assert(KC_COPY == 124, "");
-_Static_assert(KC_PSTE == 125, "");
-_Static_assert(KC_FIND == 126, "");
-_Static_assert(KC_CALC == 178, "");
-_Static_assert(KC_MAIL == 177, "");
-_Static_assert(KC_MSEL == 175, "");
-_Static_assert(KC_MYCM == 179, "");
-_Static_assert(KC_WSCH == 180, "");
-_Static_assert(KC_WHOM == 181, "");
-_Static_assert(KC_WBAK == 182, "");
-_Static_assert(KC_WFWD == 183, "");
-_Static_assert(KC_WSTP == 184, "");
-_Static_assert(KC_WREF == 185, "");
-_Static_assert(KC_WFAV == 186, "");
-_Static_assert(KC_BRIU == 189, "");
-_Static_assert(KC_BRID == 190, "");
-_Static_assert(KC_MPRV == 172, "");
-_Static_assert(KC_MNXT == 171, "");
-_Static_assert(KC_MUTE == 168, "");
-_Static_assert(KC_VOLD == 170, "");
-_Static_assert(KC_VOLU == 169, "");
-_Static_assert(KC_MSTP == 173, "");
-_Static_assert(KC_MPLY == 174, "");
-_Static_assert(KC_MRWD == 188, "");
-_Static_assert(KC_MFFD == 187, "");
-_Static_assert(KC_EJCT == 176, "");
-_Static_assert(KC_MS_U == 240, "");
-_Static_assert(KC_MS_D == 241, "");
-_Static_assert(KC_MS_L == 242, "");
-_Static_assert(KC_MS_R == 243, "");
-_Static_assert(KC_BTN1 == 244, "");
-_Static_assert(KC_BTN2 == 245, "");
-_Static_assert(KC_BTN3 == 246, "");
-_Static_assert(KC_BTN4 == 247, "");
-_Static_assert(KC_BTN5 == 248, "");
-_Static_assert(KC_WH_U == 249, "");
-_Static_assert(KC_WH_D == 250, "");
-_Static_assert(KC_WH_L == 251, "");
-_Static_assert(KC_WH_R == 252, "");
-_Static_assert(KC_ACL0 == 253, "");
-_Static_assert(KC_ACL1 == 254, "");
-_Static_assert(KC_ACL2 == 255, "");
-_Static_assert(KC_LCAP == 130, "");
-_Static_assert(KC_LNUM == 131, "");
-_Static_assert(KC_LSCR == 132, "");
+_Static_assert(KC_LEFT_CTRL == 0x00E0, "");
+_Static_assert(KC_LEFT_SHIFT == 0x00E1, "");
+_Static_assert(KC_LEFT_ALT == 0x00E2, "");
+_Static_assert(KC_LEFT_GUI == 0x00E3, "");
+_Static_assert(KC_RIGHT_CTRL == 0x00E4, "");
+_Static_assert(KC_RIGHT_SHIFT == 0x00E5, "");
+_Static_assert(KC_RIGHT_ALT == 0x00E6, "");
+_Static_assert(KC_RIGHT_GUI == 0x00E7, "");
-_Static_assert(FN_MO13 == 0x5F10, "");
-_Static_assert(FN_MO23 == 0x5F11, "");
+_Static_assert(KC_MS_U == 0x00F0, "");
+_Static_assert(KC_MS_D == 0x00F1, "");
+_Static_assert(KC_MS_L == 0x00F2, "");
+_Static_assert(KC_MS_R == 0x00F3, "");
+_Static_assert(KC_BTN1 == 0x00F4, "");
+_Static_assert(KC_BTN2 == 0x00F5, "");
+_Static_assert(KC_BTN3 == 0x00F6, "");
+_Static_assert(KC_BTN4 == 0x00F7, "");
+_Static_assert(KC_BTN5 == 0x00F8, "");
+_Static_assert(KC_WH_U == 0x00F9, "");
+_Static_assert(KC_WH_D == 0x00FA, "");
+_Static_assert(KC_WH_L == 0x00FB, "");
+_Static_assert(KC_WH_R == 0x00FC, "");
+_Static_assert(KC_ACL0 == 0x00FD, "");
+_Static_assert(KC_ACL1 == 0x00FE, "");
+_Static_assert(KC_ACL2 == 0x00FF, "");
-_Static_assert(MACRO00 == 0x5F12, "");
-_Static_assert(MACRO01 == 0x5F13, "");
-_Static_assert(MACRO02 == 0x5F14, "");
-_Static_assert(MACRO03 == 0x5F15, "");
-_Static_assert(MACRO04 == 0x5F16, "");
-_Static_assert(MACRO05 == 0x5F17, "");
-_Static_assert(MACRO06 == 0x5F18, "");
-_Static_assert(MACRO07 == 0x5F19, "");
-_Static_assert(MACRO08 == 0x5F1A, "");
-_Static_assert(MACRO09 == 0x5F1B, "");
-_Static_assert(MACRO10 == 0x5F1C, "");
-_Static_assert(MACRO11 == 0x5F1D, "");
-_Static_assert(MACRO12 == 0x5F1E, "");
-_Static_assert(MACRO13 == 0x5F1F, "");
-_Static_assert(MACRO14 == 0x5F20, "");
-_Static_assert(MACRO15 == 0x5F21, "");
+_Static_assert(KC_EXLM == 0x021E, "");
+_Static_assert(KC_AT == 0x021F, "");
+_Static_assert(KC_HASH == 0x0220, "");
+_Static_assert(KC_DLR == 0x0221, "");
+_Static_assert(KC_PERC == 0x0222, "");
+_Static_assert(KC_CIRC == 0x0223, "");
+_Static_assert(KC_AMPR == 0x0224, "");
+_Static_assert(KC_ASTR == 0x0225, "");
+_Static_assert(KC_LPRN == 0x0226, "");
+_Static_assert(KC_RPRN == 0x0227, "");
+_Static_assert(KC_UNDS == 0x022D, "");
+_Static_assert(KC_PLUS == 0x022E, "");
+_Static_assert(KC_LCBR == 0x022F, "");
+_Static_assert(KC_RCBR == 0x0230, "");
+_Static_assert(KC_PIPE == 0x0231, "");
+_Static_assert(KC_COLN == 0x0233, "");
+_Static_assert(KC_DQUO == 0x0234, "");
+_Static_assert(KC_TILD == 0x0235, "");
+_Static_assert(KC_LT == 0x0236, "");
+_Static_assert(KC_GT == 0x0237, "");
+_Static_assert(KC_QUES == 0x0238, "");
-_Static_assert(USER00 == 0x5F80, "");
-_Static_assert(USER01 == 0x5F81, "");
-_Static_assert(USER02 == 0x5F82, "");
-_Static_assert(USER03 == 0x5F83, "");
-_Static_assert(USER04 == 0x5F84, "");
-_Static_assert(USER05 == 0x5F85, "");
-_Static_assert(USER06 == 0x5F86, "");
-_Static_assert(USER07 == 0x5F87, "");
-_Static_assert(USER08 == 0x5F88, "");
-_Static_assert(USER09 == 0x5F89, "");
-_Static_assert(USER10 == 0x5F8A, "");
-_Static_assert(USER11 == 0x5F8B, "");
-_Static_assert(USER12 == 0x5F8C, "");
-_Static_assert(USER13 == 0x5F8D, "");
-_Static_assert(USER14 == 0x5F8E, "");
-_Static_assert(USER15 == 0x5F8F, "");
+_Static_assert(RESET == 0x5C00, "");
+_Static_assert(DEBUG == 0x5C01, "");
-_Static_assert(KC_POWER == 102, "");
-_Static_assert(KC_MENU == 118, "");
-_Static_assert(KC_KP_EQUAL_AS400 == 134, "");
-_Static_assert(KC_INT6 == 140, "");
-_Static_assert(KC_INT7 == 141, "");
-_Static_assert(KC_INT8 == 142, "");
-_Static_assert(KC_INT9 == 143, "");
-_Static_assert(KC_LANG3 == 146, "");
-_Static_assert(KC_LANG4 == 147, "");
-_Static_assert(KC_LANG5 == 148, "");
-_Static_assert(KC_LANG6 == 149, "");
-_Static_assert(KC_LANG7 == 150, "");
-_Static_assert(KC_LANG8 == 151, "");
-_Static_assert(KC_LANG9 == 152, "");
-_Static_assert(KC_ERAS == 153, "");
-_Static_assert(KC_SYSREQ == 154, "");
-_Static_assert(KC_CANCEL == 155, "");
-_Static_assert(KC_CLEAR == 156, "");
-_Static_assert(KC_CLR == 156, "");
-_Static_assert(KC_PRIOR == 157, "");
-_Static_assert(KC_OUT == 160, "");
-_Static_assert(KC_OPER == 161, "");
-_Static_assert(KC_CLEAR_AGAIN == 162, "");
-_Static_assert(KC_CRSEL == 163, "");
-_Static_assert(KC_EXSEL == 164, "");
-_Static_assert(KC_FN0 == 192, "");
-_Static_assert(KC_FN1 == 193, "");
-_Static_assert(KC_FN2 == 194, "");
-_Static_assert(KC_FN3 == 195, "");
-_Static_assert(KC_FN4 == 196, "");
-_Static_assert(KC_FN5 == 197, "");
-_Static_assert(KC_FN6 == 198, "");
-_Static_assert(KC_FN7 == 199, "");
-_Static_assert(KC_FN8 == 200, "");
-_Static_assert(KC_FN9 == 201, "");
-_Static_assert(KC_FN10 == 202, "");
-_Static_assert(KC_FN11 == 203, "");
-_Static_assert(KC_FN12 == 204, "");
-_Static_assert(KC_FN13 == 205, "");
-_Static_assert(KC_FN14 == 206, "");
-_Static_assert(KC_FN15 == 207, "");
-_Static_assert(KC_FN16 == 208, "");
-_Static_assert(KC_FN17 == 209, "");
-_Static_assert(KC_FN18 == 210, "");
-_Static_assert(KC_FN19 == 211, "");
-_Static_assert(KC_FN20 == 212, "");
-_Static_assert(KC_FN21 == 213, "");
-_Static_assert(KC_FN22 == 214, "");
-_Static_assert(KC_FN23 == 215, "");
-_Static_assert(KC_FN24 == 216, "");
-_Static_assert(KC_FN25 == 217, "");
-_Static_assert(KC_FN26 == 218, "");
-_Static_assert(KC_FN27 == 219, "");
-_Static_assert(KC_FN28 == 220, "");
-_Static_assert(KC_FN29 == 221, "");
-_Static_assert(KC_FN30 == 222, "");
-_Static_assert(KC_FN31 == 223, "");
-_Static_assert(RESET == 23552, "");
-_Static_assert(DEBUG == 23553, "");
-_Static_assert(MAGIC_TOGGLE_NKRO == 23572, "");
-_Static_assert(AU_ON == 23581, "");
-_Static_assert(AU_OFF == 23582, "");
-_Static_assert(AU_TOG == 23583, "");
-_Static_assert(CLICKY_TOGGLE == 23584, "");
-_Static_assert(CLICKY_ENABLE == 23585, "");
-_Static_assert(CLICKY_DISABLE == 23586, "");
-_Static_assert(CLICKY_UP == 23587, "");
-_Static_assert(CLICKY_DOWN == 23588, "");
-_Static_assert(CLICKY_RESET == 23589, "");
-_Static_assert(MU_ON == 23590, "");
-_Static_assert(MU_OFF == 23591, "");
-_Static_assert(MU_TOG == 23592, "");
-_Static_assert(MU_MOD == 23593, "");
+_Static_assert(MAGIC_TOGGLE_NKRO == 0x5C14, "");
+
+_Static_assert(KC_GESC == 0x5C16, "");
+
+_Static_assert(AU_ON == 0x5C1D, "");
+_Static_assert(AU_OFF == 0x5C1E, "");
+_Static_assert(AU_TOG == 0x5C1F, "");
+
+_Static_assert(CLICKY_TOGGLE == 0x5C20, "");
+_Static_assert(CLICKY_ENABLE == 0x5C21, "");
+_Static_assert(CLICKY_DISABLE == 0x5C22, "");
+_Static_assert(CLICKY_UP == 0x5C23, "");
+_Static_assert(CLICKY_DOWN == 0x5C24, "");
+_Static_assert(CLICKY_RESET == 0x5C25, "");
+_Static_assert(MU_ON == 0x5C26, "");
+_Static_assert(MU_OFF == 0x5C27, "");
+_Static_assert(MU_TOG == 0x5C28, "");
+_Static_assert(MU_MOD == 0x5C29, "");
+
+_Static_assert(BL_ON == 0x5CBB, "");
+_Static_assert(BL_OFF == 0x5CBC, "");
+_Static_assert(BL_DEC == 0x5CBD, "");
+_Static_assert(BL_INC == 0x5CBE, "");
+_Static_assert(BL_TOGG == 0x5CBF, "");
+_Static_assert(BL_STEP == 0x5CC0, "");
+_Static_assert(BL_BRTG == 0x5CC1, "");
+_Static_assert(RGB_TOG == 0x5CC2, "");
+_Static_assert(RGB_MOD == 0x5CC3, "");
+_Static_assert(RGB_RMOD == 0x5CC4, "");
+_Static_assert(RGB_HUI == 0x5CC5, "");
+_Static_assert(RGB_HUD == 0x5CC6, "");
+_Static_assert(RGB_SAI == 0x5CC7, "");
+_Static_assert(RGB_SAD == 0x5CC8, "");
+_Static_assert(RGB_VAI == 0x5CC9, "");
+_Static_assert(RGB_VAD == 0x5CCA, "");
+_Static_assert(RGB_SPI == 0x5CCB, "");
+_Static_assert(RGB_SPD == 0x5CCC, "");
+_Static_assert(RGB_M_P == 0x5CCD, "");
+_Static_assert(RGB_M_B == 0x5CCE, "");
+_Static_assert(RGB_M_R == 0x5CCF, "");
+_Static_assert(RGB_M_SW == 0x5CD0, "");
+_Static_assert(RGB_M_SN == 0x5CD1, "");
+_Static_assert(RGB_M_K == 0x5CD2, "");
+_Static_assert(RGB_M_X == 0x5CD3, "");
+_Static_assert(RGB_M_G == 0x5CD4, "");
+_Static_assert(RGB_M_T == 0x5CD5, "");
+
+_Static_assert(KC_LSPO == 0x5CD7, "");
+_Static_assert(KC_RSPC == 0x5CD8, "");
+_Static_assert(KC_SFTENT == 0x5CD9, "");
+
+_Static_assert(KC_LCPO == 0x5CF3, "");
+_Static_assert(KC_RCPC == 0x5CF4, "");
+_Static_assert(KC_LAPO == 0x5CF5, "");
+_Static_assert(KC_RAPC == 0x5CF6, "");
+
+_Static_assert(FN_MO13 == 0x5F10, "");
+_Static_assert(FN_MO23 == 0x5F11, "");
+_Static_assert(MACRO00 == 0x5F12, "");
+_Static_assert(MACRO01 == 0x5F13, "");
+_Static_assert(MACRO02 == 0x5F14, "");
+_Static_assert(MACRO03 == 0x5F15, "");
+_Static_assert(MACRO04 == 0x5F16, "");
+_Static_assert(MACRO05 == 0x5F17, "");
+_Static_assert(MACRO06 == 0x5F18, "");
+_Static_assert(MACRO07 == 0x5F19, "");
+_Static_assert(MACRO08 == 0x5F1A, "");
+_Static_assert(MACRO09 == 0x5F1B, "");
+_Static_assert(MACRO10 == 0x5F1C, "");
+_Static_assert(MACRO11 == 0x5F1D, "");
+_Static_assert(MACRO12 == 0x5F1E, "");
+_Static_assert(MACRO13 == 0x5F1F, "");
+_Static_assert(MACRO14 == 0x5F20, "");
+_Static_assert(MACRO15 == 0x5F21, "");
+
+_Static_assert(USER00 == 0x5F80, "");
+_Static_assert(USER01 == 0x5F81, "");
+_Static_assert(USER02 == 0x5F82, "");
+_Static_assert(USER03 == 0x5F83, "");
+_Static_assert(USER04 == 0x5F84, "");
+_Static_assert(USER05 == 0x5F85, "");
+_Static_assert(USER06 == 0x5F86, "");
+_Static_assert(USER07 == 0x5F87, "");
+_Static_assert(USER08 == 0x5F88, "");
+_Static_assert(USER09 == 0x5F89, "");
+_Static_assert(USER10 == 0x5F8A, "");
+_Static_assert(USER11 == 0x5F8B, "");
+_Static_assert(USER12 == 0x5F8C, "");
+_Static_assert(USER13 == 0x5F8D, "");
+_Static_assert(USER14 == 0x5F8E, "");
+_Static_assert(USER15 == 0x5F8F, "");
#endif
diff --git a/quantum/virtser.h b/quantum/virtser.h
new file mode 100644
index 0000000000..df7e87984c
--- /dev/null
+++ b/quantum/virtser.h
@@ -0,0 +1,9 @@
+#pragma once
+
+void virtser_init(void);
+
+/* Define this function in your code to process incoming bytes */
+void virtser_recv(const uint8_t ch);
+
+/* Call this to send a character over the Virtual Serial Device */
+void virtser_send(const uint8_t byte);
diff --git a/quantum/visualizer/LICENSE.md b/quantum/visualizer/LICENSE.md
deleted file mode 100644
index 22d4c3f08b..0000000000
--- a/quantum/visualizer/LICENSE.md
+++ /dev/null
@@ -1,29 +0,0 @@
-The files in this project are licensed under the MIT license
-It uses the following libraries
-uGFX - with it's own license, see the license.html file in the uGFX subfolder for more information
-tmk_core - is indirectly used and not included in the repository. It's licensed under the GPLv2 license
-Chibios - which is used by tmk_core is licensed under GPLv3.
-
-Therefore the effective license for any project using the library is GPLv3
-
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/quantum/visualizer/common_gfxconf.h b/quantum/visualizer/common_gfxconf.h
deleted file mode 100644
index e0735b37d0..0000000000
--- a/quantum/visualizer/common_gfxconf.h
+++ /dev/null
@@ -1,354 +0,0 @@
-/**
- * This file has a different license to the rest of the uGFX system.
- * You can copy, modify and distribute this file as you see fit.
- * You do not need to publish your source modifications to this file.
- * The only thing you are not permitted to do is to relicense it
- * under a different license.
- */
-
-/**
- * Copy this file into your project directory and rename it as gfxconf.h
- * Edit your copy to turn on the uGFX features you want to use.
- * The values below are the defaults.
- *
- * Only remove the comments from lines where you want to change the
- * default value. This allows definitions to be included from
- * driver makefiles when required and provides the best future
- * compatibility for your project.
- *
- * Please use spaces instead of tabs in this file.
- */
-
-#pragma once
-
-///////////////////////////////////////////////////////////////////////////
-// GFX - Compatibility options //
-///////////////////////////////////////////////////////////////////////////
-//#define GFX_COMPAT_V2 GFXON
-//#define GFX_COMPAT_OLDCOLORS GFXON
-
-///////////////////////////////////////////////////////////////////////////
-// GOS - One of these must be defined, preferably in your Makefile //
-///////////////////////////////////////////////////////////////////////////
-//#define GFX_USE_OS_CHIBIOS GFXOFF
-//#define GFX_USE_OS_FREERTOS GFXOFF
-// #define GFX_FREERTOS_USE_TRACE GFXOFF
-//#define GFX_USE_OS_WIN32 GFXOFF
-//#define GFX_USE_OS_LINUX GFXOFF
-//#define GFX_USE_OS_OSX GFXOFF
-//#define GFX_USE_OS_ECOS GFXOFF
-//#define GFX_USE_OS_RAWRTOS GFXOFF
-//#define GFX_USE_OS_ARDUINO GFXOFF
-//#define GFX_USE_OS_KEIL GFXOFF
-//#define GFX_USE_OS_RTX5 GFXOFF
-//#define GFX_USE_OS_CMSIS GFXOFF
-//#define GFX_USE_OS_CMSIS2 GFXOFF
-//#define GFX_USE_OS_RAW32 GFXOFF
-//#define GFX_USE_OS_ZEPHYR GFXOFF
-//#define GFX_USE_OS_NIOS GFXOFF
-//#define GFX_USE_OS_QT GFXOFF
-// #define INTERRUPTS_OFF() optional_code
-// #define INTERRUPTS_ON() optional_code
-
-// Options that (should where relevant) apply to all operating systems
-#define GFX_NO_INLINE GFXON
-// #define GFX_COMPILER GFX_COMPILER_UNKNOWN
-// #define GFX_SHOW_COMPILER GFXOFF
-// #define GFX_CPU GFX_CPU_UNKNOWN
-// #define GFX_CPU_NO_ALIGNMENT_FAULTS GFXOFF
-// #define GFX_CPU_ENDIAN GFX_CPU_ENDIAN_UNKNOWN
-// #define GFX_OS_HEAP_SIZE 0
-// #define GFX_OS_NO_INIT GFXOFF
-// #define GFX_OS_INIT_NO_WARNING GFXOFF
-// #define GFX_OS_PRE_INIT_FUNCTION myHardwareInitRoutine
-// #define GFX_OS_EXTRA_INIT_FUNCTION myOSInitRoutine
-// #define GFX_OS_EXTRA_DEINIT_FUNCTION myOSDeInitRoutine
-// #define GFX_OS_CALL_UGFXMAIN GFXOFF
-// #define GFX_OS_UGFXMAIN_STACKSIZE 0
-// #define GFX_EMULATE_MALLOC GFXOFF
-// #define GFX_MEM_LT64K GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GDISP //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GDISP GFXON
-
-//#define GDISP_NEED_AUTOFLUSH GFXOFF
-//#define GDISP_NEED_TIMERFLUSH GFXOFF
-//#define GDISP_NEED_VALIDATION GFXON
-//#define GDISP_NEED_CLIP GFXON
-#define GDISP_NEED_CIRCLE GFXON
-//#define GDISP_NEED_DUALCIRCLE GFXOFF
-#define GDISP_NEED_ELLIPSE GFXON
-#define GDISP_NEED_ARC GFXON
-#define GDISP_NEED_ARCSECTORS GFXON
-#define GDISP_NEED_CONVEX_POLYGON GFXON
-//#define GDISP_NEED_SCROLL GFXOFF
-#define GDISP_NEED_PIXELREAD GFXON
-#define GDISP_NEED_CONTROL GFXON
-//#define GDISP_NEED_QUERY GFXOFF
-//#define GDISP_NEED_MULTITHREAD GFXOFF
-//#define GDISP_NEED_STREAMING GFXOFF
-#define GDISP_NEED_TEXT GFXON
-// #define GDISP_NEED_TEXT_WORDWRAP GFXOFF
-// #define GDISP_NEED_TEXT_BOXPADLR 1
-// #define GDISP_NEED_TEXT_BOXPADTB 1
-// #define GDISP_NEED_ANTIALIAS GFXOFF
-// #define GDISP_NEED_UTF8 GFXOFF
-#define GDISP_NEED_TEXT_KERNING GFXON
-// #define GDISP_INCLUDE_FONT_UI1 GFXOFF
-// #define GDISP_INCLUDE_FONT_UI2 GFXOFF // The smallest preferred font.
-// #define GDISP_INCLUDE_FONT_LARGENUMBERS GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS10 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS12 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS16 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS20 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS24 GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS32 GFXOFF
-#define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 GFXON
-// #define GDISP_INCLUDE_FONT_FIXED_10X20 GFXOFF
-// #define GDISP_INCLUDE_FONT_FIXED_7X14 GFXOFF
-#define GDISP_INCLUDE_FONT_FIXED_5X8 GFXON
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA GFXOFF
-// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA GFXOFF
-// #define GDISP_INCLUDE_USER_FONTS GFXOFF
-
-//#define GDISP_NEED_IMAGE GFXOFF
-// #define GDISP_NEED_IMAGE_NATIVE GFXOFF
-// #define GDISP_NEED_IMAGE_GIF GFXOFF
-// #define GDISP_IMAGE_GIF_BLIT_BUFFER_SIZE 32
-// #define GDISP_NEED_IMAGE_BMP GFXOFF
-// #define GDISP_NEED_IMAGE_BMP_1 GFXON
-// #define GDISP_NEED_IMAGE_BMP_4 GFXON
-// #define GDISP_NEED_IMAGE_BMP_4_RLE GFXON
-// #define GDISP_NEED_IMAGE_BMP_8 GFXON
-// #define GDISP_NEED_IMAGE_BMP_8_RLE GFXON
-// #define GDISP_NEED_IMAGE_BMP_16 GFXON
-// #define GDISP_NEED_IMAGE_BMP_24 GFXON
-// #define GDISP_NEED_IMAGE_BMP_32 GFXON
-// #define GDISP_IMAGE_BMP_BLIT_BUFFER_SIZE 32
-// #define GDISP_NEED_IMAGE_JPG GFXOFF
-// #define GDISP_NEED_IMAGE_PNG GFXOFF
-// #define GDISP_NEED_IMAGE_PNG_INTERLACED GFXOFF
-// #define GDISP_NEED_IMAGE_PNG_TRANSPARENCY GFXON
-// #define GDISP_NEED_IMAGE_PNG_BACKGROUND GFXON
-// #define GDISP_NEED_IMAGE_PNG_ALPHACLIFF 32
-// #define GDISP_NEED_IMAGE_PNG_PALETTE_124 GFXON
-// #define GDISP_NEED_IMAGE_PNG_PALETTE_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_124 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYSCALE_16 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_GRAYALPHA_16 GFXON
-// #define GDISP_NEED_IMAGE_PNG_RGB_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_RGB_16 GFXON
-// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_8 GFXON
-// #define GDISP_NEED_IMAGE_PNG_RGBALPHA_16 GFXON
-// #define GDISP_IMAGE_PNG_BLIT_BUFFER_SIZE 32
-// #define GDISP_IMAGE_PNG_FILE_BUFFER_SIZE 8
-// #define GDISP_IMAGE_PNG_Z_BUFFER_SIZE 32768
-// #define GDISP_NEED_IMAGE_ACCOUNTING GFXOFF
-
-//#define GDISP_NEED_PIXMAP GFXOFF
-// #define GDISP_NEED_PIXMAP_IMAGE GFXOFF
-
-//#define GDISP_DEFAULT_ORIENTATION gOrientationLandscape // If not defined the native hardware orientation is used.
-//#define GDISP_LINEBUF_SIZE 128
-//#define GDISP_STARTUP_COLOR GFX_BLACK
-#define GDISP_NEED_STARTUP_LOGO GFXOFF
-
-//#define GDISP_TOTAL_DISPLAYS 1
-
-//#define GDISP_DRIVER_LIST GDISPVMT_Win32, GDISPVMT_Win32
-#ifdef GDISP_DRIVER_LIST
-// // For code and speed optimization define as GFXON or GFXOFF if all controllers have the same capability
-# define GDISP_HARDWARE_STREAM_WRITE GFXOFF
-# define GDISP_HARDWARE_STREAM_READ GFXOFF
-# define GDISP_HARDWARE_STREAM_POS GFXOFF
-# define GDISP_HARDWARE_DRAWPIXEL GFXON
-# define GDISP_HARDWARE_CLEARS GFXOFF
-# define GDISP_HARDWARE_FILLS GFXOFF
-//#define GDISP_HARDWARE_BITFILLS GFXOFF
-# define GDISP_HARDWARE_SCROLL GFXOFF
-# define GDISP_HARDWARE_PIXELREAD GFXON
-# define GDISP_HARDWARE_CONTROL GFXON
-# define GDISP_HARDWARE_QUERY GFXOFF
-# define GDISP_HARDWARE_CLIP GFXOFF
-
-# define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888
-#endif
-
-#define GDISP_USE_GFXNET GFXOFF
-// #define GDISP_GFXNET_PORT 13001
-// #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP GFXOFF
-// #define GDISP_DONT_WAIT_FOR_NET_DISPLAY GFXOFF
-// #define GDISP_GFXNET_UNSAFE_SOCKETS GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GWIN //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GWIN GFXOFF
-
-//#define GWIN_NEED_WINDOWMANAGER GFXOFF
-// #define GWIN_REDRAW_IMMEDIATE GFXOFF
-// #define GWIN_REDRAW_SINGLEOP GFXOFF
-// #define GWIN_NEED_FLASHING GFXOFF
-// #define GWIN_FLASHING_PERIOD 250
-
-//#define GWIN_NEED_CONSOLE GFXOFF
-// #define GWIN_CONSOLE_USE_HISTORY GFXOFF
-// #define GWIN_CONSOLE_HISTORY_AVERAGING GFXOFF
-// #define GWIN_CONSOLE_HISTORY_ATCREATE GFXOFF
-// #define GWIN_CONSOLE_ESCSEQ GFXOFF
-// #define GWIN_CONSOLE_USE_BASESTREAM GFXOFF
-// #define GWIN_CONSOLE_USE_FLOAT GFXOFF
-//#define GWIN_NEED_GRAPH GFXOFF
-//#define GWIN_NEED_GL3D GFXOFF
-
-//#define GWIN_NEED_WIDGET GFXOFF
-//#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1
-// #define GWIN_NEED_LABEL GFXOFF
-// #define GWIN_LABEL_ATTRIBUTE GFXOFF
-// #define GWIN_NEED_BUTTON GFXOFF
-// #define GWIN_BUTTON_LAZY_RELEASE GFXOFF
-// #define GWIN_NEED_SLIDER GFXOFF
-// #define GWIN_SLIDER_NOSNAP GFXOFF
-// #define GWIN_SLIDER_DEAD_BAND 5
-// #define GWIN_SLIDER_TOGGLE_INC 20
-// #define GWIN_NEED_CHECKBOX GFXOFF
-// #define GWIN_NEED_IMAGE GFXOFF
-// #define GWIN_NEED_IMAGE_ANIMATION GFXOFF
-// #define GWIN_NEED_RADIO GFXOFF
-// #define GWIN_NEED_LIST GFXOFF
-// #define GWIN_NEED_LIST_IMAGES GFXOFF
-// #define GWIN_NEED_PROGRESSBAR GFXOFF
-// #define GWIN_PROGRESSBAR_AUTO GFXOFF
-// #define GWIN_NEED_KEYBOARD GFXOFF
-// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1
-// #define GWIN_NEED_KEYBOARD_ENGLISH1 GFXON
-// #define GWIN_NEED_TEXTEDIT GFXOFF
-// #define GWIN_FLAT_STYLING GFXOFF
-// #define GWIN_WIDGET_TAGS GFXOFF
-
-//#define GWIN_NEED_CONTAINERS GFXOFF
-// #define GWIN_NEED_CONTAINER GFXOFF
-// #define GWIN_NEED_FRAME GFXOFF
-// #define GWIN_NEED_TABSET GFXOFF
-// #define GWIN_TABSET_TABHEIGHT 18
-
-///////////////////////////////////////////////////////////////////////////
-// GTRANS //
-///////////////////////////////////////////////////////////////////////////
-//#define GFX_USE_GTRANS GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GEVENT //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GEVENT GFXON
-
-//#define GEVENT_ASSERT_NO_RESOURCE GFXOFF
-//#define GEVENT_MAXIMUM_SIZE 32
-//#define GEVENT_MAX_SOURCE_LISTENERS 32
-
-///////////////////////////////////////////////////////////////////////////
-// GTIMER //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GTIMER GFXOFF
-
-//#define GTIMER_THREAD_PRIORITY gThreadpriorityHigh
-//#define GTIMER_THREAD_WORKAREA_SIZE 2048
-
-///////////////////////////////////////////////////////////////////////////
-// GQUEUE //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GQUEUE GFXOFF
-
-//#define GQUEUE_NEED_ASYNC GFXOFF
-//#define GQUEUE_NEED_GSYNC GFXOFF
-//#define GQUEUE_NEED_FSYNC GFXOFF
-//#define GQUEUE_NEED_BUFFERS GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GINPUT //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GINPUT GFXOFF
-
-//#define GINPUT_NEED_MOUSE GFXOFF
-// #define GINPUT_TOUCH_STARTRAW GFXOFF
-// #define GINPUT_TOUCH_NOTOUCH GFXOFF
-// #define GINPUT_TOUCH_NOCALIBRATE GFXOFF
-// #define GINPUT_TOUCH_NOCALIBRATE_GUI GFXOFF
-// #define GINPUT_MOUSE_POLL_PERIOD 25
-// #define GINPUT_MOUSE_CLICK_TIME 300
-// #define GINPUT_TOUCH_CXTCLICK_TIME 700
-// #define GINPUT_TOUCH_USER_CALIBRATION_LOAD GFXOFF
-// #define GINPUT_TOUCH_USER_CALIBRATION_SAVE GFXOFF
-// #define GMOUSE_DRIVER_LIST GMOUSEVMT_Win32, GMOUSEVMT_Win32
-// #define GINPUT_TOUCH_CALIBRATION_FONT1 "* Double"
-// #define GINPUT_TOUCH_CALIBRATION_FONT2 "* Narrow"
-// #define GINPUT_TOUCH_CALIBRATION_TITLE "Calibration"
-// #define GINPUT_TOUCH_CALIBRATION_ERROR "Calibration Failed!"
-//#define GINPUT_NEED_KEYBOARD GFXOFF
-// #define GINPUT_KEYBOARD_POLL_PERIOD 200
-// #define GKEYBOARD_DRIVER_LIST GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32
-// #define GKEYBOARD_LAYOUT_OFF GFXOFF
-// #define GKEYBOARD_LAYOUT_SCANCODE2_US GFXOFF
-//#define GINPUT_NEED_TOGGLE GFXOFF
-//#define GINPUT_NEED_DIAL GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GFILE //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GFILE GFXOFF
-
-//#define GFILE_NEED_PRINTG GFXOFF
-//#define GFILE_NEED_SCANG GFXOFF
-//#define GFILE_NEED_STRINGS GFXOFF
-//#define GFILE_NEED_FILELISTS GFXOFF
-//#define GFILE_NEED_STDIO GFXOFF
-//#define GFILE_NEED_NOAUTOMOUNT GFXOFF
-//#define GFILE_NEED_NOAUTOSYNC GFXOFF
-
-//#define GFILE_NEED_MEMFS GFXOFF
-//#define GFILE_NEED_ROMFS GFXOFF
-//#define GFILE_NEED_RAMFS GFXOFF
-//#define GFILE_NEED_FATFS GFXOFF
-//#define GFILE_NEED_NATIVEFS GFXOFF
-//#define GFILE_NEED_CHBIOSFS GFXOFF
-//#define GFILE_NEED_USERFS GFXOFF
-
-//#define GFILE_ALLOW_FLOATS GFXOFF
-//#define GFILE_ALLOW_DEVICESPECIFIC GFXOFF
-//#define GFILE_MAX_GFILES 3
-
-///////////////////////////////////////////////////////////////////////////
-// GADC //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GADC GFXOFF
-// #define GADC_MAX_LOWSPEED_DEVICES 4
-
-///////////////////////////////////////////////////////////////////////////
-// GAUDIO //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GAUDIO GFXOFF
-// #define GAUDIO_NEED_PLAY GFXOFF
-// #define GAUDIO_NEED_RECORD GFXOFF
-
-///////////////////////////////////////////////////////////////////////////
-// GMISC //
-///////////////////////////////////////////////////////////////////////////
-#define GFX_USE_GMISC GFXON
-
-//#define GMISC_NEED_ARRAYOPS GFXOFF
-//#define GMISC_NEED_FASTTRIG GFXOFF
-//#define GMISC_NEED_FIXEDTRIG GFXOFF
-//#define GMISC_NEED_INVSQRT GFXOFF
-// #define GMISC_INVSQRT_MIXED_ENDIAN GFXOFF
-// #define GMISC_INVSQRT_REAL_SLOW GFXOFF
-#define GMISC_NEED_MATRIXFLOAT2D GFXON
-#define GMISC_NEED_MATRIXFIXED2D GFXOFF
-//#define GMISC_NEED_HITTEST_POLY GFXOFF
diff --git a/quantum/visualizer/default_animations.c b/quantum/visualizer/default_animations.c
deleted file mode 100644
index 2f43c67cc8..0000000000
--- a/quantum/visualizer/default_animations.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#if defined(VISUALIZER_ENABLE)
-
-# include "default_animations.h"
-# include "visualizer.h"
-# ifdef LCD_ENABLE
-# include "lcd_keyframes.h"
-# endif
-# ifdef LCD_BACKLIGHT_ENABLE
-# include "lcd_backlight_keyframes.h"
-# endif
-
-# ifdef BACKLIGHT_ENABLE
-# include "led_backlight_keyframes.h"
-# endif
-
-# include "visualizer_keyframes.h"
-
-# if defined(LCD_ENABLE) || defined(LCD_BACKLIGHT_ENABLE) || defined(BACKLIGHT_ENABLE)
-
-static bool keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) {
-# ifdef LCD_ENABLE
- lcd_keyframe_enable(animation, state);
-# endif
-# ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_keyframe_enable(animation, state);
-# endif
-# ifdef BACKLIGHT_ENABLE
- led_backlight_keyframe_enable(animation, state);
-# endif
- return false;
-}
-
-static bool keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) {
-# ifdef LCD_ENABLE
- lcd_keyframe_disable(animation, state);
-# endif
-# ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_keyframe_disable(animation, state);
-# endif
-# ifdef BACKLIGHT_ENABLE
- led_backlight_keyframe_disable(animation, state);
-# endif
- return false;
-}
-
-static bool keyframe_fade_in(keyframe_animation_t* animation, visualizer_state_t* state) {
- bool ret = false;
-# ifdef LCD_BACKLIGHT_ENABLE
- ret |= lcd_backlight_keyframe_animate_color(animation, state);
-# endif
-# ifdef BACKLIGHT_ENABLE
- ret |= led_backlight_keyframe_fade_in_all(animation, state);
-# endif
- return ret;
-}
-
-static bool keyframe_fade_out(keyframe_animation_t* animation, visualizer_state_t* state) {
- bool ret = false;
-# ifdef LCD_BACKLIGHT_ENABLE
- ret |= lcd_backlight_keyframe_animate_color(animation, state);
-# endif
-# ifdef BACKLIGHT_ENABLE
- ret |= led_backlight_keyframe_fade_out_all(animation, state);
-# endif
- return ret;
-}
-
-// Don't worry, if the startup animation is long, you can use the keyboard like normal
-// during that time
-keyframe_animation_t default_startup_animation = {
-# if LCD_ENABLE
- .num_frames = 3,
-# else
- .num_frames = 2,
-# endif
- .loop = false,
- .frame_lengths = {0,
-# if LCD_ENABLE
- 0,
-# endif
- gfxMillisecondsToTicks(5000)},
- .frame_functions =
- {
- keyframe_enable,
-# if LCD_ENABLE
- lcd_keyframe_draw_logo,
-# endif
- keyframe_fade_in,
- },
-};
-
-keyframe_animation_t default_suspend_animation = {
-# if LCD_ENABLE
- .num_frames = 3,
-# else
- .num_frames = 2,
-# endif
- .loop = false,
- .frame_lengths =
- {
-# if LCD_ENABLE
- 0,
-# endif
- gfxMillisecondsToTicks(1000), 0},
- .frame_functions =
- {
-# if LCD_ENABLE
- lcd_keyframe_display_layer_text,
-# endif
- keyframe_fade_out,
- keyframe_disable,
- },
-};
-# endif
-
-# if defined(BACKLIGHT_ENABLE)
-# define CROSSFADE_TIME 1000
-# define GRADIENT_TIME 3000
-
-keyframe_animation_t led_test_animation = {
- .num_frames = 14,
- .loop = true,
- .frame_lengths =
- {
- gfxMillisecondsToTicks(1000), // fade in
- gfxMillisecondsToTicks(1000), // no op (leds on)
- gfxMillisecondsToTicks(1000), // fade out
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
- gfxMillisecondsToTicks(GRADIENT_TIME), // left to rigt (outside in)
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
- gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom
- 0, // mirror leds
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
- gfxMillisecondsToTicks(GRADIENT_TIME), // left_to_right (mirrored, so inside out)
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
- gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom
- 0, // normal leds
- gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
-
- },
- .frame_functions =
- {
- led_backlight_keyframe_fade_in_all,
- keyframe_no_operation,
- led_backlight_keyframe_fade_out_all,
- led_backlight_keyframe_crossfade,
- led_backlight_keyframe_left_to_right_gradient,
- led_backlight_keyframe_crossfade,
- led_backlight_keyframe_top_to_bottom_gradient,
- led_backlight_keyframe_mirror_orientation,
- led_backlight_keyframe_crossfade,
- led_backlight_keyframe_left_to_right_gradient,
- led_backlight_keyframe_crossfade,
- led_backlight_keyframe_top_to_bottom_gradient,
- led_backlight_keyframe_normal_orientation,
- led_backlight_keyframe_crossfade,
- },
-};
-# endif
-
-#endif
diff --git a/quantum/visualizer/lcd_backlight.c b/quantum/visualizer/lcd_backlight.c
deleted file mode 100644
index 23978974e3..0000000000
--- a/quantum/visualizer/lcd_backlight.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "lcd_backlight.h"
-#include <math.h>
-
-static uint8_t current_hue = 0;
-static uint8_t current_saturation = 0;
-static uint8_t current_intensity = 0;
-static uint8_t current_brightness = 0;
-
-void lcd_backlight_init(void) {
- lcd_backlight_hal_init();
- lcd_backlight_color(current_hue, current_saturation, current_intensity);
-}
-
-// This code is based on Brian Neltner's blogpost and example code
-// "Why every LED light should be using HSI colorspace".
-// http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi
-static void hsi_to_rgb(float h, float s, float i, uint16_t* r_out, uint16_t* g_out, uint16_t* b_out) {
- unsigned int r, g, b;
- h = fmodf(h, 360.0f); // cycle h around to 0-360 degrees
- h = 3.14159f * h / 180.0f; // Convert to radians.
- s = s > 0.0f ? (s < 1.0f ? s : 1.0f) : 0.0f; // clamp s and i to interval [0,1]
- i = i > 0.0f ? (i < 1.0f ? i : 1.0f) : 0.0f;
-
- // Math! Thanks in part to Kyle Miller.
- if (h < 2.09439f) {
- r = 65535.0f * i / 3.0f * (1.0f + s * cos(h) / cosf(1.047196667f - h));
- g = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cos(1.047196667f - h)));
- b = 65535.0f * i / 3.0f * (1.0f - s);
- } else if (h < 4.188787) {
- h = h - 2.09439;
- g = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h));
- b = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h)));
- r = 65535.0f * i / 3.0f * (1.0f - s);
- } else {
- h = h - 4.188787;
- b = 65535.0f * i / 3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h));
- r = 65535.0f * i / 3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h)));
- g = 65535.0f * i / 3.0f * (1.0f - s);
- }
- *r_out = r > 65535 ? 65535 : r;
- *g_out = g > 65535 ? 65535 : g;
- *b_out = b > 65535 ? 65535 : b;
-}
-
-void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity) {
- uint16_t r, g, b;
- float hue_f = 360.0f * (float)hue / 255.0f;
- float saturation_f = (float)saturation / 255.0f;
- float intensity_f = (float)intensity / 255.0f;
- intensity_f *= (float)current_brightness / 255.0f;
- hsi_to_rgb(hue_f, saturation_f, intensity_f, &r, &g, &b);
- current_hue = hue;
- current_saturation = saturation;
- current_intensity = intensity;
- lcd_backlight_hal_color(r, g, b);
-}
-
-void lcd_backlight_brightness(uint8_t b) {
- current_brightness = b;
- lcd_backlight_color(current_hue, current_saturation, current_intensity);
-}
-
-uint8_t lcd_get_backlight_brightness(void) { return current_brightness; }
diff --git a/quantum/visualizer/lcd_backlight.h b/quantum/visualizer/lcd_backlight.h
deleted file mode 100644
index 4ea5b14639..0000000000
--- a/quantum/visualizer/lcd_backlight.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdint.h>
-
-// Helper macros for storing hue, staturation and intensity as unsigned integers
-#define LCD_COLOR(hue, saturation, intensity) (hue << 16 | saturation << 8 | intensity)
-#define LCD_HUE(color) ((color >> 16) & 0xFF)
-#define LCD_SAT(color) ((color >> 8) & 0xFF)
-#define LCD_INT(color) (color & 0xFF)
-
-static inline uint32_t change_lcd_color_intensity(uint32_t color, uint8_t new_intensity) { return (color & 0xFFFFFF00) | new_intensity; }
-
-void lcd_backlight_init(void);
-void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity);
-void lcd_backlight_brightness(uint8_t b);
-uint8_t lcd_get_backlight_brightness(void);
-
-void lcd_backlight_hal_init(void);
-void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b);
diff --git a/quantum/visualizer/lcd_backlight_keyframes.c b/quantum/visualizer/lcd_backlight_keyframes.c
deleted file mode 100644
index c13cce311d..0000000000
--- a/quantum/visualizer/lcd_backlight_keyframes.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "lcd_backlight_keyframes.h"
-
-bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state) {
- int frame_length = animation->frame_lengths[animation->current_frame];
- int current_pos = frame_length - animation->time_left_in_frame;
- uint8_t t_h = LCD_HUE(state->target_lcd_color);
- uint8_t t_s = LCD_SAT(state->target_lcd_color);
- uint8_t t_i = LCD_INT(state->target_lcd_color);
- uint8_t p_h = LCD_HUE(state->prev_lcd_color);
- uint8_t p_s = LCD_SAT(state->prev_lcd_color);
- uint8_t p_i = LCD_INT(state->prev_lcd_color);
-
- uint8_t d_h1 = t_h - p_h; // Modulo arithmetic since we want to wrap around
- int d_h2 = t_h - p_h;
- // Chose the shortest way around
- int d_h = abs(d_h2) < d_h1 ? d_h2 : d_h1;
- int d_s = t_s - p_s;
- int d_i = t_i - p_i;
-
- int hue = (d_h * current_pos) / frame_length;
- int sat = (d_s * current_pos) / frame_length;
- int intensity = (d_i * current_pos) / frame_length;
- // dprintf("%X -> %X = %X\n", p_h, t_h, hue);
- hue += p_h;
- sat += p_s;
- intensity += p_i;
- state->current_lcd_color = LCD_COLOR(hue, sat, intensity);
- lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color));
-
- return true;
-}
-
-bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- state->prev_lcd_color = state->target_lcd_color;
- state->current_lcd_color = state->target_lcd_color;
- lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color));
- return false;
-}
-
-bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- lcd_backlight_hal_color(0, 0, 0);
- return false;
-}
-
-bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- lcd_backlight_color(LCD_HUE(state->current_lcd_color), LCD_SAT(state->current_lcd_color), LCD_INT(state->current_lcd_color));
- return false;
-}
diff --git a/quantum/visualizer/lcd_backlight_keyframes.h b/quantum/visualizer/lcd_backlight_keyframes.h
deleted file mode 100644
index 88768dd4a5..0000000000
--- a/quantum/visualizer/lcd_backlight_keyframes.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "visualizer.h"
-
-// Animates the LCD backlight color between the current color and the target color (of the state)
-bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state);
-// Sets the backlight color to the target color
-bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state);
-
-bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state);
-bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state);
diff --git a/quantum/visualizer/lcd_keyframes.c b/quantum/visualizer/lcd_keyframes.c
deleted file mode 100644
index 1d6f3dca18..0000000000
--- a/quantum/visualizer/lcd_keyframes.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "lcd_keyframes.h"
-#include <string.h>
-#include "action_util.h"
-#include "led.h"
-#include "resources/resources.h"
-
-bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- gdispClear(White);
- gdispDrawString(0, 10, state->layer_text, state->font_dejavusansbold12, Black);
- return false;
-}
-
-static void format_layer_bitmap_string(uint16_t default_layer, uint16_t layer, char* buffer) {
- for (int i = 0; i < 16; i++) {
- uint32_t mask = (1u << i);
- if (default_layer & mask) {
- if (layer & mask) {
- *buffer = 'B';
- } else {
- *buffer = 'D';
- }
- } else if (layer & mask) {
- *buffer = '1';
- } else {
- *buffer = '0';
- }
- ++buffer;
-
- if (i == 3 || i == 7 || i == 11) {
- *buffer = ' ';
- ++buffer;
- }
- }
- *buffer = 0;
-}
-
-bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- const char* layer_help = "1=On D=Default B=Both";
- char layer_buffer[16 + 4]; // 3 spaces and one null terminator
- gdispClear(White);
- gdispDrawString(0, 0, layer_help, state->font_fixed5x8, Black);
- format_layer_bitmap_string(state->status.default_layer, state->status.layer, layer_buffer);
- gdispDrawString(0, 10, layer_buffer, state->font_fixed5x8, Black);
- format_layer_bitmap_string(state->status.default_layer >> 16, state->status.layer >> 16, layer_buffer);
- gdispDrawString(0, 20, layer_buffer, state->font_fixed5x8, Black);
- return false;
-}
-
-static void format_mods_bitmap_string(uint8_t mods, char* buffer) {
- *buffer = ' ';
- ++buffer;
-
- for (int i = 0; i < 8; i++) {
- uint32_t mask = (1u << i);
- if (mods & mask) {
- *buffer = '1';
- } else {
- *buffer = '0';
- }
- ++buffer;
-
- if (i == 3) {
- *buffer = ' ';
- ++buffer;
- }
- }
- *buffer = 0;
-}
-
-bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
-
- const char* title = "Modifier states";
- const char* mods_header = " CSAG CSAG ";
- char status_buffer[12];
-
- gdispClear(White);
- gdispDrawString(0, 0, title, state->font_fixed5x8, Black);
- gdispDrawString(0, 10, mods_header, state->font_fixed5x8, Black);
- format_mods_bitmap_string(state->status.mods, status_buffer);
- gdispDrawString(0, 20, status_buffer, state->font_fixed5x8, Black);
-
- return false;
-}
-
-#define LED_STATE_STRING_SIZE sizeof("NUM CAPS SCRL COMP KANA")
-
-static void get_led_state_string(char* output, visualizer_state_t* state) {
- uint8_t pos = 0;
-
- if (state->status.leds & (1u << USB_LED_NUM_LOCK)) {
- memcpy(output + pos, "NUM ", 4);
- pos += 4;
- }
- if (state->status.leds & (1u << USB_LED_CAPS_LOCK)) {
- memcpy(output + pos, "CAPS ", 5);
- pos += 5;
- }
- if (state->status.leds & (1u << USB_LED_SCROLL_LOCK)) {
- memcpy(output + pos, "SCRL ", 5);
- pos += 5;
- }
- if (state->status.leds & (1u << USB_LED_COMPOSE)) {
- memcpy(output + pos, "COMP ", 5);
- pos += 5;
- }
- if (state->status.leds & (1u << USB_LED_KANA)) {
- memcpy(output + pos, "KANA", 4);
- pos += 4;
- }
- output[pos] = 0;
-}
-
-bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- char output[LED_STATE_STRING_SIZE];
- get_led_state_string(output, state);
- gdispClear(White);
- gdispDrawString(0, 10, output, state->font_dejavusansbold12, Black);
- return false;
-}
-
-bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- gdispClear(White);
- uint8_t y = 10;
- if (state->status.leds) {
- char output[LED_STATE_STRING_SIZE];
- get_led_state_string(output, state);
- gdispDrawString(0, 1, output, state->font_dejavusansbold12, Black);
- y = 17;
- }
- gdispDrawString(0, y, state->layer_text, state->font_dejavusansbold12, Black);
- return false;
-}
-
-bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- // Read the uGFX documentation for information how to use the displays
- // http://wiki.ugfx.org/index.php/Main_Page
- gdispClear(Black);
-
- // You can use static variables for things that can't be found in the animation
- // or state structs, here we use the image
-
- // gdispGBlitArea is a tricky function to use since it supports blitting part of the image
- // if you have full screen image, then just use LCD_WIDTH and LCD_HEIGHT for both source and target dimensions
- gdispGBlitArea(GDISP, 0, 0, 128, 32, 0, 0, LCD_WIDTH, (pixel_t*)resource_lcd_logo);
-
- return false;
-}
-
-bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- gdispSetPowerMode(powerOff);
- return false;
-}
-
-bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- gdispSetPowerMode(powerOn);
- return false;
-}
diff --git a/quantum/visualizer/lcd_keyframes.h b/quantum/visualizer/lcd_keyframes.h
deleted file mode 100644
index b7125e8323..0000000000
--- a/quantum/visualizer/lcd_keyframes.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "visualizer.h"
-
-// Displays the layer text centered vertically on the screen
-bool lcd_keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays a bitmap (0/1) of all the currently active layers
-bool lcd_keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays a bitmap (0/1) of all the currently active mods
-bool lcd_keyframe_display_mods_bitmap(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays the keyboard led states (CAPS (Caps lock), NUM (Num lock), SCRL (Scroll lock), COMP (Compose), KANA)
-bool lcd_keyframe_display_led_states(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays both the layer text and the led states
-bool lcd_keyframe_display_layer_and_led_states(keyframe_animation_t* animation, visualizer_state_t* state);
-// Displays the QMK logo on the LCD screen
-bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* state);
-
-bool lcd_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state);
-bool lcd_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state);
diff --git a/quantum/visualizer/led_backlight_keyframes.c b/quantum/visualizer/led_backlight_keyframes.c
deleted file mode 100644
index 338ada5227..0000000000
--- a/quantum/visualizer/led_backlight_keyframes.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-#include "gfx.h"
-#include <math.h>
-#include "led_backlight_keyframes.h"
-
-static uint8_t fade_led_color(keyframe_animation_t* animation, int from, int to) {
- int frame_length = animation->frame_lengths[animation->current_frame];
- int current_pos = frame_length - animation->time_left_in_frame;
- int delta = to - from;
- int luma = (delta * current_pos) / frame_length;
- luma += from;
- return luma;
-}
-
-static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint8_t from, uint8_t to) {
- uint8_t luma = fade_led_color(animation, from, to);
- color_t color = LUMA2COLOR(luma);
- gdispGClear(LED_DISPLAY, color);
-}
-
-// TODO: Should be customizable per keyboard
-#define NUM_ROWS LED_HEIGHT
-#define NUM_COLS LED_WIDTH
-
-static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS];
-static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS];
-
-static uint8_t compute_gradient_color(float t, float index, float num) {
- const float two_pi = M_PI * 2.0f;
- float normalized_index = (1.0f - index / (num - 1.0f)) * two_pi;
- float x = t * two_pi + normalized_index;
- float v = 0.5 * (cosf(x) + 1.0f);
- return (uint8_t)(255.0f * v);
-}
-
-bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- keyframe_fade_all_leds_from_to(animation, 0, 255);
- return true;
-}
-
-bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- keyframe_fade_all_leds_from_to(animation, 255, 0);
- return true;
-}
-
-bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- float frame_length = animation->frame_lengths[animation->current_frame];
- float current_pos = frame_length - animation->time_left_in_frame;
- float t = current_pos / frame_length;
- for (int i = 0; i < NUM_COLS; i++) {
- uint8_t color = compute_gradient_color(t, i, NUM_COLS);
- gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color));
- }
- return true;
-}
-
-bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- float frame_length = animation->frame_lengths[animation->current_frame];
- float current_pos = frame_length - animation->time_left_in_frame;
- float t = current_pos / frame_length;
- for (int i = 0; i < NUM_ROWS; i++) {
- uint8_t color = compute_gradient_color(t, i, NUM_ROWS);
- gdispGDrawLine(LED_DISPLAY, 0, i, NUM_COLS - 1, i, LUMA2COLOR(color));
- }
- return true;
-}
-
-static void copy_current_led_state(uint8_t* dest) {
- for (int i = 0; i < NUM_ROWS; i++) {
- for (int j = 0; j < NUM_COLS; j++) {
- dest[i * NUM_COLS + j] = gdispGGetPixelColor(LED_DISPLAY, j, i);
- }
- }
-}
-bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- if (animation->first_update_of_frame) {
- copy_current_led_state(&crossfade_start_frame[0][0]);
- run_next_keyframe(animation, state);
- copy_current_led_state(&crossfade_end_frame[0][0]);
- }
- for (int i = 0; i < NUM_ROWS; i++) {
- for (int j = 0; j < NUM_COLS; j++) {
- color_t color = LUMA2COLOR(fade_led_color(animation, crossfade_start_frame[i][j], crossfade_end_frame[i][j]));
- gdispGDrawPixel(LED_DISPLAY, j, i, color);
- }
- }
- return true;
-}
-
-bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180);
- return false;
-}
-
-bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0);
- return false;
-}
-
-bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- gdispGSetPowerMode(LED_DISPLAY, powerOff);
- return false;
-}
-
-bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)state;
- (void)animation;
- gdispGSetPowerMode(LED_DISPLAY, powerOn);
- return false;
-}
diff --git a/quantum/visualizer/led_backlight_keyframes.h b/quantum/visualizer/led_backlight_keyframes.h
deleted file mode 100644
index 90153be5eb..0000000000
--- a/quantum/visualizer/led_backlight_keyframes.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include "visualizer.h"
-
-bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state);
-
-bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state);
-bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state);
-
-extern keyframe_animation_t led_test_animation;
diff --git a/quantum/visualizer/readme.md b/quantum/visualizer/readme.md
deleted file mode 100644
index 298efb742f..0000000000
--- a/quantum/visualizer/readme.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# A visualization library for the TMK keyboard firmware
-
-This library is designed to work together with the [TMK keyboard firmware](https://github.com/tmk/tmk_keyboard). Currently it only works for [Chibios](http://www.chibios.org/)
- flavors, but it would be possible to add support for other configurations as well. The LCD display functionality is provided by the [uGFX library](https://ugfx.io/).
-
-## To use this library as a user
-You can and should modify the visualizer\_user.c file. Check the comments in the file for more information.
-
-## To add this library to custom keyboard projects
-
-1. Add tmk_visualizer as a submodule to your project
-1. Set VISUALIZER_DIR in the main keyboard project makefile to point to the submodule
-1. Define LCD\_ENABLE and/or LCD\_BACKLIGHT\_ENABLE, to enable support
-1. Include the visualizer.mk make file
-1. Copy the files in the example\_integration folder to your keyboard project
-1. All other files than the callback.c file are included automatically, so you will need to add callback.c to your makefile manually. If you already have a similar file in your project, you can just copy the functions instead of the whole file.
-1. Edit the files to match your hardware. You might might want to read the Chibios and UGfx documentation, for more information.
-1. If you enable LCD support you might also have to write a custom uGFX display driver, check the uGFX documentation for that. You probably also want to enable SPI support in your Chibios configuration.
diff --git a/quantum/visualizer/resources/lcd_logo.c b/quantum/visualizer/resources/lcd_logo.c
deleted file mode 100644
index 13bf734cb3..0000000000
--- a/quantum/visualizer/resources/lcd_logo.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "resources.h"
-
-// clang-format off
-
-// To generate an image array like this
-// Ensure the image is 128 x 32 or smaller
-// Convert the bitmap to a C array using a program like http://www.riuson.com/lcd-image-converter/
-// Ensure the the conversion process produces a monochrome format array - 1 bit/pixel, left to right, top to bottom
-// Update array in the source code with the C array produced by the conversion program
-
-// The image below is generated from lcd_logo.png
-__attribute__((weak)) const uint8_t resource_lcd_logo[512] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xFE, 0xEE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xEE, 0xF0, 0x01, 0xC6, 0x0D, 0x8C, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xFE, 0xEE, 0xFE, 0x03, 0xE7, 0x1D, 0x9C, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x37, 0x1D, 0xB8, 0x18, 0x0B, 0x59, 0xC8, 0x09, 0xE5, 0x9E, 0x00,
- 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x37, 0xBD, 0xF0, 0x18, 0x6F, 0x7F, 0xEC, 0x9B, 0x37, 0xB3, 0x00, 0x00, 0xFE, 0xEE, 0xFE, 0x06, 0x37, 0xBD, 0xE0, 0x1F, 0x6C, 0x66, 0x6D, 0xD8, 0x36, 0x33, 0x00,
- 0x00, 0x1E, 0xEE, 0xF0, 0x06, 0x36, 0xED, 0xF0, 0x1F, 0x6C, 0x66, 0x6D, 0x59, 0xF6, 0x3E, 0x00, 0x00, 0x1F, 0x6D, 0xF0, 0x06, 0x36, 0xED, 0xB8, 0x18, 0x6C, 0x66, 0x67, 0x73, 0x36, 0x30, 0x00,
- 0x00, 0xFF, 0x83, 0xFE, 0x03, 0xE6, 0x4D, 0x9C, 0x18, 0x6C, 0x66, 0x67, 0x73, 0x36, 0x1F, 0x00, 0x00, 0x1F, 0xEF, 0xF0, 0x01, 0xC6, 0x0D, 0x8C, 0x18, 0x6C, 0x66, 0x62, 0x21, 0xD6, 0x0E, 0x00,
- 0x00, 0xFF, 0xEF, 0xFE, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x92, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
diff --git a/quantum/visualizer/resources/lcd_logo.png b/quantum/visualizer/resources/lcd_logo.png
deleted file mode 100644
index 178ef65f15..0000000000
--- a/quantum/visualizer/resources/lcd_logo.png
+++ /dev/null
Binary files differ
diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c
deleted file mode 100644
index 709affbb77..0000000000
--- a/quantum/visualizer/visualizer.c
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#include "config.h"
-#include "visualizer.h"
-#include <string.h>
-#ifdef PROTOCOL_CHIBIOS
-# include <ch.h>
-#endif
-
-#include "gfx.h"
-
-#ifdef LCD_BACKLIGHT_ENABLE
-# include "lcd_backlight.h"
-#endif
-
-//#define DEBUG_VISUALIZER
-
-#ifdef DEBUG_VISUALIZER
-# include "debug.h"
-#else
-# include "nodebug.h"
-#endif
-
-#ifdef SERIAL_LINK_ENABLE
-# include "serial_link/protocol/transport.h"
-# include "serial_link/system/serial_link.h"
-#endif
-
-#include "action_util.h"
-
-// Define this in config.h
-#ifndef VISUALIZER_THREAD_PRIORITY
-// The visualizer needs gfx thread priorities
-# define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2)
-#endif
-
-static visualizer_keyboard_status_t current_status = {.layer = 0xFFFFFFFF,
- .default_layer = 0xFFFFFFFF,
- .leds = 0xFFFFFFFF,
-#ifdef BACKLIGHT_ENABLE
- .backlight_level = 0,
-#endif
- .mods = 0xFF,
- .suspended = false,
-#ifdef VISUALIZER_USER_DATA_SIZE
- .user_data = {0}
-#endif
-};
-
-static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) {
- return status1->layer == status2->layer && status1->default_layer == status2->default_layer && status1->mods == status2->mods && status1->leds == status2->leds && status1->suspended == status2->suspended
-#ifdef BACKLIGHT_ENABLE
- && status1->backlight_level == status2->backlight_level
-#endif
-#ifdef VISUALIZER_USER_DATA_SIZE
- && memcmp(status1->user_data, status2->user_data, VISUALIZER_USER_DATA_SIZE) == 0
-#endif
- ;
-}
-
-static bool visualizer_enabled = false;
-
-#ifdef VISUALIZER_USER_DATA_SIZE
-static uint8_t user_data[VISUALIZER_USER_DATA_SIZE];
-#endif
-
-#define MAX_SIMULTANEOUS_ANIMATIONS 4
-static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {};
-
-#ifdef SERIAL_LINK_ENABLE
-MASTER_TO_ALL_SLAVES_OBJECT(current_status, visualizer_keyboard_status_t);
-
-static remote_object_t* remote_objects[] = {
- REMOTE_OBJECT(current_status),
-};
-
-#endif
-
-GDisplay* LCD_DISPLAY = 0;
-GDisplay* LED_DISPLAY = 0;
-
-#ifdef LCD_DISPLAY_NUMBER
-__attribute__((weak)) GDisplay* get_lcd_display(void) { return gdispGetDisplay(LCD_DISPLAY_NUMBER); }
-#endif
-
-#ifdef LED_DISPLAY_NUMBER
-__attribute__((weak)) GDisplay* get_led_display(void) { return gdispGetDisplay(LED_DISPLAY_NUMBER); }
-#endif
-
-void start_keyframe_animation(keyframe_animation_t* animation) {
- animation->current_frame = -1;
- animation->time_left_in_frame = 0;
- animation->need_update = true;
- int free_index = -1;
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- if (animations[i] == animation) {
- return;
- }
- if (free_index == -1 && animations[i] == NULL) {
- free_index = i;
- }
- }
- if (free_index != -1) {
- animations[free_index] = animation;
- }
-}
-
-void stop_keyframe_animation(keyframe_animation_t* animation) {
- animation->current_frame = animation->num_frames;
- animation->time_left_in_frame = 0;
- animation->need_update = true;
- animation->first_update_of_frame = false;
- animation->last_update_of_frame = false;
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- if (animations[i] == animation) {
- animations[i] = NULL;
- return;
- }
- }
-}
-
-void stop_all_keyframe_animations(void) {
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- if (animations[i]) {
- animations[i]->current_frame = animations[i]->num_frames;
- animations[i]->time_left_in_frame = 0;
- animations[i]->need_update = true;
- animations[i]->first_update_of_frame = false;
- animations[i]->last_update_of_frame = false;
- animations[i] = NULL;
- }
- }
-}
-
-static uint8_t get_num_running_animations(void) {
- uint8_t count = 0;
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- count += animations[i] ? 1 : 0;
- }
- return count;
-}
-
-static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systemticks_t delta, systemticks_t* sleep_time) {
- // TODO: Clean up this messy code
- dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, animation->time_left_in_frame, delta);
- if (animation->current_frame == animation->num_frames) {
- animation->need_update = false;
- return false;
- }
- if (animation->current_frame == -1) {
- animation->current_frame = 0;
- animation->time_left_in_frame = animation->frame_lengths[0];
- animation->need_update = true;
- animation->first_update_of_frame = true;
- } else {
- animation->time_left_in_frame -= delta;
- while (animation->time_left_in_frame <= 0) {
- int left = animation->time_left_in_frame;
- if (animation->need_update) {
- animation->time_left_in_frame = 0;
- animation->last_update_of_frame = true;
- (*animation->frame_functions[animation->current_frame])(animation, state);
- animation->last_update_of_frame = false;
- }
- animation->current_frame++;
- animation->need_update = true;
- animation->first_update_of_frame = true;
- if (animation->current_frame == animation->num_frames) {
- if (animation->loop) {
- animation->current_frame = 0;
- } else {
- stop_keyframe_animation(animation);
- return false;
- }
- }
- delta = -left;
- animation->time_left_in_frame = animation->frame_lengths[animation->current_frame];
- animation->time_left_in_frame -= delta;
- }
- }
- if (animation->need_update) {
- animation->need_update = (*animation->frame_functions[animation->current_frame])(animation, state);
- animation->first_update_of_frame = false;
- }
-
- systemticks_t wanted_sleep = animation->need_update ? gfxMillisecondsToTicks(10) : (unsigned)animation->time_left_in_frame;
- if (wanted_sleep < *sleep_time) {
- *sleep_time = wanted_sleep;
- }
-
- return true;
-}
-
-void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state) {
- int next_frame = animation->current_frame + 1;
- if (next_frame == animation->num_frames) {
- next_frame = 0;
- }
- keyframe_animation_t temp_animation = *animation;
- temp_animation.current_frame = next_frame;
- temp_animation.time_left_in_frame = animation->frame_lengths[next_frame];
- temp_animation.first_update_of_frame = true;
- temp_animation.last_update_of_frame = false;
- temp_animation.need_update = false;
- visualizer_state_t temp_state = *state;
- (*temp_animation.frame_functions[next_frame])(&temp_animation, &temp_state);
-}
-
-// TODO: Optimize the stack size, this is probably way too big
-static DECLARE_THREAD_STACK(visualizerThreadStack, 1024);
-static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
- (void)arg;
-
- GListener event_listener;
- geventListenerInit(&event_listener);
- geventAttachSource(&event_listener, (GSourceHandle)&current_status, 0);
-
- visualizer_keyboard_status_t initial_status = {
- .default_layer = 0xFFFFFFFF,
- .layer = 0xFFFFFFFF,
- .mods = 0xFF,
- .leds = 0xFFFFFFFF,
- .suspended = false,
-#ifdef BACKLIGHT_ENABLE
- .backlight_level = 0,
-#endif
-#ifdef VISUALIZER_USER_DATA_SIZE
- .user_data = {0},
-#endif
- };
-
- visualizer_state_t state = {.status = initial_status,
- .current_lcd_color = 0,
-#ifdef LCD_ENABLE
- .font_fixed5x8 = gdispOpenFont("fixed_5x8"),
- .font_dejavusansbold12 = gdispOpenFont("DejaVuSansBold12")
-#endif
- };
- initialize_user_visualizer(&state);
- state.prev_lcd_color = state.current_lcd_color;
-
-#ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_color(LCD_HUE(state.current_lcd_color), LCD_SAT(state.current_lcd_color), LCD_INT(state.current_lcd_color));
-#endif
-
- systemticks_t sleep_time = TIME_INFINITE;
- systemticks_t current_time = gfxSystemTicks();
- bool force_update = true;
-
- while (true) {
- systemticks_t new_time = gfxSystemTicks();
- systemticks_t delta = new_time - current_time;
- current_time = new_time;
- bool enabled = visualizer_enabled;
- if (force_update || !same_status(&state.status, &current_status)) {
- force_update = false;
-#if BACKLIGHT_ENABLE
- if (current_status.backlight_level != state.status.backlight_level) {
- if (current_status.backlight_level != 0) {
- gdispGSetPowerMode(LED_DISPLAY, powerOn);
- uint16_t percent = (uint16_t)current_status.backlight_level * 100 / BACKLIGHT_LEVELS;
- gdispGSetBacklight(LED_DISPLAY, percent);
- } else {
- gdispGSetPowerMode(LED_DISPLAY, powerOff);
- }
- state.status.backlight_level = current_status.backlight_level;
- }
-#endif
- if (visualizer_enabled) {
- if (current_status.suspended) {
- stop_all_keyframe_animations();
- visualizer_enabled = false;
- state.status = current_status;
- user_visualizer_suspend(&state);
- } else {
- visualizer_keyboard_status_t prev_status = state.status;
- state.status = current_status;
- update_user_visualizer_state(&state, &prev_status);
- }
- state.prev_lcd_color = state.current_lcd_color;
- }
- }
- if (!enabled && state.status.suspended && current_status.suspended == false) {
- // Setting the status to the initial status will force an update
- // when the visualizer is enabled again
- state.status = initial_status;
- state.status.suspended = false;
- stop_all_keyframe_animations();
- user_visualizer_resume(&state);
- state.prev_lcd_color = state.current_lcd_color;
- }
- sleep_time = TIME_INFINITE;
- for (int i = 0; i < MAX_SIMULTANEOUS_ANIMATIONS; i++) {
- if (animations[i]) {
- update_keyframe_animation(animations[i], &state, delta, &sleep_time);
- }
- }
-#ifdef BACKLIGHT_ENABLE
- gdispGFlush(LED_DISPLAY);
-#endif
-
-#ifdef LCD_ENABLE
- gdispGFlush(LCD_DISPLAY);
-#endif
-
-#ifdef EMULATOR
- draw_emulator();
-#endif
- // Enable the visualizer when the startup or the suspend animation has finished
- if (!visualizer_enabled && state.status.suspended == false && get_num_running_animations() == 0) {
- visualizer_enabled = true;
- force_update = true;
- sleep_time = 0;
- }
-
- systemticks_t after_update = gfxSystemTicks();
- unsigned update_delta = after_update - current_time;
- if (sleep_time != TIME_INFINITE) {
- if (sleep_time > update_delta) {
- sleep_time -= update_delta;
- } else {
- sleep_time = 0;
- }
- }
- dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, sleep_time);
-#ifdef PROTOCOL_CHIBIOS
- // The gEventWait function really takes milliseconds, even if the documentation says ticks.
- // Unfortunately there's no generic ugfx conversion from system time to milliseconds,
- // so let's do it in a platform dependent way.
-
- // On windows the system ticks is the same as milliseconds anyway
- if (sleep_time != TIME_INFINITE) {
- sleep_time = TIME_I2MS(sleep_time);
- }
-#endif
- geventEventWait(&event_listener, sleep_time);
- }
-#ifdef LCD_ENABLE
- gdispCloseFont(state.font_fixed5x8);
- gdispCloseFont(state.font_dejavusansbold12);
-#endif
-
- return 0;
-}
-
-void visualizer_init(void) {
- gfxInit();
-
-#ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_init();
-#endif
-
-#ifdef SERIAL_LINK_ENABLE
- add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*));
-#endif
-
-#ifdef LCD_ENABLE
- LCD_DISPLAY = get_lcd_display();
-#endif
-
-#ifdef BACKLIGHT_ENABLE
- LED_DISPLAY = get_led_display();
-#endif
-
- // We are using a low priority thread, the idea is to have it run only
- // when the main thread is sleeping during the matrix scanning
- gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack), VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL);
-}
-
-void update_status(bool changed) {
- if (changed) {
- GSourceListener* listener = geventGetSourceListener((GSourceHandle)&current_status, NULL);
- if (listener) {
- geventSendEvent(listener);
- }
- }
-#ifdef SERIAL_LINK_ENABLE
- static systime_t last_update = 0;
- systime_t current_update = chVTGetSystemTimeX();
- systime_t delta = current_update - last_update;
- if (changed || delta > TIME_MS2I(10)) {
- last_update = current_update;
- visualizer_keyboard_status_t* r = begin_write_current_status();
- *r = current_status;
- end_write_current_status();
- }
-#endif
-}
-
-uint8_t visualizer_get_mods() {
- uint8_t mods = get_mods();
-
-#ifndef NO_ACTION_ONESHOT
- if (!has_oneshot_mods_timed_out()) {
- mods |= get_oneshot_mods();
- }
-#endif
- return mods;
-}
-
-#ifdef VISUALIZER_USER_DATA_SIZE
-void visualizer_set_user_data(void* u) { memcpy(user_data, u, VISUALIZER_USER_DATA_SIZE); }
-#endif
-
-void visualizer_update(layer_state_t default_state, layer_state_t state, uint8_t mods, uint32_t leds) {
- // Note that there's a small race condition here, the thread could read
- // a state where one of these are set but not the other. But this should
- // not really matter as it will be fixed during the next loop step.
- // Alternatively a mutex could be used instead of the volatile variables
-
- bool changed = false;
-#ifdef SERIAL_LINK_ENABLE
- if (is_serial_link_connected()) {
- visualizer_keyboard_status_t* new_status = read_current_status();
- if (new_status) {
- if (!same_status(&current_status, new_status)) {
- changed = true;
- current_status = *new_status;
- }
- }
- } else {
-#else
- {
-#endif
- visualizer_keyboard_status_t new_status = {
- .layer = state,
- .default_layer = default_state,
- .mods = mods,
- .leds = leds,
-#ifdef BACKLIGHT_ENABLE
- .backlight_level = current_status.backlight_level,
-#endif
- .suspended = current_status.suspended,
- };
-#ifdef VISUALIZER_USER_DATA_SIZE
- memcpy(new_status.user_data, user_data, VISUALIZER_USER_DATA_SIZE);
-#endif
- if (!same_status(&current_status, &new_status)) {
- changed = true;
- current_status = new_status;
- }
- }
- update_status(changed);
-}
-
-void visualizer_suspend(void) {
- current_status.suspended = true;
- update_status(true);
-}
-
-void visualizer_resume(void) {
- current_status.suspended = false;
- update_status(true);
-}
-
-#ifdef BACKLIGHT_ENABLE
-void backlight_set(uint8_t level) {
- current_status.backlight_level = level;
- update_status(true);
-}
-#endif
diff --git a/quantum/visualizer/visualizer.h b/quantum/visualizer/visualizer.h
deleted file mode 100644
index 627c80a305..0000000000
--- a/quantum/visualizer/visualizer.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-#pragma once
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#include "config.h"
-#include "gfx.h"
-#include "action_layer.h"
-
-#ifdef LCD_BACKLIGHT_ENABLE
-# include "lcd_backlight.h"
-#endif
-
-#ifdef BACKLIGHT_ENABLE
-# include "backlight.h"
-#endif
-
-// use this function to merge both real_mods and oneshot_mods in a uint16_t
-uint8_t visualizer_get_mods(void);
-
-// This need to be called once at the start
-void visualizer_init(void);
-// This should be called at every matrix scan
-void visualizer_update(layer_state_t default_state, layer_state_t state, uint8_t mods, uint32_t leds);
-
-// This should be called when the keyboard goes to suspend state
-void visualizer_suspend(void);
-// This should be called when the keyboard wakes up from suspend state
-void visualizer_resume(void);
-
-// These functions are week, so they can be overridden by the keyboard
-// if needed
-GDisplay* get_lcd_display(void);
-GDisplay* get_led_display(void);
-
-// For emulator builds, this function need to be implemented
-#ifdef EMULATOR
-void draw_emulator(void);
-#endif
-
-// If you need support for more than 16 keyframes per animation, you can change this
-#define MAX_VISUALIZER_KEY_FRAMES 16
-
-struct keyframe_animation_t;
-
-typedef struct {
- layer_state_t layer;
- layer_state_t default_layer;
- uint32_t leds; // See led.h for available statuses
- uint8_t mods;
- bool suspended;
-#ifdef BACKLIGHT_ENABLE
- uint8_t backlight_level;
-#endif
-#ifdef VISUALIZER_USER_DATA_SIZE
- uint8_t user_data[VISUALIZER_USER_DATA_SIZE];
-#endif
-} visualizer_keyboard_status_t;
-
-// The state struct is used by the various keyframe functions
-// It's also used for setting the LCD color and layer text
-// from the user customized code
-typedef struct visualizer_state_t {
- // The user code should primarily be modifying these
- uint32_t target_lcd_color;
- const char* layer_text;
-
- // The user visualizer(and animation functions) can read these
- visualizer_keyboard_status_t status;
-
- // These are used by the animation functions
- uint32_t current_lcd_color;
- uint32_t prev_lcd_color;
-#ifdef LCD_ENABLE
- gFont font_fixed5x8;
- gFont font_dejavusansbold12;
-#endif
-} visualizer_state_t;
-
-// Any custom keyframe function should have this signature
-// return true to get continuous updates, otherwise you will only get one
-// update per frame
-typedef bool (*frame_func)(struct keyframe_animation_t*, visualizer_state_t*);
-
-// Represents a keyframe animation, so fields are internal to the system
-// while others are meant to be initialized by the user code
-typedef struct keyframe_animation_t {
- // These should be initialized
- int num_frames;
- bool loop;
- int frame_lengths[MAX_VISUALIZER_KEY_FRAMES];
- frame_func frame_functions[MAX_VISUALIZER_KEY_FRAMES];
-
- // Used internally by the system, and can also be read by
- // keyframe update functions
- int current_frame;
- int time_left_in_frame;
- bool first_update_of_frame;
- bool last_update_of_frame;
- bool need_update;
-
-} keyframe_animation_t;
-
-extern GDisplay* LCD_DISPLAY;
-extern GDisplay* LED_DISPLAY;
-
-void start_keyframe_animation(keyframe_animation_t* animation);
-void stop_keyframe_animation(keyframe_animation_t* animation);
-// This runs the next keyframe, but does not update the animation state
-// Useful for crossfades for example
-void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state);
-
-// The master can set userdata which will be transferred to the slave
-#ifdef VISUALIZER_USER_DATA_SIZE
-void visualizer_set_user_data(void* user_data);
-#endif
-
-// These functions have to be implemented by the user
-// Called regularly each time the state has changed (but not every scan loop)
-void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status);
-// Called when the computer goes to suspend, will also stop calling update_user_visualizer_state
-void user_visualizer_suspend(visualizer_state_t* state);
-// You have to start at least one animation as a response to the following two functions
-// When the animation has finished the visualizer will resume normal operation and start calling the
-// update_user_visualizer_state again
-// Called when the keyboard boots up
-void initialize_user_visualizer(visualizer_state_t* state);
-// Called when the computer resumes from a suspend
-void user_visualizer_resume(visualizer_state_t* state);
diff --git a/quantum/visualizer/visualizer.mk b/quantum/visualizer/visualizer.mk
deleted file mode 100644
index 4c961ac59d..0000000000
--- a/quantum/visualizer/visualizer.mk
+++ /dev/null
@@ -1,123 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2016 Fred Sundvik
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-define ADD_DRIVER
- $(1)_DRIVER:=$(strip $($(1)_DRIVER))
- $(1)_WIDTH:=$(strip $($(1)_WIDTH))
- $(1)_HEIGHT:=$(strip $($(1)_HEIGHT))
- ifeq ($($(1)_DRIVER),)
- $$(error $(1)_DRIVER is not defined)
- endif
- ifeq ($($(1)_WIDTH),)
- $$(error $(1)_WIDTH is not defined)
- endif
- ifeq ($($(1)_HEIGHT),)
- $$(error $(1)_HEIGHT is not defined)
- endif
- OPT_DEFS+=-D$(1)_WIDTH=$($(1)_WIDTH)
- OPT_DEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT)
- GFXDEFS+=-D$(1)_WIDTH=$($(1)_WIDTH)
- GFXDEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT)
- $(1)_DISPLAY_NUMBER:=$$(words $$(GDISP_DRIVER_LIST))
- OPT_DEFS+=-D$(1)_DISPLAY_NUMBER=$$($(1)_DISPLAY_NUMBER)
- include $(TOP_DIR)/drivers/ugfx/gdisp/$($(1)_DRIVER)/driver.mk
-endef
-
-GDISP_DRIVER_LIST:=
-
-SRC += $(VISUALIZER_DIR)/visualizer.c \
- $(VISUALIZER_DIR)/visualizer_keyframes.c
-EXTRAINCDIRS += $(GFXINC) $(VISUALIZER_DIR)
-GFXLIB = $(LIB_PATH)/ugfx
-VPATH += $(VISUALIZER_PATH)
-
-OPT_DEFS += -DVISUALIZER_ENABLE
-
-ifdef LCD_ENABLE
-OPT_DEFS += -DLCD_ENABLE
-ULIBS += -lm
-endif
-
-ifeq ($(strip $(LCD_ENABLE)), yes)
- SRC += $(VISUALIZER_DIR)/lcd_keyframes.c
- ifeq ($(strip $(LCD_BACKLIGHT_ENABLE)), yes)
- OPT_DEFS += -DLCD_BACKLIGHT_ENABLE
- SRC += $(VISUALIZER_DIR)/lcd_backlight.c
- SRC += $(VISUALIZER_DIR)/lcd_backlight_keyframes.c
- endif
-# Note, that the linker will strip out any resources that are not actually in use
-SRC += $(VISUALIZER_DIR)/resources/lcd_logo.c
-$(eval $(call ADD_DRIVER,LCD))
-endif
-
-ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
-SRC += $(VISUALIZER_DIR)/led_backlight_keyframes.c
-$(eval $(call ADD_DRIVER,LED))
-endif
-
-SRC += $(VISUALIZER_DIR)/default_animations.c
-
-include $(GFXLIB)/gfx.mk
-# For the common_gfxconf.h
-GFXINC += quantum/visualizer
-
-GFXSRC := $(patsubst $(TOP_DIR)/%,%,$(GFXSRC))
-GFXDEFS := $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS)))
-
-GDISP_LIST_COMMA=,
-GDISP_LIST_EMPTY=
-GDISP_LIST_SPACE=$(GDISP_LIST_EMPTY) $(GDISP_LIST_EMPTY)
-
-GDISP_DRIVER_LIST := $(strip $(GDISP_DRIVER_LIST))
-GDISP_DRIVER_LIST := $(subst $(GDISP_LIST_SPACE),$(GDISP_LIST_COMMA),$(GDISP_DRIVER_LIST))
-
-GFXDEFS +=-DGDISP_DRIVER_LIST="$(GDISP_DRIVER_LIST)"
-
-ifneq ("$(wildcard $(KEYMAP_PATH)/visualizer.c)","")
- SRC += $(KEYMAP_PATH)/visualizer.c
-else
- VISUALIZER_1 := $(KEYBOARD_PATH_1)/visualizer.c
- VISUALIZER_2 := $(KEYBOARD_PATH_2)/visualizer.c
- VISUALIZER_3 := $(KEYBOARD_PATH_3)/visualizer.c
- VISUALIZER_4 := $(KEYBOARD_PATH_4)/visualizer.c
- VISUALIZER_5 := $(KEYBOARD_PATH_5)/visualizer.c
-
- ifneq ("$(wildcard $(VISUALIZER_5))","")
- SRC += $(VISUALIZER_5)
- endif
- ifneq ("$(wildcard $(VISUALIZER_4))","")
- SRC += $(VISUALIZER_4)
- endif
- ifneq ("$(wildcard $(VISUALIZER_3))","")
- SRC += $(VISUALIZER_3)
- endif
- ifneq ("$(wildcard $(VISUALIZER_2))","")
- SRC += $(VISUALIZER_2)
- endif
- ifneq ("$(wildcard $(VISUALIZER_1))","")
- SRC += $(VISUALIZER_1)
- endif
-endif
-
-ifdef EMULATOR
-UINCDIR += $(TMK_DIR)/common
-endif
diff --git a/quantum/visualizer/visualizer_keyframes.h b/quantum/visualizer/visualizer_keyframes.h
deleted file mode 100644
index c92ff16113..0000000000
--- a/quantum/visualizer/visualizer_keyframes.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright 2017 Fred Sundvik
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include "visualizer.h"
-
-// Some predefined keyframe functions that can be used by the user code
-// Does nothing, useful for adding delays
-bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state);
diff --git a/quantum/wpm.c b/quantum/wpm.c
index e711e9fe73..925e2c416e 100644
--- a/quantum/wpm.c
+++ b/quantum/wpm.c
@@ -21,13 +21,37 @@
// WPM Stuff
static uint8_t current_wpm = 0;
-static uint16_t wpm_timer = 0;
+static uint32_t wpm_timer = 0;
+#ifndef WPM_UNFILTERED
+static uint32_t smoothing_timer = 0;
+#endif
-// This smoothing is 40 keystrokes
-static const float wpm_smoothing = WPM_SMOOTHING;
+/* The WPM calculation works by specifying a certain number of 'periods' inside
+ * a ring buffer, and we count the number of keypresses which occur in each of
+ * those periods. Then to calculate WPM, we add up all of the keypresses in
+ * the whole ring buffer, divide by the number of keypresses in a 'word', and
+ * then adjust for how much time is captured by our ring buffer. Right now
+ * the ring buffer is hardcoded below to be six half-second periods, accounting
+ * for a total WPM sampling period of up to three seconds of typing.
+ *
+ * Whenever our WPM drops to absolute zero due to no typing occurring within
+ * any contiguous three seconds, we reset and start measuring fresh,
+ * which lets our WPM immediately reach the correct value even before a full
+ * three second sampling buffer has been filled.
+ */
+#define MAX_PERIODS (WPM_SAMPLE_PERIODS)
+#define PERIOD_DURATION (1000 * WPM_SAMPLE_SECONDS / MAX_PERIODS)
+#define LATENCY (100)
+static int8_t period_presses[MAX_PERIODS] = {0};
+static uint8_t current_period = 0;
+static uint8_t periods = 1;
-void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; }
+#if !defined(WPM_UNFILTERED)
+static uint8_t prev_wpm = 0;
+static uint8_t next_wpm = 0;
+#endif
+void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; }
uint8_t get_current_wpm(void) { return current_wpm; }
bool wpm_keycode(uint16_t keycode) { return wpm_keycode_kb(keycode); }
@@ -56,7 +80,7 @@ __attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) {
} else if (keycode > 0xFF) {
keycode = 0;
}
- if (keycode == KC_DEL || keycode == KC_BSPC) {
+ if (keycode == KC_DELETE || keycode == KC_BACKSPACE) {
if (((get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) || weak_modded) {
return WPM_ESTIMATED_WORD_SIZE;
} else {
@@ -68,33 +92,65 @@ __attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) {
}
#endif
+// Outside 'raw' mode we smooth results over time.
+
void update_wpm(uint16_t keycode) {
if (wpm_keycode(keycode)) {
- if (wpm_timer > 0) {
- uint16_t latest_wpm = 60000 / timer_elapsed(wpm_timer) / WPM_ESTIMATED_WORD_SIZE;
- if (latest_wpm > UINT8_MAX) {
- latest_wpm = UINT8_MAX;
- }
- current_wpm += ceilf((latest_wpm - current_wpm) * wpm_smoothing);
- }
- wpm_timer = timer_read();
+ period_presses[current_period]++;
}
#ifdef WPM_ALLOW_COUNT_REGRESSION
uint8_t regress = wpm_regress_count(keycode);
if (regress) {
- if (current_wpm < regress) {
- current_wpm = 0;
- } else {
- current_wpm -= regress;
- }
- wpm_timer = timer_read();
+ period_presses[current_period]--;
}
#endif
}
void decay_wpm(void) {
- if (timer_elapsed(wpm_timer) > 1000) {
- current_wpm += (-current_wpm) * wpm_smoothing;
- wpm_timer = timer_read();
+ int32_t presses = period_presses[0];
+ for (int i = 1; i <= periods; i++) {
+ presses += period_presses[i];
+ }
+ if (presses < 0) {
+ presses = 0;
}
+ int32_t elapsed = timer_elapsed32(wpm_timer);
+ uint32_t duration = (((periods)*PERIOD_DURATION) + elapsed);
+ uint32_t wpm_now = (60000 * presses) / (duration * WPM_ESTIMATED_WORD_SIZE);
+ wpm_now = (wpm_now > 240) ? 240 : wpm_now;
+
+ if (elapsed > PERIOD_DURATION) {
+ current_period = (current_period + 1) % MAX_PERIODS;
+ period_presses[current_period] = 0;
+ periods = (periods < MAX_PERIODS - 1) ? periods + 1 : MAX_PERIODS - 1;
+ elapsed = 0;
+ /* if (wpm_timer == 0) { */
+ wpm_timer = timer_read32();
+ /* } else { */
+ /* wpm_timer += PERIOD_DURATION; */
+ /* } */
+ }
+ if (presses < 2) // don't guess high WPM based on a single keypress.
+ wpm_now = 0;
+
+#if defined WPM_LAUNCH_CONTROL
+ if (presses == 0) {
+ current_period = 0;
+ periods = 0;
+ wpm_now = 0;
+ }
+#endif // WPM_LAUNCH_CONTROL
+
+#ifndef WPM_UNFILTERED
+ int32_t latency = timer_elapsed32(smoothing_timer);
+ if (latency > LATENCY) {
+ smoothing_timer = timer_read32();
+ prev_wpm = current_wpm;
+ next_wpm = wpm_now;
+ }
+
+ current_wpm = prev_wpm + (latency * ((int)next_wpm - (int)prev_wpm) / LATENCY);
+#else
+ current_wpm = wpm_now;
+#endif
}
diff --git a/quantum/wpm.h b/quantum/wpm.h
index 4af52d2b98..c8e7d26684 100644
--- a/quantum/wpm.h
+++ b/quantum/wpm.h
@@ -22,8 +22,11 @@
#ifndef WPM_ESTIMATED_WORD_SIZE
# define WPM_ESTIMATED_WORD_SIZE 5
#endif
-#ifndef WPM_SMOOTHING
-# define WPM_SMOOTHING 0.0487
+#ifndef WPM_SAMPLE_SECONDS
+# define WPM_SAMPLE_SECONDS 5
+#endif
+#ifndef WPM_SAMPLE_PERIODS
+# define WPM_SAMPLE_PERIODS 50
#endif
bool wpm_keycode(uint16_t keycode);