1 #+Title: Samuel's Literate QMK Config
2 #+PROPERTY: header-args :tangle ~/qmk_firmware/keyboards/planck/keymaps/samuel/keymap.c
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.
12 | <6> | <6> | <6> | <6> | <6> | <6> | <6> | <6> | <6> | <6> | <6> | <6> |
13 |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
14 | - | - | - | - | - | - | - | - | - | - | - | - |
15 | - | - | - | - | - | - | - | - | - | - | - | - |
16 | - | - | - | - | - | - | - | - | - | - | - | - |
17 | - | - | - | - | - | - | - | - | - | - | - | - |
18 |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
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.
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 |--------+--------+------+------+------+-----+-----+-----+------+-------+--------+--------|
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
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 |--------+--------+----+------+------+-----+-----+-----+------+-------+--------+--------|
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
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 |--------+--------+--------+--------+--------+------+------+-----+--------+--------+-------+--------|
62 Basic command layer for one-shot macros and function keys.
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 |----+-----+-----+-----+-----+--------+--------+------+-------+------+-----+----|
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.
75 * Keymap Conversion in Python
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.
84 #+BEGIN_SRC python :var keys=secondary-layer :tangle no
87 while row < len(keys):
90 while key < len(keys[row]):
91 keyName = str(keys[row][key])
93 keyName = 'TRANSPARENT'
94 results += 'KC_' + keyName
109 Now that we laid out our layout, lets lay out our kemap file.
111 #+BEGIN_SRC C :noweb yes
112 #include QMK_KEYBOARD_H
114 extern keymap_config_t keymap_config;
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,
159 #+BEGIN_SRC C :noweb yes
167 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
171 #+BEGIN_SRC C :noweb yes
176 #+BEGIN_SRC C :noweb yes
177 <<layer-to-array(home-layer)>>
181 #+BEGIN_SRC C :noweb yes
186 #+BEGIN_SRC C :noweb yes
187 <<layer-to-array(qwerty-layer)>>
191 #+BEGIN_SRC C :noweb yes
196 #+BEGIN_SRC C :noweb yes
197 <<layer-to-array(secondary-layer)>>
201 #+BEGIN_SRC C :noweb yes
206 #+BEGIN_SRC C :noweb yes
207 <<layer-to-array(command-layer)>>
211 #+BEGIN_SRC C :noweb yes
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.
228 #+BEGIN_SRC C :noweb yes
230 static uint16_t tap_timer = 0;
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
237 if (last_mod != id && last_mod != 10) {
238 tap_code16(tap_code);
241 tap_timer = timer_read();
243 register_code(hold_code);
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);
257 ** Process User Input
259 #+BEGIN_SRC C :noweb yes
260 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
268 #+BEGIN_SRC C :noweb yes
270 if (record->event.pressed) {
271 set_single_persistent_default_layer(_DVORAK);
280 #+BEGIN_SRC C :noweb yes
282 if (record->event.pressed) {
283 set_single_persistent_default_layer(_QWERTY);
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.
296 #+BEGIN_SRC C :noweb yes
298 if (record->event.pressed) {
299 mod_press(S(KC_9), KC_LALT, 0);
301 mod_lift(S(KC_9), KC_LALT, 0);
306 if (record->event.pressed) {
307 mod_press(S(KC_0), KC_RALT, 1);
309 mod_lift(S(KC_0), KC_RALT, 1);
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.
323 #+BEGIN_SRC C :noweb yes
325 if (record->event.pressed) {
326 mod_press(KC_GRAVE, KC_LGUI, 2);
328 mod_lift(KC_GRAVE, KC_LGUI, 2);
333 if (record->event.pressed) {
334 mod_press(KC_BSLASH, KC_RGUI, 3);
336 mod_lift(KC_BSLASH, KC_RGUI, 3);
345 Left and right control are [] respectively when they are tapped, making { and }
346 also very convenient.
348 #+BEGIN_SRC C :noweb yes
350 if (record->event.pressed) {
351 mod_press(KC_LBRACKET, KC_LCTL, 4);
353 mod_lift(KC_LBRACKET, KC_LCTL, 4);
358 if (record->event.pressed) {
359 mod_press(KC_RBRACKET, KC_RCTL, 5);
361 mod_lift(KC_RBRACKET, KC_RCTL, 5);
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.
374 #+BEGIN_SRC C :noweb yes
376 if (record->event.pressed) {
377 mod_press(KC_EQUAL, KC_LSFT, 6);
379 mod_lift(KC_EQUAL, KC_LSFT, 6);
384 if (record->event.pressed) {
385 mod_press(KC_MINUS, KC_RSFT, 7);
387 mod_lift(KC_MINUS, KC_RSFT, 7);
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
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.
407 #+BEGIN_SRC C :noweb yes
409 if (record->event.pressed) {
410 tap_timer = timer_read();
415 if (last_mod == 8 && timer_elapsed(tap_timer) < TAPPING_TERM) {
416 tap_code16(KC_DELETE);
423 if (record->event.pressed) {
424 tap_timer = timer_read();
429 if (last_mod == 9 && timer_elapsed(tap_timer) < TAPPING_TERM) {
430 tap_code16(KC_SLASH);
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.
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.
449 #+BEGIN_SRC C :noweb yes
451 if (record->event.pressed) {
452 set_oneshot_mods(MOD_LSFT);
458 if (record->event.pressed) {
459 set_oneshot_mods(MOD_LCTL);
465 if (record->event.pressed) {
466 set_oneshot_mods(MOD_LALT);
472 if (record->event.pressed) {
473 set_oneshot_mods(MOD_LGUI);
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.
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.
489 #+BEGIN_SRC C :noweb yes
491 if (record->event.pressed) {
492 register_code(KC_LCTL);
493 tap_code16(S(KC_RGHT));
494 unregister_code(KC_LCTL);
500 if (record->event.pressed) {
501 register_code(KC_LCTL);
502 tap_code16(S(KC_LEFT));
503 unregister_code(KC_LCTL);
509 if (record->event.pressed) {
510 register_code(KC_LCTL);
511 tap_code16(S(KC_DOWN));
512 unregister_code(KC_LCTL);
518 if (record->event.pressed) {
519 register_code(KC_LCTL);
520 tap_code16(S(KC_UP));
521 unregister_code(KC_LCTL);
528 *** Undo, Copy, Cut, Paste
530 #+BEGIN_SRC C :noweb yes
532 if (record->event.pressed) {
539 if (record->event.pressed) {
546 if (record->event.pressed) {
553 if (record->event.pressed) {
563 Start command layer one shot
565 #+BEGIN_SRC C :noweb yes
567 if (record->event.pressed) {
569 set_oneshot_layer(_COMMAND, ONESHOT_START);
572 clear_oneshot_layer_state (ONESHOT_PRESSED);
578 Just some strings I notice that I type a lot.
580 #+BEGIN_SRC C :noweb yes
582 if (record->event.pressed) {
583 send_string("mhostley");
589 if (record->event.pressed) {
590 send_string("mhostley@gmail.com");
596 if (record->event.pressed) {
597 send_string("Samuel Jahnke");
603 if (record->event.pressed) {
604 send_string("home/mhostley/");
612 ** Standard inputs interupt tap
614 Finally, if just a standard key is tapped, set the interupted flag.
617 #+BEGIN_SRC C :noweb yes