summaryrefslogtreecommitdiff
path: root/common
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 /common
parent93e33fb8f694c9685accd72ed0458a2cf3d3f04a (diff)
Initial version of new code for layer switch is added.
Diffstat (limited to 'common')
-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
14 files changed, 575 insertions, 437 deletions
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;
- last_timer = timer_read();
- }
- // send Fn keys
- for (uint8_t i = 0; i < 8; i++) {
- if ((sent_fn & fn_bits) & (1<<i)) {
- host_add_code(keymap_fn_keycode(1<<i));
- }
- }
-}
-
-inline
-static uint8_t new_layer(uint8_t fn_bits)
-{
- return (fn_bits ? keymap_fn_layer(fn_bits) : default_layer);
-}
diff --git a/common/layer.h b/common/layer.h
deleted file mode 100644
index d9e8cebb8f..0000000000
--- a/common/layer.h
+++ /dev/null
@@ -1,32 +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/>.
-*/
-
-#ifndef LAYER_H
-#define LAYER_H 1
-
-#include <stdint.h>
-
-extern uint8_t default_layer;
-extern uint8_t current_layer;
-
-/* return keycode for switch */
-uint8_t layer_get_keycode(uint8_t row, uint8_t col);
-
-/* process layer switching */
-void layer_switching(uint8_t fn_bits);
-
-#endif
diff --git a/common/matrix.h b/common/matrix.h
index c4b2cab518..b3332d5ff9 100644
--- a/common/matrix.h
+++ b/common/matrix.h
@@ -18,8 +18,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef MATRIX_H
#define MATRIX_H
+#include <stdint.h>
#include <stdbool.h>
+
+#if (MATRIX_COLS <= 8)
+typedef uint8_t matrix_row_t;
+#elif (MATRIX_COLS <= 16)
+typedef uint16_t matrix_row_t;
+#elif (MATRIX_COLS <= 32)
+typedef uint32_t matrix_row_t;
+#else
+#error "MATRIX_COLS: invalid value"
+#endif
+
+#define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col))
+
+
/* number of matrix rows */
uint8_t matrix_rows(void);
/* number of matrix columns */
@@ -35,11 +50,7 @@ bool matrix_has_ghost(void);
/* whether a swtich is on */
bool matrix_is_on(uint8_t row, uint8_t col);
/* matrix state on row */
-#if (MATRIX_COLS <= 8)
-uint8_t matrix_get_row(uint8_t row);
-#else
-uint16_t matrix_get_row(uint8_t row);
-#endif
+matrix_row_t matrix_get_row(uint8_t row);
/* count keys pressed */
uint8_t matrix_key_count(void);
/* print matrix for debug */
diff --git a/common/mousekey.c b/common/mousekey.c
index 1d35355b49..7f8e860aa6 100644
--- a/common/mousekey.c
+++ b/common/mousekey.c
@@ -26,7 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
static report_mouse_t report;
-static report_mouse_t report_prev;
static uint8_t mousekey_repeat = 0;
@@ -38,84 +37,111 @@ static void mousekey_debug(void);
* see wikipedia http://en.wikipedia.org/wiki/Mouse_keys
*/
#ifndef MOUSEKEY_DELAY_TIME
-# define MOUSEKEY_DELAY_TIME 255
+# define MOUSEKEY_DELAY_TIME 20
#endif
+#define MOUSEKEY_MOVE_INIT 5
+#define MOUSEKEY_WHEEL_INIT 1
+#define MOUSEKEY_MOVE_ACCEL 5
+#define MOUSEKEY_WHEEL_ACCEL 1
+
+static uint16_t last_timer = 0;
+
// acceleration parameters
-uint8_t mousekey_move_unit = 2;
-uint8_t mousekey_resolution = 5;
+//uint8_t mousekey_move_unit = 2;
+//uint8_t mousekey_resolution = 5;
static inline uint8_t move_unit(void)
{
- uint16_t unit = 5 + mousekey_repeat*2;
+ uint16_t unit = 5 + mousekey_repeat*4;
return (unit > 63 ? 63 : unit);
}
-void mousekey_decode(uint8_t code)
-{
- if (code == KB_MS_UP) report.y = -move_unit();
- else if (code == KB_MS_DOWN) report.y = move_unit();
- else if (code == KB_MS_LEFT) report.x = -move_unit();
- else if (code == KB_MS_RIGHT) report.x = move_unit();
- else if (code == KB_MS_BTN1) report.buttons |= MOUSE_BTN1;
- else if (code == KB_MS_BTN2) report.buttons |= MOUSE_BTN2;
- else if (code == KB_MS_BTN3) report.buttons |= MOUSE_BTN3;
- else if (code == KB_MS_BTN4) report.buttons |= MOUSE_BTN4;
- else if (code == KB_MS_BTN5) report.buttons |= MOUSE_BTN5;
- else if (code == KB_MS_WH_UP) report.v += move_unit()/4;
- else if (code == KB_MS_WH_DOWN) report.v -= move_unit()/4;
- else if (code == KB_MS_WH_LEFT) report.h -= move_unit()/4;
- else if (code == KB_MS_WH_RIGHT)report.h += move_unit()/4;
-}
-
-bool mousekey_changed(void)
-{
- return (report.buttons != report_prev.buttons ||
- report.x || report.y || report.v || report.h);
-}
-
-void mousekey_send(void)
+void mousekey_task(void)
{
- static uint16_t last_timer = 0;
-
- if (!mousekey_changed()) {
- mousekey_repeat = 0;
- mousekey_clear_report();
+ if (timer_elapsed(last_timer) < MOUSEKEY_DELAY_TIME)
return;
- }
- // send immediately when buttun state is changed
- if (report.buttons == report_prev.buttons) {
- if (timer_elapsed(last_timer) < 100) {
- mousekey_clear_report();
- return;
- }
- }
+ if (report.x == 0 && report.y == 0 && report.v == 0 && report.h == 0)
+ return;
- if (mousekey_repeat != 0xFF) {
+ if (mousekey_repeat != UINT8_MAX)
mousekey_repeat++;
- }
+
+
+ if (report.x > 0) report.x = move_unit();
+ if (report.x < 0) report.x = move_unit() * -1;
+ if (report.y > 0) report.y = move_unit();
+ if (report.y < 0) report.y = move_unit() * -1;
if (report.x && report.y) {
report.x *= 0.7;
report.y *= 0.7;
}
+ if (report.v > 0) report.v = move_unit();
+ if (report.v < 0) report.v = move_unit() * -1;
+ if (report.h > 0) report.h = move_unit();
+ if (report.h < 0) report.h = move_unit() * -1;
+
+ mousekey_send();
+}
+
+void mousekey_on(uint8_t code)
+{
+ if (code == KB_MS_UP) report.y = MOUSEKEY_MOVE_INIT * -1;
+ else if (code == KB_MS_DOWN) report.y = MOUSEKEY_MOVE_INIT;
+ else if (code == KB_MS_LEFT) report.x = MOUSEKEY_MOVE_INIT * -1;
+ else if (code == KB_MS_RIGHT) report.x = MOUSEKEY_MOVE_INIT;
+ else if (code == KB_MS_WH_UP) report.v = MOUSEKEY_WHEEL_INIT;
+ else if (code == KB_MS_WH_DOWN) report.v = MOUSEKEY_WHEEL_INIT * -1;
+ else if (code == KB_MS_WH_LEFT) report.h = MOUSEKEY_WHEEL_INIT * -1;
+ else if (code == KB_MS_WH_RIGHT) report.h = MOUSEKEY_WHEEL_INIT;
+ else if (code == KB_MS_BTN1) report.buttons |= MOUSE_BTN1;
+ else if (code == KB_MS_BTN2) report.buttons |= MOUSE_BTN2;
+ else if (code == KB_MS_BTN3) report.buttons |= MOUSE_BTN3;
+ else if (code == KB_MS_BTN4) report.buttons |= MOUSE_BTN4;
+ else if (code == KB_MS_BTN5) report.buttons |= MOUSE_BTN5;
+}
+
+void mousekey_off(uint8_t code)
+{
+ if (code == KB_MS_UP && report.y < 0) report.y = 0;
+ else if (code == KB_MS_DOWN && report.y > 0) report.y = 0;
+ else if (code == KB_MS_LEFT && report.x < 0) report.x = 0;
+ else if (code == KB_MS_RIGHT && report.x > 0) report.x = 0;
+ else if (code == KB_MS_WH_UP && report.v > 0) report.v = 0;
+ else if (code == KB_MS_WH_DOWN && report.v < 0) report.v = 0;
+ else if (code == KB_MS_WH_LEFT && report.h < 0) report.h = 0;
+ else if (code == KB_MS_WH_RIGHT && report.h > 0) report.h = 0;
+ else if (code == KB_MS_BTN1) report.buttons &= ~MOUSE_BTN1;
+ else if (code == KB_MS_BTN2) report.buttons &= ~MOUSE_BTN2;
+ else if (code == KB_MS_BTN3) report.buttons &= ~MOUSE_BTN3;
+ else if (code == KB_MS_BTN4) report.buttons &= ~MOUSE_BTN4;
+ else if (code == KB_MS_BTN5) report.buttons &= ~MOUSE_BTN5;
+
+ if (report.x == 0 && report.y == 0 && report.v == 0 && report.h == 0)
+ mousekey_repeat = 0;
+}
+
+void mousekey_send(void)
+{
mousekey_debug();
host_mouse_send(&report);
- report_prev = report;
last_timer = timer_read();
- mousekey_clear_report();
}
-void mousekey_clear_report(void)
+void mousekey_clear(void)
{
+ report = (report_mouse_t){};
+/*
report.buttons = 0;
report.x = 0;
report.y = 0;
report.v = 0;
report.h = 0;
+*/
}
static void mousekey_debug(void)
diff --git a/common/mousekey.h b/common/mousekey.h
index c2c24e9fa5..3006c4634f 100644
--- a/common/mousekey.h
+++ b/common/mousekey.h
@@ -21,9 +21,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdbool.h>
#include "host.h"
-void mousekey_decode(uint8_t code);
-bool mousekey_changed(void);
+void mousekey_task(void);
+void mousekey_on(uint8_t code);
+void mousekey_off(uint8_t code);
+void mousekey_clear(void);
void mousekey_send(void);
-void mousekey_clear_report(void);
#endif
diff --git a/common/timer.c b/common/timer.c
index 8b8d37e8b3..e0dec6cefc 100644
--- a/common/timer.c
+++ b/common/timer.c
@@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// counter resolution 1ms
+// NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
volatile uint32_t timer_count = 0;
void timer_init(void)
diff --git a/common/usb_keycodes.h b/common/usb_keycodes.h
index 04b398fa2a..61d6bf0029 100644
--- a/common/usb_keycodes.h
+++ b/common/usb_keycodes.h
@@ -33,8 +33,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define IS_MOUSEKEY_BUTTON(code) (KB_MS_BTN1 <= (code) && (code) <= KB_MS_BTN5)
#define IS_MOUSEKEY_WHEEL(code) (KB_MS_WH_UP <= (code) && (code) <= KB_MS_WH_RIGHT)
-#define MOD_BIT(code) (1<<((code) & 0x07))
-#define FN_BIT(code) (1<<((code) - KB_FN0))
+#define MOD_BIT(code) (1<<((code) & 0x07))
+#define FN_BIT(code) (1<<((code) - KB_FN0))
+#define FN_INDEX(code) ((code) - KB_FN0)
/* Short names */
diff --git a/common/util.c b/common/util.c
index 36afdd4470..644301fe89 100644
--- a/common/util.c
+++ b/common/util.c
@@ -17,19 +17,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "util.h"
-// bit population
-int bitpop(uint8_t bits)
+// bit population - return number of on-bit
+uint8_t bitpop(uint8_t bits)
{
- int c;
+ uint8_t c;
for (c = 0; bits; c++)
bits &= bits -1;
return c;
+/*
+ const uint8_t bit_count[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+ return bit_count[bits>>4] + bit_count[bits&0x0F]
+*/
}
-// most significant on-bit
-int biton(uint8_t bits)
+// most significant on-bit - return highest location of on-bit
+uint8_t biton(uint8_t bits)
{
- int n = 0;
+ uint8_t n = 0;
if (bits >> 4) { bits >>= 4; n += 4;}
if (bits >> 2) { bits >>= 2; n += 2;}
if (bits >> 1) { bits >>= 1; n += 1;}
diff --git a/common/util.h b/common/util.h
index 66bccbfa58..87636c9710 100644
--- a/common/util.h
+++ b/common/util.h
@@ -28,7 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define XSTR(s) #s
-int bitpop(uint8_t bits);
-int biton(uint8_t bits);
+uint8_t bitpop(uint8_t bits);
+uint8_t biton(uint8_t bits);
#endif