From 770cfcff992b6dfb56cfe42a897f0332ab455166 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 +++++++ 10 files changed, 899 insertions(+), 557 deletions(-) create mode 100644 common/action.c create mode 100644 common/action.h diff --git a/common.mk b/common.mk index 66f9fd09..bd8616e5 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 00000000..d4aae207 --- /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 00000000..08f8c560 --- /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 261ec647..28c8a819 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 207b6831..4f1f234a 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 fa22116f..5e95fb98 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 2353805e..37df6a4d 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 f9331cdb..2eec2af8 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 a73e0aba..e8582d81 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 From 38a8012defd64a9654ce946ad123cc61008d6031 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 ++++++++++++++---------------------------------- 2 files changed, 35 insertions(+), 181 deletions(-) diff --git a/common/action.c b/common/action.c index d4aae207..45e2276e 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 e8582d81..0995189b 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 } From 93078aad219f2eea083ee196ba5bf0bf0eb41302 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 - 5 files changed, 283 insertions(+), 279 deletions(-) diff --git a/common/action.c b/common/action.c index 45e2276e..425a2b00 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 08f8c560..942ce191 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 5e95fb98..1e0b8c3e 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< 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 +- 4 files changed, 146 insertions(+), 31 deletions(-) diff --git a/common/action.c b/common/action.c index 425a2b00..1a86f16d 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 28c8a819..6ed3d780 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 4f1f234a..c59fbfee 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 1e0b8c3e..4e955e12 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< 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 +- 3 files changed, 90 insertions(+), 150 deletions(-) diff --git a/common/action.c b/common/action.c index 1a86f16d..389fc5df 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 4e955e12..2e32e91e 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 11665366..cf85b123 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; From a295aa6aa9f942671600bdf1ada117ad4a4310bf 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 ++++++++++++++--------------- 2 files changed, 231 insertions(+), 169 deletions(-) diff --git a/common/action.c b/common/action.c index 389fc5df..7299a874 100644 --- a/common/action.c +++ b/common/action.c @@ -10,11 +10,12 @@ #include "action.h" - - static void process(keyevent_t event, action_t action); static void register_code(uint8_t code); static void unregister_code(uint8_t code); +static void add_mods(uint8_t mods); +static void del_mods(uint8_t mods); +static void set_mods(uint8_t mods); static void clear_keyboard(void); static void clear_keyboard_but_mods(void); static bool sending_anykey(void); @@ -24,7 +25,6 @@ static void layer_switch(uint8_t new_layer); /* tap */ #define TAP_TIME 200 static keyevent_t last_event = {}; -static uint16_t last_event_time = 0; static uint8_t tap_count = 0; /* layer */ @@ -32,6 +32,7 @@ uint8_t default_layer = 0; uint8_t current_layer = 0; keyrecord_t delaying_layer = {}; +/* waiting keys buffer */ #define WAITING_KEYS_BUFFER 3 static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {}; static uint8_t waiting_keys_head = 0; @@ -75,16 +76,87 @@ static void waiting_keys_process_in_current_layer(void) } +void action_exec(keyevent_t event) +{ + /* When delaying layer switch */ + if (delaying_layer.action.code) { + /* Layer switch when tap time elapses or waiting key is released */ + if ((timer_elapsed(delaying_layer.event.time) > TAP_TIME) || + (!event.pressed && waiting_keys_has(event.key))) { + /* layer switch */ + switch (delaying_layer.action.kind.id) { + case ACT_LAYER_PRESSED: + layer_switch(delaying_layer.action.layer.opt); + break; + case ACT_LAYER_BIT: + layer_switch(current_layer | delaying_layer.action.layer.opt); + break; + } + delaying_layer = (keyrecord_t){}; + + /* Process waiting keys in new layer */ + waiting_keys_process_in_current_layer(); + } + /* when delaying layer key is released within delay term */ + else if (!event.pressed && KEYEQ(event.key, delaying_layer.event.key)) { + /* tap key down */ + debug("tap[delaying_layer](register): fist\n"); + uint8_t tmp_mods = host_get_mods(); + host_set_mods(delaying_layer.mods); + register_code(delaying_layer.action.layer.code); + delaying_layer = (keyrecord_t){}; + host_set_mods(tmp_mods); + + /* process waiting keys */ + waiting_keys_process_in_current_layer(); + } + } + + // not real event. event just to update delaying layer. + if (IS_NOEVENT(event)) { + return; + } + + /* count tap when key is up */ + if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) { + if (!event.pressed) tap_count++; + } else { + tap_count = 0; + } + + action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); + + // TODO: all key events(pressed, released) should be recorded? + /* postpone key-down events while delaying layer */ + if (delaying_layer.action.code) { + if (event.pressed) { + waiting_keys_enqueue(event, action); + } else { + process(event, action); + } + } else { + process(event, action); + } + + /* last event */ + last_event = event; +} + + static void process(keyevent_t event, action_t action) { //action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); - debug("action: "); debug_hex16(action.code); debug("\n"); - + debug("action: "); debug_hex16(action.code); + if (event.pressed) debug("[down]\n"); else debug("[up]\n"); switch (action.kind.id) { /* Key and Mods */ case ACT_LMODS: - // normal key or key plus mods + // |pressed |released + // --------------+---------------------------------+------------ + // key |down(key) |up(key) + // mods |add(mods) |del(mods) + // key with mods |add(mods), down(key), unset(mods)|up(key) if (event.pressed) { uint8_t tmp_mods = host_get_mods(); if (action.key.mods) { @@ -105,6 +177,11 @@ static void process(keyevent_t event, action_t action) } break; case ACT_RMODS: + // |pressed |released + // --------------+---------------------------------+------------ + // key |down(key) |up(key) + // mods |add(mods) |del(mods) + // key with mods |add(mods), down(key), unset(mods)|up(key) if (event.pressed) { uint8_t tmp_mods = host_get_mods(); if (action.key.mods) { @@ -124,9 +201,49 @@ static void process(keyevent_t event, action_t action) unregister_code(action.key.code); } break; - case ACT_LMOD_TAP: + case ACT_LMODS_TAP: + if (event.pressed) { + if (tap_count == 0) { + add_mods(action.key.mods); + } else { + debug("tap[lmods](register): "); debug_hex(tap_count); debug("\n"); + register_code(action.key.code); + } + } else { + if (tap_count == 0) { + del_mods(action.key.mods); + } else if (tap_count == 1) { + debug("tap[lmods](register/unregister): "); debug_hex(tap_count); debug("\n"); + del_mods(action.key.mods); + register_code(action.key.code); + unregister_code(action.key.code); + } else { + debug("tap[lmods](unregister): "); debug_hex(tap_count); debug("\n"); + unregister_code(action.key.code); + } + } break; - case ACT_RMOD_TAP: + case ACT_RMODS_TAP: + if (event.pressed) { + if (tap_count == 0) { + add_mods(action.key.mods<<4); + } else { + debug("tap[rmods](register): "); debug_hex(tap_count); debug("\n"); + register_code(action.key.code); + } + } else { + if (tap_count == 0) { + del_mods(action.key.mods<<4); + } else if (tap_count == 1) { + debug("tap[rmods](register/unregister): "); debug_hex(tap_count); debug("\n"); + del_mods(action.key.mods<<4); + register_code(action.key.code); + unregister_code(action.key.code); + } else { + debug("tap[rmods](unregister): "); debug_hex(tap_count); debug("\n"); + unregister_code(action.key.code); + } + } break; /* other HID usage */ @@ -186,6 +303,7 @@ static void process(keyevent_t event, action_t action) // with tap key if (event.pressed) { if (tap_count == 0) { + // not tapping yet if (host_has_anykey()) { register_code(action.layer.code); } else { @@ -197,22 +315,14 @@ static void process(keyevent_t event, action_t action) }; } } else if (tap_count > 0) { - debug("tap: "); debug_hex(tap_count); debug("\n"); + // pressed after tapping + debug("tap[layer](register): "); debug_hex(tap_count); debug("\n"); register_code(action.layer.code); } } else { - // tap key - if (KEYEQ(event.key, delaying_layer.event.key) && - timer_elapsed(delaying_layer.event.time) <= TAP_TIME) { - uint8_t tmp_mods = host_get_mods(); - host_set_mods(delaying_layer.mods); - register_code(delaying_layer.action.layer.code); - host_set_mods(tmp_mods); - unregister_code(delaying_layer.action.layer.code); - } else { - unregister_code(action.layer.code); - } - delaying_layer = (keyrecord_t){}; + // released after tapping + debug("tap[layer](unregister): "); debug_hex(tap_count); debug("\n"); + unregister_code(action.layer.code); } break; } @@ -220,7 +330,7 @@ static void process(keyevent_t event, action_t action) case ACT_LAYER_RELEASED: switch (action.layer.code) { case 0x00: - if (event.pressed) { + if (!event.pressed) { layer_switch(action.layer.opt); } break; @@ -274,7 +384,7 @@ static void process(keyevent_t event, action_t action) }; } } else if (tap_count > 0) { - debug("tap: "); debug_hex(tap_count); debug("\n"); + debug("tap[layer_bit](register): "); debug_hex(tap_count); debug("\n"); register_code(action.layer.code); } } else { @@ -348,77 +458,6 @@ static void process(keyevent_t event, action_t action) } } -void action_exec(keyevent_t event) -{ -/* - debug("key["); debug_hex8(event.key.row); debug(":"); debug_hex8(event.key.col); - if (event.pressed) debug("]down\n"); else debug("]up\n"); -*/ - - /* When delaying layer switch */ - if (delaying_layer.action.code) { - /* Layer switch when tap time elapses or waiting key is released */ - if ((timer_elapsed(delaying_layer.event.time) > TAP_TIME) || - (!event.pressed && waiting_keys_has(event.key))) { - /* layer switch */ - switch (delaying_layer.action.kind.id) { - case ACT_LAYER_PRESSED: - layer_switch(delaying_layer.action.layer.opt); - break; - case ACT_LAYER_BIT: - layer_switch(current_layer | delaying_layer.action.layer.opt); - break; - } - delaying_layer = (keyrecord_t){}; - - /* Process waiting keys in new layer */ - waiting_keys_process_in_current_layer(); - } - /* when delaying layer key is released within delay term */ - else if (!event.pressed && KEYEQ(event.key, delaying_layer.event.key)) { - /* tap key down */ - uint8_t tmp_mods = host_get_mods(); - host_set_mods(delaying_layer.mods); - register_code(delaying_layer.action.layer.code); - delaying_layer = (keyrecord_t){}; - host_set_mods(tmp_mods); - - /* process waiting keys */ - waiting_keys_process_in_current_layer(); - } - } - - // not real event. event just to update delaying layer. - if (IS_NOEVENT(event)) { - return; - } - - /* count tap when key is up */ - if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) { - if (!event.pressed) tap_count++; - } else { - tap_count = 0; - } - - action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); - - // TODO: all key events(pressed, released) should be recorded? - /* postpone key-down events while delaying layer */ - if (delaying_layer.action.code) { - if (event.pressed) { - waiting_keys_enqueue(event, action); - } else { - process(event, action); - } - } else { - process(event, action); - } - - /* last event */ - last_event = event; -} - - static void register_code(uint8_t code) { if (code == KC_NO) { @@ -449,6 +488,28 @@ static void unregister_code(uint8_t code) } } +static void add_mods(uint8_t mods) +{ + if (mods) { + host_add_mods(mods); + host_send_keyboard_report(); + } +} + +static void del_mods(uint8_t mods) +{ + if (mods) { + host_del_mods(mods); + host_send_keyboard_report(); + } +} + +static void set_mods(uint8_t mods) +{ + host_set_mods(mods); + host_send_keyboard_report(); +} + static void clear_keyboard(void) { host_clear_mods(); diff --git a/common/action.h b/common/action.h index 942ce191..3115c67f 100644 --- a/common/action.h +++ b/common/action.h @@ -5,55 +5,57 @@ /* Key Action(16bit code) - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ------------------------------------------------- -ACT_LMODS(0000) - 0 0 0 0| 0 0 0 0| 0 0 0 0 0 0| 0 0 No action - 0 0 0 0| 0 0 0 0| keycode(8) Key - 0 0 0 0| mods(4) | 0 0 0 0 0 0| 0 0 Lmods Momentary - 0 0 0 0| mods(4) | 0 0 0 0 0 0| 0 1 Lmods OneShot - 0 0 0 0| mods(4) | 0 0 0 0 0 0| 1 0 (reserved) - 0 0 0 0| mods(4) | 0 0 0 0 0 0| 1 1 (reserved) - 0 0 0 0| mods(4) | keycode(8) Key+Lmods -ACT_RMODS(0001) - 0 0 0 1| 0 0 0 0| 0 0 0 0 0 0 0 0 No action(not used) - 0 0 0 1| 0 0 0 0| keycode(8) Key(not used) - 0 0 0 1| mods(4) | 0 0 0 0 0 0| 0 0 Rmods Momentary - 0 0 0 1| mods(4) | 0 0 0 0 0 0| 0 1 Rmods OneShot - 0 0 0 1| mods(4) | 0 0 0 0 0 0| 1 0 (reserved) - 0 0 0 1| mods(4) | 0 0 0 0 0 0| 1 1 (reserved) - 0 0 0 1| mods(4) | keycode(8) Key+Rmod +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) From c773478b3c819b21213273c1303dbdb7d2577bb9 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 7299a874..d5040479 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 cf85b123..907ee1f9 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 37c7b143ec7864ea653697dbc9ed59b6685c4377 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 d5040479..d0103830 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 2e32e91e..ea4d0ee7 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 c05e188e73b389527cd9f369d9bffbb314088159 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 d0103830..3a504a45 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 4518cddd..4a3ee85a 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 a2bacd10effab7c225d619c7d738bc62f9cc04c2 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 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/common/keyboard.c b/common/keyboard.c index ea4d0ee7..9f0ca767 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 From bab803d80ce126cb0494f558e62cf439d96b91c6 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 +- 4 files changed, 166 insertions(+), 67 deletions(-) diff --git a/common/action.c b/common/action.c index 3a504a45..88f8186c 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 3115c67f..9aa1d78e 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 9f0ca767..6677e801 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 4a3ee85a..6d06c95b 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 \ } From 78fd0fa6b31eb2275359b1ae21549103f918a125 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 6677e801..1aff81f5 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 88f8186c..81593154 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 9aa1d78e..327a009e 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 1aff81f5..2422fb75 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 81593154..db31613b 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 8d9bb5b10365c531cb0a8cc91c1935f319b6dba2 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 2eec2af8..cdd1e975 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 +++++++++++++++++++++++------------------------ 2 files changed, 227 insertions(+), 172 deletions(-) diff --git a/common/action.c b/common/action.c index db31613b..22f0bf0a 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 327a009e..1b5b30d8 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 */ From 1dbf26940e944ae24d9608b3d182beab3cfd8479 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 ++++---- 2 files changed, 141 insertions(+), 47 deletions(-) diff --git a/common/action.c b/common/action.c index 22f0bf0a..4b3b1dd6 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 1b5b30d8..bdd2d2f5 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 From 3b8abfb0c3324d49b1189d7b168b69ba0214ff3d 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 + 7 files changed, 221 insertions(+), 200 deletions(-) diff --git a/common.mk b/common.mk index bd8616e5..7cdaa5f7 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 4b3b1dd6..fb06e463 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 bdd2d2f5..ed3fff6c 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 a06e6a00..8ca16b91 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 2422fb75..5e9945ba 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 f992be18..f54fea90 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 */ From 7a02f1fc56d8b51bd6f3f394fb67c72892697faa 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 fb06e463..e93a9afe 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 648f0e09..e63d46f0 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 d8a899b4..08d211f2 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 e93a9afe..28d9a95f 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 88e185d69bc9e6b01354825e4d97236412aab8a7 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 28d9a95f..eb8fc2ce 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 ed3fff6c..8600e406 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 d3f8f0691c3eb7e5d87c73fc47b3c4e71a62bacb 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 eb8fc2ce..4838ea06 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 52efc71624b9d76e8125f07663a86b4b24bd6159 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 4838ea06..d1f493fe 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 8600e406..d6530df4 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 cdd1e975..341f2316 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 00000000..41512130 --- /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 f54fea90..74876155 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 4f274d125f468348d5aaba7a383a4e184c52de8f 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 +++++--- 5 files changed, 54 insertions(+), 50 deletions(-) diff --git a/common/action.c b/common/action.c index d1f493fe..cb44e272 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 d6530df4..b657aa54 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 32c1bf46..e1cab311 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 41512130..40d20f68 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 74876155..e0fafeaf 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 */ From 390cdf0c8ec613535c80c2f7ca6c7cbd81732ee6 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 +- 7 files changed, 191 insertions(+), 15 deletions(-) create mode 100644 common/action_macro.c create mode 100644 common/action_macro.h diff --git a/common.mk b/common.mk index 7cdaa5f7..86518f03 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 cb44e272..301a9b6a 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 b657aa54..b1e958a2 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 00000000..72859c0d --- /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 00000000..3833c7c8 --- /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 40d20f68..8302c270 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 e0fafeaf..30d73f79 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 From 2c27bc5876b637d7a50c029c4d8b42f90117488d 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 ++++++++++++++++++++++----------------- 2 files changed, 150 insertions(+), 249 deletions(-) diff --git a/common/action.c b/common/action.c index 301a9b6a..f6e50032 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 b1e958a2..800554eb 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 */ From 44d8bcb4621ec1e4028f22eb5e5e69193a2d91ec 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 65fc72f5..807129c3 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 a934e6c9fd4ac740f1c0b300d4e26cbcfc688bb7 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 807129c3..90c24b03 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 341f2316..4f57a588 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 00000000..41375669 --- /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 c67eb72c6b811f67a6f52a5f260d92d720708838 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 f6e50032..6d533675 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 800554eb..9b559cb1 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 0e86f6030bc2b9b2d20b5f512872555c9ec00988 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 90c24b03..cf09a940 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