1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
|
#include "ergodox_ez.h"
#include "debug.h"
#include "action_layer.h"
#include "action_util.h"
#include "led.h"
#include "keymap_common.h"
#include "timer.h"
/*
# Why this Layout
This layout was based on Kinesis layout and other ErgoDox user layouts
available. It's target to be used on a MacOS but I'm pretty sure it can be
addapted to Windows and/or Linux easily.
## Function Key
The `fn` key work almost like it would in any other keyboard with the exception
it has a semi-sticky behavior. What does that mean?
Well, if you press the `fn` and release it, the keyboard will be put on the
_function layout_ and the next key stroke will be processed as if the `fn` key
was pressed. Aftwards, the leyout get back to _normal_. If you hold `fn` and
press any other key, when you release them, the keyboard leyout is back to
_normal_.
While pressing the `fn` with the left hand and strikeing the other keys on the
right hand is farly easy, the same cannot being said for the other keys on the
left side. So, instead of trying to do contorcionism with my left hand, I
decided to do a semi-sticky version of `fn`. This way, I can press the `fn`
key with my pinky, release it and press the `1` key to issue an `F1` to the
operating system.
## Key-Pad Key
The `key pad` key is a layout switch key. If pressed, it will put the keyboard
on the _key pad layout_ and stay there until key is pressed again.
This is used to make the keyboard behave mostly like a **num pad keyboard**.
## Notes
- Regardless in which layout you are, keys from other layouts are not
accessible. This means that if you are on the _key pad layout_, the left hand
will be pretty much unusable.
Of course that like anything else, there are exceptions to this rule.
Modifiers should remain accessible throughout the layers.
- The _shift key_ is, like the _function key_, also configured to have a sticky
behavior.
- All sticky keys have a timeout of 3 seconds.
*/
#define BASE 0
#define KEYPAD 1
#define FN 2
#define MACRO_TMUX_ESC 10
#define MACRO_SHIFT_OR_LPAREN 11
#define MACRO_SHIFT_OR_RPAREN 12
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: Base Layer
*
* ,-----------------------------------------------------. ,-----------------------------------------------------.
* | `~ | 1 | 2 | 3 | 4 | 5 | ESC | | Macro| 6 | 7 | 8 | 9 | 0 | + = |
* |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
* | Tab | Q | W | E | R | T | F16 | | F17 | Y | U | I | O | P | - _ |
* |-----------+------+------+------+------+------| Meh | | Meh |------+------+------+------+------+-----------|
* | \ (Ctrl) | A | S | D | F | G |------| |------| H | J | K | L | ; | ' " (Ctrl)|
* |-----------+------+------+------+------+------| F18 | | F19 |------+------+------+------+------+-----------|
* | LShift | Z | X | C | V | B | Hyper| | Hyper| N | M | , | . | / | RShift |
* `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
* | FN | KPAD |LCtrl | LAlt | LGui | | RGui | RAlt | RCtrl| KPAD | FN |
* `-----------------------------------' `-----------------------------------'
* ,-------------. ,-------------.
* | Left | Right| | Down | Up |
* ,------|------|------| |------+------+------.
* | | | Home | | PgUp | | |
* |Backsp| Del |------| |------| Enter| Space|
* | | | End | | PgDn | | |
* `--------------------' `--------------------'
*
* Macro = Ctrk+A Esc
* (this is used to issue the Esc key to the Tmux application)
*/
[BASE]=KEYMAP(//left half
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, MEH_T(KC_F16),
CTL_T(KC_BSLS), KC_A, KC_S, KC_D, KC_F, KC_G,
KC_FN2, KC_Z, KC_X, KC_C, KC_V, KC_B, ALL_T(KC_F18),
KC_FN1, TG(KEYPAD), KC_LCTRL, KC_LALT, KC_LGUI,
KC_LEFT, KC_RIGHT,
KC_HOME,
KC_BSPC, KC_DELT, KC_END,
//right half
M(MACRO_TMUX_ESC), KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
MEH_T(KC_F17), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_MINS,
KC_H, KC_J, KC_K, KC_L, KC_SCLN, CTL_T(KC_QUOT),
ALL_T(KC_F19), KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_FN2,
KC_RGUI, ALT_T(KC_LBRC), CTL_T(KC_RBRC), TG(KEYPAD), KC_FN1,
KC_DOWN, KC_UP,
KC_PGUP,
KC_PGDN, KC_ENT, KC_SPC),
/* Keymap 1: KeyPad Layer
*
* ,-----------------------------------------------------. ,-----------------------------------------------------.
* | | | | | | | | | BTab | Clear| / | * | ^ | ( | LeftClick |
* |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
* | M.Accel 2 | |ScrlUp| U |ScrlDn| | | | Tab | 7 | 8 | 9 | + | ) | RightClick|
* |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
* | M.Accel 1 | | L | D | R | |------| |------| 4 | 5 | 6 | - | | MidClick |
* |-----------+------+------+------+------+------| | |Return|------+------+------+------+------+-----------|
* | M.Accel 0 | |ScrlL | |ScrlR | | | | | 1 | 2 | 3 | = | | |
* `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
* | | | | | | | 0 | . | , | | KPAD |
* `-----------------------------------' `-----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*/
[KEYPAD]=KEYMAP(//left half
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO, KC_MS_WH_UP, KC_MS_U, KC_MS_WH_DOWN, KC_NO, KC_NO,
KC_NO, KC_NO, KC_MS_L, KC_MS_D, KC_MS_R, KC_NO,
KC_NO, KC_NO, KC_MS_WH_LEFT, KC_NO, KC_MS_WH_RIGHT, KC_NO, KC_NO,
KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO,
KC_NO, KC_NO,
KC_NO,
KC_NO, KC_NO, KC_NO,
//right half
LSFT(KC_TAB), KC_CLEAR, KC_KP_SLASH, KC_KP_ASTERISK, KC_CIRCUMFLEX, KC_LPRN, KC_MS_BTN1,
KC_TAB, KC_KP_7, KC_KP_8, KC_KP_9, KC_KP_PLUS, KC_RPRN, KC_MS_BTN2,
KC_KP_4, KC_KP_5, KC_KP_6, KC_KP_MINUS, KC_NO, KC_MS_BTN3,
KC_KP_ENTER, KC_KP_1, KC_KP_2, KC_KP_3, KC_KP_EQUAL, KC_NO, KC_NO,
KC_KP_0, KC_KP_DOT, KC_KP_COMMA, KC_TRNS, KC_TRNS,
KC_NO, KC_NO,
KC_NO,
KC_NO, KC_NO, KC_NO),
/* Keymap 2: Functions Layer
*
* ,-----------------------------------------------------. ,-----------------------------------------------------.
* | | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 | Vol. Up |
* |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
* | | Stop | Rw | Rec | FF | | XXXX | | XXXX | | | | | | Vol. Down |
* |-----------+------+------+------+------+------| XXXX | | XXXX |------+------+------+------+------+-----------|
* | CapsLock | Eject| Prev | Play | Next | |------| |------| Left | Down | Up | Right| | Mute |
* |-----------+------+------+------+------+------| XXXX | | XXXX |------+------+------+------+------+-----------|
* | L Shift | | | | | | XXXX | | XXXX | | | | | | R Shift |
* `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
* | XXXXX | | XXXX | XXXX | XXXX | | XXXX | XXXX | XXXX | | |
* `-----------------------------------' `-----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*
* XXX = These keys are transparent keys that, when pressed, they issue the key from the previous layer.
*/
[FN]=KEYMAP(//left half
KC_NO, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6,
KC_NO, KC_MEDIA_STOP, KC_MEDIA_REWIND, KC_MEDIA_SELECT, KC_MEDIA_FAST_FORWARD, KC_NO, KC_TRNS,
KC_CAPS, KC_MEDIA_EJECT, KC_MEDIA_PREV_TRACK, KC_MEDIA_PLAY_PAUSE, KC_MEDIA_NEXT_TRACK, KC_NO,
KC_LSFT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS,
KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS,
KC_NO, KC_NO,
KC_NO,
KC_NO, KC_NO, KC_NO,
//right half
KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_VOLU,
KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_VOLD,
KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_NO, KC_MUTE,
KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_RSFT,
KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS,
KC_NO, KC_NO,
KC_NO,
KC_NO, KC_NO, KC_NO)};
const uint16_t PROGMEM fn_actions[] = {
[1] = ACTION_LAYER_ONESHOT(FN),
[2] = ACTION_MODS_ONESHOT(MOD_LSFT), // Sticky shift light. Tap for the next keypress to be shifted. Hold for regular shift.
};
static uint16_t key_timer;
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
// MACRODOWN only works in this function
switch(id) {
case MACRO_TMUX_ESC:
if (record->event.pressed) {
return MACRO(D(LCTRL), T(A), U(LCTRL), D(ESC), END);
}
return MACRO(U(ESC), END);
case MACRO_SHIFT_OR_LPAREN: {
if (record->event.pressed) {
key_timer = timer_read(); // if the key is being pressed, we start the timer.
register_code(KC_LSFT); // we're now holding down Shift.
} else { // this means the key was just released, so we can figure out how long it was pressed for (tap or "held down").
if (timer_elapsed(key_timer) < TAPPING_TERM) { // the threshhold we pick for counting something as a tap.
register_code(KC_9); // sending 9 while Shift is held down gives us an opening paren
unregister_code(KC_9); // now let's let go of that key
}
unregister_code(KC_LSFT); // let's release the Shift key now.
}
break;
}
case MACRO_SHIFT_OR_RPAREN: {
if (record->event.pressed) {
key_timer = timer_read(); // Now we're doing the same thing, only for the right shift/close paren key
register_code(KC_RSFT);
} else {
if (timer_elapsed(key_timer) < TAPPING_TERM) {
register_code(KC_0);
unregister_code(KC_0);
}
unregister_code(KC_RSFT);
}
break;
}
}
return MACRO_NONE;
};
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
uint8_t current_layer = BASE;
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
uint8_t layer = biton32(layer_state);
ergodox_led_all_off();
ergodox_led_all_set(LED_BRIGHTNESS_LO);
switch (layer) {
case BASE:
current_layer = BASE;
break;
case KEYPAD:
current_layer = KEYPAD;
break;
default:
// none
break;
}
// layer leds
if (current_layer == KEYPAD) {
ergodox_right_led_3_on();
}
// capslock
if (host_keyboard_leds() & (3<<USB_LED_CAPS_LOCK)) {
ergodox_right_led_1_on();
}
// Temporary leds
// The function layer takes over other layers and we need to reflect that on the leds.
// If the current layer is the BASE, we simply turn on the FN led, but if the current
// layer is the KEYPAD, than we must turn it off before turning on the FN led.
if (layer == FN && !has_oneshot_layer_timed_out()) {
ergodox_right_led_3_off();
ergodox_right_led_2_on();
}
// if the shifted is pressed I show the case led in a brighter color. This is nice to
// differenciate the shift from the capslock.
// Notice that I make sure that we're not using the shift on a chord shortcut (pressing
// shift togather with other modifiers).
if((keyboard_report->mods & (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) && // is shift pressed and there is no other
!(keyboard_report->mods & (~MOD_BIT(KC_LSFT) & ~MOD_BIT(KC_RSFT)))) || // modifier being pressed as well
(get_oneshot_mods() & (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) && !has_oneshot_mods_timed_out())) { // or the one shot shift didn't timed out
ergodox_right_led_1_set(LED_BRIGHTNESS_HI);
ergodox_right_led_1_on();
}
};
|