diff --git a/keyboards/crkbd/keymaps/hadeed/keymap.c b/keyboards/crkbd/keymaps/hadeed/keymap.c index 0f6e99f..b24201e 100644 --- a/keyboards/crkbd/keymaps/hadeed/keymap.c +++ b/keyboards/crkbd/keymaps/hadeed/keymap.c @@ -1,21 +1,22 @@ #include QMK_KEYBOARD_H +#include "oneshot.h" + enum LAYERS { BASE, - NUM, - SYM, + NAV, }; -#define HRM_A LALT_T(KC_A) -#define HRM_R LGUI_T(KC_R) -#define HRM_S LCTL_T(KC_S) -#define HRM_T LSFT_T(KC_T) -#define HRM_N RSFT_T(KC_N) -#define HRM_E RCTL_T(KC_E) -#define HRM_I RGUI_T(KC_I) -#define HRM_O LALT_T(KC_O) +enum KEYCODES { + LC_NAV = MO(NAV), + LC_NUM = MO(NUM), + LC_SYM = MO(SYM), -#define _KC_TAB LT(NUM, KC_TAB) + OS_SHFT = SAFE_RANGE, + OS_CTRL, + OS_GUI, + OS_ALT +}; const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* @@ -28,23 +29,64 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ [BASE] = LAYOUT_split_3x5_3( - KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, - HRM_A, HRM_R, HRM_S, HRM_T, KC_G, KC_M, HRM_N, HRM_E, HRM_I, HRM_O, + KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_QUOT, + KC_A, KC_R, KC_S, KC_T, KC_G, KC_M, KC_N, KC_E, KC_I, KC_O, KC_Z, KC_X, KC_C, KC_D, KC_V, KC_K, KC_H, KC_COMM, KC_DOT, KC_SLSH, - _KC_TAB, KC_ENT, KC_ESC, KC_BSPC, KC_SPC, MO(SYM) + QK_REP, LC_NAV, KC_ENT, KC_SPC, LC_NUM, LC_SYM ), [NUM] = LAYOUT_split_3x5_3( - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - KC_9, KC_5, KC_0, KC_3, KC_7, KC_6, KC_2, KC_1, KC_4, KC_8, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______ + _______, _______, _______, _______, _______, _______, KC_7, KC_8, KC_9, _______, + OS_ALT, OS_GUI, OS_CTRL, OS_SHFT, CW_TOGG, _______, KC_4, KC_5, KC_6, _______, + _______, _______, _______, _______, _______, _______, KC_1, KC_2, KC_3, _______, + _______, _______, _______, _______, KC_0, _______ ), - [SYM] = LAYOUT_split_3x5_3( - KC_GRV, KC_DQUO, KC_LBRC, KC_RBRC, KC_AT, KC_PERC, KC_HASH, KC_ASTR, KC_SLSH, KC_COLN, - KC_BSLS, KC_QUOT, KC_LPRN, KC_RPRN, KC_AMPR, KC_PIPE, KC_EQL, KC_MINS, KC_PLUS, KC_EXLM, - QK_BOOT, KC_TILD, KC_LCBR, KC_RCBR, KC_CIRC, KC_DLR, KC_UNDS, KC_LABK, KC_RABK, KC_QUES, - _______, _______, _______, _______, _______, _______ + [NAV] = LAYOUT_split_3x5_3( + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + OS_ALT, OS_GUI, OS_CTRL, OS_SHFT, CW_TOGG, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_BSPC, + _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END, KC_DEL, + QK_BOOT, _______, _______, KC_TAB, KC_ESC, _______ ), }; + +bool is_oneshot_cancel_key(uint16_t keycode) { + switch (keycode) { + case LC_NAV: + case LC_NUM: + case LC_SYM: + return true; + } + + return false; +} + +bool is_oneshot_ignored_key(uint16_t keycode) { + switch (keycode) { + case LC_NAV: + case LC_NUM: + case LC_SYM: + case OS_SHFT: + case OS_CTRL: + case OS_ALT: + case OS_GUI: + return true; + } + + return false; +} + +static oneshot_state os_shft_state = os_up_unqueued; +static oneshot_state os_ctrl_state = os_up_unqueued; +static oneshot_state os_alt_state = os_up_unqueued; +static oneshot_state os_cmd_state = os_up_unqueued; + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + update_oneshot(&os_shft_state, KC_LSFT, OS_SHFT, keycode, record); + update_oneshot(&os_ctrl_state, KC_LCTL, OS_CTRL, keycode, record); + update_oneshot(&os_alt_state, KC_LALT, OS_ALT, keycode, record); + update_oneshot(&os_cmd_state, KC_LCMD, OS_GUI, keycode, record); + + return true; +} + diff --git a/keyboards/crkbd/keymaps/hadeed/oneshot.c b/keyboards/crkbd/keymaps/hadeed/oneshot.c new file mode 100644 index 0000000..3d69c7c --- /dev/null +++ b/keyboards/crkbd/keymaps/hadeed/oneshot.c @@ -0,0 +1,59 @@ +// https://github.com/callum-oakley/qmk_firmware/tree/master/users/callum + +#include "oneshot.h" + +void update_oneshot( + oneshot_state *state, + uint16_t mod, + uint16_t trigger, + uint16_t keycode, + keyrecord_t *record +) { + if (keycode == trigger) { + if (record->event.pressed) { + // Trigger keydown + if (*state == os_up_unqueued) { + register_code(mod); + } + *state = os_down_unused; + } else { + // Trigger keyup + switch (*state) { + case os_down_unused: + // If we didn't use the mod while trigger was held, queue it. + *state = os_up_queued; + break; + case os_down_used: + // If we did use the mod while trigger was held, unregister it. + *state = os_up_unqueued; + unregister_code(mod); + break; + default: + break; + } + } + } else { + if (record->event.pressed) { + if (is_oneshot_cancel_key(keycode) && *state != os_up_unqueued) { + // Cancel oneshot on designated cancel keydown. + *state = os_up_unqueued; + unregister_code(mod); + } + } else { + if (!is_oneshot_ignored_key(keycode)) { + // On non-ignored keyup, consider the oneshot used. + switch (*state) { + case os_down_unused: + *state = os_down_used; + break; + case os_up_queued: + *state = os_up_unqueued; + unregister_code(mod); + break; + default: + break; + } + } + } + } +} diff --git a/keyboards/crkbd/keymaps/hadeed/oneshot.h b/keyboards/crkbd/keymaps/hadeed/oneshot.h new file mode 100644 index 0000000..ce5ddf7 --- /dev/null +++ b/keyboards/crkbd/keymaps/hadeed/oneshot.h @@ -0,0 +1,33 @@ +// https://github.com/callum-oakley/qmk_firmware/tree/master/users/callum + +#pragma once + +#include QMK_KEYBOARD_H + +// Represents the four states a oneshot key can be in +typedef enum { + os_up_unqueued, + os_up_queued, + os_down_unused, + os_down_used, +} oneshot_state; + +// Custom oneshot mod implementation that doesn't rely on timers. If a mod is +// used while it is held it will be unregistered on keyup as normal, otherwise +// it will be queued and only released after the next non-mod keyup. +void update_oneshot( + oneshot_state *state, + uint16_t mod, + uint16_t trigger, + uint16_t keycode, + keyrecord_t *record +); + +// To be implemented by the consumer. Defines keys to cancel oneshot mods. +bool is_oneshot_cancel_key(uint16_t keycode); + +// To be implemented by the consumer. Defines keys to ignore when determining +// whether a oneshot mod has been used. Setting this to modifiers and layer +// change keys allows stacking multiple oneshot modifiers, and carrying them +// between layers. +bool is_oneshot_ignored_key(uint16_t keycode); diff --git a/keyboards/crkbd/keymaps/hadeed/rules.mk b/keyboards/crkbd/keymaps/hadeed/rules.mk index dd0c8b4..469ec69 100644 --- a/keyboards/crkbd/keymaps/hadeed/rules.mk +++ b/keyboards/crkbd/keymaps/hadeed/rules.mk @@ -1 +1,5 @@ +SRC += oneshot.c CONVERT_TO=kb2040 + +CAPS_WORD_ENABLE = yes +REPEAT_KEY_ENABLE = yes