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