Skip to content

Instantly share code, notes, and snippets.

@patrickwelker
Last active February 19, 2016 14:36
Show Gist options
  • Save patrickwelker/5fa0409aa6f5581261cd to your computer and use it in GitHub Desktop.
Save patrickwelker/5fa0409aa6f5581261cd to your computer and use it in GitHub Desktop.
Minimal working example for qmk_firmware hold+tap dual key modifications
// Demonstrates how to use double keys
// hold q = 1, tap q = q
// hold Q = !, tap Q = Q
//
// hold shift = shift, tap shift = ~
// hold ctrl = ctrl, tap ctrl = !
#include "planck.h"
#include "timer.h" // Have to include timer for timer_read and timer_elapsed
#define ____ KC_NO // Just for easy reading
#define COLMAK 0
// Macros with human readable name
#define HOLD_1_TAP_Q 10
#define HOLD_SHIFT_TAP_TILDE 20
#define HOLD_CTRL_TAP_EXLAMATION_MARK 21
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[COLMAK] = {
/* ---------------------------------------------------------------------------
* | esc | q | w | f | p | g | j | l | u | y | ; | bspc|
* |-------------------------------------------------------------------------|
* | tab | a | r | s | t | d | h | n | e | i | o |enter|
* |-------------------------------------------------------------------------|
* | shift | z | x | c | v | b | k | m | , | . | / | ` |
* |-------------------------------------------------------------------------|
* | ctrl | opt | cmd | fn |lower| space |raise|left |down | up |right|
* -------------------------------------------------------------------------*/
{MEH_T(KC_ESC), M(10), KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_M, KC_BSPC},
{ALL_T(KC_TAB), KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, LCAG_T(KC_ENT)},
{M(20), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, SFT_T(KC_GRAVE)},
{M(21), KC_LALT, KC_LGUI, ____, ____, KC_SPC, KC_SPC, RESET, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
},
};
const uint16_t PROGMEM fn_actions[] = {
};
// Put everything inside the action macros function in the base template
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
// This will hold the timestamp of when we start holding the key
static uint16_t start;
switch(id) {
// When we hit our new macro
case HOLD_1_TAP_Q:
// On keydown, start the timer
if (record->event.pressed) {
start = timer_read();
// Start holding the button (with placeholder "NO"-key)
return MACRO(D(NO), END);
} else {
// On key up
// If time was greater than 150ms, it was a hold
if (timer_elapsed(start) > 150) {
// Trigger macro for exclamation mark
return MACRO(T(1), END);
} else {
// Otherwise it was a tap, put letter q
// and release the shift key
return MACRO(T(Q), END);
}
}
break;
case HOLD_SHIFT_TAP_TILDE:
// On keydown, start the timer
if (record->event.pressed) {
start = timer_read();
// Start holding shift
return MACRO(D(LSFT), END);
} else {
// On key up
// If time was greater than 150ms, it was a hold
if (timer_elapsed(start) > 150) {
// Only release the shift key
return MACRO(U(LSFT), END);
} else {
// Otherwise it was a tap, put in a tilde (since shift is still held)
// and release the shift key
return MACRO(T(GRV), U(LSFT), END);
}
}
break;
case HOLD_CTRL_TAP_EXLAMATION_MARK:
// On keydown, start the timer
if (record->event.pressed) {
start = timer_read();
// Start holding control
return MACRO(D(LCTL), END);
} else {
// On key up
// If time was greater than 150ms, it was a hold
if (timer_elapsed(start) > 150) {
// Only release the control key
return MACRO(U(LCTL), END);
} else {
// Otherwise it was a tap, put in a exclamation mark.
// Since control is still held release the control key,
// and hold shift, press 1, realease shift
return MACRO(U(LCTL), D(LSFT), T(1), U(LSFT), END);
}
}
break;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment