From c754f644dcccc44e09a3e6f9986ad70ec2fc3b54 Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Fri, 2 Jun 2023 17:46:04 -0400 Subject: [Core] Move dynamic macro "stop recording" logic to a function (#21108) --- quantum/process_keycode/process_dynamic_macro.c | 117 +++++++++++++----------- quantum/process_keycode/process_dynamic_macro.h | 1 + 2 files changed, 63 insertions(+), 55 deletions(-) (limited to 'quantum/process_keycode') diff --git a/quantum/process_keycode/process_dynamic_macro.c b/quantum/process_keycode/process_dynamic_macro.c index bf6af566e2..a022949d3d 100644 --- a/quantum/process_keycode/process_dynamic_macro.c +++ b/quantum/process_keycode/process_dynamic_macro.c @@ -151,6 +151,67 @@ void dynamic_macro_record_end(keyrecord_t *macro_buffer, keyrecord_t *macro_poin *macro_end = macro_pointer; } +/* Both macros use the same buffer but read/write on different + * ends of it. + * + * Macro1 is written left-to-right starting from the beginning of + * the buffer. + * + * Macro2 is written right-to-left starting from the end of the + * buffer. + * + * ¯o_buffer macro_end + * v v + * +------------------------------------------------------------+ + * |>>>>>> MACRO1 >>>>>> <<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| + * +------------------------------------------------------------+ + * ^ ^ + * r_macro_end r_macro_buffer + * + * During the recording when one macro encounters the end of the + * other macro, the recording is stopped. Apart from this, there + * are no arbitrary limits for the macros' length in relation to + * each other: for example one can either have two medium sized + * macros or one long macro and one short macro. Or even one empty + * and one using the whole buffer. + */ +static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE]; + +/* Pointer to the first buffer element after the first macro. + * Initially points to the very beginning of the buffer since the + * macro is empty. */ +static keyrecord_t *macro_end = macro_buffer; + +/* The other end of the macro buffer. Serves as the beginning of + * the second macro. */ +static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1; + +/* Like macro_end but for the second macro. */ +static keyrecord_t *r_macro_end = r_macro_buffer; + +/* A persistent pointer to the current macro position (iterator) + * used during the recording. */ +static keyrecord_t *macro_pointer = NULL; + +/* 0 - no macro is being recorded right now + * 1,2 - either macro 1 or 2 is being recorded */ +static uint8_t macro_id = 0; + +/** + * If a dynamic macro is currently being recorded, stop recording. + */ +void dynamic_macro_stop_recording(void) { + switch (macro_id) { + case 1: + dynamic_macro_record_end(macro_buffer, macro_pointer, +1, ¯o_end); + break; + case 2: + dynamic_macro_record_end(r_macro_buffer, macro_pointer, -1, &r_macro_end); + break; + } + macro_id = 0; +} + /* Handle the key events related to the dynamic macros. Should be * called from process_record_user() like this: * @@ -162,52 +223,6 @@ void dynamic_macro_record_end(keyrecord_t *macro_buffer, keyrecord_t *macro_poin * } */ bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) { - /* Both macros use the same buffer but read/write on different - * ends of it. - * - * Macro1 is written left-to-right starting from the beginning of - * the buffer. - * - * Macro2 is written right-to-left starting from the end of the - * buffer. - * - * ¯o_buffer macro_end - * v v - * +------------------------------------------------------------+ - * |>>>>>> MACRO1 >>>>>> <<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| - * +------------------------------------------------------------+ - * ^ ^ - * r_macro_end r_macro_buffer - * - * During the recording when one macro encounters the end of the - * other macro, the recording is stopped. Apart from this, there - * are no arbitrary limits for the macros' length in relation to - * each other: for example one can either have two medium sized - * macros or one long macro and one short macro. Or even one empty - * and one using the whole buffer. - */ - static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE]; - - /* Pointer to the first buffer element after the first macro. - * Initially points to the very beginning of the buffer since the - * macro is empty. */ - static keyrecord_t *macro_end = macro_buffer; - - /* The other end of the macro buffer. Serves as the beginning of - * the second macro. */ - static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1; - - /* Like macro_end but for the second macro. */ - static keyrecord_t *r_macro_end = r_macro_buffer; - - /* A persistent pointer to the current macro position (iterator) - * used during the recording. */ - static keyrecord_t *macro_pointer = NULL; - - /* 0 - no macro is being recorded right now - * 1,2 - either macro 1 or 2 is being recorded */ - static uint8_t macro_id = 0; - if (macro_id == 0) { /* No macro recording in progress. */ if (!record->event.pressed) { @@ -238,15 +253,7 @@ bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed ^ (keycode != QK_DYNAMIC_MACRO_RECORD_STOP)) { /* Ignore the initial release * just after the recording * starts for DM_RSTP. */ - switch (macro_id) { - case 1: - dynamic_macro_record_end(macro_buffer, macro_pointer, +1, ¯o_end); - break; - case 2: - dynamic_macro_record_end(r_macro_buffer, macro_pointer, -1, &r_macro_end); - break; - } - macro_id = 0; + dynamic_macro_stop_recording(); } return false; #ifdef DYNAMIC_MACRO_NO_NESTING diff --git a/quantum/process_keycode/process_dynamic_macro.h b/quantum/process_keycode/process_dynamic_macro.h index ab70726897..9841254af4 100644 --- a/quantum/process_keycode/process_dynamic_macro.h +++ b/quantum/process_keycode/process_dynamic_macro.h @@ -39,3 +39,4 @@ void dynamic_macro_record_start_user(int8_t direction); void dynamic_macro_play_user(int8_t direction); void dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record); void dynamic_macro_record_end_user(int8_t direction); +void dynamic_macro_stop_recording(void); -- cgit v1.2.3 From edaf6654143fdd2dffaaa9c3ba8db1c9b282b5d0 Mon Sep 17 00:00:00 2001 From: Pablo Martínez Date: Sun, 4 Jun 2023 03:11:54 +0200 Subject: [Enhancement] Decouple autocorrect logic (#21116) --- quantum/process_keycode/process_autocorrect.c | 19 ++++++++++++++++++- quantum/process_keycode/process_autocorrect.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'quantum/process_keycode') diff --git a/quantum/process_keycode/process_autocorrect.c b/quantum/process_keycode/process_autocorrect.c index 1376788266..7c9cb814e5 100644 --- a/quantum/process_keycode/process_autocorrect.c +++ b/quantum/process_keycode/process_autocorrect.c @@ -57,7 +57,7 @@ void autocorrect_toggle(void) { } /** - * @brief handler for determining if autocorrect should process keypress + * @brief handler for user to override whether autocorrect should process this keypress * * @param keycode Keycode registered by matrix press, per keymap * @param record keyrecord_t structure @@ -67,6 +67,23 @@ void autocorrect_toggle(void) { * @return false Stop processing and escape from autocorrect. */ __attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) { + return process_autocorrect_default_handler(keycode, record, typo_buffer_size, mods); +} + +/** + * @brief fallback handler for determining if autocorrect should process this keypress + * can be used by user callback to get the basic keycode being "wrapped" + * + * NOTE: These values may have been edited by user callback before getting here + * + * @param keycode Keycode registered by matrix press, per keymap + * @param record keyrecord_t structure + * @param typo_buffer_size passed along to allow resetting of autocorrect buffer + * @param mods allow processing of mod status + * @return true Allow autocorection + * @return false Stop processing and escape from autocorrect. + */ +bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) { // See quantum_keycodes.h for reference on these matched ranges. switch (*keycode) { // Exclude these keycodes from processing. diff --git a/quantum/process_keycode/process_autocorrect.h b/quantum/process_keycode/process_autocorrect.h index c7596107e5..00dacbf958 100644 --- a/quantum/process_keycode/process_autocorrect.h +++ b/quantum/process_keycode/process_autocorrect.h @@ -9,6 +9,7 @@ bool process_autocorrect(uint16_t keycode, keyrecord_t *record); bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); +bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); bool apply_autocorrect(uint8_t backspaces, const char *str); bool autocorrect_is_enabled(void); -- cgit v1.2.3 From e9ff66d8ad341917ff270c9f33b83d86fe0fb6c4 Mon Sep 17 00:00:00 2001 From: Chris Salch Date: Fri, 7 Jul 2023 06:52:24 -0500 Subject: Adds a way to separate tab from AUTO_SHIFT_SPECIAL. (#20996) --- docs/feature_auto_shift.md | 47 +++++++++++++++++++++++++--- quantum/process_keycode/process_auto_shift.c | 10 +++++- quantum/process_keycode/process_auto_shift.h | 8 +++-- 3 files changed, 58 insertions(+), 7 deletions(-) (limited to 'quantum/process_keycode') diff --git a/docs/feature_auto_shift.md b/docs/feature_auto_shift.md index 1719807e26..6241cbaeb1 100644 --- a/docs/feature_auto_shift.md +++ b/docs/feature_auto_shift.md @@ -133,7 +133,17 @@ groups in the below fallback switch. ### NO_AUTO_SHIFT_SPECIAL (simple define) Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>, -and /? +/?, and the KC_TAB. + +### NO_AUTO_SHIFT_TAB (simple define) + +Do not Auto Shift KC_TAB but leave Auto Shift enabled for the other special +characters. + +### NO_AUTO_SHIFT_SYMBOLS (simple define) + +Do not Auto Shift symbol keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>, +and /?. ### NO_AUTO_SHIFT_NUMERIC (simple define) @@ -143,9 +153,13 @@ Do not Auto Shift numeric keys, zero through nine. Do not Auto Shift alpha characters, which include A through Z. +### AUTO_SHIFT_ENTER (simple define) + +Auto Shift the enter key. + ### Auto Shift Per Key -There are functions that allows you to determine which keys shold be autoshifted, much like the tap-hold keys. +There are functions that allows you to determine which keys should be autoshifted, much like the tap-hold keys. The first of these, used to simply add a key to Auto Shift, is `get_custom_auto_shifted_key`: @@ -172,9 +186,15 @@ bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { case KC_1 ... KC_0: # endif # ifndef NO_AUTO_SHIFT_SPECIAL +# ifndef NO_AUTO_SHIFT_TAB case KC_TAB: - case KC_MINUS ... KC_SLASH: - case KC_NONUS_BACKSLASH: +# endif +# ifndef NO_AUTO_SHIFT_SYMBOLS + case AUTO_SHIFT_SYMBOLS: +# endif +# endif +# ifdef AUTO_SHIFT_ENTER + case KC_ENT: # endif return true; } @@ -192,6 +212,25 @@ Enables keyrepeat. Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded. + +### AUTO_SHIFT_ALPHA (predefined key group) + +A predefined group of keys representing A through Z. + +### AUTO_SHIFT_NUMERIC (predefined key group) + +A predefined group of keys representing 0 through 9. Note, these are defined as +1 through 0 since that is the order they normally appear in. + +### AUTO_SHIFT_SYMBOLS (predefined key group) + +A predefined group of keys representing symbolic characters which include -\_, =+, [{, ]}, ;:, '", ,<, .>, +and /?. + +### AUTO_SHIFT_SPECIAL (predefined key group) + +A predefined group of keys that combines AUTO_SHIFT_SYMBOLS and KC_TAB. + ## Custom Shifted Values Especially on small keyboards, the default shifted value for many keys is not diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c index 62c347ae0c..63e893fc18 100644 --- a/quantum/process_keycode/process_auto_shift.c +++ b/quantum/process_keycode/process_auto_shift.c @@ -75,7 +75,15 @@ __attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *r case AUTO_SHIFT_NUMERIC: # endif # ifndef NO_AUTO_SHIFT_SPECIAL - case AUTO_SHIFT_SPECIAL: +# ifndef NO_AUTO_SHIFT_TAB + case KC_TAB: +# endif +# ifndef NO_AUTO_SHIFT_SYMBOLS + case AUTO_SHIFT_SYMBOLS: +# endif +# endif +# ifdef AUTO_SHIFT_ENTER + case KC_ENT: # endif return true; } diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h index 66a4b3138a..780177d2ff 100644 --- a/quantum/process_keycode/process_auto_shift.h +++ b/quantum/process_keycode/process_auto_shift.h @@ -28,10 +28,14 @@ // clang-format off #define AUTO_SHIFT_ALPHA KC_A ... KC_Z #define AUTO_SHIFT_NUMERIC KC_1 ... KC_0 +#define AUTO_SHIFT_SYMBOLS \ + KC_MINUS ... KC_SLASH: \ + case KC_NONUS_BACKSLASH + +// Kept to avoid breaking existing keymaps. #define AUTO_SHIFT_SPECIAL \ KC_TAB: \ - case KC_MINUS ... KC_SLASH: \ - case KC_NONUS_BACKSLASH + case AUTO_SHIFT_SYMBOLS // clang-format on bool process_auto_shift(uint16_t keycode, keyrecord_t *record); -- cgit v1.2.3 From 55295ed3dc5000d4c9937602624060c168753434 Mon Sep 17 00:00:00 2001 From: Pablo Martínez Date: Fri, 7 Jul 2023 16:13:15 +0200 Subject: [Enhancement] More info on `apply_autocorrect` (#21056) Co-authored-by: Drashna Jaelre --- docs/feature_autocorrect.md | 13 +++++-- quantum/process_keycode/process_autocorrect.c | 55 +++++++++++++++++++++++++-- quantum/process_keycode/process_autocorrect.h | 3 +- users/drashna/drashna.c | 2 +- 4 files changed, 64 insertions(+), 9 deletions(-) (limited to 'quantum/process_keycode') diff --git a/docs/feature_autocorrect.md b/docs/feature_autocorrect.md index 9f80c93f82..3a0a49095c 100644 --- a/docs/feature_autocorrect.md +++ b/docs/feature_autocorrect.md @@ -198,7 +198,9 @@ bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *t ### Apply Autocorrect -Additionally, `apply_autocorrect(uint8_t backspaces, const char *str)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word). +Additionally, `apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct)` allows for users to add additional handling to the autocorrection, or replace the functionality entirely. This passes on the number of backspaces needed to replace the words, as well as the replacement string (partial word, not the full word), and the typo and corrected strings (complete words). + +?> Due to the way code works (no notion of words, just a stream of letters), the `typo` and `correct` strings are a best bet and could be "wrong". For example you may get `wordtpyo` & `wordtypo` instead of the expected `tpyo` & `typo`. #### Apply Autocorrect Example @@ -209,7 +211,7 @@ This following example will play a sound when a typo is autocorrected and execut float autocorrect_song[][2] = SONG(TERMINAL_SOUND); #endif -bool apply_autocorrect(uint8_t backspaces, const char *str) { +bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) { #ifdef AUDIO_ENABLE PLAY_SONG(autocorrect_song); #endif @@ -223,14 +225,17 @@ bool apply_autocorrect(uint8_t backspaces, const char *str) { ?> In this callback function, `return false` will stop the normal processing of autocorrect, which requires manually handling of removing the "bad" characters and typing the new characters. -!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` or `SEND_STRING`. +!> ***IMPORTANT***: `str` is a pointer to `PROGMEM` data for the autocorrection. If you return false, and want to send the string, this needs to use `send_string_P` and not `send_string` nor `SEND_STRING`. You can also use `apply_autocorrect` to detect and display the event but allow internal code to execute the autocorrection with `return true`: ```c -bool apply_autocorrect(uint8_t backspaces, const char *str) { +bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) { #ifdef OLED_ENABLE oled_write_P(PSTR("Auto-corrected"), false); +#endif +#ifdef CONSOLE_ENABLE + printf("'%s' was corrected to '%s'\n", typo, correct); #endif return true; } diff --git a/quantum/process_keycode/process_autocorrect.c b/quantum/process_keycode/process_autocorrect.c index 7c9cb814e5..cc1f19e4f9 100644 --- a/quantum/process_keycode/process_autocorrect.c +++ b/quantum/process_keycode/process_autocorrect.c @@ -1,5 +1,6 @@ // Copyright 2021 Google LLC // Copyright 2021 @filterpaper +// Copyright 2023 Pablo Martinez (@elpekenin) // SPDX-License-Identifier: Apache-2.0 // Original source: https://getreuer.info/posts/keyboards/autocorrection @@ -174,10 +175,12 @@ bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, * * @param backspaces number of characters to remove * @param str pointer to PROGMEM string to replace mistyped seletion with + * @param typo the wrong string that triggered a correction + * @param correct what it would become after the changes * @return true apply correction * @return false user handled replacement */ -__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) { +__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) { return true; } @@ -301,11 +304,57 @@ bool process_autocorrect(uint16_t keycode, keyrecord_t *record) { if (code & 128) { // A typo was found! Apply autocorrect. const uint8_t backspaces = (code & 63) + !record->event.pressed; - if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) { + const char * changes = (const char *)(autocorrect_data + state + 1); + + /* Gather info about the typo'd word + * + * Since buffer may contain several words, delimited by spaces, we + * iterate from the end to find the start and length of the typo + */ + char typo[AUTOCORRECT_MAX_LENGTH + 1] = {0}; // extra char for null terminator + + uint8_t typo_len = 0; + uint8_t typo_start = 0; + bool space_last = typo_buffer[typo_buffer_size - 1] == KC_SPC; + for (uint8_t i = typo_buffer_size; i > 0; --i) { + // stop counting after finding space (unless it is the last thing) + if (typo_buffer[i - 1] == KC_SPC && i != typo_buffer_size) { + typo_start = i; + break; + } + + ++typo_len; + } + + // when detecting 'typo:', reduce the length of the string by one + if (space_last) { + --typo_len; + } + + // convert buffer of keycodes into a string + for (uint8_t i = 0; i < typo_len; ++i) { + typo[i] = typo_buffer[typo_start + i] - KC_A + 'a'; + } + + /* Gather the corrected word + * + * A) Correction of 'typo:' -- Code takes into account + * an extra backspace to delete the space (which we dont copy) + * for this reason the offset is correct to "skip" the null terminator + * + * B) When correcting 'typo' -- Need extra offset for terminator + */ + char correct[AUTOCORRECT_MAX_LENGTH + 10] = {0}; // let's hope this is big enough + + uint8_t offset = space_last ? backspaces : backspaces + 1; + strcpy(correct, typo); + strcpy_P(correct + typo_len - offset, changes); + + if (apply_autocorrect(backspaces, changes, typo, correct)) { for (uint8_t i = 0; i < backspaces; ++i) { tap_code(KC_BSPC); } - send_string_P((char const *)(autocorrect_data + state + 1)); + send_string_P(changes); } if (keycode == KC_SPC) { diff --git a/quantum/process_keycode/process_autocorrect.h b/quantum/process_keycode/process_autocorrect.h index 00dacbf958..9cc7d46a8b 100644 --- a/quantum/process_keycode/process_autocorrect.h +++ b/quantum/process_keycode/process_autocorrect.h @@ -1,5 +1,6 @@ // Copyright 2021 Google LLC // Copyright 2021 @filterpaper +// Copyright 2023 Pablo Martinez (@elpekenin) // SPDX-License-Identifier: Apache-2.0 // Original source: https://getreuer.info/posts/keyboards/autocorrection @@ -10,7 +11,7 @@ bool process_autocorrect(uint16_t keycode, keyrecord_t *record); bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); -bool apply_autocorrect(uint8_t backspaces, const char *str); +bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct); bool autocorrect_is_enabled(void); void autocorrect_enable(void); diff --git a/users/drashna/drashna.c b/users/drashna/drashna.c index cad6db8f3d..b8ccbb028c 100644 --- a/users/drashna/drashna.c +++ b/users/drashna/drashna.c @@ -141,7 +141,7 @@ float autocorrect_song[][2] = SONG(PLOVER_GOODBYE_SOUND); # endif # endif -bool apply_autocorrect(uint8_t backspaces, const char *str) { +bool apply_autocorrect(uint8_t backspaces, const char* str, char *typo, char *correct) { if (layer_state_is(_GAMEPAD)) { return false; } -- cgit v1.2.3 From 1abf8f3e8b8a9b358be3c27867f9bee7422507f3 Mon Sep 17 00:00:00 2001 From: precondition Date: Fri, 7 Jul 2023 16:18:02 +0200 Subject: [Feature] Send a dummy keycode to neutralize flashing modifiers in retro tap and key overrides (#20992) --- docs/feature_key_overrides.md | 27 +++ docs/tap_hold.md | 25 +++ quantum/action.c | 7 + quantum/action_util.c | 25 +++ quantum/action_util.h | 13 ++ quantum/process_keycode/process_key_override.c | 9 + .../tap_hold_configurations/retro_tapping/config.h | 5 +- .../retro_tapping/test_neutralization.cpp | 201 +++++++++++++++++++++ 8 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 tests/tap_hold_configurations/retro_tapping/test_neutralization.cpp (limited to 'quantum/process_keycode') diff --git a/docs/feature_key_overrides.md b/docs/feature_key_overrides.md index 608eb001e4..ec7efd4c01 100644 --- a/docs/feature_key_overrides.md +++ b/docs/feature_key_overrides.md @@ -225,3 +225,30 @@ The duration of the key repeat delay is controlled with the `KEY_OVERRIDE_REPEAT ## Difference to Combos :id=difference-to-combos Note that key overrides are very different from [combos](https://docs.qmk.fm/#/feature_combo). Combos require that you press down several keys almost _at the same time_ and can work with any combination of non-modifier keys. Key overrides work like keyboard shortcuts (e.g. `ctrl` + `z`): They take combinations of _multiple_ modifiers and _one_ non-modifier key to then perform some custom action. Key overrides are implemented with much care to behave just like normal keyboard shortcuts would in regards to the order of pressed keys, timing, and interacton with other pressed keys. There are a number of optional settings that can be used to really fine-tune the behavior of each key override as well. Using key overrides also does not delay key input for regular key presses, which inherently happens in combos and may be undesirable. + +## Solution to the problem of flashing modifiers :id=neutralize-flashing-modifiers + +If the programs you use bind an action to taps of modifier keys (e.g. tapping left GUI to bring up the applications menu or tapping left Alt to focus the menu bar), you may find that using key overrides with suppressed mods falsely triggers those actions. To counteract this, you can define a `DUMMY_MOD_NEUTRALIZER_KEYCODE` in `config.h` that will get sent in between the register and unregister events of a suppressed modifier. That way, the programs on your computer will no longer interpret the mod suppression induced by key overrides as a lone tap of a modifier key and will thus not falsely trigger the undesired action. + +Naturally, for this technique to be effective, you must choose a `DUMMY_MOD_NEUTRALIZER_KEYCODE` for which no keyboard shortcuts are bound to. Recommended values are: `KC_RIGHT_CTRL` or `KC_F18`. +Please note that `DUMMY_MOD_NEUTRALIZER_KEYCODE` must be a basic, unmodified, HID keycode so values like `KC_NO`, `KC_TRANSPARENT` or `KC_PIPE` aka `S(KC_BACKSLASH)` are not permitted. + +By default, only left Alt and left GUI are neutralized. If you want to change the list of applicable modifier masks, use the following in your `config.h`: + +```c +#define MODS_TO_NEUTRALIZE { , , ... } +``` + +Examples: + +```c +#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RIGHT_CTRL + +// Neutralize left alt and left GUI (Default value) +#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI) } + +// Neutralize left alt, left GUI, right GUI and left Control+Shift +#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI), MOD_BIT(KC_RIGHT_GUI), MOD_BIT(KC_LEFT_CTRL)|MOD_BIT(KC_LEFT_SHIFT) } +``` + +!> Do not use `MOD_xxx` constants like `MOD_LSFT` or `MOD_RALT`, since they're 5-bit packed bit-arrays while `MODS_TO_NEUTRALIZE` expects a list of 8-bit packed bit-arrays. Use `MOD_BIT()` or `MOD_MASK_xxx` instead. diff --git a/docs/tap_hold.md b/docs/tap_hold.md index c50acdb84d..094a10753a 100644 --- a/docs/tap_hold.md +++ b/docs/tap_hold.md @@ -460,6 +460,31 @@ bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { } ``` +If the programs you use bind an action to taps of modifier keys (e.g. tapping left GUI to bring up the applications menu or tapping left Alt to focus the menu bar), you may find that using retro-tapping falsely triggers those actions. To counteract this, you can define a `DUMMY_MOD_NEUTRALIZER_KEYCODE` in `config.h` that will get sent in between the register and unregister events of a held mod-tap key. That way, the programs on your computer will no longer interpret the mod suppression induced by retro-tapping as a lone tap of a modifier key and will thus not falsely trigger the undesired action. + +Naturally, for this technique to be effective, you must choose a `DUMMY_MOD_NEUTRALIZER_KEYCODE` for which no keyboard shortcuts are bound to. Recommended values are: `KC_RIGHT_CTRL` or `KC_F18`. +Please note that `DUMMY_MOD_NEUTRALIZER_KEYCODE` must be a basic, unmodified, HID keycode so values like `KC_NO`, `KC_TRANSPARENT` or `KC_PIPE` aka `S(KC_BACKSLASH)` are not permitted. + +By default, only left Alt and left GUI are neutralized. If you want to change the list of applicable modifier masks, use the following in your `config.h`: + +```c +#define MODS_TO_NEUTRALIZE { , , ... } +``` + +Examples: + +```c +#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RIGHT_CTRL + +// Neutralize left alt and left GUI (Default value) +#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI) } + +// Neutralize left alt, left GUI, right GUI and left Control+Shift +#define MODS_TO_NEUTRALIZE { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI), MOD_BIT(KC_RIGHT_GUI), MOD_BIT(KC_LEFT_CTRL)|MOD_BIT(KC_LEFT_SHIFT) } +``` + +!> Do not use `MOD_xxx` constants like `MOD_LSFT` or `MOD_RALT`, since they're 5-bit packed bit-arrays while `MODS_TO_NEUTRALIZE` expects a list of 8-bit packed bit-arrays. Use `MOD_BIT()` or `MOD_MASK_xxx` instead. + ### Retro Shift [Auto Shift,](feature_auto_shift.md) has its own version of `retro tapping` called `retro shift`. It is extremely similar to `retro tapping`, but holding the key past `AUTO_SHIFT_TIMEOUT` results in the value it sends being shifted. Other configurations also affect it differently; see [here](feature_auto_shift.md#retro-shift) for more information. diff --git a/quantum/action.c b/quantum/action.c index 84ecf6da9a..6368f7398c 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -528,6 +528,13 @@ void process_action(keyrecord_t *record, action_t action) { unregister_code(action.key.code); } else { ac_dprintf("MODS_TAP: No tap: add_mods\n"); +# if defined(RETRO_TAPPING) && defined(DUMMY_MOD_NEUTRALIZER_KEYCODE) + // Send a dummy keycode to neutralize flashing modifiers + // if the key was held and then released with no interruptions. + if (retro_tapping_counter == 2) { + neutralize_flashing_modifiers(get_mods()); + } +# endif unregister_mods(mods); } } diff --git a/quantum/action_util.c b/quantum/action_util.c index 361f410d2d..909dea0595 100644 --- a/quantum/action_util.c +++ b/quantum/action_util.c @@ -500,3 +500,28 @@ __attribute__((weak)) void oneshot_layer_changed_kb(uint8_t layer) { uint8_t has_anymod(void) { return bitpop(real_mods); } + +#ifdef DUMMY_MOD_NEUTRALIZER_KEYCODE +/** \brief Send a dummy keycode in between the register and unregister event of a modifier key, to neutralize the "flashing modifiers" phenomenon. + * + * \param active_mods 8-bit packed bit-array describing the currently active modifiers (in the format GASCGASC). + * + * Certain QMK features like key overrides or retro tap must unregister a previously + * registered modifier before sending another keycode but this can trigger undesired + * keyboard shortcuts if the clean tap of a single modifier key is bound to an action + * on the host OS, as is for example the case for the left GUI key on Windows, which + * opens the Start Menu when tapped. + */ +void neutralize_flashing_modifiers(uint8_t active_mods) { + // In most scenarios, the flashing modifiers phenomenon is a problem + // only for a subset of modifier masks. + const static uint8_t mods_to_neutralize[] = MODS_TO_NEUTRALIZE; + const static uint8_t n_mods = ARRAY_SIZE(mods_to_neutralize); + for (uint8_t i = 0; i < n_mods; ++i) { + if (active_mods == mods_to_neutralize[i]) { + tap_code(DUMMY_MOD_NEUTRALIZER_KEYCODE); + break; + } + } +} +#endif diff --git a/quantum/action_util.h b/quantum/action_util.h index 02f6e9e6df..831caf3c0a 100644 --- a/quantum/action_util.h +++ b/quantum/action_util.h @@ -102,6 +102,19 @@ void use_oneshot_swaphands(void); void clear_oneshot_swaphands(void); #endif +#ifdef DUMMY_MOD_NEUTRALIZER_KEYCODE +// KC_A is used as the lowerbound instead of QK_BASIC because the range QK_BASIC...KC_A includes +// internal keycodes like KC_NO and KC_TRANSPARENT which are unsuitable for use with `tap_code(kc)`. +# if !(KC_A <= DUMMY_MOD_NEUTRALIZER_KEYCODE && DUMMY_MOD_NEUTRALIZER_KEYCODE <= QK_BASIC_MAX) +# error "DUMMY_MOD_NEUTRALIZER_KEYCODE must be a basic, unmodified, HID keycode!" +# endif +void neutralize_flashing_modifiers(uint8_t active_mods); +#endif +#ifndef MODS_TO_NEUTRALIZE +# define MODS_TO_NEUTRALIZE \ + { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI) } +#endif + #ifdef __cplusplus } #endif diff --git a/quantum/process_keycode/process_key_override.c b/quantum/process_keycode/process_key_override.c index 17e490e67a..de628d3fec 100644 --- a/quantum/process_keycode/process_key_override.c +++ b/quantum/process_keycode/process_key_override.c @@ -322,6 +322,15 @@ static bool try_activating_override(const uint16_t keycode, const uint8_t layer, clear_active_override(false); +#ifdef DUMMY_MOD_NEUTRALIZER_KEYCODE + // Send a dummy keycode before unregistering the modifier(s) + // so that suppressing the modifier(s) doesn't falsely get interpreted + // by the host OS as a tap of a modifier key. + // For example, unintended activations of the start menu on Windows when + // using a GUI+ key override with suppressed mods. + neutralize_flashing_modifiers(active_mods); +#endif + active_override = override; active_override_trigger_is_down = true; diff --git a/tests/tap_hold_configurations/retro_tapping/config.h b/tests/tap_hold_configurations/retro_tapping/config.h index 4b38f2644b..cc9f162477 100644 --- a/tests/tap_hold_configurations/retro_tapping/config.h +++ b/tests/tap_hold_configurations/retro_tapping/config.h @@ -18,4 +18,7 @@ #include "test_common.h" -#define RETRO_TAPPING \ No newline at end of file +#define RETRO_TAPPING +#define DUMMY_MOD_NEUTRALIZER_KEYCODE KC_RIGHT_CTRL +#define MODS_TO_NEUTRALIZE \ + { MOD_BIT(KC_LEFT_GUI) } diff --git a/tests/tap_hold_configurations/retro_tapping/test_neutralization.cpp b/tests/tap_hold_configurations/retro_tapping/test_neutralization.cpp new file mode 100644 index 0000000000..10d675a3b1 --- /dev/null +++ b/tests/tap_hold_configurations/retro_tapping/test_neutralization.cpp @@ -0,0 +1,201 @@ +/* Copyright 2023 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 3 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 . + */ + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "action_tapping.h" +#include "test_keymap_key.hpp" + +using testing::_; +using testing::InSequence; + +class RetroTapNeutralization : public TestFixture {}; + +TEST_F(RetroTapNeutralization, neutralize_retro_tapped_left_gui_mod_tap) { + TestDriver driver; + InSequence s; + auto mod_tap_hold_key = KeymapKey(0, 7, 0, LGUI_T(KC_P)); + + set_keymap({mod_tap_hold_key}); + + EXPECT_NO_REPORT(driver); + mod_tap_hold_key.press(); + idle_for(TAPPING_TERM); + VERIFY_AND_CLEAR(driver); + + EXPECT_REPORT(driver, (KC_LGUI)); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + EXPECT_REPORT(driver, (DUMMY_MOD_NEUTRALIZER_KEYCODE, KC_LGUI)); + EXPECT_REPORT(driver, (KC_LGUI)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_hold_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); +} + +TEST_F(RetroTapNeutralization, do_not_neutralize_retro_tapped_left_shift_mod_tap) { + TestDriver driver; + InSequence s; + auto mod_tap_hold_key = KeymapKey(0, 7, 0, LSFT_T(KC_P)); + + set_keymap({mod_tap_hold_key}); + + EXPECT_NO_REPORT(driver); + mod_tap_hold_key.press(); + idle_for(TAPPING_TERM); + VERIFY_AND_CLEAR(driver); + + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_hold_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); +} + +TEST_F(RetroTapNeutralization, do_not_neutralize_retro_tapped_right_gui_mod_tap) { + TestDriver driver; + InSequence s; + auto mod_tap_hold_key = KeymapKey(0, 7, 0, RGUI_T(KC_P)); + + set_keymap({mod_tap_hold_key}); + + EXPECT_NO_REPORT(driver); + mod_tap_hold_key.press(); + idle_for(TAPPING_TERM); + VERIFY_AND_CLEAR(driver); + + EXPECT_REPORT(driver, (KC_RGUI)); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_hold_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); +} + +TEST_F(RetroTapNeutralization, do_not_neutralize_retro_tapped_left_gui_shift_mod_tap) { + TestDriver driver; + InSequence s; + auto mod_tap_hold_key = KeymapKey(0, 7, 0, MT(MOD_LGUI | MOD_LSFT, KC_P)); + + set_keymap({mod_tap_hold_key}); + + EXPECT_NO_REPORT(driver); + mod_tap_hold_key.press(); + idle_for(TAPPING_TERM); + VERIFY_AND_CLEAR(driver); + + EXPECT_REPORT(driver, (KC_LSFT, KC_LGUI)); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_hold_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); +} + +TEST_F(RetroTapNeutralization, do_not_neutralize_roll_of_regular_and_mod_tap_keys) { + TestDriver driver; + InSequence s; + auto mod_tap_hold_key = KeymapKey(0, 1, 0, LGUI_T(KC_P)); + auto regular_key = KeymapKey(0, 2, 0, KC_A); + + set_keymap({mod_tap_hold_key, regular_key}); + + /* Press mod-tap-hold key. */ + EXPECT_NO_REPORT(driver); + mod_tap_hold_key.press(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Press regular key. */ + EXPECT_NO_REPORT(driver); + regular_key.press(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Release regular key. */ + EXPECT_NO_REPORT(driver); + regular_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Release mod-tap-hold key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_P, KC_A)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_hold_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Idle for tapping term of mod tap hold key. */ + idle_for(TAPPING_TERM - 3); + VERIFY_AND_CLEAR(driver); +} + +TEST_F(RetroTapNeutralization, do_not_neutralize_tap_regular_key_while_mod_tap_is_held) { + TestDriver driver; + InSequence s; + auto mod_tap_hold_key = KeymapKey(0, 1, 0, LGUI_T(KC_P)); + auto regular_key = KeymapKey(0, 2, 0, KC_A); + + set_keymap({mod_tap_hold_key, regular_key}); + + /* Press and hold mod-tap key. */ + EXPECT_REPORT(driver, (KC_LEFT_GUI)); + mod_tap_hold_key.press(); + idle_for(TAPPING_TERM + 1); + VERIFY_AND_CLEAR(driver); + + /* Press regular key. */ + EXPECT_REPORT(driver, (KC_A, KC_LEFT_GUI)); + regular_key.press(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Release regular key. */ + EXPECT_REPORT(driver, (KC_LEFT_GUI)); + regular_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Release mod-tap-hold key. */ + EXPECT_EMPTY_REPORT(driver); + mod_tap_hold_key.release(); + run_one_scan_loop(); + VERIFY_AND_CLEAR(driver); + + /* Idle for tapping term of mod tap hold key. */ + idle_for(TAPPING_TERM - 3); + VERIFY_AND_CLEAR(driver); +} -- cgit v1.2.3 From eee0384167b965c60120e1222bc24c0b40cadac4 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 11 Jul 2023 17:07:24 +1000 Subject: process_keycode: remove direct `quantum.h` includes (#21486) --- quantum/action_layer.h | 1 + quantum/midi/qmk_midi.c | 4 + quantum/process_keycode/process_audio.h | 4 + quantum/process_keycode/process_auto_shift.c | 169 ++++++++++----------- quantum/process_keycode/process_auto_shift.h | 6 +- quantum/process_keycode/process_autocorrect.c | 4 + quantum/process_keycode/process_autocorrect.h | 4 +- quantum/process_keycode/process_backlight.h | 4 +- quantum/process_keycode/process_caps_word.c | 8 + quantum/process_keycode/process_caps_word.h | 5 +- quantum/process_keycode/process_clicky.h | 4 + quantum/process_keycode/process_combo.c | 11 +- quantum/process_keycode/process_combo.h | 6 +- quantum/process_keycode/process_dynamic_macro.c | 9 ++ quantum/process_keycode/process_dynamic_macro.h | 4 +- .../process_keycode/process_dynamic_tapping_term.c | 4 +- .../process_keycode/process_dynamic_tapping_term.h | 1 + quantum/process_keycode/process_grave_esc.c | 3 + quantum/process_keycode/process_grave_esc.h | 4 +- quantum/process_keycode/process_haptic.h | 1 + quantum/process_keycode/process_joystick.h | 3 +- quantum/process_keycode/process_key_lock.h | 4 +- quantum/process_keycode/process_key_override.c | 6 +- quantum/process_keycode/process_key_override.h | 3 +- quantum/process_keycode/process_leader.c | 1 + quantum/process_keycode/process_leader.h | 4 +- quantum/process_keycode/process_magic.c | 5 + quantum/process_keycode/process_magic.h | 4 +- quantum/process_keycode/process_midi.c | 26 ++-- quantum/process_keycode/process_midi.h | 5 +- quantum/process_keycode/process_music.c | 2 + quantum/process_keycode/process_music.h | 4 +- .../process_keycode/process_programmable_button.h | 3 +- quantum/process_keycode/process_repeat_key.c | 4 + quantum/process_keycode/process_repeat_key.h | 4 +- quantum/process_keycode/process_rgb.c | 8 + quantum/process_keycode/process_rgb.h | 4 +- quantum/process_keycode/process_secure.h | 1 + quantum/process_keycode/process_sequencer.h | 4 +- quantum/process_keycode/process_space_cadet.c | 2 + quantum/process_keycode/process_space_cadet.h | 4 +- quantum/process_keycode/process_steno.c | 1 + quantum/process_keycode/process_steno.h | 4 +- quantum/process_keycode/process_tap_dance.c | 7 + quantum/process_keycode/process_tap_dance.h | 43 +++--- quantum/process_keycode/process_tri_layer.h | 2 + 46 files changed, 258 insertions(+), 156 deletions(-) (limited to 'quantum/process_keycode') diff --git a/quantum/action_layer.h b/quantum/action_layer.h index ff783bb3e7..a2410d49a5 100644 --- a/quantum/action_layer.h +++ b/quantum/action_layer.h @@ -20,6 +20,7 @@ along with this program. If not, see . #include #include "keyboard.h" #include "action.h" +#include "bitwise.h" #ifdef DYNAMIC_KEYMAP_ENABLE # ifndef DYNAMIC_KEYMAP_LAYER_COUNT diff --git a/quantum/midi/qmk_midi.c b/quantum/midi/qmk_midi.c index f6a5d92281..688259784c 100644 --- a/quantum/midi/qmk_midi.c +++ b/quantum/midi/qmk_midi.c @@ -5,6 +5,10 @@ #include "usb_descriptor.h" #include "process_midi.h" +#ifdef AUDIO_ENABLE +# include "audio.h" +#endif + /******************************************************************************* * MIDI ******************************************************************************/ diff --git a/quantum/process_keycode/process_audio.h b/quantum/process_keycode/process_audio.h index 42cfab4af2..c80136f2c2 100644 --- a/quantum/process_keycode/process_audio.h +++ b/quantum/process_keycode/process_audio.h @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include "action.h" + float compute_freq_for_midi_note(uint8_t note); bool process_audio(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c index 63e893fc18..9b78214e43 100644 --- a/quantum/process_keycode/process_auto_shift.c +++ b/quantum/process_keycode/process_auto_shift.c @@ -14,27 +14,28 @@ * along with this program. If not, see . */ -#ifdef AUTO_SHIFT_ENABLE - -# include -# include "process_auto_shift.h" - -# ifndef AUTO_SHIFT_DISABLED_AT_STARTUP -# define AUTO_SHIFT_STARTUP_STATE true /* enabled */ -# else -# define AUTO_SHIFT_STARTUP_STATE false /* disabled */ -# endif +#include "process_auto_shift.h" +#include "quantum.h" +#include "action_util.h" +#include "timer.h" +#include "keycodes.h" + +#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) +#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 +#endif static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; static uint16_t autoshift_lastkey = KC_NO; static keyrecord_t autoshift_lastrecord; @@ -68,23 +69,23 @@ __attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyreco /** \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 +#ifndef NO_AUTO_SHIFT_ALPHA case AUTO_SHIFT_ALPHA: -# endif -# ifndef NO_AUTO_SHIFT_NUMERIC +#endif +#ifndef NO_AUTO_SHIFT_NUMERIC case AUTO_SHIFT_NUMERIC: -# endif -# ifndef NO_AUTO_SHIFT_SPECIAL -# ifndef NO_AUTO_SHIFT_TAB +#endif +#ifndef NO_AUTO_SHIFT_SPECIAL +# ifndef NO_AUTO_SHIFT_TAB case KC_TAB: -# endif -# ifndef NO_AUTO_SHIFT_SYMBOLS +# endif +# ifndef NO_AUTO_SHIFT_SYMBOLS case AUTO_SHIFT_SYMBOLS: -# endif # endif -# ifdef AUTO_SHIFT_ENTER +#endif +#ifdef AUTO_SHIFT_ENTER case KC_ENT: -# endif +#endif return true; } return get_custom_auto_shifted_key(keycode, record); @@ -130,9 +131,9 @@ bool get_autoshift_shift_state(uint16_t keycode) { /** \brief Restores the shift key if it was cancelled by Auto Shift */ static void autoshift_flush_shift(void) { autoshift_flags.holding_shift = false; -# ifdef CAPS_WORD_ENABLE +#ifdef CAPS_WORD_ENABLE if (!is_caps_word_on()) -# endif // CAPS_WORD_ENABLE +#endif // CAPS_WORD_ENABLE { del_weak_mods(MOD_BIT(KC_LSFT)); } @@ -154,26 +155,26 @@ static void autoshift_flush_shift(void) { static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) { // clang-format off if ((get_mods() -# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) | get_oneshot_mods() -# endif +#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 +#ifndef AUTO_SHIFT_MODIFIERS // 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) +# 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 + return false; +#endif } // Store record to be sent to user functions if there's no release record then. @@ -181,19 +182,19 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *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 defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY) if (keycode == autoshift_lastkey && -# ifdef AUTO_SHIFT_REPEAT_PER_KEY +# ifdef AUTO_SHIFT_REPEAT_PER_KEY get_auto_shift_repeat(autoshift_lastkey, record) && -# endif -# if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY) +# endif +# 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 +# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY || get_auto_shift_no_auto_repeat(autoshift_lastkey, record) -# endif - ) && # endif + ) && +# endif TIMER_DIFF_16(now, autoshift_time) < GET_TAPPING_TERM(autoshift_lastkey, record) ) { // clang-format on @@ -210,23 +211,23 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) 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) +#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 +#else autoshift_flags.lastshifted = get_mods() & MOD_BIT(KC_LSFT); -# endif +#endif // Record the keycode so we can simulate it later. autoshift_lastkey = keycode; autoshift_time = now; autoshift_flags.in_progress = true; -# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); -# endif +#endif return false; } @@ -247,11 +248,11 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, k autoshift_flags.lastshifted = autoshift_flags.lastshifted || TIMER_DIFF_16(now, autoshift_time) >= -# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY +#ifdef AUTO_SHIFT_TIMEOUT_PER_KEY get_autoshift_timeout(autoshift_lastkey, record) -# else +#else autoshift_timeout -# endif +#endif ; // clang-format on set_autoshift_shift_state(autoshift_lastkey, autoshift_flags.lastshifted); @@ -266,23 +267,23 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, k 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 (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 +# ifdef AUTO_SHIFT_REPEAT_PER_KEY && get_auto_shift_repeat(autoshift_lastkey, record) -# endif -# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY +# endif +# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY && !get_auto_shift_no_auto_repeat(autoshift_lastkey, record) -# endif +# endif ) { // Prevents release. return; } -# endif +#endif // clang-format on -# if TAP_CODE_DELAY > 0 +#if TAP_CODE_DELAY > 0 wait_ms(TAP_CODE_DELAY); -# endif +#endif autoshift_release_user(autoshift_lastkey, autoshift_flags.lastshifted, record); autoshift_flush_shift(); @@ -310,11 +311,11 @@ void autoshift_matrix_scan(void) { if (autoshift_flags.in_progress) { const uint16_t now = timer_read(); if (TIMER_DIFF_16(now, autoshift_time) >= -# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY +#ifdef AUTO_SHIFT_TIMEOUT_PER_KEY get_autoshift_timeout(autoshift_lastkey, &autoshift_lastrecord) -# else +#else autoshift_timeout -# endif +#endif ) { autoshift_end(autoshift_lastkey, now, true, &autoshift_lastrecord); } @@ -335,18 +336,18 @@ void autoshift_disable(void) { autoshift_flush_shift(); } -# ifndef AUTO_SHIFT_NO_SETUP +#ifndef AUTO_SHIFT_NO_SETUP void autoshift_timer_report(void) { -# ifdef SEND_STRING_ENABLE +# ifdef SEND_STRING_ENABLE const char *autoshift_timeout_str = get_u16_str(autoshift_timeout, ' '); // Skip padding spaces while (*autoshift_timeout_str == ' ') { autoshift_timeout_str++; } send_string(autoshift_timeout_str); -# endif -} # endif +} +#endif bool get_autoshift_state(void) { return autoshift_flags.enabled; @@ -368,11 +369,11 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { // https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550 // clang-format off const uint16_t now = -# if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING) +#if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING) timer_read() -# else +#else (record->event.pressed) ? retroshift_time : timer_read() -# endif +#endif ; // clang-format on @@ -393,7 +394,7 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { autoshift_disable(); break; -# ifndef AUTO_SHIFT_NO_SETUP +#ifndef AUTO_SHIFT_NO_SETUP case AS_UP: autoshift_timeout += 5; break; @@ -403,27 +404,27 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { case AS_RPT: autoshift_timer_report(); break; -# endif +#endif } // If Retro Shift is disabled, possible custom actions shouldn't happen. // clang-format off -# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) -# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY const bool is_hold_on_interrupt = get_hold_on_other_key_press(keycode, record); -# else +# else const bool is_hold_on_interrupt = false; -# endif -# endif +# endif +#endif if (IS_RETRO(keycode) -# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#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 +# ifdef RETRO_TAPPING_PER_KEY || !get_retro_tapping(keycode, record) -# endif - || (record->tap.interrupted && is_hold_on_interrupt)) # endif + || (record->tap.interrupted && is_hold_on_interrupt)) +#endif ) { // clang-format on autoshift_lastkey = KC_NO; @@ -439,21 +440,21 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { // 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) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) && ( record->tap.count == 0 -# ifdef RETRO_TAPPING_PER_KEY +# ifdef RETRO_TAPPING_PER_KEY || !get_retro_tapping(keycode, record) -# endif - ) # endif + ) +#endif ) { // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set. -# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +#ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY if (autoshift_flags.in_progress && get_hold_on_other_key_press(keycode, record)) { autoshift_end(KC_NO, now, false, &autoshift_lastrecord); } -# endif +#endif // clang-format on return true; } @@ -479,7 +480,7 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { return true; } -# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#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; @@ -493,6 +494,4 @@ void retroshift_swap_times(void) { last_retroshift_time = temp; } } -# endif - #endif diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h index 780177d2ff..885a47b533 100644 --- a/quantum/process_keycode/process_auto_shift.h +++ b/quantum/process_keycode/process_auto_shift.h @@ -16,7 +16,11 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" +#include "keyboard.h" +#include "keycodes.h" #ifndef AUTO_SHIFT_TIMEOUT # define AUTO_SHIFT_TIMEOUT 175 diff --git a/quantum/process_keycode/process_autocorrect.c b/quantum/process_keycode/process_autocorrect.c index cc1f19e4f9..edc47718f3 100644 --- a/quantum/process_keycode/process_autocorrect.c +++ b/quantum/process_keycode/process_autocorrect.c @@ -6,7 +6,11 @@ #include "process_autocorrect.h" #include +#include "keycodes.h" +#include "quantum_keycodes.h" #include "keycode_config.h" +#include "send_string.h" +#include "action_util.h" #if __has_include("autocorrect_data.h") # include "autocorrect_data.h" diff --git a/quantum/process_keycode/process_autocorrect.h b/quantum/process_keycode/process_autocorrect.h index 9cc7d46a8b..ea77d6f56f 100644 --- a/quantum/process_keycode/process_autocorrect.h +++ b/quantum/process_keycode/process_autocorrect.h @@ -6,7 +6,9 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" bool process_autocorrect(uint16_t keycode, keyrecord_t *record); bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); diff --git a/quantum/process_keycode/process_backlight.h b/quantum/process_keycode/process_backlight.h index 7fe887ae67..e926833e79 100644 --- a/quantum/process_keycode/process_backlight.h +++ b/quantum/process_keycode/process_backlight.h @@ -16,6 +16,8 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" bool process_backlight(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_caps_word.c b/quantum/process_keycode/process_caps_word.c index d4382680bf..1088c8f76c 100644 --- a/quantum/process_keycode/process_caps_word.c +++ b/quantum/process_keycode/process_caps_word.c @@ -13,6 +13,14 @@ // limitations under the License. #include "process_caps_word.h" +#include "process_auto_shift.h" +#include "caps_word.h" +#include "keycodes.h" +#include "quantum_keycodes.h" +#include "modifiers.h" +#include "timer.h" +#include "action_tapping.h" +#include "action_util.h" #ifdef CAPS_WORD_INVERT_ON_SHIFT static uint8_t held_mods = 0; diff --git a/quantum/process_keycode/process_caps_word.h b/quantum/process_keycode/process_caps_word.h index f215bbc3a3..f5eb140d32 100644 --- a/quantum/process_keycode/process_caps_word.h +++ b/quantum/process_keycode/process_caps_word.h @@ -14,8 +14,9 @@ #pragma once -#include "quantum.h" -#include "caps_word.h" +#include +#include +#include "action.h" /** * @brief Process handler for Caps Word feature. diff --git a/quantum/process_keycode/process_clicky.h b/quantum/process_keycode/process_clicky.h index 67b6463c5d..dfdba14131 100644 --- a/quantum/process_keycode/process_clicky.h +++ b/quantum/process_keycode/process_clicky.h @@ -1,5 +1,9 @@ #pragma once +#include +#include +#include "action.h" + void clicky_play(void); bool process_clicky(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index bbee560be9..0d4f4f3dba 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -14,11 +14,16 @@ * along with this program. If not, see . */ -#include "keymap_common.h" -#include "print.h" #include "process_combo.h" +#include +#include "process_auto_shift.h" +#include "caps_word.h" +#include "timer.h" +#include "keyboard.h" +#include "keymap_common.h" +#include "action_layer.h" #include "action_tapping.h" -#include "action.h" +#include "action_util.h" #include "keymap_introspection.h" __attribute__((weak)) void process_combo_event(uint16_t combo_index, bool pressed) {} diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h index bba5d5ee63..f1d534236e 100644 --- a/quantum/process_keycode/process_combo.h +++ b/quantum/process_keycode/process_combo.h @@ -16,9 +16,11 @@ #pragma once -#include "progmem.h" -#include "quantum.h" #include +#include +#include "action.h" +#include "keycodes.h" +#include "quantum_keycodes.h" #ifdef EXTRA_SHORT_COMBOS # define MAX_COMBO_LENGTH 6 diff --git a/quantum/process_keycode/process_dynamic_macro.c b/quantum/process_keycode/process_dynamic_macro.c index a022949d3d..5e4a6fa308 100644 --- a/quantum/process_keycode/process_dynamic_macro.c +++ b/quantum/process_keycode/process_dynamic_macro.c @@ -17,6 +17,15 @@ /* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */ #include "process_dynamic_macro.h" +#include +#include "action_layer.h" +#include "keycodes.h" +#include "debug.h" +#include "wait.h" + +#ifdef BACKLIGHT_ENABLE +# include "backlight.h" +#endif // default feedback method void dynamic_macro_led_blink(void) { diff --git a/quantum/process_keycode/process_dynamic_macro.h b/quantum/process_keycode/process_dynamic_macro.h index 9841254af4..2f10733cae 100644 --- a/quantum/process_keycode/process_dynamic_macro.h +++ b/quantum/process_keycode/process_dynamic_macro.h @@ -18,7 +18,9 @@ /* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" /* May be overridden with a custom value. Be aware that the effective * macro length is half of this value: each keypress is recorded twice diff --git a/quantum/process_keycode/process_dynamic_tapping_term.c b/quantum/process_keycode/process_dynamic_tapping_term.c index 146b9fccd7..cf52626e42 100644 --- a/quantum/process_keycode/process_dynamic_tapping_term.c +++ b/quantum/process_keycode/process_dynamic_tapping_term.c @@ -14,8 +14,10 @@ * along with this program. If not, see . */ -#include "quantum.h" #include "process_dynamic_tapping_term.h" +#include "quantum.h" +#include "keycodes.h" +#include "send_string.h" #ifndef DYNAMIC_TAPPING_TERM_INCREMENT # define DYNAMIC_TAPPING_TERM_INCREMENT 5 diff --git a/quantum/process_keycode/process_dynamic_tapping_term.h b/quantum/process_keycode/process_dynamic_tapping_term.h index 85e83ee73b..fee29e18df 100644 --- a/quantum/process_keycode/process_dynamic_tapping_term.h +++ b/quantum/process_keycode/process_dynamic_tapping_term.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include "action.h" diff --git a/quantum/process_keycode/process_grave_esc.c b/quantum/process_keycode/process_grave_esc.c index ddf027391d..d786f57a80 100644 --- a/quantum/process_keycode/process_grave_esc.c +++ b/quantum/process_keycode/process_grave_esc.c @@ -14,6 +14,9 @@ * along with this program. If not, see . */ #include "process_grave_esc.h" +#include "keycodes.h" +#include "modifiers.h" +#include "action_util.h" /* true if the last press of QK_GRAVE_ESCAPE was shifted (i.e. GUI or SHIFT were pressed), false otherwise. * Used to ensure that the correct keycode is released if the key is released. diff --git a/quantum/process_keycode/process_grave_esc.h b/quantum/process_keycode/process_grave_esc.h index bbf4483763..358ff3c4e7 100644 --- a/quantum/process_keycode/process_grave_esc.h +++ b/quantum/process_keycode/process_grave_esc.h @@ -15,6 +15,8 @@ */ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" bool process_grave_esc(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_haptic.h b/quantum/process_keycode/process_haptic.h index 6dbb0f014d..7e61f6c0d6 100644 --- a/quantum/process_keycode/process_haptic.h +++ b/quantum/process_keycode/process_haptic.h @@ -15,6 +15,7 @@ */ #pragma once +#include #include #include "action.h" diff --git a/quantum/process_keycode/process_joystick.h b/quantum/process_keycode/process_joystick.h index 1fb8757708..aa1a443271 100644 --- a/quantum/process_keycode/process_joystick.h +++ b/quantum/process_keycode/process_joystick.h @@ -17,6 +17,7 @@ #pragma once #include -#include "quantum.h" +#include +#include "action.h" bool process_joystick(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_key_lock.h b/quantum/process_keycode/process_key_lock.h index 5159b0ba02..858945a8e4 100644 --- a/quantum/process_keycode/process_key_lock.h +++ b/quantum/process_keycode/process_key_lock.h @@ -16,7 +16,9 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" void cancel_key_lock(void); bool process_key_lock(uint16_t *keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_key_override.c b/quantum/process_keycode/process_key_override.c index de628d3fec..6ce1e4d925 100644 --- a/quantum/process_keycode/process_key_override.c +++ b/quantum/process_keycode/process_key_override.c @@ -15,12 +15,10 @@ * along with this program. If not, see . */ -#include "quantum.h" +#include "process_key_override.h" #include "report.h" #include "timer.h" -#include "process_key_override.h" - -#include +#include "debug.h" #ifndef KEY_OVERRIDE_REPEAT_DELAY # define KEY_OVERRIDE_REPEAT_DELAY 500 diff --git a/quantum/process_keycode/process_key_override.h b/quantum/process_keycode/process_key_override.h index fd76f297a8..3e37c7e63a 100644 --- a/quantum/process_keycode/process_key_override.h +++ b/quantum/process_keycode/process_key_override.h @@ -18,9 +18,8 @@ #pragma once #include -#include #include - +#include "action.h" #include "action_layer.h" /** diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c index a9823b6285..ca017a577d 100644 --- a/quantum/process_keycode/process_leader.c +++ b/quantum/process_keycode/process_leader.c @@ -16,6 +16,7 @@ #include "process_leader.h" #include "leader.h" +#include "quantum_keycodes.h" bool process_leader(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h index eb0f721f60..b78fbb94df 100644 --- a/quantum/process_keycode/process_leader.h +++ b/quantum/process_keycode/process_leader.h @@ -16,6 +16,8 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" bool process_leader(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_magic.c b/quantum/process_keycode/process_magic.c index 5fafe8550f..3b35884d68 100644 --- a/quantum/process_keycode/process_magic.c +++ b/quantum/process_keycode/process_magic.c @@ -14,8 +14,13 @@ * along with this program. If not, see . */ #include "process_magic.h" +#include "keycode_config.h" +#include "keycodes.h" +#include "eeconfig.h" #ifdef AUDIO_ENABLE +# include "audio.h" + # ifndef AG_NORM_SONG # define AG_NORM_SONG SONG(AG_NORM_SOUND) # endif diff --git a/quantum/process_keycode/process_magic.h b/quantum/process_keycode/process_magic.h index 1eb39f1455..aa65a43bae 100644 --- a/quantum/process_keycode/process_magic.h +++ b/quantum/process_keycode/process_magic.h @@ -15,6 +15,8 @@ */ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" bool process_magic(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index ce62559849..377fcb69e2 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -15,12 +15,13 @@ */ #include "process_midi.h" -#ifdef MIDI_ENABLE -# include -# include "midi.h" -# include "qmk_midi.h" +#include +#include "midi.h" +#include "qmk_midi.h" +#include "timer.h" +#include "debug.h" -# ifdef MIDI_BASIC +#ifdef MIDI_BASIC void process_midi_basic_noteon(uint8_t note) { midi_send_noteon(&midi_device, 0, note, 127); @@ -34,12 +35,9 @@ void process_midi_all_notes_off(void) { midi_send_cc(&midi_device, 0, 0x7B, 0); } -# endif // MIDI_BASIC - -# ifdef MIDI_ADVANCED - -# include "timer.h" +#endif // MIDI_BASIC +#ifdef MIDI_ADVANCED static uint8_t tone_status[2][MIDI_TONE_COUNT]; static uint8_t midi_modulation; @@ -248,11 +246,11 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) { return true; } -# endif // MIDI_ADVANCED +#endif // MIDI_ADVANCED void midi_task(void) { midi_device_process(&midi_device); -# ifdef MIDI_ADVANCED +#ifdef MIDI_ADVANCED if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval) return; midi_modulation_timer = timer_read(); @@ -270,7 +268,5 @@ void midi_task(void) { if (midi_modulation > 127) midi_modulation = 127; } -# endif +#endif } - -#endif // MIDI_ENABLE diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h index e528c6ec0c..64ccc610f9 100644 --- a/quantum/process_keycode/process_midi.h +++ b/quantum/process_keycode/process_midi.h @@ -16,7 +16,10 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" +#include "quantum_keycodes.h" #ifdef MIDI_ENABLE diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 7c572079a7..f047668504 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -14,8 +14,10 @@ * along with this program. If not, see . */ #include "process_music.h" +#include "timer.h" #ifdef AUDIO_ENABLE +# include "audio.h" # include "process_audio.h" #endif #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h index 83726a05ba..ed39d3cda5 100644 --- a/quantum/process_keycode/process_music.h +++ b/quantum/process_keycode/process_music.h @@ -16,7 +16,9 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) diff --git a/quantum/process_keycode/process_programmable_button.h b/quantum/process_keycode/process_programmable_button.h index 47c6ce5614..ef818af4ca 100644 --- a/quantum/process_keycode/process_programmable_button.h +++ b/quantum/process_keycode/process_programmable_button.h @@ -18,6 +18,7 @@ along with this program. If not, see . #pragma once #include -#include "quantum.h" +#include +#include "action.h" bool process_programmable_button(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_repeat_key.c b/quantum/process_keycode/process_repeat_key.c index f819aa226e..73f4ddedcf 100644 --- a/quantum/process_keycode/process_repeat_key.c +++ b/quantum/process_keycode/process_repeat_key.c @@ -13,6 +13,10 @@ // limitations under the License. #include "process_repeat_key.h" +#include "repeat_key.h" +#include "keycodes.h" +#include "quantum_keycodes.h" +#include "action_util.h" // Default implementation of remember_last_key_user(). __attribute__((weak)) bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { diff --git a/quantum/process_keycode/process_repeat_key.h b/quantum/process_keycode/process_repeat_key.h index eddc50f254..c3b200c632 100644 --- a/quantum/process_keycode/process_repeat_key.h +++ b/quantum/process_keycode/process_repeat_key.h @@ -14,7 +14,9 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" /** * @brief Process handler for remembering the last key. diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c index dae129786e..4e63bf3ca8 100644 --- a/quantum/process_keycode/process_rgb.c +++ b/quantum/process_keycode/process_rgb.c @@ -14,6 +14,14 @@ * along with this program. If not, see . */ #include "process_rgb.h" +#include "action_util.h" + +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif +#ifdef RGBLIGHT_ENABLE +# include "rgblight.h" +#endif typedef void (*rgb_func_pointer)(void); diff --git a/quantum/process_keycode/process_rgb.h b/quantum/process_keycode/process_rgb.h index 26aca46896..b1069d4bb6 100644 --- a/quantum/process_keycode/process_rgb.h +++ b/quantum/process_keycode/process_rgb.h @@ -15,6 +15,8 @@ */ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" bool process_rgb(const uint16_t keycode, const keyrecord_t *record); diff --git a/quantum/process_keycode/process_secure.h b/quantum/process_keycode/process_secure.h index 2814264b92..78d793f0f6 100644 --- a/quantum/process_keycode/process_secure.h +++ b/quantum/process_keycode/process_secure.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include "action.h" diff --git a/quantum/process_keycode/process_sequencer.h b/quantum/process_keycode/process_sequencer.h index 2b85f24299..3a9bdc2b24 100644 --- a/quantum/process_keycode/process_sequencer.h +++ b/quantum/process_keycode/process_sequencer.h @@ -16,6 +16,8 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" bool process_sequencer(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 3109ea1711..4d9f01077e 100644 --- a/quantum/process_keycode/process_space_cadet.c +++ b/quantum/process_keycode/process_space_cadet.c @@ -14,6 +14,8 @@ * along with this program. If not, see . */ #include "process_space_cadet.h" +#include "keycodes.h" +#include "timer.h" #include "action_tapping.h" // ********** OBSOLETE DEFINES, STOP USING! (pls?) ********** diff --git a/quantum/process_keycode/process_space_cadet.h b/quantum/process_keycode/process_space_cadet.h index fcb70f3b43..6d10051532 100644 --- a/quantum/process_keycode/process_space_cadet.h +++ b/quantum/process_keycode/process_space_cadet.h @@ -15,7 +15,9 @@ */ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdMod, uint8_t tapMod, uint8_t keycode); bool process_space_cadet(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c index d5ad61ba85..af26d4ca86 100644 --- a/quantum/process_keycode/process_steno.c +++ b/quantum/process_keycode/process_steno.c @@ -15,6 +15,7 @@ */ #include "process_steno.h" #include "quantum_keycodes.h" +#include "eeconfig.h" #include "keymap_steno.h" #include #ifdef VIRTSER_ENABLE diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h index 68d6097b9b..0dd2103218 100644 --- a/quantum/process_keycode/process_steno.h +++ b/quantum/process_keycode/process_steno.h @@ -16,7 +16,9 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" #define BOLT_STROKE_SIZE 4 #define GEMINI_STROKE_SIZE 6 diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c index 706f5cddbb..1b2c6c8a44 100644 --- a/quantum/process_keycode/process_tap_dance.c +++ b/quantum/process_keycode/process_tap_dance.c @@ -13,7 +13,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +#include "process_tap_dance.h" #include "quantum.h" +#include "action_layer.h" +#include "action_tapping.h" +#include "action_util.h" +#include "timer.h" +#include "wait.h" static uint16_t active_td; static uint16_t last_tap_time; diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h index 5cb6d9202c..386f504619 100644 --- a/quantum/process_keycode/process_tap_dance.h +++ b/quantum/process_keycode/process_tap_dance.h @@ -16,18 +16,17 @@ #pragma once -#ifdef TAP_DANCE_ENABLE - -# include -# include +#include +#include +#include "action.h" typedef struct { uint16_t interrupting_keycode; uint8_t count; uint8_t weak_mods; -# ifndef NO_ACTION_ONESHOT +#ifndef NO_ACTION_ONESHOT uint8_t oneshot_mods; -# endif +#endif bool pressed : 1; bool finished : 1; bool interrupted : 1; @@ -56,24 +55,24 @@ typedef struct { void (*layer_function)(uint8_t); } tap_dance_dual_role_t; -# define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \ - { .fn = {tap_dance_pair_on_each_tap, tap_dance_pair_finished, tap_dance_pair_reset}, .user_data = (void *)&((tap_dance_pair_t){kc1, kc2}), } +#define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \ + { .fn = {tap_dance_pair_on_each_tap, tap_dance_pair_finished, tap_dance_pair_reset}, .user_data = (void *)&((tap_dance_pair_t){kc1, kc2}), } -# define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) \ - { .fn = {tap_dance_dual_role_on_each_tap, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_move}), } +#define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) \ + { .fn = {tap_dance_dual_role_on_each_tap, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_move}), } -# define ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer) \ - { .fn = {NULL, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_invert}), } +#define ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer) \ + { .fn = {NULL, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_invert}), } -# define ACTION_TAP_DANCE_FN(user_fn) \ - { .fn = {NULL, user_fn, NULL}, .user_data = NULL, } +#define ACTION_TAP_DANCE_FN(user_fn) \ + { .fn = {NULL, user_fn, NULL}, .user_data = NULL, } -# define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) \ - { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, } +#define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) \ + { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, } -# define TD(n) (QK_TAP_DANCE | TD_INDEX(n)) -# define TD_INDEX(code) ((code)&0xFF) -# define TAP_DANCE_KEYCODE(state) TD(((tap_dance_action_t *)state) - tap_dance_actions) +#define TD(n) (QK_TAP_DANCE | TD_INDEX(n)) +#define TD_INDEX(code) ((code)&0xFF) +#define TAP_DANCE_KEYCODE(state) TD(((tap_dance_action_t *)state) - tap_dance_actions) extern tap_dance_action_t tap_dance_actions[]; @@ -92,9 +91,3 @@ void tap_dance_pair_reset(tap_dance_state_t *state, void *user_data); void tap_dance_dual_role_on_each_tap(tap_dance_state_t *state, void *user_data); void tap_dance_dual_role_finished(tap_dance_state_t *state, void *user_data); void tap_dance_dual_role_reset(tap_dance_state_t *state, void *user_data); - -#else - -# define TD(n) KC_NO - -#endif diff --git a/quantum/process_keycode/process_tri_layer.h b/quantum/process_keycode/process_tri_layer.h index 9c4e3df1c2..5e6e4ff94d 100644 --- a/quantum/process_keycode/process_tri_layer.h +++ b/quantum/process_keycode/process_tri_layer.h @@ -3,6 +3,8 @@ #pragma once +#include +#include #include "action.h" /** -- cgit v1.2.3 From 83c73d42f976fd169d6750926ded9203b0ab7f4e Mon Sep 17 00:00:00 2001 From: フィルターペーパー Date: Wed, 12 Jul 2023 16:38:59 +0800 Subject: process_combo: restore wait.h header (#21514) Required for `wait_ms()` function--- quantum/process_keycode/process_combo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'quantum/process_keycode') diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index 0d4f4f3dba..64d30fc140 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -19,6 +19,7 @@ #include "process_auto_shift.h" #include "caps_word.h" #include "timer.h" +#include "wait.h" #include "keyboard.h" #include "keymap_common.h" #include "action_layer.h" -- cgit v1.2.3 From da2d2f947d5c30aebea17f414fb22ad50fe5410b Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 16 Jul 2023 23:42:56 +1000 Subject: quantum: remove direct `quantum.h` includes (#21507) --- keyboards/boardsource/lulu/lulu.c | 2 +- keyboards/input_club/k_type/k_type-rgbdriver.c | 3 +- .../input_club/k_type/keymaps/default/keymap.c | 3 ++ keyboards/system76/launch_1/rgb_matrix_kb.inc | 1 + keyboards/system76/system76_ec.c | 6 ++++ platforms/avr/drivers/audio_pwm_hardware.c | 8 ++--- platforms/chibios/drivers/audio_dac_additive.c | 5 +-- platforms/chibios/drivers/audio_dac_basic.c | 3 +- platforms/chibios/drivers/audio_pwm_hardware.c | 3 +- platforms/chibios/drivers/audio_pwm_software.c | 3 +- quantum/audio/audio.c | 3 ++ quantum/audio/audio.h | 9 ++--- quantum/audio/muse.c | 2 ++ quantum/audio/muse.h | 3 +- quantum/audio/voices.c | 2 ++ quantum/bootmagic/bootmagic_lite.c | 7 +++- quantum/dynamic_keymap.c | 12 ++++--- quantum/encoder.c | 5 +++ quantum/encoder.h | 4 ++- quantum/encoder/tests/encoder_tests_split_role.cpp | 1 + quantum/keyboard.c | 34 +++++++++++++++++-- quantum/keyboard.h | 2 ++ quantum/keymap_common.c | 7 +++- quantum/led_matrix/led_matrix.c | 5 +++ quantum/led_matrix/led_matrix.h | 2 +- quantum/matrix.c | 3 +- quantum/matrix_common.c | 2 +- quantum/midi/qmk_midi.c | 1 + .../pointing_device/pointing_device_auto_mouse.c | 3 ++ .../pointing_device/pointing_device_auto_mouse.h | 11 +++--- quantum/process_keycode/process_audio.c | 4 +-- quantum/process_keycode/process_audio.h | 3 -- quantum/process_keycode/process_clicky.c | 4 ++- quantum/process_keycode/process_key_override.c | 4 +++ quantum/repeat_key.c | 1 + quantum/repeat_key.h | 5 ++- quantum/rgb_matrix/rgb_matrix.c | 5 +++ quantum/rgb_matrix/rgb_matrix.h | 2 +- quantum/rgb_matrix/rgb_matrix_drivers.c | 1 + quantum/split_common/split_util.c | 2 +- quantum/split_common/split_util.h | 1 - quantum/split_common/transactions.c | 39 +++++++++++++++++++++- quantum/split_common/transactions.h | 4 +-- quantum/split_common/transport.h | 4 +-- quantum/unicode/unicode.c | 2 ++ quantum/unicode/unicode.h | 3 +- quantum/via.c | 26 +++++++++++++-- quantum/via.h | 1 + tmk_core/protocol/arm_atsam/main_arm_atsam.c | 1 + tmk_core/protocol/arm_atsam/md_rgb_matrix.c | 1 + tmk_core/protocol/arm_atsam/spi_master.h | 2 ++ 51 files changed, 208 insertions(+), 62 deletions(-) (limited to 'quantum/process_keycode') diff --git a/keyboards/boardsource/lulu/lulu.c b/keyboards/boardsource/lulu/lulu.c index be6d565a32..8d011268c4 100644 --- a/keyboards/boardsource/lulu/lulu.c +++ b/keyboards/boardsource/lulu/lulu.c @@ -1,6 +1,6 @@ // Copyright 2022 Cole Smith // SPDX-License-Identifier: GPL-2.0-or-later -#include "encoder.h" +#include "quantum.h" #ifdef ENCODER_ENABLE bool encoder_update_kb(uint8_t index, bool clockwise) { diff --git a/keyboards/input_club/k_type/k_type-rgbdriver.c b/keyboards/input_club/k_type/k_type-rgbdriver.c index e663c224c4..6529f98201 100644 --- a/keyboards/input_club/k_type/k_type-rgbdriver.c +++ b/keyboards/input_club/k_type/k_type-rgbdriver.c @@ -19,8 +19,7 @@ #include "rgb_matrix.h" #include "i2c_master.h" #include "is31fl3733-dual.h" - - +#include "gpio.h" static void init(void) { i2c_init(&I2CD1, I2C1_SCL_PIN, I2C1_SDA_PIN); diff --git a/keyboards/input_club/k_type/keymaps/default/keymap.c b/keyboards/input_club/k_type/keymaps/default/keymap.c index 790bd93290..452791b13a 100644 --- a/keyboards/input_club/k_type/keymaps/default/keymap.c +++ b/keyboards/input_club/k_type/keymaps/default/keymap.c @@ -1,3 +1,6 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + #include QMK_KEYBOARD_H const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { diff --git a/keyboards/system76/launch_1/rgb_matrix_kb.inc b/keyboards/system76/launch_1/rgb_matrix_kb.inc index 02de10ed50..f29183dde0 100644 --- a/keyboards/system76/launch_1/rgb_matrix_kb.inc +++ b/keyboards/system76/launch_1/rgb_matrix_kb.inc @@ -22,6 +22,7 @@ RGB_MATRIX_EFFECT(unlocked) #ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS #include "dynamic_keymap.h" +#include "action_layer.h" static bool active_keys_initialized = false; static uint8_t active_keys_table[RGB_MATRIX_LED_COUNT] = {0}; diff --git a/keyboards/system76/system76_ec.c b/keyboards/system76/system76_ec.c index 6301659072..1b7955e19b 100644 --- a/keyboards/system76/system76_ec.c +++ b/keyboards/system76/system76_ec.c @@ -22,6 +22,12 @@ #include "raw_hid.h" #include "rgb_matrix.h" #include "version.h" +#include "keyboard.h" +#include "eeprom.h" +#include "matrix.h" +#include "action_layer.h" +#include "bootloader.h" +#include "wait.h" enum Command { CMD_PROBE = 1, // Probe for System76 EC protocol diff --git a/platforms/avr/drivers/audio_pwm_hardware.c b/platforms/avr/drivers/audio_pwm_hardware.c index 2fc448ea58..6799cf2fdd 100644 --- a/platforms/avr/drivers/audio_pwm_hardware.c +++ b/platforms/avr/drivers/audio_pwm_hardware.c @@ -15,13 +15,9 @@ * along with this program. If not, see . */ -#if defined(__AVR__) -# include -# include -# include -#endif - #include "audio.h" +#include "gpio.h" +#include extern bool playing_note; extern bool playing_melody; diff --git a/platforms/chibios/drivers/audio_dac_additive.c b/platforms/chibios/drivers/audio_dac_additive.c index d29147ca3b..9a5fe4c336 100644 --- a/platforms/chibios/drivers/audio_dac_additive.c +++ b/platforms/chibios/drivers/audio_dac_additive.c @@ -16,8 +16,9 @@ */ #include "audio.h" -#include -#include +#include "gpio.h" +#include +#include "util.h" // Need to disable GCC's "tautological-compare" warning for this file, as it causes issues when running `KEEP_INTERMEDIATES=yes`. Corresponding pop at the end of the file. #pragma GCC diagnostic push diff --git a/platforms/chibios/drivers/audio_dac_basic.c b/platforms/chibios/drivers/audio_dac_basic.c index 4ea23a2158..9a3f3fea1f 100644 --- a/platforms/chibios/drivers/audio_dac_basic.c +++ b/platforms/chibios/drivers/audio_dac_basic.c @@ -16,8 +16,7 @@ */ #include "audio.h" -#include "ch.h" -#include "hal.h" +#include "gpio.h" // Need to disable GCC's "tautological-compare" warning for this file, as it causes issues when running `KEEP_INTERMEDIATES=yes`. Corresponding pop at the end of the file. #pragma GCC diagnostic push diff --git a/platforms/chibios/drivers/audio_pwm_hardware.c b/platforms/chibios/drivers/audio_pwm_hardware.c index 54dac46605..40d891326f 100644 --- a/platforms/chibios/drivers/audio_pwm_hardware.c +++ b/platforms/chibios/drivers/audio_pwm_hardware.c @@ -12,8 +12,7 @@ // function. #include "audio.h" -#include "ch.h" -#include "hal.h" +#include "gpio.h" #if !defined(AUDIO_PIN) # error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings" diff --git a/platforms/chibios/drivers/audio_pwm_software.c b/platforms/chibios/drivers/audio_pwm_software.c index e01f86ea52..663a9eca16 100644 --- a/platforms/chibios/drivers/audio_pwm_software.c +++ b/platforms/chibios/drivers/audio_pwm_software.c @@ -25,8 +25,7 @@ this driver uses the chibios-PWM system to produce a square-wave on any given ou */ #include "audio.h" -#include "ch.h" -#include "hal.h" +#include "gpio.h" #if !defined(AUDIO_PIN) # error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings" diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index 0300483a93..b9b21066cb 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -583,3 +583,6 @@ uint16_t audio_duration_to_ms(uint16_t duration_bpm) { uint16_t audio_ms_to_duration(uint16_t duration_ms) { return ((uint32_t)duration_ms * 2 * note_tempo) / 1875; } + +__attribute__((weak)) void audio_on_user(void) {} +__attribute__((weak)) void audio_off_user(void) {} diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index 75016a1100..a4a908b43c 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -21,12 +21,6 @@ #include "musical_notes.h" #include "song_list.h" #include "voices.h" -#include "quantum.h" -#include - -#if defined(__AVR__) -# include -#endif #if defined(AUDIO_DRIVER_PWM) # include "audio_pwm.h" @@ -280,3 +274,6 @@ bool audio_update_state(void); #define increase_tempo(t) audio_increase_tempo(t) #define decrease_tempo(t) audio_decrease_tempo(t) // vibrato functions are not used in any keyboards + +void audio_on_user(void); +void audio_off_user(void); diff --git a/quantum/audio/muse.c b/quantum/audio/muse.c index 01b95671fd..4c23cd7348 100644 --- a/quantum/audio/muse.c +++ b/quantum/audio/muse.c @@ -1,5 +1,7 @@ #include "muse.h" +#include + enum { MUSE_OFF, MUSE_ON, MUSE_C_1_2, MUSE_C1, MUSE_C2, MUSE_C4, MUSE_C8, MUSE_C3, MUSE_C6, MUSE_B1, MUSE_B2, MUSE_B3, MUSE_B4, MUSE_B5, MUSE_B6, MUSE_B7, MUSE_B8, MUSE_B9, MUSE_B10, MUSE_B11, MUSE_B12, MUSE_B13, MUSE_B14, MUSE_B15, MUSE_B16, MUSE_B17, MUSE_B18, MUSE_B19, MUSE_B20, MUSE_B21, MUSE_B22, MUSE_B23, MUSE_B24, MUSE_B25, MUSE_B26, MUSE_B27, MUSE_B28, MUSE_B29, MUSE_B30, MUSE_B31 }; bool number_of_ones_to_bool[16] = {1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1}; diff --git a/quantum/audio/muse.h b/quantum/audio/muse.h index ad2f96e43a..7b289cac6c 100644 --- a/quantum/audio/muse.h +++ b/quantum/audio/muse.h @@ -1,6 +1,5 @@ #pragma once -#include "quantum.h" -#include "process_audio.h" +#include uint8_t muse_clock_pulse(void); diff --git a/quantum/audio/voices.c b/quantum/audio/voices.c index 01f257f4d4..4f511c93ba 100644 --- a/quantum/audio/voices.c +++ b/quantum/audio/voices.c @@ -16,7 +16,9 @@ */ #include "voices.h" #include "audio.h" +#include "timer.h" #include +#include uint8_t note_timbre = TIMBRE_DEFAULT; bool glissando = false; diff --git a/quantum/bootmagic/bootmagic_lite.c b/quantum/bootmagic/bootmagic_lite.c index f63c71fc6b..efce6bfd12 100644 --- a/quantum/bootmagic/bootmagic_lite.c +++ b/quantum/bootmagic/bootmagic_lite.c @@ -13,7 +13,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "quantum.h" +#include "bootmagic.h" +#include "matrix.h" +#include "keyboard.h" +#include "wait.h" +#include "eeconfig.h" +#include "bootloader.h" /** \brief Reset eeprom * diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index 2030c82a1b..4c95128337 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -14,14 +14,16 @@ * along with this program. If not, see . */ -#include "keymap_introspection.h" // to get keymaps[][][] -#include "eeprom.h" -#include "progmem.h" // to read default from flash -#include "quantum.h" // for send_string() #include "dynamic_keymap.h" +#include "keymap_introspection.h" +#include "action.h" +#include "eeprom.h" +#include "progmem.h" +#include "send_string.h" +#include "keycodes.h" #ifdef VIA_ENABLE -# include "via.h" // for VIA_EEPROM_CONFIG_END +# include "via.h" # define DYNAMIC_KEYMAP_EEPROM_START (VIA_EEPROM_CONFIG_END) #else # define DYNAMIC_KEYMAP_EEPROM_START (EECONFIG_SIZE) diff --git a/quantum/encoder.c b/quantum/encoder.c index 1046fe6cc3..7ab194ed52 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -16,6 +16,11 @@ */ #include "encoder.h" +#include "keyboard.h" +#include "action.h" +#include "keycodes.h" +#include "wait.h" + #ifdef SPLIT_KEYBOARD # include "split_util.h" #endif diff --git a/quantum/encoder.h b/quantum/encoder.h index 7644853b30..1cbac98cb5 100644 --- a/quantum/encoder.h +++ b/quantum/encoder.h @@ -17,7 +17,9 @@ #pragma once -#include "quantum.h" +#include +#include +#include "gpio.h" #include "util.h" void encoder_init(void); diff --git a/quantum/encoder/tests/encoder_tests_split_role.cpp b/quantum/encoder/tests/encoder_tests_split_role.cpp index 02264067f4..0ab7bfc2a7 100644 --- a/quantum/encoder/tests/encoder_tests_split_role.cpp +++ b/quantum/encoder/tests/encoder_tests_split_role.cpp @@ -22,6 +22,7 @@ extern "C" { #include "encoder.h" +#include "keyboard.h" #include "encoder/tests/mock_split.h" } diff --git a/quantum/keyboard.c b/quantum/keyboard.c index 5115709748..c2ca15d52d 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -16,8 +16,8 @@ along with this program. If not, see . */ #include -#include "quantum.h" #include "keyboard.h" +#include "keycode_config.h" #include "matrix.h" #include "keymap_introspection.h" #include "magic.h" @@ -33,6 +33,12 @@ along with this program. If not, see . #include "sendchar.h" #include "eeconfig.h" #include "action_layer.h" +#ifdef AUDIO_ENABLE +# include "audio.h" +#endif +#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) +# include "process_music.h" +#endif #ifdef BACKLIGHT_ENABLE # include "backlight.h" #endif @@ -54,9 +60,27 @@ along with this program. If not, see . #ifdef ENCODER_ENABLE # include "encoder.h" #endif +#ifdef HAPTIC_ENABLE +# include "haptic.h" +#endif +#ifdef AUTO_SHIFT_ENABLE +# include "process_auto_shift.h" +#endif +#ifdef COMBO_ENABLE +# include "process_combo.h" +#endif +#ifdef TAP_DANCE_ENABLE +# include "process_tap_dance.h" +#endif #ifdef STENO_ENABLE # include "process_steno.h" #endif +#ifdef KEY_OVERRIDE_ENABLE +# include "process_key_override.h" +#endif +#ifdef SECURE_ENABLE +# include "secure.h" +#endif #ifdef POINTING_DEVICE_ENABLE # include "pointing_device.h" #endif @@ -64,7 +88,7 @@ along with this program. If not, see . # include "process_midi.h" #endif #ifdef JOYSTICK_ENABLE -# include "process_joystick.h" +# include "joystick.h" #endif #ifdef HD44780_ENABLE # include "hd44780.h" @@ -108,6 +132,12 @@ along with this program. If not, see . #ifdef LEADER_ENABLE # include "leader.h" #endif +#ifdef UNICODE_COMMON_ENABLE +# include "unicode.h" +#endif +#ifdef WPM_ENABLE +# include "wpm.h" +#endif static uint32_t last_input_modification_time = 0; uint32_t last_input_activity_time(void) { diff --git a/quantum/keyboard.h b/quantum/keyboard.h index bf1890d10b..5ea57815a7 100644 --- a/quantum/keyboard.h +++ b/quantum/keyboard.h @@ -20,6 +20,8 @@ along with this program. If not, see . #include #include +#include "timer.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 0492e6fd1c..9a67fad278 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -22,7 +22,12 @@ along with this program. If not, see . #include "action_layer.h" #include "action.h" #include "debug.h" -#include "quantum.h" +#include "keycode_config.h" +#include "quantum_keycodes.h" + +#ifdef ENCODER_MAP_ENABLE +# include "encoder.h" +#endif #ifdef BACKLIGHT_ENABLE # include "backlight.h" diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c index 4b692d1904..1676a60aa3 100644 --- a/quantum/led_matrix/led_matrix.c +++ b/quantum/led_matrix/led_matrix.c @@ -20,8 +20,13 @@ #include "led_matrix.h" #include "progmem.h" #include "eeprom.h" +#include "eeconfig.h" +#include "keyboard.h" +#include "sync_timer.h" +#include "debug.h" #include #include +#include #include "led_tables.h" #include diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h index 9091f6890b..c2533ca49c 100644 --- a/quantum/led_matrix/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h @@ -23,7 +23,7 @@ #include #include #include "led_matrix_types.h" -#include "quantum.h" +#include "keyboard.h" #ifdef IS31FL3731 # include "is31fl3731-simple.h" diff --git a/quantum/matrix.c b/quantum/matrix.c index 97d41caedd..f087a215d4 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -20,7 +20,8 @@ along with this program. If not, see . #include "util.h" #include "matrix.h" #include "debounce.h" -#include "quantum.h" +#include "atomic_util.h" + #ifdef SPLIT_KEYBOARD # include "split_common/split_util.h" # include "split_common/transactions.h" diff --git a/quantum/matrix_common.c b/quantum/matrix_common.c index 3173351888..d02c527caa 100644 --- a/quantum/matrix_common.c +++ b/quantum/matrix_common.c @@ -1,9 +1,9 @@ -#include "quantum.h" #include "matrix.h" #include "debounce.h" #include "wait.h" #include "print.h" #include "debug.h" + #ifdef SPLIT_KEYBOARD # include "split_common/split_util.h" # include "split_common/transactions.h" diff --git a/quantum/midi/qmk_midi.c b/quantum/midi/qmk_midi.c index 688259784c..43ebd72937 100644 --- a/quantum/midi/qmk_midi.c +++ b/quantum/midi/qmk_midi.c @@ -7,6 +7,7 @@ #ifdef AUDIO_ENABLE # include "audio.h" +# include #endif /******************************************************************************* diff --git a/quantum/pointing_device/pointing_device_auto_mouse.c b/quantum/pointing_device/pointing_device_auto_mouse.c index b008d18db5..fc3106e37e 100644 --- a/quantum/pointing_device/pointing_device_auto_mouse.c +++ b/quantum/pointing_device/pointing_device_auto_mouse.c @@ -18,6 +18,9 @@ #ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE # include "pointing_device_auto_mouse.h" +# include "debug.h" +# include "action_util.h" +# include "quantum_keycodes.h" /* local data structure for tracking auto mouse */ static auto_mouse_context_t auto_mouse_context = { diff --git a/quantum/pointing_device/pointing_device_auto_mouse.h b/quantum/pointing_device/pointing_device_auto_mouse.h index 7db63bc6b8..1343855e00 100644 --- a/quantum/pointing_device/pointing_device_auto_mouse.h +++ b/quantum/pointing_device/pointing_device_auto_mouse.h @@ -16,11 +16,14 @@ #pragma once -#include - -#include "quantum.h" +#include +#include #include "pointing_device.h" -#include "print.h" +#include "keycodes.h" +#include "action.h" +#include "report.h" +#include "action_layer.h" +#include "action_tapping.h" /* check settings and set defaults */ #ifndef POINTING_DEVICE_AUTO_MOUSE_ENABLE diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index c189dd02b7..ef2f52c9f1 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -1,5 +1,6 @@ #include "audio.h" #include "process_audio.h" +#include #ifndef VOICE_CHANGE_SONG # define VOICE_CHANGE_SONG SONG(VOICE_CHANGE_SOUND) @@ -61,6 +62,3 @@ void process_audio_noteoff(uint8_t note) { void process_audio_all_notes_off(void) { stop_all_notes(); } - -__attribute__((weak)) void audio_on_user(void) {} -__attribute__((weak)) void audio_off_user(void) {} diff --git a/quantum/process_keycode/process_audio.h b/quantum/process_keycode/process_audio.h index c80136f2c2..69e201e447 100644 --- a/quantum/process_keycode/process_audio.h +++ b/quantum/process_keycode/process_audio.h @@ -10,6 +10,3 @@ bool process_audio(uint16_t keycode, keyrecord_t *record); void process_audio_noteon(uint8_t note); void process_audio_noteoff(uint8_t note); void process_audio_all_notes_off(void); - -void audio_on_user(void); -void audio_off_user(void); diff --git a/quantum/process_keycode/process_clicky.c b/quantum/process_keycode/process_clicky.c index b662a3f2f4..0ee58282e6 100644 --- a/quantum/process_keycode/process_clicky.c +++ b/quantum/process_keycode/process_clicky.c @@ -1,5 +1,7 @@ -#include "audio.h" #include "process_clicky.h" +#include "audio.h" +#include "eeconfig.h" +#include #ifdef AUDIO_CLICKY diff --git a/quantum/process_keycode/process_key_override.c b/quantum/process_keycode/process_key_override.c index 6ce1e4d925..264e2562b8 100644 --- a/quantum/process_keycode/process_key_override.c +++ b/quantum/process_keycode/process_key_override.c @@ -19,6 +19,10 @@ #include "report.h" #include "timer.h" #include "debug.h" +#include "wait.h" +#include "action_util.h" +#include "quantum.h" +#include "quantum_keycodes.h" #ifndef KEY_OVERRIDE_REPEAT_DELAY # define KEY_OVERRIDE_REPEAT_DELAY 500 diff --git a/quantum/repeat_key.c b/quantum/repeat_key.c index 0689c6d454..4567428723 100644 --- a/quantum/repeat_key.c +++ b/quantum/repeat_key.c @@ -13,6 +13,7 @@ // limitations under the License. #include "repeat_key.h" +#include "quantum_keycodes.h" // Variables saving the state of the last key press. static keyrecord_t last_record = {0}; diff --git a/quantum/repeat_key.h b/quantum/repeat_key.h index 06e8364529..8084be24ad 100644 --- a/quantum/repeat_key.h +++ b/quantum/repeat_key.h @@ -14,7 +14,10 @@ #pragma once -#include "quantum.h" +#include +#include +#include "action.h" +#include "keyboard.h" uint16_t get_last_keycode(void); /**< Keycode of the last key. */ uint8_t get_last_mods(void); /**< Mods active with the last key. */ diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c index 1680389793..96be615162 100644 --- a/quantum/rgb_matrix/rgb_matrix.c +++ b/quantum/rgb_matrix/rgb_matrix.c @@ -19,8 +19,13 @@ #include "rgb_matrix.h" #include "progmem.h" #include "eeprom.h" +#include "eeconfig.h" +#include "keyboard.h" +#include "sync_timer.h" +#include "debug.h" #include #include +#include #include diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h index 83851d8995..38040fb0cc 100644 --- a/quantum/rgb_matrix/rgb_matrix.h +++ b/quantum/rgb_matrix/rgb_matrix.h @@ -22,7 +22,7 @@ #include #include "rgb_matrix_types.h" #include "color.h" -#include "quantum.h" +#include "keyboard.h" #ifdef IS31FL3731 # include "is31fl3731.h" diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c index 6de20ac8a5..7bd274ee99 100644 --- a/quantum/rgb_matrix/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix/rgb_matrix_drivers.c @@ -15,6 +15,7 @@ */ #include "rgb_matrix.h" +#include "util.h" /* Each driver needs to define the struct * const rgb_matrix_driver_t rgb_matrix_driver; diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index a431383454..87838c3195 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -18,8 +18,8 @@ #include "keyboard.h" #include "timer.h" #include "transport.h" -#include "quantum.h" #include "wait.h" +#include "debug.h" #include "usb_util.h" #ifdef EE_HANDS diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index 5c9a260a14..ab42c85e9f 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -2,7 +2,6 @@ #include #include -#include #include "matrix.h" diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c index 8cd018a6ec..2b9423cd63 100644 --- a/quantum/split_common/transactions.c +++ b/quantum/split_common/transactions.c @@ -20,13 +20,50 @@ #include "crc.h" #include "debug.h" #include "matrix.h" -#include "quantum.h" +#include "host.h" +#include "action_util.h" +#include "sync_timer.h" +#include "wait.h" #include "transactions.h" #include "transport.h" #include "transaction_id_define.h" #include "split_util.h" #include "synchronization_util.h" +#ifdef BACKLIGHT_ENABLE +# include "backlight.h" +#endif +#ifdef RGBLIGHT_ENABLE +# include "rgblight.h" +#endif +#ifdef LED_MATRIX_ENABLE +# include "led_matrix.h" +#endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif +#ifdef OLED_ENABLE +# include "oled_driver.h" +#endif +#ifdef ST7565_ENABLE +# include "st7565.h" +#endif +#ifdef ENCODER_ENABLE +# include "encoder.h" +#endif +#ifdef HAPTIC_ENABLE +# include "haptic.h" +#endif +#ifdef POINTING_DEVICE_ENABLE +# include "pointing_device.h" +#endif +#ifdef OS_DETECTION_ENABLE +# include "os_detection.h" +#endif +#ifdef WPM_ENABLE +# include "wpm.h" +#endif + #define SYNC_TIMER_OFFSET 2 #ifndef FORCED_SYNC_THROTTLE_MS diff --git a/quantum/split_common/transactions.h b/quantum/split_common/transactions.h index e38ec79ce9..af3e68a15f 100644 --- a/quantum/split_common/transactions.h +++ b/quantum/split_common/transactions.h @@ -16,8 +16,8 @@ #pragma once -#include "stdint.h" -#include "stdbool.h" +#include +#include #include "matrix.h" #include "transaction_id_define.h" diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h index a3d6f1dfe9..2e2b918d45 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h @@ -16,8 +16,8 @@ #pragma once -#include "stdint.h" -#include "stdbool.h" +#include +#include #include "progmem.h" #include "action_layer.h" diff --git a/quantum/unicode/unicode.c b/quantum/unicode/unicode.c index 35cb62e700..f92ba51984 100644 --- a/quantum/unicode/unicode.c +++ b/quantum/unicode/unicode.c @@ -25,6 +25,8 @@ #include "wait.h" #include "send_string.h" #include "utf8.h" +#include "debug.h" +#include "quantum.h" #if defined(AUDIO_ENABLE) # include "audio.h" diff --git a/quantum/unicode/unicode.h b/quantum/unicode/unicode.h index 06505d87c0..ccf475d57c 100644 --- a/quantum/unicode/unicode.h +++ b/quantum/unicode/unicode.h @@ -17,8 +17,7 @@ #pragma once #include - -#include "quantum.h" +#include "quantum_keycodes.h" typedef union { uint8_t raw; diff --git a/quantum/via.c b/quantum/via.c index f4293dacd4..2acd7aa90c 100644 --- a/quantum/via.c +++ b/quantum/via.c @@ -22,19 +22,41 @@ # error "DYNAMIC_KEYMAP_ENABLE is not enabled" #endif -#include "quantum.h" - #include "via.h" #include "raw_hid.h" #include "dynamic_keymap.h" #include "eeprom.h" +#include "eeconfig.h" +#include "matrix.h" +#include "timer.h" +#include "wait.h" #include "version.h" // for QMK_BUILDDATE used in EEPROM magic +#if defined(AUDIO_ENABLE) +# include "audio.h" +#endif + +#if defined(BACKLIGHT_ENABLE) +# include "backlight.h" +#endif + +#if defined(RGBLIGHT_ENABLE) +# include "rgblight.h" +#endif + #if (defined(RGB_MATRIX_ENABLE) || defined(LED_MATRIX_ENABLE)) # include #endif +#if defined(RGB_MATRIX_ENABLE) +# include "rgb_matrix.h" +#endif + +#if defined(LED_MATRIX_ENABLE) +# include "led_matrix.h" +#endif + // Can be called in an overriding via_init_kb() to test if keyboard level code usage of // EEPROM is invalid and use/save defaults. bool via_eeprom_is_valid(void) { diff --git a/quantum/via.h b/quantum/via.h index 6c8465b81e..01d4c48b37 100644 --- a/quantum/via.h +++ b/quantum/via.h @@ -17,6 +17,7 @@ #pragma once #include "eeconfig.h" // for EECONFIG_SIZE +#include "action.h" // Keyboard level code can change where VIA stores the magic. // The magic is the build date YYMMDD encoded as BCD in 3 bytes, diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index 5bed9e0cf4..30817c17b6 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -21,6 +21,7 @@ along with this program. If not, see . #include "report.h" #include "host.h" #include "host_driver.h" +#include "suspend.h" #include "keycode_config.h" #include diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c index 6069d1e609..0f316b256c 100644 --- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c @@ -24,6 +24,7 @@ along with this program. If not, see . # include "led.h" # include "rgb_matrix.h" # include "eeprom.h" +# include "host.h" # include # include diff --git a/tmk_core/protocol/arm_atsam/spi_master.h b/tmk_core/protocol/arm_atsam/spi_master.h index 26c55128be..80678a5707 100644 --- a/tmk_core/protocol/arm_atsam/spi_master.h +++ b/tmk_core/protocol/arm_atsam/spi_master.h @@ -16,7 +16,9 @@ #pragma once +#include #include +#include "gpio.h" typedef int16_t spi_status_t; -- cgit v1.2.3 From b090354143612d2c0f5c8629510542de5bd4e29e Mon Sep 17 00:00:00 2001 From: Ryan Date: Fri, 21 Jul 2023 09:17:39 +1000 Subject: haptic: naming cleanups (#21551) --- builddefs/common_features.mk | 23 +- docs/feature_haptic_feedback.md | 19 +- drivers/haptic/DRV2605L.c | 122 ------ drivers/haptic/DRV2605L.h | 406 -------------------- drivers/haptic/drv2605l.c | 126 +++++++ drivers/haptic/drv2605l.h | 407 +++++++++++++++++++++ keyboards/adpenrose/mine/keymaps/solenoid/rules.mk | 2 +- .../adpenrose/shisaku/keymaps/solenoid/rules.mk | 2 +- keyboards/ai03/lunar_ii/rules.mk | 2 +- keyboards/boston_meetup/2019/config.h | 4 +- keyboards/boston_meetup/2019/rules.mk | 2 +- keyboards/buzzard/keymaps/crehmann/config.h | 4 +- .../keymaps/crehmann/features/haptic_utils.c | 12 +- keyboards/buzzard/keymaps/crehmann/rules.mk | 2 +- keyboards/buzzard/keymaps/default/config.h | 4 +- keyboards/buzzard/keymaps/default/rules.mk | 2 +- keyboards/buzzard/rev1/rev1.c | 12 +- keyboards/hadron/ver3/config.h | 4 +- keyboards/hadron/ver3/keymaps/ishtob/config.h | 1 - keyboards/hadron/ver3/keymaps/ishtob/keymap.c | 9 - keyboards/hadron/ver3/rules.mk | 2 +- keyboards/handwired/onekey/keymaps/haptic/rules.mk | 2 +- .../swiftrax/bumblebee/keymaps/default/rules.mk | 1 - .../swiftrax/bumblebee/keymaps/via/rules.mk | 1 - .../5x6_right/keymaps/drashna/config.h | 4 +- .../5x6_right/keymaps/drashna/rules.mk | 2 +- keyboards/hardwareabstraction/handwire/rules.mk | 2 +- keyboards/hillside/46/0_1/config.h | 4 +- keyboards/hillside/46/0_1/rules.mk | 2 +- keyboards/hillside/48/0_1/config.h | 4 +- keyboards/hillside/48/0_1/rules.mk | 2 +- keyboards/hillside/52/0_1/config.h | 4 +- keyboards/hillside/52/0_1/rules.mk | 2 +- .../ibm/model_m_4th_gen/overnumpad_1xb/rules.mk | 2 +- keyboards/mechwild/clunker/rules.mk | 2 +- keyboards/pearlboards/atlas/rules.mk | 2 +- keyboards/pearlboards/pearl/rules.mk | 2 +- keyboards/pearlboards/zeus/rules.mk | 2 +- keyboards/splitkb/zima/config.h | 4 +- keyboards/splitkb/zima/rules.mk | 2 +- .../overnumpad_1xb/rules.mk | 2 +- .../overnumpad_1xb/rules.mk | 2 +- keyboards/unicomp/pc122/overnumpad_1xb/rules.mk | 2 +- .../spacesaver_m_post_2013/overnumpad_1xb/rules.mk | 2 +- .../spacesaver_m_pre_2013/overnumpad_1xb/rules.mk | 2 +- keyboards/vertex/angle65/rules.mk | 2 +- keyboards/xw60/rules.mk | 2 +- layouts/community/ortho_4x12/drashna/config.h | 4 +- quantum/haptic.c | 81 ++-- quantum/haptic.h | 9 +- quantum/process_keycode/process_space_cadet.c | 3 + quantum/split_common/split_util.c | 1 + users/ishtob/ishtob.h | 2 +- 53 files changed, 667 insertions(+), 660 deletions(-) delete mode 100644 drivers/haptic/DRV2605L.c delete mode 100644 drivers/haptic/DRV2605L.h create mode 100644 drivers/haptic/drv2605l.c create mode 100644 drivers/haptic/drv2605l.h delete mode 100644 keyboards/hadron/ver3/keymaps/ishtob/config.h (limited to 'quantum/process_keycode') diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index 5687201d61..2de2bdd56b 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -721,18 +721,23 @@ ifeq ($(strip $(FNV_ENABLE)), yes) SRC += qmk_fnv_type_validation.c hash_32a.c hash_64a.c endif +VALID_HAPTIC_DRIVER_TYPES := drv2605l solenoid ifeq ($(strip $(HAPTIC_ENABLE)),yes) - COMMON_VPATH += $(DRIVER_PATH)/haptic + ifeq ($(filter $(HAPTIC_DRIVER),$(VALID_HAPTIC_DRIVER_TYPES)),) + $(call CATASTROPHIC_ERROR,Invalid HAPTIC_DRIVER,HAPTIC_DRIVER="$(HAPTIC_DRIVER)" is not a valid Haptic driver) + else + COMMON_VPATH += $(DRIVER_PATH)/haptic - ifneq ($(filter DRV2605L, $(HAPTIC_DRIVER)), ) - SRC += DRV2605L.c - QUANTUM_LIB_SRC += i2c_master.c - OPT_DEFS += -DDRV2605L - endif + ifeq ($(strip $(HAPTIC_DRIVER)), drv2605l) + SRC += drv2605l.c + QUANTUM_LIB_SRC += i2c_master.c + OPT_DEFS += -DHAPTIC_DRV2605L + endif - ifneq ($(filter SOLENOID, $(HAPTIC_DRIVER)), ) - SRC += solenoid.c - OPT_DEFS += -DSOLENOID_ENABLE + ifeq ($(strip $(HAPTIC_DRIVER)), solenoid) + SRC += solenoid.c + OPT_DEFS += -DHAPTIC_SOLENOID + endif endif endif diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md index b456bad736..02a231138d 100644 --- a/docs/feature_haptic_feedback.md +++ b/docs/feature_haptic_feedback.md @@ -4,11 +4,12 @@ The following options are currently available for haptic feedback in `rules.mk`: -``` +```make HAPTIC_ENABLE = yes -HAPTIC_DRIVER += DRV2605L -HAPTIC_DRIVER += SOLENOID +HAPTIC_DRIVER = drv2605l +# or +HAPTIC_DRIVER = solenoid ``` The following `config.h` settings are available for all types of haptic feedback: @@ -92,7 +93,7 @@ This driver supports 2 different feedback motors. Set the following in your `con Eccentric Rotating Mass vibration motors (ERM) is motor with a off-set weight attached so when drive signal is attached, the off-set weight spins and causes a sinusoidal wave that translate into vibrations. -``` +```c #define FB_ERM_LRA 0 #define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */ #define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */ @@ -105,7 +106,7 @@ Eccentric Rotating Mass vibration motors (ERM) is motor with a off-set weight at Linear resonant actuators (LRA, also know as a linear vibrator) works different from a ERM. A LRA has a weight and magnet suspended by springs and a voice coil. When the drive signal is applied, the weight would be vibrate on a single axis (side to side or up and down). Since the weight is attached to a spring, there is a resonance effect at a specific frequency. This frequency is where the LRA will operate the most efficiently. Refer to the motor's datasheet for the recommanded range for this frequency. -``` +```c #define FB_ERM_LRA 1 #define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */ #define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */ @@ -170,13 +171,13 @@ List of waveform sequences from the datasheet: | 42 | lg_dblclick_med_80 | 84 | transition_rampup_med_smooth1 | | | ### Optional DRV2605L defines -``` -#define DRV_GREETING *sequence name or number* +```c +#define DRV2605L_GREETING *sequence name or number* ``` If haptic feedback is enabled, the keyboard will vibrate to a specific sequence during startup. That can be selected using the following define: -``` -#define DRV_MODE_DEFAULT *sequence name or number* +```c +#define DRV2605L_DEFAULT_MODE *sequence name or number* ``` This will set what sequence `HF_RST` will set as the active mode. If not defined, mode will be set to 1 when `HF_RST` is pressed. diff --git a/drivers/haptic/DRV2605L.c b/drivers/haptic/DRV2605L.c deleted file mode 100644 index 5a1d2ca0af..0000000000 --- a/drivers/haptic/DRV2605L.c +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright 2018 ishtob - * Driver for DRV2605L written for 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 . - */ -#include "DRV2605L.h" -#include "print.h" -#include -#include -#include - -uint8_t DRV2605L_transfer_buffer[2]; -uint8_t DRV2605L_read_register; - -void DRV_write(uint8_t drv_register, uint8_t settings) { - DRV2605L_transfer_buffer[0] = drv_register; - DRV2605L_transfer_buffer[1] = settings; - i2c_transmit(DRV2605L_BASE_ADDRESS << 1, DRV2605L_transfer_buffer, 2, 100); -} - -uint8_t DRV_read(uint8_t regaddress) { - i2c_readReg(DRV2605L_BASE_ADDRESS << 1, regaddress, &DRV2605L_read_register, 1, 100); - - return DRV2605L_read_register; -} - -void DRV_init(void) { - i2c_init(); - /* 0x07 sets DRV2605 into calibration mode */ - DRV_write(DRV_MODE, 0x07); - - // DRV_write(DRV_FEEDBACK_CTRL,0xB6); - -#if FB_ERM_LRA == 0 - /* ERM settings */ - DRV_write(DRV_RATED_VOLT, (RATED_VOLTAGE / 21.33) * 1000); -# if ERM_OPEN_LOOP == 0 - DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (((V_PEAK * (DRIVE_TIME + BLANKING_TIME + IDISS_TIME)) / 0.02133) / (DRIVE_TIME - 0.0003))); -# elif ERM_OPEN_LOOP == 1 - DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK / 0.02196)); -# endif -#elif FB_ERM_LRA == 1 - DRV_write(DRV_RATED_VOLT, ((V_RMS * sqrt(1 - ((4 * ((150 + (SAMPLE_TIME * 50)) * 0.000001)) + 0.0003) * F_LRA) / 0.02071))); -# if LRA_OPEN_LOOP == 0 - DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, ((V_PEAK / sqrt(1 - (F_LRA * 0.0008)) / 0.02133))); -# elif LRA_OPEN_LOOP == 1 - DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK / 0.02196)); -# endif -#endif - - DRVREG_FBR FB_SET; - FB_SET.Bits.ERM_LRA = FB_ERM_LRA; - FB_SET.Bits.BRAKE_FACTOR = FB_BRAKEFACTOR; - FB_SET.Bits.LOOP_GAIN = FB_LOOPGAIN; - FB_SET.Bits.BEMF_GAIN = 0; /* auto-calibration populates this field*/ - DRV_write(DRV_FEEDBACK_CTRL, (uint8_t)FB_SET.Byte); - DRVREG_CTRL1 C1_SET; - C1_SET.Bits.C1_DRIVE_TIME = DRIVE_TIME; - C1_SET.Bits.C1_AC_COUPLE = AC_COUPLE; - C1_SET.Bits.C1_STARTUP_BOOST = STARTUP_BOOST; - DRV_write(DRV_CTRL_1, (uint8_t)C1_SET.Byte); - DRVREG_CTRL2 C2_SET; - C2_SET.Bits.C2_BIDIR_INPUT = BIDIR_INPUT; - C2_SET.Bits.C2_BRAKE_STAB = BRAKE_STAB; - C2_SET.Bits.C2_SAMPLE_TIME = SAMPLE_TIME; - C2_SET.Bits.C2_BLANKING_TIME = BLANKING_TIME; - C2_SET.Bits.C2_IDISS_TIME = IDISS_TIME; - DRV_write(DRV_CTRL_2, (uint8_t)C2_SET.Byte); - DRVREG_CTRL3 C3_SET; - C3_SET.Bits.C3_LRA_OPEN_LOOP = LRA_OPEN_LOOP; - C3_SET.Bits.C3_N_PWM_ANALOG = N_PWM_ANALOG; - C3_SET.Bits.C3_LRA_DRIVE_MODE = LRA_DRIVE_MODE; - C3_SET.Bits.C3_DATA_FORMAT_RTO = DATA_FORMAT_RTO; - C3_SET.Bits.C3_SUPPLY_COMP_DIS = SUPPLY_COMP_DIS; - C3_SET.Bits.C3_ERM_OPEN_LOOP = ERM_OPEN_LOOP; - C3_SET.Bits.C3_NG_THRESH = NG_THRESH; - DRV_write(DRV_CTRL_3, (uint8_t)C3_SET.Byte); - DRVREG_CTRL4 C4_SET; - C4_SET.Bits.C4_ZC_DET_TIME = ZC_DET_TIME; - C4_SET.Bits.C4_AUTO_CAL_TIME = AUTO_CAL_TIME; - DRV_write(DRV_CTRL_4, (uint8_t)C4_SET.Byte); - DRV_write(DRV_LIB_SELECTION, LIB_SELECTION); - - DRV_write(DRV_GO, 0x01); - - /* 0x00 sets DRV2605 out of standby and to use internal trigger - * 0x01 sets DRV2605 out of standby and to use external trigger */ - DRV_write(DRV_MODE, 0x00); - - // Play greeting sequence - DRV_write(DRV_GO, 0x00); - DRV_write(DRV_WAVEFORM_SEQ_1, DRV_GREETING); - DRV_write(DRV_GO, 0x01); -} - -void DRV_rtp_init(void) { - DRV_write(DRV_GO, 0x00); - DRV_write(DRV_RTP_INPUT, 20); // 20 is the lowest value I've found where haptics can still be felt. - DRV_write(DRV_MODE, 0x05); - DRV_write(DRV_GO, 0x01); -} - -void DRV_amplitude(uint8_t amplitude) { - DRV_write(DRV_RTP_INPUT, amplitude); -} - -void DRV_pulse(uint8_t sequence) { - DRV_write(DRV_GO, 0x00); - DRV_write(DRV_WAVEFORM_SEQ_1, sequence); - DRV_write(DRV_GO, 0x01); -} diff --git a/drivers/haptic/DRV2605L.h b/drivers/haptic/DRV2605L.h deleted file mode 100644 index 8b8eae38b8..0000000000 --- a/drivers/haptic/DRV2605L.h +++ /dev/null @@ -1,406 +0,0 @@ -/* Copyright 2018 ishtob - * Driver for DRV2605L written for 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 . - */ - -#pragma once -#include "i2c_master.h" - -/* Initialization settings - - * Feedback Control Settings */ -#ifndef FB_ERM_LRA -# define FB_ERM_LRA 1 /* For ERM:0 or LRA:1*/ -#endif -#ifndef FB_BRAKEFACTOR -# define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */ -#endif -#ifndef FB_LOOPGAIN -# define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */ -#endif - -/* LRA specific settings */ -#if FB_ERM_LRA == 1 -# ifndef V_RMS -# define V_RMS 2.0 -# endif -# ifndef V_PEAK -# define V_PEAK 2.1 -# endif -# ifndef F_LRA -# define F_LRA 205 -# endif -# ifndef RATED_VOLTAGE -# define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */ -# endif -#endif - -#ifndef RATED_VOLTAGE -# define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */ -#endif -#ifndef V_PEAK -# define V_PEAK 2.8 -#endif - -/* Library Selection */ -#ifndef LIB_SELECTION -# if FB_ERM_LRA == 1 -# define LIB_SELECTION 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ -# else -# define LIB_SELECTION 1 -# endif -#endif - -#ifndef DRV_GREETING -# define DRV_GREETING alert_750ms -#endif -#ifndef DRV_MODE_DEFAULT -# define DRV_MODE_DEFAULT strong_click1 -#endif - -/* Control 1 register settings */ -#ifndef DRIVE_TIME -# define DRIVE_TIME 25 -#endif -#ifndef AC_COUPLE -# define AC_COUPLE 0 -#endif -#ifndef STARTUP_BOOST -# define STARTUP_BOOST 1 -#endif - -/* Control 2 Settings */ -#ifndef BIDIR_INPUT -# define BIDIR_INPUT 1 -#endif -#ifndef BRAKE_STAB -# define BRAKE_STAB 1 /* Loopgain is reduced when braking is almost complete to improve stability */ -#endif -#ifndef SAMPLE_TIME -# define SAMPLE_TIME 3 -#endif -#ifndef BLANKING_TIME -# define BLANKING_TIME 1 -#endif -#ifndef IDISS_TIME -# define IDISS_TIME 1 -#endif - -/* Control 3 settings */ -#ifndef NG_THRESH -# define NG_THRESH 2 -#endif -#ifndef ERM_OPEN_LOOP -# define ERM_OPEN_LOOP 1 -#endif -#ifndef SUPPLY_COMP_DIS -# define SUPPLY_COMP_DIS 0 -#endif -#ifndef DATA_FORMAT_RTO -# define DATA_FORMAT_RTO 0 -#endif -#ifndef LRA_DRIVE_MODE -# define LRA_DRIVE_MODE 0 -#endif -#ifndef N_PWM_ANALOG -# define N_PWM_ANALOG 0 -#endif -#ifndef LRA_OPEN_LOOP -# define LRA_OPEN_LOOP 0 -#endif - -/* Control 4 settings */ -#ifndef ZC_DET_TIME -# define ZC_DET_TIME 0 -#endif -#ifndef AUTO_CAL_TIME -# define AUTO_CAL_TIME 3 -#endif - -/* register defines -------------------------------------------------------- */ -#define DRV2605L_BASE_ADDRESS 0x5A /* DRV2605L Base address */ -#define DRV_STATUS 0x00 -#define DRV_MODE 0x01 -#define DRV_RTP_INPUT 0x02 -#define DRV_LIB_SELECTION 0x03 -#define DRV_WAVEFORM_SEQ_1 0x04 -#define DRV_WAVEFORM_SEQ_2 0x05 -#define DRV_WAVEFORM_SEQ_3 0x06 -#define DRV_WAVEFORM_SEQ_4 0x07 -#define DRV_WAVEFORM_SEQ_5 0x08 -#define DRV_WAVEFORM_SEQ_6 0x09 -#define DRV_WAVEFORM_SEQ_7 0x0A -#define DRV_WAVEFORM_SEQ_8 0x0B -#define DRV_GO 0x0C -#define DRV_OVERDRIVE_TIME_OFFSET 0x0D -#define DRV_SUSTAIN_TIME_OFFSET_P 0x0E -#define DRV_SUSTAIN_TIME_OFFSET_N 0x0F -#define DRV_BRAKE_TIME_OFFSET 0x10 -#define DRV_AUDIO_2_VIBE_CTRL 0x11 -#define DRV_AUDIO_2_VIBE_MIN_IN 0x12 -#define DRV_AUDIO_2_VIBE_MAX_IN 0x13 -#define DRV_AUDIO_2_VIBE_MIN_OUTDRV 0x14 -#define DRV_AUDIO_2_VIBE_MAX_OUTDRV 0x15 -#define DRV_RATED_VOLT 0x16 -#define DRV_OVERDRIVE_CLAMP_VOLT 0x17 -#define DRV_AUTO_CALIB_COMP_RESULT 0x18 -#define DRV_AUTO_CALIB_BEMF_RESULT 0x19 -#define DRV_FEEDBACK_CTRL 0x1A -#define DRV_CTRL_1 0x1B -#define DRV_CTRL_2 0x1C -#define DRV_CTRL_3 0x1D -#define DRV_CTRL_4 0x1E -#define DRV_CTRL_5 0x1F -#define DRV_OPEN_LOOP_PERIOD 0x20 -#define DRV_VBAT_VOLT_MONITOR 0x21 -#define DRV_LRA_RESONANCE_PERIOD 0x22 - -void DRV_init(void); -void DRV_write(const uint8_t drv_register, const uint8_t settings); -uint8_t DRV_read(const uint8_t regaddress); -void DRV_rtp_init(void); -void DRV_amplitude(const uint8_t amplitude); -void DRV_pulse(const uint8_t sequence); - -typedef enum DRV_EFFECT { - clear_sequence = 0, - strong_click = 1, - strong_click_60 = 2, - strong_click_30 = 3, - sharp_click = 4, - sharp_click_60 = 5, - sharp_click_30 = 6, - soft_bump = 7, - soft_bump_60 = 8, - soft_bump_30 = 9, - dbl_click = 10, - dbl_click_60 = 11, - trp_click = 12, - soft_fuzz = 13, - strong_buzz = 14, - alert_750ms = 15, - alert_1000ms = 16, - strong_click1 = 17, - strong_click2_80 = 18, - strong_click3_60 = 19, - strong_click4_30 = 20, - medium_click1 = 21, - medium_click2_80 = 22, - medium_click3_60 = 23, - sharp_tick1 = 24, - sharp_tick2_80 = 25, - sharp_tick3_60 = 26, - sh_dblclick_str = 27, - sh_dblclick_str_80 = 28, - sh_dblclick_str_60 = 29, - sh_dblclick_str_30 = 30, - sh_dblclick_med = 31, - sh_dblclick_med_80 = 32, - sh_dblclick_med_60 = 33, - sh_dblsharp_tick = 34, - sh_dblsharp_tick_80 = 35, - sh_dblsharp_tick_60 = 36, - lg_dblclick_str = 37, - lg_dblclick_str_80 = 38, - lg_dblclick_str_60 = 39, - lg_dblclick_str_30 = 40, - lg_dblclick_med = 41, - lg_dblclick_med_80 = 42, - lg_dblclick_med_60 = 43, - lg_dblsharp_tick = 44, - lg_dblsharp_tick_80 = 45, - lg_dblsharp_tick_60 = 46, - buzz = 47, - buzz_80 = 48, - buzz_60 = 49, - buzz_40 = 50, - buzz_20 = 51, - pulsing_strong = 52, - pulsing_strong_80 = 53, - pulsing_medium = 54, - pulsing_medium_80 = 55, - pulsing_sharp = 56, - pulsing_sharp_80 = 57, - transition_click = 58, - transition_click_80 = 59, - transition_click_60 = 60, - transition_click_40 = 61, - transition_click_20 = 62, - transition_click_10 = 63, - transition_hum = 64, - transition_hum_80 = 65, - transition_hum_60 = 66, - transition_hum_40 = 67, - transition_hum_20 = 68, - transition_hum_10 = 69, - transition_rampdown_long_smooth1 = 70, - transition_rampdown_long_smooth2 = 71, - transition_rampdown_med_smooth1 = 72, - transition_rampdown_med_smooth2 = 73, - transition_rampdown_short_smooth1 = 74, - transition_rampdown_short_smooth2 = 75, - transition_rampdown_long_sharp1 = 76, - transition_rampdown_long_sharp2 = 77, - transition_rampdown_med_sharp1 = 78, - transition_rampdown_med_sharp2 = 79, - transition_rampdown_short_sharp1 = 80, - transition_rampdown_short_sharp2 = 81, - transition_rampup_long_smooth1 = 82, - transition_rampup_long_smooth2 = 83, - transition_rampup_med_smooth1 = 84, - transition_rampup_med_smooth2 = 85, - transition_rampup_short_smooth1 = 86, - transition_rampup_short_smooth2 = 87, - transition_rampup_long_sharp1 = 88, - transition_rampup_long_sharp2 = 89, - transition_rampup_med_sharp1 = 90, - transition_rampup_med_sharp2 = 91, - transition_rampup_short_sharp1 = 92, - transition_rampup_short_sharp2 = 93, - transition_rampdown_long_smooth1_50 = 94, - transition_rampdown_long_smooth2_50 = 95, - transition_rampdown_med_smooth1_50 = 96, - transition_rampdown_med_smooth2_50 = 97, - transition_rampdown_short_smooth1_50 = 98, - transition_rampdown_short_smooth2_50 = 99, - transition_rampdown_long_sharp1_50 = 100, - transition_rampdown_long_sharp2_50 = 101, - transition_rampdown_med_sharp1_50 = 102, - transition_rampdown_med_sharp2_50 = 103, - transition_rampdown_short_sharp1_50 = 104, - transition_rampdown_short_sharp2_50 = 105, - transition_rampup_long_smooth1_50 = 106, - transition_rampup_long_smooth2_50 = 107, - transition_rampup_med_smooth1_50 = 108, - transition_rampup_med_smooth2_50 = 109, - transition_rampup_short_smooth1_50 = 110, - transition_rampup_short_smooth2_50 = 111, - transition_rampup_long_sharp1_50 = 112, - transition_rampup_long_sharp2_50 = 113, - transition_rampup_med_sharp1_50 = 114, - transition_rampup_med_sharp2_50 = 115, - transition_rampup_short_sharp1_50 = 116, - transition_rampup_short_sharp2_50 = 117, - long_buzz_for_programmatic_stopping = 118, - smooth_hum1_50 = 119, - smooth_hum2_40 = 120, - smooth_hum3_30 = 121, - smooth_hum4_20 = 122, - smooth_hum5_10 = 123, - drv_effect_max = 124, -} DRV_EFFECT; - -/* Register bit array unions */ - -typedef union DRVREG_STATUS { /* register 0x00 */ - uint8_t Byte; - struct { - uint8_t OC_DETECT : 1; /* set to 1 when overcurrent event is detected */ - uint8_t OVER_TEMP : 1; /* set to 1 when device exceeds temp threshold */ - uint8_t FB_STS : 1; /* set to 1 when feedback controller has timed out */ - /* auto-calibration routine and diagnostic result - * result | auto-calibation | diagnostic | - * 0 | passed | actuator func normal | - * 1 | failed | actuator func fault* | - * * actuator is not present or is shorted, timing out, or giving out–of-range back-EMF */ - uint8_t DIAG_RESULT : 1; - uint8_t : 1; - uint8_t DEVICE_ID : 3; /* Device IDs 3: DRV2605 4: DRV2604 5: DRV2604L 6: DRV2605L */ - } Bits; -} DRVREG_STATUS; - -typedef union DRVREG_MODE { /* register 0x01 */ - uint8_t Byte; - struct { - uint8_t MODE : 3; /* Mode setting */ - uint8_t : 3; - uint8_t STANDBY : 1; /* 0:standby 1:ready */ - } Bits; -} DRVREG_MODE; - -typedef union DRVREG_WAIT { - uint8_t Byte; - struct { - uint8_t WAIT_MODE : 1; /* Set to 1 to interpret as wait for next 7 bits x10ms */ - uint8_t WAIT_TIME : 7; - } Bits; -} DRVREG_WAIT; - -typedef union DRVREG_FBR { /* register 0x1A */ - uint8_t Byte; - struct { - uint8_t BEMF_GAIN : 2; - uint8_t LOOP_GAIN : 2; - uint8_t BRAKE_FACTOR : 3; - uint8_t ERM_LRA : 1; - } Bits; -} DRVREG_FBR; - -typedef union DRVREG_CTRL1 { /* register 0x1B */ - uint8_t Byte; - struct { - uint8_t C1_DRIVE_TIME : 5; - uint8_t C1_AC_COUPLE : 1; - uint8_t : 1; - uint8_t C1_STARTUP_BOOST : 1; - } Bits; -} DRVREG_CTRL1; - -typedef union DRVREG_CTRL2 { /* register 0x1C */ - uint8_t Byte; - struct { - uint8_t C2_IDISS_TIME : 2; - uint8_t C2_BLANKING_TIME : 2; - uint8_t C2_SAMPLE_TIME : 2; - uint8_t C2_BRAKE_STAB : 1; - uint8_t C2_BIDIR_INPUT : 1; - } Bits; -} DRVREG_CTRL2; - -typedef union DRVREG_CTRL3 { /* register 0x1D */ - uint8_t Byte; - struct { - uint8_t C3_LRA_OPEN_LOOP : 1; - uint8_t C3_N_PWM_ANALOG : 1; - uint8_t C3_LRA_DRIVE_MODE : 1; - uint8_t C3_DATA_FORMAT_RTO : 1; - uint8_t C3_SUPPLY_COMP_DIS : 1; - uint8_t C3_ERM_OPEN_LOOP : 1; - uint8_t C3_NG_THRESH : 2; - } Bits; -} DRVREG_CTRL3; - -typedef union DRVREG_CTRL4 { /* register 0x1E */ - uint8_t Byte; - struct { - uint8_t C4_OTP_PROGRAM : 1; - uint8_t : 1; - uint8_t C4_OTP_STATUS : 1; - uint8_t : 1; - uint8_t C4_AUTO_CAL_TIME : 2; - uint8_t C4_ZC_DET_TIME : 2; - } Bits; -} DRVREG_CTRL4; - -typedef union DRVREG_CTRL5 { /* register 0x1F */ - uint8_t Byte; - struct { - uint8_t C5_IDISS_TIME : 2; - uint8_t C5_BLANKING_TIME : 2; - uint8_t C5_PLAYBACK_INTERVAL : 1; - uint8_t C5_LRA_AUTO_OPEN_LOOP : 1; - uint8_t C5_AUTO_OL_CNT : 2; - } Bits; -} DRVREG_CTRL5; diff --git a/drivers/haptic/drv2605l.c b/drivers/haptic/drv2605l.c new file mode 100644 index 0000000000..7613dc59d1 --- /dev/null +++ b/drivers/haptic/drv2605l.c @@ -0,0 +1,126 @@ +/* Copyright 2018 ishtob + * Driver for DRV2605L written for 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 . + */ + +#include "drv2605l.h" +#include "i2c_master.h" +#include + +uint8_t drv2605l_write_buffer[2]; +uint8_t drv2605l_read_buffer; + +void drv2605l_write(uint8_t reg_addr, uint8_t data) { + drv2605l_write_buffer[0] = reg_addr; + drv2605l_write_buffer[1] = data; + i2c_transmit(DRV2605L_I2C_ADDRESS << 1, drv2605l_write_buffer, 2, 100); +} + +uint8_t drv2605l_read(uint8_t reg_addr) { + i2c_readReg(DRV2605L_I2C_ADDRESS << 1, reg_addr, &drv2605l_read_buffer, 1, 100); + + return drv2605l_read_buffer; +} + +void drv2605l_init(void) { + i2c_init(); + /* 0x07 sets DRV2605 into calibration mode */ + drv2605l_write(DRV2605L_REG_MODE, 0x07); + + // drv2605l_write(DRV2605L_REG_FEEDBACK_CTRL,0xB6); + +#if FB_ERM_LRA == 0 + /* ERM settings */ + drv2605l_write(DRV2605L_REG_RATED_VOLTAGE, (RATED_VOLTAGE / 21.33) * 1000); +# if ERM_OPEN_LOOP == 0 + drv2605l_write(DRV2605L_REG_OVERDRIVE_CLAMP_VOLTAGE, (((V_PEAK * (DRIVE_TIME + BLANKING_TIME + IDISS_TIME)) / 0.02133) / (DRIVE_TIME - 0.0003))); +# elif ERM_OPEN_LOOP == 1 + drv2605l_write(DRV2605L_REG_OVERDRIVE_CLAMP_VOLTAGE, (V_PEAK / 0.02196)); +# endif +#elif FB_ERM_LRA == 1 + drv2605l_write(DRV2605L_REG_RATED_VOLTAGE, ((V_RMS * sqrt(1 - ((4 * ((150 + (SAMPLE_TIME * 50)) * 0.000001)) + 0.0003) * F_LRA) / 0.02071))); +# if LRA_OPEN_LOOP == 0 + drv2605l_write(DRV2605L_REG_OVERDRIVE_CLAMP_VOLTAGE, ((V_PEAK / sqrt(1 - (F_LRA * 0.0008)) / 0.02133))); +# elif LRA_OPEN_LOOP == 1 + drv2605l_write(DRV2605L_REG_OVERDRIVE_CLAMP_VOLTAGE, (V_PEAK / 0.02196)); +# endif +#endif + + DRVREG_FBR FB_SET; + FB_SET.Bits.ERM_LRA = FB_ERM_LRA; + FB_SET.Bits.BRAKE_FACTOR = FB_BRAKEFACTOR; + FB_SET.Bits.LOOP_GAIN = FB_LOOPGAIN; + FB_SET.Bits.BEMF_GAIN = 0; /* auto-calibration populates this field*/ + drv2605l_write(DRV2605L_REG_FEEDBACK_CTRL, (uint8_t)FB_SET.Byte); + + DRVREG_CTRL1 C1_SET; + C1_SET.Bits.C1_DRIVE_TIME = DRIVE_TIME; + C1_SET.Bits.C1_AC_COUPLE = AC_COUPLE; + C1_SET.Bits.C1_STARTUP_BOOST = STARTUP_BOOST; + drv2605l_write(DRV2605L_REG_CTRL1, (uint8_t)C1_SET.Byte); + + DRVREG_CTRL2 C2_SET; + C2_SET.Bits.C2_BIDIR_INPUT = BIDIR_INPUT; + C2_SET.Bits.C2_BRAKE_STAB = BRAKE_STAB; + C2_SET.Bits.C2_SAMPLE_TIME = SAMPLE_TIME; + C2_SET.Bits.C2_BLANKING_TIME = BLANKING_TIME; + C2_SET.Bits.C2_IDISS_TIME = IDISS_TIME; + drv2605l_write(DRV2605L_REG_CTRL2, (uint8_t)C2_SET.Byte); + + DRVREG_CTRL3 C3_SET; + C3_SET.Bits.C3_LRA_OPEN_LOOP = LRA_OPEN_LOOP; + C3_SET.Bits.C3_N_PWM_ANALOG = N_PWM_ANALOG; + C3_SET.Bits.C3_LRA_DRIVE_MODE = LRA_DRIVE_MODE; + C3_SET.Bits.C3_DATA_FORMAT_RTO = DATA_FORMAT_RTO; + C3_SET.Bits.C3_SUPPLY_COMP_DIS = SUPPLY_COMP_DIS; + C3_SET.Bits.C3_ERM_OPEN_LOOP = ERM_OPEN_LOOP; + C3_SET.Bits.C3_NG_THRESH = NG_THRESH; + drv2605l_write(DRV2605L_REG_CTRL3, (uint8_t)C3_SET.Byte); + + DRVREG_CTRL4 C4_SET; + C4_SET.Bits.C4_ZC_DET_TIME = ZC_DET_TIME; + C4_SET.Bits.C4_AUTO_CAL_TIME = AUTO_CAL_TIME; + drv2605l_write(DRV2605L_REG_CTRL4, (uint8_t)C4_SET.Byte); + + drv2605l_write(DRV2605L_REG_LIBRARY_SELECTION, DRV2605L_LIBRARY); + + drv2605l_write(DRV2605L_REG_GO, 0x01); + + /* 0x00 sets DRV2605 out of standby and to use internal trigger + * 0x01 sets DRV2605 out of standby and to use external trigger */ + drv2605l_write(DRV2605L_REG_MODE, 0x00); + + // Play greeting sequence + drv2605l_write(DRV2605L_REG_GO, 0x00); + drv2605l_write(DRV2605L_REG_WAVEFORM_SEQUENCER_1, DRV2605L_GREETING); + drv2605l_write(DRV2605L_REG_GO, 0x01); +} + +void drv2605l_rtp_init(void) { + drv2605l_write(DRV2605L_REG_GO, 0x00); + drv2605l_write(DRV2605L_REG_RTP_INPUT, 20); // 20 is the lowest value I've found where haptics can still be felt. + drv2605l_write(DRV2605L_REG_MODE, 0x05); + drv2605l_write(DRV2605L_REG_GO, 0x01); +} + +void drv2605l_amplitude(uint8_t amplitude) { + drv2605l_write(DRV2605L_REG_RTP_INPUT, amplitude); +} + +void drv2605l_pulse(uint8_t sequence) { + drv2605l_write(DRV2605L_REG_GO, 0x00); + drv2605l_write(DRV2605L_REG_WAVEFORM_SEQUENCER_1, sequence); + drv2605l_write(DRV2605L_REG_GO, 0x01); +} diff --git a/drivers/haptic/drv2605l.h b/drivers/haptic/drv2605l.h new file mode 100644 index 0000000000..796611edb6 --- /dev/null +++ b/drivers/haptic/drv2605l.h @@ -0,0 +1,407 @@ +/* Copyright 2018 ishtob + * Driver for DRV2605L written for 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 . + */ + +#pragma once + +#include + +/* Initialization settings + + * Feedback Control Settings */ +#ifndef FB_ERM_LRA +# define FB_ERM_LRA 1 /* For ERM:0 or LRA:1*/ +#endif +#ifndef FB_BRAKEFACTOR +# define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */ +#endif +#ifndef FB_LOOPGAIN +# define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */ +#endif + +/* LRA specific settings */ +#if FB_ERM_LRA == 1 +# ifndef V_RMS +# define V_RMS 2.0 +# endif +# ifndef V_PEAK +# define V_PEAK 2.1 +# endif +# ifndef F_LRA +# define F_LRA 205 +# endif +# ifndef RATED_VOLTAGE +# define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */ +# endif +#endif + +#ifndef RATED_VOLTAGE +# define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */ +#endif +#ifndef V_PEAK +# define V_PEAK 2.8 +#endif + +/* Library Selection */ +#ifndef DRV2605L_LIBRARY +# if FB_ERM_LRA == 1 +# define DRV2605L_LIBRARY 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ +# else +# define DRV2605L_LIBRARY 1 +# endif +#endif + +#ifndef DRV2605L_GREETING +# define DRV2605L_GREETING alert_750ms +#endif +#ifndef DRV2605L_DEFAULT_MODE +# define DRV2605L_DEFAULT_MODE strong_click1 +#endif + +/* Control 1 register settings */ +#ifndef DRIVE_TIME +# define DRIVE_TIME 25 +#endif +#ifndef AC_COUPLE +# define AC_COUPLE 0 +#endif +#ifndef STARTUP_BOOST +# define STARTUP_BOOST 1 +#endif + +/* Control 2 Settings */ +#ifndef BIDIR_INPUT +# define BIDIR_INPUT 1 +#endif +#ifndef BRAKE_STAB +# define BRAKE_STAB 1 /* Loopgain is reduced when braking is almost complete to improve stability */ +#endif +#ifndef SAMPLE_TIME +# define SAMPLE_TIME 3 +#endif +#ifndef BLANKING_TIME +# define BLANKING_TIME 1 +#endif +#ifndef IDISS_TIME +# define IDISS_TIME 1 +#endif + +/* Control 3 settings */ +#ifndef NG_THRESH +# define NG_THRESH 2 +#endif +#ifndef ERM_OPEN_LOOP +# define ERM_OPEN_LOOP 1 +#endif +#ifndef SUPPLY_COMP_DIS +# define SUPPLY_COMP_DIS 0 +#endif +#ifndef DATA_FORMAT_RTO +# define DATA_FORMAT_RTO 0 +#endif +#ifndef LRA_DRIVE_MODE +# define LRA_DRIVE_MODE 0 +#endif +#ifndef N_PWM_ANALOG +# define N_PWM_ANALOG 0 +#endif +#ifndef LRA_OPEN_LOOP +# define LRA_OPEN_LOOP 0 +#endif + +/* Control 4 settings */ +#ifndef ZC_DET_TIME +# define ZC_DET_TIME 0 +#endif +#ifndef AUTO_CAL_TIME +# define AUTO_CAL_TIME 3 +#endif + +#define DRV2605L_I2C_ADDRESS 0x5A + +#define DRV2605L_REG_STATUS 0x00 +#define DRV2605L_REG_MODE 0x01 +#define DRV2605L_REG_RTP_INPUT 0x02 +#define DRV2605L_REG_LIBRARY_SELECTION 0x03 +#define DRV2605L_REG_WAVEFORM_SEQUENCER_1 0x04 +#define DRV2605L_REG_WAVEFORM_SEQUENCER_2 0x05 +#define DRV2605L_REG_WAVEFORM_SEQUENCER_3 0x06 +#define DRV2605L_REG_WAVEFORM_SEQUENCER_4 0x07 +#define DRV2605L_REG_WAVEFORM_SEQUENCER_5 0x08 +#define DRV2605L_REG_WAVEFORM_SEQUENCER_6 0x09 +#define DRV2605L_REG_WAVEFORM_SEQUENCER_7 0x0A +#define DRV2605L_REG_WAVEFORM_SEQUENCER_8 0x0B +#define DRV2605L_REG_GO 0x0C +#define DRV2605L_REG_OVERDRIVE_TIME_OFFSET 0x0D +#define DRV2605L_REG_SUSTAIN_TIME_OFFSET_P 0x0E +#define DRV2605L_REG_SUSTAIN_TIME_OFFSET_N 0x0F +#define DRV2605L_REG_BRAKE_TIME_OFFSET 0x10 +#define DRV2605L_REG_AUDIO_TO_VIBE_CTRL 0x11 +#define DRV2605L_REG_AUDIO_TO_VIBE_MIN_INPUT 0x12 +#define DRV2605L_REG_AUDIO_TO_VIBE_MAX_INPUT 0x13 +#define DRV2605L_REG_AUDIO_TO_VIBE_MIN_OUTPUT_DRIVE 0x14 +#define DRV2605L_REG_AUDIO_TO_VIBE_MAX_OUTPUT_DRIVE 0x15 +#define DRV2605L_REG_RATED_VOLTAGE 0x16 +#define DRV2605L_REG_OVERDRIVE_CLAMP_VOLTAGE 0x17 +#define DRV2605L_REG_AUTO_CALIBRATION_COMPENSATION_RESULT 0x18 +#define DRV2605L_REG_AUTO_CALIBRATION_BACK_EMF_RESULT 0x19 +#define DRV2605L_REG_FEEDBACK_CTRL 0x1A +#define DRV2605L_REG_CTRL1 0x1B +#define DRV2605L_REG_CTRL2 0x1C +#define DRV2605L_REG_CTRL3 0x1D +#define DRV2605L_REG_CTRL4 0x1E +#define DRV2605L_REG_CTRL5 0x1F +#define DRV2605L_REG_LRA_OPEN_LOOP_PERIOD 0x20 +#define DRV2605L_REG_VBAT_VOLTAGE_MONITOR 0x21 +#define DRV2605L_REG_LRA_RESONANCE_PERIOD 0x22 + +void drv2605l_init(void); +void drv2605l_write(const uint8_t reg_addr, const uint8_t data); +uint8_t drv2605l_read(const uint8_t reg_addr); +void drv2605l_rtp_init(void); +void drv2605l_amplitude(const uint8_t amplitude); +void drv2605l_pulse(const uint8_t sequence); + +typedef enum DRV_EFFECT { + clear_sequence, + strong_click, + strong_click_60, + strong_click_30, + sharp_click, + sharp_click_60, + sharp_click_30, + soft_bump, + soft_bump_60, + soft_bump_30, + dbl_click, + dbl_click_60, + trp_click, + soft_fuzz, + strong_buzz, + alert_750ms, + alert_1000ms, + strong_click1, + strong_click2_80, + strong_click3_60, + strong_click4_30, + medium_click1, + medium_click2_80, + medium_click3_60, + sharp_tick1, + sharp_tick2_80, + sharp_tick3_60, + sh_dblclick_str, + sh_dblclick_str_80, + sh_dblclick_str_60, + sh_dblclick_str_30, + sh_dblclick_med, + sh_dblclick_med_80, + sh_dblclick_med_60, + sh_dblsharp_tick, + sh_dblsharp_tick_80, + sh_dblsharp_tick_60, + lg_dblclick_str, + lg_dblclick_str_80, + lg_dblclick_str_60, + lg_dblclick_str_30, + lg_dblclick_med, + lg_dblclick_med_80, + lg_dblclick_med_60, + lg_dblsharp_tick, + lg_dblsharp_tick_80, + lg_dblsharp_tick_60, + buzz, + buzz_80, + buzz_60, + buzz_40, + buzz_20, + pulsing_strong, + pulsing_strong_80, + pulsing_medium, + pulsing_medium_80, + pulsing_sharp, + pulsing_sharp_80, + transition_click, + transition_click_80, + transition_click_60, + transition_click_40, + transition_click_20, + transition_click_10, + transition_hum, + transition_hum_80, + transition_hum_60, + transition_hum_40, + transition_hum_20, + transition_hum_10, + transition_rampdown_long_smooth1, + transition_rampdown_long_smooth2, + transition_rampdown_med_smooth1, + transition_rampdown_med_smooth2, + transition_rampdown_short_smooth1, + transition_rampdown_short_smooth2, + transition_rampdown_long_sharp1, + transition_rampdown_long_sharp2, + transition_rampdown_med_sharp1, + transition_rampdown_med_sharp2, + transition_rampdown_short_sharp1, + transition_rampdown_short_sharp2, + transition_rampup_long_smooth1, + transition_rampup_long_smooth2, + transition_rampup_med_smooth1, + transition_rampup_med_smooth2, + transition_rampup_short_smooth1, + transition_rampup_short_smooth2, + transition_rampup_long_sharp1, + transition_rampup_long_sharp2, + transition_rampup_med_sharp1, + transition_rampup_med_sharp2, + transition_rampup_short_sharp1, + transition_rampup_short_sharp2, + transition_rampdown_long_smooth1_50, + transition_rampdown_long_smooth2_50, + transition_rampdown_med_smooth1_50, + transition_rampdown_med_smooth2_50, + transition_rampdown_short_smooth1_50, + transition_rampdown_short_smooth2_50, + transition_rampdown_long_sharp1_50, + transition_rampdown_long_sharp2_50, + transition_rampdown_med_sharp1_50, + transition_rampdown_med_sharp2_50, + transition_rampdown_short_sharp1_50, + transition_rampdown_short_sharp2_50, + transition_rampup_long_smooth1_50, + transition_rampup_long_smooth2_50, + transition_rampup_med_smooth1_50, + transition_rampup_med_smooth2_50, + transition_rampup_short_smooth1_50, + transition_rampup_short_smooth2_50, + transition_rampup_long_sharp1_50, + transition_rampup_long_sharp2_50, + transition_rampup_med_sharp1_50, + transition_rampup_med_sharp2_50, + transition_rampup_short_sharp1_50, + transition_rampup_short_sharp2_50, + long_buzz_for_programmatic_stopping, + smooth_hum1_50, + smooth_hum2_40, + smooth_hum3_30, + smooth_hum4_20, + smooth_hum5_10, + drv_effect_max +} DRV_EFFECT; + +/* Register bit array unions */ + +typedef union DRVREG_STATUS { /* register 0x00 */ + uint8_t Byte; + struct { + uint8_t OC_DETECT : 1; /* set to 1 when overcurrent event is detected */ + uint8_t OVER_TEMP : 1; /* set to 1 when device exceeds temp threshold */ + uint8_t FB_STS : 1; /* set to 1 when feedback controller has timed out */ + /* auto-calibration routine and diagnostic result + * result | auto-calibation | diagnostic | + * 0 | passed | actuator func normal | + * 1 | failed | actuator func fault* | + * * actuator is not present or is shorted, timing out, or giving out–of-range back-EMF */ + uint8_t DIAG_RESULT : 1; + uint8_t : 1; + uint8_t DEVICE_ID : 3; /* Device IDs 3: DRV2605 4: DRV2604 5: DRV2604L 6: DRV2605L */ + } Bits; +} DRVREG_STATUS; + +typedef union DRVREG_MODE { /* register 0x01 */ + uint8_t Byte; + struct { + uint8_t MODE : 3; /* Mode setting */ + uint8_t : 3; + uint8_t STANDBY : 1; /* 0:standby 1:ready */ + } Bits; +} DRVREG_MODE; + +typedef union DRVREG_WAIT { + uint8_t Byte; + struct { + uint8_t WAIT_MODE : 1; /* Set to 1 to interpret as wait for next 7 bits x10ms */ + uint8_t WAIT_TIME : 7; + } Bits; +} DRVREG_WAIT; + +typedef union DRVREG_FBR { /* register 0x1A */ + uint8_t Byte; + struct { + uint8_t BEMF_GAIN : 2; + uint8_t LOOP_GAIN : 2; + uint8_t BRAKE_FACTOR : 3; + uint8_t ERM_LRA : 1; + } Bits; +} DRVREG_FBR; + +typedef union DRVREG_CTRL1 { /* register 0x1B */ + uint8_t Byte; + struct { + uint8_t C1_DRIVE_TIME : 5; + uint8_t C1_AC_COUPLE : 1; + uint8_t : 1; + uint8_t C1_STARTUP_BOOST : 1; + } Bits; +} DRVREG_CTRL1; + +typedef union DRVREG_CTRL2 { /* register 0x1C */ + uint8_t Byte; + struct { + uint8_t C2_IDISS_TIME : 2; + uint8_t C2_BLANKING_TIME : 2; + uint8_t C2_SAMPLE_TIME : 2; + uint8_t C2_BRAKE_STAB : 1; + uint8_t C2_BIDIR_INPUT : 1; + } Bits; +} DRVREG_CTRL2; + +typedef union DRVREG_CTRL3 { /* register 0x1D */ + uint8_t Byte; + struct { + uint8_t C3_LRA_OPEN_LOOP : 1; + uint8_t C3_N_PWM_ANALOG : 1; + uint8_t C3_LRA_DRIVE_MODE : 1; + uint8_t C3_DATA_FORMAT_RTO : 1; + uint8_t C3_SUPPLY_COMP_DIS : 1; + uint8_t C3_ERM_OPEN_LOOP : 1; + uint8_t C3_NG_THRESH : 2; + } Bits; +} DRVREG_CTRL3; + +typedef union DRVREG_CTRL4 { /* register 0x1E */ + uint8_t Byte; + struct { + uint8_t C4_OTP_PROGRAM : 1; + uint8_t : 1; + uint8_t C4_OTP_STATUS : 1; + uint8_t : 1; + uint8_t C4_AUTO_CAL_TIME : 2; + uint8_t C4_ZC_DET_TIME : 2; + } Bits; +} DRVREG_CTRL4; + +typedef union DRVREG_CTRL5 { /* register 0x1F */ + uint8_t Byte; + struct { + uint8_t C5_IDISS_TIME : 2; + uint8_t C5_BLANKING_TIME : 2; + uint8_t C5_PLAYBACK_INTERVAL : 1; + uint8_t C5_LRA_AUTO_OPEN_LOOP : 1; + uint8_t C5_AUTO_OL_CNT : 2; + } Bits; +} DRVREG_CTRL5; diff --git a/keyboards/adpenrose/mine/keymaps/solenoid/rules.mk b/keyboards/adpenrose/mine/keymaps/solenoid/rules.mk index 2a1e874d82..345c10cdd4 100644 --- a/keyboards/adpenrose/mine/keymaps/solenoid/rules.mk +++ b/keyboards/adpenrose/mine/keymaps/solenoid/rules.mk @@ -1,4 +1,4 @@ VIA_ENABLE = yes HAPTIC_ENABLE = yes -HAPTIC_DRIVER += SOLENOID +HAPTIC_DRIVER = solenoid ENCODER_MAP_ENABLE = yes # Encoder mapping functionality \ No newline at end of file diff --git a/keyboards/adpenrose/shisaku/keymaps/solenoid/rules.mk b/keyboards/adpenrose/shisaku/keymaps/solenoid/rules.mk index e13f2bd035..6bec144827 100644 --- a/keyboards/adpenrose/shisaku/keymaps/solenoid/rules.mk +++ b/keyboards/adpenrose/shisaku/keymaps/solenoid/rules.mk @@ -1,4 +1,4 @@ VIA_ENABLE = yes LTO_ENABLE = yes HAPTIC_ENABLE = yes -HAPTIC_DRIVER += SOLENOID \ No newline at end of file +HAPTIC_DRIVER = solenoid \ No newline at end of file diff --git a/keyboards/ai03/lunar_ii/rules.mk b/keyboards/ai03/lunar_ii/rules.mk index 1448dc35c3..7ad594e1f9 100644 --- a/keyboards/ai03/lunar_ii/rules.mk +++ b/keyboards/ai03/lunar_ii/rules.mk @@ -12,4 +12,4 @@ RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow AUDIO_ENABLE = no # Audio output HAPTIC_ENABLE = yes # Enable solenoid support -HAPTIC_DRIVER += SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/boston_meetup/2019/config.h b/keyboards/boston_meetup/2019/config.h index 4ed063f738..d8888eb92f 100644 --- a/keyboards/boston_meetup/2019/config.h +++ b/keyboards/boston_meetup/2019/config.h @@ -48,7 +48,7 @@ #define V_RMS 2.3 #define V_PEAK 3.30 /* Library Selection */ -#define LIB_SELECTION 4 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ +#define DRV2605L_LIBRARY 4 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ /* default 2V LRA voltage and library */ #elif FB_ERM_LRA == 1 @@ -57,7 +57,7 @@ #define V_PEAK 2.85 #define F_LRA 200 /* Library Selection */ -#define LIB_SELECTION 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ +#define DRV2605L_LIBRARY 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ #endif diff --git a/keyboards/boston_meetup/2019/rules.mk b/keyboards/boston_meetup/2019/rules.mk index b2f1131ffd..777d555b2d 100644 --- a/keyboards/boston_meetup/2019/rules.mk +++ b/keyboards/boston_meetup/2019/rules.mk @@ -12,6 +12,6 @@ AUDIO_ENABLE = yes # Audio output RGBLIGHT_ENABLE = no RGB_MATRIX_ENABLE = no HAPTIC_ENABLE = yes -HAPTIC_DRIVER = DRV2605L +HAPTIC_DRIVER = drv2605l OLED_ENABLE = yes OLED_DRIVER = SSD1306 diff --git a/keyboards/buzzard/keymaps/crehmann/config.h b/keyboards/buzzard/keymaps/crehmann/config.h index 181396ad26..ee3192e3fd 100644 --- a/keyboards/buzzard/keymaps/crehmann/config.h +++ b/keyboards/buzzard/keymaps/crehmann/config.h @@ -25,8 +25,8 @@ #define NO_HAPTIC_PUNCTUATION #define NO_HAPTIC_NAV #define NO_HAPTIC_NUMERIC -#define DRV_GREETING alert_750ms -#define DRV_MODE_DEFAULT sharp_tick1 +#define DRV2605L_GREETING alert_750ms +#define DRV2605L_DEFAULT_MODE sharp_tick1 #endif #ifdef PS2_MOUSE_ENABLE diff --git a/keyboards/buzzard/keymaps/crehmann/features/haptic_utils.c b/keyboards/buzzard/keymaps/crehmann/features/haptic_utils.c index 37fa2902c5..8f5aa0e662 100644 --- a/keyboards/buzzard/keymaps/crehmann/features/haptic_utils.c +++ b/keyboards/buzzard/keymaps/crehmann/features/haptic_utils.c @@ -4,7 +4,7 @@ #include "haptic_utils.h" #ifdef HAPTIC_ENABLE -#include "drivers/haptic/DRV2605L.h" +#include "drivers/haptic/drv2605l.h" #endif #ifdef HAPTIC_ENABLE @@ -23,19 +23,19 @@ void process_layer_pulse(layer_state_t state) { #ifdef HAPTIC_ENABLE switch (get_highest_layer(state)) { case 1: - DRV_pulse(soft_bump); + drv2605l_pulse(soft_bump); break; case 2: - DRV_pulse(sh_dblsharp_tick); + drv2605l_pulse(sh_dblsharp_tick); break; case 3: - DRV_pulse(lg_dblclick_str); + drv2605l_pulse(lg_dblclick_str); break; case 4: - DRV_pulse(soft_bump); + drv2605l_pulse(soft_bump); break; case 5: - DRV_pulse(pulsing_sharp); + drv2605l_pulse(pulsing_sharp); break; } #endif diff --git a/keyboards/buzzard/keymaps/crehmann/rules.mk b/keyboards/buzzard/keymaps/crehmann/rules.mk index 484e7d84a6..98a83af549 100644 --- a/keyboards/buzzard/keymaps/crehmann/rules.mk +++ b/keyboards/buzzard/keymaps/crehmann/rules.mk @@ -3,7 +3,7 @@ SRC += features/haptic_utils.c OLED_ENABLE = yes HAPTIC_ENABLE = yes -HAPTIC_DRIVER = DRV2605L +HAPTIC_DRIVER = drv2605l PS2_MOUSE_ENABLE = yes MOUSEKEY_ENABLE = yes diff --git a/keyboards/buzzard/keymaps/default/config.h b/keyboards/buzzard/keymaps/default/config.h index 2a42e17d0c..d5bf3e4dc6 100644 --- a/keyboards/buzzard/keymaps/default/config.h +++ b/keyboards/buzzard/keymaps/default/config.h @@ -25,8 +25,8 @@ #define NO_HAPTIC_PUNCTUATION #define NO_HAPTIC_NAV #define NO_HAPTIC_NUMERIC -#define DRV_GREETING alert_750ms -#define DRV_MODE_DEFAULT sharp_tick1 +#define DRV2605L_GREETING alert_750ms +#define DRV2605L_DEFAULT_MODE sharp_tick1 #endif diff --git a/keyboards/buzzard/keymaps/default/rules.mk b/keyboards/buzzard/keymaps/default/rules.mk index e8124aebb9..46728f3803 100644 --- a/keyboards/buzzard/keymaps/default/rules.mk +++ b/keyboards/buzzard/keymaps/default/rules.mk @@ -1,7 +1,7 @@ OLED_ENABLE = yes # uncomment if you are using an OLED display #HAPTIC_ENABLE = yes # uncomment only on the master side if you are using a Pimoroni haptic buzz -#HAPTIC_DRIVER = DRV2605L # uncomment only on the master side if you are using a Pimoroni haptic buzz +#HAPTIC_DRIVER = drv2605l # uncomment only on the master side if you are using a Pimoroni haptic buzz #PS2_MOUSE_ENABLE = yes # uncomment only on the master side if you are usin a TrackPoint MOUSEKEY_ENABLE = yes \ No newline at end of file diff --git a/keyboards/buzzard/rev1/rev1.c b/keyboards/buzzard/rev1/rev1.c index c6cdc66187..c26e4d5831 100644 --- a/keyboards/buzzard/rev1/rev1.c +++ b/keyboards/buzzard/rev1/rev1.c @@ -3,7 +3,7 @@ #include "quantum.h" #ifdef HAPTIC_ENABLE -#include "drivers/haptic/DRV2605L.h" +#include "drivers/haptic/drv2605l.h" #endif #ifdef SWAP_HANDS_ENABLE @@ -100,27 +100,27 @@ __attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) { switch (get_highest_layer(state)) { case 1: #ifdef HAPTIC_ENABLE - DRV_pulse(soft_bump); + drv2605l_pulse(soft_bump); #endif break; case 2: #ifdef HAPTIC_ENABLE - DRV_pulse(sh_dblsharp_tick); + drv2605l_pulse(sh_dblsharp_tick); #endif break; case 3: #ifdef HAPTIC_ENABLE - DRV_pulse(lg_dblclick_str); + drv2605l_pulse(lg_dblclick_str); #endif break; case 4: #ifdef HAPTIC_ENABLE - DRV_pulse(soft_bump); + drv2605l_pulse(soft_bump); #endif break; case 5: #ifdef HAPTIC_ENABLE - DRV_pulse(pulsing_sharp); + drv2605l_pulse(pulsing_sharp); #endif break; } diff --git a/keyboards/hadron/ver3/config.h b/keyboards/hadron/ver3/config.h index be315e668a..675bd218f0 100644 --- a/keyboards/hadron/ver3/config.h +++ b/keyboards/hadron/ver3/config.h @@ -70,7 +70,7 @@ #define V_RMS 2.3 #define V_PEAK 3.30 /* Library Selection */ -#define LIB_SELECTION 4 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ +#define DRV2605L_LIBRARY 4 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ /* default 2V LRA voltage and library */ #elif FB_ERM_LRA == 1 @@ -79,7 +79,7 @@ #define V_PEAK 2.85 #define F_LRA 200 /* Library Selection */ -#define LIB_SELECTION 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ +#define DRV2605L_LIBRARY 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ #endif diff --git a/keyboards/hadron/ver3/keymaps/ishtob/config.h b/keyboards/hadron/ver3/keymaps/ishtob/config.h deleted file mode 100644 index 6f70f09bee..0000000000 --- a/keyboards/hadron/ver3/keymaps/ishtob/config.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/keyboards/hadron/ver3/keymaps/ishtob/keymap.c b/keyboards/hadron/ver3/keymaps/ishtob/keymap.c index e99ff55caf..a3b522fa04 100644 --- a/keyboards/hadron/ver3/keymaps/ishtob/keymap.c +++ b/keyboards/hadron/ver3/keymaps/ishtob/keymap.c @@ -239,12 +239,3 @@ bool music_mask_user(uint16_t keycode) { return true; } } - - -void matrix_init_keymap(void) { -} - - -void matrix_scan_keymap(void) { -} - diff --git a/keyboards/hadron/ver3/rules.mk b/keyboards/hadron/ver3/rules.mk index 5739e57d19..887fbcbfeb 100644 --- a/keyboards/hadron/ver3/rules.mk +++ b/keyboards/hadron/ver3/rules.mk @@ -12,7 +12,7 @@ AUDIO_ENABLE = yes RGBLIGHT_ENABLE = yes RGB_MATRIX_ENABLE = no # once arm_rgb is implemented HAPTIC_ENABLE = yes -HAPTIC_DRIVER = DRV2605L +HAPTIC_DRIVER = drv2605l OLED_ENABLE = yes OLED_DRIVER = SSD1306 ENCODER_ENABLER = yes diff --git a/keyboards/handwired/onekey/keymaps/haptic/rules.mk b/keyboards/handwired/onekey/keymaps/haptic/rules.mk index 802f7e5dde..05201736e6 100644 --- a/keyboards/handwired/onekey/keymaps/haptic/rules.mk +++ b/keyboards/handwired/onekey/keymaps/haptic/rules.mk @@ -1,2 +1,2 @@ HAPTIC_ENABLE = yes -HAPTIC_DRIVER = SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/handwired/swiftrax/bumblebee/keymaps/default/rules.mk b/keyboards/handwired/swiftrax/bumblebee/keymaps/default/rules.mk index 9c6098640a..ef72559a0c 100644 --- a/keyboards/handwired/swiftrax/bumblebee/keymaps/default/rules.mk +++ b/keyboards/handwired/swiftrax/bumblebee/keymaps/default/rules.mk @@ -1,2 +1 @@ AUDIO_ENABLE = yes -HAPTIC_ENABLE += SOLENOID \ No newline at end of file diff --git a/keyboards/handwired/swiftrax/bumblebee/keymaps/via/rules.mk b/keyboards/handwired/swiftrax/bumblebee/keymaps/via/rules.mk index 8c797e4309..1e79dbce26 100644 --- a/keyboards/handwired/swiftrax/bumblebee/keymaps/via/rules.mk +++ b/keyboards/handwired/swiftrax/bumblebee/keymaps/via/rules.mk @@ -1,5 +1,4 @@ VIA_ENABLE = yes -#HAPTIC_ENABLE += SOLENOID AUDIO_ENABLE = yes #either solenoid or audio not both can be enabled LTO_ENABLE = yes diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h index a449a126d6..913c613c98 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h +++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/config.h @@ -32,5 +32,5 @@ #define FB_ERM_LRA 0 -#define DRV_GREETING alert_750ms -#define DRV_MODE_DEFAULT buzz +#define DRV2605L_GREETING alert_750ms +#define DRV2605L_DEFAULT_MODE buzz diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk index 9f5341e973..1cf7a3fccf 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk +++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk @@ -35,7 +35,7 @@ ifeq ($(strip $(KEYBOARD)), handwired/tractyl_manuform/5x6_right/f411) LTO_SUPPORTED = no OVERLOAD_FEATURES = yes HAPTIC_ENABLE = yes - HAPTIC_DRIVER = DRV2605L + HAPTIC_DRIVER = drv2605l endif ifeq ($(strip $(OVERLOAD_FEATURES)), yes) diff --git a/keyboards/hardwareabstraction/handwire/rules.mk b/keyboards/hardwareabstraction/handwire/rules.mk index d782fba2a8..ede296e1e8 100644 --- a/keyboards/hardwareabstraction/handwire/rules.mk +++ b/keyboards/hardwareabstraction/handwire/rules.mk @@ -1,6 +1,6 @@ LTO_ENABLE = yes HAPTIC_ENABLE = yes -HAPTIC_DRIVER += SOLENOID +HAPTIC_DRIVER = solenoid OLED_ENABLE = yes OLED_DRIVER = SSD1306 diff --git a/keyboards/hillside/46/0_1/config.h b/keyboards/hillside/46/0_1/config.h index 55395dd407..dc8654b4bb 100644 --- a/keyboards/hillside/46/0_1/config.h +++ b/keyboards/hillside/46/0_1/config.h @@ -21,5 +21,5 @@ /* Haptic waveforms */ // Two mild waveforms -#define DRV_GREETING alert_750ms -#define DRV_MODE_DEFAULT sharp_tick3_60 +#define DRV2605L_GREETING alert_750ms +#define DRV2605L_DEFAULT_MODE sharp_tick3_60 diff --git a/keyboards/hillside/46/0_1/rules.mk b/keyboards/hillside/46/0_1/rules.mk index 2501147ea8..3c12e55b58 100644 --- a/keyboards/hillside/46/0_1/rules.mk +++ b/keyboards/hillside/46/0_1/rules.mk @@ -5,4 +5,4 @@ LTO_ENABLE = yes # Use link time optimization for smaller firmware # enable it and set its driver here or in your keymap folder # The Pimoroni board's driver is DRV2605L # HAPTIC_ENABLE = yes # Enable haptic driver -# HAPTIC_DRIVER = DRV2605L +# HAPTIC_DRIVER = drv2605l diff --git a/keyboards/hillside/48/0_1/config.h b/keyboards/hillside/48/0_1/config.h index dc642c1193..3b432cf17b 100644 --- a/keyboards/hillside/48/0_1/config.h +++ b/keyboards/hillside/48/0_1/config.h @@ -16,5 +16,5 @@ /* Haptic waveforms */ // Two mild waveforms -#define DRV_GREETING alert_750ms -#define DRV_MODE_DEFAULT sharp_tick3_60 +#define DRV2605L_GREETING alert_750ms +#define DRV2605L_DEFAULT_MODE sharp_tick3_60 diff --git a/keyboards/hillside/48/0_1/rules.mk b/keyboards/hillside/48/0_1/rules.mk index 2501147ea8..3c12e55b58 100644 --- a/keyboards/hillside/48/0_1/rules.mk +++ b/keyboards/hillside/48/0_1/rules.mk @@ -5,4 +5,4 @@ LTO_ENABLE = yes # Use link time optimization for smaller firmware # enable it and set its driver here or in your keymap folder # The Pimoroni board's driver is DRV2605L # HAPTIC_ENABLE = yes # Enable haptic driver -# HAPTIC_DRIVER = DRV2605L +# HAPTIC_DRIVER = drv2605l diff --git a/keyboards/hillside/52/0_1/config.h b/keyboards/hillside/52/0_1/config.h index 55395dd407..dc8654b4bb 100644 --- a/keyboards/hillside/52/0_1/config.h +++ b/keyboards/hillside/52/0_1/config.h @@ -21,5 +21,5 @@ /* Haptic waveforms */ // Two mild waveforms -#define DRV_GREETING alert_750ms -#define DRV_MODE_DEFAULT sharp_tick3_60 +#define DRV2605L_GREETING alert_750ms +#define DRV2605L_DEFAULT_MODE sharp_tick3_60 diff --git a/keyboards/hillside/52/0_1/rules.mk b/keyboards/hillside/52/0_1/rules.mk index 2501147ea8..3c12e55b58 100644 --- a/keyboards/hillside/52/0_1/rules.mk +++ b/keyboards/hillside/52/0_1/rules.mk @@ -5,4 +5,4 @@ LTO_ENABLE = yes # Use link time optimization for smaller firmware # enable it and set its driver here or in your keymap folder # The Pimoroni board's driver is DRV2605L # HAPTIC_ENABLE = yes # Enable haptic driver -# HAPTIC_DRIVER = DRV2605L +# HAPTIC_DRIVER = drv2605l diff --git a/keyboards/ibm/model_m_4th_gen/overnumpad_1xb/rules.mk b/keyboards/ibm/model_m_4th_gen/overnumpad_1xb/rules.mk index 225317b367..9131708828 100644 --- a/keyboards/ibm/model_m_4th_gen/overnumpad_1xb/rules.mk +++ b/keyboards/ibm/model_m_4th_gen/overnumpad_1xb/rules.mk @@ -14,4 +14,4 @@ AUDIO_ENABLE = no # Audio output KEYBOARD_SHARED_EP = yes # Free up some extra endpoints - needed if console+mouse+extra HAPTIC_ENABLE = yes -HAPTIC_DRIVER = SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/mechwild/clunker/rules.mk b/keyboards/mechwild/clunker/rules.mk index 3e6a4da7db..a521203b32 100644 --- a/keyboards/mechwild/clunker/rules.mk +++ b/keyboards/mechwild/clunker/rules.mk @@ -1 +1 @@ -HAPTIC_DRIVER += SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/pearlboards/atlas/rules.mk b/keyboards/pearlboards/atlas/rules.mk index 15d4f79cde..1dd174f436 100644 --- a/keyboards/pearlboards/atlas/rules.mk +++ b/keyboards/pearlboards/atlas/rules.mk @@ -12,6 +12,6 @@ RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow AUDIO_ENABLE = yes # Audio output ENCODER_ENABLE = yes HAPTIC_ENABLE = yes -HAPTIC_DRIVER = DRV2605L +HAPTIC_DRIVER = drv2605l LTO_ENABLE = yes diff --git a/keyboards/pearlboards/pearl/rules.mk b/keyboards/pearlboards/pearl/rules.mk index 707e9c9312..83d6c3a33f 100644 --- a/keyboards/pearlboards/pearl/rules.mk +++ b/keyboards/pearlboards/pearl/rules.mk @@ -11,6 +11,6 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow AUDIO_ENABLE = yes # Audio output HAPTIC_ENABLE = yes -HAPTIC_DRIVER = DRV2605L +HAPTIC_DRIVER = drv2605l LTO_ENABLE = yes diff --git a/keyboards/pearlboards/zeus/rules.mk b/keyboards/pearlboards/zeus/rules.mk index eeb36fee4e..5cb2d9b649 100644 --- a/keyboards/pearlboards/zeus/rules.mk +++ b/keyboards/pearlboards/zeus/rules.mk @@ -12,6 +12,6 @@ RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow AUDIO_ENABLE = yes # Audio output ENCODER_ENABLE = yes # Rotary encoder HAPTIC_ENABLE = yes # Rumble feefback -HAPTIC_DRIVER = DRV2605L # Rumble motor +HAPTIC_DRIVER = drv2605l # Rumble motor LTO_ENABLE = yes # Link time optimization diff --git a/keyboards/splitkb/zima/config.h b/keyboards/splitkb/zima/config.h index 21fc2a2609..b031fca8dd 100644 --- a/keyboards/splitkb/zima/config.h +++ b/keyboards/splitkb/zima/config.h @@ -35,5 +35,5 @@ along with this program. If not, see . #define RATED_VOLTAGE 3 #define V_PEAK 5 -#define DRV_GREETING alert_750ms -#define DRV_MODE_DEFAULT buzz +#define DRV2605L_GREETING alert_750ms +#define DRV2605L_DEFAULT_MODE buzz diff --git a/keyboards/splitkb/zima/rules.mk b/keyboards/splitkb/zima/rules.mk index fb9a585656..f491893a43 100644 --- a/keyboards/splitkb/zima/rules.mk +++ b/keyboards/splitkb/zima/rules.mk @@ -15,6 +15,6 @@ ENCODER_ENABLE = yes # ENables the use of one or more encoders OLED_ENABLE = yes OLED_DRIVER = SSD1306 # Enables the use of OLED displays HAPTIC_ENABLE = yes # Supported but not included by defaut -HAPTIC_DRIVER = DRV2605L +HAPTIC_DRIVER = drv2605l LTO_ENABLE = yes diff --git a/keyboards/unicomp/classic_ultracl_post_2013/overnumpad_1xb/rules.mk b/keyboards/unicomp/classic_ultracl_post_2013/overnumpad_1xb/rules.mk index 225317b367..9131708828 100644 --- a/keyboards/unicomp/classic_ultracl_post_2013/overnumpad_1xb/rules.mk +++ b/keyboards/unicomp/classic_ultracl_post_2013/overnumpad_1xb/rules.mk @@ -14,4 +14,4 @@ AUDIO_ENABLE = no # Audio output KEYBOARD_SHARED_EP = yes # Free up some extra endpoints - needed if console+mouse+extra HAPTIC_ENABLE = yes -HAPTIC_DRIVER = SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/unicomp/classic_ultracl_pre_2013/overnumpad_1xb/rules.mk b/keyboards/unicomp/classic_ultracl_pre_2013/overnumpad_1xb/rules.mk index 225317b367..9131708828 100644 --- a/keyboards/unicomp/classic_ultracl_pre_2013/overnumpad_1xb/rules.mk +++ b/keyboards/unicomp/classic_ultracl_pre_2013/overnumpad_1xb/rules.mk @@ -14,4 +14,4 @@ AUDIO_ENABLE = no # Audio output KEYBOARD_SHARED_EP = yes # Free up some extra endpoints - needed if console+mouse+extra HAPTIC_ENABLE = yes -HAPTIC_DRIVER = SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/unicomp/pc122/overnumpad_1xb/rules.mk b/keyboards/unicomp/pc122/overnumpad_1xb/rules.mk index 225317b367..9131708828 100644 --- a/keyboards/unicomp/pc122/overnumpad_1xb/rules.mk +++ b/keyboards/unicomp/pc122/overnumpad_1xb/rules.mk @@ -14,4 +14,4 @@ AUDIO_ENABLE = no # Audio output KEYBOARD_SHARED_EP = yes # Free up some extra endpoints - needed if console+mouse+extra HAPTIC_ENABLE = yes -HAPTIC_DRIVER = SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/unicomp/spacesaver_m_post_2013/overnumpad_1xb/rules.mk b/keyboards/unicomp/spacesaver_m_post_2013/overnumpad_1xb/rules.mk index 225317b367..9131708828 100644 --- a/keyboards/unicomp/spacesaver_m_post_2013/overnumpad_1xb/rules.mk +++ b/keyboards/unicomp/spacesaver_m_post_2013/overnumpad_1xb/rules.mk @@ -14,4 +14,4 @@ AUDIO_ENABLE = no # Audio output KEYBOARD_SHARED_EP = yes # Free up some extra endpoints - needed if console+mouse+extra HAPTIC_ENABLE = yes -HAPTIC_DRIVER = SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/unicomp/spacesaver_m_pre_2013/overnumpad_1xb/rules.mk b/keyboards/unicomp/spacesaver_m_pre_2013/overnumpad_1xb/rules.mk index 225317b367..9131708828 100644 --- a/keyboards/unicomp/spacesaver_m_pre_2013/overnumpad_1xb/rules.mk +++ b/keyboards/unicomp/spacesaver_m_pre_2013/overnumpad_1xb/rules.mk @@ -14,4 +14,4 @@ AUDIO_ENABLE = no # Audio output KEYBOARD_SHARED_EP = yes # Free up some extra endpoints - needed if console+mouse+extra HAPTIC_ENABLE = yes -HAPTIC_DRIVER = SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/vertex/angle65/rules.mk b/keyboards/vertex/angle65/rules.mk index 2849e086e8..330f6ff76b 100644 --- a/keyboards/vertex/angle65/rules.mk +++ b/keyboards/vertex/angle65/rules.mk @@ -12,4 +12,4 @@ RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow AUDIO_ENABLE = no # Audio output HAPTIC_ENABLE = yes -HAPTIC_DRIVER += SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/keyboards/xw60/rules.mk b/keyboards/xw60/rules.mk index 460d3ced43..710fb4ca88 100644 --- a/keyboards/xw60/rules.mk +++ b/keyboards/xw60/rules.mk @@ -11,4 +11,4 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. HAPTIC_ENABLE = yes -HAPTIC_DRIVER = SOLENOID +HAPTIC_DRIVER = solenoid diff --git a/layouts/community/ortho_4x12/drashna/config.h b/layouts/community/ortho_4x12/drashna/config.h index 8443ff054f..071f7cb55b 100644 --- a/layouts/community/ortho_4x12/drashna/config.h +++ b/layouts/community/ortho_4x12/drashna/config.h @@ -115,7 +115,7 @@ # define V_RMS 2.3 # define V_PEAK 3.30 /* Library Selection */ -# define LIB_SELECTION 4 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ +# define DRV2605L_LIBRARY 4 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ /* default 2V LRA voltage and library */ #elif FB_ERM_LRA == 1 @@ -124,7 +124,7 @@ # define V_PEAK 2.85 # define F_LRA 200 /* Library Selection */ -# define LIB_SELECTION 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ +# define DRV2605L_LIBRARY 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ #endif diff --git a/quantum/haptic.c b/quantum/haptic.c index c151547fca..13b2258eb8 100644 --- a/quantum/haptic.c +++ b/quantum/haptic.c @@ -14,17 +14,20 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + #include "haptic.h" #include "eeconfig.h" #include "debug.h" #include "usb_device_state.h" #include "gpio.h" -#ifdef DRV2605L -# include "DRV2605L.h" + +#ifdef HAPTIC_DRV2605L +# include "drv2605l.h" #endif -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID # include "solenoid.h" #endif + #if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE) extern uint8_t split_haptic_play; #endif @@ -59,11 +62,11 @@ void haptic_init(void) { eeconfig_init(); } haptic_config.raw = eeconfig_read_haptic(); -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID solenoid_set_dwell(haptic_config.dwell); #endif if ((haptic_config.raw == 0) -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID || (haptic_config.dwell == 0) #endif ) { @@ -77,12 +80,12 @@ void haptic_init(void) { // This is to execute any side effects of the configuration. set_haptic_config_enable(haptic_config.enable); } -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID solenoid_setup(); dprintf("Solenoid driver initialized\n"); #endif -#ifdef DRV2605L - DRV_init(); +#ifdef HAPTIC_DRV2605L + drv2605l_init(); dprintf("DRV2605 driver initialized\n"); #endif eeconfig_debug_haptic(); @@ -95,7 +98,7 @@ void haptic_init(void) { } void haptic_task(void) { -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID solenoid_check(); #endif } @@ -108,13 +111,13 @@ void eeconfig_debug_haptic(void) { void haptic_enable(void) { set_haptic_config_enable(true); - xprintf("haptic_config.enable = %u\n", haptic_config.enable); + dprintf("haptic_config.enable = %u\n", haptic_config.enable); eeconfig_update_haptic(haptic_config.raw); } void haptic_disable(void) { set_haptic_config_enable(false); - xprintf("haptic_config.enable = %u\n", haptic_config.enable); + dprintf("haptic_config.enable = %u\n", haptic_config.enable); eeconfig_update_haptic(haptic_config.raw); } @@ -130,7 +133,7 @@ void haptic_toggle(void) { void haptic_feedback_toggle(void) { haptic_config.feedback++; if (haptic_config.feedback >= HAPTIC_FEEDBACK_MAX) haptic_config.feedback = KEY_PRESS; - xprintf("haptic_config.feedback = %u\n", !haptic_config.feedback); + dprintf("haptic_config.feedback = %u\n", !haptic_config.feedback); eeconfig_update_haptic(haptic_config.raw); } @@ -142,7 +145,7 @@ void haptic_buzz_toggle(void) { void haptic_mode_increase(void) { uint8_t mode = haptic_config.mode + 1; -#ifdef DRV2605L +#ifdef HAPTIC_DRV2605L if (haptic_config.mode >= drv_effect_max) { mode = 1; } @@ -152,7 +155,7 @@ void haptic_mode_increase(void) { void haptic_mode_decrease(void) { uint8_t mode = haptic_config.mode - 1; -#ifdef DRV2605L +#ifdef HAPTIC_DRV2605L if (haptic_config.mode < 1) { mode = (drv_effect_max - 1); } @@ -161,7 +164,7 @@ void haptic_mode_decrease(void) { } void haptic_dwell_increase(void) { -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID int16_t next_dwell = ((int16_t)haptic_config.dwell) + SOLENOID_DWELL_STEP_SIZE; if (haptic_config.dwell >= SOLENOID_MAX_DWELL) { // if it's already at max, we wrap back to min @@ -178,7 +181,7 @@ void haptic_dwell_increase(void) { } void haptic_dwell_decrease(void) { -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID int16_t next_dwell = ((int16_t)haptic_config.dwell) - SOLENOID_DWELL_STEP_SIZE; if (haptic_config.dwell <= SOLENOID_MIN_DWELL) { // if it's already at min, we wrap to max @@ -196,13 +199,13 @@ void haptic_dwell_decrease(void) { void haptic_reset(void) { set_haptic_config_enable(true); - uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT; + uint8_t feedback = HAPTIC_DEFAULT_FEEDBACK; haptic_config.feedback = feedback; -#ifdef DRV2605L - uint8_t mode = HAPTIC_MODE_DEFAULT; +#ifdef HAPTIC_DRV2605L + uint8_t mode = HAPTIC_DEFAULT_MODE; haptic_config.mode = mode; #endif -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID uint8_t dwell = SOLENOID_DEFAULT_DWELL; haptic_config.dwell = dwell; haptic_config.buzz = SOLENOID_DEFAULT_BUZZ; @@ -213,41 +216,41 @@ void haptic_reset(void) { haptic_config.buzz = 0; #endif eeconfig_update_haptic(haptic_config.raw); - xprintf("haptic_config.feedback = %u\n", haptic_config.feedback); - xprintf("haptic_config.mode = %u\n", haptic_config.mode); + dprintf("haptic_config.feedback = %u\n", haptic_config.feedback); + dprintf("haptic_config.mode = %u\n", haptic_config.mode); } void haptic_set_feedback(uint8_t feedback) { haptic_config.feedback = feedback; eeconfig_update_haptic(haptic_config.raw); - xprintf("haptic_config.feedback = %u\n", haptic_config.feedback); + dprintf("haptic_config.feedback = %u\n", haptic_config.feedback); } void haptic_set_mode(uint8_t mode) { haptic_config.mode = mode; eeconfig_update_haptic(haptic_config.raw); - xprintf("haptic_config.mode = %u\n", haptic_config.mode); + dprintf("haptic_config.mode = %u\n", haptic_config.mode); } void haptic_set_amplitude(uint8_t amp) { haptic_config.amplitude = amp; eeconfig_update_haptic(haptic_config.raw); - xprintf("haptic_config.amplitude = %u\n", haptic_config.amplitude); -#ifdef DRV2605L - DRV_amplitude(amp); + dprintf("haptic_config.amplitude = %u\n", haptic_config.amplitude); +#ifdef HAPTIC_DRV2605L + drv2605l_amplitude(amp); #endif } void haptic_set_buzz(uint8_t buzz) { haptic_config.buzz = buzz; eeconfig_update_haptic(haptic_config.raw); - xprintf("haptic_config.buzz = %u\n", haptic_config.buzz); + dprintf("haptic_config.buzz = %u\n", haptic_config.buzz); } void haptic_set_dwell(uint8_t dwell) { haptic_config.dwell = dwell; eeconfig_update_haptic(haptic_config.raw); - xprintf("haptic_config.dwell = %u\n", haptic_config.dwell); + dprintf("haptic_config.dwell = %u\n", haptic_config.dwell); } uint8_t haptic_get_enable(void) { @@ -277,19 +280,19 @@ uint8_t haptic_get_dwell(void) { void haptic_enable_continuous(void) { haptic_config.cont = 1; - xprintf("haptic_config.cont = %u\n", haptic_config.cont); + dprintf("haptic_config.cont = %u\n", haptic_config.cont); eeconfig_update_haptic(haptic_config.raw); -#ifdef DRV2605L - DRV_rtp_init(); +#ifdef HAPTIC_DRV2605L + drv2605l_rtp_init(); #endif } void haptic_disable_continuous(void) { haptic_config.cont = 0; - xprintf("haptic_config.cont = %u\n", haptic_config.cont); + dprintf("haptic_config.cont = %u\n", haptic_config.cont); eeconfig_update_haptic(haptic_config.raw); -#ifdef DRV2605L - DRV_write(DRV_MODE, 0x00); +#ifdef HAPTIC_DRV2605L + drv2605l_write(DRV2605L_REG_MODE, 0x00); #endif } @@ -318,15 +321,15 @@ void haptic_cont_decrease(void) { } void haptic_play(void) { -#ifdef DRV2605L +#ifdef HAPTIC_DRV2605L uint8_t play_eff = 0; play_eff = haptic_config.mode; - DRV_pulse(play_eff); + drv2605l_pulse(play_eff); # if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE) split_haptic_play = haptic_config.mode; # endif #endif -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID solenoid_fire_handler(); # if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE) split_haptic_play = 1; @@ -335,7 +338,7 @@ void haptic_play(void) { } void haptic_shutdown(void) { -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID solenoid_shutdown(); #endif } diff --git a/quantum/haptic.h b/quantum/haptic.h index 71d95cc61b..5bd1a71916 100644 --- a/quantum/haptic.h +++ b/quantum/haptic.h @@ -16,14 +16,15 @@ */ #pragma once + #include #include -#ifndef HAPTIC_FEEDBACK_DEFAULT -# define HAPTIC_FEEDBACK_DEFAULT 0 +#ifndef HAPTIC_DEFAULT_FEEDBACK +# define HAPTIC_DEFAULT_FEEDBACK 0 #endif -#ifndef HAPTIC_MODE_DEFAULT -# define HAPTIC_MODE_DEFAULT DRV_MODE_DEFAULT +#ifndef HAPTIC_DEFAULT_MODE +# define HAPTIC_DEFAULT_MODE DRV2605L_DEFAULT_MODE #endif /* EEPROM config settings */ diff --git a/quantum/process_keycode/process_space_cadet.c b/quantum/process_keycode/process_space_cadet.c index 4d9f01077e..f948ad6238 100644 --- a/quantum/process_keycode/process_space_cadet.c +++ b/quantum/process_keycode/process_space_cadet.c @@ -13,10 +13,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + #include "process_space_cadet.h" #include "keycodes.h" #include "timer.h" +#include "action.h" #include "action_tapping.h" +#include "action_util.h" // ********** OBSOLETE DEFINES, STOP USING! (pls?) ********** // Shift / paren setup diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 87838c3195..fca95e0847 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -21,6 +21,7 @@ #include "wait.h" #include "debug.h" #include "usb_util.h" +#include "bootloader.h" #ifdef EE_HANDS # include "eeconfig.h" diff --git a/users/ishtob/ishtob.h b/users/ishtob/ishtob.h index fd9e19c809..fcc2e2b847 100644 --- a/users/ishtob/ishtob.h +++ b/users/ishtob/ishtob.h @@ -36,7 +36,7 @@ enum userspace_keycodes { #define _FNLAYER 6 #define _NUMLAY 7 #define _MOUSECURSOR 8 -#define _ADJUST 16 +#define _ADJUST 9 -- cgit v1.2.3 From 2c70d3891002337ef981a478b95c621f68dfd777 Mon Sep 17 00:00:00 2001 From: leep-frog Date: Thu, 27 Jul 2023 00:04:35 -0400 Subject: On-each-release tap dance function (#20255) Co-authored-by: Sergey Vlasov --- docs/feature_tap_dance.md | 2 +- quantum/process_keycode/process_tap_dance.c | 8 ++ quantum/process_keycode/process_tap_dance.h | 14 ++-- tests/tap_dance/examples.c | 24 +++++- tests/tap_dance/examples.h | 2 + tests/tap_dance/test_examples.cpp | 116 ++++++++++++++++++++++++++++ 6 files changed, 159 insertions(+), 7 deletions(-) (limited to 'quantum/process_keycode') diff --git a/docs/feature_tap_dance.md b/docs/feature_tap_dance.md index b7d8a5528f..42ea233962 100644 --- a/docs/feature_tap_dance.md +++ b/docs/feature_tap_dance.md @@ -28,7 +28,7 @@ After this, you'll want to use the `tap_dance_actions` array to specify what act * `ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer)`: Sends the `kc` keycode when tapped once, or toggles the state of `layer`. (this functions like the `TG` layer keycode). * `ACTION_TAP_DANCE_FN(fn)`: Calls the specified function - defined in the user keymap - with the final tap count of the tap dance action. * `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_dance_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function when the dance action finishes (like the previous option), and the last function when the tap dance action resets. - +* `ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(on_each_tap_fn, on_each_release_fn, on_dance_finished_fn, on_dance_reset_fn)`: This macro is identical to `ACTION_TAP_DANCE_FN_ADVANCED` with the addition of `on_each_release_fn` which is invoked every time the key for the tap dance is released. It is worth noting that `on_each_release_fn` will still be called even when the key is released after the dance finishes (e.g. if the key is released after being pressed and held for longer than the `TAPPING_TERM`). The first option is enough for a lot of cases, that just want dual roles. For example, `ACTION_TAP_DANCE_DOUBLE(KC_SPC, KC_ENT)` will result in `Space` being sent on single-tap, `Enter` otherwise. diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c index 1b2c6c8a44..b8a8d32f35 100644 --- a/quantum/process_keycode/process_tap_dance.c +++ b/quantum/process_keycode/process_tap_dance.c @@ -95,6 +95,10 @@ static inline void process_tap_dance_action_on_each_tap(tap_dance_action_t *acti _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_tap); } +static inline void process_tap_dance_action_on_each_release(tap_dance_action_t *action) { + _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_release); +} + static inline void process_tap_dance_action_on_reset(tap_dance_action_t *action) { _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_reset); del_weak_mods(action->state.weak_mods); @@ -158,8 +162,12 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { process_tap_dance_action_on_each_tap(action); active_td = action->state.finished ? 0 : keycode; } else { + process_tap_dance_action_on_each_release(action); if (action->state.finished) { process_tap_dance_action_on_reset(action); + if (active_td == keycode) { + active_td = 0; + } } } diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h index 386f504619..2b114dabd3 100644 --- a/quantum/process_keycode/process_tap_dance.h +++ b/quantum/process_keycode/process_tap_dance.h @@ -40,6 +40,7 @@ typedef struct { tap_dance_user_fn_t on_each_tap; tap_dance_user_fn_t on_dance_finished; tap_dance_user_fn_t on_reset; + tap_dance_user_fn_t on_each_release; } fn; void *user_data; } tap_dance_action_t; @@ -56,19 +57,22 @@ typedef struct { } tap_dance_dual_role_t; #define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \ - { .fn = {tap_dance_pair_on_each_tap, tap_dance_pair_finished, tap_dance_pair_reset}, .user_data = (void *)&((tap_dance_pair_t){kc1, kc2}), } + { .fn = {tap_dance_pair_on_each_tap, tap_dance_pair_finished, tap_dance_pair_reset, NULL}, .user_data = (void *)&((tap_dance_pair_t){kc1, kc2}), } #define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) \ - { .fn = {tap_dance_dual_role_on_each_tap, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_move}), } + { .fn = {tap_dance_dual_role_on_each_tap, tap_dance_dual_role_finished, tap_dance_dual_role_reset, NULL}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_move}), } #define ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer) \ - { .fn = {NULL, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_invert}), } + { .fn = {NULL, tap_dance_dual_role_finished, tap_dance_dual_role_reset, NULL}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_invert}), } #define ACTION_TAP_DANCE_FN(user_fn) \ - { .fn = {NULL, user_fn, NULL}, .user_data = NULL, } + { .fn = {NULL, user_fn, NULL, NULL}, .user_data = NULL, } #define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) \ - { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, } + { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, NULL}, .user_data = NULL, } + +#define ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(user_fn_on_each_tap, user_fn_on_each_release, user_fn_on_dance_finished, user_fn_on_dance_reset) \ + { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, user_fn_on_each_release}, .user_data = NULL, } #define TD(n) (QK_TAP_DANCE | TD_INDEX(n)) #define TD_INDEX(code) ((code)&0xFF) diff --git a/tests/tap_dance/examples.c b/tests/tap_dance/examples.c index af74388209..13086bbb4b 100644 --- a/tests/tap_dance/examples.c +++ b/tests/tap_dance/examples.c @@ -187,13 +187,35 @@ void x_reset(tap_dance_state_t *state, void *user_data) { xtap_state.state = TD_NONE; } +static void release_press(tap_dance_state_t *state, void *user_data) { + tap_code16(KC_P); +} + +static void release_unpress(tap_dance_state_t *state, void *user_data) { + tap_code16(KC_U); +} + +static void release_unpress_mark_finished(tap_dance_state_t *state, void *user_data) { + tap_code16(KC_U); + state->finished = true; +} + +static void release_finished(tap_dance_state_t *state, void *user_data) { + tap_code16(KC_F); +} + +static void release_reset(tap_dance_state_t *state, void *user_data) { + tap_code16(KC_R); +} tap_dance_action_t tap_dance_actions[] = { [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS), [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg), [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset), [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN), - [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset) + [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset), + [TD_RELEASE] = ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(release_press, release_unpress, release_finished, release_reset), + [TD_RELEASE_AND_FINISH] = ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(release_press, release_unpress_mark_finished, release_finished, release_reset), }; // clang-format on diff --git a/tests/tap_dance/examples.h b/tests/tap_dance/examples.h index 2622af6b2f..6118188dd1 100644 --- a/tests/tap_dance/examples.h +++ b/tests/tap_dance/examples.h @@ -26,6 +26,8 @@ enum { CT_FLSH, CT_CLN, X_CTL, + TD_RELEASE, + TD_RELEASE_AND_FINISH, }; #ifdef __cplusplus diff --git a/tests/tap_dance/test_examples.cpp b/tests/tap_dance/test_examples.cpp index 6dabc45513..7858dab92b 100644 --- a/tests/tap_dance/test_examples.cpp +++ b/tests/tap_dance/test_examples.cpp @@ -316,3 +316,119 @@ TEST_F(TapDance, QuadFunction) { EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); } + +TEST_F(TapDance, DanceFnAdvancedWithRelease) { + TestDriver driver; + InSequence s; + auto key_rls = KeymapKey(0, 1, 0, TD(TD_RELEASE)); + + set_keymap({key_rls}); + + /* Single press and unpress */ + key_rls.press(); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + key_rls.release(); + EXPECT_REPORT(driver, (KC_U)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + EXPECT_REPORT(driver, (KC_F)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_R)); + EXPECT_EMPTY_REPORT(driver); + idle_for(TAPPING_TERM); + run_one_scan_loop(); + + /* Double press and unpress */ + key_rls.press(); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + key_rls.release(); + EXPECT_REPORT(driver, (KC_U)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + key_rls.press(); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + key_rls.release(); + EXPECT_REPORT(driver, (KC_U)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + EXPECT_REPORT(driver, (KC_F)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_R)); + EXPECT_EMPTY_REPORT(driver); + idle_for(TAPPING_TERM); + run_one_scan_loop(); + + /* Unpress after tapping term has elapsed (key is registered as held) */ + key_rls.press(); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + EXPECT_REPORT(driver, (KC_F)); + EXPECT_EMPTY_REPORT(driver); + idle_for(TAPPING_TERM); + run_one_scan_loop(); + + key_rls.release(); + EXPECT_REPORT(driver, (KC_U)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_R)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DanceFnAdvancedWithReleaseAndFinish) { + TestDriver driver; + InSequence s; + auto key_rls = KeymapKey(0, 1, 0, TD(TD_RELEASE_AND_FINISH)); + + set_keymap({key_rls}); + + /* Single press and unpress */ + key_rls.press(); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + key_rls.release(); + EXPECT_REPORT(driver, (KC_U)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_R)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + // Verify the finished and/or reset functions aren't called + // after the tapping term elapses + idle_for(TAPPING_TERM); + run_one_scan_loop(); + + /* Unpress after tapping term has elapsed (key is registered as held) */ + key_rls.press(); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + EXPECT_REPORT(driver, (KC_F)); + EXPECT_EMPTY_REPORT(driver); + idle_for(TAPPING_TERM); + run_one_scan_loop(); + + key_rls.release(); + EXPECT_REPORT(driver, (KC_U)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_R)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} -- cgit v1.2.3 From 9bc85ff5afb09892312f3b130b7e5f6209835f09 Mon Sep 17 00:00:00 2001 From: Nebuleon Date: Thu, 27 Jul 2023 00:05:26 -0400 Subject: Reduce needless precision in audio note frequency calculation (#21496) --- quantum/process_keycode/process_audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'quantum/process_keycode') diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index ef2f52c9f1..a8464e1b83 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -13,7 +13,7 @@ float voice_change_song[][2] = VOICE_CHANGE_SONG; float compute_freq_for_midi_note(uint8_t note) { // https://en.wikipedia.org/wiki/MIDI_tuning_standard - return pow(2.0, (note - 69) / 12.0) * PITCH_STANDARD_A; + return powf(2.0f, (note - 69) / 12.0f) * PITCH_STANDARD_A; } bool process_audio(uint16_t keycode, keyrecord_t *record) { -- cgit v1.2.3 From eab315e935dced643c4cae9c9697ebe520627f36 Mon Sep 17 00:00:00 2001 From: James Young Date: Tue, 1 Aug 2023 22:49:58 -0700 Subject: Fix Dynamic Macro Compilation for avr-gcc 5.4.0 + Linux (#21653) Co-authored-by: Joel Challis --- quantum/process_keycode/process_dynamic_macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'quantum/process_keycode') diff --git a/quantum/process_keycode/process_dynamic_macro.c b/quantum/process_keycode/process_dynamic_macro.c index 5e4a6fa308..30a51503db 100644 --- a/quantum/process_keycode/process_dynamic_macro.c +++ b/quantum/process_keycode/process_dynamic_macro.c @@ -196,7 +196,7 @@ static keyrecord_t *macro_end = macro_buffer; static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1; /* Like macro_end but for the second macro. */ -static keyrecord_t *r_macro_end = r_macro_buffer; +static keyrecord_t *r_macro_end = macro_buffer + DYNAMIC_MACRO_SIZE - 1; /* A persistent pointer to the current macro position (iterator) * used during the recording. */ -- cgit v1.2.3 From 70e34e491c297231a3f987fd69760d38e79dbfa4 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 27 Aug 2023 13:30:19 +1000 Subject: Unicode, Unicodemap and UCIS refactor (#21659) --- Makefile | 2 +- builddefs/common_features.mk | 6 +- docs/feature_unicode.md | 464 ++++++++++++++------- keyboards/spaceman/2_milk/keymaps/emoji/keymap.c | 2 +- quantum/process_keycode/process_ucis.c | 120 +----- quantum/process_keycode/process_ucis.h | 42 -- quantum/process_keycode/process_unicode.c | 1 + quantum/process_keycode/process_unicode.h | 1 - quantum/process_keycode/process_unicode_common.c | 15 +- quantum/process_keycode/process_unicode_common.h | 1 - quantum/process_keycode/process_unicodemap.c | 35 +- quantum/process_keycode/process_unicodemap.h | 7 +- quantum/quantum.c | 4 - quantum/quantum.h | 12 +- quantum/quantum_keycodes_legacy.h | 2 +- quantum/unicode/ucis.c | 96 +++++ quantum/unicode/ucis.h | 97 +++++ quantum/unicode/unicode.c | 26 +- quantum/unicode/unicode.h | 81 +++- quantum/unicode/unicodemap.c | 43 ++ quantum/unicode/unicodemap.h | 43 ++ tests/test_common/test_driver.cpp | 9 +- tests/unicode/config.h | 8 + tests/unicode/test.mk | 5 + tests/unicode/test_unicode.cpp | 86 ++++ tests/unicode/unicode_basic/config.h | 8 + tests/unicode/unicode_basic/test.mk | 5 + tests/unicode/unicode_basic/test_unicode_basic.cpp | 26 ++ tests/unicode/unicode_map/config.h | 8 + tests/unicode/unicode_map/test.mk | 5 + tests/unicode/unicode_map/test_unicode_map.cpp | 54 +++ tests/unicode/unicode_ucis/config.h | 8 + tests/unicode/unicode_ucis/test.mk | 5 + tests/unicode/unicode_ucis/test_unicode_ucis.cpp | 221 ++++++++++ 34 files changed, 1179 insertions(+), 369 deletions(-) create mode 100644 quantum/unicode/ucis.c create mode 100644 quantum/unicode/ucis.h create mode 100644 quantum/unicode/unicodemap.c create mode 100644 quantum/unicode/unicodemap.h create mode 100644 tests/unicode/config.h create mode 100644 tests/unicode/test.mk create mode 100644 tests/unicode/test_unicode.cpp create mode 100644 tests/unicode/unicode_basic/config.h create mode 100644 tests/unicode/unicode_basic/test.mk create mode 100644 tests/unicode/unicode_basic/test_unicode_basic.cpp create mode 100644 tests/unicode/unicode_map/config.h create mode 100644 tests/unicode/unicode_map/test.mk create mode 100644 tests/unicode/unicode_map/test_unicode_map.cpp create mode 100644 tests/unicode/unicode_ucis/config.h create mode 100644 tests/unicode/unicode_ucis/test.mk create mode 100644 tests/unicode/unicode_ucis/test_unicode_ucis.cpp (limited to 'quantum/process_keycode') diff --git a/Makefile b/Makefile index c77eadf97d..9f2e4636a4 100644 --- a/Makefile +++ b/Makefile @@ -328,7 +328,7 @@ define PARSE_TEST ifeq ($$(TEST_NAME),all) MATCHED_TESTS := $$(TEST_LIST) else - MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME), $$(notdir $$(TEST))), $$(TEST),)) + MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring x$$(TEST_NAME)x, x$$(notdir $$(TEST))x), $$(TEST),)) endif $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET)))) endef diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index 60fcdc6b93..094eda6fef 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -784,13 +784,15 @@ endif ifeq ($(strip $(UCIS_ENABLE)), yes) OPT_DEFS += -DUCIS_ENABLE UNICODE_COMMON := yes - SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c + SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c \ + $(QUANTUM_DIR)/unicode/ucis.c endif ifeq ($(strip $(UNICODEMAP_ENABLE)), yes) OPT_DEFS += -DUNICODEMAP_ENABLE UNICODE_COMMON := yes - SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c + SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c \ + $(QUANTUM_DIR)/unicode/unicodemap.c endif ifeq ($(strip $(UNICODE_ENABLE)), yes) diff --git a/docs/feature_unicode.md b/docs/feature_unicode.md index 312a033257..341084f926 100644 --- a/docs/feature_unicode.md +++ b/docs/feature_unicode.md @@ -1,48 +1,77 @@ -# Unicode Support +# Unicode :id=unicode -Unicode characters can be input straight from your keyboard! There are some limitations, however. +With a little help from your OS, practically any Unicode character can be input using your keyboard. -In order to enable Unicode support on your keyboard, you will need to do the following: +## Caveats :id=caveats -1. Choose one of three supported Unicode implementations: [Basic Unicode](#basic-unicode), [Unicode Map](#unicode-map), [UCIS](#ucis). -2. Find which [input mode](#input-modes) is the best match for your operating system and setup. -3. [Set](#setting-the-input-mode) the appropriate input mode (or modes) in your configuration. -4. Add Unicode keycodes to your keymap. +There are some limitations to this feature. Because there is no "standard" method of Unicode input across all operating systems, each of them require their own setup process on both the host *and* in the firmware, which may involve installation of additional software. This also means Unicode input will not "just work" when the keyboard is plugged into another device. +## Usage :id=usage -## 1. Methods :id=methods +The core Unicode API can be used purely programmatically. However, there are also additional subsystems which build on top of it and come with keycodes to make things easier. See below for more details. -QMK supports three different methods for enabling Unicode input and adding Unicode characters to your keymap. Each has its pros and cons in terms of flexibility and ease of use. Choose the one that best fits your use case. +Add the following to your keymap's `rules.mk`: -The Basic method should be enough for most users. However, if you need a wider range of supported characters (including emoji, rare symbols etc.), you should use Unicode Map. +```make +UNICODE_COMMON = yes +``` + +## Basic Configuration :id=basic-configuration + +Add the following to your `config.h`: + +|Define |Default |Description | +|------------------------|------------------|--------------------------------------------------------------------------------| +|`UNICODE_KEY_MAC` |`KC_LEFT_ALT` |The key to hold when beginning a Unicode sequence with the macOS input mode | +|`UNICODE_KEY_LNX` |`LCTL(LSFT(KC_U))`|The key to tap when beginning a Unicode sequence with the Linux input mode | +|`UNICODE_KEY_WINC` |`KC_RIGHT_ALT` |The key to hold when beginning a Unicode sequence with the WinCompose input mode| +|`UNICODE_SELECTED_MODES`|`-1` |A comma separated list of input modes for cycling through | +|`UNICODE_CYCLE_PERSIST` |`true` |Whether to persist the current Unicode input mode to EEPROM | +|`UNICODE_TYPE_DELAY` |`10` |The amount of time to wait, in milliseconds, between Unicode sequence keystrokes| + +### Audio Feedback :id=audio-feedback -
+If you have the [Audio](feature_audio.md) feature enabled on your board, you can configure it to play sounds when the input mode is changed. -### 1.1. Basic Unicode :id=basic-unicode +Add the following to your `config.h`: -The easiest to use method, albeit somewhat limited. It stores Unicode characters as keycodes in the keymap itself, so it only supports code points up to `0x7FFF`. This covers characters for most modern languages (including East Asian), as well as symbols, but it doesn't cover emoji. +|Define |Default|Description | +|-------------------|-------|-----------------------------------------------------------| +|`UNICODE_SONG_MAC` |*n/a* |The song to play when the macOS input mode is selected | +|`UNICODE_SONG_LNX` |*n/a* |The song to play when the Linux input mode is selected | +|`UNICODE_SONG_BSD` |*n/a* |The song to play when the BSD input mode is selected | +|`UNICODE_SONG_WIN` |*n/a* |The song to play when the Windows input mode is selected | +|`UNICODE_SONG_WINC`|*n/a* |The song to play when the WinCompose input mode is selected| -Add the following to your `rules.mk`: +## Input Subsystems :id=input-subsystems + +Each of these subsystems have their own pros and cons in terms of flexibility and ease of use. Choose the one that best fits your needs. + + + +### ** Basic ** + +This is the easiest to use, albeit somewhat limited. It supports code points up to `U+7FFF`, which covers characters for most modern languages (including East Asian), as well as many symbols, but does not include emoji. + +To enable Basic Unicode, add the following to your `rules.mk`: ```make UNICODE_ENABLE = yes ``` -Then add `UC(c)` keycodes to your keymap, where _c_ is the code point of the desired character (preferably in hexadecimal, up to 4 digits long). For example, `UC(0x40B)` will output [Ћ](https://unicode-table.com/en/040B/), and `UC(0x30C4)` will output [ツ](https://unicode-table.com/en/30C4). - -
+You can then add `UC(c)` keycodes to your keymap, where *c* is the code point of the desired character (in hexadecimal - the `U+` prefix will not work). For example, `UC(0x40B)` will output [Ћ](https://unicode-table.com/en/040B/), and `UC(0x30C4)` will output [ツ](https://unicode-table.com/en/30C4). -### 1.2. Unicode Map :id=unicode-map +### ** Unicode Map ** -In addition to standard character ranges, this method also covers emoji, ancient scripts, rare symbols etc. In fact, all possible code points (up to `0x10FFFF`) are supported. Here, Unicode characters are stored in a separate mapping table. You need to maintain a `unicode_map` array in your keymap file, which may contain at most 16384 entries. +Unicode Map supports all possible code points (up to `U+10FFFF`). Here, the code points are stored in a separate mapping table (which may contain at most 16,384 entries), instead of directly in the keymap. -Add the following to your `rules.mk`: +To enable Unicode Map, add the following to your `rules.mk`: ```make UNICODEMAP_ENABLE = yes ``` -Then add `UM(i)` keycodes to your keymap, where _i_ is the desired character's index in the mapping table. This can be a numeric value, but it's recommended to keep the indices in an enum and access them by name. +Then, you will need to create a mapping table in your `keymap.c`, and (optionally) an enum for naming the array indices, like so: ```c enum unicode_names { @@ -51,242 +80,373 @@ enum unicode_names { SNEK }; -const uint32_t unicode_map[] PROGMEM = { +const uint32_t PROGMEM unicode_map[] = { [BANG] = 0x203D, // ‽ [IRONY] = 0x2E2E, // ⸮ [SNEK] = 0x1F40D, // 🐍 }; ``` -Then you can use `UM(BANG)`, `UM(SNEK)` etc. in your keymap. +Finally, add `UM(i)` keycodes to your keymap, where *i* is an index into the `unicode_map[]` array. If you defined the enum above, you can use those names instead, for example `UM(BANG)` or `UM(SNEK)`. -#### Lower and Upper Case +#### Lower and Upper Case Pairs :id=unicodemap-pairs -Characters often come in lower and upper case pairs, such as å and Å. To make inputting these characters easier, you can use `UP(i, j)` in your keymap, where _i_ and _j_ are the mapping table indices of the lower and upper case character, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the second (upper case) character will be inserted; otherwise, the first (lower case) version will appear. +Some writing systems have lowercase and uppercase variants of each character, such as å and Å. To make inputting these characters easier, you can use the `UP(i, j)` keycode in your keymap, where *i* and *j* are the mapping table indices of the lowercase and uppercase characters, respectively. If you're holding down Shift or have Caps Lock turned on when you press the key, the uppercase character will be inserted; otherwise, the lowercase character will be inserted. -This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key by using `UP()`. This helps blend Unicode keys in with regular alphas. +```c +const uint32_t PROGMEM unicode_map[] = { + [AE_LOWER] = 0x00E6, // æ + [AE_UPPER] = 0x00C6, // Æ +}; +``` -Due to keycode size constraints, _i_ and _j_ can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ _i_ ≤ 127 and 0 ≤ _j_ ≤ 127. This is enough for most use cases, but if you'd like to customize the index calculation, you can override the [`unicodemap_index()`](https://github.com/qmk/qmk_firmware/blob/71f640d47ee12c862c798e1f56392853c7b1c1a8/quantum/process_keycode/process_unicodemap.c#L36) function. This also allows you to, say, check Ctrl instead of Shift/Caps. +This is most useful when creating a keymap for an international layout with special characters. Instead of having to put the lower and upper case versions of a character on separate keys, you can have them both on the same key. This helps blend Unicode keys in with regular keycodes. -
+Due to keycode size constraints, *i* and *j* can each only refer to one of the first 128 characters in your `unicode_map`. In other words, 0 ≤ *i* ≤ 127 and 0 ≤ *j* ≤ 127. -### 1.3. UCIS :id=ucis +### ** UCIS ** -This method also supports all possible code points. As with the Unicode Map method, you need to maintain a mapping table in your keymap file. However, there are no built-in keycodes for this feature — you have to create a custom keycode or function that invokes this functionality. +As with Unicode Map, the UCIS method also supports all possible code points, and requires the use of a mapping table. However, it works much differently - Unicode characters are input by replacing a typed mnemonic. -Add the following to your `rules.mk`: +To enable UCIS, add the following to your keymap's `rules.mk`: ```make UCIS_ENABLE = yes ``` -Then define a table like this in your keymap file: +Then, create a mapping table in your `keymap.c`: ```c const ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE( UCIS_SYM("poop", 0x1F4A9), // 💩 UCIS_SYM("rofl", 0x1F923), // 🤣 - UCIS_SYM("cuba", 0x1F1E8, 0x1F1FA), // 🇨🇺 + UCIS_SYM("ukr", 0x1F1FA, 0x1F1E6), // 🇺🇦 UCIS_SYM("look", 0x0CA0, 0x005F, 0x0CA0) // ಠ_ಠ ); ``` -By default, each table entry may be up to 3 code points long. This number can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your `config.h` file. +By default, each table entry may be up to three code points long. This can be changed by adding `#define UCIS_MAX_CODE_POINTS n` to your keymap's `config.h`. -To use UCIS input, call `ucis_start()`. Then, type the mnemonic for the character (such as "rofl") and hit Space, Enter or Esc. QMK should erase the "rofl" text and insert the laughing emoji. +To invoke UCIS input, the `ucis_start()` function must first be called (for example, in a custom "Unicode" keycode). Then, type the mnemonic for the mapping table entry (such as "rofl"), and hit Space or Enter. The "rofl" text will be backspaced and the emoji inserted. -#### Customization + -There are several functions that you can define in your keymap to customize the functionality of this feature. +## Input Modes :id=input-modes -* `void ucis_start_user(void)` – This runs when you call the "start" function, and can be used to provide feedback. By default, it types out a keyboard emoji. -* `void ucis_success(uint8_t symbol_index)` – This runs when the input has matched something and has completed. By default, it doesn't do anything. -* `void ucis_symbol_fallback (void)` – This runs when the input doesn't match anything. By default, it falls back to trying that input as a Unicode code. +Unicode input works by typing a sequence of characters, similar to a macro. However, since this sequence depends on your OS, you will need to prepare both your host machine and QMK to recognise and send the correct Unicode input sequences respectively. -You can find the default implementations of these functions in [`process_ucis.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_ucis.c). +To set the list of enabled input modes, add the `UNICODE_SELECTED_MODES` define to your keymap's `config.h`, for example: +```c +#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX +// or +#define UNICODE_SELECTED_MODES UNICODE_MODE_MAC, UNICODE_MODE_WINCOMPOSE +``` -## 2. Input Modes :id=input-modes +These modes can then be cycled through using the `UC_NEXT` and `UC_PREV` keycodes. You can also switch to any input mode, even if it is not specified in `UNICODE_SELECTED_MODES`, using their respective keycodes. -Unicode input in QMK works by inputting a sequence of characters to the OS, sort of like a macro. Unfortunately, the way this is done differs for each platform. Specifically, each platform requires a different combination of keys to trigger Unicode input. Therefore, a corresponding input mode has to be set in QMK. +If your keyboard has working EEPROM, it will remember the last used input mode and continue using it on the next power up. This can be disabled by defining `UNICODE_CYCLE_PERSIST` to `false`. -The following input modes are available: + -* **`UNICODE_MODE_MACOS`**: macOS built-in Unicode hex input. Supports code points up to `0x10FFFF` (all possible code points). +### ** macOS ** - To enable, go to _System Preferences > Keyboard > Input Sources_, add _Unicode Hex Input_ to the list (it's under _Other_), then activate it from the input dropdown in the Menu Bar. - By default, this mode uses the left Option key (`KC_LALT`) for Unicode input, but this can be changed by defining [`UNICODE_KEY_MAC`](#input-key-configuration) with a different keycode. +**Mode Name:** `UNICODE_MODE_MAC` - !> Using the _Unicode Hex Input_ input source may disable some Option-based shortcuts, such as Option+Left and Option+Right. +macOS has built-in support for Unicode input as its own input source. It supports all possible code points by way of surrogate pairs for code points above `U+FFFF`. -* **`UNICODE_MODE_LINUX`**: Linux built-in IBus Unicode input. Supports code points up to `0x10FFFF` (all possible code points). +To enable, go to **System Preferences → Keyboard → Input Sources**, then add Unicode Hex Input to the list (under Other), and activate it from the input dropdown in the menu bar. Note that this may disable some Option-based shortcuts such as Option+Left and Option+Right. - Enabled by default and works almost anywhere on IBus-enabled distros. Without IBus, this mode works under GTK apps, but rarely anywhere else. - By default, this mode uses Ctrl+Shift+U (`LCTL(LSFT(KC_U))`) to start Unicode input, but this can be changed by defining [`UNICODE_KEY_LNX`](#input-key-configuration) with a different keycode. This might be required for IBus versions ≥1.5.15, where Ctrl+Shift+U behavior is consolidated into Ctrl+Shift+E. +### ** Linux (IBus) ** - Users who wish support in non-GTK apps without IBus may need to resort to a more indirect method, such as creating a custom keyboard layout ([more on this method](#custom-linux-layout)). +**Mode Name:** `UNICODE_MODE_LINUX` -* **`UNICODE_MODE_WINDOWS`**: _(not recommended)_ Windows built-in hex numpad Unicode input. Supports code points up to `0xFFFF`. +For Linux distros with IBus, Unicode input is enabled by default, supports all possible code points, and works almost anywhere. Without IBus, it works under GTK apps, but rarely anywhere else. - To enable, create a registry key under `HKEY_CURRENT_USER\Control Panel\Input Method` of type `REG_SZ` called `EnableHexNumpad` and set its value to `1`. This can be done from the Command Prompt by running `reg add "HKCU\Control Panel\Input Method" -v EnableHexNumpad -t REG_SZ -d 1` with administrator privileges. Reboot afterwards. - This mode is not recommended because of reliability and compatibility issues; use the `UNICODE_MODE_WINCOMPOSE` mode instead. +Users who would like support in non-GTK apps without IBus may need to resort to a more indirect method, such as creating a custom keyboard layout. -* **`UNICODE_MODE_BSD`**: _(non implemented)_ Unicode input under BSD. Not implemented at this time. If you're a BSD user and want to help add support for it, please [open an issue on GitHub](https://github.com/qmk/qmk_firmware/issues). +### ** Windows (WinCompose) ** -* **`UNICODE_MODE_WINCOMPOSE`**: Windows Unicode input using [WinCompose](https://github.com/samhocevar/wincompose). As of v0.9.0, supports code points up to `0x10FFFF` (all possible code points). +**Mode Name:** `UNICODE_MODE_WINCOMPOSE` - To enable, install the [latest release](https://github.com/samhocevar/wincompose/releases/latest). Once installed, WinCompose will automatically run on startup. This mode works reliably under all version of Windows supported by the app. - By default, this mode uses right Alt (`KC_RALT`) as the Compose key, but this can be changed in the WinCompose settings and by defining [`UNICODE_KEY_WINC`](#input-key-configuration) with a different keycode. +This mode requires a third-party tool called [WinCompose](https://github.com/samhocevar/wincompose). It supports all possible code points, and is the recommended input mode for Windows. +To enable, install the [latest release from GitHub](https://github.com/samhocevar/wincompose/releases/latest). Once installed, it will automatically run on startup. This works reliably under all versions of Windows supported by WinCompose. -## 3. Setting the Input Mode :id=setting-the-input-mode +### ** Windows (HexNumpad) ** -To set your desired input mode, add the following define to your `config.h`: +**Mode Name:** `UNICODE_MODE_WINDOWS` -```c -#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX -``` +!> This input mode is *not* the "Alt code" system. Alt codes are not Unicode; they instead follow [the Windows-1252 character set](https://en.wikipedia.org/wiki/Alt_code). -This example sets the board's default input mode to `UNICODE_MODE_LINUX`. You can replace this with `UNICODE_MODE_MACOS`, `UNICODE_MODE_WINCOMPOSE`, or any of the other modes listed [above](#input-modes). The board will automatically use the selected mode on startup, unless you manually switch to another mode (see [below](#keycodes)). +This is Windows' built-in hex numpad Unicode input mode. It only supports code points up to `U+FFFF`, and is not recommended due to reliability and compatibility issues. -You can also select multiple input modes, which allows you to easily cycle through them using the `UC_NEXT`/`UC_PREV` keycodes. +To enable, run the following as an administrator, then reboot: -```c -#define UNICODE_SELECTED_MODES UNICODE_MODE_MACOS, UNICODE_MODE_LINUX, UNICODE_MODE_WINCOMPOSE +``` +reg add "HKCU\Control Panel\Input Method" -v EnableHexNumpad -t REG_SZ -d 1 ``` -Note that the values are separated by commas. The board will remember the last used input mode and will continue using it on next power-up. You can disable this and force it to always start with the first mode in the list by adding `#define UNICODE_CYCLE_PERSIST false` to your `config.h`. +### ** Emacs ** -#### Keycodes +**Mode Name:** `UNICODE_MODE_EMACS` -You can switch the input mode at any time by using the following keycodes. Adding these to your keymap allows you to quickly switch to a specific input mode, including modes not listed in `UNICODE_SELECTED_MODES`. +Emacs supports code point input with the `insert-char` command. -|Keycode |Alias |Input Mode |Description | -|----------------------------|---------|-------------------------|-----------------------------------------------------------------------------| -|`QK_UNICODE_MODE_NEXT` |`UC_NEXT`|Next in list |Cycle through selected modes, reverse direction when Shift is held | -|`QK_UNICODE_MODE_PREVIOUS` |`UC_PREV`|Prev in list |Cycle through selected modes in reverse, forward direction when Shift is held| -|`QK_UNICODE_MODE_MACOS` |`UC_MAC` |`UNICODE_MODE_MACOS` |Switch to macOS input | -|`QK_UNICODE_MODE_LINUX` |`UC_LINX`|`UNICODE_MODE_LINUX` |Switch to Linux input | -|`QK_UNICODE_MODE_WINDOWS` |`UC_WIN` |`UNICODE_MODE_WINDOWS` |Switch to Windows input | -|`QK_UNICODE_MODE_BSD` |`UC_BSD` |`UNICODE_MODE_BSD` |Switch to BSD input _(not implemented)_ | -|`QK_UNICODE_MODE_WINCOMPOSE`|`UC_WINC`|`UNICODE_MODE_WINCOMPOSE`|Switch to Windows input using WinCompose | -|`QK_UNICODE_MODE_EMACS` |`UC_EMAC`|`UNICODE_MODE_EMACS` |Switch to emacs (`C-x-8 RET`) | +### ** BSD ** -You can also switch the input mode by calling `set_unicode_input_mode(x)` in your code, where _x_ is one of the above input mode constants (e.g. `UNICODE_MODE_LINUX`). +**Mode Name:** `UNICODE_MODE_BSD` -?> Using `UNICODE_SELECTED_MODES` is preferable to calling `set_unicode_input_mode()` in `matrix_init_user()` or similar functions, since it's better integrated into the Unicode system and has the added benefit of avoiding unnecessary writes to EEPROM. +Not currently implemented. If you're a BSD user and want to contribute support for this input mode, please [feel free](contributing.md)! -#### Audio Feedback + -If you have the [Audio feature](feature_audio.md) enabled on the board, you can set melodies to be played when you press the above keys. That way you can have some audio feedback when switching input modes. +## Keycodes :id=keycodes -For instance, you can add these definitions to your `config.h` file: +|Key |Aliases |Description | +|----------------------------|---------|----------------------------------------------------------------| +|`UC(c)` | |Send Unicode code point `c`, up to `0x7FFF` | +|`UM(i)` | |Send Unicode code point at index `i` in `unicode_map` | +|`UP(i, j)` | |Send Unicode code point at index `i`, or `j` if Shift/Caps is on| +|`QK_UNICODE_MODE_NEXT` |`UC_NEXT`|Cycle through selected input modes | +|`QK_UNICODE_MODE_PREVIOUS` |`UC_PREV`|Cycle through selected input modes in reverse | +|`QK_UNICODE_MODE_MACOS` |`UC_MAC` |Switch to macOS input | +|`QK_UNICODE_MODE_LINUX` |`UC_LINX`|Switch to Linux input | +|`QK_UNICODE_MODE_WINDOWS` |`UC_WIN` |Switch to Windows input | +|`QK_UNICODE_MODE_BSD` |`UC_BSD` |Switch to BSD input (not implemented) | +|`QK_UNICODE_MODE_WINCOMPOSE`|`UC_WINC`|Switch to Windows input using WinCompose | +|`QK_UNICODE_MODE_EMACS` |`UC_EMAC`|Switch to emacs (`C-x-8 RET`) | -```c -#define UNICODE_SONG_MAC AUDIO_ON_SOUND -#define UNICODE_SONG_LNX UNICODE_LINUX -#define UNICODE_SONG_BSD TERMINAL_SOUND -#define UNICODE_SONG_WIN UNICODE_WINDOWS -#define UNICODE_SONG_WINC UNICODE_WINDOWS -``` +## API :id=api +### `uint8_t get_unicode_input_mode(void)` :id=api-get-unicode-input-mode -## Additional Customization +Get the current Unicode input mode. -Because Unicode is a large and versatile feature, there are a number of options you can customize to make it work better on your system. +#### Return Value :id=api-get-unicode-input-mode-return-value -### Start and Finish Input Functions +The currently active Unicode input mode. -The functions for starting and finishing Unicode input on your platform can be overridden locally. Possible uses include customizing input mode behavior if you don't use the default keys, or adding extra visual/audio feedback to Unicode input. +--- -* `void unicode_input_start(void)` – This sends the initial sequence that tells your platform to enter Unicode input mode. For example, it holds the left Alt key followed by Num+ on Windows, and presses the `UNICODE_KEY_LNX` combination (default: Ctrl+Shift+U) on Linux. -* `void unicode_input_finish(void)` – This is called to exit Unicode input mode, for example by pressing Space or releasing the Alt key. +### `void set_unicode_input_mode(uint8_t mode)` :id=api-set-unicode-input-mode -You can find the default implementations of these functions in [`process_unicode_common.c`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicode_common.c). +Set the Unicode input mode. -### Input Mode Callbacks +#### Arguments :id=api-set-unicode-input-mode-arguments -There are callbacks functions available that are called whenever the unicode input mode changes. The new input mode is passed to the function. + - `uint8_t mode` + The input mode to set. -|Callback |Description | -|---------------------------------------------------|-----------------------------------------------------| -| `unicode_input_mode_set_kb(uint8_t input_mode)` | Callback for unicode input mode set, for keyboard. | -| `unicode_input_mode_set_user(uint8_t input_mode)` | Callback for unicode input mode set, for users. | +--- -This feature can be used, for instance, to implement LED indicators for the current unicode input mode. +### `void unicode_input_mode_step(void)` : id=api-unicode-input-mode-step -### Input Key Configuration +Change to the next Unicode input mode. -You can customize the keys used to trigger Unicode input for macOS, Linux and WinCompose by adding corresponding defines to your `config.h`. The default values match the platforms' default settings, so you shouldn't need to change this unless Unicode input isn't working, or you want to use a different key (e.g. in order to free up left or right Alt). +--- -|Define |Type |Default |Example | -|------------------|----------|------------------|-------------------------------------------| -|`UNICODE_KEY_MAC` |`uint8_t` |`KC_LALT` |`#define UNICODE_KEY_MAC KC_RALT` | -|`UNICODE_KEY_LNX` |`uint16_t`|`LCTL(LSFT(KC_U))`|`#define UNICODE_KEY_LNX LCTL(LSFT(KC_E))`| -|`UNICODE_KEY_WINC`|`uint8_t` |`KC_RALT` |`#define UNICODE_KEY_WINC KC_RGUI` | +### `void unicode_input_mode_step_reverse(void)` : id=api-unicode-input-mode-step-reverse +Change to the previous Unicode input mode. -## Sending Unicode Strings +--- -QMK provides several functions that allow you to send Unicode input to the host programmatically: +### `void unicode_input_mode_set_user(uint8_t input_mode)` :id=api-unicode-input-mode-set-user -### `send_unicode_string()` +User-level callback, invoked when the input mode is changed. -This function is much like `send_string()`, but it allows you to input UTF-8 characters directly. It supports all code points, provided the selected input mode also supports it. Make sure your `keymap.c` file is formatted using UTF-8 encoding. +#### Arguments :id=api-unicode-input-mode-set-user-arguments -```c -send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻"); -``` + - `uint8_t input_mode` + The new input mode. -Example uses include sending Unicode strings when a key is pressed, as described in [Macros](feature_macros.md). +--- -## Additional Language Support +### `void unicode_input_mode_set_kb(uint8_t input_mode)` :id=api-unicode-input-mode-set-kb -In `quantum/keymap_extras`, you'll see various language files — these work the same way as the ones for alternative layouts such as Colemak or BÉPO. When you include one of these language headers, you gain access to keycodes specific to that language / national layout. Such keycodes are defined by a 2-letter country/language code, followed by an underscore and a 4-letter abbreviation of the character to which the key corresponds. For example, including `keymap_french.h` and using `FR_UGRV` in your keymap will output `ù` when typed on a system with a native French AZERTY layout. +Keyboard-level callback, invoked when the input mode is changed. -If the primary system layout you use on your machine is different from US ANSI, using these language-specific keycodes can help your QMK keymaps better match what will actually be output on the screen. However, keep in mind that these keycodes are just aliases for the corresponding default US keycodes under the hood, and that the HID protocol used by keyboards is itself inherently based on US ANSI. +#### Arguments :id=api-unicode-input-mode-set-kb-arguments + - `uint8_t input_mode` + The new input mode. -## International Characters on Windows +--- -### AutoHotkey +### `void unicode_input_start(void)` :id=api-unicode-input-start -The method does not require Unicode support in the keyboard itself but instead depends on [AutoHotkey](https://autohotkey.com) running in the background. +Begin the Unicode input sequence. The exact behavior depends on the currently selected input mode: -First you need to select a modifier combination that is not in use by any of your programs. -Ctrl+Alt+Win is not used very widely and should therefore be perfect for this. -There is a macro defined for a mod-tab combo `LCAG_T`. -Add this mod-tab combo to a key on your keyboard, e.g.: `LCAG_T(KC_TAB)`. -This makes the key behave like a tab key if pressed and released immediately but changes it to the modifier if used with another key. + - **macOS**: Hold `UNICODE_KEY_MAC` + - **Linux**: Tap `UNICODE_KEY_LNX` + - **WinCompose**: Tap `UNICODE_KEY_WINC`, then U + - **HexNumpad**: Hold Left Alt, then tap Numpad + + - **Emacs**: Tap Ctrl+X, then 8, then Enter -In the default script of AutoHotkey you can define custom hotkeys. +This function is weakly defined, and can be overridden in user code. - <^ { [ r, R, U1F923 ] }; -``` + - **macOS**: Release `UNICODE_KEY_MAC` + - **Linux**: Tap Escape + - **WinCompose**: Tap Escape + - **HexNumpad**: Release Left Alt + - **Emacs**: Tap Ctrl+G + +This function is weakly defined, and can be overridden in user code. + +--- + +### `void register_unicode(uint32_t code_point)` :id=api-register-unicode + +Input a single Unicode character. A surrogate pair will be sent if required by the input mode. + +#### Arguments :id=api-register-unicode-arguments + + - `uint32_t code_point` + The code point of the character to send. + +--- + +### `void send_unicode_string(const char *str)` :id=api-send-unicode-string + +Send a string containing Unicode characters. + +#### Arguments :id=api-send-unicode-string-arguments + + - `const char *str` + The string to send. + +--- + +### `uint8_t unicodemap_index(uint16_t keycode)` :id=api-unicodemap-index + +Get the index into the `unicode_map` array for the given keycode, respecting shift state for pair keycodes. + +#### Arguments :id=api-unicodemap-index-arguments + + - `uint16_t keycode` + The Unicode Map keycode to get the index of. + +#### Return Value :id=api-unicodemap-index-return-value + +An index into the `unicode_map` array. + +--- + +### `uint32_t unicodemap_get_code_point(uint8_t index)` :id=api-unicodemap-get-code-point + +Get the code point for the given index in the `unicode_map` array. + +#### Arguments :id=unicodemap-get-code-point-arguments + + - `uint8_t index` + The index into the `unicode_map` array. + +#### Return Value :id=unicodemap-get-code-point-return-value + +A Unicode code point value. + +--- + +### `void register_unicodemap(uint8_t index)` :id=api-register-unicodemap + +Send the code point for the given index in the `unicode_map` array. + +#### Arguments :id=api-register-unicodemap-arguments + + - `uint8_t index` + The index into the `unicode_map` array. + +--- + +### `void ucis_start(void)` :id=api-ucis-start + +Begin the input sequence. + +--- + +### `bool ucis_active(void)` :id=api-ucis-active + +Whether UCIS is currently active. + +#### Return Value :id=api-ucis-active-return-value + +`true` if UCIS is active. + +--- + +### `uint8_t ucis_count(void)` :id=api-ucis-count + +Get the number of characters in the input sequence buffer. + +#### Return Value :id=api-ucis-count-return-value + +The current input sequence buffer length. + +--- + +### `bool ucis_add(uint16_t keycode)` :id=api-ucis-add + +Add the given keycode to the input sequence buffer. + +#### Arguments :id=api-ucis-add-arguments + + - `uint16_t keycode` + The keycode to add. Must be between `KC_A` and `KC_Z`, or `KC_1` and `KC_0`. + +#### Return Value :id=api-ucis-add-return-value + +`true` if the keycode was added. + +--- + +### `bool ucis_remove_last(void)` :id=api-ucis-remove-last + +Remove the last character from the input sequence buffer. + +#### Return Value :id=api-ucis-remove-last + +`true` if the sequence was not empty. + +--- + +### `void ucis_finish(void)` :id=api-ucis-finish + +Mark the input sequence as complete, and attempt to match. + +--- + +### `void ucis_cancel(void)` :id=api-ucis-cancel + +Cancel the input sequence. + +--- + +### `void register_ucis(void)` :id=api-register-ucis -Save the file and run the command `setxkbmap us` to reload the layout. +Send the code point(s) for the given UCIS index. -You can define one custom character for key defined in the layout, and another if you populate the fourth layer. Additional layers up to 8th are also possible. +#### Arguments :id=api-register-ucis-arguments -This method is specific to the computer on which you set the custom layout. The custom keys will be available only when Xorg is running. To avoid accidents, you should always reload the layout using `setxkbmap`, otherwise an invalid layout could prevent you from logging into your system, locking you out. + - `uint8_t index` + The index into the UCIS symbol table. diff --git a/keyboards/spaceman/2_milk/keymaps/emoji/keymap.c b/keyboards/spaceman/2_milk/keymaps/emoji/keymap.c index 8859573ce5..26ac20ad5c 100644 --- a/keyboards/spaceman/2_milk/keymaps/emoji/keymap.c +++ b/keyboards/spaceman/2_milk/keymaps/emoji/keymap.c @@ -11,7 +11,7 @@ void dance_key_one (tap_dance_state_t *state, void *user_data) { tap_code(KC_ENTER); reset_tap_dance (state); } else if (state->count == 2) { - cycle_unicode_input_mode(+1); + unicode_input_mode_step(); reset_tap_dance (state); } } diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c index 3aa09d5948..91a038bab1 100644 --- a/quantum/process_keycode/process_ucis.c +++ b/quantum/process_keycode/process_ucis.c @@ -15,110 +15,30 @@ */ #include "process_ucis.h" -#include "unicode.h" -#include "keycode.h" -#include "wait.h" +#include "ucis.h" +#include "keycodes.h" -ucis_state_t ucis_state; - -void ucis_start(void) { - ucis_state.count = 0; - ucis_state.in_progress = true; - - ucis_start_user(); -} - -__attribute__((weak)) void ucis_start_user(void) { - register_unicode(0x2328); // ⌨ -} - -__attribute__((weak)) void ucis_success(uint8_t symbol_index) {} - -static bool is_uni_seq(char *seq) { - uint8_t i; - for (i = 0; seq[i]; i++) { - uint16_t keycode; - if ('1' <= seq[i] && seq[i] <= '0') { - keycode = seq[i] - '1' + KC_1; - } else { - keycode = seq[i] - 'a' + KC_A; - } - if (i > ucis_state.count || ucis_state.codes[i] != keycode) { +bool process_ucis(uint16_t keycode, keyrecord_t *record) { + if (ucis_active() && record->event.pressed) { + bool special = keycode == KC_SPACE || keycode == KC_ENTER || keycode == KC_ESCAPE || keycode == KC_BACKSPACE; + if (ucis_count() >= UCIS_MAX_INPUT_LENGTH && !special) { return false; } - } - return ucis_state.codes[i] == KC_ENTER || ucis_state.codes[i] == KC_SPACE; -} - -__attribute__((weak)) void ucis_symbol_fallback(void) { - for (uint8_t i = 0; i < ucis_state.count - 1; i++) { - tap_code(ucis_state.codes[i]); - } -} - -__attribute__((weak)) void ucis_cancel(void) {} - -void register_ucis(const uint32_t *code_points) { - for (int i = 0; i < UCIS_MAX_CODE_POINTS && code_points[i]; i++) { - register_unicode(code_points[i]); - } -} -bool process_ucis(uint16_t keycode, keyrecord_t *record) { - if (!ucis_state.in_progress || !record->event.pressed) { - return true; - } - - bool special = keycode == KC_SPACE || keycode == KC_ENTER || keycode == KC_ESCAPE || keycode == KC_BACKSPACE; - if (ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) { - return false; - } - - ucis_state.codes[ucis_state.count] = keycode; - ucis_state.count++; - - switch (keycode) { - case KC_BACKSPACE: - if (ucis_state.count >= 2) { - ucis_state.count -= 2; - return true; - } else { - ucis_state.count--; - return false; - } - - case KC_SPACE: - case KC_ENTER: - case KC_ESCAPE: - for (uint8_t i = 0; i < ucis_state.count; i++) { - tap_code(KC_BACKSPACE); - } - - if (keycode == KC_ESCAPE) { - ucis_state.in_progress = false; - ucis_cancel(); - return false; - } - - uint8_t i; - bool symbol_found = false; - for (i = 0; ucis_symbol_table[i].symbol; i++) { - if (is_uni_seq(ucis_symbol_table[i].symbol)) { - symbol_found = true; - register_ucis(ucis_symbol_table[i].code_points); - break; - } + if (!ucis_add(keycode)) { + switch (keycode) { + case KC_BACKSPACE: + return ucis_remove_last(); + case KC_ESCAPE: + ucis_cancel(); + return false; + case KC_SPACE: + case KC_ENTER: + ucis_finish(); + return false; } - if (symbol_found) { - ucis_success(i); - } else { - ucis_symbol_fallback(); - } - - ucis_state.in_progress = false; - return false; - - default: - return true; + } } + + return true; } diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h index 54eb9413d4..6282df7893 100644 --- a/quantum/process_keycode/process_ucis.h +++ b/quantum/process_keycode/process_ucis.h @@ -18,48 +18,6 @@ #include #include - #include "action.h" -#ifndef UCIS_MAX_SYMBOL_LENGTH -# define UCIS_MAX_SYMBOL_LENGTH 32 -#endif -#ifndef UCIS_MAX_CODE_POINTS -# define UCIS_MAX_CODE_POINTS 3 -#endif - -typedef struct { - char * symbol; - uint32_t code_points[UCIS_MAX_CODE_POINTS]; -} ucis_symbol_t; - -typedef struct { - uint8_t count; - uint16_t codes[UCIS_MAX_SYMBOL_LENGTH]; - bool in_progress : 1; -} ucis_state_t; - -extern ucis_state_t ucis_state; - -// clang-format off - -#define UCIS_TABLE(...) \ - { \ - __VA_ARGS__, \ - { NULL, {} } \ - } -#define UCIS_SYM(name, ...) \ - { name, {__VA_ARGS__} } - -// clang-format on - -extern const ucis_symbol_t ucis_symbol_table[]; - -void ucis_start(void); -void ucis_start_user(void); -void ucis_symbol_fallback(void); -void ucis_success(uint8_t symbol_index); - -void register_ucis(const uint32_t *code_points); - bool process_ucis(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c index 1ec76245a3..8ee6fcd7fc 100644 --- a/quantum/process_keycode/process_unicode.c +++ b/quantum/process_keycode/process_unicode.c @@ -16,6 +16,7 @@ #include "process_unicode.h" #include "unicode.h" +#include "keycodes.h" #include "quantum_keycodes.h" bool process_unicode(uint16_t keycode, keyrecord_t *record) { diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h index 341bc8d861..9a51ffaf7c 100644 --- a/quantum/process_keycode/process_unicode.h +++ b/quantum/process_keycode/process_unicode.h @@ -18,7 +18,6 @@ #include #include - #include "action.h" bool process_unicode(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c index a0b9010027..f43770977a 100644 --- a/quantum/process_keycode/process_unicode_common.c +++ b/quantum/process_keycode/process_unicode_common.c @@ -17,7 +17,8 @@ #include "process_unicode_common.h" #include "unicode.h" #include "action_util.h" -#include "keycode.h" +#include "keycodes.h" +#include "modifiers.h" #if defined(UNICODE_ENABLE) # include "process_unicode.h" @@ -32,10 +33,18 @@ bool process_unicode_common(uint16_t keycode, keyrecord_t *record) { bool shifted = get_mods() & MOD_MASK_SHIFT; switch (keycode) { case QK_UNICODE_MODE_NEXT: - cycle_unicode_input_mode(shifted ? -1 : +1); + if (shifted) { + unicode_input_mode_step_reverse(); + } else { + unicode_input_mode_step(); + } break; case QK_UNICODE_MODE_PREVIOUS: - cycle_unicode_input_mode(shifted ? +1 : -1); + if (shifted) { + unicode_input_mode_step(); + } else { + unicode_input_mode_step_reverse(); + } break; case QK_UNICODE_MODE_MACOS: set_unicode_input_mode(UNICODE_MODE_MACOS); diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h index fd09a41818..0465830079 100644 --- a/quantum/process_keycode/process_unicode_common.h +++ b/quantum/process_keycode/process_unicode_common.h @@ -18,7 +18,6 @@ #include #include - #include "action.h" bool process_unicode_common(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c index 195c093e6e..a85568521c 100644 --- a/quantum/process_keycode/process_unicodemap.c +++ b/quantum/process_keycode/process_unicodemap.c @@ -15,41 +15,12 @@ */ #include "process_unicodemap.h" -#include "unicode.h" -#include "quantum_keycodes.h" -#include "keycode.h" -#include "action_util.h" -#include "host.h" - -__attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) { - if (keycode >= QK_UNICODEMAP_PAIR) { - // Keycode is a pair: extract index based on Shift / Caps Lock state - uint16_t index; - - uint8_t mods = get_mods() | get_weak_mods(); -#ifndef NO_ACTION_ONESHOT - mods |= get_oneshot_mods(); -#endif - - bool shift = mods & MOD_MASK_SHIFT; - bool caps = host_keyboard_led_state().caps_lock; - if (shift ^ caps) { - index = QK_UNICODEMAP_PAIR_GET_SHIFTED_INDEX(keycode); - } else { - index = QK_UNICODEMAP_PAIR_GET_UNSHIFTED_INDEX(keycode); - } - - return index; - } else { - // Keycode is a regular index - return QK_UNICODEMAP_GET_INDEX(keycode); - } -} +#include "unicodemap.h" +#include "keycodes.h" bool process_unicodemap(uint16_t keycode, keyrecord_t *record) { if (keycode >= QK_UNICODEMAP && keycode <= QK_UNICODEMAP_PAIR_MAX && record->event.pressed) { - uint32_t code_point = pgm_read_dword(unicode_map + unicodemap_index(keycode)); - register_unicode(code_point); + register_unicodemap(unicodemap_index(keycode)); } return true; } diff --git a/quantum/process_keycode/process_unicodemap.h b/quantum/process_keycode/process_unicodemap.h index 5a3aeb0000..f07082e9ef 100644 --- a/quantum/process_keycode/process_unicodemap.h +++ b/quantum/process_keycode/process_unicodemap.h @@ -18,11 +18,6 @@ #include #include - #include "action.h" -#include "progmem.h" - -extern const uint32_t unicode_map[] PROGMEM; -uint16_t unicodemap_index(uint16_t keycode); -bool process_unicodemap(uint16_t keycode, keyrecord_t *record); +bool process_unicodemap(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/quantum.c b/quantum/quantum.c index 3d440e0de8..3323a5adb6 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -68,10 +68,6 @@ # include "process_unicode_common.h" #endif -#ifdef UNICODE_ENABLE -# include "process_unicode.h" -#endif - #ifdef VELOCIKEY_ENABLE # include "velocikey.h" #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index 017844c558..4d183e755f 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -97,16 +97,16 @@ extern layer_state_t layer_state; # include "leader.h" #endif -#ifdef UCIS_ENABLE -# include "process_ucis.h" +#ifdef UNICODE_COMMON_ENABLE +# include "unicode.h" #endif -#ifdef UNICODEMAP_ENABLE -# include "process_unicodemap.h" +#ifdef UCIS_ENABLE +# include "ucis.h" #endif -#ifdef UNICODE_COMMON_ENABLE -# include "unicode.h" +#ifdef UNICODEMAP_ENABLE +# include "unicodemap.h" #endif #ifdef KEY_OVERRIDE_ENABLE diff --git a/quantum/quantum_keycodes_legacy.h b/quantum/quantum_keycodes_legacy.h index ad078cdad5..260ac1c8a4 100644 --- a/quantum/quantum_keycodes_legacy.h +++ b/quantum/quantum_keycodes_legacy.h @@ -55,4 +55,4 @@ #define GUI_TOG QK_MAGIC_TOGGLE_GUI #define X(i) UM(i) -#define XP(i, j) UM(i, j) +#define XP(i, j) UP(i, j) diff --git a/quantum/unicode/ucis.c b/quantum/unicode/ucis.c new file mode 100644 index 0000000000..32be785206 --- /dev/null +++ b/quantum/unicode/ucis.c @@ -0,0 +1,96 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "ucis.h" +#include "unicode.h" +#include "action.h" + +uint8_t count = 0; +bool active = false; +char input[UCIS_MAX_INPUT_LENGTH] = {0}; + +void ucis_start(void) { + count = 0; + active = true; + + register_unicode(0x2328); // ⌨ +} + +bool ucis_active(void) { + return active; +} + +uint8_t ucis_count(void) { + return count; +} + +static char keycode_to_char(uint16_t keycode) { + if (keycode >= KC_A && keycode <= KC_Z) { + return 'a' + (keycode - KC_A); + } else if (keycode >= KC_1 && keycode <= KC_9) { + return '1' + (keycode - KC_1); + } else if (keycode == KC_0) { + return '0'; + } + return 0; +} + +bool ucis_add(uint16_t keycode) { + char c = keycode_to_char(keycode); + if (c) { + input[count++] = c; + return true; + } + return false; +} + +bool ucis_remove_last(void) { + if (count) { + count--; + return true; + } + + return false; +} + +static bool match_mnemonic(char *mnemonic) { + for (uint8_t i = 0; input[i]; i++) { + if (i > count || input[i] != mnemonic[i]) { + return false; + } + } + return true; +} + +void ucis_finish(void) { + uint8_t i = 0; + bool found = false; + for (; ucis_symbol_table[i].mnemonic; i++) { + if (match_mnemonic(ucis_symbol_table[i].mnemonic)) { + found = true; + break; + } + } + + if (found) { + for (uint8_t j = 0; j <= count; j++) { + tap_code(KC_BACKSPACE); + } + register_ucis(i); + } + + active = false; +} + +void ucis_cancel(void) { + count = 0; + active = false; +} + +void register_ucis(uint8_t index) { + const uint32_t *code_points = ucis_symbol_table[index].code_points; + + for (int i = 0; i < UCIS_MAX_CODE_POINTS && code_points[i]; i++) { + register_unicode(code_points[i]); + } +} diff --git a/quantum/unicode/ucis.h b/quantum/unicode/ucis.h new file mode 100644 index 0000000000..5a4fa26784 --- /dev/null +++ b/quantum/unicode/ucis.h @@ -0,0 +1,97 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +/** + * \file + * + * \defgroup ucis UCIS + * \{ + */ + +#ifndef UCIS_MAX_INPUT_LENGTH +# define UCIS_MAX_INPUT_LENGTH 32 +#endif + +#ifndef UCIS_MAX_CODE_POINTS +# define UCIS_MAX_CODE_POINTS 3 +#endif + +typedef struct { + char* mnemonic; + uint32_t code_points[UCIS_MAX_CODE_POINTS]; +} ucis_symbol_t; + +// clang-format off + +#define UCIS_TABLE(...) { \ + __VA_ARGS__, \ + { NULL, {} } \ +} + +#define UCIS_SYM(name, ...) { \ + .mnemonic = name, \ + .code_points = {__VA_ARGS__} \ +} + +// clang-format on + +extern const ucis_symbol_t ucis_symbol_table[]; + +/** + * \brief Begin the input sequence. + */ +void ucis_start(void); + +/** + * \brief Whether UCIS is currently active. + * + * \return `true` if UCIS is active. + */ +bool ucis_active(void); + +/** + * \brief Get the number of characters in the input sequence buffer. + * + * \return The current input sequence buffer length. + */ +uint8_t ucis_count(void); + +/** + * \brief Add the given keycode to the input sequence buffer. + * + * \param keycode The keycode to add. Must be between `KC_A` and `KC_Z`, or `KC_1` and `KC_0`. + * + * \return `true` if the keycode was added. + */ +bool ucis_add(uint16_t keycode); + +/** + * \brief Remove the last character from the input sequence. + * + * \return `true` if the sequence was not empty. + */ +bool ucis_remove_last(void); + +/** + * Mark the input sequence as complete, and attempt to match. + */ +void ucis_finish(void); + +/** + * \brief Cancel the input sequence. + */ +void ucis_cancel(void); + +/** + * Send the code point(s) for the given UCIS index. + * + * \param index The index into the UCIS symbol table. + */ +void register_ucis(uint8_t index); + +/** \} */ diff --git a/quantum/unicode/unicode.c b/quantum/unicode/unicode.c index f92ba51984..78a4cad585 100644 --- a/quantum/unicode/unicode.c +++ b/quantum/unicode/unicode.c @@ -73,16 +73,8 @@ static int8_t selected_count = ARRAY_SIZE(selected); static int8_t selected_index; #endif -/** \brief unicode input mode set at user level - * - * Run user code on unicode input mode change - */ __attribute__((weak)) void unicode_input_mode_set_user(uint8_t input_mode) {} -/** \brief unicode input mode set at keyboard level - * - * Run keyboard code on unicode input mode change - */ __attribute__((weak)) void unicode_input_mode_set_kb(uint8_t input_mode) { unicode_input_mode_set_user(input_mode); } @@ -172,6 +164,10 @@ uint8_t get_unicode_input_mode(void) { return unicode_config.input_mode; } +static void persist_unicode_input_mode(void) { + eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode); +} + void set_unicode_input_mode(uint8_t mode) { unicode_config.input_mode = mode; persist_unicode_input_mode(); @@ -182,26 +178,34 @@ void set_unicode_input_mode(uint8_t mode) { dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode); } -void cycle_unicode_input_mode(int8_t offset) { +static void cycle_unicode_input_mode(int8_t offset) { #if UNICODE_SELECTED_MODES != -1 selected_index = (selected_index + offset) % selected_count; if (selected_index < 0) { selected_index += selected_count; } + unicode_config.input_mode = selected[selected_index]; + # if UNICODE_CYCLE_PERSIST persist_unicode_input_mode(); # endif + # ifdef AUDIO_ENABLE unicode_play_song(unicode_config.input_mode); # endif + unicode_input_mode_set_kb(unicode_config.input_mode); dprintf("Unicode input mode cycle to: %u\n", unicode_config.input_mode); #endif } -void persist_unicode_input_mode(void) { - eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode); +void unicode_input_mode_step(void) { + cycle_unicode_input_mode(1); +} + +void unicode_input_mode_step_reverse(void) { + cycle_unicode_input_mode(-1); } __attribute__((weak)) void unicode_input_start(void) { diff --git a/quantum/unicode/unicode.h b/quantum/unicode/unicode.h index fc0e9d3d2b..90a54c8b18 100644 --- a/quantum/unicode/unicode.h +++ b/quantum/unicode/unicode.h @@ -19,6 +19,13 @@ #include #include "unicode_keycodes.h" +/** + * \file + * + * \defgroup unicode Unicode + * \{ + */ + typedef union { uint8_t raw; struct { @@ -41,21 +48,87 @@ enum unicode_input_modes { UNICODE_MODE_COUNT // Number of available input modes (always leave at the end) }; -void unicode_input_mode_init(void); +void unicode_input_mode_init(void); + +/** + * \brief Get the current Unicode input mode. + * + * \return The currently active Unicode input mode. + */ uint8_t get_unicode_input_mode(void); -void set_unicode_input_mode(uint8_t mode); -void cycle_unicode_input_mode(int8_t offset); -void persist_unicode_input_mode(void); +/** + * \brief Set the Unicode input mode. + * + * \param mode The input mode to set. + */ +void set_unicode_input_mode(uint8_t mode); + +/** + * \brief Change to the next Unicode input mode. + */ +void unicode_input_mode_step(void); + +/** + * \brief Change to the previous Unicode input mode. + */ +void unicode_input_mode_step_reverse(void); + +/** + * \brief User-level callback, invoked when the input mode is changed. + * + * \param input_mode The new input mode. + */ void unicode_input_mode_set_user(uint8_t input_mode); + +/** + * \brief Keyboard-level callback, invoked when the input mode is changed. + * + * \param input_mode The new input mode. + */ void unicode_input_mode_set_kb(uint8_t input_mode); +/** + * \brief Begin the Unicode input sequence. The exact behavior depends on the currently selected input mode. + */ void unicode_input_start(void); + +/** + * \brief Complete the Unicode input sequence. The exact behavior depends on the currently selected input mode. + */ void unicode_input_finish(void); + +/** + * \brief Cancel the Unicode input sequence. The exact behavior depends on the currently selected input mode. + */ void unicode_input_cancel(void); +/** + * \brief Send a 16-bit hex number. + * + * \param hex The number to send. + */ void register_hex(uint16_t hex); + +/** + * \brief Send a 32-bit hex number. + * + * \param hex The number to send. + */ void register_hex32(uint32_t hex); + +/** + * \brief Input a single Unicode character. A surrogate pair will be sent if required by the input mode. + * + * \param code_point The code point of the character to send. + */ void register_unicode(uint32_t code_point); +/** + * \brief Send a string containing Unicode characters. + * + * \param str The string to send. + */ void send_unicode_string(const char *str); + +/** \} */ diff --git a/quantum/unicode/unicodemap.c b/quantum/unicode/unicodemap.c new file mode 100644 index 0000000000..2f618056a2 --- /dev/null +++ b/quantum/unicode/unicodemap.c @@ -0,0 +1,43 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "unicodemap.h" +#include "unicode.h" +#include "keycodes.h" +#include "quantum_keycodes.h" +#include "modifiers.h" +#include "host.h" +#include "action_util.h" + +uint8_t unicodemap_index(uint16_t keycode) { + if (keycode >= QK_UNICODEMAP_PAIR) { + // Keycode is a pair: extract index based on Shift / Caps Lock state + uint16_t index; + + uint8_t mods = get_mods() | get_weak_mods(); +#ifndef NO_ACTION_ONESHOT + mods |= get_oneshot_mods(); +#endif + + bool shift = mods & MOD_MASK_SHIFT; + bool caps = host_keyboard_led_state().caps_lock; + if (shift ^ caps) { + index = QK_UNICODEMAP_PAIR_GET_SHIFTED_INDEX(keycode); + } else { + index = QK_UNICODEMAP_PAIR_GET_UNSHIFTED_INDEX(keycode); + } + + return index; + } else { + // Keycode is a regular index + return QK_UNICODEMAP_GET_INDEX(keycode); + } +} + +uint32_t unicodemap_get_code_point(uint8_t index) { + return pgm_read_dword(unicode_map + index); +} + +void register_unicodemap(uint8_t index) { + register_unicode(unicodemap_get_code_point(index)); +} diff --git a/quantum/unicode/unicodemap.h b/quantum/unicode/unicodemap.h new file mode 100644 index 0000000000..00d2aec8fa --- /dev/null +++ b/quantum/unicode/unicodemap.h @@ -0,0 +1,43 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "progmem.h" + +/** + * \file + * + * \defgroup unicodemap Unicode Map + * \{ + */ + +extern const uint32_t unicode_map[] PROGMEM; + +/** + * \brief Get the index into the `unicode_map` array for the given keycode, respecting shift state for pair keycodes. + * + * \param keycode The Unicode Map keycode to get the index of. + * + * \return An index into the `unicode_map` array. + */ +uint8_t unicodemap_index(uint16_t keycode); + +/** + * \brief Get the code point for the given index in the `unicode_map` array. + * + * \param index The index into the `unicode_map` array. + * + * \return A Unicode code point value. + */ +uint32_t unicodemap_get_code_point(uint8_t index); + +/** + * \brief Send the code point for the given index in the `unicode_map` array. + * + * \param index The index into the `unicode_map` array. + */ +void register_unicodemap(uint8_t index); + +/** \} */ diff --git a/tests/test_common/test_driver.cpp b/tests/test_common/test_driver.cpp index f1c52cb7b6..0495da8205 100644 --- a/tests/test_common/test_driver.cpp +++ b/tests/test_common/test_driver.cpp @@ -60,7 +60,10 @@ void TestDriver::send_extra(report_extra_t* report) { namespace internal { void expect_unicode_code_point(TestDriver& driver, uint32_t code_point) { testing::InSequence seq; - EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_U)); + EXPECT_REPORT(driver, (KC_LEFT_CTRL, KC_LEFT_SHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_CTRL, KC_LEFT_SHIFT, KC_U)); + EXPECT_REPORT(driver, (KC_LEFT_CTRL, KC_LEFT_SHIFT)); + EXPECT_EMPTY_REPORT(driver); bool print_zero = false; for (int i = 7; i >= 0; --i) { @@ -71,10 +74,12 @@ void expect_unicode_code_point(TestDriver& driver, uint32_t code_point) { const uint8_t digit = (code_point >> (i * 4)) & 0xf; if (digit || print_zero) { EXPECT_REPORT(driver, (hex_digit_to_keycode(digit))); + EXPECT_EMPTY_REPORT(driver); print_zero = true; } } - EXPECT_REPORT(driver, (KC_SPC)); + EXPECT_REPORT(driver, (KC_SPACE)); + EXPECT_EMPTY_REPORT(driver); } } // namespace internal diff --git a/tests/unicode/config.h b/tests/unicode/config.h new file mode 100644 index 0000000000..16f95f7f8d --- /dev/null +++ b/tests/unicode/config.h @@ -0,0 +1,8 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "test_common.h" + +#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX, UNICODE_MODE_MACOS diff --git a/tests/unicode/test.mk b/tests/unicode/test.mk new file mode 100644 index 0000000000..1afc79be55 --- /dev/null +++ b/tests/unicode/test.mk @@ -0,0 +1,5 @@ +# -------------------------------------------------------------------------------- +# Keep this file, even if it is empty, as a marker that this folder contains tests +# -------------------------------------------------------------------------------- + +UNICODE_COMMON = yes diff --git a/tests/unicode/test_unicode.cpp b/tests/unicode/test_unicode.cpp new file mode 100644 index 0000000000..a8500e3ba1 --- /dev/null +++ b/tests/unicode/test_unicode.cpp @@ -0,0 +1,86 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_keymap_key.hpp" + +using testing::_; + +class Unicode : public TestFixture {}; + +TEST_F(Unicode, sends_bmp_unicode_sequence) { + TestDriver driver; + + set_unicode_input_mode(UNICODE_MODE_LINUX); + + EXPECT_UNICODE(driver, 0x03A8); // Ψ + register_unicode(0x03A8); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(Unicode, sends_smp_unicode_sequence) { + TestDriver driver; + + set_unicode_input_mode(UNICODE_MODE_LINUX); + + EXPECT_UNICODE(driver, 0x1F9D9); // 🧙 + register_unicode(0x1F9D9); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(Unicode, sends_surrogate_pair_for_macos) { + TestDriver driver; + + set_unicode_input_mode(UNICODE_MODE_MACOS); + + // EXPECT_UNICODE() assumes Linux input mode + { + testing::InSequence s; + + // Alt+D83EDDD9 🧙 + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_D, KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_8, KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_3, KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_E, KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_D, KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_D, KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_D, KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_9, KC_LEFT_ALT)); + EXPECT_REPORT(driver, (KC_LEFT_ALT)); + EXPECT_EMPTY_REPORT(driver); + } + + register_unicode(0x1F9D9); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(Unicode, sends_unicode_string) { + TestDriver driver; + + set_unicode_input_mode(UNICODE_MODE_LINUX); + + { + testing::InSequence s; + + EXPECT_UNICODE(driver, 0xFF31); + EXPECT_UNICODE(driver, 0xFF2D); + EXPECT_UNICODE(driver, 0xFF2B); + EXPECT_UNICODE(driver, 0xFF01); + } + send_unicode_string("QMK!"); + + VERIFY_AND_CLEAR(driver); +} diff --git a/tests/unicode/unicode_basic/config.h b/tests/unicode/unicode_basic/config.h new file mode 100644 index 0000000000..16f95f7f8d --- /dev/null +++ b/tests/unicode/unicode_basic/config.h @@ -0,0 +1,8 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "test_common.h" + +#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX, UNICODE_MODE_MACOS diff --git a/tests/unicode/unicode_basic/test.mk b/tests/unicode/unicode_basic/test.mk new file mode 100644 index 0000000000..f53051dce6 --- /dev/null +++ b/tests/unicode/unicode_basic/test.mk @@ -0,0 +1,5 @@ +# -------------------------------------------------------------------------------- +# Keep this file, even if it is empty, as a marker that this folder contains tests +# -------------------------------------------------------------------------------- + +UNICODE_ENABLE = yes diff --git a/tests/unicode/unicode_basic/test_unicode_basic.cpp b/tests/unicode/unicode_basic/test_unicode_basic.cpp new file mode 100644 index 0000000000..598b57277f --- /dev/null +++ b/tests/unicode/unicode_basic/test_unicode_basic.cpp @@ -0,0 +1,26 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_keymap_key.hpp" + +using testing::_; + +class UnicodeBasic : public TestFixture {}; + +TEST_F(UnicodeBasic, sends_unicode_sequence) { + TestDriver driver; + + set_unicode_input_mode(UNICODE_MODE_LINUX); + + auto key_uc = KeymapKey(0, 0, 0, UC(0x03A8)); // Ψ + + set_keymap({key_uc}); + + EXPECT_UNICODE(driver, 0x03A8); + tap_key(key_uc); + + VERIFY_AND_CLEAR(driver); +} diff --git a/tests/unicode/unicode_map/config.h b/tests/unicode/unicode_map/config.h new file mode 100644 index 0000000000..0d86922f0d --- /dev/null +++ b/tests/unicode/unicode_map/config.h @@ -0,0 +1,8 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "test_common.h" + +#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX diff --git a/tests/unicode/unicode_map/test.mk b/tests/unicode/unicode_map/test.mk new file mode 100644 index 0000000000..e6d0034799 --- /dev/null +++ b/tests/unicode/unicode_map/test.mk @@ -0,0 +1,5 @@ +# -------------------------------------------------------------------------------- +# Keep this file, even if it is empty, as a marker that this folder contains tests +# -------------------------------------------------------------------------------- + +UNICODEMAP_ENABLE = yes diff --git a/tests/unicode/unicode_map/test_unicode_map.cpp b/tests/unicode/unicode_map/test_unicode_map.cpp new file mode 100644 index 0000000000..cacd8f3c75 --- /dev/null +++ b/tests/unicode/unicode_map/test_unicode_map.cpp @@ -0,0 +1,54 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_keymap_key.hpp" + +using testing::_; + +const uint32_t PROGMEM unicode_map[] = { + 0x03A8, // Ψ + 0x2318 // ⌘ +}; + +class UnicodeMap : public TestFixture {}; + +TEST_F(UnicodeMap, sends_unicodemap_code_point_from_keycode) { + TestDriver driver; + + auto key_um = KeymapKey(0, 0, 0, UM(0)); + + set_keymap({key_um}); + + EXPECT_UNICODE(driver, 0x03A8); + tap_key(key_um); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(UnicodeMap, sends_unicodemap_pair_from_keycode) { + TestDriver driver; + + auto key_shift = KeymapKey(0, 0, 0, KC_LEFT_SHIFT); + auto key_up = KeymapKey(0, 1, 0, UP(0, 1)); + + set_keymap({key_shift, key_up}); + + EXPECT_UNICODE(driver, 0x03A8); + tap_key(key_up); + + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + key_shift.press(); + run_one_scan_loop(); + + EXPECT_UNICODE(driver, 0x2318); + tap_key(key_up); + + EXPECT_NO_REPORT(driver); + key_shift.release(); + run_one_scan_loop(); + + VERIFY_AND_CLEAR(driver); +} diff --git a/tests/unicode/unicode_ucis/config.h b/tests/unicode/unicode_ucis/config.h new file mode 100644 index 0000000000..0d86922f0d --- /dev/null +++ b/tests/unicode/unicode_ucis/config.h @@ -0,0 +1,8 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "test_common.h" + +#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX diff --git a/tests/unicode/unicode_ucis/test.mk b/tests/unicode/unicode_ucis/test.mk new file mode 100644 index 0000000000..d7ac651758 --- /dev/null +++ b/tests/unicode/unicode_ucis/test.mk @@ -0,0 +1,5 @@ +# -------------------------------------------------------------------------------- +# Keep this file, even if it is empty, as a marker that this folder contains tests +# -------------------------------------------------------------------------------- + +UCIS_ENABLE = yes diff --git a/tests/unicode/unicode_ucis/test_unicode_ucis.cpp b/tests/unicode/unicode_ucis/test_unicode_ucis.cpp new file mode 100644 index 0000000000..acc6329f85 --- /dev/null +++ b/tests/unicode/unicode_ucis/test_unicode_ucis.cpp @@ -0,0 +1,221 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_keymap_key.hpp" + +using testing::_; + +// clang-format off +const ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE( + UCIS_SYM("qmk", 0x03A8) // Ψ +); +// clang-format on + +class UnicodeUCIS : public TestFixture {}; + +TEST_F(UnicodeUCIS, matches_sequence) { + TestDriver driver; + + auto key_q = KeymapKey(0, 0, 0, KC_Q); + auto key_m = KeymapKey(0, 1, 0, KC_M); + auto key_k = KeymapKey(0, 2, 0, KC_K); + auto key_enter = KeymapKey(0, 3, 0, KC_ENTER); + + set_keymap({key_q, key_m, key_k, key_enter}); + + EXPECT_UNICODE(driver, 0x2328); // ⌨ + ucis_start(); + + EXPECT_EQ(ucis_active(), true); + EXPECT_EQ(ucis_count(), 0); + + EXPECT_REPORT(driver, (KC_Q)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_q); + EXPECT_EQ(ucis_count(), 1); + + EXPECT_REPORT(driver, (KC_M)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_m); + EXPECT_EQ(ucis_count(), 2); + + EXPECT_REPORT(driver, (KC_K)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_k); + EXPECT_EQ(ucis_count(), 3); + + EXPECT_REPORT(driver, (KC_BACKSPACE)).Times(4); + EXPECT_EMPTY_REPORT(driver).Times(4); + EXPECT_UNICODE(driver, 0x03A8); + tap_key(key_enter); + + EXPECT_EQ(ucis_active(), false); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(UnicodeUCIS, cancels_sequence) { + TestDriver driver; + + auto key_q = KeymapKey(0, 0, 0, KC_Q); + auto key_m = KeymapKey(0, 1, 0, KC_M); + auto key_k = KeymapKey(0, 2, 0, KC_K); + auto key_escape = KeymapKey(0, 3, 0, KC_ESCAPE); + + set_keymap({key_q, key_m, key_k, key_escape}); + + EXPECT_UNICODE(driver, 0x2328); // ⌨ + ucis_start(); + + EXPECT_EQ(ucis_active(), true); + EXPECT_EQ(ucis_count(), 0); + + EXPECT_REPORT(driver, (KC_Q)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_q); + EXPECT_EQ(ucis_count(), 1); + + EXPECT_REPORT(driver, (KC_M)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_m); + EXPECT_EQ(ucis_count(), 2); + + EXPECT_REPORT(driver, (KC_K)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_k); + EXPECT_EQ(ucis_count(), 3); + + EXPECT_NO_REPORT(driver); + tap_key(key_escape); + + EXPECT_EQ(ucis_active(), false); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(UnicodeUCIS, matches_sequence_with_corrected_typo) { + TestDriver driver; + + auto key_q = KeymapKey(0, 0, 0, KC_Q); + auto key_m = KeymapKey(0, 1, 0, KC_M); + auto key_j = KeymapKey(0, 2, 0, KC_J); + auto key_k = KeymapKey(0, 3, 0, KC_K); + auto key_backspace = KeymapKey(0, 4, 0, KC_BACKSPACE); + auto key_enter = KeymapKey(0, 5, 0, KC_ENTER); + + set_keymap({key_q, key_m, key_j, key_k, key_backspace, key_enter}); + + EXPECT_UNICODE(driver, 0x2328); // ⌨ + ucis_start(); + + EXPECT_EQ(ucis_active(), true); + EXPECT_EQ(ucis_count(), 0); + + EXPECT_REPORT(driver, (KC_Q)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_q); + EXPECT_EQ(ucis_count(), 1); + + EXPECT_REPORT(driver, (KC_M)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_m); + EXPECT_EQ(ucis_count(), 2); + + EXPECT_REPORT(driver, (KC_J)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_j); + EXPECT_EQ(ucis_count(), 3); + + EXPECT_REPORT(driver, (KC_BACKSPACE)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_backspace); + EXPECT_EQ(ucis_count(), 2); + + EXPECT_REPORT(driver, (KC_K)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_k); + EXPECT_EQ(ucis_count(), 3); + + EXPECT_REPORT(driver, (KC_BACKSPACE)).Times(4); + EXPECT_EMPTY_REPORT(driver).Times(4); + EXPECT_UNICODE(driver, 0x03A8); + tap_key(key_enter); + + EXPECT_EQ(ucis_active(), false); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(UnicodeUCIS, does_not_match_longer_sequence) { + TestDriver driver; + + auto key_q = KeymapKey(0, 0, 0, KC_Q); + auto key_m = KeymapKey(0, 1, 0, KC_M); + auto key_k = KeymapKey(0, 2, 0, KC_K); + auto key_enter = KeymapKey(0, 3, 0, KC_ENTER); + + set_keymap({key_q, key_m, key_k, key_enter}); + + EXPECT_UNICODE(driver, 0x2328); // ⌨ + ucis_start(); + + EXPECT_EQ(ucis_active(), true); + EXPECT_EQ(ucis_count(), 0); + + EXPECT_REPORT(driver, (KC_Q)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_q); + EXPECT_EQ(ucis_count(), 1); + + EXPECT_REPORT(driver, (KC_M)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_m); + EXPECT_EQ(ucis_count(), 2); + + EXPECT_REPORT(driver, (KC_K)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_k); + EXPECT_EQ(ucis_count(), 3); + + EXPECT_REPORT(driver, (KC_K)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_k); + EXPECT_EQ(ucis_count(), 4); + + EXPECT_NO_REPORT(driver); + tap_key(key_enter); + + EXPECT_EQ(ucis_active(), false); + + VERIFY_AND_CLEAR(driver); +} + +TEST_F(UnicodeUCIS, does_not_match_shorter_sequence) { + TestDriver driver; + + auto key_q = KeymapKey(0, 0, 0, KC_Q); + auto key_enter = KeymapKey(0, 1, 0, KC_ENTER); + + set_keymap({key_q, key_enter}); + + EXPECT_UNICODE(driver, 0x2328); // ⌨ + ucis_start(); + + EXPECT_EQ(ucis_active(), true); + EXPECT_EQ(ucis_count(), 0); + + EXPECT_REPORT(driver, (KC_Q)); + EXPECT_EMPTY_REPORT(driver); + tap_key(key_q); + EXPECT_EQ(ucis_count(), 1); + + EXPECT_NO_REPORT(driver); + tap_key(key_enter); + + EXPECT_EQ(ucis_active(), false); + + VERIFY_AND_CLEAR(driver); +} -- cgit v1.2.3