diff options
author | Joel Challis <git@zvecr.com> | 2021-08-18 00:18:58 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-18 00:18:58 +0100 |
commit | b8e913c8db73ebf890e4604ee41991a34354a600 (patch) | |
tree | 258035f8fda9f83f08a309f6cd608b9c61476678 /quantum/action_util.c | |
parent | 96e2b13d1de227cdc2b918fb0292bd832d346a25 (diff) | |
download | qmk_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.c | 455 |
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 | /* | ||
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 | #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 | |||
25 | extern keymap_config_t keymap_config; | ||
26 | |||
27 | static uint8_t real_mods = 0; | ||
28 | static uint8_t weak_mods = 0; | ||
29 | static uint8_t macro_mods = 0; | ||
30 | #ifdef KEY_OVERRIDE_ENABLE | ||
31 | static uint8_t weak_override_mods = 0; | ||
32 | static 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) | ||
40 | static int8_t cb_head = 0; | ||
41 | static int8_t cb_tail = 0; | ||
42 | static int8_t cb_count = 0; | ||
43 | #endif | ||
44 | |||
45 | // TODO: pointer variable is not needed | ||
46 | // report_keyboard_t keyboard_report = {}; | ||
47 | report_keyboard_t *keyboard_report = &(report_keyboard_t){}; | ||
48 | |||
49 | extern inline void add_key(uint8_t key); | ||
50 | extern inline void del_key(uint8_t key); | ||
51 | extern inline void clear_keys(void); | ||
52 | |||
53 | #ifndef NO_ACTION_ONESHOT | ||
54 | static uint8_t oneshot_mods = 0; | ||
55 | static uint8_t oneshot_locked_mods = 0; | ||
56 | uint8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; } | ||
57 | void 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 | } | ||
63 | void 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)) | ||
70 | static uint16_t oneshot_time = 0; | ||
71 | bool has_oneshot_mods_timed_out(void) { return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; } | ||
72 | # else | ||
73 | bool 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 | */ | ||
85 | static int8_t oneshot_layer_data = 0; | ||
86 | |||
87 | inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; } | ||
88 | inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; } | ||
89 | |||
90 | # ifdef SWAP_HANDS_ENABLE | ||
91 | enum { | ||
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)) | ||
100 | static uint16_t oneshot_layer_time = 0; | ||
101 | inline 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 | ||
103 | static uint16_t oneshot_swaphands_time = 0; | ||
104 | inline 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 | |||
110 | void 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 | |||
121 | void 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 | |||
130 | void 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 | |||
139 | void 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 | */ | ||
153 | void 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 | */ | ||
169 | void 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 | */ | ||
180 | void 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 | */ | ||
192 | bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); } | ||
193 | |||
194 | /** \brief set oneshot | ||
195 | * | ||
196 | * FIXME: needs doc | ||
197 | */ | ||
198 | void 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 | */ | ||
210 | void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); } | ||
211 | |||
212 | /** \brief enable oneshot | ||
213 | * | ||
214 | * FIXME: needs doc | ||
215 | */ | ||
216 | void oneshot_enable(void) { oneshot_set(true); } | ||
217 | |||
218 | /** \brief disable oneshot | ||
219 | * | ||
220 | * FIXME: needs doc | ||
221 | */ | ||
222 | void oneshot_disable(void) { oneshot_set(false); } | ||
223 | |||
224 | bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; } | ||
225 | |||
226 | #endif | ||
227 | |||
228 | /** \brief Send keyboard report | ||
229 | * | ||
230 | * FIXME: needs doc | ||
231 | */ | ||
232 | void 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 | */ | ||
266 | uint8_t get_mods(void) { return real_mods; } | ||
267 | /** \brief add mods | ||
268 | * | ||
269 | * FIXME: needs doc | ||
270 | */ | ||
271 | void add_mods(uint8_t mods) { real_mods |= mods; } | ||
272 | /** \brief del mods | ||
273 | * | ||
274 | * FIXME: needs doc | ||
275 | */ | ||
276 | void del_mods(uint8_t mods) { real_mods &= ~mods; } | ||
277 | /** \brief set mods | ||
278 | * | ||
279 | * FIXME: needs doc | ||
280 | */ | ||
281 | void set_mods(uint8_t mods) { real_mods = mods; } | ||
282 | /** \brief clear mods | ||
283 | * | ||
284 | * FIXME: needs doc | ||
285 | */ | ||
286 | void clear_mods(void) { real_mods = 0; } | ||
287 | |||
288 | /** \brief get weak mods | ||
289 | * | ||
290 | * FIXME: needs doc | ||
291 | */ | ||
292 | uint8_t get_weak_mods(void) { return weak_mods; } | ||
293 | /** \brief add weak mods | ||
294 | * | ||
295 | * FIXME: needs doc | ||
296 | */ | ||
297 | void add_weak_mods(uint8_t mods) { weak_mods |= mods; } | ||
298 | /** \brief del weak mods | ||
299 | * | ||
300 | * FIXME: needs doc | ||
301 | */ | ||
302 | void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; } | ||
303 | /** \brief set weak mods | ||
304 | * | ||
305 | * FIXME: needs doc | ||
306 | */ | ||
307 | void set_weak_mods(uint8_t mods) { weak_mods = mods; } | ||
308 | /** \brief clear weak mods | ||
309 | * | ||
310 | * FIXME: needs doc | ||
311 | */ | ||
312 | void 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 | */ | ||
317 | void 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 | */ | ||
320 | void 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 | */ | ||
324 | void 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 | */ | ||
327 | void 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 | */ | ||
335 | uint8_t get_macro_mods(void) { return macro_mods; } | ||
336 | /** \brief add macro mods | ||
337 | * | ||
338 | * FIXME: needs doc | ||
339 | */ | ||
340 | void add_macro_mods(uint8_t mods) { macro_mods |= mods; } | ||
341 | /** \brief del macro mods | ||
342 | * | ||
343 | * FIXME: needs doc | ||
344 | */ | ||
345 | void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; } | ||
346 | /** \brief set macro mods | ||
347 | * | ||
348 | * FIXME: needs doc | ||
349 | */ | ||
350 | void set_macro_mods(uint8_t mods) { macro_mods = mods; } | ||
351 | /** \brief clear macro mods | ||
352 | * | ||
353 | * FIXME: needs doc | ||
354 | */ | ||
355 | void clear_macro_mods(void) { macro_mods = 0; } | ||
356 | |||
357 | #ifndef NO_ACTION_ONESHOT | ||
358 | /** \brief get oneshot mods | ||
359 | * | ||
360 | * FIXME: needs doc | ||
361 | */ | ||
362 | uint8_t get_oneshot_mods(void) { return oneshot_mods; } | ||
363 | |||
364 | void 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 | |||
374 | void 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 | */ | ||
388 | void 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 | */ | ||
404 | void 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 | */ | ||
455 | uint8_t has_anymod(void) { return bitpop(real_mods); } | ||