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