]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/planck/keymaps/samuel/README.org
Update KBD67 readme so that it mentions the KBD65 PCB (#5143)
[qmk_firmware.git] / keyboards / planck / keymaps / samuel / README.org
1 #+Title: Samuel's Literate QMK Config
2 #+PROPERTY: header-args :tangle ~/qmk_firmware/keyboards/planck/keymaps/samuel/keymap.c
3
4 This is my qmk firmware for my keyboard. I grew tired of organizing the keycode
5 array in plain text so I made it a literate .org file. I've never done this
6 before, so bear with me.
7
8 * Layers
9
10 #+BEGIN_COMMENT
11 #+NAME: empty-layer
12 | <6>    | <6>    | <6>    | <6>    | <6>    | <6>    | <6>    | <6>    | <6>    | <6>    | <6>    | <6>    |
13 |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
14 | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      |
15 | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      |
16 | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      |
17 | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      | -      |
18 |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
19 #+END_COMMENT
20
21 This is my "pretty" org mode organized table for my main dvorak layer. If you
22 don't use org mode, it won't be that exciting, but if you enjoy working in org
23 mode, you can edit this table directly, and this file is tangled to the actual
24 keymap. No more organizing spaces or converting to and from comments.
25
26 #+NAME: home-layer
27 |--------+--------+------+------+------+-----+-----+-----+------+-------+--------+--------|
28 | T_LRSE | QUOT   | COMM | DOT  | P    | Y   | F   | G   | C    | R     | L      | T_RRSE |
29 | T_LSFT | A      | O    | E    | U    | I   | D   | H   | T    | N     | S      | T_RSFT |
30 | T_LCTL | SCLN   | Q    | J    | K    | X   | B   | M   | W    | V     | Z      | T_RCTL |
31 | T_LGUI | T_LALT | UP   | DOWN | BSPC | TAB | ENT | SPC | LEFT | RIGHT | T_RALT | T_RGUI |
32 |--------+--------+------+------+------+-----+-----+-----+------+-------+--------+--------|
33
34 This qwerty layout is just so normal people can try out the board. Tap keys
35 would need to be customized I think, more on that later. I also put another
36 dvorak key here because I have nightmares of getting trapped in this forsaken
37 layout.
38
39 #+NAME: qwerty-layer
40 |--------+--------+----+------+------+-----+-----+-----+------+-------+--------+--------|
41 | T_LRSE | Q      | W  | E    | R    | T   | Y   | U   | I    | O     | P      | T_RRSE |
42 | T_LSFT | A      | S  | D    | F    | G   | H   | J   | K    | L     | SCLN   | T_RSFT |
43 | T_LCTL | Z      | X  | C    | V    | B   | N   | M   | COMM | DOT   | QUOT   | T_RCTL |
44 | T_LGUI | T_LALT | UP | DOWN | BSPC | TAB | ENT | SPC | LEFT | RIGHT | T_RALT | DVORAK |
45 |--------+--------+----+------+------+-----+-----+-----+------+-------+--------+--------|
46
47 I tried to keep my layout bare bones, just what would be available on a normal
48 keyboard, minus some keys I never used. This one secondary layer should cover a
49 majority of the keys not found on the home layer. The bottom left copies a normal
50 keyboards symbols from shifted numbers, and the rest is placed where convenient,
51 with some considerations for one handed use, hence the shortcuts in the top
52 left.
53
54 #+NAME: secondary-layer
55 |--------+--------+--------+--------+--------+------+------+-----+--------+--------+-------+--------|
56 | --     | EZUNDO | EZCOPY | EZCUT  | EZPSTE | INS  | EQL  |   7 |      8 |      9 | --    | --     |
57 | EZSHFT | ESC    | CAPS   | PGUP   | PGDN   | HOME | ASTR |   4 |      5 |      6 | 0     | EZSHFT |
58 | EZCTRL | EXLM   | AT     | HASH   | DLR    | PERC | CIRC |   1 |      2 |      3 | COM   | EZCTRL |
59 | EZGUI  | EZALT  | EZUP   | EZDOWN | SPC    | AMPR | PIPE | END | EZLEFT | EZRGHT | EZALT | EZGUI  |
60 |--------+--------+--------+--------+--------+------+------+-----+--------+--------+-------+--------|
61
62 Basic command layer for one-shot macros and function keys.
63
64 #+NAME: command-layer
65 |----+-----+-----+-----+-----+--------+--------+------+-------+------+-----+----|
66 | -- | F1  | F2  | F3  | F4  | F5     | F6     | F7   | F8    | F9   | F10 | -- |
67 | -- | F11 | F12 | F13 | F14 | F15    | F16    | F17  | F18   | F19  | F20 | -- |
68 | -- | F21 | F22 | F23 | F24 | QWERTY | DVORAK | USER | EMAIL | NAME | --  | -- |
69 | -- | --  | --  | --  | --  | --     | --     | DIR  | --    | --   | --  | -- |
70 |----+-----+-----+-----+-----+--------+--------+------+-------+------+-----+----|
71
72 But wait, we are missing several important keys? well, yes, but the modifier keys
73 all do other keys when tapped. More about that in the keymap section.
74
75 * Keymap Conversion in Python
76
77 This python can convert that table into the array needed for the keymap file. It
78 simply prepends every key with "KC_". I used to use a dictionary to convert some
79 keys from the table into qmk keycodes, but the double convertion was
80 unneccessary so I just prepended all my macros with KC and moved all the
81 implementation to the `process-user-input` function.
82
83 #+NAME:layer-to-array
84 #+BEGIN_SRC python :var keys=secondary-layer :tangle no
85 results = "{"
86 row = 0
87 while row < len(keys):
88   results += '{ '
89   key = 0
90   while key < len(keys[row]):
91     keyName = str(keys[row][key])
92     if keyName == '--':
93       keyName = 'TRANSPARENT'
94     results += 'KC_' + keyName
95     if key != 11:
96       results += ', '
97     key+=1
98   results += '}'
99   if row != 3:
100     results += ','
101   results += '\n'
102   row+=1
103 results += '},\n'
104 return results
105 #+END_SRC
106
107 * keymap.c
108
109 Now that we laid out our layout, lets lay out our kemap file.
110
111 #+BEGIN_SRC C :noweb yes
112 #include QMK_KEYBOARD_H
113
114 extern keymap_config_t keymap_config;
115
116 #+END_SRC
117
118 ** Keycodes
119
120 #+BEGIN_SRC C :noweb yes
121 // where the 'T_' communicates how the key does something different when tapped.
122 enum planck_keycodes {
123 //DVORAK = SAFE_RANGE,
124 KC_T_LALT = SAFE_RANGE,
125 KC_T_RALT,
126 KC_T_LGUI,
127 KC_T_RGUI,
128 KC_T_LCTL,
129 KC_T_RCTL,
130 KC_T_LSFT,
131 KC_T_RSFT,
132 KC_T_LRSE,
133 KC_T_RRSE,
134 KC_EZRGHT,
135 KC_EZLEFT,
136 KC_EZUP,
137 KC_EZDOWN,
138 KC_EZUNDO,
139 KC_EZCOPY,
140 KC_EZCUT,
141 KC_EZPSTE,
142 KC_EZSHFT,
143 KC_EZCTRL,
144 KC_EZGUI,
145 KC_EZALT,
146 KC_DVORAK,
147 KC_QWERTY,
148 KC_USER,
149 KC_EMAIL,
150 KC_NAME,
151 KC_DIR,
152 KC_COM
153 };
154
155 #+END_SRC
156
157 ** Import Key table
158
159 #+BEGIN_SRC C :noweb yes
160 enum planck_layers {
161 _DVORAK,
162 _QWERTY,
163 _RISE,
164 _COMMAND
165 };
166
167 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
168
169 #+END_SRC
170
171 #+BEGIN_SRC C :noweb yes
172 [_DVORAK] =
173
174 #+END_SRC
175
176 #+BEGIN_SRC C :noweb yes
177 <<layer-to-array(home-layer)>>
178
179 #+END_SRC
180
181 #+BEGIN_SRC C :noweb yes
182 [_QWERTY] =
183
184 #+END_SRC
185
186 #+BEGIN_SRC C :noweb yes
187 <<layer-to-array(qwerty-layer)>>
188
189 #+END_SRC
190
191 #+BEGIN_SRC C :noweb yes
192 [_RISE] =
193
194 #+END_SRC
195
196 #+BEGIN_SRC C :noweb yes
197 <<layer-to-array(secondary-layer)>>
198
199 #+END_SRC
200
201 #+BEGIN_SRC C :noweb yes
202 [_COMMAND] =
203
204 #+END_SRC
205
206 #+BEGIN_SRC C :noweb yes
207 <<layer-to-array(command-layer)>>
208
209 #+END_SRC
210
211 #+BEGIN_SRC C :noweb yes
212 };
213
214 #+END_SRC
215
216 ** Tap Keys
217
218 I don't like tap keys coming out on release. When modified, I often let go of
219 the modifier too early because the tap button doesn't come out untill release. I
220 guess you could save the state of the board on press and then apply it after the
221 timer, but what I really want is the keys to come out on press when they can and
222 when it is most useful. For me, that is when they are modified a single time. So
223 I kind "locked" the board into only doing single modifiers, making them faster.
224 Disadvantages are double modified keys must be done with one shot keys (its
225 actually not that bad, it feels like emacs!) and triple modified keys are
226 impossible at the moment.
227
228 #+BEGIN_SRC C :noweb yes
229
230 static uint16_t tap_timer = 0;
231 char last_mod = 10;
232
233 void mod_press(uint16_t tap_code, uint16_t hold_code, int id) {
234     // this first if body makes double modified keys impossible, but stops the
235     // delay when modifying a tap key which would result in the tap key not
236     // getting modified.
237     if (last_mod != id && last_mod != 10) {
238         tap_code16(tap_code);
239         last_mod = 10;
240     } else {
241         tap_timer = timer_read();
242         last_mod = id;
243         register_code(hold_code);
244     }
245 }
246
247 void mod_lift(uint16_t tap_code, uint16_t hold_code, int id) {
248     unregister_code(hold_code);
249     if (last_mod == id && timer_elapsed(tap_timer) < TAPPING_TERM) {
250         tap_code16(tap_code);
251         last_mod = 10;
252     }
253 }
254
255 #+END_SRC
256
257 ** Process User Input
258
259 #+BEGIN_SRC C :noweb yes
260 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
261     switch (keycode) {
262 #+END_SRC
263
264 ** Layouts
265
266 Set Dvorak layout
267
268 #+BEGIN_SRC C :noweb yes
269 case KC_DVORAK:
270 if (record->event.pressed) {
271     set_single_persistent_default_layer(_DVORAK);
272 }
273 return true;
274 break;
275
276 #+END_SRC
277
278 Set Qwerty layout.
279
280 #+BEGIN_SRC C :noweb yes
281 case KC_QWERTY:
282 if (record->event.pressed) {
283     set_single_persistent_default_layer(_QWERTY);
284 }
285 return true;
286 break;
287
288 #+END_SRC
289
290 ** Alt and ()
291
292 Left and right alt are ( and ) when tapped. I put them on alt instead of a more
293 conveniant key like control because parentheses do not need to be shift modified
294 ever, unlike some other tap keys seen in the next sections.
295
296 #+BEGIN_SRC C :noweb yes
297 case KC_T_LALT:
298 if (record->event.pressed) {
299     mod_press(S(KC_9), KC_LALT, 0);
300 } else {
301     mod_lift(S(KC_9), KC_LALT, 0);
302 }
303 return false;
304 break;
305 case KC_T_RALT:
306 if (record->event.pressed) {
307     mod_press(S(KC_0), KC_RALT, 1);
308 } else {
309     mod_lift(S(KC_0), KC_RALT, 1);
310 }
311 return false;
312 break;
313
314 #+END_SRC
315
316 ** Gui and `\
317
318 I place gui in the bottom corner because I believe it is the hardest key to
319 reach, so gui seemed like a good fit for a dedicated key that I never want to
320 have to spam. For tap keys, I used equally unused keys that are not apart of the
321 number pad or shifted number keys.
322
323 #+BEGIN_SRC C :noweb yes
324 case KC_T_LGUI:
325 if (record->event.pressed) {
326     mod_press(KC_GRAVE, KC_LGUI, 2);
327 } else {
328     mod_lift(KC_GRAVE, KC_LGUI, 2);
329 }
330 return false;
331 break;
332 case KC_T_RGUI:
333 if (record->event.pressed) {
334     mod_press(KC_BSLASH, KC_RGUI, 3);
335 } else {
336     mod_lift(KC_BSLASH, KC_RGUI, 3);
337 }
338 return false;
339 break;
340
341 #+END_SRC
342
343 ** Ctrl and []
344
345 Left and right control are [] respectively when they are tapped, making { and }
346 also very convenient.
347
348 #+BEGIN_SRC C :noweb yes
349 case KC_T_LCTL:
350 if (record->event.pressed) {
351     mod_press(KC_LBRACKET, KC_LCTL, 4);
352 } else {
353     mod_lift(KC_LBRACKET, KC_LCTL, 4);
354 }
355 return false;
356 break;
357 case KC_T_RCTL:
358 if (record->event.pressed) {
359     mod_press(KC_RBRACKET, KC_RCTL, 5);
360 } else {
361     mod_lift(KC_RBRACKET, KC_RCTL, 5);
362 }
363 return false;
364 break;
365
366 #+END_SRC
367
368 ** Shft and =-
369
370 I place shift on the home row, so having '-' right of my pinkie is standard, and
371 it only felt natural to put its opposite, '=/+' on the other side. I put an
372 extra one on the right side in the secondary layer for the num pad.
373
374 #+BEGIN_SRC C :noweb yes
375 case KC_T_LSFT:
376 if (record->event.pressed) {
377     mod_press(KC_EQUAL, KC_LSFT, 6);
378 } else {
379     mod_lift(KC_EQUAL, KC_LSFT, 6);
380 }
381 return false;
382 break;
383 case KC_T_RSFT:
384 if (record->event.pressed) {
385     mod_press(KC_MINUS, KC_RSFT, 7);
386 } else {
387     mod_lift(KC_MINUS, KC_RSFT, 7);
388 }
389 return false;
390 break;
391
392 #+END_SRC
393
394 ** Rise, DEL, and /
395
396 I use the top corners as rise because I decided that I do not like using layers
397 with my thumbs. It feels uncomfortable to hold keys down with the side of my
398 thumb, and backspace, tab, enter, and spacebar keep them satisfied. My pinky is
399 for holding modifiers, so it makes sense to put the layer key with the other
400 modifiers. Both my left and right layer keys activate the same layer which also
401 makes sense to me. You wouldn't want left and right shift to do different things
402
403 I used to have escape in the top left, but I use delete a lot more, and putting
404 escape under a layer has not been a problem at all. I put / in the top right
405 corner again mimicing a standard dvorak keyboard.
406
407 #+BEGIN_SRC C :noweb yes
408 case KC_T_LRSE:
409 if (record->event.pressed) {
410     tap_timer = timer_read();
411     last_mod = 8;
412     layer_on(_RISE);
413 } else {
414     layer_off(_RISE);
415     if (last_mod == 8 && timer_elapsed(tap_timer) < TAPPING_TERM) {
416         tap_code16(KC_DELETE);
417         last_mod = 10;
418     }
419 }
420 return false;
421 break;
422 case KC_T_RRSE:
423 if (record->event.pressed) {
424     tap_timer = timer_read();
425     last_mod = 9;
426     layer_on(_RISE);
427 } else {
428     layer_off(_RISE);
429     if (last_mod == 9 && timer_elapsed(tap_timer) < TAPPING_TERM) {
430         tap_code16(KC_SLASH);
431         last_mod = 10;
432     }
433 }
434 return false;
435 break;
436
437 #+END_SRC
438
439 ** EZ Keys
440
441 EZ or "easy" keys do things that can already be done on the board, but I want an
442 easier way of doing them.
443
444 *** One Shot Keys
445
446 Since I made modified tap keys occur on press instead of release, I need one
447 shot keys to press any key with more than one modifier.
448
449 #+BEGIN_SRC C :noweb yes
450 case KC_EZSHFT:
451 if (record->event.pressed) {
452     set_oneshot_mods(MOD_LSFT);
453     last_mod = 10;
454 }
455 return false;
456 break;
457 case KC_EZCTRL:
458 if (record->event.pressed) {
459     set_oneshot_mods(MOD_LCTL);
460     last_mod = 10;
461 }
462 return false;
463 break;
464 case KC_EZALT:
465 if (record->event.pressed) {
466     set_oneshot_mods(MOD_LALT);
467     last_mod = 10;
468 }
469 return false;
470 break;
471 case KC_EZGUI:
472 if (record->event.pressed) {
473     set_oneshot_mods(MOD_LGUI);
474     last_mod = 10;
475 }
476 return false;
477 break;
478
479 #+END_SRC
480
481 *** Arrows
482
483 I use ctrl+shift+arrows keys a lot, so when the layer key is pressed they became
484 lazy versions of themselves with control and shift already pressed.
485
486 I also added undo, copy, paste, and cut to be easily available with only the
487 left hand like on a qwerty or colemek keyboard.
488
489 #+BEGIN_SRC C :noweb yes
490 case KC_EZRGHT:
491 if (record->event.pressed) {
492     register_code(KC_LCTL);
493     tap_code16(S(KC_RGHT));
494     unregister_code(KC_LCTL);
495     last_mod = 10;
496 }
497 return false;
498 break;
499 case KC_EZLEFT:
500 if (record->event.pressed) {
501     register_code(KC_LCTL);
502     tap_code16(S(KC_LEFT));
503     unregister_code(KC_LCTL);
504     last_mod = 10;
505 }
506 return false;
507 break;
508 case KC_EZDOWN:
509 if (record->event.pressed) {
510     register_code(KC_LCTL);
511     tap_code16(S(KC_DOWN));
512     unregister_code(KC_LCTL);
513     last_mod = 10;
514 }
515 return false;
516 break;
517 case KC_EZUP:
518 if (record->event.pressed) {
519     register_code(KC_LCTL);
520     tap_code16(S(KC_UP));
521     unregister_code(KC_LCTL);
522     last_mod = 10;
523 }
524 return false;
525 break;
526 #+END_SRC
527
528 *** Undo, Copy, Cut, Paste
529
530 #+BEGIN_SRC C :noweb yes
531 case KC_EZUNDO:
532 if (record->event.pressed) {
533     tap_code16(C(KC_Z));
534     last_mod = 10;
535 }
536 return false;
537 break;
538 case KC_EZCOPY:
539 if (record->event.pressed) {
540     tap_code16(C(KC_C));
541     last_mod = 10;
542 }
543 return false;
544 break;
545 case KC_EZCUT:
546 if (record->event.pressed) {
547     tap_code16(C(KC_X));
548     last_mod = 10;
549 }
550 return false;
551 break;
552 case KC_EZPSTE:
553 if (record->event.pressed) {
554     tap_code16(C(KC_V));
555     last_mod = 10;
556 }
557 return false;
558 break;
559 #+END_SRC
560
561 ** Commands
562
563 Start command layer one shot
564
565 #+BEGIN_SRC C :noweb yes
566 case KC_COM:
567 if (record->event.pressed) {
568     layer_on(_COMMAND);
569     set_oneshot_layer(_COMMAND, ONESHOT_START);
570     last_mod = 10;
571 } else {
572     clear_oneshot_layer_state (ONESHOT_PRESSED);
573 }
574 return false;
575 break;
576 #+END_SRC
577
578 Just some strings I notice that I type a lot.
579
580 #+BEGIN_SRC C :noweb yes
581 case KC_USER:
582 if (record->event.pressed) {
583     send_string("mhostley");
584     last_mod = 10;
585 }
586 return true;
587 break;
588 case KC_EMAIL:
589 if (record->event.pressed) {
590     send_string("mhostley@gmail.com");
591     last_mod = 10;
592 }
593 return true;
594 break;
595 case KC_NAME:
596 if (record->event.pressed) {
597     send_string("Samuel Jahnke");
598     last_mod = 10;
599 }
600 return true;
601 break;
602 case KC_DIR:
603 if (record->event.pressed) {
604     send_string("home/mhostley/");
605     last_mod = 10;
606 }
607 return true;
608 break;
609
610 #+END_SRC
611
612 ** Standard inputs interupt tap
613
614 Finally, if just a standard key is tapped, set the interupted flag.
615 Keep this last.
616
617 #+BEGIN_SRC C :noweb yes
618 }
619 last_mod = 10;
620 return true;
621 }
622 #+END_SRC