From 8a709c2750eab09ec0f83450410a13640931d48e Mon Sep 17 00:00:00 2001 From: tmk Date: Sun, 16 Dec 2012 02:32:07 +0900 Subject: [PATCH 01/30] Add initial fix for new keymap. --- common.mk | 1 + common/action.c | 572 ++++++++++++++++++++++++++++++++++++ common/action.h | 219 ++++++++++++++ common/host.c | 8 +- common/host.h | 4 +- common/keyboard.c | 550 +--------------------------------- common/keyboard.h | 5 +- common/keycode.h | 2 + common/keymap.h | 14 +- common/report.h | 81 +++++ keyboard/hhkb/Makefile.lufa | 3 + keyboard/hhkb/Makefile.vusb | 3 + keyboard/hhkb/keymap.c | 109 +++---- keyboard/hhkb/matrix.c | 7 + 14 files changed, 967 insertions(+), 611 deletions(-) create mode 100644 common/action.c create mode 100644 common/action.h diff --git a/common.mk b/common.mk index 66f9fd099..bd8616e5f 100644 --- a/common.mk +++ b/common.mk @@ -1,6 +1,7 @@ COMMON_DIR = common SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/keyboard.c \ + $(COMMON_DIR)/action.c \ $(COMMON_DIR)/command.c \ $(COMMON_DIR)/timer.c \ $(COMMON_DIR)/print.c \ diff --git a/common/action.c b/common/action.c new file mode 100644 index 000000000..d4aae207f --- /dev/null +++ b/common/action.c @@ -0,0 +1,572 @@ +#include "host.h" +#include "timer.h" +//#include "keymap.h" +#include "keycode.h" +#include "keyboard.h" +#include "mousekey.h" +#include "command.h" +#include "util.h" +#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 keyrecord_t delayed_fn = {}; +static keyrecord_t waiting_key = {}; + +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 layer_switch_on(uint8_t code); +static void layer_switch_off(uint8_t code); +static void key_action(uint8_t code, keyevent_t event); +static void key_pressed(uint8_t code, keyevent_t event); +static void key_released(uint8_t code, keyevent_t event); +static void mod_pressed(uint8_t code, keyevent_t event); +static void mod_released(uint8_t code, keyevent_t event); +*/ + +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 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 */ +uint8_t default_layer = 0; +uint8_t current_layer = 0; +uint8_t waiting_layer = 0; + + +void action_exec(action_t action, 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("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) { + case ACT_LMODS: + if (event.pressed) { + register_mods(action.key.mods); + register_code(action.key.code); + } else { + unregister_code(action.key.code); + unregister_mods(action.key.mods); + } + break; + case ACT_RMODS: + if (event.pressed) { + register_mods(action.key.mods<<4); + register_code(action.key.code); + } else { + unregister_code(action.key.code); + unregister_mods(action.key.mods<<4); + } + break; + case ACT_LAYER: + switch (action.layer_key.code) { + case 0x00: // Momentary switch + // TODO: history of layer switch + if (event.pressed) { + layer_switch(action.layer_key.layer); + } else { + layer_switch(default_layer); + } + break; + case 0x01: // Oneshot switch + // TODO: + break; + case 0x02: // reserved + case 0x03: // reserved + break; + case 0xF0 ... 0xF7: // Tap to enable/disable + case 0xF8 ... 0xFF: // Tap to toggle layer + // TODO: + break; + default: // with keycode for tap + debug("tap: "); debug_hex(tap_count); debug("\n"); + // TODO: layer switch + // TODO: in case tap is interrupted by other key + + + if (event.pressed) { + // when any key down + if (host_has_anykey()) { + if (tap_count == 0) + register_code(action.layer_key.code); + } else { + } + + if (tap_count == 0) { + if (host_has_anykey()) { + register_code(action.layer_key.code); + } else { + waiting_layer = action.layer_key.layer; + } + } + // register key when press after a tap + if (tap_count > 0) { + register_code(action.layer_key.code); + } + } else { + // type key after tap + if (tap_count == 1) { + register_code(action.layer_key.code); + } + unregister_code(action.layer_key.code); + } + break; + } + break; + case ACT_USAGE: +#ifdef EXTRAKEY_ENABLE + switch (action.usage.page) { + case ACTION_USAGE_PAGE_SYSTEM: + if (event.pressed) { + host_system_send(action.usage.code); + } else { + host_system_send(0); + } + break; + case ACTION_USAGE_PAGE_CONSUMER: + if (event.pressed) { + host_consumer_send(action.usage.code); + } else { + host_consumer_send(0); + } + break; + } +#endif + break; + case ACT_MOUSEKEY: +#ifdef MOUSEKEY_ENABLE + if (event.pressed) { + mousekey_on(action.key.code); + mousekey_send(); + } else { + mousekey_off(action.key.code); + mousekey_send(); + } +#endif + break; + case ACT_LMOD_TAP: + case ACT_RMOD_TAP: + case ACT_MACRO: + case ACT_COMMAND: + case ACT_FUNCTION: + default: + break; + } + + /* last event */ + last_event = event; + last_event_time = timer_read(); +} + + +#if 0 +/* Key Action */ +inline +static void key_action(uint8_t code, keyevent_t event) +{ + if (event.pressed) + key_pressed(code, event); + else + key_released(code, event); +} + +void fn_action(uint8_t code, keyevent_t event) +{ +} + +/* Key */ +inline static void key_pressed(uint8_t code, keyevent_t event) +{ + uint8_t tmp_mods; + switch (kbdstate) { + case IDLE: + register_code(code); + NEXT(PRESSING); + break; + case PRESSING: + register_code(code); + break; + case DELAYING: + waiting_key = (keyrecord_t) { + .event = event, + .code = code, + .mods = keyboard_report->mods, + .time = timer_read() + }; + NEXT(WAITING); + break; + case WAITING: + // play back key stroke + tmp_mods = keyboard_report->mods; + host_set_mods(delayed_fn.mods); + register_code(delayed_fn.code); + host_set_mods(waiting_key.mods); + register_code(waiting_key.code); + host_set_mods(tmp_mods); + register_code(code); + NEXT(IDLE); + break; + } +} +inline static void key_released(uint8_t code, keyevent_t event) +{ + uint8_t tmp_mods; + switch (kbdstate) { + case IDLE: + unregister_code(code); + break; + case PRESSING: + unregister_code(code); + if (!anykey_sent_to_host()) + NEXT(IDLE); + break; + case DELAYING: + unregister_code(code); + break; + case WAITING: + if (code == waiting_key.code) { + layer_switch_on(delayed_fn.code); + NEXT(IDLE); + // process waiting_key + tmp_mods = keyboard_report->mods; + host_set_mods(waiting_key.mods); + keymap_process_event(waiting_key.event); + host_set_mods(tmp_mods); + keymap_process_event(event); + } else { + unregister_code(code); + } + break; + } +} + +/* layer switch momentary */ +inline static void layerkey_pressed(uint8_t code, keyevent_t event) +{ + uint8_t tmp_mods; + switch (kbdstate) { + case IDLE: + layer_switch_on(code); + break; + case PRESSING: + // ignore + break; + case DELAYING: + waiting_key = (keyrecord_t) { + .event = event, + .code = code, + .mods = keyboard_report->mods, + .time = timer_read() + }; + NEXT(WAITING); + break; + case WAITING: + tmp_mods = keyboard_report->mods; + host_set_mods(delayed_fn.mods); + register_code(delayed_fn.code); + host_set_mods(waiting_key.mods); + register_code(waiting_key.code); + host_set_mods(tmp_mods); + 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; + } +} +inline static void layerkey_released(uint8_t code, keyevent_t event) +{ + switch (kbdstate) { + case IDLE: + layer_switch_off(code); + break; + case PRESSING: + case DELAYING: + case WAITING: + if (layer_switch_off(code)) + NEXT(IDLE); + break; + } +} +#endif + + +static void register_code(uint8_t code) +{ + if (code == KC_NO) { + return; + } + else if IS_KEY(code) { + // TODO: should push command_proc out of this block? + if (!command_proc(code)) { + host_add_key(code); + host_send_keyboard_report(); + } + } + else if IS_MOD(code) { + host_add_mods(MOD_BIT(code)); + host_send_keyboard_report(); + } +#ifdef MOUSEKEY_ENABLE + else if IS_MOUSEKEY(code) { + mousekey_on(code); + mousekey_send(); + } +#endif +#ifdef EXTRAKEY_ENABLE + else if IS_CONSUMER(code) { + uint16_t usage = 0; + switch (code) { + case KC_AUDIO_MUTE: + usage = AUDIO_MUTE; + break; + case KC_AUDIO_VOL_UP: + usage = AUDIO_VOL_UP; + break; + case KC_AUDIO_VOL_DOWN: + usage = AUDIO_VOL_DOWN; + break; + case KC_MEDIA_NEXT_TRACK: + usage = TRANSPORT_NEXT_TRACK; + break; + case KC_MEDIA_PREV_TRACK: + usage = TRANSPORT_PREV_TRACK; + break; + case KC_MEDIA_STOP: + usage = TRANSPORT_STOP; + break; + case KC_MEDIA_PLAY_PAUSE: + usage = TRANSPORT_PLAY_PAUSE; + break; + case KC_MEDIA_SELECT: + usage = AL_CC_CONFIG; + break; + case KC_MAIL: + usage = AL_EMAIL; + break; + case KC_CALCULATOR: + usage = AL_CALCULATOR; + break; + case KC_MY_COMPUTER: + usage = AL_LOCAL_BROWSER; + break; + case KC_WWW_SEARCH: + usage = AC_SEARCH; + break; + case KC_WWW_HOME: + usage = AC_HOME; + break; + case KC_WWW_BACK: + usage = AC_BACK; + break; + case KC_WWW_FORWARD: + usage = AC_FORWARD; + break; + case KC_WWW_STOP: + usage = AC_STOP; + break; + case KC_WWW_REFRESH: + usage = AC_REFRESH; + break; + case KC_WWW_FAVORITES: + usage = AC_BOOKMARKS; + break; + } + host_consumer_send(usage); + } + else if IS_SYSTEM(code) { + uint16_t usage = 0; + switch (code) { + case KC_SYSTEM_POWER: + usage = SYSTEM_POWER_DOWN; + break; + case KC_SYSTEM_SLEEP: + usage = SYSTEM_SLEEP; + break; + case KC_SYSTEM_WAKE: + usage = SYSTEM_WAKE_UP; + break; + } + host_system_send(usage); + } +#endif +} + +static void unregister_code(uint8_t code) +{ + if IS_KEY(code) { + host_del_key(code); + host_send_keyboard_report(); + } + else if IS_MOD(code) { + host_del_mods(MOD_BIT(code)); + host_send_keyboard_report(); + } +#ifdef MOUSEKEY_ENABLE + else if IS_MOUSEKEY(code) { + mousekey_off(code); + mousekey_send(); + } +#endif +#ifdef EXTRAKEY_ENABLE + else if IS_CONSUMER(code) { + host_consumer_send(0x0000); + } + else if IS_SYSTEM(code) { + host_system_send(0x0000); + } +#endif +} + +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(); + clear_keyboard_but_mods(); +} + +static void clear_keyboard_but_mods(void) +{ + host_clear_keys(); + host_send_keyboard_report(); +#ifdef MOUSEKEY_ENABLE + mousekey_clear(); + mousekey_send(); +#endif +#ifdef EXTRAKEY_ENABLE + host_system_send(0); + host_consumer_send(0); +#endif +} + +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"); + + current_layer = new_layer; + clear_keyboard_but_mods(); // To avoid stuck keys + } +} diff --git a/common/action.h b/common/action.h new file mode 100644 index 000000000..08f8c5608 --- /dev/null +++ b/common/action.h @@ -0,0 +1,219 @@ +#ifndef ACTION_H +#define ACTION_H + +#include "keyboard.h" + + +/* 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 +??? + 0 0 0 0| mods(4) | 1 1 1 1 0| tap(3) Lmods+tap Switch(enable/disable) + 0 0 0 0| mods(4) | 1 1 1 1 1| tap(3) Lmods+tap Toggle(on/off) +??? + +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 +??? + 0 0 0 1| mods(4) | 1 1 1 1 0| tap(3) Rmods+tap Switch(enable/disable) + 0 0 0 1| mods(4) | 1 1 1 1 1| tap(3) Rmods+tap Toggle(on/off) +??? + +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] + +ACT_LAYER(0100) + 0 1 0 0| layer(4) | 0 0 0 0 0 0| 0 0 Momentary + 0 1 0 0| layer(4) | 0 0 0 0 0 0| 0 1 Oneshot + 0 1 0 0| layer(4) | 0 0 0 0 0 0| 1 0 (reserved) + 0 1 0 0| layer(4) | 0 0 0 0 0 0| 1 1 (reserved) + 0 1 0 0| layer(4) | keycode(8) Fn momentary + tap Key + 0 1 0 0| layer(4) | 1 1 1 1 0| tap(3) Fn+tap Switch(enable/disable) + 0 1 0 0| layer(4) | 1 1 1 1 1| tap(3) Fn+tap Toggle(on/off) + +ACT_USAGE(0101) + 0 1 0 1| 0 0| usage(10) System usage + 0 1 0 1| 0 1| usage(10) Consumer usage + 0 1 0 1| 1 0| usage(10) (reserved) + 0 1 0 1| 1 1| usage(10) (reserved) + +ACT_MOUSEKEY(0110) + 0 1 1 0| X X X X| keycode(8) Mouse key +??? TODO: refactor + 0 1 1 0| 0 0 X X| accel(5) |cursor(3) Mouse key + 0 1 1 0| 0 1 X X| accel(5) |wheel(3) Mouse key + 0 1 1 0| 1 0 X X| button(8) Mouse key + 0 1 1 0| 1 1 X X| button(8) Mouse key +??? + + 0 1 1 1| (reserved) + 1 0 0 0| (reserved) + 1 0 0 1| (reserved) + 1 0 1 0| (reserved) + 1 0 1 1| (reserved) + 1 1 0 0| (reserved) + +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 + +ACT_COMMAND(1110) + 1 1 1 0| option(4) | comamnd id(8) Built-in Command exec + +ACT_FUNCTION(1111) + 1 1 1 1| function address(4K range) Function + Macro record(dynamicly) + Macro play(dynamicly) +*/ + +enum action_id { + ACT_LMODS = 0, + ACT_RMODS, + ACT_LMOD_TAP, + ACT_RMOD_TAP, + ACT_LAYER, + ACT_USAGE, + ACT_MOUSEKEY, + ACT_MACRO = 14, + ACT_COMMAND = 15, + ACT_FUNCTION = 16 +}; + +// TODO: not portable across compiler/endianness? +/* +In avr-gcc bit fields seems to be assigned from LSB(bit0) to MSB(bit15). +AVR seems like little endian in avr-gcc. + +Byte order and bit order of 0x1234: +Big endian: 15 ... 8 7 ... 210 + | 0x12 | 0x34 | + 0001 0010 0011 0100 +Little endian: 012 ... 7 8 ... 15 + | 0x34 | 0x12 | + 0010 1100 0100 1000 +*/ +typedef union { + uint16_t code; + struct action_kind { + uint16_t param :12; + uint16_t id :4; + } kind; + struct action_key { + uint16_t code :8; + uint16_t mods :4; + uint16_t kind :4; + } key; + struct action_layer_key { + uint16_t code :8; + uint16_t layer :4; + uint16_t kind :4; + } layer_key; + struct action_layer_tap { + uint16_t count :3; + uint16_t rest :5; + uint16_t layer :4; + uint16_t kind :4; + } layer_tap; + struct action_usage { + uint16_t code :10; + uint16_t page :2; + uint16_t kind :4; + } usage; + struct action_command { + uint16_t id :8; + uint16_t option :4; + uint16_t kind :4; + } command; +} action_t; + + +enum stroke_cmd { + STROKE_DOWN, + STROKE_UP, + STROKE_ALLUP, /* release all keys in reverse order */ +}; + +void action_exec(action_t act, 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); +*/ + + +/* action_t utility */ +#define ACTION(kind, param) { .code = ((kind)<<12 | (param)) } +#define NO_ACTION ACTION(0, 0) +#define LAYER_PARAM(layer, key) ((layer)<<8|(key)) + +/* Key & Mods */ +#define ACTION_KEY(key) ACTION(ACT_LMODS, key) +#define ACTION_LMODS(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x00) +#define ACTION_LMODS_KEY(mods, key) ACTION(ACT_LMODS, (mods)<<8 | (key)) +#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x01) +#define ACTION_LMODS_SWITCH(mods, tap) ACTION(ACT_LMODS, (mods)<<8 | 0xF0 | (tap)) +#define ACTION_LMODS_TOGGLE(mods, tap) ACTION(ACT_LMODS, (mods)<<8 | 0xF1 | (tap)) +#define ACTION_RMODS(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x00) +#define ACTION_RMODS_KEY(mods, key) ACTION(ACT_RMODS, (mods)<<8 | (key)) +#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x01) +#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)) +/* Layer Switch */ +#define ACTION_LAYER(layer) ACTION(ACT_LAYER, (layer)<<8 | 0x00) +#define ACTION_LAYER_ONESHOT(layer) ACTION(ACT_LAYER, (layer)<<8 | 0x01) +#define ACTION_LAYER_KEY(layer, key) ACTION(ACT_LAYER, (layer)<<8 | (key)) +#define ACTION_LAYER_SWITCH(layer, tap) ACTION(ACT_LAYER, (layer)<<8 | 0xF0 | (tap)) +#define ACTION_LAYER_TOGGLE(layer, tap) ACTION(ACT_LAYER, (layer)<<8 | 0xF1 | (tap)) +/* HID Usage */ +#define ACTION_USAGE_PAGE_SYSTEM 0 +#define ACTION_USAGE_PAGE_CONSUMER 1 +#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_SYSTEM<<10 | (id)) +#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_CONSUMER<<10 | (id)) +/* Mousekey */ +#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key) +/* Macro */ +#define ACTION_MACRO(opt, id) ACTION(ACT_FUNCTION, (opt)<<8 | (addr)) +/* Command */ +#define ACTION_COMMAND(opt, id) ACTION(ACT_COMMAND, (opt)<<8 | (addr)) +/* Function */ +#define ACTION_FUNCTION(addr) ACTION(ACT_FUNCTION, addr) + + +/* helpers for readability */ +#define LAYER(layer) (layer) +#define TAP(tap) (tap) +#define DOUBLE_TAP 2 +#define TRIPLE_TAP 3 +#define QUADRUPLE_TAP 4 +#define QUINTUPLE_TAP 5 +#define DOWN(key) (key) +#define UP(key) STROKE_UP, (key) + +#endif /* ACTION_H */ diff --git a/common/host.c b/common/host.c index 261ec6472..28c8a819f 100644 --- a/common/host.c +++ b/common/host.c @@ -127,14 +127,14 @@ void host_clear_keys(void) } } -void host_add_mod_bit(uint8_t mod) +void host_add_mods(uint8_t mods) { - keyboard_report->mods |= mod; + keyboard_report->mods |= mods; } -void host_del_mod_bit(uint8_t mod) +void host_del_mods(uint8_t mods) { - keyboard_report->mods &= ~mod; + keyboard_report->mods &= ~mods; } void host_set_mods(uint8_t mods) diff --git a/common/host.h b/common/host.h index 207b68310..4f1f234a9 100644 --- a/common/host.h +++ b/common/host.h @@ -51,8 +51,8 @@ void host_consumer_send(uint16_t data); void host_add_key(uint8_t key); void host_del_key(uint8_t key); void host_clear_keys(void); -void host_add_mod_bit(uint8_t mod); -void host_del_mod_bit(uint8_t mod); +void host_add_mods(uint8_t mods); +void host_del_mods(uint8_t mods); void host_set_mods(uint8_t mods); void host_clear_mods(void); uint8_t host_has_anykey(void); diff --git a/common/keyboard.c b/common/keyboard.c index fa22116f1..5e95fb984 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -31,517 +31,6 @@ along with this program. If not, see . #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 { - NONE, - FN_DOWN, FN_UP, - FNK_DOWN, FNK_UP, - KEY_DOWN, KEY_UP, - MOD_DOWN, MOD_UP, -} keykind_t; - -typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t; - - -#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; -static uint8_t fn_state_bits = 0; -static keyrecord_t delayed_fn; -static keyrecord_t waiting_key; - - -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 inline keykind_t get_keykind(uint8_t code, bool pressed) -{ - if IS_KEY(code) return (pressed ? KEY_DOWN : KEY_UP); - if IS_MOD(code) return (pressed ? MOD_DOWN : MOD_UP); - if IS_FN(code) { - if (keymap_fn_keycode(FN_INDEX(code))) - return (pressed ? FNK_DOWN : FNK_UP); - else - return (pressed ? FN_DOWN : FN_UP); - } - if IS_MOUSEKEY(code) return (pressed ? KEY_DOWN : KEY_UP); - if IS_SYSTEM(code) return (pressed ? KEY_DOWN : KEY_UP); - if IS_CONSUMER(code) return (pressed ? KEY_DOWN : KEY_UP); - return NONE; -} - -static void clear_keyboard(void) -{ - host_clear_keys(); - host_clear_mods(); - host_send_keyboard_report(); - - host_system_send(0); - host_consumer_send(0); - -#ifdef MOUSEKEY_ENABLE - mousekey_clear(); - mousekey_send(); -#endif -} - -static void clear_keyboard_but_mods(void) -{ - host_clear_keys(); - host_send_keyboard_report(); - - host_system_send(0); - host_consumer_send(0); - -#ifdef MOUSEKEY_ENABLE - mousekey_clear(); - mousekey_send(); -#endif -} - -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 layer_switch_on(uint8_t code) -{ - if (!IS_FN(code)) return; - 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(on): "); Kdebug_hex(current_layer); - Kdebug(" -> "); 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) -{ - if IS_KEY(code) { - 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) { - uint16_t usage = 0; - switch (code) { - case KC_AUDIO_MUTE: - usage = AUDIO_MUTE; - break; - case KC_AUDIO_VOL_UP: - usage = AUDIO_VOL_UP; - break; - case KC_AUDIO_VOL_DOWN: - usage = AUDIO_VOL_DOWN; - break; - case KC_MEDIA_NEXT_TRACK: - usage = TRANSPORT_NEXT_TRACK; - break; - case KC_MEDIA_PREV_TRACK: - usage = TRANSPORT_PREV_TRACK; - break; - case KC_MEDIA_STOP: - usage = TRANSPORT_STOP; - break; - case KC_MEDIA_PLAY_PAUSE: - usage = TRANSPORT_PLAY_PAUSE; - break; - case KC_MEDIA_SELECT: - usage = AL_CC_CONFIG; - break; - case KC_MAIL: - usage = AL_EMAIL; - break; - case KC_CALCULATOR: - usage = AL_CALCULATOR; - break; - case KC_MY_COMPUTER: - usage = AL_LOCAL_BROWSER; - break; - case KC_WWW_SEARCH: - usage = AC_SEARCH; - break; - case KC_WWW_HOME: - usage = AC_HOME; - break; - case KC_WWW_BACK: - usage = AC_BACK; - break; - case KC_WWW_FORWARD: - usage = AC_FORWARD; - break; - case KC_WWW_STOP: - usage = AC_STOP; - break; - case KC_WWW_REFRESH: - usage = AC_REFRESH; - break; - case KC_WWW_FAVORITES: - usage = AC_BOOKMARKS; - break; - } - host_consumer_send(usage); - } - else if IS_SYSTEM(code) { - uint16_t usage = 0; - switch (code) { - case KC_SYSTEM_POWER: - usage = SYSTEM_POWER_DOWN; - break; - case KC_SYSTEM_SLEEP: - usage = SYSTEM_SLEEP; - break; - case KC_SYSTEM_WAKE: - usage = SYSTEM_WAKE_UP; - break; - } - host_system_send(usage); - } - -} - -static void unregister_code(uint8_t code) -{ - if IS_KEY(code) { - host_del_key(code); - host_send_keyboard_report(); - } - else if IS_MOD(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); - } - else if IS_SYSTEM(code) { - host_system_send(0x0000); - } -} - -/* - * - * 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) - */ -#define NEXT(state) do { \ - Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \ - kbdstate = state; \ - Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \ -} while (0) - -static inline void process_key(keyevent_t event) -{ - 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; - - 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: - switch (kind) { - case FN_DOWN: - layer_switch_on(code); - break; - case FN_UP: - layer_switch_off(code); - break; - case FNK_DOWN: - // 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(code); - NEXT(PRESSING); - } else { - delayed_fn = (keyrecord_t) { - .event = event, - .code = code, - .mods = keyboard_report->mods, - .time = timer_read() - }; - NEXT(DELAYING); - } - break; - case FNK_UP: - layer_switch_off(code); - break; - case KEY_DOWN: - register_code(code); - NEXT(PRESSING); - break; - case MOD_DOWN: - register_code(code); - break; - case KEY_UP: - case MOD_UP: - unregister_code(code); - break; - default: - break; - } - break; - case PRESSING: - switch (kind) { - case FN_DOWN: - // ignored when any key is pressed - break; - case FN_UP: - if (layer_switch_off(code)) - NEXT(IDLE); - break; - case FNK_DOWN: - register_code(code); - break; - case FNK_UP: - 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: - register_code(code); - break; - case KEY_UP: - case MOD_UP: - unregister_code(code); - if (!anykey_sent_to_host()) - NEXT(IDLE); - break; - default: - break; - } - break; - case DELAYING: - switch (kind) { - case FN_DOWN: - case FNK_DOWN: - case KEY_DOWN: - waiting_key = (keyrecord_t) { - .event = event, - .code = code, - .mods = keyboard_report->mods, - .time = timer_read() - }; - NEXT(WAITING); - break; - case MOD_DOWN: - register_code(code); - break; - case FN_UP: - if (layer_switch_off(code)) - NEXT(IDLE); - break; - case FNK_UP: - if (code == delayed_fn.code) { - // type Fn with alt keycode - // restore the mod status at the time of pressing Fn key - tmp_mods = keyboard_report->mods; - host_set_mods(delayed_fn.mods); - register_code(delayed_fn.code); - unregister_code(delayed_fn.code); - host_set_mods(tmp_mods); - NEXT(IDLE); - } else { - if (layer_switch_off(code)) - NEXT(IDLE); - } - break; - case KEY_UP: - case MOD_UP: - unregister_code(code); - break; - default: - break; - } - break; - case WAITING: - switch (kind) { - case FN_DOWN: - case FNK_DOWN: - case KEY_DOWN: - tmp_mods = keyboard_report->mods; - host_set_mods(delayed_fn.mods); - register_code(delayed_fn.code); - host_set_mods(waiting_key.mods); - register_code(waiting_key.code); - host_set_mods(tmp_mods); - 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: - 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(delayed_fn.code); - host_set_mods(waiting_key.mods); - register_code(waiting_key.code); - unregister_code(delayed_fn.code); - host_set_mods(tmp_mods); - NEXT(IDLE); - } else { - if (layer_switch_off(code)) - NEXT(IDLE); - } - break; - case KEY_UP: - if (code == waiting_key.code) { - layer_switch_on(delayed_fn.code); - NEXT(IDLE); - // process waiting_key - tmp_mods = keyboard_report->mods; - host_set_mods(waiting_key.mods); - process_key(waiting_key.event); - host_set_mods(tmp_mods); - process_key(event); - } else { - unregister_code(code); - } - break; - case MOD_UP: - unregister_code(code); - break; - default: - break; - } - break; - } -} - void keyboard_init(void) { // TODO: to enable debug print magic key bind on boot time @@ -556,6 +45,10 @@ void keyboard_init(void) #endif } +/* + * Do keyboard routine jobs: scan mantrix, light LEDs, ... + * This is repeatedly called as fast as possible. + */ void keyboard_task(void) { static matrix_row_t matrix_prev[MATRIX_ROWS]; @@ -572,8 +65,8 @@ void keyboard_task(void) for (int c = 0; c < MATRIX_COLS; c++) { if (matrix_change & (1< LAYER_DELAY) { - if (kbdstate == DELAYING) { - layer_switch_on(delayed_fn.code); - NEXT(IDLE); - } - if (kbdstate == WAITING) { - layer_switch_on(delayed_fn.code); - NEXT(IDLE); - uint8_t tmp_mods = keyboard_report->mods; - host_set_mods(waiting_key.mods); - process_key(waiting_key.event); - host_set_mods(tmp_mods); - } - } - } - #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(); diff --git a/common/keyboard.h b/common/keyboard.h index 2353805e1..37df6a4de 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -29,10 +29,10 @@ extern "C" { typedef struct { uint8_t row; uint8_t col; -} key_t; +} keypos_t; typedef struct { - key_t key; + keypos_t key; bool pressed; } keyevent_t; @@ -45,7 +45,6 @@ typedef struct { #define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col) - extern uint8_t current_layer; extern uint8_t default_layer; diff --git a/common/keycode.h b/common/keycode.h index f9331cdbf..2eec2af85 100644 --- a/common/keycode.h +++ b/common/keycode.h @@ -43,6 +43,8 @@ along with this program. If not, see . #define MOD_INDEX(code) ((code) & 0x07) #define FN_BIT(code) (1<. #include #include +#include "action.h" - -/* keycode in specific layer */ +/* + * legacy keymap interface: keycode + */ uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col); - /* layer to move during press Fn key */ uint8_t keymap_fn_layer(uint8_t fn_bits); - /* keycode to send when release Fn key without using */ uint8_t keymap_fn_keycode(uint8_t fn_bits); +/* + * new keymap interface: action + */ +action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col); +uint8_t keymap_process_event(keyevent_t event); + #endif diff --git a/common/report.h b/common/report.h index a73e0aba1..e8582d81f 100644 --- a/common/report.h +++ b/common/report.h @@ -19,6 +19,7 @@ along with this program. If not, see . #define REPORT_H #include +#include /* report id */ @@ -97,6 +98,86 @@ typedef struct { int8_t h; } __attribute__ ((packed)) report_mouse_t; + +static uint16_t key2system(uint8_t key) +{ + uint16_t usage = 0; + switch (key) { + case KC_SYSTEM_POWER: + usage = SYSTEM_POWER_DOWN; + break; + case KC_SYSTEM_SLEEP: + usage = SYSTEM_SLEEP; + break; + case KC_SYSTEM_WAKE: + usage = SYSTEM_WAKE_UP; + break; + } + return usage; +} + +static uint16_t key2consumer(uint8_t key) +{ + uint16_t usage = 0; + switch (key) { + case KC_AUDIO_MUTE: + usage = AUDIO_MUTE; + break; + case KC_AUDIO_VOL_UP: + usage = AUDIO_VOL_UP; + break; + case KC_AUDIO_VOL_DOWN: + usage = AUDIO_VOL_DOWN; + break; + case KC_MEDIA_NEXT_TRACK: + usage = TRANSPORT_NEXT_TRACK; + break; + case KC_MEDIA_PREV_TRACK: + usage = TRANSPORT_PREV_TRACK; + break; + case KC_MEDIA_STOP: + usage = TRANSPORT_STOP; + break; + case KC_MEDIA_PLAY_PAUSE: + usage = TRANSPORT_PLAY_PAUSE; + break; + case KC_MEDIA_SELECT: + usage = AL_CC_CONFIG; + break; + case KC_MAIL: + usage = AL_EMAIL; + break; + case KC_CALCULATOR: + usage = AL_CALCULATOR; + break; + case KC_MY_COMPUTER: + usage = AL_LOCAL_BROWSER; + break; + case KC_WWW_SEARCH: + usage = AC_SEARCH; + break; + case KC_WWW_HOME: + usage = AC_HOME; + break; + case KC_WWW_BACK: + usage = AC_BACK; + break; + case KC_WWW_FORWARD: + usage = AC_FORWARD; + break; + case KC_WWW_STOP: + usage = AC_STOP; + break; + case KC_WWW_REFRESH: + usage = AC_REFRESH; + break; + case KC_WWW_FAVORITES: + usage = AC_BOOKMARKS; + break; + } + return usage; +} + #ifdef __cplusplus } #endif diff --git a/keyboard/hhkb/Makefile.lufa b/keyboard/hhkb/Makefile.lufa index 5acc93a23..afd413d01 100644 --- a/keyboard/hhkb/Makefile.lufa +++ b/keyboard/hhkb/Makefile.lufa @@ -121,3 +121,6 @@ VPATH += $(TOP_DIR) include $(TOP_DIR)/protocol/lufa.mk include $(TOP_DIR)/common.mk include $(TOP_DIR)/rules.mk + +debug-on: EXTRAFLAGS += -DDEBUG +debug-on: all diff --git a/keyboard/hhkb/Makefile.vusb b/keyboard/hhkb/Makefile.vusb index 8caf23497..0e0e4a8cd 100644 --- a/keyboard/hhkb/Makefile.vusb +++ b/keyboard/hhkb/Makefile.vusb @@ -89,3 +89,6 @@ VPATH += $(TOP_DIR) include $(TOP_DIR)/protocol/vusb.mk include $(TOP_DIR)/common.mk include $(TOP_DIR)/rules.mk + +debug-on: EXTRAFLAGS += -DDEBUG +debug-on: all diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index 5dc5582ec..382996ec7 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -26,6 +26,7 @@ along with this program. If not, see . #include "print.h" #include "debug.h" #include "util.h" +#include "action.h" #include "keymap.h" @@ -49,33 +50,18 @@ along with this program. If not, see . { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO } \ } -#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) - -// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. -static const uint8_t PROGMEM fn_layer[] = { - 0, // Fn0 - 1, // Fn1 - 2, // Fn2 - 3, // Fn3 - 3, // Fn4 - 5, // Fn5 - 0, // Fn6 - 0 // Fn7 +static const action_t PROGMEM fn_actions[] = { + ACTION_LAYER(0), // Fn0 + ACTION_LAYER(1), // Fn1 + ACTION_LAYER_KEY(2, KC_SLASH), // Fn2 + ACTION_LAYER_KEY(3, KC_SCLN), // Fn3 + ACTION_LAYER(3), // Fn3 + ACTION_LAYER_KEY(5, KC_SPC), // Fn5 + NO_ACTION, // Fn6 + NO_ACTION, // Fn7 }; -// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. -// See layer.c for details. -static const uint8_t PROGMEM fn_keycode[] = { - KC_NO, // Fn0 - KC_NO, // Fn1 - KC_SLSH, // Fn2 - KC_SCLN, // Fn3 - KC_NO, // Fn4 - KC_SPC, // Fn5 - KC_NO, // Fn6 - KC_NO // Fn7 -}; static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Layer 0: Default Layer @@ -149,24 +135,11 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * `--------------------------------------------' * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel */ -#ifdef HOST_IWRAP -// iWRAP does not support mouse wheel, use these keycodes to remap as wheel -#define KC_KPPL KC_KP_PLUS -#define KC_KPMI KC_KP_MINUS -#define KC_KPAS KC_KP_ASTERISK -#define KC_KPSL KC_KP_SLASH - KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ - TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ - LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ - LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,NO, NO, NO, RSFT,NO, \ - LGUI,LALT, BTN1, RALT,FN4), -#else KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ LGUI,LALT, BTN1, RALT,FN4), -#endif /* Layer 4: Matias half keyboard style (Space) * ,-----------------------------------------------------------. @@ -188,33 +161,61 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { LGUI,LALT, FN5, RALT,RGUI), /* Layer5: another Mouse mode (Space) */ -#ifdef HOST_IWRAP - KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ - TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ - LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ - LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ - LGUI,LALT, FN5, RALT,RGUI), -#else KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ LGUI,LALT, FN5, RALT,RGUI), -#endif }; +#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) -uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) -{ - return KEYCODE(layer, row, col); + +/* legacy interface */ +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) { return 0; } +uint8_t keymap_fn_layer(uint8_t fn_bits) { return 0; } +uint8_t keymap_fn_keycode(uint8_t fn_bits) { return 0; } + + +action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { + /* convert from legacy keycode to action */ + uint8_t key = KEYCODE(layer, row, col); + action_t action; + switch (key) { + case KC_A ... KC_EXSEL: + action = (action_t)ACTION_KEY(key); + break; + case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE: + action = (action_t)ACTION_USAGE_SYSTEM(key2system(key)); + break; + case KC_AUDIO_MUTE ... KC_WWW_FAVORITES: + action = (action_t)ACTION_USAGE_CONSUMER(key2consumer(key)); + break; + case KC_MS_UP ... KC_MS_ACCEL2: + action = (action_t)ACTION_MOUSEKEY(key); + break; + case KC_LCTRL ... KC_LGUI: + action = (action_t)ACTION_LMODS(MOD_BIT(key)); + break; + case KC_RCTRL ... KC_RGUI: + action = (action_t)ACTION_RMODS(MOD_BIT(key)>>4); + break; + case KC_FN0 ... KC_FN7: + action = (action_t)pgm_read_word(&fn_actions[FN_INDEX(key)]); + break; + case KC_NO ... KC_UNDEFINED: + default: + action = (action_t)NO_ACTION; + break; + } + debug("action: "); debug_hex16(action.code); debug("\n"); + return action; } -uint8_t keymap_fn_layer(uint8_t index) -{ - return pgm_read_byte(&fn_layer[index]); -} -uint8_t keymap_fn_keycode(uint8_t index) +uint8_t keymap_process_event(keyevent_t event) { - return pgm_read_byte(&fn_keycode[index]); + action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); + action_exec(action, event); + return 0; } diff --git a/keyboard/hhkb/matrix.c b/keyboard/hhkb/matrix.c index fd0d6f97f..f53e36dbe 100644 --- a/keyboard/hhkb/matrix.c +++ b/keyboard/hhkb/matrix.c @@ -24,6 +24,7 @@ along with this program. If not, see . #include #include #include "print.h" +#include "debug.h" #include "util.h" #include "timer.h" #include "matrix.h" @@ -135,6 +136,12 @@ uint8_t matrix_cols(void) void matrix_init(void) { +#ifdef DEBUG + print_enable = true; + debug_enable = true; + debug_keyboard = true; +#endif + KEY_INIT(); // initialize matrix state: all keys off From 4324e163360db4c6ebd25cab74d09d42b3021278 Mon Sep 17 00:00:00 2001 From: tmk Date: Mon, 17 Dec 2012 03:06:21 +0900 Subject: [PATCH 02/30] Fix action of system and consumer usage. --- common/action.c | 97 --------------------------------- common/report.h | 119 ++++++++++++----------------------------- keyboard/hhkb/keymap.c | 4 +- 3 files changed, 37 insertions(+), 183 deletions(-) diff --git a/common/action.c b/common/action.c index d4aae207f..45e2276e7 100644 --- a/common/action.c +++ b/common/action.c @@ -415,89 +415,6 @@ static void register_code(uint8_t code) host_add_mods(MOD_BIT(code)); host_send_keyboard_report(); } -#ifdef MOUSEKEY_ENABLE - else if IS_MOUSEKEY(code) { - mousekey_on(code); - mousekey_send(); - } -#endif -#ifdef EXTRAKEY_ENABLE - else if IS_CONSUMER(code) { - uint16_t usage = 0; - switch (code) { - case KC_AUDIO_MUTE: - usage = AUDIO_MUTE; - break; - case KC_AUDIO_VOL_UP: - usage = AUDIO_VOL_UP; - break; - case KC_AUDIO_VOL_DOWN: - usage = AUDIO_VOL_DOWN; - break; - case KC_MEDIA_NEXT_TRACK: - usage = TRANSPORT_NEXT_TRACK; - break; - case KC_MEDIA_PREV_TRACK: - usage = TRANSPORT_PREV_TRACK; - break; - case KC_MEDIA_STOP: - usage = TRANSPORT_STOP; - break; - case KC_MEDIA_PLAY_PAUSE: - usage = TRANSPORT_PLAY_PAUSE; - break; - case KC_MEDIA_SELECT: - usage = AL_CC_CONFIG; - break; - case KC_MAIL: - usage = AL_EMAIL; - break; - case KC_CALCULATOR: - usage = AL_CALCULATOR; - break; - case KC_MY_COMPUTER: - usage = AL_LOCAL_BROWSER; - break; - case KC_WWW_SEARCH: - usage = AC_SEARCH; - break; - case KC_WWW_HOME: - usage = AC_HOME; - break; - case KC_WWW_BACK: - usage = AC_BACK; - break; - case KC_WWW_FORWARD: - usage = AC_FORWARD; - break; - case KC_WWW_STOP: - usage = AC_STOP; - break; - case KC_WWW_REFRESH: - usage = AC_REFRESH; - break; - case KC_WWW_FAVORITES: - usage = AC_BOOKMARKS; - break; - } - host_consumer_send(usage); - } - else if IS_SYSTEM(code) { - uint16_t usage = 0; - switch (code) { - case KC_SYSTEM_POWER: - usage = SYSTEM_POWER_DOWN; - break; - case KC_SYSTEM_SLEEP: - usage = SYSTEM_SLEEP; - break; - case KC_SYSTEM_WAKE: - usage = SYSTEM_WAKE_UP; - break; - } - host_system_send(usage); - } -#endif } static void unregister_code(uint8_t code) @@ -510,20 +427,6 @@ static void unregister_code(uint8_t code) host_del_mods(MOD_BIT(code)); host_send_keyboard_report(); } -#ifdef MOUSEKEY_ENABLE - else if IS_MOUSEKEY(code) { - mousekey_off(code); - mousekey_send(); - } -#endif -#ifdef EXTRAKEY_ENABLE - else if IS_CONSUMER(code) { - host_consumer_send(0x0000); - } - else if IS_SYSTEM(code) { - host_system_send(0x0000); - } -#endif } static void register_mods(uint8_t mods) diff --git a/common/report.h b/common/report.h index e8582d81f..0995189b3 100644 --- a/common/report.h +++ b/common/report.h @@ -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 @@ -19,7 +19,7 @@ along with this program. If not, see . #define REPORT_H #include -#include +#include "keycode.h" /* report id */ @@ -34,8 +34,9 @@ along with this program. If not, see . #define MOUSE_BTN4 (1<<3) #define MOUSE_BTN5 (1<<4) -// Consumer Page(0x0C) -// following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx +/* Consumer Page(0x0C) + * following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx + */ #define AUDIO_MUTE 0x00E2 #define AUDIO_VOL_UP 0x00E9 #define AUDIO_VOL_DOWN 0x00EA @@ -43,10 +44,12 @@ along with this program. If not, see . #define TRANSPORT_PREV_TRACK 0x00B6 #define TRANSPORT_STOP 0x00B7 #define TRANSPORT_PLAY_PAUSE 0x00CD +/* application launch */ #define AL_CC_CONFIG 0x0183 #define AL_EMAIL 0x018A #define AL_CALCULATOR 0x0192 #define AL_LOCAL_BROWSER 0x0194 +/* application control */ #define AC_SEARCH 0x0221 #define AC_HOME 0x0223 #define AC_BACK 0x0224 @@ -54,20 +57,20 @@ along with this program. If not, see . #define AC_STOP 0x0226 #define AC_REFRESH 0x0227 #define AC_BOOKMARKS 0x022A -// supplement for Bluegiga iWRAP HID(not supported by Windows?) +/* supplement for Bluegiga iWRAP HID(not supported by Windows?) */ #define AL_LOCK 0x019E #define TRANSPORT_RECORD 0x00B2 #define TRANSPORT_REWIND 0x00B4 #define TRANSPORT_EJECT 0x00B8 #define AC_MINIMIZE 0x0206 -// Generic Desktop Page(0x01) +/* Generic Desktop Page(0x01) - system power control */ #define SYSTEM_POWER_DOWN 0x0081 #define SYSTEM_SLEEP 0x0082 #define SYSTEM_WAKE_UP 0x0083 -// key report size(NKRO or boot mode) +/* key report size(NKRO or boot mode) */ #if defined(HOST_PJRC) # include "usb.h" # if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS @@ -99,84 +102,32 @@ typedef struct { } __attribute__ ((packed)) report_mouse_t; -static uint16_t key2system(uint8_t key) -{ - uint16_t usage = 0; - switch (key) { - case KC_SYSTEM_POWER: - usage = SYSTEM_POWER_DOWN; - break; - case KC_SYSTEM_SLEEP: - usage = SYSTEM_SLEEP; - break; - case KC_SYSTEM_WAKE: - usage = SYSTEM_WAKE_UP; - break; - } - return usage; -} +/* keycode to system usage */ +#define KEYCODE2SYSTEM(key) \ + (key == KC_SYSTEM_POWER ? SYSTEM_POWER_DOWN : \ + (key == KC_SYSTEM_SLEEP ? SYSTEM_SLEEP : \ + (key == KC_SYSTEM_WAKE ? SYSTEM_WAKE_UP : 0))) -static uint16_t key2consumer(uint8_t key) -{ - uint16_t usage = 0; - switch (key) { - case KC_AUDIO_MUTE: - usage = AUDIO_MUTE; - break; - case KC_AUDIO_VOL_UP: - usage = AUDIO_VOL_UP; - break; - case KC_AUDIO_VOL_DOWN: - usage = AUDIO_VOL_DOWN; - break; - case KC_MEDIA_NEXT_TRACK: - usage = TRANSPORT_NEXT_TRACK; - break; - case KC_MEDIA_PREV_TRACK: - usage = TRANSPORT_PREV_TRACK; - break; - case KC_MEDIA_STOP: - usage = TRANSPORT_STOP; - break; - case KC_MEDIA_PLAY_PAUSE: - usage = TRANSPORT_PLAY_PAUSE; - break; - case KC_MEDIA_SELECT: - usage = AL_CC_CONFIG; - break; - case KC_MAIL: - usage = AL_EMAIL; - break; - case KC_CALCULATOR: - usage = AL_CALCULATOR; - break; - case KC_MY_COMPUTER: - usage = AL_LOCAL_BROWSER; - break; - case KC_WWW_SEARCH: - usage = AC_SEARCH; - break; - case KC_WWW_HOME: - usage = AC_HOME; - break; - case KC_WWW_BACK: - usage = AC_BACK; - break; - case KC_WWW_FORWARD: - usage = AC_FORWARD; - break; - case KC_WWW_STOP: - usage = AC_STOP; - break; - case KC_WWW_REFRESH: - usage = AC_REFRESH; - break; - case KC_WWW_FAVORITES: - usage = AC_BOOKMARKS; - break; - } - return usage; -} +/* keycode to consumer usage */ +#define KEYCODE2CONSUMER(key) \ + (key == KC_AUDIO_MUTE ? AUDIO_MUTE : \ + (key == KC_AUDIO_VOL_UP ? AUDIO_VOL_UP : \ + (key == KC_AUDIO_VOL_DOWN ? AUDIO_VOL_DOWN : \ + (key == KC_MEDIA_NEXT_TRACK ? TRANSPORT_NEXT_TRACK : \ + (key == KC_MEDIA_PREV_TRACK ? TRANSPORT_PREV_TRACK : \ + (key == KC_MEDIA_STOP ? TRANSPORT_STOP : \ + (key == KC_MEDIA_PLAY_PAUSE ? TRANSPORT_PLAY_PAUSE : \ + (key == KC_MEDIA_SELECT ? AL_CC_CONFIG : \ + (key == KC_MAIL ? AL_EMAIL : \ + (key == KC_CALCULATOR ? AL_CALCULATOR : \ + (key == KC_MY_COMPUTER ? AL_LOCAL_BROWSER : \ + (key == KC_WWW_SEARCH ? AC_SEARCH : \ + (key == KC_WWW_HOME ? AC_HOME : \ + (key == KC_WWW_BACK ? AC_BACK : \ + (key == KC_WWW_FORWARD ? AC_FORWARD : \ + (key == KC_WWW_STOP ? AC_STOP : \ + (key == KC_WWW_REFRESH ? AC_REFRESH : \ + (key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))) #ifdef __cplusplus } diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index 382996ec7..477ef6c33 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -186,10 +186,10 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { action = (action_t)ACTION_KEY(key); break; case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE: - action = (action_t)ACTION_USAGE_SYSTEM(key2system(key)); + action = (action_t)ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(key)); break; case KC_AUDIO_MUTE ... KC_WWW_FAVORITES: - action = (action_t)ACTION_USAGE_CONSUMER(key2consumer(key)); + action = (action_t)ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(key)); break; case KC_MS_UP ... KC_MS_ACCEL2: action = (action_t)ACTION_MOUSEKEY(key); From 411de9cc22e927313a5a768f3bf41f2f99bca126 Mon Sep 17 00:00:00 2001 From: tmk Date: Wed, 9 Jan 2013 22:33:33 +0900 Subject: [PATCH 03/30] Add new layer actions. --- common/action.c | 396 +++++++++++++++++++---------------------- common/action.h | 152 +++++++++------- common/keyboard.c | 5 +- common/keyboard.h | 8 +- common/keymap.h | 1 - keyboard/hhkb/keymap.c | 78 ++++---- 6 files changed, 324 insertions(+), 316 deletions(-) diff --git a/common/action.c b/common/action.c index 45e2276e7..425a2b00f 100644 --- a/common/action.c +++ b/common/action.c @@ -1,6 +1,6 @@ #include "host.h" #include "timer.h" -//#include "keymap.h" +#include "keymap.h" #include "keycode.h" #include "keyboard.h" #include "mousekey.h" @@ -78,8 +78,6 @@ typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t; static kbdstate_t kbdstate = IDLE; static uint8_t fn_state_bits = 0; -static keyrecord_t delayed_fn = {}; -static keyrecord_t waiting_key = {}; static const char *state_str(kbdstate_t state) { @@ -96,17 +94,6 @@ static bool anykey_sent_to_host(void) } - -/* -static void layer_switch_on(uint8_t code); -static void layer_switch_off(uint8_t code); -static void key_action(uint8_t code, keyevent_t event); -static void key_pressed(uint8_t code, keyevent_t event); -static void key_released(uint8_t code, keyevent_t event); -static void mod_pressed(uint8_t code, keyevent_t event); -static void mod_released(uint8_t code, keyevent_t event); -*/ - static void register_code(uint8_t code); static void unregister_code(uint8_t code); static void register_mods(uint8_t mods); @@ -118,6 +105,7 @@ 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; @@ -125,10 +113,10 @@ static uint8_t tap_count = 0; /* layer */ uint8_t default_layer = 0; uint8_t current_layer = 0; -uint8_t waiting_layer = 0; +keyrecord_t delaying_layer = {}; -void action_exec(action_t action, keyevent_t event) +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) { @@ -137,6 +125,20 @@ void action_exec(action_t action, keyevent_t event) tap_count = 0; } + /* layer switch after LAYER_DELAY */ + if (delaying_layer.action.code && timer_elapsed(delaying_layer.event.time) > LAYER_DELAY) { + 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){}; + } + 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"); @@ -145,6 +147,7 @@ void action_exec(action_t action, keyevent_t event) switch (action.kind.id) { case ACT_LMODS: + // normal key or key plus mods if (event.pressed) { register_mods(action.key.mods); register_code(action.key.code); @@ -162,60 +165,9 @@ void action_exec(action_t action, keyevent_t event) unregister_mods(action.key.mods<<4); } break; - case ACT_LAYER: - switch (action.layer_key.code) { - case 0x00: // Momentary switch - // TODO: history of layer switch - if (event.pressed) { - layer_switch(action.layer_key.layer); - } else { - layer_switch(default_layer); - } - break; - case 0x01: // Oneshot switch - // TODO: - break; - case 0x02: // reserved - case 0x03: // reserved - break; - case 0xF0 ... 0xF7: // Tap to enable/disable - case 0xF8 ... 0xFF: // Tap to toggle layer - // TODO: - break; - default: // with keycode for tap - debug("tap: "); debug_hex(tap_count); debug("\n"); - // TODO: layer switch - // TODO: in case tap is interrupted by other key - - - if (event.pressed) { - // when any key down - if (host_has_anykey()) { - if (tap_count == 0) - register_code(action.layer_key.code); - } else { - } - - if (tap_count == 0) { - if (host_has_anykey()) { - register_code(action.layer_key.code); - } else { - waiting_layer = action.layer_key.layer; - } - } - // register key when press after a tap - if (tap_count > 0) { - register_code(action.layer_key.code); - } - } else { - // type key after tap - if (tap_count == 1) { - register_code(action.layer_key.code); - } - unregister_code(action.layer_key.code); - } - break; - } + case ACT_LMOD_TAP: + break; + case ACT_RMOD_TAP: break; case ACT_USAGE: #ifdef EXTRAKEY_ENABLE @@ -248,8 +200,172 @@ void action_exec(action_t action, keyevent_t event) } #endif break; - case ACT_LMOD_TAP: - case ACT_RMOD_TAP: + case ACT_LAYER_PRESSED: + // layer action when pressed + switch (action.layer.code) { + case 0x00: + if (event.pressed) { + layer_switch(action.layer.opt); + } + break; + case 0xF0: + // TODO: tap toggle + break; + case 0xFF: + if (event.pressed) { + default_layer = action.layer.opt; + layer_switch(default_layer); + } + 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 { + delaying_layer = (keyrecord_t){ + .event = event, + .action = action, + .mods = keyboard_report->mods + }; + } + } else if (tap_count > 0) { + register_code(action.layer.code); + } + } else { + // type key after tap + if (tap_count == 1) { + delaying_layer = (keyrecord_t){}; + register_code(action.layer.code); + } + unregister_code(action.layer.code); + } + break; + } + break; + case ACT_LAYER_RELEASED: + switch (action.layer.code) { + case 0x00: + if (event.pressed) { + layer_switch(action.layer.opt); + } + break; + case 0xF0: + // Ignored. LAYER_RELEASED with tap toggle is invalid action. + break; + case 0xFF: + if (!event.pressed) { + default_layer = action.layer.opt; + layer_switch(default_layer); + } + break; + default: + // Ignored. LAYER_RELEASED with tap key is invalid action. + break; + } + break; + case ACT_LAYER_BIT: + switch (action.layer.code) { + case 0x00: + if (event.pressed) { + layer_switch(current_layer | action.layer.opt); + } else { + layer_switch(current_layer & ~action.layer.opt); + } + break; + case 0xF0: + // TODO: tap toggle + break; + case 0xFF: + // change default layer + if (event.pressed) { + default_layer = current_layer | action.layer.opt; + layer_switch(default_layer); + } else { + default_layer = current_layer & ~action.layer.opt; + layer_switch(default_layer); + } + 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 { + delaying_layer = (keyrecord_t){ + .event = event, + .action = action, + .mods = keyboard_report->mods + }; + } + } else if (tap_count > 0) { + register_code(action.layer.code); + } + } else { + if (tap_count == 0) { + // no tap + layer_switch(current_layer & ~action.layer.opt); + } else if (tap_count == 1) { + // tap + register_code(action.layer.code); + } + unregister_code(action.layer.code); + } + break; + } + case ACT_LAYER_EXT: + switch (action.layer.opt) { + case 0x00: + // set default layer when pressed + switch (action.layer.code) { + case 0x00: + if (event.pressed) { + layer_switch(default_layer); + } + break; + case 0xF0: + // TODO: tap toggle + break; + case 0xFF: + if (event.pressed) { + default_layer = current_layer; + layer_switch(default_layer); + } + break; + default: + // TODO: tap key + break; + } + break; + case 0x01: + // set default layer when released + switch (action.layer.code) { + case 0x00: + if (!event.pressed) { + layer_switch(default_layer); + } + break; + case 0xFF: + if (!event.pressed) { + default_layer = current_layer; + layer_switch(default_layer); + } + break; + case 0xF0: + default: + // Ignore tap. + if (!event.pressed) { + layer_switch(default_layer); + } + break; + } + break; + } + break; case ACT_MACRO: case ACT_COMMAND: case ACT_FUNCTION: @@ -263,142 +379,6 @@ void action_exec(action_t action, keyevent_t event) } -#if 0 -/* Key Action */ -inline -static void key_action(uint8_t code, keyevent_t event) -{ - if (event.pressed) - key_pressed(code, event); - else - key_released(code, event); -} - -void fn_action(uint8_t code, keyevent_t event) -{ -} - -/* Key */ -inline static void key_pressed(uint8_t code, keyevent_t event) -{ - uint8_t tmp_mods; - switch (kbdstate) { - case IDLE: - register_code(code); - NEXT(PRESSING); - break; - case PRESSING: - register_code(code); - break; - case DELAYING: - waiting_key = (keyrecord_t) { - .event = event, - .code = code, - .mods = keyboard_report->mods, - .time = timer_read() - }; - NEXT(WAITING); - break; - case WAITING: - // play back key stroke - tmp_mods = keyboard_report->mods; - host_set_mods(delayed_fn.mods); - register_code(delayed_fn.code); - host_set_mods(waiting_key.mods); - register_code(waiting_key.code); - host_set_mods(tmp_mods); - register_code(code); - NEXT(IDLE); - break; - } -} -inline static void key_released(uint8_t code, keyevent_t event) -{ - uint8_t tmp_mods; - switch (kbdstate) { - case IDLE: - unregister_code(code); - break; - case PRESSING: - unregister_code(code); - if (!anykey_sent_to_host()) - NEXT(IDLE); - break; - case DELAYING: - unregister_code(code); - break; - case WAITING: - if (code == waiting_key.code) { - layer_switch_on(delayed_fn.code); - NEXT(IDLE); - // process waiting_key - tmp_mods = keyboard_report->mods; - host_set_mods(waiting_key.mods); - keymap_process_event(waiting_key.event); - host_set_mods(tmp_mods); - keymap_process_event(event); - } else { - unregister_code(code); - } - break; - } -} - -/* layer switch momentary */ -inline static void layerkey_pressed(uint8_t code, keyevent_t event) -{ - uint8_t tmp_mods; - switch (kbdstate) { - case IDLE: - layer_switch_on(code); - break; - case PRESSING: - // ignore - break; - case DELAYING: - waiting_key = (keyrecord_t) { - .event = event, - .code = code, - .mods = keyboard_report->mods, - .time = timer_read() - }; - NEXT(WAITING); - break; - case WAITING: - tmp_mods = keyboard_report->mods; - host_set_mods(delayed_fn.mods); - register_code(delayed_fn.code); - host_set_mods(waiting_key.mods); - register_code(waiting_key.code); - host_set_mods(tmp_mods); - 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; - } -} -inline static void layerkey_released(uint8_t code, keyevent_t event) -{ - switch (kbdstate) { - case IDLE: - layer_switch_off(code); - break; - case PRESSING: - case DELAYING: - case WAITING: - if (layer_switch_off(code)) - NEXT(IDLE); - break; - } -} -#endif - - static void register_code(uint8_t code) { if (code == KC_NO) { diff --git a/common/action.h b/common/action.h index 08f8c5608..942ce191a 100644 --- a/common/action.h +++ b/common/action.h @@ -15,10 +15,6 @@ ACT_LMODS(0000) 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 -??? - 0 0 0 0| mods(4) | 1 1 1 1 0| tap(3) Lmods+tap Switch(enable/disable) - 0 0 0 0| mods(4) | 1 1 1 1 1| tap(3) Lmods+tap Toggle(on/off) -??? ACT_RMODS(0001) 0 0 0 1| 0 0 0 0| 0 0 0 0 0 0 0 0 No action(not used) @@ -28,10 +24,6 @@ ACT_RMODS(0001) 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 -??? - 0 0 0 1| mods(4) | 1 1 1 1 0| tap(3) Rmods+tap Switch(enable/disable) - 0 0 0 1| mods(4) | 1 1 1 1 1| tap(3) Rmods+tap Toggle(on/off) -??? ACT_LMODS_TAP(0010) 0 0 1 0| 0 0 0 0| X X X X X X X X (reserved)[00-FF] @@ -45,36 +37,47 @@ ACT_RMODS_TAP(0011) 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] -ACT_LAYER(0100) - 0 1 0 0| layer(4) | 0 0 0 0 0 0| 0 0 Momentary - 0 1 0 0| layer(4) | 0 0 0 0 0 0| 0 1 Oneshot - 0 1 0 0| layer(4) | 0 0 0 0 0 0| 1 0 (reserved) - 0 1 0 0| layer(4) | 0 0 0 0 0 0| 1 1 (reserved) - 0 1 0 0| layer(4) | keycode(8) Fn momentary + tap Key - 0 1 0 0| layer(4) | 1 1 1 1 0| tap(3) Fn+tap Switch(enable/disable) - 0 1 0 0| layer(4) | 1 1 1 1 1| tap(3) Fn+tap Toggle(on/off) - -ACT_USAGE(0101) - 0 1 0 1| 0 0| usage(10) System usage - 0 1 0 1| 0 1| usage(10) Consumer usage - 0 1 0 1| 1 0| usage(10) (reserved) - 0 1 0 1| 1 1| usage(10) (reserved) +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 1 0| X X X X| keycode(8) Mouse key + 0 1 0 1| X X X X| keycode(8) Mouse key ??? TODO: refactor - 0 1 1 0| 0 0 X X| accel(5) |cursor(3) Mouse key - 0 1 1 0| 0 1 X X| accel(5) |wheel(3) Mouse key - 0 1 1 0| 1 0 X X| button(8) Mouse key - 0 1 1 0| 1 1 X X| button(8) Mouse key + 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 ??? - 0 1 1 1| (reserved) - 1 0 0 0| (reserved) - 1 0 0 1| (reserved) - 1 0 1 0| (reserved) - 1 0 1 1| (reserved) - 1 1 0 0| (reserved) +Layer Action +------------ +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 +1011|0000|0000 0000 set default layer when pressed +1011|0001|0000 0000 set default layer when released + +1000|LLLL|1111 0000 set layer L when pressed + tap toggle +1001|LLLL|1111 0000 set layer L when released[tap is ignored/not used] +1010|BBBB|1111 0000 on/off bit B when pressed/released + tap toggle +1011|0000|1111 0000 set default layer when pressed + tap toggle +1011|0001|1111 0000 set default layer when released[tap is ignored/not used] + +1000|LLLL|1111 1111 set L to default layer when pressed +1001|LLLL|1111 1111 set L to default layer when released +1010|BBBB|1111 1111 on/off bit B of default layer when pressed/released +1011|0000|1111 1111 set current to default layer when pressed +1011|0001|1111 1111 set current to default layer when released + +1000|LLLL| keycode set layer L when pressed + tap key +1001|LLLL| keyocde set layer L when released[tap is ignored/not used] +1010|BBBB| keyocde on/off bit B when pressed/released + tap key +1011|0000| keyocde set default layer when pressed + tap key +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) @@ -88,25 +91,32 @@ ACT_FUNCTION(1111) 1 1 1 1| function address(4K range) Function Macro record(dynamicly) Macro play(dynamicly) +TODO: modifier + [tap key /w mod] + : layerkey + [tap key /w mod] + for example: LShift + '('[Shift+9] and RShift + ')'[Shift+0] + http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478.html#p90052 */ enum action_id { - ACT_LMODS = 0, - ACT_RMODS, - ACT_LMOD_TAP, - ACT_RMOD_TAP, - ACT_LAYER, - ACT_USAGE, - ACT_MOUSEKEY, - ACT_MACRO = 14, - ACT_COMMAND = 15, - ACT_FUNCTION = 16 + 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 }; // TODO: not portable across compiler/endianness? /* In avr-gcc bit fields seems to be assigned from LSB(bit0) to MSB(bit15). -AVR seems like little endian in avr-gcc. +AVR looks like a little endian in avr-gcc. Byte order and bit order of 0x1234: Big endian: 15 ... 8 7 ... 210 @@ -127,17 +137,11 @@ typedef union { uint16_t mods :4; uint16_t kind :4; } key; - struct action_layer_key { + struct action_layer { uint16_t code :8; - uint16_t layer :4; + uint16_t opt :4; uint16_t kind :4; - } layer_key; - struct action_layer_tap { - uint16_t count :3; - uint16_t rest :5; - uint16_t layer :4; - uint16_t kind :4; - } layer_tap; + } layer; struct action_usage { uint16_t code :10; uint16_t page :2; @@ -157,7 +161,14 @@ enum stroke_cmd { STROKE_ALLUP, /* release all keys in reverse order */ }; -void action_exec(action_t act, keyevent_t event); +typedef struct { + keyevent_t event; + action_t action; + uint8_t mods; +} keyrecord_t; + + +void action_exec(keyevent_t event); /* void key_action(uint8_t code, keyevent_t event); void mod_action(uint8_t code, keyevent_t event); @@ -166,9 +177,12 @@ void fn_action(uint8_t code, keyevent_t event); /* action_t utility */ +/* +#define ACTION_NO { .code = 0 } #define ACTION(kind, param) { .code = ((kind)<<12 | (param)) } -#define NO_ACTION ACTION(0, 0) -#define LAYER_PARAM(layer, key) ((layer)<<8|(key)) +*/ +#define ACTION_NO 0 +#define ACTION(kind, param) ((kind)<<12 | (param)) /* Key & Mods */ #define ACTION_KEY(key) ACTION(ACT_LMODS, key) @@ -185,12 +199,28 @@ void fn_action(uint8_t code, keyevent_t event); /* 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)) + /* Layer Switch */ -#define ACTION_LAYER(layer) ACTION(ACT_LAYER, (layer)<<8 | 0x00) -#define ACTION_LAYER_ONESHOT(layer) ACTION(ACT_LAYER, (layer)<<8 | 0x01) -#define ACTION_LAYER_KEY(layer, key) ACTION(ACT_LAYER, (layer)<<8 | (key)) -#define ACTION_LAYER_SWITCH(layer, tap) ACTION(ACT_LAYER, (layer)<<8 | 0xF0 | (tap)) -#define ACTION_LAYER_TOGGLE(layer, tap) ACTION(ACT_LAYER, (layer)<<8 | 0xF1 | (tap)) +#define ACTION_LAYER_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) +#define ACTION_LAYER_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0x00) +#define ACTION_LAYER_BIT(bits) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0x00) +#define ACTION_LAYER_TO_DEFAULT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0x00) +#define ACTION_LAYER_TO_DEFAULT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0x00) + +#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xF0) +#define ACTION_LAYER_BIT_TAP_TOGGLE(layer) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0xF0) +#define ACTION_LAYER_DEFAULT_TAP_TOGGLE ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xF0) + +#define ACTION_LAYER_DEFAULT_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0xFF) + +#define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | (key)) +#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (layer)<<8 | (key)) +#define ACTION_LAYER_DEFAULT_SET_TAP_KEY(key) ACTION(ACT_LAYER_EXT, 0x0<<8 | (key)) + /* HID Usage */ #define ACTION_USAGE_PAGE_SYSTEM 0 #define ACTION_USAGE_PAGE_CONSUMER 1 diff --git a/common/keyboard.c b/common/keyboard.c index 5e95fb984..1e0b8c3ed 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -65,9 +65,10 @@ void keyboard_task(void) for (int c = 0; c < MATRIX_COLS; c++) { if (matrix_change & (1<. } +/* static const action_t PROGMEM fn_actions[] = { - ACTION_LAYER(0), // Fn0 - ACTION_LAYER(1), // Fn1 - ACTION_LAYER_KEY(2, KC_SLASH), // Fn2 - ACTION_LAYER_KEY(3, KC_SCLN), // Fn3 - ACTION_LAYER(3), // Fn3 - ACTION_LAYER_KEY(5, KC_SPC), // Fn5 - NO_ACTION, // Fn6 - NO_ACTION, // Fn7 + 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 + 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 }; @@ -91,7 +103,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |-----------------------------------------------------------| * |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | * |-----------------------------------------------------------| - * |Shift | | | | | | +| -|End|PgD|Dow|Shift |xxx| + * |Shift | | | | | | +| -|End|PgD|Dow|Shift |Fn0| * `-----------------------------------------------------------' * |Gui |Alt |Space |Alt |xxx| * `--------------------------------------------' @@ -99,8 +111,8 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, BSPC, \ LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ - LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN1, \ - LGUI,LALT, SPC, RALT,FN7), + LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN0, \ + LGUI,LALT, SPC, RALT,RGUI), /* Layer 2: Vi mode (Slash) * ,-----------------------------------------------------------. @@ -110,7 +122,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |-----------------------------------------------------------| * |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | |Return | * |-----------------------------------------------------------| - * |Shift | | | | | |Hom|PgD|PgUlEnd|xxx|Shift | | + * |Shift | | | | | |Hom|PgD|PgUlEnd|Fn0|Shift | | * `-----------------------------------------------------------' * |Gui|Alt |Space |Alt |Gui| * `-------------------------------------------' @@ -118,7 +130,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \ LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \ - LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, RSFT,NO, \ + LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN0, RSFT,NO, \ LGUI,LALT, SPC, RALT,RGUI), /* Layer 3: Mouse mode (Semicolon) @@ -127,19 +139,19 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |-----------------------------------------------------------| * |Tab |MwL|MwU|McU|MwD|MwR|MwL|MwD|MwU|MwR| | | |Backs| * |-----------------------------------------------------------| - * |Contro| |McL|McD|McR| |McL|McD|McU|McR|xxx| |Return | + * |Contro| |McL|McD|McR| |McL|McD|McU|McR|Fn0| |Return | * |-----------------------------------------------------------| * |Shift |Mb4|Mb5|Mb1|Mb2|Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | | * `-----------------------------------------------------------' - * |Gui |Alt |Mb1 |Alt |Gui| + * |Gui |Alt |Mb1 |Alt |Fn0| * `--------------------------------------------' * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel */ KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ - LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ + LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, \ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ - LGUI,LALT, BTN1, RALT,FN4), + LGUI,LALT, BTN1, RALT,FN0), /* Layer 4: Matias half keyboard style (Space) * ,-----------------------------------------------------------. @@ -151,21 +163,21 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |-----------------------------------------------------------| * |Shift | /| .| ,| M| N| B| V| C| X| Z|Shift | | * `-----------------------------------------------------------' - * |Gui |Alt |xxxxxxxxxxxxxxxxxxxxxxx|Alt |Gui| + * |Gui |Alt | Fn0 |Alt |Gui| * `--------------------------------------------' */ KEYMAP(MINS,0, 9, 8, 7, 6, 5, 4, 3, 2, 1, NO, NO, NO, ESC, \ BSPC,P, O, I, U, Y, T, R, E, W, Q, NO, NO, TAB, \ LCTL,SCLN,L, K, J, H, G, F, D, S, A, RCTL,RCTL, \ LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT,NO, \ - LGUI,LALT, FN5, RALT,RGUI), + LGUI,LALT, FN0, RALT,RGUI), /* Layer5: another Mouse mode (Space) */ KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ - LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ + LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, \ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ - LGUI,LALT, FN5, RALT,RGUI), + LGUI,LALT, FN0, RALT,RGUI), }; #define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) @@ -183,39 +195,31 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { action_t action; switch (key) { case KC_A ... KC_EXSEL: - action = (action_t)ACTION_KEY(key); + action.code = ACTION_KEY(key); break; case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE: - action = (action_t)ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(key)); + action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(key)); break; case KC_AUDIO_MUTE ... KC_WWW_FAVORITES: - action = (action_t)ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(key)); + action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(key)); break; case KC_MS_UP ... KC_MS_ACCEL2: - action = (action_t)ACTION_MOUSEKEY(key); + action.code = ACTION_MOUSEKEY(key); break; case KC_LCTRL ... KC_LGUI: - action = (action_t)ACTION_LMODS(MOD_BIT(key)); + action.code = ACTION_LMODS(MOD_BIT(key)); break; case KC_RCTRL ... KC_RGUI: - action = (action_t)ACTION_RMODS(MOD_BIT(key)>>4); + action.code = ACTION_RMODS(MOD_BIT(key)>>4); break; case KC_FN0 ... KC_FN7: - action = (action_t)pgm_read_word(&fn_actions[FN_INDEX(key)]); + action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]); break; case KC_NO ... KC_UNDEFINED: default: - action = (action_t)NO_ACTION; + action.code = ACTION_NO; break; } debug("action: "); debug_hex16(action.code); debug("\n"); return action; } - - -uint8_t keymap_process_event(keyevent_t event) -{ - action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); - action_exec(action, event); - return 0; -} From 32633a42c74c65462370ef4a39a44a5784a98a06 Mon Sep 17 00:00:00 2001 From: tmk Date: Sun, 13 Jan 2013 10:24:20 +0900 Subject: [PATCH 04/30] Fix tap key using delaying_layer and waiting_key. --- common/action.c | 167 +++++++++++++++++++++++++++++++++-------- common/host.c | 5 ++ common/host.h | 3 + common/keyboard.c | 2 +- keyboard/hhkb/keymap.c | 8 +- 5 files changed, 152 insertions(+), 33 deletions(-) diff --git a/common/action.c b/common/action.c index 425a2b00f..1a86f16d3 100644 --- a/common/action.c +++ b/common/action.c @@ -115,29 +115,25 @@ uint8_t default_layer = 0; uint8_t current_layer = 0; keyrecord_t delaying_layer = {}; +keyrecord_t waiting_key = {}; -void action_exec(keyevent_t event) +// 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) { - /* 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; - } +} +static void waiting_key_dequeue(keyevent_t event) +{ +} +*/ - /* layer switch after LAYER_DELAY */ - if (delaying_layer.action.code && timer_elapsed(delaying_layer.event.time) > LAYER_DELAY) { - 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){}; - } - action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); +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"); @@ -146,29 +142,54 @@ void action_exec(keyevent_t event) debug("key.mods: "); debug_hex(action.key.mods); debug("\n"); switch (action.kind.id) { + /* Key and Mods */ case ACT_LMODS: // normal key or key plus mods if (event.pressed) { - register_mods(action.key.mods); + uint8_t tmp_mods = host_get_mods(); + if (action.key.mods) { + host_add_mods(action.key.mods); + host_send_keyboard_report(); + } register_code(action.key.code); + if (action.key.mods && action.key.code) { + host_set_mods(tmp_mods); + host_send_keyboard_report(); + } } else { + if (action.key.mods && !action.key.code) { + host_del_mods(action.key.mods); + host_send_keyboard_report(); + } unregister_code(action.key.code); - unregister_mods(action.key.mods); } break; case ACT_RMODS: if (event.pressed) { - register_mods(action.key.mods<<4); + uint8_t tmp_mods = host_get_mods(); + if (action.key.mods) { + host_add_mods(action.key.mods<<4); + host_send_keyboard_report(); + } register_code(action.key.code); + if (action.key.mods && action.key.code) { + host_set_mods(tmp_mods); + host_send_keyboard_report(); + } } else { + if (action.key.mods && !action.key.code) { + host_del_mods(action.key.mods<<4); + host_send_keyboard_report(); + } unregister_code(action.key.code); - unregister_mods(action.key.mods<<4); } break; case ACT_LMOD_TAP: break; case ACT_RMOD_TAP: break; + + /* other HID usage */ case ACT_USAGE: #ifdef EXTRAKEY_ENABLE switch (action.usage.page) { @@ -189,6 +210,8 @@ void action_exec(keyevent_t event) } #endif break; + + /* Mouse key */ case ACT_MOUSEKEY: #ifdef MOUSEKEY_ENABLE if (event.pressed) { @@ -200,6 +223,8 @@ void action_exec(keyevent_t event) } #endif break; + + /* Layer key */ case ACT_LAYER_PRESSED: // layer action when pressed switch (action.layer.code) { @@ -228,19 +253,25 @@ void action_exec(keyevent_t event) delaying_layer = (keyrecord_t){ .event = event, .action = action, - .mods = keyboard_report->mods + .mods = host_get_mods() }; } } else if (tap_count > 0) { register_code(action.layer.code); } } else { - // type key after tap - if (tap_count == 1) { - delaying_layer = (keyrecord_t){}; - register_code(action.layer.code); + // 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); } - unregister_code(action.layer.code); + delaying_layer = (keyrecord_t){}; } break; } @@ -366,12 +397,87 @@ void action_exec(keyevent_t event) break; } break; + + /* Extentions */ case ACT_MACRO: case ACT_COMMAND: case ACT_FUNCTION: default: break; } +} + +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; + } + + /* 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 */ + 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 */ + 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){}; + } + } + /* 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){}; + + /* 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); + } + } + + action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); + + /* 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() + }; + } else { + process(event, action); + } + } else { + process(event, action); + } /* last event */ last_event = event; @@ -451,5 +557,6 @@ static void layer_switch(uint8_t new_layer) current_layer = new_layer; clear_keyboard_but_mods(); // To avoid stuck keys + // TODO: update mods with full scan of matrix? if modifier changes between layers } } diff --git a/common/host.c b/common/host.c index 28c8a819f..6ed3d780f 100644 --- a/common/host.c +++ b/common/host.c @@ -127,6 +127,11 @@ void host_clear_keys(void) } } +uint8_t host_get_mods(void) +{ + return keyboard_report->mods; +} + void host_add_mods(uint8_t mods) { keyboard_report->mods |= mods; diff --git a/common/host.h b/common/host.h index 4f1f234a9..c59fbfee6 100644 --- a/common/host.h +++ b/common/host.h @@ -51,10 +51,13 @@ void host_consumer_send(uint16_t data); void host_add_key(uint8_t key); void host_del_key(uint8_t key); void host_clear_keys(void); + +uint8_t host_get_mods(void); void host_add_mods(uint8_t mods); void host_del_mods(uint8_t mods); void host_set_mods(uint8_t mods); void host_clear_mods(void); + uint8_t host_has_anykey(void); uint8_t host_has_anymod(void); uint8_t host_get_first_key(void); diff --git a/common/keyboard.c b/common/keyboard.c index 1e0b8c3ed..4e955e129 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -68,7 +68,7 @@ void keyboard_task(void) action_exec((keyevent_t){ .key = (keypos_t){ .row = r, .col = c }, .pressed = (matrix_row & (1<>4); break; +*/ case KC_FN0 ... KC_FN7: action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]); break; From f609712da3b94ea36612a6f210bd6ce902b74631 Mon Sep 17 00:00:00 2001 From: tmk Date: Tue, 15 Jan 2013 00:06:52 +0900 Subject: [PATCH 05/30] 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 1a86f16d3..389fc5df1 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 4e955e129..2e32e91e0 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 116653661..cf85b1233 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 9fe1237aa..38461290b 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; } From 9f95e9cc27f2edf4336124b01c05d03dcd5ee5ac Mon Sep 17 00:00:00 2001 From: tmk Date: Tue, 15 Jan 2013 19:04:58 +0900 Subject: [PATCH 06/30] Add support partly for modifier with tap key. --- common/action.c | 249 +++++++++++++++++++++++++---------------- common/action.h | 151 ++++++++++++------------- keyboard/hhkb/keymap.c | 18 +-- 3 files changed, 234 insertions(+), 184 deletions(-) diff --git a/common/action.c b/common/action.c index 389fc5df1..7299a874a 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 942ce191a..3115c67f4 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 +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_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(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_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] +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 -??? +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 -Layer Action ------------- 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_COMMAND(1110) - 1 1 1 0| option(4) | comamnd id(8) Built-in Command exec +ACT_MACRO(1100): +1100|opt | id(8) Macro play +1100|1111| id(8) Macro record -ACT_FUNCTION(1111) - 1 1 1 1| function address(4K range) Function +ACT_COMMAND(1110): +1110|opt | id(8) Built-in Command exec + +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 38461290b..e29b37b16 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), From 567b2ae5259634a5293afbc6a710a19d7c45dcda Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 17 Jan 2013 11:46:38 +0900 Subject: [PATCH 07/30] Fix mods with tap key but some problems still exists. - stuck tap key after tapping. seq[mods(d), key(d), mods(u), key(u)] - tap key doesn't work when fast type. [key(d), mods(d), key(u), mods(u)] --- common/action.c | 168 ++++++++++++++++++++++++++++------------------ 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 @@ #include "action.h" -static void process(keyevent_t event, action_t action); +static void process(keyevent_t event); static void register_code(uint8_t code); static void unregister_code(uint8_t code); static void add_mods(uint8_t mods); @@ -30,19 +30,26 @@ static uint8_t tap_count = 0; /* layer */ uint8_t default_layer = 0; uint8_t current_layer = 0; -keyrecord_t delaying_layer = {}; +static keyrecord_t tapping_key = {}; +// time 0 means no event. +#define IS_TAPPING (tapping_key.event.time != 0) +/* TODO: +#define IS_TAPPING_KEY(key) (tapping_key.event.time != 0 && KEYEQ(tapping_key.event.key, key)) + */ /* waiting keys buffer */ #define WAITING_KEYS_BUFFER 3 static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {}; +// TODO: double buffer? +static keyrecord_t waiting_keys0[WAITING_KEYS_BUFFER] = {}; +static keyrecord_t waiting_keys1[WAITING_KEYS_BUFFER] = {}; static uint8_t waiting_keys_head = 0; -static bool waiting_keys_enqueue(keyevent_t event, action_t action) +static bool waiting_keys_enqueue(keyevent_t event) { debug("waiting_keys["); debug_dec(waiting_keys_head); debug("] = "); - debug_hex16(action.code); debug("\n"); + debug_hex8(event.key.row); debug_hex8(event.key.col); debug("\n"); // TODO event.key.raw 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; @@ -62,80 +69,64 @@ static bool waiting_keys_has(keypos_t key) 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"); + // TODO: no need action in waiting_keys? should get_action() in process()? + process(waiting_keys[i].event); } - host_set_mods(tmp_mods); waiting_keys_clear(); } 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) || + if (IS_TAPPING) { + /* when tap time elapses or waiting key is released */ + if ((timer_elapsed(tapping_key.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){}; + + // TODO process tapping_key: layer swich, modifier, ... + // action is needed? + debug("notap: process tapping_key.\n"); + process(tapping_key.event); /* 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)) { + /* when tapping key is released within tap time */ + else if (!event.pressed && KEYEQ(event.key, tapping_key.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); + debug("tap("); debug_hex8(tap_count); debug(")[tapping_key](register): "); debug_hex8(tapping_key.action.layer.code); debug("\n"); + register_code(tapping_key.action.layer.code); + tapping_key = (keyrecord_t){}; /* process waiting keys */ waiting_keys_process_in_current_layer(); } } - // not real event. event just to update delaying layer. + // not real event. event just to handle time out of tapping key. if (IS_NOEVENT(event)) { return; } - /* count tap when key is up */ + /* count up tap when key is up */ + // key: d u d u d + // tap: 0 1 1 2 2 + // key: u d u d u + // tap: 0 0 1 1 2 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); - } + /* store key events while tapping */ + if (IS_TAPPING) { + // TODO: action is needed? + waiting_keys_enqueue(event); } else { - process(event, action); + process(event); } /* last event */ @@ -143,9 +134,9 @@ void action_exec(keyevent_t event) } -static void process(keyevent_t event, action_t action) +static void process(keyevent_t event) { - //action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); + action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); debug("action: "); debug_hex16(action.code); if (event.pressed) debug("[down]\n"); else debug("[up]\n"); @@ -204,21 +195,39 @@ static void process(keyevent_t event, action_t action) case ACT_LMODS_TAP: if (event.pressed) { if (tap_count == 0) { - add_mods(action.key.mods); + if (host_has_anykey()) { + // This key is a modifier essentially. + // Prioritize mods when key jam or rollover + add_mods(action.key.mods); + } else { + if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { + // no tapping + add_mods(action.key.mods); + tapping_key = (keyrecord_t){}; + } else { + debug("tapping lmods("); debug_hex8(action.key.mods); debug(")\n"); + tapping_key = (keyrecord_t){ + .event = event, + .action = action, + .mods = host_get_mods() + }; + } + } } else { - debug("tap[lmods](register): "); debug_hex(tap_count); debug("\n"); + // pressed after tapping + debug("tap("); debug_hex(tap_count); debug(")[lmods](register): "); debug_hex8(action.key.code); debug("\n"); register_code(action.key.code); } } else { if (tap_count == 0) { + debug("tap(00)[lmods](del_mods): "); debug_hex8(action.key.mods); debug("\n"); del_mods(action.key.mods); } else if (tap_count == 1) { - debug("tap[lmods](register/unregister): "); debug_hex(tap_count); debug("\n"); + debug("tap(01)[lmods](del_mods/unregister): "); debug_hex8(action.key.mods); debug(" "); debug_hex8(action.key.code); 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"); + debug("tap("); debug_hex(tap_count); debug(")[lmods](unregister): "); debug_hex8(action.key.code); debug("\n"); unregister_code(action.key.code); } } @@ -226,21 +235,39 @@ static void process(keyevent_t event, action_t action) case ACT_RMODS_TAP: if (event.pressed) { if (tap_count == 0) { - add_mods(action.key.mods<<4); + if (host_has_anykey()) { + // This key is a modifier essentially. + // Prioritize mods when key jam or rollover + add_mods(action.key.mods<<4); + } else { + if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { + // no tapping + add_mods(action.key.mods<<4); + tapping_key = (keyrecord_t){}; + } else { + debug("tapping rmods("); debug_hex8(action.key.mods); debug(")\n"); + tapping_key = (keyrecord_t){ + .event = event, + .action = action, + .mods = host_get_mods() + }; + } + } } else { - debug("tap[rmods](register): "); debug_hex(tap_count); debug("\n"); + // pressed after tapping + debug("tap("); debug_hex(tap_count); debug(")[rmods](register): "); debug_hex8(action.key.code); debug("\n"); register_code(action.key.code); } } else { if (tap_count == 0) { + debug("tap(00)[rmods](del_mods): "); debug_hex8(action.key.mods); debug("\n"); del_mods(action.key.mods<<4); } else if (tap_count == 1) { - debug("tap[rmods](register/unregister): "); debug_hex(tap_count); debug("\n"); + debug("tap(01)[rmods](del_mods/unregister): "); debug_hex8(action.key.mods); debug(" "); debug_hex8(action.key.code); 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"); + debug("tap("); debug_hex(tap_count); debug(")[rmods](unregister): "); debug_hex8(action.key.code); debug("\n"); unregister_code(action.key.code); } } @@ -303,16 +330,22 @@ 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()) { + // This key is a normal key than a leyar key essentially. + // Prioritize 'tap key' when key jam or rollover 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, - .mods = host_get_mods() - }; + if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { + layer_switch(action.layer.opt); + tapping_key = (keyrecord_t){}; + } else { + debug("tapping layer("); debug_hex8(action.layer.opt); debug(")\n"); + tapping_key = (keyrecord_t){ + .event = event, + .action = action, + .mods = host_get_mods() + }; + } } } else if (tap_count > 0) { // pressed after tapping @@ -371,13 +404,14 @@ static void process(keyevent_t event, action_t action) } break; default: + // TODO: see ACT_LAYER_PRESSED code // with tap key if (event.pressed) { if (tap_count == 0) { if (host_has_anykey()) { register_code(action.layer.code); } else { - delaying_layer = (keyrecord_t){ + tapping_key = (keyrecord_t){ .event = event, .action = action, .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 . extern "C" { #endif +// TODO: union {raw = row:col} typedef struct { uint8_t row; uint8_t col; From ee7ce433357a1c1bbcaba54525fc5b5b5404aa82 Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 17 Jan 2013 15:00:41 +0900 Subject: [PATCH 08/30] Refactor struct keyevent_t. --- common/action.c | 13 +++++++++---- common/keyboard.c | 4 ++-- common/keyboard.h | 12 ++++++++---- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/common/action.c b/common/action.c index d5040479e..d01038301 100644 --- a/common/action.c +++ b/common/action.c @@ -47,7 +47,7 @@ static uint8_t waiting_keys_head = 0; static bool waiting_keys_enqueue(keyevent_t event) { debug("waiting_keys["); debug_dec(waiting_keys_head); debug("] = "); - debug_hex8(event.key.row); debug_hex8(event.key.col); debug("\n"); // TODO event.key.raw + debug_hex16(event.key.raw); debug("\n"); if (waiting_keys_head < WAITING_KEYS_BUFFER) { waiting_keys[waiting_keys_head++] = (keyrecord_t){ .event = event, .mods = host_get_mods() }; @@ -59,7 +59,7 @@ static void waiting_keys_clear(void) { waiting_keys_head = 0; } -static bool waiting_keys_has(keypos_t key) +static bool waiting_keys_has(key_t key) { for (uint8_t i = 0; i < waiting_keys_head; i++) { if KEYEQ(key, waiting_keys[i].event.key) return true; @@ -71,7 +71,6 @@ static void waiting_keys_process_in_current_layer(void) // TODO: in case of including layer key in waiting keys for (uint8_t i = 0; i < waiting_keys_head; i++) { debug("waiting_keys_process_in_current_layer["); debug_dec(i); debug("]\n"); - // TODO: no need action in waiting_keys? should get_action() in process()? process(waiting_keys[i].event); } waiting_keys_clear(); @@ -80,6 +79,12 @@ static void waiting_keys_process_in_current_layer(void) void action_exec(keyevent_t event) { + if (!IS_NOEVENT(event)) { + debug("event: "); debug_hex16(event.key.raw); + debug("["); + if (event.pressed) debug("down"); else debug("up"); + debug("]\n"); + } if (IS_TAPPING) { /* when tap time elapses or waiting key is released */ if ((timer_elapsed(tapping_key.event.time) > TAP_TIME) || @@ -136,7 +141,7 @@ void action_exec(keyevent_t event) static void process(keyevent_t event) { - action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); + action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col); debug("action: "); debug_hex16(action.code); if (event.pressed) debug("[down]\n"); else debug("[up]\n"); diff --git a/common/keyboard.c b/common/keyboard.c index 2e32e91e0..ea4d0ee7e 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -66,7 +66,7 @@ void keyboard_task(void) for (int c = 0; c < MATRIX_COLS; c++) { if (matrix_change & (1<. extern "C" { #endif -// TODO: union {raw = row:col} typedef struct { - uint8_t row; uint8_t col; + uint8_t row; } keypos_t; +typedef union { + uint16_t raw; + keypos_t pos; +} key_t; + typedef struct { - keypos_t key; + key_t key; bool pressed; uint16_t time; } keyevent_t; -#define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col) +#define KEYEQ(keya, keyb) (keya.raw == keyb.raw) #define IS_NOEVENT(event) (event.time == 0) #define NOEVENT (keyevent_t) { \ .key = (keypos_t){ .row = 255, .col = 255 }, \ From f71a5217b762225eec294b02f9403f29a25ceb6a Mon Sep 17 00:00:00 2001 From: tmk Date: Sun, 20 Jan 2013 15:03:07 +0900 Subject: [PATCH 09/30] Fix mods with tapping. --- common/action.c | 378 +++++++++++++++++++++++----------------------- common/keyboard.h | 2 +- 2 files changed, 189 insertions(+), 191 deletions(-) diff --git a/common/action.c b/common/action.c index d01038301..3a504a45f 100644 --- a/common/action.c +++ b/common/action.c @@ -23,57 +23,83 @@ static void layer_switch(uint8_t new_layer); /* tap */ -#define TAP_TIME 200 -static keyevent_t last_event = {}; +#define TAP_TIME 300 +/* This counts up when tap occurs */ static uint8_t tap_count = 0; +static bool is_tap_key(keyevent_t event) +{ + action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col); + switch (action.kind.id) { + case ACT_LMODS_TAP: + case ACT_RMODS_TAP: + return true; + case ACT_LAYER_PRESSED: + case ACT_LAYER_BIT: + switch (action.layer.code) { + case 0x00: + case 0xF1 ... 0xFF: + return false; + case 0xF0: + default: + return true; + } + return false; + } + return false; +} /* layer */ uint8_t default_layer = 0; uint8_t current_layer = 0; -static keyrecord_t tapping_key = {}; -// time 0 means no event. -#define IS_TAPPING (tapping_key.event.time != 0) -/* TODO: -#define IS_TAPPING_KEY(key) (tapping_key.event.time != 0 && KEYEQ(tapping_key.event.key, key)) - */ +static keyevent_t tapping_event = {}; + +/* TAPPING: This indicates that whether tap or not is not decided yet. */ +// NOTE: keyevent_t.time 0 means no event. +#define IS_TAPPING(k) (tapping_event.time != 0 && KEYEQ(tapping_event.key, (k))) /* waiting keys buffer */ -#define WAITING_KEYS_BUFFER 3 -static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {}; -// TODO: double buffer? -static keyrecord_t waiting_keys0[WAITING_KEYS_BUFFER] = {}; -static keyrecord_t waiting_keys1[WAITING_KEYS_BUFFER] = {}; -static uint8_t waiting_keys_head = 0; -static bool waiting_keys_enqueue(keyevent_t event) +#define WAITING_KEYS_BUFFER 8 +static keyevent_t waiting_events[WAITING_KEYS_BUFFER] = {}; +static uint8_t waiting_events_head = 0; +static bool waiting_events_enqueue(keyevent_t event) { - debug("waiting_keys["); debug_dec(waiting_keys_head); debug("] = "); - debug_hex16(event.key.raw); debug("\n"); - if (waiting_keys_head < WAITING_KEYS_BUFFER) { - waiting_keys[waiting_keys_head++] = (keyrecord_t){ .event = event, - .mods = host_get_mods() }; - } else { + if (IS_NOEVENT(event)) { return true; } + + if (waiting_events_head < WAITING_KEYS_BUFFER) { + debug("waiting_events["); debug_dec(waiting_events_head); debug("] = "); + debug_hex16(event.key.raw); debug("\n"); + waiting_events[waiting_events_head++] = event; return true; } + debug("waiting_events_enqueue: Over flow.\n"); + return false; } -static void waiting_keys_clear(void) +static void waiting_events_clear(void) { - waiting_keys_head = 0; + waiting_events_head = 0; } -static bool waiting_keys_has(key_t key) +static bool waiting_events_has(key_t key) { - for (uint8_t i = 0; i < waiting_keys_head; i++) { - if KEYEQ(key, waiting_keys[i].event.key) return true; + for (uint8_t i = 0; i < waiting_events_head; i++) { + if KEYEQ(key, waiting_events[i].key) return true; } return false; } -static void waiting_keys_process_in_current_layer(void) +static void waiting_events_process_in_current_layer(void) { - // TODO: in case of including layer key in waiting keys - for (uint8_t i = 0; i < waiting_keys_head; i++) { - debug("waiting_keys_process_in_current_layer["); debug_dec(i); debug("]\n"); - process(waiting_keys[i].event); + // TODO: in case of including tap key in waiting keys + for (uint8_t i = 0; i < waiting_events_head; i++) { + debug("waiting_events_process_in_current_layer["); debug_dec(i); debug("]\n"); + process(waiting_events[i]); } - waiting_keys_clear(); + waiting_events_clear(); +} +static bool waiting_events_has_anykey_pressed(void) +{ + for (uint8_t i = 0; i < waiting_events_head; i++) { + if (waiting_events[i].pressed) return true; + } + return false; } @@ -85,62 +111,106 @@ void action_exec(keyevent_t event) if (event.pressed) debug("down"); else debug("up"); debug("]\n"); } - if (IS_TAPPING) { - /* when tap time elapses or waiting key is released */ - if ((timer_elapsed(tapping_key.event.time) > TAP_TIME) || - (!event.pressed && waiting_keys_has(event.key))) { - // TODO process tapping_key: layer swich, modifier, ... - // action is needed? - debug("notap: process tapping_key.\n"); - process(tapping_key.event); + // In tapping term + if (tapping_event.time && timer_elapsed(tapping_event.time) < TAP_TIME) { + if (tapping_event.pressed) { + if (!event.pressed && KEYEQ(tapping_event.key, event.key)) { + debug("Tapping: Release tap key.\n"); + if (tap_count == 0) { + debug("Tapping: First tap.\n"); + // count up on release + tap_count++; - /* Process waiting keys in new layer */ - waiting_keys_process_in_current_layer(); - } - /* when tapping key is released within tap time */ - else if (!event.pressed && KEYEQ(event.key, tapping_key.event.key)) { - /* tap key down */ - debug("tap("); debug_hex8(tap_count); debug(")[tapping_key](register): "); debug_hex8(tapping_key.action.layer.code); debug("\n"); - register_code(tapping_key.action.layer.code); - tapping_key = (keyrecord_t){}; + process(tapping_event); + waiting_events_process_in_current_layer(); + } + tapping_event = event; + process(event); + } else if (!event.pressed && waiting_events_has(event.key)) { + debug("Tapping: End(No tap by typing waiting key).\n"); - /* process waiting keys */ - waiting_keys_process_in_current_layer(); + process(tapping_event); + waiting_events_process_in_current_layer(); + process(event); + + tap_count = 0; + tapping_event = (keyevent_t){}; + } else { + //debug("Tapping: pressing tap key.\n"); + if (tap_count == 0) { + // store event + waiting_events_enqueue(event); + return; + } + process(event); + } + } else { + //debug("Tapping after releasing tap.\n"); + // Sequential tap + if (tap_count && event.pressed && KEYEQ(tapping_event.key, event.key)) { + tap_count++; + tapping_event = event; + debug("Tapping: Sequential tap("); debug_hex(tap_count); debug(")\n"); + } + process(event); } } + // Not in tapping term + else { + if (tapping_event.time) { + if (tapping_event.pressed) { + if (tap_count == 0) { + // Not tap, holding down normal key. + debug("Not tap.\n"); + process(tapping_event); + waiting_events_process_in_current_layer(); + + tap_count = 0; + tapping_event = (keyevent_t){}; + process(event); + } else { + // Holding down last tap key. + //debug("Time out with holding last tap.\n"); + process(event); + if (!event.pressed && KEYEQ(tapping_event.key, event.key)) { + debug("Tapping: End(Release holding last tap).\n"); + // clear after release last tap key + tap_count = 0; + tapping_event = (keyevent_t){}; + waiting_events_clear(); + } + } + } else { + // time out for sequential tap after complete last tap + debug("Tapping: End(Time out after releasing last tap).\n"); + tap_count = 0; + tapping_event = (keyevent_t){}; + waiting_events_clear(); + + process(event); + } + } else { + // Normal state without tapping + if (event.pressed && is_tap_key(event)) { + debug("Tapping: Start(Press tap key).\n"); + tapping_event = event; + tap_count = 0; + waiting_events_clear(); + } else { + //debug("Normal event(No tapping)\n"); + process(event); + } + } - // not real event. event just to handle time out of tapping key. - if (IS_NOEVENT(event)) { - return; } - - /* count up tap when key is up */ - // key: d u d u d - // tap: 0 1 1 2 2 - // key: u d u d u - // tap: 0 0 1 1 2 - if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) { - if (!event.pressed) tap_count++; - } else { - tap_count = 0; - } - - /* store key events while tapping */ - if (IS_TAPPING) { - // TODO: action is needed? - waiting_keys_enqueue(event); - } else { - process(event); - } - - /* last event */ - last_event = event; } static void process(keyevent_t event) { + if (IS_NOEVENT(event)) { return; } + action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col); debug("action: "); debug_hex16(action.code); if (event.pressed) debug("[down]\n"); else debug("[up]\n"); @@ -198,82 +268,32 @@ static void process(keyevent_t event) } break; case ACT_LMODS_TAP: - if (event.pressed) { - if (tap_count == 0) { - if (host_has_anykey()) { - // This key is a modifier essentially. - // Prioritize mods when key jam or rollover - add_mods(action.key.mods); - } else { - if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { - // no tapping - add_mods(action.key.mods); - tapping_key = (keyrecord_t){}; - } else { - debug("tapping lmods("); debug_hex8(action.key.mods); debug(")\n"); - tapping_key = (keyrecord_t){ - .event = event, - .action = action, - .mods = host_get_mods() - }; - } - } - } else { - // pressed after tapping - debug("tap("); debug_hex(tap_count); debug(")[lmods](register): "); debug_hex8(action.key.code); debug("\n"); - register_code(action.key.code); - } - } else { - if (tap_count == 0) { - debug("tap(00)[lmods](del_mods): "); debug_hex8(action.key.mods); debug("\n"); - del_mods(action.key.mods); - } else if (tap_count == 1) { - debug("tap(01)[lmods](del_mods/unregister): "); debug_hex8(action.key.mods); debug(" "); debug_hex8(action.key.code); debug("\n"); - del_mods(action.key.mods); - unregister_code(action.key.code); - } else { - debug("tap("); debug_hex(tap_count); debug(")[lmods](unregister): "); debug_hex8(action.key.code); debug("\n"); - unregister_code(action.key.code); - } - } - break; case ACT_RMODS_TAP: - if (event.pressed) { - if (tap_count == 0) { - if (host_has_anykey()) { - // This key is a modifier essentially. - // Prioritize mods when key jam or rollover - add_mods(action.key.mods<<4); - } else { - if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { - // no tapping - add_mods(action.key.mods<<4); - tapping_key = (keyrecord_t){}; + { + uint8_t tmp_mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : + action.key.mods<<4; + if (event.pressed) { + if (IS_TAPPING(event.key) && tap_count > 0) { + if (waiting_events_has_anykey_pressed()) { + debug("MODS_TAP: Tap: Cancel: add_mods\n"); + tap_count = 0; + add_mods(tmp_mods); } else { - debug("tapping rmods("); debug_hex8(action.key.mods); debug(")\n"); - tapping_key = (keyrecord_t){ - .event = event, - .action = action, - .mods = host_get_mods() - }; + debug("MODS_TAP: Tap: register_code\n"); + register_code(action.key.code); } + } else { + debug("MODS_TAP: No tap: add_mods\n"); + add_mods(tmp_mods); } } else { - // pressed after tapping - debug("tap("); debug_hex(tap_count); debug(")[rmods](register): "); debug_hex8(action.key.code); debug("\n"); - register_code(action.key.code); - } - } else { - if (tap_count == 0) { - debug("tap(00)[rmods](del_mods): "); debug_hex8(action.key.mods); debug("\n"); - del_mods(action.key.mods<<4); - } else if (tap_count == 1) { - debug("tap(01)[rmods](del_mods/unregister): "); debug_hex8(action.key.mods); debug(" "); debug_hex8(action.key.code); debug("\n"); - del_mods(action.key.mods<<4); - unregister_code(action.key.code); - } else { - debug("tap("); debug_hex(tap_count); debug(")[rmods](unregister): "); debug_hex8(action.key.code); debug("\n"); - unregister_code(action.key.code); + if (IS_TAPPING(event.key) && tap_count > 0) { + debug("MODS_TAP: Tap: unregister_code\n"); + unregister_code(action.key.code); + } else { + debug("MODS_TAP: No tap: add_mods\n"); + del_mods(tmp_mods); + } } } break; @@ -334,33 +354,20 @@ static void process(keyevent_t event) default: // with tap key if (event.pressed) { - if (tap_count == 0) { - if (host_has_anykey()) { - // This key is a normal key than a leyar key essentially. - // Prioritize 'tap key' when key jam or rollover - register_code(action.layer.code); - } else { - if (IS_TAPPING && KEYEQ(tapping_key.event.key, event.key)) { - layer_switch(action.layer.opt); - tapping_key = (keyrecord_t){}; - } else { - debug("tapping layer("); debug_hex8(action.layer.opt); debug(")\n"); - tapping_key = (keyrecord_t){ - .event = event, - .action = action, - .mods = host_get_mods() - }; - } - } - } else if (tap_count > 0) { - // pressed after tapping - debug("tap[layer](register): "); debug_hex(tap_count); debug("\n"); + if (IS_TAPPING(event.key) && tap_count > 0) { + debug("LAYER_PRESSED: Tap: register_code\n"); register_code(action.layer.code); + } else { + debug("LAYER_PRESSED: No tap: layer_switch\n"); + layer_switch(action.layer.opt); } } else { - // released after tapping - debug("tap[layer](unregister): "); debug_hex(tap_count); debug("\n"); - unregister_code(action.layer.code); + if (IS_TAPPING(event.key) && tap_count > 0) { + debug("LAYER_PRESSED: Tap: unregister_code\n"); + unregister_code(action.layer.code); + } else { + debug("LAYER_PRESSED: No tap: NO ACTION\n"); + } } break; } @@ -409,32 +416,23 @@ static void process(keyevent_t event) } break; default: - // TODO: see ACT_LAYER_PRESSED code // with tap key if (event.pressed) { - if (tap_count == 0) { - if (host_has_anykey()) { - register_code(action.layer.code); - } else { - tapping_key = (keyrecord_t){ - .event = event, - .action = action, - .mods = keyboard_report->mods - }; - } - } else if (tap_count > 0) { - debug("tap[layer_bit](register): "); debug_hex(tap_count); debug("\n"); + if (IS_TAPPING(event.key) && tap_count > 0) { + debug("LAYER_BIT: Tap: register_code\n"); register_code(action.layer.code); + } else { + debug("LAYER_BIT: No tap: layer_switch(bit on)\n"); + layer_switch(current_layer | action.layer.opt); } } else { - if (tap_count == 0) { - // no tap + if (IS_TAPPING(event.key) && tap_count > 0) { + debug("LAYER_BIT: Tap: unregister_code\n"); + unregister_code(action.layer.code); + } else { + debug("LAYER_BIT: No tap: layer_switch(bit off)\n"); layer_switch(current_layer & ~action.layer.opt); - } else if (tap_count == 1) { - // tap - register_code(action.layer.code); } - unregister_code(action.layer.code); } break; } diff --git a/common/keyboard.h b/common/keyboard.h index 4518cdddc..4a3ee85a8 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -37,7 +37,7 @@ typedef union { } key_t; typedef struct { - key_t key; + key_t key; bool pressed; uint16_t time; } keyevent_t; From 1fe820a8654b69576875a8173e22b47b365c2460 Mon Sep 17 00:00:00 2001 From: tmk Date: Tue, 22 Jan 2013 12:30:30 +0900 Subject: [PATCH 10/30] Add bootmagic keys.(hhkb) - kick bootloader - enable debug print --- common/keyboard.c | 11 +++++++++++ keyboard/hhkb/config.h | 14 ++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/common/keyboard.c b/common/keyboard.c index ea4d0ee7e..9f0ca7676 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -40,6 +40,17 @@ void keyboard_init(void) timer_init(); matrix_init(); + + /* boot magic keys goes here */ + matrix_scan(); +#ifdef IS_BOOTMAGIC_BOOTLOADER + /* kick up bootloader */ + if (IS_BOOTMAGIC_BOOTLOADER()) bootloader_jump(); +#endif +#ifdef IS_BOOTMAGIC_DEBUG + if (IS_BOOTMAGIC_DEBUG()) debug_enable = true; +#endif + #ifdef PS2_MOUSE_ENABLE ps2_mouse_init(); #endif diff --git a/keyboard/hhkb/config.h b/keyboard/hhkb/config.h index cca75f243..66dede9a5 100644 --- a/keyboard/hhkb/config.h +++ b/keyboard/hhkb/config.h @@ -37,6 +37,20 @@ along with this program. If not, see . #define MATRIX_COLS 8 +/* + * Boot magic keys + * call some function by pressing key when pluging cable or powering on. + */ +/* key position on matrix(ROW:COL) */ +#define KEY_FN 0x54 +#define KEY_D 0x14 +#define KEY_IS_ON(key) matrix_is_on((key)>>4, (key)&0xF) +/* kick up bootloader */ +#define IS_BOOTMAGIC_BOOTLOADER() KEY_IS_ON(KEY_FN) +/* debug on */ +#define IS_BOOTMAGIC_DEBUG() KEY_IS_ON(KEY_D) + + /* key combination for command */ #define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) From 28b5f69ce5c8b35d40725b490e7a2d4bfe922ad4 Mon Sep 17 00:00:00 2001 From: tmk Date: Wed, 23 Jan 2013 23:53:51 +0900 Subject: [PATCH 11/30] Add prototype of Action Function. --- common/action.c | 188 +++++++++++++++++++++++++++-------------- common/action.h | 38 ++++++++- common/keyboard.c | 3 +- common/keyboard.h | 4 +- keyboard/hhkb/keymap.c | 20 ++++- 5 files changed, 184 insertions(+), 69 deletions(-) diff --git a/common/action.c b/common/action.c index 3a504a45f..88f8186c3 100644 --- a/common/action.c +++ b/common/action.c @@ -11,47 +11,26 @@ static void process(keyevent_t event); -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); -static void layer_switch(uint8_t new_layer); - -/* tap */ -#define TAP_TIME 300 -/* This counts up when tap occurs */ -static uint8_t tap_count = 0; -static bool is_tap_key(keyevent_t event) +void test_func(keyevent_t event, uint8_t opt) { - action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col); - switch (action.kind.id) { - case ACT_LMODS_TAP: - case ACT_RMODS_TAP: - return true; - case ACT_LAYER_PRESSED: - case ACT_LAYER_BIT: - switch (action.layer.code) { - case 0x00: - case 0xF1 ... 0xFF: - return false; - case 0xF0: - default: - return true; - } - return false; + if (event.pressed) { + debug("test_func:pressed: "); debug_hex(opt); debug("\n"); + } else { + debug("test_func:released: "); debug_hex(opt); debug("\n"); } - return false; } /* layer */ uint8_t default_layer = 0; uint8_t current_layer = 0; -static keyevent_t tapping_event = {}; + +/* tap term(ms) */ +#define TAP_TIME 200 + +/* This counts up when tap occurs */ +uint8_t tap_count = 0; +keyevent_t tapping_event = {}; /* TAPPING: This indicates that whether tap or not is not decided yet. */ // NOTE: keyevent_t.time 0 means no event. @@ -61,26 +40,41 @@ static keyevent_t tapping_event = {}; #define WAITING_KEYS_BUFFER 8 static keyevent_t waiting_events[WAITING_KEYS_BUFFER] = {}; static uint8_t waiting_events_head = 0; +static uint8_t waiting_events_tail = 0; + static bool waiting_events_enqueue(keyevent_t event) { if (IS_NOEVENT(event)) { return true; } - if (waiting_events_head < WAITING_KEYS_BUFFER) { - debug("waiting_events["); debug_dec(waiting_events_head); debug("] = "); - debug_hex16(event.key.raw); debug("\n"); - waiting_events[waiting_events_head++] = event; - return true; + if ((waiting_events_head + 1) % WAITING_KEYS_BUFFER == waiting_events_tail) { + debug("waiting_events_enqueue: Over flow.\n"); + return false; } - debug("waiting_events_enqueue: Over flow.\n"); - return false; + + debug("waiting_events["); debug_dec(waiting_events_head); debug("] = "); + debug_hex16(event.key.raw); debug("\n"); + + waiting_events[waiting_events_head] = event; + waiting_events_head = (waiting_events_head + 1)% WAITING_KEYS_BUFFER; + return true; +} +static keyevent_t waiting_events_dequeue(void) +{ + if (waiting_events_head == waiting_events_tail) { + return (keyevent_t){}; + } + uint8_t tail = waiting_events_tail; + waiting_events_tail = waiting_events_tail + 1 % WAITING_KEYS_BUFFER; + return waiting_events[tail]; } static void waiting_events_clear(void) { waiting_events_head = 0; + waiting_events_tail = 0; } static bool waiting_events_has(key_t key) { - for (uint8_t i = 0; i < waiting_events_head; i++) { + for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) { if KEYEQ(key, waiting_events[i].key) return true; } return false; @@ -88,7 +82,7 @@ static bool waiting_events_has(key_t key) static void waiting_events_process_in_current_layer(void) { // TODO: in case of including tap key in waiting keys - for (uint8_t i = 0; i < waiting_events_head; i++) { + for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) { debug("waiting_events_process_in_current_layer["); debug_dec(i); debug("]\n"); process(waiting_events[i]); } @@ -96,7 +90,7 @@ static void waiting_events_process_in_current_layer(void) } static bool waiting_events_has_anykey_pressed(void) { - for (uint8_t i = 0; i < waiting_events_head; i++) { + for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) { if (waiting_events[i].pressed) return true; } return false; @@ -137,7 +131,7 @@ void action_exec(keyevent_t event) tap_count = 0; tapping_event = (keyevent_t){}; } else { - //debug("Tapping: pressing tap key.\n"); + if (!IS_NOEVENT(event)) debug("Tapping: other key while tapping.\n"); if (tap_count == 0) { // store event waiting_events_enqueue(event); @@ -146,14 +140,22 @@ void action_exec(keyevent_t event) process(event); } } else { - //debug("Tapping after releasing tap.\n"); - // Sequential tap + // Waiting for sequential tap if (tap_count && event.pressed && KEYEQ(tapping_event.key, event.key)) { tap_count++; tapping_event = event; debug("Tapping: Sequential tap("); debug_hex(tap_count); debug(")\n"); + process(event); + } else if (event.pressed && is_tap_key(event)) { + // Sequential tap can be interfered with other tap key. + debug("Tapping: Start with interfering other tap.\n"); + tapping_event = event; + tap_count = 0; + waiting_events_clear(); + } else { + if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n"); + process(event); } - process(event); } } // Not in tapping term @@ -162,7 +164,7 @@ void action_exec(keyevent_t event) if (tapping_event.pressed) { if (tap_count == 0) { // Not tap, holding down normal key. - debug("Not tap.\n"); + debug("Tapping: End. Not tap(time out).\n"); process(tapping_event); waiting_events_process_in_current_layer(); @@ -170,15 +172,27 @@ void action_exec(keyevent_t event) tapping_event = (keyevent_t){}; process(event); } else { - // Holding down last tap key. - //debug("Time out with holding last tap.\n"); - process(event); + // Holding down last tap key. waiting for releasing last tap key. if (!event.pressed && KEYEQ(tapping_event.key, event.key)) { - debug("Tapping: End(Release holding last tap).\n"); + debug("Tapping: End. Release holding last tap(time out).\n"); + process(event); // clear after release last tap key tap_count = 0; tapping_event = (keyevent_t){}; waiting_events_clear(); + } else if (event.pressed && is_tap_key(event)) { + debug("Tapping: Start with forcing to release last tap(time out).\n"); + process((keyevent_t){ + .key = tapping_event.key, + .time = event.time, + .pressed = false }); + + tap_count = 0; + tapping_event = event; + waiting_events_clear(); + } else { + if (!IS_NOEVENT(event)) debug("Tapping: other key while waiting for release of last tap(time out).\n"); + process(event); } } } else { @@ -206,7 +220,6 @@ void action_exec(keyevent_t event) } } - static void process(keyevent_t event) { if (IS_NOEVENT(event)) { return; } @@ -354,6 +367,20 @@ static void process(keyevent_t event) default: // with tap key if (event.pressed) { + if (IS_TAPPING(event.key)) { + if (tap_count > 0) { + debug("LAYER_PRESSED: Tap: register_code\n"); + register_code(action.layer.code); + } else { + debug("LAYER_PRESSED: No tap: layer_switch\n"); + layer_switch(action.layer.opt); + } + } else { + // TODO: while other key tapping + debug("LAYER_PRESSED: No tap: layer_switch\n"); + layer_switch(action.layer.opt); + } +/* if (IS_TAPPING(event.key) && tap_count > 0) { debug("LAYER_PRESSED: Tap: register_code\n"); register_code(action.layer.code); @@ -361,6 +388,7 @@ static void process(keyevent_t event) debug("LAYER_PRESSED: No tap: layer_switch\n"); layer_switch(action.layer.opt); } +*/ } else { if (IS_TAPPING(event.key) && tap_count > 0) { debug("LAYER_PRESSED: Tap: unregister_code\n"); @@ -488,14 +516,23 @@ static void process(keyevent_t event) /* Extentions */ case ACT_MACRO: + break; case ACT_COMMAND: + break; case ACT_FUNCTION: + action_call_function(event, action.func.id); + //test_func(event, action.func.opt); + break; default: break; } } -static void register_code(uint8_t code) + +/* + * Utilities for actions. + */ +void register_code(uint8_t code) { if (code == KC_NO) { return; @@ -513,7 +550,7 @@ static void register_code(uint8_t code) } } -static void unregister_code(uint8_t code) +void unregister_code(uint8_t code) { if IS_KEY(code) { host_del_key(code); @@ -525,7 +562,7 @@ static void unregister_code(uint8_t code) } } -static void add_mods(uint8_t mods) +void add_mods(uint8_t mods) { if (mods) { host_add_mods(mods); @@ -533,7 +570,7 @@ static void add_mods(uint8_t mods) } } -static void del_mods(uint8_t mods) +void del_mods(uint8_t mods) { if (mods) { host_del_mods(mods); @@ -541,19 +578,19 @@ static void del_mods(uint8_t mods) } } -static void set_mods(uint8_t mods) +void set_mods(uint8_t mods) { host_set_mods(mods); host_send_keyboard_report(); } -static void clear_keyboard(void) +void clear_keyboard(void) { host_clear_mods(); clear_keyboard_but_mods(); } -static void clear_keyboard_but_mods(void) +void clear_keyboard_but_mods(void) { host_clear_keys(); host_send_keyboard_report(); @@ -567,13 +604,13 @@ static void clear_keyboard_but_mods(void) #endif } -static bool sending_anykey(void) +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) +void layer_switch(uint8_t new_layer) { if (current_layer != new_layer) { debug("Layer Switch: "); debug_hex(current_layer); @@ -584,3 +621,30 @@ static void layer_switch(uint8_t new_layer) // TODO: update mods with full scan of matrix? if modifier changes between layers } } + +bool is_tap_key(keyevent_t event) +{ + action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col); + switch (action.kind.id) { + case ACT_LMODS_TAP: + case ACT_RMODS_TAP: + return true; + case ACT_LAYER_PRESSED: + case ACT_LAYER_BIT: + switch (action.layer.code) { + case 0x00: + case 0xF1 ... 0xFF: + return false; + case 0xF0: + default: + return true; + } + return false; + case ACT_FUNCTION: + if (action.func.opt & 0x1) { + return true; + } + return false; + } + return false; +} diff --git a/common/action.h b/common/action.h index 3115c67f4..9aa1d78e9 100644 --- a/common/action.h +++ b/common/action.h @@ -3,8 +3,30 @@ #include "keyboard.h" +extern uint8_t tap_count; +extern keyevent_t tapping_event; -/* Key Action(16bit code) + +/* + * Utilities for actions. + */ +void register_code(uint8_t code); +void unregister_code(uint8_t code); +void add_mods(uint8_t mods); +void del_mods(uint8_t mods); +void set_mods(uint8_t mods); +void clear_keyboard(void); +void clear_keyboard_but_mods(void); +bool sending_anykey(void); +void layer_switch(uint8_t new_layer); +bool is_tap_key(keyevent_t event); + + + + +/* +Action codes +16bit code: action_kind(4bit) + action_parameter(12bit) Keyboard Keys ------------- @@ -94,6 +116,7 @@ ACT_COMMAND(1110): ACT_FUNCTION(1111): 1111| address(12) Function +1111|opt | id(8) Function Macro record(dynamicly) Macro play(dynamicly) TODO: modifier + [tap key /w mod] @@ -160,6 +183,11 @@ typedef union { uint16_t option :4; uint16_t kind :4; } command; + struct action_function { + uint8_t id :8; + uint8_t opt :4; + uint8_t kind :4; + } func; } action_t; @@ -169,14 +197,20 @@ enum stroke_cmd { STROKE_ALLUP, /* release all keys in reverse order */ }; +// TODO: not needed? typedef struct { keyevent_t event; action_t action; uint8_t mods; } keyrecord_t; +/* action function */ +typedef void (*action_func_t)(keyevent_t event, uint8_t opt); + +// TODO: legacy keymap support void action_exec(keyevent_t event); +void action_call_function(keyevent_t event, uint8_t id); // TODO: proper names @@ -234,7 +268,7 @@ void action_exec(keyevent_t event); /* Command */ #define ACTION_COMMAND(opt, id) ACTION(ACT_COMMAND, (opt)<<8 | (addr)) /* Function */ -#define ACTION_FUNCTION(addr) ACTION(ACT_FUNCTION, addr) +#define ACTION_FUNCTION(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | id) /* helpers for readability */ diff --git a/common/keyboard.c b/common/keyboard.c index 9f0ca7676..6677e8011 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -89,7 +89,8 @@ void keyboard_task(void) } } } - // call to update delaying layer when no real event + // call with not real event to update state of aciton + // TODO: use NOEVENT macro action_exec((keyevent_t) { .key.pos = (keypos_t){ .row = 255, .col = 255 }, // assume this key doesn't exist .pressed = false, diff --git a/common/keyboard.h b/common/keyboard.h index 4a3ee85a8..6d06c95bb 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -44,10 +44,10 @@ typedef struct { #define KEYEQ(keya, keyb) (keya.raw == keyb.raw) #define IS_NOEVENT(event) (event.time == 0) -#define NOEVENT (keyevent_t) { \ +#define NOEVENT (keyevent_t){ \ .key = (keypos_t){ .row = 255, .col = 255 }, \ .pressed = false, \ - .time = 0, \ + .time = 0 \ } diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index e29b37b16..e4eeb3e39 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -56,7 +56,8 @@ static const uint16_t PROGMEM fn_actions[] = { 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_ON_PRESSED(3), // Fn4 + ACTION_FUNCTION(0x01, 0xA), // Fn4 ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // Fn5 ACTION_LMODS_TAP(MOD_BIT(KC_LCTL), KC_BSPC), // Fn6 ACTION_RMODS_TAP(MOD_BIT(KC_RCTL), KC_ENT), // Fn7 @@ -196,7 +197,7 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { case KC_MS_UP ... KC_MS_ACCEL2: action.code = ACTION_MOUSEKEY(key); break; -/* +/* TODO case KC_LCTRL ... KC_LGUI: action.code = ACTION_LMODS(MOD_BIT(key)); break; @@ -214,3 +215,18 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { } return action; } + +// TODO: how to define action function +void action_call_function(keyevent_t event, uint8_t id) +{ + // '(' Shift+9 + if (event.pressed) { + register_code(KC_LSHIFT); + register_code(KC_9); + debug("action_call_function: pressed: id: "); debug_hex(id); debug("\n"); + } else { + unregister_code(KC_9); + unregister_code(KC_LSHIFT); + debug("action_call_function: released: id: "); debug_hex(id); debug("\n"); + } +} From d8dddf9f25181e29e3fb82250833a00a11921452 Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 24 Jan 2013 01:02:11 +0900 Subject: [PATCH 12/30] Minor fixes in keyboard.c. --- common/keyboard.c | 16 ++++++---------- common/keyboard.h | 8 ++++---- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/common/keyboard.c b/common/keyboard.c index 6677e8011..1aff81f54 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -26,6 +26,7 @@ along with this program. If not, see . #include "command.h" #include "util.h" #include "sendchar.h" +#include "bootloader.h" #ifdef MOUSEKEY_ENABLE #include "mousekey.h" #endif @@ -68,21 +69,21 @@ void keyboard_task(void) matrix_row_t matrix_change = 0; matrix_scan(); - for (int r = 0; r < MATRIX_ROWS; r++) { + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { matrix_row = matrix_get_row(r); matrix_change = matrix_row ^ matrix_prev[r]; if (matrix_change) { if (debug_matrix) matrix_print(); - for (int c = 0; c < MATRIX_COLS; c++) { - if (matrix_change & (1< Date: Sun, 27 Jan 2013 02:42:48 +0900 Subject: [PATCH 13/30] New tapping logic. --- common/action.c | 363 ++++++++++++++++++++++++++-------------------- common/action.h | 6 +- common/keyboard.c | 6 +- common/keyboard.h | 9 +- 4 files changed, 218 insertions(+), 166 deletions(-) diff --git a/common/action.c b/common/action.c index 88f8186c3..815931548 100644 --- a/common/action.c +++ b/common/action.c @@ -10,7 +10,7 @@ #include "action.h" -static void process(keyevent_t event); +static void process(keyrecord_t *record); void test_func(keyevent_t event, uint8_t opt) { @@ -26,202 +26,250 @@ uint8_t default_layer = 0; uint8_t current_layer = 0; /* tap term(ms) */ -#define TAP_TIME 200 +#define TAP_TERM 200 /* This counts up when tap occurs */ uint8_t tap_count = 0; keyevent_t tapping_event = {}; +keyrecord_t tapping_key = {}; /* TAPPING: This indicates that whether tap or not is not decided yet. */ // NOTE: keyevent_t.time 0 means no event. -#define IS_TAPPING(k) (tapping_event.time != 0 && KEYEQ(tapping_event.key, (k))) +#define IS_TAPPING() (tapping_key.event.time != 0) +#define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed) +#define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) +#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) +#define WITHIN_TAP_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAP_TERM) /* waiting keys buffer */ -#define WAITING_KEYS_BUFFER 8 -static keyevent_t waiting_events[WAITING_KEYS_BUFFER] = {}; -static uint8_t waiting_events_head = 0; -static uint8_t waiting_events_tail = 0; +#define WAITING_BUFFER_SIZE 8 +static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; +/* point to empty cell to enq */ +static uint8_t waiting_buffer_head = 0; +/* point to the oldest data cell to deq */ +static uint8_t waiting_buffer_tail = 0; -static bool waiting_events_enqueue(keyevent_t event) +static bool waiting_buffer_enq(keyrecord_t record) { - if (IS_NOEVENT(event)) { return true; } + if (IS_NOEVENT(record.event)) { + return true; + } - if ((waiting_events_head + 1) % WAITING_KEYS_BUFFER == waiting_events_tail) { - debug("waiting_events_enqueue: Over flow.\n"); + if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) { + debug("waiting_buffer_enq: Over flow.\n"); return false; } - debug("waiting_events["); debug_dec(waiting_events_head); debug("] = "); - debug_hex16(event.key.raw); debug("\n"); + debug("waiting_buffer_enq["); debug_dec(waiting_buffer_head); debug("] = "); + debug_hex16(record.event.key.raw); debug("\n"); - waiting_events[waiting_events_head] = event; - waiting_events_head = (waiting_events_head + 1)% WAITING_KEYS_BUFFER; + waiting_buffer[waiting_buffer_head] = record; + waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE; return true; } -static keyevent_t waiting_events_dequeue(void) +static keyrecord_t waiting_buffer_deq(void) { - if (waiting_events_head == waiting_events_tail) { - return (keyevent_t){}; + if (waiting_buffer_head == waiting_buffer_tail) { + return (keyrecord_t){}; } - uint8_t tail = waiting_events_tail; - waiting_events_tail = waiting_events_tail + 1 % WAITING_KEYS_BUFFER; - return waiting_events[tail]; + uint8_t last_tail = waiting_buffer_tail; + waiting_buffer_tail = waiting_buffer_tail + 1 % WAITING_BUFFER_SIZE; + return waiting_buffer[last_tail]; } -static void waiting_events_clear(void) +static bool waiting_buffer_is_empty(void) { - waiting_events_head = 0; - waiting_events_tail = 0; + return (waiting_buffer_head == waiting_buffer_tail); } -static bool waiting_events_has(key_t key) +static void waiting_buffer_clear(void) { - for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) { - if KEYEQ(key, waiting_events[i].key) return true; + waiting_buffer_head = 0; + waiting_buffer_tail = 0; +} +static bool waiting_buffer_typed(keyevent_t event) +{ + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) { + return true; + } } return false; } -static void waiting_events_process_in_current_layer(void) +static bool waiting_buffer_has_anykey_pressed(void) { - // TODO: in case of including tap key in waiting keys - for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) { - debug("waiting_events_process_in_current_layer["); debug_dec(i); debug("]\n"); - process(waiting_events[i]); - } - waiting_events_clear(); -} -static bool waiting_events_has_anykey_pressed(void) -{ - for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) { - if (waiting_events[i].pressed) return true; + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + if (waiting_buffer[i].event.pressed) return true; } return false; } +static void waiting_buffer_process(void) +{ +} +/* + * Rule to judge tap: + * Tap key is typed(pressed and released) within TAP_TERM + * without interfaring by typing other key. + */ +/* return true when key event is processed. */ +static bool process_tap(keyrecord_t *keyp) +{ + keyevent_t event = keyp->event; + + // if tapping + if (IS_TAPPING_PRESSED()) { + if (WITHIN_TAP_TERM(event)) { + if (tapping_key.tap_count == 0) { + if (IS_TAPPING_KEY(event.key) && !event.pressed) { + // first tap! + debug("Tapping: First tap.\n"); + tapping_key.tap_count = 1; + process(&tapping_key); + + // enqueue + keyp->tap_count = tapping_key.tap_count; + return false; + } else if (!event.pressed && waiting_buffer_typed(event)) { + // other key typed. not tap. + debug("Tapping: End(No tap. Interfered by typing key).\n"); + process(&tapping_key); + tapping_key = (keyrecord_t){}; + + // enqueue + return false; + } else { + // other key events shall be stored till tapping state settles. + return false; + } + } else { + if (IS_TAPPING_KEY(event.key) && !event.pressed) { + keyp->tap_count = tapping_key.tap_count; + debug("Tapping: tap release("); debug_dec(keyp->tap_count); debug(")\n"); + tapping_key = *keyp; + return false; + } + else if (is_tap_key(keyp->event.key) && event.pressed) { + debug("Tapping: Start with forcing to release last tap.\n"); + process(&(keyrecord_t){ + .tap_count = tapping_key.tap_count, + .event.key = tapping_key.event.key, + .event.time = event.time, + .event.pressed = false + }); + tapping_key = *keyp; + return false; + } + else { + if (!IS_NOEVENT(keyp->event)) debug("Tapping: key event while tap.\n"); + process(keyp); + return true; + } + } + } + // not within TAP_TERM + else { + if (tapping_key.tap_count == 0) { + // timeout. not tap. + debug("Tapping: End. Not tap(time out).\n"); + process(&tapping_key); + tapping_key = (keyrecord_t){}; + return false; + } else { + if (IS_TAPPING_KEY(event.key) && !event.pressed) { + debug("Tapping: End. tap release."); + keyp->tap_count = tapping_key.tap_count; + process(keyp); + tapping_key = (keyrecord_t){}; + return true; + } else { + // other key after tap time out. + process(keyp); + return true; + } + } + } + } else if (IS_TAPPING_RELEASED()) { + if (WITHIN_TAP_TERM(event)) { + if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) { + // sequential tap. + keyp->tap_count = tapping_key.tap_count + 1; + debug("Tapping: tap press("); debug_dec(keyp->tap_count); debug(")\n"); + process(keyp); + tapping_key = *keyp; + return true; + } else if (event.pressed && is_tap_key(event.key)) { + // Sequential tap can be interfered with other tap key. + debug("Tapping: Start with interfering other tap.\n"); + tapping_key = *keyp; + return true; + } else { + if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n"); + process(keyp); + return true; + } + } else { + // timeout. no sequential tap. + debug("Tapping: End(Time out after releasing last tap).\n"); + tapping_key = (keyrecord_t){}; + process(keyp); + return true; + } + } else { + if (event.pressed && is_tap_key(event.key)) { + debug("Tapping: Start(Press tap key).\n"); + tapping_key = *keyp; + return true; + } else { + process(keyp); + return true; + } + } +} + void action_exec(keyevent_t event) { if (!IS_NOEVENT(event)) { - debug("event: "); debug_hex16(event.key.raw); + debug("event: "); + debug_hex16(event.time); debug(": "); + debug_hex16(event.key.raw); debug("["); if (event.pressed) debug("down"); else debug("up"); debug("]\n"); } - // In tapping term - if (tapping_event.time && timer_elapsed(tapping_event.time) < TAP_TIME) { - if (tapping_event.pressed) { - if (!event.pressed && KEYEQ(tapping_event.key, event.key)) { - debug("Tapping: Release tap key.\n"); - if (tap_count == 0) { - debug("Tapping: First tap.\n"); - // count up on release - tap_count++; + keyrecord_t record = { .event = event }; - process(tapping_event); - waiting_events_process_in_current_layer(); - } - tapping_event = event; - process(event); - } else if (!event.pressed && waiting_events_has(event.key)) { - debug("Tapping: End(No tap by typing waiting key).\n"); - - process(tapping_event); - waiting_events_process_in_current_layer(); - process(event); - - tap_count = 0; - tapping_event = (keyevent_t){}; - } else { - if (!IS_NOEVENT(event)) debug("Tapping: other key while tapping.\n"); - if (tap_count == 0) { - // store event - waiting_events_enqueue(event); - return; - } - process(event); - } - } else { - // Waiting for sequential tap - if (tap_count && event.pressed && KEYEQ(tapping_event.key, event.key)) { - tap_count++; - tapping_event = event; - debug("Tapping: Sequential tap("); debug_hex(tap_count); debug(")\n"); - process(event); - } else if (event.pressed && is_tap_key(event)) { - // Sequential tap can be interfered with other tap key. - debug("Tapping: Start with interfering other tap.\n"); - tapping_event = event; - tap_count = 0; - waiting_events_clear(); - } else { - if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n"); - process(event); - } + // pre-process on tapping + if (process_tap(&record)) { + if (!IS_NOEVENT(record.event)) debug("processed.\n"); + } else { + if (!IS_NOEVENT(record.event)) debug("enqueued.\n"); + if (!waiting_buffer_enq(record)) { + // clear all in case of overflow. + clear_keyboard(); + waiting_buffer_clear(); + tapping_key = (keyrecord_t){}; } } - // Not in tapping term - else { - if (tapping_event.time) { - if (tapping_event.pressed) { - if (tap_count == 0) { - // Not tap, holding down normal key. - debug("Tapping: End. Not tap(time out).\n"); - process(tapping_event); - waiting_events_process_in_current_layer(); - tap_count = 0; - tapping_event = (keyevent_t){}; - process(event); - } else { - // Holding down last tap key. waiting for releasing last tap key. - if (!event.pressed && KEYEQ(tapping_event.key, event.key)) { - debug("Tapping: End. Release holding last tap(time out).\n"); - process(event); - // clear after release last tap key - tap_count = 0; - tapping_event = (keyevent_t){}; - waiting_events_clear(); - } else if (event.pressed && is_tap_key(event)) { - debug("Tapping: Start with forcing to release last tap(time out).\n"); - process((keyevent_t){ - .key = tapping_event.key, - .time = event.time, - .pressed = false }); - - tap_count = 0; - tapping_event = event; - waiting_events_clear(); - } else { - if (!IS_NOEVENT(event)) debug("Tapping: other key while waiting for release of last tap(time out).\n"); - process(event); - } - } - } else { - // time out for sequential tap after complete last tap - debug("Tapping: End(Time out after releasing last tap).\n"); - tap_count = 0; - tapping_event = (keyevent_t){}; - waiting_events_clear(); - - process(event); - } + // TODO: need to process every time? + // process waiting_buffer + for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { + if (process_tap(&waiting_buffer[waiting_buffer_tail])) { + debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = "); + debug_hex16(waiting_buffer[waiting_buffer_tail].event.key.raw); debug("\n"); } else { - // Normal state without tapping - if (event.pressed && is_tap_key(event)) { - debug("Tapping: Start(Press tap key).\n"); - tapping_event = event; - tap_count = 0; - waiting_events_clear(); - } else { - //debug("Normal event(No tapping)\n"); - process(event); - } + break; } - } } -static void process(keyevent_t event) +static void process(keyrecord_t *record) { + // TODO: use record + keyevent_t event = record->event; + uint8_t tap_count = record->tap_count; + if (IS_NOEVENT(event)) { return; } action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col); @@ -286,10 +334,11 @@ static void process(keyevent_t event) uint8_t tmp_mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods<<4; if (event.pressed) { - if (IS_TAPPING(event.key) && tap_count > 0) { - if (waiting_events_has_anykey_pressed()) { + if (IS_TAPPING_KEY(event.key) && tap_count > 0) { + if (waiting_buffer_has_anykey_pressed()) { debug("MODS_TAP: Tap: Cancel: add_mods\n"); - tap_count = 0; + // ad hoc: set 0 to cancel tap + record->tap_count = 0; add_mods(tmp_mods); } else { debug("MODS_TAP: Tap: register_code\n"); @@ -300,7 +349,7 @@ static void process(keyevent_t event) add_mods(tmp_mods); } } else { - if (IS_TAPPING(event.key) && tap_count > 0) { + if (IS_TAPPING_KEY(event.key) && tap_count > 0) { debug("MODS_TAP: Tap: unregister_code\n"); unregister_code(action.key.code); } else { @@ -367,7 +416,7 @@ static void process(keyevent_t event) default: // with tap key if (event.pressed) { - if (IS_TAPPING(event.key)) { + if (IS_TAPPING_KEY(event.key)) { if (tap_count > 0) { debug("LAYER_PRESSED: Tap: register_code\n"); register_code(action.layer.code); @@ -381,7 +430,7 @@ static void process(keyevent_t event) layer_switch(action.layer.opt); } /* - if (IS_TAPPING(event.key) && tap_count > 0) { + if (IS_TAPPING_KEY(event.key) && tap_count > 0) { debug("LAYER_PRESSED: Tap: register_code\n"); register_code(action.layer.code); } else { @@ -390,7 +439,7 @@ static void process(keyevent_t event) } */ } else { - if (IS_TAPPING(event.key) && tap_count > 0) { + if (IS_TAPPING_KEY(event.key) && tap_count > 0) { debug("LAYER_PRESSED: Tap: unregister_code\n"); unregister_code(action.layer.code); } else { @@ -446,7 +495,7 @@ static void process(keyevent_t event) default: // with tap key if (event.pressed) { - if (IS_TAPPING(event.key) && tap_count > 0) { + if (IS_TAPPING_KEY(event.key) && tap_count > 0) { debug("LAYER_BIT: Tap: register_code\n"); register_code(action.layer.code); } else { @@ -454,7 +503,7 @@ static void process(keyevent_t event) layer_switch(current_layer | action.layer.opt); } } else { - if (IS_TAPPING(event.key) && tap_count > 0) { + if (IS_TAPPING_KEY(event.key) && tap_count > 0) { debug("LAYER_BIT: Tap: unregister_code\n"); unregister_code(action.layer.code); } else { @@ -622,9 +671,9 @@ void layer_switch(uint8_t new_layer) } } -bool is_tap_key(keyevent_t event) +bool is_tap_key(key_t key) { - action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col); + action_t action = keymap_get_action(current_layer, key.pos.row, key.pos.col); switch (action.kind.id) { case ACT_LMODS_TAP: case ACT_RMODS_TAP: diff --git a/common/action.h b/common/action.h index 9aa1d78e9..327a009ef 100644 --- a/common/action.h +++ b/common/action.h @@ -19,7 +19,7 @@ void clear_keyboard(void); void clear_keyboard_but_mods(void); bool sending_anykey(void); void layer_switch(uint8_t new_layer); -bool is_tap_key(keyevent_t event); +bool is_tap_key(key_t key); @@ -197,11 +197,9 @@ enum stroke_cmd { STROKE_ALLUP, /* release all keys in reverse order */ }; -// TODO: not needed? typedef struct { keyevent_t event; - action_t action; - uint8_t mods; + uint8_t tap_count; } keyrecord_t; /* action function */ diff --git a/common/keyboard.c b/common/keyboard.c index 1aff81f54..2422fb758 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -80,7 +80,7 @@ void keyboard_task(void) action_exec((keyevent_t){ .key.pos = (keypos_t){ .row = r, .col = c }, .pressed = (matrix_row & (1< Date: Sun, 27 Jan 2013 10:37:15 +0900 Subject: [PATCH 14/30] Remove test_func. --- common/action.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/common/action.c b/common/action.c index 815931548..db31613bf 100644 --- a/common/action.c +++ b/common/action.c @@ -12,15 +12,7 @@ static void process(keyrecord_t *record); -void test_func(keyevent_t event, uint8_t opt) -{ - if (event.pressed) { - debug("test_func:pressed: "); debug_hex(opt); debug("\n"); - } else { - debug("test_func:released: "); debug_hex(opt); debug("\n"); - } -} - +// TODO /* layer */ uint8_t default_layer = 0; uint8_t current_layer = 0; @@ -570,7 +562,6 @@ static void process(keyrecord_t *record) break; case ACT_FUNCTION: action_call_function(event, action.func.id); - //test_func(event, action.func.opt); break; default: break; From 66d5dd284271d85da4c161529e12526b50b0f71d Mon Sep 17 00:00:00 2001 From: tmk Date: Sun, 27 Jan 2013 15:57:07 +0900 Subject: [PATCH 15/30] Fix keycodes. It has 32 Fn keys now. --- common/keycode.h | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/common/keycode.h b/common/keycode.h index 2eec2af85..cdd1e9758 100644 --- a/common/keycode.h +++ b/common/keycode.h @@ -44,7 +44,7 @@ along with this program. If not, see . #define FN_BIT(code) (1< Date: Sun, 27 Jan 2013 16:38:19 +0900 Subject: [PATCH 16/30] Add oneshot modifier action. --- common/action.c | 201 +++++++++++++++++++++++++++-------------- common/action.h | 198 +++++++++++++++++++--------------------- keyboard/hhkb/keymap.c | 12 ++- 3 files changed, 236 insertions(+), 175 deletions(-) diff --git a/common/action.c b/common/action.c index db31613bf..22f0bf0a0 100644 --- a/common/action.c +++ b/common/action.c @@ -97,6 +97,40 @@ static void waiting_buffer_process(void) { } +/* Oneshot modifier + * + * Problem: Want to capitalize like 'The' but the result tends to be 'THe'. + * Solution: Oneshot modifier have its effect on only one key coming next. + * Tap Shift, then type 't', 'h' and 'e'. Not need to hold Shift key. + * + * Hold: works as normal modifier. + * Tap: one shot modifier. + * 2 Tap: cancel one shot modifier. + * 5-Tap: toggles enable/disable oneshot feature. + */ +static struct { + uint8_t mods; + uint8_t time; + bool ready; + bool disabled; +} oneshot_state; +static void oneshot_start(uint8_t mods, uint16_t time) +{ + oneshot_state.mods = mods; + oneshot_state.time = time; + oneshot_state.ready = true; +} +static void oneshot_cancel(void) +{ + oneshot_state.mods = 0; + oneshot_state.time = 0; + oneshot_state.ready = false; +} +static void oneshot_toggle(void) +{ + oneshot_state.disabled = !oneshot_state.disabled; +} + /* * Rule to judge tap: @@ -271,83 +305,102 @@ static void process(keyrecord_t *record) switch (action.kind.id) { /* Key and Mods */ case ACT_LMODS: - // |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) { - host_add_mods(action.key.mods); - host_send_keyboard_report(); - } - register_code(action.key.code); - if (action.key.mods && action.key.code) { - host_set_mods(tmp_mods); - host_send_keyboard_report(); - } - } else { - if (action.key.mods && !action.key.code) { - host_del_mods(action.key.mods); - host_send_keyboard_report(); - } - unregister_code(action.key.code); - } - 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) { - host_add_mods(action.key.mods<<4); - host_send_keyboard_report(); + { + uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : + action.key.mods<<4; + if (event.pressed) { + uint8_t tmp_mods = host_get_mods(); + if (mods) { + host_add_mods(mods); + host_send_keyboard_report(); + } + register_code(action.key.code); + if (mods && action.key.code) { + host_set_mods(tmp_mods); + host_send_keyboard_report(); + } + } else { + if (mods && !action.key.code) { + host_del_mods(mods); + host_send_keyboard_report(); + } + unregister_code(action.key.code); } - register_code(action.key.code); - if (action.key.mods && action.key.code) { - host_set_mods(tmp_mods); - host_send_keyboard_report(); - } - } else { - if (action.key.mods && !action.key.code) { - host_del_mods(action.key.mods<<4); - host_send_keyboard_report(); - } - unregister_code(action.key.code); } break; case ACT_LMODS_TAP: case ACT_RMODS_TAP: { - uint8_t tmp_mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : - action.key.mods<<4; - if (event.pressed) { - if (IS_TAPPING_KEY(event.key) && tap_count > 0) { - if (waiting_buffer_has_anykey_pressed()) { - debug("MODS_TAP: Tap: Cancel: add_mods\n"); - // ad hoc: set 0 to cancel tap - record->tap_count = 0; - add_mods(tmp_mods); + uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : + action.key.mods<<4; + switch (action.layer.code) { + case 0x00: + // Oneshot modifier + if (event.pressed) { + if (tap_count == 0) { + debug("MODS_TAP: Oneshot: add_mods\n"); + add_mods(mods); + } + else if (tap_count == 1) { + debug("MODS_TAP: Oneshot: start\n"); + oneshot_start(mods, event.time); + } + else if (tap_count == 5) { + debug("MODS_TAP: Oneshot: toggle\n"); + oneshot_toggle(); + } + else { + debug("MODS_TAP: Oneshot: cancel&add_mods\n"); + // double tap cancels oneshot and works as normal modifier. + oneshot_cancel(); + add_mods(mods); + } } else { - debug("MODS_TAP: Tap: register_code\n"); - register_code(action.key.code); + if (tap_count == 0) { + debug("MODS_TAP: Oneshot: cancel/del_mods\n"); + // cancel oneshot by holding. + oneshot_cancel(); + del_mods(mods); + } + else if (tap_count == 1) { + debug("MODS_TAP: Oneshot: del_mods\n"); + // retain Oneshot + del_mods(mods); + } + else { + debug("MODS_TAP: Oneshot: del_mods\n"); + // cancel Mods + del_mods(mods); + } } - } else { - debug("MODS_TAP: No tap: add_mods\n"); - add_mods(tmp_mods); - } - } else { - if (IS_TAPPING_KEY(event.key) && tap_count > 0) { - debug("MODS_TAP: Tap: unregister_code\n"); - unregister_code(action.key.code); - } else { - debug("MODS_TAP: No tap: add_mods\n"); - del_mods(tmp_mods); - } + break; + default: + if (event.pressed) { + if (tap_count > 0) { + if (waiting_buffer_has_anykey_pressed()) { + debug("MODS_TAP: Tap: Cancel: add_mods\n"); + // ad hoc: set 0 to cancel tap + record->tap_count = 0; + add_mods(mods); + } else { + debug("MODS_TAP: Tap: register_code\n"); + register_code(action.key.code); + } + } else { + debug("MODS_TAP: No tap: add_mods\n"); + add_mods(mods); + } + } else { + if (tap_count > 0) { + debug("MODS_TAP: Tap: unregister_code\n"); + unregister_code(action.key.code); + } else { + debug("MODS_TAP: No tap: add_mods\n"); + del_mods(mods); + } + } + break; } } break; @@ -579,7 +632,17 @@ void register_code(uint8_t code) } else if IS_KEY(code) { // TODO: should push command_proc out of this block? - if (!command_proc(code)) { + if (command_proc(code)) return; + + if (oneshot_state.mods && oneshot_state.ready && !oneshot_state.disabled) { + uint8_t tmp_mods = host_get_mods(); + host_add_mods(oneshot_state.mods); + host_add_key(code); + host_send_keyboard_report(); + + host_set_mods(tmp_mods); + oneshot_state.ready = false; + } else { host_add_key(code); host_send_keyboard_report(); } diff --git a/common/action.h b/common/action.h index 327a009ef..1b5b30d86 100644 --- a/common/action.h +++ b/common/action.h @@ -3,10 +3,79 @@ #include "keyboard.h" + +/* Action struct. + * + * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15). + * AVR looks like a little endian in avr-gcc. + * + * TODO: not portable across compiler/endianness? + * Byte order and bit order of 0x1234: + * Big endian: 15 ... 8 7 ... 210 + * | 0x12 | 0x34 | + * 0001 0010 0011 0100 + * Little endian: 012 ... 7 8 ... 15 + * | 0x34 | 0x12 | + * 0010 1100 0100 1000 + */ +typedef union { + uint16_t code; + struct action_kind { + uint16_t param :12; + uint16_t id :4; + } kind; + struct action_key { + uint16_t code :8; + uint16_t mods :4; + uint16_t kind :4; + } key; + struct action_layer { + uint16_t code :8; + uint16_t opt :4; + uint16_t kind :4; + } layer; + struct action_usage { + uint16_t code :10; + uint16_t page :2; + uint16_t kind :4; + } usage; + struct action_command { + uint16_t id :8; + uint16_t option :4; + uint16_t kind :4; + } command; + struct action_function { + uint8_t id :8; + uint8_t opt :4; + uint8_t kind :4; + } func; +} action_t; + +/* Action record. For internal use. */ +typedef struct { + keyevent_t event; + uint8_t tap_count; +} keyrecord_t; + + +/* Tap count: Tap is comprised of press and release within TAP_TERM. + * 0 means no tap. + * >1 means tap. + */ extern uint8_t tap_count; + +/* current tap key event */ extern keyevent_t tapping_event; +/* action function */ +typedef void (*action_func_t)(keyevent_t event, uint8_t opt); + +// TODO: legacy keymap support +void action_exec(keyevent_t event); +void action_call_function(keyevent_t event, uint8_t id); + + /* * Utilities for actions. */ @@ -25,33 +94,36 @@ bool is_tap_key(key_t key); /* -Action codes -16bit code: action_kind(4bit) + action_parameter(12bit) - + * Action codes + * ============ + * 16bit code: action_kind(4bit) + action_parameter(12bit) + * 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 +0010|mods|000000|00 Left mods Momentary 0000|mods| keycode Key+Left mods ACT_RMODS(0001): 0001|0000|000000|00 No action +0001|0000| keycode Key(no used) 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|000000|00 Left mods OneShot +0010|mods|000000|01 (reserved) +0010|mods|000000|10 (reserved) +0010|mods|000000|11 (reserved) 0010|mods| keycode Left mods+tap Key ACT_RMODS_TAP(0011): +0011|mods|000000|00 Right mods OneShot +0011|mods|000000|01 (reserved) +0011|mods|000000|10 (reserved) +0011|mods|000000|11 (reserved) 0011|mods| keycode Right mods+tap Key @@ -108,24 +180,22 @@ Extensions(11XX) NOTE: NOT FIXED ACT_MACRO(1100): -1100|opt | id(8) Macro play -1100|1111| id(8) Macro record +1100|opt | id(8) Macro play? +1100|1111| id(8) Macro record? ACT_COMMAND(1110): 1110|opt | id(8) Built-in Command exec ACT_FUNCTION(1111): -1111| address(12) Function -1111|opt | id(8) Function - Macro record(dynamicly) - Macro play(dynamicly) -TODO: modifier + [tap key /w mod] - : layerkey + [tap key /w mod] +1111| address(12) Function? +1111|opt | id(8) Function? + +TODO: modifier + function by tap? for example: LShift + '('[Shift+9] and RShift + ')'[Shift+0] http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478.html#p90052 -*/ + */ -enum action_id { +enum action_kind_id { ACT_LMODS = 0b0000, ACT_RMODS = 0b0001, ACT_LMODS_TAP = 0b0010, @@ -144,74 +214,11 @@ enum action_id { ACT_FUNCTION = 0b1111 }; -// TODO: not portable across compiler/endianness? -/* -In avr-gcc bit fields seems to be assigned from LSB(bit0) to MSB(bit15). -AVR looks like a little endian in avr-gcc. - -Byte order and bit order of 0x1234: -Big endian: 15 ... 8 7 ... 210 - | 0x12 | 0x34 | - 0001 0010 0011 0100 -Little endian: 012 ... 7 8 ... 15 - | 0x34 | 0x12 | - 0010 1100 0100 1000 -*/ -typedef union { - uint16_t code; - struct action_kind { - uint16_t param :12; - uint16_t id :4; - } kind; - struct action_key { - uint16_t code :8; - uint16_t mods :4; - uint16_t kind :4; - } key; - struct action_layer { - uint16_t code :8; - uint16_t opt :4; - uint16_t kind :4; - } layer; - struct action_usage { - uint16_t code :10; - uint16_t page :2; - uint16_t kind :4; - } usage; - struct action_command { - uint16_t id :8; - uint16_t option :4; - uint16_t kind :4; - } command; - struct action_function { - uint8_t id :8; - uint8_t opt :4; - uint8_t kind :4; - } func; -} action_t; - - -enum stroke_cmd { - STROKE_DOWN, - STROKE_UP, - STROKE_ALLUP, /* release all keys in reverse order */ +enum acion_param { + ONE_SHOT = 0x00, }; -typedef struct { - keyevent_t event; - uint8_t tap_count; -} keyrecord_t; -/* action function */ -typedef void (*action_func_t)(keyevent_t event, uint8_t opt); - - -// TODO: legacy keymap support -void action_exec(keyevent_t event); -void action_call_function(keyevent_t event, uint8_t id); - - -// TODO: proper names /* action_t utility */ #define ACTION_NO 0 #define ACTION(kind, param) ((kind)<<12 | (param)) @@ -221,16 +228,12 @@ void action_call_function(keyevent_t event, uint8_t id); #define ACTION_KEY(key) ACTION(ACT_LMODS, key) #define ACTION_LMODS(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x00) #define ACTION_LMODS_KEY(mods, key) ACTION(ACT_LMODS, (mods)<<8 | (key)) -#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x01) -#define ACTION_LMODS_SWITCH(mods, tap) ACTION(ACT_LMODS, (mods)<<8 | 0xF0 | (tap)) -#define ACTION_LMODS_TOGGLE(mods, tap) ACTION(ACT_LMODS, (mods)<<8 | 0xF1 | (tap)) #define ACTION_RMODS(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x00) #define ACTION_RMODS_KEY(mods, key) ACTION(ACT_RMODS, (mods)<<8 | (key)) -#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x01) -#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, MOD_BITS(mods)<<8 | (key)) +#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MOD_BITS(mods)<<8 | ONE_SHOT) #define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP, MOD_BITS(mods)<<8 | (key)) /* Layer Switch */ @@ -268,15 +271,4 @@ void action_call_function(keyevent_t event, uint8_t id); /* Function */ #define ACTION_FUNCTION(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | id) - -/* helpers for readability */ -#define LAYER(layer) (layer) -#define TAP(tap) (tap) -#define DOUBLE_TAP 2 -#define TRIPLE_TAP 3 -#define QUADRUPLE_TAP 4 -#define QUINTUPLE_TAP 5 -#define DOWN(key) (key) -#define UP(key) STROKE_UP, (key) - #endif /* ACTION_H */ diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index e4eeb3e39..b74dc71ba 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -61,6 +61,8 @@ static const uint16_t PROGMEM fn_actions[] = { ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // Fn5 ACTION_LMODS_TAP(MOD_BIT(KC_LCTL), KC_BSPC), // Fn6 ACTION_RMODS_TAP(MOD_BIT(KC_RCTL), KC_ENT), // Fn7 + + ACTION_LMODS_TAP(MOD_BIT(KC_LSFT), ONE_SHOT), // Fn8 }; @@ -81,7 +83,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, \ 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, \ + FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ LGUI,LALT, FN5, RALT,FN4), /* Layer 1: HHKB mode (HHKB Fn) @@ -205,8 +207,12 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { action.code = ACTION_RMODS(MOD_BIT(key)>>4); break; */ - case KC_FN0 ... KC_FN7: - action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]); + case KC_FN0 ... FN_MAX: + if (FN_INDEX(key) < sizeof(fn_actions) / sizeof(fn_actions[0])) { + action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]); + } else { + action.code = ACTION_NO; + } break; case KC_NO ... KC_UNDEFINED: default: From 854c803fdda30d7f7905c18d777ea85cac9b74d9 Mon Sep 17 00:00:00 2001 From: tmk Date: Mon, 28 Jan 2013 11:30:23 +0900 Subject: [PATCH 17/30] Add tap toggle feature to action. --- common/action.c | 162 ++++++++++++++++++++++++++++++++--------- common/action.h | 26 ++++--- keyboard/hhkb/keymap.c | 6 +- 3 files changed, 145 insertions(+), 49 deletions(-) diff --git a/common/action.c b/common/action.c index 22f0bf0a0..4b3b1dd68 100644 --- a/common/action.c +++ b/common/action.c @@ -19,6 +19,8 @@ uint8_t current_layer = 0; /* tap term(ms) */ #define TAP_TERM 200 +/* number of tap which fires toggle feature */ +#define TAP_TOGGLE 5 /* This counts up when tap occurs */ uint8_t tap_count = 0; @@ -59,10 +61,11 @@ static bool waiting_buffer_enq(keyrecord_t record) waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE; return true; } +/* static keyrecord_t waiting_buffer_deq(void) { if (waiting_buffer_head == waiting_buffer_tail) { - return (keyrecord_t){}; + return (keyrecord_t){}; // ??? } uint8_t last_tail = waiting_buffer_tail; waiting_buffer_tail = waiting_buffer_tail + 1 % WAITING_BUFFER_SIZE; @@ -72,6 +75,7 @@ static bool waiting_buffer_is_empty(void) { return (waiting_buffer_head == waiting_buffer_tail); } +*/ static void waiting_buffer_clear(void) { waiting_buffer_head = 0; @@ -93,9 +97,7 @@ static bool waiting_buffer_has_anykey_pressed(void) } return false; } -static void waiting_buffer_process(void) -{ -} + /* Oneshot modifier * @@ -270,6 +272,7 @@ void action_exec(keyevent_t event) if (!IS_NOEVENT(record.event)) debug("processed.\n"); } else { if (!IS_NOEVENT(record.event)) debug("enqueued.\n"); + // enqueue if (!waiting_buffer_enq(record)) { // clear all in case of overflow. clear_keyboard(); @@ -278,7 +281,6 @@ void action_exec(keyevent_t event) } } - // TODO: need to process every time? // process waiting_buffer for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { if (process_tap(&waiting_buffer[waiting_buffer_tail])) { @@ -292,7 +294,6 @@ void action_exec(keyevent_t event) static void process(keyrecord_t *record) { - // TODO: use record keyevent_t event = record->event; uint8_t tap_count = record->tap_count; @@ -450,9 +451,20 @@ static void process(keyrecord_t *record) } break; case 0xF0: - // TODO: tap toggle + // tap toggle + if (event.pressed) { + if (tap_count < TAP_TOGGLE) { + layer_switch(action.layer.opt); + } + } else { + if (tap_count >= TAP_TOGGLE) { + debug("LAYER_PRESSED: tap toggle.\n"); + layer_switch(action.layer.opt); + } + } break; case 0xFF: + // change default layer if (event.pressed) { default_layer = action.layer.opt; layer_switch(default_layer); @@ -461,30 +473,15 @@ static void process(keyrecord_t *record) default: // with tap key if (event.pressed) { - if (IS_TAPPING_KEY(event.key)) { - if (tap_count > 0) { - debug("LAYER_PRESSED: Tap: register_code\n"); - register_code(action.layer.code); - } else { - debug("LAYER_PRESSED: No tap: layer_switch\n"); - layer_switch(action.layer.opt); - } - } else { - // TODO: while other key tapping - debug("LAYER_PRESSED: No tap: layer_switch\n"); - layer_switch(action.layer.opt); - } -/* - if (IS_TAPPING_KEY(event.key) && tap_count > 0) { + if (tap_count > 0) { debug("LAYER_PRESSED: Tap: register_code\n"); register_code(action.layer.code); - } else { + } else { debug("LAYER_PRESSED: No tap: layer_switch\n"); layer_switch(action.layer.opt); - } -*/ + } } else { - if (IS_TAPPING_KEY(event.key) && tap_count > 0) { + if (tap_count > 0) { debug("LAYER_PRESSED: Tap: unregister_code\n"); unregister_code(action.layer.code); } else { @@ -502,16 +499,43 @@ static void process(keyrecord_t *record) } break; case 0xF0: - // Ignored. LAYER_RELEASED with tap toggle is invalid action. + // tap toggle + if (event.pressed) { + if (tap_count >= TAP_TOGGLE) { + debug("LAYER_RELEASED: tap toggle.\n"); + layer_switch(action.layer.opt); + } + } else { + if (tap_count < TAP_TOGGLE) { + layer_switch(action.layer.opt); + } + } break; case 0xFF: + // change default layer if (!event.pressed) { default_layer = action.layer.opt; layer_switch(default_layer); } break; default: - // Ignored. LAYER_RELEASED with tap key is invalid action. + // with tap key + if (event.pressed) { + if (tap_count > 0) { + debug("LAYER_RELEASED: Tap: register_code\n"); + register_code(action.layer.code); + } else { + debug("LAYER_RELEASED: No tap: NO ACTION\n"); + } + } else { + if (tap_count > 0) { + debug("LAYER_RELEASED: Tap: unregister_code\n"); + unregister_code(action.layer.code); + } else { + debug("LAYER_RELEASED: No tap: layer_switch\n"); + layer_switch(action.layer.opt); + } + } break; } break; @@ -525,7 +549,21 @@ static void process(keyrecord_t *record) } break; case 0xF0: - // TODO: tap toggle + // tap toggle + if (event.pressed) { + if (tap_count < TAP_TOGGLE) { + debug("LAYER_BIT: tap toggle(press).\n"); + layer_switch(current_layer | action.layer.opt); + } + } else { + if (tap_count < TAP_TOGGLE) { + debug("LAYER_BIT: tap toggle(release).\n"); + layer_switch(current_layer & ~action.layer.opt); + } else { + debug("LAYER_BIT: tap toggle.\n"); + layer_switch(current_layer | action.layer.opt); + } + } break; case 0xFF: // change default layer @@ -558,6 +596,7 @@ static void process(keyrecord_t *record) } break; } + break; case ACT_LAYER_EXT: switch (action.layer.opt) { case 0x00: @@ -569,16 +608,43 @@ static void process(keyrecord_t *record) } break; case 0xF0: - // TODO: tap toggle + // tap toggle + if (event.pressed) { + if (tap_count < TAP_TOGGLE) { + layer_switch(default_layer); + } + } else { + if (tap_count >= TAP_TOGGLE) { + debug("LAYER_EXT_PRESSED: tap toggle.\n"); + layer_switch(default_layer); + } + } break; case 0xFF: + // change default layer if (event.pressed) { default_layer = current_layer; layer_switch(default_layer); } break; default: - // TODO: tap key + // with tap key + if (event.pressed) { + if (tap_count > 0) { + debug("LAYER_EXT_PRESSED: Tap: register_code\n"); + register_code(action.layer.code); + } else { + debug("LAYER_EXT_PRESSED: No tap: layer_switch\n"); + layer_switch(default_layer); + } + } else { + if (tap_count > 0) { + debug("LAYER_EXT_PRESSED: Tap: unregister_code\n"); + unregister_code(action.layer.code); + } else { + debug("LAYER_EXT_PRESSED: No tap: NO ACTION\n"); + } + } break; } break; @@ -590,17 +656,43 @@ static void process(keyrecord_t *record) layer_switch(default_layer); } break; + case 0xF0: + // tap toggle + if (event.pressed) { + if (tap_count >= TAP_TOGGLE) { + debug("LAYER_EXT_RELEASED: tap toggle.\n"); + layer_switch(default_layer); + } + } else { + if (tap_count < TAP_TOGGLE) { + layer_switch(default_layer); + } + } + break; case 0xFF: + // change default layer if (!event.pressed) { default_layer = current_layer; layer_switch(default_layer); } break; - case 0xF0: default: - // Ignore tap. - if (!event.pressed) { - layer_switch(default_layer); + // with tap key + if (event.pressed) { + if (tap_count > 0) { + debug("LAYER_EXT_RELEASED: Tap: register_code\n"); + register_code(action.layer.code); + } else { + debug("LAYER_EXT_RELEASED: No tap: NO ACTION\n"); + } + } else { + if (tap_count > 0) { + debug("LAYER_EXT_RELEASED: Tap: unregister_code\n"); + unregister_code(action.layer.code); + } else { + debug("LAYER_EXT_RELEASED: No tap: layer_switch\n"); + layer_switch(default_layer); + } } break; } diff --git a/common/action.h b/common/action.h index 1b5b30d86..bdd2d2f54 100644 --- a/common/action.h +++ b/common/action.h @@ -157,10 +157,10 @@ ACT_LAYER_EXT(1011): Extentions 1011|0001|0000 0000 set default layer when released 1000|LLLL|1111 0000 set layer L when pressed + tap toggle -1001|LLLL|1111 0000 set layer L when released[tap is ignored/not used] +1001|LLLL|1111 0000 set layer L when released + tap toggle 1010|BBBB|1111 0000 on/off bit B when pressed/released + tap toggle 1011|0000|1111 0000 set default layer when pressed + tap toggle -1011|0001|1111 0000 set default layer when released[tap is ignored/not used] +1011|0001|1111 0000 set default layer when released + tap toggle 1000|LLLL|1111 1111 set L to default layer when pressed 1001|LLLL|1111 1111 set L to default layer when released @@ -169,10 +169,10 @@ ACT_LAYER_EXT(1011): Extentions 1011|0001|1111 1111 set current to default layer when released 1000|LLLL| keycode set layer L when pressed + tap key -1001|LLLL| keyocde set layer L when released[tap is ignored/not used] +1001|LLLL| keyocde set layer L when released + tap key 1010|BBBB| keyocde on/off bit B when pressed/released + tap key 1011|0000| keyocde set default layer when pressed + tap key -1011|0001| keyocde set default layer when released[tap is ignored/not used] +1011|0001| keyocde set default layer when released + tap key Extensions(11XX) @@ -235,27 +235,29 @@ enum acion_param { #define ACTION_LMODS_TAP(mods, key) ACTION(ACT_LMODS_TAP, MOD_BITS(mods)<<8 | (key)) #define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MOD_BITS(mods)<<8 | ONE_SHOT) #define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP, MOD_BITS(mods)<<8 | (key)) +#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MOD_BITS(mods)<<8 | ONE_SHOT) -/* Layer Switch */ +/* Switch current layer */ #define ACTION_LAYER_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) #define ACTION_LAYER_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0x00) #define ACTION_LAYER_BIT(bits) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0x00) #define ACTION_LAYER_TO_DEFAULT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0x00) #define ACTION_LAYER_TO_DEFAULT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0x00) - -#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xF0) -#define ACTION_LAYER_BIT_TAP_TOGGLE(layer) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0xF0) -#define ACTION_LAYER_DEFAULT_TAP_TOGGLE ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xF0) - -#define ACTION_LAYER_DEFAULT_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xFF) +/* Switch default layer */ +#define ACTION_LAYER_DEFAULT_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xFF) #define ACTION_LAYER_DEFAULT_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xFF) #define ACTION_LAYER_DEFAULT_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0xFF) #define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xFF) #define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0xFF) - +/* Layer switch with tap key */ #define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | (key)) #define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (layer)<<8 | (key)) #define ACTION_LAYER_DEFAULT_SET_TAP_KEY(key) ACTION(ACT_LAYER_EXT, 0x0<<8 | (key)) +/* with tap toggle */ +#define ACTION_LAYER_SET_ON_PRESSED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xF0) +#define ACTION_LAYER_SET_ON_RELEASED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xF0) +#define ACTION_LAYER_BIT_TAP_TOGGLE(layer) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0xF0) +#define ACTION_LAYER_DEFAULT_TAP_TOGGLE ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xF0) /* HID Usage */ #define ACTION_USAGE_PAGE_SYSTEM 0 diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index b74dc71ba..2d0dabd70 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -63,6 +63,8 @@ static const uint16_t PROGMEM fn_actions[] = { ACTION_RMODS_TAP(MOD_BIT(KC_RCTL), KC_ENT), // Fn7 ACTION_LMODS_TAP(MOD_BIT(KC_LSFT), ONE_SHOT), // Fn8 + ACTION_LAYER_SET_ON_RELEASED_TAP_TOGGLE(1), // Fn9 + ACTION_LAYER_BIT_TAP_TOGGLE(1), // Fn10 }; @@ -83,7 +85,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, \ FN6, A, S, D, F, G, H, J, K, L, FN3, QUOT,FN7, \ - FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ + FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN10, \ LGUI,LALT, FN5, RALT,FN4), /* Layer 1: HHKB mode (HHKB Fn) @@ -102,7 +104,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, BSPC, \ LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ - LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN0, \ + LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN10, \ LGUI,LALT, SPC, RALT,RGUI), /* Layer 2: Vi mode (Slash) From 1e3e41a2c9ed8b2f7d44be0aed5d96ed557fa13d Mon Sep 17 00:00:00 2001 From: tmk Date: Mon, 28 Jan 2013 14:06:42 +0900 Subject: [PATCH 18/30] Clean code. --- common.mk | 1 + common/action.c | 331 ++++++++++++++++++++++------------------- common/action.h | 39 ++--- common/command.c | 17 +-- common/keyboard.c | 10 +- common/keyboard.h | 17 ++- common/keymap.h | 6 + keyboard/hhkb/config.h | 4 + keyboard/hhkb/keymap.c | 2 +- 9 files changed, 226 insertions(+), 201 deletions(-) diff --git a/common.mk b/common.mk index bd8616e5f..7cdaa5f74 100644 --- a/common.mk +++ b/common.mk @@ -2,6 +2,7 @@ COMMON_DIR = common SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/keyboard.c \ $(COMMON_DIR)/action.c \ + $(COMMON_DIR)/keymap.c \ $(COMMON_DIR)/command.c \ $(COMMON_DIR)/timer.c \ $(COMMON_DIR)/print.c \ diff --git a/common/action.c b/common/action.c index 4b3b1dd68..fb06e463c 100644 --- a/common/action.c +++ b/common/action.c @@ -1,3 +1,19 @@ +/* +Copyright 2012,2013 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 +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ #include "host.h" #include "timer.h" #include "keymap.h" @@ -10,36 +26,44 @@ #include "action.h" -static void process(keyrecord_t *record); +static bool process_tapping(keyrecord_t *record); +static void process_action(keyrecord_t *record); -// TODO -/* layer */ -uint8_t default_layer = 0; -uint8_t current_layer = 0; -/* tap term(ms) */ -#define TAP_TERM 200 -/* number of tap which fires toggle feature */ -#define TAP_TOGGLE 5 +/* + * Tapping + */ +/* period of tapping(ms) */ +#ifndef TAPPING_TERM +#define TAPPING_TERM 200 +#endif -/* This counts up when tap occurs */ -uint8_t tap_count = 0; -keyevent_t tapping_event = {}; -keyrecord_t tapping_key = {}; +/* tap count needed for toggling a feature */ +#ifndef TAPPING_TOGGLE +#define TAPPING_TOGGLE 5 +#endif -/* TAPPING: This indicates that whether tap or not is not decided yet. */ -// NOTE: keyevent_t.time 0 means no event. -#define IS_TAPPING() (tapping_key.event.time != 0) +/* stores a key event of current tap. */ +static keyrecord_t tapping_key = {}; + +#define IS_TAPPING() !IS_NOEVENT(tapping_key.event) #define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed) #define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) #define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) -#define WITHIN_TAP_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAP_TERM) +#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM) -/* waiting keys buffer */ + +/* + * Waiting buffer + * + * stores key events waiting for settling current tap. + */ #define WAITING_BUFFER_SIZE 8 static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; + /* point to empty cell to enq */ static uint8_t waiting_buffer_head = 0; + /* point to the oldest data cell to deq */ static uint8_t waiting_buffer_tail = 0; @@ -65,7 +89,7 @@ static bool waiting_buffer_enq(keyrecord_t record) static keyrecord_t waiting_buffer_deq(void) { if (waiting_buffer_head == waiting_buffer_tail) { - return (keyrecord_t){}; // ??? + return (keyrecord_t){}; } uint8_t last_tail = waiting_buffer_tail; waiting_buffer_tail = waiting_buffer_tail + 1 % WAITING_BUFFER_SIZE; @@ -134,125 +158,6 @@ static void oneshot_toggle(void) } -/* - * Rule to judge tap: - * Tap key is typed(pressed and released) within TAP_TERM - * without interfaring by typing other key. - */ -/* return true when key event is processed. */ -static bool process_tap(keyrecord_t *keyp) -{ - keyevent_t event = keyp->event; - - // if tapping - if (IS_TAPPING_PRESSED()) { - if (WITHIN_TAP_TERM(event)) { - if (tapping_key.tap_count == 0) { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { - // first tap! - debug("Tapping: First tap.\n"); - tapping_key.tap_count = 1; - process(&tapping_key); - - // enqueue - keyp->tap_count = tapping_key.tap_count; - return false; - } else if (!event.pressed && waiting_buffer_typed(event)) { - // other key typed. not tap. - debug("Tapping: End(No tap. Interfered by typing key).\n"); - process(&tapping_key); - tapping_key = (keyrecord_t){}; - - // enqueue - return false; - } else { - // other key events shall be stored till tapping state settles. - return false; - } - } else { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { - keyp->tap_count = tapping_key.tap_count; - debug("Tapping: tap release("); debug_dec(keyp->tap_count); debug(")\n"); - tapping_key = *keyp; - return false; - } - else if (is_tap_key(keyp->event.key) && event.pressed) { - debug("Tapping: Start with forcing to release last tap.\n"); - process(&(keyrecord_t){ - .tap_count = tapping_key.tap_count, - .event.key = tapping_key.event.key, - .event.time = event.time, - .event.pressed = false - }); - tapping_key = *keyp; - return false; - } - else { - if (!IS_NOEVENT(keyp->event)) debug("Tapping: key event while tap.\n"); - process(keyp); - return true; - } - } - } - // not within TAP_TERM - else { - if (tapping_key.tap_count == 0) { - // timeout. not tap. - debug("Tapping: End. Not tap(time out).\n"); - process(&tapping_key); - tapping_key = (keyrecord_t){}; - return false; - } else { - if (IS_TAPPING_KEY(event.key) && !event.pressed) { - debug("Tapping: End. tap release."); - keyp->tap_count = tapping_key.tap_count; - process(keyp); - tapping_key = (keyrecord_t){}; - return true; - } else { - // other key after tap time out. - process(keyp); - return true; - } - } - } - } else if (IS_TAPPING_RELEASED()) { - if (WITHIN_TAP_TERM(event)) { - if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) { - // sequential tap. - keyp->tap_count = tapping_key.tap_count + 1; - debug("Tapping: tap press("); debug_dec(keyp->tap_count); debug(")\n"); - process(keyp); - tapping_key = *keyp; - return true; - } else if (event.pressed && is_tap_key(event.key)) { - // Sequential tap can be interfered with other tap key. - debug("Tapping: Start with interfering other tap.\n"); - tapping_key = *keyp; - return true; - } else { - if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n"); - process(keyp); - return true; - } - } else { - // timeout. no sequential tap. - debug("Tapping: End(Time out after releasing last tap).\n"); - tapping_key = (keyrecord_t){}; - process(keyp); - return true; - } - } else { - if (event.pressed && is_tap_key(event.key)) { - debug("Tapping: Start(Press tap key).\n"); - tapping_key = *keyp; - return true; - } else { - process(keyp); - return true; - } - } -} void action_exec(keyevent_t event) { @@ -268,7 +173,7 @@ void action_exec(keyevent_t event) keyrecord_t record = { .event = event }; // pre-process on tapping - if (process_tap(&record)) { + if (process_tapping(&record)) { if (!IS_NOEVENT(record.event)) debug("processed.\n"); } else { if (!IS_NOEVENT(record.event)) debug("enqueued.\n"); @@ -283,7 +188,7 @@ void action_exec(keyevent_t event) // process waiting_buffer for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { - if (process_tap(&waiting_buffer[waiting_buffer_tail])) { + if (process_tapping(&waiting_buffer[waiting_buffer_tail])) { debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = "); debug_hex16(waiting_buffer[waiting_buffer_tail].event.key.raw); debug("\n"); } else { @@ -292,7 +197,7 @@ void action_exec(keyevent_t event) } } -static void process(keyrecord_t *record) +static void process_action(keyrecord_t *record) { keyevent_t event = record->event; uint8_t tap_count = record->tap_count; @@ -453,11 +358,11 @@ static void process(keyrecord_t *record) case 0xF0: // tap toggle if (event.pressed) { - if (tap_count < TAP_TOGGLE) { + if (tap_count < TAPPING_TOGGLE) { layer_switch(action.layer.opt); } } else { - if (tap_count >= TAP_TOGGLE) { + if (tap_count >= TAPPING_TOGGLE) { debug("LAYER_PRESSED: tap toggle.\n"); layer_switch(action.layer.opt); } @@ -501,12 +406,12 @@ static void process(keyrecord_t *record) case 0xF0: // tap toggle if (event.pressed) { - if (tap_count >= TAP_TOGGLE) { + if (tap_count >= TAPPING_TOGGLE) { debug("LAYER_RELEASED: tap toggle.\n"); layer_switch(action.layer.opt); } } else { - if (tap_count < TAP_TOGGLE) { + if (tap_count < TAPPING_TOGGLE) { layer_switch(action.layer.opt); } } @@ -551,12 +456,12 @@ static void process(keyrecord_t *record) case 0xF0: // tap toggle if (event.pressed) { - if (tap_count < TAP_TOGGLE) { + if (tap_count < TAPPING_TOGGLE) { debug("LAYER_BIT: tap toggle(press).\n"); layer_switch(current_layer | action.layer.opt); } } else { - if (tap_count < TAP_TOGGLE) { + if (tap_count < TAPPING_TOGGLE) { debug("LAYER_BIT: tap toggle(release).\n"); layer_switch(current_layer & ~action.layer.opt); } else { @@ -610,11 +515,11 @@ static void process(keyrecord_t *record) case 0xF0: // tap toggle if (event.pressed) { - if (tap_count < TAP_TOGGLE) { + if (tap_count < TAPPING_TOGGLE) { layer_switch(default_layer); } } else { - if (tap_count >= TAP_TOGGLE) { + if (tap_count >= TAPPING_TOGGLE) { debug("LAYER_EXT_PRESSED: tap toggle.\n"); layer_switch(default_layer); } @@ -659,12 +564,12 @@ static void process(keyrecord_t *record) case 0xF0: // tap toggle if (event.pressed) { - if (tap_count >= TAP_TOGGLE) { + if (tap_count >= TAPPING_TOGGLE) { debug("LAYER_EXT_RELEASED: tap toggle.\n"); layer_switch(default_layer); } } else { - if (tap_count < TAP_TOGGLE) { + if (tap_count < TAPPING_TOGGLE) { layer_switch(default_layer); } } @@ -706,6 +611,7 @@ static void process(keyrecord_t *record) case ACT_COMMAND: break; case ACT_FUNCTION: + // TODO action_call_function(event, action.func.id); break; default: @@ -713,6 +619,127 @@ static void process(keyrecord_t *record) } } +/* Tapping + * + * Rule: Tap key is typed(pressed and released) within TAPPING_TERM + * without interfaring by typing other key. + */ +/* return true when key event is processed. */ +static bool process_tapping(keyrecord_t *keyp) +{ + keyevent_t event = keyp->event; + + // if tapping + if (IS_TAPPING_PRESSED()) { + if (WITHIN_TAPPING_TERM(event)) { + if (tapping_key.tap_count == 0) { + if (IS_TAPPING_KEY(event.key) && !event.pressed) { + // first tap! + debug("Tapping: First tap.\n"); + tapping_key.tap_count = 1; + process_action(&tapping_key); + + // enqueue + keyp->tap_count = tapping_key.tap_count; + return false; + } else if (!event.pressed && waiting_buffer_typed(event)) { + // other key typed. not tap. + debug("Tapping: End(No tap. Interfered by typing key).\n"); + process_action(&tapping_key); + tapping_key = (keyrecord_t){}; + + // enqueue + return false; + } else { + // other key events shall be stored till tapping state settles. + return false; + } + } else { + if (IS_TAPPING_KEY(event.key) && !event.pressed) { + keyp->tap_count = tapping_key.tap_count; + debug("Tapping: tap release("); debug_dec(keyp->tap_count); debug(")\n"); + tapping_key = *keyp; + return false; + } + else if (is_tap_key(keyp->event.key) && event.pressed) { + debug("Tapping: Start with forcing to release last tap.\n"); + process_action(&(keyrecord_t){ + .tap_count = tapping_key.tap_count, + .event.key = tapping_key.event.key, + .event.time = event.time, + .event.pressed = false + }); + tapping_key = *keyp; + return false; + } + else { + if (!IS_NOEVENT(keyp->event)) debug("Tapping: key event while tap.\n"); + process_action(keyp); + return true; + } + } + } + // not within TAPPING_TERM + else { + if (tapping_key.tap_count == 0) { + // timeout. not tap. + debug("Tapping: End. Not tap(time out).\n"); + process_action(&tapping_key); + tapping_key = (keyrecord_t){}; + return false; + } else { + if (IS_TAPPING_KEY(event.key) && !event.pressed) { + debug("Tapping: End. tap release."); + keyp->tap_count = tapping_key.tap_count; + process_action(keyp); + tapping_key = (keyrecord_t){}; + return true; + } else { + // other key after tap time out. + process_action(keyp); + return true; + } + } + } + } else if (IS_TAPPING_RELEASED()) { + if (WITHIN_TAPPING_TERM(event)) { + if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) { + // sequential tap. + keyp->tap_count = tapping_key.tap_count + 1; + debug("Tapping: tap press("); debug_dec(keyp->tap_count); debug(")\n"); + process_action(keyp); + tapping_key = *keyp; + return true; + } else if (event.pressed && is_tap_key(event.key)) { + // Sequential tap can be interfered with other tap key. + debug("Tapping: Start with interfering other tap.\n"); + tapping_key = *keyp; + return true; + } else { + if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n"); + process_action(keyp); + return true; + } + } else { + // timeout. no sequential tap. + debug("Tapping: End(Time out after releasing last tap).\n"); + tapping_key = (keyrecord_t){}; + process_action(keyp); + return true; + } + } else { + if (event.pressed && is_tap_key(event.key)) { + debug("Tapping: Start(Press tap key).\n"); + tapping_key = *keyp; + return true; + } else { + process_action(keyp); + return true; + } + } +} + + /* * Utilities for actions. @@ -813,7 +840,7 @@ void layer_switch(uint8_t new_layer) current_layer = new_layer; clear_keyboard_but_mods(); // To avoid stuck keys - // TODO: update mods with full scan of matrix? if modifier changes between layers + // NOTE: update mods with full scan of matrix? if modifier changes between layers } } diff --git a/common/action.h b/common/action.h index bdd2d2f54..ed3fff6c2 100644 --- a/common/action.h +++ b/common/action.h @@ -1,3 +1,19 @@ +/* +Copyright 2012,2013 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 +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ #ifndef ACTION_H #define ACTION_H @@ -9,7 +25,7 @@ * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15). * AVR looks like a little endian in avr-gcc. * - * TODO: not portable across compiler/endianness? + * NOTE: not portable across compiler/endianness? * Byte order and bit order of 0x1234: * Big endian: 15 ... 8 7 ... 210 * | 0x12 | 0x34 | @@ -51,29 +67,17 @@ typedef union { } func; } action_t; -/* Action record. For internal use. */ +/* Struct to record action and tap count */ typedef struct { keyevent_t event; uint8_t tap_count; } keyrecord_t; -/* Tap count: Tap is comprised of press and release within TAP_TERM. - * 0 means no tap. - * >1 means tap. - */ -extern uint8_t tap_count; - -/* current tap key event */ -extern keyevent_t tapping_event; - - -/* action function */ -typedef void (*action_func_t)(keyevent_t event, uint8_t opt); - -// TODO: legacy keymap support +/* execute action per keyevent */ void action_exec(keyevent_t event); -void action_call_function(keyevent_t event, uint8_t id); +typedef void (*action_func_t)(keyevent_t event, uint8_t opt); // TODO:no need? +void action_call_function(keyevent_t event, uint8_t id); // TODO: action function /* @@ -194,7 +198,6 @@ TODO: modifier + function by tap? for example: LShift + '('[Shift+9] and RShift + ')'[Shift+0] http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478.html#p90052 */ - enum action_kind_id { ACT_LMODS = 0b0000, ACT_RMODS = 0b0001, diff --git a/common/command.c b/common/command.c index a06e6a00d..8ca16b910 100644 --- a/common/command.c +++ b/common/command.c @@ -19,6 +19,7 @@ along with this program. If not, see . #include #include "keycode.h" #include "host.h" +#include "keymap.h" #include "print.h" #include "debug.h" #include "util.h" @@ -53,7 +54,6 @@ static void mousekey_console_help(void); static uint8_t numkey2num(uint8_t code); static void switch_layer(uint8_t layer); -static void clear_keyboard(void); typedef enum { ONESHOT, CONSOLE, MOUSEKEY } cmdstate_t; @@ -555,18 +555,3 @@ static void switch_layer(uint8_t layer) default_layer = layer; print("switch to "); print_val_hex8(layer); } - -static void clear_keyboard(void) -{ - host_clear_keys(); - host_clear_mods(); - host_send_keyboard_report(); - - host_system_send(0); - host_consumer_send(0); - -#ifdef MOUSEKEY_ENABLE - mousekey_clear(); - mousekey_send(); -#endif -} diff --git a/common/keyboard.c b/common/keyboard.c index 2422fb758..5e9945baf 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -1,5 +1,5 @@ /* -Copyright 2011,2012 Jun Wako +Copyright 2011,2012,2013 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 @@ -34,8 +34,6 @@ along with this program. If not, see . void keyboard_init(void) { - // TODO: to enable debug print magic key bind on boot time - // TODO: configuration of sendchar impl print_sendchar_func = sendchar; @@ -80,7 +78,7 @@ void keyboard_task(void) action_exec((keyevent_t){ .key.pos = (keypos_t){ .row = r, .col = c }, .pressed = (matrix_row & (1< +Copyright 2011,2012,2013 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 @@ -26,6 +26,7 @@ along with this program. If not, see . extern "C" { #endif +/* key matrix position */ typedef struct { uint8_t col; uint8_t row; @@ -36,29 +37,33 @@ typedef union { keypos_t pos; } key_t; +/* key event */ typedef struct { key_t key; bool pressed; uint16_t time; } keyevent_t; +/* equivalent test of key_t */ #define KEYEQ(keya, keyb) ((keya).raw == (keyb).raw) -#define IS_NOEVENT(event) ((event).key.pos.row == 255 && (event).key.pos.col == 255) + +/* (time == 0) means no event and assumes matrix has no 255 line. */ +#define IS_NOEVENT(event) ((event).time == 0 || ((event).key.pos.row == 255 && (event).key.pos.col == 255)) + #define NOEVENT (keyevent_t){ \ .key.pos = (keypos_t){ .row = 255, .col = 255 }, \ .pressed = false, \ .time = 0 \ } + +/* tick event */ #define TICK (keyevent_t){ \ .key.pos = (keypos_t){ .row = 255, .col = 255 }, \ .pressed = false, \ - .time = timer_read() \ + .time = (timer_read() | 1) \ } -extern uint8_t current_layer; -extern uint8_t default_layer; - void keyboard_init(void); void keyboard_task(void); void keyboard_set_leds(uint8_t leds); diff --git a/common/keymap.h b/common/keymap.h index f992be18e..f54fea90d 100644 --- a/common/keymap.h +++ b/common/keymap.h @@ -22,6 +22,12 @@ along with this program. If not, see . #include #include "action.h" + +/* layer used currently */ +extern uint8_t current_layer; +/* layer to return or start with */ +extern uint8_t default_layer; + /* * legacy keymap interface: keycode */ diff --git a/keyboard/hhkb/config.h b/keyboard/hhkb/config.h index 66dede9a5..5fcec95eb 100644 --- a/keyboard/hhkb/config.h +++ b/keyboard/hhkb/config.h @@ -59,6 +59,10 @@ along with this program. If not, see . # define MOUSEKEY_DELAY_TIME 100 #endif +/* period of tapping(ms) */ +#define TAPPING_TERM 200 +/* tap count needed for toggling a feature */ +#define TAPPING_TOGGLE 5 /* PS/2 mouse */ #ifdef PS2_MOUSE_ENABLE diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index 2d0dabd70..c7e4cfc38 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -1,5 +1,5 @@ /* -Copyright 2011 Jun Wako +Copyright 2011,2012,2013 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 From ddb560052a8a336b5cec64ce08399c8299c9b4da Mon Sep 17 00:00:00 2001 From: tmk Date: Tue, 29 Jan 2013 10:40:43 +0900 Subject: [PATCH 19/30] Clean debug print in action.c. --- common/action.c | 95 ++++++++++++++++++++++++++++++++++++++----------- common/debug.h | 1 + common/print.c | 9 +++-- common/print.h | 2 ++ 4 files changed, 84 insertions(+), 23 deletions(-) diff --git a/common/action.c b/common/action.c index fb06e463c..e93a9afe3 100644 --- a/common/action.c +++ b/common/action.c @@ -29,6 +29,41 @@ along with this program. If not, see . static bool process_tapping(keyrecord_t *record); static void process_action(keyrecord_t *record); +static void debug_event(keyevent_t event) +{ + debug_hex16(event.key.raw); + if (event.pressed) debug("d("); else debug("u("); + debug_dec(event.time); debug(")"); +} +static void debug_record(keyrecord_t record) +{ + debug_event(record.event); debug(":"); debug_dec(record.tap_count); +} +static void debug_action(action_t action) +{ + switch (action.kind.id) { + case ACT_LMODS: debug("ACT_LMODS"); break; + case ACT_RMODS: debug("ACT_RMODS"); break; + case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break; + case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break; + case ACT_USAGE: debug("ACT_USAGE"); break; + case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break; + case ACT_LAYER_PRESSED: debug("ACT_LAYER_PRESSED"); break; + case ACT_LAYER_RELEASED: debug("ACT_LAYER_RELEASED"); break; + case ACT_LAYER_BIT: debug("ACT_LAYER_BIT"); break; + case ACT_LAYER_EXT: debug("ACT_LAYER_EXT"); break; + case ACT_MACRO: debug("ACT_MACRO"); break; + case ACT_COMMAND: debug("ACT_COMMAND"); break; + case ACT_FUNCTION: debug("ACT_FUNCTION"); break; + default: debug("UNKNOWN"); break; + } + debug("["); + debug_hex4(action.kind.param>>8); + debug(":"); + debug_hex8(action.kind.param & 0xff); + debug("]"); +} + /* * Tapping @@ -67,6 +102,14 @@ static uint8_t waiting_buffer_head = 0; /* point to the oldest data cell to deq */ static uint8_t waiting_buffer_tail = 0; +static void debug_waiting_buffer(void) +{ + debug("{ "); + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" "); + } + debug("}\n"); +} static bool waiting_buffer_enq(keyrecord_t record) { if (IS_NOEVENT(record.event)) { @@ -78,11 +121,10 @@ static bool waiting_buffer_enq(keyrecord_t record) return false; } - debug("waiting_buffer_enq["); debug_dec(waiting_buffer_head); debug("] = "); - debug_hex16(record.event.key.raw); debug("\n"); - waiting_buffer[waiting_buffer_head] = record; waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE; + + debug("waiting_buffer_enq: "); debug_waiting_buffer(); return true; } /* @@ -162,21 +204,18 @@ static void oneshot_toggle(void) void action_exec(keyevent_t event) { if (!IS_NOEVENT(event)) { - debug("event: "); - debug_hex16(event.time); debug(": "); - debug_hex16(event.key.raw); - debug("["); - if (event.pressed) debug("down"); else debug("up"); - debug("]\n"); + debug("\n---- action_exec: start -----\n"); + debug("EVENT: "); debug_event(event); debug("\n"); } keyrecord_t record = { .event = event }; // pre-process on tapping if (process_tapping(&record)) { - if (!IS_NOEVENT(record.event)) debug("processed.\n"); + if (!IS_NOEVENT(record.event)) { + debug("processed: "); debug_record(record); debug("\n"); + } } else { - if (!IS_NOEVENT(record.event)) debug("enqueued.\n"); // enqueue if (!waiting_buffer_enq(record)) { // clear all in case of overflow. @@ -187,14 +226,20 @@ void action_exec(keyevent_t event) } // process waiting_buffer + if (!IS_NOEVENT(event) && waiting_buffer_head != waiting_buffer_tail) { + debug("---- action_exec: process waiting_buffer -----\n"); + } for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { if (process_tapping(&waiting_buffer[waiting_buffer_tail])) { debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = "); - debug_hex16(waiting_buffer[waiting_buffer_tail].event.key.raw); debug("\n"); + debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n"); } else { break; } } + if (!IS_NOEVENT(event)) { + debug("\n"); + } } static void process_action(keyrecord_t *record) @@ -205,8 +250,8 @@ static void process_action(keyrecord_t *record) if (IS_NOEVENT(event)) { return; } action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col); - debug("action: "); debug_hex16(action.code); - if (event.pressed) debug("[down]\n"); else debug("[up]\n"); + //debug("action: "); debug_hex16(action.code); if (event.pressed) debug("d\n"); else debug("u\n"); + debug("ACTION: "); debug_action(action); debug("\n"); switch (action.kind.id) { /* Key and Mods */ @@ -635,8 +680,8 @@ static bool process_tapping(keyrecord_t *keyp) if (tapping_key.tap_count == 0) { if (IS_TAPPING_KEY(event.key) && !event.pressed) { // first tap! - debug("Tapping: First tap.\n"); tapping_key.tap_count = 1; + debug("Tapping: First tap: tapping_key="); debug_record(tapping_key); debug("\n"); process_action(&tapping_key); // enqueue @@ -644,7 +689,7 @@ static bool process_tapping(keyrecord_t *keyp) return false; } else if (!event.pressed && waiting_buffer_typed(event)) { // other key typed. not tap. - debug("Tapping: End(No tap. Interfered by typing key).\n"); + debug("Tapping: End. No tap. Interfered by typing key: tapping_key={}\n"); process_action(&tapping_key); tapping_key = (keyrecord_t){}; @@ -654,15 +699,19 @@ static bool process_tapping(keyrecord_t *keyp) // other key events shall be stored till tapping state settles. return false; } - } else { + } + // tap_count > 0 + else { if (IS_TAPPING_KEY(event.key) && !event.pressed) { keyp->tap_count = tapping_key.tap_count; - debug("Tapping: tap release("); debug_dec(keyp->tap_count); debug(")\n"); + debug("Tapping: Tap release: tapping_key="); debug_record(*keyp); debug("\n"); tapping_key = *keyp; return false; } else if (is_tap_key(keyp->event.key) && event.pressed) { - debug("Tapping: Start with forcing to release last tap.\n"); + debug("Tapping: Start with forcing to release last tap: tapping_key="); + debug_record(*keyp); debug("\n"); +// TODO: need only when tap > 1? process_action(&(keyrecord_t){ .tap_count = tapping_key.tap_count, .event.key = tapping_key.event.key, @@ -673,7 +722,10 @@ static bool process_tapping(keyrecord_t *keyp) return false; } else { - if (!IS_NOEVENT(keyp->event)) debug("Tapping: key event while tap.\n"); + if (!IS_NOEVENT(keyp->event)) { + debug("Tapping: key event while tap: tapping_key="); + debug_record(tapping_key); debug("\n"); + } process_action(keyp); return true; } @@ -683,7 +735,7 @@ static bool process_tapping(keyrecord_t *keyp) else { if (tapping_key.tap_count == 0) { // timeout. not tap. - debug("Tapping: End. Not tap(time out).\n"); + debug("Tapping: End. Not tap(time out): tapping_key={}: "); debug_record(*keyp); debug("\n"); process_action(&tapping_key); tapping_key = (keyrecord_t){}; return false; @@ -731,6 +783,7 @@ static bool process_tapping(keyrecord_t *keyp) if (event.pressed && is_tap_key(event.key)) { debug("Tapping: Start(Press tap key).\n"); tapping_key = *keyp; + debug("tapping_key="); debug_record(*keyp); debug("\n"); return true; } else { process_action(keyp); diff --git a/common/debug.h b/common/debug.h index 648f0e096..e63d46f0e 100644 --- a/common/debug.h +++ b/common/debug.h @@ -36,6 +36,7 @@ along with this program. If not, see . #define debug_dec(data) do { if (debug_enable) print_dec(data); } while (0) #define debug_decs(data) do { if (debug_enable) print_decs(data); } while (0) +#define debug_hex4(data) do { if (debug_enable) print_hex4(data); } while (0) #define debug_hex8(data) do { if (debug_enable) print_hex8(data); } while (0) #define debug_hex16(data) do { if (debug_enable) print_hex16(data); } while (0) #define debug_hex32(data) do { if (debug_enable) print_hex32(data); } while (0) diff --git a/common/print.c b/common/print.c index d8a899b40..08d211f20 100644 --- a/common/print.c +++ b/common/print.c @@ -113,7 +113,6 @@ void print_decs(int16_t data) } -static inline void print_hex4(uint8_t data) { sendchar(data + ((data < 10) ? '0' : 'A' - 10)); @@ -137,8 +136,14 @@ void print_hex32(uint32_t data) print_hex16(data); } +void print_bin4(uint8_t data) +{ + for (int i = 4; i >= 0; i--) { + sendchar((data & (1<= 0; i--) { sendchar((data & (1< Date: Wed, 30 Jan 2013 20:31:32 +0900 Subject: [PATCH 20/30] Fix process_tapping(). --- common/action.c | 256 +++++++++++++++++++++++++++++++----------------- 1 file changed, 166 insertions(+), 90 deletions(-) diff --git a/common/action.c b/common/action.c index e93a9afe3..28d9a95f5 100644 --- a/common/action.c +++ b/common/action.c @@ -26,43 +26,15 @@ along with this program. If not, see . #include "action.h" -static bool process_tapping(keyrecord_t *record); static void process_action(keyrecord_t *record); +static bool process_tapping(keyrecord_t *record); +static void waiting_buffer_scan_tap(void); -static void debug_event(keyevent_t event) -{ - debug_hex16(event.key.raw); - if (event.pressed) debug("d("); else debug("u("); - debug_dec(event.time); debug(")"); -} -static void debug_record(keyrecord_t record) -{ - debug_event(record.event); debug(":"); debug_dec(record.tap_count); -} -static void debug_action(action_t action) -{ - switch (action.kind.id) { - case ACT_LMODS: debug("ACT_LMODS"); break; - case ACT_RMODS: debug("ACT_RMODS"); break; - case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break; - case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break; - case ACT_USAGE: debug("ACT_USAGE"); break; - case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break; - case ACT_LAYER_PRESSED: debug("ACT_LAYER_PRESSED"); break; - case ACT_LAYER_RELEASED: debug("ACT_LAYER_RELEASED"); break; - case ACT_LAYER_BIT: debug("ACT_LAYER_BIT"); break; - case ACT_LAYER_EXT: debug("ACT_LAYER_EXT"); break; - case ACT_MACRO: debug("ACT_MACRO"); break; - case ACT_COMMAND: debug("ACT_COMMAND"); break; - case ACT_FUNCTION: debug("ACT_FUNCTION"); break; - default: debug("UNKNOWN"); break; - } - debug("["); - debug_hex4(action.kind.param>>8); - debug(":"); - debug_hex8(action.kind.param & 0xff); - debug("]"); -} +static void debug_event(keyevent_t event); +static void debug_record(keyrecord_t record); +static void debug_action(action_t action); +static void debug_tapping_key(void); +static void debug_waiting_buffer(void); /* @@ -102,14 +74,6 @@ static uint8_t waiting_buffer_head = 0; /* point to the oldest data cell to deq */ static uint8_t waiting_buffer_tail = 0; -static void debug_waiting_buffer(void) -{ - debug("{ "); - for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { - debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" "); - } - debug("}\n"); -} static bool waiting_buffer_enq(keyrecord_t record) { if (IS_NOEVENT(record.event)) { @@ -127,26 +91,14 @@ static bool waiting_buffer_enq(keyrecord_t record) debug("waiting_buffer_enq: "); debug_waiting_buffer(); return true; } -/* -static keyrecord_t waiting_buffer_deq(void) -{ - if (waiting_buffer_head == waiting_buffer_tail) { - return (keyrecord_t){}; - } - uint8_t last_tail = waiting_buffer_tail; - waiting_buffer_tail = waiting_buffer_tail + 1 % WAITING_BUFFER_SIZE; - return waiting_buffer[last_tail]; -} -static bool waiting_buffer_is_empty(void) -{ - return (waiting_buffer_head == waiting_buffer_tail); -} -*/ + static void waiting_buffer_clear(void) { waiting_buffer_head = 0; waiting_buffer_tail = 0; } + +#if TAPPING_TERM >= 500 static bool waiting_buffer_typed(keyevent_t event) { for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { @@ -156,6 +108,8 @@ static bool waiting_buffer_typed(keyevent_t event) } return false; } +#endif + static bool waiting_buffer_has_anykey_pressed(void) { for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { @@ -182,18 +136,21 @@ static struct { bool ready; bool disabled; } oneshot_state; + static void oneshot_start(uint8_t mods, uint16_t time) { oneshot_state.mods = mods; oneshot_state.time = time; oneshot_state.ready = true; } + static void oneshot_cancel(void) { oneshot_state.mods = 0; oneshot_state.time = 0; oneshot_state.ready = false; } + static void oneshot_toggle(void) { oneshot_state.disabled = !oneshot_state.disabled; @@ -219,6 +176,7 @@ void action_exec(keyevent_t event) // enqueue if (!waiting_buffer_enq(record)) { // clear all in case of overflow. + debug("OVERFLOW: CLEAR ALL STATES\n"); clear_keyboard(); waiting_buffer_clear(); tapping_key = (keyrecord_t){}; @@ -229,6 +187,7 @@ void action_exec(keyevent_t event) if (!IS_NOEVENT(event) && waiting_buffer_head != waiting_buffer_tail) { debug("---- action_exec: process waiting_buffer -----\n"); } + for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { if (process_tapping(&waiting_buffer[waiting_buffer_tail])) { debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = "); @@ -666,10 +625,10 @@ static void process_action(keyrecord_t *record) /* Tapping * - * Rule: Tap key is typed(pressed and released) within TAPPING_TERM - * without interfaring by typing other key. + * Rule: Tap key is typed(pressed and released) within TAPPING_TERM. + * (without interfering by typing other key) */ -/* return true when key event is processed. */ +/* return true when key event is processed or consumed. */ static bool process_tapping(keyrecord_t *keyp) { keyevent_t event = keyp->event; @@ -680,74 +639,109 @@ static bool process_tapping(keyrecord_t *keyp) if (tapping_key.tap_count == 0) { if (IS_TAPPING_KEY(event.key) && !event.pressed) { // first tap! + debug("Tapping: First tap(0->1).\n"); tapping_key.tap_count = 1; - debug("Tapping: First tap: tapping_key="); debug_record(tapping_key); debug("\n"); + debug_tapping_key(); process_action(&tapping_key); // enqueue keyp->tap_count = tapping_key.tap_count; return false; - } else if (!event.pressed && waiting_buffer_typed(event)) { + } +#if TAPPING_TERM >= 500 + /* This can prevent from typing some tap keys in a row at a time. */ + else if (!event.pressed && waiting_buffer_typed(event)) { // other key typed. not tap. - debug("Tapping: End. No tap. Interfered by typing key: tapping_key={}\n"); + debug("Tapping: End. No tap. Interfered by typing key\n"); process_action(&tapping_key); tapping_key = (keyrecord_t){}; + debug_tapping_key(); // enqueue return false; - } else { - // other key events shall be stored till tapping state settles. + } +#endif + else { + // other key events shall be enq'd till tapping state settles. return false; } } // tap_count > 0 else { if (IS_TAPPING_KEY(event.key) && !event.pressed) { + debug("Tapping: Tap release("); debug_dec(tapping_key.tap_count); debug(")\n"); keyp->tap_count = tapping_key.tap_count; - debug("Tapping: Tap release: tapping_key="); debug_record(*keyp); debug("\n"); + process_action(keyp); tapping_key = *keyp; - return false; + debug_tapping_key(); + return true; } else if (is_tap_key(keyp->event.key) && event.pressed) { - debug("Tapping: Start with forcing to release last tap: tapping_key="); - debug_record(*keyp); debug("\n"); -// TODO: need only when tap > 1? - process_action(&(keyrecord_t){ - .tap_count = tapping_key.tap_count, - .event.key = tapping_key.event.key, - .event.time = event.time, - .event.pressed = false - }); + if (tapping_key.tap_count > 1) { + debug("Tapping: Start new tap with releasing last tap(>1).\n"); + // unregister key + process_action(&(keyrecord_t){ + .tap_count = tapping_key.tap_count, + .event.key = tapping_key.event.key, + .event.time = event.time, + .event.pressed = false + }); + } else { + debug("Tapping: Start while last tap(1).\n"); + } tapping_key = *keyp; - return false; + waiting_buffer_scan_tap(); + debug_tapping_key(); + return true; } else { if (!IS_NOEVENT(keyp->event)) { - debug("Tapping: key event while tap: tapping_key="); - debug_record(tapping_key); debug("\n"); + debug("Tapping: key event while last tap(>0).\n"); } process_action(keyp); return true; } } } - // not within TAPPING_TERM + // after TAPPING_TERM else { if (tapping_key.tap_count == 0) { - // timeout. not tap. - debug("Tapping: End. Not tap(time out): tapping_key={}: "); debug_record(*keyp); debug("\n"); + debug("Tapping: End. Timeout. Not tap(0): "); + debug_event(event); debug("\n"); process_action(&tapping_key); tapping_key = (keyrecord_t){}; + debug_tapping_key(); return false; } else { if (IS_TAPPING_KEY(event.key) && !event.pressed) { - debug("Tapping: End. tap release."); + debug("Tapping: End. last timeout tap release(>0)."); keyp->tap_count = tapping_key.tap_count; process_action(keyp); tapping_key = (keyrecord_t){}; return true; - } else { - // other key after tap time out. + } + else if (is_tap_key(keyp->event.key) && event.pressed) { + if (tapping_key.tap_count > 1) { + debug("Tapping: Start new tap with releasing last timeout tap(>1).\n"); + // unregister key + process_action(&(keyrecord_t){ + .tap_count = tapping_key.tap_count, + .event.key = tapping_key.event.key, + .event.time = event.time, + .event.pressed = false + }); + } else { + debug("Tapping: Start while last timeout tap(1).\n"); + } + tapping_key = *keyp; + waiting_buffer_scan_tap(); + debug_tapping_key(); + return true; + } + else { + if (!IS_NOEVENT(keyp->event)) { + debug("Tapping: key event while last timeout tap(>0).\n"); + } process_action(keyp); return true; } @@ -758,14 +752,17 @@ static bool process_tapping(keyrecord_t *keyp) if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) { // sequential tap. keyp->tap_count = tapping_key.tap_count + 1; - debug("Tapping: tap press("); debug_dec(keyp->tap_count); debug(")\n"); + debug("Tapping: Tap press("); debug_dec(keyp->tap_count); debug(")\n"); process_action(keyp); tapping_key = *keyp; + debug_tapping_key(); return true; } else if (event.pressed && is_tap_key(event.key)) { // Sequential tap can be interfered with other tap key. debug("Tapping: Start with interfering other tap.\n"); tapping_key = *keyp; + waiting_buffer_scan_tap(); + debug_tapping_key(); return true; } else { if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n"); @@ -774,16 +771,21 @@ static bool process_tapping(keyrecord_t *keyp) } } else { // timeout. no sequential tap. - debug("Tapping: End(Time out after releasing last tap).\n"); + debug("Tapping: End(Timeout after releasing last tap): "); + debug_event(event); debug("\n"); tapping_key = (keyrecord_t){}; + debug_tapping_key(); process_action(keyp); return true; } - } else { + } + // not tapping satate + else { if (event.pressed && is_tap_key(event.key)) { debug("Tapping: Start(Press tap key).\n"); tapping_key = *keyp; - debug("tapping_key="); debug_record(*keyp); debug("\n"); + waiting_buffer_scan_tap(); + debug_tapping_key(); return true; } else { process_action(keyp); @@ -792,6 +794,29 @@ static bool process_tapping(keyrecord_t *keyp) } } +/* scan buffer for tapping */ +static void waiting_buffer_scan_tap(void) +{ + // tapping already is settled + if (tapping_key.tap_count > 0) return; + // invalid state: tapping_key released && tap_count == 0 + if (!tapping_key.event.pressed) return; + + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + if (IS_TAPPING_KEY(waiting_buffer[i].event.key) && + !waiting_buffer[i].event.pressed && + WITHIN_TAPPING_TERM(waiting_buffer[i].event)) { + tapping_key.tap_count = 1; + waiting_buffer[i].tap_count = 1; + process_action(&tapping_key); + + debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n"); + debug_waiting_buffer(); + return; + } + } +} + /* @@ -923,3 +948,54 @@ bool is_tap_key(key_t key) } return false; } + + +/* + * debug print + */ +static void debug_event(keyevent_t event) +{ + debug_hex16(event.key.raw); + if (event.pressed) debug("d("); else debug("u("); + debug_dec(event.time); debug(")"); +} +static void debug_record(keyrecord_t record) +{ + debug_event(record.event); debug(":"); debug_dec(record.tap_count); +} +static void debug_action(action_t action) +{ + switch (action.kind.id) { + case ACT_LMODS: debug("ACT_LMODS"); break; + case ACT_RMODS: debug("ACT_RMODS"); break; + case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break; + case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break; + case ACT_USAGE: debug("ACT_USAGE"); break; + case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break; + case ACT_LAYER_PRESSED: debug("ACT_LAYER_PRESSED"); break; + case ACT_LAYER_RELEASED: debug("ACT_LAYER_RELEASED"); break; + case ACT_LAYER_BIT: debug("ACT_LAYER_BIT"); break; + case ACT_LAYER_EXT: debug("ACT_LAYER_EXT"); break; + case ACT_MACRO: debug("ACT_MACRO"); break; + case ACT_COMMAND: debug("ACT_COMMAND"); break; + case ACT_FUNCTION: debug("ACT_FUNCTION"); break; + default: debug("UNKNOWN"); break; + } + debug("["); + debug_hex4(action.kind.param>>8); + debug(":"); + debug_hex8(action.kind.param & 0xff); + debug("]"); +} +static void debug_tapping_key(void) +{ + debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n"); +} +static void debug_waiting_buffer(void) +{ + debug("{ "); + for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { + debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" "); + } + debug("}\n"); +} From 7e1093b70f424ed012a4122a91ba6bb1784b9eb8 Mon Sep 17 00:00:00 2001 From: tmk Date: Wed, 30 Jan 2013 22:47:16 +0900 Subject: [PATCH 21/30] Fix: action LAYER_BIT uses xor now instead of and/or. --- common/action.c | 21 +++++++++------------ common/action.h | 14 +++++++------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/common/action.c b/common/action.c index 28d9a95f5..eb8fc2ce2 100644 --- a/common/action.c +++ b/common/action.c @@ -452,9 +452,9 @@ static void process_action(keyrecord_t *record) switch (action.layer.code) { case 0x00: if (event.pressed) { - layer_switch(current_layer | action.layer.opt); + layer_switch(current_layer ^ action.layer.opt); } else { - layer_switch(current_layer & ~action.layer.opt); + layer_switch(current_layer ^ action.layer.opt); } break; case 0xF0: @@ -462,25 +462,22 @@ static void process_action(keyrecord_t *record) if (event.pressed) { if (tap_count < TAPPING_TOGGLE) { debug("LAYER_BIT: tap toggle(press).\n"); - layer_switch(current_layer | action.layer.opt); + layer_switch(current_layer ^ action.layer.opt); } } else { - if (tap_count < TAPPING_TOGGLE) { + if (tap_count <= TAPPING_TOGGLE) { debug("LAYER_BIT: tap toggle(release).\n"); - layer_switch(current_layer & ~action.layer.opt); - } else { - debug("LAYER_BIT: tap toggle.\n"); - layer_switch(current_layer | action.layer.opt); + layer_switch(current_layer ^ action.layer.opt); } } break; case 0xFF: // change default layer if (event.pressed) { - default_layer = current_layer | action.layer.opt; + default_layer = current_layer ^ action.layer.opt; layer_switch(default_layer); } else { - default_layer = current_layer & ~action.layer.opt; + default_layer = current_layer ^ action.layer.opt; layer_switch(default_layer); } break; @@ -492,7 +489,7 @@ static void process_action(keyrecord_t *record) register_code(action.layer.code); } else { debug("LAYER_BIT: No tap: layer_switch(bit on)\n"); - layer_switch(current_layer | action.layer.opt); + layer_switch(current_layer ^ action.layer.opt); } } else { if (IS_TAPPING_KEY(event.key) && tap_count > 0) { @@ -500,7 +497,7 @@ static void process_action(keyrecord_t *record) unregister_code(action.layer.code); } else { debug("LAYER_BIT: No tap: layer_switch(bit off)\n"); - layer_switch(current_layer & ~action.layer.opt); + layer_switch(current_layer ^ action.layer.opt); } } break; diff --git a/common/action.h b/common/action.h index ed3fff6c2..8600e4061 100644 --- a/common/action.h +++ b/common/action.h @@ -225,7 +225,6 @@ enum acion_param { /* action_t utility */ #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) @@ -235,15 +234,16 @@ enum acion_param { #define ACTION_RMODS_KEY(mods, key) ACTION(ACT_RMODS, (mods)<<8 | (key)) /* Mods + Tap key */ -#define ACTION_LMODS_TAP(mods, key) ACTION(ACT_LMODS_TAP, MOD_BITS(mods)<<8 | (key)) -#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MOD_BITS(mods)<<8 | ONE_SHOT) -#define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP, MOD_BITS(mods)<<8 | (key)) -#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MOD_BITS(mods)<<8 | ONE_SHOT) +#define MODS4(mods) (((mods)>>4 | (mods)) & 0x0F) +#define ACTION_LMODS_TAP(mods, key) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | (key)) +#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | ONE_SHOT) +#define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | (key)) +#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | ONE_SHOT) /* Switch current layer */ #define ACTION_LAYER_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) #define ACTION_LAYER_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0x00) -#define ACTION_LAYER_BIT(bits) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0x00) +#define ACTION_LAYER_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0x00) #define ACTION_LAYER_TO_DEFAULT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0x00) #define ACTION_LAYER_TO_DEFAULT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0x00) /* Switch default layer */ @@ -254,7 +254,7 @@ enum acion_param { #define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0xFF) /* Layer switch with tap key */ #define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | (key)) -#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (layer)<<8 | (key)) +#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (bits)<<8 | (key)) #define ACTION_LAYER_DEFAULT_SET_TAP_KEY(key) ACTION(ACT_LAYER_EXT, 0x0<<8 | (key)) /* with tap toggle */ #define ACTION_LAYER_SET_ON_PRESSED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xF0) From e760953910a51e5972dda21aa9d03279e6f1230b Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 31 Jan 2013 15:07:01 +0900 Subject: [PATCH 22/30] Fix tapping. tap key just after tap timeout. --- common/action.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/action.c b/common/action.c index eb8fc2ce2..4838ea062 100644 --- a/common/action.c +++ b/common/action.c @@ -772,8 +772,7 @@ static bool process_tapping(keyrecord_t *keyp) debug_event(event); debug("\n"); tapping_key = (keyrecord_t){}; debug_tapping_key(); - process_action(keyp); - return true; + return false; } } // not tapping satate From d95463f2e0369dc0e28497bb923b3012fb09e900 Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 31 Jan 2013 17:50:53 +0900 Subject: [PATCH 23/30] Add legacy keymap support. --- common/action.c | 9 ++++- common/action.h | 87 ++++++++++++++++++++++++++++++++---------------- common/keycode.h | 4 +-- common/keymap.c | 73 ++++++++++++++++++++++++++++++++++++++++ common/keymap.h | 20 ++++++----- 5 files changed, 153 insertions(+), 40 deletions(-) create mode 100644 common/keymap.c diff --git a/common/action.c b/common/action.c index 4838ea062..d1f493fe0 100644 --- a/common/action.c +++ b/common/action.c @@ -358,6 +358,10 @@ static void process_action(keyrecord_t *record) if (event.pressed) { layer_switch(action.layer.opt); } +//TODO: this is ok? + else { + layer_switch(default_layer); + } break; case 0xF0: // tap toggle @@ -394,7 +398,10 @@ static void process_action(keyrecord_t *record) debug("LAYER_PRESSED: Tap: unregister_code\n"); unregister_code(action.layer.code); } else { - debug("LAYER_PRESSED: No tap: NO ACTION\n"); + //debug("LAYER_PRESSED: No tap: NO ACTION\n"); +//TODO: this is ok? + debug("LAYER_PRESSED: No tap: return to default layer\n"); + layer_switch(default_layer); } } break; diff --git a/common/action.h b/common/action.h index 8600e4061..d6530df42 100644 --- a/common/action.h +++ b/common/action.h @@ -18,6 +18,7 @@ along with this program. If not, see . #define ACTION_H #include "keyboard.h" +#include "keycode.h" /* Action struct. @@ -107,28 +108,28 @@ Keyboard Keys ACT_LMODS(0000): 0000|0000|000000|00 No action 0000|0000| keycode Key -0010|mods|000000|00 Left mods Momentary -0000|mods| keycode Key+Left mods +0000|mods|000000|00 Left mods +0000|mods| keycode Key & Left mods ACT_RMODS(0001): 0001|0000|000000|00 No action 0001|0000| keycode Key(no used) -0001|mods|000000|00 Right mods Momentary -0001|mods| keycode Key+Right mods +0001|mods|000000|00 Right mods +0001|mods| keycode Key & Right mods ACT_LMODS_TAP(0010): 0010|mods|000000|00 Left mods OneShot 0010|mods|000000|01 (reserved) 0010|mods|000000|10 (reserved) 0010|mods|000000|11 (reserved) -0010|mods| keycode Left mods+tap Key +0010|mods| keycode Left mods + tap Key ACT_RMODS_TAP(0011): 0011|mods|000000|00 Right mods OneShot 0011|mods|000000|01 (reserved) 0011|mods|000000|10 (reserved) 0011|mods|000000|11 (reserved) -0011|mods| keycode Right mods+tap Key +0011|mods| keycode Right mods + tap Key Other HID Usage @@ -143,12 +144,20 @@ ACT_USAGE(0100): Mouse Keys ---------- +TODO: can be combined with 'Other HID Usage'? to save action kind id. ACT_MOUSEKEY(0110): 0101|XXXX| keycode Mouse key Layer Actions ------------- +TODO: reconsider layer methods. +1 momemtary + tap key up: L, down: default +1 bitwise + tap key up: xor B, down: xor B +3 momemtary go + tap key? up: X, down: +3 toggle(mementary back) + tap key? up: down: Y +3 no tap up: X, down: Y + 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 @@ -222,57 +231,77 @@ enum acion_param { }; -/* action_t utility */ +/* action utility */ #define ACTION_NO 0 #define ACTION(kind, param) ((kind)<<12 | (param)) +#define MODS4(mods) (((mods)>>4 | (mods)) & 0x0F) -/* Key & Mods */ +/* Key */ #define ACTION_KEY(key) ACTION(ACT_LMODS, key) +/* Mods & key */ #define ACTION_LMODS(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x00) #define ACTION_LMODS_KEY(mods, key) ACTION(ACT_LMODS, (mods)<<8 | (key)) #define ACTION_RMODS(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x00) #define ACTION_RMODS_KEY(mods, key) ACTION(ACT_RMODS, (mods)<<8 | (key)) +/* Mod & key */ +#define ACTION_LMOD(mod) ACTION(ACT_LMODS, MODS4(MOD_BIT(mod))<<8 | 0x00) +#define ACTION_LMOD_KEY(mod, key) ACTION(ACT_LMODS, MODS4(MOD_BIT(mod))<<8 | (key)) +#define ACTION_RMOD(mod) ACTION(ACT_RMODS, MODS4(MOD_BIT(mod))<<8 | 0x00) +#define ACTION_RMOD_KEY(mod, key) ACTION(ACT_RMODS, MODS4(MOD_BIT(mod))<<8 | (key)) /* Mods + Tap key */ -#define MODS4(mods) (((mods)>>4 | (mods)) & 0x0F) -#define ACTION_LMODS_TAP(mods, key) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | (key)) +#define ACTION_LMODS_TAP_KEY(mods, key) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | (key)) #define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | ONE_SHOT) -#define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | (key)) +#define ACTION_RMODS_TAP_KEY(mods, key) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | (key)) #define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | ONE_SHOT) +/* Mod + Tap key */ +#define ACTION_LMOD_TAP_KEY(mod, key) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key)) +#define ACTION_LMOD_ONESHOT(mod) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | ONE_SHOT) +#define ACTION_RMOD_TAP_KEY(mod, key) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key)) +#define ACTION_RMOD_ONESHOT(mod) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | ONE_SHOT) +// TODO: contemplate about layer action /* Switch current layer */ -#define ACTION_LAYER_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) -#define ACTION_LAYER_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0x00) -#define ACTION_LAYER_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0x00) -#define ACTION_LAYER_TO_DEFAULT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0x00) -#define ACTION_LAYER_TO_DEFAULT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0x00) +#define ACTION_LAYER_SET(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) +#define ACTION_LAYER_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) +#define ACTION_LAYER_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0x00) +#define ACTION_LAYER_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0x00) +#define ACTION_LAYER_SET_DEFAULT ACTION(ACT_LAYER_EXT, 0x0<<8 | 0x00) +#define ACTION_LAYER_RETURN_DEFAULT ACTION(ACT_LAYER_EXT, 0x1<<8 | 0x00) +#define ACTION_LAYER_SET_DEFAULT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0x00) +#define ACTION_LAYER_SET_DEFAULT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0x00) /* Switch default layer */ -#define ACTION_LAYER_DEFAULT_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_SET(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xFF) +#define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0xFF) /* Layer switch with tap key */ -#define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | (key)) -#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (bits)<<8 | (key)) -#define ACTION_LAYER_DEFAULT_SET_TAP_KEY(key) ACTION(ACT_LAYER_EXT, 0x0<<8 | (key)) -/* with tap toggle */ -#define ACTION_LAYER_SET_ON_PRESSED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xF0) -#define ACTION_LAYER_SET_ON_RELEASED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xF0) -#define ACTION_LAYER_BIT_TAP_TOGGLE(layer) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0xF0) -#define ACTION_LAYER_DEFAULT_TAP_TOGGLE ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xF0) +#define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | (key)) +#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (bits)<<8 | (key)) +#define ACTION_LAYER_DEFAULT_SET_TAP_KEY(key) ACTION(ACT_LAYER_EXT, 0x0<<8 | (key)) +/* Layer switch with tap toggle */ +#define ACTION_LAYER_SET_ON_PRESSED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xF0) +#define ACTION_LAYER_SET_ON_RELEASED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xF0) +#define ACTION_LAYER_BIT_TAP_TOGGLE(layer) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0xF0) +#define ACTION_LAYER_DEFAULT_TAP_TOGGLE ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xF0) /* HID Usage */ #define ACTION_USAGE_PAGE_SYSTEM 0 #define ACTION_USAGE_PAGE_CONSUMER 1 #define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_SYSTEM<<10 | (id)) #define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_CONSUMER<<10 | (id)) + /* Mousekey */ #define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key) + /* Macro */ #define ACTION_MACRO(opt, id) ACTION(ACT_FUNCTION, (opt)<<8 | (addr)) + /* Command */ #define ACTION_COMMAND(opt, id) ACTION(ACT_COMMAND, (opt)<<8 | (addr)) + /* Function */ #define ACTION_FUNCTION(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | id) diff --git a/common/keycode.h b/common/keycode.h index cdd1e9758..341f23161 100644 --- a/common/keycode.h +++ b/common/keycode.h @@ -28,14 +28,14 @@ along with this program. If not, see . #define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL) #define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI) -#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN7) +#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31) #define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2) #define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT) #define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN5) #define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT) #define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2) -#define IS_SPECIAL(code) ((0xB0 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF)) +#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF)) #define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_WFAV) #define IS_SYSTEM(code) (KC_POWER <= (code) && (code) <= KC_WAKE) diff --git a/common/keymap.c b/common/keymap.c new file mode 100644 index 000000000..415121308 --- /dev/null +++ b/common/keymap.c @@ -0,0 +1,73 @@ +/* +Copyright 2013 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 +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include "keymap.h" +#include "report.h" +#include "keycode.h" + + +/* layer */ +uint8_t default_layer = 0; +uint8_t current_layer = 0; + + +#ifndef NO_LEGACY_KEYMAP_SUPPORT +/* legacy support with weak reference */ +__attribute__ ((weak)) +action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) +{ + /* convert from legacy keycode to action */ + uint8_t key = keymap_get_keycode(layer, row, col); + action_t action; + switch (key) { + case KC_A ... KC_EXSEL: + action.code = ACTION_KEY(key); + break; + case KC_LCTRL ... KC_LGUI: + action.code = ACTION_LMOD(key); + break; + case KC_RCTRL ... KC_RGUI: + action.code = ACTION_RMOD(key); + break; + case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE: + action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(key)); + break; + case KC_AUDIO_MUTE ... KC_WWW_FAVORITES: + action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(key)); + break; + case KC_MS_UP ... KC_MS_ACCEL2: + action.code = ACTION_MOUSEKEY(key); + break; + case KC_FN0 ... KC_FN31: + { + uint8_t layer = keymap_fn_layer(FN_INDEX(key)); + uint8_t code = keymap_fn_keycode(FN_INDEX(key)); + action.code = ACTION_LAYER_SET_TAP_KEY(layer, code); + } + break; + case KC_NO ... KC_UNDEFINED: + default: + action.code = ACTION_NO; + break; + } + return action; +} +#endif + +__attribute__ ((weak)) +void action_call_function(keyevent_t event, uint8_t id) +{ +} diff --git a/common/keymap.h b/common/keymap.h index f54fea90d..748761551 100644 --- a/common/keymap.h +++ b/common/keymap.h @@ -28,18 +28,22 @@ extern uint8_t current_layer; /* layer to return or start with */ extern uint8_t default_layer; -/* - * legacy keymap interface: keycode - */ -uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col); -/* layer to move during press Fn key */ -uint8_t keymap_fn_layer(uint8_t fn_bits); -/* keycode to send when release Fn key without using */ -uint8_t keymap_fn_keycode(uint8_t fn_bits); /* * new keymap interface: action */ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col); + +#ifndef NO_LEGACY_KEYMAP_SUPPORT +/* keycode of key */ +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col); + +/* layer to move during press Fn key */ +uint8_t keymap_fn_layer(uint8_t fn_bits); + +/* keycode to send when release Fn key without using */ +uint8_t keymap_fn_keycode(uint8_t fn_bits); +#endif + #endif From 1d7962ba8a20323dc13cc913381608e117afaeb4 Mon Sep 17 00:00:00 2001 From: tmk Date: Fri, 1 Feb 2013 14:48:11 +0900 Subject: [PATCH 24/30] Add user defined function to action. --- common/action.c | 46 ++++++------ common/action.h | 47 ++++++------ common/keyboard.h | 1 + common/keymap.c | 2 +- common/keymap.h | 8 +- keyboard/hhkb/keymap.c | 165 ++++++++++++++++++++++++++++------------- 6 files changed, 168 insertions(+), 101 deletions(-) diff --git a/common/action.c b/common/action.c index d1f493fe0..cb44e272a 100644 --- a/common/action.c +++ b/common/action.c @@ -110,7 +110,7 @@ static bool waiting_buffer_typed(keyevent_t event) } #endif -static bool waiting_buffer_has_anykey_pressed(void) +bool waiting_buffer_has_anykey_pressed(void) { for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { if (waiting_buffer[i].event.pressed) return true; @@ -256,7 +256,7 @@ static void process_action(keyrecord_t *record) debug("MODS_TAP: Oneshot: start\n"); oneshot_start(mods, event.time); } - else if (tap_count == 5) { + else if (tap_count == TAPPING_TOGGLE) { debug("MODS_TAP: Oneshot: toggle\n"); oneshot_toggle(); } @@ -356,7 +356,7 @@ static void process_action(keyrecord_t *record) switch (action.layer.code) { case 0x00: if (event.pressed) { - layer_switch(action.layer.opt); + layer_switch(action.layer.val); } //TODO: this is ok? else { @@ -367,19 +367,19 @@ static void process_action(keyrecord_t *record) // tap toggle if (event.pressed) { if (tap_count < TAPPING_TOGGLE) { - layer_switch(action.layer.opt); + layer_switch(action.layer.val); } } else { if (tap_count >= TAPPING_TOGGLE) { debug("LAYER_PRESSED: tap toggle.\n"); - layer_switch(action.layer.opt); + layer_switch(action.layer.val); } } break; case 0xFF: // change default layer if (event.pressed) { - default_layer = action.layer.opt; + default_layer = action.layer.val; layer_switch(default_layer); } break; @@ -391,7 +391,7 @@ static void process_action(keyrecord_t *record) register_code(action.layer.code); } else { debug("LAYER_PRESSED: No tap: layer_switch\n"); - layer_switch(action.layer.opt); + layer_switch(action.layer.val); } } else { if (tap_count > 0) { @@ -411,7 +411,7 @@ static void process_action(keyrecord_t *record) switch (action.layer.code) { case 0x00: if (!event.pressed) { - layer_switch(action.layer.opt); + layer_switch(action.layer.val); } break; case 0xF0: @@ -419,18 +419,18 @@ static void process_action(keyrecord_t *record) if (event.pressed) { if (tap_count >= TAPPING_TOGGLE) { debug("LAYER_RELEASED: tap toggle.\n"); - layer_switch(action.layer.opt); + layer_switch(action.layer.val); } } else { if (tap_count < TAPPING_TOGGLE) { - layer_switch(action.layer.opt); + layer_switch(action.layer.val); } } break; case 0xFF: // change default layer if (!event.pressed) { - default_layer = action.layer.opt; + default_layer = action.layer.val; layer_switch(default_layer); } break; @@ -449,7 +449,7 @@ static void process_action(keyrecord_t *record) unregister_code(action.layer.code); } else { debug("LAYER_RELEASED: No tap: layer_switch\n"); - layer_switch(action.layer.opt); + layer_switch(action.layer.val); } } break; @@ -459,9 +459,9 @@ static void process_action(keyrecord_t *record) switch (action.layer.code) { case 0x00: if (event.pressed) { - layer_switch(current_layer ^ action.layer.opt); + layer_switch(current_layer ^ action.layer.val); } else { - layer_switch(current_layer ^ action.layer.opt); + layer_switch(current_layer ^ action.layer.val); } break; case 0xF0: @@ -469,22 +469,22 @@ static void process_action(keyrecord_t *record) if (event.pressed) { if (tap_count < TAPPING_TOGGLE) { debug("LAYER_BIT: tap toggle(press).\n"); - layer_switch(current_layer ^ action.layer.opt); + layer_switch(current_layer ^ action.layer.val); } } else { if (tap_count <= TAPPING_TOGGLE) { debug("LAYER_BIT: tap toggle(release).\n"); - layer_switch(current_layer ^ action.layer.opt); + layer_switch(current_layer ^ action.layer.val); } } break; case 0xFF: // change default layer if (event.pressed) { - default_layer = current_layer ^ action.layer.opt; + default_layer = current_layer ^ action.layer.val; layer_switch(default_layer); } else { - default_layer = current_layer ^ action.layer.opt; + default_layer = current_layer ^ action.layer.val; layer_switch(default_layer); } break; @@ -496,7 +496,7 @@ static void process_action(keyrecord_t *record) register_code(action.layer.code); } else { debug("LAYER_BIT: No tap: layer_switch(bit on)\n"); - layer_switch(current_layer ^ action.layer.opt); + layer_switch(current_layer ^ action.layer.val); } } else { if (IS_TAPPING_KEY(event.key) && tap_count > 0) { @@ -504,14 +504,14 @@ static void process_action(keyrecord_t *record) unregister_code(action.layer.code); } else { debug("LAYER_BIT: No tap: layer_switch(bit off)\n"); - layer_switch(current_layer ^ action.layer.opt); + layer_switch(current_layer ^ action.layer.val); } } break; } break; case ACT_LAYER_EXT: - switch (action.layer.opt) { + switch (action.layer.val) { case 0x00: // set default layer when pressed switch (action.layer.code) { @@ -620,7 +620,7 @@ static void process_action(keyrecord_t *record) break; case ACT_FUNCTION: // TODO - action_call_function(event, action.func.id); + keymap_call_function(record, action.func.id); break; default: break; @@ -944,7 +944,7 @@ bool is_tap_key(key_t key) } return false; case ACT_FUNCTION: - if (action.func.opt & 0x1) { + if (action.func.opt & O_TAP) { return true; } return false; diff --git a/common/action.h b/common/action.h index d6530df42..b657aa540 100644 --- a/common/action.h +++ b/common/action.h @@ -21,6 +21,16 @@ along with this program. If not, see . #include "keycode.h" +/* Execute action per keyevent */ +void action_exec(keyevent_t event); + + +/* Struct to record event and tap count */ +typedef struct { + keyevent_t event; + uint8_t tap_count; +} keyrecord_t; + /* Action struct. * * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15). @@ -48,7 +58,7 @@ typedef union { } key; struct action_layer { uint16_t code :8; - uint16_t opt :4; + uint16_t val :4; uint16_t kind :4; } layer; struct action_usage { @@ -58,7 +68,7 @@ typedef union { } usage; struct action_command { uint16_t id :8; - uint16_t option :4; + uint16_t opt :4; uint16_t kind :4; } command; struct action_function { @@ -68,18 +78,6 @@ typedef union { } func; } action_t; -/* Struct to record action and tap count */ -typedef struct { - keyevent_t event; - uint8_t tap_count; -} keyrecord_t; - - -/* execute action per keyevent */ -void action_exec(keyevent_t event); -typedef void (*action_func_t)(keyevent_t event, uint8_t opt); // TODO:no need? -void action_call_function(keyevent_t event, uint8_t id); // TODO: action function - /* * Utilities for actions. @@ -94,6 +92,7 @@ void clear_keyboard_but_mods(void); bool sending_anykey(void); void layer_switch(uint8_t new_layer); bool is_tap_key(key_t key); +bool waiting_buffer_has_anykey_pressed(void); @@ -203,9 +202,6 @@ ACT_FUNCTION(1111): 1111| address(12) Function? 1111|opt | id(8) Function? -TODO: modifier + function by tap? - for example: LShift + '('[Shift+9] and RShift + ')'[Shift+0] - http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478.html#p90052 */ enum action_kind_id { ACT_LMODS = 0b0000, @@ -226,8 +222,12 @@ enum action_kind_id { ACT_FUNCTION = 0b1111 }; -enum acion_param { - ONE_SHOT = 0x00, +enum params { + P_ONESHOT = 0x00, +}; + +enum options { + O_TAP = 0x8, }; @@ -251,14 +251,14 @@ enum acion_param { /* Mods + Tap key */ #define ACTION_LMODS_TAP_KEY(mods, key) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | (key)) -#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | ONE_SHOT) +#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | P_ONESHOT) #define ACTION_RMODS_TAP_KEY(mods, key) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | (key)) -#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | ONE_SHOT) +#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | P_ONESHOT) /* Mod + Tap key */ #define ACTION_LMOD_TAP_KEY(mod, key) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key)) -#define ACTION_LMOD_ONESHOT(mod) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | ONE_SHOT) +#define ACTION_LMOD_ONESHOT(mod) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | P_ONESHOT) #define ACTION_RMOD_TAP_KEY(mod, key) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key)) -#define ACTION_RMOD_ONESHOT(mod) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | ONE_SHOT) +#define ACTION_RMOD_ONESHOT(mod) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | P_ONESHOT) // TODO: contemplate about layer action /* Switch current layer */ @@ -304,5 +304,6 @@ enum acion_param { /* Function */ #define ACTION_FUNCTION(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | id) +#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, O_TAP<<8 | id) #endif /* ACTION_H */ diff --git a/common/keyboard.h b/common/keyboard.h index 32c1bf464..e1cab3119 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -32,6 +32,7 @@ typedef struct { uint8_t row; } keypos_t; +// TODO: need raw? keypos_t -> key_t? typedef union { uint16_t raw; keypos_t pos; diff --git a/common/keymap.c b/common/keymap.c index 415121308..40d20f684 100644 --- a/common/keymap.c +++ b/common/keymap.c @@ -68,6 +68,6 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) #endif __attribute__ ((weak)) -void action_call_function(keyevent_t event, uint8_t id) +void keymap_call_function(keyrecord_t *event, uint8_t id) { } diff --git a/common/keymap.h b/common/keymap.h index 748761551..e0fafeaf2 100644 --- a/common/keymap.h +++ b/common/keymap.h @@ -29,11 +29,13 @@ extern uint8_t current_layer; extern uint8_t default_layer; -/* - * new keymap interface: action - */ +/* action for key */ +// TODO: should use struct key_t? action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col); +/* user defined special function */ +void keymap_call_function(keyrecord_t *record, uint8_t id); + #ifndef NO_LEGACY_KEYMAP_SUPPORT /* keycode of key */ diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index c7e4cfc38..e11b4563a 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -51,23 +51,6 @@ along with this program. If not, see . } -static const uint16_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_FUNCTION(0x01, 0xA), // Fn4 - ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // Fn5 - ACTION_LMODS_TAP(MOD_BIT(KC_LCTL), KC_BSPC), // Fn6 - ACTION_RMODS_TAP(MOD_BIT(KC_RCTL), KC_ENT), // Fn7 - - ACTION_LMODS_TAP(MOD_BIT(KC_LSFT), ONE_SHOT), // Fn8 - ACTION_LAYER_SET_ON_RELEASED_TAP_TOGGLE(1), // Fn9 - ACTION_LAYER_BIT_TAP_TOGGLE(1), // Fn10 -}; - - static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Layer 0: Default Layer * ,-----------------------------------------------------------. @@ -85,7 +68,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, \ FN6, A, S, D, F, G, H, J, K, L, FN3, QUOT,FN7, \ - FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN10, \ + FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, FN12,FN10, \ LGUI,LALT, FN5, RALT,FN4), /* Layer 1: HHKB mode (HHKB Fn) @@ -173,25 +156,128 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { LGUI,LALT, FN0, RALT,RGUI), }; -#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) -/* legacy interface */ -uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) { return 0; } -uint8_t keymap_fn_layer(uint8_t fn_bits) { return 0; } -uint8_t keymap_fn_keycode(uint8_t fn_bits) { return 0; } +/* id for user defined functions */ +enum function_id { + LSHIFT_LPAREN, + RSHIFT_RPAREN, +}; +/* + * Fn action definition + */ +static const uint16_t PROGMEM fn_actions[] = { + ACTION_LAYER_RETURN_DEFAULT, // FN0 + ACTION_LAYER_SET(1), // FN1 + ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH), // FN2 + ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // FN3 + ACTION_LAYER_SET(3), // FN4 + ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // FN5 + ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // FN6 + ACTION_RMOD_TAP_KEY(KC_RCTL, KC_ENT), // FN7 + ACTION_LMOD_ONESHOT(KC_LSFT), // FN8 Oneshot Shift + ACTION_LAYER_SET_ON_RELEASED_TAP_TOGGLE(1), // FN9 + ACTION_LAYER_BIT_TAP_KEY(1, KC_GRV), // FN10 + //ACTION_LAYER_BIT(1), // FN10 + //ACTION_LAYER_BIT_TAP_TOGGLE(1), // FN10 + ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // FN11 + ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // FN12 +}; +/* + * user defined action function + */ +void keymap_call_function(keyrecord_t *record, uint8_t id) +{ + keyevent_t event = record->event; + uint8_t tap_count = record->tap_count; + + debug("action_call_function: "); + if (event.pressed) debug("pressed"); else debug("released"); + debug(" id: "); debug_hex(id); + debug(" tap_count: "); debug_dec(tap_count); + debug("\n"); + + switch (id) { + case LSHIFT_LPAREN: + // LShft + tap '(' + if (event.pressed) { + if (tap_count == 0) { + add_mods(MOD_BIT(KC_LSHIFT)); + } else { + if (waiting_buffer_has_anykey_pressed()) { + // ad hoc: set 0 to cancel tap + record->tap_count = 0; + add_mods(MOD_BIT(KC_LSHIFT)); + } else { + // NOTE to avoid conflicting command key bind(LShift+RShift) + //register_code(KC_LSHIFT); + //register_code(KC_9); + host_add_mods(MOD_BIT(KC_LSHIFT)); + host_add_key(KC_9); + host_send_keyboard_report(); + } + } + } else { + if (tap_count == 0) { + del_mods(MOD_BIT(KC_LSHIFT)); + } else { + //unregister_code(KC_9); + //unregister_code(KC_LSHIFT); + host_del_mods(MOD_BIT(KC_LSHIFT)); + host_del_key(KC_9); + host_send_keyboard_report(); + } + } + break; + case RSHIFT_RPAREN: + // RShift + tap ')' + if (event.pressed) { + if (tap_count == 0) { + add_mods(MOD_BIT(KC_RSHIFT)); + } else { + if (waiting_buffer_has_anykey_pressed()) { + // ad hoc: set 0 to cancel tap + record->tap_count = 0; + add_mods(MOD_BIT(KC_RSHIFT)); + } else { + //register_code(KC_RSHIFT); + //register_code(KC_0); + host_add_mods(MOD_BIT(KC_RSHIFT)); + host_add_key(KC_0); + host_send_keyboard_report(); + } + } + } else { + if (tap_count == 0) { + del_mods(MOD_BIT(KC_RSHIFT)); + } else { + //unregister_code(KC_0); + //unregister_code(KC_RSHIFT); + host_del_mods(MOD_BIT(KC_RSHIFT)); + host_del_key(KC_0); + host_send_keyboard_report(); + } + } + break; + } +} + +/* convert keycode to action */ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { - /* convert from legacy keycode to action */ - uint8_t key = KEYCODE(layer, row, col); + uint8_t key = (pgm_read_byte(&keymaps[(layer)][(row)][(col)])); action_t action; switch (key) { case KC_A ... KC_EXSEL: - case KC_LCTRL ... KC_LGUI: - case KC_RCTRL ... KC_RGUI: action.code = ACTION_KEY(key); break; + case KC_LCTRL ... KC_LGUI: + action.code = ACTION_LMOD(key); + break; + case KC_RCTRL ... KC_RGUI: + action.code = ACTION_RMOD(key); + break; case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE: action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(key)); break; @@ -201,15 +287,7 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { case KC_MS_UP ... KC_MS_ACCEL2: action.code = ACTION_MOUSEKEY(key); break; -/* TODO - case KC_LCTRL ... KC_LGUI: - action.code = ACTION_LMODS(MOD_BIT(key)); - break; - case KC_RCTRL ... KC_RGUI: - action.code = ACTION_RMODS(MOD_BIT(key)>>4); - break; -*/ - case KC_FN0 ... FN_MAX: + case KC_FN0 ... KC_FN31: if (FN_INDEX(key) < sizeof(fn_actions) / sizeof(fn_actions[0])) { action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]); } else { @@ -223,18 +301,3 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { } return action; } - -// TODO: how to define action function -void action_call_function(keyevent_t event, uint8_t id) -{ - // '(' Shift+9 - if (event.pressed) { - register_code(KC_LSHIFT); - register_code(KC_9); - debug("action_call_function: pressed: id: "); debug_hex(id); debug("\n"); - } else { - unregister_code(KC_9); - unregister_code(KC_LSHIFT); - debug("action_call_function: released: id: "); debug_hex(id); debug("\n"); - } -} From aad91a30a34d61739e1261bb82a1cb1ace581afa Mon Sep 17 00:00:00 2001 From: tmk Date: Mon, 4 Feb 2013 22:53:45 +0900 Subject: [PATCH 25/30] Add macro feature. --- common.mk | 1 + common/action.c | 2 +- common/action.h | 24 ++++----- common/action_macro.c | 67 ++++++++++++++++++++++++++ common/action_macro.h | 107 +++++++++++++++++++++++++++++++++++++++++ common/keymap.c | 2 +- common/keymap.h | 3 +- keyboard/hhkb/keymap.c | 42 +++++++++++++--- 8 files changed, 226 insertions(+), 22 deletions(-) create mode 100644 common/action_macro.c create mode 100644 common/action_macro.h diff --git a/common.mk b/common.mk index 7cdaa5f74..86518f03f 100644 --- a/common.mk +++ b/common.mk @@ -2,6 +2,7 @@ COMMON_DIR = common SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/keyboard.c \ $(COMMON_DIR)/action.c \ + $(COMMON_DIR)/action_macro.c \ $(COMMON_DIR)/keymap.c \ $(COMMON_DIR)/command.c \ $(COMMON_DIR)/timer.c \ diff --git a/common/action.c b/common/action.c index cb44e272a..301a9b6a0 100644 --- a/common/action.c +++ b/common/action.c @@ -620,7 +620,7 @@ static void process_action(keyrecord_t *record) break; case ACT_FUNCTION: // TODO - keymap_call_function(record, action.func.id); + keymap_call_function(record, action.func.id, action.func.opt); break; default: break; diff --git a/common/action.h b/common/action.h index b657aa540..b1e958a26 100644 --- a/common/action.h +++ b/common/action.h @@ -49,27 +49,27 @@ typedef union { uint16_t code; struct action_kind { uint16_t param :12; - uint16_t id :4; + uint8_t id :4; } kind; struct action_key { - uint16_t code :8; - uint16_t mods :4; - uint16_t kind :4; + uint8_t code :8; + uint8_t mods :4; + uint8_t kind :4; } key; struct action_layer { - uint16_t code :8; - uint16_t val :4; - uint16_t kind :4; + uint8_t code :8; + uint8_t val :4; + uint8_t kind :4; } layer; struct action_usage { uint16_t code :10; - uint16_t page :2; - uint16_t kind :4; + uint8_t page :2; + uint8_t kind :4; } usage; struct action_command { - uint16_t id :8; - uint16_t opt :4; - uint16_t kind :4; + uint8_t id :8; + uint8_t opt :4; + uint8_t kind :4; } command; struct action_function { uint8_t id :8; diff --git a/common/action_macro.c b/common/action_macro.c new file mode 100644 index 000000000..72859c0dd --- /dev/null +++ b/common/action_macro.c @@ -0,0 +1,67 @@ +/* +Copyright 2013 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 +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#include +#include "debug.h" +#include "action.h" +#include "action_macro.h" + + +#define MACRO_READ() (macro = pgm_read_byte(macro_p++)) +void action_macro_play(const prog_macro_t *macro_p) +{ + macro_t macro = END; + uint8_t interval = 0; + + if (!macro_p) return; + while (true) { + switch (MACRO_READ()) { + case INTERVAL: + interval = MACRO_READ(); + debug("INTERVAL("); debug_dec(interval); debug(")\n"); + break; + case WAIT: + MACRO_READ(); + debug("WAIT("); debug_dec(macro); debug(")\n"); + { uint8_t ms = macro; while (ms--) _delay_ms(1); } + break; + case MODS_DOWN: + MACRO_READ(); + debug("MODS_DOWN("); debug_hex(macro); debug(")\n"); + debug("MODS_UP("); debug_hex(macro); debug(")\n"); + add_mods(macro); + break; + case MODS_UP: + MACRO_READ(); + debug("MODS_UP("); debug_hex(macro); debug(")\n"); + del_mods(macro); + break; + case 0x04 ... 0x73: + debug("DOWN("); debug_hex(macro); debug(")\n"); + register_code(macro); + break; + case 0x84 ... 0xF3: + debug("UP("); debug_hex(macro); debug(")\n"); + unregister_code(macro&0x7F); + break; + case END: + default: + return; + } + // interval + { uint8_t ms = interval; while (ms--) _delay_ms(1); } + } +} diff --git a/common/action_macro.h b/common/action_macro.h new file mode 100644 index 000000000..3833c7c8a --- /dev/null +++ b/common/action_macro.h @@ -0,0 +1,107 @@ +/* +Copyright 2013 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 +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef ACTION_MACRO_H +#define ACTION_MACRO_H +#include +#include + + +typedef uint8_t macro_t; +typedef macro_t prog_macro_t PROGMEM; + + +void action_macro_play(const prog_macro_t *macro); + + + +/* TODO: NOT FINISHED +normal mode command: + key(down): 0x04-7f/73(F24) + key(up): 0x84-ff +command: 0x00-03, 0x80-83(0x74-7f, 0xf4-ff) + mods down 0x00 + mods up 0x01 + wait 0x02 + interval 0x03 + extkey down 0x80 + extkey up 0x81 + ext commad 0x82 + ext mode 0x83 + end 0xff + +extension mode command: NOT IMPLEMENTED + key down 0x00 + key up 0x01 + key down + wait + key up + wait + mods push + mods pop + wait + interval + if + loop + push + pop + all up + end +*/ +enum macro_command_id{ + /* 0x00 - 0x03 */ + END = 0x00, + MODS_DOWN = 0x01, + MODS_UP = 0x02, + MODS_SET, + MODS_PUSH, + MODS_POP, + + WAIT = 0x74, + INTERVAL, + /* 0x74 - 0x7f */ + /* 0x80 - 0x84 */ + + EXT_DOWN, + EXT_UP, + EXT_WAIT, + EXT_INTERVAL, + COMPRESSION_MODE, + + EXTENSION_MODE = 0xff, +}; + + +/* normal mode */ +#define DOWN(key) (key) +#define UP(key) ((key) | 0x80) +#define TYPE(key) (key), (key | 0x80) +#define MODS_DOWN(mods) MODS_DOWN, (mods) +#define MODS_UP(mods) MODS_UP, (mods) +#define WAIT(ms) WAIT, (ms) +#define INTERVAL(ms) INTERVAL, (ms) + +#define D(key) DOWN(KC_##key) +#define U(key) UP(KC_##key) +#define T(key) TYPE(KC_##key) +#define MD(key) MODS_DOWN(MOD_BIT(KC_##key)) +#define MU(key) MODS_UP(MOD_BIT(KC_##key)) +#define W(ms) WAIT(ms) +#define I(ms) INTERVAL(ms) + + +/* extension mode */ + + +#endif /* ACTION_MACRO_H */ diff --git a/common/keymap.c b/common/keymap.c index 40d20f684..8302c2704 100644 --- a/common/keymap.c +++ b/common/keymap.c @@ -68,6 +68,6 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) #endif __attribute__ ((weak)) -void keymap_call_function(keyrecord_t *event, uint8_t id) +void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt) { } diff --git a/common/keymap.h b/common/keymap.h index e0fafeaf2..30d73f797 100644 --- a/common/keymap.h +++ b/common/keymap.h @@ -23,6 +23,7 @@ along with this program. If not, see . #include "action.h" +// TODO: move to action.h? /* layer used currently */ extern uint8_t current_layer; /* layer to return or start with */ @@ -34,7 +35,7 @@ extern uint8_t default_layer; action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col); /* user defined special function */ -void keymap_call_function(keyrecord_t *record, uint8_t id); +void keymap_call_function(keyrecord_t *record, uint8_t id, uint8_t opt); #ifndef NO_LEGACY_KEYMAP_SUPPORT diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index e11b4563a..f2f21e8ce 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -21,12 +21,11 @@ along with this program. If not, see . #include #include #include -#include "host.h" #include "keycode.h" -#include "print.h" -#include "debug.h" -#include "util.h" #include "action.h" +#include "action_macro.h" +#include "host.h" +#include "debug.h" #include "keymap.h" @@ -69,7 +68,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ FN6, A, S, D, F, G, H, J, K, L, FN3, QUOT,FN7, \ FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, FN12,FN10, \ - LGUI,LALT, FN5, RALT,FN4), + LGUI,LALT, FN5, FN13,FN4), /* Layer 1: HHKB mode (HHKB Fn) * ,-----------------------------------------------------------. @@ -162,6 +161,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { enum function_id { LSHIFT_LPAREN, RSHIFT_RPAREN, + MACRO = 0xff }; /* @@ -172,7 +172,8 @@ static const uint16_t PROGMEM fn_actions[] = { ACTION_LAYER_SET(1), // FN1 ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH), // FN2 ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // FN3 - ACTION_LAYER_SET(3), // FN4 + //ACTION_LAYER_SET(3), // FN4 + ACTION_FUNCTION(MACRO, 0), // FN4 ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // FN5 ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // FN6 ACTION_RMOD_TAP_KEY(KC_RCTL, KC_ENT), // FN7 @@ -183,12 +184,36 @@ static const uint16_t PROGMEM fn_actions[] = { //ACTION_LAYER_BIT_TAP_TOGGLE(1), // FN10 ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // FN11 ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // FN12 + ACTION_FUNCTION(MACRO, 1), // FN13 }; + +/* + * Macro definition + */ +#define MACRO(...) ({ static prog_macro_t _m[] PROGMEM = { __VA_ARGS__ }; _m; }) +#define MACRO_NONE 0 +static const prog_macro_t *get_macro(uint8_t id, bool pressed) +{ + switch (id) { + case 0: + return (pressed ? + MACRO( MD(LSHIFT), D(D), END ) : + MACRO( U(D), MU(LSHIFT), END ) ); + case 1: + return (pressed ? + MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END ) : + MACRO_NONE ); + } + return 0; +} + + + /* * user defined action function */ -void keymap_call_function(keyrecord_t *record, uint8_t id) +void keymap_call_function(keyrecord_t *record, uint8_t id, uint8_t opt) { keyevent_t event = record->event; uint8_t tap_count = record->tap_count; @@ -261,6 +286,9 @@ void keymap_call_function(keyrecord_t *record, uint8_t id) } } break; + case MACRO: + action_macro_play(get_macro(opt, event.pressed)); + break; } } From b2aa142ee0a88ae6c38798f33cf5d833b0ae3864 Mon Sep 17 00:00:00 2001 From: tmk Date: Fri, 8 Feb 2013 00:50:51 +0900 Subject: [PATCH 26/30] Clean layer actions. --- common/action.c | 219 +++++++++-------------------------------- common/action.h | 180 ++++++++++++++++++--------------- keyboard/hhkb/keymap.c | 77 +++++++++------ 3 files changed, 197 insertions(+), 279 deletions(-) diff --git a/common/action.c b/common/action.c index 301a9b6a0..f6e50032e 100644 --- a/common/action.c +++ b/common/action.c @@ -319,14 +319,14 @@ static void process_action(keyrecord_t *record) case ACT_USAGE: #ifdef EXTRAKEY_ENABLE switch (action.usage.page) { - case ACTION_USAGE_PAGE_SYSTEM: + case PAGE_SYSTEM: if (event.pressed) { host_system_send(action.usage.code); } else { host_system_send(0); } break; - case ACTION_USAGE_PAGE_CONSUMER: + case PAGE_CONSUMER: if (event.pressed) { host_consumer_send(action.usage.code); } else { @@ -351,20 +351,44 @@ static void process_action(keyrecord_t *record) break; /* Layer key */ - case ACT_LAYER_PRESSED: - // layer action when pressed + case ACT_LAYER: switch (action.layer.code) { - case 0x00: + case LAYER_MOMENTARY: /* momentary */ if (event.pressed) { layer_switch(action.layer.val); } -//TODO: this is ok? else { layer_switch(default_layer); } break; - case 0xF0: - // tap toggle + case LAYER_ON_PRESS: + if (event.pressed) { + layer_switch(action.layer.val); + } + break; + case LAYER_ON_RELEASE: + if (!event.pressed) { + layer_switch(action.layer.val); + } + break; + case LAYER_DEFAULT: /* default layer */ + switch (action.layer.val) { + case DEFAULT_ON_BOTH: + layer_switch(default_layer); + break; + case DEFAULT_ON_PRESS: + if (event.pressed) { + layer_switch(default_layer); + } + break; + case DEFAULT_ON_RELEASE: + if (!event.pressed) { + layer_switch(default_layer); + } + break; + } + break; + case LAYER_TAP_TOGGLE: /* switch on hold and toggle on several taps */ if (event.pressed) { if (tap_count < TAPPING_TOGGLE) { layer_switch(action.layer.val); @@ -376,15 +400,13 @@ static void process_action(keyrecord_t *record) } } break; - case 0xFF: - // change default layer + case LAYER_CHANGE_DEFAULT: /* change default layer */ if (event.pressed) { default_layer = action.layer.val; layer_switch(default_layer); } break; - default: - // with tap key + default: /* switch layer on hold and key on tap*/ if (event.pressed) { if (tap_count > 0) { debug("LAYER_PRESSED: Tap: register_code\n"); @@ -407,65 +429,26 @@ static void process_action(keyrecord_t *record) break; } break; - case ACT_LAYER_RELEASED: - switch (action.layer.code) { - case 0x00: - if (!event.pressed) { - layer_switch(action.layer.val); - } - break; - case 0xF0: - // tap toggle - if (event.pressed) { - if (tap_count >= TAPPING_TOGGLE) { - debug("LAYER_RELEASED: tap toggle.\n"); - layer_switch(action.layer.val); - } - } else { - if (tap_count < TAPPING_TOGGLE) { - layer_switch(action.layer.val); - } - } - break; - case 0xFF: - // change default layer - if (!event.pressed) { - default_layer = action.layer.val; - layer_switch(default_layer); - } - break; - default: - // with tap key - if (event.pressed) { - if (tap_count > 0) { - debug("LAYER_RELEASED: Tap: register_code\n"); - register_code(action.layer.code); - } else { - debug("LAYER_RELEASED: No tap: NO ACTION\n"); - } - } else { - if (tap_count > 0) { - debug("LAYER_RELEASED: Tap: unregister_code\n"); - unregister_code(action.layer.code); - } else { - debug("LAYER_RELEASED: No tap: layer_switch\n"); - layer_switch(action.layer.val); - } - } - break; - } - break; case ACT_LAYER_BIT: switch (action.layer.code) { - case 0x00: + case LAYER_MOMENTARY: /* momentary */ if (event.pressed) { layer_switch(current_layer ^ action.layer.val); } else { layer_switch(current_layer ^ action.layer.val); } break; - case 0xF0: - // tap toggle + case LAYER_ON_PRESS: + if (event.pressed) { + layer_switch(current_layer ^ action.layer.val); + } + break; + case LAYER_ON_RELEASE: + if (!event.pressed) { + layer_switch(current_layer ^ action.layer.val); + } + break; + case LAYER_TAP_TOGGLE: /* switch on hold and toggle on several taps */ if (event.pressed) { if (tap_count < TAPPING_TOGGLE) { debug("LAYER_BIT: tap toggle(press).\n"); @@ -510,108 +493,6 @@ static void process_action(keyrecord_t *record) break; } break; - case ACT_LAYER_EXT: - switch (action.layer.val) { - case 0x00: - // set default layer when pressed - switch (action.layer.code) { - case 0x00: - if (event.pressed) { - layer_switch(default_layer); - } - break; - case 0xF0: - // tap toggle - if (event.pressed) { - if (tap_count < TAPPING_TOGGLE) { - layer_switch(default_layer); - } - } else { - if (tap_count >= TAPPING_TOGGLE) { - debug("LAYER_EXT_PRESSED: tap toggle.\n"); - layer_switch(default_layer); - } - } - break; - case 0xFF: - // change default layer - if (event.pressed) { - default_layer = current_layer; - layer_switch(default_layer); - } - break; - default: - // with tap key - if (event.pressed) { - if (tap_count > 0) { - debug("LAYER_EXT_PRESSED: Tap: register_code\n"); - register_code(action.layer.code); - } else { - debug("LAYER_EXT_PRESSED: No tap: layer_switch\n"); - layer_switch(default_layer); - } - } else { - if (tap_count > 0) { - debug("LAYER_EXT_PRESSED: Tap: unregister_code\n"); - unregister_code(action.layer.code); - } else { - debug("LAYER_EXT_PRESSED: No tap: NO ACTION\n"); - } - } - break; - } - break; - case 0x01: - // set default layer when released - switch (action.layer.code) { - case 0x00: - if (!event.pressed) { - layer_switch(default_layer); - } - break; - case 0xF0: - // tap toggle - if (event.pressed) { - if (tap_count >= TAPPING_TOGGLE) { - debug("LAYER_EXT_RELEASED: tap toggle.\n"); - layer_switch(default_layer); - } - } else { - if (tap_count < TAPPING_TOGGLE) { - layer_switch(default_layer); - } - } - break; - case 0xFF: - // change default layer - if (!event.pressed) { - default_layer = current_layer; - layer_switch(default_layer); - } - break; - default: - // with tap key - if (event.pressed) { - if (tap_count > 0) { - debug("LAYER_EXT_RELEASED: Tap: register_code\n"); - register_code(action.layer.code); - } else { - debug("LAYER_EXT_RELEASED: No tap: NO ACTION\n"); - } - } else { - if (tap_count > 0) { - debug("LAYER_EXT_RELEASED: Tap: unregister_code\n"); - unregister_code(action.layer.code); - } else { - debug("LAYER_EXT_RELEASED: No tap: layer_switch\n"); - layer_switch(default_layer); - } - } - break; - } - break; - } - break; /* Extentions */ case ACT_MACRO: @@ -932,7 +813,7 @@ bool is_tap_key(key_t key) case ACT_LMODS_TAP: case ACT_RMODS_TAP: return true; - case ACT_LAYER_PRESSED: + case ACT_LAYER: case ACT_LAYER_BIT: switch (action.layer.code) { case 0x00: @@ -944,7 +825,7 @@ bool is_tap_key(key_t key) } return false; case ACT_FUNCTION: - if (action.func.opt & O_TAP) { + if (action.func.opt & FUNC_TAP) { return true; } return false; @@ -975,10 +856,8 @@ static void debug_action(action_t action) case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break; case ACT_USAGE: debug("ACT_USAGE"); break; case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break; - case ACT_LAYER_PRESSED: debug("ACT_LAYER_PRESSED"); break; - case ACT_LAYER_RELEASED: debug("ACT_LAYER_RELEASED"); break; + case ACT_LAYER: debug("ACT_LAYER"); break; case ACT_LAYER_BIT: debug("ACT_LAYER_BIT"); break; - case ACT_LAYER_EXT: debug("ACT_LAYER_EXT"); break; case ACT_MACRO: debug("ACT_MACRO"); break; case ACT_COMMAND: debug("ACT_COMMAND"); break; case ACT_FUNCTION: debug("ACT_FUNCTION"); break; diff --git a/common/action.h b/common/action.h index b1e958a26..800554eb8 100644 --- a/common/action.h +++ b/common/action.h @@ -150,42 +150,26 @@ ACT_MOUSEKEY(0110): Layer Actions ------------- -TODO: reconsider layer methods. -1 momemtary + tap key up: L, down: default -1 bitwise + tap key up: xor B, down: xor B -3 momemtary go + tap key? up: X, down: -3 toggle(mementary back) + tap key? up: down: Y -3 no tap up: X, down: Y +ACT_LAYER(1000): Set layer +ACT_LAYER_BIT(1001): Bit-op layer -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 L to layer on press and set default on release(momentary) +1000|LLLL|0000 0001 set L to layer on press +1000|LLLL|0000 0010 set L to layer on release +1000|----|0000 0011 set default to layer on both(return to default layer) +1000|LLLL|xxxx xxxx set L to layer while hold and send key on tap +1000|LLLL|1111 0000 set L to layer while hold and toggle on several taps +1000|LLLL|1111 1111 set L to default and layer(on press) -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 -1011|0000|0000 0000 set default layer when pressed -1011|0001|0000 0000 set default layer when released +1001|BBBB|0000 0000 (not used) +1001|BBBB|0000 0001 bit-xor layer with B on press +1001|BBBB|0000 0010 bit-xor layer with B on release +1001|BBBB|0000 0011 bit-xor layer with B on both(momentary) +1001|BBBB|xxxx xxxx bit-xor layer with B while hold and send key on tap +1001|BBBB|1111 0000 bit-xor layer with B while hold and toggle on several taps +1001|BBBB|1111 1111 bit-xor default with B and set layer(on press) -1000|LLLL|1111 0000 set layer L when pressed + tap toggle -1001|LLLL|1111 0000 set layer L when released + tap toggle -1010|BBBB|1111 0000 on/off bit B when pressed/released + tap toggle -1011|0000|1111 0000 set default layer when pressed + tap toggle -1011|0001|1111 0000 set default layer when released + tap toggle -1000|LLLL|1111 1111 set L to default layer when pressed -1001|LLLL|1111 1111 set L to default layer when released -1010|BBBB|1111 1111 on/off bit B of default layer when pressed/released -1011|0000|1111 1111 set current to default layer when pressed -1011|0001|1111 1111 set current to default layer when released - -1000|LLLL| keycode set layer L when pressed + tap key -1001|LLLL| keyocde set layer L when released + tap key -1010|BBBB| keyocde on/off bit B when pressed/released + tap key -1011|0000| keyocde set default layer when pressed + tap key -1011|0001| keyocde set default layer when released + tap key - Extensions(11XX) ---------------- @@ -212,24 +196,14 @@ enum action_kind_id { ACT_USAGE = 0b0100, ACT_MOUSEKEY = 0b0101, - ACT_LAYER_PRESSED = 0b1000, - ACT_LAYER_RELEASED = 0b1001, - ACT_LAYER_BIT = 0b1010, - ACT_LAYER_EXT = 0b1011, + ACT_LAYER = 0b1000, + ACT_LAYER_BIT = 0b1001, ACT_MACRO = 0b1100, ACT_COMMAND = 0b1110, ACT_FUNCTION = 0b1111 }; -enum params { - P_ONESHOT = 0x00, -}; - -enum options { - O_TAP = 0x8, -}; - /* action utility */ #define ACTION_NO 0 @@ -250,48 +224,93 @@ enum options { #define ACTION_RMOD_KEY(mod, key) ACTION(ACT_RMODS, MODS4(MOD_BIT(mod))<<8 | (key)) /* Mods + Tap key */ +enum mods_codes { + MODS_ONESHOT = 0x00, +}; #define ACTION_LMODS_TAP_KEY(mods, key) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | (key)) -#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | P_ONESHOT) +#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | MODS_ONESHOT) #define ACTION_RMODS_TAP_KEY(mods, key) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | (key)) -#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | P_ONESHOT) +#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | MODS_ONESHOT) /* Mod + Tap key */ #define ACTION_LMOD_TAP_KEY(mod, key) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key)) -#define ACTION_LMOD_ONESHOT(mod) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | P_ONESHOT) +#define ACTION_LMOD_ONESHOT(mod) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | MODS_ONESHOT) #define ACTION_RMOD_TAP_KEY(mod, key) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key)) -#define ACTION_RMOD_ONESHOT(mod) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | P_ONESHOT) +#define ACTION_RMOD_ONESHOT(mod) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | MODS_ONESHOT) + + +/* + * Switch layer + */ +enum layer_codes { + LAYER_MOMENTARY = 0, + LAYER_ON_PRESS = 1, + LAYER_ON_RELEASE = 2, + LAYER_DEFAULT =3, + LAYER_TAP_TOGGLE = 0xF0, + LAYER_CHANGE_DEFAULT = 0xFF +}; +enum layer_vals_default { + DEFAULT_ON_PRESS = 1, + DEFAULT_ON_RELEASE = 2, + DEFAULT_ON_BOTH = 3, +}; + +/* + * return to default layer + */ +#define ACTION_LAYER_DEFAULT ACTION_LAYER_DEFAULT_R +/* set default layer on press */ +#define ACTION_LAYER_DEFAULT_P ACTION(ACT_LAYER, DEFAULT_ON_PRESS<<8 | LAYER_DEFAULT) +/* set default layer on release */ +#define ACTION_LAYER_DEFAULT_R ACTION(ACT_LAYER, DEFAULT_ON_RELEASE<<8 | LAYER_DEFAULT) +/* change default layer and set layer */ + +/* + * Set layer + */ +/* set layer on press and set default on release */ +#define ACTION_LAYER_SET(layer) ACTION_LAYER_SET_MOMENTARY(layer) +#define ACTION_LAYER_SET_MOMENTARY(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_MOMENTARY) +/* set layer on press and none on release */ +#define ACTION_LAYER_SET_TOGGLE(layer) ACTION_LAYER_SET_R(layer) +/* set layer while hold and send key on tap */ +#define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER, (layer)<<8 | (key)) +/* set layer on press */ +#define ACTION_LAYER_SET_P(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_ON_PRESS) +/* set layer on release */ +#define ACTION_LAYER_SET_R(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_ON_RELEASE) +/* set layer on hold and toggle on several taps */ +#define ACTION_LAYER_SET_TAP_TOGGLE(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_TAP_TOGGLE) +/* set default layer on both press and release */ +#define ACTION_LAYER_SET_DEFAULT(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_CHANGE_DEFAULT) + +/* + * Bit-op layer + */ +/* bit-xor on both press and release */ +#define ACTION_LAYER_BIT(bits) ACTION_LAYER_BIT_MOMENTARY(bits) +#define ACTION_LAYER_BIT_MOMENTARY(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_MOMENTARY) +/* bit-xor on press */ +#define ACTION_LAYER_BIT_TOGGLE(bits) ACTION_LAYER_BIT_R(bits) +/* bit-xor while hold and send key on tap */ +#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (bits)<<8 | (key)) +/* bit-xor on press */ +#define ACTION_LAYER_BIT_P(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_ON_PRESS) +/* bit-xor on release */ +#define ACTION_LAYER_BIT_R(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_ON_RELEASE) +/* bit-xor while hold and toggle on several taps */ +#define ACTION_LAYER_BIT_TAP_TOGGLE(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_TAP_TOGGLE) +/* bit-xor default layer and set layer */ +#define ACTION_LAYER_BIT_DEFAULT(bits) ACTION(ACT_LAYER, (bits)<<8 | LAYER_CHANGE_DEFAULT) -// TODO: contemplate about layer action -/* Switch current layer */ -#define ACTION_LAYER_SET(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) -#define ACTION_LAYER_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0x00) -#define ACTION_LAYER_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0x00) -#define ACTION_LAYER_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0x00) -#define ACTION_LAYER_SET_DEFAULT ACTION(ACT_LAYER_EXT, 0x0<<8 | 0x00) -#define ACTION_LAYER_RETURN_DEFAULT ACTION(ACT_LAYER_EXT, 0x1<<8 | 0x00) -#define ACTION_LAYER_SET_DEFAULT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0x00) -#define ACTION_LAYER_SET_DEFAULT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0x00) -/* Switch default layer */ -#define ACTION_LAYER_DEFAULT_SET(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_SET_ON_PRESSED(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_SET_ON_RELEASED(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_BIT(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_PRESSED ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xFF) -#define ACTION_LAYER_DEFAULT_SET_CURRENT_ON_RELEASED ACTION(ACT_LAYER_EXT, 0x1<<8 | 0xFF) -/* Layer switch with tap key */ -#define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | (key)) -#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (bits)<<8 | (key)) -#define ACTION_LAYER_DEFAULT_SET_TAP_KEY(key) ACTION(ACT_LAYER_EXT, 0x0<<8 | (key)) -/* Layer switch with tap toggle */ -#define ACTION_LAYER_SET_ON_PRESSED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_PRESSED, (layer)<<8 | 0xF0) -#define ACTION_LAYER_SET_ON_RELEASED_TAP_TOGGLE(layer) ACTION(ACT_LAYER_RELEASED, (layer)<<8 | 0xF0) -#define ACTION_LAYER_BIT_TAP_TOGGLE(layer) ACTION(ACT_LAYER_BIT, (layer)<<8 | 0xF0) -#define ACTION_LAYER_DEFAULT_TAP_TOGGLE ACTION(ACT_LAYER_EXT, 0x0<<8 | 0xF0) /* HID Usage */ -#define ACTION_USAGE_PAGE_SYSTEM 0 -#define ACTION_USAGE_PAGE_CONSUMER 1 -#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_SYSTEM<<10 | (id)) -#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_CONSUMER<<10 | (id)) +enum usage_pages { + PAGE_SYSTEM, + PAGE_CONSUMER +}; +#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM<<10 | (id)) +#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER<<10 | (id)) /* Mousekey */ #define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key) @@ -303,7 +322,10 @@ enum options { #define ACTION_COMMAND(opt, id) ACTION(ACT_COMMAND, (opt)<<8 | (addr)) /* Function */ +enum function_opts { + FUNC_TAP = 0x8, +}; #define ACTION_FUNCTION(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | id) -#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, O_TAP<<8 | id) +#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | id) #endif /* ACTION_H */ diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index f2f21e8ce..65ef89ad7 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -29,8 +29,6 @@ along with this program. If not, see . #include "keymap.h" -// Convert physical keyboard layout to matrix array. -// This is a macro to define keymap easily in keyboard layout form. #define KEYMAP( \ K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \ K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \ @@ -50,6 +48,7 @@ along with this program. If not, see . } +// TODO: use [1] = KEYMAP(...) to prevent from changing index of element? static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Layer 0: Default Layer * ,-----------------------------------------------------------. @@ -57,17 +56,17 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |-----------------------------------------------------------| * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs| * |-----------------------------------------------------------| - * |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | + * |Fn6 | A| S| D| F| G| H| J| K| L|Fn3| '|Return | * |-----------------------------------------------------------| - * |Shift | Z| X| C| V| B| N| M| ,| .|Fn2|Shift |Fn1| + * |Fn8 | Z| X| C| V| B| N| M| ,| .|Fn2|Fn12 |Fn1| * `-----------------------------------------------------------' - * |Gui|Alt |Fn5 |Alt |Fn4| + * |Gui|Alt | Fn5 |Alt |Fn4| * `-------------------------------------------' */ 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, \ FN6, A, S, D, F, G, H, J, K, L, FN3, QUOT,FN7, \ - FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, FN12,FN10, \ + FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, FN12,FN9, \ LGUI,LALT, FN5, FN13,FN4), /* Layer 1: HHKB mode (HHKB Fn) @@ -80,13 +79,13 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |-----------------------------------------------------------| * |Shift | | | | | | +| -|End|PgD|Dow|Shift |Fn0| * `-----------------------------------------------------------' - * |Gui |Alt |Space |Alt |xxx| - * `--------------------------------------------' + * |Gui|Alt | Space |Alt |Gui| + * `-------------------------------------------' */ KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ - CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, BSPC, \ + CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS, UP, NO, BSPC, \ LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ - LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN10, \ + LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN0, \ LGUI,LALT, SPC, RALT,RGUI), /* Layer 2: Vi mode (Slash) @@ -99,7 +98,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |-----------------------------------------------------------| * |Shift | | | | | |Hom|PgD|PgUlEnd|Fn0|Shift | | * `-----------------------------------------------------------' - * |Gui|Alt |Space |Alt |Gui| + * |Gui|Alt | Space |Alt |Gui| * `-------------------------------------------' */ KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ @@ -112,13 +111,13 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * ,-----------------------------------------------------------. * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| * |-----------------------------------------------------------| - * |Tab |MwL|MwU|McU|MwD|MwR|MwL|MwD|MwU|MwR| | | |Backs| + * |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs| * |-----------------------------------------------------------| - * |Contro| |McL|McD|McR| |McL|McD|McU|McR|Fn0| |Return | + * |Contro| | | | | |McL|McD|McU|McR|Fn0| |Return | * |-----------------------------------------------------------| - * |Shift |Mb4|Mb5|Mb1|Mb2|Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | | + * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | | * `-----------------------------------------------------------' - * |Gui |Alt |Mb1 |Alt |Fn0| + * |Gui |Alt | Mb1 |Alt |Fn0| * `--------------------------------------------' * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel */ @@ -147,10 +146,23 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT,NO, \ LGUI,LALT, FN0, RALT,RGUI), - /* Layer5: another Mouse mode (Space) */ + /* Layer5: another Mouse mode (Space) + * ,-----------------------------------------------------------. + * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| + * |-----------------------------------------------------------| + * |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs| + * |-----------------------------------------------------------| + * |Contro| | | | | |McL|McD|McU|McR|Fn0| |Return | + * |-----------------------------------------------------------| + * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | | + * `-----------------------------------------------------------' + * |Gui |Alt | Fn0 |Alt |Fn0| + * `--------------------------------------------' + * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel + */ KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ - LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, \ + LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,NO, NO, ENT, \ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ LGUI,LALT, FN0, RALT,RGUI), }; @@ -164,27 +176,32 @@ enum function_id { MACRO = 0xff }; + /* * Fn action definition */ +// TODO: use [1] = KEYMAP(...) to prevent from changing index of element? static const uint16_t PROGMEM fn_actions[] = { - ACTION_LAYER_RETURN_DEFAULT, // FN0 + ACTION_LAYER_DEFAULT, // FN0 ACTION_LAYER_SET(1), // FN1 - ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH), // FN2 - ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // FN3 - //ACTION_LAYER_SET(3), // FN4 - ACTION_FUNCTION(MACRO, 0), // FN4 + ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH), // FN2 Layer with Slash + ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // FN3 Layer with Semicolon + + ACTION_LAYER_SET(3), // FN4 +// ACTION_LAYER_SET_TOGGLE(3), // FN4 +// ACTION_FUNCTION(MACRO, 0), // FN4 ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // FN5 - ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // FN6 - ACTION_RMOD_TAP_KEY(KC_RCTL, KC_ENT), // FN7 - ACTION_LMOD_ONESHOT(KC_LSFT), // FN8 Oneshot Shift - ACTION_LAYER_SET_ON_RELEASED_TAP_TOGGLE(1), // FN9 - ACTION_LAYER_BIT_TAP_KEY(1, KC_GRV), // FN10 +// ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // FN6 Control with tap Backspace + ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC), // FN6 Control with tap Backspace + ACTION_RMOD_TAP_KEY(KC_RCTL, KC_ENT), // FN7 Control with tap Enter + ACTION_LMOD_ONESHOT(KC_LSFT), // FN8 Oneshot Shift + ACTION_LAYER_SET_TAP_TOGGLE(1), // FN9 + ACTION_LAYER_BIT_TAP_KEY(1, KC_GRV), // FN10 Layer with Grave //ACTION_LAYER_BIT(1), // FN10 //ACTION_LAYER_BIT_TAP_TOGGLE(1), // FN10 - ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // FN11 - ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // FN12 - ACTION_FUNCTION(MACRO, 1), // FN13 + ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // FN11 Function: LShift with tap '(' + ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // FN12 Function: RShift with tap ')' + ACTION_FUNCTION(MACRO, 1), // FN13 Macro: }; From 74ecdd15a72ee344f3ae0c01cff52f5fee04a011 Mon Sep 17 00:00:00 2001 From: tmk Date: Sun, 10 Feb 2013 16:11:58 +0900 Subject: [PATCH 27/30] Add description of keymap and layer in README.md --- README.md | 500 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 428 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index 65fc72f53..807129c35 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,17 @@ Source code is available here: Features -------- -* Mouse key - Mouse control by keyboard. -* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up. -* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc. -* USB NKRO - Can send 120 keys(+ 8 modifiers) simultaneously. -* PS/2 mouse support - integrate PS/2 mouse(TrackPoint) into keyboard as composite device. -* keyboard protocols - PS/2, ADB and old keyboard protocols. +* Multi-layer keymap - Multiple keyboard layouts with layer switching. +* Mouse key - Mouse control with keyboard +* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up +* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc +* USB NKRO - 120 keys(+ 8 modifiers) simultaneously +* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device +* Keyboard protocols - PS/2, ADB, M0110, Sun and other old keyboard protocols +* User Function - Customizable function of key with writing code +* Macro - Very primitive at this time +* Keyboard Tricks - Oneshot modifier and modifier with tapping feature +* Debug Console - Messages for debug and interaction with firmware Projects @@ -24,11 +29,17 @@ Projects * terminal_usb - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal] * news_usb - [Sony NEWS keyboard to USB][GH_news] * x68k_usb - [Sharp X68000 keyboard to USB][GH_x68k] +* sun_usb - Sun to USB(type4, 5 and 3?) +* usb_usb - USB to USB(experimental) ### keyboard -* hhkb - [Happy Hacking Keyboard professional][GH_hhkb] -* macway - [Compact keyboard mod][GH_macway] -* hbkb - [Happy Buckling sprint keyboard(IBM Model M mod)][GH_hbkb] +* hhkb - [Happy Hacking Keyboard professional][GH_hhkb] +* macway - [Compact keyboard mod][GH_macway] +* hbkb - [Happy Buckling sprint keyboard(IBM Model M mod)][GH_hbkb] +* IIgs_Standard - Apple IIGS keyboard mod(by JeffreySung) +* hid_liber - [HID liberation controller][HID_liber](by alaricljs) +* phantom - [Phantom keyboard][PHANTOM] (by Tranquilite) +* gh60 - [GH60 keyboard][GH60] [GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930 [GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047 @@ -40,52 +51,99 @@ Projects [GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272 [GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060 [GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483 +[HID_liber]: http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions +[PHANTOM]: http://geekhack.org/index.php?topic=26742 +[GH60]: http://geekhack.org/index.php?topic=34959 -Files & Directories -------------------- -### Top -* common/ - common codes -* protocol/ - keyboard protocol support -* keyboard/ - keyboard projects -* converter/ - protocol converter projects -* doc/ - documents -* common.mk - Makefile for common -* protoco.mk - Makefile for protocol -* rules.mk - Makefile for build rules - -### Keyboard Protocols -* pjrc/ - PJRC USB stack -* vusb/ - Objective Development V-USB -* iwrap/ - Bluetooth HID for Bluegiga iWRAP -* ps2.c - PS/2 protocol -* adb.c - Apple Desktop Bus protocol -* m0110.c - Macintosh 128K/512K/Plus keyboard protocol -* news.c - Sony NEWS keyboard protocol -* x68k.c - Sharp X68000 keyboard protocol - - Build & Program --------------- +### Install Tools +First, you need tools to build firmware and program your controller. I assume you are on Windows here. + +1. Install [WinAVR][winavr]. This is old but works well for this purpose. `WinAVR` is a tool set to build firmware including C compiler(gcc) and make commands. You can use [CrossPack][crosspack] instead if you are on Mac. + +2. Install [Atmel FLIP][flip]. `FLIP` is a tool to program(load) firmware into AVR controller(ATMega32u4) via DFU bootloader. ATMega32u4 has DFU bootloader by factory default. You can use [dfu-programmer][dfu-prog] instead if you are on Mac. + +3. Install driver for DFU bootloader. At first time you start DFU bootloader on Chip 'Found New Hardware Wizard' will come up on Windows. If you install device driver properly you can find chip name like 'ATmega32U4' under 'LibUSB-Win32 Devices' tree on 'Device Manager'. If not you shall need to update its driver on 'Device Manager'. You will find the driver in `FLIP` install directory like: C:\Program Files (x86)\Atmel\Flip 3.4.5\usb\. If you use `dfu-programmer` install its driver. + +If you use PJRC Teensy you don't need step 2 and 3, just get [Teensy loader][teensy-loader]. + + +### Download source +You can find firmware source at github: https://github.com/tmk/tmk_keyboard + +If you are familiar with `Git` tools you are recommended to use it. +If not you can download zip archive from: https://github.com/tmk/tmk_keyboard/archive/master.zip + + ### Build firmware -To compile you need `AVR GCC`, `AVR Libc` and `GNU make`. -You can use [WinAVR][winavr] on Windows and [CrossPack][crosspack] on Mac. +1. Open terminal window to get access to commands. You can use `cmd` in Windows or `Terminal.app` on Mac OSX. In Windows press `Windows` key and `R` then enter `cmd` in Run command dialog showing up. - $ cd - $ make +2. Move to project directory in the firmware source. + + cd tmk_keyboard/{keyboard or converter}/ + +3. Build firmware using GNU `make` command. You'll see _.hex file in that directory unless something unexpected occurs in build process. + + mkae -f Makefile. clean + make -f Makefile. + + + + +### Program Controller +Sock AVR USB chip including ATmega32U4 has DFU bootloader by factory default, you can use DFU tools for this purpose. `FLIP` is a DFU tool on Windows offered by Atmel. Open source command line DFU tool `dfu-programmer` also supports AVR chips, which run on Linux, Mac OSX and even Windows. If you have a PJRC Teensy you should use `Teensy Loader`. + +#### DFU bootloader +To program AVR chip with DFU bootloader use `FLIP` or `dfu-programmer`. +If you have a proper program command in `Makefile` just type this. + +`FLIP` has two version of tool, GUI app and command line program. If you want GUI see tutorial section below. +To use command line tool run this command. Note that you need to set PATH variable properly. + + $ make -f Makefile. flip + +To program with `dfu-programmer` run: + + $ make -f Makefile. dfu + +#### Teensy +If you have PJRC Teensy see instruction of `Teensy Loader` at: +Or use this command if you have command line version of Teensy Loader installed. + + $ make -f Makefile. teensy + + +#### Other programmer +You may want to use other you favorite programmer like `avrdude` with AVRISPmkII, Aruduino or USBasp. In that case you can still use make target `program` for build with configuring PROGRAM_CMD in Makefile. + + $ make -f Makefile. program + + + +#### FLIP GUI tutorial +1. On menu bar click Device -> Select, then. `ATmega32u4`. +2. On menu bar click Settings -> Communication -> USB, then click 'Open' button on 'USB Port Connection' dialog. +At this point you'll see greyouted widgets on the app get colored and ready. + +3. On menu bar click File -> Load HEX File, then select your firmware hex file on File Selector dialog. +4. On 'Operations Flow' panel click 'Run' button to load the firmware binary to the chip. Note that you should keep 'Erase', 'Blank Check', 'Program' and 'Verify' check boxes selected. +5. Re-plug USB cord or click 'Start Application' button to restart your controller. +Done. + +See also these instaructions if you need. + +- +- -The firmware will be compiled as a file `tmk_.hex`. [winavr]: http://winavr.sourceforge.net/ [crosspack]: http://www.obdev.at/products/crosspack/index.html - -### Program Controller -If you have a proper program command in `Makefile` just type this. - - $ make program - -As for `Teensy` you can use `PJRC's loader` to program hex file. +[flip]: http://www.atmel.com/tools/FLIP.aspx +[dfu-prog]: http://dfu-programmer.sourceforge.net/ +[teensy-loader]:http://www.pjrc.com/teensy/loader.html @@ -106,20 +164,22 @@ Note that ***comment out*** to disable them. NKRO_ENABLE = yes # USB Nkey Rollover ### 3. Programmer -Set proper command for your controller, bootloader and programmer. +Optional. Set proper command for your controller, bootloader and programmer. # for PJRC Teensy PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex - # for Atmel AT90USBKEY + # for Atmel chip with DFU bootloader PROGRAM_CMD = dfu-programmer $(MCU) flash $(TARGET).hex - # avrdude + # avrdude with other methods PROGRAM_CMD = avrdude -p $(MCU) -c avrispmkII -P USB -U flash:w:$(TARGET).hex PROGRAM_CMD = avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex PROGRAM_CMD = avrdude -p $(MCU) -c arduino -P COM1 -b 57600 -U flash:w:$(TARGET).hex -config.h Options + + +Config.h Options ---------------- ### 1. USB vendor/product ID and device description #define VENDOR_ID 0xFEED @@ -145,42 +205,338 @@ config.h Options Keymap ------ +Many of existent projects offer keymap framework to define your own keymap easily. The following will explain how you can define keymap using this framework. + Instead, you can also implement your own `keymap_get_action()` to return action code for each key if you want. + +This is keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard. Keyamp is defined in `keymaps[]` array. + + static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Layer 0: Default Layer + * ,-----------------------------------------------------------. + * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `| + * |-----------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs| + * |-----------------------------------------------------------| + * |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter | + * |-----------------------------------------------------------| + * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn1| + * `-----------------------------------------------------------' + * |Gui|Alt |Space |Alt |Fn2| + * `-------------------------------------------' + */ + 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, FN2, QUOT,ENT, \ + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN1, \ + LGUI,LALT, SPC, RALT,FN3), + + /* Layer 1: HHKB mode (HHKB Fn) + * ,-----------------------------------------------------------. + * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| + * |-----------------------------------------------------------| + * |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs| + * |-----------------------------------------------------------| + * |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | + * |-----------------------------------------------------------| + * |Shift | | | | | | +| -|End|PgD|Dow|Shift |Fn1| + * `-----------------------------------------------------------' + * |Gui |Alt |Space |Alt |Gui| + * `--------------------------------------------' + */ + KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ + CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, BSPC, \ + LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ + LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN0, \ + LGUI,LALT, SPC, RALT,RGUI), + /* Layer 2: Mouse mode (Semicolon) + * ,-----------------------------------------------------------. + * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| + * |-----------------------------------------------------------| + * |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs| + * |-----------------------------------------------------------| + * |Contro| | | | | |McL|McD|McU|McR|Fn0| |Return | + * |-----------------------------------------------------------| + * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | | + * `-----------------------------------------------------------' + * |Gui |Alt |Mb1 |Alt |Fn0| + * `--------------------------------------------' + * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel + */ + KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ + TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ + LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, QUOT,ENT, \ + LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,NO, \ + LGUI,LALT, BTN1, RALT,FN0), + }; + + static const uint16_t PROGMEM fn_actions[] = { + ACTION_LAYER_DEFAULT, // FN0 + ACTION_LAYER_SET(1), // FN1 + ACTION_LAYER_SET_TAP_KEY(2, KC_SCLN), // FN2 + ACTION_LAYER_BIT_TOGGLE(2), // FN3 + }; -Build your own firmware ------------------------ + +### 1. Keycode +See `common/keycode.h`. Keycode is 8bit internal code to inidicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like 'KC_A' have simple action register key on press and unregister on release, on the other some of keycodes has some special actions like Fn keys, Media contorl keys, System control keys and Mouse keys. + + ***In `KEYMAP` definition you need to omit prefix part `KC_` of keycode to keep keymap compact.*** For example, just use `A` instead you place `KC_A` in `KEYMAP`. Some keycodes has 4-letter short name in addition to descriptive name, you'll prefer short one in `KEYMAP`. + + **`KC_NO`** indicates the key has no keycode to transmit. + + **`KC_LGUI`** and **`KC_RGUI`** are windows key or command key in Mac. + + **`KC_FNnn`** are `Fn` keys which not given any action at the beginning unlike most of keycodes has its own action. To use these keys in `KEYMAP` you need to assign action you want at first. Action of `Fn` is defined in `fn_actions[]` and index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` designates action defined in first element of the array. ***32 `Fn` keys can be defined at most.*** + + See keycode table or `keycode.h` for other keycodes. + ***TODO: Keycode table link here.*** + + In regard to implementation side most of keycodes are identical with [HID usage] sent to host for real and some virtual keycodes are defined to support special actions. +[HID usage]: http://www.usb.org/developers/devclass_docs/Hut1_11.pdf + + + +### 2. Action +See `common/action.h`. Action is a 16bit code and defines function to perform on events of a key like press, release, hold and tap. You can define various actions to use various action codes. + +Most of keys just register 8bit keycode as HID usage(or scan code) to host, but to support other complex functions needs 16bit extended action codes internally. But using 16bit action codes with keymap results in double size in memory against keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP` to define instead of action codes. ***Keycodes can be considered as subset of action codes.*** Like `KC_A`(0x04) is equal to a `Key` action(0x0004) that transmit keycode of `A`. + +#### 2.1 Key action +Key is simple action that registers keycode on press of key and unregister on release. +You can define `Key` action on `A` with: + + ACTION_KEY(KC_A) + +But you won't need to use this expression directly because you can just put symbol like `A` in `KEYMAP`. + + Say you want to assign a key to `Shift + 1` to get *!* or `Alt + Tab` to switch windows. + + ACTION_MOD_KEY(KC_LSHIFT, KC_1) + ACTION_MOD_KEY(KC_LALT, KC_TAB) + +`Alt,Shift + Tab` + ACTION_MODS_KEY((MOD_BIT(KC_LALT) | MOD_BIT(KC_LSHIFT)), KC_TAB) + +These actions are comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes. + +#### 2.2 Layer Actions +This sets `default layer` into `current layer`. With this action you can return to `default layer`. + + ACTION_LAYER_DEFAULT + +`Layer Set` action sets given layer argument to `current layer`. `Layer Set` action can take 0 to 15 as argument. + + ACTION_LAYER_SET(layer) + ACTION_LAYER_SET_TOGGLE(layer) + ACTION_LAYER_SET_TAP_KEY(layer, key) + ACTION_LAYER_SET_TAP_TOGGLE(layer) + +`Layer Bit` action XOR bits with `current layer`. `Layer Bit` action can take 0 to 8 as argument. + + ACTION_LAYER_BIT(bits) + ACTION_LAYER_BIT_TOGGLE(bits) + ACTION_LAYER_BIT_TAP_KEY(bits, key) + ACTION_LAYER_BIT_TAP_TOGGLE(bits) + +These acitons change `default layer`. + ACTION_LAYER_SET_DEFAULT(layer) + ACTION_LAYER_BIT_DEFAULT(bits) + + +#### 2.3 Macro action +`Macro` action indicates complex key strokes. ***TODO*** + + +#### 2.4 Function action +`Function` action can be defined freely in C function. ***TODO*** +`Function` action is implemented in `keymap_call_function()` + + + +### 3. Layer + Layer is key-action map to assign action to every physical key. You can define multiple layers in keymap and select a layer out of keymap during operation at will. + + First layer is indexed by `Layer 0` which usually become **`default layer`** and active in initial state. **`current layer`** is active layer at that time and can be changed with user interaction. You can define **16 layers** at most in default keymap framework. + + you can define a layer with placing keycode symbols separated with `comma` in `KEYMAP`, which is formed with resemblance to physical keyboard layout so as you can easily put keycode on place you want to map. ***You can define most of keys with just using keycodes*** except for `Fn` key serving special actions. + + + +### 4. Layer switching +You can have some ways to switch layer with these actions. +There are two kind of layer switch action `Layer Set` and `Layer Bit` and two type of switching behaviour **Momentary** and **Toggle**. + +#### 4.1 Momentary switching +Momentary switching changes layer only while holding Fn key. + +##### 4.1.1 Momentary Set +This `Layer Set` action sets new layer(`Layer 1`) to `current layer` on key press event. + + ACTION_LAYER_SET(1) + +It switches to destination layer immediately when key is pressed, after that actions on keymap of destination layer is perfomed. ***Thus you shall need to place action to come back on destination layer***, or you will be stuck in destination layer without way to get back. To get back to `default layer` you can use this action. + + ACTION_LAYER_DEFAULT + +##### 4.1.2 Momentary Bit +This `Layer Bit` action performs XOR(`1`) with `current layer` on both press and release event. If you are on `Layer 0` now next layer to switch will be `Layer 1`. To come back to previous layer you need to place same action on destination layer. + + ACTION_LAYER_BIT(1) + +#### 4.2 Toggle switching +Toggle switching changes layer after press then release. You keep being on the layer until you press key to return. + +##### 4.2.1 Toggle Set +This `Layer Set Toggle` action is to set `Layer 1` to `current layer` on release and do none on press. + + ACTION_LAYER_SET_TOGGLE(1) + +To get back to `default layer` you can use this action. + + ACTION_LAYER_DEFAULT + +##### 4.2.2 Toggle Bit +This `Layer Bit Toggle` action is to XOR `1` with `current layer` on release and do none on press. If you are on `Layer 2` you'll switch to `Layer 3` on press. To come back to previous layer you need to place same action on destination layer. + + ACTION_LAYER_BIT_TOGGLE(1) + + +#### 4.3 Momentary switching with Tap key +These actions switch to layer only while holding `Fn` key and register key on tap. **Tap** means to press and release key quickly. + + ACTION_LAYER_SET_TAP_KEY(2, KC_SCLN) + ACTION_LAYER_SET_BIT_KEY(2, KC_SCLN) + +With these you can place layer switching function on normal alphabet key like `;` without losing its original register function. + +#### 4.4 Momentary switching with Tap Toggle +This changes layer only while holding `Fn` key and toggle layer after several taps. **Tap** means to press and release key quickly. + + ACTION_LAYER_SET_TAP_TOGGLE(layer) + ACTION_LAYER_BIT_TAP_TOGGLE(layer) + +Number of taps can be defined with `TAPPING_TOGGLE` in `config.h`, `5` by default. + + + + +Legacy Keymap +------------- +This was used in prior version and still works due to legacy support code in `common/keymap.c`. Legacy keymap doesn't support many of features that new keymap offers. + +In comparison with new keymap how to define Fn key is different. It uses two arrays `fn_layer[]` and `fn_keycode[]`. The index of arrays corresponds with postfix number of `Fn` key. Array `fn_layer[]` indicates destination layer to switch and `fn_keycode[]` has keycodes to send when tapping `Fn` key. + +In following setting example, `Fn0`, `Fn1` and `Fn2` switch layer to 1, 2 and 2 respectively. `Fn2` registers `Space` key when tap while `Fn0` and `Fn1` doesn't send any key. + + static const uint8_t PROGMEM fn_layer[] = { + 1, // Fn0 + 2, // Fn1 + 2, // Fn2 + }; + + static const uint8_t PROGMEM fn_keycode[] = { + KC_NO, // Fn0 + KC_NO, // Fn1 + KC_SPC, // Fn2 + }; + Debuging -------- -Use PJRC's `hid_listen` to see debug messages and press ` + H` to debug menu. -See `config.h` for definition of `` key combination. +Use PJRC's `hid_listen` to see debug messages. You can use the tool for debug even if firmware use LUFA stack. + +You will see output from firmware like this. + + r/c 01234567 + 00: 00000000 + 01: 00000000 + 02: 00000000 + 03: 00000000 + 04: 00000000 + 05: 00000000 + 06: 00000000 + 07: 00000000 + + ---- action_exec: start ----- + EVENT: 0307u(22511) + Tapping: Tap release(2) + ACTION: ACT_LAYER[5:2C] + LAYER_PRESSED: Tap: unregister_code + TAPPING_KEY=0307u(22511):2 + processed: 0307u(22511):2 + + Tapping: End(Timeout after releasing last tap): FFFFu(22715) + TAPPING_KEY=0000u(0):0 -Other Keyboard Projects + + +Magic Comannds +-------------- +To see help press `Magic` + `H`. + + `Magic` key bind may be `LShift` + `RShift` in many project, but `Power` key on ADB converter. `Magic` keybind can be vary on each project, check `config.h` in project directory. + +Following commands can be also executed with `Magic` + key. In console mode `Magic` keybind is not needed. + + ----- Command Help ----- + c: enter console mode + d: toggle debug enable + x: toggle matrix debug + k: toggle keyboard debug + m: toggle mouse debug + p: toggle print enable + v: print device version & info + t: print timer count + s: print status + 0/F10: switch to Layer0 + 1/F1: switch to Layer1 + 2/F2: switch to Layer2 + 3/F3: switch to Layer3 + 4/F4: switch to Layer4 + PScr: power down/remote wake-up + Caps: Lock Keyboard(Child Proof) + Paus: jump to bootloader + + + +Start Your Own Project ----------------------- -### PJRC USB Keyboard/Mouse Example -- -- -### kbupgrade -- -- -### c64key -- -### rump -- -- +Files & Directories +------------------- +### Top +* common/ - common codes +* protocol/ - keyboard protocol support +* keyboard/ - keyboard projects +* converter/ - protocol converter projects +* doc/ - documents +* common.mk - Makefile for common +* protoco.mk - Makefile for protocol +* rules.mk - Makefile for build rules -### dulcimer -- +### Common +***TODO*** -### humblehacker-keyboard -- -- -- +### Keyboard Protocols +* lufa/ - LUFA USB stack +* pjrc/ - PJRC USB stack +* vusb/ - Objective Development V-USB +* iwrap/ - Bluetooth HID for Bluegiga iWRAP +* ps2.c - PS/2 protocol +* adb.c - Apple Desktop Bus protocol +* m0110.c - Macintosh 128K/512K/Plus keyboard protocol +* news.c - Sony NEWS keyboard protocol +* x68k.c - Sharp X68000 keyboard protocol +* serial_soft.c - Asynchronous Serial protocol implemented by software -### ps2avr -- + + +License +------- +Under `GPL` 2 or later. Some protocol files are under `Modified BSD License`. +PJRC stack has its own license. From 0be309ccc6acae61616f89bcc43df5e02c4df92a Mon Sep 17 00:00:00 2001 From: tmk Date: Sun, 10 Feb 2013 21:37:03 +0900 Subject: [PATCH 28/30] Add doc/keycode.txt --- README.md | 26 ++++- common/keycode.h | 4 +- doc/keycode.txt | 261 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+), 5 deletions(-) create mode 100644 doc/keycode.txt diff --git a/README.md b/README.md index 807129c35..90c24b031 100644 --- a/README.md +++ b/README.md @@ -289,8 +289,7 @@ See `common/keycode.h`. Keycode is 8bit internal code to inidicate action perfor **`KC_FNnn`** are `Fn` keys which not given any action at the beginning unlike most of keycodes has its own action. To use these keys in `KEYMAP` you need to assign action you want at first. Action of `Fn` is defined in `fn_actions[]` and index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` designates action defined in first element of the array. ***32 `Fn` keys can be defined at most.*** - See keycode table or `keycode.h` for other keycodes. - ***TODO: Keycode table link here.*** + See [keycode table](doc/keycode.txt) in `doc/keycode.txt` or `common/keycode.h` for other keycodes. In regard to implementation side most of keycodes are identical with [HID usage] sent to host for real and some virtual keycodes are defined to support special actions. [HID usage]: http://www.usb.org/developers/devclass_docs/Hut1_11.pdf @@ -520,7 +519,28 @@ Files & Directories * rules.mk - Makefile for build rules ### Common -***TODO*** +* action.[ch] +* action_macro.[ch] +* bootloader.[ch] +* command.[ch] +* controller_teensy.h +* debug.[ch] +* host.[ch] +* host_driver.h +* keyboard.[ch] +* keycode.h +* keymap.[ch] +* led.h +* matrix.h +* mousekey.[ch] +* print.[ch] +* report.h +* sendchar.h +* sendchar_null.c +* sendchar_uart.c +* timer.[ch] +* uart.[ch] +* util.[ch] ### Keyboard Protocols * lufa/ - LUFA USB stack diff --git a/common/keycode.h b/common/keycode.h index 341f23161..4f57a5887 100644 --- a/common/keycode.h +++ b/common/keycode.h @@ -392,7 +392,7 @@ enum internal_special_keycodes { KC_SYSTEM_SLEEP, KC_SYSTEM_WAKE, - /* Consumer Page */ + /* Media Control */ KC_AUDIO_MUTE, KC_AUDIO_VOL_UP, KC_AUDIO_VOL_DOWN, @@ -412,7 +412,7 @@ enum internal_special_keycodes { KC_WWW_REFRESH, KC_WWW_FAVORITES, /* 0xB9 */ - /* Layer Switching */ + /* Fn key */ KC_FN0 = 0xC0, KC_FN1, KC_FN2, diff --git a/doc/keycode.txt b/doc/keycode.txt new file mode 100644 index 000000000..413756692 --- /dev/null +++ b/doc/keycode.txt @@ -0,0 +1,261 @@ +Keycode Symbol Table +==================== +Keycodes are defined in `common/keycode.h`. +Range of 00-A4 and E0-E7 are identical with HID Usage: + +Virtual keycodes are defined out of above range to support special actions. + + +Keycode Symbol Short name Description +-------------------------------------------------------------------------------- +KC_NO 00 Reserved (no event indicated) +KC_ROLL_OVER 01 Keyboard ErrorRollOver +KC_POST_FAIL 02 Keyboard POSTFail +KC_UNDEFINED 03 Keyboard ErrorUndefined +KC_A 04 Keyboard a and A +KC_B 05 Keyboard b and B +KC_C 06 Keyboard c and C +KC_D 07 Keyboard d and D +KC_E 08 Keyboard e and E +KC_F 09 Keyboard f and F +KC_G 0A Keyboard g and G +KC_H 0B Keyboard h and H +KC_I 0C Keyboard i and I +KC_J 0D Keyboard j and J +KC_K 0E Keyboard k and K +KC_L 0F Keyboard l and L +KC_M 10 Keyboard m and M +KC_N 11 Keyboard n and N +KC_O 12 Keyboard o and O +KC_P 13 Keyboard p and P +KC_Q 14 Keyboard q and Q +KC_R 15 Keyboard r and R +KC_S 16 Keyboard s and S +KC_T 17 Keyboard t and T +KC_U 18 Keyboard u and U +KC_V 19 Keyboard v and V +KC_W 1A Keyboard w and W +KC_X 1B Keyboard x and X +KC_Y 1C Keyboard y and Y +KC_Z 1D Keyboard z and Z +KC_1 1E Keyboard 1 and ! +KC_2 1F Keyboard 2 and @ +KC_3 20 Keyboard 3 and # +KC_4 21 Keyboard 4 and $ +KC_5 22 Keyboard 5 and % +KC_6 23 Keyboard 6 and ^ +KC_7 24 Keyboard 7 and & +KC_8 25 Keyboard 8 and * +KC_9 26 Keyboard 9 and ( +KC_0 27 Keyboard 0 and ) +KC_ENTER KC_ENT 28 Keyboard Return (ENTER) +KC_ESCAPE KC_ESC 29 Keyboard ESCAPE +KC_BSPACE KC_BSPC 2A Keyboard DELETE (Backspace) +KC_TAB 2B Keyboard Tab +KC_SPACE KC_SPC 2C Keyboard Spacebar +KC_MINUS KC_MINS 2D Keyboard - and (underscore) +KC_EQUAL KC_EQL 2E Keyboard = and + +KC_LBRACKET KC_LBRC 2F Keyboard [ and { +KC_RBRACKET KC_RBRC 30 Keyboard ] and } +KC_BSLASH KC_BSLS 31 Keyboard \ and | +KC_NONUS_HASH KC_NUHS 32 Keyboard Non-US # and ~ +KC_SCOLON KC_SCLN 33 Keyboard ; and : +KC_QUOTE KC_QUOT 34 Keyboard ‘ and “ +KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde +KC_COMMA KC_COMM 36 Keyboard, and < +KC_DOT 37 Keyboard . and > +KC_SLASH KC_SLSH 38 Keyboard / and ? +KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock +KC_F1 3A Keyboard F1 +KC_F2 3B Keyboard F2 +KC_F3 3C Keyboard F3 +KC_F4 3D Keyboard F4 +KC_F5 3E Keyboard F5 +KC_F6 3F Keyboard F6 +KC_F7 40 Keyboard F7 +KC_F8 41 Keyboard F8 +KC_F9 42 Keyboard F9 +KC_F10 43 Keyboard F10 +KC_F11 44 Keyboard F11 +KC_F12 45 Keyboard F12 +KC_PSCREEN KC_PSCR 46 Keyboard PrintScreen1 +KC_SCKLOCK KC_SLCK 47 Keyboard Scroll Lock11 +KC_PAUSE KC_PAUS 48 Keyboard Pause1 +KC_INSERT KC_INT 49 Keyboard Insert1 +KC_HOME 4A Keyboard Home1 +KC_PGUP 4B Keyboard PageUp1 +KC_DELETE KC_DELETE 4C Keyboard Delete Forward +KC_END 4D Keyboard End1 +KC_PGDOWN KC_PGDN 4E Keyboard PageDown1 +KC_RIGHT KC_RGHT 4F Keyboard RightArrow1 +KC_LEFT 50 Keyboard LeftArrow1 +KC_DOWN 51 Keyboard DownArrow1 +KC_UP 52 Keyboard UpArrow1 +KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11 +KC_KP_SLASH KC_PSLS 54 Keypad /1 +KC_KP_ASTERISK KC_PAST 55 Keypad * +KC_KP_MINUS KC_PMNS 56 Keypad - +KC_KP_PLUS KC_PPLS 57 Keypad + +KC_KP_ENTER KC_PENT 58 Keypad ENTER5 +KC_KP_1 KC_P1 59 Keypad 1 and End +KC_KP_2 KC_P2 5A Keypad 2 and Down Arrow +KC_KP_3 KC_P3 5B Keypad 3 and PageDn +KC_KP_4 KC_P4 5C Keypad 4 and Left Arrow +KC_KP_5 KC_P5 5D Keypad 5 +KC_KP_6 KC_P6 5E Keypad 6 and Right Arrow +KC_KP_7 KC_P7 5F Keypad 7 and Home +KC_KP_8 KC_P8 60 Keypad 8 and Up Arrow +KC_KP_9 KC_P9 61 Keypad 9 and PageUp +KC_KP_0 KC_P0 62 Keypad 0 and Insert +KC_KP_DOT KC_PDOT 63 Keypad . and Delete +KC_NONUS_BSLASH KC_NUBS 64 Keyboard Non-US \ and | +KC_APPLICATION KC_APP 65 Keyboard Application10 +KC_POWER 66 Keyboard Power9 +KC_KP_EQUAL KC_PEQL 67 Keypad = +KC_F13 68 Keyboard F13 +KC_F14 69 Keyboard F14 +KC_F15 6A Keyboard F15 +KC_F16 6B Keyboard F16 +KC_F17 6C Keyboard F17 +KC_F18 6D Keyboard F18 +KC_F19 6E Keyboard F19 +KC_F20 6F Keyboard F20 +KC_F21 70 Keyboard F21 +KC_F22 71 Keyboard F22 +KC_F23 72 Keyboard F23 +KC_F24 73 Keyboard F24 +KC_EXECUTE 74 Keyboard Execute +KC_HELP 75 Keyboard Help +KC_MENU 76 Keyboard Menu +KC_SELECT 77 Keyboard Select +KC_STOP 78 Keyboard Stop +KC_AGAIN 79 Keyboard Again +KC_UNDO 7A Keyboard Undo +KC_CUT 7B Keyboard Cut +KC_COPY 7C Keyboard Copy +KC_PASTE 7D Keyboard Paste +KC_FIND 7E Keyboard Find +KC__MUTE 7F Keyboard Mute +KC__VOLUP 80 Keyboard Volume Up +KC__VOLDOWN 81 Keyboard Volume Down +KC_LOCKING_CAPS 82 Keyboard Locking Caps Lock12 +KC_LOCKING_NUM 83 Keyboard Locking Num Lock12 +KC_LOCKING_SCROLL 84 Keyboard Locking Scroll Lock12 +KC_KP_COMMA KC_PCMM 85 Keypad Comma27 +KC_KP_EQUAL_AS400 86 Keypad Equal Sign29 +KC_INT1 KC_RO 87 Keyboard International115,28 +KC_INT2 KC_KANA 88 Keyboard International216 +KC_INT3 KC_JYEN 89 Keyboard International317 +KC_INT4 KC_HENK 8A Keyboard International418 +KC_INT5 KC_MHEN 8B Keyboard International519 +KC_INT6 8C Keyboard International620 +KC_INT7 8D Keyboard International721 +KC_INT8 8E Keyboard International822 +KC_INT9 8F Keyboard International922 +KC_LANG1 90 Keyboard LANG125 +KC_LANG2 91 Keyboard LANG226 +KC_LANG3 92 Keyboard LANG330 +KC_LANG4 93 Keyboard LANG431 +KC_LANG5 94 Keyboard LANG532 +KC_LANG6 95 Keyboard LANG68 +KC_LANG7 96 Keyboard LANG78 +KC_LANG8 97 Keyboard LANG88 +KC_LANG9 98 Keyboard LANG98 +KC_ALT_ERASE 99 Keyboard Alternate Erase7 +KC_SYSREQ 9A Keyboard SysReq/Attention1 +KC_CANCEL 9B Keyboard Cancel +KC_CLEAR 9C Keyboard Clear +KC_PRIOR 9D Keyboard Prior +KC_RETURN 9E Keyboard Return +KC_SEPARATOR 9F Keyboard Separator +KC_OUT A0 Keyboard Out +KC_OPER A1 Keyboard Oper +KC_CLEAR_AGAIN A2 Keyboard Clear/Again +KC_CRSEL A3 Keyboard CrSel/Props +KC_EXSEL A4 Keyboard ExSel +/* Modifiers */ +KC_LCTRL KC_LCTRL E0 Keyboard LeftControl +KC_LSHIFT KC_LSFT E1 Keyboard LeftShift +KC_LALT E2 Keyboard LeftAlt +KC_LGUI E3 Keyboard Left GUI(Windows/Apple/Meta key) +KC_RCTRL KC_RCTL E4 Keyboard RightControl +KC_RSHIFT KC_RSFT E5 Keyboard RightShift +KC_RALT E6 Keyboard RightAlt +KC_RGUI E7 Keyboard Right GUI(Windows/Apple/Meta key) + +/* + * Virtual keycodes + */ +/* System Control */ +KC_SYSTEM_POWER KC_PWR System Power Down +KC_SYSTEM_SLEEP KC_SLEP System Sleep +KC_SYSTEM_WAKE KC_WAKE System Wake +/* Consumer Page */ +KC_AUDIO_MUTE KC_MUTE +KC_AUDIO_VOL_UP KC_VOLU +KC_AUDIO_VOL_DOWN KC_VOLD +KC_MEDIA_NEXT_TRACK KC_MNXT +KC_MEDIA_PREV_TRACK KC_MPRV +KC_MEDIA_STOP KC_MSTP +KC_MEDIA_PLAY_PAUSE KC_MPLY +KC_MEDIA_SELECT KC_MSEL +KC_MAIL KC_MAIL +KC_CALCULATOR KC_CALC +KC_MY_COMPUTER KC_MYCM +KC_WWW_SEARCH KC_WSCH +KC_WWW_HOME KC_WHOM +KC_WWW_BACK KC_WBAK +KC_WWW_FORWARD KC_WFWD +KC_WWW_STOP KC_WSTP +KC_WWW_REFRESH KC_WREF +KC_WWW_FAVORITES KC_WFAV +/* Mousekey */ +KC_MS_UP KC_MS_U Mouse Cursor Up +KC_MS_DOWN KC_MS_D Mouse Cursor Down +KC_MS_LEFT KC_MS_L Mouse Cursor Left +KC_MS_RIGHT KC_MS_R Mouse Cursor Right +KC_MS_BTN1 KC_BTN1 Mouse Button 1 +KC_MS_BTN2 KC_BTN2 Mouse Button 2 +KC_MS_BTN3 KC_BTN3 Mouse Button 3 +KC_MS_BTN4 KC_BTN4 Mouse Button 4 +KC_MS_BTN5 KC_BTN5 Mouse Button 5 +KC_MS_WH_UP KC_WH_U Mouse Wheel Up +KC_MS_WH_DOWN KC_WH_D Mouse Wheel Down +KC_MS_WH_LEFT KC_WH_L Mouse Wheel Left +KC_MS_WH_RIGHT KC_WH_R Mouse Wheel Right +KC_MS_ACCEL0 KC_ACL0 Mouse Acceleration 0 +KC_MS_ACCEL1 KC_ACL1 Mouse Acceleration 1 +KC_MS_ACCEL2 KC_ACL2 Mouse Acceleration 2 +/* Fn key */ +KC_FN0 +KC_FN1 +KC_FN2 +KC_FN3 +KC_FN4 +KC_FN5 +KC_FN6 +KC_FN7 +KC_FN8 +KC_FN9 +KC_FN10 +KC_FN11 +KC_FN12 +KC_FN13 +KC_FN14 +KC_FN15 +KC_FN16 +KC_FN17 +KC_FN18 +KC_FN19 +KC_FN20 +KC_FN21 +KC_FN22 +KC_FN23 +KC_FN24 +KC_FN25 +KC_FN26 +KC_FN27 +KC_FN28 +KC_FN29 +KC_FN30 +KC_FN31 From eea85c7e24c4ff61bff0a6db8246a19896b5b630 Mon Sep 17 00:00:00 2001 From: tmk Date: Mon, 11 Feb 2013 00:02:11 +0900 Subject: [PATCH 29/30] Fix is_tap_key() --- common/action.c | 14 +++++++------- common/action.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/action.c b/common/action.c index f6e50032e..6d5336752 100644 --- a/common/action.c +++ b/common/action.c @@ -816,18 +816,18 @@ bool is_tap_key(key_t key) case ACT_LAYER: case ACT_LAYER_BIT: switch (action.layer.code) { - case 0x00: - case 0xF1 ... 0xFF: + case LAYER_MOMENTARY: + case LAYER_ON_PRESS: + case LAYER_ON_RELEASE: + case LAYER_DEFAULT: return false; - case 0xF0: - default: + case LAYER_TAP_TOGGLE: + default: /* tap key */ return true; } return false; case ACT_FUNCTION: - if (action.func.opt & FUNC_TAP) { - return true; - } + if (action.func.opt & FUNC_TAP) { return true; } return false; } return false; diff --git a/common/action.h b/common/action.h index 800554eb8..9b559cb18 100644 --- a/common/action.h +++ b/common/action.h @@ -323,7 +323,7 @@ enum usage_pages { /* Function */ enum function_opts { - FUNC_TAP = 0x8, + FUNC_TAP = 0x8, /* indciates function is tappable */ }; #define ACTION_FUNCTION(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | id) #define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | id) From 39d093339393e1758eede06f736b1f99a68ac74c Mon Sep 17 00:00:00 2001 From: tmk Date: Mon, 11 Feb 2013 12:26:37 +0900 Subject: [PATCH 30/30] Fix and add some in README --- README.md | 130 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 115 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 90c24b031..cf09a9407 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ Keymap Many of existent projects offer keymap framework to define your own keymap easily. The following will explain how you can define keymap using this framework. Instead, you can also implement your own `keymap_get_action()` to return action code for each key if you want. -This is keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard. Keyamp is defined in `keymaps[]` array. +This is keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard. Keymap is defined in `keymaps[]` array. static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Layer 0: Default Layer @@ -279,17 +279,44 @@ This is keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Key ### 1. Keycode -See `common/keycode.h`. Keycode is 8bit internal code to inidicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like 'KC_A' have simple action register key on press and unregister on release, on the other some of keycodes has some special actions like Fn keys, Media contorl keys, System control keys and Mouse keys. +See `common/keycode.h`. Keycode is 8bit internal code to inidicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like `KC_A` have simple action register key on press and unregister on release, on the other some of keycodes has some special actions like Fn keys, Media contorl keys, System control keys and Mouse keys. ***In `KEYMAP` definition you need to omit prefix part `KC_` of keycode to keep keymap compact.*** For example, just use `A` instead you place `KC_A` in `KEYMAP`. Some keycodes has 4-letter short name in addition to descriptive name, you'll prefer short one in `KEYMAP`. - **`KC_NO`** indicates the key has no keycode to transmit. +#### 1.1 Normal key +- `KC_NO` for no aciton +- `KC_A` to `KC_Z`, `KC_1` to `KC_0` for alpha numeric key +- `KC_MINS`, `KC_EQL`, `KC_GRV`, `KC_RBRC`, `KC_LBRC`, `KC_COMM`, `KC_DOT`, `KC_BSLS`, `KC_SLSH`, `KC_SCLN`, `KC_QUOT` +- `KC_ESC`, `KC_TAB`, `KC_SPC`, `KC_BSPC`, `KC_ENT`, `KC_DEL`, `KC_INS` +- `KC_UP`, `KC_DOWN`, `KC_RGHT`, `KC_LEFT`, `KC_PGUP`, `KC_PGDN`, `KC_HOME`, `KC_END` +- `KC_CAPS`, `KC_NLCK`, `KC_SLCK`, `KC_PSCR`, `KC_PAUS`, `KC_APP`, `KC_F1` to `KC_F24` +- `KC_P1` to `KC_P0`, `KC_PDOT`, `KC_PCMM`, `KC_PSLS`, `KC_PAST`, `KC_PMNS`, `KC_PPLS`, `KC_PEQL`, `KC_PENT` for keypad. - **`KC_LGUI`** and **`KC_RGUI`** are windows key or command key in Mac. +#### 1.2 Modifier +There are 8 modifiers which has discrimination between left and right. +- `KC_LCTL` and `KC_RCTL` for Control +- `KC_LSFT` and `KC_RSFT` for Shift +- `KC_LALT` and `KC_RALT` for Alt +- `KC_LGUI` and `KC_RGUI` for Windows key or Command key in Mac + +#### 1.3 Fn key **`KC_FNnn`** are `Fn` keys which not given any action at the beginning unlike most of keycodes has its own action. To use these keys in `KEYMAP` you need to assign action you want at first. Action of `Fn` is defined in `fn_actions[]` and index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` designates action defined in first element of the array. ***32 `Fn` keys can be defined at most.*** - See [keycode table](doc/keycode.txt) in `doc/keycode.txt` or `common/keycode.h` for other keycodes. +#### 1.4 Mousekey +- `KC_MS_U`, `KC_MS_D`, `KC_MS_L`, `KC_MS_R` for mouse cursor +- `KC_WH_U`, `KC_WH_D`, `KC_WH_L`, `KC_WH_R` for mouse wheel +- `KC_BTN1`, `KC_BTN2`, `KC_BTN3`, `KC_BTN4`, `KC_BTN5` for mouse buttons + +#### 1.5 System & Media key +- `KC_PWR`, `KC_SLEP`, `KC_WAKE` for Power, Sleep, Wake +- `KC_MUTE`, `KC_VOLU`, `KC_VOLD` for audio volume control +- `KC_MNXT`, `KC_MPRV`, `KC_MSTP`, `KC_MPLY`, `KC_MSEL` for media control +- `KC_MAIL`, `KC_CALC`, `KC_MYCM` for application launch +- `KC_WSCH`, `KC_WHOM`, `KC_WBAK`, `KC_WFWD`, `KC_WSTP`, `KC_WREF`, `KC_WFAV` for web browser operation + +#### Keycode Table + See [keycode table](doc/keycode.txt) in `doc/keycode.txt` or `common/keycode.h` for the detail or other keycodes. In regard to implementation side most of keycodes are identical with [HID usage] sent to host for real and some virtual keycodes are defined to support special actions. [HID usage]: http://www.usb.org/developers/devclass_docs/Hut1_11.pdf @@ -299,22 +326,23 @@ See `common/keycode.h`. Keycode is 8bit internal code to inidicate action perfor ### 2. Action See `common/action.h`. Action is a 16bit code and defines function to perform on events of a key like press, release, hold and tap. You can define various actions to use various action codes. -Most of keys just register 8bit keycode as HID usage(or scan code) to host, but to support other complex functions needs 16bit extended action codes internally. But using 16bit action codes with keymap results in double size in memory against keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP` to define instead of action codes. ***Keycodes can be considered as subset of action codes.*** Like `KC_A`(0x04) is equal to a `Key` action(0x0004) that transmit keycode of `A`. +Most of keys just register 8bit keycode as HID usage(or scan code) to host, but to support other complex features needs 16bit extended action codes internally. But using 16bit action codes in keymap results in double size in memory against keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP` to define instead of action codes. ***Keycodes can be considered as subset of action codes.*** Like `KC_A`(0x04) is equal to a `Key` action(0x0004) that transmit keycode of *'A'*. #### 2.1 Key action Key is simple action that registers keycode on press of key and unregister on release. -You can define `Key` action on `A` with: +You can define `Key` action on *'A'* key with: ACTION_KEY(KC_A) -But you won't need to use this expression directly because you can just put symbol like `A` in `KEYMAP`. +But you don't need to use this expression directly because you can just put symbol `A` in `KEYMAP` definition. - Say you want to assign a key to `Shift + 1` to get *!* or `Alt + Tab` to switch windows. + Say you want to assign a key to `Shift + 1` to get charactor *'!'* or `Alt + Tab` to switch windows. ACTION_MOD_KEY(KC_LSHIFT, KC_1) ACTION_MOD_KEY(KC_LALT, KC_TAB) -`Alt,Shift + Tab` +Or `Alt,Shift + Tab` can be defined. + ACTION_MODS_KEY((MOD_BIT(KC_LALT) | MOD_BIT(KC_LSHIFT)), KC_TAB) These actions are comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes. @@ -344,12 +372,73 @@ These acitons change `default layer`. #### 2.3 Macro action -`Macro` action indicates complex key strokes. ***TODO*** +***NOT FIXED*** +`Macro` action indicates complex key strokes. + + MACRO( MD(LSHIFT), D(D), END ) + MACRO( U(D), MU(LSHIFT), END ) + MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END ) + +##### 2.3.1 Normal mode +- **I()** change interavl of stroke. +- **D()** press key +- **U()** release key +- **T()** type key(press and release) +- **W()** wait +- **MD()** modifier down +- **MU()** modifier up +- **END** end mark + +##### 2.3.2 Extended mode + +***TODO: sample impl*** +See `keyboard/hhkb/keymap.c` for sample. #### 2.4 Function action -`Function` action can be defined freely in C function. ***TODO*** -`Function` action is implemented in `keymap_call_function()` +***NOT FIXED*** +There are two type of action, normal `Function` and tappable `Function`. +These actions call user defined function with `id`, `opt`, and key event information as arguments. + +##### 2.4.1 Function +To define normal `Function` action in keymap use this. + + ACTION_FUNCTION(id, opt) + +##### 2.4.2 Function with tap +To define tappable `Function` action in keymap use this. + + ACTION_FUNCTION_TAP(id, opt) + +##### 2.4.3 Implement user function +`Function` actions can be defined freely with C by user in callback function: + + void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt) + +This C function is called every time key is operated, argument `id` selects action to be performed and `opt` can be used for option. Functon `id` can be 0-255 and `opt` can be 0-15. + + `keyrecord_t` is comprised of key event and tap count. `keyevent_t` indicates which and when key is pressed or released. From `tap_count` you can know tap state, 0 means no tap. These information will be used in user function to decide how action of key is performed. + + typedef struct { + keyevent_t event; + uint8_t tap_count; + } keyrecord_t; + + typedef struct { + key_t key; + bool pressed; + uint16_t time; + } keyevent_t; + + typedef struct { + uint8_t col; + uint8_t row; + } key_t; + +***TODO: sample impl*** +See `keyboard/hhkb/keymap.c` for sample. + + @@ -370,7 +459,7 @@ There are two kind of layer switch action `Layer Set` and `Layer Bit` and two ty Momentary switching changes layer only while holding Fn key. ##### 4.1.1 Momentary Set -This `Layer Set` action sets new layer(`Layer 1`) to `current layer` on key press event. +This `Layer Set` action sets new layer `Layer 1` to `current layer` on key press event. ACTION_LAYER_SET(1) @@ -379,7 +468,7 @@ It switches to destination layer immediately when key is pressed, after that act ACTION_LAYER_DEFAULT ##### 4.1.2 Momentary Bit -This `Layer Bit` action performs XOR(`1`) with `current layer` on both press and release event. If you are on `Layer 0` now next layer to switch will be `Layer 1`. To come back to previous layer you need to place same action on destination layer. +This `Layer Bit` action performs XOR `1` with `current layer` on both press and release event. If you are on `Layer 0` now next layer to switch will be `Layer 1`. To come back to previous layer you need to place same action on destination layer. ACTION_LAYER_BIT(1) @@ -499,6 +588,17 @@ Following commands can be also executed with `Magic` + key. In console mode `Mag Caps: Lock Keyboard(Child Proof) Paus: jump to bootloader +### Boot Magic +Magic commands are executed when boot time. Press `Magic` command key then pulgin. + +Define these macros in config.h. + + IS_BOOTMAGIC_DEBUG + IS_BOOTMAGIC_BOOTLOADER + +***TODO: sample impl*** +See `keyboard/hhkb/config.h` for sample. + Start Your Own Project