diff options
| -rw-r--r-- | common/action.c | 168 | ||||
| -rw-r--r-- | common/keyboard.h | 1 |
2 files changed, 102 insertions, 67 deletions
diff --git a/common/action.c b/common/action.c index 7299a874a..d5040479e 100644 --- a/common/action.c +++ b/common/action.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "action.h" | 10 | #include "action.h" |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | static void process(keyevent_t event, action_t action); | 13 | static void process(keyevent_t event); |
| 14 | static void register_code(uint8_t code); | 14 | static void register_code(uint8_t code); |
| 15 | static void unregister_code(uint8_t code); | 15 | static void unregister_code(uint8_t code); |
| 16 | static void add_mods(uint8_t mods); | 16 | static void add_mods(uint8_t mods); |
| @@ -30,19 +30,26 @@ static uint8_t tap_count = 0; | |||
| 30 | /* layer */ | 30 | /* layer */ |
| 31 | uint8_t default_layer = 0; | 31 | uint8_t default_layer = 0; |
| 32 | uint8_t current_layer = 0; | 32 | uint8_t current_layer = 0; |
| 33 | keyrecord_t delaying_layer = {}; | 33 | static keyrecord_t tapping_key = {}; |
| 34 | // time 0 means no event. | ||
| 35 | #define IS_TAPPING (tapping_key.event.time != 0) | ||
| 36 | /* TODO: | ||
| 37 | #define IS_TAPPING_KEY(key) (tapping_key.event.time != 0 && KEYEQ(tapping_key.event.key, key)) | ||
| 38 | */ | ||
| 34 | 39 | ||
| 35 | /* waiting keys buffer */ | 40 | /* waiting keys buffer */ |
| 36 | #define WAITING_KEYS_BUFFER 3 | 41 | #define WAITING_KEYS_BUFFER 3 |
| 37 | static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {}; | 42 | static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {}; |
| 43 | // TODO: double buffer? | ||
| 44 | static keyrecord_t waiting_keys0[WAITING_KEYS_BUFFER] = {}; | ||
| 45 | static keyrecord_t waiting_keys1[WAITING_KEYS_BUFFER] = {}; | ||
| 38 | static uint8_t waiting_keys_head = 0; | 46 | static uint8_t waiting_keys_head = 0; |
| 39 | static bool waiting_keys_enqueue(keyevent_t event, action_t action) | 47 | static bool waiting_keys_enqueue(keyevent_t event) |
| 40 | { | 48 | { |
| 41 | debug("waiting_keys["); debug_dec(waiting_keys_head); debug("] = "); | 49 | debug("waiting_keys["); debug_dec(waiting_keys_head); debug("] = "); |
| 42 | debug_hex16(action.code); debug("\n"); | 50 | debug_hex8(event.key.row); debug_hex8(event.key.col); debug("\n"); // TODO event.key.raw |
| 43 | if (waiting_keys_head < WAITING_KEYS_BUFFER) { | 51 | if (waiting_keys_head < WAITING_KEYS_BUFFER) { |
| 44 | waiting_keys[waiting_keys_head++] = (keyrecord_t){ .event = event, | 52 | waiting_keys[waiting_keys_head++] = (keyrecord_t){ .event = event, |
| 45 | .action = action, | ||
| 46 | .mods = host_get_mods() }; | 53 | .mods = host_get_mods() }; |
| 47 | } else { | 54 | } else { |
| 48 | return true; | 55 | return true; |
| @@ -62,80 +69,64 @@ static bool waiting_keys_has(keypos_t key) | |||
| 62 | static void waiting_keys_process_in_current_layer(void) | 69 | static void waiting_keys_process_in_current_layer(void) |
| 63 | { | 70 | { |
| 64 | // TODO: in case of including layer key in waiting keys | 71 | // TODO: in case of including layer key in waiting keys |
| 65 | uint8_t tmp_mods = host_get_mods(); | ||
| 66 | for (uint8_t i = 0; i < waiting_keys_head; i++) { | 72 | for (uint8_t i = 0; i < waiting_keys_head; i++) { |
| 67 | /* revive status of mods */ | ||
| 68 | host_set_mods(waiting_keys[i].mods); | ||
| 69 | process(waiting_keys[i].event, keymap_get_action(current_layer, | ||
| 70 | waiting_keys[i].event.key.row, | ||
| 71 | waiting_keys[i].event.key.col)); | ||
| 72 | debug("waiting_keys_process_in_current_layer["); debug_dec(i); debug("]\n"); | 73 | debug("waiting_keys_process_in_current_layer["); debug_dec(i); debug("]\n"); |
| 74 | // TODO: no need action in waiting_keys? should get_action() in process()? | ||
| 75 | process(waiting_keys[i].event); | ||
| 73 | } | 76 | } |
| 74 | host_set_mods(tmp_mods); | ||
| 75 | waiting_keys_clear(); | 77 | waiting_keys_clear(); |
| 76 | } | 78 | } |
| 77 | 79 | ||
| 78 | 80 | ||
| 79 | void action_exec(keyevent_t event) | 81 | void action_exec(keyevent_t event) |
| 80 | { | 82 | { |
| 81 | /* When delaying layer switch */ | 83 | if (IS_TAPPING) { |
| 82 | if (delaying_layer.action.code) { | 84 | /* when tap time elapses or waiting key is released */ |
| 83 | /* Layer switch when tap time elapses or waiting key is released */ | 85 | if ((timer_elapsed(tapping_key.event.time) > TAP_TIME) || |
| 84 | if ((timer_elapsed(delaying_layer.event.time) > TAP_TIME) || | ||
| 85 | (!event.pressed && waiting_keys_has(event.key))) { | 86 | (!event.pressed && waiting_keys_has(event.key))) { |
| 86 | /* layer switch */ | 87 | |
| 87 | switch (delaying_layer.action.kind.id) { | 88 | // TODO process tapping_key: layer swich, modifier, ... |
| 88 | case ACT_LAYER_PRESSED: | 89 | // action is needed? |
| 89 | layer_switch(delaying_layer.action.layer.opt); | 90 | debug("notap: process tapping_key.\n"); |
| 90 | break; | 91 | process(tapping_key.event); |
| 91 | case ACT_LAYER_BIT: | ||
| 92 | layer_switch(current_layer | delaying_layer.action.layer.opt); | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | delaying_layer = (keyrecord_t){}; | ||
| 96 | 92 | ||
| 97 | /* Process waiting keys in new layer */ | 93 | /* Process waiting keys in new layer */ |
| 98 | waiting_keys_process_in_current_layer(); | 94 | waiting_keys_process_in_current_layer(); |
| 99 | } | 95 | } |
| 100 | /* when delaying layer key is released within delay term */ | 96 | /* when tapping key is released within tap time */ |
| 101 | else if (!event.pressed && KEYEQ(event.key, delaying_layer.event.key)) { | 97 | else if (!event.pressed && KEYEQ(event.key, tapping_key.event.key)) { |
| 102 | /* tap key down */ | 98 | /* tap key down */ |
| 103 | debug("tap[delaying_layer](register): fist\n"); | 99 | debug("tap("); debug_hex8(tap_count); debug(")[tapping_key](register): "); debug_hex8(tapping_key.action.layer.code); debug("\n"); |
| 104 | uint8_t tmp_mods = host_get_mods(); | 100 | register_code(tapping_key.action.layer.code); |
| 105 | host_set_mods(delaying_layer.mods); | 101 | tapping_key = (keyrecord_t){}; |
| 106 | register_code(delaying_layer.action.layer.code); | ||
| 107 | delaying_layer = (keyrecord_t){}; | ||
| 108 | host_set_mods(tmp_mods); | ||
| 109 | 102 | ||
| 110 | /* process waiting keys */ | 103 | /* process waiting keys */ |
| 111 | waiting_keys_process_in_current_layer(); | 104 | waiting_keys_process_in_current_layer(); |
| 112 | } | 105 | } |
| 113 | } | 106 | } |
| 114 | 107 | ||
| 115 | // not real event. event just to update delaying layer. | 108 | // not real event. event just to handle time out of tapping key. |
| 116 | if (IS_NOEVENT(event)) { | 109 | if (IS_NOEVENT(event)) { |
| 117 | return; | 110 | return; |
| 118 | } | 111 | } |
| 119 | 112 | ||
| 120 | /* count tap when key is up */ | 113 | /* count up tap when key is up */ |
| 114 | // key: d u d u d | ||
| 115 | // tap: 0 1 1 2 2 | ||
| 116 | // key: u d u d u | ||
| 117 | // tap: 0 0 1 1 2 | ||
| 121 | if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) { | 118 | if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) { |
| 122 | if (!event.pressed) tap_count++; | 119 | if (!event.pressed) tap_count++; |
| 123 | } else { | 120 | } else { |
| 124 | tap_count = 0; | 121 | tap_count = 0; |
| 125 | } | 122 | } |
| 126 | 123 | ||
| 127 | action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); | 124 | /* store key events while tapping */ |
| 128 | 125 | if (IS_TAPPING) { | |
| 129 | // TODO: all key events(pressed, released) should be recorded? | 126 | // TODO: action is needed? |
| 130 | /* postpone key-down events while delaying layer */ | 127 | waiting_keys_enqueue(event); |
| 131 | if (delaying_layer.action.code) { | ||
| 132 | if (event.pressed) { | ||
| 133 | waiting_keys_enqueue(event, action); | ||
| 134 | } else { | ||
| 135 | process(event, action); | ||
| 136 | } | ||
| 137 | } else { | 128 | } else { |
| 138 | process(event, action); | 129 | process(event); |
| 139 | } | 130 | } |
| 140 | 131 | ||
| 141 | /* last event */ | 132 | /* last event */ |
| @@ -143,9 +134,9 @@ void action_exec(keyevent_t event) | |||
| 143 | } | 134 | } |
| 144 | 135 | ||
| 145 | 136 | ||
| 146 | static void process(keyevent_t event, action_t action) | 137 | static void process(keyevent_t event) |
| 147 | { | 138 | { |
| 148 | //action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); | 139 | action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); |
| 149 | debug("action: "); debug_hex16(action.code); | 140 | debug("action: "); debug_hex16(action.code); |
| 150 | if (event.pressed) debug("[down]\n"); else debug("[up]\n"); | 141 | if (event.pressed) debug("[down]\n"); else debug("[up]\n"); |
| 151 | 142 | ||
| @@ -204,21 +195,39 @@ static void process(keyevent_t event, action_t action) | |||
| 204 | case ACT_LMODS_TAP: | 195 | case ACT_LMODS_TAP: |
| 205 | if (event.pressed) { | 196 | if (event.pressed) { |
| 206 | if (tap_count == 0) { | 197 | if (tap_count == 0) { |
| 207 | add_mods(action.key.mods); | 198 | if (host_has_anykey()) { |
| 199 | // This key is a modifier essentially. | ||
| 200 | // Prioritize mods when key jam or rollover | ||
| 201 | add_mods(action.key.mods); | ||
| 202 | } else { | ||
| 203 | if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { | ||
| 204 | // no tapping | ||
| 205 | add_mods(action.key.mods); | ||
| 206 | tapping_key = (keyrecord_t){}; | ||
| 207 | } else { | ||
| 208 | debug("tapping lmods("); debug_hex8(action.key.mods); debug(")\n"); | ||
| 209 | tapping_key = (keyrecord_t){ | ||
| 210 | .event = event, | ||
| 211 | .action = action, | ||
| 212 | .mods = host_get_mods() | ||
| 213 | }; | ||
| 214 | } | ||
| 215 | } | ||
| 208 | } else { | 216 | } else { |
| 209 | debug("tap[lmods](register): "); debug_hex(tap_count); debug("\n"); | 217 | // pressed after tapping |
| 218 | debug("tap("); debug_hex(tap_count); debug(")[lmods](register): "); debug_hex8(action.key.code); debug("\n"); | ||
| 210 | register_code(action.key.code); | 219 | register_code(action.key.code); |
| 211 | } | 220 | } |
| 212 | } else { | 221 | } else { |
| 213 | if (tap_count == 0) { | 222 | if (tap_count == 0) { |
| 223 | debug("tap(00)[lmods](del_mods): "); debug_hex8(action.key.mods); debug("\n"); | ||
| 214 | del_mods(action.key.mods); | 224 | del_mods(action.key.mods); |
| 215 | } else if (tap_count == 1) { | 225 | } else if (tap_count == 1) { |
| 216 | debug("tap[lmods](register/unregister): "); debug_hex(tap_count); debug("\n"); | 226 | debug("tap(01)[lmods](del_mods/unregister): "); debug_hex8(action.key.mods); debug(" "); debug_hex8(action.key.code); debug("\n"); |
| 217 | del_mods(action.key.mods); | 227 | del_mods(action.key.mods); |
| 218 | register_code(action.key.code); | ||
| 219 | unregister_code(action.key.code); | 228 | unregister_code(action.key.code); |
| 220 | } else { | 229 | } else { |
| 221 | debug("tap[lmods](unregister): "); debug_hex(tap_count); debug("\n"); | 230 | debug("tap("); debug_hex(tap_count); debug(")[lmods](unregister): "); debug_hex8(action.key.code); debug("\n"); |
| 222 | unregister_code(action.key.code); | 231 | unregister_code(action.key.code); |
| 223 | } | 232 | } |
| 224 | } | 233 | } |
| @@ -226,21 +235,39 @@ static void process(keyevent_t event, action_t action) | |||
| 226 | case ACT_RMODS_TAP: | 235 | case ACT_RMODS_TAP: |
| 227 | if (event.pressed) { | 236 | if (event.pressed) { |
| 228 | if (tap_count == 0) { | 237 | if (tap_count == 0) { |
| 229 | add_mods(action.key.mods<<4); | 238 | if (host_has_anykey()) { |
| 239 | // This key is a modifier essentially. | ||
| 240 | // Prioritize mods when key jam or rollover | ||
| 241 | add_mods(action.key.mods<<4); | ||
| 242 | } else { | ||
| 243 | if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { | ||
| 244 | // no tapping | ||
| 245 | add_mods(action.key.mods<<4); | ||
| 246 | tapping_key = (keyrecord_t){}; | ||
| 247 | } else { | ||
| 248 | debug("tapping rmods("); debug_hex8(action.key.mods); debug(")\n"); | ||
| 249 | tapping_key = (keyrecord_t){ | ||
| 250 | .event = event, | ||
| 251 | .action = action, | ||
| 252 | .mods = host_get_mods() | ||
| 253 | }; | ||
| 254 | } | ||
| 255 | } | ||
| 230 | } else { | 256 | } else { |
| 231 | debug("tap[rmods](register): "); debug_hex(tap_count); debug("\n"); | 257 | // pressed after tapping |
| 258 | debug("tap("); debug_hex(tap_count); debug(")[rmods](register): "); debug_hex8(action.key.code); debug("\n"); | ||
| 232 | register_code(action.key.code); | 259 | register_code(action.key.code); |
| 233 | } | 260 | } |
| 234 | } else { | 261 | } else { |
| 235 | if (tap_count == 0) { | 262 | if (tap_count == 0) { |
| 263 | debug("tap(00)[rmods](del_mods): "); debug_hex8(action.key.mods); debug("\n"); | ||
| 236 | del_mods(action.key.mods<<4); | 264 | del_mods(action.key.mods<<4); |
| 237 | } else if (tap_count == 1) { | 265 | } else if (tap_count == 1) { |
| 238 | debug("tap[rmods](register/unregister): "); debug_hex(tap_count); debug("\n"); | 266 | debug("tap(01)[rmods](del_mods/unregister): "); debug_hex8(action.key.mods); debug(" "); debug_hex8(action.key.code); debug("\n"); |
| 239 | del_mods(action.key.mods<<4); | 267 | del_mods(action.key.mods<<4); |
| 240 | register_code(action.key.code); | ||
| 241 | unregister_code(action.key.code); | 268 | unregister_code(action.key.code); |
| 242 | } else { | 269 | } else { |
| 243 | debug("tap[rmods](unregister): "); debug_hex(tap_count); debug("\n"); | 270 | debug("tap("); debug_hex(tap_count); debug(")[rmods](unregister): "); debug_hex8(action.key.code); debug("\n"); |
| 244 | unregister_code(action.key.code); | 271 | unregister_code(action.key.code); |
| 245 | } | 272 | } |
| 246 | } | 273 | } |
| @@ -303,16 +330,22 @@ static void process(keyevent_t event, action_t action) | |||
| 303 | // with tap key | 330 | // with tap key |
| 304 | if (event.pressed) { | 331 | if (event.pressed) { |
| 305 | if (tap_count == 0) { | 332 | if (tap_count == 0) { |
| 306 | // not tapping yet | ||
| 307 | if (host_has_anykey()) { | 333 | if (host_has_anykey()) { |
| 334 | // This key is a normal key than a leyar key essentially. | ||
| 335 | // Prioritize 'tap key' when key jam or rollover | ||
| 308 | register_code(action.layer.code); | 336 | register_code(action.layer.code); |
| 309 | } else { | 337 | } else { |
| 310 | debug("Delay switching layer("); debug_hex8(action.layer.opt); debug(")\n"); | 338 | if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { |
| 311 | delaying_layer = (keyrecord_t){ | 339 | layer_switch(action.layer.opt); |
| 312 | .event = event, | 340 | tapping_key = (keyrecord_t){}; |
| 313 | .action = action, | 341 | } else { |
| 314 | .mods = host_get_mods() | 342 | debug("tapping layer("); debug_hex8(action.layer.opt); debug(")\n"); |
| 315 | }; | 343 | tapping_key = (keyrecord_t){ |
| 344 | .event = event, | ||
| 345 | .action = action, | ||
| 346 | .mods = host_get_mods() | ||
| 347 | }; | ||
| 348 | } | ||
| 316 | } | 349 | } |
| 317 | } else if (tap_count > 0) { | 350 | } else if (tap_count > 0) { |
| 318 | // pressed after tapping | 351 | // pressed after tapping |
| @@ -371,13 +404,14 @@ static void process(keyevent_t event, action_t action) | |||
| 371 | } | 404 | } |
| 372 | break; | 405 | break; |
| 373 | default: | 406 | default: |
| 407 | // TODO: see ACT_LAYER_PRESSED code | ||
| 374 | // with tap key | 408 | // with tap key |
| 375 | if (event.pressed) { | 409 | if (event.pressed) { |
| 376 | if (tap_count == 0) { | 410 | if (tap_count == 0) { |
| 377 | if (host_has_anykey()) { | 411 | if (host_has_anykey()) { |
| 378 | register_code(action.layer.code); | 412 | register_code(action.layer.code); |
| 379 | } else { | 413 | } else { |
| 380 | delaying_layer = (keyrecord_t){ | 414 | tapping_key = (keyrecord_t){ |
| 381 | .event = event, | 415 | .event = event, |
| 382 | .action = action, | 416 | .action = action, |
| 383 | .mods = keyboard_report->mods | 417 | .mods = keyboard_report->mods |
diff --git a/common/keyboard.h b/common/keyboard.h index cf85b1233..907ee1f97 100644 --- a/common/keyboard.h +++ b/common/keyboard.h | |||
| @@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 26 | extern "C" { | 26 | extern "C" { |
| 27 | #endif | 27 | #endif |
| 28 | 28 | ||
| 29 | // TODO: union {raw = row:col} | ||
| 29 | typedef struct { | 30 | typedef struct { |
| 30 | uint8_t row; | 31 | uint8_t row; |
| 31 | uint8_t col; | 32 | uint8_t col; |
