X-Git-Url: https://git.friedersdorff.com/?a=blobdiff_plain;f=common%2Fkeyboard.c;h=fa22116f177175670e7dc64f76d77e15e9b8710c;hb=878daae9c337e712d5ec65232851dd5e58aca0b9;hp=6adad88824fd7bf4faed6e035ebfee1d11a1b555;hpb=373ab0e7192811944786c095facb80938c33f1d5;p=max%2Ftmk_keyboard.git diff --git a/common/keyboard.c b/common/keyboard.c index 6adad888..fa22116f 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -1,5 +1,5 @@ /* -Copyright 2011 Jun Wako +Copyright 2011,2012 Jun Wako This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,14 +25,16 @@ along with this program. If not, see . #include "debug.h" #include "command.h" #include "util.h" +#include "sendchar.h" #ifdef MOUSEKEY_ENABLE #include "mousekey.h" #endif -#ifdef EXTRAKEY_ENABLE -#include -#endif +#define Kdebug(s) do { if (debug_keyboard) debug(s); } while(0) +#define Kdebug_P(s) do { if (debug_keyboard) debug_P(s); } while(0) +#define Kdebug_hex(s) do { if (debug_keyboard) debug_hex(s); } while(0) + #define LAYER_DELAY 250 typedef enum keykind { @@ -46,8 +48,13 @@ typedef enum keykind { typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t; -uint8_t current_layer = 0; +#ifdef KEYMAP_DEFAULT_LAYER +uint8_t default_layer = KEYMAP_DEFAULT_LAYER; +uint8_t current_layer = KEYMAP_DEFAULT_LAYER; +#else uint8_t default_layer = 0; +uint8_t current_layer = 0; +#endif /* keyboard internal states */ static kbdstate_t kbdstate = IDLE; @@ -81,80 +88,96 @@ static inline keykind_t get_keykind(uint8_t code, bool pressed) return NONE; } -static void layer_switch_on(uint8_t code) +static void clear_keyboard(void) { - if (!IS_FN(code)) return; - fn_state_bits |= FN_BIT(code); - if (current_layer != keymap_fn_layer(FN_INDEX(code))) { - // clear all key execpt Mod key - host_clear_all_keys_but_mods(); - host_system_send(0); - host_consumer_send(0); - mousekey_clear(); - mousekey_send(); + host_clear_keys(); + host_clear_mods(); + host_send_keyboard_report(); - debug("Layer Switch(on): "); debug_hex(current_layer); - current_layer = keymap_fn_layer(FN_INDEX(code)); - debug(" -> "); debug_hex(current_layer); debug("\n"); - } + host_system_send(0); + host_consumer_send(0); + +#ifdef MOUSEKEY_ENABLE + mousekey_clear(); + mousekey_send(); +#endif } -static void layer_switch_off(uint8_t code) +static void clear_keyboard_but_mods(void) { - if (!IS_FN(code)) return; - fn_state_bits &= ~FN_BIT(code); - if (current_layer != keymap_fn_layer(biton(fn_state_bits))) { - // clear all key execpt Mod key - host_clear_all_keys_but_mods(); - host_system_send(0); - host_consumer_send(0); - mousekey_clear(); - mousekey_send(); + host_clear_keys(); + host_send_keyboard_report(); - debug("Layer Switch(off): "); debug_hex(current_layer); - current_layer = keymap_fn_layer(biton(fn_state_bits)); - debug(" -> "); debug_hex(current_layer); debug("\n"); - } + host_system_send(0); + host_consumer_send(0); + +#ifdef MOUSEKEY_ENABLE + mousekey_clear(); + mousekey_send(); +#endif } -static inline uint8_t get_keycode(key_t key) +static bool anykey_sent_to_host(void) { - return keymap_get_keycode(current_layer, key.row, key.col); + return (host_has_anykey() || host_mouse_in_use() || + host_last_sysytem_report() || host_last_consumer_report()); } -// whether any key except modifier is down or not -static inline bool is_anykey_down(void) +static void layer_switch_on(uint8_t code) { - for (int r = 0; r < MATRIX_ROWS; r++) { - matrix_row_t matrix_row = matrix_get_row(r); - for (int c = 0; c < MATRIX_COLS; c++) { - if (matrix_row && (1< "); Kdebug_hex(new_layer); Kdebug("\n"); + + clear_keyboard_but_mods(); + current_layer = new_layer; + } +} + +static bool layer_switch_off(uint8_t code) +{ + if (!IS_FN(code)) return false; + fn_state_bits &= ~FN_BIT(code); + uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer); + if (current_layer != new_layer) { + Kdebug("Layer Switch(off): "); Kdebug_hex(current_layer); + Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n"); + + clear_keyboard_but_mods(); + current_layer = new_layer; + return true; } return false; } static void register_code(uint8_t code) { -debug("register_code\n"); if IS_KEY(code) { - host_add_key(code); - host_send_keyboard_report(); + if (!command_proc(code)) { + host_add_key(code); + host_send_keyboard_report(); + } } else if IS_MOD(code) { host_add_mod_bit(MOD_BIT(code)); host_send_keyboard_report(); } + else if IS_FN(code) { + if (!command_proc(keymap_fn_keycode(FN_INDEX(code)))) { + host_add_key(keymap_fn_keycode(FN_INDEX(code))); + host_send_keyboard_report(); + } + } else if IS_MOUSEKEY(code) { +#ifdef MOUSEKEY_ENABLE mousekey_on(code); mousekey_send(); +#endif } else if IS_CONSUMER(code) { -debug("consumer\n"); uint16_t usage = 0; switch (code) { case KC_AUDIO_MUTE: @@ -212,7 +235,6 @@ debug("consumer\n"); usage = AC_BOOKMARKS; break; } -debug("usage: "); phex16(usage); debug("\n"); host_consumer_send(usage); } else if IS_SYSTEM(code) { @@ -243,9 +265,15 @@ static void unregister_code(uint8_t code) host_del_mod_bit(MOD_BIT(code)); host_send_keyboard_report(); } + else if IS_FN(code) { + host_del_key(keymap_fn_keycode(FN_INDEX(code))); + host_send_keyboard_report(); + } else if IS_MOUSEKEY(code) { +#ifdef MOUSEKEY_ENABLE mousekey_off(code); mousekey_send(); +#endif } else if IS_CONSUMER(code) { host_consumer_send(0x0000); @@ -257,24 +285,31 @@ static void unregister_code(uint8_t code) /* * - * Event/State|IDLE DELAYING[f] WAITING[f,k] PRESSING + * Event/State|IDLE PRESSING DELAYING[f] WAITING[f,k] * -----------+------------------------------------------------------------------ - * Fn Down |IDLE(L+) WAITING(Sk) WAITING(Sk) - - * Up |IDLE(L-) IDLE(L-) IDLE(L-) IDLE(L-) - * Fnk Down |DELAYING(Sf) WAITING(Sk) WAINTING(Sk) PRESSING(Rf) - * Up |IDLE(L-) IDLE(Rf,Uf) IDLE(Rf,Ps,Uf)*3 PRESSING(Uf) - * Key Down |PRESSING(Rk) WAITING(Sk) WAITING(Sk) PRESSING(Rk) - * Up |IDLE(Uk) DELAYING(Uk) IDLE(L+,Ps,Uk) IDLE(Uk)*4 - * Delay |- IDLE(L+) IDLE(L+,Ps) - + * Fn Down |(L+) -*1 WAITING(Sk) IDLE(Rf,Ps)*7 + * Up |(L-) IDLE(L-)*8 IDLE(L-)*8 IDLE(L-)*8 + * Fnk Down |DELAYING(Sf)* (Rf) WAITING(Sk) IDLE(Rf,Ps,Rf) + * Up |(L-) IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3 + * Key Down |PRESSING(Rk) (Rk) WAITING(Sk) IDLE(Rf,Ps,Rk) + * Up |(Uk) IDLE(Uk)*4 (Uk) IDLE(L+,Ps,Pk)/(Uk)*a * | - * No key Down|IDLE(Ld) IDLE(Ld) IDLE(Ld) IDLE(Ld) + * Delay |- - IDLE(L+) IDLE(L+,Ps) + * Magic Key |COMMAND*5 * + * *1: ignore Fn if other key is down. * *2: register Fnk if any key is pressing - * *3: when Fnk == Stored Fnk, if not ignore. - * *4: when no registered key any more + * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8 + * *4: if no keys registered to host + * *5: unregister all keys + * *6: only if no keys down + * *7: ignore Fn because Fnk key and stored key are down. + * *8: move to IDLE if layer switch(off) occurs, else stay at current state + * *9: repeat key if pressing Fnk twice quickly(move to PRESSING) + * *a: layer switch and process waiting key and code if code == wainting key, else unregister key * * States: - * IDLE: + * IDLE: No key is down except modifiers * DELAYING: delay layer switch after pressing Fn with alt keycode * WAITING: key is pressed during DELAYING * @@ -282,45 +317,42 @@ static void unregister_code(uint8_t code) * Fn: Fn key without alternative keycode * Fnk: Fn key with alternative keycode * -: ignore + * Delay: layer switch delay term is elapsed * * Actions: * Rk: register key * Uk: unregister key - * Rf: register stored Fn(alt keycode) - * Uf: unregister stored Fn(alt keycode) + * Rf: register Fn(alt keycode) + * Uf: unregister Fn(alt keycode) * Rs: register stored key * Us: unregister stored key - * Sk: store key - * Sf: store Fn - * Ps: play stored key(Interpret stored key and transit state) - * L+: Switch to new layer(*retain* Modifiers only) - * L-: Switch back to last layer(*clear* stored key/Fn, *unregister* all Modifier/key) - * Ld: Switch back to default layer(*clear* stored key/Fn, *unregister* all Modifier/key) + * Sk: Store key(waiting Key) + * Sf: Store Fn(delayed Fn) + * Ps: Process stored key + * Ps: Process key + * Is: Interpret stored keys in current layer + * L+: Switch to new layer(*unregister* all keys but modifiers) + * L-: Switch back to last layer(*unregister* all keys but modifiers) + * Ld: Switch back to default layer(*unregister* all keys but modifiers) */ #define NEXT(state) do { \ - debug("NEXT: "); print_P(state_str(kbdstate)); \ + Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \ kbdstate = state; \ - debug(" -> "); print_P(state_str(kbdstate)); debug("\n"); \ + Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \ } while (0) static inline void process_key(keyevent_t event) { - /* TODO: ring buffer - static keyrecord_t waiting_keys[5]; - static uint8_t waiting_keys_head = 0; - static uint8_t waiting_keys_tail = 0; - */ - - uint8_t code = get_keycode(event.key); + uint8_t code = keymap_get_keycode(current_layer, event.key.row, event.key.col); keykind_t kind = get_keykind(code, event.pressed); uint8_t tmp_mods; - debug("state: "); print_P(state_str(kbdstate)); - debug(" kind: "); debug_hex(kind); - debug(" code: "); debug_hex(code); - if (event.pressed) { debug("d"); } else { debug("u"); } - debug("\n"); + Kdebug("state: "); Kdebug_P(state_str(kbdstate)); + Kdebug(" kind: "); Kdebug_hex(kind); + Kdebug(" code: "); Kdebug_hex(code); + if (event.pressed) { Kdebug("d"); } else { Kdebug("u"); } + Kdebug("\n"); switch (kbdstate) { case IDLE: @@ -335,7 +367,7 @@ static inline void process_key(keyevent_t event) // repeat Fn alt key when press Fn key down, up then down again quickly if (KEYEQ(delayed_fn.event.key, event.key) && timer_elapsed(delayed_fn.time) < LAYER_DELAY) { - register_code(keymap_fn_keycode(FN_INDEX(code))); + register_code(code); NEXT(PRESSING); } else { delayed_fn = (keyrecord_t) { @@ -371,16 +403,20 @@ static inline void process_key(keyevent_t event) // ignored when any key is pressed break; case FN_UP: - layer_switch_off(code); - NEXT(IDLE); + if (layer_switch_off(code)) + NEXT(IDLE); break; case FNK_DOWN: - register_code(keymap_fn_keycode(FN_INDEX(code))); + register_code(code); break; case FNK_UP: - // can't know whether layer switched or not - layer_switch_off(code); - unregister_code(keymap_fn_keycode(FN_INDEX(code))); + if (layer_switch_off(code)) { + NEXT(IDLE); + } else { + unregister_code(code); + if (!anykey_sent_to_host()) + NEXT(IDLE); + } break; case KEY_DOWN: case MOD_DOWN: @@ -389,8 +425,7 @@ static inline void process_key(keyevent_t event) case KEY_UP: case MOD_UP: unregister_code(code); - // no key registered? mousekey, mediakey, systemkey - if (!host_has_anykey()) + if (!anykey_sent_to_host()) NEXT(IDLE); break; default: @@ -414,8 +449,8 @@ static inline void process_key(keyevent_t event) register_code(code); break; case FN_UP: - layer_switch_off(code); - NEXT(IDLE); + if (layer_switch_off(code)) + NEXT(IDLE); break; case FNK_UP: if (code == delayed_fn.code) { @@ -423,19 +458,16 @@ static inline void process_key(keyevent_t event) // restore the mod status at the time of pressing Fn key tmp_mods = keyboard_report->mods; host_set_mods(delayed_fn.mods); - register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); - unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); + register_code(delayed_fn.code); + unregister_code(delayed_fn.code); host_set_mods(tmp_mods); NEXT(IDLE); } else { - layer_switch_off(code); - NEXT(IDLE); + if (layer_switch_off(code)) + NEXT(IDLE); } break; case KEY_UP: - unregister_code(code); - NEXT(IDLE); - break; case MOD_UP: unregister_code(code); break; @@ -450,34 +482,40 @@ static inline void process_key(keyevent_t event) case KEY_DOWN: tmp_mods = keyboard_report->mods; host_set_mods(delayed_fn.mods); - register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); + register_code(delayed_fn.code); host_set_mods(waiting_key.mods); register_code(waiting_key.code); host_set_mods(tmp_mods); - register_code(code); + if (kind == FN_DOWN) { + // ignore Fn + } else if (kind == FNK_DOWN) { + register_code(code); + } else if (kind == KEY_DOWN) { + register_code(code); + } NEXT(IDLE); break; case MOD_DOWN: register_code(code); break; case FN_UP: - layer_switch_off(code); - NEXT(IDLE); + if (layer_switch_off(code)) + NEXT(IDLE); break; case FNK_UP: if (code == delayed_fn.code) { // alt down, key down, alt up tmp_mods = keyboard_report->mods; host_set_mods(delayed_fn.mods); - register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); + register_code(delayed_fn.code); host_set_mods(waiting_key.mods); register_code(waiting_key.code); - unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); + unregister_code(delayed_fn.code); host_set_mods(tmp_mods); NEXT(IDLE); } else { - layer_switch_off(code); - NEXT(IDLE); + if (layer_switch_off(code)) + NEXT(IDLE); } break; case KEY_UP: @@ -502,13 +540,14 @@ static inline void process_key(keyevent_t event) } break; } - - // TODO: FAIL SAFE: unregister all keys when no key down } void keyboard_init(void) { - debug_keyboard = true; + // TODO: to enable debug print magic key bind on boot time + + // TODO: configuration of sendchar impl + print_sendchar_func = sendchar; timer_init(); matrix_init(); @@ -520,17 +559,11 @@ void keyboard_init(void) void keyboard_task(void) { static matrix_row_t matrix_prev[MATRIX_ROWS]; + static uint8_t led_status = 0; matrix_row_t matrix_row = 0; matrix_row_t matrix_change = 0; matrix_scan(); - if (command_proc()) { - debug("COMMAND\n"); - // TODO: clear all keys - host_clear_keyboard_report(); - host_send_keyboard_report(); - return; - } for (int r = 0; r < MATRIX_ROWS; r++) { matrix_row = matrix_get_row(r); matrix_change = matrix_row ^ matrix_prev[r]; @@ -552,7 +585,6 @@ void keyboard_task(void) } } MATRIX_LOOP_END: - // TODO: FAIL SAFE: clear all key if no key down // layer switch when delay term elapses if (kbdstate == DELAYING || kbdstate == WAITING) { @@ -572,8 +604,29 @@ void keyboard_task(void) } } +#ifdef MOUSEKEY_ENABLE // mousekey repeat & acceleration mousekey_task(); +#endif + + // FAIL SAFE: clear all key if no key down + if (matrix_change) { + matrix_row_t is_matrix_on = 0; + for (int r = 0; r < MATRIX_ROWS; r++) { + is_matrix_on |= matrix_get_row(r); + } + if (!is_matrix_on) { + Kdebug("FAIL SAFE: clear all keys(default layer).\n"); + clear_keyboard(); + current_layer = default_layer; + } + } + + // update LED + if (led_status != host_keyboard_leds()) { + led_status = host_keyboard_leds(); + keyboard_set_leds(led_status); + } return; }