]> git.donarmstrong.com Git - qmk_firmware.git/commitdiff
Add support for various tapping macros
authorLuke Silva <lukemasilva@gmail.com>
Sat, 28 Jan 2017 07:42:35 +0000 (18:42 +1100)
committerLuke Silva <lukemasilva@gmail.com>
Sat, 28 Jan 2017 07:42:35 +0000 (18:42 +1100)
A macro key can now be easily set to act as a modifier on hold, and
press a shifted key when tapped. Or to switch layers when held, and
again press a shifted key when tapped.

Various other helper defines have been created which send macros when
the key is pressed, released and tapped, cleaning up the
action_get_macro function inside keymap definitions.

The layer switching macros require a GCC extension - 'compound
statements enclosed within parentheses'. The use of this extension is
already present within the macro subsystem of this project, so its use
in this commit should not cause any additional issues.

MACRO_NONE had to be cast to a (macro_t*) to suppress compiler
warnings within some tapping macros.

quantum/quantum_keycodes.h
tmk_core/common/action_macro.h

index 4566395fd8a22d8b64e25298f93a545a1ff21d6b..e0d469561869819d13cbdc18a107de7af4ed8c25 100644 (file)
@@ -249,6 +249,7 @@ enum quantum_keycodes {
 #define MACROTAP(kc) (kc | QK_MACRO | FUNC_TAP<<8)
 #define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
 
+
 // L-ayer, T-ap - 256 keycode max, 16 layer max
 #define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
 
index aedc32ec6b2c428e53cd24d3d5c105eb1f1143eb..f373f5068e57a709a88ca752616fb7cb1b7a137a 100644 (file)
@@ -20,11 +20,33 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "progmem.h"
 
 
-#define MACRO_NONE      0
+
+typedef uint8_t macro_t;
+
+#define MACRO_NONE      (macro_t*)0
 #define MACRO(...)      ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
 #define MACRO_GET(p)    pgm_read_byte(p)
 
-typedef uint8_t macro_t;
+// Sends press when the macro key is pressed, release when release, or tap_macro when the key has been tapped
+#define MACRO_TAP_HOLD(record, press, release, tap_macro) ( ((record)->event.pressed) ? \
+     ( ((record)->tap.count <= 0 || (record)->tap.interrupted) ? (press) : MACRO_NONE ) : \
+     ( ((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (tap_macro) : (release) ) )
+
+// Holds down the modifier mod when the macro key is held, or sends macro instead when tapped
+#define MACRO_TAP_HOLD_MOD(record, macro, mod) MACRO_TAP_HOLD(record, (MACRO(D(mod), END)), MACRO(U(mod), END), macro)
+
+// Holds down the modifier mod when the macro key is held, or pressed a shifted key when tapped (eg: shift+3 for #)
+#define MACRO_TAP_SHFT_KEY_HOLD_MOD(record, key, mod) MACRO_TAP_HOLD_MOD(record, (MACRO(I(10), D(LSFT), T(key), U(LSFT), END)), mod)
+
+
+// Momentary switch layer when held, sends macro if tapped
+#define MACRO_TAP_HOLD_LAYER(record, macro, layer) ( ((record)->event.pressed) ? \
+     ( ((record)->tap.count <= 0 || (record)->tap.interrupted) ? ({layer_on((layer)); MACRO_NONE; }) : MACRO_NONE ) : \
+     ( ((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (macro) : ({layer_off((layer)); MACRO_NONE; }) ) )
+
+// Momentary switch layer when held, presses a shifted key when tapped (eg: shift+3 for #)
+#define MACRO_TAP_SHFT_KEY_HOLD_LAYER(record, key, layer) MACRO_TAP_HOLD_LAYER(record, MACRO(I(10), D(LSFT), T(key), U(LSFT), END), layer)
+     
 
 
 #ifndef NO_ACTION_MACRO