]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/action.c
Add new layer actions.
[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 #define Kdebug(s)       do { if (debug_keyboard) debug(s); } while(0)
13 #define Kdebug_P(s)     do { if (debug_keyboard) debug_P(s); } while(0)
14 #define Kdebug_hex(s)   do { if (debug_keyboard) debug_hex(s); } while(0)
15
16
17 /*
18  *
19  * Event/State|IDLE          PRESSING      DELAYING[f]      WAITING[f,k]         
20  * -----------+------------------------------------------------------------------
21  * Fn  Down   |(L+)          -*1           WAITING(Sk)      IDLE(Rf,Ps)*7        
22  *     Up     |(L-)          IDLE(L-)*8    IDLE(L-)*8       IDLE(L-)*8           
23  * Fnk Down   |DELAYING(Sf)* (Rf)          WAITING(Sk)      IDLE(Rf,Ps,Rf)       
24  *     Up     |(L-)          IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3  
25  * Key Down   |PRESSING(Rk)  (Rk)          WAITING(Sk)      IDLE(Rf,Ps,Rk)       
26  *     Up     |(Uk)          IDLE(Uk)*4    (Uk)             IDLE(L+,Ps,Pk)/(Uk)*a
27  *            |
28  * Delay      |-             -             IDLE(L+)         IDLE(L+,Ps)          
29  * Magic Key  |COMMAND*5
30  *
31  * *1: ignore Fn if other key is down.
32  * *2: register Fnk if any key is pressing
33  * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8
34  * *4: if no keys registered to host
35  * *5: unregister all keys
36  * *6: only if no keys down
37  * *7: ignore Fn because Fnk key and stored key are down.
38  * *8: move to IDLE if layer switch(off) occurs, else stay at current state
39  * *9: repeat key if pressing Fnk twice quickly(move to PRESSING)
40  * *a: layer switch and process waiting key and code if code == wainting key, else unregister key
41  *
42  * States:
43  *      IDLE: No key is down except modifiers
44  *      DELAYING: delay layer switch after pressing Fn with alt keycode
45  *      WAITING: key is pressed during DELAYING
46  *
47  * Events:
48  *      Fn: Fn key without alternative keycode
49  *      Fnk: Fn key with alternative keycode
50  *      -: ignore
51  *      Delay: layer switch delay term is elapsed
52  *
53  * Actions:
54  *      Rk: register key
55  *      Uk: unregister key
56  *      Rf: register Fn(alt keycode)
57  *      Uf: unregister Fn(alt keycode)
58  *      Rs: register stored key
59  *      Us: unregister stored key
60  *      Sk: Store key(waiting Key)
61  *      Sf: Store Fn(delayed Fn)
62  *      Ps: Process stored key
63  *      Ps: Process key
64  *      Is: Interpret stored keys in current layer
65  *      L+: Switch to new layer(*unregister* all keys but modifiers)
66  *      L-: Switch back to last layer(*unregister* all keys but modifiers)
67  *      Ld: Switch back to default layer(*unregister* all keys but modifiers)
68  */
69
70
71 typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
72 #define NEXT(state)     do { \
73     Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \
74     kbdstate = state; \
75     Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \
76 } while (0)
77
78
79 static kbdstate_t kbdstate = IDLE;
80 static uint8_t fn_state_bits = 0;
81
82 static const char *state_str(kbdstate_t state)
83 {
84     if (state == IDLE)      return PSTR("IDLE");
85     if (state == DELAYING)  return PSTR("DELAYING");
86     if (state == WAITING)   return PSTR("WAITING");
87     if (state == PRESSING)  return PSTR("PRESSING");
88     return PSTR("UNKNOWN");
89 }
90 static bool anykey_sent_to_host(void)
91 {
92     return (host_has_anykey() || host_mouse_in_use() ||
93             host_last_sysytem_report() || host_last_consumer_report());
94 }
95
96
97 static void register_code(uint8_t code);
98 static void unregister_code(uint8_t code);
99 static void register_mods(uint8_t mods);
100 static void unregister_mods(uint8_t mods);
101 static void clear_keyboard(void);
102 static void clear_keyboard_but_mods(void);
103 static void layer_switch(uint8_t new_layer);
104
105
106 /* tap */
107 #define TAP_TIME    200
108 #define LAYER_DELAY 200
109 static keyevent_t last_event = {};
110 static uint16_t last_event_time = 0;
111 static uint8_t tap_count = 0;
112
113 /* layer */
114 uint8_t default_layer = 0;
115 uint8_t current_layer = 0;
116 keyrecord_t delaying_layer = {};
117
118
119 void action_exec(keyevent_t event)
120 {
121     /* count tap when key is up */
122     if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event_time) < TAP_TIME) {
123         if (!event.pressed) tap_count++;
124     } else {
125         tap_count = 0;
126     }
127
128     /* layer switch after LAYER_DELAY */
129     if (delaying_layer.action.code && timer_elapsed(delaying_layer.event.time) > LAYER_DELAY) {
130         switch (delaying_layer.action.kind.id) {
131             case ACT_LAYER_PRESSED:
132                 layer_switch(delaying_layer.action.layer.opt);
133                 break;
134             case ACT_LAYER_BIT:
135                 layer_switch(current_layer | delaying_layer.action.layer.opt);
136                 break;
137         }
138         delaying_layer = (keyrecord_t){};
139     }
140     action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);
141
142     debug("action: "); debug_hex16(action.code); debug("\n");
143     debug("kind.id: "); debug_hex(action.kind.id); debug("\n");
144     debug("kind.param: "); debug_hex16(action.kind.param); debug("\n");
145     debug("key.code: "); debug_hex(action.key.code); debug("\n");
146     debug("key.mods: "); debug_hex(action.key.mods); debug("\n");
147
148     switch (action.kind.id) {
149         case ACT_LMODS:
150             // normal key or key plus mods
151             if (event.pressed) {
152                 register_mods(action.key.mods);
153                 register_code(action.key.code);
154             } else {
155                 unregister_code(action.key.code);
156                 unregister_mods(action.key.mods);
157             }
158             break;
159         case ACT_RMODS:
160             if (event.pressed) {
161                 register_mods(action.key.mods<<4);
162                 register_code(action.key.code);
163             } else {
164                 unregister_code(action.key.code);
165                 unregister_mods(action.key.mods<<4);
166             }
167             break;
168         case ACT_LMOD_TAP:
169             break;
170         case ACT_RMOD_TAP:
171             break;
172         case ACT_USAGE:
173 #ifdef EXTRAKEY_ENABLE
174             switch (action.usage.page) {
175                 case ACTION_USAGE_PAGE_SYSTEM:
176                     if (event.pressed) {
177                         host_system_send(action.usage.code);
178                     } else {
179                         host_system_send(0);
180                     }
181                     break;
182                 case ACTION_USAGE_PAGE_CONSUMER:
183                     if (event.pressed) {
184                         host_consumer_send(action.usage.code);
185                     } else {
186                         host_consumer_send(0);
187                     }
188                     break;
189             }
190 #endif
191             break;
192         case ACT_MOUSEKEY:
193 #ifdef MOUSEKEY_ENABLE
194             if (event.pressed) {
195                 mousekey_on(action.key.code);
196                 mousekey_send();
197             } else {
198                 mousekey_off(action.key.code);
199                 mousekey_send();
200             }
201 #endif
202             break;
203         case ACT_LAYER_PRESSED:
204             // layer action when pressed
205             switch (action.layer.code) {
206                 case 0x00:
207                     if (event.pressed) {
208                         layer_switch(action.layer.opt);
209                     }
210                     break;
211                 case 0xF0:
212                     // TODO: tap toggle
213                     break;
214                 case 0xFF:
215                     if (event.pressed) {
216                         default_layer = action.layer.opt;
217                         layer_switch(default_layer);
218                     }
219                     break;
220                 default:
221                     // with tap key
222                     debug("tap: "); debug_hex(tap_count); debug("\n");
223                     if (event.pressed) {
224                         if (tap_count == 0) {
225                             if (host_has_anykey()) {
226                                 register_code(action.layer.code);
227                             } else {
228                                 delaying_layer = (keyrecord_t){
229                                     .event = event,
230                                     .action = action,
231                                     .mods = keyboard_report->mods
232                                 };
233                             }
234                         } else if (tap_count > 0) {
235                             register_code(action.layer.code);
236                         }
237                     } else {
238                         // type key after tap
239                         if (tap_count == 1) {
240                             delaying_layer = (keyrecord_t){};
241                             register_code(action.layer.code);
242                         }
243                         unregister_code(action.layer.code);
244                     }
245                     break;
246             }
247             break;
248         case ACT_LAYER_RELEASED:
249             switch (action.layer.code) {
250                 case 0x00:
251                     if (event.pressed) {
252                         layer_switch(action.layer.opt);
253                     }
254                     break;
255                 case 0xF0:
256                     // Ignored. LAYER_RELEASED with tap toggle is invalid action.
257                     break;
258                 case 0xFF:
259                     if (!event.pressed) {
260                         default_layer = action.layer.opt;
261                         layer_switch(default_layer);
262                     }
263                     break;
264                 default:
265                     // Ignored. LAYER_RELEASED with tap key is invalid action.
266                     break;
267             }
268             break;
269         case ACT_LAYER_BIT:
270             switch (action.layer.code) {
271                 case 0x00:
272                     if (event.pressed) {
273                         layer_switch(current_layer | action.layer.opt);
274                     } else {
275                         layer_switch(current_layer & ~action.layer.opt);
276                     }
277                     break;
278                 case 0xF0:
279                     // TODO: tap toggle
280                     break;
281                 case 0xFF:
282                     // change default layer
283                     if (event.pressed) {
284                         default_layer = current_layer | action.layer.opt;
285                         layer_switch(default_layer);
286                     } else {
287                         default_layer = current_layer & ~action.layer.opt;
288                         layer_switch(default_layer);
289                     }
290                     break;
291                 default:
292                     // with tap key
293                     debug("tap: "); debug_hex(tap_count); debug("\n");
294                     if (event.pressed) {
295                         if (tap_count == 0) {
296                             if (host_has_anykey()) {
297                                 register_code(action.layer.code);
298                             } else {
299                                 delaying_layer = (keyrecord_t){
300                                     .event = event,
301                                     .action = action,
302                                     .mods = keyboard_report->mods
303                                 };
304                             }
305                         } else if (tap_count > 0) {
306                             register_code(action.layer.code);
307                         }
308                     } else {
309                         if (tap_count == 0) {
310                             // no tap
311                             layer_switch(current_layer & ~action.layer.opt);
312                         } else if (tap_count == 1) {
313                             // tap
314                             register_code(action.layer.code);
315                         }
316                         unregister_code(action.layer.code);
317                     }
318                     break;
319             }
320         case ACT_LAYER_EXT:
321             switch (action.layer.opt) {
322                 case 0x00:
323                     // set default layer when pressed
324                     switch (action.layer.code) {
325                         case 0x00:
326                             if (event.pressed) {
327                                 layer_switch(default_layer);
328                             }
329                             break;
330                         case 0xF0:
331                             // TODO: tap toggle
332                             break;
333                         case 0xFF:
334                             if (event.pressed) {
335                                 default_layer = current_layer;
336                                 layer_switch(default_layer);
337                             }
338                             break;
339                         default:
340                             // TODO: tap key
341                             break;
342                     }
343                     break;
344                 case 0x01:
345                     // set default layer when released
346                     switch (action.layer.code) {
347                         case 0x00:
348                             if (!event.pressed) {
349                                 layer_switch(default_layer);
350                             }
351                             break;
352                         case 0xFF:
353                             if (!event.pressed) {
354                                 default_layer = current_layer;
355                                 layer_switch(default_layer);
356                             }
357                             break;
358                         case 0xF0:
359                         default:
360                             // Ignore tap.
361                             if (!event.pressed) {
362                                 layer_switch(default_layer);
363                             }
364                             break;
365                     }
366                     break;
367             }
368             break;
369         case ACT_MACRO:
370         case ACT_COMMAND:
371         case ACT_FUNCTION:
372         default:
373             break;
374     }
375
376     /* last event */
377     last_event = event;
378     last_event_time = timer_read();
379 }
380
381
382 static void register_code(uint8_t code)
383 {
384     if (code == KC_NO) {
385         return;
386     }
387     else if IS_KEY(code) {
388         // TODO: should push command_proc out of this block?
389         if (!command_proc(code)) {
390             host_add_key(code);
391             host_send_keyboard_report();
392         }
393     }
394     else if IS_MOD(code) {
395         host_add_mods(MOD_BIT(code));
396         host_send_keyboard_report();
397     }
398 }
399
400 static void unregister_code(uint8_t code)
401 {
402     if IS_KEY(code) {
403         host_del_key(code);
404         host_send_keyboard_report();
405     }
406     else if IS_MOD(code) {
407         host_del_mods(MOD_BIT(code));
408         host_send_keyboard_report();
409     }
410 }
411
412 static void register_mods(uint8_t mods)
413 {
414     if (!mods) return;
415     host_add_mods(mods);
416     host_send_keyboard_report();
417 }
418
419 static void unregister_mods(uint8_t mods)
420 {
421     if (!mods) return;
422     host_del_mods(mods);
423     host_send_keyboard_report();
424 }
425
426 static void clear_keyboard(void)
427 {
428     host_clear_mods();
429     clear_keyboard_but_mods();
430 }
431
432 static void clear_keyboard_but_mods(void)
433 {
434     host_clear_keys();
435     host_send_keyboard_report();
436 #ifdef MOUSEKEY_ENABLE
437     mousekey_clear();
438     mousekey_send();
439 #endif
440 #ifdef EXTRAKEY_ENABLE
441     host_system_send(0);
442     host_consumer_send(0);
443 #endif
444 }
445
446 static void layer_switch(uint8_t new_layer)
447 {
448     if (current_layer != new_layer) {
449         Kdebug("Layer Switch: "); Kdebug_hex(current_layer);
450         Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");
451
452         current_layer = new_layer;
453         clear_keyboard_but_mods(); // To avoid stuck keys
454     }
455 }