From 361146bf4a6ace7419e7c78c25dd6a2fe993a49c Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 13 Feb 2017 13:59:48 +0100 Subject: [PATCH 1/9] Merge plugin.h into Kaleidoscope.h The plugin.h header only defined the KaleidoscopePlugin class, and while there was a reason it was separate from Kaleidoscope.h, that reason is long gone. Merge it there, and remove any reference to plugin.h, as it is not needed anymore. Signed-off-by: Gergely Nagy --- src/Kaleidoscope.h | 6 +++++- src/layers.h | 1 - src/plugin.h | 7 ------- 3 files changed, 5 insertions(+), 9 deletions(-) delete mode 100644 src/plugin.h diff --git a/src/Kaleidoscope.h b/src/Kaleidoscope.h index d1319b29..07022894 100644 --- a/src/Kaleidoscope.h +++ b/src/Kaleidoscope.h @@ -22,7 +22,6 @@ void setup(); #include KALEIDOSCOPE_HARDWARE_H #include "key_events.h" -#include "plugin.h" #include "layers.h" extern HARDWARE_IMPLEMENTATION KeyboardHardware; @@ -33,6 +32,11 @@ extern HARDWARE_IMPLEMENTATION KeyboardHardware; #define KEYMAP_SIZE (sizeof(keymaps) / ROWS / COLS / sizeof(Key)) +class KaleidoscopePlugin { + public: + virtual void begin(void) = 0; +}; + class Kaleidoscope_ { public: Kaleidoscope_(void); diff --git a/src/layers.h b/src/layers.h index 74737df1..33025d3e 100644 --- a/src/layers.h +++ b/src/layers.h @@ -2,7 +2,6 @@ #include #include "key_defs.h" -#include "plugin.h" #include KALEIDOSCOPE_HARDWARE_H class Layer_ { diff --git a/src/plugin.h b/src/plugin.h deleted file mode 100644 index 87b1a817..00000000 --- a/src/plugin.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class KaleidoscopePlugin { - public: - virtual void begin(void) = 0; -}; - From f7834f05fc3c0fb75a56e41dc31e80dba055484f Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 13 Feb 2017 15:23:36 +0100 Subject: [PATCH 2/9] Merge the hooks into the Kaleidoscope object Having the hooks, and the hook methods in the Kaleidoscope object means we don't have to litter the definitions of the arrays around, and that the hooks are more tied to the object. We pollute the global namespace less, and having them in the object means that the hook helper functions will not be optimized out if not used within the Kaleidoscope repo. All in all, this saves us about 56 bytes of code, allows us to remove some hacks, and pulls things that are closely knit, closer together. While there, also changed the name of the `custom_handler_t` and `custom_loop_t` types to `eventHandlerHook` and `loopHook` (both under the `Kaleidoscope_` class), to better reflect what they are for. Signed-off-by: Gergely Nagy --- src/Kaleidoscope.cpp | 62 +++++++++++++++++++++++++++++++++++++------- src/Kaleidoscope.h | 41 +++++++++++++++++++++++++++++ src/hooks.cpp | 49 ---------------------------------- src/hooks.h | 34 ------------------------ src/key_events.cpp | 9 +++---- src/key_events.h | 1 - 6 files changed, 97 insertions(+), 99 deletions(-) delete mode 100644 src/hooks.cpp delete mode 100644 src/hooks.h diff --git a/src/Kaleidoscope.cpp b/src/Kaleidoscope.cpp index 61ab7483..d7bbb0d7 100644 --- a/src/Kaleidoscope.cpp +++ b/src/Kaleidoscope.cpp @@ -1,9 +1,10 @@ #include "Kaleidoscope.h" #include +Kaleidoscope_::eventHandlerHook Kaleidoscope_::eventHandlers[HOOK_MAX]; +Kaleidoscope_::loopHook Kaleidoscope_::loopHooks[HOOK_MAX]; + Kaleidoscope_::Kaleidoscope_(void) { - memset(eventHandlers, 0, HOOK_MAX * sizeof(custom_handler_t)); - memset(loopHooks, 0, HOOK_MAX * sizeof(custom_handler_t)); } void @@ -13,20 +14,15 @@ Kaleidoscope_::setup(const byte keymap_count) { Keyboard.begin(); KeyboardHardware.setup(); - event_handler_hook_use (NULL); - loop_hook_use (NULL); - Layer.defaultLayer (KeyboardHardware.load_primary_layer (keymap_count)); } -custom_loop_t loopHooks[HOOK_MAX]; - void Kaleidoscope_::loop(void) { KeyboardHardware.scan_matrix(); for (byte i = 0; loopHooks[i] != NULL && i < HOOK_MAX; i++) { - custom_loop_t hook = loopHooks[i]; + loopHook hook = loopHooks[i]; (*hook)(false); } @@ -34,7 +30,7 @@ Kaleidoscope_::loop(void) { Keyboard.releaseAll(); for (byte i = 0; loopHooks[i] != NULL && i < HOOK_MAX; i++) { - custom_loop_t hook = loopHooks[i]; + loopHook hook = loopHooks[i]; (*hook)(true); } } @@ -52,4 +48,52 @@ Kaleidoscope_::use(KaleidoscopePlugin *plugin, ...) { va_end(ap); } +void +Kaleidoscope_::replaceEventHandlerHook(eventHandlerHook oldHook, eventHandlerHook newHook) { + for (byte i = 0; i < HOOK_MAX; i++) { + if (eventHandlers[i] == oldHook) { + eventHandlers[i] = newHook; + return; + } + } +} + +void +Kaleidoscope_::appendEventHandlerHook (eventHandlerHook hook) { + replaceEventHandlerHook((eventHandlerHook)NULL, hook); +} + +void +Kaleidoscope_::useEventHandlerHook (eventHandlerHook hook) { + for (byte i = 0; i < HOOK_MAX; i++) { + if (eventHandlers[i] == hook) + return; + } + appendEventHandlerHook(hook); +} + +void +Kaleidoscope_::replaceLoopHook(loopHook oldHook, loopHook newHook) { + for (byte i = 0; i < HOOK_MAX; i++) { + if (loopHooks[i] == oldHook) { + loopHooks[i] = newHook; + return; + } + } +} + +void +Kaleidoscope_::appendLoopHook(loopHook hook) { + replaceLoopHook((loopHook)NULL, hook); +} + +void +Kaleidoscope_::useLoopHook(loopHook hook) { + for (byte i = 0; i < HOOK_MAX; i++) { + if (loopHooks[i] == hook) + return; + } + appendLoopHook (hook); +} + Kaleidoscope_ Kaleidoscope; diff --git a/src/Kaleidoscope.h b/src/Kaleidoscope.h index 07022894..0f07e240 100644 --- a/src/Kaleidoscope.h +++ b/src/Kaleidoscope.h @@ -24,6 +24,8 @@ void setup(); #include "key_events.h" #include "layers.h" +#define HOOK_MAX 64 + extern HARDWARE_IMPLEMENTATION KeyboardHardware; #ifndef VERSION @@ -44,6 +46,45 @@ class Kaleidoscope_ { void setup(const byte keymap_count); void loop(void); void use(KaleidoscopePlugin *plugin, ...) __attribute__((sentinel)); + + // ---- hooks ---- + + /* + * In most cases, one only wants a single copy of a hook. On the other hand, + * plugins that depend on other plugins, may want to make it easier for the + * end-user to use the plugin, and call the setup function of the dependent + * plugins too. In case the end-user calls the same setup function, we'd end up + * with hooks registered multiple times. + * + * To avoid this, protection against double-registration has been introduced. + * The `event_handler_hook_use` and `loop_hook_use` functions will only allow + * one copy of the hook. The `event_handler_hook_append` and `loop_hook_append` + * functions will, on the other hand, just append the hooks, and not care about + * protection. + */ + typedef Key (*eventHandlerHook)(Key mappedKey, byte row, byte col, uint8_t keyState); + static eventHandlerHook eventHandlers[HOOK_MAX]; + + static void replaceEventHandlerHook(eventHandlerHook oldHook, eventHandlerHook newHook); + static void appendEventHandlerHook(eventHandlerHook hook); + static void useEventHandlerHook(eventHandlerHook hook); + + typedef void (*loopHook)(bool postClear); + static loopHook loopHooks[HOOK_MAX]; + + static void replaceLoopHook(loopHook oldHook, loopHook newHook); + static void appendLoopHook(loopHook hook); + static void useLoopHook(loopHook hook); }; extern Kaleidoscope_ Kaleidoscope; + +/* -- DEPRECATED aliases; remove them when there are no more users. -- */ + +#define event_handler_hook_use(hook) Kaleidoscope.useEventHandlerHook(hook); +#define event_handler_hook_append(hook) Kaleidoscope.appendEventHandlerHook(hook) +#define event_handler_hook_replace(oldHook, newHook) Kaleidoscope.replaceEventHandlerHook(oldHook, newHook) + +#define loop_hook_use(hook) Kaleidoscope.useLoopHook(hook) +#define loop_hook_append(hook) Kaleidoscope.appendLoopHook(hook) +#define loop_hook_replace(oldHook, newHook) Kaleidoscope.replaceLoopHook(oldHook, newHook) diff --git a/src/hooks.cpp b/src/hooks.cpp deleted file mode 100644 index f304b51a..00000000 --- a/src/hooks.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "hooks.h" - -void -event_handler_hook_replace (custom_handler_t oldHook, custom_handler_t newHook) { - for (byte i = 0; i < HOOK_MAX; i++) { - if (eventHandlers[i] == oldHook) { - eventHandlers[i] = newHook; - return; - } - } -} - -void -event_handler_hook_append (custom_handler_t hook) { - event_handler_hook_replace ((custom_handler_t)NULL, hook); -} - -void -event_handler_hook_use (custom_handler_t hook) { - for (byte i = 0; i < HOOK_MAX; i++) { - if (eventHandlers[i] == hook) - return; - } - event_handler_hook_append (hook); -} - -void -loop_hook_replace (custom_loop_t oldHook, custom_loop_t newHook) { - for (byte i = 0; i < HOOK_MAX; i++) { - if (loopHooks[i] == oldHook) { - loopHooks[i] = newHook; - return; - } - } -} - -void -loop_hook_append (custom_loop_t hook) { - loop_hook_replace ((custom_loop_t)NULL, hook); -} - -void -loop_hook_use (custom_loop_t hook) { - for (byte i = 0; i < HOOK_MAX; i++) { - if (loopHooks[i] == hook) - return; - } - loop_hook_append (hook); -} diff --git a/src/hooks.h b/src/hooks.h deleted file mode 100644 index 29cedd61..00000000 --- a/src/hooks.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include "key_defs.h" - -#define HOOK_MAX 64 - -typedef Key (*custom_handler_t)(Key mappedKey, byte row, byte col, uint8_t keyState); -extern custom_handler_t eventHandlers[HOOK_MAX]; - -/* - * In most cases, one only wants a single copy of a hook. On the other hand, - * plugins that depend on other plugins, may want to make it easier for the - * end-user to use the plugin, and call the setup function of the dependent - * plugins too. In case the end-user calls the same setup function, we'd end up - * with hooks registered multiple times. - * - * To avoid this, protection against double-registration has been introduced. - * The `event_handler_hook_use` and `loop_hook_use` functions will only allow - * one copy of the hook. The `event_handler_hook_append` and `loop_hook_append` - * functions will, on the other hand, just append the hooks, and not care about - * protection. - */ - -void event_handler_hook_use (custom_handler_t hook); -void event_handler_hook_append (custom_handler_t hook); -void event_handler_hook_replace (custom_handler_t oldHook, custom_handler_t newHook); - -typedef void (*custom_loop_t)(bool postClear); -extern custom_loop_t loopHooks[HOOK_MAX]; - -void loop_hook_use (custom_loop_t hook); -void loop_hook_append (custom_loop_t hook); -void loop_hook_replace (custom_loop_t oldHook, custom_loop_t newHook); diff --git a/src/key_events.cpp b/src/key_events.cpp index cfc2b551..0e34355c 100644 --- a/src/key_events.cpp +++ b/src/key_events.cpp @@ -1,5 +1,4 @@ -#include "key_events.h" -#include "layers.h" +#include "Kaleidoscope.h" static bool handle_synthetic_key_event(Key mappedKey, uint8_t keyState) { if (mappedKey.flags & RESERVED) @@ -24,8 +23,6 @@ static bool handle_synthetic_key_event(Key mappedKey, uint8_t keyState) { return true; } -custom_handler_t eventHandlers[HOOK_MAX]; - static bool handle_key_event_default(Key mappedKey, byte row, byte col, uint8_t keyState) { //for every newly pressed button, figure out what logical key it is and send a key down event // for every newly released button, figure out what logical key it is and send a key up event @@ -83,8 +80,8 @@ void handle_key_event(Key mappedKey, byte row, byte col, uint8_t keyState) { if (!(keyState & INJECTED)) { mappedKey = Layer.lookup(row, col); } - for (byte i = 0; eventHandlers[i] != NULL && i < HOOK_MAX; i++) { - custom_handler_t handler = eventHandlers[i]; + for (byte i = 0; Kaleidoscope.eventHandlers[i] != NULL && i < HOOK_MAX; i++) { + Kaleidoscope_::eventHandlerHook handler = Kaleidoscope.eventHandlers[i]; mappedKey = (*handler)(mappedKey, row, col, keyState); if (mappedKey.raw == Key_NoKey.raw) return; diff --git a/src/key_events.h b/src/key_events.h index 0192d494..deb3e0f1 100644 --- a/src/key_events.h +++ b/src/key_events.h @@ -5,7 +5,6 @@ #include KALEIDOSCOPE_HARDWARE_H #include "key_defs.h" #include "keyswitch_state.h" -#include "hooks.h" extern const Key keymaps[][ROWS][COLS]; From 9a48b832902c4f4b20e31aa71c788a450147731a Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 13 Feb 2017 16:01:16 +0100 Subject: [PATCH 3/9] Include Kaleidoscope.h in layers.cpp To make things easier, just include the main header. It includes everything else we need, and this way we do not need to cherry pick, nor care if any of the other headers move, disappear, etc. Signed-off-by: Gergely Nagy --- src/layers.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/layers.cpp b/src/layers.cpp index d9dfa497..7dff82d4 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -1,5 +1,4 @@ -#include "layers.h" -#include "key_events.h" +#include "Kaleidoscope.h" static uint8_t DefaultLayer; static uint32_t LayerState; From 5d46660bef2d8a0f885ee703d8f96e61258dca6a Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 14 Feb 2017 07:37:06 +0100 Subject: [PATCH 4/9] Workaround for the compiler optimizing things out... Signed-off-by: Gergely Nagy --- src/Kaleidoscope.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Kaleidoscope.cpp b/src/Kaleidoscope.cpp index d7bbb0d7..94c687bd 100644 --- a/src/Kaleidoscope.cpp +++ b/src/Kaleidoscope.cpp @@ -14,6 +14,9 @@ Kaleidoscope_::setup(const byte keymap_count) { Keyboard.begin(); KeyboardHardware.setup(); + // A workaround, so that the compiler does not optimize this out... + handle_key_event (Key_NoKey, 255, 255, 0); + Layer.defaultLayer (KeyboardHardware.load_primary_layer (keymap_count)); } From d1a14b6d329de7db3b6d30cb173a423ee8ee8ddd Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 16 Feb 2017 13:29:55 +0100 Subject: [PATCH 5/9] Add a USE_PLUGINS() macro The `USE_PLUGINS()` macro is a clever hack, to make it seem like `Kaleidoscope.use()` is type-safe. It pushes its arguments into an appropriately typed array, so anything that does not fit the criteria, will trigger a compiler error. It then never uses the array, and passes the plugins over to `Kaleidoscope.use`, adding the trailing `NULL`, making it even easier to use. Since the array this macro creates is never used, the compiler will optimize it out fully. As such, by using this macro, we incur neither any size penalties, nor any run-time penalties. Everything happens at compile-time. Fixes #100. Signed-off-by: Gergely Nagy --- src/Kaleidoscope.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Kaleidoscope.h b/src/Kaleidoscope.h index 0f07e240..f9212efa 100644 --- a/src/Kaleidoscope.h +++ b/src/Kaleidoscope.h @@ -34,6 +34,24 @@ extern HARDWARE_IMPLEMENTATION KeyboardHardware; #define KEYMAP_SIZE (sizeof(keymaps) / ROWS / COLS / sizeof(Key)) +/* + * The `USE_PLUGINS()` macro is a clever hack, to make it seem like + * `Kaleidoscope.use()` is type-safe. It pushes its arguments into an + * appropriately typed array, so anything that does not fit the criteria, will + * trigger a compiler error. + * + * It then never uses the array, and passes the plugins over to + * `Kaleidoscope.use`, adding the trailing `NULL`, making it even easier to use. + * + * Since the array this macro creates is never used, the compiler will optimize + * it out fully. As such, by using this macro, we incur neither any size + * penalties, nor any run-time penalties. Everything happens at compile-time. + */ +#define USE_PLUGINS(plugins...) ({ \ + static KaleidoscopePlugin *__p[] = {plugins, NULL}; \ + Kaleidoscope.use(plugins, NULL); \ + }) + class KaleidoscopePlugin { public: virtual void begin(void) = 0; From 6c190f26f1b3bb690abc9bdb844d2778e1df0448 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Sun, 19 Feb 2017 18:54:30 -0800 Subject: [PATCH 6/9] System and Consumer keys really ought to be explicitly pressed and released using their internal support. This fixes volume keys --- src/key_events.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/key_events.cpp b/src/key_events.cpp index 0e34355c..38a7cc0a 100644 --- a/src/key_events.cpp +++ b/src/key_events.cpp @@ -13,9 +13,9 @@ static bool handle_synthetic_key_event(Key mappedKey, uint8_t keyState) { if (mappedKey.flags & IS_INTERNAL) { return false; } else if (mappedKey.flags & IS_CONSUMER) { - ConsumerControl.press(mappedKey.keyCode); + ConsumerControl.write(mappedKey.keyCode); } else if (mappedKey.flags & IS_SYSCTL) { - SystemControl.press(mappedKey.keyCode); + SystemControl.write(mappedKey.keyCode); } else if (mappedKey.flags & SWITCH_TO_KEYMAP) { // Should not happen, handled elsewhere. } From 11c7c7db8df7a1552a8e87c1a75a57cd7e895407 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 20 Feb 2017 08:33:08 +0100 Subject: [PATCH 7/9] Minor cleanup in the Kaleidoscope example Drop the `primary_keymap` and `temporary_keymap` variables, they've been long unused. Signed-off-by: Gergely Nagy --- examples/Kaleidoscope/Kaleidoscope.ino | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/Kaleidoscope/Kaleidoscope.ino b/examples/Kaleidoscope/Kaleidoscope.ino index 2db600eb..dc1916d7 100644 --- a/examples/Kaleidoscope/Kaleidoscope.ino +++ b/examples/Kaleidoscope/Kaleidoscope.ino @@ -17,9 +17,6 @@ #include "Kaleidoscope-LEDEffect-Rainbow.h" #include "Kaleidoscope-Model01-TestMode.h" -uint8_t primary_keymap = 0; -uint8_t temporary_keymap = 0; - #define NUMPAD_KEYMAP 2 #define COLEMAK KEYMAP ( \ From 71d49dee511c3edb76ba4b01c24e391f0dba61e1 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 21 Feb 2017 20:20:51 +0100 Subject: [PATCH 8/9] Don't try to load the saved layer on setup() If we want to allow plugins to implement EEPROM storage, it is best if we don't do anything with EEPROM in the core firmware. As such, remove the `Layer.defaultLayer` call from `Kaleidoscope.setup`. With that gone, the `keymap_count` argument is obsolete, so drop it from `Kaleidoscope.setup()` - but we keep an temporary `setup()` with the old arity, so that plugins can be updated at a slower pace. Signed-off-by: Gergely Nagy --- examples/Kaleidoscope/Kaleidoscope.ino | 2 +- src/Kaleidoscope.cpp | 4 +--- src/Kaleidoscope.h | 3 ++- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/Kaleidoscope/Kaleidoscope.ino b/examples/Kaleidoscope/Kaleidoscope.ino index dc1916d7..dfec7a8d 100644 --- a/examples/Kaleidoscope/Kaleidoscope.ino +++ b/examples/Kaleidoscope/Kaleidoscope.ino @@ -125,7 +125,7 @@ const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) { } void setup() { - Kaleidoscope.setup(KEYMAP_SIZE); + Kaleidoscope.setup(); Kaleidoscope.use(&TestMode, &LEDControl, &LEDOff, diff --git a/src/Kaleidoscope.cpp b/src/Kaleidoscope.cpp index 94c687bd..876d095c 100644 --- a/src/Kaleidoscope.cpp +++ b/src/Kaleidoscope.cpp @@ -8,7 +8,7 @@ Kaleidoscope_::Kaleidoscope_(void) { } void -Kaleidoscope_::setup(const byte keymap_count) { +Kaleidoscope_::setup(void) { wdt_disable(); delay(100); Keyboard.begin(); @@ -16,8 +16,6 @@ Kaleidoscope_::setup(const byte keymap_count) { // A workaround, so that the compiler does not optimize this out... handle_key_event (Key_NoKey, 255, 255, 0); - - Layer.defaultLayer (KeyboardHardware.load_primary_layer (keymap_count)); } void diff --git a/src/Kaleidoscope.h b/src/Kaleidoscope.h index f9212efa..fbdeb8dc 100644 --- a/src/Kaleidoscope.h +++ b/src/Kaleidoscope.h @@ -61,7 +61,8 @@ class Kaleidoscope_ { public: Kaleidoscope_(void); - void setup(const byte keymap_count); + void setup(const byte keymap_count) { setup(); }; + void setup(void); void loop(void); void use(KaleidoscopePlugin *plugin, ...) __attribute__((sentinel)); From 6d641e7fc52b5b93df28f563369661ae42a43c6b Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Tue, 21 Feb 2017 20:51:56 +0100 Subject: [PATCH 9/9] Make the lookup of a key pluggable We want to allow plugins to change how keys are looked up - or where they are looked up from -, and for this, the way we do that final lookup from `keymaps` or elsewhere, must be overrideable. We do this by having a `getKey` function pointer in the `Layer_` class, which defaults to `getKeyFromPROGMEM`. Any plugin, or sketch, can change where `getKey` points to, and thereby change the way keys are looked up. Signed-off-by: Gergely Nagy --- src/layers.cpp | 18 ++++++++++++------ src/layers.h | 6 ++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/layers.cpp b/src/layers.cpp index 7dff82d4..c9464b2b 100644 --- a/src/layers.cpp +++ b/src/layers.cpp @@ -5,6 +5,7 @@ static uint32_t LayerState; uint8_t Layer_::highestLayer; uint8_t Layer_::keyMap[ROWS][COLS]; +Key (*Layer_::getKey)(uint8_t layer, byte row, byte col) = Layer.getKeyFromPROGMEM; static void handle_keymap_key_event(Key keymapEntry, uint8_t keyState) { if (keymapEntry.keyCode >= MOMENTARY_OFFSET) { @@ -51,6 +52,15 @@ Layer_::Layer_ (void) { defaultLayer (0); } +Key +Layer_::getKeyFromPROGMEM (uint8_t layer, byte row, byte col) { + Key key; + + key.raw = pgm_read_word(&(keymaps[layer][row][col])); + + return key; +} + void Layer_::mergeLayers(void) { @@ -65,9 +75,7 @@ Layer_::mergeLayers(void) { while (layer > DefaultLayer) { if (Layer.isOn (layer)) { - Key mappedKey; - - mappedKey.raw = pgm_read_word(&(keymaps[layer][r][c])); + Key mappedKey = (*getKey)(layer, r, c); if (mappedKey != Key_Transparent) { keyMap[r][c] = layer; @@ -82,10 +90,8 @@ Layer_::mergeLayers(void) { Key Layer_::lookup(byte row, byte col) { uint8_t layer = keyMap[row][col]; - Key mappedKey; - mappedKey.raw = pgm_read_word(&(keymaps[layer][row][col])); - return mappedKey; + return (*getKey)(layer, row, col); } uint8_t Layer_::top (void) { diff --git a/src/layers.h b/src/layers.h index 33025d3e..3f1f748f 100644 --- a/src/layers.h +++ b/src/layers.h @@ -26,6 +26,10 @@ class Layer_ { static Key eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState); + static Key (*getKey)(uint8_t layer, byte row, byte col); + + static Key getKeyFromPROGMEM(uint8_t layer, byte row, byte col); + private: static uint8_t highestLayer; static uint8_t keyMap[ROWS][COLS]; @@ -33,4 +37,6 @@ class Layer_ { static void mergeLayers(void); }; +Key layer_getKey (uint8_t layer, uint8_t r, uint8_t c); + extern Layer_ Layer;