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 exiting, 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 I tried to keep my layout bare bones, just what would be available on a normal
35 keyboard, minus some keys I never used. The bottom left copies a normal
36 keyboards symbols from shifted numbers, and the rest is placed where convenient,
37 with some considerations for one handed use, hence the shortcuts in the top
40 #+TODO: qwerty layer for ma friends
42 #+NAME: secondary-layer
43 |----+--------+--------+--------+--------+------+------+----+--------+--------+-----+----|
44 | -- | EZUNDO | EZCOPY | EZCUT | EZPSTE | INS | EQL | 7 | 8 | 9 | F11 | -- |
45 | -- | ESC | CAPS | PGUP | PGDN | F4 | ASTR | 4 | 5 | 6 | 0 | -- |
46 | -- | EXLM | AT | HASH | DLR | PERC | CIRC | 1 | 2 | 3 | F12 | -- |
47 | -- | -- | EZUP | EZDOWN | -- | AMPR | PIPE | -- | EZLEFT | EZRGHT | -- | -- |
48 |----+--------+--------+--------+--------+------+------+----+--------+--------+-----+----|
50 But wait, we are missing several important keys!? yes, well, the modifier keys
51 all do other keys when tapped. More about that in the keymap section.
53 * Keymap Conversion in Python
55 This python can convert that table into the array needed for the keymap file. It
56 simply prepends every key with "KC_". I used to use a dictionary to convert some
57 keys from the table into qmk keycodes, but the double convertion was
58 unneccessary so I simply prepended all my macros with KC and moved all the
59 implementation to the `process-user-input` function.
62 #+BEGIN_SRC python :var keys=secondary-layer :tangle no
65 while row < len(keys):
68 while key < len(keys[row]):
69 keyName = str(keys[row][key])
71 keyName = 'TRANSPARENT'
72 results += 'KC_' + keyName
87 Now that we have done all the hard work, lets layout our keymap file then define
90 ** Headers And Layer Declaration
92 #+BEGIN_SRC C :noweb yes
93 #include QMK_KEYBOARD_H
95 extern keymap_config_t keymap_config;
97 static uint16_t tap_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
106 // where the 'T_' communicates how the key does something different when tapped.
107 enum planck_keycodes {
129 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
135 #+BEGIN_SRC C :noweb yes
140 #+BEGIN_SRC C :noweb yes
141 <<layer-to-array(home-layer)>>
145 #+BEGIN_SRC C :noweb yes
150 #+BEGIN_SRC C :noweb yes
151 <<layer-to-array(secondary-layer)>>
155 ** Process User Input
156 *** Tap Key Functionality
158 These methods define how I implemented the tap mechanic. Basically, I believe
159 that /pressing/ any other key should be grounds for the hold functionality to be
160 assumed. My natuaral typing style experiences no delays from my method.
162 #+BEGIN_SRC C :noweb yes
165 void mod_press(uint16_t hold_code, int id) {
166 tap_timers[id] = timer_read();
168 register_code(hold_code);
171 void mod_lift(uint16_t tap_code, uint16_t hold_code, int id) {
172 unregister_code(hold_code);
173 if (last_mod == id && timer_elapsed(tap_timers[id]) < TAPPING_TERM) {
174 tap_code16(tap_code);
181 *** Set DVORAK layout
183 The function that filter's user inputs and applies macros, the begginning is
184 pretty basic, setting our main layer and configuring our secondary layer.
186 #+BEGIN_SRC C :noweb yes
187 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
190 if (record->event.pressed) {
191 set_single_persistent_default_layer(_DVORAK);
200 Left and right alt are ( and ) when tapped. I put them on alt instead of a more
201 conveniant key like control because parentheses do not need to be shift modified
202 ever, unlike some other tap keys seen in the next sections.
204 #+BEGIN_SRC C :noweb yes
206 if (record->event.pressed) {
207 mod_press(KC_LALT, 0);
209 mod_lift(S(KC_9), KC_LALT, 0);
214 if (record->event.pressed) {
215 mod_press(KC_RALT, 1);
217 mod_lift(S(KC_0), KC_RALT, 1);
226 I place gui in the bottom corner because I believe it is the hardest key to
227 reach, so gui seemed like a good fit for a dedicated key that I never want to
228 have to spam. For tap keys, I used equally unused keys that are not apart of the
229 number pad or shifted number keys.
231 #+BEGIN_SRC C :noweb yes
233 if (record->event.pressed) {
234 mod_press(KC_LGUI, 2);
236 mod_lift(KC_GRAVE, KC_LGUI, 2);
241 if (record->event.pressed) {
242 mod_press(KC_RGUI, 3);
244 mod_lift(KC_BSLASH, KC_RGUI, 3);
253 Left and right control are [] respectively when they are tapped, making { and }
254 also very convenient.
256 #+BEGIN_SRC C :noweb yes
258 if (record->event.pressed) {
259 mod_press(KC_LCTL, 4);
261 mod_lift(KC_LBRACKET, KC_LCTL, 4);
266 if (record->event.pressed) {
267 mod_press(KC_RCTL, 5);
269 mod_lift(KC_RBRACKET, KC_RCTL, 5);
278 I place shift on the home row, so having '-' right of my pinkie is standard, and
279 it only felt natural to put its opposite, '=/+' on the other side. I put an
280 extra one on the right side in the secondary layer for the num pad.
282 #+BEGIN_SRC C :noweb yes
284 if (record->event.pressed) {
285 mod_press(KC_LSFT, 6);
287 mod_lift(KC_EQUAL, KC_LSFT, 6);
292 if (record->event.pressed) {
293 mod_press(KC_RSFT, 7);
295 mod_lift(KC_MINUS, KC_RSFT, 7);
304 I use the top corners as rise because I decided that I do not like using layers
305 with my thumbs. It feels uncomfortable to hold keys down with the side of my
306 thumb, and backspace, tab, enter, and spacebar keep them satisfied. My pinky is
307 for holding modifiers, so it makes sense to put the layer key with the other
308 modifiers. Both my left and right layer keys activate the same layer which also
309 makes sense to me. You wouldn't want left and right shift to do different things
311 I used to have escape in the top left, but I use delete a lot more, and putting
312 escape under a layer has not been a problem at all. I put / in the top right
313 corner again mimicing a standard dvorak keyboard.
315 #+BEGIN_SRC C :noweb yes
317 if (record->event.pressed) {
318 tap_timers[8] = timer_read();
323 if (last_mod == 8 && timer_elapsed(tap_timers[8]) < TAPPING_TERM) {
324 tap_code16(KC_DELETE);
331 if (record->event.pressed) {
332 tap_timers[9] = timer_read();
337 if (last_mod == 9 && timer_elapsed(tap_timers[9]) < TAPPING_TERM) {
338 tap_code16(KC_SLASH);
349 I use ctrl+shift+arrows keys a lot, so when the layer key is pressed they became
350 lazy versions of themselves with control and shift already pressed.
352 I also added undo, copy, paste, and cut to be easily available with only the
353 left hand like on a qwerty or colemek keyboard.
355 #+BEGIN_SRC C :noweb yes
357 if (record->event.pressed) {
358 register_code(KC_LCTL);
359 tap_code16(S(KC_RGHT));
360 unregister_code(KC_LCTL);
366 if (record->event.pressed) {
367 register_code(KC_LCTL);
368 tap_code16(S(KC_LEFT));
369 unregister_code(KC_LCTL);
375 if (record->event.pressed) {
376 register_code(KC_LCTL);
377 tap_code16(S(KC_DOWN));
378 unregister_code(KC_LCTL);
384 if (record->event.pressed) {
385 register_code(KC_LCTL);
386 tap_code16(S(KC_UP));
387 unregister_code(KC_LCTL);
393 if (record->event.pressed) {
400 if (record->event.pressed) {
407 if (record->event.pressed) {
414 if (record->event.pressed) {
422 *** Standard inputs interupt tap
424 Finally, if just a standard key is tapped, set the interupted flag.
426 #+BEGIN_SRC C :noweb yes