aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/Makefile3
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/adore-layer.pngbin0 -> 95615 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/base-layer.pngbin105162 -> 95654 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/experimental-layer.pngbin105172 -> 0 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/heatmap.pngbin0 -> 137912 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/keymap.c181
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/readme.md207
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/tools/heatmap-base-layout.json533
-rwxr-xr-xkeyboards/ergodox_ez/keymaps/algernon/tools/log-to-heatmap.py145
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/keymap.c455
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/ordinary-special.pngbin0 -> 63065 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/ordinary-special.txt27
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/readme.md45
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-base.json434
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-base.pngbin0 -> 93743 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-media.json436
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-media.pngbin0 -> 112216 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-symbol.json422
-rw-r--r--keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-symbol.pngbin0 -> 97350 bytes
-rw-r--r--quantum/process_keycode/process_tap_dance.c111
-rw-r--r--quantum/process_keycode/process_tap_dance.h43
-rw-r--r--readme.md29
23 files changed, 2762 insertions, 310 deletions
diff --git a/.gitignore b/.gitignore
index 7c1e434e3..849143352 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,4 @@ CMakeLists.txt
.project
.settings/
.idea
+.browse.VC.db* \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/algernon/Makefile b/keyboards/ergodox_ez/keymaps/algernon/Makefile
index cd7e9e9d2..005f9750c 100644
--- a/keyboards/ergodox_ez/keymaps/algernon/Makefile
+++ b/keyboards/ergodox_ez/keymaps/algernon/Makefile
@@ -3,6 +3,9 @@ COMMAND_ENABLE=no
SLEEP_LED_ENABLE=no
UNICODE_ENABLE=no
FORCE_NKRO ?= yes
+DEBUG_ENABLE = no
+CONSOLE_ENABLE = yes
+TAP_DANCE_ENABLE = yes
ifeq (${FORCE_NKRO},yes)
OPT_DEFS += -DFORCE_NKRO
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/adore-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/adore-layer.png
new file mode 100644
index 000000000..3df68ea53
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/adore-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/base-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/base-layer.png
index c4e298b6b..7b25a05b3 100644
--- a/keyboards/ergodox_ez/keymaps/algernon/images/base-layer.png
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/base-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/experimental-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/experimental-layer.png
deleted file mode 100644
index 81155851b..000000000
--- a/keyboards/ergodox_ez/keymaps/algernon/images/experimental-layer.png
+++ /dev/null
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/heatmap.png b/keyboards/ergodox_ez/keymaps/algernon/images/heatmap.png
new file mode 100644
index 000000000..356035e0a
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/heatmap.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/keymap.c b/keyboards/ergodox_ez/keymaps/algernon/keymap.c
index 2af3d5f8c..09d8dffd5 100644
--- a/keyboards/ergodox_ez/keymaps/algernon/keymap.c
+++ b/keyboards/ergodox_ez/keymaps/algernon/keymap.c
@@ -10,12 +10,13 @@
#include "mousekey.h"
#include "timer.h"
#include "keymap_plover.h"
+#include "eeconfig.h"
/* Layers */
enum {
BASE = 0,
- EXPRM,
+ ADORE,
ARRW,
APPSEL,
HUN,
@@ -94,7 +95,7 @@ enum {
/* Custom keycodes */
enum {
- CT_CLN = 0x7101
+ CT_CLN = 0
};
/* States & timers */
@@ -114,8 +115,7 @@ uint16_t oh_left_blink_timer = 0;
uint8_t oh_right_blink = 0;
uint16_t oh_right_blink_timer = 0;
-uint8_t ct_cln_count = 0;
-uint16_t ct_cln_timer = 0;
+bool log_enable = false;
/* The Keymap */
@@ -124,18 +124,18 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: Base Layer
*
* ,-----------------------------------------------------. ,-----------------------------------------------------.
- * | `~ | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | 1HND | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 |
+ * | `~ | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | Apps | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 |
* |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
* | Next/Prev | ' | , | . | P | Y | [ | | ] | F | G | C | R | L | \ |
* |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
- * | Tab | A | O | E | U | I |------| |------| D | H | T | N | S | = |
+ * | Tab/ARROW | A | O | E | U | I |------| |------| D | H | T | N | S | = / Arrow |
* |-----------+------+------+------+------+------| ( | | ) |------+------+------+------+------+-----------|
* | Play/Pause| / | Q | J | K | X | | | | B | M | W | V | Z | Stop |
* `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
- * | | | Left | Up | : | | - | Down | Rght | | |
+ * | | | | | : | | - | | | | |
* `-----------------------------------' `-----------------------------------'
* ,-------------. ,-------------.
- * | LAlt | GUI | | MDIA | ARRW |
+ * | LAlt | GUI | | MDIA | 1HND |
* ,------|------|------| |------+------+------.
* | | | Ctrl | | LEAD | | |
* |Backsp|LShift|------| |------| Enter| Space|
@@ -146,67 +146,67 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// left hand
KC_GRV ,M(KF_1) ,M(KF_2) ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR)
,M(A_MPN) ,KC_QUOT ,KC_COMM ,KC_DOT ,KC_P ,KC_Y ,KC_LBRC
-,KC_TAB ,KC_A ,KC_O ,KC_E ,KC_U ,KC_I
+,LT(ARRW,KC_TAB) ,KC_A ,KC_O ,KC_E ,KC_U ,KC_I
,KC_MPLY ,KC_SLSH ,KC_Q ,KC_J ,KC_K ,KC_X ,KC_LPRN
-,KC_NO ,KC_NO ,KC_LEFT ,KC_UP ,CT_CLN
+,KC_NO ,KC_NO ,KC_NO ,KC_NO ,TD(CT_CLN)
,F(F_ALT),F(F_GUI)
,F(F_CTRL)
,KC_BSPC,F(F_SFT),M(A_ESC)
// right hand
- ,M(OH_LEFT),M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
- ,KC_RBRC ,KC_F ,KC_G ,KC_C ,KC_R ,KC_L ,KC_BSLS
- ,KC_D ,KC_H ,KC_T ,KC_N ,KC_S ,KC_EQL
- ,KC_RPRN ,KC_B ,KC_M ,KC_W ,KC_V ,KC_Z ,KC_MSTP
- ,KC_MINS,KC_DOWN,KC_RGHT ,KC_NO ,KC_NO
+ ,KC_APP ,M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
+ ,KC_RBRC ,KC_F ,KC_G ,KC_C ,KC_R ,KC_L ,KC_BSLS
+ ,KC_D ,KC_H ,KC_T ,KC_N ,KC_S ,LT(ARRW, KC_EQL)
+ ,KC_RPRN ,KC_B ,KC_M ,KC_W ,KC_V ,KC_Z ,KC_MSTP
+ ,KC_MINS,KC_NO ,KC_NO ,KC_NO ,KC_NO
- ,OSL(NMDIA),OSL(ARRW)
+ ,OSL(NMDIA),M(OH_LEFT)
,KC_LEAD
,F(F_HUN) ,KC_ENT ,KC_SPC
),
-/* Keymap 1: Experimental layer
+/* Keymap 1: Adore layer
*
* ,-----------------------------------------------------. ,-----------------------------------------------------.
- * | `~ | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | 1HND | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 |
+ * | `~ | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | Apps | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 |
* |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
- * | Next/Prev | ' | , | . | P | Y | [ | | ] | L | F | C | R | J | = |
+ * | Next/Prev | , | . | L | W | M | [ | | ] | F | H | C | P | Y | \ |
* |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
- * | Tab | A | O | E | U | I |------| |------| D | H | T | N | S | \ |
+ * | Tab/Arrow | A | O | E | I | U |------| |------| D | R | T | N | S | = / Arrow |
* |-----------+------+------+------+------+------| ( | | ) |------+------+------+------+------+-----------|
- * | Play/Pause| Z | G | V | K | X | | | | Q | M | W | B | / | Stop |
+ * | Play/Pause| / | Z | ' | K | X | | | | B | G | V | J | Q | Stop |
* `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
- * | | | Left | Up | : | | - | Down | Rght | | |
+ * | | | | | : | | - | | | | |
* `-----------------------------------' `-----------------------------------'
* ,-------------. ,-------------.
- * | LAlt | GUI | | MDIA | ARRW |
+ * | LAlt | GUI | | MDIA | 1HND |
* ,------|------|------| |------+------+------.
* | | | Ctrl | | LEAD | | |
* |Backsp|LShift|------| |------| Enter| Space|
* | | | ESC | | HUN | | |
* `--------------------' `--------------------'
*/
-[EXPRM] = KEYMAP(
+[ADORE] = KEYMAP(
// left hand
KC_GRV ,M(KF_1) ,M(KF_2) ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR)
-,M(A_MPN) ,KC_QUOT ,KC_COMM ,KC_DOT ,KC_P ,KC_Y ,KC_LBRC
-,KC_TAB ,KC_A ,KC_O ,KC_E ,KC_U ,KC_I
-,KC_MPLY ,KC_Z ,KC_G ,KC_V ,KC_K ,KC_X ,KC_LPRN
-,KC_NO ,KC_NO ,KC_LEFT ,KC_UP ,CT_CLN
+,M(A_MPN) ,KC_COMM ,KC_DOT ,KC_L ,KC_W ,KC_M ,KC_LBRC
+,LT(ARRW, KC_TAB) ,KC_A ,KC_O ,KC_E ,KC_I ,KC_U
+,KC_MPLY ,KC_SLSH ,KC_Z ,KC_QUOT,KC_K ,KC_X ,KC_LPRN
+,KC_NO ,KC_NO ,KC_NO ,KC_NO ,TD(CT_CLN)
,F(F_ALT),F(F_GUI)
,F(F_CTRL)
,KC_BSPC,F(F_SFT),M(A_ESC)
// right hand
- ,M(OH_LEFT),M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
- ,KC_RBRC ,KC_L ,KC_F ,KC_C ,KC_R ,KC_J ,KC_BSLS
- ,KC_D ,KC_H ,KC_T ,KC_N ,KC_S ,KC_EQL
- ,KC_RPRN ,KC_Q ,KC_M ,KC_W ,KC_B ,KC_SLSH ,KC_MSTP
- ,KC_MINS,KC_DOWN,KC_RGHT ,KC_NO ,KC_NO
+ ,KC_APP ,M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
+ ,KC_RBRC ,KC_F ,KC_H ,KC_C ,KC_P ,KC_Y ,KC_BSLS
+ ,KC_D ,KC_R ,KC_T ,KC_N ,KC_S ,LT(ARRW, KC_EQL)
+ ,KC_RPRN ,KC_B ,KC_G ,KC_V ,KC_J ,KC_Q ,KC_MSTP
+ ,KC_MINS,KC_NO ,KC_NO ,KC_NO ,KC_NO
- ,OSL(NMDIA),OSL(ARRW)
+ ,OSL(NMDIA),M(OH_LEFT)
,KC_LEAD
,F(F_HUN) ,KC_ENT ,KC_SPC
),
@@ -216,19 +216,19 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* ,-----------------------------------------------------. ,-----------------------------------------------------.
* | | | | | | | | | | | | | | | |
* |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
- * | | | | | | | | | | | | | | | |
+ * | | | | | | | | | | | Home | Up | End | | |
* |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
- * | | | | | | |------| |------| | | | | | |
+ * | | | | | | |------| |------| | Left | Down | Rght | | |
* |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
* | | | | | | | | | | | | | | | |
* `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
- * | | | Home | PgUp | | | | PgDn | End | | |
+ * | | | | | | | | | | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
- * | | |------| |------| | |
+ * | | |------| |------| PgUp | PgDn |
* | | | | | | | |
* `--------------------' `--------------------'
*/
@@ -239,7 +239,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
-,KC_TRNS ,KC_TRNS ,KC_HOME ,KC_PGUP ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
,KC_TRNS ,KC_TRNS
,KC_TRNS
@@ -247,14 +247,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// right hand
,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_HOME ,KC_UP ,KC_END ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_LEFT ,KC_DOWN ,KC_RGHT ,KC_TRNS ,KC_TRNS
,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
- ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
- ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
- ,KC_TRNS ,KC_PGDN ,KC_END ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
,KC_TRNS ,KC_TRNS
,KC_TRNS
- ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_PGUP ,KC_PGDN
),
/* Keymap 3: Application select layer
@@ -843,8 +843,12 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
return MACRO_NONE;
};
+uint8_t is_adore = 0;
+
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
+ uint8_t dl;
+
ergodox_led_all_on();
for (int i = LED_BRIGHTNESS_HI; i > LED_BRIGHTNESS_LO; i--) {
ergodox_led_all_set (i);
@@ -856,6 +860,12 @@ void matrix_init_user(void) {
_delay_ms (10);
}
ergodox_led_all_off();
+
+ if (!eeconfig_is_enabled())
+ eeconfig_init();
+ dl = eeconfig_read_default_layer ();
+ if (dl == (1UL << ADORE))
+ is_adore = 1;
};
LEADER_EXTERNS();
@@ -882,29 +892,32 @@ void ang_tap (uint16_t codes[]) {
register_code (code); \
unregister_code (code)
-uint8_t is_exp = 0;
-
-// Runs constantly in the background, in a loop.
-void matrix_scan_user(void) {
- uint8_t layer = biton32(layer_state);
-
- if (gui_timer && timer_elapsed (gui_timer) > TAPPING_TERM)
- unregister_code (KC_LGUI);
-
- if (ct_cln_timer && timer_elapsed (ct_cln_timer) > TAPPING_TERM) {
- if (ct_cln_count == 1) {
+void ang_tap_dance (qk_tap_dance_state_t *state) {
+ switch (state->keycode) {
+ case TD(CT_CLN):
+ if (state->count == 1) {
register_code (KC_RSFT);
register_code (KC_SCLN);
unregister_code (KC_SCLN);
unregister_code (KC_RSFT);
- } else if (ct_cln_count == 2) {
+ } else if (state->count == 2) {
register_code (KC_SCLN);
unregister_code (KC_SCLN);
+ reset_tap_dance (state);
}
-
- ct_cln_count = 0;
- ct_cln_timer = 0;
}
+}
+
+const qk_tap_dance_action_t tap_dance_actions[] = {
+ [CT_CLN] = ACTION_TAP_DANCE_FN (ang_tap_dance)
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+
+ if (gui_timer && timer_elapsed (gui_timer) > TAPPING_TERM)
+ unregister_code (KC_LGUI);
if (layer != OHLFT)
oh_left_blink = 0;
@@ -921,7 +934,7 @@ void matrix_scan_user(void) {
ergodox_right_led_1_on ();
ergodox_right_led_2_on ();
ergodox_right_led_3_on ();
- } else if (layer == EXPRM) {
+ } else if (layer == ADORE) {
ergodox_right_led_1_on ();
ergodox_right_led_2_on ();
ergodox_right_led_3_on ();
@@ -961,7 +974,7 @@ void matrix_scan_user(void) {
ergodox_right_led_1_on ();
} else {
ergodox_right_led_1_set (LED_BRIGHTNESS_LO);
- if (layer != OHLFT && layer != NMDIA && layer != PLVR && layer != EXPRM)
+ if (layer != OHLFT && layer != NMDIA && layer != PLVR && layer != ADORE)
ergodox_right_led_1_off ();
}
@@ -971,7 +984,7 @@ void matrix_scan_user(void) {
ergodox_right_led_2_on ();
} else {
ergodox_right_led_2_set (LED_BRIGHTNESS_LO);
- if (layer != OHRGT && layer != HUN && layer != OHLFT && layer != NMDIA && layer != PLVR && layer != EXPRM)
+ if (layer != OHRGT && layer != HUN && layer != OHLFT && layer != NMDIA && layer != PLVR && layer != ADORE)
ergodox_right_led_2_off ();
}
@@ -981,7 +994,7 @@ void matrix_scan_user(void) {
ergodox_right_led_3_on ();
} else {
ergodox_right_led_3_set (LED_BRIGHTNESS_LO);
- if (layer != OHRGT && layer != HUN && layer != PLVR && layer != EXPRM)
+ if (layer != OHRGT && layer != HUN && layer != PLVR && layer != ADORE)
ergodox_right_led_3_off ();
}
@@ -989,6 +1002,10 @@ void matrix_scan_user(void) {
leading = false;
leader_end ();
+ SEQ_ONE_KEY (KC_D) {
+ log_enable = !log_enable;
+ }
+
SEQ_ONE_KEY (KC_U) {
ang_do_unicode ();
}
@@ -1036,11 +1053,12 @@ void matrix_scan_user(void) {
unregister_code (KC_LGUI);
}
- SEQ_ONE_KEY (KC_E) {
- if (is_exp == 0) {
+ SEQ_ONE_KEY (KC_A) {
+ if (is_adore == 0) {
default_layer_and (0);
- default_layer_or ((1 << EXPRM));
- is_exp = 1;
+ default_layer_or ((1UL << ADORE));
+ eeconfig_update_default_layer ((1UL << ADORE));
+ is_adore = 1;
ergodox_led_all_off ();
ergodox_right_led_3_on ();
@@ -1054,9 +1072,10 @@ void matrix_scan_user(void) {
_delay_ms (100);
ergodox_right_led_1_off ();
} else {
- is_exp = 0;
+ is_adore = 0;
default_layer_and (0);
- default_layer_or (1 << BASE);
+ default_layer_or (1UL << BASE);
+ eeconfig_update_default_layer ((1UL << BASE));
ergodox_led_all_off ();
ergodox_right_led_1_on ();
@@ -1075,29 +1094,11 @@ void matrix_scan_user(void) {
}
bool process_record_user (uint16_t keycode, keyrecord_t *record) {
- switch(keycode) {
- case CT_CLN:
- if (record->event.pressed) {
- ct_cln_count++;
- ct_cln_timer = timer_read ();
- } else {
- }
- return false;
- break;
+ uint8_t layer = biton32(layer_state);
- default:
- if (ct_cln_count == 1) {
- register_code (KC_RSFT);
- register_code (KC_SCLN);
- unregister_code (KC_SCLN);
- unregister_code (KC_RSFT);
- } else if (ct_cln_count == 2) {
- register_code (KC_SCLN);
- unregister_code (KC_SCLN);
- }
- ct_cln_count = 0;
- ct_cln_timer = 0;
- break;
+ if (log_enable && layer == BASE) {
+ xprintf ("KL: col=%d, row=%d\n", record->event.key.col,
+ record->event.key.row);
}
return true;
diff --git a/keyboards/ergodox_ez/keymaps/algernon/readme.md b/keyboards/ergodox_ez/keymaps/algernon/readme.md
index 6b7e8fa2e..2312dc59e 100644
--- a/keyboards/ergodox_ez/keymaps/algernon/readme.md
+++ b/keyboards/ergodox_ez/keymaps/algernon/readme.md
@@ -1,27 +1,28 @@
+<!-- -*- mode: markdown; fill-column: 8192 -*- -->
+
algernon's layout
=======================
-This 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].
+This 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].
[blog-ergodox]: https://asylum.madhouse-project.org/blog/tags/ergodox/
-Some of the things in the layout only work when one uses Spacemacs and GNOME
-under Linux. Your mileage may vary.
+Some of the things in the layout only work when one uses Spacemacs and GNOME under Linux. Your mileage may vary.
## Table of Contents
* [Layouts](#layouts)
- - [Base layer](#base-layer)
- - [Experimental layer](#experimental-layer)
- - [Hungarian layer](#hungarian-layer)
- - [Navigation and media layer](#navigation-and-media-layer)
- - [One-handed layer](#one-handed-layer)
- - [Steno layer](#steno-layer)
- - [LED states](#led-states)
+ - [Base layer](#base-layer)
+ - [ADORE layer](#adore-layer)
+ - [Hungarian layer](#hungarian-layer)
+ - [Navigation and media layer](#navigation-and-media-layer)
+ - [One-handed layer](#one-handed-layer)
+ - [Steno layer](#steno-layer)
+ - [LED states](#led-states)
+* [Tools](#tools)
+ - [Heatmap](#heatmap)
* [Building](#building)
- - [Using on Windows](#using-on-windows)
+ - [Using on Windows](#using-on-windows)
* [Changelog](#changelog)
* [License](#license)
@@ -31,133 +32,98 @@ under Linux. Your mileage may vary.
[![Base layer](images/base-layer.png)](http://www.keyboard-layout-editor.com/#/gists/28f7eb305fdbff943613e1dc7aa9e82b)
-At its core, this is a Dvorak layout, with some minor changes. The more
-interesting parts are how certain keys behave:
-
-* The keys on the number row double as function keys, when held for a bit longer
- than an usual tap. This allows me to use the function keys without having to
- switch layers.
-* The `Shift`, `Alt`, and `Control` modifiers are one-shot. When tapped, they
- are considered active for the next key press only. When double tapped, they
- toggle on, until a third, single tap sometime later. When held, they act as
- expected. My usual pattern is that I use these for the next keypress only, so
- this behaviour is perfect. If I need them held, I'll just double-tap.
-* 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.
-* 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.
-* The **Media**, **Arrow**, and **Hun** layer keys are one-shot, the **1Hand**
- and **STENO** keys are toggles.
-* Toggling the **Arrow** layer toggles between the cursor arrows and the paging
- keys on the bottom row.
+At its core, this is a Dvorak layout, with some minor changes. The more interesting parts are how certain keys behave:
+
+* The keys on the number row double as function keys, when held for a bit longer than an usual tap. This allows me to use the function keys without having to switch layers.
+* The `Shift`, `Alt`, and `Control` modifiers are one-shot. When tapped, they are considered active for the next key press only. When double tapped, they toggle on, until a third, single tap sometime later. When held, they act as expected. My usual pattern is that I use these for the next keypress only, so this behaviour is perfect. If I need them held, I'll just double-tap.
+* 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.
+* 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.
+* The **Media** and **Hun** layer keys are one-shot, the **1Hand** and **STENO** keys are toggles.
+* 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.
* Tapping the `:` key once yields `:`, tapping it twice yields `;`.
-* The **Lead** key allows me to type in a sequence of keys, and trigger some
- actions:
- - `LEAD u` enters unicode input mode, by sending the GTK+ key sequence that
- does this.
+* The **Lead** key allows me to type in a sequence of keys, and trigger some actions:
+ - `LEAD u` enters unicode input mode, by sending the GTK+ key sequence that does this.
- `LEAD l` uses the unicode input method to enter a `λ`.
- `LEAD s` does a lot of magic to type in a shruggie: `¯\_(ツ)_/¯`
- `LEAD y` types `\o/`.
- `LEAD w m` maximises the currently focused window.
- - `LEAD e` makes the [experimental layer](#experimental-layer) the default.
+ - `LEAD a` makes the [ADORE layer](#adore-layer) the default.
- `LEAD v` prints the firmware version, the keyboard and the keymap.
+ - `LEAD d` toggles logging keypress positions to the HID console.
-## Experimental layer
+## ADORE layer
-[![Experimental layer](images/experimental-layer.png)](http://www.keyboard-layout-editor.com/#/gists/6ff50bf71248e05aab5b3fec4fae3d08)
+[![ADORE layer](images/adore-layer.png)](http://www.keyboard-layout-editor.com/#/gists/45681a17453d235925b6028dd83bf12a)
-While using the standard Dvorak layout, I encountered a number of
-inconveniences, and on this layer, I am playing with ideas to make the layout
-feel better. Initially, it was based on [Capewell-Dvorak][cpd], but that too,
-had shortcomings I was not happy with. So now this is something inbetween, with
-own observations thrown in. How it works out in the long run remains to be seen.
+While using the standard Dvorak layout, I encountered a number of inconveniences, and on this layer, I am playing with ideas to make the layout feel better. Initially, it was based on [Capewell-Dvorak][cpd], but that too, had shortcomings I was not happy with. So now this is something inbetween, with own observations thrown in. How it works out in the long run remains to be seen.
[cpd]: http://www.michaelcapewell.com/projects/keyboard/layout_capewell-dvorak.htm
+
+Based on a week and a half of typing, the keys were rearranged, and the home row neatly spelled out **ADORE**, that gave the layout its name.
## Hungarian layer
[![Hungarian layer](images/hun-layer.png)](http://www.keyboard-layout-editor.com/#/gists/b160f6ec90d58c127c114c89f66e9dc9)
-On this layer, the accented characters are at the same position as their base
-variant. For some, which can have other diatribes, the long one is on top,
-short's on bottom. Tapping any of the accented characters takes us back to the
-base layer.
+On this layer, the accented characters are at the same position as their base variant. For some, which can have other diatribes, the long one is on top, short's on bottom. Tapping any of the accented characters takes us back to the base layer.
## Navigation and media layer
[![Navigation and media layer](images/nav-n-media-layer.png)](http://www.keyboard-layout-editor.com/#/gists/c59c453f9fe1a3238ba1494e7e5c6892)
-This layer is primarily for navigating with the cursor or the mouse, and some
-media things.
+This layer is primarily for navigating with the cursor or the mouse, and some media things.
## One-handed layer
[![One-handed layer](images/one-handed-layer.png)](http://www.keyboard-layout-editor.com/#/gists/edff2495135955b8963198dace7f7ece)
-The one-handed layer is used in situations where the right hand is occupied, by
-mousing around, for example. Tapping the `OTHER` key switches which side is
-active. For the most part, keys remain in their usual position. When the right
-half is active, keys are mirrored to the left half.
+The one-handed layer is used in situations where the right hand is occupied, by mousing around, for example. Tapping the `OTHER` key switches which side is active. For the most part, keys remain in their usual position. When the right half is active, keys are mirrored to the left half.
The differences are as follows:
-* The `ESC` key has been moved to the bottom row, so the `OTHER` key is easier
- to tap.
-* Most keys on the thumb cluster now have dual uses, and these do not change
- when switching sides:
- - The `Space`/`Backspace` key sends `Space` on tap, `Backspace` when held
- for longer than a normal tap.
+* The `ESC` key has been moved to the bottom row, so the `OTHER` key is easier to tap.
+* Most keys on the thumb cluster now have dual uses, and these do not change when switching sides:
+ - The `Space`/`Backspace` key sends `Space` on tap, `Backspace` when held for longer than a normal tap.
- The `Enter`/`Shift` key sends `Enter` on short-tap, `Shift` on long-tap.
-* The `Apps`/`BASE` key can be used to go back to the base layer, by
- long-tapping it. A short-tap will send the `App` key, as usual.
+* The `Apps`/`BASE` key can be used to go back to the base layer, by long-tapping it. A short-tap will send the `App` key, as usual.
## Steno layer
[![Steno layer for Plover](images/steno-layer.png)](http://www.keyboard-layout-editor.com/#/gists/401ef9a84369e47c57f9aedcf0a0d667)
-This is to be used with [Plover](http://www.openstenoproject.org/plover/),
-nothing really fancy here. The **STENO** key toggles the layer on and off, and
-sends the toggle command to Plover too.
+This is to be used with [Plover](http://www.openstenoproject.org/plover/), nothing really fancy here. The **STENO** key toggles the layer on and off, and sends the toggle command to Plover too.
## LED states
-The primary purpose of the LEDs is to show the modifier status, a secondary, to
-show which layer is active. Each modifier, `Shift`, `Alt` and `Control` each
-have their designated LEDs: the *red*, *green* and *blue*, respectively. When a
-modifier is in a one-shot state, the respective LED will turn on with a dimmer
-light. If the modifier is toggled on, the brightness of the LED turns full.
+The primary purpose of the LEDs is to show the modifier status, a secondary, to show which layer is active. Each modifier, `Shift`, `Alt` and `Control` each have their designated LEDs: the *red*, *green* and *blue*, respectively. When a modifier is in a one-shot state, the respective LED will turn on with a dimmer light. If the modifier is toggled on, the brightness of the LED turns full.
For the layers, the following rules apply:
-* When the [Experimental layer](#experimental-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.
-* When the [Hungarian layer](#hungarian-layer) is active, the *green* and *blue*
- LEDs are on.
-* When the [Navigation and media layer](#navigation-and-media-layer) is active,
- the *red* and *green* ones are on.
-* When the [One-handed layer](#one-handed-layer) is active, the *green* LED is
- on and bright, and either the *red* or the *blue* one is going to slowly
- blink, depending on the currently active side.
+* 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.
+* When the [Hungarian layer](#hungarian-layer) is active, the *green* and *blue* LEDs are on.
+* When the [Navigation and media layer](#navigation-and-media-layer) is active, the *red* and *green* ones are on.
+* When the [One-handed layer](#one-handed-layer) is active, the *green* LED is on and bright, and either the *red* or the *blue* one is going to slowly blink, depending on the currently active side.
* For the [Steno layer](#steno-layer), all LEDs will be turned on.
-Unless 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.
+Unless 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.
+
+# Tools
+
+## Heatmap
+
+When 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.
+
+Included 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.
+
+ [kle]: http://www.keyboard-layout-editor.com/
+
+The generated heatmap looks somewhat like this:
+
+ ![Heatmap](images/heatmap.png)
# Building
-To make my workflow easier, this layout is maintained in
-[its own repository][algernon:ez-layout]. To build it, you will need the
-[QMK][qmk] firmware checked out, and this repo either checked out to something
-like `keyboards/ergodox_ez/algernon-master`. One way to achieve that is this:
+To make my workflow easier, this layout is maintained in [its own repository][algernon:ez-layout]. To build it, you will need the [QMK][qmk] firmware checked out, and this repo either checked out to something like `keyboards/ergodox_ez/algernon-master`. One way to achieve that is this:
[algernon:ez-layout]: https://github.com/algernon/ergodox-layout
[qmk]: https://github.com/jackhumbert/qmk_firmware
@@ -170,9 +136,7 @@ $ git clone https://github.com/algernon/ergodox-layout.git \
$ make KEYBOARD=ergodox_ez KEYMAP=algernon-master
```
-From time to time, updates may be submitted back to the QMK repository. If you
-are reading it there, you can build the firmware like any other firmware
-included with it (assuming you are in the root directory of the firmware):
+From time to time, updates may be submitted back to the QMK repository. If you are reading it there, you can build the firmware like any other firmware included with it (assuming you are in the root directory of the firmware):
```
$ make KEYBOARD=ergodox_ez KEYMAP=algernon
@@ -180,43 +144,40 @@ $ make KEYBOARD=ergodox_ez KEYMAP=algernon
## Using on Windows
-The keymap default to forcing NKRO, which seems to upset Windows, and except the
-modifiers, none of them work. If you experience this problem, recompile the
-firmware with `FORCE_NKRO=no` added to the `make` command line.
+The keymap default to forcing NKRO, which seems to upset Windows, and except the modifiers, none of them work. If you experience this problem, recompile the firmware with `FORCE_NKRO=no` added to the `make` command line.
# Changelog
+## v1.3 - 2016-07-06
+
+* Added support for logging keys, by pressing `LEAD d`. Also included is a tool to generate a [heatmap](#heatmap) out of the logs.
+* 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.
+* The **experimental** layer has been redone, and is now called [ADORE](#adore-layer), and as such, can be enabled by `LEAD a` now.
+* Switching between Dvorak and ADORE is now persisted into EEPROM, and survives a reboot.
+
## v1.2 - 2016-06-22
-* The forced NKRO mode can be easily toggled off at compile-time, to make the
- firmware compatible with [certain operating systems](#using-on-windows).
-* The `:;` key has changed behaviour: to access the `;` symbol, the key needs to
- be double-tapped, instead of shifted.
-* The `=` and `\` keys were swapped, `=` moved to the home row, on both the
- [base](#base-layer) and the [experimental](#experimental-layer) layers.
-* The arrow and navigation keys were redone, they are now more accessible, but
- the navigation keys require an extra tap to access.
-* The **Emacs** layer is gone, replaced by a simplified
- [navigation and media](#navigation-and-media-layer) layer.
+* The forced NKRO mode can be easily toggled off at compile-time, to make the firmware compatible with [certain operating systems](#using-on-windows).
+* The `:;` key has changed behaviour: to access the `;` symbol, the key needs to be double-tapped, instead of shifted.
+* The `=` and `\` keys were swapped, `=` moved to the home row, on both the [base](#base-layer) and the **experimental** layers.
+* The arrow and navigation keys were redone, they are now more accessible, but the navigation keys require an extra tap to access.
+* The **Emacs** layer is gone, replaced by a simplified [navigation and media](#navigation-and-media-layer) layer.
* `LEAD v` types the firmware version, and the keymap version.
-* On the [experimental](#experimental-layer) layer, the `L` and `Q`, and the `K`
- and `G` keys were swapped.
-* The [Steno](#steno-layer) layer gained a few more `#` and `*` keys, to make it
- easier on my fingers.
+* On the **experimental** layer, the `L` and `Q`, and the `K` and `G` keys were swapped.
+* The [Steno](#steno-layer) layer gained a few more `#` and `*` keys, to make it easier on my fingers.
## v1.1 - 2016-06-14
* The keyboard starts in NKRO mode, bootmagic and other things are disabled.
* A [Steno](#steno-layer) layer was added, to be used with Plover.
-* An [experimental](#experimental-layer) layer was added, something halfway
- between Dvorak and Capewell-Dvorak. A work in progress.
+* An **experimental** layer was added, something halfway between Dvorak and Capewell-Dvorak. A work in progress.
* `LEAD y` types `\o/`.
* Some keys on the [Base](#base-layer) layer have been moved around:
- - `?` moved to the left pinky, left of `Q`.
- - `=` shifted one row down, but `F11` stayed where it was.
- - `-` on the left half was replaced by `Tab`.
- - `Tab`'s original position is taken by a `Media Next`/`Media Prev` key.
- - `:` now inputs `;` when shifted.
+ - `?` moved to the left pinky, left of `Q`.
+ - `=` shifted one row down, but `F11` stayed where it was.
+ - `-` on the left half was replaced by `Tab`.
+ - `Tab`'s original position is taken by a `Media Next`/`Media Prev` key.
+ - `:` now inputs `;` when shifted.
* `ESC` cancels the [Hungarian](#hungarian-layer) layer too, not just modifiers.
## v1.0 - 2016-05-26
@@ -225,6 +186,4 @@ Initial version.
# License
-The layout, being a derivative of the original TMK firmware which is under the
-GPL-2+, this layout is under the GPL as well, but GPL-3+, rather than the older
-version.
+The layout, being a derivative of the original TMK firmware which is under the GPL-2+, this layout is under the GPL as well, but GPL-3+, rather than the older version.
diff --git a/keyboards/ergodox_ez/keymaps/algernon/tools/heatmap-base-layout.json b/keyboards/ergodox_ez/keymaps/algernon/tools/heatmap-base-layout.json
new file mode 100644
index 000000000..148bb1f23
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/tools/heatmap-base-layout.json
@@ -0,0 +1,533 @@
+[
+ {
+ "backcolor": "#ffffff",
+ "name": "ErgoDox - algernon's layout: Heatmap",
+ "author": "Gergely Nagy <kbd@gergo.csillger.hu>",
+ "notes": "See [here](https://github.com/algernon/ergodox-layout#readme) for the QMK keymap source.",
+ "switchMount": "cherry",
+ "switchBrand": "gateron",
+ "switchType": "KS-3-Tea",
+ "pcb": true,
+ "css": ".keyborder { -webkit-filter: blur(5px); filter: blur(5px); } .keytop { -webkit-filter: blur(10px); } .keylabels { border: 1px solid black; }"
+ },
+ [
+ {
+ "x": 3.5,
+ "c": "#a7d0db",
+ "fa": [
+ 0,
+ 0,
+ 2
+ ]
+ },
+ "#\n3\nF3",
+ {
+ "x": 10.5,
+ "c": "#a7d0db",
+ "t": "#000000",
+ "a": 4,
+ "fa": [
+ 0,
+ 0,
+ 2
+ ]
+ },
+ "*\n8\nF8"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#bfbad1",
+ "t": "#0d0d0b"
+ },
+ "@\n2\nF2",
+ {
+ "x": 1,
+ "c": "#7adabd",
+ "t": "#000000"
+ },
+ "$\n4\nF4",
+ {
+ "x": 8.5
+ },
+ "&\n7\nF7",
+ {
+ "x": 1,
+ "c": "#bfbad1",
+ "t": "#0d0d0b"
+ },
+ "(\n9\nF9"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#7adabd",
+ "t": "#000000"
+ },
+ "%\n5\nF5",
+ {
+ "c": "#f9cd31",
+ "a": 7,
+ "f": 2
+ },
+ "STENO",
+ {
+ "x": 4.5,
+ "f": 6
+ },
+ "<i class='mss mss-Unicode-Option-3'></i>",
+ {
+ "c": "#7adabd",
+ "a": 4,
+ "f": 3,
+ "fa": [
+ 0,
+ 0,
+ 2
+ ]
+ },
+ "^\n6\nF6"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#ffb2d2",
+ "f": 3,
+ "w": 1.5
+ },
+ "\n\n~\n`",
+ {
+ "t": "#0d0d0b"
+ },
+ "!\n1\nF1",
+ {
+ "x": 14.5
+ },
+ ")\n0\nF10",
+ {
+ "a": 7,
+ "w": 1.5
+ },
+ "F11"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#a7d0db",
+ "t": "#000000",
+ "a": 4
+ },
+ ">\n.",
+ {
+ "x": 10.5,
+ "a": 6
+ },
+ "C"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#bfbad1",
+ "t": "#0d0d0b",
+ "a": 4
+ },
+ "<\n,",
+ {
+ "x": 1,
+ "c": "#7adabd",
+ "t": "#000000",
+ "a": 6
+ },
+ "P",
+ {
+ "x": 8.5
+ },
+ "G",
+ {
+ "x": 1,
+ "c": "#bfbad1",
+ "t": "#0d0d0b"
+ },
+ "R"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#7adabd",
+ "t": "#000000"
+ },
+ "Y",
+ {
+ "c": "#93c9b7",
+ "a": 4,
+ "h": 1.5
+ },
+ "{\n[",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ "}\n]",
+ {
+ "c": "#7adabd",
+ "a": 6
+ },
+ "F"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#ffb07b",
+ "t": "#0d0d0b",
+ "f": 6,
+ "w": 1.5
+ },
+ "<i class='fa fa-fast-backward'></i>\n\n<i class='fa fa-fast-forward'></i>",
+ {
+ "c": "#ffb2d2",
+ "a": 4,
+ "f": 3
+ },
+ "\"\n'",
+ {
+ "x": 14.5,
+ "a": 6
+ },
+ "L",
+ {
+ "a": 4,
+ "w": 1.5
+ },
+ "|\n\\"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#a7d0db",
+ "t": "#000000",
+ "a": 6
+ },
+ "E",
+ {
+ "x": 10.5
+ },
+ "T"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#bfbad1",
+ "t": "#0d0d0b"
+ },
+ "O",
+ {
+ "x": 1,
+ "c": "#7adabd",
+ "t": "#000000",
+ "n": true
+ },
+ "U",
+ {
+ "x": 8.5,
+ "n": true
+ },
+ "H",
+ {
+ "x": 1,
+ "c": "#bfbad1",
+ "t": "#0d0d0b"
+ },
+ "N"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#7adabd",
+ "t": "#000000"
+ },
+ "I",
+ {
+ "x": 6.5
+ },
+ "D"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#ffb2d2",
+ "t": "#0d0d0b",
+ "fa": [
+ 6
+ ],
+ "w": 1.5
+ },
+ "<i class='fa fa-arrows'></i>\n\nTab",
+ {
+ "f": 3
+ },
+ "A",
+ {
+ "x": 14.5,
+ "f": 3
+ },
+ "S",
+ {
+ "a": 4,
+ "fa": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6
+ ],
+ "w": 1.5
+ },
+ "+\n="
+ ],
+ [
+ {
+ "y": -0.625,
+ "x": 6.5,
+ "c": "#93c9b7",
+ "t": "#000000",
+ "a": 7,
+ "h": 1.5
+ },
+ "(",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ ")"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 3.5,
+ "c": "#a7d0db",
+ "a": 6
+ },
+ "J",
+ {
+ "x": 10.5
+ },
+ "W"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#bfbad1",
+ "t": "#0d0d0b"
+ },
+ "Q",
+ {
+ "x": 1,
+ "c": "#7adabd",
+ "t": "#000000"
+ },
+ "K",
+ {
+ "x": 8.5
+ },
+ "M",
+ {
+ "x": 1,
+ "c": "#bfbad1",
+ "t": "#0d0d0b"
+ },
+ "V"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#7adabd",
+ "t": "#000000"
+ },
+ "X",
+ {
+ "x": 6.5
+ },
+ "B"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#ffb07b",
+ "f": 9,
+ "w": 1.5
+ },
+ "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>",
+ {
+ "c": "#ffb2d2",
+ "t": "#0d0d0b",
+ "a": 4,
+ "f": 3
+ },
+ "?\n/",
+ {
+ "x": 14.5,
+ "a": 6
+ },
+ "Z",
+ {
+ "c": "#ffb07b",
+ "t": "#000000",
+ "f": 9,
+ "w": 1.5
+ },
+ "<i class='kb kb-Multimedia-Stop'></i>"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#d9dae0",
+ "g": true,
+ "a": 7,
+ "f": 3
+ },
+ "",
+ {
+ "x": 10.5
+ },
+ ""
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "",
+ {
+ "x": 1,
+ "c": "#d4872a",
+ "g": false,
+ "a": 5
+ },
+ ";\n:",
+ {
+ "x": 8.5
+ },
+ "_\n-",
+ {
+ "x": 1,
+ "c": "#d9dae0",
+ "g": true,
+ "a": 7
+ },
+ ""
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 0.5
+ },
+ "",
+ {},
+ "",
+ {
+ "x": 14.5
+ },
+ "",
+ {},
+ ""
+ ],
+ [
+ {
+ "r": 30,
+ "rx": 6.5,
+ "ry": 4.25,
+ "y": -1,
+ "x": 1,
+ "c": "#f9cd31",
+ "g": false
+ },
+ "Alt",
+ {
+ "a": 4,
+ "fa": [
+ 0,
+ 0,
+ 0,
+ 9
+ ]
+ },
+ "\n\n\n<i class='kb kb-logo-linux-debian fa-large'></i>"
+ ],
+ [
+ {
+ "c": "#d4872a",
+ "a": 7,
+ "f": 9,
+ "h": 2
+ },
+ "<i class='kb kb-Unicode-BackSpace-DeleteLeft-Big'></i>",
+ {
+ "h": 2
+ },
+ "<i class='fa fa-angle-double-up'></i>",
+ {
+ "c": "#f9cd31",
+ "f": 3
+ },
+ "Ctrl"
+ ],
+ [
+ {
+ "x": 2,
+ "c": "#e26757"
+ },
+ "ESC"
+ ],
+ [
+ {
+ "r": -30,
+ "rx": 13,
+ "y": -1,
+ "x": -3,
+ "c": "#f9cd31",
+ "f": 2
+ },
+ "MEDIA",
+ {},
+ "1HAND"
+ ],
+ [
+ {
+ "x": -3
+ },
+ "LEAD",
+ {
+ "c": "#d4872a",
+ "f": 9,
+ "h": 2
+ },
+ "<i class='kb kb-Return-2'></i>",
+ {
+ "f": 3,
+ "h": 2
+ },
+ "SPC"
+ ],
+ [
+ {
+ "x": -3,
+ "c": "#f9cd31",
+ "f": 2
+ },
+ "HUN"
+ ]
+]
diff --git a/keyboards/ergodox_ez/keymaps/algernon/tools/log-to-heatmap.py b/keyboards/ergodox_ez/keymaps/algernon/tools/log-to-heatmap.py
new file mode 100755
index 000000000..a13d12e81
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/tools/log-to-heatmap.py
@@ -0,0 +1,145 @@
+#! /usr/bin/env python
+import json
+import os
+import sys
+import re
+
+from math import floor
+
+cr_coord_map = [
+ [
+ # Row 0
+ [ 4, 0], [ 4, 2], [ 2, 0], [ 1, 0], [ 2, 2], [ 3, 0], [ 3, 2],
+ [ 3, 4], [ 3, 6], [ 2, 4], [ 1, 2], [ 2, 6], [ 4, 4], [ 4, 6],
+ ],
+ [
+ # Row 1
+ [ 8, 0], [ 8, 2], [ 6, 0], [ 5, 0], [ 6, 2], [ 7, 0], [ 7, 2],
+ [ 7, 4], [ 7, 6], [ 6, 4], [ 5, 2], [ 6, 6], [ 8, 4], [ 8, 6],
+ ],
+ [
+ # Row 2
+ [12, 0], [12, 2], [10, 0], [ 9, 0], [10, 2], [11, 0], [ ],
+ [ ], [11, 2], [10, 4], [ 9, 2], [10, 6], [12, 4], [12, 6],
+ ],
+ [
+ # Row 3
+ [17, 0], [17, 2], [15, 0], [14, 0], [15, 2], [16, 0], [13, 0],
+ [13, 2], [16, 2], [15, 4], [14, 2], [15, 6], [17, 4], [17, 6],
+ ],
+ [
+ # Row 4
+ [20, 0], [20, 2], [19, 0], [18, 0], [19, 2], [], [], [], [],
+ [19, 4], [18, 2], [19, 6], [20, 4], [20, 6],
+ ],
+ [
+ # Row 5
+ [ ], [23, 0], [22, 2], [22, 0], [22, 4], [21, 0], [21, 2],
+ [24, 0], [24, 2], [25, 0], [25, 4], [25, 2], [26, 0], [ ],
+ ],
+]
+
+def set_attr_at(j, b, n, attr, fn, val):
+ blk = j[b][n]
+ if attr in blk:
+ blk[attr] = fn(blk[attr], val)
+ else:
+ blk[attr] = fn(None, val)
+
+def coord(col, row):
+ return cr_coord_map[row][col]
+
+def set_attr(orig, new):
+ return new
+
+def set_bg(j, (b, n), color):
+ set_attr_at(j, b, n, "c", set_attr, color)
+ #set_attr_at(j, b, n, "g", set_attr, False)
+
+def _set_tap_info(o, count, cap):
+ ns = 4 - o.count ("\n")
+ return o + "\n" * ns + "%.02f%%" % (float(count) / float(cap) * 100)
+
+def set_tap_info(j, (b, n), count, cap):
+ j[b][n + 1] = _set_tap_info (j[b][n + 1], count, cap)
+
+def heatmap_color (v):
+ colors = [ [0.3, 0.3, 1], [0.3, 1, 0.3], [1, 1, 0.3], [1, 0.3, 0.3]]
+ fb = 0
+ if v <= 0:
+ idx1, idx2 = 0, 0
+ elif v >= 1:
+ idx1, idx2 = len(colors) - 1, len(colors) - 1
+ else:
+ val = v * (len(colors) - 1)
+ idx1 = int(floor(val))
+ idx2 = idx1 + 1
+ fb = val - float(idx1)
+
+ r = (colors[idx2][0] - colors[idx1][0]) * fb + colors[idx1][0]
+ g = (colors[idx2][1] - colors[idx1][1]) * fb + colors[idx1][1]
+ b = (colors[idx2][2] - colors[idx1][2]) * fb + colors[idx1][2]
+
+ r, g, b = [x * 255 for x in r, g, b]
+ return "#%02x%02x%02x" % (r, g, b)
+
+# Load the keylog
+def load_keylog(fname, restrict_row):
+ keylog = {}
+ total = 0
+ with open(fname, "r") as f:
+ lines = f.readlines()
+ for line in lines:
+ m = re.search ('KL: col=(\d+), row=(\d+)', line)
+ if not m:
+ continue
+ (c, r) = (int(m.group (2)), int(m.group (1)))
+ if restrict_row != None and r != int(restrict_row):
+ continue
+ if (c, r) in keylog:
+ keylog[(c, r)] = keylog[(c, r)] + 1
+ else:
+ keylog[(c, r)] = 1
+ total = total + 1
+ return total / 2, keylog
+
+def l_flat(s):
+ f = s.split("\n")
+ return ", ".join (f)
+
+def main(base_fn, log_fn, restrict_row = None):
+
+ with open(base_fn, "r") as f:
+ layout = json.load (f)
+
+ ## Reset colors
+ for row in cr_coord_map:
+ for col in row:
+ if col != []:
+ set_bg (layout, col, "#d9dae0")
+ #set_attr_at (layout, col[0], col[1], "g", set_attr, True)
+
+ total, log = load_keylog (log_fn, restrict_row)
+ max_cnt = 0
+ for (c, r) in log:
+ max_cnt = max(max_cnt, log[(c, r)])
+
+ # Create the heatmap
+ for (c, r) in log:
+ coords = coord(c, r)
+ b, n = coords
+ cap = max_cnt
+ v = float(log[(c, r)]) / cap
+ print >> sys.stderr, "%s => %d/%d => %f = %s" % (l_flat(layout[b][n+1]), log[(c,r)], cap, v, heatmap_color(v))
+ set_bg (layout, coord(c, r), heatmap_color (v))
+ set_tap_info (layout, coord (c, r), log[(c, r)], total)
+
+ print json.dumps(layout)
+
+if __name__ == "__main__":
+ if len(sys.argv) < 3:
+ print """Log to Heatmap -- creates a heatmap out of keyboard logs
+
+Usage: log-to-heatmap.py base-layout.json logfile [row] >layout.json"""
+ sys.exit (1)
+ main(*sys.argv[1:])
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/keymap.c b/keyboards/ergodox_ez/keymaps/teckinesis/keymap.c
new file mode 100644
index 000000000..ec6ceb96b
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/keymap.c
@@ -0,0 +1,455 @@
+#include "ergodox_ez.h"
+#include "led.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "action_util.h"
+#include "mousekey.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols layer
+#define MDIA 2 // media layer
+#define SPEC 3 // special layer
+
+#define LCaps 10 // left caps-shift key
+#define LSymb 11 // left symbol-shift key
+#define LMdia 12 // left media-shift key
+#define LSpec 13 // left special-shift key
+#define RCaps 14 // right caps-shift key
+#define RSymb 15 // right symbol-shift key
+#define RMdia 16 // right media-shift key
+#define RSpec 17 // right special-shift key
+
+#define MUL 20 // mouse up left
+#define MUR 21 // mouse up right
+#define MDL 22 // mouse down left
+#define MDR 23 // mouse down right
+
+/*
+ * teckinesis layout for ErgoDox (EZ)
+ *
+ * Modifications from The Ordinary Layout v4 by Will Wolff-Myren willwm@gmail.com
+ * Modifications from default by Nicholas Keene ergodoxez@nicholaskeene.com
+ *
+ * No rights reserved. This software is in the public domain.
+ * Credit me if you are friendly but if you're a jerk don't bother.
+ *
+ * Details: readme.md
+ * https://github.com/willwm/qmk_firmware/tree/master/keyboard/ergodox_ez/keymaps/teckinesis
+ */
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/******* Base Layer ********************************************************************************************************
+ *
+ * ,------------------------------------------------------. ,------------------------------------------------------.
+ * | Special =+ | 1 | 2 | 3 | 4 | 5 | ESC | | ` | 6 | 7 | 8 | 9 | 0 | -_ Special |
+ * |------------+------+------+------+------+-------------| |------+------+------+------+------+------+------------|
+ * | Media Tab | Q | W | E | R | T | [ | | ] | Y | U | I | O | P | \| Media |
+ * |------------+------+------+------+------+------| | | |------+------+------+------+------+------------|
+ * | Symbol | A | S | D | F | G |------| |------| H | J | K | L | ; | '" Symbol |
+ * |------------+------+------+------+------+------|Shift | | Tab |------+------+------+------+------+------------|
+ * | Capitals | Z | X | C | V | B | -Tab | | | N | M | , | . | / | Capitals |
+ * `------------+------+------+------+------+-------------' `-------------+------+------+------+------+------------'
+ * | LCtrl |Meh/\ |Hypr//| LAlt | LGui | | RGui | RAlt |Hypr/[|Meh/] | RCtrl |
+ * `-----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | Home | End | | Left | Right|
+ * ,------|------|------| |------+------+------.
+ * | | | PgUp | | Up | | |
+ * |Backsp| Del |------| |------| Enter| Space|
+ * | | | PgDn | | Down | | |
+ * `--------------------' `--------------------'
+ */
+[BASE] = KEYMAP(
+// left hand
+ F(LSpec),KC_1,KC_2,KC_3 ,KC_4 ,KC_5 ,KC_ESC
+,F(LMdia) ,KC_Q ,KC_W ,KC_E ,KC_R ,KC_T ,KC_LBRC
+,M(LSymb) ,KC_A ,KC_S ,KC_D ,KC_F ,KC_G
+,M(LCaps) ,KC_Z ,KC_X ,KC_C ,KC_V ,KC_B ,LSFT(KC_TAB)
+,KC_LCTL,MEH_T(KC_BSLS),ALL_T(KC_SLSH),KC_LALT,KC_LGUI
+ ,KC_HOME,KC_END
+ ,KC_PGUP
+ ,KC_BSPC,KC_DEL ,KC_PGDN
+ // right hand
+ ,KC_GRV ,KC_6 ,KC_7 ,KC_8 ,KC_9 ,KC_0 ,F(RSpec)
+ ,KC_RBRC ,KC_Y ,KC_U ,KC_I ,KC_O ,KC_P ,F(RMdia)
+ ,KC_H ,KC_J ,KC_K ,KC_L ,KC_SCLN ,F(RSymb)
+ ,KC_TAB ,KC_N ,KC_M ,KC_COMM,KC_DOT ,KC_SLSH ,M(RCaps)
+ ,KC_RGUI,KC_RALT,ALL_T(KC_LBRC),MEH_T(KC_RBRC),KC_RCTL
+ ,KC_LEFT ,KC_RGHT
+ ,KC_UP
+ ,KC_DOWN ,KC_ENT ,KC_SPC
+ ),
+
+/******* Symbols Layer *****************************************************************************************************
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | Esc | | - | F6 | F7 | F8 | F9 | F10 | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | | ! | @ | { | } | & | < | | > | | | 7 | 8 | 9 | / | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | # | $ | ( | ) | ` |------| |------| / | 4 | 5 | 6 | * | |
+ * |-----------+------+------+------+------+------| Tab | | Shift|------+------+------+------+------+-----------|
+ * | | % | ^ | [ | ] | ~ | | | -Tab| \ | 1 | 2 | 3 | - | |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | LCtrl | Meh |Hyper | LAlt | LGui | |RGui/0|RAlt/.|Hypr/=|Meh/+ |RCtrl/Ent|
+ * `-----------------------------------' `-------------------------------------'
+ * ,-------------. ,-------------.
+ * | Left | Right| | Home | End |
+ * ,------|------|------| |------+------+------.
+ * | | | Up | | PgUp | | |
+ * |Space |Enter |------| |------|BackSp| Del |
+ * | | | Down | | PgDn | | |
+ * `--------------------' `--------------------'
+ */
+[SYMB] = KEYMAP(
+// left hand
+ KC_TRNS ,KC_F1 ,KC_F2 ,KC_F3 ,KC_F4 ,KC_F5 ,KC_ESC
+,KC_TRNS ,KC_EXLM ,KC_AT ,KC_LCBR ,KC_RCBR ,KC_AMPR ,LSFT(KC_COMM)
+,KC_TRNS ,KC_HASH ,KC_DLR ,KC_LPRN ,KC_RPRN ,KC_GRV
+,KC_TRNS ,KC_PERC ,KC_CIRC ,KC_LBRC ,KC_RBRC ,KC_TILD ,KC_TAB
+,KC_LCTL ,KC_MEH ,KC_HYPR ,KC_LALT ,KC_LGUI
+ ,KC_LEFT ,KC_RGHT
+ ,KC_UP
+ ,KC_SPC ,KC_ENT ,KC_DOWN
+ // right hand
+ ,KC_MINS ,KC_F6 ,KC_F7 ,KC_F8 ,KC_F9 ,KC_F10 ,KC_TRNS
+ ,LSFT(KC_DOT),KC_PIPE ,KC_7 ,KC_8 ,KC_9 ,KC_SLSH ,KC_TRNS
+ ,KC_SLSH ,KC_4 ,KC_5 ,KC_6 ,KC_ASTR ,KC_TRNS
+ ,LSFT(KC_TAB),KC_BSLS ,KC_1 ,KC_2 ,KC_3 ,KC_MINS ,KC_TRNS
+ ,GUI_T(KC_0),ALT_T(KC_DOT),ALL_T(KC_EQL),MEH_T(KC_PLUS),CTL_T(KC_ENT)
+ ,KC_HOME ,KC_END
+ ,KC_PGUP
+ ,KC_PGDN ,KC_BSPC ,KC_DEL
+),
+
+/******* Media Layer *******************************************************************************************************
+ *
+ * ,---------------------------------------------------------------. ,---------------------------------------------------------------.
+ * | | F11 | F12 | F13 | F14 | F15 | Esc | | | F16 | F17 | F18 | F19 | F20 | |
+ * |------+---------+---------+---------+---------+----------------| |------+---------+---------+---------+---------+---------+------|
+ * | | |MouseUpLf|Mouse Up |MouseUpRg|Volume Up|Scroll| |Scroll|PrintScrn| Home | Up | PgUp | | |
+ * |------+---------+---------+---------+---------+---------| Up | | Up |---------+---------+---------+---------+---------+------|
+ * | | |MouseLeft|MouseDown|MouseRght|Volume Dn|------| |------| Num Lock| Left | Down | Right | | |
+ * |------+---------+---------+---------+---------+---------|Scroll| |Scroll|---------+---------+---------+---------+---------+------|
+ * | | |MouseDnLf|MouseDown|MouseDnRg| Mute | Down | | Down | | End | Down | PgDn | | |
+ * `------+---------+---------+---------+---------+----------------' `----------------+---------+---------+---------+---------+------'
+ * |LCtrl| Meh | MClick | LClick | R Click| |Cmd/Insrt|Optn/Del | Hyper | Meh |RCtrl|
+ * `---------------------------------------------' `---------------------------------------------'
+ * ,-------------. ,-------------.
+ * | Stop |Refrsh| | Prev | Next |
+ * ,------|------|------| |------+------+------.
+ * |Brwser|Brwser|Search| |VolUp | | |
+ * |Back | Fwd |------| |------| Stop | Play-|
+ * | | | Home | |VolDn | | Pause|
+ * `--------------------' `--------------------'
+ */
+[MDIA] = KEYMAP(
+// left hand
+ KC_TRNS ,KC_F11 ,KC_F12 ,KC_F13 ,KC_F14 ,KC_F15 ,KC_ESC
+,KC_TRNS ,KC_NO ,M(MUL) ,KC_MS_U ,M(MUR) ,KC_VOLU ,KC_WH_U
+,KC_TRNS ,KC_NO ,KC_MS_L ,KC_MS_D ,KC_MS_R ,KC_VOLD
+,KC_TRNS ,KC_NO ,M(MDL) ,KC_MS_D ,M(MDR) ,KC_MUTE ,KC_WH_D
+,KC_LCTL ,KC_MEH ,KC_BTN3 ,KC_BTN1 ,KC_BTN2
+ ,KC_WSTP ,KC_WREF
+ ,KC_WSCH
+ ,KC_WBAK ,KC_NO ,KC_WHOM
+ // right hand
+ ,KC_NO ,KC_F16 ,KC_F17 ,KC_F18 ,KC_F19 ,KC_F20 ,KC_TRNS
+ ,KC_WH_U ,KC_PSCR ,KC_HOME ,KC_UP ,KC_PGUP ,KC_NO ,KC_TRNS
+ ,KC_NLCK ,KC_LEFT ,KC_DOWN ,KC_RIGHT,KC_NO ,KC_TRNS
+ ,KC_WH_D ,KC_NO ,KC_END ,KC_DOWN ,KC_PGDN ,KC_NO ,KC_TRNS
+ ,GUI_T(KC_INS),ALT_T(KC_DEL),KC_HYPR ,KC_MEH ,KC_RCTL
+ ,KC_MPRV ,KC_MNXT
+ ,KC_VOLU
+ ,KC_VOLD ,KC_MSTP ,KC_MPLY
+),
+
+/******* Special Layer *****************************************************************************************************
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | | Esc | | | | | | | | | | | | Bspc | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | | | | | | | | | | | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | | | | |------| |------| | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | | | | | | | | | | | | | RShift |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[SPEC] = KEYMAP(
+// left hand
+ KC_TRNS ,KC_ESC ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,KC_TRNS,KC_TRNS ,KC_TRNS
+ // right hand
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_BSPC ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_RSFT
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ )
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ // the faux shift keys are implemented as macro taps
+ [LCaps] = ACTION_MACRO_TAP(LCaps)
+ ,[LSymb] = ACTION_MACRO_TAP(LSymb)
+ ,[LMdia] = ACTION_MACRO_TAP(LMdia)
+ ,[LSpec] = ACTION_MACRO_TAP(LSpec)
+ ,[RCaps] = ACTION_MACRO_TAP(RCaps)
+ ,[RSymb] = ACTION_MACRO_TAP(RSymb)
+ ,[RMdia] = ACTION_MACRO_TAP(RMdia)
+ ,[RSpec] = ACTION_MACRO_TAP(RSpec)
+};
+
+uint16_t caps_shift = 0;
+uint16_t symb_shift = 0;
+uint16_t mdia_shift = 0;
+
+bool symb_lock = false;
+bool mdia_lock = false;
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ // There are two shift keys for each layer so we increment a layer_shift var when one
+ // is pressed and decrement when one is released. If both are pressed at the same time
+ // then the layer is locked (or unlocked). The shift counts are bound between 0 and 2
+ // only because sometimes rapid pressing led to irregular events; this way the states
+ // are self healing during use.
+
+ case LCaps: // both caps-shift keys trigger Left Shift
+ case RCaps: // so they don't interfere with the magic combo
+ if (record->event.pressed && !record->tap.count) {
+ if(++caps_shift > 2) caps_shift = 2;
+ if(caps_shift == 2) {
+ register_code(KC_CAPS);
+ unregister_code(KC_CAPS);
+ } else if(caps_shift == 1) {
+ register_code(KC_LSFT);
+ }
+ } else {
+ if(--caps_shift < 0) caps_shift = 0;
+ if(caps_shift == 0) unregister_code(KC_LSFT);
+ }
+ break;
+
+ case LSymb:
+ if (record->event.pressed) {
+ if(++symb_shift > 2) symb_shift = 2;
+ if(symb_shift == 2) {
+ symb_lock = !symb_lock;
+ } else if(symb_shift == 1) {
+ layer_on(SYMB);
+ }
+ } else {
+ if(--symb_shift < 0) symb_shift = 0;
+ if((symb_shift == 0) && (!symb_lock)) layer_off(SYMB);
+ }
+ break;
+
+ case LMdia:
+ if (record->event.pressed) {
+ if (record->tap.count && (!mdia_shift) && (!mdia_lock)) {
+ register_code(KC_TAB);
+ } else {
+ if(++mdia_shift > 2) mdia_shift = 2;
+ if(mdia_shift == 2) {
+ mdia_lock = !mdia_lock;
+ } else if(mdia_shift == 1) {
+ layer_on(MDIA);
+ }
+ }
+ } else {
+ if(record->tap.count && (!mdia_shift) && (!mdia_lock)) {
+ unregister_code(KC_TAB);
+ } else {
+ if(--mdia_shift < 0) mdia_shift = 0;
+ if((!mdia_shift) && (!mdia_lock)) layer_off(MDIA);
+ }
+ }
+ break;
+
+ case LSpec:
+ if (record->event.pressed) {
+ if (record->tap.count && !record->tap.interrupted) {
+ register_code(KC_EQL);
+ } else {
+ layer_on(SPEC);
+ }
+ } else {
+ if(record->tap.count && !record->tap.interrupted) {
+ unregister_code(KC_EQL);
+ } else {
+ layer_off(SPEC);
+ }
+ }
+ break;
+
+ case RSymb:
+ if (record->event.pressed) {
+ if (record->tap.count && (!symb_shift) && (!symb_lock)) {
+ register_code(KC_QUOT);
+ } else {
+ if(++symb_shift > 2) symb_shift = 2;
+ if(symb_shift == 2) {
+ symb_lock = !symb_lock;
+ } else if(symb_shift == 1) {
+ layer_on(SYMB);
+ }
+ }
+ } else {
+ if(record->tap.count && symb_shift == 0) {
+ unregister_code(KC_QUOT);
+ } else {
+ if(--symb_shift < 0) symb_shift = 0;
+ if((!symb_shift) && (!symb_lock)) layer_off(SYMB);
+ }
+ }
+ break;
+
+ case RMdia:
+ if (record->event.pressed) {
+ if (record->tap.count && (!mdia_shift) && (!mdia_lock)) {
+ register_code(KC_BSLS);
+ } else {
+ if(++mdia_shift > 2) mdia_shift = 2;
+ if(mdia_shift == 2) {
+ mdia_lock = !mdia_lock;
+ } else if(mdia_shift == 1) {
+ layer_on(MDIA);
+ }
+ }
+ } else {
+ if(record->tap.count && (!mdia_shift) && (!mdia_lock)) {
+ unregister_code(KC_BSLS);
+ } else {
+ if(--mdia_shift < 0) mdia_shift = 0;
+ if((!mdia_shift) && (!mdia_lock)) layer_off(MDIA);
+ }
+ }
+ break;
+
+ case RSpec:
+ if (record->event.pressed) {
+ if (record->tap.count && !record->tap.interrupted) {
+ register_code(KC_MINS);
+ } else {
+ layer_on(SPEC);
+ }
+ } else {
+ if(record->tap.count && !record->tap.interrupted) {
+ unregister_code(KC_MINS);
+ } else {
+ layer_off(SPEC);
+ }
+ }
+ break;
+
+ // mouse diagonals
+
+ case MUL: // mouse up left
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_UP);
+ mousekey_on(KC_MS_LEFT);
+ mousekey_send();
+ } else {
+ mousekey_off(KC_MS_UP);
+ mousekey_off(KC_MS_LEFT);
+ mousekey_send();
+ }
+ break;
+
+ case MUR: // mouse up right
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_UP);
+ mousekey_on(KC_MS_RIGHT);
+ mousekey_send();
+ } else {
+ mousekey_off(KC_MS_UP);
+ mousekey_off(KC_MS_RIGHT);
+ mousekey_send();
+ }
+ break;
+
+ case MDL: // mouse down left
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_DOWN);
+ mousekey_on(KC_MS_LEFT);
+ mousekey_send();
+ } else {
+ mousekey_off(KC_MS_DOWN);
+ mousekey_off(KC_MS_LEFT);
+ mousekey_send();
+ }
+ break;
+
+ case MDR: // mouse down right
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_DOWN);
+ mousekey_on(KC_MS_RIGHT);
+ mousekey_send();
+ } else {
+ mousekey_off(KC_MS_DOWN);
+ mousekey_off(KC_MS_RIGHT);
+ mousekey_send();
+ }
+ break;
+
+ default:
+ // none
+ break;
+ }
+
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ // shift or caps lock turns on red light
+ if(caps_shift || (keyboard_report->mods & MOD_BIT(KC_RSFT)) || (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) {
+ ergodox_right_led_1_on();
+ } else {
+ ergodox_right_led_1_off();
+ }
+
+ // Symbol layer turns on green light
+ if(layer_state & (1UL<<SYMB)) {
+ ergodox_right_led_2_on();
+ } else {
+ ergodox_right_led_2_off();
+ }
+
+ // Media layer turns on blue light
+ if(layer_state & (1UL<<MDIA)) {
+ ergodox_right_led_3_on();
+ } else {
+ ergodox_right_led_3_off();
+ }
+};
+
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/ordinary-special.png b/keyboards/ergodox_ez/keymaps/teckinesis/ordinary-special.png
new file mode 100644
index 000000000..6eecf447e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/ordinary-special.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/ordinary-special.txt b/keyboards/ergodox_ez/keymaps/teckinesis/ordinary-special.txt
new file mode 100644
index 000000000..a08827c6d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/ordinary-special.txt
@@ -0,0 +1,27 @@
+[{x:3.5,a:7},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.875,x:5.5},"",{c:"#ff4444",a:4},"Esc",{x:4.5,c:"#cccccc",a:7},"",""],
+[{y:-0.875,c:"#000000",t:"#ff0000",a:4,w:1.5},"Special\n\n\n\n\n\nShift",{c:"#ff4444",t:"#000000"},"Esc",{x:14.5,c:"#54d6de"},"Back\n\n\n\n\n\nspace",{c:"#000000",t:"#ff0000",w:1.5},"\n\nSpecial\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#cccccc",t:"#000000",a:7},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.875,x:5.5},"",{h:1.5},"",{x:4.5,h:1.5},"",""],
+[{y:-0.875,w:1.5},"","",{x:14.5},"",{w:1.5},""],
+[{y:-0.375,x:3.5},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.875,x:5.5},"",{x:6.5},""],
+[{y:-0.875,w:1.5},"","",{x:14.5},"",{w:1.5},""],
+[{y:-0.625,x:6.5,h:1.5},"",{x:4.5,h:1.5},""],
+[{y:-0.75,x:3.5},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.875,x:5.5},"",{x:6.5},""],
+[{y:-0.875,w:1.5},"","",{x:14.5},"",{c:"#2277ff",w:1.5},"RShift"],
+[{y:-0.375,x:3.5,c:"#cccccc"},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.75,x:0.5},"","",{x:14.5},"",""],
+[{r:30,rx:6.5,ry:4.25,y:-1,x:1},"",""],
+[{h:2},"",{h:2},"",""],
+[{x:2},""],
+[{r:-30,rx:13,y:-1,x:-3},"",""],
+[{x:-3},"",{h:2},"",{h:2},""],
+[{x:-3},""]
+
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/readme.md b/keyboards/ergodox_ez/keymaps/teckinesis/readme.md
new file mode 100644
index 000000000..9494a4d4c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/readme.md
@@ -0,0 +1,45 @@
+# teckinesis Layout
+
+*A blend of TECK and Kinesis layouts, based on ["The Ordinary Layout" by Nicholas Keene](http://qmk.fm/keyboards/ergodox_ez/keymaps/ordinary/#the-ordinary-layout-a-familiar-and-powerful-layout)*
+
+I love "The Ordinary Layout", but I still use a [TECK](https://www.trulyergonomic.com/store/index.php)
+at the office, and I found the transition back and forth to be a bit more difficult than I expected.
+
+This layout consists of only slight changes to "The Ordinary Layout" based on the layouts of the
+[(original) TECK Model 209](https://www.trulyergonomic.com/store/layout-designer--configurator--reprogrammable--truly-ergonomic-mechanical-keyboard/#KTo7PD0+P0BBQkNERUw5394rNR4fICEi4yMkJSYnLS4xOBQaCBUXTBwYDBITLzDhBBYHCQorCw0ODzPl4B0bBhkFKhEQNjc05OPiSktOTSwoLFBSUU/mZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX2BhAFZXAAAAAAAAAAAAXF1eVAAAAAAAAAAAAABZWltVAAAAAAAAAAAAYgBjAAAAAAAAAAAAWFcAAAAAAACTAQAMAiMBAAwBigEADAIhAQAMAZQBAAwBkgEADAGDAQAMALYBAAwAzQEADAC1AQAMAOIBAAwA6gEADADpAQAMALhJAEYAAAAAAEitR64AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACk6Ozw9Pj9AQUJDREVMOd/eKzUeHyAhIuMjJCUmJy0uMTgUGggVF0wcGAwSEy8w4QQWBwkKKwsNDg8z5eMdGwYZBSoREDY3NOfg4kpLTk0sKCxQUlFP5uQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF9gYQBWVwAAAAAAAAAAAFxdXlQAAAAAAAAAAAAAWVpbVQAAAAAAAAAAAGIAYwAAAAAAAAAAAFhXAAAAAAAAkwEADAIjAQAMAYoBAAwCIQEADAGUAQAMAZIBAAwBgwEADAC2AQAMAM0BAAwAtQEADADiAQAMAOoBAAwA6QEADAC4SQBGAAAAAABIrUeuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) and
+the [Kinesis Advantage](http://www.kinesis-ergo.com/wp-content/uploads/2013/06/advantage_layout_win.pdf)
+
+## The Base Layout ##
+
+[teckinesis (Base Layer)](http://www.keyboard-layout-editor.com/#/gists/befd4c5800d92114aa9e50d4f7c0dfb0)
+![teckinesis base layout](teckinesis-base.png)
+
+### Changes from The Ordinary Layout ###
+
+* Moved KC_MINS from the key left of the 6 to the RSpec key.
+* Moved KC_EQL from RSpec to LSpec.
+* Moved KC_GRV from LSpec to the key left of the 6.
+* Mdded KC_BSLS to the left Meh key.
+* Added KC_SLSH to the left Hyper key.
+* Added KC_LBRC to the right Hyper key.
+* Added KC_RBRC to the right Meh key.
+
+## The Symbols Layer ##
+
+[teckinesis (Symbols Layer)](http://www.keyboard-layout-editor.com/#/gists/e6ddc4e9e0d194b3e52ac0616238ab61)
+![teckinesis symbols layout](teckinesis-symbol.png)
+
+### Changes from The Ordinary Layout ###
+
+* None.
+
+## The Media Layer ##
+
+[teckinesis (Media Layer)](http://www.keyboard-layout-editor.com/#/gists/41ff65e6a7c490211fd6702fb34d9908)
+![teckinesis media layout](teckinesis-media.png)
+
+### Changes from The Ordinary Layout ###
+
+* Removed Power, Sleep, Mail, My Computer keys.
+(I kept hitting these while using the mouse/cursor. =P)
+
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-base.json b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-base.json
new file mode 100644
index 000000000..69fe28cf7
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-base.json
@@ -0,0 +1,434 @@
+[
+ {
+ "name": "teckinesis (Base Layer)",
+ "author": "Will Wolff-Myren",
+ "notes": "# teckinesis Layout # \r\n\r\n*A blend of TECK and Kinesis layouts, based on [\"The Ordinary Layout\" by Nicholas Keene](http://qmk.fm/keyboards/ergodox_ez/keymaps/ordinary/#the-ordinary-layout-a-familiar-and-powerful-layout)*\r\n\r\n## The Base Layout ##\r\n\r\n![teckinesis base layout](teckinesis-base.png)\r\n\r\n## The Symbols Layer ##\r\n\r\n![teckinesis symbols layout](teckinesis-symbol.png)\r\n\r\n## The Media Layer ##\r\n\r\n(placeholder)\r\n",
+ "switchMount": "cherry",
+ "switchBrand": "gateron",
+ "switchType": "KS-3-Tea"
+ },
+ [
+ {
+ "x": 3.5
+ },
+ "#\n3",
+ {
+ "x": 10.5
+ },
+ "*\n8"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "@\n2",
+ {
+ "x": 1
+ },
+ "$\n4",
+ {
+ "x": 8.5
+ },
+ "&\n7",
+ {
+ "x": 1
+ },
+ "(\n9"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "%\n5",
+ {
+ "c": "#ff4444"
+ },
+ "Esc",
+ {
+ "x": 4.5,
+ "c": "#cccccc"
+ },
+ "~\n`",
+ "^\n6"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "Special\n\n+\n\n\n\nShift\n=",
+ {
+ "c": "#cccccc"
+ },
+ "!\n1",
+ {
+ "x": 14.5
+ },
+ ")\n0",
+ {
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "_\n\nSpecial\n\n\n\n-\nShift"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#cccccc"
+ },
+ "E",
+ {
+ "x": 10.5
+ },
+ "I"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "W",
+ {
+ "x": 1
+ },
+ "R",
+ {
+ "x": 8.5
+ },
+ "U",
+ {
+ "x": 1
+ },
+ "O"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "T",
+ {
+ "h": 1.5
+ },
+ "{\n\n\n\n\n\n[",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ "}\n\n\n\n\n\n]",
+ "Y"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#2277ff",
+ "fa": [
+ 0,
+ 0,
+ 4
+ ],
+ "w": 1.5
+ },
+ "Media\n\n<i class='kb kb-Line-Start-End'></i>\n\n\n\nShift",
+ {
+ "c": "#cccccc"
+ },
+ "Q",
+ {
+ "x": 14.5
+ },
+ "P",
+ {
+ "c": "#2277ff",
+ "f": 3,
+ "w": 1.5
+ },
+ "|\n\\\nMedia\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#cccccc"
+ },
+ "D",
+ {
+ "x": 10.5
+ },
+ "K"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "S",
+ {
+ "x": 1
+ },
+ "F",
+ {
+ "x": 8.5
+ },
+ "J",
+ {
+ "x": 1
+ },
+ "L"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "G",
+ {
+ "x": 6.5
+ },
+ "H"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "Symbols\n\n\n\n\n\nShift",
+ {
+ "c": "#cccccc"
+ },
+ "A",
+ {
+ "x": 14.5
+ },
+ ":\n;",
+ {
+ "c": "#2277ff",
+ "f": 3,
+ "w": 1.5
+ },
+ "\"\n'\nSymbols\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.625,
+ "x": 6.5,
+ "c": "#54d6de",
+ "fa": [
+ 0,
+ 0,
+ 4,
+ 1
+ ],
+ "h": 1.5
+ },
+ "< Tab\n\n\nShift Tab",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ "Tab >\n\n\nTab"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 3.5,
+ "c": "#cccccc"
+ },
+ "C",
+ {
+ "x": 10.5
+ },
+ "<\n,"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "X",
+ {
+ "x": 1
+ },
+ "V",
+ {
+ "x": 8.5
+ },
+ "M",
+ {
+ "x": 1
+ },
+ ">\n."
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "B",
+ {
+ "x": 6.5
+ },
+ "N"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "Capitals\n\n\n\n\n\nShift",
+ {
+ "c": "#cccccc"
+ },
+ "Z",
+ {
+ "x": 14.5
+ },
+ "?\n/",
+ {
+ "c": "#2277ff",
+ "f": 3,
+ "w": 1.5
+ },
+ "\n\nCapitals\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#77aaff",
+ "fa": [
+ 5,
+ 0,
+ 4,
+ 1
+ ]
+ },
+ "<i class='mss mss-Unicode-Option-3'></i>\n\n\nLAlt",
+ {
+ "x": 10.5
+ },
+ "<i class='mss mss-Unicode-Option-3'></i>\n\n\nRAlt"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "fa": [
+ 5,
+ 1
+ ]
+ },
+ "\nHyper\n?\n/",
+ {
+ "x": 1,
+ "fa": [
+ 5,
+ 1,
+ 0,
+ 1
+ ]
+ },
+ "<i class='mss mss-Unicode-Command-3'></i>\n\n\nSuper",
+ {
+ "x": 8.5
+ },
+ "<i class='mss mss-Unicode-Command-3'></i>\n\n\nSuper",
+ {
+ "x": 1,
+ "fa": [
+ 0,
+ 0,
+ 0,
+ 1
+ ]
+ },
+ "{\n[\n\nHyper"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 0.5
+ },
+ "Ctrl\n\n\nLCtrl",
+ {
+ "f2": 1
+ },
+ "\nMeh\n|\n\\",
+ {
+ "x": 14.5,
+ "fa": [
+ 0,
+ 0,
+ 1,
+ 1
+ ]
+ },
+ "}\n]\n\nMeh",
+ "Ctrl\n\n\nRCtrl"
+ ],
+ [
+ {
+ "r": 30,
+ "rx": 6.5,
+ "ry": 4.25,
+ "y": -1,
+ "x": 1,
+ "c": "#54d6de"
+ },
+ "Home",
+ "End"
+ ],
+ [
+ {
+ "h": 2
+ },
+ "< Del\n\n\nBackspace",
+ {
+ "h": 2
+ },
+ "Del >\n\n\nDelete",
+ "Page\n\n\n\n\n\nUp"
+ ],
+ [
+ {
+ "x": 2
+ },
+ "Page\n\n\n\n\n\nDown"
+ ],
+ [
+ {
+ "r": -30,
+ "rx": 13,
+ "y": -1,
+ "x": -3
+ },
+ "Left",
+ "Right"
+ ],
+ [
+ {
+ "x": -3
+ },
+ "Up",
+ {
+ "h": 2
+ },
+ "Enter",
+ {
+ "h": 2
+ },
+ "Space"
+ ],
+ [
+ {
+ "x": -3
+ },
+ "Down"
+ ]
+] \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-base.png b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-base.png
new file mode 100644
index 000000000..7c4584e9f
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-base.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-media.json b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-media.json
new file mode 100644
index 000000000..65fe394e8
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-media.json
@@ -0,0 +1,436 @@
+[
+ {
+ "name": "teckinesis (MediaLayer)",
+ "author": "Will Wolff-Myren",
+ "switchMount": "cherry",
+ "switchBrand": "gateron",
+ "switchType": "KS-3-Tea"
+ },
+ [
+ {
+ "x": 3.5,
+ "c": "#99de2a"
+ },
+ "F13",
+ {
+ "x": 10.5
+ },
+ "F18"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "F12",
+ {
+ "x": 1
+ },
+ "F14",
+ {
+ "x": 8.5
+ },
+ "F17",
+ {
+ "x": 1
+ },
+ "F19"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "F15",
+ {
+ "c": "#ff4444"
+ },
+ "Esc",
+ {
+ "x": 4.5
+ },
+ "Esc",
+ {
+ "c": "#99de2a"
+ },
+ "F16"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 1.5
+ },
+ "F11",
+ {
+ "x": 14.5
+ },
+ "F20"
+ ],
+ [
+ {
+ "y": -0.995,
+ "c": "#000000",
+ "t": "#ff0000",
+ "w": 1.5
+ },
+ "Media\n\n\n\n\n\nShift",
+ {
+ "x": 16.5,
+ "w": 1.5
+ },
+ "\n\nMedia\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.3799999999999999,
+ "x": 3.5,
+ "c": "#ff8500",
+ "t": "#000000"
+ },
+ "Mouse\n\n\n\n\n\nUp",
+ {
+ "x": 10.5
+ },
+ "Cursor\n\n\n\n\n\nUp"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "Mouse\n\n\n\n\n\nUpLeft",
+ {
+ "x": 1
+ },
+ "Mouse\n\n\n\n\n\nUpRgt",
+ {
+ "x": 8.5,
+ "c": "#ffb063"
+ },
+ "Home",
+ {
+ "x": 1
+ },
+ "Page\n\n\n\n\n\nUp"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#e6e067"
+ },
+ "Vol\n\n\n\n\n\nUp",
+ {
+ "c": "#ffb063",
+ "h": 1.5
+ },
+ "Scroll\n\n\n\n\n\nUp",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ "Scroll\n\n\n\n\n\nUp",
+ {
+ "c": "#e6e067"
+ },
+ "Print\n\n\n\n\n\nScreen"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 1.5,
+ "c": "#737373",
+ "a": 7
+ },
+ "",
+ {
+ "x": 14.5
+ },
+ ""
+ ],
+ [
+ {
+ "y": -0.9950000000000001,
+ "c": "#2277ff",
+ "a": 4,
+ "w": 1.5
+ },
+ "Symbols\n\n\n\n\n\nShift",
+ {
+ "x": 16.5,
+ "w": 1.5
+ },
+ "\n\nSymbols\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.3799999999999999,
+ "x": 3.5,
+ "c": "#ff8500"
+ },
+ "Mouse\n\n\n\n\n\nDown",
+ {
+ "x": 10.5
+ },
+ "Cursor\n\n\n\n\n\nDown"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "Mouse\n\n\n\n\n\nLeft",
+ {
+ "x": 1
+ },
+ "Mouse\n\n\n\n\n\nRight",
+ {
+ "x": 8.5
+ },
+ "Cursor\n\n\n\n\n\nLeft",
+ {
+ "x": 1
+ },
+ "Cursor\n\n\n\n\n\nRight"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#e6e067"
+ },
+ "Vol\n\n\n\n\n\nDown",
+ {
+ "x": 6.5
+ },
+ "Num\n\n\n\n\n\nLock"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 1.5,
+ "c": "#737373",
+ "a": 7
+ },
+ "",
+ {
+ "x": 14.5
+ },
+ ""
+ ],
+ [
+ {
+ "y": -0.9950000000000001,
+ "c": "#2277ff",
+ "a": 4,
+ "w": 1.5
+ },
+ "Capitals\n\n\n\n\n\nShift",
+ {
+ "x": 16.5,
+ "w": 1.5
+ },
+ "\n\nCapitals\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.6299999999999999,
+ "x": 6.5,
+ "c": "#ffb063",
+ "h": 1.5
+ },
+ "Scroll\n\n\n\n\n\nDown",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ "Scroll\n\n\n\n\n\nDown"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 3.5,
+ "c": "#ff8500"
+ },
+ "Mouse\n\n\n\n\n\nDown",
+ {
+ "x": 10.5
+ },
+ "Cursor\n\n\n\n\n\nDown"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "Mouse\n\n\n\n\n\nDnLeft",
+ {
+ "x": 1
+ },
+ "Mouse\n\n\n\n\n\nDnRgt",
+ {
+ "x": 8.5,
+ "c": "#ffb063"
+ },
+ "End",
+ {
+ "x": 1
+ },
+ "Page\n\n\n\n\n\nDown"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#e6e067"
+ },
+ "Mute",
+ {
+ "x": 6.5,
+ "c": "#737373",
+ "a": 7
+ },
+ ""
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 1.5
+ },
+ "",
+ {
+ "x": 14.5
+ },
+ ""
+ ],
+ [
+ {
+ "y": -0.9950000000000001,
+ "c": "#2277ff",
+ "a": 4,
+ "w": 1.5
+ },
+ "Ctrl",
+ {
+ "x": 16.5,
+ "w": 1.5
+ },
+ "Ctrl"
+ ],
+ [
+ {
+ "y": -0.3799999999999999,
+ "x": 3.5,
+ "c": "#ff8500"
+ },
+ "Middle\n\n\n\n\n\nClick",
+ {
+ "x": 10.5,
+ "c": "#ffb063",
+ "fa": [
+ 0,
+ 0,
+ 0,
+ 1
+ ]
+ },
+ "Delete\n\n\nOption"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#ff8500"
+ },
+ "Left\n\n\n\n\n\nClick",
+ {
+ "x": 1
+ },
+ "Right\n\n\n\n\n\nClick",
+ {
+ "x": 8.5,
+ "c": "#ffb063"
+ },
+ "Insert\n\n\nCmd",
+ {
+ "x": 1,
+ "c": "#77aaff"
+ },
+ "Hyper"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 0.5
+ },
+ "Alt\n\n\nLAlt",
+ "Meh",
+ {
+ "x": 14.5
+ },
+ "Meh",
+ "Alt\n\n\nRAlt"
+ ],
+ [
+ {
+ "r": 30,
+ "rx": 6.5,
+ "ry": 4.25,
+ "y": -1,
+ "x": 1,
+ "c": "#ccbb00"
+ },
+ "Stop\n\n\nBrowser",
+ "Reload\n\n\nBrowser"
+ ],
+ [
+ {
+ "h": 2
+ },
+ "< Web\n\n\nBrowser",
+ {
+ "h": 2
+ },
+ "Web >\n\n\nBrowser",
+ "Search\n\n\nBrowser"
+ ],
+ [
+ {
+ "x": 2
+ },
+ "Home\n\n\nBrowser"
+ ],
+ [
+ {
+ "r": -30,
+ "rx": 13,
+ "y": -1,
+ "x": -3
+ },
+ "Prev\n\n\nAudio\n\n\nTrack",
+ "Next\n\n\nAudio\n\n\nTrack"
+ ],
+ [
+ {
+ "x": -3,
+ "c": "#e6e067"
+ },
+ "Vol\n\n\n\n\n\nUp",
+ {
+ "c": "#ccbb00",
+ "h": 2
+ },
+ "Stop\n\n\nAudio",
+ {
+ "h": 2
+ },
+ "Play\n\n\nAudio\n\n\nPause"
+ ],
+ [
+ {
+ "x": -3,
+ "c": "#e6e067"
+ },
+ "Vol\n\n\n\n\n\nDown"
+ ]
+] \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-media.png b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-media.png
new file mode 100644
index 000000000..cc51605f9
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-media.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-symbol.json b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-symbol.json
new file mode 100644
index 000000000..439d0128e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-symbol.json
@@ -0,0 +1,422 @@
+[
+ {
+ "name": "teckinesis (Symbol Layer)",
+ "author": "Will Wolff-Myren",
+ "switchMount": "cherry",
+ "switchBrand": "gateron",
+ "switchType": "KS-3-Tea"
+ },
+ [
+ {
+ "x": 3.5,
+ "c": "#99de2a"
+ },
+ "F3",
+ {
+ "x": 10.5
+ },
+ "F8"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "F2",
+ {
+ "x": 1
+ },
+ "F4",
+ {
+ "x": 8.5
+ },
+ "F7",
+ {
+ "x": 1
+ },
+ "F9"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "F5",
+ {
+ "c": "#ff4444"
+ },
+ "Esc",
+ {
+ "x": 4.5,
+ "c": "#bbddbb"
+ },
+ "_\n\n\n\n\n\n-",
+ {
+ "c": "#99de2a"
+ },
+ "F6"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "Special\n\n\n\n\n\nShift",
+ {
+ "c": "#99de2a"
+ },
+ "F1",
+ {
+ "x": 14.5
+ },
+ "F10",
+ {
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "\n\nSpecial\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#bbddbb"
+ },
+ "{",
+ {
+ "x": 10.5,
+ "c": "#89b087"
+ },
+ "8"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#bbddbb"
+ },
+ "@",
+ {
+ "x": 1
+ },
+ "}",
+ {
+ "x": 8.5,
+ "c": "#89b087"
+ },
+ "7",
+ {
+ "x": 1
+ },
+ "9"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#bbddbb"
+ },
+ "&",
+ {
+ "h": 1.5
+ },
+ "<",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ ">",
+ "|"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "Media\n\n\n\n\n\nShift",
+ {
+ "c": "#bbddbb"
+ },
+ "!",
+ {
+ "x": 14.5,
+ "c": "#89b087"
+ },
+ "/",
+ {
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "\n\nMedia\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#bbddbb"
+ },
+ "(",
+ {
+ "x": 10.5,
+ "c": "#89b087"
+ },
+ "5"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#bbddbb"
+ },
+ "$",
+ {
+ "x": 1
+ },
+ ")",
+ {
+ "x": 8.5,
+ "c": "#89b087"
+ },
+ "4",
+ {
+ "x": 1
+ },
+ "6"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#bbddbb"
+ },
+ "`",
+ {
+ "x": 6.5
+ },
+ "/"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#000000",
+ "t": "#ff0000",
+ "w": 1.5
+ },
+ "Symbols\n\n\n\n\n\nShift",
+ {
+ "c": "#bbddbb",
+ "t": "#000000"
+ },
+ "#",
+ {
+ "x": 14.5,
+ "c": "#89b087"
+ },
+ "*",
+ {
+ "c": "#000000",
+ "t": "#ff0000",
+ "w": 1.5
+ },
+ "\n\nSymbols\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.625,
+ "x": 6.5,
+ "c": "#54d6de",
+ "t": "#000000",
+ "fa": [
+ 0,
+ 0,
+ 0,
+ 1
+ ],
+ "h": 1.5
+ },
+ "Tab >\n\n\nTab",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ "< Tab\n\n\nShift Tab"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 3.5,
+ "c": "#bbddbb"
+ },
+ "[",
+ {
+ "x": 10.5,
+ "c": "#89b087"
+ },
+ "2"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#bbddbb"
+ },
+ "^",
+ {
+ "x": 1
+ },
+ "]",
+ {
+ "x": 8.5,
+ "c": "#89b087"
+ },
+ "1",
+ {
+ "x": 1
+ },
+ "3"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "c": "#bbddbb"
+ },
+ "~",
+ {
+ "x": 6.5
+ },
+ "\\"
+ ],
+ [
+ {
+ "y": -0.875,
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "Capitals\n\n\n\n\n\nShift",
+ {
+ "c": "#bbddbb"
+ },
+ "%",
+ {
+ "x": 14.5,
+ "c": "#89b087"
+ },
+ "-",
+ {
+ "c": "#2277ff",
+ "w": 1.5
+ },
+ "\n\nCapitals\n\n\n\n\nShift"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "c": "#77aaff"
+ },
+ "<i class='mss mss-Unicode-Option-3'></i>\n\n\nLAlt",
+ {
+ "x": 10.5,
+ "c": "#89b087"
+ },
+ ".\n\n\nOption"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "c": "#77aaff"
+ },
+ "Hyper",
+ {
+ "x": 1
+ },
+ "<i class='mss mss-Unicode-Command-3'></i>\n\n\nSuper",
+ {
+ "x": 8.5,
+ "c": "#89b087"
+ },
+ "0\n\n\nCmd",
+ {
+ "x": 1
+ },
+ "=\n\n\nHyper"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 0.5,
+ "c": "#77aaff"
+ },
+ "Ctrl\n\n\nLCtrl",
+ "Meh",
+ {
+ "x": 14.5,
+ "c": "#89b087"
+ },
+ "+\n\n\nMeh",
+ "Enter\n\n\nCtrl"
+ ],
+ [
+ {
+ "r": 30,
+ "rx": 6.5,
+ "ry": 4.25,
+ "y": -1,
+ "x": 1,
+ "c": "#54d6de"
+ },
+ "Left",
+ "Right"
+ ],
+ [
+ {
+ "h": 2
+ },
+ "Space",
+ {
+ "h": 2
+ },
+ "Enter",
+ "Up"
+ ],
+ [
+ {
+ "x": 2
+ },
+ "Down"
+ ],
+ [
+ {
+ "r": -30,
+ "rx": 13,
+ "y": -1,
+ "x": -3
+ },
+ "Home",
+ "End"
+ ],
+ [
+ {
+ "x": -3
+ },
+ "Page\n\n\n\n\n\nUp",
+ {
+ "h": 2
+ },
+ "< Del\n\n\nBackspace",
+ {
+ "h": 2
+ },
+ "Del >\n\n\nDelete"
+ ],
+ [
+ {
+ "x": -3
+ },
+ "Page\n\n\n\n\n\nDown"
+ ]
+] \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-symbol.png b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-symbol.png
new file mode 100644
index 000000000..7ca86cf47
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/teckinesis/teckinesis-symbol.png
Binary files differ
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index b9b836df2..d240dc2e6 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -2,81 +2,70 @@
static qk_tap_dance_state_t qk_tap_dance_state;
-static void _process_tap_dance_action_pair (qk_tap_dance_state_t *state,
- uint16_t kc1, uint16_t kc2) {
- uint16_t kc;
+void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) {
+ qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
- if (state->count == 0)
- return;
-
- kc = (state->count == 1) ? kc1 : kc2;
+ if (state->count == 1) {
+ register_code (pair->kc1);
+ } else if (state->count == 2) {
+ register_code (pair->kc2);
+ }
+}
- register_code (kc);
- unregister_code (kc);
+void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) {
+ qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
- if (state->count >= 2) {
- reset_tap_dance (state);
+ if (state->count == 1) {
+ unregister_code (pair->kc1);
+ } else if (state->count == 2) {
+ unregister_code (pair->kc2);
}
}
-static void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
+static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
+ void *user_data,
qk_tap_dance_user_fn_t fn)
{
if (fn) {
- fn(state);
+ fn(state, user_data);
}
}
-void process_tap_dance_action_on_each_tap (uint16_t keycode)
+static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t action)
{
- uint16_t idx = keycode - QK_TAP_DANCE;
- qk_tap_dance_action_t action;
-
- action = tap_dance_actions[idx];
-
- switch (action.type) {
- case QK_TAP_DANCE_TYPE_FN:
- _process_tap_dance_action_fn (&qk_tap_dance_state, action.fn.on_each_tap);
- break;
-
- default:
- break;
- }
+ _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_each_tap);
}
-void process_tap_dance_action_on_dance_finished (uint16_t keycode)
+static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t action)
{
- uint16_t idx = keycode - QK_TAP_DANCE;
- qk_tap_dance_action_t action;
-
- action = tap_dance_actions[idx];
-
- switch (action.type) {
- case QK_TAP_DANCE_TYPE_PAIR:
- _process_tap_dance_action_pair (&qk_tap_dance_state,
- action.pair.kc1, action.pair.kc2);
- break;
- case QK_TAP_DANCE_TYPE_FN:
- _process_tap_dance_action_fn (&qk_tap_dance_state, action.fn.on_dance_finished);
- break;
+ _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_dance_finished);
+}
- default:
- break;
- }
+static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t action)
+{
+ _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_reset);
}
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
bool r = true;
+ uint16_t idx = keycode - QK_TAP_DANCE;
+ qk_tap_dance_action_t action;
switch(keycode) {
case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
- process_tap_dance_action_on_each_tap (qk_tap_dance_state.keycode);
+ action = tap_dance_actions[idx];
+
+ process_tap_dance_action_on_each_tap (action);
if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) {
- process_tap_dance_action_on_dance_finished (qk_tap_dance_state.keycode);
+ process_tap_dance_action_on_dance_finished (action);
+ } else if (qk_tap_dance_state.active && qk_tap_dance_state.pressed) {
+ reset_tap_dance (&qk_tap_dance_state);
} else {
r = false;
}
+ qk_tap_dance_state.active = true;
+ qk_tap_dance_state.pressed = record->event.pressed;
if (record->event.pressed) {
qk_tap_dance_state.keycode = keycode;
qk_tap_dance_state.timer = timer_read ();
@@ -87,9 +76,13 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
default:
if (qk_tap_dance_state.keycode) {
// if we are here, the tap dance was interrupted by a different key
- process_tap_dance_action_on_each_tap (qk_tap_dance_state.keycode);
- process_tap_dance_action_on_dance_finished (qk_tap_dance_state.keycode);
+ idx = qk_tap_dance_state.keycode - QK_TAP_DANCE;
+ action = tap_dance_actions[idx];
+
+ process_tap_dance_action_on_each_tap (action);
+ process_tap_dance_action_on_dance_finished (action);
reset_tap_dance (&qk_tap_dance_state);
+ qk_tap_dance_state.active = false;
}
break;
}
@@ -98,9 +91,12 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
}
void matrix_scan_tap_dance () {
- if (qk_tap_dance_state.keycode && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) {
+ if (qk_tap_dance_state.active && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) {
// if we are here, the tap dance was timed out
- process_tap_dance_action_on_dance_finished (qk_tap_dance_state.keycode);
+ uint16_t idx = qk_tap_dance_state.keycode - QK_TAP_DANCE;
+ qk_tap_dance_action_t action = tap_dance_actions[idx];
+
+ process_tap_dance_action_on_dance_finished (action);
reset_tap_dance (&qk_tap_dance_state);
}
}
@@ -109,18 +105,13 @@ void reset_tap_dance (qk_tap_dance_state_t *state) {
uint16_t idx = state->keycode - QK_TAP_DANCE;
qk_tap_dance_action_t action;
- action = tap_dance_actions[idx];
- switch (action.type) {
- case QK_TAP_DANCE_TYPE_FN:
- if (action.fn.on_reset) {
- action.fn.on_reset(state);
- }
- break;
+ if (state->pressed)
+ return;
- default:
- break;
- }
+ action = tap_dance_actions[idx];
+ process_tap_dance_action_on_reset (action);
state->keycode = 0;
state->count = 0;
+ state->active = false;
}
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
index 7b820584a..e2c74efe9 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -11,46 +11,40 @@ typedef struct
uint8_t count;
uint16_t keycode;
uint16_t timer;
+ bool active:1;
+ bool pressed:1;
} qk_tap_dance_state_t;
#define TD(n) (QK_TAP_DANCE + n)
-typedef enum
-{
- QK_TAP_DANCE_TYPE_PAIR,
- QK_TAP_DANCE_TYPE_FN,
-} qk_tap_dance_type_t;
-
-typedef void (*qk_tap_dance_user_fn_t) (qk_tap_dance_state_t *state);
+typedef void (*qk_tap_dance_user_fn_t) (qk_tap_dance_state_t *state, void *user_data);
typedef struct
{
- qk_tap_dance_type_t type;
- union {
- struct {
- uint16_t kc1;
- uint16_t kc2;
- } pair;
- struct {
- qk_tap_dance_user_fn_t on_each_tap;
- qk_tap_dance_user_fn_t on_dance_finished;
- qk_tap_dance_user_fn_t on_reset;
- } fn;
- };
+ struct {
+ qk_tap_dance_user_fn_t on_each_tap;
+ qk_tap_dance_user_fn_t on_dance_finished;
+ qk_tap_dance_user_fn_t on_reset;
+ } fn;
+ void *user_data;
} qk_tap_dance_action_t;
+typedef struct
+{
+ uint16_t kc1;
+ uint16_t kc2;
+} qk_tap_dance_pair_t;
+
#define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) { \
- .type = QK_TAP_DANCE_TYPE_PAIR, \
- .pair = { kc1, kc2 } \
+ .fn = { NULL, qk_tap_dance_pair_finished, qk_tap_dance_pair_reset }, \
+ .user_data = (void *)&((qk_tap_dance_pair_t) { kc1, kc2 }) \
}
#define ACTION_TAP_DANCE_FN(user_fn) { \
- .type = QK_TAP_DANCE_TYPE_FN, \
.fn = { NULL, user_fn, NULL } \
}
#define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset) { \
- .type = QK_TAP_DANCE_TYPE_FN, \
.fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset } \
}
@@ -62,6 +56,9 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record);
void matrix_scan_tap_dance (void);
void reset_tap_dance (qk_tap_dance_state_t *state);
+void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data);
+void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data);
+
#else
#define TD(n) KC_NO
diff --git a/readme.md b/readme.md
index ed3da43bd..4d6250f8e 100644
--- a/readme.md
+++ b/readme.md
@@ -373,7 +373,7 @@ As you can see, you have three function. you can use - `SEQ_ONE_KEY` for single-
### Tap Dance: A single key can do 3, 5, or 100 different things
-Hit the semicolon key once, send a semicolon. Hit it twice, rapidly -- send a colon. Hit it three times, and your keyboard's LEDs do a wild dance. That's just one example of what Tap Dance can do. It's one of the nicest community-contributed features in the firmware, conceived and created by [algernon](https://github.com/algernon) in [#451](https://github.com/jackhumbert/qmk_firmware/pull/451). Here's how Algernon describes the feature:
+Hit the semicolon key once, send a semicolon. Hit it twice, rapidly -- send a colon. Hit it three times, and your keyboard's LEDs do a wild dance. That's just one example of what Tap Dance can do. It's one of the nicest community-contributed features in the firmware, conceived and created by [algernon](https://github.com/algernon) in [#451](https://github.com/jackhumbert/qmk_firmware/pull/451). Here's how algernon describes the feature:
With this feature one can specify keys that behave differently, based on the amount of times they have been tapped, and when interrupted, they get handled before the interrupter.
@@ -389,7 +389,7 @@ First, you will need `TAP_DANCE_ENABLE=yes` in your `Makefile`, because the feat
This array specifies what actions shall be taken when a tap-dance key is in action. Currently, there are three possible options:
-* `ACTION_TAP_DANCE_DOUBLE(kc1, kc2)`: Sends the `kc1` keycode when tapped once, `kc2` otherwise.
+* `ACTION_TAP_DANCE_DOUBLE(kc1, kc2)`: Sends the `kc1` keycode when tapped once, `kc2` otherwise. When the key is held, the appropriate keycode is registered: `kc1` when pressed and held, `kc2` when tapped once, then pressed and held.
* `ACTION_TAP_DANCE_FN(fn)`: Calls the specified function - defined in the user keymap - with the final tap count of the tap dance action.
* `ACTION_TAP_DANCE_FN_ADVANCED(on_each_tap_fn, on_dance_finished_fn, on_reset_fn)`: Calls the first specified function - defined in the user keymap - on every tap, the second function on when the dance action finishes (like the previous option), and the last function when the tap dance action resets.
@@ -397,8 +397,6 @@ The first option is enough for a lot of cases, that just want dual roles. For ex
And that's the bulk of it!
-Do note, however, that this implementation does have some consequences: keys do not register until either they reach the tapping ceiling, or they time out. This means that if you hold the key, nothing happens, no repeat, no nothing. It is possible to detect held state, and register an action then too, but that's not implemented yet. Keys also unregister immediately after being registered, so you can't even hold the second tap. This is intentional, to be consistent.
-
And now, on to the explanation of how it works!
The main entry point is `process_tap_dance()`, called from `process_record_quantum()`, which is run for every keypress, and our handler gets to run early. This function checks whether the key pressed is a tap-dance key. If it is not, and a tap-dance was in action, we handle that first, and enqueue the newly pressed key. If it is a tap-dance key, then we check if it is the same as the already active one (if there's one active, that is). If it is not, we fire off the old one first, then register the new one. If it was the same, we increment the counter and the timer.
@@ -421,20 +419,25 @@ enum {
/* Have the above three on the keymap, TD(CT_SE), etc... */
-void dance_cln (qk_tap_dance_state_t *state) {
+void dance_cln_finished (qk_tap_dance_state_t *state, void *user_data) {
if (state->count == 1) {
register_code (KC_RSFT);
register_code (KC_SCLN);
- unregister_code (KC_SCLN);
- unregister_code (KC_RSFT);
} else {
register_code (KC_SCLN);
+ }
+}
+
+void dance_cln_reset (qk_tap_dance_state_t *state, void *user_data) {
+ if (state->count == 1) {
+ unregister_code (KC_RSFT);
+ unregister_code (KC_SCLN);
+ } else {
unregister_code (KC_SCLN);
- reset_tap_dance (state);
}
}
-void dance_egg (qk_tap_dance_state_t *state) {
+void dance_egg (qk_tap_dance_state_t *state, void *user_data) {
if (state->count >= 100) {
SEND_STRING ("Safety dance!");
reset_tap_dance (state);
@@ -443,7 +446,7 @@ void dance_egg (qk_tap_dance_state_t *state) {
// on each tap, light up one led, from right to left
// on the forth tap, turn them off from right to left
-void dance_flsh_each(qk_tap_dance_state_t *state) {
+void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) {
switch (state->count) {
case 1:
ergodox_right_led_3_on();
@@ -464,7 +467,7 @@ void dance_flsh_each(qk_tap_dance_state_t *state) {
}
// on the fourth tap, set the keyboard on flash state
-void dance_flsh_finished(qk_tap_dance_state_t *state) {
+void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) {
if (state->count >= 4) {
reset_keyboard();
reset_tap_dance(state);
@@ -472,7 +475,7 @@ void dance_flsh_finished(qk_tap_dance_state_t *state) {
}
// if the flash state didnt happen, then turn off leds, left to right
-void dance_flsh_reset(qk_tap_dance_state_t *state) {
+void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
ergodox_right_led_1_off();
_delay_ms(50);
ergodox_right_led_2_off();
@@ -482,7 +485,7 @@ void dance_flsh_reset(qk_tap_dance_state_t *state) {
const qk_tap_dance_action_t tap_dance_actions[] = {
[CT_SE] = ACTION_TAP_DANCE_DOUBLE (KC_SPC, KC_ENT)
- ,[CT_CLN] = ACTION_TAP_DANCE_FN (dance_cln)
+ ,[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, dance_cln_finished, dance_cln_reset)
,[CT_EGG] = ACTION_TAP_DANCE_FN (dance_egg)
,[CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED (dance_flsh_each, dance_flsh_finished, dance_flsh_reset)
};