From 8a709c2750eab09ec0f83450410a13640931d48e Mon Sep 17 00:00:00 2001 From: tmk Date: Sun, 16 Dec 2012 02:32:07 +0900 Subject: [PATCH] Add initial fix for new keymap. --- common.mk | 1 + common/action.c | 572 ++++++++++++++++++++++++++++++++++++ common/action.h | 219 ++++++++++++++ common/host.c | 8 +- common/host.h | 4 +- common/keyboard.c | 550 +--------------------------------- common/keyboard.h | 5 +- common/keycode.h | 2 + common/keymap.h | 14 +- common/report.h | 81 +++++ keyboard/hhkb/Makefile.lufa | 3 + keyboard/hhkb/Makefile.vusb | 3 + keyboard/hhkb/keymap.c | 109 +++---- keyboard/hhkb/matrix.c | 7 + 14 files changed, 967 insertions(+), 611 deletions(-) create mode 100644 common/action.c create mode 100644 common/action.h diff --git a/common.mk b/common.mk index 66f9fd099..bd8616e5f 100644 --- a/common.mk +++ b/common.mk @@ -1,6 +1,7 @@ COMMON_DIR = common SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/keyboard.c \ + $(COMMON_DIR)/action.c \ $(COMMON_DIR)/command.c \ $(COMMON_DIR)/timer.c \ $(COMMON_DIR)/print.c \ diff --git a/common/action.c b/common/action.c new file mode 100644 index 000000000..d4aae207f --- /dev/null +++ b/common/action.c @@ -0,0 +1,572 @@ +#include "host.h" +#include "timer.h" +//#include "keymap.h" +#include "keycode.h" +#include "keyboard.h" +#include "mousekey.h" +#include "command.h" +#include "util.h" +#include "debug.h" +#include "action.h" + +#define Kdebug(s) do { if (debug_keyboard) debug(s); } while(0) +#define Kdebug_P(s) do { if (debug_keyboard) debug_P(s); } while(0) +#define Kdebug_hex(s) do { if (debug_keyboard) debug_hex(s); } while(0) + + +/* + * + * Event/State|IDLE PRESSING DELAYING[f] WAITING[f,k] + * -----------+------------------------------------------------------------------ + * Fn Down |(L+) -*1 WAITING(Sk) IDLE(Rf,Ps)*7 + * Up |(L-) IDLE(L-)*8 IDLE(L-)*8 IDLE(L-)*8 + * Fnk Down |DELAYING(Sf)* (Rf) WAITING(Sk) IDLE(Rf,Ps,Rf) + * Up |(L-) IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3 + * Key Down |PRESSING(Rk) (Rk) WAITING(Sk) IDLE(Rf,Ps,Rk) + * Up |(Uk) IDLE(Uk)*4 (Uk) IDLE(L+,Ps,Pk)/(Uk)*a + * | + * Delay |- - IDLE(L+) IDLE(L+,Ps) + * Magic Key |COMMAND*5 + * + * *1: ignore Fn if other key is down. + * *2: register Fnk if any key is pressing + * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8 + * *4: if no keys registered to host + * *5: unregister all keys + * *6: only if no keys down + * *7: ignore Fn because Fnk key and stored key are down. + * *8: move to IDLE if layer switch(off) occurs, else stay at current state + * *9: repeat key if pressing Fnk twice quickly(move to PRESSING) + * *a: layer switch and process waiting key and code if code == wainting key, else unregister key + * + * States: + * IDLE: No key is down except modifiers + * DELAYING: delay layer switch after pressing Fn with alt keycode + * WAITING: key is pressed during DELAYING + * + * Events: + * Fn: Fn key without alternative keycode + * Fnk: Fn key with alternative keycode + * -: ignore + * Delay: layer switch delay term is elapsed + * + * Actions: + * Rk: register key + * Uk: unregister key + * Rf: register Fn(alt keycode) + * Uf: unregister Fn(alt keycode) + * Rs: register stored key + * Us: unregister stored key + * Sk: Store key(waiting Key) + * Sf: Store Fn(delayed Fn) + * Ps: Process stored key + * Ps: Process key + * Is: Interpret stored keys in current layer + * L+: Switch to new layer(*unregister* all keys but modifiers) + * L-: Switch back to last layer(*unregister* all keys but modifiers) + * Ld: Switch back to default layer(*unregister* all keys but modifiers) + */ + + +typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t; +#define NEXT(state) do { \ + Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \ + kbdstate = state; \ + Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \ +} while (0) + + +static kbdstate_t kbdstate = IDLE; +static uint8_t fn_state_bits = 0; +static keyrecord_t delayed_fn = {}; +static keyrecord_t waiting_key = {}; + +static const char *state_str(kbdstate_t state) +{ + if (state == IDLE) return PSTR("IDLE"); + if (state == DELAYING) return PSTR("DELAYING"); + if (state == WAITING) return PSTR("WAITING"); + if (state == PRESSING) return PSTR("PRESSING"); + return PSTR("UNKNOWN"); +} +static bool anykey_sent_to_host(void) +{ + return (host_has_anykey() || host_mouse_in_use() || + host_last_sysytem_report() || host_last_consumer_report()); +} + + + +/* +static void layer_switch_on(uint8_t code); +static void layer_switch_off(uint8_t code); +static void key_action(uint8_t code, keyevent_t event); +static void key_pressed(uint8_t code, keyevent_t event); +static void key_released(uint8_t code, keyevent_t event); +static void mod_pressed(uint8_t code, keyevent_t event); +static void mod_released(uint8_t code, keyevent_t event); +*/ + +static void register_code(uint8_t code); +static void unregister_code(uint8_t code); +static void register_mods(uint8_t mods); +static void unregister_mods(uint8_t mods); +static void clear_keyboard(void); +static void clear_keyboard_but_mods(void); +static void layer_switch(uint8_t new_layer); + + +/* tap */ +#define TAP_TIME 200 +static keyevent_t last_event = {}; +static uint16_t last_event_time = 0; +static uint8_t tap_count = 0; + +/* layer */ +uint8_t default_layer = 0; +uint8_t current_layer = 0; +uint8_t waiting_layer = 0; + + +void action_exec(action_t action, keyevent_t event) +{ + /* count tap when key is up */ + if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event_time) < TAP_TIME) { + if (!event.pressed) tap_count++; + } else { + tap_count = 0; + } + + debug("action: "); debug_hex16(action.code); debug("\n"); + debug("kind.id: "); debug_hex(action.kind.id); debug("\n"); + debug("kind.param: "); debug_hex16(action.kind.param); debug("\n"); + debug("key.code: "); debug_hex(action.key.code); debug("\n"); + debug("key.mods: "); debug_hex(action.key.mods); debug("\n"); + + switch (action.kind.id) { + case ACT_LMODS: + if (event.pressed) { + register_mods(action.key.mods); + register_code(action.key.code); + } else { + unregister_code(action.key.code); + unregister_mods(action.key.mods); + } + break; + case ACT_RMODS: + if (event.pressed) { + register_mods(action.key.mods<<4); + register_code(action.key.code); + } else { + unregister_code(action.key.code); + unregister_mods(action.key.mods<<4); + } + break; + case ACT_LAYER: + switch (action.layer_key.code) { + case 0x00: // Momentary switch + // TODO: history of layer switch + if (event.pressed) { + layer_switch(action.layer_key.layer); + } else { + layer_switch(default_layer); + } + break; + case 0x01: // Oneshot switch + // TODO: + break; + case 0x02: // reserved + case 0x03: // reserved + break; + case 0xF0 ... 0xF7: // Tap to enable/disable + case 0xF8 ... 0xFF: // Tap to toggle layer + // TODO: + break; + default: // with keycode for tap + debug("tap: "); debug_hex(tap_count); debug("\n"); + // TODO: layer switch + // TODO: in case tap is interrupted by other key + + + if (event.pressed) { + // when any key down + if (host_has_anykey()) { + if (tap_count == 0) + register_code(action.layer_key.code); + } else { + } + + if (tap_count == 0) { + if (host_has_anykey()) { + register_code(action.layer_key.code); + } else { + waiting_layer = action.layer_key.layer; + } + } + // register key when press after a tap + if (tap_count > 0) { + register_code(action.layer_key.code); + } + } else { + // type key after tap + if (tap_count == 1) { + register_code(action.layer_key.code); + } + unregister_code(action.layer_key.code); + } + break; + } + break; + case ACT_USAGE: +#ifdef EXTRAKEY_ENABLE + switch (action.usage.page) { + case ACTION_USAGE_PAGE_SYSTEM: + if (event.pressed) { + host_system_send(action.usage.code); + } else { + host_system_send(0); + } + break; + case ACTION_USAGE_PAGE_CONSUMER: + if (event.pressed) { + host_consumer_send(action.usage.code); + } else { + host_consumer_send(0); + } + break; + } +#endif + break; + case ACT_MOUSEKEY: +#ifdef MOUSEKEY_ENABLE + if (event.pressed) { + mousekey_on(action.key.code); + mousekey_send(); + } else { + mousekey_off(action.key.code); + mousekey_send(); + } +#endif + break; + case ACT_LMOD_TAP: + case ACT_RMOD_TAP: + case ACT_MACRO: + case ACT_COMMAND: + case ACT_FUNCTION: + default: + break; + } + + /* last event */ + last_event = event; + last_event_time = timer_read(); +} + + +#if 0 +/* Key Action */ +inline +static void key_action(uint8_t code, keyevent_t event) +{ + if (event.pressed) + key_pressed(code, event); + else + key_released(code, event); +} + +void fn_action(uint8_t code, keyevent_t event) +{ +} + +/* Key */ +inline static void key_pressed(uint8_t code, keyevent_t event) +{ + uint8_t tmp_mods; + switch (kbdstate) { + case IDLE: + register_code(code); + NEXT(PRESSING); + break; + case PRESSING: + register_code(code); + break; + case DELAYING: + waiting_key = (keyrecord_t) { + .event = event, + .code = code, + .mods = keyboard_report->mods, + .time = timer_read() + }; + NEXT(WAITING); + break; + case WAITING: + // play back key stroke + tmp_mods = keyboard_report->mods; + host_set_mods(delayed_fn.mods); + register_code(delayed_fn.code); + host_set_mods(waiting_key.mods); + register_code(waiting_key.code); + host_set_mods(tmp_mods); + register_code(code); + NEXT(IDLE); + break; + } +} +inline static void key_released(uint8_t code, keyevent_t event) +{ + uint8_t tmp_mods; + switch (kbdstate) { + case IDLE: + unregister_code(code); + break; + case PRESSING: + unregister_code(code); + if (!anykey_sent_to_host()) + NEXT(IDLE); + break; + case DELAYING: + unregister_code(code); + break; + case WAITING: + if (code == waiting_key.code) { + layer_switch_on(delayed_fn.code); + NEXT(IDLE); + // process waiting_key + tmp_mods = keyboard_report->mods; + host_set_mods(waiting_key.mods); + keymap_process_event(waiting_key.event); + host_set_mods(tmp_mods); + keymap_process_event(event); + } else { + unregister_code(code); + } + break; + } +} + +/* layer switch momentary */ +inline static void layerkey_pressed(uint8_t code, keyevent_t event) +{ + uint8_t tmp_mods; + switch (kbdstate) { + case IDLE: + layer_switch_on(code); + break; + case PRESSING: + // ignore + break; + case DELAYING: + waiting_key = (keyrecord_t) { + .event = event, + .code = code, + .mods = keyboard_report->mods, + .time = timer_read() + }; + NEXT(WAITING); + break; + case WAITING: + tmp_mods = keyboard_report->mods; + host_set_mods(delayed_fn.mods); + register_code(delayed_fn.code); + host_set_mods(waiting_key.mods); + register_code(waiting_key.code); + host_set_mods(tmp_mods); + if (kind == FN_DOWN) { + // ignore Fn + } else if (kind == FNK_DOWN) { + register_code(code); + } else if (kind == KEY_DOWN) { + register_code(code); + } + NEXT(IDLE); + break; + } +} +inline static void layerkey_released(uint8_t code, keyevent_t event) +{ + switch (kbdstate) { + case IDLE: + layer_switch_off(code); + break; + case PRESSING: + case DELAYING: + case WAITING: + if (layer_switch_off(code)) + NEXT(IDLE); + break; + } +} +#endif + + +static void register_code(uint8_t code) +{ + if (code == KC_NO) { + return; + } + else if IS_KEY(code) { + // TODO: should push command_proc out of this block? + if (!command_proc(code)) { + host_add_key(code); + host_send_keyboard_report(); + } + } + else if IS_MOD(code) { + host_add_mods(MOD_BIT(code)); + host_send_keyboard_report(); + } +#ifdef MOUSEKEY_ENABLE + else if IS_MOUSEKEY(code) { + mousekey_on(code); + mousekey_send(); + } +#endif +#ifdef EXTRAKEY_ENABLE + else if IS_CONSUMER(code) { + uint16_t usage = 0; + switch (code) { + case KC_AUDIO_MUTE: + usage = AUDIO_MUTE; + break; + case KC_AUDIO_VOL_UP: + usage = AUDIO_VOL_UP; + break; + case KC_AUDIO_VOL_DOWN: + usage = AUDIO_VOL_DOWN; + break; + case KC_MEDIA_NEXT_TRACK: + usage = TRANSPORT_NEXT_TRACK; + break; + case KC_MEDIA_PREV_TRACK: + usage = TRANSPORT_PREV_TRACK; + break; + case KC_MEDIA_STOP: + usage = TRANSPORT_STOP; + break; + case KC_MEDIA_PLAY_PAUSE: + usage = TRANSPORT_PLAY_PAUSE; + break; + case KC_MEDIA_SELECT: + usage = AL_CC_CONFIG; + break; + case KC_MAIL: + usage = AL_EMAIL; + break; + case KC_CALCULATOR: + usage = AL_CALCULATOR; + break; + case KC_MY_COMPUTER: + usage = AL_LOCAL_BROWSER; + break; + case KC_WWW_SEARCH: + usage = AC_SEARCH; + break; + case KC_WWW_HOME: + usage = AC_HOME; + break; + case KC_WWW_BACK: + usage = AC_BACK; + break; + case KC_WWW_FORWARD: + usage = AC_FORWARD; + break; + case KC_WWW_STOP: + usage = AC_STOP; + break; + case KC_WWW_REFRESH: + usage = AC_REFRESH; + break; + case KC_WWW_FAVORITES: + usage = AC_BOOKMARKS; + break; + } + host_consumer_send(usage); + } + else if IS_SYSTEM(code) { + uint16_t usage = 0; + switch (code) { + case KC_SYSTEM_POWER: + usage = SYSTEM_POWER_DOWN; + break; + case KC_SYSTEM_SLEEP: + usage = SYSTEM_SLEEP; + break; + case KC_SYSTEM_WAKE: + usage = SYSTEM_WAKE_UP; + break; + } + host_system_send(usage); + } +#endif +} + +static void unregister_code(uint8_t code) +{ + if IS_KEY(code) { + host_del_key(code); + host_send_keyboard_report(); + } + else if IS_MOD(code) { + host_del_mods(MOD_BIT(code)); + host_send_keyboard_report(); + } +#ifdef MOUSEKEY_ENABLE + else if IS_MOUSEKEY(code) { + mousekey_off(code); + mousekey_send(); + } +#endif +#ifdef EXTRAKEY_ENABLE + else if IS_CONSUMER(code) { + host_consumer_send(0x0000); + } + else if IS_SYSTEM(code) { + host_system_send(0x0000); + } +#endif +} + +static void register_mods(uint8_t mods) +{ + if (!mods) return; + host_add_mods(mods); + host_send_keyboard_report(); +} + +static void unregister_mods(uint8_t mods) +{ + if (!mods) return; + host_del_mods(mods); + host_send_keyboard_report(); +} + +static void clear_keyboard(void) +{ + host_clear_mods(); + clear_keyboard_but_mods(); +} + +static void clear_keyboard_but_mods(void) +{ + host_clear_keys(); + host_send_keyboard_report(); +#ifdef MOUSEKEY_ENABLE + mousekey_clear(); + mousekey_send(); +#endif +#ifdef EXTRAKEY_ENABLE + host_system_send(0); + host_consumer_send(0); +#endif +} + +static void layer_switch(uint8_t new_layer) +{ + if (current_layer != new_layer) { + Kdebug("Layer Switch: "); Kdebug_hex(current_layer); + Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n"); + + current_layer = new_layer; + clear_keyboard_but_mods(); // To avoid stuck keys + } +} diff --git a/common/action.h b/common/action.h new file mode 100644 index 000000000..08f8c5608 --- /dev/null +++ b/common/action.h @@ -0,0 +1,219 @@ +#ifndef ACTION_H +#define ACTION_H + +#include "keyboard.h" + + +/* Key Action(16bit code) + 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +------------------------------------------------ +ACT_LMODS(0000) + 0 0 0 0| 0 0 0 0| 0 0 0 0 0 0| 0 0 No action + 0 0 0 0| 0 0 0 0| keycode(8) Key + 0 0 0 0| mods(4) | 0 0 0 0 0 0| 0 0 Lmods Momentary + 0 0 0 0| mods(4) | 0 0 0 0 0 0| 0 1 Lmods OneShot + 0 0 0 0| mods(4) | 0 0 0 0 0 0| 1 0 (reserved) + 0 0 0 0| mods(4) | 0 0 0 0 0 0| 1 1 (reserved) + 0 0 0 0| mods(4) | keycode(8) Key+Lmods +??? + 0 0 0 0| mods(4) | 1 1 1 1 0| tap(3) Lmods+tap Switch(enable/disable) + 0 0 0 0| mods(4) | 1 1 1 1 1| tap(3) Lmods+tap Toggle(on/off) +??? + +ACT_RMODS(0001) + 0 0 0 1| 0 0 0 0| 0 0 0 0 0 0 0 0 No action(not used) + 0 0 0 1| 0 0 0 0| keycode(8) Key(not used) + 0 0 0 1| mods(4) | 0 0 0 0 0 0| 0 0 Rmods Momentary + 0 0 0 1| mods(4) | 0 0 0 0 0 0| 0 1 Rmods OneShot + 0 0 0 1| mods(4) | 0 0 0 0 0 0| 1 0 (reserved) + 0 0 0 1| mods(4) | 0 0 0 0 0 0| 1 1 (reserved) + 0 0 0 1| mods(4) | keycode(8) Key+Rmod +??? + 0 0 0 1| mods(4) | 1 1 1 1 0| tap(3) Rmods+tap Switch(enable/disable) + 0 0 0 1| mods(4) | 1 1 1 1 1| tap(3) Rmods+tap Toggle(on/off) +??? + +ACT_LMODS_TAP(0010) + 0 0 1 0| 0 0 0 0| X X X X X X X X (reserved)[00-FF] + 0 0 1 0| mods(4) | 0 0 0 0 0 0| X X (reserved) + 0 0 1 0| mods(4) | keycode(8) Lmods+tap Key + 0 0 1 0| mods(4) | 1 1 1 1| X X X X (reserved)[F0-FF] + +ACT_RMODS_TAP(0011) + 0 0 1 1| 0 0 0 0| X X X X X X X X (reserved)[00-FF] + 0 0 1 1| mods(4) | 0 0 0 0 0 0| X X (reserved) + 0 0 1 1| mods(4) | keycode(8) Rmods+tap Key + 0 0 1 1| mods(4) | 1 1 1 1| X X X X (reserved)[F0-FF] + +ACT_LAYER(0100) + 0 1 0 0| layer(4) | 0 0 0 0 0 0| 0 0 Momentary + 0 1 0 0| layer(4) | 0 0 0 0 0 0| 0 1 Oneshot + 0 1 0 0| layer(4) | 0 0 0 0 0 0| 1 0 (reserved) + 0 1 0 0| layer(4) | 0 0 0 0 0 0| 1 1 (reserved) + 0 1 0 0| layer(4) | keycode(8) Fn momentary + tap Key + 0 1 0 0| layer(4) | 1 1 1 1 0| tap(3) Fn+tap Switch(enable/disable) + 0 1 0 0| layer(4) | 1 1 1 1 1| tap(3) Fn+tap Toggle(on/off) + +ACT_USAGE(0101) + 0 1 0 1| 0 0| usage(10) System usage + 0 1 0 1| 0 1| usage(10) Consumer usage + 0 1 0 1| 1 0| usage(10) (reserved) + 0 1 0 1| 1 1| usage(10) (reserved) + +ACT_MOUSEKEY(0110) + 0 1 1 0| X X X X| keycode(8) Mouse key +??? TODO: refactor + 0 1 1 0| 0 0 X X| accel(5) |cursor(3) Mouse key + 0 1 1 0| 0 1 X X| accel(5) |wheel(3) Mouse key + 0 1 1 0| 1 0 X X| button(8) Mouse key + 0 1 1 0| 1 1 X X| button(8) Mouse key +??? + + 0 1 1 1| (reserved) + 1 0 0 0| (reserved) + 1 0 0 1| (reserved) + 1 0 1 0| (reserved) + 1 0 1 1| (reserved) + 1 1 0 0| (reserved) + +ACT_MACRO(1100) + 1 1 0 0| option(4) | macro-table id(8) Macro play(Flash) + 1 1 0 0| option(4) | macro-table id(8) Macro play(EEPROM) + 1 1 0 0| 1 1 1 1| macro-table id(8) Macro record + +ACT_COMMAND(1110) + 1 1 1 0| option(4) | comamnd id(8) Built-in Command exec + +ACT_FUNCTION(1111) + 1 1 1 1| function address(4K range) Function + Macro record(dynamicly) + Macro play(dynamicly) +*/ + +enum action_id { + ACT_LMODS = 0, + ACT_RMODS, + ACT_LMOD_TAP, + ACT_RMOD_TAP, + ACT_LAYER, + ACT_USAGE, + ACT_MOUSEKEY, + ACT_MACRO = 14, + ACT_COMMAND = 15, + ACT_FUNCTION = 16 +}; + +// TODO: not portable across compiler/endianness? +/* +In avr-gcc bit fields seems to be assigned from LSB(bit0) to MSB(bit15). +AVR seems like little endian in avr-gcc. + +Byte order and bit order of 0x1234: +Big endian: 15 ... 8 7 ... 210 + | 0x12 | 0x34 | + 0001 0010 0011 0100 +Little endian: 012 ... 7 8 ... 15 + | 0x34 | 0x12 | + 0010 1100 0100 1000 +*/ +typedef union { + uint16_t code; + struct action_kind { + uint16_t param :12; + uint16_t id :4; + } kind; + struct action_key { + uint16_t code :8; + uint16_t mods :4; + uint16_t kind :4; + } key; + struct action_layer_key { + uint16_t code :8; + uint16_t layer :4; + uint16_t kind :4; + } layer_key; + struct action_layer_tap { + uint16_t count :3; + uint16_t rest :5; + uint16_t layer :4; + uint16_t kind :4; + } layer_tap; + struct action_usage { + uint16_t code :10; + uint16_t page :2; + uint16_t kind :4; + } usage; + struct action_command { + uint16_t id :8; + uint16_t option :4; + uint16_t kind :4; + } command; +} action_t; + + +enum stroke_cmd { + STROKE_DOWN, + STROKE_UP, + STROKE_ALLUP, /* release all keys in reverse order */ +}; + +void action_exec(action_t act, keyevent_t event); +/* +void key_action(uint8_t code, keyevent_t event); +void mod_action(uint8_t code, keyevent_t event); +void fn_action(uint8_t code, keyevent_t event); +*/ + + +/* action_t utility */ +#define ACTION(kind, param) { .code = ((kind)<<12 | (param)) } +#define NO_ACTION ACTION(0, 0) +#define LAYER_PARAM(layer, key) ((layer)<<8|(key)) + +/* Key & Mods */ +#define ACTION_KEY(key) ACTION(ACT_LMODS, key) +#define ACTION_LMODS(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x00) +#define ACTION_LMODS_KEY(mods, key) ACTION(ACT_LMODS, (mods)<<8 | (key)) +#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x01) +#define ACTION_LMODS_SWITCH(mods, tap) ACTION(ACT_LMODS, (mods)<<8 | 0xF0 | (tap)) +#define ACTION_LMODS_TOGGLE(mods, tap) ACTION(ACT_LMODS, (mods)<<8 | 0xF1 | (tap)) +#define ACTION_RMODS(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x00) +#define ACTION_RMODS_KEY(mods, key) ACTION(ACT_RMODS, (mods)<<8 | (key)) +#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x01) +#define ACTION_RMODS_SWITCH(mods, tap) ACTION(ACT_RMODS, (mods)<<8 | 0xF0 | (tap)) +#define ACTION_RMODS_TOGGLE(mods, tap) ACTION(ACT_RMODS, (mods)<<8 | 0xF1 | (tap)) +/* Mods + Tap key */ +#define ACTION_LMODS_TAP(mods, key) ACTION(ACT_LMODS_TAP,(mods)<<8 | (key)) +#define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP,(mods)<<8 | (key)) +/* Layer Switch */ +#define ACTION_LAYER(layer) ACTION(ACT_LAYER, (layer)<<8 | 0x00) +#define ACTION_LAYER_ONESHOT(layer) ACTION(ACT_LAYER, (layer)<<8 | 0x01) +#define ACTION_LAYER_KEY(layer, key) ACTION(ACT_LAYER, (layer)<<8 | (key)) +#define ACTION_LAYER_SWITCH(layer, tap) ACTION(ACT_LAYER, (layer)<<8 | 0xF0 | (tap)) +#define ACTION_LAYER_TOGGLE(layer, tap) ACTION(ACT_LAYER, (layer)<<8 | 0xF1 | (tap)) +/* HID Usage */ +#define ACTION_USAGE_PAGE_SYSTEM 0 +#define ACTION_USAGE_PAGE_CONSUMER 1 +#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_SYSTEM<<10 | (id)) +#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_CONSUMER<<10 | (id)) +/* Mousekey */ +#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key) +/* Macro */ +#define ACTION_MACRO(opt, id) ACTION(ACT_FUNCTION, (opt)<<8 | (addr)) +/* Command */ +#define ACTION_COMMAND(opt, id) ACTION(ACT_COMMAND, (opt)<<8 | (addr)) +/* Function */ +#define ACTION_FUNCTION(addr) ACTION(ACT_FUNCTION, addr) + + +/* helpers for readability */ +#define LAYER(layer) (layer) +#define TAP(tap) (tap) +#define DOUBLE_TAP 2 +#define TRIPLE_TAP 3 +#define QUADRUPLE_TAP 4 +#define QUINTUPLE_TAP 5 +#define DOWN(key) (key) +#define UP(key) STROKE_UP, (key) + +#endif /* ACTION_H */ diff --git a/common/host.c b/common/host.c index 261ec6472..28c8a819f 100644 --- a/common/host.c +++ b/common/host.c @@ -127,14 +127,14 @@ void host_clear_keys(void) } } -void host_add_mod_bit(uint8_t mod) +void host_add_mods(uint8_t mods) { - keyboard_report->mods |= mod; + keyboard_report->mods |= mods; } -void host_del_mod_bit(uint8_t mod) +void host_del_mods(uint8_t mods) { - keyboard_report->mods &= ~mod; + keyboard_report->mods &= ~mods; } void host_set_mods(uint8_t mods) diff --git a/common/host.h b/common/host.h index 207b68310..4f1f234a9 100644 --- a/common/host.h +++ b/common/host.h @@ -51,8 +51,8 @@ void host_consumer_send(uint16_t data); void host_add_key(uint8_t key); void host_del_key(uint8_t key); void host_clear_keys(void); -void host_add_mod_bit(uint8_t mod); -void host_del_mod_bit(uint8_t mod); +void host_add_mods(uint8_t mods); +void host_del_mods(uint8_t mods); void host_set_mods(uint8_t mods); void host_clear_mods(void); uint8_t host_has_anykey(void); diff --git a/common/keyboard.c b/common/keyboard.c index fa22116f1..5e95fb984 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -31,517 +31,6 @@ along with this program. If not, see . #endif -#define Kdebug(s) do { if (debug_keyboard) debug(s); } while(0) -#define Kdebug_P(s) do { if (debug_keyboard) debug_P(s); } while(0) -#define Kdebug_hex(s) do { if (debug_keyboard) debug_hex(s); } while(0) - -#define LAYER_DELAY 250 - -typedef enum keykind { - NONE, - FN_DOWN, FN_UP, - FNK_DOWN, FNK_UP, - KEY_DOWN, KEY_UP, - MOD_DOWN, MOD_UP, -} keykind_t; - -typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t; - - -#ifdef KEYMAP_DEFAULT_LAYER -uint8_t default_layer = KEYMAP_DEFAULT_LAYER; -uint8_t current_layer = KEYMAP_DEFAULT_LAYER; -#else -uint8_t default_layer = 0; -uint8_t current_layer = 0; -#endif - -/* keyboard internal states */ -static kbdstate_t kbdstate = IDLE; -static uint8_t fn_state_bits = 0; -static keyrecord_t delayed_fn; -static keyrecord_t waiting_key; - - -static const char *state_str(kbdstate_t state) -{ - if (state == IDLE) return PSTR("IDLE"); - if (state == DELAYING) return PSTR("DELAYING"); - if (state == WAITING) return PSTR("WAITING"); - if (state == PRESSING) return PSTR("PRESSING"); - return PSTR("UNKNOWN"); -} - -static inline keykind_t get_keykind(uint8_t code, bool pressed) -{ - if IS_KEY(code) return (pressed ? KEY_DOWN : KEY_UP); - if IS_MOD(code) return (pressed ? MOD_DOWN : MOD_UP); - if IS_FN(code) { - if (keymap_fn_keycode(FN_INDEX(code))) - return (pressed ? FNK_DOWN : FNK_UP); - else - return (pressed ? FN_DOWN : FN_UP); - } - if IS_MOUSEKEY(code) return (pressed ? KEY_DOWN : KEY_UP); - if IS_SYSTEM(code) return (pressed ? KEY_DOWN : KEY_UP); - if IS_CONSUMER(code) return (pressed ? KEY_DOWN : KEY_UP); - return NONE; -} - -static void clear_keyboard(void) -{ - host_clear_keys(); - host_clear_mods(); - host_send_keyboard_report(); - - host_system_send(0); - host_consumer_send(0); - -#ifdef MOUSEKEY_ENABLE - mousekey_clear(); - mousekey_send(); -#endif -} - -static void clear_keyboard_but_mods(void) -{ - host_clear_keys(); - host_send_keyboard_report(); - - host_system_send(0); - host_consumer_send(0); - -#ifdef MOUSEKEY_ENABLE - mousekey_clear(); - mousekey_send(); -#endif -} - -static bool anykey_sent_to_host(void) -{ - return (host_has_anykey() || host_mouse_in_use() || - host_last_sysytem_report() || host_last_consumer_report()); -} - -static void layer_switch_on(uint8_t code) -{ - if (!IS_FN(code)) return; - fn_state_bits |= FN_BIT(code); - uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer); - if (current_layer != new_layer) { - Kdebug("Layer Switch(on): "); Kdebug_hex(current_layer); - Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n"); - - clear_keyboard_but_mods(); - current_layer = new_layer; - } -} - -static bool layer_switch_off(uint8_t code) -{ - if (!IS_FN(code)) return false; - fn_state_bits &= ~FN_BIT(code); - uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer); - if (current_layer != new_layer) { - Kdebug("Layer Switch(off): "); Kdebug_hex(current_layer); - Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n"); - - clear_keyboard_but_mods(); - current_layer = new_layer; - return true; - } - return false; -} - -static void register_code(uint8_t code) -{ - if IS_KEY(code) { - if (!command_proc(code)) { - host_add_key(code); - host_send_keyboard_report(); - } - } - else if IS_MOD(code) { - host_add_mod_bit(MOD_BIT(code)); - host_send_keyboard_report(); - } - else if IS_FN(code) { - if (!command_proc(keymap_fn_keycode(FN_INDEX(code)))) { - host_add_key(keymap_fn_keycode(FN_INDEX(code))); - host_send_keyboard_report(); - } - } - else if IS_MOUSEKEY(code) { -#ifdef MOUSEKEY_ENABLE - mousekey_on(code); - mousekey_send(); -#endif - } - else if IS_CONSUMER(code) { - uint16_t usage = 0; - switch (code) { - case KC_AUDIO_MUTE: - usage = AUDIO_MUTE; - break; - case KC_AUDIO_VOL_UP: - usage = AUDIO_VOL_UP; - break; - case KC_AUDIO_VOL_DOWN: - usage = AUDIO_VOL_DOWN; - break; - case KC_MEDIA_NEXT_TRACK: - usage = TRANSPORT_NEXT_TRACK; - break; - case KC_MEDIA_PREV_TRACK: - usage = TRANSPORT_PREV_TRACK; - break; - case KC_MEDIA_STOP: - usage = TRANSPORT_STOP; - break; - case KC_MEDIA_PLAY_PAUSE: - usage = TRANSPORT_PLAY_PAUSE; - break; - case KC_MEDIA_SELECT: - usage = AL_CC_CONFIG; - break; - case KC_MAIL: - usage = AL_EMAIL; - break; - case KC_CALCULATOR: - usage = AL_CALCULATOR; - break; - case KC_MY_COMPUTER: - usage = AL_LOCAL_BROWSER; - break; - case KC_WWW_SEARCH: - usage = AC_SEARCH; - break; - case KC_WWW_HOME: - usage = AC_HOME; - break; - case KC_WWW_BACK: - usage = AC_BACK; - break; - case KC_WWW_FORWARD: - usage = AC_FORWARD; - break; - case KC_WWW_STOP: - usage = AC_STOP; - break; - case KC_WWW_REFRESH: - usage = AC_REFRESH; - break; - case KC_WWW_FAVORITES: - usage = AC_BOOKMARKS; - break; - } - host_consumer_send(usage); - } - else if IS_SYSTEM(code) { - uint16_t usage = 0; - switch (code) { - case KC_SYSTEM_POWER: - usage = SYSTEM_POWER_DOWN; - break; - case KC_SYSTEM_SLEEP: - usage = SYSTEM_SLEEP; - break; - case KC_SYSTEM_WAKE: - usage = SYSTEM_WAKE_UP; - break; - } - host_system_send(usage); - } - -} - -static void unregister_code(uint8_t code) -{ - if IS_KEY(code) { - host_del_key(code); - host_send_keyboard_report(); - } - else if IS_MOD(code) { - host_del_mod_bit(MOD_BIT(code)); - host_send_keyboard_report(); - } - else if IS_FN(code) { - host_del_key(keymap_fn_keycode(FN_INDEX(code))); - host_send_keyboard_report(); - } - else if IS_MOUSEKEY(code) { -#ifdef MOUSEKEY_ENABLE - mousekey_off(code); - mousekey_send(); -#endif - } - else if IS_CONSUMER(code) { - host_consumer_send(0x0000); - } - else if IS_SYSTEM(code) { - host_system_send(0x0000); - } -} - -/* - * - * Event/State|IDLE PRESSING DELAYING[f] WAITING[f,k] - * -----------+------------------------------------------------------------------ - * Fn Down |(L+) -*1 WAITING(Sk) IDLE(Rf,Ps)*7 - * Up |(L-) IDLE(L-)*8 IDLE(L-)*8 IDLE(L-)*8 - * Fnk Down |DELAYING(Sf)* (Rf) WAITING(Sk) IDLE(Rf,Ps,Rf) - * Up |(L-) IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3 - * Key Down |PRESSING(Rk) (Rk) WAITING(Sk) IDLE(Rf,Ps,Rk) - * Up |(Uk) IDLE(Uk)*4 (Uk) IDLE(L+,Ps,Pk)/(Uk)*a - * | - * Delay |- - IDLE(L+) IDLE(L+,Ps) - * Magic Key |COMMAND*5 - * - * *1: ignore Fn if other key is down. - * *2: register Fnk if any key is pressing - * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8 - * *4: if no keys registered to host - * *5: unregister all keys - * *6: only if no keys down - * *7: ignore Fn because Fnk key and stored key are down. - * *8: move to IDLE if layer switch(off) occurs, else stay at current state - * *9: repeat key if pressing Fnk twice quickly(move to PRESSING) - * *a: layer switch and process waiting key and code if code == wainting key, else unregister key - * - * States: - * IDLE: No key is down except modifiers - * DELAYING: delay layer switch after pressing Fn with alt keycode - * WAITING: key is pressed during DELAYING - * - * Events: - * Fn: Fn key without alternative keycode - * Fnk: Fn key with alternative keycode - * -: ignore - * Delay: layer switch delay term is elapsed - * - * Actions: - * Rk: register key - * Uk: unregister key - * Rf: register Fn(alt keycode) - * Uf: unregister Fn(alt keycode) - * Rs: register stored key - * Us: unregister stored key - * Sk: Store key(waiting Key) - * Sf: Store Fn(delayed Fn) - * Ps: Process stored key - * Ps: Process key - * Is: Interpret stored keys in current layer - * L+: Switch to new layer(*unregister* all keys but modifiers) - * L-: Switch back to last layer(*unregister* all keys but modifiers) - * Ld: Switch back to default layer(*unregister* all keys but modifiers) - */ -#define NEXT(state) do { \ - Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \ - kbdstate = state; \ - Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \ -} while (0) - -static inline void process_key(keyevent_t event) -{ - uint8_t code = keymap_get_keycode(current_layer, event.key.row, event.key.col); - keykind_t kind = get_keykind(code, event.pressed); - - uint8_t tmp_mods; - - Kdebug("state: "); Kdebug_P(state_str(kbdstate)); - Kdebug(" kind: "); Kdebug_hex(kind); - Kdebug(" code: "); Kdebug_hex(code); - if (event.pressed) { Kdebug("d"); } else { Kdebug("u"); } - Kdebug("\n"); - - switch (kbdstate) { - case IDLE: - switch (kind) { - case FN_DOWN: - layer_switch_on(code); - break; - case FN_UP: - layer_switch_off(code); - break; - case FNK_DOWN: - // repeat Fn alt key when press Fn key down, up then down again quickly - if (KEYEQ(delayed_fn.event.key, event.key) && - timer_elapsed(delayed_fn.time) < LAYER_DELAY) { - register_code(code); - NEXT(PRESSING); - } else { - delayed_fn = (keyrecord_t) { - .event = event, - .code = code, - .mods = keyboard_report->mods, - .time = timer_read() - }; - NEXT(DELAYING); - } - break; - case FNK_UP: - layer_switch_off(code); - break; - case KEY_DOWN: - register_code(code); - NEXT(PRESSING); - break; - case MOD_DOWN: - register_code(code); - break; - case KEY_UP: - case MOD_UP: - unregister_code(code); - break; - default: - break; - } - break; - case PRESSING: - switch (kind) { - case FN_DOWN: - // ignored when any key is pressed - break; - case FN_UP: - if (layer_switch_off(code)) - NEXT(IDLE); - break; - case FNK_DOWN: - register_code(code); - break; - case FNK_UP: - if (layer_switch_off(code)) { - NEXT(IDLE); - } else { - unregister_code(code); - if (!anykey_sent_to_host()) - NEXT(IDLE); - } - break; - case KEY_DOWN: - case MOD_DOWN: - register_code(code); - break; - case KEY_UP: - case MOD_UP: - unregister_code(code); - if (!anykey_sent_to_host()) - NEXT(IDLE); - break; - default: - break; - } - break; - case DELAYING: - switch (kind) { - case FN_DOWN: - case FNK_DOWN: - case KEY_DOWN: - waiting_key = (keyrecord_t) { - .event = event, - .code = code, - .mods = keyboard_report->mods, - .time = timer_read() - }; - NEXT(WAITING); - break; - case MOD_DOWN: - register_code(code); - break; - case FN_UP: - if (layer_switch_off(code)) - NEXT(IDLE); - break; - case FNK_UP: - if (code == delayed_fn.code) { - // type Fn with alt keycode - // restore the mod status at the time of pressing Fn key - tmp_mods = keyboard_report->mods; - host_set_mods(delayed_fn.mods); - register_code(delayed_fn.code); - unregister_code(delayed_fn.code); - host_set_mods(tmp_mods); - NEXT(IDLE); - } else { - if (layer_switch_off(code)) - NEXT(IDLE); - } - break; - case KEY_UP: - case MOD_UP: - unregister_code(code); - break; - default: - break; - } - break; - case WAITING: - switch (kind) { - case FN_DOWN: - case FNK_DOWN: - case KEY_DOWN: - tmp_mods = keyboard_report->mods; - host_set_mods(delayed_fn.mods); - register_code(delayed_fn.code); - host_set_mods(waiting_key.mods); - register_code(waiting_key.code); - host_set_mods(tmp_mods); - if (kind == FN_DOWN) { - // ignore Fn - } else if (kind == FNK_DOWN) { - register_code(code); - } else if (kind == KEY_DOWN) { - register_code(code); - } - NEXT(IDLE); - break; - case MOD_DOWN: - register_code(code); - break; - case FN_UP: - if (layer_switch_off(code)) - NEXT(IDLE); - break; - case FNK_UP: - if (code == delayed_fn.code) { - // alt down, key down, alt up - tmp_mods = keyboard_report->mods; - host_set_mods(delayed_fn.mods); - register_code(delayed_fn.code); - host_set_mods(waiting_key.mods); - register_code(waiting_key.code); - unregister_code(delayed_fn.code); - host_set_mods(tmp_mods); - NEXT(IDLE); - } else { - if (layer_switch_off(code)) - NEXT(IDLE); - } - break; - case KEY_UP: - if (code == waiting_key.code) { - layer_switch_on(delayed_fn.code); - NEXT(IDLE); - // process waiting_key - tmp_mods = keyboard_report->mods; - host_set_mods(waiting_key.mods); - process_key(waiting_key.event); - host_set_mods(tmp_mods); - process_key(event); - } else { - unregister_code(code); - } - break; - case MOD_UP: - unregister_code(code); - break; - default: - break; - } - break; - } -} - void keyboard_init(void) { // TODO: to enable debug print magic key bind on boot time @@ -556,6 +45,10 @@ void keyboard_init(void) #endif } +/* + * Do keyboard routine jobs: scan mantrix, light LEDs, ... + * This is repeatedly called as fast as possible. + */ void keyboard_task(void) { static matrix_row_t matrix_prev[MATRIX_ROWS]; @@ -572,8 +65,8 @@ void keyboard_task(void) for (int c = 0; c < MATRIX_COLS; c++) { if (matrix_change & (1< LAYER_DELAY) { - if (kbdstate == DELAYING) { - layer_switch_on(delayed_fn.code); - NEXT(IDLE); - } - if (kbdstate == WAITING) { - layer_switch_on(delayed_fn.code); - NEXT(IDLE); - uint8_t tmp_mods = keyboard_report->mods; - host_set_mods(waiting_key.mods); - process_key(waiting_key.event); - host_set_mods(tmp_mods); - } - } - } - #ifdef MOUSEKEY_ENABLE // mousekey repeat & acceleration mousekey_task(); #endif - // FAIL SAFE: clear all key if no key down - if (matrix_change) { - matrix_row_t is_matrix_on = 0; - for (int r = 0; r < MATRIX_ROWS; r++) { - is_matrix_on |= matrix_get_row(r); - } - if (!is_matrix_on) { - Kdebug("FAIL SAFE: clear all keys(default layer).\n"); - clear_keyboard(); - current_layer = default_layer; - } - } - // update LED if (led_status != host_keyboard_leds()) { led_status = host_keyboard_leds(); diff --git a/common/keyboard.h b/common/keyboard.h index 2353805e1..37df6a4de 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -29,10 +29,10 @@ extern "C" { typedef struct { uint8_t row; uint8_t col; -} key_t; +} keypos_t; typedef struct { - key_t key; + keypos_t key; bool pressed; } keyevent_t; @@ -45,7 +45,6 @@ typedef struct { #define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col) - extern uint8_t current_layer; extern uint8_t default_layer; diff --git a/common/keycode.h b/common/keycode.h index f9331cdbf..2eec2af85 100644 --- a/common/keycode.h +++ b/common/keycode.h @@ -43,6 +43,8 @@ along with this program. If not, see . #define MOD_INDEX(code) ((code) & 0x07) #define FN_BIT(code) (1<. #include #include +#include "action.h" - -/* keycode in specific layer */ +/* + * legacy keymap interface: keycode + */ uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col); - /* layer to move during press Fn key */ uint8_t keymap_fn_layer(uint8_t fn_bits); - /* keycode to send when release Fn key without using */ uint8_t keymap_fn_keycode(uint8_t fn_bits); +/* + * new keymap interface: action + */ +action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col); +uint8_t keymap_process_event(keyevent_t event); + #endif diff --git a/common/report.h b/common/report.h index a73e0aba1..e8582d81f 100644 --- a/common/report.h +++ b/common/report.h @@ -19,6 +19,7 @@ along with this program. If not, see . #define REPORT_H #include +#include /* report id */ @@ -97,6 +98,86 @@ typedef struct { int8_t h; } __attribute__ ((packed)) report_mouse_t; + +static uint16_t key2system(uint8_t key) +{ + uint16_t usage = 0; + switch (key) { + case KC_SYSTEM_POWER: + usage = SYSTEM_POWER_DOWN; + break; + case KC_SYSTEM_SLEEP: + usage = SYSTEM_SLEEP; + break; + case KC_SYSTEM_WAKE: + usage = SYSTEM_WAKE_UP; + break; + } + return usage; +} + +static uint16_t key2consumer(uint8_t key) +{ + uint16_t usage = 0; + switch (key) { + case KC_AUDIO_MUTE: + usage = AUDIO_MUTE; + break; + case KC_AUDIO_VOL_UP: + usage = AUDIO_VOL_UP; + break; + case KC_AUDIO_VOL_DOWN: + usage = AUDIO_VOL_DOWN; + break; + case KC_MEDIA_NEXT_TRACK: + usage = TRANSPORT_NEXT_TRACK; + break; + case KC_MEDIA_PREV_TRACK: + usage = TRANSPORT_PREV_TRACK; + break; + case KC_MEDIA_STOP: + usage = TRANSPORT_STOP; + break; + case KC_MEDIA_PLAY_PAUSE: + usage = TRANSPORT_PLAY_PAUSE; + break; + case KC_MEDIA_SELECT: + usage = AL_CC_CONFIG; + break; + case KC_MAIL: + usage = AL_EMAIL; + break; + case KC_CALCULATOR: + usage = AL_CALCULATOR; + break; + case KC_MY_COMPUTER: + usage = AL_LOCAL_BROWSER; + break; + case KC_WWW_SEARCH: + usage = AC_SEARCH; + break; + case KC_WWW_HOME: + usage = AC_HOME; + break; + case KC_WWW_BACK: + usage = AC_BACK; + break; + case KC_WWW_FORWARD: + usage = AC_FORWARD; + break; + case KC_WWW_STOP: + usage = AC_STOP; + break; + case KC_WWW_REFRESH: + usage = AC_REFRESH; + break; + case KC_WWW_FAVORITES: + usage = AC_BOOKMARKS; + break; + } + return usage; +} + #ifdef __cplusplus } #endif diff --git a/keyboard/hhkb/Makefile.lufa b/keyboard/hhkb/Makefile.lufa index 5acc93a23..afd413d01 100644 --- a/keyboard/hhkb/Makefile.lufa +++ b/keyboard/hhkb/Makefile.lufa @@ -121,3 +121,6 @@ VPATH += $(TOP_DIR) include $(TOP_DIR)/protocol/lufa.mk include $(TOP_DIR)/common.mk include $(TOP_DIR)/rules.mk + +debug-on: EXTRAFLAGS += -DDEBUG +debug-on: all diff --git a/keyboard/hhkb/Makefile.vusb b/keyboard/hhkb/Makefile.vusb index 8caf23497..0e0e4a8cd 100644 --- a/keyboard/hhkb/Makefile.vusb +++ b/keyboard/hhkb/Makefile.vusb @@ -89,3 +89,6 @@ VPATH += $(TOP_DIR) include $(TOP_DIR)/protocol/vusb.mk include $(TOP_DIR)/common.mk include $(TOP_DIR)/rules.mk + +debug-on: EXTRAFLAGS += -DDEBUG +debug-on: all diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c index 5dc5582ec..382996ec7 100644 --- a/keyboard/hhkb/keymap.c +++ b/keyboard/hhkb/keymap.c @@ -26,6 +26,7 @@ along with this program. If not, see . #include "print.h" #include "debug.h" #include "util.h" +#include "action.h" #include "keymap.h" @@ -49,33 +50,18 @@ along with this program. If not, see . { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO } \ } -#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) - -// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. -static const uint8_t PROGMEM fn_layer[] = { - 0, // Fn0 - 1, // Fn1 - 2, // Fn2 - 3, // Fn3 - 3, // Fn4 - 5, // Fn5 - 0, // Fn6 - 0 // Fn7 +static const action_t PROGMEM fn_actions[] = { + ACTION_LAYER(0), // Fn0 + ACTION_LAYER(1), // Fn1 + ACTION_LAYER_KEY(2, KC_SLASH), // Fn2 + ACTION_LAYER_KEY(3, KC_SCLN), // Fn3 + ACTION_LAYER(3), // Fn3 + ACTION_LAYER_KEY(5, KC_SPC), // Fn5 + NO_ACTION, // Fn6 + NO_ACTION, // Fn7 }; -// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. -// See layer.c for details. -static const uint8_t PROGMEM fn_keycode[] = { - KC_NO, // Fn0 - KC_NO, // Fn1 - KC_SLSH, // Fn2 - KC_SCLN, // Fn3 - KC_NO, // Fn4 - KC_SPC, // Fn5 - KC_NO, // Fn6 - KC_NO // Fn7 -}; static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Layer 0: Default Layer @@ -149,24 +135,11 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * `--------------------------------------------' * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel */ -#ifdef HOST_IWRAP -// iWRAP does not support mouse wheel, use these keycodes to remap as wheel -#define KC_KPPL KC_KP_PLUS -#define KC_KPMI KC_KP_MINUS -#define KC_KPAS KC_KP_ASTERISK -#define KC_KPSL KC_KP_SLASH - KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ - TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ - LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ - LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,NO, NO, NO, RSFT,NO, \ - LGUI,LALT, BTN1, RALT,FN4), -#else KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ LGUI,LALT, BTN1, RALT,FN4), -#endif /* Layer 4: Matias half keyboard style (Space) * ,-----------------------------------------------------------. @@ -188,33 +161,61 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { LGUI,LALT, FN5, RALT,RGUI), /* Layer5: another Mouse mode (Space) */ -#ifdef HOST_IWRAP - KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ - TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ - LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ - LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ - LGUI,LALT, FN5, RALT,RGUI), -#else KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ LGUI,LALT, FN5, RALT,RGUI), -#endif }; +#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) -uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) -{ - return KEYCODE(layer, row, col); + +/* legacy interface */ +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) { return 0; } +uint8_t keymap_fn_layer(uint8_t fn_bits) { return 0; } +uint8_t keymap_fn_keycode(uint8_t fn_bits) { return 0; } + + +action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) { + /* convert from legacy keycode to action */ + uint8_t key = KEYCODE(layer, row, col); + action_t action; + switch (key) { + case KC_A ... KC_EXSEL: + action = (action_t)ACTION_KEY(key); + break; + case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE: + action = (action_t)ACTION_USAGE_SYSTEM(key2system(key)); + break; + case KC_AUDIO_MUTE ... KC_WWW_FAVORITES: + action = (action_t)ACTION_USAGE_CONSUMER(key2consumer(key)); + break; + case KC_MS_UP ... KC_MS_ACCEL2: + action = (action_t)ACTION_MOUSEKEY(key); + break; + case KC_LCTRL ... KC_LGUI: + action = (action_t)ACTION_LMODS(MOD_BIT(key)); + break; + case KC_RCTRL ... KC_RGUI: + action = (action_t)ACTION_RMODS(MOD_BIT(key)>>4); + break; + case KC_FN0 ... KC_FN7: + action = (action_t)pgm_read_word(&fn_actions[FN_INDEX(key)]); + break; + case KC_NO ... KC_UNDEFINED: + default: + action = (action_t)NO_ACTION; + break; + } + debug("action: "); debug_hex16(action.code); debug("\n"); + return action; } -uint8_t keymap_fn_layer(uint8_t index) -{ - return pgm_read_byte(&fn_layer[index]); -} -uint8_t keymap_fn_keycode(uint8_t index) +uint8_t keymap_process_event(keyevent_t event) { - return pgm_read_byte(&fn_keycode[index]); + action_t action = keymap_get_action(current_layer, event.key.row, event.key.col); + action_exec(action, event); + return 0; } diff --git a/keyboard/hhkb/matrix.c b/keyboard/hhkb/matrix.c index fd0d6f97f..f53e36dbe 100644 --- a/keyboard/hhkb/matrix.c +++ b/keyboard/hhkb/matrix.c @@ -24,6 +24,7 @@ along with this program. If not, see . #include #include #include "print.h" +#include "debug.h" #include "util.h" #include "timer.h" #include "matrix.h" @@ -135,6 +136,12 @@ uint8_t matrix_cols(void) void matrix_init(void) { +#ifdef DEBUG + print_enable = true; + debug_enable = true; + debug_keyboard = true; +#endif + KEY_INIT(); // initialize matrix state: all keys off