summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2012-10-18 01:11:06 +0900
committertmk <nobody@nowhere>2012-10-18 01:11:06 +0900
commit3c822b511e7af60332a7e5a938c08bafb2516ba3 (patch)
tree0a78cce225b04930de14935dffd36ce8f3bf2d76 /common
parent93e33fb8f694c9685accd72ed0458a2cf3d3f04a (diff)
parentfffc375b45ad795c4a8d3cde94783dac195a2613 (diff)
Merge branch 'layerfix'
Diffstat (limited to 'common')
-rw-r--r--common/command.c536
-rw-r--r--common/command.h4
-rw-r--r--common/debug.h2
-rw-r--r--common/host.c138
-rw-r--r--common/host.h28
-rw-r--r--common/keyboard.c690
-rw-r--r--common/keyboard.h28
-rw-r--r--common/keycode.h448
-rw-r--r--common/layer.c207
-rw-r--r--common/layer.h32
-rw-r--r--common/matrix.h21
-rw-r--r--common/mousekey.c202
-rw-r--r--common/mousekey.h46
-rw-r--r--common/print.c8
-rw-r--r--common/print.h1
-rw-r--r--common/timer.c1
-rw-r--r--common/usb_keycodes.h424
-rw-r--r--common/util.c16
-rw-r--r--common/util.h4
19 files changed, 1775 insertions, 1061 deletions
diff --git a/common/command.c b/common/command.c
index 13d37242d9..8e2e21a707 100644
--- a/common/command.c
+++ b/common/command.c
@@ -17,16 +17,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
#include <util/delay.h>
-#include "usb_keycodes.h"
+#include "keycode.h"
#include "host.h"
#include "print.h"
#include "debug.h"
#include "util.h"
#include "timer.h"
-#include "layer.h"
-#include "matrix.h"
+#include "keyboard.h"
#include "bootloader.h"
#include "command.h"
+#ifdef MOUSEKEY_ENABLE
+#include "mousekey.h"
+#endif
#ifdef HOST_PJRC
# include "usb_keyboard.h"
@@ -40,104 +42,182 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
-static uint8_t command_common(void);
-static void help(void);
+static bool command_common(uint8_t code);
+static void command_common_help(void);
+static bool command_console(uint8_t code);
+static void command_console_help(void);
+#ifdef MOUSEKEY_ENABLE
+static bool mousekey_console(uint8_t code);
+static void mousekey_console_help(void);
+#endif
+
+static uint8_t numkey2num(uint8_t code);
static void switch_layer(uint8_t layer);
+static void clear_keyboard(void);
-static bool last_print_enable;
-uint8_t command_proc(void)
-{
- uint8_t processed = 0;
- last_print_enable = print_enable;
+typedef enum { ONESHOT, CONSOLE, MOUSEKEY } cmdstate_t;
+static cmdstate_t state = ONESHOT;
- if (!IS_COMMAND())
- return 0;
- print_enable = true;
- if (command_extra() || command_common()) {
- processed = 1;
- _delay_ms(500);
+bool command_proc(uint8_t code)
+{
+ switch (state) {
+ case ONESHOT:
+ if (!IS_COMMAND())
+ return false;
+ return (command_extra(code) || command_common(code));
+ case CONSOLE:
+ command_console(code);
+ break;
+#ifdef MOUSEKEY_ENABLE
+ case MOUSEKEY:
+ mousekey_console(code);
+ break;
+#endif
+ default:
+ state = ONESHOT;
+ return false;
}
- print_enable = last_print_enable;
- return processed;
+ return true;
}
-/* This allows to define extra commands. return 0 when not processed. */
-uint8_t command_extra(void) __attribute__ ((weak));
-uint8_t command_extra(void)
+/* This allows to define extra commands. return false when not processed. */
+bool command_extra(uint8_t code) __attribute__ ((weak));
+bool command_extra(uint8_t code)
{
- return 0;
+ return false;
}
-static uint8_t command_common(void)
+/***********************************************************
+ * Command common
+ ***********************************************************/
+static void command_common_help(void)
+{
+ print_enable = true;
+ print("\n\n----- Command Help -----\n");
+ print("c: enter console mode\n");
+ print("d: toggle debug enable\n");
+ print("x: toggle matrix debug\n");
+ print("k: toggle keyboard debug\n");
+ print("m: toggle mouse debug\n");
+ print("p: toggle print enable\n");
+ print("v: print device version & info\n");
+ print("t: print timer count\n");
+ print("s: print status\n");
+#ifdef NKRO_ENABLE
+ print("n: toggle NKRO\n");
+#endif
+ print("0/F10: switch to Layer0 \n");
+ print("1/F1: switch to Layer1 \n");
+ print("2/F2: switch to Layer2 \n");
+ print("3/F3: switch to Layer3 \n");
+ print("4/F4: switch to Layer4 \n");
+ print("PScr: power down/remote wake-up\n");
+ print("Caps: Lock Keyboard(Child Proof)\n");
+ print("Paus: jump to bootloader\n");
+}
+
+static bool command_common(uint8_t code)
{
- switch (host_get_first_key()) {
- case KB_H:
- help();
- break;
- case KB_B:
- host_clear_keyboard_report();
- host_send_keyboard_report();
- print("jump to bootloader... ");
+ static host_driver_t *host_driver = 0;
+ switch (code) {
+ case KC_CAPSLOCK:
+ if (host_get_driver()) {
+ host_driver = host_get_driver();
+ host_set_driver(0);
+ print("Locked.\n");
+ } else {
+ host_set_driver(host_driver);
+ print("Unlocked.\n");
+ }
+ break;
+ case KC_H:
+ case KC_SLASH: /* ? */
+ command_common_help();
+ break;
+ case KC_C:
+ print_enable = true;
+ debug_matrix = false;
+ debug_keyboard = false;
+ debug_mouse = false;
+ debug_enable = false;
+ command_console_help();
+ print("\nEnter Console Mode\n");
+ print("C> ");
+ state = CONSOLE;
+ break;
+ case KC_PAUSE:
+ clear_keyboard();
+ print("\n\nJump to bootloader... ");
_delay_ms(1000);
bootloader_jump(); // not return
print("not supported.\n");
break;
- case KB_D:
- debug_enable = !debug_enable;
+ case KC_D:
if (debug_enable) {
- last_print_enable = true;
- print("debug enabled.\n");
- debug_matrix = true;
- debug_keyboard = true;
- debug_mouse = true;
- } else {
- print("debug disabled.\n");
- last_print_enable = false;
- debug_matrix = false;
+ print("\nDEBUG: disabled.\n");
+ debug_matrix = false;
debug_keyboard = false;
- debug_mouse = false;
+ debug_mouse = false;
+ debug_enable = false;
+ } else {
+ print("\nDEBUG: enabled.\n");
+ debug_matrix = true;
+ debug_keyboard = true;
+ debug_mouse = true;
+ debug_enable = true;
}
break;
- case KB_X: // debug matrix toggle
+ case KC_X: // debug matrix toggle
debug_matrix = !debug_matrix;
- if (debug_matrix)
- print("debug matrix enabled.\n");
- else
- print("debug matrix disabled.\n");
+ if (debug_matrix) {
+ print("\nDEBUG: matrix enabled.\n");
+ debug_enable = true;
+ } else {
+ print("\nDEBUG: matrix disabled.\n");
+ }
break;
- case KB_K: // debug keyboard toggle
+ case KC_K: // debug keyboard toggle
debug_keyboard = !debug_keyboard;
- if (debug_keyboard)
- print("debug keyboard enabled.\n");
- else
- print("debug keyboard disabled.\n");
+ if (debug_keyboard) {
+ print("\nDEBUG: keyboard enabled.\n");
+ debug_enable = true;
+ } else {
+ print("\nDEBUG: keyboard disabled.\n");
+ }
break;
- case KB_M: // debug mouse toggle
+ case KC_M: // debug mouse toggle
debug_mouse = !debug_mouse;
- if (debug_mouse)
- print("debug mouse enabled.\n");
- else
- print("debug mouse disabled.\n");
+ if (debug_mouse) {
+ print("\nDEBUG: mouse enabled.\n");
+ debug_enable = true;
+ } else {
+ print("\nDEBUG: mouse disabled.\n");
+ }
break;
- case KB_V: // print version & information
+ case KC_V: // print version & information
+ print("\n\n----- Version -----\n");
print(STR(DESCRIPTION) "\n");
+ print(STR(MANUFACTURER) "(" STR(VENDOR_ID) ")/");
+ print(STR(PRODUCT) "(" STR(PRODUCT_ID) ") ");
+ print("VERSION: " STR(DEVICE_VER) "\n");
break;
- case KB_T: // print timer
- print("timer: "); phex16(timer_count); print("\n");
+ case KC_T: // print timer
+ print("timer: "); phex16(timer_count>>16); phex16(timer_count); print("\n");
break;
- case KB_P: // print toggle
- if (last_print_enable) {
+ case KC_P: // print toggle
+ if (print_enable) {
print("print disabled.\n");
- last_print_enable = false;
+ print_enable = false;
} else {
- last_print_enable = true;
+ print_enable = true;
print("print enabled.\n");
}
break;
- case KB_S:
+ case KC_S:
+ print("\n\n----- Status -----\n");
print("host_keyboard_leds:"); phex(host_keyboard_leds()); print("\n");
#ifdef HOST_PJRC
print("UDCON: "); phex(UDCON); print("\n");
@@ -156,10 +236,7 @@ static uint8_t command_common(void)
#endif
break;
#ifdef NKRO_ENABLE
- case KB_N:
- // send empty report before change
- host_clear_keyboard_report();
- host_send_keyboard_report();
+ case KC_N:
keyboard_nkro = !keyboard_nkro;
if (keyboard_nkro)
print("NKRO: enabled\n");
@@ -168,9 +245,8 @@ static uint8_t command_common(void)
break;
#endif
#ifdef EXTRAKEY_ENABLE
- case KB_ESC:
- host_clear_keyboard_report();
- host_send_keyboard_report();
+ case KC_PSCREEN:
+ // TODO: Power key should take this feature? otherwise any key during suspend.
#ifdef HOST_PJRC
if (suspend && remote_wakeup) {
usb_remote_wakeup();
@@ -181,57 +257,296 @@ static uint8_t command_common(void)
}
#else
host_system_send(SYSTEM_POWER_DOWN);
+ _delay_ms(100);
host_system_send(0);
_delay_ms(500);
#endif
break;
#endif
- case KB_BSPC:
- matrix_init();
- print("clear matrix\n");
- break;
- case KB_0:
+ case KC_0:
+ case KC_F10:
switch_layer(0);
break;
- case KB_1:
+ case KC_1:
+ case KC_F1:
switch_layer(1);
break;
- case KB_2:
+ case KC_2:
+ case KC_F2:
switch_layer(2);
break;
- case KB_3:
+ case KC_3:
+ case KC_F3:
switch_layer(3);
break;
- case KB_4:
+ case KC_4:
+ case KC_F4:
switch_layer(4);
break;
default:
- return 0;
+ print("?");
+ return false;
}
- return 1;
+ return true;
}
-static void help(void)
+
+/***********************************************************
+ * Command console
+ ***********************************************************/
+static void command_console_help(void)
{
- print("b: jump to bootloader\n");
- print("d: toggle debug enable\n");
- print("x: toggle matrix debug\n");
- print("k: toggle keyboard debug\n");
- print("m: toggle mouse debug\n");
- print("p: toggle print enable\n");
- print("v: print version\n");
- print("t: print timer count\n");
- print("s: print status\n");
-#ifdef NKRO_ENABLE
- print("n: toggle NKRO\n");
+ print_enable = true;
+ print("\n\n----- Console Help -----\n");
+ print("ESC/q: quit\n");
+#ifdef MOUSEKEY_ENABLE
+ print("m: mousekey\n");
+#endif
+}
+
+static bool command_console(uint8_t code)
+{
+ switch (code) {
+ case KC_H:
+ case KC_SLASH: /* ? */
+ command_console_help();
+ break;
+ case KC_Q:
+ case KC_ESC:
+ print("\nQuit Console Mode\n");
+ state = ONESHOT;
+ return false;
+#ifdef MOUSEKEY_ENABLE
+ case KC_M:
+ mousekey_console_help();
+ print("\nEnter Mousekey Console\n");
+ print("M0>");
+ state = MOUSEKEY;
+ return true;
+#endif
+ default:
+ print("?");
+ return false;
+ }
+ print("C> ");
+ return true;
+}
+
+
+#ifdef MOUSEKEY_ENABLE
+/***********************************************************
+ * Mousekey console
+ ***********************************************************/
+static uint8_t mousekey_param = 0;
+
+static void mousekey_param_print(void)
+{
+ print("\n\n----- Mousekey Parameters -----\n");
+ print("1: mk_delay(*10ms): "); pdec(mk_delay); print("\n");
+ print("2: mk_interval(ms): "); pdec(mk_interval); print("\n");
+ print("3: mk_max_speed: "); pdec(mk_max_speed); print("\n");
+ print("4: mk_time_to_max: "); pdec(mk_time_to_max); print("\n");
+ print("5: mk_wheel_max_speed: "); pdec(mk_wheel_max_speed); print("\n");
+ print("6: mk_wheel_time_to_max: "); pdec(mk_wheel_time_to_max); print("\n");
+}
+
+static void mousekey_param_inc(uint8_t param, uint8_t inc)
+{
+ switch (param) {
+ case 1:
+ if (mk_delay + inc < UINT8_MAX)
+ mk_delay += inc;
+ else
+ mk_delay = UINT8_MAX;
+ print("mk_delay = "); pdec(mk_delay); print("\n");
+ break;
+ case 2:
+ if (mk_interval + inc < UINT8_MAX)
+ mk_interval += inc;
+ else
+ mk_interval = UINT8_MAX;
+ print("mk_interval = "); pdec(mk_interval); print("\n");
+ break;
+ case 3:
+ if (mk_max_speed + inc < UINT8_MAX)
+ mk_max_speed += inc;
+ else
+ mk_max_speed = UINT8_MAX;
+ print("mk_max_speed = "); pdec(mk_max_speed); print("\n");
+ break;
+ case 4:
+ if (mk_time_to_max + inc < UINT8_MAX)
+ mk_time_to_max += inc;
+ else
+ mk_time_to_max = UINT8_MAX;
+ print("mk_time_to_max = "); pdec(mk_time_to_max); print("\n");
+ break;
+ case 5:
+ if (mk_wheel_max_speed + inc < UINT8_MAX)
+ mk_wheel_max_speed += inc;
+ else
+ mk_wheel_max_speed = UINT8_MAX;
+ print("mk_wheel_max_speed = "); pdec(mk_wheel_max_speed); print("\n");
+ break;
+ case 6:
+ if (mk_wheel_time_to_max + inc < UINT8_MAX)
+ mk_wheel_time_to_max += inc;
+ else
+ mk_wheel_time_to_max = UINT8_MAX;
+ print("mk_wheel_time_to_max = "); pdec(mk_wheel_time_to_max); print("\n");
+ break;
+ }
+}
+
+static void mousekey_param_dec(uint8_t param, uint8_t dec)
+{
+ switch (param) {
+ case 1:
+ if (mk_delay > dec)
+ mk_delay -= dec;
+ else
+ mk_delay = 0;
+ print("mk_delay = "); pdec(mk_delay); print("\n");
+ break;
+ case 2:
+ if (mk_interval > dec)
+ mk_interval -= dec;
+ else
+ mk_interval = 0;
+ print("mk_interval = "); pdec(mk_interval); print("\n");
+ break;
+ case 3:
+ if (mk_max_speed > dec)
+ mk_max_speed -= dec;
+ else
+ mk_max_speed = 0;
+ print("mk_max_speed = "); pdec(mk_max_speed); print("\n");
+ break;
+ case 4:
+ if (mk_time_to_max > dec)
+ mk_time_to_max -= dec;
+ else
+ mk_time_to_max = 0;
+ print("mk_time_to_max = "); pdec(mk_time_to_max); print("\n");
+ break;
+ case 5:
+ if (mk_wheel_max_speed > dec)
+ mk_wheel_max_speed -= dec;
+ else
+ mk_wheel_max_speed = 0;
+ print("mk_wheel_max_speed = "); pdec(mk_wheel_max_speed); print("\n");
+ break;
+ case 6:
+ if (mk_wheel_time_to_max > dec)
+ mk_wheel_time_to_max -= dec;
+ else
+ mk_wheel_time_to_max = 0;
+ print("mk_wheel_time_to_max = "); pdec(mk_wheel_time_to_max); print("\n");
+ break;
+ }
+}
+
+static void mousekey_console_help(void)
+{
+ print("\n\n----- Mousekey Parameters Help -----\n");
+ print("ESC/q: quit\n");
+ print("1: select mk_delay(*10ms)\n");
+ print("2: select mk_interval(ms)\n");
+ print("3: select mk_max_speed\n");
+ print("4: select mk_time_to_max\n");
+ print("5: select mk_wheel_max_speed\n");
+ print("6: select mk_wheel_time_to_max\n");
+ print("p: print prameters\n");
+ print("d: set default values\n");
+ print("up: increase prameters(+1)\n");
+ print("down: decrease prameters(-1)\n");
+ print("pgup: increase prameters(+10)\n");
+ print("pgdown: decrease prameters(-10)\n");
+ print("\nspeed = delta * max_speed * (repeat / time_to_max)\n");
+ print("where delta: cursor="); pdec(MOUSEKEY_MOVE_DELTA);
+ print(", wheel="); pdec(MOUSEKEY_WHEEL_DELTA); print("\n");
+ print("See http://en.wikipedia.org/wiki/Mouse_keys\n");
+}
+
+static bool mousekey_console(uint8_t code)
+{
+ switch (code) {
+ case KC_H:
+ case KC_SLASH: /* ? */
+ mousekey_console_help();
+ break;
+ case KC_Q:
+ case KC_ESC:
+ mousekey_param = 0;
+ print("\nQuit Mousekey Console\n");
+ print("C> ");
+ state = CONSOLE;
+ return false;
+ case KC_P:
+ mousekey_param_print();
+ break;
+ case KC_1:
+ case KC_2:
+ case KC_3:
+ case KC_4:
+ case KC_5:
+ case KC_6:
+ case KC_7:
+ case KC_8:
+ case KC_9:
+ case KC_0:
+ mousekey_param = numkey2num(code);
+ print("selected parameter: "); pdec(mousekey_param); print("\n");
+ break;
+ case KC_UP:
+ mousekey_param_inc(mousekey_param, 1);
+ break;
+ case KC_DOWN:
+ mousekey_param_dec(mousekey_param, 1);
+ break;
+ case KC_PGUP:
+ mousekey_param_inc(mousekey_param, 10);
+ break;
+ case KC_PGDN:
+ mousekey_param_dec(mousekey_param, 10);
+ break;
+ case KC_D:
+ mk_delay = MOUSEKEY_DELAY/10;
+ mk_interval = MOUSEKEY_INTERVAL;
+ mk_max_speed = MOUSEKEY_MAX_SPEED;
+ mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
+ mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
+ mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
+ print("set default values.\n");
+ break;
+ default:
+ print("?");
+ return false;
+ }
+ print("M"); pdec(mousekey_param); print("> ");
+ return true;
+}
#endif
- print("Backspace: clear matrix\n");
- print("ESC: power down/wake up\n");
- print("0: switch to Layer0 \n");
- print("1: switch to Layer1 \n");
- print("2: switch to Layer2 \n");
- print("3: switch to Layer3 \n");
- print("4: switch to Layer4 \n");
+
+
+/***********************************************************
+ * Utilities
+ ***********************************************************/
+static uint8_t numkey2num(uint8_t code)
+{
+ switch (code) {
+ case KC_1: return 1;
+ case KC_2: return 2;
+ case KC_3: return 3;
+ case KC_4: return 4;
+ case KC_5: return 5;
+ case KC_6: return 6;
+ case KC_7: return 7;
+ case KC_8: return 8;
+ case KC_9: return 9;
+ case KC_0: return 0;
+ }
+ return 0;
}
static void switch_layer(uint8_t layer)
@@ -242,3 +557,18 @@ static void switch_layer(uint8_t layer)
default_layer = layer;
print("switch to Layer: "); phex(layer); print("\n");
}
+
+static void clear_keyboard(void)
+{
+ host_clear_keys();
+ host_clear_mods();
+ host_send_keyboard_report();
+
+ host_system_send(0);
+ host_consumer_send(0);
+
+#ifdef MOUSEKEY_ENABLE
+ mousekey_clear();
+ mousekey_send();
+#endif
+}
diff --git a/common/command.h b/common/command.h
index 4888f5ee0b..dafd4d0f38 100644
--- a/common/command.h
+++ b/common/command.h
@@ -18,8 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef COMMAND_H
#define COMMAND
-uint8_t command_proc(void);
+bool command_proc(uint8_t code);
/* This allows to extend commands. Return 0 when command is not processed. */
-uint8_t command_extra(void);
+bool command_extra(uint8_t code);
#endif
diff --git a/common/debug.h b/common/debug.h
index 9cc8d882f3..1d56e21f77 100644
--- a/common/debug.h
+++ b/common/debug.h
@@ -23,6 +23,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define debug(s) if(debug_enable) print_P(PSTR(s))
+#define debug_P(s) if(debug_enable) print_P(s)
+#define debug_S(s) if(debug_enable) print_S(s)
#define debug_hex(c) if(debug_enable) phex(c)
#define debug_hex16(i) if(debug_enable) phex16(i)
#define debug_bin(c) if(debug_enable) pbin(c)
diff --git a/common/host.c b/common/host.c
index 8dd2abbee8..261ec6472f 100644
--- a/common/host.c
+++ b/common/host.c
@@ -1,5 +1,5 @@
/*
-Copyright 2011 Jun Wako <wakojun@gmail.com>
+Copyright 2011,2012 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
@@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <avr/interrupt.h>
-#include "usb_keycodes.h"
+#include "keycode.h"
#include "host.h"
#include "util.h"
#include "debug.h"
@@ -27,12 +27,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
bool keyboard_nkro = false;
#endif
-static host_driver_t *driver;
-static report_keyboard_t report0;
-static report_keyboard_t report1;
-report_keyboard_t *keyboard_report = &report0;
-report_keyboard_t *keyboard_report_prev = &report1;
+report_keyboard_t *keyboard_report = &(report_keyboard_t){};
+report_mouse_t mouse_report = {};
+
+static host_driver_t *driver;
+static uint16_t last_system_report = 0;
+static uint16_t last_consumer_report = 0;
static inline void add_key_byte(uint8_t code);
static inline void del_key_byte(uint8_t code);
@@ -55,8 +56,48 @@ uint8_t host_keyboard_leds(void)
if (!driver) return 0;
return (*driver->keyboard_leds)();
}
+/* send report */
+void host_keyboard_send(report_keyboard_t *report)
+{
+ if (!driver) return;
+ (*driver->send_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)
+{
+ if (!driver) return;
+ (*driver->send_mouse)(report);
+}
+
+void host_system_send(uint16_t report)
+{
+ if (report == last_system_report) return;
+ last_system_report = report;
+
+ if (!driver) return;
+ (*driver->send_system)(report);
+}
+
+void host_consumer_send(uint16_t report)
+{
+ if (report == last_consumer_report) return;
+ last_consumer_report = report;
+
+ if (!driver) return;
+ (*driver->send_consumer)(report);
+}
+
-/* keyboard report operations */
+
+/* keyboard report utils */
void host_add_key(uint8_t key)
{
#ifdef NKRO_ENABLE
@@ -79,6 +120,13 @@ void host_del_key(uint8_t key)
del_key_byte(key);
}
+void host_clear_keys(void)
+{
+ for (int8_t i = 0; i < REPORT_KEYS; i++) {
+ keyboard_report->keys[i] = 0;
+ }
+}
+
void host_add_mod_bit(uint8_t mod)
{
keyboard_report->mods |= mod;
@@ -94,40 +142,9 @@ void host_set_mods(uint8_t mods)
keyboard_report->mods = mods;
}
-void host_add_code(uint8_t code)
-{
- if (IS_MOD(code)) {
- host_add_mod_bit(MOD_BIT(code));
- } else {
- host_add_key(code);
- }
-}
-
-void host_del_code(uint8_t code)
-{
- if (IS_MOD(code)) {
- host_del_mod_bit(MOD_BIT(code));
- } else {
- host_del_key(code);
- }
-}
-
-void host_swap_keyboard_report(void)
-{
- uint8_t sreg = SREG;
- cli();
- report_keyboard_t *tmp = keyboard_report_prev;
- keyboard_report_prev = keyboard_report;
- keyboard_report = tmp;
- SREG = sreg;
-}
-
-void host_clear_keyboard_report(void)
+void host_clear_mods(void)
{
keyboard_report->mods = 0;
- for (int8_t i = 0; i < REPORT_KEYS; i++) {
- keyboard_report->keys[i] = 0;
- }
}
uint8_t host_has_anykey(void)
@@ -140,6 +157,11 @@ uint8_t host_has_anykey(void)
return cnt;
}
+uint8_t host_has_anymod(void)
+{
+ return bitpop(keyboard_report->mods);
+}
+
uint8_t host_get_first_key(void)
{
#ifdef NKRO_ENABLE
@@ -153,53 +175,36 @@ uint8_t host_get_first_key(void)
return keyboard_report->keys[0];
}
-
void host_send_keyboard_report(void)
{
if (!driver) return;
- (*driver->send_keyboard)(keyboard_report);
+ host_keyboard_send(keyboard_report);
}
-void host_mouse_send(report_mouse_t *report)
+uint8_t host_mouse_in_use(void)
{
- if (!driver) return;
- (*driver->send_mouse)(report);
+ return (mouse_report.buttons | mouse_report.x | mouse_report.y | mouse_report.v | mouse_report.h);
}
-void host_system_send(uint16_t data)
+uint16_t host_last_sysytem_report(void)
{
- static uint16_t last_data = 0;
- if (data == last_data) return;
- last_data = data;
-
- if (!driver) return;
- (*driver->send_system)(data);
+ return last_system_report;
}
-void host_consumer_send(uint16_t data)
+uint16_t host_last_consumer_report(void)
{
- static uint16_t last_data = 0;
- if (data == last_data) return;
- last_data = data;
-
- if (!driver) return;
- (*driver->send_consumer)(data);
+ return last_consumer_report;
}
-
static inline void add_key_byte(uint8_t code)
{
- // TODO: fix ugly code
int8_t i = 0;
int8_t empty = -1;
for (; i < REPORT_KEYS; i++) {
- if (keyboard_report_prev->keys[i] == code) {
- keyboard_report->keys[i] = code;
+ if (keyboard_report->keys[i] == code) {
break;
}
- if (empty == -1 &&
- keyboard_report_prev->keys[i] == 0 &&
- keyboard_report->keys[i] == 0) {
+ if (empty == -1 && keyboard_report->keys[i] == 0) {
empty = i;
}
}
@@ -216,7 +221,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..207b683100 100644
--- a/common/host.h
+++ b/common/host.h
@@ -31,32 +31,40 @@ extern "C" {
extern bool keyboard_nkro;
#endif
+/* report */
extern report_keyboard_t *keyboard_report;
-extern report_keyboard_t *keyboard_report_prev;
+extern report_mouse_t mouse_report;
+/* host driver */
void host_set_driver(host_driver_t *driver);
host_driver_t *host_get_driver(void);
+
+/* host driver interface */
uint8_t host_keyboard_leds(void);
+void host_keyboard_send(report_keyboard_t *report);
+void host_mouse_send(report_mouse_t *report);
+void host_system_send(uint16_t data);
+void host_consumer_send(uint16_t data);
-/* keyboard report operations */
+/* keyboard report utils */
void host_add_key(uint8_t key);
void host_del_key(uint8_t key);
+void host_clear_keys(void);
void host_add_mod_bit(uint8_t mod);
void host_del_mod_bit(uint8_t mod);
void host_set_mods(uint8_t mods);
-void host_add_code(uint8_t code);
-void host_del_code(uint8_t code);
-void host_swap_keyboard_report(void);
-void host_clear_keyboard_report(void);
+void host_clear_mods(void);
uint8_t host_has_anykey(void);
+uint8_t host_has_anymod(void);
uint8_t host_get_first_key(void);
+void host_send_keyboard_report(void);
+/* mouse report utils */
+uint8_t host_mouse_in_use(void);
-void host_send_keyboard_report(void);
-void host_mouse_send(report_mouse_t *report);
-void host_system_send(uint16_t data);
-void host_consumer_send(uint16_t data);
+uint16_t host_last_sysytem_report(void);
+uint16_t host_last_consumer_report(void);
#ifdef __cplusplus
}
diff --git a/common/keyboard.c b/common/keyboard.c
index 25f32eb02f..e973c46d5b 100644
--- a/common/keyboard.c
+++ b/common/keyboard.c
@@ -15,179 +15,609 @@ 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 "keycode.h"
#include "timer.h"
#include "print.h"
#include "debug.h"
#include "command.h"
+#include "util.h"
#ifdef MOUSEKEY_ENABLE
#include "mousekey.h"
#endif
-#ifdef EXTRAKEY_ENABLE
-#include <util/delay.h>
+
+
+#define Kdebug(s) do { if (debug_keyboard) debug(s); } while(0)
+#define Kdebug_P(s) do { if (debug_keyboard) debug_P(s); } while(0)
+#define Kdebug_hex(s) do { if (debug_keyboard) debug_hex(s); } while(0)
+
+#define LAYER_DELAY 250
+
+typedef enum keykind {
+ NONE,
+ FN_DOWN, FN_UP,
+ FNK_DOWN, FNK_UP,
+ KEY_DOWN, KEY_UP,
+ MOD_DOWN, MOD_UP,
+} keykind_t;
+
+typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
+
+
+#ifdef KEYMAP_DEFAULT_LAYER
+uint8_t default_layer = KEYMAP_DEFAULT_LAYER;
+uint8_t current_layer = KEYMAP_DEFAULT_LAYER;
+#else
+uint8_t default_layer = 0;
+uint8_t current_layer = 0;
#endif
+/* keyboard internal states */
+static kbdstate_t kbdstate = IDLE;
+static uint8_t fn_state_bits = 0;
+static keyrecord_t delayed_fn;
+static keyrecord_t waiting_key;
-static uint8_t last_leds = 0;
+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");
+}
-void keyboard_init(void)
+static inline keykind_t get_keykind(uint8_t code, bool pressed)
{
- timer_init();
- matrix_init();
-#ifdef PS2_MOUSE_ENABLE
- ps2_mouse_init();
-#endif
+ if IS_KEY(code) return (pressed ? KEY_DOWN : KEY_UP);
+ if IS_MOD(code) return (pressed ? MOD_DOWN : MOD_UP);
+ if IS_FN(code) {
+ if (keymap_fn_keycode(FN_INDEX(code)))
+ return (pressed ? FNK_DOWN : FNK_UP);
+ else
+ return (pressed ? FN_DOWN : FN_UP);
+ }
+ if IS_MOUSEKEY(code) return (pressed ? KEY_DOWN : KEY_UP);
+ if IS_SYSTEM(code) return (pressed ? KEY_DOWN : KEY_UP);
+ if IS_CONSUMER(code) return (pressed ? KEY_DOWN : KEY_UP);
+ return NONE;
}
-void keyboard_proc(void)
+static void clear_keyboard(void)
{
- uint8_t fn_bits = 0;
-#ifdef EXTRAKEY_ENABLE
- uint16_t consumer_code = 0;
- uint16_t system_code = 0;
+ host_clear_keys();
+ host_clear_mods();
+ host_send_keyboard_report();
+
+ host_system_send(0);
+ host_consumer_send(0);
+
+#ifdef MOUSEKEY_ENABLE
+ mousekey_clear();
+ mousekey_send();
#endif
+}
- matrix_scan();
+static void clear_keyboard_but_mods(void)
+{
+ host_clear_keys();
+ host_send_keyboard_report();
+
+ host_system_send(0);
+ host_consumer_send(0);
- if (matrix_is_modified()) {
- if (debug_matrix) matrix_print();
-#ifdef DEBUG_LED
- // LED flash for debug
- DEBUG_LED_CONFIG;
- DEBUG_LED_ON;
+#ifdef MOUSEKEY_ENABLE
+ mousekey_clear();
+ mousekey_send();
#endif
+}
+
+static bool anykey_sent_to_host(void)
+{
+ return (host_has_anykey() || host_mouse_in_use() ||
+ host_last_sysytem_report() || host_last_consumer_report());
+}
+
+static void layer_switch_on(uint8_t code)
+{
+ if (!IS_FN(code)) return;
+ fn_state_bits |= FN_BIT(code);
+ uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer);
+ if (current_layer != new_layer) {
+ Kdebug("Layer Switch(on): "); Kdebug_hex(current_layer);
+ Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");
+
+ clear_keyboard_but_mods();
+ current_layer = new_layer;
+ }
+}
+
+static bool layer_switch_off(uint8_t code)
+{
+ if (!IS_FN(code)) return false;
+ fn_state_bits &= ~FN_BIT(code);
+ uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer);
+ if (current_layer != new_layer) {
+ Kdebug("Layer Switch(off): "); Kdebug_hex(current_layer);
+ Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");
+
+ clear_keyboard_but_mods();
+ current_layer = new_layer;
+ return true;
}
+ return false;
+}
- if (matrix_has_ghost()) {
- // should send error?
- debug("matrix has ghost!!\n");
- return;
+static void register_code(uint8_t code)
+{
+ if IS_KEY(code) {
+ if (!command_proc(code)) {
+ host_add_key(code);
+ host_send_keyboard_report();
+ }
+ }
+ else if IS_MOD(code) {
+ host_add_mod_bit(MOD_BIT(code));
+ host_send_keyboard_report();
+ }
+ else if IS_FN(code) {
+ if (!command_proc(keymap_fn_keycode(FN_INDEX(code)))) {
+ host_add_key(keymap_fn_keycode(FN_INDEX(code)));
+ host_send_keyboard_report();
+ }
+ }
+ else if IS_MOUSEKEY(code) {
+#ifdef MOUSEKEY_ENABLE
+ mousekey_on(code);
+ mousekey_send();
+#endif
+ }
+ else if IS_CONSUMER(code) {
+ uint16_t usage = 0;
+ switch (code) {
+ case KC_AUDIO_MUTE:
+ usage = AUDIO_MUTE;
+ break;
+ case KC_AUDIO_VOL_UP:
+ usage = AUDIO_VOL_UP;
+ break;
+ case KC_AUDIO_VOL_DOWN:
+ usage = AUDIO_VOL_DOWN;
+ break;
+ case KC_MEDIA_NEXT_TRACK:
+ usage = TRANSPORT_NEXT_TRACK;
+ break;
+ case KC_MEDIA_PREV_TRACK:
+ usage = TRANSPORT_PREV_TRACK;
+ break;
+ case KC_MEDIA_STOP:
+ usage = TRANSPORT_STOP;
+ break;
+ case KC_MEDIA_PLAY_PAUSE:
+ usage = TRANSPORT_PLAY_PAUSE;
+ break;
+ case KC_MEDIA_SELECT:
+ usage = AL_CC_CONFIG;
+ break;
+ case KC_MAIL:
+ usage = AL_EMAIL;
+ break;
+ case KC_CALCULATOR:
+ usage = AL_CALCULATOR;
+ break;
+ case KC_MY_COMPUTER:
+ usage = AL_LOCAL_BROWSER;
+ break;
+ case KC_WWW_SEARCH:
+ usage = AC_SEARCH;
+ break;
+ case KC_WWW_HOME:
+ usage = AC_HOME;
+ break;
+ case KC_WWW_BACK:
+ usage = AC_BACK;
+ break;
+ case KC_WWW_FORWARD:
+ usage = AC_FORWARD;
+ break;
+ case KC_WWW_STOP:
+ usage = AC_STOP;
+ break;
+ case KC_WWW_REFRESH:
+ usage = AC_REFRESH;
+ break;
+ case KC_WWW_FAVORITES:
+ usage = AC_BOOKMARKS;
+ break;
+ }
+ host_consumer_send(usage);
+ }
+ else if IS_SYSTEM(code) {
+ uint16_t usage = 0;
+ switch (code) {
+ case KC_SYSTEM_POWER:
+ usage = SYSTEM_POWER_DOWN;
+ break;
+ case KC_SYSTEM_SLEEP:
+ usage = SYSTEM_SLEEP;
+ break;
+ case KC_SYSTEM_WAKE:
+ usage = SYSTEM_WAKE_UP;
+ break;
+ }
+ host_system_send(usage);
}
- 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 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_FN(code) {
+ host_del_key(keymap_fn_keycode(FN_INDEX(code)));
+ host_send_keyboard_report();
+ }
+ else if IS_MOUSEKEY(code) {
+#ifdef MOUSEKEY_ENABLE
+ mousekey_off(code);
+ mousekey_send();
#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;
+ }
+ else if IS_CONSUMER(code) {
+ host_consumer_send(0x0000);
+ }
+ else if IS_SYSTEM(code) {
+ host_system_send(0x0000);
+ }
+}
+
+/*
+ *
+ * Event/State|IDLE PRESSING DELAYING[f] WAITING[f,k]
+ * -----------+------------------------------------------------------------------
+ * Fn Down |(L+) -*1 WAITING(Sk) IDLE(Rf,Ps)*7
+ * Up |(L-) IDLE(L-)*8 IDLE(L-)*8 IDLE(L-)*8
+ * Fnk Down |DELAYING(Sf)* (Rf) WAITING(Sk) IDLE(Rf,Ps,Rf)
+ * Up |(L-) IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3
+ * Key Down |PRESSING(Rk) (Rk) WAITING(Sk) IDLE(Rf,Ps,Rk)
+ * Up |(Uk) IDLE(Uk)*4 (Uk) IDLE(L+,Ps,Pk)/(Uk)*a
+ * |
+ * Delay |- - IDLE(L+) IDLE(L+,Ps)
+ * Magic Key |COMMAND*5
+ *
+ * *1: ignore Fn if other key is down.
+ * *2: register Fnk if any key is pressing
+ * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8
+ * *4: if no keys registered to host
+ * *5: unregister all keys
+ * *6: only if no keys down
+ * *7: ignore Fn because Fnk key and stored key are down.
+ * *8: move to IDLE if layer switch(off) occurs, else stay at current state
+ * *9: repeat key if pressing Fnk twice quickly(move to PRESSING)
+ * *a: layer switch and process waiting key and code if code == wainting key, else unregister key
+ *
+ * States:
+ * IDLE: No key is down except modifiers
+ * DELAYING: delay layer switch after pressing Fn with alt keycode
+ * WAITING: key is pressed during DELAYING
+ *
+ * Events:
+ * Fn: Fn key without alternative keycode
+ * Fnk: Fn key with alternative keycode
+ * -: ignore
+ * Delay: layer switch delay term is elapsed
+ *
+ * Actions:
+ * Rk: register key
+ * Uk: unregister key
+ * Rf: register Fn(alt keycode)
+ * Uf: unregister Fn(alt keycode)
+ * Rs: register stored key
+ * Us: unregister stored key
+ * Sk: Store key(waiting Key)
+ * Sf: Store Fn(delayed Fn)
+ * Ps: Process stored key
+ * Ps: Process key
+ * Is: Interpret stored keys in current layer
+ * L+: Switch to new layer(*unregister* all keys but modifiers)
+ * L-: Switch back to last layer(*unregister* all keys but modifiers)
+ * Ld: Switch back to default layer(*unregister* all keys but modifiers)
+ */
+#define NEXT(state) do { \
+ Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \
+ kbdstate = state; \
+ Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \
+} while (0)
+
+static inline void process_key(keyevent_t event)
+{
+ uint8_t code = keymap_get_keycode(current_layer, event.key.row, event.key.col);
+ keykind_t kind = get_keykind(code, event.pressed);
+
+ uint8_t tmp_mods;
+
+ Kdebug("state: "); Kdebug_P(state_str(kbdstate));
+ Kdebug(" kind: "); Kdebug_hex(kind);
+ Kdebug(" code: "); Kdebug_hex(code);
+ if (event.pressed) { Kdebug("d"); } else { Kdebug("u"); }
+ Kdebug("\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:
+ // repeat Fn alt key when press Fn key down, up then down again quickly
+ if (KEYEQ(delayed_fn.event.key, event.key) &&
+ timer_elapsed(delayed_fn.time) < LAYER_DELAY) {
+ register_code(code);
+ NEXT(PRESSING);
+ } else {
+ 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:
+ register_code(code);
+ NEXT(PRESSING);
+ break;
+ case MOD_DOWN:
+ register_code(code);
+ break;
+ case KEY_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:
+ if (layer_switch_off(code))
+ NEXT(IDLE);
+ break;
+ case FNK_DOWN:
+ register_code(code);
+ break;
+ case FNK_UP:
+ if (layer_switch_off(code)) {
+ NEXT(IDLE);
+ } else {
+ unregister_code(code);
+ if (!anykey_sent_to_host())
+ NEXT(IDLE);
+ }
+ break;
+ case KEY_DOWN:
+ case MOD_DOWN:
+ register_code(code);
+ break;
+ case KEY_UP:
+ case MOD_UP:
+ unregister_code(code);
+ if (!anykey_sent_to_host())
+ 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:
+ 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:
+ if (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(delayed_fn.code);
+ unregister_code(delayed_fn.code);
+ host_set_mods(tmp_mods);
+ NEXT(IDLE);
+ } else {
+ if (layer_switch_off(code))
+ NEXT(IDLE);
+ }
+ break;
+ case KEY_UP:
+ 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:
+ tmp_mods = keyboard_report->mods;
+ host_set_mods(delayed_fn.mods);
+ register_code(delayed_fn.code);
+ host_set_mods(waiting_key.mods);
+ register_code(waiting_key.code);
+ host_set_mods(tmp_mods);
+ if (kind == FN_DOWN) {
+ // ignore Fn
+ } else if (kind == FNK_DOWN) {
+ register_code(code);
+ } else if (kind == KEY_DOWN) {
+ register_code(code);
+ }
+ NEXT(IDLE);
+ break;
+ case MOD_DOWN:
+ register_code(code);
+ break;
+ case FN_UP:
+ if (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(delayed_fn.code);
+ host_set_mods(waiting_key.mods);
+ register_code(waiting_key.code);
+ unregister_code(delayed_fn.code);
+ host_set_mods(tmp_mods);
+ NEXT(IDLE);
+ } else {
+ if (layer_switch_off(code))
+ NEXT(IDLE);
+ }
+ break;
+ case KEY_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);
+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;
- if (command_proc()) {
- return;
+ matrix_scan();
+ for (int r = 0; r < MATRIX_ROWS; r++) {
+ matrix_row = matrix_get_row(r);
+ matrix_change = matrix_row ^ matrix_prev[r];
+ if (matrix_change) {
+ if (debug_matrix) matrix_print();
+
+ 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: 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
+ // 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 MOUSEKEY_ENABLE
- mousekey_send();
-#endif
-
-#ifdef PS2_MOUSE_ENABLE
- // TODO: should comform new API
- if (ps2_mouse_read() == 0)
- ps2_mouse_usb_send();
+ // mousekey repeat & acceleration
+ mousekey_task();
#endif
- if (last_leds != host_keyboard_leds()) {
- keyboard_set_leds(host_keyboard_leds());
- last_leds = host_keyboard_leds();
+ // FAIL SAFE: clear all key if no key down
+ if (matrix_change) {
+ matrix_row_t is_matrix_on = 0;
+ for (int r = 0; r < MATRIX_ROWS; r++) {
+ is_matrix_on |= matrix_get_row(r);
+ }
+ if (!is_matrix_on) {
+ Kdebug("FAIL SAFE: clear all keys(default layer).\n");
+ clear_keyboard();
+ current_layer = default_layer;
+ }
}
+
+ return;
}
void keyboard_set_leds(uint8_t leds)
diff --git a/common/keyboard.h b/common/keyboard.h
index 51bf67379a..2353805e17 100644
--- 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/keycode.h b/common/keycode.h
new file mode 100644
index 0000000000..f9331cdbf3
--- /dev/null
+++ b/common/keycode.h
@@ -0,0 +1,448 @@
+/*
+Copyright 2011,2012 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/>.
+*/
+
+/*
+ * Keycodes based on HID Usage Keyboard/Keypad Page(0x07) plus special codes
+ * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
+ */
+#ifndef KEYCODE_H
+#define KEYCODE_H
+
+
+#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED)
+#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF)
+#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL)
+#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI)
+
+#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN7)
+#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2)
+#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT)
+#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN5)
+#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT)
+#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2)
+
+#define IS_SPECIAL(code) ((0xB0 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
+#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_WFAV)
+#define IS_SYSTEM(code) (KC_POWER <= (code) && (code) <= KC_WAKE)
+
+#define MOD_BIT(code) (1<<MOD_INDEX(code))
+#define MOD_INDEX(code) ((code) & 0x07)
+#define FN_BIT(code) (1<<FN_INDEX(code))
+#define FN_INDEX(code) ((code) - KC_FN0)
+
+
+/*
+ * Short names for ease of definition of keymap
+ */
+#define KC_LCTL KC_LCTRL
+#define KC_RCTL KC_RCTRL
+#define KC_LSFT KC_LSHIFT
+#define KC_RSFT KC_RSHIFT
+#define KC_ESC KC_ESCAPE
+#define KC_BSPC KC_BSPACE
+#define KC_ENT KC_ENTER
+#define KC_DEL KC_DELETE
+#define KC_INS KC_INSERT
+#define KC_CAPS KC_CAPSLOCK
+#define KC_RGHT KC_RIGHT
+#define KC_PGDN KC_PGDOWN
+#define KC_PSCR KC_PSCREEN
+#define KC_SLCK KC_SCKLOCK
+#define KC_PAUS KC_PAUSE
+#define KC_BRK KC_PAUSE
+#define KC_NLCK KC_NUMLOCK
+#define KC_SPC KC_SPACE
+#define KC_MINS KC_MINUS
+#define KC_EQL KC_EQUAL
+#define KC_GRV KC_GRAVE
+#define KC_RBRC KC_RBRACKET
+#define KC_LBRC KC_LBRACKET
+#define KC_COMM KC_COMMA
+#define KC_BSLS KC_BSLASH
+#define KC_SLSH KC_SLASH
+#define KC_SCLN KC_SCOLON
+#define KC_QUOT KC_QUOTE
+#define KC_APP KC_APPLICATION
+#define KC_NUHS KC_NONUS_HASH
+#define KC_NUBS KC_NONUS_BSLASH
+#define KC_ERAS KC_ALT_ERASE,
+#define KC_CLR KC_CLEAR
+/* Japanese specific */
+#define KC_ZKHK KC_GRAVE
+#define KC_RO KC_INT1
+#define KC_KANA KC_INT2
+#define KC_JYEN KC_INT3
+#define KC_HENK KC_INT4
+#define KC_MHEN KC_INT5
+/* Keypad */
+#define KC_P1 KC_KP_1
+#define KC_P2 KC_KP_2
+#define KC_P3 KC_KP_3
+#define KC_P4 KC_KP_4
+#define KC_P5 KC_KP_5
+#define KC_P6 KC_KP_6
+#define KC_P7 KC_KP_7
+#define KC_P8 KC_KP_8
+#define KC_P9 KC_KP_9
+#define KC_P0 KC_KP_0
+#define KC_PDOT KC_KP_DOT
+#define KC_PCMM KC_KP_COMMA
+#define KC_PSLS KC_KP_SLASH
+#define KC_PAST KC_KP_ASTERISK
+#define KC_PMNS KC_KP_MINUS
+#define KC_PPLS KC_KP_PLUS
+#define KC_PEQL KC_KP_EQUAL
+#define KC_PENT KC_KP_ENTER
+/* Mousekey */
+#define KC_MS_U KC_MS_UP
+#define KC_MS_D KC_MS_DOWN
+#define KC_MS_L KC_MS_LEFT
+#define KC_MS_R KC_MS_RIGHT
+#define KC_BTN1 KC_MS_BTN1
+#define KC_BTN2 KC_MS_BTN2
+#define KC_BTN3 KC_MS_BTN3
+#define KC_BTN4 KC_MS_BTN4
+#define KC_BTN5 KC_MS_BTN5
+#define KC_WH_U KC_MS_WH_UP
+#define KC_WH_D KC_MS_WH_DOWN
+#define KC_WH_L KC_MS_WH_LEFT
+#define KC_WH_R KC_MS_WH_RIGHT
+#define KC_ACL0 KC_MS_ACCEL0
+#define KC_ACL1 KC_MS_ACCEL1
+#define KC_ACL2 KC_MS_ACCEL2
+/* Sytem Control */
+#define KC_PWR KC_SYSTEM_POWER
+#define KC_SLEP KC_SYSTEM_SLEEP
+#define KC_WAKE KC_SYSTEM_WAKE
+/* Consumer Page */
+#define KC_MUTE KC_AUDIO_MUTE
+#define KC_VOLU KC_AUDIO_VOL_UP
+#define KC_VOLD KC_AUDIO_VOL_DOWN
+#define KC_MNXT KC_MEDIA_NEXT_TRACK
+#define KC_MPRV KC_MEDIA_PREV_TRACK
+#define KC_MSTP KC_MEDIA_STOP
+#define KC_MPLY KC_MEDIA_PLAY_PAUSE
+#define KC_MSEL KC_MEDIA_SELECT
+#define KC_MAIL KC_MAIL
+#define KC_CALC KC_CALCULATOR
+#define KC_MYCM KC_MY_COMPUTER
+#define KC_WSCH KC_WWW_SEARCH
+#define KC_WHOM KC_WWW_HOME
+#define KC_WBAK KC_WWW_BACK
+#define KC_WFWD KC_WWW_FORWARD
+#define KC_WSTP KC_WWW_STOP
+#define KC_WREF KC_WWW_REFRESH
+#define KC_WFAV KC_WWW_FAVORITES
+
+
+/* USB HID Keyboard/Keypad Usage(0x07) */
+enum hid_keyboard_keypad_usage {
+ KC_NO = 0x00,
+ KC_ROLL_OVER,
+ KC_POST_FAIL,
+ KC_UNDEFINED,
+ KC_A,
+ KC_B,
+ KC_C,
+ KC_D,
+ KC_E,
+ KC_F,
+ KC_G,
+ KC_H,
+ KC_I,
+ KC_J,
+ KC_K,
+ KC_L,
+ KC_M, /* 0x10 */
+ KC_N,
+ KC_O,
+ KC_P,
+ KC_Q,
+ KC_R,
+ KC_S,
+ KC_T,
+ KC_U,
+ KC_V,
+ KC_W,
+ KC_X,
+ KC_Y,
+ KC_Z,
+ KC_1,
+ KC_2,
+ KC_3, /* 0x20 */
+ KC_4,
+ KC_5,
+ KC_6,
+ KC_7,
+ KC_8,
+ KC_9,
+ KC_0,
+ KC_ENTER,
+ KC_ESCAPE,
+ KC_BSPACE,
+ KC_TAB,
+ KC_SPACE,
+ KC_MINUS,
+ KC_EQUAL,
+ KC_LBRACKET,
+ KC_RBRACKET, /* 0x30 */
+ KC_BSLASH, /* \ (and |) */
+ KC_NONUS_HASH, /* Non-US # and ~ */
+ KC_SCOLON, /* ; (and :) */
+ KC_QUOTE, /* ' and " */
+ KC_GRAVE, /* Grave accent and tilde */
+ KC_COMMA, /* , and < */
+ KC_DOT, /* . and > */
+ KC_SLASH, /* / and ? */
+ KC_CAPSLOCK,
+ KC_F1,
+ KC_F2,
+ KC_F3,
+ KC_F4,
+ KC_F5,
+ KC_F6,
+ KC_F7, /* 0x40 */
+ KC_F8,
+ KC_F9,
+ KC_F10,
+ KC_F11,
+ KC_F12,
+ KC_PSCREEN,
+ KC_SCKLOCK,
+ KC_PAUSE,
+ KC_INSERT,
+ KC_HOME,
+ KC_PGUP,
+ KC_DELETE,
+ KC_END,
+ KC_PGDOWN,
+ KC_RIGHT,
+ KC_LEFT, /* 0x50 */
+ KC_DOWN,
+ KC_UP,
+ KC_NUMLOCK,
+ KC_KP_SLASH,
+ KC_KP_ASTERISK,
+ KC_KP_MINUS,
+ KC_KP_PLUS,
+ KC_KP_ENTER,
+ KC_KP_1,
+ KC_KP_2,
+ KC_KP_3,
+ KC_KP_4,
+ KC_KP_5,
+ KC_KP_6,
+ KC_KP_7,
+ KC_KP_8, /* 0x60 */
+ KC_KP_9,
+ KC_KP_0,
+ KC_KP_DOT,
+ KC_NONUS_BSLASH, /* Non-US \ and | */
+ KC_APPLICATION,
+ KC_POWER,
+ KC_KP_EQUAL,
+ KC_F13,
+ KC_F14,
+ KC_F15,
+ KC_F16,
+ KC_F17,
+ KC_F18,
+ KC_F19,
+ KC_F20,
+ KC_F21, /* 0x70 */
+ KC_F22,
+ KC_F23,
+ KC_F24,
+ KC_EXECUTE,
+ KC_HELP,
+ KC_MENU,
+ KC_SELECT,
+ KC_STOP,
+ KC_AGAIN,
+ KC_UNDO,
+ KC_CUT,
+ KC_COPY,
+ KC_PASTE,
+ KC_FIND,
+ KC__MUTE,
+ KC__VOLUP, /* 0x80 */
+ KC__VOLDOWN,
+ KC_LOCKING_CAPS, /* locking Caps Lock */
+ KC_LOCKING_NUM, /* locking Num Lock */
+ KC_LOCKING_SCROLL, /* locking Scroll Lock */
+ KC_KP_COMMA,
+ KC_KP_EQUAL_AS400, /* equal sign on AS/400 */
+ KC_INT1,
+ KC_INT2,
+ KC_INT3,
+ KC_INT4,
+ KC_INT5,
+ KC_INT6,
+ KC_INT7,
+ KC_INT8,
+ KC_INT9,
+ KC_LANG1, /* 0x90 */
+ KC_LANG2,
+ KC_LANG3,
+ KC_LANG4,
+ KC_LANG5,
+ KC_LANG6,
+ KC_LANG7,
+ KC_LANG8,
+ KC_LANG9,
+ KC_ALT_ERASE,
+ KC_SYSREQ,
+ KC_CANCEL,
+ KC_CLEAR,
+ KC_PRIOR,
+ KC_RETURN,
+ KC_SEPARATOR,
+ KC_OUT, /* 0xA0 */
+ KC_OPER,
+ KC_CLEAR_AGAIN,
+ KC_CRSEL,
+ KC_EXSEL, /* 0xA4 */
+
+ /* NOTE: 0xA5-DF are used for internal special purpose */
+
+#if 0
+ /* NOTE: Following codes(0xB0-DD) are not used. Leave them for reference. */
+ KC_KP_00 = 0xB0,
+ KC_KP_000,
+ KC_THOUSANDS_SEPARATOR,
+ KC_DECIMAL_SEPARATOR,
+ KC_CURRENCY_UNIT,
+ KC_CURRENCY_SUB_UNIT,
+ KC_KP_LPAREN,
+ KC_KP_RPAREN,
+ KC_KP_LCBRACKET, /* { */
+ KC_KP_RCBRACKET, /* } */
+ KC_KP_TAB,
+ KC_KP_BSPACE,
+ KC_KP_A,
+ KC_KP_B,
+ KC_KP_C,
+ KC_KP_D,
+ KC_KP_E, /* 0xC0 */
+ KC_KP_F,
+ KC_KP_XOR,
+ KC_KP_HAT,
+ KC_KP_PERC,
+ KC_KP_LT,
+ KC_KP_GT,
+ KC_KP_AND,
+ KC_KP_LAZYAND,
+ KC_KP_OR,
+ KC_KP_LAZYOR,
+ KC_KP_COLON,
+ KC_KP_HASH,
+ KC_KP_SPACE,
+ KC_KP_ATMARK,
+ KC_KP_EXCLAMATION,
+ KC_KP_MEM_STORE, /* 0xD0 */
+ KC_KP_MEM_RECALL,
+ KC_KP_MEM_CLEAR,
+ KC_KP_MEM_ADD,
+ KC_KP_MEM_SUB,
+ KC_KP_MEM_MUL,
+ KC_KP_MEM_DIV,
+ KC_KP_PLUS_MINUS,
+ KC_KP_CLEAR,
+ KC_KP_CLEAR_ENTRY,
+ KC_KP_BINARY,
+ KC_KP_OCTAL,
+ KC_KP_DECIMAL,
+ KC_KP_HEXADECIMAL, /* 0xDD */
+#endif
+
+ /* Modifiers */
+ KC_LCTRL = 0xE0,
+ KC_LSHIFT,
+ KC_LALT,
+ KC_LGUI,
+ KC_RCTRL,
+ KC_RSHIFT,
+ KC_RALT,
+ KC_RGUI,
+
+ /* NOTE: 0xE8-FF are used for internal special purpose */
+};
+
+/* Special keycodes */
+/* NOTE: 0xA5-DF and 0xE8-FF are used for internal special purpose */
+enum internal_special_keycodes {
+ /* System Control */
+ KC_SYSTEM_POWER = 0xA5,
+ KC_SYSTEM_SLEEP,
+ KC_SYSTEM_WAKE, /* 0xA7 */
+ /* 0xA8-AF */
+
+ /* Consumer Page */
+ KC_AUDIO_MUTE = 0xB0,
+ KC_AUDIO_VOL_UP,
+ KC_AUDIO_VOL_DOWN,
+ KC_MEDIA_NEXT_TRACK,
+ KC_MEDIA_PREV_TRACK,
+ KC_MEDIA_STOP,
+ KC_MEDIA_PLAY_PAUSE,
+ KC_MEDIA_SELECT,
+ KC_MAIL,
+ KC_CALCULATOR,
+ KC_MY_COMPUTER,
+ KC_WWW_SEARCH,
+ KC_WWW_HOME,
+ KC_WWW_BACK,
+ KC_WWW_FORWARD,
+ KC_WWW_STOP,
+ KC_WWW_REFRESH, /* 0xC0 */
+ KC_WWW_FAVORITES, /* 0xC1 */
+ /* 0xC2-DF vacant for future use */
+
+ /* 0xE0-E7 for Modifiers. DO NOT USE. */
+
+ /* Layer Switching */
+ KC_FN0 = 0xE8,
+ KC_FN1,
+ KC_FN2,
+ KC_FN3,
+ KC_FN4,
+ KC_FN5,
+ KC_FN6,
+ KC_FN7, /* 0xEF */
+
+ /* Mousekey */
+ KC_MS_UP = 0xF0,
+ KC_MS_DOWN,
+ KC_MS_LEFT,
+ KC_MS_RIGHT,
+ KC_MS_BTN1,
+ KC_MS_BTN2,
+ KC_MS_BTN3,
+ KC_MS_BTN4,
+ KC_MS_BTN5, /* 0xF8 */
+ /* Mousekey wheel */
+ KC_MS_WH_UP,
+ KC_MS_WH_DOWN,
+ KC_MS_WH_LEFT,
+ KC_MS_WH_RIGHT, /* 0xFC */
+ /* Mousekey accel */
+ KC_MS_ACCEL0,
+ KC_MS_ACCEL1,
+ KC_MS_ACCEL2 /* 0xFF */
+};
+
+#endif /* KEYCODE_H */
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..b8af3e59c7 100644
--- a/common/mousekey.c
+++ b/common/mousekey.c
@@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <util/delay.h>
-#include "usb_keycodes.h"
+#include "keycode.h"
#include "host.h"
#include "timer.h"
#include "print.h"
@@ -25,108 +25,172 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "mousekey.h"
-static report_mouse_t report;
-static report_mouse_t report_prev;
static uint8_t mousekey_repeat = 0;
+static uint8_t mousekey_accel = 0;
static void mousekey_debug(void);
/*
- * TODO: fix acceleration algorithm
- * see wikipedia http://en.wikipedia.org/wiki/Mouse_keys
+ * Mouse keys acceleration algorithm
+ * http://en.wikipedia.org/wiki/Mouse_keys
+ *
+ * speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
*/
-#ifndef MOUSEKEY_DELAY_TIME
-# define MOUSEKEY_DELAY_TIME 255
-#endif
+/* milliseconds between the initial key press and first repeated motion event (0-2550) */
+uint8_t mk_delay = MOUSEKEY_DELAY/10;
+/* milliseconds between repeated motion events (0-255) */
+uint8_t mk_interval = MOUSEKEY_INTERVAL;
+/* steady speed (in action_delta units) applied each event (0-255) */
+uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED;
+/* number of events (count) accelerating to steady speed (0-255) */
+uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
+/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
+//int8_t mk_curve = 0;
+/* wheel params */
+uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
+uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
-// acceleration parameters
-uint8_t mousekey_move_unit = 2;
-uint8_t mousekey_resolution = 5;
+static uint16_t last_timer = 0;
-static inline uint8_t move_unit(void)
-{
- uint16_t unit = 5 + mousekey_repeat*2;
- return (unit > 63 ? 63 : unit);
-}
-void mousekey_decode(uint8_t code)
+static uint8_t move_unit(void)
{
- 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;
+ uint16_t unit;
+ if (mousekey_accel & (1<<0)) {
+ unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/4;
+ } else if (mousekey_accel & (1<<1)) {
+ unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/2;
+ } else if (mousekey_accel & (1<<2)) {
+ unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
+ } else if (mousekey_repeat == 0) {
+ unit = MOUSEKEY_MOVE_DELTA;
+ } else if (mousekey_repeat >= mk_time_to_max) {
+ unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
+ } else {
+ unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
+ }
+ return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
}
-bool mousekey_changed(void)
+static uint8_t wheel_unit(void)
{
- return (report.buttons != report_prev.buttons ||
- report.x || report.y || report.v || report.h);
+ uint16_t unit;
+ if (mousekey_accel & (1<<0)) {
+ unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/4;
+ } else if (mousekey_accel & (1<<1)) {
+ unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/2;
+ } else if (mousekey_accel & (1<<2)) {
+ unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
+ } else if (mousekey_repeat == 0) {
+ unit = MOUSEKEY_WHEEL_DELTA;
+ } else if (mousekey_repeat >= mk_time_to_max) {
+ unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
+ } else {
+ unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
+ }
+ return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
}
-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_repeat ? mk_interval : mk_delay*10))
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 (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
+ return;
- if (mousekey_repeat != 0xFF) {
+ if (mousekey_repeat != UINT8_MAX)
mousekey_repeat++;
- }
- if (report.x && report.y) {
- report.x *= 0.7;
- report.y *= 0.7;
+
+ if (mouse_report.x > 0) mouse_report.x = move_unit();
+ if (mouse_report.x < 0) mouse_report.x = move_unit() * -1;
+ if (mouse_report.y > 0) mouse_report.y = move_unit();
+ if (mouse_report.y < 0) mouse_report.y = move_unit() * -1;
+
+ /* diagonal move [1/sqrt(2) = 0.7] */
+ if (mouse_report.x && mouse_report.y) {
+ mouse_report.x *= 0.7;
+ mouse_report.y *= 0.7;
}
+ if (mouse_report.v > 0) mouse_report.v = wheel_unit();
+ if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1;
+ if (mouse_report.h > 0) mouse_report.h = wheel_unit();
+ if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1;
+
+ mousekey_send();
+}
+
+void mousekey_on(uint8_t code)
+{
+ if (code == KC_MS_UP) mouse_report.y = move_unit() * -1;
+ else if (code == KC_MS_DOWN) mouse_report.y = move_unit();
+ else if (code == KC_MS_LEFT) mouse_report.x = move_unit() * -1;
+ else if (code == KC_MS_RIGHT) mouse_report.x = move_unit();
+ else if (code == KC_MS_WH_UP) mouse_report.v = wheel_unit();
+ else if (code == KC_MS_WH_DOWN) mouse_report.v = wheel_unit() * -1;
+ else if (code == KC_MS_WH_LEFT) mouse_report.h = wheel_unit() * -1;
+ else if (code == KC_MS_WH_RIGHT) mouse_report.h = wheel_unit();
+ else if (code == KC_MS_BTN1) mouse_report.buttons |= MOUSE_BTN1;
+ else if (code == KC_MS_BTN2) mouse_report.buttons |= MOUSE_BTN2;
+ else if (code == KC_MS_BTN3) mouse_report.buttons |= MOUSE_BTN3;
+ else if (code == KC_MS_BTN4) mouse_report.buttons |= MOUSE_BTN4;
+ else if (code == KC_MS_BTN5) mouse_report.buttons |= MOUSE_BTN5;
+ else if (code == KC_MS_ACCEL0) mousekey_accel |= (1<<0);
+ else if (code == KC_MS_ACCEL1) mousekey_accel |= (1<<1);
+ else if (code == KC_MS_ACCEL2) mousekey_accel |= (1<<2);
+}
+
+void mousekey_off(uint8_t code)
+{
+ if (code == KC_MS_UP && mouse_report.y < 0) mouse_report.y = 0;
+ else if (code == KC_MS_DOWN && mouse_report.y > 0) mouse_report.y = 0;
+ else if (code == KC_MS_LEFT && mouse_report.x < 0) mouse_report.x = 0;
+ else if (code == KC_MS_RIGHT && mouse_report.x > 0) mouse_report.x = 0;
+ else if (code == KC_MS_WH_UP && mouse_report.v > 0) mouse_report.v = 0;
+ else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) mouse_report.v = 0;
+ else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) mouse_report.h = 0;
+ else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) mouse_report.h = 0;
+ else if (code == KC_MS_BTN1) mouse_report.buttons &= ~MOUSE_BTN1;
+ else if (code == KC_MS_BTN2) mouse_report.buttons &= ~MOUSE_BTN2;
+ else if (code == KC_MS_BTN3) mouse_report.buttons &= ~MOUSE_BTN3;
+ else if (code == KC_MS_BTN4) mouse_report.buttons &= ~MOUSE_BTN4;
+ else if (code == KC_MS_BTN5) mouse_report.buttons &= ~MOUSE_BTN5;
+ else if (code == KC_MS_ACCEL0) mousekey_accel &= ~(1<<0);
+ else if (code == KC_MS_ACCEL1) mousekey_accel &= ~(1<<1);
+ else if (code == KC_MS_ACCEL2) mousekey_accel &= ~(1<<2);
+
+ if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
+ mousekey_repeat = 0;
+}
+
+void mousekey_send(void)
+{
mousekey_debug();
- host_mouse_send(&report);
- report_prev = report;
+ host_mouse_send(&mouse_report);
last_timer = timer_read();
- mousekey_clear_report();
}
-void mousekey_clear_report(void)
+void mousekey_clear(void)
{
- report.buttons = 0;
- report.x = 0;
- report.y = 0;
- report.v = 0;
- report.h = 0;
+ mouse_report = (report_mouse_t){};
+ mousekey_repeat = 0;
+ mousekey_accel = 0;
}
static void mousekey_debug(void)
{
if (!debug_mouse) return;
- print("mousekey [btn|x y v h]rep: [");
- phex(report.buttons); print("|");
- phex(report.x); print(" ");
- phex(report.y); print(" ");
- phex(report.v); print(" ");
- phex(report.h); print("]");
- phex(mousekey_repeat);
- print("\n");
+ print("mousekey [btn|x y v h](rep/acl): [");
+ phex(mouse_report.buttons); print("|");
+ phex(mouse_report.x); print(" ");
+ phex(mouse_report.y); print(" ");
+ phex(mouse_report.v); print(" ");
+ phex(mouse_report.h); print("](");
+ phex(mousekey_repeat); print("/");
+ phex(mousekey_accel); print(")\n");
}
diff --git a/common/mousekey.h b/common/mousekey.h
index c2c24e9fa5..ac26a46c89 100644
--- a/common/mousekey.h
+++ b/common/mousekey.h
@@ -21,9 +21,49 @@ 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);
+
+/* max value on report descriptor */
+#define MOUSEKEY_MOVE_MAX 127
+#define MOUSEKEY_WHEEL_MAX 127
+
+#ifndef MOUSEKEY_MOVE_DELTA
+#define MOUSEKEY_MOVE_DELTA 5
+#endif
+#ifndef MOUSEKEY_WHEEL_DELTA
+#define MOUSEKEY_WHEEL_DELTA 1
+#endif
+#ifndef MOUSEKEY_DELAY
+#define MOUSEKEY_DELAY 300
+#endif
+#ifndef MOUSEKEY_INTERVAL
+#define MOUSEKEY_INTERVAL 50
+#endif
+#ifndef MOUSEKEY_MAX_SPEED
+#define MOUSEKEY_MAX_SPEED 10
+#endif
+#ifndef MOUSEKEY_TIME_TO_MAX
+#define MOUSEKEY_TIME_TO_MAX 20
+#endif
+#ifndef MOUSEKEY_WHEEL_MAX_SPEED
+#define MOUSEKEY_WHEEL_MAX_SPEED 16
+#endif
+#ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
+#define MOUSEKEY_WHEEL_TIME_TO_MAX 40
+#endif
+
+
+uint8_t mk_delay;
+uint8_t mk_interval;
+uint8_t mk_max_speed;
+uint8_t mk_time_to_max;
+uint8_t mk_wheel_max_speed;
+uint8_t mk_wheel_time_to_max;
+
+
+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/print.c b/common/print.c
index 558181ea72..4e36d3935b 100644
--- a/common/print.c
+++ b/common/print.c
@@ -75,6 +75,14 @@ void phex16(unsigned int i)
phex(i);
}
+void pdec(uint8_t i)
+{
+ if (!print_enable) return;
+ if (i/100) sendchar('0' + (i/100));
+ if (i/100 || i%100/10) sendchar('0' + (i%100/10));
+ sendchar('0' + (i%10));
+}
+
void pbin(unsigned char c)
{
diff --git a/common/print.h b/common/print.h
index d55f5695dc..1c4567862f 100644
--- a/common/print.h
+++ b/common/print.h
@@ -45,6 +45,7 @@ void print_S(const char *s);
void print_P(const char *s);
void phex(unsigned char c);
void phex16(unsigned int i);
+void pdec(uint8_t i);
void pbin(unsigned char c);
void pbin_reverse(unsigned char c);
#ifdef __cplusplus
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
deleted file mode 100644
index 04b398fa2a..0000000000
--- a/common/usb_keycodes.h
+++ /dev/null
@@ -1,424 +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/>.
-*/
-
-/*
- * Key codes: HID Keyboard/Keypad Page(0x07)
- * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
- */
-#ifndef USB_KEYCODES_H
-#define USB_KEYCODES_H
-
-
-#define IS_ERROR(code) (KB_ROLL_OVER <= (code) && (code) <= KB_UNDEFINED)
-#define IS_ANY(code) (KB_A <= (code))
-#define IS_KEY(code) (KB_A <= (code) && (code) <= KB_EXSEL)
-#define IS_MOD(code) (KB_LCTRL <= (code) && (code) <= KB_RGUI)
-#define IS_FN(code) (KB_FN0 <= (code) && (code) <= KB_FN7)
-#define IS_MOUSEKEY(code) (KB_MS_UP <= (code) && (code) <= KB_MS_WH_RIGHT)
-#define IS_MOUSEKEY_MOVE(code) (KB_MS_UP <= (code) && (code) <= KB_MS_RIGHT)
-#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))
-
-
-/* Short names */
-#define KB_LCTL KB_LCTRL
-#define KB_RCTL KB_RCTRL
-#define KB_LSFT KB_LSHIFT
-#define KB_RSFT KB_RSHIFT
-#define KB_ESC KB_ESCAPE
-#define KB_BSPC KB_BSPACE
-#define KB_ENT KB_ENTER
-#define KB_DEL KB_DELETE
-#define KB_INS KB_INSERT
-#define KB_CAPS KB_CAPSLOCK
-#define KB_RGHT KB_RIGHT
-#define KB_PGDN KB_PGDOWN
-#define KB_PSCR KB_PSCREEN
-#define KB_SLCK KB_SCKLOCK
-#define KB_PAUS KB_PAUSE
-#define KB_BRK KB_PAUSE
-#define KB_NLCK KB_NUMLOCK
-#define KB_SPC KB_SPACE
-#define KB_MINS KB_MINUS
-#define KB_EQL KB_EQUAL
-#define KB_GRV KB_GRAVE
-#define KB_RBRC KB_RBRACKET
-#define KB_LBRC KB_LBRACKET
-#define KB_COMM KB_COMMA
-#define KB_BSLS KB_BSLASH
-#define KB_SLSH KB_SLASH
-#define KB_SCLN KB_SCOLON
-#define KB_QUOT KB_QUOTE
-#define KB_APP KB_APPLICATION
-#define KB_NUHS KB_NONUS_HASH
-#define KB_NUBS KB_NONUS_BSLASH
-#define KB_ERAS KB_ALT_ERASE,
-#define KB_CLR KB_CLEAR
-/* for Japanese */
-#define KB_ZKHK KB_GRAVE
-#define KB_RO KB_INT1
-#define KB_KANA KB_INT2
-#define KB_JYEN KB_INT3
-#define KB_HENK KB_INT4
-#define KB_MHEN KB_INT5
-/* Keypad */
-#define KB_P1 KB_KP_1
-#define KB_P2 KB_KP_2
-#define KB_P3 KB_KP_3
-#define KB_P4 KB_KP_4
-#define KB_P5 KB_KP_5
-#define KB_P6 KB_KP_6
-#define KB_P7 KB_KP_7
-#define KB_P8 KB_KP_8
-#define KB_P9 KB_KP_9
-#define KB_P0 KB_KP_0
-#define KB_PDOT KB_KP_DOT
-#define KB_PCMM KB_KP_COMMA
-#define KB_PSLS KB_KP_SLASH
-#define KB_PAST KB_KP_ASTERISK
-#define KB_PMNS KB_KP_MINUS
-#define KB_PPLS KB_KP_PLUS
-#define KB_PEQL KB_KP_EQUAL
-#define KB_PENT KB_KP_ENTER
-/* Mousekey */
-#define KB_MS_U KB_MS_UP
-#define KB_MS_D KB_MS_DOWN
-#define KB_MS_L KB_MS_LEFT
-#define KB_MS_R KB_MS_RIGHT
-#define KB_BTN1 KB_MS_BTN1
-#define KB_BTN2 KB_MS_BTN2
-#define KB_BTN3 KB_MS_BTN3
-#define KB_BTN4 KB_MS_BTN4
-#define KB_BTN5 KB_MS_BTN5
-#define KB_WH_U KB_MS_WH_UP
-#define KB_WH_D KB_MS_WH_DOWN
-#define KB_WH_L KB_MS_WH_LEFT
-#define KB_WH_R KB_MS_WH_RIGHT
-/* Sytem Control & Consumer usage */
-#define KB_PWR KB_SYSTEM_POWER
-#define KB_SLEP KB_SYSTEM_SLEEP
-#define KB_WAKE KB_SYSTEM_WAKE
-#define KB_MUTE KB_AUDIO_MUTE
-#define KB_VOLU KB_AUDIO_VOL_UP
-#define KB_VOLD KB_AUDIO_VOL_DOWN
-#define KB_MNXT KB_MEDIA_NEXT_TRACK
-#define KB_MPRV KB_MEDIA_PREV_TRACK
-#define KB_MSTP KB_MEDIA_STOP
-#define KB_MPLY KB_MEDIA_PLAY_PAUSE
-#define KB_MSEL KB_MEDIA_SELECT
-#define KB_MAIL KB_MAIL
-#define KB_CALC KB_CALCULATOR
-#define KB_MYCM KB_MY_COMPUTER
-#define KB_WSCH KB_WWW_SEARCH
-#define KB_WHOM KB_WWW_HOME
-#define KB_WBAK KB_WWW_BACK
-#define KB_WFWD KB_WWW_FORWARD
-#define KB_WSTP KB_WWW_STOP
-#define KB_WREF KB_WWW_REFRESH
-#define KB_WFAV KB_WWW_FAVORITES
-
-
-/* Special keycode */
-enum special_keycodes {
- /* System Control */
- KB_SYSTEM_POWER = 0xB0,
- KB_SYSTEM_SLEEP,
- KB_SYSTEM_WAKE,
-
- /* Consumer Page */
- KB_AUDIO_MUTE,
- KB_AUDIO_VOL_UP,
- KB_AUDIO_VOL_DOWN,
- KB_MEDIA_NEXT_TRACK,
- KB_MEDIA_PREV_TRACK,
- KB_MEDIA_STOP,
- KB_MEDIA_PLAY_PAUSE,
- KB_MEDIA_SELECT,
- KB_MAIL,
- KB_CALCULATOR,
- KB_MY_COMPUTER,
- KB_WWW_SEARCH,
- KB_WWW_HOME,
- KB_WWW_BACK, /* 0xC0 */
- KB_WWW_FORWARD,
- KB_WWW_STOP,
- KB_WWW_REFRESH,
- KB_WWW_FAVORITES,
-
- /* reserve 0xE0-E7 for Modifiers */
-
- /* Layer Switching */
- KB_FN0 = 0xE8,
- KB_FN1,
- KB_FN2,
- KB_FN3,
- KB_FN4,
- KB_FN5,
- KB_FN6,
- KB_FN7,
-
- /* Mousekey */
- KB_MS_UP = 0xF0,
- KB_MS_DOWN,
- KB_MS_LEFT,
- KB_MS_RIGHT,
- KB_MS_BTN1,
- KB_MS_BTN2,
- KB_MS_BTN3,
- KB_MS_BTN4,
- KB_MS_BTN5,
- /* Mousekey wheel */
- KB_MS_WH_UP,
- KB_MS_WH_DOWN,
- KB_MS_WH_LEFT,
- KB_MS_WH_RIGHT,
-};
-
-enum keycodes {
- KB_NO = 0,
- KB_ROLL_OVER,
- KB_POST_FAIL,
- KB_UNDEFINED,
- KB_A,
- KB_B,
- KB_C,
- KB_D,
- KB_E,
- KB_F,
- KB_G,
- KB_H,
- KB_I,
- KB_J,
- KB_K,
- KB_L,
- KB_M, /* 0x10 */
- KB_N,
- KB_O,
- KB_P,
- KB_Q,
- KB_R,
- KB_S,
- KB_T,
- KB_U,
- KB_V,
- KB_W,
- KB_X,
- KB_Y,
- KB_Z,
- KB_1,
- KB_2,
- KB_3, /* 0x20 */
- KB_4,
- KB_5,
- KB_6,
- KB_7,
- KB_8,
- KB_9,
- KB_0,
- KB_ENTER,
- KB_ESCAPE,
- KB_BSPACE,
- KB_TAB,
- KB_SPACE,
- KB_MINUS,
- KB_EQUAL,
- KB_LBRACKET,
- KB_RBRACKET, /* 0x30 */
- KB_BSLASH, /* \ (and |) */
- KB_NONUS_HASH, /* Non-US # and ~ */
- KB_SCOLON, /* ; (and :) */
- KB_QUOTE, /* ' and " */
- KB_GRAVE, /* Grave accent and tilde */
- KB_COMMA, /* , and < */
- KB_DOT, /* . and > */
- KB_SLASH, /* / and ? */
- KB_CAPSLOCK,
- KB_F1,
- KB_F2,
- KB_F3,
- KB_F4,
- KB_F5,
- KB_F6,
- KB_F7, /* 0x40 */
- KB_F8,
- KB_F9,
- KB_F10,
- KB_F11,
- KB_F12,
- KB_PSCREEN,
- KB_SCKLOCK,
- KB_PAUSE,
- KB_INSERT,
- KB_HOME,
- KB_PGUP,
- KB_DELETE,
- KB_END,
- KB_PGDOWN,
- KB_RIGHT,
- KB_LEFT, /* 0x50 */
- KB_DOWN,
- KB_UP,
- KB_NUMLOCK,
- KB_KP_SLASH,
- KB_KP_ASTERISK,
- KB_KP_MINUS,
- KB_KP_PLUS,
- KB_KP_ENTER,
- KB_KP_1,
- KB_KP_2,
- KB_KP_3,
- KB_KP_4,
- KB_KP_5,
- KB_KP_6,
- KB_KP_7,
- KB_KP_8, /* 0x60 */
- KB_KP_9,
- KB_KP_0,
- KB_KP_DOT,
- KB_NONUS_BSLASH, /* Non-US \ and | */
- KB_APPLICATION,
- KB_POWER,
- KB_KP_EQUAL,
- KB_F13,
- KB_F14,
- KB_F15,
- KB_F16,
- KB_F17,
- KB_F18,
- KB_F19,
- KB_F20,
- KB_F21, /* 0x70 */
- KB_F22,
- KB_F23,
- KB_F24,
- KB_EXECUTE,
- KB_HELP,
- KB_MENU,
- KB_SELECT,
- KB_STOP,
- KB_AGAIN,
- KB_UNDO,
- KB_CUT,
- KB_COPY,
- KB_PASTE,
- KB_FIND,
- KB__MUTE,
- KB__VOLUP, /* 0x80 */
- KB__VOLDOWN,
- KB_LOCKING_CAPS, /* locking Caps Lock */
- KB_LOCKING_NUM, /* locking Num Lock */
- KB_LOCKING_SCROLL, /* locking Scroll Lock */
- KB_KP_COMMA,
- KB_KP_EQUAL_AS400, /* equal sign on AS/400 */
- KB_INT1,
- KB_INT2,
- KB_INT3,
- KB_INT4,
- KB_INT5,
- KB_INT6,
- KB_INT7,
- KB_INT8,
- KB_INT9,
- KB_LANG1, /* 0x90 */
- KB_LANG2,
- KB_LANG3,
- KB_LANG4,
- KB_LANG5,
- KB_LANG6,
- KB_LANG7,
- KB_LANG8,
- KB_LANG9,
- KB_ALT_ERASE,
- KB_SYSREQ,
- KB_CANCEL,
- KB_CLEAR,
- KB_PRIOR,
- KB_RETURN,
- KB_SEPARATOR,
- KB_OUT, /* 0xA0 */
- KB_OPER,
- KB_CLEAR_AGAIN,
- KB_CRSEL,
- KB_EXSEL,
-
- /* NOTE: 0xB0-DF are used as special_keycodes */
-#if 0
- KB_KP_00 = 0xB0,
- KB_KP_000,
- KB_THOUSANDS_SEPARATOR,
- KB_DECIMAL_SEPARATOR,
- KB_CURRENCY_UNIT,
- KB_CURRENCY_SUB_UNIT,
- KB_KP_LPAREN,
- KB_KP_RPAREN,
- KB_KP_LCBRACKET, /* { */
- KB_KP_RCBRACKET, /* } */
- KB_KP_TAB,
- KB_KP_BSPACE,
- KB_KP_A,
- KB_KP_B,
- KB_KP_C,
- KB_KP_D,
- KB_KP_E, /* 0xC0 */
- KB_KP_F,
- KB_KP_XOR,
- KB_KP_HAT,
- KB_KP_PERC,
- KB_KP_LT,
- KB_KP_GT,
- KB_KP_AND,
- KB_KP_LAZYAND,
- KB_KP_OR,
- KB_KP_LAZYOR,
- KB_KP_COLON,
- KB_KP_HASH,
- KB_KP_SPACE,
- KB_KP_ATMARK,
- KB_KP_EXCLAMATION,
- KB_KP_MEM_STORE, /* 0xD0 */
- KB_KP_MEM_RECALL,
- KB_KP_MEM_CLEAR,
- KB_KP_MEM_ADD,
- KB_KP_MEM_SUB,
- KB_KP_MEM_MUL,
- KB_KP_MEM_DIV,
- KB_KP_PLUS_MINUS,
- KB_KP_CLEAR,
- KB_KP_CLEAR_ENTRY,
- KB_KP_BINARY,
- KB_KP_OCTAL,
- KB_KP_DECIMAL,
- KB_KP_HEXADECIMAL,
-#endif
-
- /* Modifiers */
- KB_LCTRL = 0xE0,
- KB_LSHIFT,
- KB_LALT,
- KB_LGUI,
- KB_RCTRL,
- KB_RSHIFT,
- KB_RALT,
- KB_RGUI,
-
- /* NOTE: 0xE8-FF are used as special_keycodes */
-};
-
-#endif /* USB_KEYCODES_H */
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