diff options
Diffstat (limited to 'users/twschum/twschum.c')
-rw-r--r-- | users/twschum/twschum.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/users/twschum/twschum.c b/users/twschum/twschum.c new file mode 100644 index 000000000..2d34f9571 --- /dev/null +++ b/users/twschum/twschum.c @@ -0,0 +1,257 @@ +#include "twschum.h" + +#ifdef TWSCHUM_TAPPING_CTRL_PREFIX +// state for the great state machine of custom actions! +#define TIMEOUT_DELAY 200 // ms +static uint16_t idle_timer; +static bool timeout_is_active = false; + +static bool ctrl_shortcuts_enabled_g = false; +//static bool B_down = 0; // TODO just use top bit from count +//static int8_t B_count = 0; + +#define N_TAPPING_CTRL_KEYS 2 +static struct Tapping_ctrl_key_t special_keys_g[N_TAPPING_CTRL_KEYS] = { + {false, 0, KC_B}, {false, 0, KC_A} +}; + +static inline void start_idle_timer(void) { + idle_timer = timer_read(); + timeout_is_active = true; +} +static inline void clear_state_after_idle_timeout(void) { + idle_timer = 0; + timeout_is_active = false; + + // send timed out plain keys from tapping ctrl mod + for (int i = 0; i < N_TAPPING_CTRL_KEYS; ++i) { + struct Tapping_ctrl_key_t* key = special_keys_g + i; + repeat_send_keys(key->count, key->keycode); + key->count = 0; + } +} + +inline void matrix_scan_user(void) { + if (timeout_is_active && timer_elapsed(idle_timer) > TIMEOUT_DELAY) { + clear_state_after_idle_timeout(); + } +} + +static inline bool tap_ctrl_event(struct Tapping_ctrl_key_t* key, keyrecord_t* record) { + if (!ctrl_shortcuts_enabled_g) { + // normal operation, just send the plain keycode + if (record->event.pressed) { + register_code(key->keycode); + } + else { + unregister_code(key->keycode); + } + return false; + } + key->down = record->event.pressed; + // increment count and reset timer when key pressed + // start the timeout when released + if (key->down) { + ++(key->count); + timeout_is_active = false; + idle_timer = 0; + } + else { + if (key->count) { + start_idle_timer(); + } + } + return false; +} + +static inline bool tap_ctrl_other_pressed(void) { + for (int i = 0; i < N_TAPPING_CTRL_KEYS; ++i) { + struct Tapping_ctrl_key_t* key = special_keys_g + i; + if (key->count) { + if (key->down) { + // another key has been pressed while the leader key is down, + // so send number of ctrl-KEY combos before the other key + repeat_send_keys(key->count, KC_LCTL, key->keycode); + key->count = 0; + } + else { + // another key pressed after leader key released, + // need to send the plain keycode plus potential mods + if (get_mods() & MOD_MASK_CTRL) { + // make sure to send a shift if prssed + repeat_send_keys(key->count, KC_RSHIFT, key->keycode); + } + else { + repeat_send_keys(key->count, key->keycode); + } + key->count = 0; + } + return true; // will send the other keycode + } + } + return true; // safe default +} +#endif /* TWSCHUM_TAPPING_CTRL_PREFIX */ + + +/* Use RGB underglow to indicate layer + * https://docs.qmk.fm/reference/customizing-functionality + */ +// add to quantum/rgblight_list.h +#ifdef RGBLIGHT_ENABLE +static bool rgb_layers_enabled = true; +static bool rgb_L0_enabled = false; + +layer_state_t layer_state_set_user(layer_state_t state) { + if (!rgb_layers_enabled) { + return state; + } + switch (get_highest_layer(state)) { + case _Base: + if (rgb_L0_enabled) { + rgblight_sethsv_noeeprom(_Base_HSV_ON); + } + else { + rgblight_sethsv_noeeprom(_Base_HSV_OFF); + } + break; + case _Vim: + rgblight_sethsv_noeeprom(_Vim_HSV); + break; + case _Fn: + rgblight_sethsv_noeeprom(_Fn_HSV); + break; + case _Nav: + rgblight_sethsv_noeeprom(_Nav_HSV); + break; + case _Num: + rgblight_sethsv_noeeprom(_Num_HSV); + break; + case _Cfg: + rgblight_sethsv_noeeprom(_Cfg_HSV); + break; + case _None: + rgblight_sethsv_noeeprom(_None_HSV); + break; + } + return state; +} +#endif /* RGBLIGHT_ENABLE */ + +/* process_record_vimlayer: handles the VIM_ keycodes from xtonhasvim's vim + * emulation layer + * add process_record_keymap to allow specific keymap to still add keys + * Makes the callstack look like: + * process_record_ + * _quantum + * _kb + * _user + * _keymap + * _vimlayer + */ +__attribute__ ((weak)) +bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { + return true; +} + +/* Return True to continue processing keycode, false to stop further processing + * process_record_keymap to be call by process_record_user in the vim addon */ +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + + /* keymap gets first whack, then vimlayer */ + if(!process_record_keymap(keycode, record)) return false; + if(!process_record_vimlayer(keycode, record)) return false; + + switch (keycode) { + /* KC_MAKE is a keycode to be used with any keymap + * Outputs `make <keyboard>:<keymap>` + * Holding shift will add the appropriate flashing command (:dfu, + * :teensy, :avrdude, :dfu-util) for a majority of keyboards. + * Holding control will add some commands that will speed up compiling + * time by processing multiple files at once + * For the boards that lack a shift key, or that you want to always + * attempt the flashing part, you can add FLASH_BOOTLOADER = yes to the + * rules.mk of that keymap. + */ + case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader + if (!record->event.pressed) { + uint8_t temp_mod = get_mods(); + uint8_t temp_osm = get_oneshot_mods(); + clear_mods(); clear_oneshot_mods(); + SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP); + #ifndef FLASH_BOOTLOADER + if ( (temp_mod | temp_osm) & MOD_MASK_SHIFT ) { + SEND_STRING(":flash"); + } + #endif + if ( (temp_mod | temp_osm) & MOD_MASK_CTRL) { + SEND_STRING(" -j8 --output-sync"); + } + SEND_STRING(SS_TAP(X_ENTER)); + set_mods(temp_mod); + } + break; + + #ifdef RGBLIGHT_ENABLE + case TG_LAYER_RGB: + if (record->event.pressed) { + rgb_layers_enabled = !rgb_layers_enabled; + } + return false; + case TG_L0_RGB: + if (record->event.pressed) { + rgb_L0_enabled = !rgb_L0_enabled; + } + return false; + #endif + + case SALT_CMD: + if (!record->event.pressed) { + SEND_STRING(SALT_CMD_MACRO); + } + return false; + case LESS_PD: + if (!record->event.pressed) { + SEND_STRING(LESS_PD_MACRO); + } + return false; + case CODE_PASTE: + if (!record->event.pressed) { + SEND_STRING(CODE_PASTE_MACRO); + } + return false; + + #ifdef TWSCHUM_TAPPING_CTRL_PREFIX + case EN_CTRL_SHORTCUTS: + if (record->event.pressed) { + ctrl_shortcuts_enabled_g = !ctrl_shortcuts_enabled_g; + start_idle_timer(); // need to clear out state in some cases + } + return false; + case CTRL_A: + return tap_ctrl_event(&special_keys_g[1], record); + case CTRL_B: + return tap_ctrl_event(&special_keys_g[0], record); + default: + if (record->event.pressed) { + return tap_ctrl_other_pressed(); + } + #endif + } + return true; +} + +#ifdef RGBLIGHT_ENABLE +void matrix_init_user(void) { + // called once on board init + rgblight_enable(); +} +#endif + +void suspend_power_down_user(void) { + // TODO shut off backlighting +} + +void suspend_wakeup_init_user(void) { + // TODO turn on backlighting +} |