keymap.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /* Copyright 2022 PHSC138
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include QMK_KEYBOARD_H
  17. // These are all aliases for the function layers.
  18. enum custom_layers {
  19. _BASE,
  20. _PROG,
  21. _GAME,
  22. _FN,
  23. _FN1,
  24. _NUM
  25. };
  26. // Tap Dance
  27. typedef struct {
  28. char is_press_action;
  29. int state;
  30. } tap;
  31. enum {
  32. SINGLE_TAP = 1,
  33. SINGLE_HOLD = 2,
  34. DOUBLE_TAP = 3,
  35. DOUBLE_HOLD = 4,
  36. DOUBLE_SINGLE_TAP = 5, // Send two single taps
  37. TRIPLE_TAP = 6,
  38. TRIPLE_HOLD = 7
  39. };
  40. // Tap dance enums
  41. enum {
  42. PN_SWAP = 0,
  43. LAPO = 1,
  44. LCPO = 2,
  45. RAPC = 3,
  46. RCPC = 4,
  47. D20 = 5
  48. };
  49. enum custom_keycodes {
  50. PROF_MAC = QK_USER
  51. };
  52. uint8_t cur_dance (tap_dance_state_t *state);
  53. void pn_finished (tap_dance_state_t *state, void *user_data);
  54. void pn_reset (tap_dance_state_t *state, void *user_data);
  55. const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  56. // TREE: 'pn' to enter custom layers:
  57. // _BASE
  58. // _FN
  59. // _FN1
  60. // _NUM
  61. // _PROG
  62. // _PROG
  63. // _FN
  64. // _FN1
  65. // _NUM
  66. // _GAME
  67. // _GAME
  68. // _BASE
  69. // Tap pn for toggle to _PROG, or hold for numpad
  70. [_BASE] = LAYOUT_split_space(
  71. QK_GESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, KC_BSPC,
  72. KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT,
  73. KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_RSFT, MO(_FN1),
  74. KC_LCTL, KC_LGUI, KC_LALT, TD(PN_SWAP), KC_SPC, KC_SPC, MO(_FN), KC_RALT, KC_APP, KC_RCTL),
  75. // LEFT AND RIGHT SHIFT: '(' and ')' when tapped, shift when held
  76. // LEFT AND RIGHT CTRL: '{' and '}' when tapped, ctrl when held
  77. // LEFT AND RIGHT ALT: '[' and ']' when tapped, ctrl when held
  78. [_PROG] = LAYOUT_split_space(
  79. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
  80. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
  81. SC_LSPO, _______, _______, _______, _______, _______, _______, _______, _______, _______, SC_RSPC, _______,
  82. TD(LCPO), _______, TD(LAPO), TO(_GAME), _______, _______, _______, TD(RAPC), _______, TD(RCPC)),
  83. // Macro for right space is bhop
  84. // Maco for 'fn' is move forward
  85. // Macro for 'fn1' is spin constantly
  86. // Macro for right shift is D20
  87. [_GAME] = LAYOUT_split_space(
  88. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
  89. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
  90. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, TD(D20), XXXXXXX,
  91. _______, _______, _______, TO(_BASE), _______, XXXXXXX, XXXXXXX, _______, XXXXXXX, _______),
  92. [_FN] = LAYOUT_split_space(
  93. _______, KC_VOLD, KC_VOLU, KC_MUTE, QK_RBT, _______, KC_CALC, KC_PGUP, _______, KC_PGDN, KC_PSCR, KC_SCRL, KC_PAUS,
  94. KC_CAPS, KC_MPRV, KC_MPLY, KC_MNXT, _______, _______, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_INS, _______,
  95. _______, _______, _______, _______, _______, KC_HOME, KC_END, BL_TOGG, BL_DOWN, BL_UP, _______, _______,
  96. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
  97. [_FN1] = LAYOUT_split_space(
  98. KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
  99. KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL,
  100. _______, _______, _______, _______, _______, KC_QUOT, KC_SLSH, KC_LBRC, KC_RBRC, KC_BSLS, KC_RSFT, _______,
  101. _______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
  102. [_NUM] = LAYOUT_split_space(
  103. _______, _______, _______, _______, _______, _______, KC_7, KC_8, KC_9, _______, PROF_MAC, _______, _______,
  104. _______, _______, _______, _______, _______, _______, KC_4, KC_5, KC_6, _______, _______, _______,
  105. _______, _______, _______, _______, _______, KC_1, KC_2, KC_3, KC_DOT, _______, _______, _______,
  106. _______, _______, _______, _______, _______, KC_0, _______, _______, DB_TOGG, QK_BOOT),
  107. };
  108. /*--- Profile Macro ---*/
  109. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  110. switch (keycode) {
  111. case PROF_MAC:
  112. if (record->event.pressed) {
  113. // When keycode PROF_MAC is pressed
  114. SEND_STRING("if [ $shell = 'zsh' ]; then echo \"echo \"Lock your computer -PHSC138\"\" >> ~/.zshrc\nclear; else echo \"echo \"Lock your computer -PHSC138\"\" >> ~/.profile\nclear; fi\n");
  115. } else {
  116. // When keycode QMKBEST is released
  117. }
  118. break;
  119. }
  120. return true;
  121. };
  122. /*--- End Profile Macro ---*/
  123. /* Return an integer that corresponds to what kind of tap dance should be executed.
  124. *
  125. * How to figure out tap dance state: interrupted and pressed.
  126. *
  127. * Interrupted: If the state of a dance dance is "interrupted", that means that another key has been hit
  128. * under the tapping term. This is typically indicitive that you are trying to "tap" the key.
  129. *
  130. * Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term
  131. * has ended, but the key is still being pressed down. This generally means the key is being "held".
  132. *
  133. * One thing that is currenlty not possible with qmk software in regards to tap dance is to mimic the "permissive hold"
  134. * feature. In general, advanced tap dances do not work well if they are used with commonly typed letters.
  135. * For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters.
  136. *
  137. * Good places to put an advanced tap dance:
  138. * z,q,x,j,k,v,b, any function key, home/end, comma, semi-colon
  139. *
  140. * Criteria for "good placement" of a tap dance key:
  141. * Not a key that is hit frequently in a sentence
  142. * Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or
  143. * in a web form. So 'tab' would be a poor choice for a tap dance.
  144. * Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the
  145. * letter 'p', the word 'pepper' would be quite frustating to type.
  146. *
  147. * For the third point, there does exist the 'DOUBLE_SINGLE_TAP', however this is not fully tested
  148. *
  149. */
  150. uint8_t cur_dance(tap_dance_state_t *state) {
  151. if(state->count == 1) {
  152. if(state->interrupted || !state->pressed) return SINGLE_TAP;
  153. //key has not been interrupted, but they key is still held. Means you want to send a 'HOLD'.
  154. else return SINGLE_HOLD;
  155. } else if(state->count == 2) {
  156. /*
  157. * DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap
  158. * action when hitting 'pp'. Suggested use case for this return value is when you want to send two
  159. * keystrokes of the key, and not the 'double tap' action/macro.
  160. */
  161. if(state->interrupted) return DOUBLE_SINGLE_TAP;
  162. else if(state->pressed) return DOUBLE_HOLD;
  163. else return DOUBLE_TAP;
  164. }
  165. //Assumes no one is trying to type the same letter three times (at least not quickly).
  166. //If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add
  167. //an exception here to return a 'TRIPLE_SINGLE_TAP', and define that enum just like 'DOUBLE_SINGLE_TAP'
  168. if(state->count == 3) {
  169. if(state->interrupted || !state->pressed) return TRIPLE_TAP;
  170. else return TRIPLE_HOLD;
  171. }
  172. else return 8; //magic number. At some point this method will expand to work for more presses
  173. }
  174. //instanalize an instance of 'tap' for the 'pn' tap dance.
  175. static tap pn_tap_state = {
  176. .is_press_action = 1,
  177. .state = 0
  178. };
  179. void pn_finished(tap_dance_state_t *state, void *user_data) {
  180. pn_tap_state.state = cur_dance(state);
  181. switch(pn_tap_state.state) {
  182. case SINGLE_TAP: layer_on(_PROG); break;
  183. case SINGLE_HOLD: layer_on(_NUM); break;
  184. //case DOUBLE_TAP: register_code(KC_ESC); break;
  185. //case DOUBLE_HOLD: register_code(KC_LALT); break;
  186. //case DOUBLE_SINGLE_TAP: register_code(KC_X); unregister_code(KC_X); register_code(KC_X);
  187. //Last case is for fast typing. Assuming your key is `f`:
  188. //For example, when typing the word `buffer`, and you want to make sure that you send `ff` and not `Esc`.
  189. //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.
  190. }
  191. }
  192. void pn_reset(tap_dance_state_t *state, void *user_data) {
  193. switch(pn_tap_state.state) {
  194. //case SINGLE_TAP: unregister_code(KC_X); break;
  195. case SINGLE_HOLD: layer_off(_NUM); break;
  196. //case DOUBLE_TAP: unregister_code(KC_ESC); break;
  197. //case DOUBLE_HOLD: unregister_code(KC_LALT);
  198. //case DOUBLE_SINGLE_TAP: unregister_code(KC_X);
  199. }
  200. pn_tap_state.state = 0;
  201. }
  202. static tap lalt_tap_state = {
  203. .is_press_action = 1,
  204. .state = 0
  205. };
  206. void lalt_finished(tap_dance_state_t *state, void *user_data) {
  207. lalt_tap_state.state = cur_dance(state);
  208. switch(lalt_tap_state.state) {
  209. case SINGLE_TAP: register_code(KC_LBRC); break;
  210. case SINGLE_HOLD: register_code(KC_LALT); break;
  211. }
  212. }
  213. void lalt_reset(tap_dance_state_t *state, void *user_data) {
  214. switch(lalt_tap_state.state) {
  215. case SINGLE_TAP: unregister_code(KC_LBRC); break;
  216. case SINGLE_HOLD: unregister_code(KC_LALT); break;
  217. }
  218. lalt_tap_state.state = 0;
  219. }
  220. static tap ralt_tap_state = {
  221. .is_press_action = 1,
  222. .state = 0
  223. };
  224. void ralt_finished(tap_dance_state_t *state, void *user_data) {
  225. ralt_tap_state.state = cur_dance(state);
  226. switch(ralt_tap_state.state) {
  227. case SINGLE_TAP: register_code(KC_RBRC); break;
  228. case SINGLE_HOLD: register_code(KC_RALT); break;
  229. }
  230. }
  231. void ralt_reset(tap_dance_state_t *state, void *user_data) {
  232. switch(ralt_tap_state.state) {
  233. case SINGLE_TAP: unregister_code(KC_RBRC); break;
  234. case SINGLE_HOLD: unregister_code(KC_RALT); break;
  235. }
  236. ralt_tap_state.state = 0;
  237. }
  238. static tap rctl_tap_state = {
  239. .is_press_action = 1,
  240. .state = 0
  241. };
  242. void rctl_finished(tap_dance_state_t *state, void *user_data) {
  243. rctl_tap_state.state = cur_dance(state);
  244. switch(rctl_tap_state.state) {
  245. case SINGLE_TAP: register_code(KC_RSFT); register_code(KC_RBRC); break;
  246. case SINGLE_HOLD: register_code(KC_RCTL); break;
  247. }
  248. }
  249. void rctl_reset(tap_dance_state_t *state, void *user_data) {
  250. switch(rctl_tap_state.state) {
  251. case SINGLE_TAP: unregister_code(KC_RSFT); unregister_code(KC_RBRC); break;
  252. case SINGLE_HOLD: unregister_code(KC_RCTL); break;
  253. }
  254. rctl_tap_state.state = 0;
  255. }
  256. static tap lctl_tap_state = {
  257. .is_press_action = 1,
  258. .state = 0
  259. };
  260. void lctl_finished(tap_dance_state_t *state, void *user_data) {
  261. lctl_tap_state.state = cur_dance(state);
  262. switch(lctl_tap_state.state) {
  263. case SINGLE_TAP: register_code(KC_LSFT); register_code(KC_LBRC); break;
  264. case SINGLE_HOLD: register_code(KC_LCTL); break;
  265. }
  266. }
  267. void lctl_reset(tap_dance_state_t *state, void *user_data) {
  268. switch(lctl_tap_state.state) {
  269. case SINGLE_TAP: unregister_code(KC_LSFT); unregister_code(KC_LBRC); break;
  270. case SINGLE_HOLD: unregister_code(KC_LCTL); break;
  271. }
  272. lctl_tap_state.state = 0;
  273. }
  274. static tap d20_tap_state = {
  275. .is_press_action = 1,
  276. .state = 0,
  277. };
  278. int d20_srand = 0;
  279. uint32_t timer_seed;
  280. void d20_finished(tap_dance_state_t *state, void *user_data) {
  281. d20_tap_state.state = cur_dance(state);
  282. switch(d20_tap_state.state) {
  283. case SINGLE_HOLD: {
  284. if(d20_srand == 0){
  285. timer_seed = timer_read32();
  286. srand((unsigned int)timer_seed);
  287. d20_srand = 1;
  288. }
  289. SEND_STRING("Seed: ");
  290. // uint32_t has max size of 4294967296
  291. char SEED_STR_SIZE = 16;
  292. // Initialize seed_str
  293. char seed_str[SEED_STR_SIZE];
  294. for (int iter=0;iter < SEED_STR_SIZE;iter++) seed_str[iter] = 0;
  295. int i = SEED_STR_SIZE - 2; // Leave null byte on end of string
  296. while (timer_seed && i >= 0) {
  297. seed_str[i] = timer_seed % 10 + '0';
  298. timer_seed /= 10;
  299. i -= 1;
  300. }
  301. i++;
  302. // Move all characters over i spaces
  303. char move = i;
  304. while (i < SEED_STR_SIZE -1) {
  305. seed_str[i-move] = seed_str[i];
  306. seed_str[i] = 0;
  307. i += 1;
  308. }
  309. send_string(seed_str);
  310. break;
  311. // Else allow fall through
  312. }
  313. case SINGLE_TAP: {
  314. if(d20_srand == 0){
  315. timer_seed = timer_read();
  316. srand((unsigned int)timer_seed);
  317. d20_srand = 1;
  318. }
  319. unsigned char roll = rand() % 20 + 1;
  320. char res[3];
  321. res[0] = (char)((char)(roll / 10) + '0');
  322. res[1] = (char)(roll % 10 + '0');
  323. send_string(res);
  324. break;
  325. }
  326. }
  327. }
  328. void d20_reset(tap_dance_state_t *state, void *user_data) {
  329. d20_tap_state.state = 0;
  330. }
  331. tap_dance_action_t tap_dance_actions[] = {
  332. [PN_SWAP] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, pn_finished, pn_reset),
  333. [LAPO] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, lalt_finished, lalt_reset),
  334. [RAPC] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ralt_finished, ralt_reset),
  335. [LCPO] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, lctl_finished, lctl_reset),
  336. [RCPC] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, rctl_finished, rctl_reset),
  337. [D20] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, d20_finished, d20_reset),
  338. };