]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/action.c
Refactor struct keyevent_t.
[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(keyevent_t event);
14 static void register_code(uint8_t code);
15 static void unregister_code(uint8_t code);
16 static void add_mods(uint8_t mods);
17 static void del_mods(uint8_t mods);
18 static void set_mods(uint8_t mods);
19 static void clear_keyboard(void);
20 static void clear_keyboard_but_mods(void);
21 static bool sending_anykey(void);
22 static void layer_switch(uint8_t new_layer);
23
24
25 /* tap */
26 #define TAP_TIME    200
27 static keyevent_t last_event = {};
28 static uint8_t tap_count = 0;
29
30 /* layer */
31 uint8_t default_layer = 0;
32 uint8_t current_layer = 0;
33 static keyrecord_t tapping_key = {};
34 // time 0 means no event.
35 #define IS_TAPPING      (tapping_key.event.time != 0)
36 /* TODO: 
37 #define IS_TAPPING_KEY(key) (tapping_key.event.time != 0 && KEYEQ(tapping_key.event.key, key))
38  */
39
40 /* waiting keys buffer */
41 #define WAITING_KEYS_BUFFER 3
42 static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {};
43 // TODO: double buffer?
44 static keyrecord_t waiting_keys0[WAITING_KEYS_BUFFER] = {};
45 static keyrecord_t waiting_keys1[WAITING_KEYS_BUFFER] = {};
46 static uint8_t waiting_keys_head = 0;
47 static bool waiting_keys_enqueue(keyevent_t event)
48 {
49     debug("waiting_keys["); debug_dec(waiting_keys_head); debug("] = ");
50     debug_hex16(event.key.raw); debug("\n");
51     if (waiting_keys_head < WAITING_KEYS_BUFFER) {
52         waiting_keys[waiting_keys_head++] = (keyrecord_t){ .event = event,
53                                                            .mods = host_get_mods() };
54     } else {
55         return true;
56     }
57 }
58 static void waiting_keys_clear(void)
59 {
60     waiting_keys_head = 0;
61 }
62 static bool waiting_keys_has(key_t key)
63 {
64     for (uint8_t i = 0; i < waiting_keys_head; i++) {
65         if KEYEQ(key, waiting_keys[i].event.key) return true;
66     }
67     return false;
68 }
69 static void waiting_keys_process_in_current_layer(void)
70 {
71     // TODO: in case of including layer key in waiting keys
72     for (uint8_t i = 0; i < waiting_keys_head; i++) {
73         debug("waiting_keys_process_in_current_layer["); debug_dec(i); debug("]\n");
74         process(waiting_keys[i].event);
75     }
76     waiting_keys_clear();
77 }
78
79
80 void action_exec(keyevent_t event)
81 {
82     if (!IS_NOEVENT(event)) {
83         debug("event: "); debug_hex16(event.key.raw);
84         debug("[");
85         if (event.pressed) debug("down"); else debug("up");
86         debug("]\n");
87     }
88     if (IS_TAPPING) {
89         /* when tap time elapses or waiting key is released */
90         if ((timer_elapsed(tapping_key.event.time) > TAP_TIME) ||
91             (!event.pressed && waiting_keys_has(event.key))) {
92
93             // TODO process tapping_key: layer swich, modifier, ...
94             // action is needed?
95             debug("notap: process tapping_key.\n");
96             process(tapping_key.event);
97
98             /* Process waiting keys in new layer */
99             waiting_keys_process_in_current_layer();
100         }
101         /* when tapping key is released within tap time */
102         else if (!event.pressed && KEYEQ(event.key, tapping_key.event.key)) {
103             /* tap key down */
104             debug("tap("); debug_hex8(tap_count); debug(")[tapping_key](register): "); debug_hex8(tapping_key.action.layer.code);  debug("\n");
105             register_code(tapping_key.action.layer.code);
106             tapping_key = (keyrecord_t){};
107
108             /* process waiting keys */
109             waiting_keys_process_in_current_layer();
110         }
111     }
112
113     // not real event. event just to handle time out of tapping key.
114     if (IS_NOEVENT(event)) {
115         return;
116     }
117
118     /* count up tap when key is up */
119     // key: d u d u d
120     // tap: 0 1 1 2 2
121     // key: u d u d u
122     // tap: 0 0 1 1 2
123     if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) {
124         if (!event.pressed) tap_count++;
125     } else {
126         tap_count = 0;
127     }
128
129     /* store key events while tapping */
130     if (IS_TAPPING) {
131         // TODO: action is needed?
132         waiting_keys_enqueue(event);
133     } else {
134         process(event);
135     }
136
137     /* last event */
138     last_event = event;
139 }
140
141
142 static void process(keyevent_t event)
143 {
144     action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col);
145     debug("action: "); debug_hex16(action.code);
146     if (event.pressed) debug("[down]\n"); else debug("[up]\n");
147
148     switch (action.kind.id) {
149         /* Key and Mods */
150         case ACT_LMODS:
151             //               |pressed                          |released
152             // --------------+---------------------------------+------------
153             // key           |down(key)                        |up(key)
154             // mods          |add(mods)                        |del(mods)
155             // key with mods |add(mods), down(key), unset(mods)|up(key)
156             if (event.pressed) {
157                 uint8_t tmp_mods = host_get_mods();
158                 if (action.key.mods) {
159                     host_add_mods(action.key.mods);
160                     host_send_keyboard_report();
161                 }
162                 register_code(action.key.code);
163                 if (action.key.mods && action.key.code) {
164                     host_set_mods(tmp_mods);
165                     host_send_keyboard_report();
166                 }
167             } else {
168                 if (action.key.mods && !action.key.code) {
169                     host_del_mods(action.key.mods);
170                     host_send_keyboard_report();
171                 }
172                 unregister_code(action.key.code);
173             }
174             break;
175         case ACT_RMODS:
176             //               |pressed                          |released
177             // --------------+---------------------------------+------------
178             // key           |down(key)                        |up(key)
179             // mods          |add(mods)                        |del(mods)
180             // key with mods |add(mods), down(key), unset(mods)|up(key)
181             if (event.pressed) {
182                 uint8_t tmp_mods = host_get_mods();
183                 if (action.key.mods) {
184                     host_add_mods(action.key.mods<<4);
185                     host_send_keyboard_report();
186                 }
187                 register_code(action.key.code);
188                 if (action.key.mods && action.key.code) {
189                     host_set_mods(tmp_mods);
190                     host_send_keyboard_report();
191                 }
192             } else {
193                 if (action.key.mods && !action.key.code) {
194                     host_del_mods(action.key.mods<<4);
195                     host_send_keyboard_report();
196                 }
197                 unregister_code(action.key.code);
198             }
199             break;
200         case ACT_LMODS_TAP:
201             if (event.pressed) {
202                 if (tap_count == 0) {
203                     if (host_has_anykey()) {
204                         // This key is a modifier essentially.
205                         // Prioritize mods when key jam or rollover
206                         add_mods(action.key.mods);
207                     } else {
208                         if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) {
209                             // no tapping
210                             add_mods(action.key.mods);
211                             tapping_key = (keyrecord_t){};
212                         } else {
213                             debug("tapping lmods("); debug_hex8(action.key.mods); debug(")\n");
214                             tapping_key = (keyrecord_t){
215                                 .event = event,
216                                 .action = action,
217                                 .mods = host_get_mods()
218                             };
219                         }
220                     }
221                 } else {
222                     // pressed after tapping
223                     debug("tap("); debug_hex(tap_count); debug(")[lmods](register): "); debug_hex8(action.key.code); debug("\n");
224                     register_code(action.key.code);
225                 }
226             } else {
227                 if (tap_count == 0) {
228                     debug("tap(00)[lmods](del_mods): "); debug_hex8(action.key.mods); debug("\n");
229                     del_mods(action.key.mods);
230                 } else if (tap_count == 1) {
231                     debug("tap(01)[lmods](del_mods/unregister): "); debug_hex8(action.key.mods); debug(" "); debug_hex8(action.key.code); debug("\n");
232                     del_mods(action.key.mods);
233                     unregister_code(action.key.code);
234                 } else {
235                     debug("tap("); debug_hex(tap_count); debug(")[lmods](unregister): "); debug_hex8(action.key.code); debug("\n");
236                     unregister_code(action.key.code);
237                 }
238             }
239             break;
240         case ACT_RMODS_TAP:
241             if (event.pressed) {
242                 if (tap_count == 0) {
243                     if (host_has_anykey()) {
244                         // This key is a modifier essentially.
245                         // Prioritize mods when key jam or rollover
246                         add_mods(action.key.mods<<4);
247                     } else {
248                         if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) {
249                             // no tapping
250                             add_mods(action.key.mods<<4);
251                             tapping_key = (keyrecord_t){};
252                         } else {
253                             debug("tapping rmods("); debug_hex8(action.key.mods); debug(")\n");
254                             tapping_key = (keyrecord_t){
255                                 .event = event,
256                                 .action = action,
257                                 .mods = host_get_mods()
258                             };
259                         }
260                     }
261                 } else {
262                     // pressed after tapping
263                     debug("tap("); debug_hex(tap_count); debug(")[rmods](register): "); debug_hex8(action.key.code); debug("\n");
264                     register_code(action.key.code);
265                 }
266             } else {
267                 if (tap_count == 0) {
268                     debug("tap(00)[rmods](del_mods): "); debug_hex8(action.key.mods); debug("\n");
269                     del_mods(action.key.mods<<4);
270                 } else if (tap_count == 1) {
271                     debug("tap(01)[rmods](del_mods/unregister): "); debug_hex8(action.key.mods); debug(" "); debug_hex8(action.key.code); debug("\n");
272                     del_mods(action.key.mods<<4);
273                     unregister_code(action.key.code);
274                 } else {
275                     debug("tap("); debug_hex(tap_count); debug(")[rmods](unregister): "); debug_hex8(action.key.code); debug("\n");
276                     unregister_code(action.key.code);
277                 }
278             }
279             break;
280
281         /* other HID usage */
282         case ACT_USAGE:
283 #ifdef EXTRAKEY_ENABLE
284             switch (action.usage.page) {
285                 case ACTION_USAGE_PAGE_SYSTEM:
286                     if (event.pressed) {
287                         host_system_send(action.usage.code);
288                     } else {
289                         host_system_send(0);
290                     }
291                     break;
292                 case ACTION_USAGE_PAGE_CONSUMER:
293                     if (event.pressed) {
294                         host_consumer_send(action.usage.code);
295                     } else {
296                         host_consumer_send(0);
297                     }
298                     break;
299             }
300 #endif
301             break;
302
303         /* Mouse key */
304         case ACT_MOUSEKEY:
305 #ifdef MOUSEKEY_ENABLE
306             if (event.pressed) {
307                 mousekey_on(action.key.code);
308                 mousekey_send();
309             } else {
310                 mousekey_off(action.key.code);
311                 mousekey_send();
312             }
313 #endif
314             break;
315
316         /* Layer key */
317         case ACT_LAYER_PRESSED:
318             // layer action when pressed
319             switch (action.layer.code) {
320                 case 0x00:
321                     if (event.pressed) {
322                         layer_switch(action.layer.opt);
323                     }
324                     break;
325                 case 0xF0:
326                     // TODO: tap toggle
327                     break;
328                 case 0xFF:
329                     if (event.pressed) {
330                         default_layer = action.layer.opt;
331                         layer_switch(default_layer);
332                     }
333                     break;
334                 default:
335                     // with tap key
336                     if (event.pressed) {
337                         if (tap_count == 0) {
338                             if (host_has_anykey()) {
339                                 // This key is a normal key than a leyar key essentially.
340                                 // Prioritize 'tap key' when key jam or rollover
341                                 register_code(action.layer.code);
342                             } else {
343                                 if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) {
344                                     layer_switch(action.layer.opt);
345                                     tapping_key = (keyrecord_t){};
346                                 } else {
347                                     debug("tapping layer("); debug_hex8(action.layer.opt); debug(")\n");
348                                     tapping_key = (keyrecord_t){
349                                         .event = event,
350                                         .action = action,
351                                         .mods = host_get_mods()
352                                     };
353                                 }
354                             }
355                         } else if (tap_count > 0) {
356                             // pressed after tapping
357                             debug("tap[layer](register): "); debug_hex(tap_count); debug("\n");
358                             register_code(action.layer.code);
359                         }
360                     } else {
361                         // released after tapping
362                         debug("tap[layer](unregister): "); debug_hex(tap_count); debug("\n");
363                         unregister_code(action.layer.code);
364                     }
365                     break;
366             }
367             break;
368         case ACT_LAYER_RELEASED:
369             switch (action.layer.code) {
370                 case 0x00:
371                     if (!event.pressed) {
372                         layer_switch(action.layer.opt);
373                     }
374                     break;
375                 case 0xF0:
376                     // Ignored. LAYER_RELEASED with tap toggle is invalid action.
377                     break;
378                 case 0xFF:
379                     if (!event.pressed) {
380                         default_layer = action.layer.opt;
381                         layer_switch(default_layer);
382                     }
383                     break;
384                 default:
385                     // Ignored. LAYER_RELEASED with tap key is invalid action.
386                     break;
387             }
388             break;
389         case ACT_LAYER_BIT:
390             switch (action.layer.code) {
391                 case 0x00:
392                     if (event.pressed) {
393                         layer_switch(current_layer | action.layer.opt);
394                     } else {
395                         layer_switch(current_layer & ~action.layer.opt);
396                     }
397                     break;
398                 case 0xF0:
399                     // TODO: tap toggle
400                     break;
401                 case 0xFF:
402                     // change default layer
403                     if (event.pressed) {
404                         default_layer = current_layer | action.layer.opt;
405                         layer_switch(default_layer);
406                     } else {
407                         default_layer = current_layer & ~action.layer.opt;
408                         layer_switch(default_layer);
409                     }
410                     break;
411                 default:
412                     // TODO: see ACT_LAYER_PRESSED code
413                     // with tap key
414                     if (event.pressed) {
415                         if (tap_count == 0) {
416                             if (host_has_anykey()) {
417                                 register_code(action.layer.code);
418                             } else {
419                                 tapping_key = (keyrecord_t){
420                                     .event = event,
421                                     .action = action,
422                                     .mods = keyboard_report->mods
423                                 };
424                             }
425                         } else if (tap_count > 0) {
426                             debug("tap[layer_bit](register): "); debug_hex(tap_count); debug("\n");
427                             register_code(action.layer.code);
428                         }
429                     } else {
430                         if (tap_count == 0) {
431                             // no tap
432                             layer_switch(current_layer & ~action.layer.opt);
433                         } else if (tap_count == 1) {
434                             // tap
435                             register_code(action.layer.code);
436                         }
437                         unregister_code(action.layer.code);
438                     }
439                     break;
440             }
441         case ACT_LAYER_EXT:
442             switch (action.layer.opt) {
443                 case 0x00:
444                     // set default layer when pressed
445                     switch (action.layer.code) {
446                         case 0x00:
447                             if (event.pressed) {
448                                 layer_switch(default_layer);
449                             }
450                             break;
451                         case 0xF0:
452                             // TODO: tap toggle
453                             break;
454                         case 0xFF:
455                             if (event.pressed) {
456                                 default_layer = current_layer;
457                                 layer_switch(default_layer);
458                             }
459                             break;
460                         default:
461                             // TODO: tap key
462                             break;
463                     }
464                     break;
465                 case 0x01:
466                     // set default layer when released
467                     switch (action.layer.code) {
468                         case 0x00:
469                             if (!event.pressed) {
470                                 layer_switch(default_layer);
471                             }
472                             break;
473                         case 0xFF:
474                             if (!event.pressed) {
475                                 default_layer = current_layer;
476                                 layer_switch(default_layer);
477                             }
478                             break;
479                         case 0xF0:
480                         default:
481                             // Ignore tap.
482                             if (!event.pressed) {
483                                 layer_switch(default_layer);
484                             }
485                             break;
486                     }
487                     break;
488             }
489             break;
490
491         /* Extentions */
492         case ACT_MACRO:
493         case ACT_COMMAND:
494         case ACT_FUNCTION:
495         default:
496             break;
497     }
498 }
499
500 static void register_code(uint8_t code)
501 {
502     if (code == KC_NO) {
503         return;
504     }
505     else if IS_KEY(code) {
506         // TODO: should push command_proc out of this block?
507         if (!command_proc(code)) {
508             host_add_key(code);
509             host_send_keyboard_report();
510         }
511     }
512     else if IS_MOD(code) {
513         host_add_mods(MOD_BIT(code));
514         host_send_keyboard_report();
515     }
516 }
517
518 static void unregister_code(uint8_t code)
519 {
520     if IS_KEY(code) {
521         host_del_key(code);
522         host_send_keyboard_report();
523     }
524     else if IS_MOD(code) {
525         host_del_mods(MOD_BIT(code));
526         host_send_keyboard_report();
527     }
528 }
529
530 static void add_mods(uint8_t mods)
531 {
532     if (mods) {
533         host_add_mods(mods);
534         host_send_keyboard_report();
535     }
536 }
537
538 static void del_mods(uint8_t mods)
539 {
540     if (mods) {
541         host_del_mods(mods);
542         host_send_keyboard_report();
543     }
544 }
545
546 static void set_mods(uint8_t mods)
547 {
548     host_set_mods(mods);
549     host_send_keyboard_report();
550 }
551
552 static void clear_keyboard(void)
553 {
554     host_clear_mods();
555     clear_keyboard_but_mods();
556 }
557
558 static void clear_keyboard_but_mods(void)
559 {
560     host_clear_keys();
561     host_send_keyboard_report();
562 #ifdef MOUSEKEY_ENABLE
563     mousekey_clear();
564     mousekey_send();
565 #endif
566 #ifdef EXTRAKEY_ENABLE
567     host_system_send(0);
568     host_consumer_send(0);
569 #endif
570 }
571
572 static bool sending_anykey(void)
573 {
574     return (host_has_anykey() || host_mouse_in_use() ||
575             host_last_sysytem_report() || host_last_consumer_report());
576 }
577
578 static void layer_switch(uint8_t new_layer)
579 {
580     if (current_layer != new_layer) {
581         debug("Layer Switch: "); debug_hex(current_layer);
582         debug(" -> "); debug_hex(new_layer); debug("\n");
583
584         current_layer = new_layer;
585         clear_keyboard_but_mods(); // To avoid stuck keys
586         // TODO: update mods with full scan of matrix? if modifier changes between layers
587     }
588 }