]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/keyboard.c
Initial version of new code for layer switch is added.
[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     
212     /* TODO: ring buffer
213     static keyrecord_t waiting_keys[5];
214     static uint8_t waiting_keys_head = 0;
215     static uint8_t waiting_keys_tail = 0;
216     */
217
218     uint8_t code = get_keycode(event.key);
219     keykind_t kind = get_keykind(code, event.pressed);
220
221     uint8_t tmp_mods;
222
223     //debug("kbdstate: "); debug_hex(kbdstate);
224     debug("state: "); print_P(state_str(kbdstate));
225     debug(" kind: "); debug_hex(kind);
226     debug(" code: "); debug_hex(code);
227     if (event.pressed) { debug("d"); } else { debug("u"); }
228     debug("\n");
229     switch (kbdstate) {
230         case IDLE:
231             switch (kind) {
232                 case FN_DOWN:
233                     layer_switch_on(code);
234                     break;
235                 case FN_UP:
236                     layer_switch_off(code);
237                     break;
238                 case FNK_DOWN:
239                     // store event
240                     delayed_fn = (keyrecord_t) { .event = event, .code = code, .mods = keyboard_report->mods, .time = timer_read() };
241                     NEXT(DELAYING);
242                     break;
243                 case FNK_UP:
244                     layer_switch_off(code);
245                     break;
246                 case KEY_DOWN:
247                 case MOUSEKEY_DOWN:
248                     register_code(code);
249                     NEXT(PRESSING);
250                     break;
251                 case MOD_DOWN:
252                     register_code(code);
253                     break;
254                 case KEY_UP:
255                 case MOUSEKEY_UP:
256                 case MOD_UP:
257                     unregister_code(code);
258                     break;
259                 default:
260                     break;
261             }
262             break;
263         case PRESSING:
264             switch (kind) {
265                 case FN_DOWN:
266                     // ignored when any key is pressed
267                     break;
268                 case FN_UP:
269                     layer_switch_off(code);
270                     NEXT(IDLE);
271                     break;
272                 case FNK_DOWN:
273                     register_code(keymap_fn_keycode(FN_INDEX(code)));
274                     break;
275                 case FNK_UP:
276                     unregister_code(keymap_fn_keycode(FN_INDEX(code)));
277                     break;
278                 case KEY_DOWN:
279                 case MOD_DOWN:
280                 case MOUSEKEY_DOWN:
281                     register_code(code);
282                     break;
283                 case KEY_UP:
284                 case MOD_UP:
285                 case MOUSEKEY_UP:
286                     unregister_code(code);
287                     // no key registered? mousekey, mediakey, systemkey
288                     if (!host_has_anykey())
289                         NEXT(IDLE);
290                     break;
291                 default:
292                     break;
293             }
294             break;
295         case DELAYING:
296             switch (kind) {
297                 case FN_DOWN:
298                 case FNK_DOWN:
299                 case KEY_DOWN:
300                 case MOUSEKEY_DOWN:
301                     waiting_key = (keyrecord_t) { .event = event, .code = code, .mods = keyboard_report->mods, .time = timer_read() };
302                     NEXT(WAITING);
303                     break;
304                 case MOD_DOWN:
305                     register_code(code);
306                     break;
307                 case FN_UP:
308                     layer_switch_off(code);
309                     NEXT(IDLE);
310                     break;
311                 case FNK_UP:
312                     if (code == delayed_fn.code) {
313                         // type Fn with alt keycode
314                         // restore the mod status at the time of pressing Fn key
315                         tmp_mods = keyboard_report->mods;
316                         host_set_mods(delayed_fn.mods);
317                         register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
318                         unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
319                         host_set_mods(tmp_mods);
320                         NEXT(IDLE);
321                     } else {
322                         layer_switch_off(code);
323                         NEXT(IDLE);
324                     }
325                     break;
326                 case KEY_UP:
327                 case MOUSEKEY_UP:
328                     unregister_code(code);
329                     NEXT(IDLE);
330                     break;
331                 case MOD_UP:
332                     unregister_code(code);
333                     break;
334                 default:
335                     break;
336             }
337             break;
338         case WAITING:
339             switch (kind) {
340                 case FN_DOWN:
341                 case FNK_DOWN:
342                 case KEY_DOWN:
343                 case MOUSEKEY_DOWN:
344                     tmp_mods = keyboard_report->mods;
345                     host_set_mods(delayed_fn.mods);
346                     register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
347                     host_set_mods(waiting_key.mods);
348                     register_code(waiting_key.code);
349                     host_set_mods(tmp_mods);
350                     register_code(code);
351                     NEXT(IDLE);
352                     break;
353                 case MOD_DOWN:
354                     register_code(code);
355                     break;
356                 case FN_UP:
357                     layer_switch_off(code);
358                     NEXT(IDLE);
359                     break;
360                 case FNK_UP:
361                     if (code == delayed_fn.code) {
362                         // alt down, key down, alt up
363                         tmp_mods = keyboard_report->mods;
364                         host_set_mods(delayed_fn.mods);
365                         register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
366                         host_set_mods(waiting_key.mods);
367                         register_code(waiting_key.code);
368                         unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
369                         host_set_mods(tmp_mods);
370                         NEXT(IDLE);
371                     } else {
372                         layer_switch_off(code);
373                         NEXT(IDLE);
374                     }
375                     break;
376                 case KEY_UP:
377                 case MOUSEKEY_UP:
378                     if (code == waiting_key.code) {
379                         layer_switch_on(delayed_fn.code);
380                         NEXT(IDLE);
381                         // process waiting_key
382                         tmp_mods = keyboard_report->mods;
383                         host_set_mods(waiting_key.mods);
384                         process_key(waiting_key.event);
385                         host_set_mods(tmp_mods);
386                         process_key(event);
387                     } else {
388                         unregister_code(code);
389                     }
390                     break;
391                 case MOD_UP:
392                     unregister_code(code);
393                     break;
394                 default:
395                     break;
396             }
397             break;
398     }
399
400     // TODO: FAIL SAFE: unregister all keys when no key down
401 }
402
403 void keyboard_init(void)
404 {
405     debug_keyboard = true;
406
407     timer_init();
408     matrix_init();
409 #ifdef PS2_MOUSE_ENABLE
410     ps2_mouse_init();
411 #endif
412 }
413
414 void keyboard_task(void)
415 {
416     static matrix_row_t matrix_prev[MATRIX_ROWS];
417     matrix_row_t matrix_row = 0;
418     matrix_row_t matrix_change = 0;
419
420     matrix_scan();
421     if (command_proc()) {
422         debug("COMMAND\n");
423         // TODO: clear all keys
424         host_clear_keyboard_report();
425         host_send_keyboard_report();
426         return;
427     }
428     for (int r = 0; r < MATRIX_ROWS; r++) {
429         matrix_row = matrix_get_row(r);
430         matrix_change = matrix_row ^ matrix_prev[r];
431         if (matrix_change) {
432             // TODO: print once per scan
433             if (debug_matrix) matrix_print();
434
435             for (int c = 0; c < MATRIX_COLS; c++) {
436                 if (matrix_change & (1<<c)) {
437                     process_key((keyevent_t){
438                         .key = (key_t){ .row = r, .col = c },
439                         .pressed = (matrix_row & (1<<c))
440                     });
441                     // record a processed key
442                     matrix_prev[r] ^= (1<<c);
443                     // process a key per task call
444                     goto MATRIX_LOOP_END;
445                 }
446             }
447         }
448     }
449     MATRIX_LOOP_END:
450     // TODO: FAIL SAFE: clear all key if no key down
451
452     // layer switch when delay term elapses
453     if (kbdstate == DELAYING || kbdstate == WAITING) {
454         if (timer_elapsed(delayed_fn.time) > LAYER_DELAY) {
455             if (kbdstate == DELAYING) {
456                 layer_switch_on(delayed_fn.code);
457                 NEXT(IDLE);
458             }
459             if (kbdstate == WAITING) {
460                 layer_switch_on(delayed_fn.code);
461                 NEXT(IDLE);
462                 uint8_t tmp_mods = keyboard_report->mods;
463                 host_set_mods(waiting_key.mods);
464                 process_key(waiting_key.event);
465                 host_set_mods(tmp_mods);
466             }
467         }
468     }
469
470     // mousekey repeat & acceleration
471     mousekey_task();
472
473     return;
474 }
475
476 void keyboard_set_leds(uint8_t leds)
477 {
478     led_set(leds);
479 }