From 9f95e9cc27f2edf4336124b01c05d03dcd5ee5ac Mon Sep 17 00:00:00 2001 From: tmk Date: Tue, 15 Jan 2013 19:04:58 +0900 Subject: [PATCH] Add support partly for modifier with tap key. --- common/action.c | 249 +++++++++++++++++++++++++---------------- common/action.h | 161 +++++++++++++------------- keyboard/hhkb/keymap.c | 18 +-- 3 files changed, 239 insertions(+), 189 deletions(-) diff --git a/common/action.c b/common/action.c index 389fc5df..7299a874 100644 --- a/common/action.c +++ b/common/action.c @@ -10,11 +10,12 @@ #include "action.h" - - 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 add_mods(uint8_t mods); +static void del_mods(uint8_t mods); +static void set_mods(uint8_t mods); static void clear_keyboard(void); static void clear_keyboard_but_mods(void); static bool sending_anykey(void); @@ -24,7 +25,6 @@ static void layer_switch(uint8_t new_layer); /* tap */ #define TAP_TIME 200 static keyevent_t last_event = {}; -static uint16_t last_event_time = 0; static uint8_t tap_count = 0; /* layer */ @@ -32,6 +32,7 @@ uint8_t default_layer = 0; uint8_t current_layer = 0; keyrecord_t delaying_layer = {}; +/* waiting keys buffer */ #define WAITING_KEYS_BUFFER 3 static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {}; static uint8_t waiting_keys_head = 0; @@ -75,16 +76,87 @@ static void waiting_keys_process_in_current_layer(void) } +void action_exec(keyevent_t event) +{ + /* When delaying layer switch */ + if (delaying_layer.action.code) { + /* 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: + layer_switch(delaying_layer.action.layer.opt); + break; + case ACT_LAYER_BIT: + layer_switch(current_layer | delaying_layer.action.layer.opt); + break; + } + delaying_layer = (keyrecord_t){}; + + /* Process waiting keys in new layer */ + 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)) { + /* tap key down */ + debug("tap[delaying_layer](register): fist\n"); + uint8_t tmp_mods = host_get_mods(); + 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 */ + 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) { + waiting_keys_enqueue(event, action); + } else { + process(event, action); + } + } else { + process(event, action); + } + + /* last event */ + last_event = event; +} + + 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("action: "); debug_hex16(action.code); + if (event.pressed) debug("[down]\n"); else debug("[up]\n"); switch (action.kind.id) { /* Key and Mods */ case ACT_LMODS: - // normal key or key plus mods + // |pressed |released + // --------------+---------------------------------+------------ + // key |down(key) |up(key) + // mods |add(mods) |del(mods) + // key with mods |add(mods), down(key), unset(mods)|up(key) if (event.pressed) { uint8_t tmp_mods = host_get_mods(); if (action.key.mods) { @@ -105,6 +177,11 @@ static void process(keyevent_t event, action_t action) } break; case ACT_RMODS: + // |pressed |released + // --------------+---------------------------------+------------ + // key |down(key) |up(key) + // mods |add(mods) |del(mods) + // key with mods |add(mods), down(key), unset(mods)|up(key) if (event.pressed) { uint8_t tmp_mods = host_get_mods(); if (action.key.mods) { @@ -124,9 +201,49 @@ static void process(keyevent_t event, action_t action) unregister_code(action.key.code); } break; - case ACT_LMOD_TAP: + case ACT_LMODS_TAP: + if (event.pressed) { + if (tap_count == 0) { + add_mods(action.key.mods); + } else { + debug("tap[lmods](register): "); debug_hex(tap_count); debug("\n"); + register_code(action.key.code); + } + } else { + if (tap_count == 0) { + del_mods(action.key.mods); + } else if (tap_count == 1) { + debug("tap[lmods](register/unregister): "); debug_hex(tap_count); debug("\n"); + del_mods(action.key.mods); + register_code(action.key.code); + unregister_code(action.key.code); + } else { + debug("tap[lmods](unregister): "); debug_hex(tap_count); debug("\n"); + unregister_code(action.key.code); + } + } break; - case ACT_RMOD_TAP: + case ACT_RMODS_TAP: + if (event.pressed) { + if (tap_count == 0) { + add_mods(action.key.mods<<4); + } else { + debug("tap[rmods](register): "); debug_hex(tap_count); debug("\n"); + register_code(action.key.code); + } + } else { + if (tap_count == 0) { + del_mods(action.key.mods<<4); + } else if (tap_count == 1) { + debug("tap[rmods](register/unregister): "); debug_hex(tap_count); debug("\n"); + del_mods(action.key.mods<<4); + register_code(action.key.code); + unregister_code(action.key.code); + } else { + debug("tap[rmods](unregister): "); debug_hex(tap_count); debug("\n"); + unregister_code(action.key.code); + } + } break; /* other HID usage */ @@ -186,6 +303,7 @@ static void process(keyevent_t event, action_t action) // with tap key if (event.pressed) { if (tap_count == 0) { + // not tapping yet if (host_has_anykey()) { register_code(action.layer.code); } else { @@ -197,22 +315,14 @@ static void process(keyevent_t event, action_t action) }; } } else if (tap_count > 0) { - debug("tap: "); debug_hex(tap_count); debug("\n"); + // pressed after tapping + debug("tap[layer](register): "); 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) { - uint8_t tmp_mods = host_get_mods(); - host_set_mods(delaying_layer.mods); - register_code(delaying_layer.action.layer.code); - host_set_mods(tmp_mods); - unregister_code(delaying_layer.action.layer.code); - } else { - unregister_code(action.layer.code); - } - delaying_layer = (keyrecord_t){}; + // released after tapping + debug("tap[layer](unregister): "); debug_hex(tap_count); debug("\n"); + unregister_code(action.layer.code); } break; } @@ -220,7 +330,7 @@ static void process(keyevent_t event, action_t action) case ACT_LAYER_RELEASED: switch (action.layer.code) { case 0x00: - if (event.pressed) { + if (!event.pressed) { layer_switch(action.layer.opt); } break; @@ -274,7 +384,7 @@ static void process(keyevent_t event, action_t action) }; } } else if (tap_count > 0) { - debug("tap: "); debug_hex(tap_count); debug("\n"); + debug("tap[layer_bit](register): "); debug_hex(tap_count); debug("\n"); register_code(action.layer.code); } } else { @@ -348,77 +458,6 @@ static void process(keyevent_t event, action_t action) } } -void action_exec(keyevent_t event) -{ -/* - 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 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: - layer_switch(delaying_layer.action.layer.opt); - break; - case ACT_LAYER_BIT: - layer_switch(current_layer | delaying_layer.action.layer.opt); - break; - } - delaying_layer = (keyrecord_t){}; - - /* Process waiting keys in new layer */ - 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)) { - /* tap key down */ - uint8_t tmp_mods = host_get_mods(); - 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 */ - 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) { - waiting_keys_enqueue(event, action); - } else { - process(event, action); - } - } else { - process(event, action); - } - - /* last event */ - last_event = event; -} - - static void register_code(uint8_t code) { if (code == KC_NO) { @@ -449,6 +488,28 @@ static void unregister_code(uint8_t code) } } +static void add_mods(uint8_t mods) +{ + if (mods) { + host_add_mods(mods); + host_send_keyboard_report(); + } +} + +static void del_mods(uint8_t mods) +{ + if (mods) { + host_del_mods(mods); + host_send_keyboard_report(); + } +} + +static void set_mods(uint8_t mods) +{ + host_set_mods(mods); + host_send_keyboard_report(); +} + static void clear_keyboard(void) { host_clear_mods(); diff --git a/common/action.h b/common/action.h index 942ce191..3115c67f 100644 --- a/common/action.h +++ b/common/action.h @@ -5,55 +5,57 @@ /* Key Action(16bit code) - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ------------------------------------------------- -ACT_LMODS(0000) - 0 0 0 0| 0 0 0 0| 0 0 0 0 0 0| 0 0 No action - 0 0 0 0| 0 0 0 0| keycode(8) Key - 0 0 0 0| mods(4) | 0 0 0 0 0 0| 0 0 Lmods Momentary - 0 0 0 0| mods(4) | 0 0 0 0 0 0| 0 1 Lmods OneShot - 0 0 0 0| mods(4) | 0 0 0 0 0 0| 1 0 (reserved) - 0 0 0 0| mods(4) | 0 0 0 0 0 0| 1 1 (reserved) - 0 0 0 0| mods(4) | keycode(8) Key+Lmods - -ACT_RMODS(0001) - 0 0 0 1| 0 0 0 0| 0 0 0 0 0 0 0 0 No action(not used) - 0 0 0 1| 0 0 0 0| keycode(8) Key(not used) - 0 0 0 1| mods(4) | 0 0 0 0 0 0| 0 0 Rmods Momentary - 0 0 0 1| mods(4) | 0 0 0 0 0 0| 0 1 Rmods OneShot - 0 0 0 1| mods(4) | 0 0 0 0 0 0| 1 0 (reserved) - 0 0 0 1| mods(4) | 0 0 0 0 0 0| 1 1 (reserved) - 0 0 0 1| mods(4) | keycode(8) Key+Rmod - -ACT_LMODS_TAP(0010) - 0 0 1 0| 0 0 0 0| X X X X X X X X (reserved)[00-FF] - 0 0 1 0| mods(4) | 0 0 0 0 0 0| X X (reserved) - 0 0 1 0| mods(4) | keycode(8) Lmods+tap Key - 0 0 1 0| mods(4) | 1 1 1 1| X X X X (reserved)[F0-FF] - -ACT_RMODS_TAP(0011) - 0 0 1 1| 0 0 0 0| X X X X X X X X (reserved)[00-FF] - 0 0 1 1| mods(4) | 0 0 0 0 0 0| X X (reserved) - 0 0 1 1| mods(4) | keycode(8) Rmods+tap Key - 0 0 1 1| mods(4) | 1 1 1 1| X X X X (reserved)[F0-FF] + +Keyboard Keys +------------- +ACT_LMODS(0000): +0000|0000|000000|00 No action +0000|mods|000000|00 Left mods Momentary +0000|mods|000000|01 Left mods OneShot +0000|mods|000000|10 (reserved) +0000|mods|000000|11 (reserved) +0000|0000| keycode Key +0000|mods| keycode Key+Left mods + +ACT_RMODS(0001): +0001|0000|000000|00 No action +0001|mods|000000|00 Right mods Momentary +0001|mods|000000|01 Right mods OneShot +0001|mods|000000|10 (reserved) +0001|mods|000000|11 (reserved) +0001|0000| keycode Key +0001|mods| keycode Key+Right mods + +ACT_LMODS_TAP(0010): +0010|mods| keycode Left mods+tap Key + +ACT_RMODS_TAP(0011): +0011|mods| keycode Right mods+tap Key -ACT_USAGE - other HID usage than keyboard - 0 1 0 0| 0 0| usage(10) System usage - 0 1 0 0| 0 1| usage(10) Consumer usage - 0 1 0 0| 1 0| usage(10) (reserved) - 0 1 0 0| 1 1| usage(10) (reserved) - -ACT_MOUSEKEY(0110) - 0 1 0 1| X X X X| keycode(8) Mouse key -??? TODO: refactor - 0 1 0 1| 0 0 X X| accel(5) |cursor(3) Mouse key - 0 1 0 1| 0 1 X X| accel(5) |wheel(3) Mouse key - 0 1 0 1| 1 0 X X| button(8) Mouse key - 0 1 0 1| 1 1 X X| button(8) Mouse key -??? - -Layer Action ------------- + +Other HID Usage +--------------- +This action handles other usages than keyboard. +ACT_USAGE(0100): +0100|00| usage(10) System control(0x80) - General Desktop page(0x01) +0100|01| usage(10) Consumer control(0x01) - Consumer page(0x0C) +0100|10| usage(10) (reserved) +0100|11| usage(10) (reserved) + + +Mouse Keys +---------- +ACT_MOUSEKEY(0110): +0101|XXXX| keycode Mouse key + + +Layer Actions +------------- +ACT_LAYER_PRESSED(1000): Set layer on key pressed +ACT_LAYER_RELEASED(1001): Set layer on key released +ACT_LAYER_BIT(1010): On/Off layer bit +ACT_LAYER_EXT(1011): Extentions + 1000|LLLL|0000 0000 set layer L when pressed 1001|LLLL|0000 0000 set layer L when released 1010|BBBB|0000 0000 on/off bit B when pressed/released @@ -79,16 +81,19 @@ Layer Action 1011|0001| keyocde set default layer when released[tap is ignored/not used] -ACT_MACRO(1100) - 1 1 0 0| option(4) | macro-table id(8) Macro play(Flash) - 1 1 0 0| option(4) | macro-table id(8) Macro play(EEPROM) - 1 1 0 0| 1 1 1 1| macro-table id(8) Macro record +Extensions(11XX) +---------------- +NOTE: NOT FIXED + +ACT_MACRO(1100): +1100|opt | id(8) Macro play +1100|1111| id(8) Macro record -ACT_COMMAND(1110) - 1 1 1 0| option(4) | comamnd id(8) Built-in Command exec +ACT_COMMAND(1110): +1110|opt | id(8) Built-in Command exec -ACT_FUNCTION(1111) - 1 1 1 1| function address(4K range) Function +ACT_FUNCTION(1111): +1111| address(12) Function Macro record(dynamicly) Macro play(dynamicly) TODO: modifier + [tap key /w mod] @@ -98,19 +103,22 @@ TODO: modifier + [tap key /w mod] */ enum action_id { - ACT_LMODS = 0b0000, - ACT_RMODS = 0b0001, - ACT_LMOD_TAP = 0b0010, - ACT_RMOD_TAP = 0b0011, - ACT_USAGE = 0b0100, - ACT_MOUSEKEY = 0b0101, - ACT_LAYER_PRESSED = 0b1000, - ACT_LAYER_RELEASED = 0b1001, - ACT_LAYER_BIT = 0b1010, - ACT_LAYER_EXT = 0b1011, - ACT_MACRO = 0b1100, - ACT_COMMAND = 0b1110, - ACT_FUNCTION = 0b1111 + ACT_LMODS = 0b0000, + ACT_RMODS = 0b0001, + ACT_LMODS_TAP = 0b0010, + ACT_RMODS_TAP = 0b0011, + + ACT_USAGE = 0b0100, + ACT_MOUSEKEY = 0b0101, + + ACT_LAYER_PRESSED = 0b1000, + ACT_LAYER_RELEASED = 0b1001, + ACT_LAYER_BIT = 0b1010, + ACT_LAYER_EXT = 0b1011, + + ACT_MACRO = 0b1100, + ACT_COMMAND = 0b1110, + ACT_FUNCTION = 0b1111 }; // TODO: not portable across compiler/endianness? @@ -169,20 +177,13 @@ typedef struct { void action_exec(keyevent_t event); -/* -void key_action(uint8_t code, keyevent_t event); -void mod_action(uint8_t code, keyevent_t event); -void fn_action(uint8_t code, keyevent_t event); -*/ +// TODO: proper names /* action_t utility */ -/* -#define ACTION_NO { .code = 0 } -#define ACTION(kind, param) { .code = ((kind)<<12 | (param)) } -*/ #define ACTION_NO 0 #define ACTION(kind, param) ((kind)<<12 | (param)) +#define MOD_BITS(mods) (((mods)>>4 | (mods)) & 0x0F) /* Key & Mods */ #define ACTION_KEY(key) ACTION(ACT_LMODS, key) @@ -197,8 +198,8 @@ void fn_action(uint8_t code, keyevent_t event); #define ACTION_RMODS_SWITCH(mods, tap) ACTION(ACT_RMODS, (mods)<<8 | 0xF0 | (tap)) #define ACTION_RMODS_TOGGLE(mods, tap) ACTION(ACT_RMODS, (mods)<<8 | 0xF1 | (tap)) /* Mods + Tap key */ -#define ACTION_LMODS_TAP(mods, key) ACTION(ACT_LMODS_TAP,(mods)<<8 | (key)) -#define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP,(mods)<<8 | (key)) +#define ACTION_LMODS_TAP(mods, key) ACTION(ACT_LMODS_TAP, MOD_BITS(mods)<<8 | (key)) +#define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP, MOD_BITS(mods)<<8 | (key)) /* Layer Switch */ #define ACTION_LAYER_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index 38461290..e29b37b1 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -51,18 +51,6 @@ along with this program. If not, see . } -/* -static const action_t PROGMEM fn_actions[] = { - ACTION_LAYER_TO_DEFAULT_ON_RELEASED, // Fn0 - ACTION_LAYER_SET_ON_PRESSED(1), // Fn1 - ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH), // Fn2 - ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // Fn3 - ACTION_LAYER_SET_ON_PRESSED(3), // Fn4 - ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // Fn5 - ACTION_NO, // Fn6 - ACTION_NO, // Fn7 -}; -*/ static const uint16_t PROGMEM fn_actions[] = { ACTION_LAYER_TO_DEFAULT_ON_RELEASED, // Fn0 ACTION_LAYER_SET_ON_PRESSED(1), // Fn1 @@ -70,8 +58,8 @@ static const uint16_t PROGMEM fn_actions[] = { ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // Fn3 ACTION_LAYER_SET_ON_PRESSED(3), // Fn4 ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // Fn5 - ACTION_NO, // Fn6 - ACTION_NO, // Fn7 + ACTION_LMODS_TAP(MOD_BIT(KC_LCTL), KC_BSPC), // Fn6 + ACTION_RMODS_TAP(MOD_BIT(KC_RCTL), KC_ENT), // Fn7 }; @@ -91,7 +79,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ - LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,ENT, \ + FN6, A, S, D, F, G, H, J, K, L, FN3, QUOT,FN7, \ LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ LGUI,LALT, FN5, RALT,FN4), -- 2.39.3