]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/keyboard.c
Add repeating of Fn key with alt keycode.
[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 "usb_keycodes.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     MOUSEKEY_DOWN, MOUSEKEY_UP,
45     DELAY
46 } keykind_t;
47
48 typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
49
50
51 uint8_t current_layer = 0;
52 uint8_t default_layer = 0;
53
54 /* keyboard internal states */
55 static kbdstate_t kbdstate = IDLE;
56 static uint8_t fn_state_bits = 0;
57 static keyrecord_t delayed_fn;
58 static keyrecord_t waiting_key;
59
60
61 static const char *state_str(kbdstate_t state)
62 {
63     if (state == IDLE)      return PSTR("IDLE");
64     if (state == DELAYING)  return PSTR("DELAYING");
65     if (state == WAITING)   return PSTR("WAITING");
66     if (state == PRESSING)  return PSTR("PRESSING");
67     return PSTR("UNKNOWN");
68 }
69
70 static inline keykind_t get_keykind(uint8_t code, bool pressed)
71 {
72     if IS_KEY(code) return (pressed ? KEY_DOWN      : KEY_UP);
73     if IS_MOD(code) return (pressed ? MOD_DOWN      : MOD_UP);
74     if IS_FN(code) {
75         if (keymap_fn_keycode(FN_INDEX(code)))
76             return (pressed ? FNK_DOWN : FNK_UP);
77         else
78             return (pressed ? FN_DOWN : FN_UP);
79     }
80     if IS_MOUSEKEY(code)    return (pressed ? MOUSEKEY_DOWN : MOUSEKEY_UP);
81     return  NONE;
82 }
83
84 static void layer_switch_on(uint8_t code)
85 {
86     if (!IS_FN(code)) return;
87     fn_state_bits |= FN_BIT(code);
88     if (current_layer != keymap_fn_layer(FN_INDEX(code))) {
89         //TODO: clear all key execpt Mod key
90         debug("Layer Switch(on): "); debug_hex(current_layer);
91         current_layer = keymap_fn_layer(FN_INDEX(code));
92         debug(" -> "); debug_hex(current_layer); debug("\n");
93     }
94 }
95
96 static void layer_switch_off(uint8_t code)
97 {
98     if (!IS_FN(code)) return;
99     fn_state_bits &= ~FN_BIT(code);
100     if (current_layer != keymap_fn_layer(biton(fn_state_bits))) {
101         //TODO: clear all key execpt Mod key
102         debug("Layer Switch(off): "); debug_hex(current_layer);
103         current_layer = keymap_fn_layer(biton(fn_state_bits));
104         debug(" -> "); debug_hex(current_layer); debug("\n");
105     }
106 }
107
108 static inline uint8_t get_keycode(key_t key)
109 {
110     return keymap_get_keycode(current_layer, key.row, key.col);
111 }
112
113 // whether any key except modifier is down or not
114 static inline bool is_anykey_down(void)
115 {
116     for (int r = 0; r < MATRIX_ROWS; r++) {
117         matrix_row_t matrix_row = matrix_get_row(r);
118         for (int c = 0; c < MATRIX_COLS; c++) {
119             if (matrix_row && (1<<c)) {
120                 if (IS_KEY(get_keycode((key_t){ .row = r, .col = c }))) {
121                     return true;
122                 }
123             }
124         }
125     }
126     return false;
127 }
128
129 static void register_code(uint8_t code)
130 {
131     if IS_KEY(code) {
132         host_add_key(code);
133         host_send_keyboard_report();
134     }
135     else if IS_MOD(code) {
136         host_add_mod_bit(MOD_BIT(code));
137         host_send_keyboard_report();
138     }
139     else if IS_MOUSEKEY(code) {
140         mousekey_on(code);
141         mousekey_send();
142     }
143 }
144
145 static void unregister_code(uint8_t code)
146 {
147     if IS_KEY(code) {
148         host_del_key(code);
149         host_send_keyboard_report();
150     }
151     else if IS_MOD(code) {
152         host_del_mod_bit(MOD_BIT(code));
153         host_send_keyboard_report();
154     }
155     else if IS_MOUSEKEY(code) {
156         mousekey_off(code);
157         mousekey_send();
158     }
159 }
160
161 /*
162  *
163  * Event/State|IDLE             DELAYING[f]     WAITING[f,k]        PRESSING
164  * -----------+------------------------------------------------------------------
165  * Fn  Down   |IDLE(L+)         WAITING(Sk)     WAITING(Sk)         -
166  *     Up     |IDLE(L-)         IDLE(L-)        IDLE(L-)            IDLE(L-)
167  * Fnk Down   |DELAYING(Sf)     WAITING(Sk)     WAINTING(Sk)        PRESSING(Rf)
168  *     Up     |IDLE(L-)         IDLE(Rf,Uf)     IDLE(Rf,Ps,Uf)*3    PRESSING(Uf)
169  * Key Down   |PRESSING(Rk)     WAITING(Sk)     WAITING(Sk)         PRESSING(Rk)
170  *     Up     |IDLE(Uk)         DELAYING(Uk)    IDLE(L+,Ps,Uk)      IDLE(Uk)*4
171  * Delay      |-                IDLE(L+)        IDLE(L+,Ps)         -
172  *            |
173  * No key Down|IDLE(Ld)         IDLE(Ld)        IDLE(Ld)            IDLE(Ld)
174  *
175  * *2: register Fnk if any key is pressing
176  * *3: when Fnk == Stored Fnk, if not ignore.
177  * *4: when no registered key any more
178  *
179  * States:
180  *      IDLE:
181  *      DELAYING: delay layer switch after pressing Fn with alt keycode
182  *      WAITING: key is pressed during DELAYING
183  *
184  * Events:
185  *      Fn: Fn key without alternative keycode
186  *      Fnk: Fn key with alternative keycode
187  *      -: ignore
188  *
189  * Actions:
190  *      Rk: register key
191  *      Uk: unregister key
192  *      Rf: register stored Fn(alt keycode)
193  *      Uf: unregister stored Fn(alt keycode)
194  *      Rs: register stored key
195  *      Us: unregister stored key
196  *      Sk: store key
197  *      Sf: store Fn
198  *      Ps: play stored key(Interpret stored key and transit state)
199  *      L+: Switch to new layer(*retain* Modifiers only)
200  *      L-: Switch back to last layer(*clear* stored key/Fn, *unregister* all Modifier/key)
201  *      Ld: Switch back to default layer(*clear* stored key/Fn, *unregister* all Modifier/key)
202  */
203 #define NEXT(state)     do { \
204     debug("NEXT: "); print_P(state_str(kbdstate)); \
205     kbdstate = state; \
206     debug(" -> "); print_P(state_str(kbdstate)); debug("\n"); \
207 } while (0)
208
209 static inline void process_key(keyevent_t event)
210 {
211     /* TODO: ring buffer
212     static keyrecord_t waiting_keys[5];
213     static uint8_t waiting_keys_head = 0;
214     static uint8_t waiting_keys_tail = 0;
215     */
216
217     uint8_t code = get_keycode(event.key);
218     keykind_t kind = get_keykind(code, event.pressed);
219
220     uint8_t tmp_mods;
221
222     debug("state: "); print_P(state_str(kbdstate));
223     debug(" kind: "); debug_hex(kind);
224     debug(" code: "); debug_hex(code);
225     if (event.pressed) { debug("d"); } else { debug("u"); }
226     debug("\n");
227
228     switch (kbdstate) {
229         case IDLE:
230             switch (kind) {
231                 case FN_DOWN:
232                     layer_switch_on(code);
233                     break;
234                 case FN_UP:
235                     layer_switch_off(code);
236                     break;
237                 case FNK_DOWN:
238                     // repeat Fn alt key when press Fn key down, up then down again quickly
239                     if (KEYEQ(delayed_fn.event.key, event.key) &&
240                             timer_elapsed(delayed_fn.time) < LAYER_DELAY) {
241                         register_code(keymap_fn_keycode(FN_INDEX(code)));
242                         NEXT(PRESSING);
243                     } else {
244                         delayed_fn = (keyrecord_t) {
245                             .event = event,
246                             .code = code,
247                             .mods = keyboard_report->mods,
248                             .time = timer_read()
249                         };
250                         NEXT(DELAYING);
251                     }
252                     break;
253                 case FNK_UP:
254                     layer_switch_off(code);
255                     break;
256                 case KEY_DOWN:
257                 case MOUSEKEY_DOWN:
258                     register_code(code);
259                     NEXT(PRESSING);
260                     break;
261                 case MOD_DOWN:
262                     register_code(code);
263                     break;
264                 case KEY_UP:
265                 case MOUSEKEY_UP:
266                 case MOD_UP:
267                     unregister_code(code);
268                     break;
269                 default:
270                     break;
271             }
272             break;
273         case PRESSING:
274             switch (kind) {
275                 case FN_DOWN:
276                     // ignored when any key is pressed
277                     break;
278                 case FN_UP:
279                     layer_switch_off(code);
280                     NEXT(IDLE);
281                     break;
282                 case FNK_DOWN:
283                     register_code(keymap_fn_keycode(FN_INDEX(code)));
284                     break;
285                 case FNK_UP:
286                     unregister_code(keymap_fn_keycode(FN_INDEX(code)));
287                     break;
288                 case KEY_DOWN:
289                 case MOD_DOWN:
290                 case MOUSEKEY_DOWN:
291                     register_code(code);
292                     break;
293                 case KEY_UP:
294                 case MOD_UP:
295                 case MOUSEKEY_UP:
296                     unregister_code(code);
297                     // no key registered? mousekey, mediakey, systemkey
298                     if (!host_has_anykey())
299                         NEXT(IDLE);
300                     break;
301                 default:
302                     break;
303             }
304             break;
305         case DELAYING:
306             switch (kind) {
307                 case FN_DOWN:
308                 case FNK_DOWN:
309                 case KEY_DOWN:
310                 case MOUSEKEY_DOWN:
311                     waiting_key = (keyrecord_t) {
312                         .event = event,
313                         .code = code,
314                         .mods = keyboard_report->mods,
315                         .time = timer_read()
316                     };
317                     NEXT(WAITING);
318                     break;
319                 case MOD_DOWN:
320                     register_code(code);
321                     break;
322                 case FN_UP:
323                     layer_switch_off(code);
324                     NEXT(IDLE);
325                     break;
326                 case FNK_UP:
327                     if (code == delayed_fn.code) {
328                         // type Fn with alt keycode
329                         // restore the mod status at the time of pressing Fn key
330                         tmp_mods = keyboard_report->mods;
331                         host_set_mods(delayed_fn.mods);
332                         register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
333                         unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
334                         host_set_mods(tmp_mods);
335                         NEXT(IDLE);
336                     } else {
337                         layer_switch_off(code);
338                         NEXT(IDLE);
339                     }
340                     break;
341                 case KEY_UP:
342                 case MOUSEKEY_UP:
343                     unregister_code(code);
344                     NEXT(IDLE);
345                     break;
346                 case MOD_UP:
347                     unregister_code(code);
348                     break;
349                 default:
350                     break;
351             }
352             break;
353         case WAITING:
354             switch (kind) {
355                 case FN_DOWN:
356                 case FNK_DOWN:
357                 case KEY_DOWN:
358                 case MOUSEKEY_DOWN:
359                     tmp_mods = keyboard_report->mods;
360                     host_set_mods(delayed_fn.mods);
361                     register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
362                     host_set_mods(waiting_key.mods);
363                     register_code(waiting_key.code);
364                     host_set_mods(tmp_mods);
365                     register_code(code);
366                     NEXT(IDLE);
367                     break;
368                 case MOD_DOWN:
369                     register_code(code);
370                     break;
371                 case FN_UP:
372                     layer_switch_off(code);
373                     NEXT(IDLE);
374                     break;
375                 case FNK_UP:
376                     if (code == delayed_fn.code) {
377                         // alt down, key down, alt up
378                         tmp_mods = keyboard_report->mods;
379                         host_set_mods(delayed_fn.mods);
380                         register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
381                         host_set_mods(waiting_key.mods);
382                         register_code(waiting_key.code);
383                         unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
384                         host_set_mods(tmp_mods);
385                         NEXT(IDLE);
386                     } else {
387                         layer_switch_off(code);
388                         NEXT(IDLE);
389                     }
390                     break;
391                 case KEY_UP:
392                 case MOUSEKEY_UP:
393                     if (code == waiting_key.code) {
394                         layer_switch_on(delayed_fn.code);
395                         NEXT(IDLE);
396                         // process waiting_key
397                         tmp_mods = keyboard_report->mods;
398                         host_set_mods(waiting_key.mods);
399                         process_key(waiting_key.event);
400                         host_set_mods(tmp_mods);
401                         process_key(event);
402                     } else {
403                         unregister_code(code);
404                     }
405                     break;
406                 case MOD_UP:
407                     unregister_code(code);
408                     break;
409                 default:
410                     break;
411             }
412             break;
413     }
414
415     // TODO: FAIL SAFE: unregister all keys when no key down
416 }
417
418 void keyboard_init(void)
419 {
420     debug_keyboard = true;
421
422     timer_init();
423     matrix_init();
424 #ifdef PS2_MOUSE_ENABLE
425     ps2_mouse_init();
426 #endif
427 }
428
429 void keyboard_task(void)
430 {
431     static matrix_row_t matrix_prev[MATRIX_ROWS];
432     matrix_row_t matrix_row = 0;
433     matrix_row_t matrix_change = 0;
434
435     matrix_scan();
436     if (command_proc()) {
437         debug("COMMAND\n");
438         // TODO: clear all keys
439         host_clear_keyboard_report();
440         host_send_keyboard_report();
441         return;
442     }
443     for (int r = 0; r < MATRIX_ROWS; r++) {
444         matrix_row = matrix_get_row(r);
445         matrix_change = matrix_row ^ matrix_prev[r];
446         if (matrix_change) {
447             // TODO: print once per scan
448             if (debug_matrix) matrix_print();
449
450             for (int c = 0; c < MATRIX_COLS; c++) {
451                 if (matrix_change & (1<<c)) {
452                     process_key((keyevent_t){
453                         .key = (key_t){ .row = r, .col = c },
454                         .pressed = (matrix_row & (1<<c))
455                     });
456                     // record a processed key
457                     matrix_prev[r] ^= (1<<c);
458                     // process a key per task call
459                     goto MATRIX_LOOP_END;
460                 }
461             }
462         }
463     }
464     MATRIX_LOOP_END:
465     // TODO: FAIL SAFE: clear all key if no key down
466
467     // layer switch when delay term elapses
468     if (kbdstate == DELAYING || kbdstate == WAITING) {
469         if (timer_elapsed(delayed_fn.time) > LAYER_DELAY) {
470             if (kbdstate == DELAYING) {
471                 layer_switch_on(delayed_fn.code);
472                 NEXT(IDLE);
473             }
474             if (kbdstate == WAITING) {
475                 layer_switch_on(delayed_fn.code);
476                 NEXT(IDLE);
477                 uint8_t tmp_mods = keyboard_report->mods;
478                 host_set_mods(waiting_key.mods);
479                 process_key(waiting_key.event);
480                 host_set_mods(tmp_mods);
481             }
482         }
483     }
484
485     // mousekey repeat & acceleration
486     mousekey_task();
487
488     return;
489 }
490
491 void keyboard_set_leds(uint8_t leds)
492 {
493     led_set(leds);
494 }