aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keyboards/planck/keymaps/samuel/README.org431
-rw-r--r--keyboards/planck/keymaps/samuel/config.h1
-rw-r--r--keyboards/planck/keymaps/samuel/keymap.c245
3 files changed, 677 insertions, 0 deletions
diff --git a/keyboards/planck/keymaps/samuel/README.org b/keyboards/planck/keymaps/samuel/README.org
new file mode 100644
index 000000000..d0750ee03
--- /dev/null
+++ b/keyboards/planck/keymaps/samuel/README.org
@@ -0,0 +1,431 @@
1#+Title: Samuel's Literate QMK Config
2#+PROPERTY: header-args :tangle ~/qmk_firmware/keyboards/planck/keymaps/samuel/keymap.c
3
4This is my qmk firmware for my keyboard. I grew tired of organizing the keycode
5array in plain text so I made it a literate .org file. I've never done this
6before, 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
21This is my "pretty" org mode organized table for my main dvorak layer. If you
22don't use org mode, it won't be that exiting, but if you enjoy working in org
23mode, you can edit this table directly, and this file is tangled to the actual
24keymap. 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
34I tried to keep my layout bare bones, just what would be available on a normal
35keyboard, minus some keys I never used. The bottom left copies a normal
36keyboards symbols from shifted numbers, and the rest is placed where convenient,
37with some considerations for one handed use, hence the shortcuts in the top
38left.
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
50But wait, we are missing several important keys!? yes, well, the modifier keys
51all do other keys when tapped. More about that in the keymap section.
52
53* Keymap Conversion in Python
54
55This python can convert that table into the array needed for the keymap file. It
56simply prepends every key with "KC_". I used to use a dictionary to convert some
57keys from the table into qmk keycodes, but the double convertion was
58unneccessary so I simply prepended all my macros with KC and moved all the
59implementation to the `process-user-input` function.
60
61#+NAME:layer-to-array
62#+BEGIN_SRC python :var keys=secondary-layer :tangle no
63results = "{"
64row = 0
65while 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
81results += '},\n'
82return results
83#+END_SRC
84
85* keymap.c
86
87Now that we have done all the hard work, lets layout our keymap file then define
88our macros.
89
90** Headers And Layer Declaration
91
92#+BEGIN_SRC C :noweb yes
93#include QMK_KEYBOARD_H
94
95extern keymap_config_t keymap_config;
96
97static uint16_t tap_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
98
99char last_mod = -1;
100
101enum planck_layers {
102 _DVORAK,
103 _RISE
104};
105
106// where the 'T_' communicates how the key does something different when tapped.
107enum 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
129const 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
158These methods define how I implemented the tap mechanic. Basically, I believe
159that /pressing/ any other key should be grounds for the hold functionality to be
160assumed. My natuaral typing style experiences no delays from my method.
161
162#+BEGIN_SRC C :noweb yes
163};
164
165void 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
171void 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
183The function that filter's user inputs and applies macros, the begginning is
184pretty basic, setting our main layer and configuring our secondary layer.
185
186#+BEGIN_SRC C :noweb yes
187bool 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
200Left and right alt are ( and ) when tapped. I put them on alt instead of a more
201conveniant key like control because parentheses do not need to be shift modified
202ever, unlike some other tap keys seen in the next sections.
203
204#+BEGIN_SRC C :noweb yes
205case KC_T_LALT:
206if (record->event.pressed) {
207 mod_press(KC_LALT, 0);
208 } else {
209 mod_lift(S(KC_9), KC_LALT, 0);
210 }
211return false;
212break;
213case KC_T_RALT:
214if (record->event.pressed) {
215 mod_press(KC_RALT, 1);
216 } else {
217 mod_lift(S(KC_0), KC_RALT, 1);
218 }
219return false;
220break;
221
222#+END_SRC
223
224*** Gui and `\
225
226I place gui in the bottom corner because I believe it is the hardest key to
227reach, so gui seemed like a good fit for a dedicated key that I never want to
228have to spam. For tap keys, I used equally unused keys that are not apart of the
229number pad or shifted number keys.
230
231#+BEGIN_SRC C :noweb yes
232case KC_T_LGUI:
233if (record->event.pressed) {
234 mod_press(KC_LGUI, 2);
235 } else {
236 mod_lift(KC_GRAVE, KC_LGUI, 2);
237 }
238return false;
239break;
240case KC_T_RGUI:
241if (record->event.pressed) {
242 mod_press(KC_RGUI, 3);
243 } else {
244 mod_lift(KC_BSLASH, KC_RGUI, 3);
245 }
246return false;
247break;
248
249#+END_SRC
250
251*** Ctrl and []
252
253Left and right control are [] respectively when they are tapped, making { and }
254also very convenient.
255
256#+BEGIN_SRC C :noweb yes
257case KC_T_LCTL:
258if (record->event.pressed) {
259 mod_press(KC_LCTL, 4);
260 } else {
261 mod_lift(KC_LBRACKET, KC_LCTL, 4);
262 }
263return false;
264break;
265case KC_T_RCTL:
266if (record->event.pressed) {
267 mod_press(KC_RCTL, 5);
268 } else {
269 mod_lift(KC_RBRACKET, KC_RCTL, 5);
270 }
271return false;
272break;
273
274#+END_SRC
275
276*** Shft and =-
277
278I place shift on the home row, so having '-' right of my pinkie is standard, and
279it only felt natural to put its opposite, '=/+' on the other side. I put an
280extra one on the right side in the secondary layer for the num pad.
281
282#+BEGIN_SRC C :noweb yes
283case KC_T_LSFT:
284if (record->event.pressed) {
285 mod_press(KC_LSFT, 6);
286 } else {
287 mod_lift(KC_EQUAL, KC_LSFT, 6);
288 }
289return false;
290break;
291case KC_T_RSFT:
292if (record->event.pressed) {
293 mod_press(KC_RSFT, 7);
294 } else {
295 mod_lift(KC_MINUS, KC_RSFT, 7);
296 }
297return false;
298break;
299
300#+END_SRC
301
302*** Rise, DEL, and /
303
304I use the top corners as rise because I decided that I do not like using layers
305with my thumbs. It feels uncomfortable to hold keys down with the side of my
306thumb, and backspace, tab, enter, and spacebar keep them satisfied. My pinky is
307for holding modifiers, so it makes sense to put the layer key with the other
308modifiers. Both my left and right layer keys activate the same layer which also
309makes sense to me. You wouldn't want left and right shift to do different things
310
311I used to have escape in the top left, but I use delete a lot more, and putting
312escape under a layer has not been a problem at all. I put / in the top right
313corner again mimicing a standard dvorak keyboard.
314
315#+BEGIN_SRC C :noweb yes
316case KC_T_LRSE:
317if (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 }
328return false;
329break;
330case KC_T_RRSE:
331if (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 }
342return false;
343break;
344
345#+END_SRC
346
347*** EZ keys
348
349I use ctrl+shift+arrows keys a lot, so when the layer key is pressed they became
350lazy versions of themselves with control and shift already pressed.
351
352I also added undo, copy, paste, and cut to be easily available with only the
353left hand like on a qwerty or colemek keyboard.
354
355#+BEGIN_SRC C :noweb yes
356case KC_EZRGHT:
357if (record->event.pressed) {
358 register_code(KC_LCTL);
359 tap_code16(S(KC_RGHT));
360 unregister_code(KC_LCTL);
361 last_mod = -1;
362 }
363return false;
364break;
365case KC_EZLEFT:
366if (record->event.pressed) {
367 register_code(KC_LCTL);
368 tap_code16(S(KC_LEFT));
369 unregister_code(KC_LCTL);
370 last_mod = -1;
371 }
372return false;
373break;
374case KC_EZDOWN:
375if (record->event.pressed) {
376 register_code(KC_LCTL);
377 tap_code16(S(KC_DOWN));
378 unregister_code(KC_LCTL);
379 last_mod = -1;
380 }
381return false;
382break;
383case KC_EZUP:
384if (record->event.pressed) {
385 register_code(KC_LCTL);
386 tap_code16(S(KC_UP));
387 unregister_code(KC_LCTL);
388 last_mod = -1;
389 }
390return false;
391break;
392case KC_EZUNDO:
393if (record->event.pressed) {
394 tap_code16(C(KC_Z));
395 last_mod = -1;
396}
397return false;
398break;
399case KC_EZCOPY:
400if (record->event.pressed) {
401 tap_code16(C(KC_C));
402 last_mod = -1;
403}
404return false;
405break;
406case KC_EZCUT:
407if (record->event.pressed) {
408 tap_code16(C(KC_X));
409 last_mod = -1;
410}
411return false;
412break;
413case KC_EZPSTE:
414if (record->event.pressed) {
415 tap_code16(C(KC_P));
416 last_mod = -1;
417}
418return false;
419break;
420#+END_SRC
421
422*** Standard inputs interupt tap
423
424Finally, 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
diff --git a/keyboards/planck/keymaps/samuel/config.h b/keyboards/planck/keymaps/samuel/config.h
new file mode 100644
index 000000000..95bfdd36f
--- /dev/null
+++ b/keyboards/planck/keymaps/samuel/config.h
@@ -0,0 +1 @@
#define TAPPING_TERM 250
diff --git a/keyboards/planck/keymaps/samuel/keymap.c b/keyboards/planck/keymaps/samuel/keymap.c
new file mode 100644
index 000000000..53760da76
--- /dev/null
+++ b/keyboards/planck/keymaps/samuel/keymap.c
@@ -0,0 +1,245 @@
1#include QMK_KEYBOARD_H
2
3extern keymap_config_t keymap_config;
4
5static uint16_t tap_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
6
7char last_mod = -1;
8
9enum planck_layers {
10 _DVORAK,
11 _RISE
12};
13
14// where the 'T_' communicates how the key does something different when tapped.
15enum planck_keycodes {
16 DVORAK = SAFE_RANGE,
17 KC_T_LALT,
18 KC_T_RALT,
19 KC_T_LGUI,
20 KC_T_RGUI,
21 KC_T_LCTL,
22 KC_T_RCTL,
23 KC_T_LSFT,
24 KC_T_RSFT,
25 KC_T_LRSE,
26 KC_T_RRSE,
27 KC_EZRGHT,
28 KC_EZLEFT,
29 KC_EZUP,
30 KC_EZDOWN,
31 KC_EZUNDO,
32 KC_EZCOPY,
33 KC_EZCUT,
34 KC_EZPSTE
35};
36
37const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
38
39[_DVORAK] =
40
41{{ KC_T_LRSE, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_T_RRSE},
42{ KC_T_LSFT, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_T_RSFT},
43{ KC_T_LCTL, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_T_RCTL},
44{ KC_T_LGUI, KC_T_LALT, KC_UP, KC_DOWN, KC_BSPC, KC_TAB, KC_ENT, KC_SPC, KC_LEFT, KC_RIGHT, KC_T_RALT, KC_T_RGUI}
45},
46
47[_RISE] =
48
49{{ KC_TRANSPARENT, KC_EZUNDO, KC_EZCOPY, KC_EZCUT, KC_EZPSTE, KC_INS, KC_EQL, KC_7, KC_8, KC_9, KC_F11, KC_TRANSPARENT},
50{ KC_TRANSPARENT, KC_ESC, KC_CAPS, KC_PGUP, KC_PGDN, KC_F4, KC_ASTR, KC_4, KC_5, KC_6, KC_0, KC_TRANSPARENT},
51{ KC_TRANSPARENT, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_1, KC_2, KC_3, KC_F12, KC_TRANSPARENT},
52{ KC_TRANSPARENT, KC_TRANSPARENT, KC_EZUP, KC_EZDOWN, KC_TRANSPARENT, KC_AMPR, KC_PIPE, KC_TRANSPARENT, KC_EZLEFT, KC_EZRGHT, KC_TRANSPARENT, KC_TRANSPARENT}
53},
54
55};
56
57void mod_press(uint16_t hold_code, int id) {
58 tap_timers[id] = timer_read();
59 last_mod = id;
60 register_code(hold_code);
61}
62
63void mod_lift(uint16_t tap_code, uint16_t hold_code, int id) {
64 unregister_code(hold_code);
65 if (last_mod == id && timer_elapsed(tap_timers[id]) < TAPPING_TERM) {
66 tap_code16(tap_code);
67 last_mod = -1;
68 }
69}
70
71bool process_record_user(uint16_t keycode, keyrecord_t *record) {
72 switch (keycode) {
73 case DVORAK:
74 if (record->event.pressed) {
75 set_single_persistent_default_layer(_DVORAK);
76 }
77 return false;
78 break;
79
80case KC_T_LALT:
81if (record->event.pressed) {
82 mod_press(KC_LALT, 0);
83 } else {
84 mod_lift(S(KC_9), KC_LALT, 0);
85 }
86return false;
87break;
88case KC_T_RALT:
89if (record->event.pressed) {
90 mod_press(KC_RALT, 1);
91 } else {
92 mod_lift(S(KC_0), KC_RALT, 1);
93 }
94return false;
95break;
96
97case KC_T_LGUI:
98if (record->event.pressed) {
99 mod_press(KC_LGUI, 2);
100 } else {
101 mod_lift(KC_GRAVE, KC_LGUI, 2);
102 }
103return false;
104break;
105case KC_T_RGUI:
106if (record->event.pressed) {
107 mod_press(KC_RGUI, 3);
108 } else {
109 mod_lift(KC_BSLASH, KC_RGUI, 3);
110 }
111return false;
112break;
113
114case KC_T_LCTL:
115if (record->event.pressed) {
116 mod_press(KC_LCTL, 4);
117 } else {
118 mod_lift(KC_LBRACKET, KC_LCTL, 4);
119 }
120return false;
121break;
122case KC_T_RCTL:
123if (record->event.pressed) {
124 mod_press(KC_RCTL, 5);
125 } else {
126 mod_lift(KC_RBRACKET, KC_RCTL, 5);
127 }
128return false;
129break;
130
131case KC_T_LSFT:
132if (record->event.pressed) {
133 mod_press(KC_LSFT, 6);
134 } else {
135 mod_lift(KC_EQUAL, KC_LSFT, 6);
136 }
137return false;
138break;
139case KC_T_RSFT:
140if (record->event.pressed) {
141 mod_press(KC_RSFT, 7);
142 } else {
143 mod_lift(KC_MINUS, KC_RSFT, 7);
144 }
145return false;
146break;
147
148case KC_T_LRSE:
149if (record->event.pressed) {
150 tap_timers[8] = timer_read();
151 last_mod = 8;
152 layer_on(_RISE);
153 } else {
154 layer_off(_RISE);
155 if (last_mod == 8 && timer_elapsed(tap_timers[8]) < TAPPING_TERM) {
156 tap_code16(KC_DELETE);
157 last_mod = -1;
158 }
159 }
160return false;
161break;
162case KC_T_RRSE:
163if (record->event.pressed) {
164 tap_timers[9] = timer_read();
165 last_mod = 9;
166 layer_on(_RISE);
167 } else {
168 layer_off(_RISE);
169 if (last_mod == 9 && timer_elapsed(tap_timers[9]) < TAPPING_TERM) {
170 tap_code16(KC_SLASH);
171 last_mod = -1;
172 }
173 }
174return false;
175break;
176
177case KC_EZRGHT:
178if (record->event.pressed) {
179 register_code(KC_LCTL);
180 tap_code16(S(KC_RGHT));
181 unregister_code(KC_LCTL);
182 last_mod = -1;
183 }
184return false;
185break;
186case KC_EZLEFT:
187if (record->event.pressed) {
188 register_code(KC_LCTL);
189 tap_code16(S(KC_LEFT));
190 unregister_code(KC_LCTL);
191 last_mod = -1;
192 }
193return false;
194break;
195case KC_EZDOWN:
196if (record->event.pressed) {
197 register_code(KC_LCTL);
198 tap_code16(S(KC_DOWN));
199 unregister_code(KC_LCTL);
200 last_mod = -1;
201 }
202return false;
203break;
204case KC_EZUP:
205if (record->event.pressed) {
206 register_code(KC_LCTL);
207 tap_code16(S(KC_UP));
208 unregister_code(KC_LCTL);
209 last_mod = -1;
210 }
211return false;
212break;
213case KC_EZUNDO:
214if (record->event.pressed) {
215 tap_code16(C(KC_Z));
216 last_mod = -1;
217}
218return false;
219break;
220case KC_EZCOPY:
221if (record->event.pressed) {
222 tap_code16(C(KC_C));
223 last_mod = -1;
224}
225return false;
226break;
227case KC_EZCUT:
228if (record->event.pressed) {
229 tap_code16(C(KC_X));
230 last_mod = -1;
231}
232return false;
233break;
234case KC_EZPSTE:
235if (record->event.pressed) {
236 tap_code16(C(KC_P));
237 last_mod = -1;
238}
239return false;
240break;
241
242 }
243 last_mod = -1;
244 return true;
245}