Cache the keymap when changing layers

Instead of going through all the active layers each time we are looking for a
key, whenever we switch layers, compute the effective keymap, and store the
indexes. This makes the lookup a considerably faster operation, and lookups
happen far more often than layer switching.

This comes at a cost of ROWS*COLS amount of memory, and a bit of code, but on
the flip side, the lookup operation is now O(1), which is a very nice property
to have, if you want responsiveness. Changing layers is marginally slower,
however, but even with 32 active layers, doing the computation once, instead of
potentially many dozens of time, is still worth it.

We could further reduce the memory requirements if we stored more columns per
byte, but that's for a future optimization.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
pull/108/head
Gergely Nagy 8 years ago
parent 830ab623e3
commit 3dc51b233a

@ -5,6 +5,7 @@ static uint8_t DefaultLayer;
static uint32_t LayerState; static uint32_t LayerState;
uint8_t Layer_::highestLayer; uint8_t Layer_::highestLayer;
uint8_t Layer_::keyMap[ROWS][COLS];
static void handle_keymap_key_event(Key keymapEntry, uint8_t keyState) { static void handle_keymap_key_event(Key keymapEntry, uint8_t keyState) {
if (keymapEntry.keyCode >= MOMENTARY_OFFSET) { if (keymapEntry.keyCode >= MOMENTARY_OFFSET) {
@ -51,18 +52,36 @@ Layer_::Layer_ (void) {
defaultLayer (0); defaultLayer (0);
} }
Key Layer_::lookup(byte row, byte col) { void
Key mappedKey; Layer_::mergeLayers(void) {
int8_t layer = highestLayer;
memset (keyMap, DefaultLayer, ROWS * COLS);
mappedKey.raw = Key_Transparent.raw; for (uint8_t r = 0; r < ROWS; r++) {
for (uint8_t c = 0; c < COLS; c++) {
int8_t layer = highestLayer;
while (mappedKey.raw == Key_Transparent.raw && while (layer >= DefaultLayer) {
layer >= DefaultLayer) { if (Layer.isOn (layer)) {
if (Layer.isOn (layer)) Key mappedKey;
mappedKey.raw = pgm_read_word(&(keymaps[layer][row][col]));
layer--; mappedKey.raw = pgm_read_word(&(keymaps[layer][r][c]));
if (mappedKey != Key_Transparent) {
keyMap[r][c] = layer;
break;
}
}
layer--;
}
}
} }
}
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 mappedKey;
} }
@ -84,12 +103,14 @@ void Layer_::on (uint8_t layer) {
bitSet (LayerState, layer); bitSet (LayerState, layer);
if (layer > highestLayer) if (layer > highestLayer)
highestLayer = layer; highestLayer = layer;
mergeLayers();
} }
void Layer_::off (uint8_t layer) { void Layer_::off (uint8_t layer) {
bitClear (LayerState, layer); bitClear (LayerState, layer);
if (layer == highestLayer) if (layer == highestLayer)
highestLayer = top(); highestLayer = top();
mergeLayers();
} }
boolean Layer_::isOn (uint8_t layer) { boolean Layer_::isOn (uint8_t layer) {

@ -3,6 +3,7 @@
#include <Arduino.h> #include <Arduino.h>
#include "key_defs.h" #include "key_defs.h"
#include "plugin.h" #include "plugin.h"
#include KALEIDOSCOPE_HARDWARE_H
class Layer_ { class Layer_ {
public: public:
@ -28,6 +29,9 @@ class Layer_ {
private: private:
static uint8_t highestLayer; static uint8_t highestLayer;
static uint8_t keyMap[ROWS][COLS];
static void mergeLayers(void);
}; };
extern Layer_ Layer; extern Layer_ Layer;

Loading…
Cancel
Save