diff --git a/common.mk b/common.mk
index 26b4bb85..66f9fd09 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 13d37242..0020d8a1 100644
--- a/common/command.c
+++ b/common/command.c
@@ -23,7 +23,7 @@ along with this program. If not, see .
#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 8dd2abbe..fddd5b66 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 26bf3c36..84a6c247 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
old mode 100644
new mode 100755
index 25f32eb0..9f0c2767
--- 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 .
*/
#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 .
#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< "); 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< 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
old mode 100644
new mode 100755
index 51bf6737..2353805e
--- a/common/keyboard.h
+++ b/common/keyboard.h
@@ -18,15 +18,41 @@ along with this program. If not, see .
#ifndef KEYBOARD_H
#define KEYBOARD_H
+#include
#include
#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 0854eede..00000000
--- a/common/layer.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
-Copyright 2011 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
-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 .
-*/
-
-#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<
-
-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 .
-*/
-
-#ifndef LAYER_H
-#define LAYER_H 1
-
-#include
-
-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 c4b2cab5..b3332d5f 100644
--- a/common/matrix.h
+++ b/common/matrix.h
@@ -18,8 +18,23 @@ along with this program. If not, see .
#ifndef MATRIX_H
#define MATRIX_H
+#include
#include
+
+#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<.
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 c2c24e9f..3006c463 100644
--- a/common/mousekey.h
+++ b/common/mousekey.h
@@ -21,9 +21,10 @@ along with this program. If not, see .
#include
#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 8b8d37e8..e0dec6ce 100644
--- a/common/timer.c
+++ b/common/timer.c
@@ -22,6 +22,7 @@ along with this program. If not, see .
// 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 04b398fa..61d6bf00 100644
--- a/common/usb_keycodes.h
+++ b/common/usb_keycodes.h
@@ -33,8 +33,9 @@ along with this program. If not, see .
#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 36afdd44..644301fe 100644
--- a/common/util.c
+++ b/common/util.c
@@ -17,19 +17,23 @@ along with this program. If not, see .
#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 66bccbfa..87636c97 100644
--- a/common/util.h
+++ b/common/util.h
@@ -28,7 +28,7 @@ along with this program. If not, see .
#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
diff --git a/keyboard/hhkb/config.h b/keyboard/hhkb/config.h
index bf946ac0..17a44940 100644
--- a/keyboard/hhkb/config.h
+++ b/keyboard/hhkb/config.h
@@ -35,8 +35,6 @@ along with this program. If not, see .
/* matrix size */
#define MATRIX_ROWS 8
#define MATRIX_COLS 8
-/* define if matrix has ghost */
-//#define MATRIX_HAS_GHOST
/* key combination for command */
diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c
index f05962ae..43f777c5 100644
--- a/keyboard/hhkb/keymap.c
+++ b/keyboard/hhkb/keymap.c
@@ -210,12 +210,12 @@ uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
return KEYCODE(layer, row, col);
}
-uint8_t keymap_fn_layer(uint8_t fn_bits)
+uint8_t keymap_fn_layer(uint8_t index)
{
- return pgm_read_byte(&fn_layer[biton(fn_bits)]);
+ return pgm_read_byte(&fn_layer[index]);
}
-uint8_t keymap_fn_keycode(uint8_t fn_bits)
+uint8_t keymap_fn_keycode(uint8_t index)
{
- return pgm_read_byte(&fn_keycode[(biton(fn_bits))]);
+ return pgm_read_byte(&fn_keycode[index]);
}
diff --git a/keyboard/hhkb/matrix.c b/keyboard/hhkb/matrix.c
index 79d2d987..3bd6e73b 100644
--- a/keyboard/hhkb/matrix.c
+++ b/keyboard/hhkb/matrix.c
@@ -43,22 +43,10 @@ along with this program. If not, see .
// matrix state buffer(1:on, 0:off)
-#if (MATRIX_COLS <= 8)
-static uint8_t *matrix;
-static uint8_t *matrix_prev;
-static uint8_t _matrix0[MATRIX_ROWS];
-static uint8_t _matrix1[MATRIX_ROWS];
-#else
-static uint16_t *matrix;
-static uint16_t *matrix_prev;
-static uint16_t _matrix0[MATRIX_ROWS];
-static uint16_t _matrix1[MATRIX_ROWS];
-#endif
-
-// HHKB has no ghost and no bounce.
-#ifdef MATRIX_HAS_GHOST
-static bool matrix_has_ghost_in_row(uint8_t row);
-#endif
+static matrix_row_t *matrix;
+static matrix_row_t *matrix_prev;
+static matrix_row_t _matrix0[MATRIX_ROWS];
+static matrix_row_t _matrix1[MATRIX_ROWS];
// Matrix I/O ports
@@ -192,6 +180,8 @@ uint8_t matrix_scan(void)
}
// Ignore if this code region execution time elapses more than 20us.
+ // MEMO: 20[us] * (TIMER_RAW_FREQ / 1000000)[count per us]
+ // MEMO: then change above using this rule: a/(b/c) = a*1/(b/c) = a*(c/b)
if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) {
matrix[row] = matrix_prev[row];
}
@@ -219,12 +209,6 @@ bool matrix_is_modified(void)
inline
bool matrix_has_ghost(void)
{
-#ifdef MATRIX_HAS_GHOST
- for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
- if (matrix_has_ghost_in_row(i))
- return true;
- }
-#endif
return false;
}
@@ -257,11 +241,6 @@ void matrix_print(void)
pbin_reverse(matrix_get_row(row));
#else
pbin_reverse16(matrix_get_row(row));
-#endif
-#ifdef MATRIX_HAS_GHOST
- if (matrix_has_ghost_in_row(row)) {
- print("