X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=common%2Fkeyboard.c;h=9a809ff4a153dbfca52f1a248cb9e001e26cfd06;hb=1f96edaed60def1f513ddd8adcdfa3e12b971006;hp=9f0c27670efbd1d132e44361df60916e005d828c;hpb=4ae979f6ef8dbf9e1d1f35be15322ad6d02e2958;p=tmk_firmware.git diff --git a/common/keyboard.c b/common/keyboard.c old mode 100755 new mode 100644 index 9f0c276..9a809ff --- a/common/keyboard.c +++ b/common/keyboard.c @@ -1,5 +1,5 @@ /* -Copyright 2011 Jun Wako +Copyright 2011,2012,2013 Jun Wako This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,466 +14,126 @@ 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 "keyboard.h" #include "matrix.h" #include "keymap.h" #include "host.h" #include "led.h" -#include "usb_keycodes.h" +#include "keycode.h" #include "timer.h" #include "print.h" #include "debug.h" #include "command.h" #include "util.h" +#include "sendchar.h" +#include "bootmagic.h" +#include "eeconfig.h" +#include "backlight.h" #ifdef MOUSEKEY_ENABLE -#include "mousekey.h" +# include "mousekey.h" #endif -#ifdef EXTRAKEY_ENABLE -#include +#ifdef PS2_MOUSE_ENABLE +# include "ps2_mouse.h" #endif -#define LAYER_DELAY 250 - -typedef enum keykind { - NONE, - FN_DOWN, FN_UP, - FNK_DOWN, FNK_UP, - KEY_DOWN, KEY_UP, - MOD_DOWN, MOD_UP, - MOUSEKEY_DOWN, MOUSEKEY_UP, - DELAY -} keykind_t; - -typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t; - - -uint8_t current_layer = 0; -uint8_t default_layer = 0; - -/* 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 ? MOUSEKEY_DOWN : MOUSEKEY_UP); - return NONE; -} - -static void layer_switch_on(uint8_t code) -{ - if (!IS_FN(code)) return; - fn_state_bits |= FN_BIT(code); - if (current_layer != keymap_fn_layer(FN_INDEX(code))) { - //TODO: clear all key execpt Mod key - debug("Layer Switch(on): "); debug_hex(current_layer); - current_layer = keymap_fn_layer(FN_INDEX(code)); - debug(" -> "); debug_hex(current_layer); debug("\n"); - } -} - -static void layer_switch_off(uint8_t code) +#ifdef MATRIX_HAS_GHOST +static bool has_ghost_in_row(uint8_t row) { - if (!IS_FN(code)) return; - fn_state_bits &= ~FN_BIT(code); - if (current_layer != keymap_fn_layer(biton(fn_state_bits))) { - //TODO: clear all key execpt Mod key - debug("Layer Switch(off): "); debug_hex(current_layer); - current_layer = keymap_fn_layer(biton(fn_state_bits)); - debug(" -> "); debug_hex(current_layer); debug("\n"); - } -} - -static inline uint8_t get_keycode(key_t key) -{ - return keymap_get_keycode(current_layer, key.row, key.col); -} - -// whether any key except modifier is down or not -static inline bool is_anykey_down(void) -{ - for (int r = 0; r < MATRIX_ROWS; r++) { - matrix_row_t matrix_row = matrix_get_row(r); - for (int c = 0; c < MATRIX_COLS; c++) { - if (matrix_row && (1< "); print_P(state_str(kbdstate)); debug("\n"); \ -} while (0) - -static inline void process_key(keyevent_t event) -{ - - /* TODO: ring buffer - static keyrecord_t waiting_keys[5]; - static uint8_t waiting_keys_head = 0; - static uint8_t waiting_keys_tail = 0; - */ - - uint8_t code = get_keycode(event.key); - keykind_t kind = get_keykind(code, event.pressed); - - uint8_t tmp_mods; - - //debug("kbdstate: "); debug_hex(kbdstate); - debug("state: "); print_P(state_str(kbdstate)); - debug(" kind: "); debug_hex(kind); - debug(" code: "); debug_hex(code); - if (event.pressed) { debug("d"); } else { debug("u"); } - debug("\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: - // store event - 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: - case MOUSEKEY_DOWN: - register_code(code); - NEXT(PRESSING); - break; - case MOD_DOWN: - register_code(code); - break; - case KEY_UP: - case MOUSEKEY_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: - layer_switch_off(code); - NEXT(IDLE); - break; - case FNK_DOWN: - register_code(keymap_fn_keycode(FN_INDEX(code))); - break; - case FNK_UP: - unregister_code(keymap_fn_keycode(FN_INDEX(code))); - break; - case KEY_DOWN: - case MOD_DOWN: - case MOUSEKEY_DOWN: - register_code(code); - break; - case KEY_UP: - case MOD_UP: - case MOUSEKEY_UP: - unregister_code(code); - // no key registered? mousekey, mediakey, systemkey - if (!host_has_anykey()) - NEXT(IDLE); - break; - default: - break; - } - break; - case DELAYING: - switch (kind) { - case FN_DOWN: - case FNK_DOWN: - case KEY_DOWN: - case MOUSEKEY_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: - 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(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); - unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); - host_set_mods(tmp_mods); - NEXT(IDLE); - } else { - layer_switch_off(code); - NEXT(IDLE); - } - break; - case KEY_UP: - case MOUSEKEY_UP: - unregister_code(code); - NEXT(IDLE); - break; - case MOD_UP: - unregister_code(code); - break; - default: - break; - } - break; - case WAITING: - switch (kind) { - case FN_DOWN: - case FNK_DOWN: - case KEY_DOWN: - case MOUSEKEY_DOWN: - tmp_mods = keyboard_report->mods; - host_set_mods(delayed_fn.mods); - register_code(keymap_fn_keycode(FN_INDEX(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; - case MOD_DOWN: - register_code(code); - break; - case FN_UP: - 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(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); - host_set_mods(waiting_key.mods); - register_code(waiting_key.code); - unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); - host_set_mods(tmp_mods); - NEXT(IDLE); - } else { - layer_switch_off(code); - NEXT(IDLE); - } - break; - case KEY_UP: - case MOUSEKEY_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; - } - - // TODO: FAIL SAFE: unregister all keys when no key down -} void keyboard_init(void) { - debug_keyboard = true; - timer_init(); matrix_init(); #ifdef PS2_MOUSE_ENABLE ps2_mouse_init(); #endif + +#ifdef BOOTMAGIC_ENABLE + bootmagic(); +#endif + +#ifdef BACKLIGHT_ENABLE + backlight_init(); +#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]; + static uint8_t led_status = 0; matrix_row_t matrix_row = 0; matrix_row_t matrix_change = 0; matrix_scan(); - if (command_proc()) { - debug("COMMAND\n"); - // TODO: clear all keys - host_clear_keyboard_report(); - host_send_keyboard_report(); - return; - } - 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) { - // TODO: print once per scan if (debug_matrix) matrix_print(); - - 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); - } - } - } +MATRIX_LOOP_END: +#ifdef MOUSEKEY_ENABLE // mousekey repeat & acceleration mousekey_task(); +#endif - return; +#ifdef PS2_MOUSE_ENABLE + ps2_mouse_task(); +#endif + + // update LED + if (led_status != host_keyboard_leds()) { + led_status = host_keyboard_leds(); + keyboard_set_leds(led_status); + } } void keyboard_set_leds(uint8_t leds) { + if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); } led_set(leds); }