]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/action.c
Remove test_func.
[tmk_firmware.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
101 /*
102  * Rule to judge tap:
103  * Tap key is typed(pressed and released) within TAP_TERM
104  * without interfaring by typing other key.
105  */
106 /* return true when key event is processed. */
107 static bool process_tap(keyrecord_t *keyp)
108 {
109     keyevent_t event = keyp->event;
110
111     // if tapping
112     if (IS_TAPPING_PRESSED()) {
113         if (WITHIN_TAP_TERM(event)) {
114             if (tapping_key.tap_count == 0) {
115                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
116                     // first tap!
117                     debug("Tapping: First tap.\n");
118                     tapping_key.tap_count = 1;
119                     process(&tapping_key);
120
121                     // enqueue
122                     keyp->tap_count = tapping_key.tap_count;
123                     return false;
124                 } else if (!event.pressed && waiting_buffer_typed(event)) {
125                     // other key typed. not tap.
126                     debug("Tapping: End(No tap. Interfered by typing key).\n");
127                     process(&tapping_key);
128                     tapping_key = (keyrecord_t){};
129
130                     // enqueue
131                     return false;
132                 } else {
133                     // other key events shall be stored till tapping state settles.
134                     return false;
135                 }
136             } else {
137                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
138                     keyp->tap_count = tapping_key.tap_count;
139                     debug("Tapping: tap release("); debug_dec(keyp->tap_count); debug(")\n");
140                     tapping_key = *keyp;
141                     return false;
142                 }
143                 else if (is_tap_key(keyp->event.key) && event.pressed) {
144                     debug("Tapping: Start with forcing to release last tap.\n");
145                     process(&(keyrecord_t){
146                             .tap_count = tapping_key.tap_count,
147                             .event.key = tapping_key.event.key,
148                             .event.time = event.time,
149                             .event.pressed = false
150                     });
151                     tapping_key = *keyp;
152                     return false;
153                 }
154                 else {
155                     if (!IS_NOEVENT(keyp->event)) debug("Tapping: key event while tap.\n");
156                     process(keyp);
157                     return true;
158                 }
159             }
160         }
161         // not within TAP_TERM
162         else {
163             if (tapping_key.tap_count == 0) {
164                 // timeout. not tap.
165                 debug("Tapping: End. Not tap(time out).\n");
166                 process(&tapping_key);
167                 tapping_key = (keyrecord_t){};
168                 return false;
169             }  else {
170                 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
171                     debug("Tapping: End. tap release.");
172                     keyp->tap_count = tapping_key.tap_count;
173                     process(keyp);
174                     tapping_key = (keyrecord_t){};
175                     return true;
176                 } else {
177                     // other key after tap time out.
178                     process(keyp);
179                     return true;
180                 }
181             }
182         }
183     } else if (IS_TAPPING_RELEASED()) {
184         if (WITHIN_TAP_TERM(event)) {
185             if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
186                 // sequential tap.
187                 keyp->tap_count = tapping_key.tap_count + 1;
188                 debug("Tapping: tap press("); debug_dec(keyp->tap_count); debug(")\n");
189                 process(keyp);
190                 tapping_key = *keyp;
191                 return true;
192             } else if (event.pressed && is_tap_key(event.key)) {
193                 // Sequential tap can be interfered with other tap key.
194                 debug("Tapping: Start with interfering other tap.\n");
195                 tapping_key = *keyp;
196                 return true;
197             } else {
198                 if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n");
199                 process(keyp);
200                 return true;
201             }
202         } else {
203             // timeout. no sequential tap.
204             debug("Tapping: End(Time out after releasing last tap).\n");
205             tapping_key = (keyrecord_t){};
206             process(keyp);
207             return true;
208         }
209     } else {
210         if (event.pressed && is_tap_key(event.key)) {
211             debug("Tapping: Start(Press tap key).\n");
212             tapping_key = *keyp;
213             return true;
214         } else {
215             process(keyp);
216             return true;
217         }
218     }
219 }
220
221 void action_exec(keyevent_t event)
222 {
223     if (!IS_NOEVENT(event)) {
224         debug("event: "); 
225         debug_hex16(event.time); debug(": ");
226         debug_hex16(event.key.raw);
227         debug("[");
228         if (event.pressed) debug("down"); else debug("up");
229         debug("]\n");
230     }
231
232     keyrecord_t record = { .event = event };
233
234     // pre-process on tapping
235     if (process_tap(&record)) {
236         if (!IS_NOEVENT(record.event)) debug("processed.\n");
237     } else {
238         if (!IS_NOEVENT(record.event)) debug("enqueued.\n");
239         if (!waiting_buffer_enq(record)) {
240             // clear all in case of overflow.
241             clear_keyboard();
242             waiting_buffer_clear();
243             tapping_key = (keyrecord_t){};
244         }
245     }
246
247     // TODO: need to process every time?
248     // process waiting_buffer
249     for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
250         if (process_tap(&waiting_buffer[waiting_buffer_tail])) {
251             debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
252             debug_hex16(waiting_buffer[waiting_buffer_tail].event.key.raw); debug("\n");
253         } else {
254             break;
255         }
256     }
257 }
258
259 static void process(keyrecord_t *record)
260 {
261     // TODO: use record
262     keyevent_t event = record->event;
263     uint8_t tap_count = record->tap_count;
264
265     if (IS_NOEVENT(event)) { return; }
266
267     action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col);
268     debug("action: "); debug_hex16(action.code);
269     if (event.pressed) debug("[down]\n"); else debug("[up]\n");
270
271     switch (action.kind.id) {
272         /* Key and Mods */
273         case ACT_LMODS:
274             //               |pressed                          |released
275             // --------------+---------------------------------+------------
276             // key           |down(key)                        |up(key)
277             // mods          |add(mods)                        |del(mods)
278             // key with mods |add(mods), down(key), unset(mods)|up(key)
279             if (event.pressed) {
280                 uint8_t tmp_mods = host_get_mods();
281                 if (action.key.mods) {
282                     host_add_mods(action.key.mods);
283                     host_send_keyboard_report();
284                 }
285                 register_code(action.key.code);
286                 if (action.key.mods && action.key.code) {
287                     host_set_mods(tmp_mods);
288                     host_send_keyboard_report();
289                 }
290             } else {
291                 if (action.key.mods && !action.key.code) {
292                     host_del_mods(action.key.mods);
293                     host_send_keyboard_report();
294                 }
295                 unregister_code(action.key.code);
296             }
297             break;
298         case ACT_RMODS:
299             //               |pressed                          |released
300             // --------------+---------------------------------+------------
301             // key           |down(key)                        |up(key)
302             // mods          |add(mods)                        |del(mods)
303             // key with mods |add(mods), down(key), unset(mods)|up(key)
304             if (event.pressed) {
305                 uint8_t tmp_mods = host_get_mods();
306                 if (action.key.mods) {
307                     host_add_mods(action.key.mods<<4);
308                     host_send_keyboard_report();
309                 }
310                 register_code(action.key.code);
311                 if (action.key.mods && action.key.code) {
312                     host_set_mods(tmp_mods);
313                     host_send_keyboard_report();
314                 }
315             } else {
316                 if (action.key.mods && !action.key.code) {
317                     host_del_mods(action.key.mods<<4);
318                     host_send_keyboard_report();
319                 }
320                 unregister_code(action.key.code);
321             }
322             break;
323         case ACT_LMODS_TAP:
324         case ACT_RMODS_TAP:
325             {
326                 uint8_t tmp_mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
327                                                                         action.key.mods<<4;
328                 if (event.pressed) {
329                     if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
330                         if (waiting_buffer_has_anykey_pressed()) {
331                             debug("MODS_TAP: Tap: Cancel: add_mods\n");
332                             // ad hoc: set 0 to cancel tap
333                             record->tap_count = 0;
334                             add_mods(tmp_mods);
335                         } else {
336                             debug("MODS_TAP: Tap: register_code\n");
337                             register_code(action.key.code);
338                         }
339                     } else {
340                         debug("MODS_TAP: No tap: add_mods\n");
341                         add_mods(tmp_mods);
342                     }
343                 } else {
344                     if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
345                         debug("MODS_TAP: Tap: unregister_code\n");
346                         unregister_code(action.key.code);
347                     } else {
348                         debug("MODS_TAP: No tap: add_mods\n");
349                         del_mods(tmp_mods);
350                     }
351                 }
352             }
353             break;
354
355         /* other HID usage */
356         case ACT_USAGE:
357 #ifdef EXTRAKEY_ENABLE
358             switch (action.usage.page) {
359                 case ACTION_USAGE_PAGE_SYSTEM:
360                     if (event.pressed) {
361                         host_system_send(action.usage.code);
362                     } else {
363                         host_system_send(0);
364                     }
365                     break;
366                 case ACTION_USAGE_PAGE_CONSUMER:
367                     if (event.pressed) {
368                         host_consumer_send(action.usage.code);
369                     } else {
370                         host_consumer_send(0);
371                     }
372                     break;
373             }
374 #endif
375             break;
376
377         /* Mouse key */
378         case ACT_MOUSEKEY:
379 #ifdef MOUSEKEY_ENABLE
380             if (event.pressed) {
381                 mousekey_on(action.key.code);
382                 mousekey_send();
383             } else {
384                 mousekey_off(action.key.code);
385                 mousekey_send();
386             }
387 #endif
388             break;
389
390         /* Layer key */
391         case ACT_LAYER_PRESSED:
392             // layer action when pressed
393             switch (action.layer.code) {
394                 case 0x00:
395                     if (event.pressed) {
396                         layer_switch(action.layer.opt);
397                     }
398                     break;
399                 case 0xF0:
400                     // TODO: tap toggle
401                     break;
402                 case 0xFF:
403                     if (event.pressed) {
404                         default_layer = action.layer.opt;
405                         layer_switch(default_layer);
406                     }
407                     break;
408                 default:
409                     // with tap key
410                     if (event.pressed) {
411                         if (IS_TAPPING_KEY(event.key)) {
412                            if (tap_count > 0) {
413                                 debug("LAYER_PRESSED: Tap: register_code\n");
414                                 register_code(action.layer.code);
415                            } else {
416                                 debug("LAYER_PRESSED: No tap: layer_switch\n");
417                                 layer_switch(action.layer.opt);
418                            }
419                         } else {
420                             // TODO: while other key tapping
421                                 debug("LAYER_PRESSED: No tap: layer_switch\n");
422                                 layer_switch(action.layer.opt);
423                         }
424 /*
425                         if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
426                             debug("LAYER_PRESSED: Tap: register_code\n");
427                             register_code(action.layer.code);
428                         } else {
429                             debug("LAYER_PRESSED: No tap: layer_switch\n");
430                             layer_switch(action.layer.opt);
431                         }
432 */
433                     } else {
434                         if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
435                             debug("LAYER_PRESSED: Tap: unregister_code\n");
436                             unregister_code(action.layer.code);
437                         } else {
438                             debug("LAYER_PRESSED: No tap: NO ACTION\n");
439                         }
440                     }
441                     break;
442             }
443             break;
444         case ACT_LAYER_RELEASED:
445             switch (action.layer.code) {
446                 case 0x00:
447                     if (!event.pressed) {
448                         layer_switch(action.layer.opt);
449                     }
450                     break;
451                 case 0xF0:
452                     // Ignored. LAYER_RELEASED with tap toggle is invalid action.
453                     break;
454                 case 0xFF:
455                     if (!event.pressed) {
456                         default_layer = action.layer.opt;
457                         layer_switch(default_layer);
458                     }
459                     break;
460                 default:
461                     // Ignored. LAYER_RELEASED with tap key is invalid action.
462                     break;
463             }
464             break;
465         case ACT_LAYER_BIT:
466             switch (action.layer.code) {
467                 case 0x00:
468                     if (event.pressed) {
469                         layer_switch(current_layer | action.layer.opt);
470                     } else {
471                         layer_switch(current_layer & ~action.layer.opt);
472                     }
473                     break;
474                 case 0xF0:
475                     // TODO: tap toggle
476                     break;
477                 case 0xFF:
478                     // change default layer
479                     if (event.pressed) {
480                         default_layer = current_layer | action.layer.opt;
481                         layer_switch(default_layer);
482                     } else {
483                         default_layer = current_layer & ~action.layer.opt;
484                         layer_switch(default_layer);
485                     }
486                     break;
487                 default:
488                     // with tap key
489                     if (event.pressed) {
490                         if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
491                             debug("LAYER_BIT: Tap: register_code\n");
492                             register_code(action.layer.code);
493                         } else {
494                             debug("LAYER_BIT: No tap: layer_switch(bit on)\n");
495                             layer_switch(current_layer | action.layer.opt);
496                         }
497                     } else {
498                         if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
499                             debug("LAYER_BIT: Tap: unregister_code\n");
500                             unregister_code(action.layer.code);
501                         } else {
502                             debug("LAYER_BIT: No tap: layer_switch(bit off)\n");
503                             layer_switch(current_layer & ~action.layer.opt);
504                         }
505                     }
506                     break;
507             }
508         case ACT_LAYER_EXT:
509             switch (action.layer.opt) {
510                 case 0x00:
511                     // set default layer when pressed
512                     switch (action.layer.code) {
513                         case 0x00:
514                             if (event.pressed) {
515                                 layer_switch(default_layer);
516                             }
517                             break;
518                         case 0xF0:
519                             // TODO: tap toggle
520                             break;
521                         case 0xFF:
522                             if (event.pressed) {
523                                 default_layer = current_layer;
524                                 layer_switch(default_layer);
525                             }
526                             break;
527                         default:
528                             // TODO: tap key
529                             break;
530                     }
531                     break;
532                 case 0x01:
533                     // set default layer when released
534                     switch (action.layer.code) {
535                         case 0x00:
536                             if (!event.pressed) {
537                                 layer_switch(default_layer);
538                             }
539                             break;
540                         case 0xFF:
541                             if (!event.pressed) {
542                                 default_layer = current_layer;
543                                 layer_switch(default_layer);
544                             }
545                             break;
546                         case 0xF0:
547                         default:
548                             // Ignore tap.
549                             if (!event.pressed) {
550                                 layer_switch(default_layer);
551                             }
552                             break;
553                     }
554                     break;
555             }
556             break;
557
558         /* Extentions */
559         case ACT_MACRO:
560             break;
561         case ACT_COMMAND:
562             break;
563         case ACT_FUNCTION:
564             action_call_function(event, action.func.id);
565             break;
566         default:
567             break;
568     }
569 }
570
571
572 /*
573  * Utilities for actions.
574  */
575 void register_code(uint8_t code)
576 {
577     if (code == KC_NO) {
578         return;
579     }
580     else if IS_KEY(code) {
581         // TODO: should push command_proc out of this block?
582         if (!command_proc(code)) {
583             host_add_key(code);
584             host_send_keyboard_report();
585         }
586     }
587     else if IS_MOD(code) {
588         host_add_mods(MOD_BIT(code));
589         host_send_keyboard_report();
590     }
591 }
592
593 void unregister_code(uint8_t code)
594 {
595     if IS_KEY(code) {
596         host_del_key(code);
597         host_send_keyboard_report();
598     }
599     else if IS_MOD(code) {
600         host_del_mods(MOD_BIT(code));
601         host_send_keyboard_report();
602     }
603 }
604
605 void add_mods(uint8_t mods)
606 {
607     if (mods) {
608         host_add_mods(mods);
609         host_send_keyboard_report();
610     }
611 }
612
613 void del_mods(uint8_t mods)
614 {
615     if (mods) {
616         host_del_mods(mods);
617         host_send_keyboard_report();
618     }
619 }
620
621 void set_mods(uint8_t mods)
622 {
623     host_set_mods(mods);
624     host_send_keyboard_report();
625 }
626
627 void clear_keyboard(void)
628 {
629     host_clear_mods();
630     clear_keyboard_but_mods();
631 }
632
633 void clear_keyboard_but_mods(void)
634 {
635     host_clear_keys();
636     host_send_keyboard_report();
637 #ifdef MOUSEKEY_ENABLE
638     mousekey_clear();
639     mousekey_send();
640 #endif
641 #ifdef EXTRAKEY_ENABLE
642     host_system_send(0);
643     host_consumer_send(0);
644 #endif
645 }
646
647 bool sending_anykey(void)
648 {
649     return (host_has_anykey() || host_mouse_in_use() ||
650             host_last_sysytem_report() || host_last_consumer_report());
651 }
652
653 void layer_switch(uint8_t new_layer)
654 {
655     if (current_layer != new_layer) {
656         debug("Layer Switch: "); debug_hex(current_layer);
657         debug(" -> "); debug_hex(new_layer); debug("\n");
658
659         current_layer = new_layer;
660         clear_keyboard_but_mods(); // To avoid stuck keys
661         // TODO: update mods with full scan of matrix? if modifier changes between layers
662     }
663 }
664
665 bool is_tap_key(key_t key)
666 {
667     action_t action = keymap_get_action(current_layer, key.pos.row, key.pos.col);
668     switch (action.kind.id) {
669         case ACT_LMODS_TAP:
670         case ACT_RMODS_TAP:
671             return true;
672         case ACT_LAYER_PRESSED:
673         case ACT_LAYER_BIT:
674             switch (action.layer.code) {
675                 case 0x00:
676                 case 0xF1 ... 0xFF:
677                     return false;
678                 case 0xF0:
679                 default:
680                     return true;
681             }
682             return false;
683         case ACT_FUNCTION:
684             if (action.func.opt & 0x1) {
685                 return true;
686             }
687             return false;
688     }
689     return false;
690 }