]> git.gir.st - tmk_keyboard.git/blob - common/action.c
Add oneshot modifier action.
[tmk_keyboard.git] / common / action.c
1 #include "host.h"
2 #include "timer.h"
3 #include "keymap.h"
4 #include "keycode.h"
5 #include "keyboard.h"
6 #include "mousekey.h"
7 #include "command.h"
8 #include "util.h"
9 #include "debug.h"
10 #include "action.h"
11
12
13 static void process(keyrecord_t *record);
14
15 // TODO
16 /* layer */
17 uint8_t default_layer = 0;
18 uint8_t current_layer = 0;
19
20 /* tap term(ms) */
21 #define TAP_TERM 200
22
23 /* This counts up when tap occurs */
24 uint8_t tap_count = 0;
25 keyevent_t tapping_event = {};
26 keyrecord_t tapping_key = {};
27
28 /* TAPPING: This indicates that whether tap or not is not decided yet. */
29 // NOTE: keyevent_t.time 0 means no event.
30 #define IS_TAPPING() (tapping_key.event.time != 0)
31 #define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
32 #define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
33 #define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
34 #define WITHIN_TAP_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAP_TERM)
35
36 /* waiting keys buffer */
37 #define WAITING_BUFFER_SIZE 8
38 static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
39 /* point to empty cell to enq */
40 static uint8_t waiting_buffer_head = 0;
41 /* point to the oldest data cell to deq */
42 static uint8_t waiting_buffer_tail = 0;
43
44 static bool waiting_buffer_enq(keyrecord_t record)
45 {
46 if (IS_NOEVENT(record.event)) {
47 return true;
48 }
49
50 if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
51 debug("waiting_buffer_enq: Over flow.\n");
52 return false;
53 }
54
55 debug("waiting_buffer_enq["); debug_dec(waiting_buffer_head); debug("] = ");
56 debug_hex16(record.event.key.raw); debug("\n");
57
58 waiting_buffer[waiting_buffer_head] = record;
59 waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
60 return true;
61 }
62 static keyrecord_t waiting_buffer_deq(void)
63 {
64 if (waiting_buffer_head == waiting_buffer_tail) {
65 return (keyrecord_t){};
66 }
67 uint8_t last_tail = waiting_buffer_tail;
68 waiting_buffer_tail = waiting_buffer_tail + 1 % WAITING_BUFFER_SIZE;
69 return waiting_buffer[last_tail];
70 }
71 static bool waiting_buffer_is_empty(void)
72 {
73 return (waiting_buffer_head == waiting_buffer_tail);
74 }
75 static void waiting_buffer_clear(void)
76 {
77 waiting_buffer_head = 0;
78 waiting_buffer_tail = 0;
79 }
80 static bool waiting_buffer_typed(keyevent_t event)
81 {
82 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
83 if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) {
84 return true;
85 }
86 }
87 return false;
88 }
89 static bool waiting_buffer_has_anykey_pressed(void)
90 {
91 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
92 if (waiting_buffer[i].event.pressed) return true;
93 }
94 return false;
95 }
96 static void waiting_buffer_process(void)
97 {
98 }
99
100 /* Oneshot modifier
101 *
102 * Problem: Want to capitalize like 'The' but the result tends to be 'THe'.
103 * Solution: Oneshot modifier have its effect on only one key coming next.
104 * Tap Shift, then type 't', 'h' and 'e'. Not need to hold Shift key.
105 *
106 * Hold: works as normal modifier.
107 * Tap: one shot modifier.
108 * 2 Tap: cancel one shot modifier.
109 * 5-Tap: toggles enable/disable oneshot feature.
110 */
111 static struct {
112 uint8_t mods;
113 uint8_t time;
114 bool ready;
115 bool disabled;
116 } oneshot_state;
117 static void oneshot_start(uint8_t mods, uint16_t time)
118 {
119 oneshot_state.mods = mods;
120 oneshot_state.time = time;
121 oneshot_state.ready = true;
122 }
123 static void oneshot_cancel(void)
124 {
125 oneshot_state.mods = 0;
126 oneshot_state.time = 0;
127 oneshot_state.ready = false;
128 }
129 static void oneshot_toggle(void)
130 {
131 oneshot_state.disabled = !oneshot_state.disabled;
132 }
133
134
135 /*
136 * Rule to judge tap:
137 * Tap key is typed(pressed and released) within TAP_TERM
138 * without interfaring by typing other key.
139 */
140 /* return true when key event is processed. */
141 static bool process_tap(keyrecord_t *keyp)
142 {
143 keyevent_t event = keyp->event;
144
145 // if tapping
146 if (IS_TAPPING_PRESSED()) {
147 if (WITHIN_TAP_TERM(event)) {
148 if (tapping_key.tap_count == 0) {
149 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
150 // first tap!
151 debug("Tapping: First tap.\n");
152 tapping_key.tap_count = 1;
153 process(&tapping_key);
154
155 // enqueue
156 keyp->tap_count = tapping_key.tap_count;
157 return false;
158 } else if (!event.pressed && waiting_buffer_typed(event)) {
159 // other key typed. not tap.
160 debug("Tapping: End(No tap. Interfered by typing key).\n");
161 process(&tapping_key);
162 tapping_key = (keyrecord_t){};
163
164 // enqueue
165 return false;
166 } else {
167 // other key events shall be stored till tapping state settles.
168 return false;
169 }
170 } else {
171 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
172 keyp->tap_count = tapping_key.tap_count;
173 debug("Tapping: tap release("); debug_dec(keyp->tap_count); debug(")\n");
174 tapping_key = *keyp;
175 return false;
176 }
177 else if (is_tap_key(keyp->event.key) && event.pressed) {
178 debug("Tapping: Start with forcing to release last tap.\n");
179 process(&(keyrecord_t){
180 .tap_count = tapping_key.tap_count,
181 .event.key = tapping_key.event.key,
182 .event.time = event.time,
183 .event.pressed = false
184 });
185 tapping_key = *keyp;
186 return false;
187 }
188 else {
189 if (!IS_NOEVENT(keyp->event)) debug("Tapping: key event while tap.\n");
190 process(keyp);
191 return true;
192 }
193 }
194 }
195 // not within TAP_TERM
196 else {
197 if (tapping_key.tap_count == 0) {
198 // timeout. not tap.
199 debug("Tapping: End. Not tap(time out).\n");
200 process(&tapping_key);
201 tapping_key = (keyrecord_t){};
202 return false;
203 } else {
204 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
205 debug("Tapping: End. tap release.");
206 keyp->tap_count = tapping_key.tap_count;
207 process(keyp);
208 tapping_key = (keyrecord_t){};
209 return true;
210 } else {
211 // other key after tap time out.
212 process(keyp);
213 return true;
214 }
215 }
216 }
217 } else if (IS_TAPPING_RELEASED()) {
218 if (WITHIN_TAP_TERM(event)) {
219 if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
220 // sequential tap.
221 keyp->tap_count = tapping_key.tap_count + 1;
222 debug("Tapping: tap press("); debug_dec(keyp->tap_count); debug(")\n");
223 process(keyp);
224 tapping_key = *keyp;
225 return true;
226 } else if (event.pressed && is_tap_key(event.key)) {
227 // Sequential tap can be interfered with other tap key.
228 debug("Tapping: Start with interfering other tap.\n");
229 tapping_key = *keyp;
230 return true;
231 } else {
232 if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n");
233 process(keyp);
234 return true;
235 }
236 } else {
237 // timeout. no sequential tap.
238 debug("Tapping: End(Time out after releasing last tap).\n");
239 tapping_key = (keyrecord_t){};
240 process(keyp);
241 return true;
242 }
243 } else {
244 if (event.pressed && is_tap_key(event.key)) {
245 debug("Tapping: Start(Press tap key).\n");
246 tapping_key = *keyp;
247 return true;
248 } else {
249 process(keyp);
250 return true;
251 }
252 }
253 }
254
255 void action_exec(keyevent_t event)
256 {
257 if (!IS_NOEVENT(event)) {
258 debug("event: ");
259 debug_hex16(event.time); debug(": ");
260 debug_hex16(event.key.raw);
261 debug("[");
262 if (event.pressed) debug("down"); else debug("up");
263 debug("]\n");
264 }
265
266 keyrecord_t record = { .event = event };
267
268 // pre-process on tapping
269 if (process_tap(&record)) {
270 if (!IS_NOEVENT(record.event)) debug("processed.\n");
271 } else {
272 if (!IS_NOEVENT(record.event)) debug("enqueued.\n");
273 if (!waiting_buffer_enq(record)) {
274 // clear all in case of overflow.
275 clear_keyboard();
276 waiting_buffer_clear();
277 tapping_key = (keyrecord_t){};
278 }
279 }
280
281 // TODO: need to process every time?
282 // process waiting_buffer
283 for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
284 if (process_tap(&waiting_buffer[waiting_buffer_tail])) {
285 debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
286 debug_hex16(waiting_buffer[waiting_buffer_tail].event.key.raw); debug("\n");
287 } else {
288 break;
289 }
290 }
291 }
292
293 static void process(keyrecord_t *record)
294 {
295 // TODO: use record
296 keyevent_t event = record->event;
297 uint8_t tap_count = record->tap_count;
298
299 if (IS_NOEVENT(event)) { return; }
300
301 action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col);
302 debug("action: "); debug_hex16(action.code);
303 if (event.pressed) debug("[down]\n"); else debug("[up]\n");
304
305 switch (action.kind.id) {
306 /* Key and Mods */
307 case ACT_LMODS:
308 case ACT_RMODS:
309 {
310 uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
311 action.key.mods<<4;
312 if (event.pressed) {
313 uint8_t tmp_mods = host_get_mods();
314 if (mods) {
315 host_add_mods(mods);
316 host_send_keyboard_report();
317 }
318 register_code(action.key.code);
319 if (mods && action.key.code) {
320 host_set_mods(tmp_mods);
321 host_send_keyboard_report();
322 }
323 } else {
324 if (mods && !action.key.code) {
325 host_del_mods(mods);
326 host_send_keyboard_report();
327 }
328 unregister_code(action.key.code);
329 }
330 }
331 break;
332 case ACT_LMODS_TAP:
333 case ACT_RMODS_TAP:
334 {
335 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
336 action.key.mods<<4;
337 switch (action.layer.code) {
338 case 0x00:
339 // Oneshot modifier
340 if (event.pressed) {
341 if (tap_count == 0) {
342 debug("MODS_TAP: Oneshot: add_mods\n");
343 add_mods(mods);
344 }
345 else if (tap_count == 1) {
346 debug("MODS_TAP: Oneshot: start\n");
347 oneshot_start(mods, event.time);
348 }
349 else if (tap_count == 5) {
350 debug("MODS_TAP: Oneshot: toggle\n");
351 oneshot_toggle();
352 }
353 else {
354 debug("MODS_TAP: Oneshot: cancel&add_mods\n");
355 // double tap cancels oneshot and works as normal modifier.
356 oneshot_cancel();
357 add_mods(mods);
358 }
359 } else {
360 if (tap_count == 0) {
361 debug("MODS_TAP: Oneshot: cancel/del_mods\n");
362 // cancel oneshot by holding.
363 oneshot_cancel();
364 del_mods(mods);
365 }
366 else if (tap_count == 1) {
367 debug("MODS_TAP: Oneshot: del_mods\n");
368 // retain Oneshot
369 del_mods(mods);
370 }
371 else {
372 debug("MODS_TAP: Oneshot: del_mods\n");
373 // cancel Mods
374 del_mods(mods);
375 }
376 }
377 break;
378 default:
379 if (event.pressed) {
380 if (tap_count > 0) {
381 if (waiting_buffer_has_anykey_pressed()) {
382 debug("MODS_TAP: Tap: Cancel: add_mods\n");
383 // ad hoc: set 0 to cancel tap
384 record->tap_count = 0;
385 add_mods(mods);
386 } else {
387 debug("MODS_TAP: Tap: register_code\n");
388 register_code(action.key.code);
389 }
390 } else {
391 debug("MODS_TAP: No tap: add_mods\n");
392 add_mods(mods);
393 }
394 } else {
395 if (tap_count > 0) {
396 debug("MODS_TAP: Tap: unregister_code\n");
397 unregister_code(action.key.code);
398 } else {
399 debug("MODS_TAP: No tap: add_mods\n");
400 del_mods(mods);
401 }
402 }
403 break;
404 }
405 }
406 break;
407
408 /* other HID usage */
409 case ACT_USAGE:
410 #ifdef EXTRAKEY_ENABLE
411 switch (action.usage.page) {
412 case ACTION_USAGE_PAGE_SYSTEM:
413 if (event.pressed) {
414 host_system_send(action.usage.code);
415 } else {
416 host_system_send(0);
417 }
418 break;
419 case ACTION_USAGE_PAGE_CONSUMER:
420 if (event.pressed) {
421 host_consumer_send(action.usage.code);
422 } else {
423 host_consumer_send(0);
424 }
425 break;
426 }
427 #endif
428 break;
429
430 /* Mouse key */
431 case ACT_MOUSEKEY:
432 #ifdef MOUSEKEY_ENABLE
433 if (event.pressed) {
434 mousekey_on(action.key.code);
435 mousekey_send();
436 } else {
437 mousekey_off(action.key.code);
438 mousekey_send();
439 }
440 #endif
441 break;
442
443 /* Layer key */
444 case ACT_LAYER_PRESSED:
445 // layer action when pressed
446 switch (action.layer.code) {
447 case 0x00:
448 if (event.pressed) {
449 layer_switch(action.layer.opt);
450 }
451 break;
452 case 0xF0:
453 // TODO: tap toggle
454 break;
455 case 0xFF:
456 if (event.pressed) {
457 default_layer = action.layer.opt;
458 layer_switch(default_layer);
459 }
460 break;
461 default:
462 // with tap key
463 if (event.pressed) {
464 if (IS_TAPPING_KEY(event.key)) {
465 if (tap_count > 0) {
466 debug("LAYER_PRESSED: Tap: register_code\n");
467 register_code(action.layer.code);
468 } else {
469 debug("LAYER_PRESSED: No tap: layer_switch\n");
470 layer_switch(action.layer.opt);
471 }
472 } else {
473 // TODO: while other key tapping
474 debug("LAYER_PRESSED: No tap: layer_switch\n");
475 layer_switch(action.layer.opt);
476 }
477 /*
478 if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
479 debug("LAYER_PRESSED: Tap: register_code\n");
480 register_code(action.layer.code);
481 } else {
482 debug("LAYER_PRESSED: No tap: layer_switch\n");
483 layer_switch(action.layer.opt);
484 }
485 */
486 } else {
487 if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
488 debug("LAYER_PRESSED: Tap: unregister_code\n");
489 unregister_code(action.layer.code);
490 } else {
491 debug("LAYER_PRESSED: No tap: NO ACTION\n");
492 }
493 }
494 break;
495 }
496 break;
497 case ACT_LAYER_RELEASED:
498 switch (action.layer.code) {
499 case 0x00:
500 if (!event.pressed) {
501 layer_switch(action.layer.opt);
502 }
503 break;
504 case 0xF0:
505 // Ignored. LAYER_RELEASED with tap toggle is invalid action.
506 break;
507 case 0xFF:
508 if (!event.pressed) {
509 default_layer = action.layer.opt;
510 layer_switch(default_layer);
511 }
512 break;
513 default:
514 // Ignored. LAYER_RELEASED with tap key is invalid action.
515 break;
516 }
517 break;
518 case ACT_LAYER_BIT:
519 switch (action.layer.code) {
520 case 0x00:
521 if (event.pressed) {
522 layer_switch(current_layer | action.layer.opt);
523 } else {
524 layer_switch(current_layer & ~action.layer.opt);
525 }
526 break;
527 case 0xF0:
528 // TODO: tap toggle
529 break;
530 case 0xFF:
531 // change default layer
532 if (event.pressed) {
533 default_layer = current_layer | action.layer.opt;
534 layer_switch(default_layer);
535 } else {
536 default_layer = current_layer & ~action.layer.opt;
537 layer_switch(default_layer);
538 }
539 break;
540 default:
541 // with tap key
542 if (event.pressed) {
543 if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
544 debug("LAYER_BIT: Tap: register_code\n");
545 register_code(action.layer.code);
546 } else {
547 debug("LAYER_BIT: No tap: layer_switch(bit on)\n");
548 layer_switch(current_layer | action.layer.opt);
549 }
550 } else {
551 if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
552 debug("LAYER_BIT: Tap: unregister_code\n");
553 unregister_code(action.layer.code);
554 } else {
555 debug("LAYER_BIT: No tap: layer_switch(bit off)\n");
556 layer_switch(current_layer & ~action.layer.opt);
557 }
558 }
559 break;
560 }
561 case ACT_LAYER_EXT:
562 switch (action.layer.opt) {
563 case 0x00:
564 // set default layer when pressed
565 switch (action.layer.code) {
566 case 0x00:
567 if (event.pressed) {
568 layer_switch(default_layer);
569 }
570 break;
571 case 0xF0:
572 // TODO: tap toggle
573 break;
574 case 0xFF:
575 if (event.pressed) {
576 default_layer = current_layer;
577 layer_switch(default_layer);
578 }
579 break;
580 default:
581 // TODO: tap key
582 break;
583 }
584 break;
585 case 0x01:
586 // set default layer when released
587 switch (action.layer.code) {
588 case 0x00:
589 if (!event.pressed) {
590 layer_switch(default_layer);
591 }
592 break;
593 case 0xFF:
594 if (!event.pressed) {
595 default_layer = current_layer;
596 layer_switch(default_layer);
597 }
598 break;
599 case 0xF0:
600 default:
601 // Ignore tap.
602 if (!event.pressed) {
603 layer_switch(default_layer);
604 }
605 break;
606 }
607 break;
608 }
609 break;
610
611 /* Extentions */
612 case ACT_MACRO:
613 break;
614 case ACT_COMMAND:
615 break;
616 case ACT_FUNCTION:
617 action_call_function(event, action.func.id);
618 break;
619 default:
620 break;
621 }
622 }
623
624
625 /*
626 * Utilities for actions.
627 */
628 void register_code(uint8_t code)
629 {
630 if (code == KC_NO) {
631 return;
632 }
633 else if IS_KEY(code) {
634 // TODO: should push command_proc out of this block?
635 if (command_proc(code)) return;
636
637 if (oneshot_state.mods && oneshot_state.ready && !oneshot_state.disabled) {
638 uint8_t tmp_mods = host_get_mods();
639 host_add_mods(oneshot_state.mods);
640 host_add_key(code);
641 host_send_keyboard_report();
642
643 host_set_mods(tmp_mods);
644 oneshot_state.ready = false;
645 } else {
646 host_add_key(code);
647 host_send_keyboard_report();
648 }
649 }
650 else if IS_MOD(code) {
651 host_add_mods(MOD_BIT(code));
652 host_send_keyboard_report();
653 }
654 }
655
656 void unregister_code(uint8_t code)
657 {
658 if IS_KEY(code) {
659 host_del_key(code);
660 host_send_keyboard_report();
661 }
662 else if IS_MOD(code) {
663 host_del_mods(MOD_BIT(code));
664 host_send_keyboard_report();
665 }
666 }
667
668 void add_mods(uint8_t mods)
669 {
670 if (mods) {
671 host_add_mods(mods);
672 host_send_keyboard_report();
673 }
674 }
675
676 void del_mods(uint8_t mods)
677 {
678 if (mods) {
679 host_del_mods(mods);
680 host_send_keyboard_report();
681 }
682 }
683
684 void set_mods(uint8_t mods)
685 {
686 host_set_mods(mods);
687 host_send_keyboard_report();
688 }
689
690 void clear_keyboard(void)
691 {
692 host_clear_mods();
693 clear_keyboard_but_mods();
694 }
695
696 void clear_keyboard_but_mods(void)
697 {
698 host_clear_keys();
699 host_send_keyboard_report();
700 #ifdef MOUSEKEY_ENABLE
701 mousekey_clear();
702 mousekey_send();
703 #endif
704 #ifdef EXTRAKEY_ENABLE
705 host_system_send(0);
706 host_consumer_send(0);
707 #endif
708 }
709
710 bool sending_anykey(void)
711 {
712 return (host_has_anykey() || host_mouse_in_use() ||
713 host_last_sysytem_report() || host_last_consumer_report());
714 }
715
716 void layer_switch(uint8_t new_layer)
717 {
718 if (current_layer != new_layer) {
719 debug("Layer Switch: "); debug_hex(current_layer);
720 debug(" -> "); debug_hex(new_layer); debug("\n");
721
722 current_layer = new_layer;
723 clear_keyboard_but_mods(); // To avoid stuck keys
724 // TODO: update mods with full scan of matrix? if modifier changes between layers
725 }
726 }
727
728 bool is_tap_key(key_t key)
729 {
730 action_t action = keymap_get_action(current_layer, key.pos.row, key.pos.col);
731 switch (action.kind.id) {
732 case ACT_LMODS_TAP:
733 case ACT_RMODS_TAP:
734 return true;
735 case ACT_LAYER_PRESSED:
736 case ACT_LAYER_BIT:
737 switch (action.layer.code) {
738 case 0x00:
739 case 0xF1 ... 0xFF:
740 return false;
741 case 0xF0:
742 default:
743 return true;
744 }
745 return false;
746 case ACT_FUNCTION:
747 if (action.func.opt & 0x1) {
748 return true;
749 }
750 return false;
751 }
752 return false;
753 }
Imprint / Impressum