summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2012-10-06 02:23:12 +0900
committertmk <nobody@nowhere>2012-10-17 15:55:37 +0900
commit4ae979f6ef8dbf9e1d1f35be15322ad6d02e2958 (patch)
tree9f5132005c27ef04ae793b77d4699cb285479466
parent93e33fb8f694c9685accd72ed0458a2cf3d3f04a (diff)
Initial version of new code for layer switch is added.
-rw-r--r--common.mk1
-rw-r--r--common/command.c2
-rw-r--r--common/host.c22
-rw-r--r--common/host.h4
-rwxr-xr-x[-rw-r--r--]common/keyboard.c543
-rwxr-xr-x[-rw-r--r--]common/keyboard.h28
-rw-r--r--common/layer.c207
-rw-r--r--common/layer.h32
-rw-r--r--common/matrix.h21
-rw-r--r--common/mousekey.c120
-rw-r--r--common/mousekey.h7
-rw-r--r--common/timer.c1
-rw-r--r--common/usb_keycodes.h5
-rw-r--r--common/util.c16
-rw-r--r--common/util.h4
-rw-r--r--keyboard/hhkb/config.h2
-rw-r--r--keyboard/hhkb/keymap.c8
-rw-r--r--keyboard/hhkb/matrix.c50
-rw-r--r--protocol/lufa/lufa.c2
19 files changed, 586 insertions, 489 deletions
diff --git a/common.mk b/common.mk
index 26b4bb8596..66f9fd0999 100644
--- a/common.mk
+++ b/common.mk
@@ -2,7 +2,6 @@ COMMON_DIR = common
SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/keyboard.c \
$(COMMON_DIR)/command.c \
- $(COMMON_DIR)/layer.c \
$(COMMON_DIR)/timer.c \
$(COMMON_DIR)/print.c \
$(COMMON_DIR)/debug.c \
diff --git a/common/command.c b/common/command.c
index 13d37242d9..0020d8a17c 100644
--- a/common/command.c
+++ b/common/command.c
@@ -23,7 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "debug.h"
#include "util.h"
#include "timer.h"
-#include "layer.h"
+#include "keyboard.h"
#include "matrix.h"
#include "bootloader.h"
#include "command.h"
diff --git a/common/host.c b/common/host.c
index 8dd2abbee8..fddd5b6627 100644
--- a/common/host.c
+++ b/common/host.c
@@ -56,6 +56,19 @@ uint8_t host_keyboard_leds(void)
return (*driver->keyboard_leds)();
}
+/* new interface */
+void host_register_key(uint8_t key)
+{
+ host_add_key(key);
+ host_send_keyboard_report();
+}
+
+void host_unregister_key(uint8_t key)
+{
+ host_del_key(key);
+ host_send_keyboard_report();
+}
+
/* keyboard report operations */
void host_add_key(uint8_t key)
{
@@ -158,6 +171,14 @@ void host_send_keyboard_report(void)
{
if (!driver) return;
(*driver->send_keyboard)(keyboard_report);
+
+ if (debug_keyboard) {
+ print("keys: ");
+ for (int i = 0; i < REPORT_KEYS; i++) {
+ phex(keyboard_report->keys[i]); print(" ");
+ }
+ print(" mods: "); phex(keyboard_report->mods); print("\n");
+ }
}
void host_mouse_send(report_mouse_t *report)
@@ -216,7 +237,6 @@ static inline void del_key_byte(uint8_t code)
for (; i < REPORT_KEYS; i++) {
if (keyboard_report->keys[i] == code) {
keyboard_report->keys[i] = 0;
- break;
}
}
}
diff --git a/common/host.h b/common/host.h
index 26bf3c362f..84a6c24773 100644
--- a/common/host.h
+++ b/common/host.h
@@ -39,6 +39,10 @@ void host_set_driver(host_driver_t *driver);
host_driver_t *host_get_driver(void);
uint8_t host_keyboard_leds(void);
+/* new interface */
+void host_register_key(uint8_t key);
+void host_unregister_key(uint8_t key);
+
/* keyboard report operations */
void host_add_key(uint8_t key);
void host_del_key(uint8_t key);
diff --git a/common/keyboard.c b/common/keyboard.c
index 25f32eb02f..9f0c27670e 100644..100755
--- a/common/keyboard.c
+++ b/common/keyboard.c
@@ -15,15 +15,16 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "keyboard.h"
-#include "host.h"
-#include "layer.h"
#include "matrix.h"
+#include "keymap.h"
+#include "host.h"
#include "led.h"
#include "usb_keycodes.h"
#include "timer.h"
#include "print.h"
#include "debug.h"
#include "command.h"
+#include "util.h"
#ifdef MOUSEKEY_ENABLE
#include "mousekey.h"
#endif
@@ -32,162 +33,444 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
-static uint8_t last_leds = 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,
+ MOUSEKEY_DOWN, MOUSEKEY_UP,
+ DELAY
+} keykind_t;
-void keyboard_init(void)
+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)
{
- timer_init();
- matrix_init();
-#ifdef PS2_MOUSE_ENABLE
- ps2_mouse_init();
-#endif
+ 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");
}
-void keyboard_proc(void)
+static inline keykind_t get_keykind(uint8_t code, bool pressed)
{
- uint8_t fn_bits = 0;
-#ifdef EXTRAKEY_ENABLE
- uint16_t consumer_code = 0;
- uint16_t system_code = 0;
-#endif
-
- matrix_scan();
+ 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;
+}
- if (matrix_is_modified()) {
- if (debug_matrix) matrix_print();
-#ifdef DEBUG_LED
- // LED flash for debug
- DEBUG_LED_CONFIG;
- DEBUG_LED_ON;
-#endif
+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");
}
+}
- if (matrix_has_ghost()) {
- // should send error?
- debug("matrix has ghost!!\n");
- return;
+static void layer_switch_off(uint8_t code)
+{
+ 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");
}
+}
- host_swap_keyboard_report();
- host_clear_keyboard_report();
- for (int row = 0; row < matrix_rows(); row++) {
- for (int col = 0; col < matrix_cols(); col++) {
- if (!matrix_is_on(row, col)) continue;
-
- uint8_t code = layer_get_keycode(row, col);
- if (code == KB_NO) {
- // do nothing
- } else if (IS_MOD(code)) {
- host_add_mod_bit(MOD_BIT(code));
- } else if (IS_FN(code)) {
- fn_bits |= FN_BIT(code);
- }
-// TODO: use table or something
-#ifdef EXTRAKEY_ENABLE
- // System Control
- else if (code == KB_SYSTEM_POWER) {
-#ifdef HOST_PJRC
- if (suspend && remote_wakeup) {
- usb_remote_wakeup();
+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<<c)) {
+ if (IS_KEY(get_keycode((key_t){ .row = r, .col = c }))) {
+ return true;
}
-#endif
- system_code = SYSTEM_POWER_DOWN;
- } else if (code == KB_SYSTEM_SLEEP) {
- system_code = SYSTEM_SLEEP;
- } else if (code == KB_SYSTEM_WAKE) {
- system_code = SYSTEM_WAKE_UP;
- }
- // Consumer Page
- else if (code == KB_AUDIO_MUTE) {
- consumer_code = AUDIO_MUTE;
- } else if (code == KB_AUDIO_VOL_UP) {
- consumer_code = AUDIO_VOL_UP;
- } else if (code == KB_AUDIO_VOL_DOWN) {
- consumer_code = AUDIO_VOL_DOWN;
}
- else if (code == KB_MEDIA_NEXT_TRACK) {
- consumer_code = TRANSPORT_NEXT_TRACK;
- } else if (code == KB_MEDIA_PREV_TRACK) {
- consumer_code = TRANSPORT_PREV_TRACK;
- } else if (code == KB_MEDIA_STOP) {
- consumer_code = TRANSPORT_STOP;
- } else if (code == KB_MEDIA_PLAY_PAUSE) {
- consumer_code = TRANSPORT_PLAY_PAUSE;
- } else if (code == KB_MEDIA_SELECT) {
- consumer_code = AL_CC_CONFIG;
- }
- else if (code == KB_MAIL) {
- consumer_code = AL_EMAIL;
- } else if (code == KB_CALCULATOR) {
- consumer_code = AL_CALCULATOR;
- } else if (code == KB_MY_COMPUTER) {
- consumer_code = AL_LOCAL_BROWSER;
- }
- else if (code == KB_WWW_SEARCH) {
- consumer_code = AC_SEARCH;
- } else if (code == KB_WWW_HOME) {
- consumer_code = AC_HOME;
- } else if (code == KB_WWW_BACK) {
- consumer_code = AC_BACK;
- } else if (code == KB_WWW_FORWARD) {
- consumer_code = AC_FORWARD;
- } else if (code == KB_WWW_STOP) {
- consumer_code = AC_STOP;
- } else if (code == KB_WWW_REFRESH) {
- consumer_code = AC_REFRESH;
- } else if (code == KB_WWW_FAVORITES) {
- consumer_code = AC_BOOKMARKS;
+ }
+ }
+ return false;
+}
+
+static void register_code(uint8_t code)
+{
+ if IS_KEY(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_MOUSEKEY(code) {
+ mousekey_on(code);
+ mousekey_send();
+ }
+}
+
+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_MOUSEKEY(code) {
+ mousekey_off(code);
+ mousekey_send();
+ }
+}
+
+/*
+ *
+ * Event/State|IDLE DELAYING[f] WAITING[f,k] PRESSING
+ * -----------+------------------------------------------------------------------
+ * Fn Down |IDLE(L+) WAITING(Sk) WAITING(Sk) -
+ * Up |IDLE(L-) IDLE(L-) IDLE(L-) IDLE(L-)
+ * Fnk Down |DELAYING(Sf) WAITING(Sk) WAINTING(Sk) PRESSING(Rf)
+ * Up |IDLE(L-) IDLE(Rf,Uf) IDLE(Rf,Ps,Uf)*3 PRESSING(Uf)
+ * Key Down |PRESSING(Rk) WAITING(Sk) WAITING(Sk) PRESSING(Rk)
+ * Up |IDLE(Uk) DELAYING(Uk) IDLE(L+,Ps,Uk) IDLE(Uk)*4
+ * Delay |- IDLE(L+) IDLE(L+,Ps) -
+ * |
+ * No key Down|IDLE(Ld) IDLE(Ld) IDLE(Ld) IDLE(Ld)
+ *
+ * *2: register Fnk if any key is pressing
+ * *3: when Fnk == Stored Fnk, if not ignore.
+ * *4: when no registered key any more
+ *
+ * States:
+ * IDLE:
+ * 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
+ *
+ * Actions:
+ * Rk: register key
+ * Uk: unregister key
+ * Rf: register stored Fn(alt keycode)
+ * Uf: unregister stored Fn(alt keycode)
+ * Rs: register stored key
+ * Us: unregister stored key
+ * Sk: store key
+ * Sf: store Fn
+ * Ps: play stored key(Interpret stored key and transit state)
+ * L+: Switch to new layer(*retain* Modifiers only)
+ * L-: Switch back to last layer(*clear* stored key/Fn, *unregister* all Modifier/key)
+ * Ld: Switch back to default layer(*clear* stored key/Fn, *unregister* all Modifier/key)
+ */
+#define NEXT(state) do { \
+ debug("NEXT: "); print_P(state_str(kbdstate)); \
+ kbdstate = state; \
+ debug(" -> "); 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;
}
-#endif
- else if (IS_KEY(code)) {
- host_add_key(code);
+ 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;
}
-#ifdef MOUSEKEY_ENABLE
- else if (IS_MOUSEKEY(code)) {
- mousekey_decode(code);
+ 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;
}
-#endif
- else {
- debug("ignore keycode: "); debug_hex(code); debug("\n");
+ 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;
}
- layer_switching(fn_bits);
+ // 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
+}
+
+void keyboard_task(void)
+{
+ static matrix_row_t matrix_prev[MATRIX_ROWS];
+ 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++) {
+ 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();
- // TODO: should send only when changed from last report
- if (matrix_is_modified()) {
- host_send_keyboard_report();
-#ifdef EXTRAKEY_ENABLE
- host_consumer_send(consumer_code);
- host_system_send(system_code);
-#endif
-#ifdef DEBUG_LED
- // LED flash for debug
- DEBUG_LED_CONFIG;
- DEBUG_LED_OFF;
-#endif
+ for (int c = 0; c < MATRIX_COLS; c++) {
+ if (matrix_change & (1<<c)) {
+ process_key((keyevent_t){
+ .key = (key_t){ .row = r, .col = c },
+ .pressed = (matrix_row & (1<<c))
+ });
+ // record a processed key
+ matrix_prev[r] ^= (1<<c);
+ // process a key per task call
+ goto MATRIX_LOOP_END;
+ }
+ }
+ }
}
+ MATRIX_LOOP_END:
+ // TODO: FAIL SAFE: clear all key if no key down
-#ifdef MOUSEKEY_ENABLE
- mousekey_send();
-#endif
+ // layer switch when delay term elapses
+ if (kbdstate == DELAYING || kbdstate == WAITING) {
+ if (timer_elapsed(delayed_fn.time) > 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 PS2_MOUSE_ENABLE
- // TODO: should comform new API
- if (ps2_mouse_read() == 0)
- ps2_mouse_usb_send();
-#endif
+ // mousekey repeat & acceleration
+ mousekey_task();
- if (last_leds != host_keyboard_leds()) {
- keyboard_set_leds(host_keyboard_leds());
- last_leds = host_keyboard_leds();
- }
+ return;
}
void keyboard_set_leds(uint8_t leds)
diff --git a/common/keyboard.h b/common/keyboard.h
index 51bf67379a..2353805e17 100644..100755
--- a/common/keyboard.h
+++ b/common/keyboard.h
@@ -18,15 +18,41 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KEYBOARD_H
#define KEYBOARD_H
+#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
+
+typedef struct {
+ uint8_t row;
+ uint8_t col;
+} key_t;
+
+typedef struct {
+ key_t key;
+ bool pressed;
+} keyevent_t;
+
+typedef struct {
+ keyevent_t event;
+ uint8_t code;
+ uint8_t mods;
+ uint16_t time;
+} keyrecord_t;
+
+#define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col)
+
+
+extern uint8_t current_layer;
+extern uint8_t default_layer;
+
void keyboard_init(void);
-void keyboard_proc(void);
+void keyboard_task(void);
void keyboard_set_leds(uint8_t leds);
+
#ifdef __cplusplus
}
#endif
diff --git a/common/layer.c b/common/layer.c
deleted file mode 100644
index 0854eede0d..0000000000
--- a/common/layer.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
-Copyright 2011 Jun Wako <wakojun@gmail.com>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#include "keymap.h"
-#include "host.h"
-#include "debug.h"
-#include "timer.h"
-#include "usb_keycodes.h"
-#include "layer.h"
-
-
-/*
- * Parameters:
- * SWITCH_DELAY |=======|
- * SEND_FN_TERM |================|
- *
- * Fn key processing cases:
- * 1. release Fn after SEND_FN_TERM.
- * Layer sw ___________|~~~~~~~~~~~|___
- * Fn press ___|~~~~~~~~~~~~~~~~~~~|___
- * Fn send ___________________________
- *
- * 2. release Fn during SEND_FN_TERM.(not layer used)
- * Layer sw ___________|~~~~~~|________
- * Fn press ___|~~~~~~~~~~~~~~|________
- * Fn key send __________________|~|______
- * other key press ___________________________
- * other key send ___________________________
- *
- * 3. release Fn during SEND_FN_TERM.(layer used)
- * Layer sw ___________|~~~~~~|________
- * Fn press ___|~~~~~~~~~~~~~~|________
- * Fn key send ___________________________
- * Fn send ___________________________
- * other key press _____________|~~|__________
- * other key send _____________|~~|__________
- *
- * 4. press other key during SWITCH_DELAY.
- * Layer sw ___________________________
- * Fn key press ___|~~~~~~~~~|_____________
- * Fn key send ______|~~~~~~|_____________
- * other key press ______|~~~|________________
- * other key send _______|~~|________________
- *
- * 5. press Fn while press other key.
- * Layer sw ___________________________
- * Fn key press ___|~~~~~~~~~|_____________
- * Fn key send ___|~~~~~~~~~|_____________
- * other key press ~~~~~~~|___________________
- * other key send ~~~~~~~|___________________
- *
- * 6. press Fn twice quickly and keep holding down.(repeat)
- * Layer sw ___________________________
- * Fn key press ___|~|____|~~~~~~~~~~~~~~~~
- * Fn key send _____|~|__|~~~~~~~~~~~~~~~~
- */
-
-// LAYER_SWITCH_DELAY: prevent from moving to new layer
-#ifndef LAYER_SWITCH_DELAY
-# define LAYER_SWITCH_DELAY 150
-#endif
-
-// LAYER_SEND_FN_TERM: send keycode if release key in this term
-#ifndef LAYER_SEND_FN_TERM
-# define LAYER_SEND_FN_TERM 500
-#endif
-
-
-uint8_t default_layer = 0;
-uint8_t current_layer = 0;
-
-static bool layer_used = false;
-static uint8_t new_layer(uint8_t fn_bits);
-
-
-uint8_t layer_get_keycode(uint8_t row, uint8_t col)
-{
- uint8_t code = keymap_get_keycode(current_layer, row, col);
- // normal key or mouse key
- if ((IS_KEY(code) || IS_MOUSEKEY(code))) {
- layer_used = true;
- }
- return code;
-}
-
-// bit substract b from a
-#define BIT_SUBST(a, b) (a&(a^b))
-void layer_switching(uint8_t fn_bits)
-{
- // layer switching
- static uint8_t last_fn = 0;
- static uint8_t last_mods = 0;
- static uint16_t last_timer = 0;
- static uint8_t sent_fn = 0;
-
- if (fn_bits == last_fn) { // Fn state is not changed
- if (fn_bits == 0) {
- // do nothing
- } else {
- if (!keymap_fn_keycode(BIT_SUBST(fn_bits, sent_fn)) ||
- timer_elapsed(last_timer) > LAYER_SWITCH_DELAY) {
- uint8_t _layer_to_switch = new_layer(BIT_SUBST(fn_bits, sent_fn));
- if (current_layer != _layer_to_switch) { // not switch layer yet
- debug("Fn case: 1,2,3(LAYER_SWITCH_DELAY passed)\n");
- debug("Switch Layer: "); debug_hex(current_layer);
- current_layer = _layer_to_switch;
- layer_used = false;
- debug(" -> "); debug_hex(current_layer); debug("\n");
- }
- } else {
- if (host_has_anykey()) { // other keys is pressed
- uint8_t _fn_to_send = BIT_SUBST(fn_bits, sent_fn);
- if (_fn_to_send) {
- debug("Fn case: 4(press other key during SWITCH_DELAY.)\n");
- // send only Fn key first
- uint8_t tmp_mods = keyboard_report->mods;
- host_add_code(keymap_fn_keycode(_fn_to_send));
- host_set_mods(last_mods);
- host_send_keyboard_report();
- host_set_mods(tmp_mods);
- host_del_code(keymap_fn_keycode(_fn_to_send));
- sent_fn |= _fn_to_send;
- }
- }
- }
- // add Fn keys to send
- //host_add_code(keymap_fn_keycode(fn_bits&sent_fn)); // TODO: do all Fn keys
- }
- } else { // Fn state is changed(edge)
- uint8_t fn_changed = 0;
-
- debug("fn_bits: "); debug_bin(fn_bits); debug("\n");
- debug("sent_fn: "); debug_bin(sent_fn); debug("\n");
- debug("last_fn: "); debug_bin(last_fn); debug("\n");
- debug("last_mods: "); debug_hex(last_mods); debug("\n");
- debug("last_timer: "); debug_hex16(last_timer); debug("\n");
- debug("timer_count: "); debug_hex16(timer_count); debug("\n");
-
- // pressed Fn
- if ((fn_changed = BIT_SUBST(fn_bits, last_fn))) {
- debug("fn_changed: "); debug_bin(fn_changed); debug("\n");
- if (host_has_anykey()) {
- debug("Fn case: 5(pressed Fn with other key)\n");
- sent_fn |= fn_changed;
- } else if (fn_changed & sent_fn) { // pressed same Fn in a row
- if (timer_elapsed(last_timer) > LAYER_SEND_FN_TERM) {
- debug("Fn case: 6(not repeat)\n");
- // time passed: not repeate
- sent_fn &= ~fn_changed;
- } else {
- debug("Fn case: 6(repeat)\n");
- }
- }
- }
- // released Fn
- if ((fn_changed = BIT_SUBST(last_fn, fn_bits))) {
- debug("fn_changed: "); debug_bin(fn_changed); debug("\n");
- if (timer_elapsed(last_timer) < LAYER_SEND_FN_TERM) {
- if (!layer_used && BIT_SUBST(fn_changed, sent_fn)) {
- debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n");
- // send only Fn key first
- uint8_t tmp_mods = keyboard_report->mods;
- host_add_code(keymap_fn_keycode(fn_changed));
- host_set_mods(last_mods);
- host_send_keyboard_report();
- host_set_mods(tmp_mods);
- host_del_code(keymap_fn_keycode(fn_changed));
- sent_fn |= fn_changed;
- }
- }
- debug("Switch Layer(released Fn): "); debug_hex(current_layer);
- current_layer = new_layer(BIT_SUBST(fn_bits, sent_fn));
- debug(" -> "); debug_hex(current_layer); debug("\n");
- }
-
- layer_used = false;
- last_fn = fn_bits;
- last_mods = keyboard_report->mods;
-