From f609712da3b94ea36612a6f210bd6ce902b74631 Mon Sep 17 00:00:00 2001 From: tmk Date: Tue, 15 Jan 2013 00:06:52 +0900 Subject: [PATCH] Fix waiting_keys and periodical update for delaying layer. --- common/action.c | 222 ++++++++++++++--------------------------- common/keyboard.c | 9 +- common/keyboard.h | 9 +- keyboard/hhkb/keymap.c | 1 - 4 files changed, 90 insertions(+), 151 deletions(-) diff --git a/common/action.c b/common/action.c index 1a86f16d31..389fc5df1b 100644 --- a/common/action.c +++ b/common/action.c @@ -9,103 +9,20 @@ #include "debug.h" #include "action.h" -#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) -/* - * - * Event/State|IDLE PRESSING DELAYING[f] WAITING[f,k] - * -----------+------------------------------------------------------------------ - * 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 - * | - * 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: 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: No key is down except modifiers - * DELAYING: delay layer switch after pressing Fn with alt keycode - * WAITING: key is pressed during DELAYING - * - * Events: - * 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 Fn(alt keycode) - * Uf: unregister Fn(alt keycode) - * Rs: register stored key - * Us: unregister stored 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) - */ - - -typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t; -#define NEXT(state) do { \ - Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \ - kbdstate = state; \ - Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \ -} while (0) - - -static kbdstate_t kbdstate = IDLE; -static uint8_t fn_state_bits = 0; - -static const char *state_str(kbdstate_t state) -{ - if (state == IDLE) return PSTR("IDLE"); - if (state == DELAYING) return PSTR("DELAYING"); - if (state == WAITING) return PSTR("WAITING"); - if (state == PRESSING) return PSTR("PRESSING"); - return PSTR("UNKNOWN"); -} -static bool anykey_sent_to_host(void) -{ - return (host_has_anykey() || host_mouse_in_use() || - host_last_sysytem_report() || host_last_consumer_report()); -} - +static void process(keyevent_t event, action_t action); static void register_code(uint8_t code); static void unregister_code(uint8_t code); -static void register_mods(uint8_t mods); -static void unregister_mods(uint8_t mods); static void clear_keyboard(void); static void clear_keyboard_but_mods(void); +static bool sending_anykey(void); static void layer_switch(uint8_t new_layer); /* tap */ #define TAP_TIME 200 -#define LAYER_DELAY 200 static keyevent_t last_event = {}; static uint16_t last_event_time = 0; static uint8_t tap_count = 0; @@ -115,31 +32,54 @@ uint8_t default_layer = 0; uint8_t current_layer = 0; keyrecord_t delaying_layer = {}; -keyrecord_t waiting_key = {}; - -// TODO: ring buffer: waiting_keys[] -/* #define WAITING_KEYS_BUFFER 3 static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {}; static uint8_t waiting_keys_head = 0; -static uint8_t waiting_keys_tail = 0; -static void waiting_key_queue(keyevent_t event) +static bool waiting_keys_enqueue(keyevent_t event, action_t action) { + debug("waiting_keys["); debug_dec(waiting_keys_head); debug("] = "); + debug_hex16(action.code); debug("\n"); + if (waiting_keys_head < WAITING_KEYS_BUFFER) { + waiting_keys[waiting_keys_head++] = (keyrecord_t){ .event = event, + .action = action, + .mods = host_get_mods() }; + } else { + return true; + } } -static void waiting_key_dequeue(keyevent_t event) +static void waiting_keys_clear(void) { + waiting_keys_head = 0; } -*/ +static bool waiting_keys_has(keypos_t key) +{ + for (uint8_t i = 0; i < waiting_keys_head; i++) { + if KEYEQ(key, waiting_keys[i].event.key) return true; + } + return false; +} +static void waiting_keys_process_in_current_layer(void) +{ + // TODO: in case of including layer key in waiting keys + uint8_t tmp_mods = host_get_mods(); + for (uint8_t i = 0; i < waiting_keys_head; i++) { + /* revive status of mods */ + host_set_mods(waiting_keys[i].mods); + process(waiting_keys[i].event, keymap_get_action(current_layer, + waiting_keys[i].event.key.row, + waiting_keys[i].event.key.col)); + debug("waiting_keys_process_in_current_layer["); debug_dec(i); debug("]\n"); + } + host_set_mods(tmp_mods); + waiting_keys_clear(); +} + static void process(keyevent_t event, action_t action) { //action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); - debug("action: "); debug_hex16(action.code); debug("\n"); - debug("kind.id: "); debug_hex(action.kind.id); debug("\n"); - debug("kind.param: "); debug_hex16(action.kind.param); debug("\n"); - debug("key.code: "); debug_hex(action.key.code); debug("\n"); - debug("key.mods: "); debug_hex(action.key.mods); debug("\n"); + switch (action.kind.id) { /* Key and Mods */ @@ -244,12 +184,12 @@ static void process(keyevent_t event, action_t action) break; default: // with tap key - debug("tap: "); debug_hex(tap_count); debug("\n"); if (event.pressed) { if (tap_count == 0) { if (host_has_anykey()) { register_code(action.layer.code); } else { + debug("Delay switching layer("); debug_hex8(action.layer.opt); debug(")\n"); delaying_layer = (keyrecord_t){ .event = event, .action = action, @@ -257,12 +197,13 @@ static void process(keyevent_t event, action_t action) }; } } else if (tap_count > 0) { + debug("tap: "); debug_hex(tap_count); debug("\n"); register_code(action.layer.code); } } else { // tap key if (KEYEQ(event.key, delaying_layer.event.key) && - timer_elapsed(delaying_layer.event.time) < TAP_TIME) { + timer_elapsed(delaying_layer.event.time) <= TAP_TIME) { uint8_t tmp_mods = host_get_mods(); host_set_mods(delaying_layer.mods); register_code(delaying_layer.action.layer.code); @@ -321,7 +262,6 @@ static void process(keyevent_t event, action_t action) break; default: // with tap key - debug("tap: "); debug_hex(tap_count); debug("\n"); if (event.pressed) { if (tap_count == 0) { if (host_has_anykey()) { @@ -334,6 +274,7 @@ static void process(keyevent_t event, action_t action) }; } } else if (tap_count > 0) { + debug("tap: "); debug_hex(tap_count); debug("\n"); register_code(action.layer.code); } } else { @@ -409,18 +350,16 @@ static void process(keyevent_t event, action_t action) void action_exec(keyevent_t event) { - /* count tap when key is up */ - if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event_time) < TAP_TIME) { - if (!event.pressed) tap_count++; - } else { - tap_count = 0; - } +/* + debug("key["); debug_hex8(event.key.row); debug(":"); debug_hex8(event.key.col); + if (event.pressed) debug("]down\n"); else debug("]up\n"); +*/ /* When delaying layer switch */ if (delaying_layer.action.code) { - /* Layer switch when delay time elapses or waiting key is released */ - if ((timer_elapsed(delaying_layer.event.time) > LAYER_DELAY) || - (!event.pressed && KEYEQ(event.key, waiting_key.event.key))) { + /* Layer switch when tap time elapses or waiting key is released */ + if ((timer_elapsed(delaying_layer.event.time) > TAP_TIME) || + (!event.pressed && waiting_keys_has(event.key))) { /* layer switch */ switch (delaying_layer.action.kind.id) { case ACT_LAYER_PRESSED: @@ -433,15 +372,7 @@ void action_exec(keyevent_t event) delaying_layer = (keyrecord_t){}; /* Process waiting keys in new layer */ - if (waiting_key.event.time) { - uint8_t tmp_mods = host_get_mods(); - host_set_mods(waiting_key.mods); - process(waiting_key.event, keymap_get_action(current_layer, - waiting_key.event.key.row, - waiting_key.event.key.col)); - host_set_mods(tmp_mods); - waiting_key = (keyrecord_t){}; - } + waiting_keys_process_in_current_layer(); } /* when delaying layer key is released within delay term */ else if (!event.pressed && KEYEQ(event.key, delaying_layer.event.key)) { @@ -450,28 +381,32 @@ void action_exec(keyevent_t event) host_set_mods(delaying_layer.mods); register_code(delaying_layer.action.layer.code); delaying_layer = (keyrecord_t){}; + host_set_mods(tmp_mods); /* process waiting keys */ - if (waiting_key.event.time) { - host_set_mods(waiting_key.mods); - process(waiting_key.event, waiting_key.action); - waiting_key = (keyrecord_t){}; - } - host_set_mods(tmp_mods); + waiting_keys_process_in_current_layer(); } } + // not real event. event just to update delaying layer. + if (IS_NOEVENT(event)) { + return; + } + + /* count tap when key is up */ + if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) { + if (!event.pressed) tap_count++; + } else { + tap_count = 0; + } + action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); + // TODO: all key events(pressed, released) should be recorded? /* postpone key-down events while delaying layer */ if (delaying_layer.action.code) { if (event.pressed) { - // TODO: waiting_keys[] - waiting_key = (keyrecord_t){ - .event = event, - .action = action, - .mods = host_get_mods() - }; + waiting_keys_enqueue(event, action); } else { process(event, action); } @@ -481,7 +416,6 @@ void action_exec(keyevent_t event) /* last event */ last_event = event; - last_event_time = timer_read(); } @@ -515,20 +449,6 @@ static void unregister_code(uint8_t code) } } -static void register_mods(uint8_t mods) -{ - if (!mods) return; - host_add_mods(mods); - host_send_keyboard_report(); -} - -static void unregister_mods(uint8_t mods) -{ - if (!mods) return; - host_del_mods(mods); - host_send_keyboard_report(); -} - static void clear_keyboard(void) { host_clear_mods(); @@ -549,11 +469,17 @@ static void clear_keyboard_but_mods(void) #endif } +static bool sending_anykey(void) +{ + return (host_has_anykey() || host_mouse_in_use() || + host_last_sysytem_report() || host_last_consumer_report()); +} + static void layer_switch(uint8_t new_layer) { if (current_layer != new_layer) { - Kdebug("Layer Switch: "); Kdebug_hex(current_layer); - Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n"); + debug("Layer Switch: "); debug_hex(current_layer); + debug(" -> "); debug_hex(new_layer); debug("\n"); current_layer = new_layer; clear_keyboard_but_mods(); // To avoid stuck keys diff --git a/common/keyboard.c b/common/keyboard.c index 4e955e129b..2e32e91e08 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -78,7 +78,14 @@ void keyboard_task(void) } } } - MATRIX_LOOP_END: + // call to update delaying layer when no real event + action_exec((keyevent_t) { + .key = (keypos_t){ .row = 255, .col = 255 }, // assume this key doesn't exist + .pressed = false, + .time = 0, + }); + +MATRIX_LOOP_END: #ifdef MOUSEKEY_ENABLE // mousekey repeat & acceleration diff --git a/common/keyboard.h b/common/keyboard.h index 1166536617..cf85b12336 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -37,7 +37,14 @@ typedef struct { uint16_t time; } keyevent_t; -#define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col) +#define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col) +#define IS_NOEVENT(event) (event.time == 0) +#define NOEVENT (keyevent_t) { \ + .key = (keypos_t){ .row = 255, .col = 255 }, \ + .pressed = false, \ + .time = 0, \ +} + extern uint8_t current_layer; extern uint8_t default_layer; diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index 9fe1237aa4..38461290b3 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -224,6 +224,5 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { action.code = ACTION_NO; break; } - debug("action: "); debug_hex16(action.code); debug("\n"); return action; }