aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGergely Nagy <algernon@madhouse-project.org>2016-08-24 13:17:01 +0200
committerGergely Nagy <algernon@madhouse-project.org>2016-08-24 23:22:57 +0200
commitf512179e66e4d4dfbcc92c6ba1aaa1b6cf1ef12b (patch)
tree982b6483c74c01ef5bad18cdf585290397e278c4
parentad206155aa6f87de3fb9f0aefe60685ec12905a8 (diff)
downloadqmk_firmware-f512179e66e4d4dfbcc92c6ba1aaa1b6cf1ef12b.tar.gz
qmk_firmware-f512179e66e4d4dfbcc92c6ba1aaa1b6cf1ef12b.zip
ergodox: Update algernon's keymap to v1.6
Major changes include: Base layer changes ------------------ * The parentheses & bracket keys have been merged: tapping them results in `[` or `{` (if it was shifted), double tapping leads to `(`. * The `:;` and `-_` keys are now available on the base layer, on their **ADORE** location, too, just below `[{(`/`]})`. * The `Apps` key has been replaced by `F12`. * The `-`/`_` is no longer a tap-dance key. ADORE layer changes ------------------- * Adjustments were made to the **ADORE** layer, to separate some inconvenient combinations. Miscellaneous changes --------------------- * `LEAD u` now starts the symbolic unicode input system, instead of the OS-one. * The mouse acceleration keys on the **Navigation and Media* layer have been turned into toggles: tap them once to turn them on, until tapped again. Tapping an accelerator button will turn all the others off. * When the **ARROW** layer is on, the *red* and *blue* LEDs light up now. Heatmap ------- * The built-in keylogger has been greatly enhanced, it now outputs the pressed state, and the layer (Dvorak or ADORE). As such, the `ADORE_AUTOLOG` option has been removed, instead there is `AUTOLOG_ENABLE` now, which when enabled, makes the keylogger start when the keyboard boots. It defaults to off. * The heatmap generator received a lot of updates. Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
-rw-r--r--keyboards/ergodox/keymaps/algernon/Makefile9
-rw-r--r--keyboards/ergodox/keymaps/algernon/images/adore-layer.pngbin93748 -> 93893 bytes
-rw-r--r--keyboards/ergodox/keymaps/algernon/images/base-layer.pngbin95222 -> 95204 bytes
-rw-r--r--keyboards/ergodox/keymaps/algernon/keymap.c494
-rw-r--r--keyboards/ergodox/keymaps/algernon/readme.md67
-rw-r--r--keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json (renamed from keyboards/ergodox/keymaps/algernon/tools/heatmap-adore-layout.json)108
-rw-r--r--keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json (renamed from keyboards/ergodox/keymaps/algernon/tools/heatmap-base-layout.json)29
-rwxr-xr-xkeyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py368
8 files changed, 552 insertions, 523 deletions
diff --git a/keyboards/ergodox/keymaps/algernon/Makefile b/keyboards/ergodox/keymaps/algernon/Makefile
index 00194857a..7c2b3ad97 100644
--- a/keyboards/ergodox/keymaps/algernon/Makefile
+++ b/keyboards/ergodox/keymaps/algernon/Makefile
@@ -1,22 +1,23 @@
1BOOTMAGIC_ENABLE=no 1BOOTMAGIC_ENABLE=no
2COMMAND_ENABLE=no 2COMMAND_ENABLE=no
3SLEEP_LED_ENABLE=no 3SLEEP_LED_ENABLE=no
4UNICODE_ENABLE=no
5FORCE_NKRO ?= yes 4FORCE_NKRO ?= yes
6DEBUG_ENABLE = no 5DEBUG_ENABLE = no
7CONSOLE_ENABLE = no 6CONSOLE_ENABLE = no
8TAP_DANCE_ENABLE = yes 7TAP_DANCE_ENABLE = yes
9KEYLOGGER_ENABLE ?= yes 8KEYLOGGER_ENABLE ?= yes
9UCIS_ENABLE = yes
10MOUSEKEY_ENABLE ?= yes
10 11
11ADORE_AUTOLOG ?= no 12AUTOLOG_ENABLE ?= no
12 13
13ifeq (${FORCE_NKRO},yes) 14ifeq (${FORCE_NKRO},yes)
14OPT_DEFS += -DFORCE_NKRO 15OPT_DEFS += -DFORCE_NKRO
15endif 16endif
16 17
17ifeq (${ADORE_AUTOLOG},yes) 18ifeq (${AUTOLOG_ENABLE},yes)
18KEYLOGGER_ENABLE = yes 19KEYLOGGER_ENABLE = yes
19OPT_DEFS += -DADORE_AUTOLOG 20OPT_DEFS += -DAUTOLOG_ENABLE
20endif 21endif
21 22
22ifeq (${KEYLOGGER_ENABLE},yes) 23ifeq (${KEYLOGGER_ENABLE},yes)
diff --git a/keyboards/ergodox/keymaps/algernon/images/adore-layer.png b/keyboards/ergodox/keymaps/algernon/images/adore-layer.png
index 44ad8a1eb..3d0a5fb20 100644
--- a/keyboards/ergodox/keymaps/algernon/images/adore-layer.png
+++ b/keyboards/ergodox/keymaps/algernon/images/adore-layer.png
Binary files differ
diff --git a/keyboards/ergodox/keymaps/algernon/images/base-layer.png b/keyboards/ergodox/keymaps/algernon/images/base-layer.png
index da159fbe2..7ea57aae3 100644
--- a/keyboards/ergodox/keymaps/algernon/images/base-layer.png
+++ b/keyboards/ergodox/keymaps/algernon/images/base-layer.png
Binary files differ
diff --git a/keyboards/ergodox/keymaps/algernon/keymap.c b/keyboards/ergodox/keymaps/algernon/keymap.c
index 144030e2e..9f476d8a6 100644
--- a/keyboards/ergodox/keymaps/algernon/keymap.c
+++ b/keyboards/ergodox/keymaps/algernon/keymap.c
@@ -2,6 +2,7 @@
2 * algernon's ErgoDox EZ layout, please see the readme.md file! 2 * algernon's ErgoDox EZ layout, please see the readme.md file!
3 */ 3 */
4 4
5#include <stdarg.h>
5#include "ergodox.h" 6#include "ergodox.h"
6#include "led.h" 7#include "led.h"
7#include "debug.h" 8#include "debug.h"
@@ -33,7 +34,6 @@ enum {
33 // Buttons that do extra stuff 34 // Buttons that do extra stuff
34 A_GUI, 35 A_GUI,
35 A_PLVR, 36 A_PLVR,
36 A_ESC,
37 A_MPN, 37 A_MPN,
38 38
39 // Function / number keys 39 // Function / number keys
@@ -47,7 +47,6 @@ enum {
47 KF_8, 47 KF_8,
48 KF_9, 48 KF_9,
49 KF_10, 49 KF_10,
50 KF_11, // =, F11
51 50
52 // Application select keys 51 // Application select keys
53 APP_SLK, // Slack 52 APP_SLK, // Slack
@@ -62,6 +61,11 @@ enum {
62 A_MDL, 61 A_MDL,
63 A_MDR, 62 A_MDR,
64 63
64 // Mouse acceleration
65 A_ACL0,
66 A_ACL1,
67 A_ACL2,
68
65 // Hungarian layer keys 69 // Hungarian layer keys
66 HU_AA, // Á 70 HU_AA, // Á
67 HU_OO, // Ó 71 HU_OO, // Ó
@@ -89,7 +93,6 @@ enum {
89 93
90enum { 94enum {
91 CT_CLN = 0, 95 CT_CLN = 0,
92 CT_MNS,
93 CT_TA, 96 CT_TA,
94 CT_LBP, 97 CT_LBP,
95 CT_RBP 98 CT_RBP
@@ -102,7 +105,11 @@ uint16_t gui_timer = 0;
102uint16_t kf_timers[12]; 105uint16_t kf_timers[12];
103 106
104#if KEYLOGGER_ENABLE 107#if KEYLOGGER_ENABLE
108# ifdef AUTOLOG_ENABLE
109bool log_enable = true;
110# else
105bool log_enable = false; 111bool log_enable = false;
112# endif
106#endif 113#endif
107 114
108bool time_travel = false; 115bool time_travel = false;
@@ -114,12 +121,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
114/* Keymap 0: Base Layer 121/* Keymap 0: Base Layer
115 * 122 *
116 * ,-----------------------------------------------------. ,-----------------------------------------------------. 123 * ,-----------------------------------------------------. ,-----------------------------------------------------.
117 * | Next/Prev | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | Apps | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 | 124 * | Next/Prev | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | F12 | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 |
118 * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------| 125 * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
119 * | ~ | ' | , | . | P | Y | [ | | ] | F | G | C | R | L | \ | 126 * | ~ | ' | , | . | P | Y | ( | | ) | F | G | C | R | L | \ |
120 * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------| 127 * |-----------+------+------+------+------+------| [ | | ] |------+------+------+------+------+-----------|
121 * | Tab/ARROW | A | O | E | U | I |------| |------| D | H | T | N | S | = / Arrow | 128 * | Tab/ARROW | A | O | E | U | I |------| |------| D | H | T | N | S | = / Arrow |
122 * |-----------+------+------+------+------+------| ( | | ) |------+------+------+------+------+-----------| 129 * |-----------+------+------+------+------+------| : | | - |------+------+------+------+------+-----------|
123 * | Play/Pause| / | Q | J | K | X | | | | B | M | W | V | Z | Stop | 130 * | Play/Pause| / | Q | J | K | X | | | | B | M | W | V | Z | Stop |
124 * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------' 131 * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
125 * | | | | | : | | - | | | | | 132 * | | | | | : | | - | | | | |
@@ -135,21 +142,21 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
135[BASE] = KEYMAP( 142[BASE] = KEYMAP(
136// left hand 143// left hand
137 M(A_MPN) ,M(KF_1) ,M(KF_2) ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR) 144 M(A_MPN) ,M(KF_1) ,M(KF_2) ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR)
138,KC_GRV ,KC_QUOT ,KC_COMM ,KC_DOT ,KC_P ,KC_Y ,KC_LBRC 145,KC_GRV ,KC_QUOT ,KC_COMM ,KC_DOT ,KC_P ,KC_Y ,TD(CT_LBP)
139,TD(CT_TA) ,KC_A ,KC_O ,KC_E ,KC_U ,KC_I 146,TD(CT_TA) ,KC_A ,KC_O ,KC_E ,KC_U ,KC_I
140,KC_MPLY ,KC_SLSH ,KC_Q ,KC_J ,KC_K ,KC_X ,KC_LPRN 147,KC_MPLY ,KC_SLSH ,KC_Q ,KC_J ,KC_K ,KC_X ,TD(CT_CLN)
141,KC_NO ,KC_NO ,KC_NO ,KC_NO ,TD(CT_CLN) 148,KC_NO ,KC_NO ,KC_NO ,KC_NO ,TD(CT_CLN)
142 149
143 ,F(F_ALT),F(F_GUI) 150 ,F(F_ALT),F(F_GUI)
144 ,F(F_CTRL) 151 ,F(F_CTRL)
145 ,KC_BSPC,F(F_SFT),M(A_ESC) 152 ,KC_BSPC,F(F_SFT),KC_ESC
146 153
147 // right hand 154 // right hand
148 ,KC_APP ,M(KF_6),M(KF_7) ,M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11 155 ,KC_F12 ,M(KF_6),M(KF_7) ,M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
149 ,KC_RBRC ,KC_F ,KC_G ,KC_C ,KC_R ,KC_L ,KC_BSLS 156 ,TD(CT_RBP),KC_F ,KC_G ,KC_C ,KC_R ,KC_L ,KC_BSLS
150 ,KC_D ,KC_H ,KC_T ,KC_N ,KC_S ,KC_EQL 157 ,KC_D ,KC_H ,KC_T ,KC_N ,KC_S ,KC_EQL
151 ,KC_RPRN ,KC_B ,KC_M ,KC_W ,KC_V ,KC_Z ,KC_MSTP 158 ,KC_MINS ,KC_B ,KC_M ,KC_W ,KC_V ,KC_Z ,KC_MSTP
152 ,TD(CT_MNS),KC_NO ,KC_NO ,KC_NO ,KC_NO 159 ,KC_MINS ,KC_NO ,KC_NO ,KC_NO ,KC_NO
153 160
154 ,OSL(NMDIA),KC_DEL 161 ,OSL(NMDIA),KC_DEL
155 ,KC_LEAD 162 ,KC_LEAD
@@ -159,13 +166,13 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
159/* Keymap 1: Adore layer 166/* Keymap 1: Adore layer
160 * 167 *
161 * ,-----------------------------------------------------. ,-----------------------------------------------------. 168 * ,-----------------------------------------------------. ,-----------------------------------------------------.
162 * | Play/Pause| 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | Apps | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 | 169 * | Play/Pause| 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | F12 | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 |
163 * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------| 170 * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
164 * | `~ | X | W | K | L | M | ( | | ) | F | H | C | P | Y | \ | 171 * | `~ | Y | W | G | L | M | ( | | ) | F | H | C | P | X | \ |
165 * |-----------+------+------+------+------+------| [ | | ] |------+------+------+------+------+-----------| 172 * |-----------+------+------+------+------+------| [ | | ] |------+------+------+------+------+-----------|
166 * | Tab/Arrow | A | O | E | I | U |------| |------| D | R | T | N | S | = | 173 * | Tab/Arrow | A | O | E | I | U |------| |------| D | R | T | N | S | = |
167 * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------| 174 * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
168 * | | Z | Q | ' | , | . | : | | - | B | G | V | J | / | | 175 * | | Z | Q | ' | , | . | : | | - | B | K | V | J | / | |
169 * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------' 176 * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
170 * | | | | | | | | | | | | 177 * | | | | | | | | | | | |
171 * `-----------------------------------' `-----------------------------------' 178 * `-----------------------------------' `-----------------------------------'
@@ -180,20 +187,20 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
180[ADORE] = KEYMAP( 187[ADORE] = KEYMAP(
181// left hand 188// left hand
182 KC_MPLY ,M(KF_1) ,M(KF_2) ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR) 189 KC_MPLY ,M(KF_1) ,M(KF_2) ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR)
183,KC_GRV ,KC_X ,KC_W ,KC_K ,KC_L ,KC_M ,TD(CT_LBP) 190,KC_GRV ,KC_Y ,KC_W ,KC_G ,KC_L ,KC_M ,TD(CT_LBP)
184,TD(CT_TA) ,KC_A ,KC_O ,KC_E ,KC_I ,KC_U 191,TD(CT_TA) ,KC_A ,KC_O ,KC_E ,KC_I ,KC_U
185,KC_NO ,KC_Z ,KC_Q ,KC_QUOT,KC_COMM,KC_DOT ,TD(CT_CLN) 192,KC_NO ,KC_Z ,KC_Q ,KC_QUOT,KC_COMM,KC_DOT ,TD(CT_CLN)
186,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO 193,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
187 194
188 ,F(F_ALT),F(F_GUI) 195 ,F(F_ALT),F(F_GUI)
189 ,F(F_CTRL) 196 ,F(F_CTRL)
190 ,KC_BSPC,F(F_SFT),M(A_ESC) 197 ,KC_BSPC,F(F_SFT),KC_ESC
191 198
192 // right hand 199 // right hand
193 ,KC_APP ,M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11 200 ,KC_F12 ,M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
194 ,TD(CT_RBP),KC_F ,KC_H ,KC_C ,KC_P ,KC_Y ,KC_BSLS 201 ,TD(CT_RBP),KC_F ,KC_H ,KC_C ,KC_P ,KC_X ,KC_BSLS
195 ,KC_D ,KC_R ,KC_T ,KC_N ,KC_S ,KC_EQL 202 ,KC_D ,KC_R ,KC_T ,KC_N ,KC_S ,KC_EQL
196 ,TD(CT_MNS),KC_B ,KC_G ,KC_V ,KC_J ,KC_SLSH ,KC_NO 203 ,KC_MINS ,KC_B ,KC_K ,KC_V ,KC_J ,KC_SLSH ,KC_NO
197 ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO 204 ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
198 205
199 ,OSL(NMDIA),KC_DEL 206 ,OSL(NMDIA),KC_DEL
@@ -363,14 +370,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
363 */ 370 */
364[NMDIA] = KEYMAP( 371[NMDIA] = KEYMAP(
365// left hand 372// left hand
366 KC_ACL0 ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,LGUI(KC_L) 373 M(A_ACL0) ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,LGUI(KC_L)
367,KC_ACL1 ,KC_NO ,KC_HOME ,KC_UP ,KC_PGUP ,KC_NO ,KC_NO 374,M(A_ACL1) ,KC_NO ,KC_HOME ,KC_UP ,KC_PGUP ,KC_NO ,KC_NO
368,KC_ACL2 ,KC_NO ,KC_LEFT ,KC_DOWN ,KC_RIGHT,KC_NO 375,M(A_ACL2) ,KC_NO ,KC_LEFT ,KC_DOWN ,KC_RIGHT,KC_NO
369,KC_MPLY ,KC_NO ,KC_END ,KC_DOWN ,KC_PGDN ,KC_NO ,KC_NO 376,KC_MPLY ,KC_NO ,KC_END ,KC_DOWN ,KC_PGDN ,KC_NO ,KC_NO
370,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO 377,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
371 ,KC_MUTE ,KC_VOLU 378 ,KC_MUTE ,KC_VOLU
372 ,KC_VOLD 379 ,KC_VOLD
373 ,KC_SPC,KC_ENTER,M(A_ESC) 380 ,KC_SPC,KC_ENTER,KC_ESC
374 381
375 // right hand 382 // right hand
376 ,LGUI(KC_L),KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO 383 ,LGUI(KC_L),KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
@@ -439,7 +446,7 @@ const uint16_t PROGMEM fn_actions[] = {
439 ,[F_CTRL] = ACTION_MODS_ONESHOT (MOD_LCTL) 446 ,[F_CTRL] = ACTION_MODS_ONESHOT (MOD_LCTL)
440}; 447};
441 448
442void toggle_steno(int pressed) 449static void toggle_steno(int pressed)
443{ 450{
444 uint8_t layer = biton32(layer_state); 451 uint8_t layer = biton32(layer_state);
445 452
@@ -462,7 +469,7 @@ void toggle_steno(int pressed)
462 } 469 }
463} 470}
464 471
465macro_t *ang_do_hun (keyrecord_t *record, uint16_t accent, uint16_t hun_char) 472static macro_t *ang_do_hun (keyrecord_t *record, uint16_t accent, uint16_t hun_char)
466{ 473{
467 uint8_t need_shift = 0; 474 uint8_t need_shift = 0;
468 uint8_t hold_shift = 0; 475 uint8_t hold_shift = 0;
@@ -507,46 +514,43 @@ macro_t *ang_do_hun (keyrecord_t *record, uint16_t accent, uint16_t hun_char)
507 return MACRO_NONE; 514 return MACRO_NONE;
508} 515}
509 516
510void ang_handle_kf (keyrecord_t *record, uint8_t id) 517static bool from_appsel;
518
519static void ang_handle_kf (keyrecord_t *record, uint8_t id)
511{ 520{
512 uint8_t code = id - KF_1; 521 uint8_t code = id - KF_1;
513 522
514 if (record->event.pressed) { 523 if (record->event.pressed) {
515 kf_timers[code] = timer_read (); 524 kf_timers[code] = timer_read ();
516 } else { 525 } else {
517 uint8_t kc; 526 uint8_t kc_base;
518 527
519 if (timer_elapsed (kf_timers[code]) > TAPPING_TERM) { 528 if (from_appsel) {
529 from_appsel = false;
530 return;
531 }
532
533 if (kf_timers[code] && timer_elapsed (kf_timers[code]) > TAPPING_TERM) {
520 // Long press 534 // Long press
521 kc = KC_F1 + code; 535 kc_base = KC_F1;
522 } else { 536 } else {
523 if (id == KF_11) 537 kc_base = KC_1;
524 kc = KC_EQL;
525 else
526 kc = KC_1 + code;
527 } 538 }
539 kf_timers[code] = 0;
540 code += kc_base;
528 541
529 register_code (kc); 542 register_code (code);
530 unregister_code (kc); 543 unregister_code (code);
531 } 544 }
532} 545}
533 546
547static struct {
548 uint8_t idx;
549} m_accel_state;
550
534const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) 551const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
535{ 552{
536 switch(id) { 553 switch(id) {
537 case A_ESC:
538 if (record->event.pressed) {
539 if ((get_oneshot_mods ()) && !has_oneshot_mods_timed_out ()) {
540 clear_oneshot_mods ();
541 } else {
542 register_code (KC_ESC);
543 }
544 layer_off (HUN);
545 } else {
546 unregister_code (KC_ESC);
547 }
548 break;
549
550 case A_MPN: 554 case A_MPN:
551 if (record->event.pressed) { 555 if (record->event.pressed) {
552 if (keyboard_report->mods & MOD_BIT(KC_LSFT) || 556 if (keyboard_report->mods & MOD_BIT(KC_LSFT) ||
@@ -588,6 +592,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
588 case HU_UEE: 592 case HU_UEE:
589 return ang_do_hun (record, KC_EQL, KC_U); 593 return ang_do_hun (record, KC_EQL, KC_U);
590 594
595#if MOUSEKEY_ENABLE
591 /* Mouse movement */ 596 /* Mouse movement */
592 case A_MUL: 597 case A_MUL:
593 if (record->event.pressed) { 598 if (record->event.pressed) {
@@ -633,6 +638,24 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
633 mousekey_send(); 638 mousekey_send();
634 break; 639 break;
635 640
641 case A_ACL0 ... A_ACL2:
642 if (record->event.pressed) {
643 uint8_t idx = id - A_ACL0;
644 if (m_accel_state.idx == id) {
645 mousekey_off(m_accel_state.idx - A_ACL0 + KC_ACL0);
646 m_accel_state.idx = 0;
647 } else {
648 if (m_accel_state.idx) {
649 mousekey_off(m_accel_state.idx - A_ACL0 + KC_ACL0);
650 m_accel_state.idx = 0;
651 }
652 mousekey_on(KC_ACL0 + idx);
653 m_accel_state.idx = id;
654 }
655 }
656 break;
657#endif
658
636 /* Plover base */ 659 /* Plover base */
637 case A_PLVR: 660 case A_PLVR:
638 toggle_steno(record->event.pressed); 661 toggle_steno(record->event.pressed);
@@ -663,22 +686,34 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
663 break; 686 break;
664 687
665 case APP_SLK: 688 case APP_SLK:
689 from_appsel = true;
666 return MACRODOWN(T(S), T(L), T(A), T(C), T(K), T(ENT), END); 690 return MACRODOWN(T(S), T(L), T(A), T(C), T(K), T(ENT), END);
667 691
668 case APP_EMCS: 692 case APP_EMCS:
693 from_appsel = true;
669 return MACRODOWN(T(G), T(N), T(U), T(SPC), T(E), T(M), T(A), T(C), T(S), T(SPC), T(2), T(4), T(ENT), END); 694 return MACRODOWN(T(G), T(N), T(U), T(SPC), T(E), T(M), T(A), T(C), T(S), T(SPC), T(2), T(4), T(ENT), END);
670 695
671 case APP_TERM: 696 case APP_TERM:
672 return MACRODOWN(T(T), T(E), T(R), T(M), T(ENT), END); 697 from_appsel = true;
698 if (!record->event.pressed) {
699 register_code(KC_ESC);
700 unregister_code(KC_ESC);
701 wait_ms(TAPPING_TERM + 25);
702 register_code(KC_DEL);
703 unregister_code(KC_DEL);
704 }
705 break;
673 706
674 case APP_CHRM: 707 case APP_CHRM:
708 from_appsel = true;
675 return MACRODOWN(T(C), T(H), T(R), T(O), T(M), T(ENT), END); 709 return MACRODOWN(T(C), T(H), T(R), T(O), T(M), T(ENT), END);
676 710
677 case APP_MSIC: 711 case APP_MSIC:
712 from_appsel = true;
678 return MACRODOWN(T(R), T(H), T(Y), T(T), T(H), T(M), T(B), T(O), T(X), T(ENT), END); 713 return MACRODOWN(T(R), T(H), T(Y), T(T), T(H), T(M), T(B), T(O), T(X), T(ENT), END);
679 714
680 /* Function keys */ 715 /* Function keys */
681 case KF_1 ... KF_11: 716 case KF_1 ... KF_10:
682 ang_handle_kf (record, id); 717 ang_handle_kf (record, id);
683 break; 718 break;
684 } 719 }
@@ -686,12 +721,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
686 return MACRO_NONE; 721 return MACRO_NONE;
687}; 722};
688 723
689uint8_t is_adore = 0; 724static uint8_t is_adore = 0;
690 725
691// Runs just one time when the keyboard initializes. 726// Runs just one time when the keyboard initializes.
692void matrix_init_user(void) { 727void matrix_init_user(void) {
693 uint8_t dl; 728 uint8_t dl;
694 729
730 set_unicode_input_mode(UC_LNX);
731
695 ergodox_led_all_on(); 732 ergodox_led_all_on();
696 for (int i = LED_BRIGHTNESS_HI; i > LED_BRIGHTNESS_LO; i--) { 733 for (int i = LED_BRIGHTNESS_HI; i > LED_BRIGHTNESS_LO; i--) {
697 ergodox_led_all_set (i); 734 ergodox_led_all_set (i);
@@ -709,120 +746,38 @@ void matrix_init_user(void) {
709 dl = eeconfig_read_default_layer (); 746 dl = eeconfig_read_default_layer ();
710 if (dl == (1UL << ADORE)) { 747 if (dl == (1UL << ADORE)) {
711 is_adore = 1; 748 is_adore = 1;
712#if ADORE_AUTOLOG
713 log_enable = true;
714#endif
715 } 749 }
716}; 750};
717 751
718LEADER_EXTERNS(); 752LEADER_EXTERNS();
719 753
720void ang_do_unicode (void) { 754static void ang_tap (uint8_t code, ...) {
721 register_code (KC_RCTL); 755 uint8_t kc = code;
722 register_code (KC_RSFT); 756 va_list ap;
723 register_code (KC_U);
724 unregister_code (KC_U);
725 unregister_code (KC_RSFT);
726 unregister_code (KC_RCTL);
727 wait_ms (100);
728}
729 757
730void ang_tap (uint16_t codes[]) { 758 va_start(ap, code);
731 for (int i = 0; codes[i] != 0; i++) { 759
732 register_code (codes[i]); 760 do {
733 unregister_code (codes[i]); 761 register_code(kc);
734 wait_ms (50); 762 unregister_code(kc);
735 } 763 wait_ms(50);
764 kc = va_arg(ap, int);
765 } while (kc != 0);
766 va_end(ap);
736} 767}
737 768
738#define TAP_ONCE(code) \ 769#define TAP_ONCE(code) \
739 register_code (code); \ 770 register_code (code); \
740 unregister_code (code) 771 unregister_code (code)
741 772
742void ang_tap_dance_bp_finished (qk_tap_dance_state_t *state, void *user_data) {
743 bool left, parens;
744
745 if (state->count > 2) {
746 state->count = 0;
747 return;
748 }
749
750 if (state->keycode == TD(CT_LBP))
751 left = true;
752 else
753 left = false;
754
755 if (state->count == 1)
756 parens = false;
757 else
758 parens = true;
759
760 if (parens) {
761 register_code (KC_RSFT);
762 if (left) {
763 TAP_ONCE(KC_9);
764 } else {
765 TAP_ONCE(KC_0);
766 }
767 unregister_code (KC_RSFT);
768 } else {
769 if (left) {
770 TAP_ONCE (KC_LBRC);
771 } else {
772 TAP_ONCE (KC_RBRC);
773 }
774 }
775}
776
777void ang_tap_dance_cln_finished (qk_tap_dance_state_t *state, void *user_data) {
778 if (state->count == 1) {
779 register_code (KC_RSFT);
780 register_code (KC_SCLN);
781 } else if (state->count == 2) {
782 register_code (KC_SCLN);
783 }
784}
785
786void ang_tap_dance_cln_reset (qk_tap_dance_state_t *state, void *user_data) {
787 if (state->count == 1) {
788 unregister_code (KC_SCLN);
789 unregister_code (KC_RSFT);
790 } else if (state->count == 2) {
791 unregister_code (KC_SCLN);
792 }
793}
794
795void ang_tap_dance_mns_finished (qk_tap_dance_state_t *state, void *user_data) {
796 if (state->count == 1) {
797 register_code (KC_MINS);
798 } else if (state->count == 2) {
799 register_code (KC_RSFT);
800 register_code (KC_MINS);
801 }
802}
803
804void ang_tap_dance_mns_reset (qk_tap_dance_state_t *state, void *user_data) {
805 if (state->count == 1) {
806 unregister_code (KC_MINS);
807 } else if (state->count == 2) {
808 unregister_code (KC_RSFT);
809 unregister_code (KC_MINS);
810 }
811}
812
813typedef struct { 773typedef struct {
814 bool layer_toggle; 774 bool layer_toggle;
815 bool sticky; 775 bool sticky;
816 bool finished_once;
817} td_ta_state_t; 776} td_ta_state_t;
818 777
819void ang_tap_dance_ta_finished (qk_tap_dance_state_t *state, void *user_data) { 778static void ang_tap_dance_ta_finished (qk_tap_dance_state_t *state, void *user_data) {
820 td_ta_state_t *td_ta = (td_ta_state_t *) user_data; 779 td_ta_state_t *td_ta = (td_ta_state_t *) user_data;
821 780
822 if (td_ta->finished_once) {
823 return;
824 }
825
826 if (td_ta->sticky) { 781 if (td_ta->sticky) {
827 td_ta->sticky = false; 782 td_ta->sticky = false;
828 td_ta->layer_toggle = false; 783 td_ta->layer_toggle = false;
@@ -830,7 +785,6 @@ void ang_tap_dance_ta_finished (qk_tap_dance_state_t *state, void *user_data) {
830 return; 785 return;
831 } 786 }
832 787
833 td_ta->finished_once = true;
834 if (state->count == 1 && !state->pressed) { 788 if (state->count == 1 && !state->pressed) {
835 register_code (KC_TAB); 789 register_code (KC_TAB);
836 td_ta->sticky = false; 790 td_ta->sticky = false;
@@ -842,35 +796,29 @@ void ang_tap_dance_ta_finished (qk_tap_dance_state_t *state, void *user_data) {
842 } 796 }
843} 797}
844 798
845void ang_tap_dance_ta_reset (qk_tap_dance_state_t *state, void *user_data) { 799static void ang_tap_dance_ta_reset (qk_tap_dance_state_t *state, void *user_data) {
846 td_ta_state_t *td_ta = (td_ta_state_t *) user_data; 800 td_ta_state_t *td_ta = (td_ta_state_t *) user_data;
847 801
848 if (!td_ta->layer_toggle) 802 if (!td_ta->layer_toggle)
849 unregister_code (KC_TAB); 803 unregister_code (KC_TAB);
850 if (!td_ta->sticky) 804 if (!td_ta->sticky)
851 layer_off (ARRW); 805 layer_off (ARRW);
852
853 td_ta->finished_once = false;
854} 806}
855 807
856qk_tap_dance_action_t tap_dance_actions[] = { 808qk_tap_dance_action_t tap_dance_actions[] = {
857 [CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, ang_tap_dance_cln_finished, ang_tap_dance_cln_reset) 809 [CT_CLN] = ACTION_TAP_DANCE_DOUBLE (KC_COLN, KC_SCLN)
858 ,[CT_MNS] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, ang_tap_dance_mns_finished, ang_tap_dance_mns_reset)
859 ,[CT_TA] = { 810 ,[CT_TA] = {
860 .fn = { NULL, ang_tap_dance_ta_finished, ang_tap_dance_ta_reset }, 811 .fn = { NULL, ang_tap_dance_ta_finished, ang_tap_dance_ta_reset },
861 .user_data = (void *)&((td_ta_state_t) { false, false, false }) 812 .user_data = (void *)&((td_ta_state_t) { false, false })
862 } 813 }
863 ,[CT_LBP] = ACTION_TAP_DANCE_FN (ang_tap_dance_bp_finished) 814 ,[CT_LBP] = ACTION_TAP_DANCE_DOUBLE (KC_LBRC, KC_LPRN)
864 ,[CT_RBP] = ACTION_TAP_DANCE_FN (ang_tap_dance_bp_finished) 815 ,[CT_RBP] = ACTION_TAP_DANCE_DOUBLE (KC_RBRC, KC_RPRN)
865}; 816};
866 817
867static uint16_t uni[32];
868static uint8_t unicnt;
869static bool unimagic = false;
870
871// Runs constantly in the background, in a loop. 818// Runs constantly in the background, in a loop.
872void matrix_scan_user(void) { 819void matrix_scan_user(void) {
873 uint8_t layer = biton32(layer_state); 820 uint8_t layer = biton32(layer_state);
821 bool is_arrow = false;
874 822
875 if (gui_timer && timer_elapsed (gui_timer) > TAPPING_TERM) 823 if (gui_timer && timer_elapsed (gui_timer) > TAPPING_TERM)
876 unregister_code (KC_LGUI); 824 unregister_code (KC_LGUI);
@@ -893,13 +841,19 @@ void matrix_scan_user(void) {
893 ergodox_right_led_2_set (LED_BRIGHTNESS_HI); 841 ergodox_right_led_2_set (LED_BRIGHTNESS_HI);
894 } 842 }
895 843
844 if (layer_state & (1UL << ARRW)) {
845 ergodox_right_led_1_on ();
846 ergodox_right_led_3_on ();
847 is_arrow = true;
848 }
849
896 if (keyboard_report->mods & MOD_BIT(KC_LSFT) || 850 if (keyboard_report->mods & MOD_BIT(KC_LSFT) ||
897 ((get_oneshot_mods() & MOD_BIT(KC_LSFT)) && !has_oneshot_mods_timed_out())) { 851 ((get_oneshot_mods() & MOD_BIT(KC_LSFT)) && !has_oneshot_mods_timed_out())) {
898 ergodox_right_led_1_set (LED_BRIGHTNESS_HI); 852 ergodox_right_led_1_set (LED_BRIGHTNESS_HI);
899 ergodox_right_led_1_on (); 853 ergodox_right_led_1_on ();
900 } else { 854 } else {
901 ergodox_right_led_1_set (LED_BRIGHTNESS_LO); 855 ergodox_right_led_1_set (LED_BRIGHTNESS_LO);
902 if (layer != NMDIA && layer != PLVR && layer != ADORE) 856 if (layer != NMDIA && layer != PLVR && layer != ADORE && !is_arrow)
903 ergodox_right_led_1_off (); 857 ergodox_right_led_1_off ();
904 } 858 }
905 859
@@ -919,7 +873,7 @@ void matrix_scan_user(void) {
919 ergodox_right_led_3_on (); 873 ergodox_right_led_3_on ();
920 } else { 874 } else {
921 ergodox_right_led_3_set (LED_BRIGHTNESS_LO); 875 ergodox_right_led_3_set (LED_BRIGHTNESS_LO);
922 if (layer != HUN && layer != PLVR && layer != ADORE) 876 if (layer != HUN && layer != PLVR && layer != ADORE && !is_arrow)
923 ergodox_right_led_3_off (); 877 ergodox_right_led_3_off ();
924 } 878 }
925 879
@@ -936,20 +890,17 @@ void matrix_scan_user(void) {
936 } 890 }
937#endif 891#endif
938 892
893 SEQ_ONE_KEY (KC_Q) {
894 register_code16 (LCTL(KC_1));
895 unregister_code16 (LCTL(KC_1));
896 }
897
939 SEQ_ONE_KEY (KC_T) { 898 SEQ_ONE_KEY (KC_T) {
940 time_travel = !time_travel; 899 time_travel = !time_travel;
941 } 900 }
942 901
943 SEQ_ONE_KEY (KC_U) { 902 SEQ_ONE_KEY (KC_U) {
944 ang_do_unicode (); 903 qk_ucis_start();
945 }
946
947 SEQ_TWO_KEYS (KC_LEAD, KC_U) {
948 unicnt = 0;
949 unimagic = true;
950 register_code(KC_RSFT);
951 TAP_ONCE(KC_U);
952 unregister_code(KC_RSFT);
953 } 904 }
954 905
955 SEQ_ONE_KEY (KC_V) { 906 SEQ_ONE_KEY (KC_V) {
@@ -958,25 +909,23 @@ void matrix_scan_user(void) {
958 909
959 SEQ_ONE_KEY (KC_L) { 910 SEQ_ONE_KEY (KC_L) {
960 /* λ */ 911 /* λ */
961 ang_do_unicode (); 912 unicode_input_start();
962 913 register_hex(0x03bb);
963 uint16_t codes[] = {KC_0, KC_3, KC_B, KC_B, KC_ENT, 0}; 914 unicode_input_finish();
964 ang_tap (codes);
965 } 915 }
966 916
967 SEQ_ONE_KEY (KC_Y) { 917 SEQ_ONE_KEY (KC_Y) {
968 uint16_t codes[] = {KC_BSLS, KC_O, KC_SLSH, 0}; 918 ang_tap (KC_BSLS, KC_O, KC_SLSH, 0);
969 ang_tap (codes);
970 } 919 }
971 920
972 SEQ_ONE_KEY (KC_S) { 921 SEQ_ONE_KEY (KC_S) {
973 ang_do_unicode (); TAP_ONCE (KC_A); TAP_ONCE (KC_F); TAP_ONCE (KC_SPC); 922 unicode_input_start(); register_hex(0xaf); unicode_input_finish();
974 TAP_ONCE (KC_BSLS); 923 TAP_ONCE (KC_BSLS);
975 register_code (KC_RSFT); TAP_ONCE (KC_MINS); TAP_ONCE (KC_9); unregister_code (KC_RSFT); 924 register_code (KC_RSFT); TAP_ONCE (KC_MINS); TAP_ONCE (KC_9); unregister_code (KC_RSFT);
976 ang_do_unicode (); TAP_ONCE (KC_3); TAP_ONCE (KC_0); TAP_ONCE (KC_C); TAP_ONCE (KC_4); TAP_ONCE (KC_SPC); 925 unicode_input_start (); register_hex(0x30c4); unicode_input_finish();
977 register_code (KC_RSFT); TAP_ONCE (KC_0); TAP_ONCE (KC_MINS); unregister_code (KC_RSFT); 926 register_code (KC_RSFT); TAP_ONCE (KC_0); TAP_ONCE (KC_MINS); unregister_code (KC_RSFT);
978 TAP_ONCE (KC_SLSH); 927 TAP_ONCE (KC_SLSH);
979 ang_do_unicode (); TAP_ONCE (KC_A); TAP_ONCE (KC_F); TAP_ONCE (KC_SPC); 928 unicode_input_start (); register_hex(0xaf); unicode_input_finish();
980 } 929 }
981 930
982 SEQ_TWO_KEYS (KC_W, KC_M) { 931 SEQ_TWO_KEYS (KC_W, KC_M) {
@@ -987,8 +936,7 @@ void matrix_scan_user(void) {
987 936
988 wait_ms (1000); 937 wait_ms (1000);
989 938
990 uint16_t codes[] = {KC_M, KC_A, KC_X, KC_MINS, KC_F, KC_O, KC_C, KC_U, KC_S, KC_E, KC_D, KC_ENT, 0}; 939 ang_tap (KC_M, KC_A, KC_X, KC_MINS, KC_F, KC_O, KC_C, KC_U, KC_S, KC_E, KC_D, KC_ENT, 0);
991 ang_tap (codes);
992 register_code (KC_LGUI); 940 register_code (KC_LGUI);
993 register_code (KC_UP); 941 register_code (KC_UP);
994 unregister_code (KC_UP); 942 unregister_code (KC_UP);
@@ -1013,13 +961,7 @@ void matrix_scan_user(void) {
1013 ergodox_right_led_2_off (); 961 ergodox_right_led_2_off ();
1014 wait_ms (100); 962 wait_ms (100);
1015 ergodox_right_led_1_off (); 963 ergodox_right_led_1_off ();
1016#if ADORE_AUTOLOG
1017 log_enable = true;
1018#endif
1019 } else { 964 } else {
1020#if ADORE_AUTOLOG
1021 log_enable = false;
1022#endif
1023 is_adore = 0; 965 is_adore = 0;
1024 default_layer_and (0); 966 default_layer_and (0);
1025 default_layer_or (1UL << BASE); 967 default_layer_or (1UL << BASE);
@@ -1043,140 +985,38 @@ void matrix_scan_user(void) {
1043 985
1044static uint16_t last4[4]; 986static uint16_t last4[4];
1045 987
1046bool is_uni_seq(char *seq) { 988const qk_ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE
1047 uint8_t i; 989(
1048 990 UCIS_SYM("poop", 0x1f4a9),
1049 for (i = 0; seq[i]; i++) { 991 UCIS_SYM("rofl", 0x1f923),
1050 uint16_t code; 992 UCIS_SYM("kiss", 0x1f619),
1051 if (('1' <= seq[i]) && (seq[i] <= '9')) 993 UCIS_SYM("snowman", 0x2603),
1052 code = seq[i] - '1' + KC_1; 994 UCIS_SYM("coffee", 0x2615),
1053 else if (seq[i] == '0') 995 UCIS_SYM("heart", 0x2764),
1054 code = KC_0; 996 UCIS_SYM("bolt", 0x26a1)
1055 else 997);
1056 code = seq[i] - 'a' + KC_A;
1057
1058 if (i > unicnt)
1059 return false;
1060 if (uni[i] != code)
1061 return false;
1062 }
1063
1064 if (uni[i] == KC_ENT || uni[i] == KC_SPC)
1065 return true;
1066
1067 return false;
1068}
1069
1070uint16_t hex_to_keycode(uint8_t hex)
1071{
1072 if (hex == 0x0) {
1073 return KC_0;
1074 } else if (hex < 0xA) {
1075 return KC_1 + (hex - 0x1);
1076 } else {
1077 return KC_A + (hex - 0xA);
1078 }
1079}
1080
1081void register_hex(uint16_t hex) {
1082 bool leading_zeros = true;
1083
1084 for(int i = 3; i >= 0; i--) {
1085 uint8_t digit = ((hex >> (i*4)) & 0xF);
1086 if (digit != 0)
1087 leading_zeros = false;
1088 else if (leading_zeros)
1089 continue;
1090 register_code(hex_to_keycode(digit));
1091 unregister_code(hex_to_keycode(digit));
1092 wait_ms(10);
1093 }
1094}
1095
1096typedef struct {
1097 char *symbol;
1098 uint16_t codes[4];
1099} qk_ucis_symbol_t;
1100
1101static qk_ucis_symbol_t ucis_symbol_table[] = {
1102 {"poop", {0x1, 0xf4a9, 0}},
1103 {"rofl", {0x1, 0xf923, 0}},
1104 {"kiss", {0x1, 0xf619, 0}},
1105 {"snowman", {0x2603, 0}},
1106 {NULL, {}}
1107};
1108
1109bool process_record_ucis (uint16_t keycode, keyrecord_t *record) {
1110 uint8_t i;
1111
1112 if (!unimagic)
1113 return true;
1114
1115 if (!record->event.pressed)
1116 return true;
1117
1118 uni[unicnt] = keycode;
1119 unicnt++;
1120
1121 if (keycode == KC_BSPC) {
1122 if (unicnt >= 2) {
1123 unicnt-= 2;
1124 return true;
1125 } else {
1126 unicnt--;
1127 return false;
1128 }
1129 }
1130
1131 if (keycode == KC_ENT || keycode == KC_SPC) {
1132 bool symbol_found = false;
1133
1134 for (i = unicnt; i > 0; i--) {
1135 register_code (KC_BSPC);
1136 unregister_code (KC_BSPC);
1137 wait_ms(10);
1138 }
1139
1140 ang_do_unicode();
1141 wait_ms(10);
1142 for (i = 0; ucis_symbol_table[i].symbol; i++) {
1143 if (is_uni_seq (ucis_symbol_table[i].symbol)) {
1144 symbol_found = true;
1145 for (uint8_t j = 0; ucis_symbol_table[i].codes[j]; j++) {
1146 register_hex(ucis_symbol_table[i].codes[j]);
1147 }
1148 break;
1149 }
1150 }
1151 if (!symbol_found) {
1152 for (i = 0; i < unicnt - 1; i++) {
1153 uint8_t code;
1154
1155 if (uni[i] > KF_1)
1156 code = uni[i] - KF_1 + KC_1;
1157 else
1158 code = uni[i];
1159 TAP_ONCE(code);
1160 wait_ms (10);
1161 }
1162 }
1163
1164 unimagic = false;
1165 return true;
1166 }
1167 return true;
1168}
1169 998
1170bool process_record_user (uint16_t keycode, keyrecord_t *record) { 999bool process_record_user (uint16_t keycode, keyrecord_t *record) {
1171#if KEYLOGGER_ENABLE 1000#if KEYLOGGER_ENABLE
1172 if (log_enable) { 1001 if (log_enable) {
1173 xprintf ("KL: col=%d, row=%d\n", record->event.key.col, 1002 xprintf ("KL: col=%02d, row=%02d, pressed=%d, layer=%s\n", record->event.key.col,
1174 record->event.key.row); 1003 record->event.key.row, record->event.pressed, (is_adore) ? "ADORE" : "Dvorak");
1175 } 1004 }
1176#endif 1005#endif
1177 1006
1178 if (!process_record_ucis (keycode, record)) 1007 if (keycode == KC_ESC && record->event.pressed) {
1179 return false; 1008 bool queue = true;
1009
1010 if ((get_oneshot_mods ()) && !has_oneshot_mods_timed_out ()) {
1011 clear_oneshot_mods ();
1012 queue = false;
1013 }
1014 if (layer_state & (1UL<<HUN)) {
1015 layer_off (HUN);
1016 queue = false;
1017 }
1018 return queue;
1019 }
1180 1020
1181 if (time_travel && !record->event.pressed) { 1021 if (time_travel && !record->event.pressed) {
1182 uint8_t p; 1022 uint8_t p;
@@ -1188,15 +1028,13 @@ bool process_record_user (uint16_t keycode, keyrecord_t *record) {
1188 last4[3] = keycode; 1028 last4[3] = keycode;
1189 1029
1190 if (last4[0] == KC_D && last4[1] == KC_A && last4[2] == KC_T && last4[3] == KC_E) { 1030 if (last4[0] == KC_D && last4[1] == KC_A && last4[2] == KC_T && last4[3] == KC_E) {
1191 uint16_t codes[] = {KC_E, KC_SPC, KC_MINS, KC_D, KC_SPC, KC_QUOT, 0}; 1031 ang_tap (KC_E, KC_SPC, KC_MINS, KC_D, KC_SPC, KC_QUOT, 0);
1192 ang_tap (codes);
1193 register_code (KC_RSFT); 1032 register_code (KC_RSFT);
1194 register_code (KC_EQL); 1033 register_code (KC_EQL);
1195 unregister_code (KC_EQL); 1034 unregister_code (KC_EQL);
1196 unregister_code (KC_RSFT); 1035 unregister_code (KC_RSFT);
1197 1036
1198 uint16_t codes2[] = {KC_4, KC_SPC, KC_D, KC_A, KC_Y, KC_S, KC_QUOT, 0}; 1037 ang_tap (KC_4, KC_SPC, KC_D, KC_A, KC_Y, KC_S, KC_QUOT, 0);
1199 ang_tap (codes2);
1200 1038
1201 return false; 1039 return false;
1202 } 1040 }
@@ -1204,3 +1042,17 @@ bool process_record_user (uint16_t keycode, keyrecord_t *record) {
1204 1042
1205 return true; 1043 return true;
1206} 1044}
1045
1046void qk_ucis_symbol_fallback (void) {
1047 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
1048 uint8_t code;
1049
1050 if (qk_ucis_state.codes[i] > KF_1)
1051 code = qk_ucis_state.codes[i] - KF_1 + KC_1;
1052 else
1053 code = qk_ucis_state.codes[i];
1054 register_code(code);
1055 unregister_code(code);
1056 wait_ms (10);
1057 }
1058}
diff --git a/keyboards/ergodox/keymaps/algernon/readme.md b/keyboards/ergodox/keymaps/algernon/readme.md
index 26dfddbe6..5e7adb332 100644
--- a/keyboards/ergodox/keymaps/algernon/readme.md
+++ b/keyboards/ergodox/keymaps/algernon/readme.md
@@ -3,11 +3,15 @@
3algernon's layout 3algernon's layout
4======================= 4=======================
5 5
6This is an unconventional layout for the ErgoDox EZ. For more details about the history of the layout, see my [blog posts about my ErgoDox journey][blog-ergodox]. 6This is an unconventional layout for the [ErgoDox EZ][ez]. For more details about the history of the layout, see my [blog posts about my ErgoDox journey][blog-ergodox].
7 7
8 [ez]: https://ergodox-ez.com/
8 [blog-ergodox]: https://asylum.madhouse-project.org/blog/tags/ergodox/ 9 [blog-ergodox]: https://asylum.madhouse-project.org/blog/tags/ergodox/
9 10
10Some of the things in the layout only work when one uses Spacemacs and GNOME under Linux. Your mileage may vary. 11Some of the things in the layout only work when one uses [Spacemacs][spacemacs] and [GNOME][gnome] under Linux. Your mileage may vary.
12
13 [spacemacs]: http://spacemacs.org/
14 [gnome]: https://www.gnome.org/
11 15
12## Table of Contents 16## Table of Contents
13 17
@@ -40,10 +44,10 @@ At its core, this is a Dvorak layout, with some minor changes. The more interest
40* The `GUI` key is special, because when I double-tap it, it sends `GUI + w`, which pops up an application selector. It also switches to a one-shot layer, where the number row on the left half turns into app selector macros, for the most common things I usually want to switch to. Otherwise it behaves as on a normal layout. 44* The `GUI` key is special, because when I double-tap it, it sends `GUI + w`, which pops up an application selector. It also switches to a one-shot layer, where the number row on the left half turns into app selector macros, for the most common things I usually want to switch to. Otherwise it behaves as on a normal layout.
41* The `ESC` key also doubles as a one-shot cancel key: if tapped while any of the one-shot modifiers are in-flight (as in, single-tapped, and not expired yet), it cancels all one-shot modifiers. It also cancels the **Hun** layer, if active. Otherwise it sends the usual keycode. 45* The `ESC` key also doubles as a one-shot cancel key: if tapped while any of the one-shot modifiers are in-flight (as in, single-tapped, and not expired yet), it cancels all one-shot modifiers. It also cancels the **Hun** layer, if active. Otherwise it sends the usual keycode.
42* The **Media** and **Hun** layer keys are one-shot, the **STENO** key is a toggle. 46* The **Media** and **Hun** layer keys are one-shot, the **STENO** key is a toggle.
43* When holding any of the **Arrow** layer keys, the arrow layer activates while the layer key is held. Tapping the key produces the normal key. 47* When holding the `Tab`/**Arrow** key, the arrow layer activates while the key is held. Tapping the key produces the normal, `Tab` key. Double-tapping it toggles the **Arrow** layer on until a third tap.
44* Tapping the `:` key once yields `:`, tapping it twice yields `;`. 48* Tapping the `:` key once yields `:`, tapping it twice yields `;`.
49* Tapping the `[{(`/`)}]` keys once yields `[` (or `{` when shifted), tapping them twice yields `(`.
45* The **Lead** key allows me to type in a sequence of keys, and trigger some actions: 50* The **Lead** key allows me to type in a sequence of keys, and trigger some actions:
46 - `LEAD u` enters unicode input mode, by sending the GTK+ key sequence that does this.
47 - `LEAD l` uses the unicode input method to enter a `λ`. 51 - `LEAD l` uses the unicode input method to enter a `λ`.
48 - `LEAD s` does a lot of magic to type in a shruggie: `¯\_(ツ)_/¯` 52 - `LEAD s` does a lot of magic to type in a shruggie: `¯\_(ツ)_/¯`
49 - `LEAD y` types `\o/`. 53 - `LEAD y` types `\o/`.
@@ -52,7 +56,7 @@ At its core, this is a Dvorak layout, with some minor changes. The more interest
52 - `LEAD v` prints the firmware version, the keyboard and the keymap. 56 - `LEAD v` prints the firmware version, the keyboard and the keymap.
53 - `LEAD d` toggles logging keypress positions to the HID console. 57 - `LEAD d` toggles logging keypress positions to the HID console.
54 - `LEAD t` toggles time travel. Figuring out the current `date` is left as an exercise to the reader. 58 - `LEAD t` toggles time travel. Figuring out the current `date` is left as an exercise to the reader.
55 - `LEAD LEAD u` enters the [Unicode symbol input][#unicode-symbol-input] mode. 59 - `LEAD u` enters the [Unicode symbol input](#unicode-symbol-input) mode.
56 60
57## ADORE layer 61## ADORE layer
58 62
@@ -91,6 +95,7 @@ For the layers, the following rules apply:
91* When the [ADORE layer](#adore-layer) is toggled on, LEDs will light up from left to right in a sequence, then turn off. When the layer is toggled off, the LEDs light up and turn off in the other direction. No LEDs are on while the layer is active. 95* When the [ADORE layer](#adore-layer) is toggled on, LEDs will light up from left to right in a sequence, then turn off. When the layer is toggled off, the LEDs light up and turn off in the other direction. No LEDs are on while the layer is active.
92* When the [Hungarian layer](#hungarian-layer) is active, the *green* and *blue* LEDs are on. 96* When the [Hungarian layer](#hungarian-layer) is active, the *green* and *blue* LEDs are on.
93* When the [Navigation and media layer](#navigation-and-media-layer) is active, the *red* and *green* ones are on. 97* When the [Navigation and media layer](#navigation-and-media-layer) is active, the *red* and *green* ones are on.
98* When the **ARROW** layer is active, the *red* and *blue* ones are on.
94* For the [Steno layer](#steno-layer), all LEDs will be turned on. 99* For the [Steno layer](#steno-layer), all LEDs will be turned on.
95 100
96Unless noted otherwise, the layers use a dim light for the LEDs, while modifiers use a stronger one, and modifiers override any layer preferences. For example, when on the one-handed layer, with the left side active (*red* light blinking), if `Shift` is on, the *red* light will be constantly on. 101Unless noted otherwise, the layers use a dim light for the LEDs, while modifiers use a stronger one, and modifiers override any layer preferences. For example, when on the one-handed layer, with the left side active (*red* light blinking), if `Shift` is on, the *red* light will be constantly on.
@@ -116,7 +121,7 @@ This is an experimental feature, and may or may not work reliably.
116 121
117When the keypress logging functionality is enabled (by `LEAD d`), the keyboard will output a line every time a key is pressed, containing the position of the key in the matrix. This allows one to collect this information, and build analytics over it, such as a heat map, including dead keys too. 122When the keypress logging functionality is enabled (by `LEAD d`), the keyboard will output a line every time a key is pressed, containing the position of the key in the matrix. This allows one to collect this information, and build analytics over it, such as a heat map, including dead keys too.
118 123
119Included with the firmware is a small tool that can parse these logs, and create a heatmap that one can import into [KLE][kle]. To use it, simply point `tools/log-to-heatmap.py` to a base layout file (one is included in the `tools/` directory), and the key position log. The latter one can create by running `hid-listen`, and redirecting its output to a file. 124Included with the firmware is a small tool that can parse these logs, and create a heatmap that one can import into [KLE][kle]. To use it, either pipe the output of `hid_listen` into it, or pipe it an already saved log, and it will save the results into files in an output directory (given on the command-line). See the output of `tools/log-to-heatmap.py --help` for more information.
120 125
121 [kle]: http://www.keyboard-layout-editor.com/ 126 [kle]: http://www.keyboard-layout-editor.com/
122 127
@@ -151,7 +156,35 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
151 156
152# Changelog 157# Changelog
153 158
154## v1.5 - 2016-08-12 159## v1.6
160
161*2016-08-24*
162
163### Base layer changes
164
165* The parentheses & bracket keys have been merged: tapping them results in `[` or `{` (if it was shifted), double tapping leads to `(`.
166* The `:;` and `-_` keys are now available on the base layer, on their [ADORE](#adore-layer) location, too, just below `[{(`/`]})`.
167* The `Apps` key has been replaced by `F12`.
168* The `-`/`_` is no longer a tap-dance key.
169
170### ADORE layer changes
171
172* Adjustments were made to the [ADORE](#adore-layer) layer, to separate some inconvenient combinations.
173
174### Miscellaneous changes
175
176* `LEAD u` now starts the symbolic unicode input system, instead of the OS-one.
177* The mouse acceleration keys on the [Navigation and Media](#navigation-and-media-layer) layer have been turned into toggles: tap them once to turn them on, until tapped again. Tapping an accelerator button will turn all the others off.
178* When the **ARROW** layer is on, the *red* and *blue* LEDs light up now.
179
180### Heatmap
181
182* The built-in keylogger has been greatly enhanced, it now outputs the pressed state, and the layer (Dvorak or ADORE). As such, the `ADORE_AUTOLOG` option has been removed, instead there is `AUTOLOG_ENABLE` now, which when enabled, makes the keylogger start when the keyboard boots. It defaults to off.
183* The heatmap generator received a lot of updates.
184
185## v1.5
186
187*2016-08-12*
155 188
156* The **1HAND** layer has been removed. 189* The **1HAND** layer has been removed.
157* A `Delete` key is now available on the right thumb cluster. 190* A `Delete` key is now available on the right thumb cluster.
@@ -161,7 +194,9 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
161* On the **ARROW** layer, `Backspace` has been replaced by `Enter`. 194* On the **ARROW** layer, `Backspace` has been replaced by `Enter`.
162* There is some experimental support for entering Unicode symbols. 195* There is some experimental support for entering Unicode symbols.
163 196
164## v1.4 - 2016-07-29 197## v1.4
198
199*2016-07-29*
165 200
166* When toggling the key logging on or off, the LEDs will do a little dance. 201* When toggling the key logging on or off, the LEDs will do a little dance.
167* The keylogger is now optional, but enabled by default. Use `KEYLOGGER_ENABLE=no` on the `make` command line to disable it. 202* The keylogger is now optional, but enabled by default. Use `KEYLOGGER_ENABLE=no` on the `make` command line to disable it.
@@ -169,14 +204,18 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
169* The `-`/`_` key was turned into a tap-dance key too. 204* The `-`/`_` key was turned into a tap-dance key too.
170* There is now a way to travel time with the keyboard, toggle the feature on by hitting `LEAD t`. 205* There is now a way to travel time with the keyboard, toggle the feature on by hitting `LEAD t`.
171 206
172## v1.3 - 2016-07-06 207## v1.3
208
209*2016-07-06*
173 210
174* Added support for logging keys, by pressing `LEAD d`. Also included is a tool to generate a [heatmap](#heatmap) out of the logs. 211* Added support for logging keys, by pressing `LEAD d`. Also included is a tool to generate a [heatmap](#heatmap) out of the logs.
175* The arrow and navigation keys were rearranged again, and now require an additional key being held to activate. See the [base layer](#base-layer) for an image that shows where arrows are. 212* The arrow and navigation keys were rearranged again, and now require an additional key being held to activate. See the [base layer](#base-layer) for an image that shows where arrows are.
176* The **experimental** layer has been redone, and is now called [ADORE](#adore-layer), and as such, can be enabled by `LEAD a` now. 213* The **experimental** layer has been redone, and is now called [ADORE](#adore-layer), and as such, can be enabled by `LEAD a` now.
177* Switching between Dvorak and ADORE is now persisted into EEPROM, and survives a reboot. 214* Switching between Dvorak and ADORE is now persisted into EEPROM, and survives a reboot.
178 215
179## v1.2 - 2016-06-22 216## v1.2
217
218*2016-06-22*
180 219
181* The forced NKRO mode can be easily toggled off at compile-time, to make the firmware compatible with [certain operating systems](#using-on-windows). 220* The forced NKRO mode can be easily toggled off at compile-time, to make the firmware compatible with [certain operating systems](#using-on-windows).
182* The `:;` key has changed behaviour: to access the `;` symbol, the key needs to be double-tapped, instead of shifted. 221* The `:;` key has changed behaviour: to access the `;` symbol, the key needs to be double-tapped, instead of shifted.
@@ -187,7 +226,9 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
187* On the **experimental** layer, the `L` and `Q`, and the `K` and `G` keys were swapped. 226* On the **experimental** layer, the `L` and `Q`, and the `K` and `G` keys were swapped.
188* The [Steno](#steno-layer) layer gained a few more `#` and `*` keys, to make it easier on my fingers. 227* The [Steno](#steno-layer) layer gained a few more `#` and `*` keys, to make it easier on my fingers.
189 228
190## v1.1 - 2016-06-14 229## v1.1
230
231*2016-06-14*
191 232
192* The keyboard starts in NKRO mode, bootmagic and other things are disabled. 233* The keyboard starts in NKRO mode, bootmagic and other things are disabled.
193* A [Steno](#steno-layer) layer was added, to be used with Plover. 234* A [Steno](#steno-layer) layer was added, to be used with Plover.
@@ -201,7 +242,9 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
201 - `:` now inputs `;` when shifted. 242 - `:` now inputs `;` when shifted.
202* `ESC` cancels the [Hungarian](#hungarian-layer) layer too, not just modifiers. 243* `ESC` cancels the [Hungarian](#hungarian-layer) layer too, not just modifiers.
203 244
204## v1.0 - 2016-05-26 245## v1.0
246
247*2016-05-26*
205 248
206Initial version. 249Initial version.
207 250
diff --git a/keyboards/ergodox/keymaps/algernon/tools/heatmap-adore-layout.json b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json
index 544f61ce8..4dfa877a7 100644
--- a/keyboards/ergodox/keymaps/algernon/tools/heatmap-adore-layout.json
+++ b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json
@@ -75,9 +75,9 @@
75 "STENO", 75 "STENO",
76 { 76 {
77 "x": 4.5, 77 "x": 4.5,
78 "f": 6 78 "f": 3
79 }, 79 },
80 "<i class='mss mss-Unicode-Option-3'></i>", 80 "F12",
81 { 81 {
82 "c": "#7adabd", 82 "c": "#7adabd",
83 "a": 4, 83 "a": 4,
@@ -94,12 +94,20 @@
94 { 94 {
95 "y": -0.875, 95 "y": -0.875,
96 "c": "#ffb2d2", 96 "c": "#ffb2d2",
97 "f": 3, 97 "f": 9,
98 "a": 6,
98 "w": 1.5 99 "w": 1.5
99 }, 100 },
100 "\n\n~\n`", 101 "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>",
101 { 102 {
102 "t": "#0d0d0b" 103 "t": "#0d0d0b",
104 "f": 3,
105 "a": 4,
106 "fa": [
107 0,
108 0,
109 2
110 ]
103 }, 111 },
104 "!\n1\nF1", 112 "!\n1\nF1",
105 { 113 {
@@ -120,7 +128,7 @@
120 "t": "#000000", 128 "t": "#000000",
121 "a": 6 129 "a": 6
122 }, 130 },
123 "L", 131 "G",
124 { 132 {
125 "x": 10.5 133 "x": 10.5
126 }, 134 },
@@ -132,16 +140,16 @@
132 "x": 2.5, 140 "x": 2.5,
133 "c": "#bfbad1", 141 "c": "#bfbad1",
134 "t": "#0d0d0b", 142 "t": "#0d0d0b",
135 "a": 4 143 "a": 6
136 }, 144 },
137 ">\n.", 145 "W",
138 { 146 {
139 "x": 1, 147 "x": 1,
140 "c": "#7adabd", 148 "c": "#7adabd",
141 "t": "#000000", 149 "t": "#000000",
142 "a": 6 150 "a": 6
143 }, 151 },
144 "W", 152 "L",
145 { 153 {
146 "x": 8.5 154 "x": 8.5
147 }, 155 },
@@ -164,14 +172,15 @@
164 { 172 {
165 "c": "#93c9b7", 173 "c": "#93c9b7",
166 "a": 4, 174 "a": 4,
175 "fa": [0, 0, 0],
167 "h": 1.5 176 "h": 1.5
168 }, 177 },
169 "{\n[", 178 "{\n(\n[",
170 { 179 {
171 "x": 4.5, 180 "x": 4.5,
172 "h": 1.5 181 "h": 1.5
173 }, 182 },
174 "}\n]", 183 "}\n)\n]",
175 { 184 {
176 "c": "#7adabd", 185 "c": "#7adabd",
177 "a": 6 186 "a": 6
@@ -183,21 +192,22 @@
183 "y": -0.875, 192 "y": -0.875,
184 "c": "#ffb07b", 193 "c": "#ffb07b",
185 "t": "#0d0d0b", 194 "t": "#0d0d0b",
186 "f": 6, 195 "f": 3,
196 "a": 4,
187 "w": 1.5 197 "w": 1.5
188 }, 198 },
189 "<i class='fa fa-fast-backward'></i>\n\n<i class='fa fa-fast-forward'></i>", 199 "\n\n~\n`",
190 { 200 {
191 "c": "#ffb2d2", 201 "c": "#ffb2d2",
192 "a": 4, 202 "a": 6,
193 "f": 3 203 "f": 3
194 }, 204 },
195 "<\n,", 205 "Y",
196 { 206 {
197 "x": 14.5, 207 "x": 14.5,
198 "a": 6 208 "a": 6
199 }, 209 },
200 "Y", 210 "X",
201 { 211 {
202 "a": 4, 212 "a": 4,
203 "w": 1.5 213 "w": 1.5
@@ -300,15 +310,14 @@
300 "x": 6.5, 310 "x": 6.5,
301 "c": "#93c9b7", 311 "c": "#93c9b7",
302 "t": "#000000", 312 "t": "#000000",
303 "a": 7,
304 "h": 1.5 313 "h": 1.5
305 }, 314 },
306 "(", 315 ";\n:",
307 { 316 {
308 "x": 4.5, 317 "x": 4.5,
309 "h": 1.5 318 "h": 1.5
310 }, 319 },
311 ")" 320 "_\n-"
312 ], 321 ],
313 [ 322 [
314 { 323 {
@@ -320,7 +329,9 @@
320 }, 329 },
321 "\"\n'", 330 "\"\n'",
322 { 331 {
323 "x": 10.5 332 "x": 10.5,
333 "a": 6,
334 "f": 3
324 }, 335 },
325 "V" 336 "V"
326 ], 337 ],
@@ -329,19 +340,22 @@
329 "y": -0.875, 340 "y": -0.875,
330 "x": 2.5, 341 "x": 2.5,
331 "c": "#bfbad1", 342 "c": "#bfbad1",
332 "t": "#0d0d0b" 343 "t": "#0d0d0b",
344 "a": 6
333 }, 345 },
334 "Z", 346 "Q",
335 { 347 {
336 "x": 1, 348 "x": 1,
337 "c": "#7adabd", 349 "c": "#7adabd",
338 "t": "#000000" 350 "t": "#000000",
351 "a": 4
339 }, 352 },
340 "K", 353 "<\n,",
341 { 354 {
342 "x": 8.5 355 "x": 8.5,
356 "a": 6
343 }, 357 },
344 "G", 358 "K",
345 { 359 {
346 "x": 1, 360 "x": 1,
347 "c": "#bfbad1", 361 "c": "#bfbad1",
@@ -354,11 +368,13 @@
354 "y": -0.875, 368 "y": -0.875,
355 "x": 5.5, 369 "x": 5.5,
356 "c": "#7adabd", 370 "c": "#7adabd",
357 "t": "#000000" 371 "t": "#000000",
372 "a": 4
358 }, 373 },
359 "X", 374 ">\n.",
360 { 375 {
361 "x": 6.5 376 "x": 6.5,
377 "a": 6
362 }, 378 },
363 "B" 379 "B"
364 ], 380 ],
@@ -367,28 +383,32 @@
367 "y": -0.875, 383 "y": -0.875,
368 "c": "#ffb07b", 384 "c": "#ffb07b",
369 "f": 9, 385 "f": 9,
370 "w": 1.5 386 "w": 1.5,
387 "g": true
371 }, 388 },
372 "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>", 389 "",
373 { 390 {
374 "c": "#ffb2d2", 391 "c": "#ffb2d2",
375 "t": "#0d0d0b", 392 "t": "#0d0d0b",
376 "a": 4, 393 "a": 6,
377 "f": 3 394 "f": 3,
395 "g": false
378 }, 396 },
379 "?\n/", 397 "Z",
380 { 398 {
381 "x": 14.5, 399 "x": 14.5,
382 "a": 6 400 "a": 4
383 }, 401 },
384 "Q", 402 "?\n/",
385 { 403 {
386 "c": "#ffb07b", 404 "c": "#ffb07b",
387 "t": "#000000", 405 "t": "#000000",
388 "f": 9, 406 "f": 9,
389 "w": 1.5 407 "g": true,
408 "w": 1.5,
409 "a": 4
390 }, 410 },
391 "<i class='kb kb-Multimedia-Stop'></i>" 411 ""
392 ], 412 ],
393 [ 413 [
394 { 414 {
@@ -414,14 +434,14 @@
414 { 434 {
415 "x": 1, 435 "x": 1,
416 "c": "#d4872a", 436 "c": "#d4872a",
417 "g": false, 437 "g": true,
418 "a": 5 438 "a": 5
419 }, 439 },
420 ";\n:", 440 "",
421 { 441 {
422 "x": 8.5 442 "x": 8.5
423 }, 443 },
424 "_\n-", 444 "",
425 { 445 {
426 "x": 1, 446 "x": 1,
427 "c": "#d9dae0", 447 "c": "#d9dae0",
@@ -503,13 +523,13 @@
503 }, 523 },
504 "MEDIA", 524 "MEDIA",
505 {}, 525 {},
506 "1HAND" 526 "DEL"
507 ], 527 ],
508 [ 528 [
509 { 529 {
510 "x": -3 530 "x": -3
511 }, 531 },
512 "LEAD", 532 "HUN",
513 { 533 {
514 "c": "#d4872a", 534 "c": "#d4872a",
515 "f": 9, 535 "f": 9,
@@ -528,6 +548,6 @@
528 "c": "#f9cd31", 548 "c": "#f9cd31",
529 "f": 2 549 "f": 2
530 }, 550 },
531 "HUN" 551 "LEAD"
532 ] 552 ]
533] 553]
diff --git a/keyboards/ergodox/keymaps/algernon/tools/heatmap-base-layout.json b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json
index 148bb1f23..1248d36af 100644
--- a/keyboards/ergodox/keymaps/algernon/tools/heatmap-base-layout.json
+++ b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json
@@ -75,9 +75,9 @@
75 "STENO", 75 "STENO",
76 { 76 {
77 "x": 4.5, 77 "x": 4.5,
78 "f": 6 78 "f": 3
79 }, 79 },
80 "<i class='mss mss-Unicode-Option-3'></i>", 80 "F12",
81 { 81 {
82 "c": "#7adabd", 82 "c": "#7adabd",
83 "a": 4, 83 "a": 4,
@@ -94,12 +94,21 @@
94 { 94 {
95 "y": -0.875, 95 "y": -0.875,
96 "c": "#ffb2d2", 96 "c": "#ffb2d2",
97 "f": 3, 97 "f": 6,
98 "a": 6,
98 "w": 1.5 99 "w": 1.5
99 }, 100 },
100 "\n\n~\n`", 101 "<i class='fa fa-fast-backward'></i>\n\n<i class='fa fa-fast-forward'></i>",
101 { 102 {
102 "t": "#0d0d0b" 103 "f": 3,
104 "t": "#0d0d0b",
105 "a": 4,
106 "fa": [
107 0,
108 0,
109 2
110 ]
111
103 }, 112 },
104 "!\n1\nF1", 113 "!\n1\nF1",
105 { 114 {
@@ -167,12 +176,12 @@
167 "a": 4, 176 "a": 4,
168 "h": 1.5 177 "h": 1.5
169 }, 178 },
170 "{\n[", 179 "{\n(\n[",
171 { 180 {
172 "x": 4.5, 181 "x": 4.5,
173 "h": 1.5 182 "h": 1.5
174 }, 183 },
175 "}\n]", 184 "}\n)\n]",
176 { 185 {
177 "c": "#7adabd", 186 "c": "#7adabd",
178 "a": 6 187 "a": 6
@@ -184,10 +193,10 @@
184 "y": -0.875, 193 "y": -0.875,
185 "c": "#ffb07b", 194 "c": "#ffb07b",
186 "t": "#0d0d0b", 195 "t": "#0d0d0b",
187 "f": 6, 196 "f": 3,
188 "w": 1.5 197 "w": 1.5
189 }, 198 },
190 "<i class='fa fa-fast-backward'></i>\n\n<i class='fa fa-fast-forward'></i>", 199 "\n\n~\n`",
191 { 200 {
192 "c": "#ffb2d2", 201 "c": "#ffb2d2",
193 "a": 4, 202 "a": 4,
@@ -503,7 +512,7 @@
503 }, 512 },
504 "MEDIA", 513 "MEDIA",
505 {}, 514 {},
506 "1HAND" 515 "DEL"
507 ], 516 ],
508 [ 517 [
509 { 518 {
diff --git a/keyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py b/keyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py
index a13d12e81..68585843b 100755
--- a/keyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py
+++ b/keyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py
@@ -3,143 +3,247 @@ import json
3import os 3import os
4import sys 4import sys
5import re 5import re
6import argparse
6 7
7from math import floor 8from math import floor
9from os.path import dirname
10
11class Heatmap(object):
12 coords = [
13 [
14 # Row 0
15 [ 4, 0], [ 4, 2], [ 2, 0], [ 1, 0], [ 2, 2], [ 3, 0], [ 3, 2],
16 [ 3, 4], [ 3, 6], [ 2, 4], [ 1, 2], [ 2, 6], [ 4, 4], [ 4, 6],
17 ],
18 [
19 # Row 1
20 [ 8, 0], [ 8, 2], [ 6, 0], [ 5, 0], [ 6, 2], [ 7, 0], [ 7, 2],
21 [ 7, 4], [ 7, 6], [ 6, 4], [ 5, 2], [ 6, 6], [ 8, 4], [ 8, 6],
22 ],
23 [
24 # Row 2
25 [12, 0], [12, 2], [10, 0], [ 9, 0], [10, 2], [11, 0], [ ],
26 [ ], [11, 2], [10, 4], [ 9, 2], [10, 6], [12, 4], [12, 6],
27 ],
28 [
29 # Row 3
30 [17, 0], [17, 2], [15, 0], [14, 0], [15, 2], [16, 0], [13, 0],
31 [13, 2], [16, 2], [15, 4], [14, 2], [15, 6], [17, 4], [17, 6],
32 ],
33 [
34 # Row 4
35 [20, 0], [20, 2], [19, 0], [18, 0], [19, 2], [], [], [], [],
36 [19, 4], [18, 2], [19, 6], [20, 4], [20, 6],
37 ],
38 [
39 # Row 5
40 [ ], [23, 0], [22, 2], [22, 0], [22, 4], [21, 0], [21, 2],
41 [24, 0], [24, 2], [25, 0], [25, 4], [25, 2], [26, 0], [ ],
42 ],
43 ]
44
45 def set_attr_at(self, block, n, attr, fn, val):
46 blk = self.heatmap[block][n]
47 if attr in blk:
48 blk[attr] = fn(blk[attr], val)
49 else:
50 blk[attr] = fn(None, val)
51
52 def coord(self, col, row):
53 return self.coords[row][col]
54
55 @staticmethod
56 def set_attr(orig, new):
57 return new
58
59 def set_bg(self, (block, n), color):
60 self.set_attr_at(block, n, "c", self.set_attr, color)
61 #self.set_attr_at(block, n, "g", self.set_attr, False)
62
63 def set_tap_info(self, (block, n), count, cap):
64 def _set_tap_info(o, _count, _cap):
65 ns = 4 - o.count ("\n")
66 return o + "\n" * ns + "%.02f%%" % (float(_count) / float(_cap) * 100)
67
68 if not cap:
69 cap = 1
70 self.heatmap[block][n + 1] = _set_tap_info (self.heatmap[block][n + 1], count, cap)
71
72 @staticmethod
73 def heatmap_color (v):
74 colors = [ [0.3, 0.3, 1], [0.3, 1, 0.3], [1, 1, 0.3], [1, 0.3, 0.3]]
75 fb = 0
76 if v <= 0:
77 idx1, idx2 = 0, 0
78 elif v >= 1:
79 idx1, idx2 = len(colors) - 1, len(colors) - 1
80 else:
81 val = v * (len(colors) - 1)
82 idx1 = int(floor(val))
83 idx2 = idx1 + 1
84 fb = val - float(idx1)
85
86 r = (colors[idx2][0] - colors[idx1][0]) * fb + colors[idx1][0]
87 g = (colors[idx2][1] - colors[idx1][1]) * fb + colors[idx1][1]
88 b = (colors[idx2][2] - colors[idx1][2]) * fb + colors[idx1][2]
89
90 r, g, b = [x * 255 for x in r, g, b]
91 return "#%02x%02x%02x" % (r, g, b)
92
93 def __init__(self, layout):
94 self.log = {}
95 self.total = 0
96 self.max_cnt = 0
97 self.layout = layout
98
99 def update_log(self, (c, r)):
100 if not (c, r) in self.log:
101 self.log[(c, r)] = 0
102 self.log[(c, r)] = self.log[(c, r)] + 1
103 self.total = self.total + 1
104 if self.max_cnt < self.log[(c, r)]:
105 self.max_cnt = self.log[(c, r)]
106
107 def get_heatmap(self):
108 with open("%s/heatmap-layout.%s.json" % (dirname(sys.argv[0]), self.layout), "r") as f:
109 self.heatmap = json.load (f)
110
111 ## Reset colors
112 for row in self.coords:
113 for coord in row:
114 if coord != []:
115 self.set_bg (coord, "#d9dae0")
116
117 for (c, r) in self.log:
118 coords = self.coord(c, r)
119 b, n = coords
120 cap = self.max_cnt
121 if cap == 0:
122 cap = 1
123 v = float(self.log[(c, r)]) / cap
124 self.set_bg (coords, self.heatmap_color (v))
125 self.set_tap_info (coords, self.log[(c, r)], self.total)
126 return self.heatmap
127
128 def get_stats(self):
129 usage = [
130 # left hand
131 [0, 0, 0, 0, 0],
132 # right hand
133 [0, 0, 0, 0, 0]
134 ]
135 finger_map = [0, 0, 1, 2, 3, 4, 4]
136 for (c, r) in self.log:
137 if r == 5: # thumb cluster
138 if c <= 6: # left side
139 usage[0][4] = usage[0][4] + self.log[(c, r)]
140 else:
141 usage[1][4] = usage[1][4] + self.log[(c, r)]
142 else:
143 fc = c
144 hand = 0
145 if fc >= 7:
146 fc = fc - 7
147 hand = 1
148 fm = finger_map[fc]
149 usage[hand][fm] = usage[hand][fm] + self.log[(c, r)]
150 hand_usage = [0, 0]
151 for f in usage[0]:
152 hand_usage[0] = hand_usage[0] + f
153 for f in usage[1]:
154 hand_usage[1] = hand_usage[1] + f
155
156 total = self.total
157 if total == 0:
158 total = 1
159 stats = {
160 "hands": {
161 "left": {
162 "usage": float(hand_usage[0]) / total * 100,
163 "fingers": {
164 "0 - pinky": 0,
165 "1 - ring": 0,
166 "2 - middle": 0,
167 "3 - index": 0,
168 "4 - thumb": 0,
169 }
170 },
171 "right": {
172 "usage": float(hand_usage[1]) / total * 100,
173 "fingers": {
174 "0 - thumb": 0,
175 "1 - index": 0,
176 "2 - middle": 0,
177 "3 - ring": 0,
178 "4 - pinky": 0,
179 }
180 },
181 }
182 }
183
184 hmap = ['left', 'right']
185 fmap = ['0 - pinky', '1 - ring', '2 - middle', '3 - index', '4 - thumb',
186 '0 - thumb', '1 - index', '2 - middle', '3 - ring', '4 - pinky']
187 for hand_idx in range(len(usage)):
188 hand = usage[hand_idx]
189 for finger_idx in range(len(hand)):
190 stats['hands'][hmap[hand_idx]]['fingers'][fmap[finger_idx + hand_idx * 5]] = float(hand[finger_idx]) / total * 100
191 return stats
192
193def dump_all(out_dir, heatmaps):
194 for layer in heatmaps.keys():
195 if len(heatmaps[layer].log) == 0:
196 continue
8 197
9cr_coord_map = [ 198 with open ("%s/%s.json" % (out_dir, layer), "w") as f:
10 [ 199 json.dump(heatmaps[layer].get_heatmap(), f)
11 # Row 0 200 print >>sys.stderr, "%s stats:" % (layer)
12 [ 4, 0], [ 4, 2], [ 2, 0], [ 1, 0], [ 2, 2], [ 3, 0], [ 3, 2], 201 json.dump (heatmaps[layer].get_stats(), sys.stderr,
13 [ 3, 4], [ 3, 6], [ 2, 4], [ 1, 2], [ 2, 6], [ 4, 4], [ 4, 6], 202 indent = 4, sort_keys = True)
14 ], 203 print >>sys.stderr, ""
15 [ 204 print >>sys.stderr, ""
16 # Row 1 205
17 [ 8, 0], [ 8, 2], [ 6, 0], [ 5, 0], [ 6, 2], [ 7, 0], [ 7, 2], 206def main(opts):
18 [ 7, 4], [ 7, 6], [ 6, 4], [ 5, 2], [ 6, 6], [ 8, 4], [ 8, 6], 207
19 ], 208 heatmaps = {"Dvorak": Heatmap("Dvorak"),
20 [ 209 "ADORE": Heatmap("ADORE")
21 # Row 2 210 }
22 [12, 0], [12, 2], [10, 0], [ 9, 0], [10, 2], [11, 0], [ ], 211 cnt = 0
23 [ ], [11, 2], [10, 4], [ 9, 2], [10, 6], [12, 4], [12, 6], 212 restrict_row = opts.restrict_row
24 ], 213 out_dir = opts.outdir
25 [ 214
26 # Row 3 215 while True:
27 [17, 0], [17, 2], [15, 0], [14, 0], [15, 2], [16, 0], [13, 0], 216 line = sys.stdin.readline()
28 [13, 2], [16, 2], [15, 4], [14, 2], [15, 6], [17, 4], [17, 6], 217 if not line:
29 ], 218 break
30 [ 219 m = re.search ('KL: col=(\d+), row=(\d+), pressed=(\d+), layer=(.*)', line)
31 # Row 4
32 [20, 0], [20, 2], [19, 0], [18, 0], [19, 2], [], [], [], [],
33 [19, 4], [18, 2], [19, 6], [20, 4], [20, 6],
34 ],
35 [
36 # Row 5
37 [ ], [23, 0], [22, 2], [22, 0], [22, 4], [21, 0], [21, 2],
38 [24, 0], [24, 2], [25, 0], [25, 4], [25, 2], [26, 0], [ ],
39 ],
40]
41
42def set_attr_at(j, b, n, attr, fn, val):
43 blk = j[b][n]
44 if attr in blk:
45 blk[attr] = fn(blk[attr], val)
46 else:
47 blk[attr] = fn(None, val)
48
49def coord(col, row):
50 return cr_coord_map[row][col]
51
52def set_attr(orig, new):
53 return new
54
55def set_bg(j, (b, n), color):
56 set_attr_at(j, b, n, "c", set_attr, color)
57 #set_attr_at(j, b, n, "g", set_attr, False)
58
59def _set_tap_info(o, count, cap):
60 ns = 4 - o.count ("\n")
61 return o + "\n" * ns + "%.02f%%" % (float(count) / float(cap) * 100)
62
63def set_tap_info(j, (b, n), count, cap):
64 j[b][n + 1] = _set_tap_info (j[b][n + 1], count, cap)
65
66def heatmap_color (v):
67 colors = [ [0.3, 0.3, 1], [0.3, 1, 0.3], [1, 1, 0.3], [1, 0.3, 0.3]]
68 fb = 0
69 if v <= 0:
70 idx1, idx2 = 0, 0
71 elif v >= 1:
72 idx1, idx2 = len(colors) - 1, len(colors) - 1
73 else:
74 val = v * (len(colors) - 1)
75 idx1 = int(floor(val))
76 idx2 = idx1 + 1
77 fb = val - float(idx1)
78
79 r = (colors[idx2][0] - colors[idx1][0]) * fb + colors[idx1][0]
80 g = (colors[idx2][1] - colors[idx1][1]) * fb + colors[idx1][1]
81 b = (colors[idx2][2] - colors[idx1][2]) * fb + colors[idx1][2]
82
83 r, g, b = [x * 255 for x in r, g, b]
84 return "#%02x%02x%02x" % (r, g, b)
85
86# Load the keylog
87def load_keylog(fname, restrict_row):
88 keylog = {}
89 total = 0
90 with open(fname, "r") as f:
91 lines = f.readlines()
92 for line in lines:
93 m = re.search ('KL: col=(\d+), row=(\d+)', line)
94 if not m: 220 if not m:
95 continue 221 continue
96 (c, r) = (int(m.group (2)), int(m.group (1))) 222
97 if restrict_row != None and r != int(restrict_row): 223 cnt = cnt + 1
224 (c, r, l) = (int(m.group (2)), int(m.group (1)), m.group (4))
225 if restrict_row != -1 and r != restrict_row:
226 continue
227 if c in opts.ignore_columns:
98 continue 228 continue
99 if (c, r) in keylog:
100 keylog[(c, r)] = keylog[(c, r)] + 1
101 else:
102 keylog[(c, r)] = 1
103 total = total + 1
104 return total / 2, keylog
105
106def l_flat(s):
107 f = s.split("\n")
108 return ", ".join (f)
109
110def main(base_fn, log_fn, restrict_row = None):
111
112 with open(base_fn, "r") as f:
113 layout = json.load (f)
114
115 ## Reset colors
116 for row in cr_coord_map:
117 for col in row:
118 if col != []:
119 set_bg (layout, col, "#d9dae0")
120 #set_attr_at (layout, col[0], col[1], "g", set_attr, True)
121
122 total, log = load_keylog (log_fn, restrict_row)
123 max_cnt = 0
124 for (c, r) in log:
125 max_cnt = max(max_cnt, log[(c, r)])
126
127 # Create the heatmap
128 for (c, r) in log:
129 coords = coord(c, r)
130 b, n = coords
131 cap = max_cnt
132 v = float(log[(c, r)]) / cap
133 print >> sys.stderr, "%s => %d/%d => %f = %s" % (l_flat(layout[b][n+1]), log[(c,r)], cap, v, heatmap_color(v))
134 set_bg (layout, coord(c, r), heatmap_color (v))
135 set_tap_info (layout, coord (c, r), log[(c, r)], total)
136
137 print json.dumps(layout)
138 229
139if __name__ == "__main__": 230 heatmaps[l].update_log ((c, r))
140 if len(sys.argv) < 3: 231
141 print """Log to Heatmap -- creates a heatmap out of keyboard logs 232 if opts.dump_interval != -1 and cnt >= opts.dump_interval:
233 cnt = 0
234 dump_all(out_dir, heatmaps)
142 235
143Usage: log-to-heatmap.py base-layout.json logfile [row] >layout.json""" 236 dump_all (out_dir, heatmaps)
144 sys.exit (1) 237
145 main(*sys.argv[1:]) 238if __name__ == "__main__":
239 parser = argparse.ArgumentParser (description = "keylog to heatmap processor")
240 parser.add_argument ('outdir', action = 'store',
241 help = 'Output directory')
242 parser.add_argument ('--row', dest = 'restrict_row', action = 'store', type = int,
243 default = -1, help = 'Restrict processing to this row only')
244 parser.add_argument ('--dump-interval', dest = 'dump_interval', action = 'store', type = int,
245 default = 100, help = 'Dump stats and heatmap at every Nth event, -1 for dumping at EOF only')
246 parser.add_argument ('--ignore-column', dest = 'ignore_columns', action = 'append', type = int,
247 default = [], help = 'Ignore the specified columns')
248 args = parser.parse_args()
249 main(args)