Clean code.
parent
854c803fdd
commit
1e3e41a2c9
|
@ -2,6 +2,7 @@ COMMON_DIR = common
|
||||||
SRC += $(COMMON_DIR)/host.c \
|
SRC += $(COMMON_DIR)/host.c \
|
||||||
$(COMMON_DIR)/keyboard.c \
|
$(COMMON_DIR)/keyboard.c \
|
||||||
$(COMMON_DIR)/action.c \
|
$(COMMON_DIR)/action.c \
|
||||||
|
$(COMMON_DIR)/keymap.c \
|
||||||
$(COMMON_DIR)/command.c \
|
$(COMMON_DIR)/command.c \
|
||||||
$(COMMON_DIR)/timer.c \
|
$(COMMON_DIR)/timer.c \
|
||||||
$(COMMON_DIR)/print.c \
|
$(COMMON_DIR)/print.c \
|
||||||
|
|
331
common/action.c
331
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 "host.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "keymap.h"
|
#include "keymap.h"
|
||||||
|
@ -10,36 +26,44 @@
|
||||||
#include "action.h"
|
#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;
|
|
||||||
|
|
||||||
/* tap term(ms) */
|
/*
|
||||||
#define TAP_TERM 200
|
* Tapping
|
||||||
/* number of tap which fires toggle feature */
|
*/
|
||||||
#define TAP_TOGGLE 5
|
/* period of tapping(ms) */
|
||||||
|
#ifndef TAPPING_TERM
|
||||||
|
#define TAPPING_TERM 200
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This counts up when tap occurs */
|
/* tap count needed for toggling a feature */
|
||||||
uint8_t tap_count = 0;
|
#ifndef TAPPING_TOGGLE
|
||||||
keyevent_t tapping_event = {};
|
#define TAPPING_TOGGLE 5
|
||||||
keyrecord_t tapping_key = {};
|
#endif
|
||||||
|
|
||||||
/* TAPPING: This indicates that whether tap or not is not decided yet. */
|
/* stores a key event of current tap. */
|
||||||
// NOTE: keyevent_t.time 0 means no event.
|
static keyrecord_t tapping_key = {};
|
||||||
#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_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
|
||||||
#define IS_TAPPING_RELEASED() (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 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
|
#define WAITING_BUFFER_SIZE 8
|
||||||
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
|
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
|
||||||
|
|
||||||
/* point to empty cell to enq */
|
/* point to empty cell to enq */
|
||||||
static uint8_t waiting_buffer_head = 0;
|
static uint8_t waiting_buffer_head = 0;
|
||||||
|
|
||||||
/* point to the oldest data cell to deq */
|
/* point to the oldest data cell to deq */
|
||||||
static uint8_t waiting_buffer_tail = 0;
|
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)
|
static keyrecord_t waiting_buffer_deq(void)
|
||||||
{
|
{
|
||||||
if (waiting_buffer_head == waiting_buffer_tail) {
|
if (waiting_buffer_head == waiting_buffer_tail) {
|
||||||
return (keyrecord_t){}; // ???
|
return (keyrecord_t){};
|
||||||
}
|
}
|
||||||
uint8_t last_tail = waiting_buffer_tail;
|
uint8_t last_tail = waiting_buffer_tail;
|
||||||
waiting_buffer_tail = waiting_buffer_tail + 1 % WAITING_BUFFER_SIZE;
|
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)
|
void action_exec(keyevent_t event)
|
||||||
{
|
{
|
||||||
|
@ -268,7 +173,7 @@ void action_exec(keyevent_t event)
|
||||||
keyrecord_t record = { .event = event };
|
keyrecord_t record = { .event = event };
|
||||||
|
|
||||||
// pre-process on tapping
|
// pre-process on tapping
|
||||||
if (process_tap(&record)) {
|
if (process_tapping(&record)) {
|
||||||
if (!IS_NOEVENT(record.event)) debug("processed.\n");
|
if (!IS_NOEVENT(record.event)) debug("processed.\n");
|
||||||
} else {
|
} else {
|
||||||
if (!IS_NOEVENT(record.event)) debug("enqueued.\n");
|
if (!IS_NOEVENT(record.event)) debug("enqueued.\n");
|
||||||
|
@ -283,7 +188,7 @@ void action_exec(keyevent_t event)
|
||||||
|
|
||||||
// process waiting_buffer
|
// process waiting_buffer
|
||||||
for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
|
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("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
|
||||||
debug_hex16(waiting_buffer[waiting_buffer_tail].event.key.raw); debug("\n");
|
debug_hex16(waiting_buffer[waiting_buffer_tail].event.key.raw); debug("\n");
|
||||||
} else {
|
} 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;
|
keyevent_t event = record->event;
|
||||||
uint8_t tap_count = record->tap_count;
|
uint8_t tap_count = record->tap_count;
|
||||||
|
@ -453,11 +358,11 @@ static void process(keyrecord_t *record)
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
// tap toggle
|
// tap toggle
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
if (tap_count < TAP_TOGGLE) {
|
if (tap_count < TAPPING_TOGGLE) {
|
||||||
layer_switch(action.layer.opt);
|
layer_switch(action.layer.opt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tap_count >= TAP_TOGGLE) {
|
if (tap_count >= TAPPING_TOGGLE) {
|
||||||
debug("LAYER_PRESSED: tap toggle.\n");
|
debug("LAYER_PRESSED: tap toggle.\n");
|
||||||
layer_switch(action.layer.opt);
|
layer_switch(action.layer.opt);
|
||||||
}
|
}
|
||||||
|
@ -501,12 +406,12 @@ static void process(keyrecord_t *record)
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
// tap toggle
|
// tap toggle
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
if (tap_count >= TAP_TOGGLE) {
|
if (tap_count >= TAPPING_TOGGLE) {
|
||||||
debug("LAYER_RELEASED: tap toggle.\n");
|
debug("LAYER_RELEASED: tap toggle.\n");
|
||||||
layer_switch(action.layer.opt);
|
layer_switch(action.layer.opt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tap_count < TAP_TOGGLE) {
|
if (tap_count < TAPPING_TOGGLE) {
|
||||||
layer_switch(action.layer.opt);
|
layer_switch(action.layer.opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -551,12 +456,12 @@ static void process(keyrecord_t *record)
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
// tap toggle
|
// tap toggle
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
if (tap_count < TAP_TOGGLE) {
|
if (tap_count < TAPPING_TOGGLE) {
|
||||||
debug("LAYER_BIT: tap toggle(press).\n");
|
debug("LAYER_BIT: tap toggle(press).\n");
|
||||||
layer_switch(current_layer | action.layer.opt);
|
layer_switch(current_layer | action.layer.opt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tap_count < TAP_TOGGLE) {
|
if (tap_count < TAPPING_TOGGLE) {
|
||||||
debug("LAYER_BIT: tap toggle(release).\n");
|
debug("LAYER_BIT: tap toggle(release).\n");
|
||||||
layer_switch(current_layer & ~action.layer.opt);
|
layer_switch(current_layer & ~action.layer.opt);
|
||||||
} else {
|
} else {
|
||||||
|
@ -610,11 +515,11 @@ static void process(keyrecord_t *record)
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
// tap toggle
|
// tap toggle
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
if (tap_count < TAP_TOGGLE) {
|
if (tap_count < TAPPING_TOGGLE) {
|
||||||
layer_switch(default_layer);
|
layer_switch(default_layer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tap_count >= TAP_TOGGLE) {
|
if (tap_count >= TAPPING_TOGGLE) {
|
||||||
debug("LAYER_EXT_PRESSED: tap toggle.\n");
|
debug("LAYER_EXT_PRESSED: tap toggle.\n");
|
||||||
layer_switch(default_layer);
|
layer_switch(default_layer);
|
||||||
}
|
}
|
||||||
|
@ -659,12 +564,12 @@ static void process(keyrecord_t *record)
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
// tap toggle
|
// tap toggle
|
||||||
if (event.pressed) {
|
if (event.pressed) {
|
||||||
if (tap_count >= TAP_TOGGLE) {
|
if (tap_count >= TAPPING_TOGGLE) {
|
||||||
debug("LAYER_EXT_RELEASED: tap toggle.\n");
|
debug("LAYER_EXT_RELEASED: tap toggle.\n");
|
||||||
layer_switch(default_layer);
|
layer_switch(default_layer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tap_count < TAP_TOGGLE) {
|
if (tap_count < TAPPING_TOGGLE) {
|
||||||
layer_switch(default_layer);
|
layer_switch(default_layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -706,6 +611,7 @@ static void process(keyrecord_t *record)
|
||||||
case ACT_COMMAND:
|
case ACT_COMMAND:
|
||||||
break;
|
break;
|
||||||
case ACT_FUNCTION:
|
case ACT_FUNCTION:
|
||||||
|
// TODO
|
||||||
action_call_function(event, action.func.id);
|
action_call_function(event, action.func.id);
|
||||||
break;
|
break;
|
||||||
default:
|
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.
|
* Utilities for actions.
|
||||||
|
@ -813,7 +840,7 @@ void layer_switch(uint8_t new_layer)
|
||||||
|
|
||||||
current_layer = new_layer;
|
current_layer = new_layer;
|
||||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
#ifndef ACTION_H
|
||||||
#define ACTION_H
|
#define ACTION_H
|
||||||
|
|
||||||
|
@ -9,7 +25,7 @@
|
||||||
* In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
|
* In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
|
||||||
* AVR looks like a little endian in avr-gcc.
|
* 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:
|
* Byte order and bit order of 0x1234:
|
||||||
* Big endian: 15 ... 8 7 ... 210
|
* Big endian: 15 ... 8 7 ... 210
|
||||||
* | 0x12 | 0x34 |
|
* | 0x12 | 0x34 |
|
||||||
|
@ -51,29 +67,17 @@ typedef union {
|
||||||
} func;
|
} func;
|
||||||
} action_t;
|
} action_t;
|
||||||
|
|
||||||
/* Action record. For internal use. */
|
/* Struct to record action and tap count */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
keyevent_t event;
|
keyevent_t event;
|
||||||
uint8_t tap_count;
|
uint8_t tap_count;
|
||||||
} keyrecord_t;
|
} keyrecord_t;
|
||||||
|
|
||||||
|
|
||||||
/* Tap count: Tap is comprised of press and release within TAP_TERM.
|
/* execute action per keyevent */
|
||||||
* 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
|
|
||||||
void action_exec(keyevent_t event);
|
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]
|
for example: LShift + '('[Shift+9] and RShift + ')'[Shift+0]
|
||||||
http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478.html#p90052
|
http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478.html#p90052
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum action_kind_id {
|
enum action_kind_id {
|
||||||
ACT_LMODS = 0b0000,
|
ACT_LMODS = 0b0000,
|
||||||
ACT_RMODS = 0b0001,
|
ACT_RMODS = 0b0001,
|
||||||
|
|
|
@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
#include "keymap.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -53,7 +54,6 @@ static void mousekey_console_help(void);
|
||||||
|
|
||||||
static uint8_t numkey2num(uint8_t code);
|
static uint8_t numkey2num(uint8_t code);
|
||||||
static void switch_layer(uint8_t layer);
|
static void switch_layer(uint8_t layer);
|
||||||
static void clear_keyboard(void);
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum { ONESHOT, CONSOLE, MOUSEKEY } cmdstate_t;
|
typedef enum { ONESHOT, CONSOLE, MOUSEKEY } cmdstate_t;
|
||||||
|
@ -555,18 +555,3 @@ static void switch_layer(uint8_t layer)
|
||||||
default_layer = layer;
|
default_layer = layer;
|
||||||
print("switch to "); print_val_hex8(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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
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
|
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)
|
void keyboard_init(void)
|
||||||
{
|
{
|
||||||
// TODO: to enable debug print magic key bind on boot time
|
|
||||||
|
|
||||||
// TODO: configuration of sendchar impl
|
// TODO: configuration of sendchar impl
|
||||||
print_sendchar_func = sendchar;
|
print_sendchar_func = sendchar;
|
||||||
|
|
||||||
|
@ -80,7 +78,7 @@ void keyboard_task(void)
|
||||||
action_exec((keyevent_t){
|
action_exec((keyevent_t){
|
||||||
.key.pos = (keypos_t){ .row = r, .col = c },
|
.key.pos = (keypos_t){ .row = r, .col = c },
|
||||||
.pressed = (matrix_row & (1<<c)),
|
.pressed = (matrix_row & (1<<c)),
|
||||||
.time = timer_read()
|
.time = (timer_read() | 1) /* time should not be 0 */
|
||||||
});
|
});
|
||||||
// record a processed key
|
// record a processed key
|
||||||
matrix_prev[r] ^= ((matrix_row_t)1<<c);
|
matrix_prev[r] ^= ((matrix_row_t)1<<c);
|
||||||
|
@ -94,19 +92,15 @@ void keyboard_task(void)
|
||||||
action_exec(TICK);
|
action_exec(TICK);
|
||||||
|
|
||||||
MATRIX_LOOP_END:
|
MATRIX_LOOP_END:
|
||||||
|
|
||||||
#ifdef MOUSEKEY_ENABLE
|
#ifdef MOUSEKEY_ENABLE
|
||||||
// mousekey repeat & acceleration
|
// mousekey repeat & acceleration
|
||||||
mousekey_task();
|
mousekey_task();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// update LED
|
// update LED
|
||||||
if (led_status != host_keyboard_leds()) {
|
if (led_status != host_keyboard_leds()) {
|
||||||
led_status = host_keyboard_leds();
|
led_status = host_keyboard_leds();
|
||||||
keyboard_set_leds(led_status);
|
keyboard_set_leds(led_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyboard_set_leds(uint8_t leds)
|
void keyboard_set_leds(uint8_t leds)
|
||||||
|
|
|
@ -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
|
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
|
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" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* key matrix position */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t col;
|
uint8_t col;
|
||||||
uint8_t row;
|
uint8_t row;
|
||||||
|
@ -36,29 +37,33 @@ typedef union {
|
||||||
keypos_t pos;
|
keypos_t pos;
|
||||||
} key_t;
|
} key_t;
|
||||||
|
|
||||||
|
/* key event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
key_t key;
|
key_t key;
|
||||||
bool pressed;
|
bool pressed;
|
||||||
uint16_t time;
|
uint16_t time;
|
||||||
} keyevent_t;
|
} keyevent_t;
|
||||||
|
|
||||||
|
/* equivalent test of key_t */
|
||||||
#define KEYEQ(keya, keyb) ((keya).raw == (keyb).raw)
|
#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){ \
|
#define NOEVENT (keyevent_t){ \
|
||||||
.key.pos = (keypos_t){ .row = 255, .col = 255 }, \
|
.key.pos = (keypos_t){ .row = 255, .col = 255 }, \
|
||||||
.pressed = false, \
|
.pressed = false, \
|
||||||
.time = 0 \
|
.time = 0 \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tick event */
|
||||||
#define TICK (keyevent_t){ \
|
#define TICK (keyevent_t){ \
|
||||||
.key.pos = (keypos_t){ .row = 255, .col = 255 }, \
|
.key.pos = (keypos_t){ .row = 255, .col = 255 }, \
|
||||||
.pressed = false, \
|
.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_init(void);
|
||||||
void keyboard_task(void);
|
void keyboard_task(void);
|
||||||
void keyboard_set_leds(uint8_t leds);
|
void keyboard_set_leds(uint8_t leds);
|
||||||
|
|
|
@ -22,6 +22,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "action.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
|
* legacy keymap interface: keycode
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -59,6 +59,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
# define MOUSEKEY_DELAY_TIME 100
|
# define MOUSEKEY_DELAY_TIME 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* period of tapping(ms) */
|
||||||
|
#define TAPPING_TERM 200
|
||||||
|
/* tap count needed for toggling a feature */
|
||||||
|
#define TAPPING_TOGGLE 5
|
||||||
|
|
||||||
/* PS/2 mouse */
|
/* PS/2 mouse */
|
||||||
#ifdef PS2_MOUSE_ENABLE
|
#ifdef PS2_MOUSE_ENABLE
|
||||||
|
|
|
@ -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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
Loading…
Reference in New Issue