diff --git a/src/Kaleidoscope/SpaceCadet.cpp b/src/Kaleidoscope/SpaceCadet.cpp index 7ee88dd1..e5bc8556 100644 --- a/src/Kaleidoscope/SpaceCadet.cpp +++ b/src/Kaleidoscope/SpaceCadet.cpp @@ -14,84 +14,202 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * Modified by Ben Gemperline to support additional keys. */ #include #include +#include +#include "SpaceCadet.h" namespace kaleidoscope { -uint8_t SpaceCadetShift::paren_needed_; -uint32_t SpaceCadetShift::start_time_; -uint16_t SpaceCadetShift::time_out = 1000; -Key SpaceCadetShift::opening_paren = Key_9, SpaceCadetShift::closing_paren = Key_0; + //Default constructor + ModifierKeyMap::ModifierKeyMap(){ + } -SpaceCadetShift::SpaceCadetShift() { -} + //Constructor with input and output, and assume default timeout + ModifierKeyMap::ModifierKeyMap(Key input_, Key output_){ + input = input_; + output = output_; + } -void SpaceCadetShift::begin() { - Kaleidoscope.useEventHandlerHook(eventHandlerHook); -} + //Constructor with all three set + ModifierKeyMap::ModifierKeyMap(Key input_, Key output_, uint16_t timeout_) { + input = input_; + output = output_; + timeout = timeout_; + } -Key SpaceCadetShift::eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state) { - // If nothing happened, bail out fast. - if (!keyIsPressed(key_state) && !keyWasPressed(key_state)) { - return mapped_key; - } - - // If a key has been just toggled on... - if (keyToggledOn(key_state)) { - if (mapped_key.raw == Key_LeftShift.raw) { // if it is LShift, remember it - bitWrite(paren_needed_, 0, 1); - start_time_ = millis(); - } else if (mapped_key.raw == Key_RightShift.raw) { // if it is RShift, remember it - bitWrite(paren_needed_, 1, 1); - start_time_ = millis(); - } else { // if it is something else, we do not need a paren at the end. - paren_needed_ = 0; - start_time_ = 0; + //Space Cadet + uint8_t SpaceCadet::map_size = 0; + ModifierKeyMap * SpaceCadet::map; + uint16_t SpaceCadet::time_out = 1000; + + SpaceCadet::SpaceCadet() { + //By default, we make one with left shift sending left paren, and right shift sending right paren + static ModifierKeyMap internalMap[] = { + {Key_LeftShift,Key_LeftParen,250} + ,{Key_RightShift,Key_RightParen,250} + /*,{Key_LeftGui,Key_LeftCurlyBracket,250} + ,{Key_RightAlt,Key_RightCurlyBracket,250} + ,{Key_LeftControl,Key_LeftBracket,250} + ,{Key_RightControl,Key_RightBracket,250}*/ + }; + + map = internalMap; + map_size = sizeof(internalMap)/sizeof(internalMap[0]); + //setMap(internalMap, sizeof(internalMap)); } - // this is all we need to do on keypress, let the next handler do its thing too. - return mapped_key; - } - - // if the state is empty, that means that either the shifts weren't pressed, - // or we used another key in the interim. in both cases, nothing special to do. - if (!paren_needed_) - return mapped_key; - - // if we timed out, that means we need to keep pressing shift, but won't - // need the parens in the end. - if ((millis() - start_time_) >= time_out) { - paren_needed_ = 0; - return mapped_key; - } - - // if we have a state, but the key in question is not either of the shifts, - // return. This can happen when another key is released, and that should not - // interrupt us. - if (mapped_key.raw != Key_LeftShift.raw && - mapped_key.raw != Key_RightShift.raw) - return mapped_key; - - // if a key toggled off (and that must be one of the shifts at this point), - // send the parens too (if we were interrupted, we bailed out earlier). - if (keyToggledOff(key_state)) { - Key paren = opening_paren; - if (bitRead(paren_needed_, 1)) - paren = closing_paren; - - handleKeyswitchEvent(mapped_key, row, col, IS_PRESSED | INJECTED); - handleKeyswitchEvent(paren, row, col, IS_PRESSED | INJECTED); - hid::sendKeyboardReport(); - - paren_needed_ = 0; - } - - return mapped_key; -} + SpaceCadet::SpaceCadet(ModifierKeyMap * map_, uint8_t map_size_) { + //Call the initializer + setMap(map_, map_size_); + } + + void SpaceCadet::setMap(ModifierKeyMap * map_, uint8_t map_size_){ + //Set the map + map = map_; + //set the map size to be the length of the array + map_size = map_size_; + } + + void SpaceCadet::begin() { + Kaleidoscope.useEventHandlerHook(eventHandlerHook); + } + + Key SpaceCadet::eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state) { + //char buffer[50]; + + //Serial.print("In eventHandlerHook"); + // If nothing happened, bail out fast. + if (!keyIsPressed(key_state) && !keyWasPressed(key_state)) { + return mapped_key; + } + + // If a key has been just toggled on... + if (keyToggledOn(key_state)) { + + /* + sprintf(buffer, "Pressed Key: %u\n", mapped_key.raw ); + Serial.print(buffer); + */ + + if(map_size > 0) { + //This will only set one key, and if it isn't in our map it clears everything for the non-pressed key + for (uint8_t i = 0; i < map_size; ++i) { + if(mapped_key.raw == map[i].input.raw) { + map[i].flagged = true; + map[i].start_time = millis(); + //There was a valid keypress + /*sprintf(buffer, "Valid Key: %u\n", mapped_key.raw); + Serial.print(buffer);*/ + + } else { + map[i].flagged = false; + map[i].start_time = 0; + } + + /* + sprintf(buffer, "Key: %u\n", map[i].input.raw); + Serial.print(buffer); + if(map[i].flagged){ + Serial.print("Flagged\n"); + } else { + Serial.print("Not Flagged\n"); + } + sprintf(buffer, "Start Time: %u\n", map[i].start_time); + Serial.print(buffer); + */ + } + } + + // this is all we need to do on keypress, let the next handler do its thing too. + return mapped_key; + } + + // if the state is empty, that means that either the shifts weren't pressed, + // or we used another key in the interim. in both cases, nothing special to do. + bool valid_key = false; + bool pressed_key_was_valid = false; + uint8_t index = 0; + if(map_size > 0) { + //Look to see if any are flagged + for (uint8_t i = 0; i < map_size; ++i) { + + if (map[i].flagged) { + valid_key = true; + index = i; + } + if (map[i].input.raw == mapped_key.raw) { + pressed_key_was_valid = true; + } + } + } + if (!valid_key) { + return mapped_key; + } + + //use the map index to find the local timeout for this key + uint16_t current_timeout = map[index].timeout; + //If that isn't set, use the global timeout setting. + if(current_timeout == 0){ + current_timeout = time_out; + } + + + + if ((millis() - map[index].start_time) >= current_timeout) { + // if we timed out, that means we need to keep pressing shift, but won't + // need the parens in the end. + map[index].flagged = false; + map[index].start_time = 0; + return mapped_key; + } + + /* + sprintf(buffer, "Check Index: %u\n", index ); + Serial.print(buffer); + + sprintf(buffer, "Current Timeout: %u\n", current_timeout ); + Serial.print(buffer); + + sprintf(buffer, "Start Time: %u\n", map[index].start_time ); + Serial.print(buffer); + + Serial.print("Made it past timeout check\n"); + */ + + // if we have a state, but the key in question is not either of the shifts, + // return. This can happen when another key is released, and that should not + // interrupt us. + + if (!pressed_key_was_valid) { + return mapped_key; + } + + //Serial.print("Made it validity check\n"); + + + // if a key toggled off (and that must be one of the shifts at this point), + // send the parens too (if we were interrupted, we bailed out earlier). + if (keyToggledOff(key_state)) { + Key pressed_key = map[index].input; + Key alternate_key = map[index].output; + + //Don't necessarily need to send the original key + //handleKeyswitchEvent(pressed_key, row, col, WAS_PRESSED | INJECTED); + handleKeyswitchEvent(alternate_key, row, col, IS_PRESSED | INJECTED); + hid::sendKeyboardReport(); + + map[index].flagged = false; + map[index].start_time = 0; + } + + return mapped_key; + } } -kaleidoscope::SpaceCadetShift SpaceCadetShift; +kaleidoscope::SpaceCadet SpaceCadet; diff --git a/src/Kaleidoscope/SpaceCadet.h b/src/Kaleidoscope/SpaceCadet.h index 626ef573..62af27c2 100644 --- a/src/Kaleidoscope/SpaceCadet.h +++ b/src/Kaleidoscope/SpaceCadet.h @@ -21,22 +21,47 @@ #include namespace kaleidoscope { + //Declarations for the modifier key mapping + class ModifierKeyMap { + public: + //Empty constructor; set the vars separately + ModifierKeyMap(void); + //Constructor with input and output + ModifierKeyMap(Key input_, Key output_); + //Constructor with all three set + ModifierKeyMap(Key input_, Key output_, uint16_t timeout_); + //The key that is pressed + Key input; + //the key that is sent + Key output; + //The timeout (default to global timeout) + uint16_t timeout = 0; + //The flag (set to 0) + bool flagged = false; + //the start time for this key press + uint32_t start_time = 0; + }; -class SpaceCadetShift : public KaleidoscopePlugin { - public: - SpaceCadetShift(void); + //Declaration for the method (implementing KaleidoscopePlugin) + class SpaceCadet : public KaleidoscopePlugin { + public: + //Empty constructor + SpaceCadet(void); - void begin(void) final; + //Constructor with mapping + SpaceCadet(ModifierKeyMap * map, uint8_t map_size); - static uint16_t time_out; - static Key opening_paren, closing_paren; + //Methods + void setMap(ModifierKeyMap * map, uint8_t map_size); + void begin(void) final; - private: - static uint8_t paren_needed_; - static uint32_t start_time_; + static uint16_t time_out; - static Key eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state); -}; + private: + static uint8_t map_size; + static ModifierKeyMap * map; + static Key eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state); + }; }; -extern kaleidoscope::SpaceCadetShift SpaceCadetShift; +extern kaleidoscope::SpaceCadet SpaceCadet;