aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorGravatar tmk <nobody@nowhere>2013-01-28 14:06:42 +0900
committerGravatar tmk <nobody@nowhere>2013-01-28 14:06:42 +0900
commit1e3e41a2c9ed8b2f7d44be0aed5d96ed557fa13d (patch)
tree4846c3d3f8144b3796322ac669d13837f4e09f17 /common
parent854c803fdda30d7f7905c18d777ea85cac9b74d9 (diff)
downloadqmk_firmware-1e3e41a2c9ed8b2f7d44be0aed5d96ed557fa13d.tar.gz
Clean code.
Diffstat (limited to 'common')
-rw-r--r--common/action.c331
-rw-r--r--common/action.h39
-rw-r--r--common/command.c17
-rw-r--r--common/keyboard.c10
-rw-r--r--common/keyboard.h17
-rw-r--r--common/keymap.h6
6 files changed, 220 insertions, 200 deletions
diff --git a/common/action.c b/common/action.c
index 4b3b1dd68..fb06e463c 100644
--- a/common/action.c
+++ b/common/action.c
@@ -1,3 +1,19 @@
+/*
+Copyright 2012,2013 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 "host.h"
#include "timer.h"
#include "keymap.h"
@@ -10,36 +26,44 @@
#include "action.h"
-static void process(keyrecord_t *record);
+static bool process_tapping(keyrecord_t *record);
+static void process_action(keyrecord_t *record);
+
-// TODO
-/* layer */
-uint8_t default_layer = 0;
-uint8_t current_layer = 0;
+/*
+ * Tapping
+ */
+/* period of tapping(ms) */
+#ifndef TAPPING_TERM
+#define TAPPING_TERM 200
+#endif
-/* tap term(ms) */
-#define TAP_TERM 200
-/* number of tap which fires toggle feature */
-#define TAP_TOGGLE 5
+/* tap count needed for toggling a feature */
+#ifndef TAPPING_TOGGLE
+#define TAPPING_TOGGLE 5
+#endif
-/* This counts up when tap occurs */
-uint8_t tap_count = 0;
-keyevent_t tapping_event = {};
-keyrecord_t tapping_key = {};
+/* stores a key event of current tap. */
+static keyrecord_t tapping_key = {};
-/* TAPPING: This indicates that whether tap or not is not decided yet. */
-// NOTE: keyevent_t.time 0 means no event.
-#define IS_TAPPING() (tapping_key.event.time != 0)
+#define IS_TAPPING() !IS_NOEVENT(tapping_key.event)
#define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
#define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
-#define WITHIN_TAP_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAP_TERM)
+#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
+
-/* waiting keys buffer */
+/*
+ * Waiting buffer
+ *
+ * stores key events waiting for settling current tap.
+ */
#define WAITING_BUFFER_SIZE 8
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
+
/* point to empty cell to enq */
static uint8_t waiting_buffer_head = 0;
+
/* point to the oldest data cell to deq */
static uint8_t waiting_buffer_tail = 0;
@@ -65,7 +89,7 @@ static bool waiting_buffer_enq(keyrecord_t record)
static keyrecord_t waiting_buffer_deq(void)
{
if (waiting_buffer_head == waiting_buffer_tail) {
- return (keyrecord_t){}; // ???
+ return (keyrecord_t){};
}
uint8_t last_tail = waiting_buffer_tail;
waiting_buffer_tail = waiting_buffer_tail + 1 % WAITING_BUFFER_SIZE;
@@ -134,125 +158,6 @@ static void oneshot_toggle(void)
}
-/*
- * Rule to judge tap:
- * Tap key is typed(pressed and released) within TAP_TERM
- * without interfaring by typing other key.
- */
-/* return true when key event is processed. */
-static bool process_tap(keyrecord_t *keyp)
-{
- keyevent_t event = keyp->event;
-
- // if tapping
- if (IS_TAPPING_PRESSED()) {
- if (WITHIN_TAP_TERM(event)) {
- if (tapping_key.tap_count == 0) {
- if (IS_TAPPING_KEY(event.key) && !event.pressed) {
- // first tap!
- debug("Tapping: First tap.\n");
- tapping_key.tap_count = 1;
- process(&tapping_key);
-
- // enqueue
- keyp->tap_count = tapping_key.tap_count;
- return false;
- } else if (!event.pressed && waiting_buffer_typed(event)) {
- // other key typed. not tap.
- debug("Tapping: End(No tap. Interfered by typing key).\n");
- process(&tapping_key);
- tapping_key = (keyrecord_t){};
-
- // enqueue
- return false;
- } else {
- // other key events shall be stored till tapping state settles.
- return false;
- }
- } else {
- if (IS_TAPPING_KEY(event.key) && !event.pressed) {
- keyp->tap_count = tapping_key.tap_count;
- debug("Tapping: tap release("); debug_dec(keyp->tap_count); debug(")\n");
- tapping_key = *keyp;
- return false;
- }
- else if (is_tap_key(keyp->event.key) && event.pressed) {
- debug("Tapping: Start with forcing to release last tap.\n");
- process(&(keyrecord_t){
- .tap_count = tapping_key.tap_count,
- .event.key = tapping_key.event.key,
- .event.time = event.time,
- .event.pressed = false
- });
- tapping_key = *keyp;
- return false;
- }
- else {
- if (!IS_NOEVENT(keyp->event)) debug("Tapping: key event while tap.\n");
- process(keyp);
- return true;
- }
- }
- }
- // not within TAP_TERM
- else {
- if (tapping_key.tap_count == 0) {
- // timeout. not tap.
- debug("Tapping: End. Not tap(time out).\n");
- process(&tapping_key);
- tapping_key = (keyrecord_t){};
- return false;
- } else {
- if (IS_TAPPING_KEY(event.key) && !event.pressed) {
- debug("Tapping: End. tap release.");
- keyp->tap_count = tapping_key.tap_count;
- process(keyp);
- tapping_key = (keyrecord_t){};
- return true;
- } else {
- // other key after tap time out.
- process(keyp);
- return true;
- }
- }
- }
- } else if (IS_TAPPING_RELEASED()) {
- if (WITHIN_TAP_TERM(event)) {
- if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
- // sequential tap.
- keyp->tap_count = tapping_key.tap_count + 1;
- debug("Tapping: tap press("); debug_dec(keyp->tap_count); debug(")\n");
- process(keyp);
- tapping_key = *keyp;
- return true;
- } else if (event.pressed && is_tap_key(event.key)) {
- // Sequential tap can be interfered with other tap key.
- debug("Tapping: Start with interfering other tap.\n");
- tapping_key = *keyp;
- return true;
- } else {
- if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n");
- process(keyp);
- return true;
- }
- } else {
- // timeout. no sequential tap.
- debug("Tapping: End(Time out after releasing last tap).\n");
- tapping_key = (keyrecord_t){};
- process(keyp);
- return true;
- }
- } else {
- if (event.pressed && is_tap_key(event.key)) {
- debug("Tapping: Start(Press tap key).\n");
- tapping_key = *keyp;
- return true;
- } else {
- process(keyp);
- return true;
- }
- }
-}
void action_exec(keyevent_t event)
{
@@ -268,7 +173,7 @@ void action_exec(keyevent_t event)
keyrecord_t record = { .event = event };
// pre-process on tapping
- if (process_tap(&record)) {
+ if (process_tapping(&record)) {
if (!IS_NOEVENT(record.event)) debug("processed.\n");
} else {
if (!IS_NOEVENT(record.event)) debug("enqueued.\n");
@@ -283,7 +188,7 @@ void action_exec(keyevent_t event)
// process waiting_buffer
for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
- if (process_tap(&waiting_buffer[waiting_buffer_tail])) {
+ if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
debug_hex16(waiting_buffer[waiting_buffer_tail].event.key.raw); debug("\n");
} else {
@@ -292,7 +197,7 @@ void action_exec(keyevent_t event)
}
}
-static void process(keyrecord_t *record)
+static void process_action(keyrecord_t *record)
{
keyevent_t event = record->event;
uint8_t tap_count = record->tap_count;
@@ -453,11 +358,11 @@ static void process(keyrecord_t *record)
case 0xF0:
// tap toggle
if (event.pressed) {
- if (tap_count < TAP_TOGGLE) {
+ if (tap_count < TAPPING_TOGGLE) {
layer_switch(action.layer.opt);
}
} else {
- if (tap_count >= TAP_TOGGLE) {
+ if (tap_count >= TAPPING_TOGGLE) {
debug("LAYER_PRESSED: tap toggle.\n");
layer_switch(action.layer.opt);
}
@@ -501,12 +406,12 @@ static void process(keyrecord_t *record)
case 0xF0:
// tap toggle
if (event.pressed) {
- if (tap_count >= TAP_TOGGLE) {
+ if (tap_count >= TAPPING_TOGGLE) {
debug("LAYER_RELEASED: tap toggle.\n");
layer_switch(action.layer.opt);
}
} else {
- if (tap_count < TAP_TOGGLE) {
+ if (tap_count < TAPPING_TOGGLE) {
layer_switch(action.layer.opt);
}
}
@@ -551,12 +456,12 @@ static void process(keyrecord_t *record)
case 0xF0:
// tap toggle
if (event.pressed) {
- if (tap_count < TAP_TOGGLE) {
+ if (tap_count < TAPPING_TOGGLE) {
debug("LAYER_BIT: tap toggle(press).\n");
layer_switch(current_layer | action.layer.opt);
}
} else {
- if (tap_count < TAP_TOGGLE) {
+ if (tap_count < TAPPING_TOGGLE) {
debug("LAYER_BIT: tap toggle(release).\n");
layer_switch(current_layer & ~action.layer.opt);
} else {
@@ -610,11 +515,11 @@ static void process(keyrecord_t *record)
case 0xF0:
// tap toggle
if (event.pressed) {
- if (tap_count < TAP_TOGGLE) {
+ if (tap_count < TAPPING_TOGGLE) {
layer_switch(default_layer);
}
} else {
- if (tap_count >= TAP_TOGGLE) {
+ if (tap_count >= TAPPING_TOGGLE) {
debug("LAYER_EXT_PRESSED: tap toggle.\n");
layer_switch(default_layer);
}
@@ -659,12 +564,12 @@ static void process(keyrecord_t *record)
case 0xF0:
// tap toggle
if (event.pressed) {
- if (tap_count >= TAP_TOGGLE) {
+ if (tap_count >= TAPPING_TOGGLE) {
debug("LAYER_EXT_RELEASED: tap toggle.\n");
layer_switch(default_layer);
}
} else {
- if (tap_count < TAP_TOGGLE) {
+ if (tap_count < TAPPING_TOGGLE) {
layer_switch(default_layer);
}
}
@@ -706,6 +611,7 @@ static void process(keyrecord_t *record)
case ACT_COMMAND:
break;
case ACT_FUNCTION:
+ // TODO
action_call_function(event, action.func.id);
break;
default:
@@ -713,6 +619,127 @@ static void process(keyrecord_t *record)
}
}
+/* Tapping
+ *
+ * Rule: Tap key is typed(pressed and released) within TAPPING_TERM
+ * without interfaring by typing other key.
+ */
+/* return true when key event is processed. */
+static bool process_tapping(keyrecord_t *keyp)
+{
+ keyevent_t event = keyp->event;
+
+ // if tapping
+ if (IS_TAPPING_PRESSED()) {
+ if (WITHIN_TAPPING_TERM(event)) {
+ if (tapping_key.tap_count == 0) {
+ if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+ // first tap!
+ debug("Tapping: First tap.\n");
+ tapping_key.tap_count = 1;
+ process_action(&tapping_key);
+
+ // enqueue
+ keyp->tap_count = tapping_key.tap_count;
+ return false;
+ } else if (!event.pressed && waiting_buffer_typed(event)) {
+ // other key typed. not tap.
+ debug("Tapping: End(No tap. Interfered by typing key).\n");
+ process_action(&tapping_key);
+ tapping_key = (keyrecord_t){};
+
+ // enqueue
+ return false;
+ } else {
+ // other key events shall be stored till tapping state settles.
+ return false;
+ }
+ } else {
+ if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+ keyp->tap_count = tapping_key.tap_count;
+ debug("Tapping: tap release("); debug_dec(keyp->tap_count); debug(")\n");
+ tapping_key = *keyp;
+ return false;
+ }
+ else if (is_tap_key(keyp->event.key) && event.pressed) {
+ debug("Tapping: Start with forcing to release last tap.\n");
+ process_action(&(keyrecord_t){
+ .tap_count = tapping_key.tap_count,
+ .event.key = tapping_key.event.key,
+ .event.time = event.time,
+ .event.pressed = false
+ });
+ tapping_key = *keyp;
+ return false;
+ }
+ else {
+ if (!IS_NOEVENT(keyp->event)) debug("Tapping: key event while tap.\n");
+ process_action(keyp);
+ return true;
+ }
+ }
+ }
+ // not within TAPPING_TERM
+ else {
+ if (tapping_key.tap_count == 0) {
+ // timeout. not tap.
+ debug("Tapping: End. Not tap(time out).\n");
+ process_action(&tapping_key);
+ tapping_key = (keyrecord_t){};
+ return false;
+ } else {
+ if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+ debug("Tapping: End. tap release.");
+ keyp->tap_count = tapping_key.tap_count;
+ process_action(keyp);
+ tapping_key = (keyrecord_t){};
+ return true;
+ } else {
+ // other key after tap time out.
+ process_action(keyp);
+ return true;
+ }
+ }
+ }
+ } else if (IS_TAPPING_RELEASED()) {
+ if (WITHIN_TAPPING_TERM(event)) {
+ if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
+ // sequential tap.
+ keyp->tap_count = tapping_key.tap_count + 1;
+ debug("Tapping: tap press("); debug_dec(keyp->tap_count); debug(")\n");
+ process_action(keyp);
+ tapping_key = *keyp;
+ return true;
+ } else if (event.pressed && is_tap_key(event.key)) {
+ // Sequential tap can be interfered with other tap key.
+ debug("Tapping: Start with interfering other tap.\n");
+ tapping_key = *keyp;
+ return true;
+ } else {
+ if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n");
+ process_action(keyp);
+ return true;
+ }
+ } else {
+ // timeout. no sequential tap.
+ debug("Tapping: End(Time out after releasing last tap).\n");
+ tapping_key = (keyrecord_t){};
+ process_action(keyp);
+ return true;
+ }
+ } else {
+ if (event.pressed && is_tap_key(event.key)) {
+ debug("Tapping: Start(Press tap key).\n");
+ tapping_key = *keyp;
+ return true;
+ } else {
+ process_action(keyp);
+ return true;
+ }
+ }
+}
+
+
/*
* Utilities for actions.
@@ -813,7 +840,7 @@ void layer_switch(uint8_t new_layer)
current_layer = new_layer;
clear_keyboard_but_mods(); // To avoid stuck keys
- // TODO: update mods with full scan of matrix? if modifier changes between layers
+ // NOTE: update mods with full scan of matrix? if modifier changes between layers
}
}
diff --git a/common/action.h b/common/action.h
index bdd2d2f54..ed3fff6c2 100644
--- a/common/action.h
+++ b/common/action.h
@@ -1,3 +1,19 @@
+/*
+Copyright 2012,2013 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 ACTION_H
#define ACTION_H
@@ -9,7 +25,7 @@
* In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
* AVR looks like a little endian in avr-gcc.
*
- * TODO: not portable across compiler/endianness?
+ * NOTE: not portable across compiler/endianness?
* Byte order and bit order of 0x1234:
* Big endian: 15 ... 8 7 ... 210
* | 0x12 | 0x34 |
@@ -51,29 +67,17 @@ typedef union {
} func;
} action_t;
-/* Action record. For internal use. */
+/* Struct to record action and tap count */
typedef struct {
keyevent_t event;
uint8_t tap_count;
} keyrecord_t;
-/* Tap count: Tap is comprised of press and release within TAP_TERM.
- * 0 means no tap.
- * >1 means tap.
- */
-extern uint8_t tap_count;
-
-/* current tap key event */
-extern keyevent_t tapping_event;
-
-
-/* action function */
-typedef void (*action_func_t)(keyevent_t event, uint8_t opt);
-
-// TODO: legacy keymap support
+/* execute action per keyevent */
void action_exec(keyevent_t event);
-void action_call_function(keyevent_t event, uint8_t id);
+typedef void (*action_func_t)(keyevent_t event, uint8_t opt); // TODO:no need?
+void action_call_function(keyevent_t event, uint8_t id); // TODO: action function
/*
@@ -194,7 +198,6 @@ TODO: modifier + function by tap?
for example: LShift + '('[Shift+9] and RShift + ')'[Shift+0]
http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478.html#p90052
*/
-
enum action_kind_id {
ACT_LMODS = 0b0000,
ACT_RMODS = 0b0001,
diff --git a/common/command.c b/common/command.c
index a06e6a00d..8ca16b910 100644
--- a/common/command.c
+++ b/common/command.c
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <util/delay.h>
#include "keycode.h"
#include "host.h"
+#include "keymap.h"
#include "print.h"
#include "debug.h"
#include "util.h"
@@ -53,7 +54,6 @@ static void mousekey_console_help(void);
static uint8_t numkey2num(uint8_t code);
static void switch_layer(uint8_t layer);
-static void clear_keyboard(void);
typedef enum { ONESHOT, CONSOLE, MOUSEKEY } cmdstate_t;
@@ -555,18 +555,3 @@ static void switch_layer(uint8_t layer)
default_layer = layer;
print("switch to "); print_val_hex8(layer);
}
-
-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/keyboard.c b/common/keyboard.c
index 2422fb758..5e9945baf 100644
--- a/common/keyboard.c
+++ b/common/keyboard.c
@@ -1,5 +1,5 @@
/*
-Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
+Copyright 2011,2012,2013 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
@@ -34,8 +34,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
void keyboard_init(void)
{
- // TODO: to enable debug print magic key bind on boot time
-
// TODO: configuration of sendchar impl
print_sendchar_func = sendchar;
@@ -80,7 +78,7 @@ void keyboard_task(void)
action_exec((keyevent_t){
.key.pos = (keypos_t){ .row = r, .col = c },
.pressed = (matrix_row & (1<<c)),
- .time = timer_read()
+ .time = (timer_read() | 1) /* time should not be 0 */
});
// record a processed key
matrix_prev[r] ^= ((matrix_row_t)1<<c);
@@ -94,19 +92,15 @@ void keyboard_task(void)
action_exec(TICK);
MATRIX_LOOP_END:
-
#ifdef MOUSEKEY_ENABLE
// mousekey repeat & acceleration
mousekey_task();
#endif
-
// update LED
if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds();
keyboard_set_leds(led_status);
}
-
- return;
}
void keyboard_set_leds(uint8_t leds)
diff --git a/common/keyboard.h b/common/keyboard.h
index dd1ebb2bd..32c1bf464 100644
--- a/common/keyboard.h
+++ b/common/keyboard.h
@@ -1,5 +1,5 @@
/*
-Copyright 2011 Jun Wako <wakojun@gmail.com>
+Copyright 2011,2012,2013 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
@@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
extern "C" {
#endif
+/* key matrix position */
typedef struct {
uint8_t col;
uint8_t row;
@@ -36,29 +37,33 @@ typedef union {
keypos_t pos;
} key_t;
+/* key event */
typedef struct {
key_t key;
bool pressed;
uint16_t time;
} keyevent_t;
+/* equivalent test of key_t */
#define KEYEQ(keya, keyb) ((keya).raw == (keyb).raw)
-#define IS_NOEVENT(event) ((event).key.pos.row == 255 && (event).key.pos.col == 255)
+
+/* (time == 0) means no event and assumes matrix has no 255 line. */
+#define IS_NOEVENT(event) ((event).time == 0 || ((event).key.pos.row == 255 && (event).key.pos.col == 255))
+
#define NOEVENT (keyevent_t){ \
.key.pos = (keypos_t){ .row = 255, .col = 255 }, \
.pressed = false, \
.time = 0 \
}
+
+/* tick event */
#define TICK (keyevent_t){ \
.key.pos = (keypos_t){ .row = 255, .col = 255 }, \
.pressed = false, \
- .time = timer_read() \
+ .time = (timer_read() | 1) \
}
-extern uint8_t current_layer;
-extern uint8_t default_layer;
-
void keyboard_init(void);
void keyboard_task(void);
void keyboard_set_leds(uint8_t leds);
diff --git a/common/keymap.h b/common/keymap.h
index f992be18e..f54fea90d 100644
--- a/common/keymap.h
+++ b/common/keymap.h
@@ -22,6 +22,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdbool.h>
#include "action.h"
+
+/* layer used currently */
+extern uint8_t current_layer;
+/* layer to return or start with */
+extern uint8_t default_layer;
+
/*
* legacy keymap interface: keycode
*/