3 #ifdef TWSCHUM_TAPPING_CTRL_PREFIX
4 // state for the great state machine of custom actions!
5 #define TIMEOUT_DELAY 200 // ms
6 static uint16_t idle_timer;
7 static bool timeout_is_active = false;
9 static bool ctrl_shortcuts_enabled_g = false;
10 //static bool B_down = 0; // TODO just use top bit from count
11 //static int8_t B_count = 0;
13 #define N_TAPPING_CTRL_KEYS 2
14 static struct Tapping_ctrl_key_t special_keys_g[N_TAPPING_CTRL_KEYS] = {
15 {false, 0, KC_B}, {false, 0, KC_A}
18 static inline void start_idle_timer(void) {
19 idle_timer = timer_read();
20 timeout_is_active = true;
22 static inline void clear_state_after_idle_timeout(void) {
24 timeout_is_active = false;
26 // send timed out plain keys from tapping ctrl mod
27 for (int i = 0; i < N_TAPPING_CTRL_KEYS; ++i) {
28 struct Tapping_ctrl_key_t* key = special_keys_g + i;
29 repeat_send_keys(key->count, key->keycode);
34 inline void matrix_scan_user(void) {
35 if (timeout_is_active && timer_elapsed(idle_timer) > TIMEOUT_DELAY) {
36 clear_state_after_idle_timeout();
40 static inline bool tap_ctrl_event(struct Tapping_ctrl_key_t* key, keyrecord_t* record) {
41 if (!ctrl_shortcuts_enabled_g) {
42 // normal operation, just send the plain keycode
43 if (record->event.pressed) {
44 register_code(key->keycode);
47 unregister_code(key->keycode);
51 key->down = record->event.pressed;
52 // increment count and reset timer when key pressed
53 // start the timeout when released
56 timeout_is_active = false;
67 static inline bool tap_ctrl_other_pressed(void) {
68 for (int i = 0; i < N_TAPPING_CTRL_KEYS; ++i) {
69 struct Tapping_ctrl_key_t* key = special_keys_g + i;
72 // another key has been pressed while the leader key is down,
73 // so send number of ctrl-KEY combos before the other key
74 repeat_send_keys(key->count, KC_LCTL, key->keycode);
78 // another key pressed after leader key released,
79 // need to send the plain keycode plus potential mods
80 if (get_mods() & MOD_MASK_CTRL) {
81 // make sure to send a shift if prssed
82 repeat_send_keys(key->count, KC_RSHIFT, key->keycode);
85 repeat_send_keys(key->count, key->keycode);
89 return true; // will send the other keycode
92 return true; // safe default
94 #endif /* TWSCHUM_TAPPING_CTRL_PREFIX */
97 /* Use RGB underglow to indicate layer
98 * https://docs.qmk.fm/reference/customizing-functionality
100 // add to quantum/rgblight_list.h
101 #ifdef RGBLIGHT_ENABLE
102 static bool rgb_layers_enabled = true;
103 static bool rgb_L0_enabled = false;
105 layer_state_t layer_state_set_user(layer_state_t state) {
106 if (!rgb_layers_enabled) {
109 switch (get_highest_layer(state)) {
111 if (rgb_L0_enabled) {
112 rgblight_sethsv_noeeprom(_Base_HSV_ON);
115 rgblight_sethsv_noeeprom(_Base_HSV_OFF);
119 rgblight_sethsv_noeeprom(_Vim_HSV);
122 rgblight_sethsv_noeeprom(_Fn_HSV);
125 rgblight_sethsv_noeeprom(_Nav_HSV);
128 rgblight_sethsv_noeeprom(_Num_HSV);
131 rgblight_sethsv_noeeprom(_Cfg_HSV);
134 rgblight_sethsv_noeeprom(_None_HSV);
139 #endif /* RGBLIGHT_ENABLE */
141 /* process_record_vimlayer: handles the VIM_ keycodes from xtonhasvim's vim
143 * add process_record_keymap to allow specific keymap to still add keys
144 * Makes the callstack look like:
152 __attribute__ ((weak))
153 bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
157 /* Return True to continue processing keycode, false to stop further processing
158 * process_record_keymap to be call by process_record_user in the vim addon */
159 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
161 /* keymap gets first whack, then vimlayer */
162 if(!process_record_keymap(keycode, record)) return false;
163 if(!process_record_vimlayer(keycode, record)) return false;
166 /* KC_MAKE is a keycode to be used with any keymap
167 * Outputs `make <keyboard>:<keymap>`
168 * Holding shift will add the appropriate flashing command (:dfu,
169 * :teensy, :avrdude, :dfu-util) for a majority of keyboards.
170 * Holding control will add some commands that will speed up compiling
171 * time by processing multiple files at once
172 * For the boards that lack a shift key, or that you want to always
173 * attempt the flashing part, you can add FLASH_BOOTLOADER = yes to the
174 * rules.mk of that keymap.
176 case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader
177 if (!record->event.pressed) {
178 uint8_t temp_mod = get_mods();
179 uint8_t temp_osm = get_oneshot_mods();
180 clear_mods(); clear_oneshot_mods();
181 SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP);
182 #ifndef FLASH_BOOTLOADER
183 if ( (temp_mod | temp_osm) & MOD_MASK_SHIFT ) {
184 SEND_STRING(":flash");
187 if ( (temp_mod | temp_osm) & MOD_MASK_CTRL) {
188 SEND_STRING(" -j8 --output-sync");
190 SEND_STRING(SS_TAP(X_ENTER));
195 #ifdef RGBLIGHT_ENABLE
197 if (record->event.pressed) {
198 rgb_layers_enabled = !rgb_layers_enabled;
202 if (record->event.pressed) {
203 rgb_L0_enabled = !rgb_L0_enabled;
209 if (!record->event.pressed) {
210 SEND_STRING(SALT_CMD_MACRO);
214 if (!record->event.pressed) {
215 SEND_STRING(LESS_PD_MACRO);
219 if (!record->event.pressed) {
220 SEND_STRING(CODE_PASTE_MACRO);
224 #ifdef TWSCHUM_TAPPING_CTRL_PREFIX
225 case EN_CTRL_SHORTCUTS:
226 if (record->event.pressed) {
227 ctrl_shortcuts_enabled_g = !ctrl_shortcuts_enabled_g;
228 start_idle_timer(); // need to clear out state in some cases
232 return tap_ctrl_event(&special_keys_g[1], record);
234 return tap_ctrl_event(&special_keys_g[0], record);
236 if (record->event.pressed) {
237 return tap_ctrl_other_pressed();
244 #ifdef RGBLIGHT_ENABLE
245 void matrix_init_user(void) {
246 // called once on board init
251 void suspend_power_down_user(void) {
252 // TODO shut off backlighting
255 void suspend_wakeup_init_user(void) {
256 // TODO turn on backlighting