]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/planck/keymaps/samuel/README.org
Update keyboards/kbdfans/kbd67/readme.md
[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 * Keymap
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 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.
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 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
38 left.
39
40 #+TODO: qwerty layer for ma friends
41
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 |----+--------+--------+--------+--------+------+------+----+--------+--------+-----+----|
49
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.
52
53 * Keymap Conversion in Python
54
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.
60
61 #+NAME:layer-to-array
62 #+BEGIN_SRC python :var keys=secondary-layer :tangle no
63 results = "{"
64 row = 0
65 while row < len(keys):
66   results += '{ '
67   key = 0
68   while key < len(keys[row]):
69     keyName = str(keys[row][key])
70     if keyName == '--':
71       keyName = 'TRANSPARENT'
72     results += 'KC_' + keyName
73     if key != 11:
74       results += ', '
75     key+=1
76   results += '}'
77   if row != 3:
78     results += ','
79   results += '\n'
80   row+=1
81 results += '},\n'
82 return results
83 #+END_SRC
84
85 * keymap.c
86
87 Now that we have done all the hard work, lets layout our keymap file then define
88 our macros.
89
90 ** Headers And Layer Declaration
91
92 #+BEGIN_SRC C :noweb yes
93 #include QMK_KEYBOARD_H
94
95 extern keymap_config_t keymap_config;
96
97 static uint16_t tap_timers[10]  = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
98
99 char last_mod = -1;
100
101 enum planck_layers {
102   _DVORAK,
103   _RISE
104 };
105
106 // where the 'T_' communicates how the key does something different when tapped.
107 enum planck_keycodes {
108   DVORAK = SAFE_RANGE,
109   KC_T_LALT,
110   KC_T_RALT,
111   KC_T_LGUI,
112   KC_T_RGUI,
113   KC_T_LCTL,
114   KC_T_RCTL,
115   KC_T_LSFT,
116   KC_T_RSFT,
117   KC_T_LRSE,
118   KC_T_RRSE,
119   KC_EZRGHT,
120   KC_EZLEFT,
121   KC_EZUP,
122   KC_EZDOWN,
123   KC_EZUNDO,
124   KC_EZCOPY,
125   KC_EZCUT,
126   KC_EZPSTE
127 };
128
129 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
130
131 #+END_SRC
132
133 ** Import Key table
134
135 #+BEGIN_SRC C :noweb yes
136 [_DVORAK] =
137
138 #+END_SRC
139
140 #+BEGIN_SRC C :noweb yes
141 <<layer-to-array(home-layer)>>
142
143 #+END_SRC
144
145 #+BEGIN_SRC C :noweb yes
146 [_RISE] =
147
148 #+END_SRC
149
150 #+BEGIN_SRC C :noweb yes
151 <<layer-to-array(secondary-layer)>>
152
153 #+END_SRC
154
155 ** Process User Input
156 *** Tap Key Functionality
157
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.
161
162 #+BEGIN_SRC C :noweb yes
163 };
164
165 void mod_press(uint16_t hold_code, int id) {
166     tap_timers[id] = timer_read();
167     last_mod = id;
168     register_code(hold_code);
169 }
170
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);
175       last_mod = -1;
176     }
177 }
178
179 #+END_SRC
180
181 *** Set DVORAK layout
182
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.
185
186 #+BEGIN_SRC C :noweb yes
187 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
188   switch (keycode) {
189     case DVORAK:
190       if (record->event.pressed) {
191         set_single_persistent_default_layer(_DVORAK);
192       }
193       return false;
194       break;
195
196 #+END_SRC
197
198 *** Alt  and ()
199
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.
203
204 #+BEGIN_SRC C :noweb yes
205 case KC_T_LALT:
206 if (record->event.pressed) {
207   mod_press(KC_LALT, 0);
208  } else {
209   mod_lift(S(KC_9), KC_LALT, 0);
210  }
211 return false;
212 break;
213 case KC_T_RALT:
214 if (record->event.pressed) {
215   mod_press(KC_RALT, 1);
216  } else {
217   mod_lift(S(KC_0), KC_RALT, 1);
218  }
219 return false;
220 break;
221
222 #+END_SRC
223
224 *** Gui  and `\
225
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.
230
231 #+BEGIN_SRC C :noweb yes
232 case KC_T_LGUI:
233 if (record->event.pressed) {
234   mod_press(KC_LGUI, 2);
235  } else {
236   mod_lift(KC_GRAVE, KC_LGUI, 2);
237  }
238 return false;
239 break;
240 case KC_T_RGUI:
241 if (record->event.pressed) {
242   mod_press(KC_RGUI, 3);
243  } else {
244   mod_lift(KC_BSLASH, KC_RGUI, 3);
245  }
246 return false;
247 break;
248
249 #+END_SRC
250
251 *** Ctrl and []
252
253 Left and right control are [] respectively when they are tapped, making { and }
254 also very convenient.
255
256 #+BEGIN_SRC C :noweb yes
257 case KC_T_LCTL:
258 if (record->event.pressed) {
259   mod_press(KC_LCTL, 4);
260  } else {
261   mod_lift(KC_LBRACKET, KC_LCTL, 4);
262  }
263 return false;
264 break;
265 case KC_T_RCTL:
266 if (record->event.pressed) {
267   mod_press(KC_RCTL, 5);
268  } else {
269   mod_lift(KC_RBRACKET, KC_RCTL, 5);
270  }
271 return false;
272 break;
273
274 #+END_SRC
275
276 *** Shft and =-
277
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.
281
282 #+BEGIN_SRC C :noweb yes
283 case KC_T_LSFT:
284 if (record->event.pressed) {
285   mod_press(KC_LSFT, 6);
286  } else {
287   mod_lift(KC_EQUAL, KC_LSFT, 6);
288  }
289 return false;
290 break;
291 case KC_T_RSFT:
292 if (record->event.pressed) {
293   mod_press(KC_RSFT, 7);
294  } else {
295   mod_lift(KC_MINUS, KC_RSFT, 7);
296  }
297 return false;
298 break;
299
300 #+END_SRC
301
302 *** Rise, DEL, and /
303
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
310
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.
314
315 #+BEGIN_SRC C :noweb yes
316 case KC_T_LRSE:
317 if (record->event.pressed) {
318   tap_timers[8] = timer_read();
319   last_mod = 8;
320   layer_on(_RISE);
321  } else {
322   layer_off(_RISE);
323   if (last_mod == 8 && timer_elapsed(tap_timers[8]) < TAPPING_TERM) {
324     tap_code16(KC_DELETE);
325     last_mod = -1;
326   }
327  }
328 return false;
329 break;
330 case KC_T_RRSE:
331 if (record->event.pressed) {
332   tap_timers[9] = timer_read();
333   last_mod = 9;
334   layer_on(_RISE);
335  } else {
336   layer_off(_RISE);
337   if (last_mod == 9 && timer_elapsed(tap_timers[9]) < TAPPING_TERM) {
338     tap_code16(KC_SLASH);
339     last_mod = -1;
340   }
341  }
342 return false;
343 break;
344
345 #+END_SRC
346
347 *** EZ keys
348
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.
351
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.
354
355 #+BEGIN_SRC C :noweb yes
356 case KC_EZRGHT:
357 if (record->event.pressed) {
358   register_code(KC_LCTL);
359   tap_code16(S(KC_RGHT));
360   unregister_code(KC_LCTL);
361   last_mod = -1;
362  }
363 return false;
364 break;
365 case KC_EZLEFT:
366 if (record->event.pressed) {
367   register_code(KC_LCTL);
368   tap_code16(S(KC_LEFT));
369   unregister_code(KC_LCTL);
370   last_mod = -1;
371  }
372 return false;
373 break;
374 case KC_EZDOWN:
375 if (record->event.pressed) {
376   register_code(KC_LCTL);
377   tap_code16(S(KC_DOWN));
378   unregister_code(KC_LCTL);
379   last_mod = -1;
380  }
381 return false;
382 break;
383 case KC_EZUP:
384 if (record->event.pressed) {
385   register_code(KC_LCTL);
386   tap_code16(S(KC_UP));
387   unregister_code(KC_LCTL);
388   last_mod = -1;
389  }
390 return false;
391 break;
392 case KC_EZUNDO:
393 if (record->event.pressed) {
394   tap_code16(C(KC_Z));
395   last_mod = -1;
396 }
397 return false;
398 break;
399 case KC_EZCOPY:
400 if (record->event.pressed) {
401   tap_code16(C(KC_C));
402   last_mod = -1;
403 }
404 return false;
405 break;
406 case KC_EZCUT:
407 if (record->event.pressed) {
408   tap_code16(C(KC_X));
409   last_mod = -1;
410 }
411 return false;
412 break;
413 case KC_EZPSTE:
414 if (record->event.pressed) {
415   tap_code16(C(KC_P));
416   last_mod = -1;
417 }
418 return false;
419 break;
420 #+END_SRC
421
422 *** Standard inputs interupt tap
423
424 Finally, if just a standard key is tapped, set the interupted flag.
425
426 #+BEGIN_SRC C :noweb yes
427   }
428   last_mod = -1;
429   return true;
430 }
431 #+END_SRC