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