]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/keyboard.c
Fix layer switching and host API.
[tmk_firmware.git] / common / keyboard.c
1 /*
2 Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "keyboard.h"
18 #include "matrix.h"
19 #include "keymap.h"
20 #include "host.h"
21 #include "led.h"
22 #include "keycode.h"
23 #include "timer.h"
24 #include "print.h"
25 #include "debug.h"
26 #include "command.h"
27 #include "util.h"
28 #ifdef MOUSEKEY_ENABLE
29 #include "mousekey.h"
30 #endif
31 #ifdef EXTRAKEY_ENABLE
32 #include <util/delay.h>
33 #endif
34
35
36 #define LAYER_DELAY     250
37
38 typedef enum keykind {
39     NONE,
40     FN_DOWN, FN_UP,
41     FNK_DOWN, FNK_UP,
42     KEY_DOWN, KEY_UP,
43     MOD_DOWN, MOD_UP,
44 } keykind_t;
45
46 typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
47
48
49 uint8_t current_layer = 0;
50 uint8_t default_layer = 0;
51
52 /* keyboard internal states */
53 static kbdstate_t kbdstate = IDLE;
54 static uint8_t fn_state_bits = 0;
55 static keyrecord_t delayed_fn;
56 static keyrecord_t waiting_key;
57
58
59 static const char *state_str(kbdstate_t state)
60 {
61     if (state == IDLE)      return PSTR("IDLE");
62     if (state == DELAYING)  return PSTR("DELAYING");
63     if (state == WAITING)   return PSTR("WAITING");
64     if (state == PRESSING)  return PSTR("PRESSING");
65     return PSTR("UNKNOWN");
66 }
67
68 static inline keykind_t get_keykind(uint8_t code, bool pressed)
69 {
70     if IS_KEY(code)         return (pressed ? KEY_DOWN : KEY_UP);
71     if IS_MOD(code)         return (pressed ? MOD_DOWN : MOD_UP);
72     if IS_FN(code) {
73         if (keymap_fn_keycode(FN_INDEX(code)))
74             return (pressed ? FNK_DOWN : FNK_UP);
75         else
76             return (pressed ? FN_DOWN : FN_UP);
77     }
78     if IS_MOUSEKEY(code)    return (pressed ? KEY_DOWN : KEY_UP);
79     if IS_SYSTEM(code)      return (pressed ? KEY_DOWN : KEY_UP);
80     if IS_CONSUMER(code)    return (pressed ? KEY_DOWN : KEY_UP);
81     return  NONE;
82 }
83
84 static void clear_keyboard(void)
85 {
86     host_clear_keys();
87     host_clear_mods();
88     host_send_keyboard_report();
89
90     host_system_send(0);
91     host_consumer_send(0);
92
93 #ifdef MOUSEKEY_ENABLE
94     mousekey_clear();
95     mousekey_send();
96 #endif
97 }
98
99 static void clear_keyboard_but_mods(void)
100 {
101     host_clear_keys();
102     host_send_keyboard_report();
103
104     host_system_send(0);
105     host_consumer_send(0);
106
107 #ifdef MOUSEKEY_ENABLE
108     mousekey_clear();
109     mousekey_send();
110 #endif
111 }
112
113 static bool anykey_sent_to_host(void)
114 {
115     return (host_has_anykey() || host_mouse_in_use() ||
116             host_last_sysytem_report() || host_last_consumer_report());
117 }
118
119 static void layer_switch_on(uint8_t code)
120 {
121     if (!IS_FN(code)) return;
122     fn_state_bits |= FN_BIT(code);
123     if (current_layer != keymap_fn_layer(FN_INDEX(code))) {
124         clear_keyboard_but_mods();
125
126         debug("Layer Switch(on): "); debug_hex(current_layer);
127         current_layer = keymap_fn_layer(FN_INDEX(code));
128         debug(" -> "); debug_hex(current_layer); debug("\n");
129     }
130 }
131
132 static bool layer_switch_off(uint8_t code)
133 {
134     if (!IS_FN(code)) return false;
135     fn_state_bits &= ~FN_BIT(code);
136     if (current_layer != keymap_fn_layer(biton(fn_state_bits))) {
137         clear_keyboard_but_mods();
138
139         debug("Layer Switch(off): "); debug_hex(current_layer);
140         current_layer = keymap_fn_layer(biton(fn_state_bits));
141         debug(" -> "); debug_hex(current_layer); debug("\n");
142         return true;
143     }
144     return false;
145 }
146
147 static void register_code(uint8_t code)
148 {
149     if IS_KEY(code) {
150         host_add_key(code);
151         host_send_keyboard_report();
152     }
153     else if IS_MOD(code) {
154         host_add_mod_bit(MOD_BIT(code));
155         host_send_keyboard_report();
156     }
157     else if IS_FN(code) {
158         host_add_key(keymap_fn_keycode(FN_INDEX(code)));
159         host_send_keyboard_report();
160     }
161     else if IS_MOUSEKEY(code) {
162 #ifdef MOUSEKEY_ENABLE
163         mousekey_on(code);
164         mousekey_send();
165 #endif
166     }
167     else if IS_CONSUMER(code) {
168         uint16_t usage = 0;
169         switch (code) {
170             case KC_AUDIO_MUTE:
171                 usage = AUDIO_MUTE;
172                 break;
173             case KC_AUDIO_VOL_UP:
174                 usage = AUDIO_VOL_UP;
175                 break;
176             case KC_AUDIO_VOL_DOWN:
177                 usage = AUDIO_VOL_DOWN;
178                 break;
179             case KC_MEDIA_NEXT_TRACK:
180                 usage = TRANSPORT_NEXT_TRACK;
181                 break;
182             case KC_MEDIA_PREV_TRACK:
183                 usage = TRANSPORT_PREV_TRACK;
184                 break;
185             case KC_MEDIA_STOP:
186                 usage = TRANSPORT_STOP;
187                 break;
188             case KC_MEDIA_PLAY_PAUSE:
189                 usage = TRANSPORT_PLAY_PAUSE;
190                 break;
191             case KC_MEDIA_SELECT:
192                 usage = AL_CC_CONFIG;
193                 break;
194             case KC_MAIL:
195                 usage = AL_EMAIL;
196                 break;
197             case KC_CALCULATOR:
198                 usage = AL_CALCULATOR;
199                 break;
200             case KC_MY_COMPUTER:
201                 usage = AL_LOCAL_BROWSER;
202                 break;
203             case KC_WWW_SEARCH:
204                 usage = AC_SEARCH;
205                 break;
206             case KC_WWW_HOME:
207                 usage = AC_HOME;
208                 break;
209             case KC_WWW_BACK:
210                 usage = AC_BACK;
211                 break;
212             case KC_WWW_FORWARD:
213                 usage = AC_FORWARD;
214                 break;
215             case KC_WWW_STOP:
216                 usage = AC_STOP;
217                 break;
218             case KC_WWW_REFRESH:
219                 usage = AC_REFRESH;
220                 break;
221             case KC_WWW_FAVORITES:
222                 usage = AC_BOOKMARKS;
223                 break;
224         }
225         host_consumer_send(usage);
226     }
227     else if IS_SYSTEM(code) {
228         uint16_t usage = 0;
229         switch (code) {
230             case KC_SYSTEM_POWER:
231                 usage = SYSTEM_POWER_DOWN;
232                 break;
233             case KC_SYSTEM_SLEEP:
234                 usage = SYSTEM_SLEEP;
235                 break;
236             case KC_SYSTEM_WAKE:
237                 usage = SYSTEM_WAKE_UP;
238                 break;
239         }
240         host_system_send(usage);
241     }
242
243 }
244
245 static void unregister_code(uint8_t code)
246 {
247     if IS_KEY(code) {
248         host_del_key(code);
249         host_send_keyboard_report();
250     }
251     else if IS_MOD(code) {
252         host_del_mod_bit(MOD_BIT(code));
253         host_send_keyboard_report();
254     }
255     else if IS_FN(code) {
256         host_del_key(keymap_fn_keycode(FN_INDEX(code)));
257         host_send_keyboard_report();
258     }
259     else if IS_MOUSEKEY(code) {
260 #ifdef MOUSEKEY_ENABLE
261         mousekey_off(code);
262         mousekey_send();
263 #endif
264     }
265     else if IS_CONSUMER(code) {
266         host_consumer_send(0x0000);
267     }
268     else if IS_SYSTEM(code) {
269         host_system_send(0x0000);
270     }
271 }
272
273 /*
274  *
275  * Event/State|IDLE          PRESSING      DELAYING[f]      WAITING[f,k]         
276  * -----------+------------------------------------------------------------------
277  * Fn  Down   |(L+)          -*1           WAITING(Sk)      IDLE(Rf,Ps)*7        
278  *     Up     |(L-)          IDLE(L-)*8    IDLE(L-)*8       IDLE(L-)*8           
279  * Fnk Down   |DELAYING(Sf)* (Rf)          WAITING(Sk)      IDLE(Rf,Ps,Rf)       
280  *     Up     |(L-)          IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3  
281  * Key Down   |PRESSING(Rk)  (Rk)          WAITING(Sk)      IDLE(Rf,Ps,Rk)       
282  *     Up     |(Uk)          IDLE(Uk)*4    (Uk)             IDLE(L+,Ps,Pk)/(Uk)*a
283  *            |
284  * Delay      |-             -             IDLE(L+)         IDLE(L+,Ps)          
285  * Magic Key  |COMMAND*5
286  *
287  * *1: ignore Fn if other key is down.
288  * *2: register Fnk if any key is pressing
289  * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8
290  * *4: if no keys registered to host
291  * *5: unregister all keys
292  * *6: only if no keys down
293  * *7: ignore Fn because Fnk key and stored key are down.
294  * *8: move to IDLE if layer switch(off) occurs, else stay at current state
295  * *9: repeat key if pressing Fnk twice quickly(move to PRESSING)
296  * *a: layer switch and process waiting key and code if code == wainting key, else unregister key
297  *
298  * States:
299  *      IDLE: No key is down except modifiers
300  *      DELAYING: delay layer switch after pressing Fn with alt keycode
301  *      WAITING: key is pressed during DELAYING
302  *
303  * Events:
304  *      Fn: Fn key without alternative keycode
305  *      Fnk: Fn key with alternative keycode
306  *      -: ignore
307  *      Delay: layer switch delay term is elapsed
308  *
309  * Actions:
310  *      Rk: register key
311  *      Uk: unregister key
312  *      Rf: register Fn(alt keycode)
313  *      Uf: unregister Fn(alt keycode)
314  *      Rs: register stored key
315  *      Us: unregister stored key
316  *      Sk: Store key(waiting Key)
317  *      Sf: Store Fn(delayed Fn)
318  *      Ps: Process stored key
319  *      Ps: Process key
320  *      Is: Interpret stored keys in current layer
321  *      L+: Switch to new layer(*unregister* all keys but modifiers)
322  *      L-: Switch back to last layer(*unregister* all keys but modifiers)
323  *      Ld: Switch back to default layer(*unregister* all keys but modifiers)
324  */
325 #define NEXT(state)     do { \
326     debug("NEXT: "); print_P(state_str(kbdstate)); \
327     kbdstate = state; \
328     debug(" -> "); print_P(state_str(kbdstate)); debug("\n"); \
329 } while (0)
330
331 static inline void process_key(keyevent_t event)
332 {
333     uint8_t code = keymap_get_keycode(current_layer, event.key.row, event.key.col);
334     keykind_t kind = get_keykind(code, event.pressed);
335
336     uint8_t tmp_mods;
337
338     debug("state: "); print_P(state_str(kbdstate));
339     debug(" kind: "); debug_hex(kind);
340     debug(" code: "); debug_hex(code);
341     if (event.pressed) { debug("d"); } else { debug("u"); }
342     debug("\n");
343
344     switch (kbdstate) {
345         case IDLE:
346             switch (kind) {
347                 case FN_DOWN:
348                     layer_switch_on(code);
349                     break;
350                 case FN_UP:
351                     layer_switch_off(code);
352                     break;
353                 case FNK_DOWN:
354                     // repeat Fn alt key when press Fn key down, up then down again quickly
355                     if (KEYEQ(delayed_fn.event.key, event.key) &&
356                             timer_elapsed(delayed_fn.time) < LAYER_DELAY) {
357                         register_code(code);
358                         NEXT(PRESSING);
359                     } else {
360                         delayed_fn = (keyrecord_t) {
361                             .event = event,
362                             .code = code,
363                             .mods = keyboard_report->mods,
364                             .time = timer_read()
365                         };
366                         NEXT(DELAYING);
367                     }
368                     break;
369                 case FNK_UP:
370                     layer_switch_off(code);
371                     break;
372                 case KEY_DOWN:
373                     register_code(code);
374                     NEXT(PRESSING);
375                     break;
376                 case MOD_DOWN:
377                     register_code(code);
378                     break;
379                 case KEY_UP:
380                 case MOD_UP:
381                     unregister_code(code);
382                     break;
383                 default:
384                     break;
385             }
386             break;
387         case PRESSING:
388             switch (kind) {
389                 case FN_DOWN:
390                     // ignored when any key is pressed
391                     break;
392                 case FN_UP:
393                     if (layer_switch_off(code))
394                         NEXT(IDLE);
395                     break;
396                 case FNK_DOWN:
397                     register_code(code);
398                     break;
399                 case FNK_UP:
400                     if (layer_switch_off(code)) {
401                         NEXT(IDLE);
402                     } else {
403                         unregister_code(code);
404                         if (!anykey_sent_to_host())
405                             NEXT(IDLE);
406                     }
407                     break;
408                 case KEY_DOWN:
409                 case MOD_DOWN:
410                     register_code(code);
411                     break;
412                 case KEY_UP:
413                 case MOD_UP:
414                     unregister_code(code);
415                     if (!anykey_sent_to_host())
416                         NEXT(IDLE);
417                     break;
418                 default:
419                     break;
420             }
421             break;
422         case DELAYING:
423             switch (kind) {
424                 case FN_DOWN:
425                 case FNK_DOWN:
426                 case KEY_DOWN:
427                     waiting_key = (keyrecord_t) {
428                         .event = event,
429                         .code = code,
430                         .mods = keyboard_report->mods,
431                         .time = timer_read()
432                     };
433                     NEXT(WAITING);
434                     break;
435                 case MOD_DOWN:
436                     register_code(code);
437                     break;
438                 case FN_UP:
439                     if (layer_switch_off(code))
440                         NEXT(IDLE);
441                     break;
442                 case FNK_UP:
443                     if (code == delayed_fn.code) {
444                         // type Fn with alt keycode
445                         // restore the mod status at the time of pressing Fn key
446                         tmp_mods = keyboard_report->mods;
447                         host_set_mods(delayed_fn.mods);
448                         register_code(delayed_fn.code);
449                         unregister_code(delayed_fn.code);
450                         host_set_mods(tmp_mods);
451                         NEXT(IDLE);
452                     } else {
453                         if (layer_switch_off(code))
454                             NEXT(IDLE);
455                     }
456                     break;
457                 case KEY_UP:
458                 case MOD_UP:
459                     unregister_code(code);
460                     break;
461                 default:
462                     break;
463             }
464             break;
465         case WAITING:
466             switch (kind) {
467                 case FN_DOWN:
468                 case FNK_DOWN:
469                 case KEY_DOWN:
470                     tmp_mods = keyboard_report->mods;
471                     host_set_mods(delayed_fn.mods);
472                     register_code(delayed_fn.code);
473                     host_set_mods(waiting_key.mods);
474                     register_code(waiting_key.code);
475                     host_set_mods(tmp_mods);
476                     if (kind == FN_DOWN) {
477                         // ignore Fn
478                     } else if (kind == FNK_DOWN) {
479                         register_code(code);
480                     } else if (kind == KEY_DOWN) {
481                         register_code(code);
482                     }
483                     NEXT(IDLE);
484                     break;
485                 case MOD_DOWN:
486                     register_code(code);
487                     break;
488                 case FN_UP:
489                     if (layer_switch_off(code))
490                         NEXT(IDLE);
491                     break;
492                 case FNK_UP:
493                     if (code == delayed_fn.code) {
494                         // alt down, key down, alt up
495                         tmp_mods = keyboard_report->mods;
496                         host_set_mods(delayed_fn.mods);
497                         register_code(delayed_fn.code);
498                         host_set_mods(waiting_key.mods);
499                         register_code(waiting_key.code);
500                         unregister_code(delayed_fn.code);
501                         host_set_mods(tmp_mods);
502                         NEXT(IDLE);
503                     } else {
504                         if (layer_switch_off(code))
505                             NEXT(IDLE);
506                     }
507                     break;
508                 case KEY_UP:
509                     if (code == waiting_key.code) {
510                         layer_switch_on(delayed_fn.code);
511                         NEXT(IDLE);
512                         // process waiting_key
513                         tmp_mods = keyboard_report->mods;
514                         host_set_mods(waiting_key.mods);
515                         process_key(waiting_key.event);
516                         host_set_mods(tmp_mods);
517                         process_key(event);
518                     } else {
519                         unregister_code(code);
520                     }
521                     break;
522                 case MOD_UP:
523                     unregister_code(code);
524                     break;
525                 default:
526                     break;
527             }
528             break;
529     }
530 }
531
532 void keyboard_init(void)
533 {
534     debug_keyboard = true;
535
536     timer_init();
537     matrix_init();
538 #ifdef PS2_MOUSE_ENABLE
539     ps2_mouse_init();
540 #endif
541 }
542
543 void keyboard_task(void)
544 {
545     static matrix_row_t matrix_prev[MATRIX_ROWS];
546     matrix_row_t matrix_row = 0;
547     matrix_row_t matrix_change = 0;
548
549     matrix_scan();
550     if (command_proc()) {
551         debug("COMMAND\n");
552         // TODO: COMMAND state?
553         clear_keyboard();
554         return;
555     }
556
557     for (int r = 0; r < MATRIX_ROWS; r++) {
558         matrix_row = matrix_get_row(r);
559         matrix_change = matrix_row ^ matrix_prev[r];
560         if (matrix_change) {
561             if (debug_matrix) matrix_print();
562
563             for (int c = 0; c < MATRIX_COLS; c++) {
564                 if (matrix_change & (1<<c)) {
565                     process_key((keyevent_t){
566                         .key = (key_t){ .row = r, .col = c },
567                         .pressed = (matrix_row & (1<<c))
568                     });
569                     // record a processed key
570                     matrix_prev[r] ^= (1<<c);
571                     // process a key per task call
572                     goto MATRIX_LOOP_END;
573                 }
574             }
575         }
576     }
577     MATRIX_LOOP_END:
578
579     // layer switch when delay term elapses
580     if (kbdstate == DELAYING || kbdstate == WAITING) {
581         if (timer_elapsed(delayed_fn.time) > LAYER_DELAY) {
582             if (kbdstate == DELAYING) {
583                 layer_switch_on(delayed_fn.code);
584                 NEXT(IDLE);
585             }
586             if (kbdstate == WAITING) {
587                 layer_switch_on(delayed_fn.code);
588                 NEXT(IDLE);
589                 uint8_t tmp_mods = keyboard_report->mods;
590                 host_set_mods(waiting_key.mods);
591                 process_key(waiting_key.event);
592                 host_set_mods(tmp_mods);
593             }
594         }
595     }
596
597 #ifdef MOUSEKEY_ENABLE
598     // mousekey repeat & acceleration
599     mousekey_task();
600 #endif
601
602     // FAIL SAFE: clear all key if no key down
603     if (matrix_change) {
604         matrix_row_t is_matrix_on = 0;
605         for (int r = 0; r < MATRIX_ROWS; r++) {
606             is_matrix_on |= matrix_get_row(r);
607         }
608         if (!is_matrix_on) {
609             debug("FAIL SAFE: clear all keys.\n");
610             clear_keyboard();
611         }
612     }
613     
614     return;
615 }
616
617 void keyboard_set_leds(uint8_t leds)
618 {
619     led_set(leds);
620 }