aboutsummaryrefslogtreecommitdiff
path: root/quantum/action_util.c
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_util.c
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_util.c')
-rw-r--r--quantum/action_util.c455
1 files changed, 455 insertions, 0 deletions
diff --git a/quantum/action_util.c b/quantum/action_util.c
new file mode 100644
index 000000000..2b3c00cba
--- /dev/null
+++ b/quantum/action_util.c
@@ -0,0 +1,455 @@
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#include "host.h"
18#include "report.h"
19#include "debug.h"
20#include "action_util.h"
21#include "action_layer.h"
22#include "timer.h"
23#include "keycode_config.h"
24
25extern keymap_config_t keymap_config;
26
27static uint8_t real_mods = 0;
28static uint8_t weak_mods = 0;
29static uint8_t macro_mods = 0;
30#ifdef KEY_OVERRIDE_ENABLE
31static uint8_t weak_override_mods = 0;
32static uint8_t suppressed_mods = 0;
33#endif
34
35#ifdef USB_6KRO_ENABLE
36# define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
37# define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
38# define RO_INC(a) RO_ADD(a, 1)
39# define RO_DEC(a) RO_SUB(a, 1)
40static int8_t cb_head = 0;
41static int8_t cb_tail = 0;
42static int8_t cb_count = 0;
43#endif
44
45// TODO: pointer variable is not needed
46// report_keyboard_t keyboard_report = {};
47report_keyboard_t *keyboard_report = &(report_keyboard_t){};
48
49extern inline void add_key(uint8_t key);
50extern inline void del_key(uint8_t key);
51extern inline void clear_keys(void);
52
53#ifndef NO_ACTION_ONESHOT
54static uint8_t oneshot_mods = 0;
55static uint8_t oneshot_locked_mods = 0;
56uint8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
57void set_oneshot_locked_mods(uint8_t mods) {
58 if (mods != oneshot_locked_mods) {
59 oneshot_locked_mods = mods;
60 oneshot_locked_mods_changed_kb(oneshot_locked_mods);
61 }
62}
63void clear_oneshot_locked_mods(void) {
64 if (oneshot_locked_mods) {
65 oneshot_locked_mods = 0;
66 oneshot_locked_mods_changed_kb(oneshot_locked_mods);
67 }
68}
69# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
70static uint16_t oneshot_time = 0;
71bool has_oneshot_mods_timed_out(void) { return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; }
72# else
73bool has_oneshot_mods_timed_out(void) { return false; }
74# endif
75#endif
76
77/* oneshot layer */
78#ifndef NO_ACTION_ONESHOT
79/** \brief oneshot_layer_data bits
80 * LLLL LSSS
81 * where:
82 * L => are layer bits
83 * S => oneshot state bits
84 */
85static int8_t oneshot_layer_data = 0;
86
87inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; }
88inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; }
89
90# ifdef SWAP_HANDS_ENABLE
91enum {
92 SHO_OFF,
93 SHO_ACTIVE, // Swap hands button was pressed, and we didn't send any swapped keys yet
94 SHO_PRESSED, // Swap hands button is currently pressed
95 SHO_USED, // Swap hands button is still pressed, and we already sent swapped keys
96} swap_hands_oneshot = SHO_OFF;
97# endif
98
99# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
100static uint16_t oneshot_layer_time = 0;
101inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); }
102# ifdef SWAP_HANDS_ENABLE
103static uint16_t oneshot_swaphands_time = 0;
104inline bool has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= ONESHOT_TIMEOUT && (swap_hands_oneshot == SHO_ACTIVE); }
105# endif
106# endif
107
108# ifdef SWAP_HANDS_ENABLE
109
110void set_oneshot_swaphands(void) {
111 swap_hands_oneshot = SHO_PRESSED;
112 swap_hands = true;
113# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
114 oneshot_swaphands_time = timer_read();
115 if (oneshot_layer_time != 0) {
116 oneshot_layer_time = oneshot_swaphands_time;
117 }
118# endif
119}
120
121void release_oneshot_swaphands(void) {
122 if (swap_hands_oneshot == SHO_PRESSED) {
123 swap_hands_oneshot = SHO_ACTIVE;
124 }
125 if (swap_hands_oneshot == SHO_USED) {
126 clear_oneshot_swaphands();
127 }
128}
129
130void use_oneshot_swaphands(void) {
131 if (swap_hands_oneshot == SHO_PRESSED) {
132 swap_hands_oneshot = SHO_USED;
133 }
134 if (swap_hands_oneshot == SHO_ACTIVE) {
135 clear_oneshot_swaphands();
136 }
137}
138
139void clear_oneshot_swaphands(void) {
140 swap_hands_oneshot = SHO_OFF;
141 swap_hands = false;
142# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
143 oneshot_swaphands_time = 0;
144# endif
145}
146
147# endif
148
149/** \brief Set oneshot layer
150 *
151 * FIXME: needs doc
152 */
153void set_oneshot_layer(uint8_t layer, uint8_t state) {
154 if (!keymap_config.oneshot_disable) {
155 oneshot_layer_data = layer << 3 | state;
156 layer_on(layer);
157# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
158 oneshot_layer_time = timer_read();
159# endif
160 oneshot_layer_changed_kb(get_oneshot_layer());
161 } else {
162 layer_on(layer);
163 }
164}
165/** \brief Reset oneshot layer
166 *
167 * FIXME: needs doc
168 */
169void reset_oneshot_layer(void) {
170 oneshot_layer_data = 0;
171# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
172 oneshot_layer_time = 0;
173# endif
174 oneshot_layer_changed_kb(get_oneshot_layer());
175}
176/** \brief Clear oneshot layer
177 *
178 * FIXME: needs doc
179 */
180void clear_oneshot_layer_state(oneshot_fullfillment_t state) {
181 uint8_t start_state = oneshot_layer_data;
182 oneshot_layer_data &= ~state;
183 if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) || keymap_config.oneshot_disable) {
184 layer_off(get_oneshot_layer());
185 reset_oneshot_layer();
186 }
187}
188/** \brief Is oneshot layer active
189 *
190 * FIXME: needs doc
191 */
192bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); }
193
194/** \brief set oneshot
195 *
196 * FIXME: needs doc
197 */
198void oneshot_set(bool active) {
199 if (keymap_config.oneshot_disable != active) {
200 keymap_config.oneshot_disable = active;
201 eeconfig_update_keymap(keymap_config.raw);
202 dprintf("Oneshot: active: %d\n", active);
203 }
204}
205
206/** \brief toggle oneshot
207 *
208 * FIXME: needs doc
209 */
210void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); }
211
212/** \brief enable oneshot
213 *
214 * FIXME: needs doc
215 */
216void oneshot_enable(void) { oneshot_set(true); }
217
218/** \brief disable oneshot
219 *
220 * FIXME: needs doc
221 */
222void oneshot_disable(void) { oneshot_set(false); }
223
224bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; }
225
226#endif
227
228/** \brief Send keyboard report
229 *
230 * FIXME: needs doc
231 */
232void send_keyboard_report(void) {
233 keyboard_report->mods = real_mods;
234 keyboard_report->mods |= weak_mods;
235 keyboard_report->mods |= macro_mods;
236
237#ifndef NO_ACTION_ONESHOT
238 if (oneshot_mods) {
239# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
240 if (has_oneshot_mods_timed_out()) {
241 dprintf("Oneshot: timeout\n");
242 clear_oneshot_mods();
243 }
244# endif
245 keyboard_report->mods |= oneshot_mods;
246 if (has_anykey(keyboard_report)) {
247 clear_oneshot_mods();
248 }
249 }
250
251#endif
252
253#ifdef KEY_OVERRIDE_ENABLE
254 // These need to be last to be able to properly control key overrides
255 keyboard_report->mods &= ~suppressed_mods;
256 keyboard_report->mods |= weak_override_mods;
257#endif
258
259 host_keyboard_send(keyboard_report);
260}
261
262/** \brief Get mods
263 *
264 * FIXME: needs doc
265 */
266uint8_t get_mods(void) { return real_mods; }
267/** \brief add mods
268 *
269 * FIXME: needs doc
270 */
271void add_mods(uint8_t mods) { real_mods |= mods; }
272/** \brief del mods
273 *
274 * FIXME: needs doc
275 */
276void del_mods(uint8_t mods) { real_mods &= ~mods; }
277/** \brief set mods
278 *
279 * FIXME: needs doc
280 */
281void set_mods(uint8_t mods) { real_mods = mods; }
282/** \brief clear mods
283 *
284 * FIXME: needs doc
285 */
286void clear_mods(void) { real_mods = 0; }
287
288/** \brief get weak mods
289 *
290 * FIXME: needs doc
291 */
292uint8_t get_weak_mods(void) { return weak_mods; }
293/** \brief add weak mods
294 *
295 * FIXME: needs doc
296 */
297void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
298/** \brief del weak mods
299 *
300 * FIXME: needs doc
301 */
302void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
303/** \brief set weak mods
304 *
305 * FIXME: needs doc
306 */
307void set_weak_mods(uint8_t mods) { weak_mods = mods; }
308/** \brief clear weak mods
309 *
310 * FIXME: needs doc
311 */
312void clear_weak_mods(void) { weak_mods = 0; }
313
314#ifdef KEY_OVERRIDE_ENABLE
315/** \brief set weak mods used by key overrides. DO not call this manually
316 */
317void set_weak_override_mods(uint8_t mods) { weak_override_mods = mods; }
318/** \brief clear weak mods used by key overrides. DO not call this manually
319 */
320void clear_weak_override_mods(void) { weak_override_mods = 0; }
321
322/** \brief set suppressed mods used by key overrides. DO not call this manually
323 */
324void set_suppressed_override_mods(uint8_t mods) { suppressed_mods = mods; }
325/** \brief clear suppressed mods used by key overrides. DO not call this manually
326 */
327void clear_suppressed_override_mods(void) { suppressed_mods = 0; }
328#endif
329
330/* macro modifier */
331/** \brief get macro mods
332 *
333 * FIXME: needs doc
334 */
335uint8_t get_macro_mods(void) { return macro_mods; }
336/** \brief add macro mods
337 *
338 * FIXME: needs doc
339 */
340void add_macro_mods(uint8_t mods) { macro_mods |= mods; }
341/** \brief del macro mods
342 *
343 * FIXME: needs doc
344 */
345void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; }
346/** \brief set macro mods
347 *
348 * FIXME: needs doc
349 */
350void set_macro_mods(uint8_t mods) { macro_mods = mods; }
351/** \brief clear macro mods
352 *
353 * FIXME: needs doc
354 */
355void clear_macro_mods(void) { macro_mods = 0; }
356
357#ifndef NO_ACTION_ONESHOT
358/** \brief get oneshot mods
359 *
360 * FIXME: needs doc
361 */
362uint8_t get_oneshot_mods(void) { return oneshot_mods; }
363
364void add_oneshot_mods(uint8_t mods) {
365 if ((oneshot_mods & mods) != mods) {
366# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
367 oneshot_time = timer_read();
368# endif
369 oneshot_mods |= mods;
370 oneshot_mods_changed_kb(mods);
371 }
372}
373
374void del_oneshot_mods(uint8_t mods) {
375 if (oneshot_mods & mods) {
376 oneshot_mods &= ~mods;
377# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
378 oneshot_time = oneshot_mods ? timer_read() : 0;
379# endif
380 oneshot_mods_changed_kb(oneshot_mods);
381 }
382}
383
384/** \brief set oneshot mods
385 *
386 * FIXME: needs doc
387 */
388void set_oneshot_mods(uint8_t mods) {
389 if (!keymap_config.oneshot_disable) {
390 if (oneshot_mods != mods) {
391# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
392 oneshot_time = timer_read();
393# endif
394 oneshot_mods = mods;
395 oneshot_mods_changed_kb(mods);
396 }
397 }
398}
399
400/** \brief clear oneshot mods
401 *
402 * FIXME: needs doc
403 */
404void clear_oneshot_mods(void) {
405 if (oneshot_mods) {
406 oneshot_mods = 0;
407# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
408 oneshot_time = 0;
409# endif
410 oneshot_mods_changed_kb(oneshot_mods);
411 }
412}
413#endif
414
415/** \brief Called when the one shot modifiers have been changed.
416 *
417 * \param mods Contains the active modifiers active after the change.
418 */
419__attribute__((weak)) void oneshot_locked_mods_changed_user(uint8_t mods) {}
420
421/** \brief Called when the locked one shot modifiers have been changed.
422 *
423 * \param mods Contains the active modifiers active after the change.
424 */
425__attribute__((weak)) void oneshot_locked_mods_changed_kb(uint8_t mods) { oneshot_locked_mods_changed_user(mods); }
426
427/** \brief Called when the one shot modifiers have been changed.
428 *
429 * \param mods Contains the active modifiers active after the change.
430 */
431__attribute__((weak)) void oneshot_mods_changed_user(uint8_t mods) {}
432
433/** \brief Called when the one shot modifiers have been changed.
434 *
435 * \param mods Contains the active modifiers active after the change.
436 */
437__attribute__((weak)) void oneshot_mods_changed_kb(uint8_t mods) { oneshot_mods_changed_user(mods); }
438
439/** \brief Called when the one shot layers have been changed.
440 *
441 * \param layer Contains the layer that is toggled on, or zero when toggled off.
442 */
443__attribute__((weak)) void oneshot_layer_changed_user(uint8_t layer) {}
444
445/** \brief Called when the one shot layers have been changed.
446 *
447 * \param layer Contains the layer that is toggled on, or zero when toggled off.
448 */
449__attribute__((weak)) void oneshot_layer_changed_kb(uint8_t layer) { oneshot_layer_changed_user(layer); }
450
451/** \brief inspect keyboard state
452 *
453 * FIXME: needs doc
454 */
455uint8_t has_anymod(void) { return bitpop(real_mods); }