]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/action_macro.h
Extended the hint of the programmer to link to the relevant README part instead of...
[qmk_firmware.git] / tmk_core / common / action_macro.h
1 /*
2 Copyright 2013 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 #ifndef ACTION_MACRO_H
18 #define ACTION_MACRO_H
19 #include <stdint.h>
20 #include "progmem.h"
21
22
23
24 typedef uint8_t macro_t;
25
26 #define MACRO_NONE      (macro_t*)0
27 #define MACRO(...)      ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
28 #define MACRO_GET(p)    pgm_read_byte(p)
29
30 // Sends press when the macro key is pressed, release when release, or tap_macro when the key has been tapped
31 #define MACRO_TAP_HOLD(record, press, release, tap_macro) ( ((record)->event.pressed) ? \
32      ( ((record)->tap.count <= 0 || (record)->tap.interrupted) ? (press) : MACRO_NONE ) : \
33      ( ((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (tap_macro) : (release) ) )
34
35 // Holds down the modifier mod when the macro key is held, or sends macro instead when tapped
36 #define MACRO_TAP_HOLD_MOD(record, macro, mod) MACRO_TAP_HOLD(record, (MACRO(D(mod), END)), MACRO(U(mod), END), macro)
37
38 // Holds down the modifier mod when the macro key is held, or pressed a shifted key when tapped (eg: shift+3 for #)
39 #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)
40
41
42 // Momentary switch layer when held, sends macro if tapped
43 #define MACRO_TAP_HOLD_LAYER(record, macro, layer) ( ((record)->event.pressed) ? \
44      ( ((record)->tap.count <= 0 || (record)->tap.interrupted) ? ({layer_on((layer)); MACRO_NONE; }) : MACRO_NONE ) : \
45      ( ((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (macro) : ({layer_off((layer)); MACRO_NONE; }) ) )
46
47 // Momentary switch layer when held, presses a shifted key when tapped (eg: shift+3 for #)
48 #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)
49      
50
51
52 #ifndef NO_ACTION_MACRO
53 void action_macro_play(const macro_t *macro_p);
54 #else
55 #define action_macro_play(macro)
56 #endif
57
58
59
60 /* Macro commands
61  *   code(0x04-73)                      // key down(1byte)
62  *   code(0x04-73) | 0x80               // key up(1byte)
63  *   { KEY_DOWN, code(0x04-0xff) }      // key down(2bytes)
64  *   { KEY_UP,   code(0x04-0xff) }      // key up(2bytes)
65  *   WAIT                               // wait milli-seconds
66  *   INTERVAL                           // set interval between macro commands
67  *   END                                // stop macro execution
68  *
69  * Ideas(Not implemented):
70  *   modifiers
71  *   system usage
72  *   consumer usage
73  *   unicode usage
74  *   function call
75  *   conditionals
76  *   loop
77  */
78 enum macro_command_id{
79     /* 0x00 - 0x03 */
80     END                 = 0x00,
81     KEY_DOWN,
82     KEY_UP,
83
84     /* 0x04 - 0x73 (reserved for keycode down) */
85
86     /* 0x74 - 0x83 */
87     WAIT                = 0x74,
88     INTERVAL,
89
90     /* 0x84 - 0xf3 (reserved for keycode up) */
91
92     /* 0xf4 - 0xff */
93 };
94
95
96 /* TODO: keycode:0x04-0x73 can be handled by 1byte command  else 2bytes are needed
97  * if keycode between 0x04 and 0x73
98  *      keycode / (keycode|0x80)
99  * else
100  *      {KEY_DOWN, keycode} / {KEY_UP, keycode}
101 */
102 #define DOWN(key)       KEY_DOWN, (key)
103 #define UP(key)         KEY_UP, (key)
104 #define TYPE(key)       DOWN(key), UP(key)
105 #define WAIT(ms)        WAIT, (ms)
106 #define INTERVAL(ms)    INTERVAL, (ms)
107
108 /* key down */
109 #define D(key)          DOWN(KC_##key)
110 /* key up */
111 #define U(key)          UP(KC_##key)
112 /* key type */
113 #define T(key)          TYPE(KC_##key)
114 /* wait */
115 #define W(ms)           WAIT(ms)
116 /* interval */
117 #define I(ms)           INTERVAL(ms)
118
119 /* for backward comaptibility */
120 #define MD(key)         DOWN(KC_##key)
121 #define MU(key)         UP(KC_##key)
122
123
124 #endif /* ACTION_MACRO_H */