Skip to content

Instantly share code, notes, and snippets.

@hia3
Created July 20, 2016 02:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hia3/2752ce267f110a1681be92e40824a25d to your computer and use it in GitHub Desktop.
Save hia3/2752ce267f110a1681be92e40824a25d to your computer and use it in GitHub Desktop.
Workman, tap dance, hold=repeat, no delay
#include "ergodox_ez.h"
#include "debug.h"
#include "action_layer.h"
#define BASE 0 // default layer
#define SYMB 1 // symbols
#define MDIA 2 // media keys
#define TD_A 0 // use TD(TD_A)
#define TD_S 1 // use TD(TD_B)
#define LFT_T(kc) MT(MOD_LSFT, kc)
#define RFT_T(kc) MT(MOD_RSFT, kc)
enum keyboard_functions
{
kf_ver,
kf_F1, kf_F2, kf_F3, kf_F4, kf_F5, kf_F6, kf_F7, kf_F8, kf_F9, kf_F10, kf_F11, kf_F12,
kf_a, kf_b, kf_c, kf_d, kf_e, kf_f, kf_g, kf_h, kf_i, kf_j, kf_k, kf_l, kf_m,
kf_n, kf_o, kf_p, kf_q, kf_r, kf_s, kf_t, kf_u, kf_v, kf_w, kf_x, kf_y, kf_z,
};
uint16_t kf_timers[10];
void
handle_kf(keyrecord_t* record, uint8_t id, uint8_t opt)
{
if (id == kf_F11 || id == kf_F12) {
uint8_t const kc = id - kf_F11 + KC_F11;
if (record->event.pressed) {
register_code(kc);
} else {
unregister_code(kc);
}
return;
}
uint8_t const timer_index = id - kf_F1;
if (record->event.pressed) {
kf_timers[timer_index] = timer_read();
} else {
bool const is_long_press = timer_elapsed(kf_timers[timer_index]) > 200;
uint8_t const kc_base = is_long_press ? KC_F1 : KC_1;
uint8_t const kc = kc_base + timer_index;
register_code(kc);
unregister_code(kc);
}
}
typedef struct
{
uint8_t kc;
uint16_t time;
} prev_tap_t;
typedef struct
{
uint8_t physical;
uint16_t virtual;
} substitute_t;
struct prev_tap_info_t
{
union info_t
{
prev_tap_t prev;
substitute_t subs;
} info;
bool active;
} prev_tap = {};
/*
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | | ! | & | # | | | @ | | | | $ | ^ | % | * | ? | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | + | ( | [ | { | ~ |------| |------| ` | } | ] | ) | - | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | | | / | = | " | | | | ' | _ | \ | | | |
// left hand
KC_TRNS, KC_EXLM, KC_AMPR, KC_HASH, KC_PIPE, KC_AT, KC_TRNS,
KC_TRNS, KC_PLUS, KC_LPRN, KC_LBRC, KC_LCBR, KC_TILD,
KC_TRNS, KC_NO, KC_NO, KC_SLSH, KC_EQL, KC_DQT, KC_TRNS,
// right hand
KC_TRNS, KC_DLR, KC_CIRC, KC_PERC, KC_ASTR, ???KC_QUES???, KC_TRNS,
KC_GRV, KC_RCBR, KC_RBRC, KC_RPRN, KC_MINS, KC_TRNS,
KC_TRNS, KC_QUOT, KC_UNDERSCORE, ???KC_BSLS???, KC_NO, KC_NO, KC_TRNS,
*/
uint16_t physical_to_virtual[] = {
KC_PLUS, // A
KC_AT, // B
KC_EQL, // C
KC_AMPR, // D
KC_RBRC, // E
KC_CIRC, // F
KC_TILD, // G
KC_LBRC, // H
KC_MINS, // I
KC_DLR, // J
KC_QUOT, // K
KC_UNDS, // L
KC_SLSH, // M
KC_RCBR, // N
KC_RPRN, // O
KC_ASTR, // P
KC_EXLM, // Q
KC_HASH, // R
KC_LPRN, // S
KC_LCBR, // T
KC_PERC, // U
KC_DQT, // V
KC_PIPE, // W
KC_X, // X
KC_GRV, // Y
KC_Z, // Z
};
void
handle_kf_az(keyrecord_t* record, uint8_t id, uint8_t opt)
{
uint8_t const kc = id - kf_a + KC_A;
if (record->event.pressed) {
if (prev_tap.active) {
// substitute_t * data = &prev_tap.info.subs;
register_code(kc);
} else {
// not active
prev_tap_t* data = &prev_tap.info.prev;
bool const same_key = data->kc == kc;
bool const quick_tap = timer_elapsed(data->time) < 200;
if (same_key && quick_tap) {
prev_tap.active = true;
substitute_t* data = &prev_tap.info.subs;
data->physical = kc;
data->virtual = physical_to_virtual[kc - KC_A];
register_code(KC_BSPC);
unregister_code(KC_BSPC);
if (QK_LSFT & data->virtual)
register_code(KC_LSFT);
register_code(data->virtual);
} else {
register_code(kc);
data->kc = kc;
data->time = timer_read();
}
}
} else {
// some key goes up
if (prev_tap.active) {
substitute_t* data = &prev_tap.info.subs;
bool const our_key = data->physical == kc;
if (our_key) {
unregister_code(data->virtual);
if (QK_LSFT & data->virtual)
unregister_code(KC_LSFT);
data->virtual = 0;
data->physical = 0;
prev_tap.active = false;
} else {
unregister_code(kc);
}
} else {
// not active
// prev_tap_t * data = &prev_tap.info.prev;
unregister_code(kc);
}
}
}
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: Basic layer
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | ESC | 1/F1 | 2/F2 | 3/F3 | 4/F4 | 5/F5 | F11 | | F12 | 6/F6 | 7/F7 | 8/F8 | 9/F9 | 0/F10| |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | Tab | Q | D | R | W | B | | | | J | F | U | P | ; | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* |CapsLock| A | S | H | T | G |------| |------| Y | N | E | O | I | |
* |--------+------+------+------+------+------| | | Meh |------+------+------+------+------+--------|
* |LSh/Home| Z | X | M | C | V |Alt-F4| | | K | L | , | . | |RSh/End |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | CMD | | Lead | OPT | CTRL | | L3 | L2 | Lead | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | PrtSc| |
* ,------|------|------| |------+------+------.
* | | | Home | | PgUp | | |
* |Space |Bckspc|------| |------|Delete|Enter |
* | | | End | | PgDn | | |
* `--------------------' `--------------------'
*/
// If it accepts an argument (i.e, is a function), it doesn't need KC_.
// Otherwise, it needs KC_*
[BASE] = KEYMAP( // layer 0 : default
// left hand
KC_ESC, M(kf_F1), M(kf_F2), M(kf_F3), M(kf_F4), M(kf_F5), M(kf_F11),
KC_TAB, M(kf_q), M(kf_d), M(kf_r), M(kf_w), M(kf_b), KC_NO, //KC_Q, KC_D, KC_R, KC_W, KC_B, KC_NO,
KC_CAPS, M(kf_a), M(kf_s), M(kf_h), M(kf_t), M(kf_g), //KC_A, KC_S, KC_H, KC_T, KC_G,
LFT_T(KC_HOME), M(kf_z), M(kf_x), M(kf_m), M(kf_c), M(kf_v), LALT(KC_F4), //KC_Z, KC_X, KC_M, KC_C, KC_V, LALT(KC_F4),
KC_LGUI, KC_NO, KC_LEAD, KC_LALT, KC_LCTL,
KC_NO, KC_NO,
KC_HOME,
KC_SPC, KC_BSPC, KC_END,
// right hand
M(kf_F12), M(kf_F6), M(kf_F7), M(kf_F8), M(kf_F9), M(kf_F10), KC_NO,
KC_NO, M(kf_j), M(kf_f), M(kf_u), M(kf_p), KC_SCLN, KC_NO, //KC_J, KC_F, KC_U, KC_P, KC_SCLN, KC_NO,
M(kf_y), M(kf_n), M(kf_e), M(kf_o), M(kf_i), KC_NO, //KC_Y, KC_N, KC_E, KC_O, KC_I, KC_NO,
MEH_T(KC_NO), M(kf_k), M(kf_l), KC_COMM, KC_DOT, KC_NO, RFT_T(KC_END), //KC_K, KC_L, KC_COMM, KC_DOT, KC_NO, RFT_T(KC_END),
OSL(SYMB), MO(MDIA), KC_LEAD, KC_NO, KC_NO,
KC_PSCR, KC_NO,
KC_PGUP,
KC_PGDN,KC_DELT,KC_ENT
),
/* Keymap 1: Symbol Layer
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | | | | | | | | | | | | | | | |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | | ! | & | # | | | @ | | | | $ | ^ | % | * | ? | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | + | ( | [ | { | ~ |------| |------| ` | } | ] | ) | - | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | | | / | = | " | | | | ' | _ | \ | | | |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | | | | | | | | | | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*/
// SYMBOLS
[SYMB] = KEYMAP(
// left hand
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_EXLM, KC_AMPR, KC_HASH, KC_PIPE, KC_AT, KC_TRNS,
KC_TRNS, KC_PLUS, KC_LPRN, KC_LBRC, KC_LCBR, KC_TILD,
KC_TRNS, KC_NO, KC_NO, KC_SLSH, KC_EQL, KC_DQT, 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_TRNS, KC_TRNS,
KC_TRNS, KC_DLR, KC_CIRC, KC_PERC, KC_ASTR, KC_QUES, KC_TRNS,
KC_GRV, KC_RCBR, KC_RBRC, KC_RPRN, KC_MINS, KC_TRNS,
KC_TRNS, KC_QUOT, KC_UNDERSCORE, KC_BSLS, KC_NO, KC_NO, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
),
/* Keymap 2: Media and mouse keys
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | RESET | | | | | | | | | | | | | | Mute |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | Version| | | MsUp | | | | | | | | Up | | | VolUp |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | |MsLeft|MsDown|MsRght| |------| |------| | Left | Down |Right | | VolDn |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | | | | | | | | | | | Prev | Next | | Play |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | | | | Lclk | Rclk | | | | | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | |Brwser|
* | | |------| |------| |Back |
* | | | | | | | |
* `--------------------' `--------------------'
*/
// MEDIA AND MOUSE
[MDIA] = KEYMAP(
RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
M(kf_ver), KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
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_TRNS, KC_MUTE,
KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_VOLU,
KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_VOLD,
KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_MPLY,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_WBAK
),
};
const uint16_t PROGMEM fn_actions[] = {
};
qk_tap_dance_action_t const tap_dance_actions[] = {
[TD_A] = ACTION_TAP_DANCE_DOUBLE(KC_A, KC_PLUS),
[TD_S] = ACTION_TAP_DANCE_DOUBLE(KC_S, KC_LPRN),
};
const macro_t*
action_get_macro(keyrecord_t* record, uint8_t id, uint8_t opt)
{
// MACRODOWN only works in this function
switch (id) {
case kf_ver: {
if (record->event.pressed) {
SEND_STRING("SMS " __DATE__ " " __TIME__);
}
} break;
case kf_F1... kf_F12: {
handle_kf(record, id, opt);
} break;
case kf_a... kf_z: {
handle_kf_az(record, id, opt);
} break;
default:
return MACRO_NONE;
}
return MACRO_NONE;
};
// Runs just one time when the keyboard initializes.
void matrix_init_user(void){
};
LEADER_EXTERNS();
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {
LEADER_DICTIONARY()
{
leading = false;
leader_end();
SEQ_TWO_KEYS(KC_A, KC_A)
{
SEND_STRING("alignas");
}
SEQ_TWO_KEYS(KC_A, KC_O)
{
SEND_STRING("alignof");
}
SEQ_ONE_KEY(KC_A)
{
SEND_STRING("auto");
}
SEQ_ONE_KEY(KC_B)
{
SEND_STRING("bool");
}
SEQ_TWO_KEYS(KC_B, KC_R)
{
SEND_STRING("break");
}
SEQ_TWO_KEYS(KC_C, KC_S)
{
SEND_STRING("case");
}
SEQ_TWO_KEYS(KC_C, KC_H)
{
SEND_STRING("catch");
}
SEQ_ONE_KEY(KC_C)
{
SEND_STRING("char");
}
SEQ_TWO_KEYS(KC_C, KC_2)
{
SEND_STRING("char16_t");
}
SEQ_TWO_KEYS(KC_C, KC_4)
{
SEND_STRING("char32_t");
}
SEQ_TWO_KEYS(KC_C, KC_L)
{
SEND_STRING("class");
}
SEQ_TWO_KEYS(KC_C, KC_O)
{
SEND_STRING("const");
}
SEQ_TWO_KEYS(KC_C, KC_E)
{
SEND_STRING("constexpr");
}
SEQ_TWO_KEYS(KC_C, KC_C)
{
SEND_STRING("const_cast");
}
SEQ_TWO_KEYS(KC_C, KC_T)
{
SEND_STRING("continue");
}
SEQ_TWO_KEYS(KC_D, KC_T)
{
SEND_STRING("decltype");
}
SEQ_TWO_KEYS(KC_D, KC_F)
{
SEND_STRING("default");
}
SEQ_TWO_KEYS(KC_D, KC_L)
{
SEND_STRING("delete");
}
SEQ_ONE_KEY(KC_D)
{
SEND_STRING("double");
}
SEQ_TWO_KEYS(KC_D, KC_C)
{
SEND_STRING("dynamic_cast");
}
SEQ_TWO_KEYS(KC_E, KC_L)
{
SEND_STRING("else");
}
SEQ_TWO_KEYS(KC_E, KC_N)
{
SEND_STRING("enum");
}
SEQ_TWO_KEYS(KC_E, KC_P)
{
SEND_STRING("explicit");
}
SEQ_TWO_KEYS(KC_E, KC_T)
{
SEND_STRING("extern");
}
SEQ_TWO_KEYS(KC_F, KC_A)
{
SEND_STRING("false");
}
SEQ_ONE_KEY(KC_F)
{
SEND_STRING("float");
}
SEQ_TWO_KEYS(KC_F, KC_R)
{
SEND_STRING("friend");
}
SEQ_ONE_KEY(KC_G)
{
SEND_STRING("goto");
}
SEQ_TWO_KEYS(KC_I, KC_L)
{
SEND_STRING("inline");
}
SEQ_ONE_KEY(KC_I)
{
SEND_STRING("int");
}
SEQ_TWO_KEYS(KC_I, KC_C)
{
SEND_STRING("#include");
}
SEQ_ONE_KEY(KC_L)
{
SEND_STRING("long");
}
SEQ_ONE_KEY(KC_M)
{
SEND_STRING("mutable");
}
SEQ_TWO_KEYS(KC_N, KC_S)
{
SEND_STRING("namespace");
}
SEQ_TWO_KEYS(KC_N, KC_E)
{
SEND_STRING("noexcept");
}
SEQ_TWO_KEYS(KC_N, KC_P)
{
SEND_STRING("nullptr");
}
SEQ_ONE_KEY(KC_O)
{
SEND_STRING("operator");
}
SEQ_TWO_KEYS(KC_P, KC_V)
{
SEND_STRING("private");
}
SEQ_TWO_KEYS(KC_P, KC_T)
{
SEND_STRING("protected");
}
SEQ_TWO_KEYS(KC_P, KC_B)
{
SEND_STRING("public");
}
SEQ_TWO_KEYS(KC_R, KC_G)
{
SEND_STRING("register");
}
SEQ_TWO_KEYS(KC_R, KC_C)
{
SEND_STRING("reinterpret_cast");
}
SEQ_TWO_KEYS(KC_R, KC_T)
{
SEND_STRING("return");
}
SEQ_ONE_KEY(KC_S)
{
SEND_STRING("short");
}
SEQ_TWO_KEYS(KC_S, KC_I)
{
SEND_STRING("signed");
}
SEQ_TWO_KEYS(KC_S, KC_Z)
{
SEND_STRING("sizeof");
}
SEQ_TWO_KEYS(KC_S, KC_T)
{
SEND_STRING("static");
}
SEQ_TWO_KEYS(KC_S, KC_A)
{
SEND_STRING("static_assert");
}
SEQ_TWO_KEYS(KC_S, KC_C)
{
SEND_STRING("static_cast");
}
SEQ_TWO_KEYS(KC_S, KC_R)
{
SEND_STRING("struct");
}
SEQ_TWO_KEYS(KC_S, KC_W)
{
SEND_STRING("switch");
}
SEQ_TWO_KEYS(KC_T, KC_E)
{
SEND_STRING("template");
}
SEQ_TWO_KEYS(KC_T, KC_S)
{
SEND_STRING("this");
}
SEQ_TWO_KEYS(KC_T, KC_L)
{
SEND_STRING("thread_local");
}
SEQ_TWO_KEYS(KC_T, KC_W)
{
SEND_STRING("throw");
}
SEQ_TWO_KEYS(KC_T, KC_R)
{
SEND_STRING("true");
}
SEQ_TWO_KEYS(KC_T, KC_D)
{
SEND_STRING("typedef");
}
SEQ_TWO_KEYS(KC_T, KC_I)
{
SEND_STRING("typeid");
}
SEQ_TWO_KEYS(KC_T, KC_N)
{
SEND_STRING("typename");
}
SEQ_TWO_KEYS(KC_U, KC_N)
{
SEND_STRING("union");
}
SEQ_ONE_KEY(KC_U)
{
SEND_STRING("unsigned");
}
SEQ_TWO_KEYS(KC_U, KC_S)
{
SEND_STRING("using");
}
SEQ_TWO_KEYS(KC_V, KC_I)
{
SEND_STRING("virtual");
}
SEQ_ONE_KEY(KC_V)
{
SEND_STRING("void");
}
SEQ_TWO_KEYS(KC_V, KC_O)
{
SEND_STRING("volatile");
}
SEQ_ONE_KEY(KC_W)
{
SEND_STRING("wchar_t");
}
SEQ_TWO_KEYS(KC_W, KC_H)
{
SEND_STRING("while");
}
}
ergodox_led_all_off();
uint8_t layer = biton32(layer_state);
static int cc = 0;
if (++cc > 500) {
cc = 0;
}
if (cc > 250) {
ergodox_right_led_3_on();
}
switch (layer) {
case SYMB:
ergodox_right_led_1_on();
break;
case MDIA:
ergodox_right_led_2_on();
break;
default:
// none
break;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment