diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/action.c | 572 | ||||
-rw-r--r-- | common/action.h | 219 | ||||
-rw-r--r-- | common/host.c | 8 | ||||
-rw-r--r-- | common/host.h | 4 | ||||
-rw-r--r-- | common/keyboard.c | 550 | ||||
-rw-r--r-- | common/keyboard.h | 5 | ||||
-rw-r--r-- | common/keycode.h | 2 | ||||
-rw-r--r-- | common/keymap.h | 14 | ||||
-rw-r--r-- | common/report.h | 81 |
9 files changed, 898 insertions, 557 deletions
diff --git a/common/action.c b/common/action.c new file mode 100644 index 0000000000..d4aae207f4 --- /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 0000000000..08f8c5608c --- /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 261ec6472f..28c8a819fd 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 207b683100..4f1f234a96 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 fa22116f17..5e95fb9845 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -31,517 +31,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #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; - |