aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorGravatar tmk <tmk@users.noreply.github.com>2014-07-07 12:46:12 +0900
committerGravatar tmk <tmk@users.noreply.github.com>2014-07-07 12:46:12 +0900
commit34373185b746ae5b49cf56ac956080525c7dd6f8 (patch)
tree960fd040c50fa234b69fa381f065f84b1dd93a17 /common
parent3eeb0a96232af825962fa1e9b05b80ac1cfd1868 (diff)
parentac570686b6bde1e5066ea68636ae780392739cb4 (diff)
downloadqmk_firmware-34373185b746ae5b49cf56ac956080525c7dd6f8.tar.gz
Merge pull request #124 from kairyu/6kro
USB 6KRO with pseudo- or half- NKRO feature
Diffstat (limited to 'common')
-rw-r--r--common/action_util.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/common/action_util.c b/common/action_util.c
index 99a3adaab..5f44b3812 100644
--- a/common/action_util.c
+++ b/common/action_util.c
@@ -30,6 +30,15 @@ static inline void del_key_bit(uint8_t code);
static uint8_t real_mods = 0;
static uint8_t weak_mods = 0;
+#ifdef USB_6KRO_ENABLE
+#define RO_ADD(a, b) ((a + b) % REPORT_KEYS)
+#define RO_SUB(a, b) ((a - b + REPORT_KEYS) % REPORT_KEYS)
+#define RO_INC(a) RO_ADD(a, 1)
+#define RO_DEC(a) RO_SUB(a, 1)
+static int8_t cb_head = 0;
+static int8_t cb_tail = 0;
+static int8_t cb_count = 0;
+#endif
// TODO: pointer variable is not needed
//report_keyboard_t keyboard_report = {};
@@ -158,7 +167,18 @@ uint8_t get_first_key(void)
return i<<3 | biton(keyboard_report->nkro.bits[i]);
}
#endif
+#ifdef USB_6KRO_ENABLE
+ uint8_t i = cb_head;
+ do {
+ if (keyboard_report->keys[i] != 0) {
+ break;
+ }
+ i = RO_INC(i);
+ } while (i != cb_tail);
+ return keyboard_report->keys[i];
+#else
return keyboard_report->keys[0];
+#endif
}
@@ -166,6 +186,52 @@ uint8_t get_first_key(void)
/* local functions */
static inline void add_key_byte(uint8_t code)
{
+#ifdef USB_6KRO_ENABLE
+ int8_t i = cb_head;
+ int8_t empty = -1;
+ if (cb_count) {
+ do {
+ if (keyboard_report->keys[i] == code) {
+ return;
+ }
+ if (empty == -1 && keyboard_report->keys[i] == 0) {
+ empty = i;
+ }
+ i = RO_INC(i);
+ } while (i != cb_tail);
+ if (i == cb_tail) {
+ if (cb_tail == cb_head) {
+ // buffer is full
+ if (empty == -1) {
+ // pop head when has no empty space
+ cb_head = RO_INC(cb_head);
+ cb_count--;
+ }
+ else {
+ // left shift when has empty space
+ uint8_t offset = 1;
+ i = RO_INC(empty);
+ do {
+ if (keyboard_report->keys[i] != 0) {
+ keyboard_report->keys[empty] = keyboard_report->keys[i];
+ keyboard_report->keys[i] = 0;
+ empty = RO_INC(empty);
+ }
+ else {
+ offset++;
+ }
+ i = RO_INC(i);
+ } while (i != cb_tail);
+ cb_tail = RO_SUB(cb_tail, offset);
+ }
+ }
+ }
+ }
+ // add to tail
+ keyboard_report->keys[cb_tail] = code;
+ cb_tail = RO_INC(cb_tail);
+ cb_count++;
+#else
int8_t i = 0;
int8_t empty = -1;
for (; i < REPORT_KEYS; i++) {
@@ -181,15 +247,43 @@ static inline void add_key_byte(uint8_t code)
keyboard_report->keys[empty] = code;
}
}
+#endif
}
static inline void del_key_byte(uint8_t code)
{
+#ifdef USB_6KRO_ENABLE
+ uint8_t i = cb_head;
+ if (cb_count) {
+ do {
+ if (keyboard_report->keys[i] == code) {
+ keyboard_report->keys[i] = 0;
+ cb_count--;
+ if (cb_count == 0) {
+ // reset head and tail
+ cb_tail = cb_head = 0;
+ }
+ if (i == RO_DEC(cb_tail)) {
+ // left shift when next to tail
+ do {
+ cb_tail = RO_DEC(cb_tail);
+ if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
+ break;
+ }
+ } while (cb_tail != cb_head);
+ }
+ break;
+ }
+ i = RO_INC(i);
+ } while (i != cb_tail);
+ }
+#else
for (uint8_t i = 0; i < REPORT_KEYS; i++) {
if (keyboard_report->keys[i] == code) {
keyboard_report->keys[i] = 0;
}
}
+#endif
}
#ifdef NKRO_ENABLE