[Keymap] Improvements to Samuel's literate keymap (#5428)

* added my own keymap

* changed thing

* updated keymap Samuel

* updated laypout for better one handed use

* updated stuff I want

* happy with my lagout

* formatting

* Added new literate config

* made everything nice

* cleaned

* fixed spelling and two small bugs in macros

* Made press and lift function for modifiers

* made taps occur on press instead of release

* added oneshot keys and chars cant be negative!

* removed debug message

* Added command and qwerty layers

* fixed bug with oneshot layer

* same bug, different key
This commit is contained in:
Samuel Jahnke 2019-03-17 10:22:35 -07:00 committed by Drashna Jaelre
parent fcc9b4b8e7
commit c74b11a959
2 changed files with 593 additions and 288 deletions

View File

@ -5,7 +5,7 @@ This is my qmk firmware for my keyboard. I grew tired of organizing the keycode
array in plain text so I made it a literate .org file. I've never done this array in plain text so I made it a literate .org file. I've never done this
before, so bear with me. before, so bear with me.
* Keymap * Layers
#+BEGIN_COMMENT #+BEGIN_COMMENT
#+NAME: empty-layer #+NAME: empty-layer
@ -19,7 +19,7 @@ before, so bear with me.
#+END_COMMENT #+END_COMMENT
This is my "pretty" org mode organized table for my main dvorak layer. If you This is my "pretty" org mode organized table for my main dvorak layer. If you
don't use org mode, it won't be that exiting, but if you enjoy working in org don't use org mode, it won't be that exciting, but if you enjoy working in org
mode, you can edit this table directly, and this file is tangled to the actual mode, you can edit this table directly, and this file is tangled to the actual
keymap. No more organizing spaces or converting to and from comments. keymap. No more organizing spaces or converting to and from comments.
@ -31,23 +31,45 @@ keymap. No more organizing spaces or converting to and from comments.
| T_LGUI | T_LALT | UP | DOWN | BSPC | TAB | ENT | SPC | LEFT | RIGHT | T_RALT | T_RGUI | | T_LGUI | T_LALT | UP | DOWN | BSPC | TAB | ENT | SPC | LEFT | RIGHT | T_RALT | T_RGUI |
|--------+--------+------+------+------+-----+-----+-----+------+-------+--------+--------| |--------+--------+------+------+------+-----+-----+-----+------+-------+--------+--------|
This qwerty layout is just so normal people can try out the board. Tap keys
would need to be customized I think, more on that later. I also put another
dvorak key here because I have nightmares of getting trapped in this forsaken
layout.
#+NAME: qwerty-layer
|--------+--------+----+------+------+-----+-----+-----+------+-------+--------+--------|
| T_LRSE | Q | W | E | R | T | Y | U | I | O | P | T_RRSE |
| T_LSFT | A | S | D | F | G | H | J | K | L | SCLN | T_RSFT |
| T_LCTL | Z | X | C | V | B | N | M | COMM | DOT | QUOT | T_RCTL |
| T_LGUI | T_LALT | UP | DOWN | BSPC | TAB | ENT | SPC | LEFT | RIGHT | T_RALT | DVORAK |
|--------+--------+----+------+------+-----+-----+-----+------+-------+--------+--------|
I tried to keep my layout bare bones, just what would be available on a normal I tried to keep my layout bare bones, just what would be available on a normal
keyboard, minus some keys I never used. The bottom left copies a normal keyboard, minus some keys I never used. This one secondary layer should cover a
majority of the keys not found on the home layer. The bottom left copies a normal
keyboards symbols from shifted numbers, and the rest is placed where convenient, keyboards symbols from shifted numbers, and the rest is placed where convenient,
with some considerations for one handed use, hence the shortcuts in the top with some considerations for one handed use, hence the shortcuts in the top
left. left.
#+TODO: qwerty layer for ma friends
#+NAME: secondary-layer #+NAME: secondary-layer
|----+--------+--------+--------+--------+------+------+----+--------+--------+-----+----| |--------+--------+--------+--------+--------+------+------+-----+--------+--------+-------+--------|
| -- | EZUNDO | EZCOPY | EZCUT | EZPSTE | INS | EQL | 7 | 8 | 9 | F11 | -- | | -- | EZUNDO | EZCOPY | EZCUT | EZPSTE | INS | EQL | 7 | 8 | 9 | -- | -- |
| -- | ESC | CAPS | PGUP | PGDN | F4 | ASTR | 4 | 5 | 6 | 0 | -- | | EZSHFT | ESC | CAPS | PGUP | PGDN | HOME | ASTR | 4 | 5 | 6 | 0 | EZSHFT |
| -- | EXLM | AT | HASH | DLR | PERC | CIRC | 1 | 2 | 3 | F12 | -- | | EZCTRL | EXLM | AT | HASH | DLR | PERC | CIRC | 1 | 2 | 3 | COM | EZCTRL |
| -- | -- | EZUP | EZDOWN | -- | AMPR | PIPE | -- | EZLEFT | EZRGHT | -- | -- | | EZGUI | EZALT | EZUP | EZDOWN | SPC | AMPR | PIPE | END | EZLEFT | EZRGHT | EZALT | EZGUI |
|----+--------+--------+--------+--------+------+------+----+--------+--------+-----+----| |--------+--------+--------+--------+--------+------+------+-----+--------+--------+-------+--------|
But wait, we are missing several important keys!? yes, well, the modifier keys Basic command layer for one-shot macros and function keys.
#+NAME: command-layer
|----+-----+-----+-----+-----+--------+--------+------+-------+------+-----+----|
| -- | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | -- |
| -- | F11 | F12 | F13 | F14 | F15 | F16 | F17 | F18 | F19 | F20 | -- |
| -- | F21 | F22 | F23 | F24 | QWERTY | DVORAK | USER | EMAIL | NAME | -- | -- |
| -- | -- | -- | -- | -- | -- | -- | DIR | -- | -- | -- | -- |
|----+-----+-----+-----+-----+--------+--------+------+-------+------+-----+----|
But wait, we are missing several important keys? well, yes, but the modifier keys
all do other keys when tapped. More about that in the keymap section. all do other keys when tapped. More about that in the keymap section.
* Keymap Conversion in Python * Keymap Conversion in Python
@ -55,7 +77,7 @@ all do other keys when tapped. More about that in the keymap section.
This python can convert that table into the array needed for the keymap file. It This python can convert that table into the array needed for the keymap file. It
simply prepends every key with "KC_". I used to use a dictionary to convert some simply prepends every key with "KC_". I used to use a dictionary to convert some
keys from the table into qmk keycodes, but the double convertion was keys from the table into qmk keycodes, but the double convertion was
unneccessary so I simply prepended all my macros with KC and moved all the unneccessary so I just prepended all my macros with KC and moved all the
implementation to the `process-user-input` function. implementation to the `process-user-input` function.
#+NAME:layer-to-array #+NAME:layer-to-array
@ -84,54 +106,68 @@ return results
* keymap.c * keymap.c
Now that we have done all the hard work, lets layout our keymap file then define Now that we laid out our layout, lets lay out our kemap file.
our macros.
** Headers And Layer Declaration
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
#include QMK_KEYBOARD_H #include QMK_KEYBOARD_H
extern keymap_config_t keymap_config; extern keymap_config_t keymap_config;
static uint16_t tap_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; #+END_SRC
char last_mod = -1; ** Keycodes
enum planck_layers {
_DVORAK,
_RISE
};
#+BEGIN_SRC C :noweb yes
// where the 'T_' communicates how the key does something different when tapped. // where the 'T_' communicates how the key does something different when tapped.
enum planck_keycodes { enum planck_keycodes {
DVORAK = SAFE_RANGE, //DVORAK = SAFE_RANGE,
KC_T_LALT, KC_T_LALT = SAFE_RANGE,
KC_T_RALT, KC_T_RALT,
KC_T_LGUI, KC_T_LGUI,
KC_T_RGUI, KC_T_RGUI,
KC_T_LCTL, KC_T_LCTL,
KC_T_RCTL, KC_T_RCTL,
KC_T_LSFT, KC_T_LSFT,
KC_T_RSFT, KC_T_RSFT,
KC_T_LRSE, KC_T_LRSE,
KC_T_RRSE, KC_T_RRSE,
KC_EZRGHT, KC_EZRGHT,
KC_EZLEFT, KC_EZLEFT,
KC_EZUP, KC_EZUP,
KC_EZDOWN, KC_EZDOWN,
KC_EZUNDO, KC_EZUNDO,
KC_EZCOPY, KC_EZCOPY,
KC_EZCUT, KC_EZCUT,
KC_EZPSTE KC_EZPSTE,
KC_EZSHFT,
KC_EZCTRL,
KC_EZGUI,
KC_EZALT,
KC_DVORAK,
KC_QWERTY,
KC_USER,
KC_EMAIL,
KC_NAME,
KC_DIR,
KC_COM
};
#+END_SRC
** Import Key table
#+BEGIN_SRC C :noweb yes
enum planck_layers {
_DVORAK,
_QWERTY,
_RISE,
_COMMAND
}; };
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#+END_SRC #+END_SRC
** Import Key table
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
[_DVORAK] = [_DVORAK] =
@ -142,6 +178,16 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#+END_SRC #+END_SRC
#+BEGIN_SRC C :noweb yes
[_QWERTY] =
#+END_SRC
#+BEGIN_SRC C :noweb yes
<<layer-to-array(qwerty-layer)>>
#+END_SRC
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
[_RISE] = [_RISE] =
@ -152,50 +198,96 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#+END_SRC #+END_SRC
** Process User Input #+BEGIN_SRC C :noweb yes
*** Tap Key Functionality [_COMMAND] =
These methods define how I implemented the tap mechanic. Basically, I believe #+END_SRC
that /pressing/ any other key should be grounds for the hold functionality to be
assumed. My natuaral typing style experiences no delays from my method. #+BEGIN_SRC C :noweb yes
<<layer-to-array(command-layer)>>
#+END_SRC
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
}; };
void mod_press(uint16_t hold_code, int id) { #+END_SRC
tap_timers[id] = timer_read();
** Tap Keys
I don't like tap keys coming out on release. When modified, I often let go of
the modifier too early because the tap button doesn't come out untill release. I
guess you could save the state of the board on press and then apply it after the
timer, but what I really want is the keys to come out on press when they can and
when it is most useful. For me, that is when they are modified a single time. So
I kind "locked" the board into only doing single modifiers, making them faster.
Disadvantages are double modified keys must be done with one shot keys (its
actually not that bad, it feels like emacs!) and triple modified keys are
impossible at the moment.
#+BEGIN_SRC C :noweb yes
static uint16_t tap_timer = 0;
char last_mod = 10;
void mod_press(uint16_t tap_code, uint16_t hold_code, int id) {
// this first if body makes double modified keys impossible, but stops the
// delay when modifying a tap key which would result in the tap key not
// getting modified.
if (last_mod != id && last_mod != 10) {
tap_code16(tap_code);
last_mod = 10;
} else {
tap_timer = timer_read();
last_mod = id; last_mod = id;
register_code(hold_code); register_code(hold_code);
}
} }
void mod_lift(uint16_t tap_code, uint16_t hold_code, int id) { void mod_lift(uint16_t tap_code, uint16_t hold_code, int id) {
unregister_code(hold_code); unregister_code(hold_code);
if (last_mod == id && timer_elapsed(tap_timers[id]) < TAPPING_TERM) { if (last_mod == id && timer_elapsed(tap_timer) < TAPPING_TERM) {
tap_code16(tap_code); tap_code16(tap_code);
last_mod = -1; last_mod = 10;
} }
} }
#+END_SRC #+END_SRC
*** Set DVORAK layout ** Process User Input
The function that filter's user inputs and applies macros, the begginning is
pretty basic, setting our main layer and configuring our secondary layer.
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
bool process_record_user(uint16_t keycode, keyrecord_t *record) { bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) { switch (keycode) {
case DVORAK: #+END_SRC
if (record->event.pressed) {
** Layouts
Set Dvorak layout
#+BEGIN_SRC C :noweb yes
case KC_DVORAK:
if (record->event.pressed) {
set_single_persistent_default_layer(_DVORAK); set_single_persistent_default_layer(_DVORAK);
} }
return false; return true;
break; break;
#+END_SRC #+END_SRC
*** Alt and () Set Qwerty layout.
#+BEGIN_SRC C :noweb yes
case KC_QWERTY:
if (record->event.pressed) {
set_single_persistent_default_layer(_QWERTY);
}
return true;
break;
#+END_SRC
** Alt and ()
Left and right alt are ( and ) when tapped. I put them on alt instead of a more Left and right alt are ( and ) when tapped. I put them on alt instead of a more
conveniant key like control because parentheses do not need to be shift modified conveniant key like control because parentheses do not need to be shift modified
@ -204,24 +296,24 @@ ever, unlike some other tap keys seen in the next sections.
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
case KC_T_LALT: case KC_T_LALT:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_LALT, 0); mod_press(S(KC_9), KC_LALT, 0);
} else { } else {
mod_lift(S(KC_9), KC_LALT, 0); mod_lift(S(KC_9), KC_LALT, 0);
} }
return false; return false;
break; break;
case KC_T_RALT: case KC_T_RALT:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_RALT, 1); mod_press(S(KC_0), KC_RALT, 1);
} else { } else {
mod_lift(S(KC_0), KC_RALT, 1); mod_lift(S(KC_0), KC_RALT, 1);
} }
return false; return false;
break; break;
#+END_SRC #+END_SRC
*** Gui and `\ ** Gui and `\
I place gui in the bottom corner because I believe it is the hardest key to I place gui in the bottom corner because I believe it is the hardest key to
reach, so gui seemed like a good fit for a dedicated key that I never want to reach, so gui seemed like a good fit for a dedicated key that I never want to
@ -231,24 +323,24 @@ number pad or shifted number keys.
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
case KC_T_LGUI: case KC_T_LGUI:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_LGUI, 2); mod_press(KC_GRAVE, KC_LGUI, 2);
} else { } else {
mod_lift(KC_GRAVE, KC_LGUI, 2); mod_lift(KC_GRAVE, KC_LGUI, 2);
} }
return false; return false;
break; break;
case KC_T_RGUI: case KC_T_RGUI:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_RGUI, 3); mod_press(KC_BSLASH, KC_RGUI, 3);
} else { } else {
mod_lift(KC_BSLASH, KC_RGUI, 3); mod_lift(KC_BSLASH, KC_RGUI, 3);
} }
return false; return false;
break; break;
#+END_SRC #+END_SRC
*** Ctrl and [] ** Ctrl and []
Left and right control are [] respectively when they are tapped, making { and } Left and right control are [] respectively when they are tapped, making { and }
also very convenient. also very convenient.
@ -256,24 +348,24 @@ also very convenient.
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
case KC_T_LCTL: case KC_T_LCTL:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_LCTL, 4); mod_press(KC_LBRACKET, KC_LCTL, 4);
} else { } else {
mod_lift(KC_LBRACKET, KC_LCTL, 4); mod_lift(KC_LBRACKET, KC_LCTL, 4);
} }
return false; return false;
break; break;
case KC_T_RCTL: case KC_T_RCTL:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_RCTL, 5); mod_press(KC_RBRACKET, KC_RCTL, 5);
} else { } else {
mod_lift(KC_RBRACKET, KC_RCTL, 5); mod_lift(KC_RBRACKET, KC_RCTL, 5);
} }
return false; return false;
break; break;
#+END_SRC #+END_SRC
*** Shft and =- ** Shft and =-
I place shift on the home row, so having '-' right of my pinkie is standard, and I place shift on the home row, so having '-' right of my pinkie is standard, and
it only felt natural to put its opposite, '=/+' on the other side. I put an it only felt natural to put its opposite, '=/+' on the other side. I put an
@ -282,24 +374,24 @@ extra one on the right side in the secondary layer for the num pad.
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
case KC_T_LSFT: case KC_T_LSFT:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_LSFT, 6); mod_press(KC_EQUAL, KC_LSFT, 6);
} else { } else {
mod_lift(KC_EQUAL, KC_LSFT, 6); mod_lift(KC_EQUAL, KC_LSFT, 6);
} }
return false; return false;
break; break;
case KC_T_RSFT: case KC_T_RSFT:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_RSFT, 7); mod_press(KC_MINUS, KC_RSFT, 7);
} else { } else {
mod_lift(KC_MINUS, KC_RSFT, 7); mod_lift(KC_MINUS, KC_RSFT, 7);
} }
return false; return false;
break; break;
#+END_SRC #+END_SRC
*** Rise, DEL, and / ** Rise, DEL, and /
I use the top corners as rise because I decided that I do not like using layers I use the top corners as rise because I decided that I do not like using layers
with my thumbs. It feels uncomfortable to hold keys down with the side of my with my thumbs. It feels uncomfortable to hold keys down with the side of my
@ -315,36 +407,78 @@ corner again mimicing a standard dvorak keyboard.
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
case KC_T_LRSE: case KC_T_LRSE:
if (record->event.pressed) { if (record->event.pressed) {
tap_timers[8] = timer_read(); tap_timer = timer_read();
last_mod = 8; last_mod = 8;
layer_on(_RISE); layer_on(_RISE);
} else { } else {
layer_off(_RISE); layer_off(_RISE);
if (last_mod == 8 && timer_elapsed(tap_timers[8]) < TAPPING_TERM) { if (last_mod == 8 && timer_elapsed(tap_timer) < TAPPING_TERM) {
tap_code16(KC_DELETE); tap_code16(KC_DELETE);
last_mod = -1; last_mod = 10;
}
} }
}
return false; return false;
break; break;
case KC_T_RRSE: case KC_T_RRSE:
if (record->event.pressed) { if (record->event.pressed) {
tap_timers[9] = timer_read(); tap_timer = timer_read();
last_mod = 9; last_mod = 9;
layer_on(_RISE); layer_on(_RISE);
} else { } else {
layer_off(_RISE); layer_off(_RISE);
if (last_mod == 9 && timer_elapsed(tap_timers[9]) < TAPPING_TERM) { if (last_mod == 9 && timer_elapsed(tap_timer) < TAPPING_TERM) {
tap_code16(KC_SLASH); tap_code16(KC_SLASH);
last_mod = -1; last_mod = 10;
}
} }
}
return false; return false;
break; break;
#+END_SRC #+END_SRC
*** EZ keys ** EZ Keys
EZ or "easy" keys do things that can already be done on the board, but I want an
easier way of doing them.
*** One Shot Keys
Since I made modified tap keys occur on press instead of release, I need one
shot keys to press any key with more than one modifier.
#+BEGIN_SRC C :noweb yes
case KC_EZSHFT:
if (record->event.pressed) {
set_oneshot_mods(MOD_LSFT);
last_mod = 10;
}
return false;
break;
case KC_EZCTRL:
if (record->event.pressed) {
set_oneshot_mods(MOD_LCTL);
last_mod = 10;
}
return false;
break;
case KC_EZALT:
if (record->event.pressed) {
set_oneshot_mods(MOD_LALT);
last_mod = 10;
}
return false;
break;
case KC_EZGUI:
if (record->event.pressed) {
set_oneshot_mods(MOD_LGUI);
last_mod = 10;
}
return false;
break;
#+END_SRC
*** Arrows
I use ctrl+shift+arrows keys a lot, so when the layer key is pressed they became I use ctrl+shift+arrows keys a lot, so when the layer key is pressed they became
lazy versions of themselves with control and shift already pressed. lazy versions of themselves with control and shift already pressed.
@ -358,8 +492,8 @@ if (record->event.pressed) {
register_code(KC_LCTL); register_code(KC_LCTL);
tap_code16(S(KC_RGHT)); tap_code16(S(KC_RGHT));
unregister_code(KC_LCTL); unregister_code(KC_LCTL);
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZLEFT: case KC_EZLEFT:
@ -367,8 +501,8 @@ if (record->event.pressed) {
register_code(KC_LCTL); register_code(KC_LCTL);
tap_code16(S(KC_LEFT)); tap_code16(S(KC_LEFT));
unregister_code(KC_LCTL); unregister_code(KC_LCTL);
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZDOWN: case KC_EZDOWN:
@ -376,8 +510,8 @@ if (record->event.pressed) {
register_code(KC_LCTL); register_code(KC_LCTL);
tap_code16(S(KC_DOWN)); tap_code16(S(KC_DOWN));
unregister_code(KC_LCTL); unregister_code(KC_LCTL);
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZUP: case KC_EZUP:
@ -385,47 +519,104 @@ if (record->event.pressed) {
register_code(KC_LCTL); register_code(KC_LCTL);
tap_code16(S(KC_UP)); tap_code16(S(KC_UP));
unregister_code(KC_LCTL); unregister_code(KC_LCTL);
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
#+END_SRC
*** Undo, Copy, Cut, Paste
#+BEGIN_SRC C :noweb yes
case KC_EZUNDO: case KC_EZUNDO:
if (record->event.pressed) { if (record->event.pressed) {
tap_code16(C(KC_Z)); tap_code16(C(KC_Z));
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZCOPY: case KC_EZCOPY:
if (record->event.pressed) { if (record->event.pressed) {
tap_code16(C(KC_C)); tap_code16(C(KC_C));
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZCUT: case KC_EZCUT:
if (record->event.pressed) { if (record->event.pressed) {
tap_code16(C(KC_X)); tap_code16(C(KC_X));
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZPSTE: case KC_EZPSTE:
if (record->event.pressed) { if (record->event.pressed) {
tap_code16(C(KC_P)); tap_code16(C(KC_V));
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
#+END_SRC #+END_SRC
*** Standard inputs interupt tap ** Commands
Finally, if just a standard key is tapped, set the interupted flag. Start command layer one shot
#+BEGIN_SRC C :noweb yes #+BEGIN_SRC C :noweb yes
} case KC_COM:
last_mod = -1; if (record->event.pressed) {
return true; layer_on(_COMMAND);
set_oneshot_layer(_COMMAND, ONESHOT_START);
last_mod = 10;
} else {
clear_oneshot_layer_state (ONESHOT_PRESSED);
}
return false;
break;
#+END_SRC
Just some strings I notice that I type a lot.
#+BEGIN_SRC C :noweb yes
case KC_USER:
if (record->event.pressed) {
send_string("mhostley");
last_mod = 10;
}
return true;
break;
case KC_EMAIL:
if (record->event.pressed) {
send_string("mhostley@gmail.com");
last_mod = 10;
}
return true;
break;
case KC_NAME:
if (record->event.pressed) {
send_string("Samuel Jahnke");
last_mod = 10;
}
return true;
break;
case KC_DIR:
if (record->event.pressed) {
send_string("home/mhostley/");
last_mod = 10;
}
return true;
break;
#+END_SRC
** Standard inputs interupt tap
Finally, if just a standard key is tapped, set the interupted flag.
Keep this last.
#+BEGIN_SRC C :noweb yes
}
last_mod = 10;
return true;
} }
#+END_SRC #+END_SRC

View File

@ -2,36 +2,45 @@
extern keymap_config_t keymap_config; extern keymap_config_t keymap_config;
static uint16_t tap_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char last_mod = -1;
enum planck_layers {
_DVORAK,
_RISE
};
// where the 'T_' communicates how the key does something different when tapped. // where the 'T_' communicates how the key does something different when tapped.
enum planck_keycodes { enum planck_keycodes {
DVORAK = SAFE_RANGE, //DVORAK = SAFE_RANGE,
KC_T_LALT, KC_T_LALT = SAFE_RANGE,
KC_T_RALT, KC_T_RALT,
KC_T_LGUI, KC_T_LGUI,
KC_T_RGUI, KC_T_RGUI,
KC_T_LCTL, KC_T_LCTL,
KC_T_RCTL, KC_T_RCTL,
KC_T_LSFT, KC_T_LSFT,
KC_T_RSFT, KC_T_RSFT,
KC_T_LRSE, KC_T_LRSE,
KC_T_RRSE, KC_T_RRSE,
KC_EZRGHT, KC_EZRGHT,
KC_EZLEFT, KC_EZLEFT,
KC_EZUP, KC_EZUP,
KC_EZDOWN, KC_EZDOWN,
KC_EZUNDO, KC_EZUNDO,
KC_EZCOPY, KC_EZCOPY,
KC_EZCUT, KC_EZCUT,
KC_EZPSTE KC_EZPSTE,
KC_EZSHFT,
KC_EZCTRL,
KC_EZGUI,
KC_EZALT,
KC_DVORAK,
KC_QWERTY,
KC_USER,
KC_EMAIL,
KC_NAME,
KC_DIR,
KC_COM
};
enum planck_layers {
_DVORAK,
_QWERTY,
_RISE,
_COMMAND
}; };
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
@ -44,133 +53,197 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
{ 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} { 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}
}, },
[_QWERTY] =
{{ KC_T_LRSE, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_T_RRSE},
{ KC_T_LSFT, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_T_RSFT},
{ KC_T_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_QUOT, KC_T_RCTL},
{ 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_DVORAK}
},
[_RISE] = [_RISE] =
{{ KC_TRANSPARENT, KC_EZUNDO, KC_EZCOPY, KC_EZCUT, KC_EZPSTE, KC_INS, KC_EQL, KC_7, KC_8, KC_9, KC_F11, KC_TRANSPARENT}, {{ KC_TRANSPARENT, KC_EZUNDO, KC_EZCOPY, KC_EZCUT, KC_EZPSTE, KC_INS, KC_EQL, KC_7, KC_8, KC_9, KC_TRANSPARENT, KC_TRANSPARENT},
{ KC_TRANSPARENT, KC_ESC, KC_CAPS, KC_PGUP, KC_PGDN, KC_F4, KC_ASTR, KC_4, KC_5, KC_6, KC_0, KC_TRANSPARENT}, { KC_EZSHFT, KC_ESC, KC_CAPS, KC_PGUP, KC_PGDN, KC_HOME, KC_ASTR, KC_4, KC_5, KC_6, KC_0, KC_EZSHFT},
{ KC_TRANSPARENT, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_1, KC_2, KC_3, KC_F12, KC_TRANSPARENT}, { KC_EZCTRL, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_1, KC_2, KC_3, KC_COM, KC_EZCTRL},
{ KC_TRANSPARENT, KC_TRANSPARENT, KC_EZUP, KC_EZDOWN, KC_TRANSPARENT, KC_AMPR, KC_PIPE, KC_TRANSPARENT, KC_EZLEFT, KC_EZRGHT, KC_TRANSPARENT, KC_TRANSPARENT} { KC_EZGUI, KC_EZALT, KC_EZUP, KC_EZDOWN, KC_SPC, KC_AMPR, KC_PIPE, KC_END, KC_EZLEFT, KC_EZRGHT, KC_EZALT, KC_EZGUI}
},
[_COMMAND] =
{{ KC_TRANSPARENT, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRANSPARENT},
{ KC_TRANSPARENT, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_TRANSPARENT},
{ KC_TRANSPARENT, KC_F21, KC_F22, KC_F23, KC_F24, KC_QWERTY, KC_DVORAK, KC_USER, KC_EMAIL, KC_NAME, KC_TRANSPARENT, KC_TRANSPARENT},
{ KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_DIR, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT, KC_TRANSPARENT}
}, },
}; };
void mod_press(uint16_t hold_code, int id) { static uint16_t tap_timer = 0;
tap_timers[id] = timer_read(); char last_mod = 10;
void mod_press(uint16_t tap_code, uint16_t hold_code, int id) {
// this first if body makes double modified keys impossible, but stops the
// delay when modifying a tap key which would result in the tap key not
// getting modified.
if (last_mod != id && last_mod != 10) {
tap_code16(tap_code);
last_mod = 10;
} else {
tap_timer = timer_read();
last_mod = id; last_mod = id;
register_code(hold_code); register_code(hold_code);
}
} }
void mod_lift(uint16_t tap_code, uint16_t hold_code, int id) { void mod_lift(uint16_t tap_code, uint16_t hold_code, int id) {
unregister_code(hold_code); unregister_code(hold_code);
if (last_mod == id && timer_elapsed(tap_timers[id]) < TAPPING_TERM) { if (last_mod == id && timer_elapsed(tap_timer) < TAPPING_TERM) {
tap_code16(tap_code); tap_code16(tap_code);
last_mod = -1; last_mod = 10;
} }
} }
bool process_record_user(uint16_t keycode, keyrecord_t *record) { bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) { switch (keycode) {
case DVORAK:
if (record->event.pressed) { case KC_DVORAK:
if (record->event.pressed) {
set_single_persistent_default_layer(_DVORAK); set_single_persistent_default_layer(_DVORAK);
} }
return false; return true;
break; break;
case KC_QWERTY:
if (record->event.pressed) {
set_single_persistent_default_layer(_QWERTY);
}
return true;
break;
case KC_T_LALT: case KC_T_LALT:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_LALT, 0); mod_press(S(KC_9), KC_LALT, 0);
} else { } else {
mod_lift(S(KC_9), KC_LALT, 0); mod_lift(S(KC_9), KC_LALT, 0);
} }
return false; return false;
break; break;
case KC_T_RALT: case KC_T_RALT:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_RALT, 1); mod_press(S(KC_0), KC_RALT, 1);
} else { } else {
mod_lift(S(KC_0), KC_RALT, 1); mod_lift(S(KC_0), KC_RALT, 1);
} }
return false; return false;
break; break;
case KC_T_LGUI: case KC_T_LGUI:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_LGUI, 2); mod_press(KC_GRAVE, KC_LGUI, 2);
} else { } else {
mod_lift(KC_GRAVE, KC_LGUI, 2); mod_lift(KC_GRAVE, KC_LGUI, 2);
} }
return false; return false;
break; break;
case KC_T_RGUI: case KC_T_RGUI:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_RGUI, 3); mod_press(KC_BSLASH, KC_RGUI, 3);
} else { } else {
mod_lift(KC_BSLASH, KC_RGUI, 3); mod_lift(KC_BSLASH, KC_RGUI, 3);
} }
return false; return false;
break; break;
case KC_T_LCTL: case KC_T_LCTL:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_LCTL, 4); mod_press(KC_LBRACKET, KC_LCTL, 4);
} else { } else {
mod_lift(KC_LBRACKET, KC_LCTL, 4); mod_lift(KC_LBRACKET, KC_LCTL, 4);
} }
return false; return false;
break; break;
case KC_T_RCTL: case KC_T_RCTL:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_RCTL, 5); mod_press(KC_RBRACKET, KC_RCTL, 5);
} else { } else {
mod_lift(KC_RBRACKET, KC_RCTL, 5); mod_lift(KC_RBRACKET, KC_RCTL, 5);
} }
return false; return false;
break; break;
case KC_T_LSFT: case KC_T_LSFT:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_LSFT, 6); mod_press(KC_EQUAL, KC_LSFT, 6);
} else { } else {
mod_lift(KC_EQUAL, KC_LSFT, 6); mod_lift(KC_EQUAL, KC_LSFT, 6);
} }
return false; return false;
break; break;
case KC_T_RSFT: case KC_T_RSFT:
if (record->event.pressed) { if (record->event.pressed) {
mod_press(KC_RSFT, 7); mod_press(KC_MINUS, KC_RSFT, 7);
} else { } else {
mod_lift(KC_MINUS, KC_RSFT, 7); mod_lift(KC_MINUS, KC_RSFT, 7);
} }
return false; return false;
break; break;
case KC_T_LRSE: case KC_T_LRSE:
if (record->event.pressed) { if (record->event.pressed) {
tap_timers[8] = timer_read(); tap_timer = timer_read();
last_mod = 8; last_mod = 8;
layer_on(_RISE); layer_on(_RISE);
} else { } else {
layer_off(_RISE); layer_off(_RISE);
if (last_mod == 8 && timer_elapsed(tap_timers[8]) < TAPPING_TERM) { if (last_mod == 8 && timer_elapsed(tap_timer) < TAPPING_TERM) {
tap_code16(KC_DELETE); tap_code16(KC_DELETE);
last_mod = -1; last_mod = 10;
}
} }
}
return false; return false;
break; break;
case KC_T_RRSE: case KC_T_RRSE:
if (record->event.pressed) { if (record->event.pressed) {
tap_timers[9] = timer_read(); tap_timer = timer_read();
last_mod = 9; last_mod = 9;
layer_on(_RISE); layer_on(_RISE);
} else { } else {
layer_off(_RISE); layer_off(_RISE);
if (last_mod == 9 && timer_elapsed(tap_timers[9]) < TAPPING_TERM) { if (last_mod == 9 && timer_elapsed(tap_timer) < TAPPING_TERM) {
tap_code16(KC_SLASH); tap_code16(KC_SLASH);
last_mod = -1; last_mod = 10;
}
} }
}
return false;
break;
case KC_EZSHFT:
if (record->event.pressed) {
set_oneshot_mods(MOD_LSFT);
last_mod = 10;
}
return false;
break;
case KC_EZCTRL:
if (record->event.pressed) {
set_oneshot_mods(MOD_LCTL);
last_mod = 10;
}
return false;
break;
case KC_EZALT:
if (record->event.pressed) {
set_oneshot_mods(MOD_LALT);
last_mod = 10;
}
return false;
break;
case KC_EZGUI:
if (record->event.pressed) {
set_oneshot_mods(MOD_LGUI);
last_mod = 10;
}
return false; return false;
break; break;
@ -179,8 +252,8 @@ if (record->event.pressed) {
register_code(KC_LCTL); register_code(KC_LCTL);
tap_code16(S(KC_RGHT)); tap_code16(S(KC_RGHT));
unregister_code(KC_LCTL); unregister_code(KC_LCTL);
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZLEFT: case KC_EZLEFT:
@ -188,8 +261,8 @@ if (record->event.pressed) {
register_code(KC_LCTL); register_code(KC_LCTL);
tap_code16(S(KC_LEFT)); tap_code16(S(KC_LEFT));
unregister_code(KC_LCTL); unregister_code(KC_LCTL);
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZDOWN: case KC_EZDOWN:
@ -197,8 +270,8 @@ if (record->event.pressed) {
register_code(KC_LCTL); register_code(KC_LCTL);
tap_code16(S(KC_DOWN)); tap_code16(S(KC_DOWN));
unregister_code(KC_LCTL); unregister_code(KC_LCTL);
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZUP: case KC_EZUP:
@ -206,40 +279,81 @@ if (record->event.pressed) {
register_code(KC_LCTL); register_code(KC_LCTL);
tap_code16(S(KC_UP)); tap_code16(S(KC_UP));
unregister_code(KC_LCTL); unregister_code(KC_LCTL);
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZUNDO: case KC_EZUNDO:
if (record->event.pressed) { if (record->event.pressed) {
tap_code16(C(KC_Z)); tap_code16(C(KC_Z));
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZCOPY: case KC_EZCOPY:
if (record->event.pressed) { if (record->event.pressed) {
tap_code16(C(KC_C)); tap_code16(C(KC_C));
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZCUT: case KC_EZCUT:
if (record->event.pressed) { if (record->event.pressed) {
tap_code16(C(KC_X)); tap_code16(C(KC_X));
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
case KC_EZPSTE: case KC_EZPSTE:
if (record->event.pressed) { if (record->event.pressed) {
tap_code16(C(KC_P)); tap_code16(C(KC_V));
last_mod = -1; last_mod = 10;
} }
return false; return false;
break; break;
} case KC_COM:
last_mod = -1; if (record->event.pressed) {
return true; layer_on(_COMMAND);
set_oneshot_layer(_COMMAND, ONESHOT_START);
last_mod = 10;
} else {
clear_oneshot_layer_state (ONESHOT_PRESSED);
}
return false;
break;
case KC_USER:
if (record->event.pressed) {
send_string("mhostley");
last_mod = 10;
}
return true;
break;
case KC_EMAIL:
if (record->event.pressed) {
send_string("mhostley@gmail.com");
last_mod = 10;
}
return true;
break;
case KC_NAME:
if (record->event.pressed) {
send_string("Samuel Jahnke");
last_mod = 10;
}
return true;
break;
case KC_DIR:
if (record->event.pressed) {
send_string("home/mhostley/");
last_mod = 10;
}
return true;
break;
}
last_mod = 10;
return true;
} }