From c4551d7ef1ed2c1069f23cc8499b7c7fc30f3ecf Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Wed, 29 Dec 2021 20:17:34 -0800 Subject: [Keymap] Reorganization, cleanup and readmes for drashna code (#15617) --- .../4x6_right/keymaps/drashna/keymap.c | 100 ------- .../5x6_right/keymaps/drashna/rules.mk | 46 +++- keyboards/keebio/iris/keymaps/drashna/config.h | 9 - keyboards/keebio/iris/keymaps/drashna/rules.mk | 5 +- keyboards/moonlander/keymaps/drashna/keymap.c | 64 ++--- keyboards/moonlander/keymaps/drashna/rules.mk | 10 +- keyboards/splitkb/kyria/keymaps/drashna/rules.mk | 29 +- .../work_board/keymaps/drashna/config.h | 5 + .../work_board/keymaps/drashna/keymap.c | 37 +-- .../work_board/keymaps/drashna/rules.mk | 4 + layouts/community/ergodox/drashna/config.h | 7 +- layouts/community/ergodox/drashna/keymap.c | 40 +-- layouts/community/ortho_4x12/drashna/keymap.c | 55 +--- layouts/community/ortho_4x12/drashna/rules.mk | 24 +- layouts/community/split_3x6_3/drashna/config.h | 4 + layouts/community/split_3x6_3/drashna/keymap.c | 5 +- layouts/community/split_3x6_3/drashna/rules.mk | 35 ++- users/drashna/callbacks.c | 215 +++++++++++++++ users/drashna/callbacks.h | 25 ++ users/drashna/callbacks.md | 71 +++++ users/drashna/config.h | 35 +-- users/drashna/drashna.c | 291 +------------------- users/drashna/drashna.h | 59 +--- .../keyrecords/autocorrection/autocorrection.c | 14 +- .../keyrecords/autocorrection/autocorrection.h | 2 +- .../autocorrection/make_autocorrection_data.py | 5 +- users/drashna/keyrecords/autocorrection/readme.md | 301 +++++++++++++++++++++ users/drashna/keyrecords/caps_word.c | 6 +- users/drashna/keyrecords/capwords.md | 36 +++ users/drashna/keyrecords/keycodes.md | 18 ++ users/drashna/keyrecords/process_records.c | 42 ++- users/drashna/keyrecords/process_records.h | 37 +-- users/drashna/keyrecords/readme.md | 9 + users/drashna/keyrecords/secrets.md | 123 +++++++++ users/drashna/keyrecords/tap_dance.md | 121 +++++++++ users/drashna/keyrecords/tap_dances.c | 17 +- users/drashna/keyrecords/tap_dances.h | 17 +- users/drashna/keyrecords/tapping.c | 64 +++++ users/drashna/keyrecords/unicode.c | 35 +-- users/drashna/keyrecords/unicode.md | 27 ++ users/drashna/keyrecords/wrappers.h | 18 +- users/drashna/keyrecords/wrappers.md | 11 + users/drashna/oled/drashna_font.h | 4 +- users/drashna/oled/oled_stuff.c | 9 +- users/drashna/oled/readme.md | 42 +++ users/drashna/pointing/pointing.c | 17 +- users/drashna/pointing/pointing.h | 17 +- users/drashna/pointing/readme.md | 19 ++ users/drashna/post_config.h | 21 +- users/drashna/readme.md | 24 +- users/drashna/readme/handlers.md | 97 ------- users/drashna/readme/keycodes.md | 10 - users/drashna/readme/rgb.md | 43 --- users/drashna/readme/secrets.md | 123 --------- users/drashna/readme/tap_dance.md | 119 -------- users/drashna/readme/wrappers.md | 11 - users/drashna/rgb/readme.md | 52 ++++ users/drashna/rgb/rgb_matrix_stuff.c | 94 ++++--- users/drashna/rgb/rgb_matrix_stuff.h | 20 +- users/drashna/rgb/rgb_stuff.c | 17 +- users/drashna/rgb/rgb_stuff.h | 17 +- users/drashna/rgblight_breathe_table.h | 17 +- users/drashna/rules.mk | 41 +-- users/drashna/split/readme.md | 29 ++ users/drashna/split/transport_sync.c | 57 +++- users/drashna/split/transport_sync.h | 18 +- users/drashna/template.c | 17 +- users/drashna/template.h | 17 +- 68 files changed, 1579 insertions(+), 1451 deletions(-) create mode 100644 users/drashna/callbacks.c create mode 100644 users/drashna/callbacks.h create mode 100644 users/drashna/callbacks.md create mode 100644 users/drashna/keyrecords/autocorrection/readme.md create mode 100644 users/drashna/keyrecords/capwords.md create mode 100644 users/drashna/keyrecords/keycodes.md create mode 100644 users/drashna/keyrecords/readme.md create mode 100644 users/drashna/keyrecords/secrets.md create mode 100644 users/drashna/keyrecords/tap_dance.md create mode 100644 users/drashna/keyrecords/tapping.c create mode 100644 users/drashna/keyrecords/unicode.md create mode 100644 users/drashna/keyrecords/wrappers.md create mode 100644 users/drashna/oled/readme.md create mode 100644 users/drashna/pointing/readme.md delete mode 100644 users/drashna/readme/handlers.md delete mode 100644 users/drashna/readme/keycodes.md delete mode 100644 users/drashna/readme/rgb.md delete mode 100644 users/drashna/readme/secrets.md delete mode 100644 users/drashna/readme/tap_dance.md delete mode 100644 users/drashna/readme/wrappers.md create mode 100644 users/drashna/rgb/readme.md create mode 100644 users/drashna/split/readme.md diff --git a/keyboards/handwired/tractyl_manuform/4x6_right/keymaps/drashna/keymap.c b/keyboards/handwired/tractyl_manuform/4x6_right/keymaps/drashna/keymap.c index 78a7db67a9..290ea22c5f 100644 --- a/keyboards/handwired/tractyl_manuform/4x6_right/keymaps/drashna/keymap.c +++ b/keyboards/handwired/tractyl_manuform/4x6_right/keymaps/drashna/keymap.c @@ -115,103 +115,3 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ), }; // clang-format on - -#ifdef POINTING_DEVICE_ENABLE -static uint16_t mouse_timer = 0; -static uint16_t mouse_debounce_timer = 0; -static uint8_t mouse_keycode_tracker = 0; -bool tap_toggling = false; - -void process_mouse_user(report_mouse_t* mouse_report, int8_t x, int8_t y) { - if ((x || y) && timer_elapsed(mouse_timer) > 125) { - mouse_timer = timer_read(); - if (!layer_state_is(_MOUSE) && !(layer_state_is(_GAMEPAD) || layer_state_is(_DIABLO)) && timer_elapsed(mouse_debounce_timer) > 125) { - layer_on(_MOUSE); - } - } - -# ifdef TAPPING_TERM_PER_KEY - if (timer_elapsed(mouse_debounce_timer) > get_tapping_term(KC_BTN1, NULL) -# else - if (timer_elapsed(mouse_debounce_timer) > TAPPING_TERM -# endif - || (layer_state_is(_GAMEPAD) || layer_state_is(_DIABLO))) { - mouse_report->x = x; - mouse_report->y = y; - } -# ifdef OLED_ENABLE - if (x || y) oled_timer = timer_read32(); -# endif -} - -void matrix_scan_keymap(void) { - if (timer_elapsed(mouse_timer) > 650 && layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) { - layer_off(_MOUSE); - } - if (tap_toggling) { - if (!layer_state_is(_MOUSE)) { - layer_on(_MOUSE); - } - } -} - -bool process_record_keymap(uint16_t keycode, keyrecord_t* record) { - switch (keycode) { - case TT(_MOUSE): - { - if (record->event.pressed) { - mouse_keycode_tracker++; - } else { -# if TAPPING_TOGGLE != 0 - if (record->tap.count == TAPPING_TOGGLE) { - tap_toggling ^= 1; -# if TAPPING_TOGGLE == 1 - if (!tap_toggling) mouse_keycode_tracker -= record->tap.count + 1; -# else - if (!tap_toggling) mouse_keycode_tracker -= record->tap.count; -# endif - } else { - mouse_keycode_tracker--; - } -# endif - } - mouse_timer = timer_read(); - break; - } - case MO(_MOUSE): - case DPI_CONFIG: - case KC_MS_UP ... KC_MS_WH_RIGHT: - record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--; - mouse_timer = timer_read(); - break; - default: - if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) { - layer_off(_MOUSE); - } - mouse_keycode_tracker = 0; - mouse_debounce_timer = timer_read(); - break; - } - return true; -} - -layer_state_t layer_state_set_keymap(layer_state_t state) { - if (layer_state_cmp(state, _GAMEPAD) || layer_state_cmp(state, _DIABLO)) { - state |= (1UL << _MOUSE); - } - return state; -} -#endif - -void matrix_init_keymap(void) { -#ifdef AUDIO_ENABLE - extern audio_config_t audio_config; - - if (!is_keyboard_master()) { - audio_stop_all(); - audio_config.enable = false; - } -#endif -} - -void keyboard_post_init_keymap(void) { matrix_init_keymap(); } 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 9b9032837e..0765bb2c6e 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk +++ b/keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/rules.mk @@ -1,14 +1,34 @@ -RGBLIGHT_ENABLE = yes -RGBLIGHT_STARTUP_ANIMATION = yes -AUDIO_ENABLE = yes -HAPTIC_ENABLE = no -COMMAND_ENABLE = no -TAP_DANCE_ENABLE = yes -UNICODE_ENABLE = yes -OLED_ENABLE = yes -WPM_ENABLE = yes -ENCODER_ENABLE = yes -ENCODER_MAP_ENABLE = yes -# DEBOUNCE_TYPE = sym_eager_pk +COMMAND_ENABLE = no +RGBLIGHT_ENABLE = yes +RGBLIGHT_STARTUP_ANIMATION = yes +AUDIO_ENABLE = yes +HAPTIC_ENABLE = no +TAP_DANCE_ENABLE = yes +OLED_ENABLE = yes +WPM_ENABLE = yes +ENCODER_ENABLE = yes +ENCODER_MAP_ENABLE = yes +AUTOCORRECTION_ENABLE = yes +CAPS_WORD_ENABLE = yes -LTO_SUPPORTED = no +ifeq ($(strip $(KEYBOARD)), handwired/tractyl_manuform/5x6_right/elite_c) + RGBLIGHT_ENABLE = no + AUDIO_ENABLE = no + HAPTIC_ENABLE = no + TAP_DANCE_ENABLE = no + OLED_ENABLE = no + WPM_ENABLE = no + ENCODER_ENABLE = no + AUTOCORRECTION_ENABLE = no + LTO_SUPPORTED = yes + SWAP_HANDS_ENABLE = no + CUSTOM_UNICODE_ENABLE = no + CAPS_WORD_ENABLE = no + BOOTLOADER = qmk-hid + BOOTLOADER_SIZE = 512 +endif +ifeq ($(strip $(KEYBOARD)), handwired/tractyl_manuform/5x6_right/teensy2pp) + AUTOCORRECTION_ENABLE = no + CAPS_WORD_ENABLE = yes +endif +# DEBOUNCE_TYPE = sym_eager_pk diff --git a/keyboards/keebio/iris/keymaps/drashna/config.h b/keyboards/keebio/iris/keymaps/drashna/config.h index f68166c98f..cf67aa6984 100644 --- a/keyboards/keebio/iris/keymaps/drashna/config.h +++ b/keyboards/keebio/iris/keymaps/drashna/config.h @@ -16,15 +16,6 @@ #pragma once -/* Use I2C or Serial, not both */ - -// #define USE_SERIAL -#define USE_I2C - -/* Select hand configuration */ - -// #define MASTER_LEFT -// #define MASTER_RIGHT #define EE_HANDS #ifdef RGBLIGHT_ENABLE diff --git a/keyboards/keebio/iris/keymaps/drashna/rules.mk b/keyboards/keebio/iris/keymaps/drashna/rules.mk index ca140d76ce..51b9a105d2 100644 --- a/keyboards/keebio/iris/keymaps/drashna/rules.mk +++ b/keyboards/keebio/iris/keymaps/drashna/rules.mk @@ -4,7 +4,6 @@ EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = no # Console for debug COMMAND_ENABLE = no # Commands for debug and configuration TAP_DANCE_ENABLE = no -RGBLIGHT_ENABLE = yes AUDIO_ENABLE = no NKRO_ENABLE = yes BACKLIGHT_ENABLE = no @@ -15,3 +14,7 @@ INDICATOR_LIGHTS = no RGBLIGHT_STARTUP_ANIMATION = no CUSTOM_UNICODE_ENABLE = no CUSTOM_SPLIT_TRANSPORT_SYNC = no + +ifneq ($(strip $(KEYBOARD)), keebio/iris/rev6) + RGBLIGHT_ENABLE = yes +endif diff --git a/keyboards/moonlander/keymaps/drashna/keymap.c b/keyboards/moonlander/keymaps/drashna/keymap.c index 1b5280e742..82abdb0055 100644 --- a/keyboards/moonlander/keymaps/drashna/keymap.c +++ b/keyboards/moonlander/keymaps/drashna/keymap.c @@ -63,27 +63,27 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [_GAMEPAD] = LAYOUT_moonlander_wrapper( - KC_ESC, KC_NO, KC_1, KC_2, KC_3, KC_4, HYPR(KC_Q), KC_TRNS, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, - KC_F1, KC_K, KC_Q, KC_W, KC_E, KC_R, KC_T, UC_SHRG, UC_DISA, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_TAB, KC_G, KC_A, KC_S, KC_D, KC_F, KC_TRNS, TG_GAME, KC_I, KC_O, KC_NO, KC_NO, KC_NO, KC_NO, - KC_LCTL, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_N, KC_M, KC_NO, KC_NO, KC_NO, KC_NO, + KC_ESC, XXXXXXX, KC_1, KC_2, KC_3, KC_4, HYPR(KC_Q), _______, KC_F9, KC_F10, KC_F11, KC_F12, XXXXXXX, KC_NO, + KC_F1, KC_K, KC_Q, KC_W, KC_E, KC_R, KC_T, UC_SHRG, UC_DISA, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, + KC_TAB, KC_G, KC_A, KC_S, KC_D, KC_F, _______, TG_GAME, KC_I, KC_O, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, + KC_LCTL, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, KC_GRV, KC_U, KC_I, KC_Y, KC_T, KC_PSCR, _______, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_NO, - KC_V, KC_SPC, KC_H, KC_NO, KC_NO, KC_SWAP_NUM + KC_V, KC_SPC, KC_H, KC_NO, XXXXXXX,KC_SWAP_NUM ), [_DIABLO] = LAYOUT_moonlander_wrapper( - KC_ESC, KC_V, KC_D, KC_LALT, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, - KC_TAB, KC_S, KC_I, KC_F, KC_M, KC_T, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_NO, KC_1, KC_2, KC_3, KC_4, KC_G, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_LCTL, KC_D3_1, KC_D3_2, KC_D3_3, KC_D3_4, KC_Z, KC_N, KC_M, KC_NO, KC_NO, KC_NO, KC_NO, - KC_NO, KC_NO, KC_L, KC_J, KC_F, KC_PSCR, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_ESC, KC_V, KC_D, KC_LALT, XXXXXXX, XXXXXXX, XXXXXXX, _______, KC_F9, KC_F10, KC_F11, KC_F12, XXXXXXX, KC_NO, + KC_TAB, KC_S, KC_I, KC_F, KC_M, KC_T, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, + XXXXXXX, KC_1, KC_2, KC_3, KC_4, KC_G, XXXXXXX, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, + KC_LCTL, KC_D3_1, KC_D3_2, KC_D3_3, KC_D3_4, KC_Z, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, + XXXXXXX, XXXXXXX, KC_L, KC_J, KC_F, KC_PSCR, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, KC_DIABLO_CLEAR, SFT_T(KC_SPACE), ALT_T(KC_Q), KC_PGDN, KC_DEL, KC_ENT ), [_DIABLOII] = LAYOUT_moonlander_wrapper( - KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_GRV, KC_NO, KC_TRNS, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, - KC_TAB, KC_A, KC_T, KC_Q, KC_I, KC_M, TG(_DIABLOII), KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_S, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, - KC_LCTL, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_N, KC_M, KC_NO, KC_NO, KC_NO, KC_NO, - KC_NO, KC_NO, KC_G, KC_F, KC_L, KC_V, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_GRV, XXXXXXX, _______, KC_F9, KC_F10, KC_F11, KC_F12, XXXXXXX, KC_NO, + KC_TAB, KC_A, KC_T, KC_Q, KC_I, KC_M, TG(_DIABLOII), _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, + KC_S, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, XXXXXXX, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, + KC_LCTL, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, + XXXXXXX, XXXXXXX, KC_G, KC_F, KC_L, KC_V, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_NO, KC_G, KC_LSFT, KC_LCTL, KC_PGDN, KC_DEL, KC_ENT ), @@ -164,7 +164,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { } #ifdef RGB_MATRIX_ENABLE -void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { +bool rgb_matrix_indicators_advanced_keymap(uint8_t led_min, uint8_t led_max) { if (layer_state_is(_GAMEPAD)) { RGB_MATRIX_INDICATOR_SET_COLOR(11, 0x00, 0xFF, 0x00); // Q RGB_MATRIX_INDICATOR_SET_COLOR(16, 0x00, 0xFF, 0xFF); // W @@ -180,37 +180,7 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { RGB_MATRIX_INDICATOR_SET_COLOR(20, 0x7A, 0x00, 0xFF); // 3 } - if (userspace_config.rgb_layer_change) { - switch (get_highest_layer(layer_state|default_layer_state)) { - case _DEFAULT_LAYER_1: - rgb_matrix_layer_helper(DEFAULT_LAYER_1_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_2: - rgb_matrix_layer_helper(DEFAULT_LAYER_2_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_3: - rgb_matrix_layer_helper(DEFAULT_LAYER_3_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_4: - rgb_matrix_layer_helper(DEFAULT_LAYER_4_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _GAMEPAD: - rgb_matrix_layer_helper(HSV_ORANGE, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DIABLO: - rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed * 8, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _RAISE: - rgb_matrix_layer_helper(HSV_YELLOW, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _LOWER: - rgb_matrix_layer_helper(HSV_GREEN, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _ADJUST: - rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - } - } + return true; } #endif diff --git a/keyboards/moonlander/keymaps/drashna/rules.mk b/keyboards/moonlander/keymaps/drashna/rules.mk index 2a6d20bed5..feb91c774b 100644 --- a/keyboards/moonlander/keymaps/drashna/rules.mk +++ b/keyboards/moonlander/keymaps/drashna/rules.mk @@ -1,4 +1,6 @@ -TAP_DANCE_ENABLE = yes -BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite -UNICODE_ENABLE = yes -UNICODEMAP_ENABLE = no +TAP_DANCE_ENABLE = yes +BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite +UNICODE_ENABLE = yes +UNICODEMAP_ENABLE = no +AUTOCORRECTION_ENABLE = yes +CAPS_WORD_ENABLE = yes diff --git a/keyboards/splitkb/kyria/keymaps/drashna/rules.mk b/keyboards/splitkb/kyria/keymaps/drashna/rules.mk index 2f4f4d091f..3cdfe1becd 100644 --- a/keyboards/splitkb/kyria/keymaps/drashna/rules.mk +++ b/keyboards/splitkb/kyria/keymaps/drashna/rules.mk @@ -1,20 +1,27 @@ BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite -MOUSEKEY_ENABLE = yes # Mouse keys +MOUSEKEY_ENABLE = no # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control -CONSOLE_ENABLE = yes # Console for debug +CONSOLE_ENABLE = no # Console for debug COMMAND_ENABLE = no # Commands for debug and configuration NKRO_ENABLE = yes # USB Nkey Rollover -UNICODE_ENABLE = yes # Unicode OLED_ENABLE = yes -OLED_DRIVER = SSD1306 # Enables the use of OLED displays ENCODER_ENABLE = yes # Enables the use of one or more encoders - RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow -RGBLIGHT_STARTUP_ANIMATION = yes -RGB_MATRIX_ENABLE = yes -TAP_DANCE_ENABLE = yes KEY_LOCK_ENABLE = no WPM_ENABLE = yes -SWAP_HANDS_ENABLE = yes -LTO_ENABLE = no -CTPC = yes + +ifeq ($(strip $(KEYBOARD)), splitkb/kyria/rev1/proton_c) + RGB_MATRIX_ENABLE = yes + CONSOLE_ENABLE = yes # Console for debug + MOUSEKEY_ENABLE = yes # Mouse keys + TAP_DANCE_ENABLE = yes + SWAP_HANDS_ENABLE = yes + LTO_ENABLE = no + CTPC = yes + AUTOCORRECTION_ENABLE = yes + CAPS_WORD_ENABLE = yes +else + LTO_ENABLE = yes + BOOTLOADER = qmk-hid + BOOTLOADER_SIZE = 512 +endif diff --git a/keyboards/work_louder/work_board/keymaps/drashna/config.h b/keyboards/work_louder/work_board/keymaps/drashna/config.h index 5ea4dc7e48..b3bcaca25d 100644 --- a/keyboards/work_louder/work_board/keymaps/drashna/config.h +++ b/keyboards/work_louder/work_board/keymaps/drashna/config.h @@ -15,3 +15,8 @@ */ #pragma once + +#define RGBLIGHT_EFFECT_KNIGHT_LED_NUM 12 + +#undef RGB_MATRIX_MAXIMUM_BRIGHTNESS +#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255 diff --git a/keyboards/work_louder/work_board/keymaps/drashna/keymap.c b/keyboards/work_louder/work_board/keymaps/drashna/keymap.c index 3bbb81bf04..3b0f4921ac 100644 --- a/keyboards/work_louder/work_board/keymaps/drashna/keymap.c +++ b/keyboards/work_louder/work_board/keymaps/drashna/keymap.c @@ -126,45 +126,12 @@ bool encoder_update_user(uint8_t index, bool clockwise) { #endif -void rgb_matrix_indicators_user(void) {} - -void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { +bool rgb_matrix_indicators_advanced_keymap(uint8_t led_min, uint8_t led_max) { uint8_t this_mod = get_mods(); uint8_t this_led = host_keyboard_leds(); uint8_t this_osm = get_oneshot_mods(); #define THUMB_LED 6 #define RGB_MATRIX_INDICATOR_SET_COLOR_wrapper(...) RGB_MATRIX_INDICATOR_SET_COLOR(__VA_ARGS__) - if (!userspace_config.rgb_layer_change) { - switch (get_highest_layer(layer_state | default_layer_state)) { - case _GAMEPAD: - rgb_matrix_layer_helper(HSV_ORANGE, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DIABLO: - rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed * 8, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _RAISE: - rgb_matrix_layer_helper(HSV_YELLOW, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _LOWER: - rgb_matrix_layer_helper(HSV_GREEN, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _ADJUST: - rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_1: - rgb_matrix_layer_helper(DEFAULT_LAYER_1_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_2: - rgb_matrix_layer_helper(DEFAULT_LAYER_2_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_3: - rgb_matrix_layer_helper(DEFAULT_LAYER_3_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_4: - rgb_matrix_layer_helper(DEFAULT_LAYER_4_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - } - } extern bool host_driver_disabled; if (host_driver_disabled) { @@ -214,4 +181,6 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { RGB_MATRIX_INDICATOR_SET_COLOR(4, 0xFF, 0xFF, 0x00); RGB_MATRIX_INDICATOR_SET_COLOR(5, 0xFF, 0xFF, 0x00); } + + return true; } diff --git a/keyboards/work_louder/work_board/keymaps/drashna/rules.mk b/keyboards/work_louder/work_board/keymaps/drashna/rules.mk index 363f2d0edb..6cccd5f8d2 100644 --- a/keyboards/work_louder/work_board/keymaps/drashna/rules.mk +++ b/keyboards/work_louder/work_board/keymaps/drashna/rules.mk @@ -1,6 +1,10 @@ BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite EXTRAKEY_ENABLE = yes +MOUSEKEY_ENABLE = yes TAP_DANCE_ENABLE = no NKRO_ENABLE = yes RGBLIGHT_STARTUP_ANIMATION = yes ENCODER_MAP_ENABLE = yes + +AUTOCORRECTION_ENABLE = no +CUSTOM_UNICODE_ENABLE = no diff --git a/layouts/community/ergodox/drashna/config.h b/layouts/community/ergodox/drashna/config.h index f9daf277fb..d669f27298 100644 --- a/layouts/community/ergodox/drashna/config.h +++ b/layouts/community/ergodox/drashna/config.h @@ -45,6 +45,7 @@ # endif #endif -#define PIMORONI_TRACKBALL_INVERT_X -#define PIMORONI_TRACKBALL_INVERT_Y -#define PIMORONI_TRACKBALL_CLICK +#ifdef TAPPING_TERM +# undef TAPPING_TERM +#endif +#define TAPPING_TERM 185 diff --git a/layouts/community/ergodox/drashna/keymap.c b/layouts/community/ergodox/drashna/keymap.c index 3c9bcfeaa2..798680628f 100644 --- a/layouts/community/ergodox/drashna/keymap.c +++ b/layouts/community/ergodox/drashna/keymap.c @@ -317,7 +317,7 @@ void suspend_power_down_keymap(void) { rgb_matrix_set_suspend_state(true); } void suspend_wakeup_init_keymap(void) { rgb_matrix_set_suspend_state(false); } -void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { +bool rgb_matrix_indicators_advanced_keymap(uint8_t led_min, uint8_t led_max) { if (layer_state_is(_GAMEPAD)) { RGB_MATRIX_INDICATOR_SET_COLOR(32, 0x00, 0xFF, 0x00); // Q RGB_MATRIX_INDICATOR_SET_COLOR(31, 0x00, 0xFF, 0xFF); // W @@ -332,43 +332,7 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { RGB_MATRIX_INDICATOR_SET_COLOR((userspace_config.swapped_numbers ? 27 : 26), 0x00, 0xFF, 0x00); // 2 RGB_MATRIX_INDICATOR_SET_COLOR(25, 0x7A, 0x00, 0xFF); // 3 } - -# if defined(RGBLIGHT_ENABLE) - if (!userspace_config.rgb_layer_change) -# else - if (userspace_config.rgb_layer_change) -# endif - { - switch (get_highest_layer(layer_state | default_layer_state)) { - case _GAMEPAD: - rgb_matrix_layer_helper(HSV_ORANGE, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DIABLO: - rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed * 8, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _RAISE: - rgb_matrix_layer_helper(HSV_YELLOW, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _LOWER: - rgb_matrix_layer_helper(HSV_GREEN, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _ADJUST: - rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_1: - rgb_matrix_layer_helper(DEFAULT_LAYER_1_HSV, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_2: - rgb_matrix_layer_helper(DEFAULT_LAYER_2_HSV, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_3: - rgb_matrix_layer_helper(DEFAULT_LAYER_3_HSV, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_4: - rgb_matrix_layer_helper(DEFAULT_LAYER_4_HSV, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - } - } + return true; } #endif // RGB_MATRIX_INIT diff --git a/layouts/community/ortho_4x12/drashna/keymap.c b/layouts/community/ortho_4x12/drashna/keymap.c index 3ba9cf64f9..ce241fd76d 100644 --- a/layouts/community/ortho_4x12/drashna/keymap.c +++ b/layouts/community/ortho_4x12/drashna/keymap.c @@ -201,17 +201,8 @@ led_config_t g_led_config = { // clange-format on # endif -// clang-format off -void suspend_power_down_keymap(void) { - rgb_matrix_set_suspend_state(true); -} -void suspend_wakeup_init_keymap(void) { - rgb_matrix_set_suspend_state(false); -} -// clang-format on - -void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { +bool rgb_matrix_indicators_advanced_keymap(uint8_t led_min, uint8_t led_max) { uint8_t this_mod = get_mods(); uint8_t this_led = host_keyboard_leds(); uint8_t this_osm = get_oneshot_mods(); @@ -221,48 +212,6 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { # define THUMB_LED 42 # endif # define RGB_MATRIX_INDICATOR_SET_COLOR_wrapper(...) RGB_MATRIX_INDICATOR_SET_COLOR(__VA_ARGS__) -# if defined(RGBLIGHT_ENABLE) - if (!userspace_config.rgb_layer_change) -# else - if (userspace_config.rgb_layer_change) -# endif - { - switch (get_highest_layer(layer_state)) { - case _GAMEPAD: - rgb_matrix_layer_helper(HSV_ORANGE, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DIABLO: - rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed * 8, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _RAISE: - rgb_matrix_layer_helper(HSV_YELLOW, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _LOWER: - rgb_matrix_layer_helper(HSV_GREEN, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _ADJUST: - rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - default: - { - switch (get_highest_layer(default_layer_state)) { - case _DEFAULT_LAYER_1: - rgb_matrix_layer_helper(DEFAULT_LAYER_1_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_2: - rgb_matrix_layer_helper(DEFAULT_LAYER_2_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_3: - rgb_matrix_layer_helper(DEFAULT_LAYER_3_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - case _DEFAULT_LAYER_4: - rgb_matrix_layer_helper(DEFAULT_LAYER_4_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); - break; - } - break; - } - } - } switch (get_highest_layer(default_layer_state)) { case _DEFAULT_LAYER_1: @@ -296,6 +245,8 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { if ((this_mod | this_osm) & MOD_MASK_ALT) { RGB_MATRIX_INDICATOR_SET_COLOR(38, 0x00, 0x00, 0xFF); } + + return true; } void matrix_init_keymap(void) { diff --git a/layouts/community/ortho_4x12/drashna/rules.mk b/layouts/community/ortho_4x12/drashna/rules.mk index d766245260..2905fb0fd4 100644 --- a/layouts/community/ortho_4x12/drashna/rules.mk +++ b/layouts/community/ortho_4x12/drashna/rules.mk @@ -1,33 +1,35 @@ BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite -MOUSEKEY_ENABLE = no # Mouse keys(+4700) -EXTRAKEY_ENABLE = yes # Audio control and System control(+450) +MOUSEKEY_ENABLE = no # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control TAP_DANCE_ENABLE = no SPACE_CADET_ENABLE = no NKRO_ENABLE = yes +CAPS_WORD_ENABLE = no ifneq ($(strip $(KEYBOARD)), planck/rev6) - CONSOLE_ENABLE = no - COMMAND_ENABLE = no + CONSOLE_ENABLE = no + COMMAND_ENABLE = no ifeq ($(strip $(LAYOUT_HAS_RGB)), yes) RGBLIGHT_ENABLE = yes - INDICATOR_LIGHTS = yes + INDICATOR_LIGHTS = yes RGBLIGHT_STARTUP_ANIMATION = yes endif else - CONSOLE_ENABLE = yes - COMMAND_ENABLE = yes + CONSOLE_ENABLE = yes RGBLIGHT_ENABLE = yes RGBLIGHT_STARTUP_ANIMATION = yes RGB_MATRIX_ENABLE = no - AUDIO_ENABLE = yes - EEPROM_DRIVER = i2c + AUDIO_ENABLE = yes + EEPROM_DRIVER = i2c ENCODER_MAP_ENABLE = yes + AUTOCORRECTION_ENABLE = yes + CAPS_WORD_ENABLE = yes endif ifeq ($(strip $(KEYBOARD)), planck/light) RGB_MATRIX_ENABLE = yes RGBLIGHT_ENABLE = yes RGBLIGHT_STARTUP_ANIMATION = yes - AUDIO_ENABLE = yes + AUDIO_ENABLE = yes endif ifeq ($(strip $(KEYBOARD)), planck/ez) RGBLIGHT_ENABLE = no @@ -39,4 +41,6 @@ ifeq ($(strip $(KEYBOARD)), planck/ez) CONSOLE_ENABLE = yes COMMAND_ENABLE = yes AUDIO_ENABLE = yes + AUTOCORRECTION_ENABLE = yes + CAPS_WORD_ENABLE = yes endif diff --git a/layouts/community/split_3x6_3/drashna/config.h b/layouts/community/split_3x6_3/drashna/config.h index b86448c671..cfcb873a80 100644 --- a/layouts/community/split_3x6_3/drashna/config.h +++ b/layouts/community/split_3x6_3/drashna/config.h @@ -93,3 +93,7 @@ #endif #define TAPPING_TERM_PER_KEY +#ifdef TAPPING_TERM +# undef TAPPING_TERM +#endif +#define TAPPING_TERM 200 diff --git a/layouts/community/split_3x6_3/drashna/keymap.c b/layouts/community/split_3x6_3/drashna/keymap.c index 7c31972e3f..476ca5fcef 100644 --- a/layouts/community/split_3x6_3/drashna/keymap.c +++ b/layouts/community/split_3x6_3/drashna/keymap.c @@ -90,7 +90,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET, VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST, KEYLOCK, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL, - HPT_TOG, KC_NUKE, _______, _______, TG_MODS, HPT_FBK + AUTO_CTN,KC_NUKE, _______, _______, TG_MODS, HPT_FBK ) }; // clang-format on @@ -265,7 +265,7 @@ void check_default_layer(uint8_t mode, uint8_t type, uint8_t led_min, uint8_t le } } -void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { +bool rgb_matrix_indicators_advanced_keymap(uint8_t led_min, uint8_t led_max) { if (userspace_config.rgb_layer_change) { switch (get_highest_layer(layer_state)) { case _GAMEPAD: @@ -291,5 +291,6 @@ void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { } check_default_layer(0, LED_FLAG_MODIFIER, led_min, led_max); } + return false; } #endif diff --git a/layouts/community/split_3x6_3/drashna/rules.mk b/layouts/community/split_3x6_3/drashna/rules.mk index cf2dfbdc88..9164dcdeba 100644 --- a/layouts/community/split_3x6_3/drashna/rules.mk +++ b/layouts/community/split_3x6_3/drashna/rules.mk @@ -1,9 +1,8 @@ - # Build Options -# change to "no" to disable the options, or define them in the Makefile in -# the appropriate keymap folder that will get included automatically +# change to "no" to disable the options # -BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite + +BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite MOUSEKEY_ENABLE = no # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and System control CONSOLE_ENABLE = no # Console for debug @@ -12,27 +11,25 @@ NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see her BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output UNICODE_ENABLE = no # Unicode -BLUETOOTH_ENABLE = no # Enable Bluetooth RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. SWAP_HANDS_ENABLE = no # Enable one-hand typing -# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE -SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend - ifeq ($(strip $(KEYBOARD)), crkbd/rev1) - OLED_ENABLE = yes - RGB_MATRIX_ENABLE = yes - HAPTIC_ENABLE = no + OLED_ENABLE = yes + RGB_MATRIX_ENABLE = yes + HAPTIC_ENABLE = no endif ifeq ($(strip $(CTPC)), yes) - HAPTIC_ENABLE = no - WS2812_DRIVER = pwm # won't work without a patch to the ctpc mk file - SERIAL_DRIVER = usart - SWAP_HANDS_ENABLE = yes - WPM_ENABLE = yes + HAPTIC_ENABLE = no + WS2812_DRIVER = pwm # won't work without a patch to the ctpc mk file + SERIAL_DRIVER = usart + SWAP_HANDS_ENABLE = yes + WPM_ENABLE = yes + AUTOCORRECTION_ENABLE = yes + CAPS_WORD_ENABLE = yes else - CUSTOM_UNICODE_ENABLE = no - BOOTLOADER = qmk-hid - BOOTLOADER_SIZE = 512 + CUSTOM_UNICODE_ENABLE = no + BOOTLOADER = qmk-hid + BOOTLOADER_SIZE = 512 endif diff --git a/users/drashna/callbacks.c b/users/drashna/callbacks.c new file mode 100644 index 0000000000..48b076b6ba --- /dev/null +++ b/users/drashna/callbacks.c @@ -0,0 +1,215 @@ +// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "drashna.h" + +__attribute__((weak)) void keyboard_pre_init_keymap(void) {} +void keyboard_pre_init_user(void) { + userspace_config.raw = eeconfig_read_user(); + keyboard_pre_init_keymap(); +} +// Add reconfigurable functions here, for keymap customization +// This allows for a global, userspace functions, and continued +// customization of the keymap. Use _keymap instead of _user +// functions in the keymaps +// Call user matrix init, set default RGB colors and then +// call the keymap's init function +__attribute__((weak)) void matrix_init_keymap(void) {} +__attribute__((weak)) void matrix_init_secret(void) {} +void matrix_init_user(void) { +#if defined(BOOTLOADER_CATERINA) && defined(__AVR__) && defined(__AVR_ATmega32U4__) + DDRD &= ~(1 << 5); + PORTD &= ~(1 << 5); + + DDRB &= ~(1 << 0); + PORTB &= ~(1 << 0); +#endif +#ifdef CUSTOM_UNICODE_ENABLE + matrix_init_unicode(); +#endif + matrix_init_secret(); + matrix_init_keymap(); +} + +__attribute__((weak)) void keyboard_post_init_keymap(void) {} +void keyboard_post_init_user(void) { +#if defined(RGBLIGHT_ENABLE) + keyboard_post_init_rgb_light(); +#endif +#if defined(RGB_MATRIX_ENABLE) + keyboard_post_init_rgb_matrix(); +#endif +#if defined(SPLIT_KEYBOARD) && defined(SPLIT_TRANSACTION_IDS_USER) + keyboard_post_init_transport_sync(); +#endif + keyboard_post_init_keymap(); +} + +#ifdef RGB_MATRIX_ENABLE +void rgb_matrix_update_pwm_buffers(void); +#endif + +__attribute__((weak)) void shutdown_keymap(void) {} +void shutdown_user(void) { +#ifdef RGBLIGHT_ENABLE + rgblight_enable_noeeprom(); + rgblight_mode_noeeprom(1); + rgblight_setrgb_red(); +#endif // RGBLIGHT_ENABLE +#ifdef RGB_MATRIX_ENABLE + rgb_matrix_set_color_all(0xFF, 0x00, 0x00); + rgb_matrix_update_pwm_buffers(); +#endif // RGB_MATRIX_ENABLE +#ifdef OLED_ENABLE + oled_off(); +#endif + + shutdown_keymap(); +} + +__attribute__((weak)) void suspend_power_down_keymap(void) {} + +void suspend_power_down_user(void) { +#ifdef OLED_ENABLE + oled_off(); +#endif + suspend_power_down_keymap(); +} + +__attribute__((weak)) void suspend_wakeup_init_keymap(void) {} +void suspend_wakeup_init_user(void) { + if (layer_state_is(_GAMEPAD)) { + layer_off(_GAMEPAD); + } + if (layer_state_is(_DIABLO)) { + layer_off(_DIABLO); + } + suspend_wakeup_init_keymap(); +} + +// No global matrix scan code, so just run keymap's matrix +// scan function +__attribute__((weak)) void matrix_scan_keymap(void) {} +__attribute__((weak)) void matrix_scan_secret(void) {} +void matrix_scan_user(void) { + static bool has_ran_yet; + if (!has_ran_yet) { + has_ran_yet = true; + startup_user(); + } + +#ifdef TAP_DANCE_ENABLE // Run Diablo 3 macro checking code. + run_diablo_macro_check(); +#endif // TAP_DANCE_ENABLE + +#if defined(RGBLIGHT_ENABLE) + matrix_scan_rgb_light(); +#endif // RGBLIGHT_ENABLE +#if defined(RGB_MATRIX_ENABLE) + matrix_scan_rgb_matrix(); +#endif +#if defined(POINTING_DEVICE_ENABLE) + matrix_scan_pointing(); +#endif + + matrix_scan_secret(); + + matrix_scan_keymap(); +} + +#ifdef AUDIO_ENABLE +float doom_song[][2] = SONG(E1M1_DOOM); +#endif + +// on layer change, no matter where the change was initiated +// Then runs keymap's layer change check +__attribute__((weak)) layer_state_t layer_state_set_keymap(layer_state_t state) { return state; } +layer_state_t layer_state_set_user(layer_state_t state) { + if (!is_keyboard_master()) { + return state; + } + + state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST); +#if defined(POINTING_DEVICE_ENABLE) + state = layer_state_set_pointing(state); +#endif +#if defined(RGBLIGHT_ENABLE) + state = layer_state_set_rgb_light(state); +#endif // RGBLIGHT_ENABLE +#if defined(AUDIO_ENABLE) && !defined(__arm__) + static bool is_gamepad_on = false; + if (layer_state_cmp(state, _GAMEPAD) != is_gamepad_on) { + is_gamepad_on = layer_state_cmp(state, _GAMEPAD); + if (is_gamepad_on) { + PLAY_LOOP(doom_song); + } else { + stop_all_notes(); + } + } +#endif + state = layer_state_set_keymap(state); + return state; +} + +// Runs state check and changes underglow color and animation +__attribute__((weak)) layer_state_t default_layer_state_set_keymap(layer_state_t state) { return state; } +layer_state_t default_layer_state_set_user(layer_state_t state) { + if (!is_keyboard_master()) { + return state; + } + + state = default_layer_state_set_keymap(state); +#if 0 +# if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) + state = default_layer_state_set_rgb(state); +# endif // RGBLIGHT_ENABLE +#endif + return state; +} + +__attribute__((weak)) void led_set_keymap(uint8_t usb_led) {} +void led_set_user(uint8_t usb_led) { led_set_keymap(usb_led); } + +__attribute__((weak)) void eeconfig_init_keymap(void) {} +void eeconfig_init_user(void) { + userspace_config.raw = 0; + userspace_config.rgb_layer_change = true; + eeconfig_update_user(userspace_config.raw); + eeconfig_init_keymap(); +} + +#ifdef SPLIT_KEYBOARD +__attribute__((weak)) void matrix_slave_scan_keymap(void) {} +void matrix_slave_scan_user(void) { +# if defined(AUDIO_ENABLE) +# if !defined(NO_MUSIC_MODE) + music_task(); +# endif +# ifdef AUDIO_INIT_DELAY + if (!is_keyboard_master()) { + static bool delayed_tasks_run = false; + static uint16_t delayed_task_timer = 0; + if (!delayed_tasks_run) { + if (!delayed_task_timer) { + delayed_task_timer = timer_read(); + } else if (timer_elapsed(delayed_task_timer) > 300) { + audio_startup(); + delayed_tasks_run = true; + } + } + } +# endif +# endif +# ifdef SEQUENCER_ENABLE + sequencer_task(); +# endif +# ifdef LED_MATRIX_ENABLE + led_matrix_task(); +# endif +# ifdef HAPTIC_ENABLE + haptic_task(); +# endif + + matrix_slave_scan_keymap(); +} +#endif diff --git a/users/drashna/callbacks.h b/users/drashna/callbacks.h new file mode 100644 index 0000000000..f6ac6b88de --- /dev/null +++ b/users/drashna/callbacks.h @@ -0,0 +1,25 @@ +// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "quantum.h" + +void matrix_init_keymap(void); +void matrix_init_secret(void); +void shutdown_keymap(void); +void suspend_power_down_keymap(void); +void suspend_wakeup_init_keymap(void); +void matrix_scan_keymap(void); +void matrix_scan_secret(void); +layer_state_t layer_state_set_keymap(layer_state_t state); +layer_state_t default_layer_state_set_keymap(layer_state_t state); +void led_set_keymap(uint8_t usb_led); +void eeconfig_init_keymap(void); + +#ifdef CUSTOM_UNICODE_ENABLE +void matrix_init_unicode(void); +#endif +#ifdef SPLIT_KEYBOARD +void matrix_slave_scan_keymap(void); +#endif diff --git a/users/drashna/callbacks.md b/users/drashna/callbacks.md new file mode 100644 index 0000000000..a0f0d9fdae --- /dev/null +++ b/users/drashna/callbacks.md @@ -0,0 +1,71 @@ +# Custom Userspace Callback Functions + +Specifically QMK works by using customized callback functions for everything. This allows for multiple levels of customization. + +`matrix_scan` calls `matrix_scan_quantum`, which calls `matrix_scan_kb`, which calls `matrix_scan_user`. +`process_record` calls a bunch of stuff, but eventually calls `process_record_kb` which calls `process_record_user` +The same goes for `matrix_init`, `layer_state_set`, `led_set`, and a few other functions. + +All (most) `_user` functions are handled here, in the userspace instead. To allow keyboard specific configuration, I've created `_keymap` functions that can be called by the keymap.c files instead. + +This allows for keyboard specific configuration while maintaining the ability to customize the board. + +My [Ergodox EZ Keymap](https://github.com/qmk/qmk_firmware/blob/master/layouts/community/ergodox/drashna/keymap.c) is a good example of this, as it uses the LEDs as modifier indicators. + +You can see a list of these files in [callbacks.c](callbacks.c), or a shortend list here + +```c +__attribute__((weak)) void matrix_init_keymap(void) {} +void matrix_init_user(void) { + matrix_init_keymap(); +} + +__attribute__((weak)) void keyboard_post_init_keymap(void) {} +void keyboard_post_init_user(void) { + keyboard_post_init_keymap(); +} + +__attribute__((weak)) void matrix_scan_keymap(void) {} +void matrix_scan_user(void) { + matrix_scan_keymap(); +} + +__attribute__ ((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { return true; } +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + if (!process_record_keymap(keycode, record)) { return false; } + return true; +} + +__attribute__((weak)) layer_state_t layer_state_set_keymap(layer_state_t state) { return state; } +layer_state_t layer_state_set_user(layer_state_t state) { + state = layer_state_set_keymap(state); + return state; +} + +__attribute__ ((weak)) void led_set_keymap(uint8_t usb_led) {} +void led_set_user(uint8_t usb_led) { + led_set_keymap(usb_led); +} + +__attribute__ ((weak)) void suspend_power_down_keymap(void) {} +void suspend_power_down_user(void) { + suspend_power_down_keymap(); +} + +__attribute__ ((weak)) void suspend_wakeup_init_keymap(void) {} +void suspend_wakeup_init_user(void) { + suspend_wakeup_init_keymap(); +} + + +__attribute__ ((weak)) void shutdown_keymap(void) {} +void shutdown_user (void) { + shutdown_keymap(); +} + +__attribute__ ((weak)) void eeconfig_init_keymap(void) {} +void eeconfig_init_user(void) { + eeconfig_update_user(0); + eeconfig_init_keymap(); +} +``` diff --git a/users/drashna/config.h b/users/drashna/config.h index cc8f9ac83c..46cd276dd4 100644 --- a/users/drashna/config.h +++ b/users/drashna/config.h @@ -1,24 +1,16 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once // Use custom magic number so that when switching branches, EEPROM always gets reset #define EECONFIG_MAGIC_NUMBER (uint16_t)0x1339 +#ifdef IS_COMMAND +#undef IS_COMMAND +#endif +#define IS_COMMAND() (((get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) + /* Set Polling rate to 1000Hz */ #define USB_POLLING_INTERVAL_MS 1 @@ -37,7 +29,7 @@ # define SELECT_SOFT_SERIAL_SPEED 1 # endif # ifdef CUSTOM_SPLIT_TRANSPORT_SYNC -# define SPLIT_TRANSACTION_IDS_USER RPC_ID_USER_STATE_SYNC, RPC_ID_USER_KEYMAP_SYNC, RPC_ID_USER_CONFIG_SYNC +# define SPLIT_TRANSACTION_IDS_USER RPC_ID_USER_STATE_SYNC, RPC_ID_USER_KEYMAP_SYNC, RPC_ID_USER_CONFIG_SYNC, RPC_ID_USER_WATCHDOG_SYNC # endif #endif @@ -251,17 +243,6 @@ # define TAPPING_TOGGLE 1 #endif -#ifdef TAPPING_TERM -# undef TAPPING_TERM -#endif // TAPPING_TERM -#if defined(KEYBOARD_ergodox_ez) -# define TAPPING_TERM 185 -#elif defined(KEYBOARD_crkbd) -# define TAPPING_TERM 200 -#else -# define TAPPING_TERM 175 -#endif - #define TAP_CODE_DELAY 5 /* Disable unused and unneeded features to reduce on firmware size */ diff --git a/users/drashna/drashna.c b/users/drashna/drashna.c index 9c1233ed90..9128a89bc6 100644 --- a/users/drashna/drashna.c +++ b/users/drashna/drashna.c @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "drashna.h" @@ -49,182 +36,6 @@ bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this return false; } -__attribute__((weak)) void keyboard_pre_init_keymap(void) {} -void keyboard_pre_init_user(void) { - userspace_config.raw = eeconfig_read_user(); - keyboard_pre_init_keymap(); -} -// Add reconfigurable functions here, for keymap customization -// This allows for a global, userspace functions, and continued -// customization of the keymap. Use _keymap instead of _user -// functions in the keymaps -// Call user matrix init, set default RGB colors and then -// call the keymap's init function -__attribute__((weak)) void matrix_init_keymap(void) {} -__attribute__((weak)) void matrix_init_secret(void) {} -void matrix_init_user(void) { -#if defined(BOOTLOADER_CATERINA) && defined(__AVR__) - DDRD &= ~(1 << 5); - PORTD &= ~(1 << 5); - - DDRB &= ~(1 << 0); - PORTB &= ~(1 << 0); -#endif -#ifdef CUSTOM_UNICODE_ENABLE - matrix_init_unicode(); -#endif - matrix_init_secret(); - matrix_init_keymap(); -} - -__attribute__((weak)) void keyboard_post_init_keymap(void) {} -void keyboard_post_init_user(void) { -#if defined(RGBLIGHT_ENABLE) - keyboard_post_init_rgb_light(); -#endif -#if defined(RGB_MATRIX_ENABLE) - keyboard_post_init_rgb_matrix(); -#endif -#if defined(SPLIT_KEYBOARD) && defined(SPLIT_TRANSACTION_IDS_USER) - keyboard_post_init_transport_sync(); -#endif - keyboard_post_init_keymap(); -} - -#ifdef RGB_MATRIX_ENABLE -void rgb_matrix_update_pwm_buffers(void); -#endif - -__attribute__((weak)) void shutdown_keymap(void) {} -void shutdown_user(void) { -#ifdef RGBLIGHT_ENABLE - rgblight_enable_noeeprom(); - rgblight_mode_noeeprom(1); - rgblight_setrgb_red(); -#endif // RGBLIGHT_ENABLE -#ifdef RGB_MATRIX_ENABLE - rgb_matrix_set_color_all(0xFF, 0x00, 0x00); - rgb_matrix_update_pwm_buffers(); -#endif // RGB_MATRIX_ENABLE -#ifdef OLED_ENABLE - oled_off(); -#endif - - shutdown_keymap(); -} - -__attribute__((weak)) void suspend_power_down_keymap(void) {} - -void suspend_power_down_user(void) { -#ifdef OLED_ENABLE - oled_off(); -#endif - suspend_power_down_keymap(); -} - -__attribute__((weak)) void suspend_wakeup_init_keymap(void) {} -void suspend_wakeup_init_user(void) { - if (layer_state_is(_GAMEPAD)) { - layer_off(_GAMEPAD); - } - if (layer_state_is(_DIABLO)) { - layer_off(_DIABLO); - } - suspend_wakeup_init_keymap(); -} - -// No global matrix scan code, so just run keymap's matrix -// scan function -__attribute__((weak)) void matrix_scan_keymap(void) {} -__attribute__((weak)) void matrix_scan_secret(void) {} -void matrix_scan_user(void) { - static bool has_ran_yet; - if (!has_ran_yet) { - has_ran_yet = true; - startup_user(); - } - -#ifdef TAP_DANCE_ENABLE // Run Diablo 3 macro checking code. - run_diablo_macro_check(); -#endif // TAP_DANCE_ENABLE - -#if defined(RGBLIGHT_ENABLE) - matrix_scan_rgb_light(); -#endif // RGBLIGHT_ENABLE -#if defined(RGB_MATRIX_ENABLE) - matrix_scan_rgb_matrix(); -#endif -#if defined(POINTING_DEVICE_ENABLE) - matrix_scan_pointing(); -#endif - - matrix_scan_secret(); - - matrix_scan_keymap(); -} - -#ifdef AUDIO_ENABLE -float doom_song[][2] = SONG(E1M1_DOOM); -#endif - -// on layer change, no matter where the change was initiated -// Then runs keymap's layer change check -__attribute__((weak)) layer_state_t layer_state_set_keymap(layer_state_t state) { return state; } -layer_state_t layer_state_set_user(layer_state_t state) { - if (!is_keyboard_master()) { - return state; - } - - state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST); -#if defined(POINTING_DEVICE_ENABLE) - state = layer_state_set_pointing(state); -#endif -#if defined(RGBLIGHT_ENABLE) - state = layer_state_set_rgb_light(state); -#endif // RGBLIGHT_ENABLE -#if defined(AUDIO_ENABLE) && !defined(__arm__) - static bool is_gamepad_on = false; - if (layer_state_cmp(state, _GAMEPAD) != is_gamepad_on) { - is_gamepad_on = layer_state_cmp(state, _GAMEPAD); - if (is_gamepad_on) { - PLAY_LOOP(doom_song); - } else { - stop_all_notes(); - } - } -#endif - state = layer_state_set_keymap(state); - return state; -} - -// Runs state check and changes underglow color and animation -__attribute__((weak)) layer_state_t default_layer_state_set_keymap(layer_state_t state) { return state; } -layer_state_t default_layer_state_set_user(layer_state_t state) { - if (!is_keyboard_master()) { - return state; - } - - state = default_layer_state_set_keymap(state); -#if 0 -# if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) - state = default_layer_state_set_rgb(state); -# endif // RGBLIGHT_ENABLE -#endif - return state; -} - -__attribute__((weak)) void led_set_keymap(uint8_t usb_led) {} -void led_set_user(uint8_t usb_led) { led_set_keymap(usb_led); } - -__attribute__((weak)) void eeconfig_init_keymap(void) {} -void eeconfig_init_user(void) { - userspace_config.raw = 0; - userspace_config.rgb_layer_change = true; - eeconfig_update_user(userspace_config.raw); - eeconfig_init_keymap(); - keyboard_init(); -} - bool hasAllBitsInMask(uint8_t value, uint8_t mask) { value &= 0xF; mask &= 0xF; @@ -232,96 +43,10 @@ bool hasAllBitsInMask(uint8_t value, uint8_t mask) { return (value & mask) == mask; } -#ifdef SPLIT_KEYBOARD -__attribute__((weak)) void matrix_slave_scan_keymap(void) {} -void matrix_slave_scan_user(void) { -# if defined(AUDIO_ENABLE) -# if !defined(NO_MUSIC_MODE) - music_task(); -# endif -# ifdef AUDIO_INIT_DELAY - if (!is_keyboard_master()) { - static bool delayed_tasks_run = false; - static uint16_t delayed_task_timer = 0; - if (!delayed_tasks_run) { - if (!delayed_task_timer) { - delayed_task_timer = timer_read(); - } else if (timer_elapsed(delayed_task_timer) > 300) { - audio_startup(); - delayed_tasks_run = true; - } - } - } -# endif -# endif -# ifdef SEQUENCER_ENABLE - sequencer_task(); -# endif -# ifdef LED_MATRIX_ENABLE - led_matrix_task(); -# endif -# ifdef HAPTIC_ENABLE - haptic_task(); -# endif - - matrix_slave_scan_keymap(); -} -#endif - -__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { - switch (keycode) { - default: - return TAPPING_TERM; - } -} - -__attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { - // Immediately select the hold action when another key is tapped: - // return true; - // Do not select the hold action when another key is tapped. - // return false; - switch (keycode) { - default: - return false; - } -} - -__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { - // Immediately select the hold action when another key is pressed. - // return true; - // Do not select the hold action when another key is pressed. - // return false; - switch (keycode) { - case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: - return true; - default: - return false; - } -} - -__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { - // Do not force the mod-tap key press to be handled as a modifier - // if any other key was pressed while the mod-tap key is held down. - // return true; - // Force the mod-tap key press to be handled as a modifier if any - // other key was pressed while the mod-tap key is held down. - // return false; - switch (keycode) { - default: - return true; - } -} - -__attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { - switch (keycode) { - default: - return false; - } -} - -__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { - switch (keycode) { - default: - return false; - } +void tap_code16_nomods(uint8_t kc) { + uint8_t temp_mod = get_mods(); + clear_mods(); + clear_oneshot_mods(); + tap_code16(kc); + set_mods(temp_mod); } diff --git a/users/drashna/drashna.h b/users/drashna/drashna.h index 7bcae881e4..5a9da16273 100644 --- a/users/drashna/drashna.h +++ b/users/drashna/drashna.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include QMK_KEYBOARD_H @@ -20,6 +7,8 @@ #include "eeprom.h" #include "keyrecords/wrappers.h" #include "keyrecords/process_records.h" +#include "callbacks.h" + #ifdef TAP_DANCE_ENABLE # include "keyrecords/tap_dances.h" #endif // TAP_DANCE_ENABLE @@ -58,7 +47,7 @@ enum userspace_layers { _ADJUST, }; -#define _MACROS _MOUSE +#define _MACROS _MOUSE #define _DEFAULT_LAYER_1 FIRST_DEFAULT_LAYER #define _DEFAULT_LAYER_2 (FIRST_DEFAULT_LAYER + 1) #define _DEFAULT_LAYER_3 (FIRST_DEFAULT_LAYER + 2) @@ -86,23 +75,10 @@ enum userspace_layers { #define DEFAULT_LAYER_3_RGB RGB_MAGENTA #define DEFAULT_LAYER_4_RGB RGB_GOLDENROD -bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed); -bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer); -void matrix_init_keymap(void); -void matrix_init_secret(void); -void shutdown_keymap(void); -void suspend_power_down_keymap(void); -void suspend_wakeup_init_keymap(void); -void matrix_scan_keymap(void); -void matrix_scan_secret(void); -layer_state_t layer_state_set_keymap(layer_state_t state); -layer_state_t default_layer_state_set_keymap(layer_state_t state); -void led_set_keymap(uint8_t usb_led); -void eeconfig_init_keymap(void); -bool hasAllBitsInMask(uint8_t value, uint8_t mask); -#ifdef SPLIT_KEYBOARD -void matrix_slave_scan_keymap(void); -#endif +bool mod_key_press_timer(uint16_t code, uint16_t mod_code, bool pressed); +bool mod_key_press(uint16_t code, uint16_t mod_code, bool pressed, uint16_t this_timer); +bool hasAllBitsInMask(uint8_t value, uint8_t mask); +void tap_code16_nomods(uint8_t kc); // clang-format off typedef union { @@ -119,20 +95,3 @@ typedef union { // clang-format on extern userspace_config_t userspace_config; - -/* -Custom Keycodes for Diablo 3 layer -But since TD() doesn't work when tap dance is disabled -We use custom codes here, so we can substitute the right stuff -*/ -#ifdef TAP_DANCE_ENABLE -# define KC_D3_1 TD(TD_D3_1) -# define KC_D3_2 TD(TD_D3_2) -# define KC_D3_3 TD(TD_D3_3) -# define KC_D3_4 TD(TD_D3_4) -#else // TAP_DANCE_ENABLE -# define KC_D3_1 KC_1 -# define KC_D3_2 KC_2 -# define KC_D3_3 KC_3 -# define KC_D3_4 KC_4 -#endif // TAP_DANCE_ENABLE diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.c b/users/drashna/keyrecords/autocorrection/autocorrection.c index 7c8c28c674..e561224374 100644 --- a/users/drashna/keyrecords/autocorrection/autocorrection.c +++ b/users/drashna/keyrecords/autocorrection/autocorrection.c @@ -1,5 +1,5 @@ // Copyright 2021 Google LLC -// Copyright 2022 @filterpaper +// Copyright 2021 @filterpaper // SPDX-License-Identifier: Apache-2.0 // Original source: https://getreuer.info/posts/keyboards/autocorrection @@ -7,10 +7,15 @@ #include #if __has_include("autocorrection_data.h") +# pragma GCC push_options +# pragma GCC optimize("O0") # include "autocorrection_data.h" # if AUTOCORRECTION_MIN_LENGTH < 4 # error Minimum Length is too short and may cause overflows # endif +# if DICTIONARY_SIZE > SIZE_MAX +# error Dictionary size excees maximum size permitted +# endif bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {KC_SPC}; @@ -55,11 +60,17 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { } # endif default: + // Disable autocorrection while a mod other than shift is active. + if (((get_mods() | get_oneshot_mods()) & ~MOD_MASK_SHIFT) != 0) { + typo_buffer_size = 0; + return true; + } if (!record->event.pressed) { return true; } } + // Subtract buffer for Backspace key, reset for other non-alpha. if (!(KC_A <= keycode && keycode <= KC_Z)) { if (keycode == KC_BSPC) { @@ -137,6 +148,7 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { } return true; } +# pragma GCC pop_options #else # pragma message "Warning!!! Autocorrect is not corretly setup!" bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { return true; } diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.h b/users/drashna/keyrecords/autocorrection/autocorrection.h index 57685eb4b5..cea93159ae 100644 --- a/users/drashna/keyrecords/autocorrection/autocorrection.h +++ b/users/drashna/keyrecords/autocorrection/autocorrection.h @@ -1,5 +1,5 @@ // Copyright 2021 Google LLC -// Copyright 2022 @filterpaper +// Copyright 2021 @filterpaper // SPDX-License-Identifier: Apache-2.0 // Original source: https://getreuer.info/posts/keyboards/autocorrection diff --git a/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py b/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py index 27383b8955..54fd9ba594 100755 --- a/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py +++ b/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py @@ -252,8 +252,9 @@ def write_generated_code(autocorrections: List[Tuple[str, str]], for typo, correction in autocorrections)), f'\n#define AUTOCORRECTION_MIN_LENGTH {len(min_typo)} // "{min_typo}"\n', f'#define AUTOCORRECTION_MAX_LENGTH {len(max_typo)} // "{max_typo}"\n\n', - textwrap.fill('static const uint8_t autocorrection_data[%d] PROGMEM = {%s};' % ( - len(data), ', '.join(map(str, data))), width=80, subsequent_indent=' '), + f'#define DICTIONARY_SIZE {len(data)}\n\n', + textwrap.fill('static const uint8_t autocorrection_data[DICTIONARY_SIZE] PROGMEM = {%s};' % ( + ', '.join(map(str, data))), width=120, subsequent_indent=' '), '\n\n']) with open(file_name, 'wt') as f: diff --git a/users/drashna/keyrecords/autocorrection/readme.md b/users/drashna/keyrecords/autocorrection/readme.md new file mode 100644 index 0000000000..d920508793 --- /dev/null +++ b/users/drashna/keyrecords/autocorrection/readme.md @@ -0,0 +1,301 @@ +# Autocorrection + +This is taken from [Pascal Getreuer's implemenation](https://getreuer.info/posts/keyboards/autocorrection/index.html), with a number of modifications. + +To enabled Autocorrection, add `AUTOCORRECTION_ENABLE = yes` to your `rules.mk` file. + +This is mostly a reproduction of Pascal's docs: + +## Overview +Some words are more prone to typos than others. I have a habit of typo-ing *ouput* and *fitler*. This post describes a rudimentary autocorrection implementation that runs on your keyboard with QMK. + +The animation below shows the effect as I type *aparent*. As I press the final t, the autocorrection feature detects the typo and automatically sends keys to correct it: + +Example: Autocorrecting *aparent* → apparent. + +**Features**: +* It runs on your keyboard, so it is always active no matter what software. +* Low resource cost: for an autocorrection dictionary of 70 entries, firmware size cost is 1620 bytes and average CPU cost per key press is about 20 µs. +* It is case insensitive. It corrects Fitler to Filter and FITLER to FILTER. +* It works within words. It corrects fitlered, fitlering, and useful for programming, within longer identifiers like DesignButterworthFitle*r. + +**Limitations**: Running autocorrection on the keyboard comes with some constraints. It is rudimentary like I said: +* It is limited to alphabet characters a–z. No accented or Unicode letters; I’m sorry this probably isn’t useful for languages besides English. +* It does not follow mouse or hotkey driven cursor movement. + +## Taking autocorrection for a test drive +With the above flashed to your keyboard, try for instance typing the misspelled word ouput. The instant you type the final t, the word should be speedily autocorrected to output. As further tests, try becuase and invliad. + +Here is the full list of typos corrected using the provided autocorrection_data.h file. : is a special character denoting a word break. See below for how to change the autocorrection dictionary. + +``` +:guage -> gauge +:the:the: -> the +:thier -> their +:ture -> true +accomodate -> accommodate +acommodate -> accommodate +aparent -> apparent +aparrent -> apparent +apparant -> apparent +apparrent -> apparent +aquire -> acquire +becuase -> because +cauhgt -> caught +cheif -> chief +choosen -> chosen +cieling -> ceiling +collegue -> colleague +concensus -> consensus +contians -> contains +cosnt -> const +dervied -> derived +fales -> false +fasle -> false +fitler -> filter +flase -> false +foward -> forward +frequecy -> frequency +gaurantee -> guarantee +guaratee -> guarantee +heigth -> height +heirarchy -> hierarchy +inclued -> include +interator -> iterator +intput -> input +invliad -> invalid +lenght -> length +liasion -> liaison +libary -> library +listner -> listener +looses: -> loses +looup -> lookup +manefist -> manifest +namesapce -> namespace +namespcae -> namespace +occassion -> occasion +occured -> occurred +ouptut -> output +ouput -> output +overide -> override +postion -> position +priviledge -> privilege +psuedo -> pseudo +recieve -> receive +refered -> referred +relevent -> relevant +repitition -> repetition +reuslt -> result +retrun -> return +retun -> return +reutrn -> return +saftey -> safety +seperate -> separate +singed -> signed +stirng -> string +strign -> string +swithc -> switch +swtich -> switch +thresold -> threshold +udpate -> update +widht -> width +``` + +## Firmware size and CPU costs +I am anxiously aware that a keyboard microcontroller has limited resources. So I was sure to measure how much memory and CPU time autocorrection consumes during development. These measurements are for the example autocorrection dictionary as used above, which has 70 entries: +* **Firmware size**: Autocorrection increases my firmware size by a total of 1620 bytes. Breaking that down, 1104 bytes are for the autocorrection_data array and 516 bytes for the autocorrection code. +* **CPU time**: On my Elite-C microcontrollers, the average CPU time for process_autocorrection to process an alpha key press is around 20 µs. Consider this a rough order-of-magnitude cost. Processing cost increases (more trie nodes are visited) when recent input is close to a known typo, with the max being when a long typo is matched. + +The costs are not free but reasonable. For reference, the firmware size cost for mouse keys is 2124 bytes and the CPU time to process a layer switch is about 70 µs, so autocorrection is cheaper than those things. Of course, the cost scales with the size of the autocorrection dictionary, so keep that in mind if you add a lot more entries. + +## How does it work? +The function process_autocorrection maintains a small buffer of recent key presses. On each key press, it checks whether the buffer ends in a recognized typo, and if so, automatically sends keystrokes to correct it. + +The tricky part is how to efficiently check the buffer for typos. We don’t want to spend too much memory or time on storing or searching the typos. A good solution is to represent the typos with a trie data structure. A trie is a tree data structure where each node is a letter, and words are formed by following a path to one of the leaves. + + +An example trie. +Since we search whether the buffer ends in a typo, we store the trie writing in reverse. The trie is queried starting from the last letter, then second to last letter, and so on, until either a letter doesn’t match or we reach a leaf, meaning a typo was found. + +## Changing the autocorrection dictionary +The file autocorrection_data.h encodes the typos to correct. While you could simply use the version of this file provided above for a practical configuration, you can make your own to personalize the autocorrection to your most troublesome typos: + +1. First, create an autocorrection dictionary autocorrection_dict.txt, like + + ``` +:thier -> their +fitler -> filter +lenght -> length +ouput -> output +widht -> width +``` + For a practical 70-entry example, see autocorrection_dict.txt. And for a yet larger 400-entry example, see autocorrection_dict_extra.txt. + + The syntax is `typo -> correction`. Typos and corrections are case insensitive, and any whitespace before or after the typo and correction is ignored. The typo must be only the letters a–z, or the special character : representing a word break. The correction may have any characters. + +2. Use the make_autocorrection_data.py Python script to process the dictionary + +``` +$ python3 make_autocorrection_data.py +Processed 70 autocorrection entries to table with 1104 bytes. +``` +The script arranges the entries in autocorrection_dict.txt into a trie and generates autocorrection_data.h with the serialized trie embedded as an array. + +3. Finally, recompile and flash your keymap. + +The generated C header looks like this: + +autocorrection_data.h +```c +// Generated code. + +#define AUTOCORRECTION_MIN_LENGTH 5 // "cheif" +#define AUTOCORRECTION_MAX_LENGTH 10 // "accomodate" + +static const uint8_t autocorrection_data[1104] PROGMEM = {108, 43, 0, 6, + 71, 0, 7, 81, 0, 8, 199, 0, 9, 240, 1, 10, 250, 1, 11, 26, 2, 17, 53, 2, + 18, 190, 2, 19, 202, 2, 21, 212, 2, 22, 20, 3, 23, 67, 3, 28, 16, 4, 0, + 72, 50, 0, 22, 60, 0, 0, 11, 23, 44, 8, 11, 23, 44, 0, 132, 0, 8, 22, 18, + 18, 15, 0, 132, 115, 101, 115, 0, 11, 23, 12, 26, 22, 0, 129, 99, 104, 0, + 68, 94, 0, 8, 106, 0, 15, 174, 0, 21, 187, 0, 0, 12, 15, 25, 17, 12, 0, + 131, 97, 108, 105, 100, 0, 74, 119, 0, 12, 129, 0, 21, 140, 0, 24, 165, + 0, 0, 17, 12, 22, 0, 131, 103, 110, 101, 100, 0, 25, 21, 8, 7, 0, 131, + 105, 118, 101, 100, 0, 72, 147, 0, 24, 156, 0, 0, 9, 8, 21, 0, 129, 114, + 101, 100, 0, 6, 6, 18, 0, 129, 114, 101, 100, 0, 15, 6, 17, 12, 0, 129, + 100, 101, 0, 18, 22, 8, 21, 11, 23, 0, 130, 104, 111, 108, 100, 0, 4, 26, + 18, 9, 0, 131, 114, 119, 97, 114, 100, 0, 68, 233, 0, 6, 246, 0, 7, 4, 1, + 8, 16, 1, 10, 52, 1, 15, 81, 1, 21, 90, 1, 22, 117, 1, 23, 144, 1, 24, + 215, 1, 25, 228, 1, 0, 6, 19, 22, 8, 16, 4, 17, 0, 130, 97, 99, 101, 0, + 19, 4, 22, 8, 16, 4, 17, 0, 131, 112, 97, 99, 101, 0, 12, 21, 8, 25, 18, + 0, 130, 114, 105, 100, 101, 0, 23, 0, 68, 25, 1, 17, 36, 1, 0, 21, 4, 24, + 10, 0, 130, 110, 116, 101, 101, 0, 4, 21, 24, 4, 10, 0, 135, 117, 97, + 114, 97, 110, 116, 101, 101, 0, 68, 59, 1, 7, 69, 1, 0, 24, 10, 44, 0, + 131, 97, 117, 103, 101, 0, 8, 15, 12, 25, 12, 21, 19, 0, 130, 103, 101, + 0, 22, 4, 9, 0, 130, 108, 115, 101, 0, 76, 97, 1, 24, 109, 1, 0, 24, 20, + 4, 0, 132, 99, 113, 117, 105, 114, 101, 0, 23, 44, 0, 130, 114, 117, 101, + 0, 4, 0, 79, 126, 1, 24, 134, 1, 0, 9, 0, 131, 97, 108, 115, 101, 0, 6, + 8, 5, 0, 131, 97, 117, 115, 101, 0, 4, 0, 71, 156, 1, 19, 193, 1, 21, + 203, 1, 0, 18, 16, 0, 80, 166, 1, 18, 181, 1, 0, 18, 6, 4, 0, 135, 99, + 111, 109, 109, 111, 100, 97, 116, 101, 0, 6, 6, 4, 0, 132, 109, 111, 100, + 97, 116, 101, 0, 7, 24, 0, 132, 112, 100, 97, 116, 101, 0, 8, 19, 8, 22, + 0, 132, 97, 114, 97, 116, 101, 0, 10, 8, 15, 15, 18, 6, 0, 130, 97, 103, + 117, 101, 0, 8, 12, 6, 8, 21, 0, 131, 101, 105, 118, 101, 0, 12, 8, 11, + 6, 0, 130, 105, 101, 102, 0, 17, 0, 76, 3, 2, 21, 16, 2, 0, 15, 8, 12, 6, + 0, 133, 101, 105, 108, 105, 110, 103, 0, 12, 23, 22, 0, 131, 114, 105, + 110, 103, 0, 70, 33, 2, 23, 44, 2, 0, 12, 23, 26, 22, 0, 131, 105, 116, + 99, 104, 0, 10, 12, 8, 11, 0, 129, 104, 116, 0, 72, 69, 2, 10, 80, 2, 18, + 89, 2, 21, 156, 2, 24, 167, 2, 0, 22, 18, 18, 11, 6, 0, 131, 115, 101, + 110, 0, 12, 21, 23, 22, 0, 129, 110, 103, 0, 12, 0, 86, 98, 2, 23, 124, + 2, 0, 68, 105, 2, 22, 114, 2, 0, 12, 15, 0, 131, 105, 115, 111, 110, 0, + 4, 6, 6, 18, 0, 131, 105, 111, 110, 0, 76, 131, 2, 22, 146, 2, 0, 23, 12, + 19, 8, 21, 0, 134, 101, 116, 105, 116, 105, 111, 110, 0, 18, 19, 0, 131, + 105, 116, 105, 111, 110, 0, 23, 24, 8, 21, 0, 131, 116, 117, 114, 110, 0, + 85, 174, 2, 23, 183, 2, 0, 23, 8, 21, 0, 130, 117, 114, 110, 0, 8, 21, 0, + 128, 114, 110, 0, 7, 8, 24, 22, 19, 0, 131, 101, 117, 100, 111, 0, 24, + 18, 18, 15, 0, 129, 107, 117, 112, 0, 72, 219, 2, 18, 3, 3, 0, 76, 229, + 2, 15, 238, 2, 17, 248, 2, 0, 11, 23, 44, 0, 130, 101, 105, 114, 0, 23, + 12, 9, 0, 131, 108, 116, 101, 114, 0, 23, 22, 12, 15, 0, 130, 101, 110, + 101, 114, 0, 23, 4, 21, 8, 23, 17, 12, 0, 135, 116, 101, 114, 97, 116, + 111, 114, 0, 72, 30, 3, 17, 38, 3, 24, 51, 3, 0, 15, 4, 9, 0, 129, 115, + 101, 0, 4, 12, 23, 17, 18, 6, 0, 131, 97, 105, 110, 115, 0, 22, 17, 8, 6, + 17, 18, 6, 0, 133, 115, 101, 110, 115, 117, 115, 0, 74, 86, 3, 11, 96, 3, + 15, 118, 3, 17, 129, 3, 22, 218, 3, 24, 232, 3, 0, 11, 24, 4, 6, 0, 130, + 103, 104, 116, 0, 71, 103, 3, 10, 110, 3, 0, 12, 26, 0, 129, 116, 104, 0, + 17, 8, 15, 0, 129, 116, 104, 0, 22, 24, 8, 21, 0, 131, 115, 117, 108, + 116, 0, 68, 139, 3, 8, 150, 3, 22, 210, 3, 0, 21, 4, 19, 19, 4, 0, 130, + 101, 110, 116, 0, 85, 157, 3, 25, 200, 3, 0, 68, 164, 3, 21, 175, 3, 0, + 19, 4, 0, 132, 112, 97, 114, 101, 110, 116, 0, 4, 19, 0, 68, 185, 3, 19, + 193, 3, 0, 133, 112, 97, 114, 101, 110, 116, 0, 4, 0, 131, 101, 110, 116, + 0, 8, 15, 8, 21, 0, 130, 97, 110, 116, 0, 18, 6, 0, 130, 110, 115, 116, + 0, 12, 9, 8, 17, 4, 16, 0, 132, 105, 102, 101, 115, 116, 0, 83, 239, 3, + 23, 6, 4, 0, 87, 246, 3, 24, 254, 3, 0, 17, 12, 0, 131, 112, 117, 116, 0, + 18, 0, 130, 116, 112, 117, 116, 0, 19, 24, 18, 0, 131, 116, 112, 117, + 116, 0, 70, 29, 4, 8, 41, 4, 11, 51, 4, 21, 69, 4, 0, 8, 24, 20, 8, 21, + 9, 0, 129, 110, 99, 121, 0, 23, 9, 4, 22, 0, 130, 101, 116, 121, 0, 6, + 21, 4, 21, 12, 8, 11, 0, 135, 105, 101, 114, 97, 114, 99, 104, 121, 0, 4, + 5, 12, 15, 0, 130, 114, 97, 114, 121, 0}; +``` + +## Troubleshooting +### Avoiding false triggers +By default, typos are searched within words, to find typos within longer identifiers like maxFitlerOuput. While this is useful, a consequence is that autocorrection will falsely trigger when a typo happens to be a substring of a correctly-spelled word. For instance, if we had thier -> their as an entry, it would falsely trigger on (correct, though relatively uncommon) words like “wealthier” and “filthier.” + +The solution is to set a word break : before and/or after the typo to constrain matching. : matches space, period, comma, underscore, digits, and most other non-alpha characters. + +| Text | thier | :thier | thier: | :thier: | +|------|-------|--------|--------|---------| +|see thier typo|matches|matches|matches|matches| +it’s thiers |matches|matches|no|no| +wealthier words|matches|no|matches|no| + +:thier: is most restrictive, matching only when thier is a whole word. + +The make_autocorrection_data.py script makes an effort to check for entries that would false trigger as substrings of correct words. It searches each typo against a dictionary of 25K English words from the english_words Python package, provided it’s installed. + +### Overriding autocorrection +Occasionally you might actually want to type a typo (for instance, while editing autocorrection_dict.txt) without being autocorrected. Here is a way to do that: + +1. Begin typing the typo. +2. Before typing the last letter, press and release the Ctrl or Alt key. +3. Type the remaining letters. + +This works because the autocorrection implementation doesn’t understand hotkeys, so it resets itself whenever a modifier other than shift is held. + +Alternatively, the `AUTO_CTN` keycode will toggle autocorrection on and off. + +## Closing thoughts +Based on my own use, an autocorrection dictionary of a few dozen entries is enough to help in day-to-day writing. On the other hand, it is of course far from comprehensively checking that every word is spelled correctly. Keyboard microcontrollers might not have the resources check against a full English dictionary any time soon, but a lot of editors and other software have good integrated spell check features. + +I suggest to enable and use spell check in combination with autocorrection: +* Sublime: Open the View menu and enable “Spell Check.” +* Eclipse: Open the Window menu, click Preferences, and search for “Spelling.” +* Vim: Type :set spell, and misspellings will be highlighted. Use ]s to jump to the next misspelled word and z= to get suggested corrections for the word under the cursor. See the :help spell documentation. Vim also has an abbreviations feature that can autocorrect misspellings (see :help abbreviations). +* Emacs: Use M-x flyspell-mode to enable Flyspell mode in the current buffer. Or for programming, use M-x flyspell-prog-mode to check comments and strings only. See the spelling documentation. There is also an abbreviations feature that can do autocorrection. + +Some useful resources: + +* Wikipedia has a [large list of common typos](https://en.wikipedia.org/wiki/Wikipedia:Lists_of_common_misspellings/For_machines). +* EmacsWiki has another [list of typos](https://www.emacswiki.org/emacs/autocorrection_abbrev_defs). +* You can find data on English word frequencies at https://www.wordfrequency.info/samples.asp. + +# Appendix: Trie binary data format +This section details how the trie is serialized to byte data in autocorrection_data. You don’t need to care about this to use this autocorrection implementation. But I document it for the record in case anyone is interested in modifying the implementation, or just curious how it works. + +What I did here is fairly arbitrary, but it is simple to decode and gets the job done. + +## Encoding +All autocorrection data is stored in a single flat array autocorrection_data. Each trie node is associated with a byte offset into this array, where data for that node is encoded, beginning with root at offset 0. There are three kinds of nodes. The highest two bits of the first byte of the node indicate what kind: + +* 00 ⇒ chain node: a trie node with a single child. +* 01 ⇒ branching node: a trie node with multiple children. +* 10 ⇒ leaf node: a leaf, corresponding to a typo and storing its correction. + +An example trie. +Branching node. Each branch is encoded with one byte for the keycode (KC_A–KC_Z) followed by a link to the child node. Links between nodes are 16-bit byte offsets relative to the beginning of the array, serialized in little endian order. + +All branches are serialized this way, one after another, and terminated with a zero byte. As described above, the node is identified as a branch by setting the two high bits of the first byte to 01, done by bitwise ORing the first keycode with 64. keycode. The root node for the above figure would be serialized like: + + +-------+-------+-------+-------+-------+-------+-------+ + | R|64 | node 2 | T | node 3 | 0 | + +-------+-------+-------+-------+-------+-------+-------+ + +Chain node. Tries tend to have long chains of single-child nodes, as seen in the example above with f-i-t-l in fitler. So to save space, we use a different format to encode chains than branching nodes. A chain is encoded as a string of keycodes, beginning with the node closest to the root, and terminated with a zero byte. The child of the last node in the chain is encoded immediately after. That child could be either a branching node or a leaf. + +In the figure above, the f-i-t-l chain is encoded as + + +-------+-------+-------+-------+-------+ + | L | T | I | F | 0 | + +-------+-------+-------+-------+-------+ +If we were to encode this chain using the same format used for branching nodes, we would encode a 16-bit node link with every node, costing 8 more bytes in this example. Across the whole trie, this adds up. Conveniently, we can point to intermediate points in the chain and interpret the bytes in the same way as before. E.g. starting at the i instead of the l, and the subchain has the same format. + +Leaf node. A leaf node corresponds to a particular typo and stores data to correct the typo. The leaf begins with a byte for the number of backspaces to type, and is followed by a null-terminated ASCII string of the replacement text. The idea is, after tapping backspace the indicated number of times, we can simply pass this string to QMK’s send_string_P function. For fitler, we need to tap backspace 3 times (not 4, because we catch the typo as the final ‘r’ is pressed) and replace it with lter. To identify the node as a leaf, the two high bits are set to 10 by ORing the backspace count with 128: + + +-------+-------+-------+-------+-------+-------+ + | 3|128 | 'l' | 't' | 'e' | 'r' | 0 | + +-------+-------+-------+-------+-------+-------+ +## Decoding +This format is by design decodable with fairly simple logic. A 16-bit variable state represents our current position in the trie, initialized with 0 to start at the root node. Then, for each keycode, test the highest two bits in the byte at state to identify the kind of node. + +* 00 ⇒ chain node: If the node’s byte matches the keycode, increment state by one to go to the next byte. If the next byte is zero, increment again to go to the following node. +* 01 ⇒ branching node: Search the branches for one that matches the keycode, and follow its node link. +* 10 ⇒ leaf node: a typo has been found! We read its first byte for the number of backspaces to type, then pass its following bytes to send_string_P to type the correction. diff --git a/users/drashna/keyrecords/caps_word.c b/users/drashna/keyrecords/caps_word.c index 731568328a..cc9ca93b72 100644 --- a/users/drashna/keyrecords/caps_word.c +++ b/users/drashna/keyrecords/caps_word.c @@ -3,13 +3,17 @@ #include "caps_word.h" +#ifndef IS_COMMAND +# define IS_COMMAND() (get_mods() == MOD_MASK_SHIFT) +#endif + bool caps_word_enabled = false; bool caps_word_shifted = false; bool process_caps_word(uint16_t keycode, keyrecord_t* record) { if (!caps_word_enabled) { // Pressing both shift keys at the same time enables caps word. - if (((get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) { + if (IS_COMMAND()) { clear_mods(); clear_oneshot_mods(); caps_word_shifted = false; diff --git a/users/drashna/keyrecords/capwords.md b/users/drashna/keyrecords/capwords.md new file mode 100644 index 0000000000..1ca01ed853 --- /dev/null +++ b/users/drashna/keyrecords/capwords.md @@ -0,0 +1,36 @@ +# Cap Words + +This is taken from [Pascal Getreuer's implemenation](https://getreuer.info/posts/keyboards/caps-word/index.html), with a number of modifications. + +To enable Caps Word, add `CAPS_WORD_ENABLE = yes` to your `rules.mk`. + +This is mostly a reproduction of Pascal's docs: + +## Overview + +All-caps identifiers like “MOD_MASK_ALT” are awkward to type. + +Caps Lock would be the standard solution to this problem, but it is awkward: it needs a dedicated key to toggle it (an imposition on smaller keyboards), and we need to remember to toggle it off after typing the word. Or with normal shifting, we either perform finger gymnastics or need to stop typing in the middle of the word to release shift with one hand to switch to holding shift with the other hand. In my experience, this is a nuisance especially if your shift keys are mod-taps, as in home row mods. + +Caps Word, implemented here, is a modern alternative to Caps Lock: + +* Caps Word is activated by pressing the left and right shift keys at the same time. This way you don’t need a dedicated key for using Caps Word. +* Caps Word automatically disables itself at the end of the word. + +**Compatibility**: I’ve tested that this implementation works with one-shot mods and Space Cadet Shift, and it predictably handles key repeating. + +Unlike some other QMK Caps Word implementations, this library does not use the Caps Lock (KC_CAPS) keycode. It works even if the OS remaps Caps Lock to Ctrl or something else, as Emacs and Vim users often do. + +## Using Caps Word +With the above flashed to your keyboard: + +1. **Activating**: Press and release both left and right shift keys at the same time. If your shift keys are mod-taps, activate Caps Word by holding both shift mod-tap keys until the tapping term, then release them. +2. Then begin typing to get capitalized letters. +3. **Disabling**: Caps Word disables itself when the next word breaking key is typed. + +If you want to explicitly stop Caps Word, press and release Ctrl or another non-shift modifier or layer key. This also disables Caps Word. + +## Explanation +The code checks the mod bits on each key event, enabling Caps Word when both left and right shifts are active. + +While enabled, Caps Word automatically presses and releases left shift (KC_LSFT) as needed so that letters are shifted and other keys are not. The word continues while typing a–z, 0–9, -, _, and backspace. Any other key is considered “word breaking” and disables Caps Word. You can edit the switch statement at the end of the process_caps_word() function to adjust which keys count as word breaking. diff --git a/users/drashna/keyrecords/keycodes.md b/users/drashna/keyrecords/keycodes.md new file mode 100644 index 0000000000..348c68e46c --- /dev/null +++ b/users/drashna/keyrecords/keycodes.md @@ -0,0 +1,18 @@ + +# Custom Keycodes + +Keycodes are defined in the `process_record.h` file and need to be included in the keymap.c files, so that they can be used there. + +A bunch of macros are present and are only included on boards that are not the Ergodox EZ or Orthodox, as they are not needed for those boards. + +* `KC_MAKE` - outputs `qmk compile -kb (keyboard) -km (keymap)` and enter, to start compiling the currenct keyboard. This uses generated variables to always use the current keyboard and keymap. Will work with any keyboard and any keymap. + * If you are holding shift, it will use `qmk flash` instead of `qmk compile`. + * If `MAKE_BOOTLOADER` is defined, it will always use `qmk flash` instead of `qmk compile`. +* `DEFAULT_LAYER_1` ... `DEFAULT_LAYER_4` - This sets layer 0-3 as the default layer, and writes that to eeprom, and plays a chime. +* `VRSN`, outputs the keyboard, keymap, commit and date info. Eg: + * `handwired/tractyl_manuform/5x6_right/f411/drashna @ 0.15.9-162-g087d08, Built on: 2021-12-19-21:10:26` +* `KC_DIABLO_CLEAR` - clears the diablo tapdance status. +* `KC_CCCV` - Copy on hold, paste on tap. +* `KEYLOCK` - This unloads the host driver, and prevents any data from being sent to the host. Hitting it again loads the driver, back. +* `REBOOT` - Uses watchdog timer on AVR, and `NVIC_SystemReset()` on ChibiOS to reset the board, without jumping to the bootloader. +* `EEP_RST` - Overrides the default behavior, disables EEPROM (which will trigger a reset on init), and reboots the keyboard as per `REBOOT` keycode. diff --git a/users/drashna/keyrecords/process_records.c b/users/drashna/keyrecords/process_records.c index c7d4a925b0..f49ac6ef64 100644 --- a/users/drashna/keyrecords/process_records.c +++ b/users/drashna/keyrecords/process_records.c @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "drashna.h" #include "version.h" @@ -22,6 +9,9 @@ #ifdef AUTOCORRECTION_ENABLE # include "autocorrection/autocorrection.h" #endif +#ifdef __AVR__ +#include +#endif uint16_t copy_paste_timer; bool host_driver_disabled = false; @@ -212,6 +202,28 @@ bool process_record_user(uint16_t keycode, keyrecord_t *re } break; } + case EEP_RST: + if (record->event.pressed) { + eeconfig_disable(); + shutdown_user(); +#ifdef __AVR__ + wdt_enable(WDTO_250MS); +#else + NVIC_SystemReset(); +#endif + } + return false; + case REBOOT: + if (record->event.pressed) { + shutdown_user(); +#ifdef __AVR__ + wdt_enable(WDTO_250MS); +#else + NVIC_SystemReset(); +#endif + } + return false; + } return true; } diff --git a/users/drashna/keyrecords/process_records.h b/users/drashna/keyrecords/process_records.h index df506b3647..d7a81d4607 100644 --- a/users/drashna/keyrecords/process_records.h +++ b/users/drashna/keyrecords/process_records.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "drashna.h" @@ -58,6 +45,7 @@ enum userspace_custom_keycodes { KC_ZALGO, KC_ACCEL, AUTO_CTN, // Toggle Autocorrect status + REBOOT, NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes }; @@ -66,7 +54,6 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record); void post_process_record_keymap(uint16_t keycode, keyrecord_t *record); #ifdef CUSTOM_UNICODE_ENABLE bool process_record_unicode(uint16_t keycode, keyrecord_t *record); -void matrix_init_unicode(void); #endif #define LOWER MO(_LOWER) @@ -140,3 +127,21 @@ void matrix_init_unicode(void); #define ALT_APP ALT_T(KC_APP) #define MG_NKRO MAGIC_TOGGLE_NKRO + + +/* +Custom Keycodes for Diablo 3 layer +But since TD() doesn't work when tap dance is disabled +We use custom codes here, so we can substitute the right stuff +*/ +#ifdef TAP_DANCE_ENABLE +# define KC_D3_1 TD(TD_D3_1) +# define KC_D3_2 TD(TD_D3_2) +# define KC_D3_3 TD(TD_D3_3) +# define KC_D3_4 TD(TD_D3_4) +#else // TAP_DANCE_ENABLE +# define KC_D3_1 KC_1 +# define KC_D3_2 KC_2 +# define KC_D3_3 KC_3 +# define KC_D3_4 KC_4 +#endif // TAP_DANCE_ENABLE diff --git a/users/drashna/keyrecords/readme.md b/users/drashna/keyrecords/readme.md new file mode 100644 index 0000000000..5f708f9edf --- /dev/null +++ b/users/drashna/keyrecords/readme.md @@ -0,0 +1,9 @@ +# Keycode handling and interception + + * [Autocorrection](autocorrection/readme.md) + * [Cap Words](capwords.md) + * [Diablo Tap Dancing](tap_dance.md) + * [Keymap Wrappers](wrappers.md) + * [Secret Macros](secrets.md) + * [Custom Keycodes](keycodes.md) + * [Unicode Input](unicode.md) diff --git a/users/drashna/keyrecords/secrets.md b/users/drashna/keyrecords/secrets.md new file mode 100644 index 0000000000..a9408dc2ef --- /dev/null +++ b/users/drashna/keyrecords/secrets.md @@ -0,0 +1,123 @@ +# Secret Macros + +With help from gitter and Colinta, this adds the ability to add hidden macros from other users. + +First, I have several files that are hidden/excluded from Git/GitHub. These contain everything needed for the macros. To hide these files, open `.git/info/exclude` and add `secrets.c` and `secrets.h` to that file, below the comments. + +And this requires `KC_SECRET_1` through `KC_SECRET_5` to be added in your keycode enum (usually in your `.h` file) the keycodes for the new macros. + +## Git Exclusion + +To prevent `git` from seeing, or committing the secret files, you can exclude them. What's the point of having secrets if they're posted on GitHub for everyone to see!?! + +You can do this with the `.git/info/exclude` file, so that it's only ignored locally. Unfortunately, that means it's not consistently handled on each system. + +However, if you create a `.gitignore` file in the same folder, you keep things consistent between every system that the code is checked out on. + +```c +secrets.c +secrets.h +``` + +## secrets.c + +Here is the magic. This handles including the "secrets", and adding the custom macros to send them. + +```c +#include "drashna.h" // replace with your keymap's "h" file, or whatever file stores the keycodes + +#if (__has_include("secrets.h") && !defined(NO_SECRETS)) +#include "secrets.h" +#else +// `PROGMEM const char secret[][x]` may work better, but it takes up more space in the firmware +// And I'm not familiar enough to know which is better or why... +static const char * const secret[] = { + "test1", + "test2", + "test3", + "test4", + "test5" +}; +#endif + +bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case KC_SECRET_1 ... KC_SECRET_5: // Secrets! Externally defined strings, not stored in repo + if (!record->event.pressed) { + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + send_string_with_delay(secret[keycode - KC_SECRET_1], MACRO_TIMER); + } + return false; + break; + } + return true; +} +``` + +## secrets.h + +Now, for the actual secrets! The file needs to look like + +```c +static const char * secrets[] = { + "secret1", + "secret2", + "secret3", + "secret4", + "secret5" +}; +``` + +Replacing the strings with the codes that you need. + +## Process Record + +In whichever file you have your `process_record_*` function in, you will want to add this to the top: + +```c +__attribute__ ((weak)) +bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { + return true; +} +``` + +This is so that the function can be called here, and replaced in the `secrets.c` file, and so it won't error out if it doesn't exist. + +And then, in the `process_record_user` function, assuming you have `return process_record_keymap(keycode, record)` here, you'll want to replace the "final" return with the following. Otherwise, you want to replace the `return true;` with `return process_record_secrets(keycode, record);` + +```c +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + // your existing macro code here. + return process_record_keymap(keycode, record) && process_record_secrets(keycode, record); +} +``` + +## rules.mk + +Here, you want your `/users//rules.mk` file to "detect" the existence of the `secrets.c` file, and only add it if the file exists. + +Additionally, to ensure that it's not added or processed in any way, it checks to see if `NO_SECRETS` is set. This way, if you run `make keyboard:name NO_SECRETS=yes`, it will remove the feature altogether. + +```make +ifneq ($(strip $(NO_SECRETS)), yes) + ifneq ("$(wildcard $(USER_PATH)/secrets.c)","") + SRC += secrets.c + endif +endif +``` + +Alternately, if you want to make sure that you can disable the function without messing with the file, you need to add this to your `/users//rules.mk`, so that it catches the flag: + +```make +ifneq ("$(wildcard $(USER_PATH)/secrets.c)","") + SRC += secrets.c +endif + +ifeq ($(strip $(NO_SECRETS)), yes) + OPT_DEFS += -DNO_SECRETS +endif +``` + +## Extras + +Additionally, because this file isn't present in the repo at all, you could add additional functionality that nobody else will see. diff --git a/users/drashna/keyrecords/tap_dance.md b/users/drashna/keyrecords/tap_dance.md new file mode 100644 index 0000000000..0bf67cbd5a --- /dev/null +++ b/users/drashna/keyrecords/tap_dance.md @@ -0,0 +1,121 @@ +# Diablo Tap Dances + +My [Tap Dance](tap_dances.c) file includes the tap dance declarations, and everything needed for them. + +To disable, add `CUSTOM_TAP_DANCE = no` to your `rules.mk`. + +This is used for making Diablo 3 much easier to plan, especially at high rift levels. + +This works by using Tap Dances. The taps don't actually "do anything". Instead, it sets up the interval for how often to send specific keypresses. As you can tell, this makes automating things very easy. + +For critics that think this is cheating, just search "[diablo 3 num lock auto cast](http://lmgtfy.com/?q=diablo+3+numlock+autocast)". This is just a simpler method, that doesn't require a numpad. + + +## Custom Tap Dance Type +The real fun here is that the tap dances use a custom defined Tap Dance type: + +```c +#define ACTION_TAP_DANCE_DIABLO(index, keycode) { \ + .fn = { NULL, (void *)diablo_tapdance_master, NULL }, \ + .user_data = (void *)&((diable_keys_t) { index, keycode }), \ + } +``` +This lets me set an index and keycode for the tap dance. This isn't the cool part yet, but this allows for the really cool stuff. + +The Index is needed because I don't know how to handle it otherwise. + +## The Actual Dances + +These are the custom defined dances that I'm using. It sets up everything for later, using the above custom dance type. + +```c +//Tap Dance Definitions, sets the index and the keycode. +qk_tap_dance_action_t tap_dance_actions[] = { + // tap once to disable, and more to enable timed micros + [TD_D3_1] = ACTION_TAP_DANCE_DIABLO(0, KC_1), + [TD_D3_2] = ACTION_TAP_DANCE_DIABLO(1, KC_2), + [TD_D3_3] = ACTION_TAP_DANCE_DIABLO(2, KC_3), + [TD_D3_4] = ACTION_TAP_DANCE_DIABLO(3, KC_4), +}; +``` + +## Custom Data Structures + +First, to get this all working, there are a couple of things that need to be set up. In a header file (or you could put it into the keymap), you need to create a couple of custom structures: + +```c +typedef struct { + uint16_t timer; + uint8_t key_interval; + uint8_t keycode; +} diablo_timer_t; + +typedef struct { + uint8_t index; + uint8_t keycode; +} diable_keys_t; +``` + +The first structure is for tracking each key that is being used. The second is to pass data from the Tap Dance action array to the actual function that we will need. + + +## Custom Arrays + +To facilitate things, you will need a couple of arrays in your `c` file. + +```c +//define diablo macro timer variables +diablo_timer_t diablo_timer[4]; + +// Set the default intervals. Always start with 0 so that it will disable on first hit. +// Otherwise, you will need to hit a bunch of times, or hit the "clear" command +uint8_t diablo_times[] = { 0, 1, 3, 5, 10, 30 }; +``` + +The first one (`diablo_timer`) is what keeps track of the timer used for the keys, the interval that it uses, and the actual keycode. This makes managing it a lot easier. + +The second array is a list of predefined intervals, in seconds. You can add more here, or remove entries. It doesn't matter how long the array is, as this is computed automatically. + +## The Magic - Part 1: Master function + +The first part of the magic here is the `diablo_tapdance_master` function. The Tap Dance feature calls this function, directly, and passes some data to the function. Namely, it passes the array of the index and the keycode (`diablo_keys_t` from above). This sets the keycode and the interval for the specific index of `diabolo_timer` based on the number of taps. If you hit it more than the number of items in the array, then it zeroes out the interval, disabling it. + +```c +// Cycle through the times for the macro, starting at 0, for disabled. +void diablo_tapdance_master(qk_tap_dance_state_t *state, void *user_data) { + diable_keys_t *diablo_keys = (diable_keys_t *)user_data; + // Sets the keycode based on the index + diablo_timer[diablo_keys->index].keycode = diablo_keys->keycode; + + // if the tapdance is hit more than the number of elemints in the array, reset + if (state->count >= (sizeof(diablo_times) / sizeof(uint8_t) ) ) { + diablo_timer[diablo_keys->index].key_interval = 0; + reset_tap_dance(state); + } else { // else set the interval (tapdance count starts at 1, array starts at 0, so offset by one) + diablo_timer[diablo_keys->index].key_interval = diablo_times[state->count - 1]; + } +} +``` + +## The Magic - Part 2: The Coup de Grace + +The real core here is the `run_diablo_macro_check()` function. You need to call this from `matrix_scan_user`, as this handles the timer check. + +Specifically, it runs a check for each index of the timer. It checks to see if it's enabled, and if enough time has passed. If enough time has passed, it resets the timer, and will tap the keycode that you set for that index, but only if the Diablo layer is enabled. + +```c +// Checks each of the 4 timers/keys to see if enough time has elapsed +void run_diablo_macro_check(void) { + for (uint8_t index = 0; index < NUM_OF_DIABLO_KEYS; index++) { + // if key_interval is 0, it's disabled, so only run if it's set. If it's set, check the timer. + if ( diablo_timer[index].key_interval && timer_elapsed( diablo_timer[index].timer ) > ( diablo_timer[index].key_interval * 1000 ) ) { + // reset the timer, since enough time has passed + diablo_timer[index].timer = timer_read(); + // send keycode ONLY if we're on the diablo layer. + if (IS_LAYER_ON(_DIABLO)) { + tap_code(diablo_timer[index].keycode); + } + } + } +} +``` diff --git a/users/drashna/keyrecords/tap_dances.c b/users/drashna/keyrecords/tap_dances.c index 01873489d8..63eb0c3348 100644 --- a/users/drashna/keyrecords/tap_dances.c +++ b/users/drashna/keyrecords/tap_dances.c @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "tap_dances.h" diff --git a/users/drashna/keyrecords/tap_dances.h b/users/drashna/keyrecords/tap_dances.h index 81e462ce29..d9baedc867 100644 --- a/users/drashna/keyrecords/tap_dances.h +++ b/users/drashna/keyrecords/tap_dances.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "drashna.h" diff --git a/users/drashna/keyrecords/tapping.c b/users/drashna/keyrecords/tapping.c new file mode 100644 index 0000000000..9c4892b33d --- /dev/null +++ b/users/drashna/keyrecords/tapping.c @@ -0,0 +1,64 @@ +// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "drashna.h" + +__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case BK_LWER: + return TAPPING_TERM + 25; + default: + return TAPPING_TERM; + } +} + +__attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { + // Immediately select the hold action when another key is tapped: + // return true; + // Do not select the hold action when another key is tapped. + // return false; + switch (keycode) { + default: + return false; + } +} + +__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { + // Immediately select the hold action when another key is pressed. + // return true; + // Do not select the hold action when another key is pressed. + // return false; + switch (keycode) { + case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: + return true; + default: + return false; + } +} + +__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { + // Do not force the mod-tap key press to be handled as a modifier + // if any other key was pressed while the mod-tap key is held down. + // return true; + // Force the mod-tap key press to be handled as a modifier if any + // other key was pressed while the mod-tap key is held down. + // return false; + switch (keycode) { + default: + return true; + } +} + +__attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + default: + return false; + } +} + +__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + default: + return false; + } +} diff --git a/users/drashna/keyrecords/unicode.c b/users/drashna/keyrecords/unicode.c index 88df2c9df9..4010b9c1c6 100644 --- a/users/drashna/keyrecords/unicode.c +++ b/users/drashna/keyrecords/unicode.c @@ -1,34 +1,13 @@ -/* Copyright 2020 @ridingqwerty - * Copyright 2020 @tzarc - * Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 @ridingqwerty +// Copyright 2020 @tzarc +// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "drashna.h" #include "process_unicode_common.h" uint16_t typing_mode; -void tap_code16_nomods(uint8_t kc) { - uint8_t temp_mod = get_mods(); - clear_mods(); - clear_oneshot_mods(); - tap_code16(kc); - set_mods(temp_mod); -} - void tap_unicode_glyph_nomods(uint32_t glyph) { uint8_t temp_mod = get_mods(); clear_mods(); @@ -188,6 +167,7 @@ bool process_record_aussie(uint16_t keycode, keyrecord_t *record) { bool process_record_zalgo(uint16_t keycode, keyrecord_t *record) { if ((KC_A <= keycode) && (keycode <= KC_0)) { if (record->event.pressed) { + tap_code16_nomods(keycode); int number = (rand() % (8 + 1 - 2)) + 2; @@ -247,9 +227,12 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) { } } break; + } - break; + if (((get_mods() | get_oneshot_mods()) & ~MOD_MASK_SHIFT) != 0) { + return true; } + if (((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) && record->tap.count) { keycode &= 0xFF; } diff --git a/users/drashna/keyrecords/unicode.md b/users/drashna/keyrecords/unicode.md new file mode 100644 index 0000000000..1b3f696a82 --- /dev/null +++ b/users/drashna/keyrecords/unicode.md @@ -0,0 +1,27 @@ +# Custom Unicode + +To disable, add `CUSTOM_UNICODE_ENABLE = no` to the keymap's `rules.mk`. + +This disables all of the various implementations of unicode, enables the common unicode core, and allows usage. + +In addition to a number of unicode keycodes: + +* `UC_FLIP` - `(ノಠ痊ಠ)ノ彡┻━┻` +* `UC_TABL` - `┬─┬ノ( º _ ºノ)` +* `UC_SHRG` - `¯\_(ツ)_/¯` +* `UC_DISA` - `ಠ_ಠ` +* `UC_IRNY` - `⸮` +* `UC_CLUE` - `‽` + +There are a number of unicode typing modes. This replaces the normal alpha keys with special unicodes. + +* `KC_WIDE` - this is wide mode +* `KC_SCRIPT` - 𝓽𝓱𝓲𝓼 𝓲𝓼 𝓼𝓬𝓻𝓲𝓹𝓽 𝓶𝓸𝓭𝓮 +* `KC_BLOCKS` - 🆃🅷🅸🆂 🅸🆂 🅱🅻🅾🅲🅺 🅼🅾🅳🅴 +* `KC_REGIONAL` - 🇹‌‌🇭‌‌🇮‌‌🇸‌‌ ‌‌🇮‌‌🇸‌‌ ‌‌🇷‌‌🇪‌‌🇬‌‌🇮‌‌🇴‌‌🇳‌‌🇦‌‌🇱‌‌ ‌‌🇲‌‌🇴‌‌🇩‌‌🇪‌‌ +* `KC_AUSSIE` - ǝpoɯ ǝᴉssnɐ sᴉ sᴉɥʇ +* `KC_ZALGO` - t̨͕͙̺͍͐̾ĥ̻ï̳̻̗̜͔ͦs͎̠͈͓͗̀ i̶̫ͭ̆s̛̫̻̜̝͑͡ z̩͈̠͗a͚̜̓͜l͈̟g͋͢͝ò͚ͥ͘͡͞ ḿ̴̡̻̼̔ͪò͔̭̿ͪ̍ḏ̻̊̄̈e̳͕̤ͣͯ +* `KC_NOMODE` - this is the normal typing mode with no unicode glyphs + + +Credit goes to ridingqwerty and tzarc for the unicode typing modes. diff --git a/users/drashna/keyrecords/wrappers.h b/users/drashna/keyrecords/wrappers.h index c1ae815579..cb8dc6189a 100644 --- a/users/drashna/keyrecords/wrappers.h +++ b/users/drashna/keyrecords/wrappers.h @@ -1,18 +1,6 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// Copyright 2020 @jola5 +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "drashna.h" diff --git a/users/drashna/keyrecords/wrappers.md b/users/drashna/keyrecords/wrappers.md new file mode 100644 index 0000000000..fd62ff1609 --- /dev/null +++ b/users/drashna/keyrecords/wrappers.md @@ -0,0 +1,11 @@ +## Keyboard Layout Templates + +This borrows from @jola5's "Not quite neo" code. This allows me to maintain blocks of keymaps in the userspace, so that I can modify the userspace, and this is reflected in all of the keyboards that use it, at once. + +This makes adding tap/hold mods, or other special keycodes or functions to all keyboards super easy, as it's done to all of them at once. + +The caveat here is that the keymap needs a processor/wrapper, as it doesn't like the substitutions. However, this is as simple as just pushing it through a define. For instance: + +`#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__)` + +Once that's been done and you've switched the keymaps to use the "wrapper", it will read the substitution blocks just fine. diff --git a/users/drashna/oled/drashna_font.h b/users/drashna/oled/drashna_font.h index 844292a53a..7ba03c4c13 100644 --- a/users/drashna/oled/drashna_font.h +++ b/users/drashna/oled/drashna_font.h @@ -3,8 +3,8 @@ // additional fonts from // https://github.com/datacute/TinyOLED-Fonts -#if __has_include("../../../../Documents/qmk/oled_font.h") -# include "../../../../Documents/qmk/oled_font.h" +#if __has_include("oled_font.h") +# include "oled_font.h" #else // additional fonts from diff --git a/users/drashna/oled/oled_stuff.c b/users/drashna/oled/oled_stuff.c index 9ee2cbfed8..de84766725 100644 --- a/users/drashna/oled/oled_stuff.c +++ b/users/drashna/oled/oled_stuff.c @@ -162,15 +162,8 @@ void render_keylock_status(uint8_t led_usb_state) { void render_matrix_scan_rate(void) { #ifdef DEBUG_MATRIX_SCAN_RATE - char matrix_rate[5]; - uint16_t n = get_matrix_scan_rate(); - matrix_rate[4] = '\0'; - matrix_rate[3] = '0' + n % 10; - matrix_rate[2] = (n /= 10) % 10 ? '0' + (n) % 10 : (n / 10) % 10 ? '0' : ' '; - matrix_rate[1] = n / 10 ? '0' + n / 10 : ' '; - matrix_rate[0] = ' '; oled_write_P(PSTR("MS:"), false); - oled_write(matrix_rate, false); + oled_write(get_u16_str(get_matrix_scan_rate(), ' '), false); #endif } diff --git a/users/drashna/oled/readme.md b/users/drashna/oled/readme.md new file mode 100644 index 0000000000..dbb8187d49 --- /dev/null +++ b/users/drashna/oled/readme.md @@ -0,0 +1,42 @@ +# OLED Display + +To disable the pre genrated oled display, add `CUSTOM_OLED_DRIVER = no` to your `rules.mk`. + + +## OLED Font + +My font file has multiple fonts and multiple logs integrated into the one file. And it uses the full 255 possible characters. + +In addition to the default font and logos: + +```c +# define OLED_FONT_5X5 +# define OLED_FONT_AZTECH +# define OLED_FONT_BMPLAIN +# define OLED_FONT_CRACKERS +# define OLED_FONT_EIN +# define OLED_FONT_HISKYF21 +# define OLED_FONT_SQUASH +# define OLED_FONT_SUPER_DIGG +# define OLED_FONT_ZXPIX +``` + +```c +# define OLED_LOGO_CORNE +# define OLED_LOGO_GMK_BAD +# define OLED_LOGO_GOTHAM +# define OLED_LOGO_HUE_MANITEE +# define OLED_LOGO_LOOSE +# define OLED_LOGO_SETS3N +# define OLED_LOGO_SKEEB +``` + +Additionally, the font file allows for external oled font files, instead. This allows for additional files that cannot be hosted in the QMK Repo. + +## Display + +A picture is worth a thousand words. So here are two: + +![Right](https://i.imgur.com/4XFOVKBl.jpg) + +![Left](https://i.imgur.com/W5RX4pAl.jpg) diff --git a/users/drashna/pointing/pointing.c b/users/drashna/pointing/pointing.c index 0198a8ae23..0bd14e4775 100644 --- a/users/drashna/pointing/pointing.c +++ b/users/drashna/pointing/pointing.c @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "pointing.h" diff --git a/users/drashna/pointing/pointing.h b/users/drashna/pointing/pointing.h index 4ad16eeff3..8b00ffc0ec 100644 --- a/users/drashna/pointing/pointing.h +++ b/users/drashna/pointing/pointing.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "drashna.h" diff --git a/users/drashna/pointing/readme.md b/users/drashna/pointing/readme.md new file mode 100644 index 0000000000..7770755050 --- /dev/null +++ b/users/drashna/pointing/readme.md @@ -0,0 +1,19 @@ +# User Pointing Device customization + +To disable the customized pointing device code and implement it at the keymap, add `CUSTOM_POINTING_DEVICE = no` to your `rules.mk`. + +## Automatic Mouse Layer + +Movement on the optical sensor triggers a layer that has all of the mouse keys on that layer. After a set time, the layer will automatically turn itself off after 650ms. + +Also, using mousekeys will extend the amount of time that the layer will stay active. + +Additionally, layer keys for the mouse layer will lock the layer on. + +## Gaming + +When the gamepad or diablo layers are enabled, the mouse layer is locked on, as well. + +## Keycodes + +The only custom keycode for Pointing devices here is `KC_ACCEL`. This allow the mouse report to have an acceleration curve (exponential). diff --git a/users/drashna/post_config.h b/users/drashna/post_config.h index b9d934c42b..0c9bda2eeb 100644 --- a/users/drashna/post_config.h +++ b/users/drashna/post_config.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -137,3 +124,7 @@ #ifndef DYNAMIC_KEYMAP_LAYER_COUNT # define DYNAMIC_KEYMAP_LAYER_COUNT 11 #endif + +#ifndef TAPPING_TERM +# define TAPPING_TERM 175 +#endif diff --git a/users/drashna/readme.md b/users/drashna/readme.md index b8d10aada2..e52b67e835 100644 --- a/users/drashna/readme.md +++ b/users/drashna/readme.md @@ -2,14 +2,16 @@ This is my personal userspace file. Most of my code exists here, as it's heavily shared. -* [RGB Customization](readme/rgb.md) -* [Diablo Tap Dancing](readme/tap_dance.md) -* [Keymap Wrappers](readme/wrappers.md) -* [Custom Function Handlers](readme/handlers.md) -* [Secret Macros](readme/secrets.md) -* [Custom Keycodes](readme/keycodes.md) - - -## Pro Micro Hacking - -See [this thread](https://www.reddit.com/r/olkb/comments/8sxgzb/replace_pro_micro_bootloader_with_qmk_dfu/) for details on how to flash QMK DFU to Pro Micros. +* [Callback (keymap+misc)](callbacks.md) +* [Keycode Handling](keyrecords/readme.md) + * [Autocorrection](keyrecords/autocorrection/readme.md) + * [Cap Words](keyrecords/capwords.md) + * [Diablo Tap Dancing](keyrecords/tap_dance.md) + * [Keymap Wrappers](keyrecords/wrappers.md) + * [Secret Macros](keyrecords/secrets.md) + * [Custom Keycodes](keyrecords/keycodes.md) + * [Unicode Input](keyrecords/unicode.md) +* [OLED Display](oled/readme.md) +* [Pointing Devices](pointing/readme.md) +* [RGB Customization](rgb/readme.md) +* [Split Transport](split/readme.md) diff --git a/users/drashna/readme/handlers.md b/users/drashna/readme/handlers.md deleted file mode 100644 index 4abaf51473..0000000000 --- a/users/drashna/readme/handlers.md +++ /dev/null @@ -1,97 +0,0 @@ -# Custom Userspace Function handlers - -Specifically QMK works by using customized handlers for everything. This allows for multiple levels of customization. - -`matrix_scan` calls `matrix_scan_quantum`, which calls `matrix_scan_kb`, which calls `matrix_scan_user`. -`process_record` calls a bunch of stuff, but eventually calls `process_record_kb` which calls `process_record_user` -The same goes for `matrix_init`, `layer_state_set`, `led_set`, and a few other functions. - -All (most) `_user` functions are handled here, in the userspace instead. To allow keyboard specific configuration, I've created `_keymap` functions that can be called by the keymap.c files instead. - -This allows for keyboard specific configuration while maintaining the ability to customize the board. - -My [Ergodox EZ Keymap](https://github.com/qmk/qmk_firmware/blob/master/layouts/community/ergodox/drashna/keymap.c) is a good example of this, as it uses the LEDs as modifier indicators. - -But for a list: - -```c -__attribute__ ((weak)) -void matrix_init_keymap(void) {} - -void matrix_init_user(void) { - matrix_init_keymap(); -} - -__attribute__((weak)) -void keyboard_post_init_keymap(void){ } - -void keyboard_post_init_user(void){ - keyboard_post_init_keymap(); -} - -__attribute__ ((weak)) -void matrix_scan_keymap(void) {} - -void matrix_scan_user(void) { - matrix_scan_keymap(); -} - - -__attribute__ ((weak)) -bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { - return true; -} - -bool process_record_user(uint16_t keycode, keyrecord_t *record) { - return process_record_keymap(keycode, record); -} - - -__attribute__ ((weak)) -layer_state_t layer_state_set_keymap (layer_state_t state) { - return state; -} - -layer_state_t layer_state_set_user (layer_state_t state) { - return layer_state_set_keymap (state); -} - - -__attribute__ ((weak)) -void led_set_keymap(uint8_t usb_led) {} - -void led_set_user(uint8_t usb_led) { - led_set_keymap(usb_led); -} - - -__attribute__ ((weak)) -void suspend_power_down_keymap(void) {} - -void suspend_power_down_user(void) { - suspend_power_down_keymap(); -} - - -__attribute__ ((weak)) -void suspend_wakeup_init_keymap(void) {} - -void suspend_wakeup_init_user(void) { - suspend_wakeup_init_keymap(); -} - - -__attribute__ ((weak)) -void shutdown_keymap(void) {} - -void shutdown_user (void) { - shutdown_keymap(); -} - -__attribute__ ((weak)) -void eeconfig_init_keymap(void) {} - -void eeconfig_init_user(void) { - eeconfig_init_keymap(); -} -``` diff --git a/users/drashna/readme/keycodes.md b/users/drashna/readme/keycodes.md deleted file mode 100644 index af4dd54bc0..0000000000 --- a/users/drashna/readme/keycodes.md +++ /dev/null @@ -1,10 +0,0 @@ - -# Custom Keycodes - -Keycodes are defined in the drashna.h file and need to be included in the keymap.c files, so that they can be used there. - -A bunch of macros are present and are only included on boards that are not the Ergodox EZ or Orthodox, as they are not needed for those boards. - -Included is a custom macro for compiling my keyboards. This includes the bootloader target (`:teensy`, `:avrdude`, or `:dfu`), and keeps RGBLIGHT, AUDIO enabled, if it previously was (regardless of the rules file). - -This also includes a modified RESET keycode as well, that sets the underglow to red. diff --git a/users/drashna/readme/rgb.md b/users/drashna/readme/rgb.md deleted file mode 100644 index acf01b051e..0000000000 --- a/users/drashna/readme/rgb.md +++ /dev/null @@ -1,43 +0,0 @@ -# Layer Indication Code - -At least for RGB Light, the `layer_state_set` function is used to detect the current highest layer, and change the underglow based on that layer. - -This works for both the regular layers, and for the default layers, too. - -I use the sethsv variants of the commands, so that different modes can be used, as well. - -RGB Matrix uses a custom, per board implementation, at the moment. - -# RGB Light Startup Animation - -On startup, if enabled, the board will cycle through the entire hue wheel, starting and ending on the default layer color. - -```c -void keyboard_post_init_rgb(void) { -#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_STARTUP_ANIMATION) - if (userspace_config.rgb_layer_change) { rgblight_enable_noeeprom(); } - if (rgblight_config.enable) { - layer_state_set_user(layer_state); - uint16_t old_hue = rgblight_config.hue; - rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT); - for (uint16_t i = 255; i > 0; i--) { - rgblight_sethsv_noeeprom( ( i + old_hue) % 255, 255, 255); - matrix_scan(); - wait_ms(10); - } - } -#endif - layer_state_set_user(layer_state); -} -``` - -This could probably benefit from some cleanup and better handling. - - -# RGB Light Twinkling - -This enables random twinkling of the LEDs when typing. - -# RGB Light Mod Indicators - -Allows feedback of which mods (oneshot or otherwise) are enabled. diff --git a/users/drashna/readme/secrets.md b/users/drashna/readme/secrets.md deleted file mode 100644 index a9408dc2ef..0000000000 --- a/users/drashna/readme/secrets.md +++ /dev/null @@ -1,123 +0,0 @@ -# Secret Macros - -With help from gitter and Colinta, this adds the ability to add hidden macros from other users. - -First, I have several files that are hidden/excluded from Git/GitHub. These contain everything needed for the macros. To hide these files, open `.git/info/exclude` and add `secrets.c` and `secrets.h` to that file, below the comments. - -And this requires `KC_SECRET_1` through `KC_SECRET_5` to be added in your keycode enum (usually in your `.h` file) the keycodes for the new macros. - -## Git Exclusion - -To prevent `git` from seeing, or committing the secret files, you can exclude them. What's the point of having secrets if they're posted on GitHub for everyone to see!?! - -You can do this with the `.git/info/exclude` file, so that it's only ignored locally. Unfortunately, that means it's not consistently handled on each system. - -However, if you create a `.gitignore` file in the same folder, you keep things consistent between every system that the code is checked out on. - -```c -secrets.c -secrets.h -``` - -## secrets.c - -Here is the magic. This handles including the "secrets", and adding the custom macros to send them. - -```c -#include "drashna.h" // replace with your keymap's "h" file, or whatever file stores the keycodes - -#if (__has_include("secrets.h") && !defined(NO_SECRETS)) -#include "secrets.h" -#else -// `PROGMEM const char secret[][x]` may work better, but it takes up more space in the firmware -// And I'm not familiar enough to know which is better or why... -static const char * const secret[] = { - "test1", - "test2", - "test3", - "test4", - "test5" -}; -#endif - -bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { - switch (keycode) { - case KC_SECRET_1 ... KC_SECRET_5: // Secrets! Externally defined strings, not stored in repo - if (!record->event.pressed) { - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - send_string_with_delay(secret[keycode - KC_SECRET_1], MACRO_TIMER); - } - return false; - break; - } - return true; -} -``` - -## secrets.h - -Now, for the actual secrets! The file needs to look like - -```c -static const char * secrets[] = { - "secret1", - "secret2", - "secret3", - "secret4", - "secret5" -}; -``` - -Replacing the strings with the codes that you need. - -## Process Record - -In whichever file you have your `process_record_*` function in, you will want to add this to the top: - -```c -__attribute__ ((weak)) -bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { - return true; -} -``` - -This is so that the function can be called here, and replaced in the `secrets.c` file, and so it won't error out if it doesn't exist. - -And then, in the `process_record_user` function, assuming you have `return process_record_keymap(keycode, record)` here, you'll want to replace the "final" return with the following. Otherwise, you want to replace the `return true;` with `return process_record_secrets(keycode, record);` - -```c -bool process_record_user(uint16_t keycode, keyrecord_t *record) { - // your existing macro code here. - return process_record_keymap(keycode, record) && process_record_secrets(keycode, record); -} -``` - -## rules.mk - -Here, you want your `/users//rules.mk` file to "detect" the existence of the `secrets.c` file, and only add it if the file exists. - -Additionally, to ensure that it's not added or processed in any way, it checks to see if `NO_SECRETS` is set. This way, if you run `make keyboard:name NO_SECRETS=yes`, it will remove the feature altogether. - -```make -ifneq ($(strip $(NO_SECRETS)), yes) - ifneq ("$(wildcard $(USER_PATH)/secrets.c)","") - SRC += secrets.c - endif -endif -``` - -Alternately, if you want to make sure that you can disable the function without messing with the file, you need to add this to your `/users//rules.mk`, so that it catches the flag: - -```make -ifneq ("$(wildcard $(USER_PATH)/secrets.c)","") - SRC += secrets.c -endif - -ifeq ($(strip $(NO_SECRETS)), yes) - OPT_DEFS += -DNO_SECRETS -endif -``` - -## Extras - -Additionally, because this file isn't present in the repo at all, you could add additional functionality that nobody else will see. diff --git a/users/drashna/readme/tap_dance.md b/users/drashna/readme/tap_dance.md deleted file mode 100644 index a61dd1f2b0..0000000000 --- a/users/drashna/readme/tap_dance.md +++ /dev/null @@ -1,119 +0,0 @@ -# Diablo Tap Dances - -My [Tap Dance](https://github.com/qmk/qmk_firmware/blob/master/users/drashna/tap_dances.c) file includes the tap dance declarations, and everything needed for them. - -This is used for making Diablo 3 much easier to plan, especially at high rift levels. - -This works by using Tap Dances. The taps don't actually "do anything". Instead, it sets up the interval for how often to send specific keypresses. As you can tell, this makes automating things very easy. - -For critics that think this is cheating, just search "[diablo 3 num lock auto cast](http://lmgtfy.com/?q=diablo+3+numlock+autocast)". This is just a simpler method, that doesn't require a numpad. - - -## Custom Tap Dance Type -The real fun here is that the tap dances use a custom defined Tap Dance type: - -```c -#define ACTION_TAP_DANCE_DIABLO(index, keycode) { \ - .fn = { NULL, (void *)diablo_tapdance_master, NULL }, \ - .user_data = (void *)&((diable_keys_t) { index, keycode }), \ - } -``` -This lets me set an index and keycode for the tap dance. This isn't the cool part yet, but this allows for the really cool stuff. - -The Index is needed because I don't know how to handle it otherwise. - -## The Actual Dances - -These are the custom defined dances that I'm using. It sets up everything for later, using the above custom dance type. - -```c -//Tap Dance Definitions, sets the index and the keycode. -qk_tap_dance_action_t tap_dance_actions[] = { - // tap once to disable, and more to enable timed micros - [TD_D3_1] = ACTION_TAP_DANCE_DIABLO(0, KC_1), - [TD_D3_2] = ACTION_TAP_DANCE_DIABLO(1, KC_2), - [TD_D3_3] = ACTION_TAP_DANCE_DIABLO(2, KC_3), - [TD_D3_4] = ACTION_TAP_DANCE_DIABLO(3, KC_4), -}; -``` - -## Custom Data Structures - -First, to get this all working, there are a couple of things that need to be set up. In a header file (or you could put it into the keymap), you need to create a couple of custom structures: - -```c -typedef struct { - uint16_t timer; - uint8_t key_interval; - uint8_t keycode; -} diablo_timer_t; - -typedef struct { - uint8_t index; - uint8_t keycode; -} diable_keys_t; -``` - -The first structure is for tracking each key that is being used. The second is to pass data from the Tap Dance action array to the actual function that we will need. - - -## Custom Arrays - -To facilitate things, you will need a couple of arrays in your `c` file. - -```c -//define diablo macro timer variables -diablo_timer_t diablo_timer[4]; - -// Set the default intervals. Always start with 0 so that it will disable on first hit. -// Otherwise, you will need to hit a bunch of times, or hit the "clear" command -uint8_t diablo_times[] = { 0, 1, 3, 5, 10, 30 }; -``` - -The first one (`diablo_timer`) is what keeps track of the timer used for the keys, the interval that it uses, and the actual keycode. This makes managing it a lot easier. - -The second array is a list of predefined intervals, in seconds. You can add more here, or remove entries. It doesn't matter how long the array is, as this is computed automatically. - -## The Magic - Part 1: Master function - -The first part of the magic here is the `diablo_tapdance_master` function. The Tap Dance feature calls this function, directly, and passes some data to the function. Namely, it passes the array of the index and the keycode (`diablo_keys_t` from above). This sets the keycode and the interval for the specific index of `diabolo_timer` based on the number of taps. If you hit it more than the number of items in the array, then it zeroes out the interval, disabling it. - -```c -// Cycle through the times for the macro, starting at 0, for disabled. -void diablo_tapdance_master(qk_tap_dance_state_t *state, void *user_data) { - diable_keys_t *diablo_keys = (diable_keys_t *)user_data; - // Sets the keycode based on the index - diablo_timer[diablo_keys->index].keycode = diablo_keys->keycode; - - // if the tapdance is hit more than the number of elemints in the array, reset - if (state->count >= (sizeof(diablo_times) / sizeof(uint8_t) ) ) { - diablo_timer[diablo_keys->index].key_interval = 0; - reset_tap_dance(state); - } else { // else set the interval (tapdance count starts at 1, array starts at 0, so offset by one) - diablo_timer[diablo_keys->index].key_interval = diablo_times[state->count - 1]; - } -} -``` - -## The Magic - Part 2: The Coup de Grace - -The real core here is the `run_diablo_macro_check()` function. You need to call this from `matrix_scan_user`, as this handles the timer check. - -Specifically, it runs a check for each index of the timer. It checks to see if it's enabled, and if enough time has passed. If enough time has passed, it resets the timer, and will tap the keycode that you set for that index, but only if the Diablo layer is enabled. - -```c -// Checks each of the 4 timers/keys to see if enough time has elapsed -void run_diablo_macro_check(void) { - for (uint8_t index = 0; index < NUM_OF_DIABLO_KEYS; index++) { - // if key_interval is 0, it's disabled, so only run if it's set. If it's set, check the timer. - if ( diablo_timer[index].key_interval && timer_elapsed( diablo_timer[index].timer ) > ( diablo_timer[index].key_interval * 1000 ) ) { - // reset the timer, since enough time has passed - diablo_timer[index].timer = timer_read(); - // send keycode ONLY if we're on the diablo layer. - if (IS_LAYER_ON(_DIABLO)) { - tap_code(diablo_timer[index].keycode); - } - } - } -} -``` diff --git a/users/drashna/readme/wrappers.md b/users/drashna/readme/wrappers.md deleted file mode 100644 index fd62ff1609..0000000000 --- a/users/drashna/readme/wrappers.md +++ /dev/null @@ -1,11 +0,0 @@ -## Keyboard Layout Templates - -This borrows from @jola5's "Not quite neo" code. This allows me to maintain blocks of keymaps in the userspace, so that I can modify the userspace, and this is reflected in all of the keyboards that use it, at once. - -This makes adding tap/hold mods, or other special keycodes or functions to all keyboards super easy, as it's done to all of them at once. - -The caveat here is that the keymap needs a processor/wrapper, as it doesn't like the substitutions. However, this is as simple as just pushing it through a define. For instance: - -`#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__)` - -Once that's been done and you've switched the keymaps to use the "wrapper", it will read the substitution blocks just fine. diff --git a/users/drashna/rgb/readme.md b/users/drashna/rgb/readme.md new file mode 100644 index 0000000000..4deaa0a463 --- /dev/null +++ b/users/drashna/rgb/readme.md @@ -0,0 +1,52 @@ +# RGB + +Custom RGB code can be disabled by setting `CUSTOM_RGBLIGHT = no` or `CUSTOM_RGB_MATRIX = no` in your `rules.mk` + +## RGB Light + +### Layer Indication Code + +At least for RGB Light, the `layer_state_set` function is used to detect the current highest layer, and change the underglow based on that layer. + +This works for both the regular layers, and for the default layers, too. + +I use the sethsv variants of the commands, so that different modes can be used, as well. + +RGB Matrix uses a custom, per board implementation, at the moment. + +### RGB Light Startup Animation + +On startup, if enabled, the board will cycle through the entire hue wheel, starting and ending on the default layer color. + +```c +void keyboard_post_init_rgb(void) { +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_STARTUP_ANIMATION) + if (userspace_config.rgb_layer_change) { rgblight_enable_noeeprom(); } + if (rgblight_config.enable) { + layer_state_set_user(layer_state); + uint16_t old_hue = rgblight_config.hue; + rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT); + for (uint16_t i = 255; i > 0; i--) { + rgblight_sethsv_noeeprom( ( i + old_hue) % 255, 255, 255); + matrix_scan(); + wait_ms(10); + } + } +#endif + layer_state_set_user(layer_state); +} +``` + +This could probably benefit from some cleanup and better handling. + +## RGB Matrix + +### Idle Animation + +This feature can be toggled with the `RGB_IDL` keycode. + +This sets the mode to the Heatmap Animation when typing, but will switch to the cycle in animations when idle. + +### Layer Indication + +This sets the modifier keys to indicate the current layer state, with the option to override the behavior. diff --git a/users/drashna/rgb/rgb_matrix_stuff.c b/users/drashna/rgb/rgb_matrix_stuff.c index 97811092c1..e6d631466d 100644 --- a/users/drashna/rgb/rgb_matrix_stuff.c +++ b/users/drashna/rgb/rgb_matrix_stuff.c @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "drashna.h" #include "rgb_matrix.h" @@ -29,27 +16,27 @@ void rgb_matrix_layer_helper(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode switch (mode) { case 1: // breathing - { - uint16_t time = scale16by8(g_rgb_timer, speed / 8); - hsv.v = scale8(abs8(sin8(time) - 128) * 2, hsv.v); - RGB rgb = hsv_to_rgb(hsv); - for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) { - if (HAS_FLAGS(g_led_config.flags[i], led_type)) { - RGB_MATRIX_INDICATOR_SET_COLOR(i, rgb.r, rgb.g, rgb.b); - } + { + uint16_t time = scale16by8(g_rgb_timer, speed / 8); + hsv.v = scale8(abs8(sin8(time) - 128) * 2, hsv.v); + RGB rgb = hsv_to_rgb(hsv); + for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) { + if (HAS_FLAGS(g_led_config.flags[i], led_type)) { + RGB_MATRIX_INDICATOR_SET_COLOR(i, rgb.r, rgb.g, rgb.b); } - break; } + break; + } default: // Solid Color - { - RGB rgb = hsv_to_rgb(hsv); - for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) { - if (HAS_FLAGS(g_led_config.flags[i], led_type)) { - RGB_MATRIX_INDICATOR_SET_COLOR(i, rgb.r, rgb.g, rgb.b); - } + { + RGB rgb = hsv_to_rgb(hsv); + for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) { + if (HAS_FLAGS(g_led_config.flags[i], led_type)) { + RGB_MATRIX_INDICATOR_SET_COLOR(i, rgb.r, rgb.g, rgb.b); } - break; } + break; + } } } @@ -95,3 +82,48 @@ bool process_record_user_rgb_matrix(uint16_t keycode, keyrecord_t *record) { } return true; } + +__attribute__((weak)) bool rgb_matrix_indicators_advanced_keymap(uint8_t led_min, uint8_t led_max) { return true; } +void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { + if (!rgb_matrix_indicators_advanced_keymap(led_min, led_max)) { return; } + +#if defined(RGBLIGHT_ENABLE) + if (!userspace_config.rgb_layer_change) +#else + if (userspace_config.rgb_layer_change) +#endif + { + switch (get_highest_layer(layer_state | default_layer_state)) { + case _DEFAULT_LAYER_1: + rgb_matrix_layer_helper(DEFAULT_LAYER_1_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); + break; + case _DEFAULT_LAYER_2: + rgb_matrix_layer_helper(DEFAULT_LAYER_2_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); + break; + case _DEFAULT_LAYER_3: + rgb_matrix_layer_helper(DEFAULT_LAYER_3_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); + break; + case _DEFAULT_LAYER_4: + rgb_matrix_layer_helper(DEFAULT_LAYER_4_HSV, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); + break; + case _GAMEPAD: + rgb_matrix_layer_helper(HSV_ORANGE, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); + break; + case _DIABLO: + rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed * 8, LED_FLAG_MODIFIER, led_min, led_max); + break; + case _RAISE: + rgb_matrix_layer_helper(HSV_YELLOW, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); + break; + case _LOWER: + rgb_matrix_layer_helper(HSV_GREEN, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); + break; + case _ADJUST: + rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER, led_min, led_max); + break; + } + } +} + +__attribute__((weak)) bool rgb_matrix_indicators_keymap(void) { return true; } +void rgb_matrix_indicators_user(void) { rgb_matrix_indicators_keymap(); } diff --git a/users/drashna/rgb/rgb_matrix_stuff.h b/users/drashna/rgb/rgb_matrix_stuff.h index b86f2f6514..7c6f6c271e 100644 --- a/users/drashna/rgb/rgb_matrix_stuff.h +++ b/users/drashna/rgb/rgb_matrix_stuff.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "quantum.h" @@ -23,3 +10,6 @@ void matrix_scan_rgb_matrix(void); void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue); void rgb_matrix_layer_helper(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode, uint8_t speed, uint8_t led_type, uint8_t led_min, uint8_t led_max); + +bool rgb_matrix_indicators_advanced_keymap(uint8_t led_min, uint8_t led_max); +bool rgb_matrix_indicators_keymap(void); diff --git a/users/drashna/rgb/rgb_stuff.c b/users/drashna/rgb/rgb_stuff.c index 15108bde04..e0422334aa 100644 --- a/users/drashna/rgb/rgb_stuff.c +++ b/users/drashna/rgb/rgb_stuff.c @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #ifdef RGBLIGHT_ENABLE diff --git a/users/drashna/rgb/rgb_stuff.h b/users/drashna/rgb/rgb_stuff.h index af1acdde71..d720275b60 100644 --- a/users/drashna/rgb/rgb_stuff.h +++ b/users/drashna/rgb/rgb_stuff.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "quantum.h" diff --git a/users/drashna/rgblight_breathe_table.h b/users/drashna/rgblight_breathe_table.h index b6f7a13ac1..d406395978 100644 --- a/users/drashna/rgblight_breathe_table.h +++ b/users/drashna/rgblight_breathe_table.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #ifndef RGBLIGHT_EFFECT_BREATHE_TABLE #define RGBLIGHT_EFFECT_BREATHE_TABLE diff --git a/users/drashna/rules.mk b/users/drashna/rules.mk index 32afae22c9..445d1cf5ac 100644 --- a/users/drashna/rules.mk +++ b/users/drashna/rules.mk @@ -1,5 +1,7 @@ SRC += $(USER_PATH)/drashna.c \ - $(USER_PATH)/keyrecords/process_records.c + $(USER_PATH)/callbacks.c \ + $(USER_PATH)/keyrecords/process_records.c \ + $(USER_PATH)/keyrecords/tapping.c ifneq ($(PLATFORM),CHIBIOS) ifneq ($(strip $(LTO_SUPPORTED)), no) @@ -8,6 +10,7 @@ ifneq ($(PLATFORM),CHIBIOS) endif SPACE_CADET_ENABLE = no GRAVE_ESC_ENABLE = no +# DEBUG_MATRIX_SCAN_RATE_ENABLE = api ifneq ($(strip $(NO_SECRETS)), yes) ifneq ("$(wildcard $(USER_PATH)/keyrecords/secrets.c)","") @@ -18,12 +21,23 @@ ifneq ($(strip $(NO_SECRETS)), yes) endif endif +ifeq ($(strip $(MAKE_BOOTLOADER)), yes) + OPT_DEFS += -DMAKE_BOOTLOADER +endif + +# At least until build.mk or the like drops, this is here to prevent +# VUSB boards from enabling NKRO, as they do not support it. Ideally +# this should be handled per keyboard, but until that happens ... +ifeq ($(strip $(PROTOCOL)), VUSB) + NKRO_ENABLE := no +endif + CUSTOM_UNICODE_ENABLE ?= yes ifeq ($(strip $(CUSTOM_UNICODE_ENABLE)), yes) - UNICODE_ENABLE = no - UNICODEMAP_ENABLE = no - UCIS_ENABLE = no - UNICODE_COMMON = yes + UNICODE_ENABLE := no + UNICODEMAP_ENABLE := no + UCIS_ENABLE := no + UNICODE_COMMON := yes OPT_DEFS += -DCUSTOM_UNICODE_ENABLE SRC += $(USER_PATH)/keyrecords/unicode.c endif @@ -62,17 +76,6 @@ ifdef CONSOLE_ENABLE endif endif -ifeq ($(strip $(MAKE_BOOTLOADER)), yes) - OPT_DEFS += -DMAKE_BOOTLOADER -endif - -# At least until build.mk or the like drops, this is here to prevent -# VUSB boards from enabling NKRO, as they do not support it. Ideally -# this should be handled per keyboard, but until that happens ... -ifeq ($(strip $(PROTOCOL)), VUSB) - NKRO_ENABLE = no -endif - CUSTOM_OLED_DRIVER ?= yes ifeq ($(strip $(OLED_ENABLE)), yes) ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes) @@ -96,15 +99,13 @@ ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes) endif endif -# DEBUG_MATRIX_SCAN_RATE_ENABLE = api - -AUTOCORRECTION_ENABLE ?= yes +AUTOCORRECTION_ENABLE ?= no ifeq ($(strip $(AUTOCORRECTION_ENABLE)), yes) SRC += $(USER_PATH)/keyrecords/autocorrection/autocorrection.c OPT_DEFS += -DAUTOCORRECTION_ENABLE endif -CAPS_WORD_ENABLE ?= yes +CAPS_WORD_ENABLE ?= no ifeq ($(strip $(CAPS_WORD_ENABLE)), yes) SRC += $(USER_PATH)/keyrecords/caps_word.c OPT_DEFS += -DCAPS_WORD_ENABLE diff --git a/users/drashna/split/readme.md b/users/drashna/split/readme.md new file mode 100644 index 0000000000..5dad340122 --- /dev/null +++ b/users/drashna/split/readme.md @@ -0,0 +1,29 @@ +# Custom Split Transport + +To disable the customized split transport, add `CUSTOM_SPLIT_TRANSPORT_SYNC = no` to your `rules.mk`. + +This syncs a number of additional settings, such as the keymap_config (magic settings), user eeprom configs, and misc firmware settings. + +Additionally, this supports a watchdog timer reset for the secondary split side. + +## User State Config + +The User states that it sync are: + +* Audio Enable status +* Audio Clicky states +* Unicode mode +* Pointing Device tap toggle status +* Swap Hands status +* Host Driver status + +## Userspace Config + +The userspace config states that are synced are: + +* RGB layer indication +* "is overwatch" status +* nuke switch +* Swapped numbers +* RGB Matrix idle animation +* Autocorrect enable status diff --git a/users/drashna/split/transport_sync.c b/users/drashna/split/transport_sync.c index cee3f04c8f..794664293c 100644 --- a/users/drashna/split/transport_sync.c +++ b/users/drashna/split/transport_sync.c @@ -1,22 +1,12 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "transport_sync.h" #include "transactions.h" #include +#ifdef __AVR__ +# include +#endif #ifdef CUSTOM_UNICODE_ENABLE #include "process_unicode_common.h" @@ -33,6 +23,10 @@ extern bool tap_toggling; #ifdef SWAP_HANDS_ENABLE extern bool swap_hands; #endif + +static bool watchdog_ping_done = false; +static uint32_t watchdog_timer = 0; + extern userspace_config_t userspace_config; extern bool host_driver_disabled; @@ -57,11 +51,20 @@ void user_config_sync(uint8_t initiator2target_buffer_size, const void* initiato } } +void watchdog_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { watchdog_ping_done = true; } + + void keyboard_post_init_transport_sync(void) { // Register keyboard state sync split transaction transaction_register_rpc(RPC_ID_USER_STATE_SYNC, user_state_sync); transaction_register_rpc(RPC_ID_USER_KEYMAP_SYNC, user_keymap_sync); transaction_register_rpc(RPC_ID_USER_CONFIG_SYNC, user_config_sync); + +#ifdef __AVR__ + wdt_disable(); +#endif + transaction_register_rpc(RPC_ID_USER_WATCHDOG_SYNC, watchdog_handler); + watchdog_timer = timer_read32(); } void user_transport_update(void) { @@ -163,6 +166,30 @@ void user_transport_sync(void) { } } } + + if (!watchdog_ping_done) { + if (is_keyboard_master()) { + if (timer_elapsed32(watchdog_timer) > 100) { + uint8_t any_data = 1; + if (transaction_rpc_send(RPC_ID_USER_WATCHDOG_SYNC, sizeof(any_data), &any_data)) { + watchdog_ping_done = true; // successful ping + } else { + dprint("Watchdog ping failed!\n"); + } + watchdog_timer = timer_read32(); + } + } else { + if (timer_elapsed32(watchdog_timer) > 3500) { +#ifdef __AVR__ + wdt_enable(WDTO_250MS); +#else + NVIC_SystemReset(); +#endif + while (1) { + } + } + } + } } void housekeeping_task_user(void) { diff --git a/users/drashna/split/transport_sync.h b/users/drashna/split/transport_sync.h index 70b6ea522b..6b6f0c388b 100644 --- a/users/drashna/split/transport_sync.h +++ b/users/drashna/split/transport_sync.h @@ -1,19 +1,5 @@ - -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once diff --git a/users/drashna/template.c b/users/drashna/template.c index f98964ae4f..c4a62c6448 100644 --- a/users/drashna/template.c +++ b/users/drashna/template.c @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #include "template.h" diff --git a/users/drashna/template.h b/users/drashna/template.h index cb1ad75d8a..26ac98edb9 100644 --- a/users/drashna/template.h +++ b/users/drashna/template.h @@ -1,18 +1,5 @@ -/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) - * - * 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 . - */ +// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) +// SPDX-License-Identifier: GPL-2.0-or-later #pragma once -- cgit v1.2.3