#include "report.h"
#include "debug.h"
#include "action_util.h"
+#include "timer.h"
static inline void add_key_byte(uint8_t code);
static inline void del_key_byte(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 = {};
report_keyboard_t *keyboard_report = &(report_keyboard_t){};
#ifndef NO_ACTION_ONESHOT
-static bool oneshot_enabled = true;
static int8_t oneshot_mods = 0;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+static int16_t oneshot_time = 0;
+#endif
#endif
+
void send_keyboard_report(void) {
keyboard_report->mods = real_mods;
keyboard_report->mods |= weak_mods;
#ifndef NO_ACTION_ONESHOT
- keyboard_report->mods |= oneshot_mods;
- if (has_anykey()) {
- clear_oneshot_mods();
+ if (oneshot_mods) {
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ if (TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT) {
+ dprintf("Oneshot: timeout\n");
+ clear_oneshot_mods();
+ }
+#endif
+ keyboard_report->mods |= oneshot_mods;
+ if (has_anykey()) {
+ clear_oneshot_mods();
+ }
}
#endif
host_keyboard_send(keyboard_report);
/* Oneshot modifier */
#ifndef NO_ACTION_ONESHOT
-void set_oneshot_mods(uint8_t mods) { oneshot_mods = mods; }
-void clear_oneshot_mods(void) { oneshot_mods = 0; }
-void oneshot_toggle(void) { oneshot_enabled = !oneshot_enabled; }
-void oneshot_enable(void) { oneshot_enabled = true; }
-void oneshot_disable(void) { oneshot_enabled = false; }
+void set_oneshot_mods(uint8_t mods)
+{
+ oneshot_mods = mods;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_time = timer_read();
+#endif
+}
+void clear_oneshot_mods(void)
+{
+ oneshot_mods = 0;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_time = 0;
+#endif
+}
#endif
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
}
/* 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++) {
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