aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode/process_tap_dance.c
diff options
context:
space:
mode:
authorRyan Ascheman <rascheman@groupon.com>2016-10-18 12:42:02 -0700
committerRyan Ascheman <rascheman@groupon.com>2016-10-18 12:42:02 -0700
commit55b8b8477cc6aee82dfe6792eea4e589cac433d5 (patch)
treece5bfbd1b0ee59dbffdc2044bcf90c89614392ed /quantum/process_keycode/process_tap_dance.c
parentd1c70328f8d8ded6ce1e5422b468fc41ef315e7d (diff)
parent04df74f6360464661bcc1e6794e9fd3549084390 (diff)
downloadqmk_firmware-55b8b8477cc6aee82dfe6792eea4e589cac433d5.tar.gz
qmk_firmware-55b8b8477cc6aee82dfe6792eea4e589cac433d5.zip
Merge remote-tracking branch 'upstream/master'
* upstream/master: (1239 commits) Update ez.c removes planck/rev3 temporarily Move hand_swap_config to ez.c, removes error for infinity Update Makefile ergodox: Update algernon's keymap to v1.9 Added VS Code dir to .gitignore Support the Pegasus Hoof controller. [Jack & Erez] Simplifies and documents TO add readme use wait_ms instead of _delay_ms add messenger init keymap Add example keymap Adding whiskey_tango_foxtrot_capslock ergodox keymap Unicode map framework. Allow unicode up to 0xFFFFF using separate mapping table CIE 1931 dim curve Apply the dim curve to the RGB output Update the Cluecard readme files Tune snake and knight intervals for Cluecard Tunable RGB light intervals ...
Diffstat (limited to 'quantum/process_keycode/process_tap_dance.c')
-rw-r--r--quantum/process_keycode/process_tap_dance.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
new file mode 100644
index 000000000..6ae362c4c
--- /dev/null
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -0,0 +1,136 @@
1#include "quantum.h"
2#include "action_tapping.h"
3
4static uint16_t last_td;
5static int8_t highest_td = -1;
6
7void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) {
8 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
9
10 if (state->count == 1) {
11 register_code16 (pair->kc1);
12 } else if (state->count == 2) {
13 register_code16 (pair->kc2);
14 }
15}
16
17void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) {
18 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
19
20 if (state->count == 1) {
21 unregister_code16 (pair->kc1);
22 } else if (state->count == 2) {
23 unregister_code16 (pair->kc2);
24 }
25}
26
27static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
28 void *user_data,
29 qk_tap_dance_user_fn_t fn)
30{
31 if (fn) {
32 fn(state, user_data);
33 }
34}
35
36static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action)
37{
38 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap);
39}
40
41static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action)
42{
43 if (action->state.finished)
44 return;
45 action->state.finished = true;
46 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
47}
48
49static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
50{
51 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
52}
53
54bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
55 uint16_t idx = keycode - QK_TAP_DANCE;
56 qk_tap_dance_action_t *action;
57
58 if (last_td && last_td != keycode) {
59 (&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true;
60 }
61
62 switch(keycode) {
63 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
64 if ((int16_t)idx > highest_td)
65 highest_td = idx;
66 action = &tap_dance_actions[idx];
67
68 action->state.pressed = record->event.pressed;
69 if (record->event.pressed) {
70 action->state.keycode = keycode;
71 action->state.count++;
72 action->state.timer = timer_read();
73 process_tap_dance_action_on_each_tap (action);
74
75 if (last_td && last_td != keycode) {
76 qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE];
77 paction->state.interrupted = true;
78 process_tap_dance_action_on_dance_finished (paction);
79 reset_tap_dance (&paction->state);
80 }
81
82 last_td = keycode;
83 }
84
85 break;
86
87 default:
88 if (!record->event.pressed)
89 return true;
90
91 if (highest_td == -1)
92 return true;
93
94 for (int i = 0; i <= highest_td; i++) {
95 action = &tap_dance_actions[i];
96 if (action->state.count == 0)
97 continue;
98 action->state.interrupted = true;
99 process_tap_dance_action_on_dance_finished (action);
100 reset_tap_dance (&action->state);
101 }
102 break;
103 }
104
105 return true;
106}
107
108void matrix_scan_tap_dance () {
109 if (highest_td == -1)
110 return;
111
112 for (int i = 0; i <= highest_td; i++) {
113 qk_tap_dance_action_t *action = &tap_dance_actions[i];
114
115 if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
116 process_tap_dance_action_on_dance_finished (action);
117 reset_tap_dance (&action->state);
118 }
119 }
120}
121
122void reset_tap_dance (qk_tap_dance_state_t *state) {
123 qk_tap_dance_action_t *action;
124
125 if (state->pressed)
126 return;
127
128 action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
129
130 process_tap_dance_action_on_reset (action);
131
132 state->count = 0;
133 state->interrupted = false;
134 state->finished = false;
135 last_td = 0;
136}