From 46038df07ed3c3f085748a85255d9052d25b4c01 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 2 Dec 2021 12:14:55 +0100 Subject: [PATCH] Macros: Make it possible to read macros from sources other than PROGMEM Instead of the `Macros` plugin reading from progmem unconditionally, allow one to override a function (similar to how we can override `Layer.getKey()`), and use that function to read macro data. This allows `DynamicMacros` to re-use most of `Macros`, and not reimplement all of it. The only remaining duplication is `updateDynamicMacroCache()`, which walks the storage to build a macro index->offset map, and as such, needs to be able to parse macros. Signed-off-by: Gergely Nagy --- .../src/kaleidoscope/plugin/DynamicMacros.cpp | 130 +++--------------- .../src/kaleidoscope/plugin/DynamicMacros.h | 14 +- .../src/kaleidoscope/plugin/Macros.cpp | 31 +++-- .../src/kaleidoscope/plugin/Macros.h | 11 +- 4 files changed, 51 insertions(+), 135 deletions(-) diff --git a/plugins/Kaleidoscope-DynamicMacros/src/kaleidoscope/plugin/DynamicMacros.cpp b/plugins/Kaleidoscope-DynamicMacros/src/kaleidoscope/plugin/DynamicMacros.cpp index 9b4a6e43..51a370f0 100644 --- a/plugins/Kaleidoscope-DynamicMacros/src/kaleidoscope/plugin/DynamicMacros.cpp +++ b/plugins/Kaleidoscope-DynamicMacros/src/kaleidoscope/plugin/DynamicMacros.cpp @@ -25,33 +25,6 @@ namespace plugin { uint16_t DynamicMacros::storage_base_; uint16_t DynamicMacros::storage_size_; uint16_t DynamicMacros::map_[]; -Key DynamicMacros::active_macro_keys_[]; - -// ============================================================================= -// It might be possible to use Macros instead of reproducing it -void DynamicMacros::press(Key key) { - Runtime.handleKeyEvent(KeyEvent(KeyAddr::none(), IS_PRESSED | INJECTED, key)); - for (Key &mkey : active_macro_keys_) { - if (mkey == Key_NoKey) { - mkey = key; - break; - } - } -} - -void DynamicMacros::release(Key key) { - for (Key &mkey : active_macro_keys_) { - if (mkey == key) { - mkey = Key_NoKey; - } - } - Runtime.handleKeyEvent(KeyEvent(KeyAddr::none(), WAS_PRESSED | INJECTED, key)); -} - -void DynamicMacros::tap(Key key) { - Runtime.handleKeyEvent(KeyEvent(KeyAddr::none(), IS_PRESSED | INJECTED, key)); - Runtime.handleKeyEvent(KeyEvent(KeyAddr::none(), WAS_PRESSED | INJECTED, key)); -} void DynamicMacros::updateDynamicMacroCache() { uint16_t pos = storage_base_; @@ -118,92 +91,29 @@ void DynamicMacros::updateDynamicMacroCache() { } // public -void DynamicMacros::play(uint8_t macro_id) { - macro_t macro = MACRO_ACTION_END; - uint8_t interval = 0; - uint16_t pos; - Key key; - - pos = storage_base_ + map_[macro_id]; +void DynamicMacros::setup(uint16_t storage_size) { + Macros::readMacroByte = &DynamicMacros::readMacroByte; - while (true) { - switch (macro = Runtime.storage().read(pos++)) { - case MACRO_ACTION_STEP_EXPLICIT_REPORT: - case MACRO_ACTION_STEP_IMPLICIT_REPORT: - case MACRO_ACTION_STEP_SEND_REPORT: - break; - - case MACRO_ACTION_STEP_INTERVAL: - interval = Runtime.storage().read(pos++); - break; - case MACRO_ACTION_STEP_WAIT: { - uint8_t wait = Runtime.storage().read(pos++); - delay(wait); - break; - } - - case MACRO_ACTION_STEP_KEYDOWN: - key.setFlags(Runtime.storage().read(pos++)); - key.setKeyCode(Runtime.storage().read(pos++)); - press(key); - break; - case MACRO_ACTION_STEP_KEYUP: - key.setFlags(Runtime.storage().read(pos++)); - key.setKeyCode(Runtime.storage().read(pos++)); - release(key); - break; - case MACRO_ACTION_STEP_TAP: - key.setFlags(Runtime.storage().read(pos++)); - key.setKeyCode(Runtime.storage().read(pos++)); - tap(key); - break; + reserve_storage(storage_size); +} - case MACRO_ACTION_STEP_KEYCODEDOWN: - key.setFlags(0); - key.setKeyCode(Runtime.storage().read(pos++)); - press(key); - break; - case MACRO_ACTION_STEP_KEYCODEUP: - key.setFlags(0); - key.setKeyCode(Runtime.storage().read(pos++)); - release(key); - break; - case MACRO_ACTION_STEP_TAPCODE: - key.setFlags(0); - key.setKeyCode(Runtime.storage().read(pos++)); - tap(key); - break; +uint8_t DynamicMacros::readMacroByteFromEEPROM(const macro_t *ptr, uint8_t source) { + int idx = (int)*(ptr++); + return Runtime.storage().read(idx); +} - case MACRO_ACTION_STEP_TAP_SEQUENCE: { - while (true) { - key.setFlags(0); - key.setKeyCode(pgm_read_byte(pos++)); - if (key == Key_NoKey) - break; - tap(key); - delay(interval); - } - break; - } - case MACRO_ACTION_STEP_TAP_CODE_SEQUENCE: { - while (true) { - key.setFlags(0); - key.setKeyCode(pgm_read_byte(pos++)); - if (key.getKeyCode() == 0) - break; - tap(key); - delay(interval); - } - break; - } +uint8_t DynamicMacros::readMacroByte(const macro_t *ptr, uint8_t source) { + if (source == MACRO_SOURCE_PROGMEM) { + return Macros::readMacroByteFromPROGMEM(ptr, source); + } else { + return readMacroByteFromEEPROM(ptr, source); + } +} - case MACRO_ACTION_END: - default: - return; - } +void DynamicMacros::play(uint8_t macro_id) { + uint16_t pos = storage_base_ + map_[macro_id]; - delay(interval); - } + ::Macros.play((const macro_t *)&pos, MACRO_SOURCE_EEPROM); } bool isDynamicMacrosKey(Key key) { @@ -220,9 +130,7 @@ EventHandlerResult DynamicMacros::onKeyEvent(KeyEvent &event) { uint8_t macro_id = event.key.getRaw() - ranges::DYNAMIC_MACRO_FIRST; play(macro_id); } else { - for (Key key : active_macro_keys_) { - release(key); - } + ::Macros.release(event.key); } return EventHandlerResult::EVENT_CONSUMED; diff --git a/plugins/Kaleidoscope-DynamicMacros/src/kaleidoscope/plugin/DynamicMacros.h b/plugins/Kaleidoscope-DynamicMacros/src/kaleidoscope/plugin/DynamicMacros.h index 5499dab0..f21b5e01 100644 --- a/plugins/Kaleidoscope-DynamicMacros/src/kaleidoscope/plugin/DynamicMacros.h +++ b/plugins/Kaleidoscope-DynamicMacros/src/kaleidoscope/plugin/DynamicMacros.h @@ -18,13 +18,11 @@ #include "kaleidoscope/Runtime.h" #include +#include #include -#include "kaleidoscope/plugin/Macros/MacroSteps.h" - #define DM(n) Key(kaleidoscope::ranges::DYNAMIC_MACRO_FIRST + n) - -#define MAX_CONCURRENT_DYNAMIC_MACRO_KEYS 8 +#define MACRO_SOURCE_EEPROM 1 namespace kaleidoscope { namespace plugin { @@ -36,18 +34,18 @@ class DynamicMacros : public kaleidoscope::Plugin { EventHandlerResult onFocusEvent(const char *command); static void reserve_storage(uint16_t size); + static void setup(uint16_t storage_size); void play(uint8_t seq_id); + static uint8_t readMacroByteFromEEPROM(const macro_t *ptr, uint8_t source); + static uint8_t readMacroByte(const macro_t *ptr, uint8_t source); + private: static uint16_t storage_base_; static uint16_t storage_size_; static uint16_t map_[31]; static void updateDynamicMacroCache(); - static Key active_macro_keys_[MAX_CONCURRENT_DYNAMIC_MACRO_KEYS]; - static void press(Key key); - static void release(Key key); - static void tap(Key key); }; } // namespace plugin diff --git a/plugins/Kaleidoscope-Macros/src/kaleidoscope/plugin/Macros.cpp b/plugins/Kaleidoscope-Macros/src/kaleidoscope/plugin/Macros.cpp index c70e936f..20aff308 100644 --- a/plugins/Kaleidoscope-Macros/src/kaleidoscope/plugin/Macros.cpp +++ b/plugins/Kaleidoscope-Macros/src/kaleidoscope/plugin/Macros.cpp @@ -52,6 +52,7 @@ constexpr uint8_t release_state = WAS_PRESSED | INJECTED; // Initialized to zeroes (i.e. `Key_NoKey`) Key Macros::active_macro_keys_[]; +Macros::readMacroByteFunction Macros::readMacroByte = &Macros::readMacroByteFromPROGMEM; #ifndef NDEPRECATED #pragma GCC diagnostic push @@ -106,7 +107,7 @@ void Macros::tap(Key key) const { Runtime.handleKeyEvent(KeyEvent{KeyAddr::none(), release_state, key}); } -void Macros::play(const macro_t *macro_p) { +void Macros::play(const macro_t *macro_p, uint8_t source) { macro_t macro = MACRO_ACTION_END; uint8_t interval = 0; Key key; @@ -115,7 +116,7 @@ void Macros::play(const macro_t *macro_p) { return; while (true) { - switch (macro = pgm_read_byte(macro_p++)) { + switch (macro = readMacroByte(macro_p, source)) { // These are unlikely to be useful now that we have KeyEvent. I think the // whole `explicit_report` came about as a result of scan-order bugs. case MACRO_ACTION_STEP_EXPLICIT_REPORT: @@ -126,50 +127,50 @@ void Macros::play(const macro_t *macro_p) { // Timing case MACRO_ACTION_STEP_INTERVAL: - interval = pgm_read_byte(macro_p++); + interval = readMacroByte(macro_p, source); break; case MACRO_ACTION_STEP_WAIT: { - uint8_t wait = pgm_read_byte(macro_p++); + uint8_t wait = readMacroByte(macro_p, source); delay(wait); break; } case MACRO_ACTION_STEP_KEYDOWN: - key.setFlags(pgm_read_byte(macro_p++)); - key.setKeyCode(pgm_read_byte(macro_p++)); + key.setFlags(readMacroByte(macro_p, source)); + key.setKeyCode(readMacroByte(macro_p, source)); press(key); break; case MACRO_ACTION_STEP_KEYUP: - key.setFlags(pgm_read_byte(macro_p++)); - key.setKeyCode(pgm_read_byte(macro_p++)); + key.setFlags(readMacroByte(macro_p, source)); + key.setKeyCode(readMacroByte(macro_p, source)); release(key); break; case MACRO_ACTION_STEP_TAP: - key.setFlags(pgm_read_byte(macro_p++)); - key.setKeyCode(pgm_read_byte(macro_p++)); + key.setFlags(readMacroByte(macro_p, source)); + key.setKeyCode(readMacroByte(macro_p, source)); tap(key); break; case MACRO_ACTION_STEP_KEYCODEDOWN: key.setFlags(0); - key.setKeyCode(pgm_read_byte(macro_p++)); + key.setKeyCode(readMacroByte(macro_p, source)); press(key); break; case MACRO_ACTION_STEP_KEYCODEUP: key.setFlags(0); - key.setKeyCode(pgm_read_byte(macro_p++)); + key.setKeyCode(readMacroByte(macro_p, source)); release(key); break; case MACRO_ACTION_STEP_TAPCODE: key.setFlags(0); - key.setKeyCode(pgm_read_byte(macro_p++)); + key.setKeyCode(readMacroByte(macro_p, source)); tap(key); break; case MACRO_ACTION_STEP_TAP_SEQUENCE: { while (true) { key.setFlags(0); - key.setKeyCode(pgm_read_byte(macro_p++)); + key.setKeyCode(readMacroByte(macro_p, source)); if (key == Key_NoKey) break; tap(key); @@ -180,7 +181,7 @@ void Macros::play(const macro_t *macro_p) { case MACRO_ACTION_STEP_TAP_CODE_SEQUENCE: { while (true) { key.setFlags(0); - key.setKeyCode(pgm_read_byte(macro_p++)); + key.setKeyCode(readMacroByte(macro_p, source)); if (key.getKeyCode() == 0) break; tap(key); diff --git a/plugins/Kaleidoscope-Macros/src/kaleidoscope/plugin/Macros.h b/plugins/Kaleidoscope-Macros/src/kaleidoscope/plugin/Macros.h index 3847ebef..db93e0de 100644 --- a/plugins/Kaleidoscope-Macros/src/kaleidoscope/plugin/Macros.h +++ b/plugins/Kaleidoscope-Macros/src/kaleidoscope/plugin/Macros.h @@ -92,6 +92,8 @@ struct MacroKeyEvent { #define MAX_CONCURRENT_MACRO_KEYS 8 #endif +#define MACRO_SOURCE_PROGMEM 0 + namespace kaleidoscope { namespace plugin { @@ -126,7 +128,14 @@ class Macros : public kaleidoscope::Plugin { void tap(Key key) const; /// Play a macro sequence of key events - void play(const macro_t* macro_ptr); + void play(const macro_t* macro_ptr, uint8_t source = MACRO_SOURCE_PROGMEM); + + typedef uint8_t (*readMacroByteFunction)(const macro_t *ptr, uint8_t source); + static readMacroByteFunction readMacroByte; + + static uint8_t readMacroByteFromPROGMEM(const macro_t *ptr, uint8_t source) { + return pgm_read_byte(ptr++); + } // Templates provide a `type()` function that takes a variable number of // `char*` (string) arguments, in the form of a list of strings stored in