diff options
| author | Eric Gebhart <e.a.gebhart@gmail.com> | 2018-06-08 19:06:25 +0200 |
|---|---|---|
| committer | Drashna Jaelre <drashna@live.com> | 2018-06-08 10:06:25 -0700 |
| commit | 984621835d929b79a22ef33c0a4e602adb1ecc5b (patch) | |
| tree | 11637c54105b229f3127b019ff0cc962926fb770 /users/ericgebhart/ericgebhart.c | |
| parent | 03c9deb7456d84a8d8cc31496ae2736305bbafd3 (diff) | |
| download | qmk_firmware-984621835d929b79a22ef33c0a4e602adb1ecc5b.tar.gz qmk_firmware-984621835d929b79a22ef33c0a4e602adb1ecc5b.zip | |
Keyboard that works on Qwerty or Bepo OS keyboards. (#3149)
* New layout.
* new dvorak bepo layout.
* first commit of new ergodox_ez dvorak keyboard for qwerty and bepo.
Diffstat (limited to 'users/ericgebhart/ericgebhart.c')
| -rw-r--r-- | users/ericgebhart/ericgebhart.c | 637 |
1 files changed, 637 insertions, 0 deletions
diff --git a/users/ericgebhart/ericgebhart.c b/users/ericgebhart/ericgebhart.c new file mode 100644 index 000000000..69aa450e0 --- /dev/null +++ b/users/ericgebhart/ericgebhart.c | |||
| @@ -0,0 +1,637 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2018 Eric Gebhart <e.a.gebhart@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #include "ericgebhart.h" | ||
| 18 | |||
| 19 | #include "quantum.h" | ||
| 20 | #include "version.h" | ||
| 21 | #include "action.h" | ||
| 22 | #include "action_layer.h" | ||
| 23 | #include "process_keycode/process_tap_dance.h" | ||
| 24 | #include "keymap_bepo.h" | ||
| 25 | |||
| 26 | float tone_copy[][2] = SONG(SCROLL_LOCK_ON_SOUND); | ||
| 27 | float tone_paste[][2] = SONG(SCROLL_LOCK_OFF_SOUND); | ||
| 28 | |||
| 29 | static uint16_t copy_paste_timer; | ||
| 30 | userspace_config_t userspace_config; | ||
| 31 | |||
| 32 | void tap(uint16_t keycode){ register_code(keycode); unregister_code(keycode); }; | ||
| 33 | |||
| 34 | |||
| 35 | // Add reconfigurable functions here, for keymap customization | ||
| 36 | // This allows for a global, userspace functions, and continued | ||
| 37 | // customization of the keymap. Use _keymap instead of _user | ||
| 38 | // functions in the keymaps | ||
| 39 | __attribute__ ((weak)) | ||
| 40 | void matrix_init_keymap(void) {} | ||
| 41 | |||
| 42 | __attribute__ ((weak)) | ||
| 43 | void matrix_scan_keymap(void) {} | ||
| 44 | |||
| 45 | __attribute__ ((weak)) | ||
| 46 | bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { | ||
| 47 | return true; | ||
| 48 | } | ||
| 49 | |||
| 50 | __attribute__ ((weak)) | ||
| 51 | bool process_record_secrets(uint16_t keycode, keyrecord_t *record) { | ||
| 52 | return true; | ||
| 53 | } | ||
| 54 | |||
| 55 | __attribute__ ((weak)) | ||
| 56 | uint32_t layer_state_set_keymap (uint32_t state) { | ||
| 57 | return state; | ||
| 58 | } | ||
| 59 | |||
| 60 | __attribute__ ((weak)) | ||
| 61 | void led_set_keymap(uint8_t usb_led) {} | ||
| 62 | |||
| 63 | // Runs just one time when the keyboard initializes. | ||
| 64 | void matrix_init_user(void) { | ||
| 65 | //ACTION_DEFAULT_LAYER_SET(DVORAK) ; | ||
| 66 | } | ||
| 67 | |||
| 68 | // check default layerstate to see which layer we are on. | ||
| 69 | // if (biton32(layer_state) == _DIABLO) { --- current layer | ||
| 70 | // if (biton32(default_layer_state) == _DIABLO) { --- current default layer | ||
| 71 | // check for left shift on. | ||
| 72 | // if (mods & MOD_BIT(KC_LSFT)) register_code(KC_LSFT); | ||
| 73 | |||
| 74 | static void switch_default_layer(uint8_t layer) { | ||
| 75 | default_layer_set(1UL<<layer); | ||
| 76 | clear_keyboard(); | ||
| 77 | } | ||
| 78 | |||
| 79 | // so the keyboard remembers which layer it's in after power disconnect. | ||
| 80 | /* | ||
| 81 | uint32_t default_layer_state_set_kb(uint32_t state) { | ||
| 82 | eeconfig_update_default_layer(state); | ||
| 83 | return state; | ||
| 84 | } | ||
| 85 | */ | ||
| 86 | |||
| 87 | // These are the keys for dvorak on bepo. column one is the keycode and mods for | ||
| 88 | // the unshifted key, the second column is the keycode and mods for the shifted key. | ||
| 89 | // GR is Good Range. It subtracts SAFE_RANGE from the keycode so we can make a | ||
| 90 | // reasnably sized array without difficulties. The macro is for the constant declarations | ||
| 91 | // the function is for when we use it. | ||
| 92 | const uint8_t key_translations[][2][2] = { | ||
| 93 | [GR(DB_1)] = {{BP_DQOT, MOD_LSFT}, {BP_DCRC, MOD_LSFT}}, | ||
| 94 | [GR(DB_2)] = {{BP_LGIL, MOD_LSFT}, {BP_AT, MOD_NONE}}, | ||
| 95 | [GR(DB_3)] = {{BP_RGIL, MOD_LSFT}, {BP_DLR, MOD_LSFT}}, | ||
| 96 | [GR(DB_4)] = {{BP_LPRN, MOD_LSFT}, {BP_DLR, MOD_NONE}}, | ||
| 97 | [GR(DB_5)] = {{BP_RPRN, MOD_LSFT}, {BP_PERC, MOD_NONE}}, | ||
| 98 | [GR(DB_6)] = {{BP_AT, MOD_LSFT}, {BP_AT, MOD_BIT(KC_RALT)}}, | ||
| 99 | [GR(DB_7)] = {{BP_PLUS, MOD_LSFT}, {BP_P, MOD_BIT(KC_RALT)}}, | ||
| 100 | [GR(DB_8)] = {{BP_MINS, MOD_LSFT}, {BP_ASTR, MOD_NONE}}, | ||
| 101 | [GR(DB_9)] = {{BP_SLASH, MOD_LSFT}, {BP_LPRN, MOD_NONE}}, | ||
| 102 | [GR(DB_0)] = {{BP_ASTR, MOD_LSFT}, {BP_RPRN, MOD_NONE}}, | ||
| 103 | [GR(DB_GRV)] = {{BP_PERC, MOD_LSFT}, {BP_K, MOD_BIT(KC_RALT)}}, | ||
| 104 | [GR(DB_SCOLON)] = {{BP_COMM, MOD_LSFT}, {BP_DOT, MOD_LSFT}}, | ||
| 105 | [GR(DB_SLASH)] = {{BP_SLASH, MOD_NONE}, {BP_APOS, MOD_LSFT}}, | ||
| 106 | [GR(DB_BACKSLASH)] = {{BP_AGRV, MOD_BIT(KC_RALT)}, {BP_B, MOD_BIT(KC_RALT)}}, | ||
| 107 | [GR(DB_EQL)] = {{BP_EQL, MOD_NONE}, {BP_PLUS, MOD_NONE}}, | ||
| 108 | [GR(DB_COMM)] = {{BP_COMMA, MOD_NONE}, {BP_LGIL, MOD_BIT(KC_RALT)}}, | ||
| 109 | [GR(DB_DOT)] = {{BP_DOT, MOD_NONE}, {BP_RGIL, MOD_BIT(KC_RALT)}}, | ||
| 110 | [GR(DB_QUOT)] = {{BP_APOS, MOD_NONE}, {BP_DQOT, MOD_NONE}}, | ||
| 111 | [GR(DB_MINUS)] = {{BP_MINUS, MOD_NONE}, {KC_SPC, MOD_BIT(KC_RALT)}}, | ||
| 112 | [GR(DB_LPRN)] = {{BP_LPRN, MOD_NONE}, {BP_LPRN, MOD_BIT(KC_RALT)}}, | ||
| 113 | [GR(DB_RPRN)] = {{BP_RPRN, MOD_NONE}, {BP_RPRN, MOD_BIT(KC_RALT)}}, | ||
| 114 | [GR(DB_LBRC)] = {{BP_Y, MOD_BIT(KC_RALT)}, {BP_LPRN, MOD_BIT(KC_RALT)}}, | ||
| 115 | [GR(DB_RBRC)] = {{BP_X, MOD_BIT(KC_RALT)}, {BP_RPRN, MOD_BIT(KC_RALT)}}, | ||
| 116 | // For the symbol layer | ||
| 117 | [GR(DB_HASH)] = {{BP_DLR, MOD_LSFT}, {BP_DLR, MOD_LSFT}}, | ||
| 118 | [GR(DB_LCBR)] = {{BP_LPRN, MOD_BIT(KC_RALT)}, {BP_LPRN, MOD_BIT(KC_RALT)}}, | ||
| 119 | [GR(DB_RCBR)] = {{BP_LPRN, MOD_BIT(KC_RALT)}, {BP_RPRN, MOD_BIT(KC_RALT)}}, | ||
| 120 | [GR(DB_PIPE)] = {{BP_B, MOD_BIT(KC_RALT)}, {BP_B, MOD_BIT(KC_RALT)}}, | ||
| 121 | [GR(DB_TILD)] = {{BP_K, MOD_BIT(KC_RALT)}, {BP_K, MOD_BIT(KC_RALT)}}, | ||
| 122 | [GR(DB_CIRC)] = {{BP_AT, MOD_BIT(KC_RALT)}, {BP_AT, MOD_BIT(KC_RALT)}}, | ||
| 123 | [GR(DB_LESS)] = {{BP_LGIL, MOD_BIT(KC_RALT)}, {BP_LGIL, MOD_BIT(KC_RALT)}}, | ||
| 124 | [GR(DB_GRTR)] = {{BP_RGIL, MOD_BIT(KC_RALT)}, {BP_RGIL, MOD_BIT(KC_RALT)}}, | ||
| 125 | |||
| 126 | |||
| 127 | }; | ||
| 128 | |||
| 129 | |||
| 130 | uint8_t gr(uint8_t kc){ | ||
| 131 | return (kc - SAFE_RANGE); | ||
| 132 | } | ||
| 133 | // send the right keycode for the right mod. | ||
| 134 | // remove the mods we are taking care of, | ||
| 135 | // send our keycodes then restore them. | ||
| 136 | // all so we can make dvorak keys from bepo keycodes. | ||
| 137 | void send_keycode(uint8_t kc){ | ||
| 138 | uint8_t tmp_mods = get_mods(); | ||
| 139 | bool is_shifted = ( tmp_mods & (MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT)) ); | ||
| 140 | //uint8_t key[2][2] = key_translations[GR(kc)]; | ||
| 141 | // need to turn of the shift if it is on. | ||
| 142 | unregister_mods((MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT))); | ||
| 143 | if(is_shifted){ | ||
| 144 | register_mods(SHIFTED_MODS(kc)); | ||
| 145 | register_code(SHIFTED_KEY(kc)); | ||
| 146 | unregister_code(SHIFTED_KEY(kc)); | ||
| 147 | unregister_mods(SHIFTED_MODS(kc)); | ||
| 148 | } else{ | ||
| 149 | register_mods(UNSHIFTED_MODS(kc)); | ||
| 150 | register_code(UNSHIFTED_KEY(kc)); | ||
| 151 | unregister_code(UNSHIFTED_KEY(kc)); | ||
| 152 | unregister_mods(UNSHIFTED_MODS(kc)); | ||
| 153 | } | ||
| 154 | clear_mods(); | ||
| 155 | register_mods(tmp_mods); | ||
| 156 | } | ||
| 157 | |||
| 158 | |||
| 159 | bool process_record_user(uint16_t keycode, keyrecord_t *record) { | ||
| 160 | |||
| 161 | // If console is enabled, it will print the matrix position and status of each key pressed | ||
| 162 | #ifdef KEYLOGGER_ENABLE | ||
| 163 | xprintf("KL: row: %u, column: %u, pressed: %u\n", record->event.key.col, record->event.key.row, record->event.pressed); | ||
| 164 | #endif //KEYLOGGER_ENABLE | ||
| 165 | |||
| 166 | // still dont know how to make #&_ And RALT is not ALTGR, That isn't working in the bepo keyboard | ||
| 167 | // either. No {} either probably for the same reasons. ALtGR is the key to some of these. | ||
| 168 | switch (keycode) { | ||
| 169 | // Handle the key translations for Dvorak on bepo. It's best if these are the first | ||
| 170 | // enums after SAFE_RANGE. | ||
| 171 | case DB_1: | ||
| 172 | case DB_2: | ||
| 173 | case DB_3: | ||
| 174 | case DB_4: | ||
| 175 | case DB_5: | ||
| 176 | case DB_6: | ||
| 177 | case DB_7: | ||
| 178 | case DB_8: | ||
| 179 | case DB_9: | ||
| 180 | case DB_0: | ||
| 181 | case DB_GRV: | ||
| 182 | case DB_SCOLON: | ||
| 183 | case DB_SLASH: | ||
| 184 | case DB_BACKSLASH: | ||
| 185 | case DB_EQL: | ||
| 186 | case DB_DOT: | ||
| 187 | case DB_COMM: | ||
| 188 | case DB_QUOT: | ||
| 189 | case DB_MINUS: | ||
| 190 | case DB_LPRN: | ||
| 191 | case DB_RPRN: | ||
| 192 | case DB_LBRC: | ||
| 193 | case DB_RBRC: | ||
| 194 | if(record->event.pressed) | ||
| 195 | send_keycode(keycode); | ||
| 196 | unregister_code(keycode); | ||
| 197 | break; | ||
| 198 | |||
| 199 | case KC_QWERTY: | ||
| 200 | if (record->event.pressed) { | ||
| 201 | set_single_persistent_default_layer(QWERTY); | ||
| 202 | } | ||
| 203 | return false; | ||
| 204 | break; | ||
| 205 | case KC_COLEMAK: | ||
| 206 | if (record->event.pressed) { | ||
| 207 | set_single_persistent_default_layer(COLEMAK); | ||
| 208 | } | ||
| 209 | return false; | ||
| 210 | break; | ||
| 211 | case KC_DVORAK: | ||
| 212 | if (record->event.pressed) { | ||
| 213 | set_single_persistent_default_layer(DVORAK); | ||
| 214 | } | ||
| 215 | return false; | ||
| 216 | break; | ||
| 217 | case KC_WORKMAN: | ||
| 218 | if (record->event.pressed) { | ||
| 219 | set_single_persistent_default_layer(WORKMAN); | ||
| 220 | } | ||
| 221 | return false; | ||
| 222 | break; | ||
| 223 | |||
| 224 | case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader | ||
| 225 | if (!record->event.pressed) { | ||
| 226 | SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP | ||
| 227 | #if (defined(BOOTLOADER_DFU) || defined(BOOTLOADER_LUFA_DFU) || defined(BOOTLOADER_QMK_DFU)) | ||
| 228 | ":dfu" | ||
| 229 | #elif defined(BOOTLOADER_HALFKAY) | ||
| 230 | ":teensy" | ||
| 231 | #elif defined(BOOTLOADER_CATERINA) | ||
| 232 | ":avrdude" | ||
| 233 | #endif // bootloader options | ||
| 234 | SS_TAP(X_ENTER)); | ||
| 235 | } | ||
| 236 | return false; | ||
| 237 | break; | ||
| 238 | |||
| 239 | |||
| 240 | case KC_RESET: // Custom RESET code | ||
| 241 | if (!record->event.pressed) { | ||
| 242 | reset_keyboard(); | ||
| 243 | } | ||
| 244 | return false; | ||
| 245 | break; | ||
| 246 | |||
| 247 | |||
| 248 | case EPRM: // Resets EEPROM | ||
| 249 | if (record->event.pressed) { | ||
| 250 | eeconfig_init(); | ||
| 251 | default_layer_set(1UL<<eeconfig_read_default_layer()); | ||
| 252 | layer_state_set(layer_state); | ||
| 253 | } | ||
| 254 | return false; | ||
| 255 | break; | ||
| 256 | case VRSN: // Prints firmware version | ||
| 257 | if (record->event.pressed) { | ||
| 258 | SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE); | ||
| 259 | } | ||
| 260 | return false; | ||
| 261 | break; | ||
| 262 | |||
| 263 | /* Code has been depreciated | ||
| 264 | case KC_SECRET_1 ... KC_SECRET_5: // Secrets! Externally defined strings, not stored in repo | ||
| 265 | if (!record->event.pressed) { | ||
| 266 | clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); | ||
| 267 | send_string(decoy_secret[keycode - KC_SECRET_1]); | ||
| 268 | } | ||
| 269 | return false; | ||
| 270 | break; | ||
| 271 | */ | ||
| 272 | |||
| 273 | // These are a serious of gaming macros. | ||
| 274 | // Only enables for the viterbi, basically, | ||
| 275 | // to save on firmware space, since it's limited. | ||
| 276 | #ifdef MACROS_ENABLED | ||
| 277 | case KC_OVERWATCH: // Toggle's if we hit "ENTER" or "BACKSPACE" to input macros | ||
| 278 | if (record->event.pressed) { userspace_config.is_overwatch ^= 1; eeprom_update_byte(EECONFIG_USERSPACE, userspace_config.raw); } | ||
| 279 | return false; break; | ||
| 280 | #endif // MACROS_ENABLED | ||
| 281 | |||
| 282 | case KC_CCCV: // One key copy/paste | ||
| 283 | if(record->event.pressed){ | ||
| 284 | copy_paste_timer = timer_read(); | ||
| 285 | } else { | ||
| 286 | if (timer_elapsed(copy_paste_timer) > TAPPING_TERM) { // Hold, copy | ||
| 287 | register_code(KC_LCTL); | ||
| 288 | tap(KC_C); | ||
| 289 | unregister_code(KC_LCTL); | ||
| 290 | #ifdef AUDIO_ENABLE | ||
| 291 | PLAY_SONG(tone_copy); | ||
| 292 | #endif | ||
| 293 | } else { // Tap, paste | ||
| 294 | register_code(KC_LCTL); | ||
| 295 | tap(KC_V); | ||
| 296 | unregister_code(KC_LCTL); | ||
| 297 | #ifdef AUDIO_ENABLE | ||
| 298 | PLAY_SONG(tone_paste); | ||
| 299 | #endif | ||
| 300 | } | ||
| 301 | } | ||
| 302 | return false; | ||
| 303 | break; | ||
| 304 | case CLICKY_TOGGLE: | ||
| 305 | #ifdef AUDIO_CLICKY | ||
| 306 | userspace_config.clicky_enable = clicky_enable; | ||
| 307 | eeprom_update_byte(EECONFIG_USERSPACE, userspace_config.raw); | ||
| 308 | #endif | ||
| 309 | break; | ||
| 310 | #ifdef UNICODE_ENABLE | ||
| 311 | case UC_FLIP: // (╯°□°)╯ ︵ ┻━┻ | ||
| 312 | if (record->event.pressed) { | ||
| 313 | register_code(KC_RSFT); | ||
| 314 | tap(KC_9); | ||
| 315 | unregister_code(KC_RSFT); | ||
| 316 | process_unicode((0x256F | QK_UNICODE), record); // Arm | ||
| 317 | process_unicode((0x00B0 | QK_UNICODE), record); // Eye | ||
| 318 | process_unicode((0x25A1 | QK_UNICODE), record); // Mouth | ||
| 319 | process_unicode((0x00B0 | QK_UNICODE), record); // Eye | ||
| 320 | register_code(KC_RSFT); | ||
| 321 | tap(KC_0); | ||
| 322 | unregister_code(KC_RSFT); | ||
| 323 | process_unicode((0x256F | QK_UNICODE), record); // Arm | ||
| 324 | tap(KC_SPC); | ||
| 325 | process_unicode((0x0361 | QK_UNICODE), record); // Flippy | ||
| 326 | tap(KC_SPC); | ||
| 327 | process_unicode((0x253B | QK_UNICODE), record); // Table | ||
| 328 | process_unicode((0x2501 | QK_UNICODE), record); // Table | ||
| 329 | process_unicode((0x253B | QK_UNICODE), record); // Table | ||
| 330 | } | ||
| 331 | return false; | ||
| 332 | break; | ||
| 333 | #endif // UNICODE_ENABLE | ||
| 334 | |||
| 335 | } | ||
| 336 | |||
| 337 | return true; | ||
| 338 | // return process_record_keymap(keycode, record) && process_record_secrets(keycode, record); | ||
| 339 | } | ||
| 340 | |||
| 341 | void tap_dance_mouse_btns (qk_tap_dance_state_t *state, void *user_data) { | ||
| 342 | switch(state->count){ | ||
| 343 | case 1: | ||
| 344 | register_code(KC_BTN1); | ||
| 345 | break; | ||
| 346 | case 2: | ||
| 347 | register_code(KC_BTN2); | ||
| 348 | break; | ||
| 349 | case 3: | ||
| 350 | register_code(KC_BTN3); | ||
| 351 | break; | ||
| 352 | case 4: | ||
| 353 | register_code(KC_BTN4); | ||
| 354 | break; | ||
| 355 | case 5: | ||
| 356 | register_code(KC_BTN5); | ||
| 357 | break; | ||
| 358 | default: | ||
| 359 | break; | ||
| 360 | } | ||
| 361 | reset_tap_dance(state); | ||
| 362 | } | ||
| 363 | |||
| 364 | // counting on all the qwerty layers to be less than dvorak_on_bepo | ||
| 365 | int on_qwerty(){ | ||
| 366 | uint8_t deflayer = (biton32(default_layer_state)); | ||
| 367 | return (deflayer < DVORAK_ON_BEPO); | ||
| 368 | } | ||
| 369 | |||
| 370 | void tap_dance_df_bepo_layers_switch (qk_tap_dance_state_t *state, void *user_data) { | ||
| 371 | switch(state->count){ | ||
| 372 | case 1: | ||
| 373 | switch_default_layer(DVORAK_ON_BEPO); | ||
| 374 | break; | ||
| 375 | case 2: | ||
| 376 | switch_default_layer(BEPO); | ||
| 377 | break; | ||
| 378 | case 3: | ||
| 379 | layer_invert(LAYERS); | ||
| 380 | break; | ||
| 381 | default: | ||
| 382 | break; | ||
| 383 | } | ||
| 384 | reset_tap_dance(state); | ||
| 385 | } | ||
| 386 | |||
| 387 | void tap_dance_layer_switch (qk_tap_dance_state_t *state, void *user_data) { | ||
| 388 | switch(state->count){ | ||
| 389 | case 1: | ||
| 390 | if(on_qwerty()) | ||
| 391 | layer_invert(SYMB); | ||
| 392 | else | ||
| 393 | layer_invert(SYMB_ON_BEPO); | ||
| 394 | break; | ||
| 395 | case 2: | ||
| 396 | layer_invert(MDIA); | ||
| 397 | break; | ||
| 398 | case 3: | ||
| 399 | layer_invert(LAYERS); | ||
| 400 | default: | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | reset_tap_dance(state); | ||
| 404 | } | ||
| 405 | |||
| 406 | void tap_dance_default_layer_switch (qk_tap_dance_state_t *state, void *user_data) { | ||
| 407 | switch(state->count){ | ||
| 408 | case 1: | ||
| 409 | switch_default_layer(DVORAK); | ||
| 410 | break; | ||
| 411 | case 2: | ||
| 412 | switch_default_layer(DVORAK_ON_BEPO); | ||
| 413 | break; | ||
| 414 | case 3: | ||
| 415 | switch_default_layer(BEPO); | ||
| 416 | break; | ||
| 417 | default: | ||
| 418 | break; | ||
| 419 | } | ||
| 420 | reset_tap_dance(state); | ||
| 421 | } | ||
| 422 | |||
| 423 | // switch the default layer to another qwerty based layer. | ||
| 424 | void switch_default_layer_on_qwerty(int count) { | ||
| 425 | switch(count){ | ||
| 426 | case 1: | ||
| 427 | switch_default_layer(DVORAK); | ||
| 428 | break; | ||
| 429 | case 2: | ||
| 430 | switch_default_layer(QWERTY); | ||
| 431 | break; | ||
| 432 | case 3: | ||
| 433 | switch_default_layer(COLEMAK); | ||
| 434 | break; | ||
| 435 | case 4: | ||
| 436 | switch_default_layer(WORKMAN); | ||
| 437 | break; | ||
| 438 | case 5: | ||
| 439 | switch_default_layer(NORMAN); | ||
| 440 | break; | ||
| 441 | default: | ||
| 442 | switch_default_layer(DVORAK); | ||
| 443 | break; | ||
| 444 | } | ||
| 445 | } | ||
| 446 | |||
| 447 | // switch the default layer to another bepo based layer. | ||
| 448 | void switch_default_layer_on_bepo(int count) { | ||
| 449 | switch(count){ | ||
| 450 | case 1: | ||
| 451 | switch_default_layer(DVORAK_ON_BEPO); | ||
| 452 | break; | ||
| 453 | case 2: | ||
| 454 | switch_default_layer(BEPO); | ||
| 455 | break; | ||
| 456 | default: | ||
| 457 | switch_default_layer(DVORAK_ON_BEPO); | ||
| 458 | break; | ||
| 459 | } | ||
| 460 | } | ||
| 461 | |||
| 462 | |||
| 463 | // tap to change the default layer. Distinguishes between layers that are based on | ||
| 464 | // a qwerty software keyboard and a bepo software keyboard. | ||
| 465 | // if shifted, choose layers based on the other software keyboard, otherwise choose only | ||
| 466 | // layers that work on the current software keyboard. | ||
| 467 | void tap_dance_default_os_layer_switch (qk_tap_dance_state_t *state, void *user_data) { | ||
| 468 | //uint8_t shifted = (get_mods() & MOD_BIT(KC_LSFT|KC_RSFT)); | ||
| 469 | bool shifted = ( keyboard_report->mods & (MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT)) ); | ||
| 470 | int qwerty = on_qwerty(); | ||
| 471 | |||
| 472 | |||
| 473 | // shifted, choose between layers on the other software keyboard | ||
| 474 | if(shifted){ | ||
| 475 | if (qwerty) | ||
| 476 | switch_default_layer_on_bepo(state->count); | ||
| 477 | else | ||
| 478 | switch_default_layer_on_qwerty(state->count); | ||
| 479 | |||
| 480 | // not shifted, choose between layers on the same software keyboard | ||
| 481 | } else { | ||
| 482 | if (qwerty) | ||
| 483 | switch_default_layer_on_qwerty(state->count); | ||
| 484 | else | ||
| 485 | switch_default_layer_on_bepo(state->count); | ||
| 486 | } | ||
| 487 | |||
| 488 | reset_tap_dance(state); | ||
| 489 | } | ||
| 490 | |||
| 491 | |||
| 492 | /* Return an integer that corresponds to what kind of tap dance should be executed. | ||
| 493 | * | ||
| 494 | * How to figure out tap dance state: interrupted and pressed. | ||
| 495 | * | ||
| 496 | * Interrupted: If the state of a dance dance is "interrupted", that means that another key has been hit | ||
| 497 | * under the tapping term. This is typically indicitive that you are trying to "tap" the key. | ||
| 498 | * | ||
| 499 | * Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term | ||
| 500 | * has ended, but the key is still being pressed down. This generally means the key is being "held". | ||
| 501 | * | ||
| 502 | * One thing that is currenlty not possible with qmk software in regards to tap dance is to mimic the "permissive hold" | ||
| 503 | * feature. In general, advanced tap dances do not work well if they are used with commonly typed letters. | ||
| 504 | * For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters. | ||
| 505 | * | ||
| 506 | * Good places to put an advanced tap dance: | ||
| 507 | * z,q,x,j,k,v,b, any function key, home/end, comma, semi-colon | ||
| 508 | * | ||
| 509 | * Criteria for "good placement" of a tap dance key: | ||
| 510 | * Not a key that is hit frequently in a sentence | ||
| 511 | * Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or | ||
| 512 | * in a web form. So 'tab' would be a poor choice for a tap dance. | ||
| 513 | * Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the | ||
| 514 | * letter 'p', the word 'pepper' would be quite frustating to type. | ||
| 515 | * | ||
| 516 | * For the third point, there does exist the 'DOUBLE_SINGLE_TAP', however this is not fully tested | ||
| 517 | * | ||
| 518 | */ | ||
| 519 | int cur_dance (qk_tap_dance_state_t *state) { | ||
| 520 | if (state->count == 1) { | ||
| 521 | if (state->interrupted || !state->pressed) return SINGLE_TAP; | ||
| 522 | //key has not been interrupted, but they key is still held. Means you want to send a 'HOLD'. | ||
| 523 | else return SINGLE_HOLD; | ||
| 524 | } | ||
| 525 | else if (state->count == 2) { | ||
| 526 | /* | ||
| 527 | * DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap | ||
| 528 | * action when hitting 'pp'. Suggested use case for this return value is when you want to send two | ||
| 529 | * keystrokes of the key, and not the 'double tap' action/macro. | ||
| 530 | */ | ||
| 531 | if (state->interrupted) return DOUBLE_SINGLE_TAP; | ||
| 532 | else if (state->pressed) return DOUBLE_HOLD; | ||
| 533 | else return DOUBLE_TAP; | ||
| 534 | } | ||
| 535 | //Assumes no one is trying to type the same letter three times (at least not quickly). | ||
| 536 | //If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add | ||
| 537 | //an exception here to return a 'TRIPLE_SINGLE_TAP', and define that enum just like 'DOUBLE_SINGLE_TAP' | ||
| 538 | if (state->count == 3) { | ||
| 539 | if (state->interrupted || !state->pressed) return TRIPLE_TAP; | ||
| 540 | else return TRIPLE_HOLD; | ||
| 541 | } | ||
| 542 | else return 8; //magic number. At some point this method will expand to work for more presses | ||
| 543 | } | ||
| 544 | //instanalize an instance of 'tap' for the 'x' tap dance. | ||
| 545 | static tdtap xtap_state = { | ||
| 546 | .is_press_action = true, | ||
| 547 | .state = 0 | ||
| 548 | }; | ||
| 549 | /* | ||
| 550 | This so I can have a single key that acts like LGUI in DVORAK no | ||
| 551 | matter which keymap is my current default. | ||
| 552 | It also allows for the | ||
| 553 | shift gui and ctl gui, on the same key, So the same key is Escape, | ||
| 554 | and the mostcommon modifiers in my xmonad control keymap, while also | ||
| 555 | insuring that dvorak is active for the xmonad command key | ||
| 556 | Single tap = ESC | ||
| 557 | tap and hold = dvorak with L_GUI | ||
| 558 | double tap = One shot dvorak layer with LSFT LGUI mods | ||
| 559 | double hold = dvorak with LCTL LGUI | ||
| 560 | double single tap = esc. | ||
| 561 | */ | ||
| 562 | int get_xmonad_layer(){ | ||
| 563 | int qwerty = on_qwerty(); | ||
| 564 | |||
| 565 | if (qwerty) | ||
| 566 | return(XMONAD); | ||
| 567 | else | ||
| 568 | return(XMONAD_FR); | ||
| 569 | } | ||
| 570 | |||
| 571 | |||
| 572 | void x_finished (qk_tap_dance_state_t *state, void *user_data) { | ||
| 573 | int xmonad_layer = get_xmonad_layer(); | ||
| 574 | xtap_state.state = cur_dance(state); | ||
| 575 | switch (xtap_state.state) { | ||
| 576 | case SINGLE_TAP: | ||
| 577 | register_code(KC_ESC); | ||
| 578 | break; | ||
| 579 | case SINGLE_HOLD: | ||
| 580 | layer_on(xmonad_layer); | ||
| 581 | set_oneshot_mods (MOD_LGUI); | ||
| 582 | //set_oneshot_layer (DVORAK, ONESHOT_START); | ||
| 583 | break; | ||
| 584 | case DOUBLE_TAP: | ||
| 585 | set_oneshot_mods ((MOD_LCTL | MOD_LGUI)); | ||
| 586 | layer_on (xmonad_layer); | ||
| 587 | set_oneshot_layer (xmonad_layer, ONESHOT_START); | ||
| 588 | break; | ||
| 589 | case DOUBLE_HOLD: | ||
| 590 | set_oneshot_mods (MOD_LSFT | MOD_LGUI); | ||
| 591 | if (xmonad_layer != -1) | ||
| 592 | layer_on(xmonad_layer); | ||
| 593 | break; | ||
| 594 | case DOUBLE_SINGLE_TAP: | ||
| 595 | register_code(KC_ESC); | ||
| 596 | unregister_code(KC_ESC); | ||
| 597 | register_code(KC_ESC); | ||
| 598 | //Last case is for fast typing. Assuming your key is `f`: | ||
| 599 | //For example, when typing the word `buffer`, and you want to make sure that you send `ff` and not `Esc`. | ||
| 600 | //In order to type `ff` when typing fast, the next character will have to be hit within the `TAPPING_TERM`, which by default is 200ms. | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 604 | void x_reset (qk_tap_dance_state_t *state, void *user_data) { | ||
| 605 | int xmonad_layer = get_xmonad_layer(); | ||
| 606 | switch (xtap_state.state) { | ||
| 607 | case SINGLE_TAP: | ||
| 608 | unregister_code(KC_ESC); | ||
| 609 | break; | ||
| 610 | case SINGLE_HOLD: | ||
| 611 | layer_off(xmonad_layer); | ||
| 612 | break; | ||
| 613 | case DOUBLE_TAP: | ||
| 614 | set_oneshot_layer (xmonad_layer, ONESHOT_PRESSED); | ||
| 615 | break; | ||
| 616 | case DOUBLE_HOLD: | ||
| 617 | layer_off(xmonad_layer); | ||
| 618 | break; | ||
| 619 | case DOUBLE_SINGLE_TAP: | ||
| 620 | unregister_code(KC_ESC); | ||
| 621 | } | ||
| 622 | xtap_state.state = 0; | ||
| 623 | } | ||
| 624 | |||
| 625 | //Tap Dance Definitions | ||
| 626 | qk_tap_dance_action_t tap_dance_actions[] = { | ||
| 627 | //Tap once for Esc, twice for Caps Lock | ||
| 628 | [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS), | ||
| 629 | [TD_TAB_BKTAB] = ACTION_TAP_DANCE_DOUBLE(KC_TAB, LSFT(KC_TAB)), | ||
| 630 | [TD_MDIA_SYMB] = ACTION_TAP_DANCE_FN(tap_dance_layer_switch), | ||
| 631 | [TD_DVORAK_BEPO] = ACTION_TAP_DANCE_FN(tap_dance_df_bepo_layers_switch), | ||
| 632 | [TD_DEF_LAYER_SW] = ACTION_TAP_DANCE_FN(tap_dance_default_layer_switch), | ||
| 633 | [TD_DEF_OS_LAYER_SW] = ACTION_TAP_DANCE_FN(tap_dance_default_os_layer_switch), | ||
| 634 | [TD_HOME_END] = ACTION_TAP_DANCE_DOUBLE(KC_HOME, KC_END), | ||
| 635 | [TD_XMONAD_ESC] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset), | ||
| 636 | [TD_MOUSE_BTNS] = ACTION_TAP_DANCE_FN(tap_dance_mouse_btns) | ||
| 637 | }; | ||
