summaryrefslogtreecommitdiff
path: root/common/action.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/action.c')
-rw-r--r--common/action.c222
1 files changed, 74 insertions, 148 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