From 2fba5c4541c0861b29a99cfccdc4027014b82e06 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Wed, 29 Nov 2017 11:41:00 -0600 Subject: [PATCH] First working version Too many bug fixes to list them all. Luckily, at this early stage, that doesn't matter. --- examples/Qukeys/Qukeys.ino | 20 ++++--------- src/Kaleidoscope/Qukeys.cpp | 57 ++++++++++++++++++++++++++----------- src/Kaleidoscope/Qukeys.h | 5 ++-- 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/examples/Qukeys/Qukeys.ino b/examples/Qukeys/Qukeys.ino index f819a875..b3588088 100644 --- a/examples/Qukeys/Qukeys.ino +++ b/examples/Qukeys/Qukeys.ino @@ -23,26 +23,18 @@ const Key keymaps[][ROWS][COLS] PROGMEM = { ___), }; -// Define the Qukeys map -// QUKEYS( -// Qukey(0, 2, 1, Key_LeftShift), -// Qukey(0, 2, 2, Key_LeftControl), -// Qukey(0, 2, 3, Key_LeftAlt), -// Qukey(0, 2, 4, Key_LeftGui) -// ) - void setup() { // Use Qukeys Kaleidoscope.use(&Qukeys); - //kaleidoscope::Qukeys.init(qukeys, count); - kaleidoscope::Qukey qukeys[] = { - kaleidoscope::Qukey(0, 2, 1, Key_LeftShift), - kaleidoscope::Qukey(0, 2, 2, Key_LeftControl) + static kaleidoscope::Qukey qukeys[] = { + kaleidoscope::Qukey(0, 2, 1, Key_LeftGui), // A/cmd + kaleidoscope::Qukey(0, 2, 2, Key_LeftAlt), // S/alt + kaleidoscope::Qukey(0, 2, 3, Key_LeftControl), // D/ctrl + kaleidoscope::Qukey(0, 2, 4, Key_LeftShift) // F/shift }; - uint8_t count = sizeof(qukeys) / sizeof(kaleidoscope::Qukey); Qukeys.qukeys_ = qukeys; - Qukeys.qukeys_count_ = count; + Qukeys.qukeys_count_ = sizeof(qukeys) / sizeof(kaleidoscope::Qukey); Kaleidoscope.setup(); } diff --git a/src/Kaleidoscope/Qukeys.cpp b/src/Kaleidoscope/Qukeys.cpp index 3a79ee08..1f2ba5e1 100644 --- a/src/Kaleidoscope/Qukeys.cpp +++ b/src/Kaleidoscope/Qukeys.cpp @@ -39,7 +39,7 @@ Qukey::Qukey(int8_t layer, byte row, byte col, Key alt_keycode) { Qukey * Qukeys::qukeys_; uint8_t Qukeys::qukeys_count_ = 0; bool Qukeys::active_ = true; -uint16_t Qukeys::time_limit_ = 200; +uint16_t Qukeys::time_limit_ = 500; QueueItem Qukeys::key_queue_[QUKEYS_QUEUE_MAX] = {}; uint8_t Qukeys::key_queue_length_ = 0; @@ -52,15 +52,15 @@ Qukeys::Qukeys(void) {} // } int8_t Qukeys::lookupQukey(uint8_t key_addr) { - if (key_addr == QUKEY_UNKNOWN_ADDR) + if (key_addr == QUKEY_UNKNOWN_ADDR) { return QUKEY_NOT_FOUND; + } for (int8_t i = 0; i < qukeys_count_; i++) { - Qukey qukey = qukeys_[i]; - if (qukey.addr == key_addr) { + if (qukeys_[i].addr == key_addr) { byte row = addr::row(key_addr); byte col = addr::col(key_addr); - if ((qukey.layer == QUKEY_ALL_LAYERS) || - (qukey.layer == Layer.lookupActiveLayer(row, col))) { + if ((qukeys_[i].layer == QUKEY_ALL_LAYERS) || + (qukeys_[i].layer == Layer.lookupActiveLayer(row, col))) { return i; } } @@ -70,7 +70,7 @@ int8_t Qukeys::lookupQukey(uint8_t key_addr) { void Qukeys::enqueue(uint8_t key_addr) { if (key_queue_length_ == QUKEYS_QUEUE_MAX) { - flushKey(QUKEY_STATE_PRIMARY); + flushKey(QUKEY_STATE_PRIMARY, IS_PRESSED | WAS_PRESSED); } key_queue_[key_queue_length_].addr = key_addr; key_queue_[key_queue_length_].flush_time = millis() + time_limit_; @@ -82,11 +82,11 @@ int8_t Qukeys::searchQueue(uint8_t key_addr) { if (key_queue_[i].addr == key_addr) return i; } - return -1; + return QUKEY_NOT_FOUND; } // flush a single entry from the head of the queue -void Qukeys::flushKey(int8_t state) { +void Qukeys::flushKey(int8_t state, uint8_t keyswitch_state) { int8_t qukey_index = lookupQukey(key_queue_[0].addr); if (qukey_index != QUKEY_NOT_FOUND) { qukeys_[qukey_index].state = state; @@ -112,23 +112,43 @@ void Qukeys::flushKey(int8_t state) { handleKeyswitchEvent(keycode, row, col, IS_PRESSED | INJECTED); // Now we send the report (if there were any changes) hid::sendKeyboardReport(); + // Now for the tricky bit; we need to know if the key was actually + // released, or if it's still being held. Otherwise, we'll screw up + // the next call to flushKey(). + handleKeyswitchEvent(keycode, row, col, keyswitch_state | INJECTED); + hid::sendKeyboardReport(); // Shift the queue, so key_queue[0] is always the first key that gets processed for (byte i = 0; i < key_queue_length_; i++) { key_queue_[i] = key_queue_[i + 1]; } key_queue_length_--; + // If a qukey was released, reset its state to undetermined. This + // probably doesn't hurt, but it's also probably useless: + if (!(keyswitch_state & IS_PRESSED) && + (qukey_index != QUKEY_NOT_FOUND)) { + qukeys_[qukey_index].state = QUKEY_STATE_UNDETERMINED; + } } -void Qukeys::flushQueue(int8_t state, int8_t index) { - for (int8_t i = 0; i <= index; i++) { +// flushQueue() is called when a key that's in the key_queue is +// released. This means that all the keys ahead of it in the queue are +// still being held, so first we flush them, then we flush the +// released key (with different parameters). +void Qukeys::flushQueue(int8_t index) { + if (index == QUKEY_NOT_FOUND) + return; + for (int8_t i = 0; i < index; i++) { if (key_queue_length_ == 0) break; - flushKey(state); + flushKey(QUKEY_STATE_ALTERNATE, IS_PRESSED | WAS_PRESSED); } + flushKey(QUKEY_STATE_PRIMARY, WAS_PRESSED); } Key Qukeys::keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state) { + // Uncomment this for debugging, so as not to make flashing difficult + //if (row == 0 && col == 0) return mapped_key; // If Qukeys is turned off, continue to next plugin if (!active_) @@ -165,10 +185,15 @@ Key Qukeys::keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state) { // If the key was just released: if (keyToggledOff(key_state)) { - if (queue_index == QUKEY_NOT_FOUND) + // If the key isn't in the key_queue, proceed + if (queue_index == QUKEY_NOT_FOUND) { + // If a qukey that was not in the queue toggles off, reset its state + if (qukey_index != QUKEY_NOT_FOUND) + qukeys_[qukey_index].state = QUKEY_STATE_UNDETERMINED; return mapped_key; - flushQueue(QUKEY_STATE_ALTERNATE, queue_index); - return Key_NoKey; + } + flushQueue(queue_index); + return mapped_key; } // Otherwise, the key is still pressed @@ -200,7 +225,7 @@ void Qukeys::preReportHook(void) { uint32_t current_time = millis(); for (int8_t i = 0; i < key_queue_length_; i++) { if (current_time > key_queue_[i].flush_time) { - flushKey(QUKEY_STATE_ALTERNATE); + flushKey(QUKEY_STATE_ALTERNATE, IS_PRESSED | WAS_PRESSED); } else { break; } diff --git a/src/Kaleidoscope/Qukeys.h b/src/Kaleidoscope/Qukeys.h index 958ae542..ddd0694f 100644 --- a/src/Kaleidoscope/Qukeys.h +++ b/src/Kaleidoscope/Qukeys.h @@ -83,8 +83,8 @@ class Qukeys : public KaleidoscopePlugin { static int8_t lookupQukey(uint8_t key_addr); static void enqueue(uint8_t key_addr); static int8_t searchQueue(uint8_t key_addr); - static void flushKey(int8_t state); - static void flushQueue(int8_t state, int8_t index); + static void flushKey(int8_t state, uint8_t keyswitch_state); + static void flushQueue(int8_t index); static Qukey * qukeys_; static uint8_t qukeys_count_; @@ -94,6 +94,7 @@ class Qukeys : public KaleidoscopePlugin { static uint16_t time_limit_; static QueueItem key_queue_[QUKEYS_QUEUE_MAX]; static uint8_t key_queue_length_; + //static uint8_t keyswitch_state[]; static Key keyScanHook(Key mapped_key, byte row, byte col, uint8_t key_state); static void preReportHook(void);