diff --git a/README.md b/README.md index 2c6c1285..7f17b417 100644 --- a/README.md +++ b/README.md @@ -5,26 +5,54 @@ [travis:image]: https://travis-ci.org/keyboardio/Kaleidoscope-EEPROM-Keymap.svg?branch=master [travis:status]: https://travis-ci.org/keyboardio/Kaleidoscope-EEPROM-Keymap - [st:stable]: https://img.shields.io/badge/stable-✔-black.png?style=flat&colorA=44cc11&colorB=494e52 - [st:broken]: https://img.shields.io/badge/broken-X-black.png?style=flat&colorA=e05d44&colorB=494e52 - [st:experimental]: https://img.shields.io/badge/experimental----black.png?style=flat&colorA=dfb317&colorB=494e52 + [st:stable]: https://img.shields.io/badge/stable-✔-black.svg?style=flat&colorA=44cc11&colorB=494e52 + [st:broken]: https://img.shields.io/badge/broken-X-black.svg?style=flat&colorA=e05d44&colorB=494e52 + [st:experimental]: https://img.shields.io/badge/experimental----black.svg?style=flat&colorA=dfb317&colorB=494e52 -TODO +While keyboards usually ship with a keymap programmed in, to be able to change +that keymap, without flashing new firmware, we need a way to place the keymap +into a place we can update at run-time, and which persists across reboots. +Fortunately, we have a bit of `EEPROM` on the keyboard, and can use it to store +either the full keymap (and saving space in the firmware then), or store an +overlay there. In the latter case, whenever there is a non-transparent key on +the overlay, we will use that instead of the keyboard default. + +In short, this plugin allows us to change our keymaps, without having to compile +and flash new firmware. It does so through the use of the [Focus][plugin:focus] +plugin. + + [plugin:focus]: https://github.com/keyboardio/Kaleidoscope-Focus ## Using the plugin -TODO +Using the plugin is reasonably simple: after including the header, enable the +plugin, and let the `Layer` object know that we'll be using `EEPROMKeymap` to +figure out which keys to use. We can either use the `getKeyOverride` or the +`getKey` method, depending on whether we want to override, or fully replace the +built-in keymap. Then we need to set at most how many layers we want to store in +`EEPROM`, and that is about it. + +We can then update the keymap via [Focus][plugin:focus]. ```c++ #include #include +#include +#include -void setup () { - Kaleidoscope.setup (); +void setup() { + Serial.begin(9600); + USE_PLUGINS(&EEPROMKeymap, &Focus); - USE_PLUGINS (&EEPROMKeymap); + Kaleidoscope.setup(); + + Focus.addHook(FOCUS_HOOK_KEYMAP); + Focus.addHook(FOCUS_HOOK_KEYMAP_TRANSFER); + + Layer.getKey = EEPROMKeymap.getKeyOverride; - // TODO + EEPROMKeymap.max_layers(1); + EEPROMSettings.seal(); } ``` @@ -32,7 +60,37 @@ void setup () { The plugin provides the `EEPROMKeymap` object, which has the following methods: -**TODO** +### `.max_layers(max)` + +> Tells the extension to reserve space in EEPROM for up to `max` layers. Can +> only be called once, any subsequent call will be a no-op. + +## Focus commands + +The plugin provides two `Focus` hooks: `FOCUS_HOOK_KEYMAP`, and +`FOCUS_HOOK_KEYMAP_TRANSFER`. Together, they make the following commands +available, respectively: + +### `keymap.map [codes...]` + +> Without arguments, displays the keymap currently in effect. Each key is +> printed as its raw, 16-bit keycode. +> +> With arguments, it stores as many keys as given. One does not need to set all +> keys, on all layers: the command will start from the first key on the first +> layer, and go on as long as it has input. It will not go past the layer set +> via the `.max_layers()` method. + +### `keymap.transfer LAYER` + +> Transfers the `LAYER` from the built-in memory of the keyboard into `EEPROM` +> storage. +> +> Useful mostly when one wants to remove the built-in keymap, and wants to +> easily transfer it into `EEPROM` first. +> +> This is generally not needed, and it is recommended to not enable this +> command, unless the feature this command implements is truly needed. ## Dependencies diff --git a/examples/EEPROM-Keymap/EEPROM-Keymap.ino b/examples/EEPROM-Keymap/EEPROM-Keymap.ino index e3480f37..207d7bae 100644 --- a/examples/EEPROM-Keymap/EEPROM-Keymap.ino +++ b/examples/EEPROM-Keymap/EEPROM-Keymap.ino @@ -21,45 +21,43 @@ #include const Key keymaps[][ROWS][COLS] PROGMEM = { - [0] = KEYMAP_STACKED - ( - Key_NoKey, Key_1, Key_2, Key_3, Key_4, Key_5, Key_NoKey, - Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab, - Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G, - Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape, - - Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift, - Key_skip, - - Key_skip, Key_6, Key_7, Key_8, Key_9, Key_0, Key_skip, - Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals, - Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote, - Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus, - - Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl, - Key_skip - ), + [0] = KEYMAP_STACKED + (Key_NoKey, Key_1, Key_2, Key_3, Key_4, Key_5, Key_NoKey, + Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab, + Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G, + Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape, + + Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift, + Key_skip, + + Key_skip, Key_6, Key_7, Key_8, Key_9, Key_0, Key_skip, + Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals, + Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote, + Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus, + + Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl, + Key_skip), }; -void setup () { - Serial.begin (9600); +void setup() { + Serial.begin(9600); - Kaleidoscope.setup (); + USE_PLUGINS(&EEPROMKeymap, &Focus); - USE_PLUGINS (&EEPROMKeymap, &Focus); + Kaleidoscope.setup(); - Focus.addHook (FOCUS_HOOK_SETTINGS); - Focus.addHook (FOCUS_HOOK_KEYMAP); - Focus.addHook (FOCUS_HOOK_KEYMAP_TRANSFER); - Focus.addHook (FOCUS_HOOK_HELP); - Focus.addHook (FOCUS_HOOK_VERSION); + Focus.addHook(FOCUS_HOOK_SETTINGS); + Focus.addHook(FOCUS_HOOK_KEYMAP); + Focus.addHook(FOCUS_HOOK_KEYMAP_TRANSFER); + Focus.addHook(FOCUS_HOOK_HELP); + Focus.addHook(FOCUS_HOOK_VERSION); - Layer.getKey = EEPROMKeymap.getKeyOverride; + Layer.getKey = EEPROMKeymap.getKeyOverride; - EEPROMKeymap.reserveSpace (1); - EEPROMSettings.seal (); + EEPROMKeymap.max_layers(1); + EEPROMSettings.seal(); } -void loop () { - Kaleidoscope.loop (); +void loop() { + Kaleidoscope.loop(); } diff --git a/src/Kaleidoscope/EEPROM-Keymap.cpp b/src/Kaleidoscope/EEPROM-Keymap.cpp index 314b65a2..7acbfdb0 100644 --- a/src/Kaleidoscope/EEPROM-Keymap.cpp +++ b/src/Kaleidoscope/EEPROM-Keymap.cpp @@ -20,121 +20,111 @@ #include #include -namespace KaleidoscopePlugins { -uint16_t EEPROMKeymap::keymapBase; -uint8_t EEPROMKeymap::maxLayers; +namespace kaleidoscope { +uint16_t EEPROMKeymap::keymap_base_; +uint8_t EEPROMKeymap::max_layers_; -EEPROMKeymap::EEPROMKeymap (void) { +EEPROMKeymap::EEPROMKeymap(void) { } -void -EEPROMKeymap::begin (void) { - USE_PLUGINS (&::EEPROMSettings); +void EEPROMKeymap::begin(void) { + USE_PLUGINS(&::EEPROMSettings); } -void -EEPROMKeymap::reserveSpace (uint8_t layers) { - maxLayers = layers; - keymapBase = ::EEPROMSettings.requestSlice (maxLayers * ROWS * COLS * 2); +void EEPROMKeymap::max_layers(uint8_t max) { + max_layers_ = max; + keymap_base_ = ::EEPROMSettings.requestSlice(max_layers_ * ROWS * COLS * 2); } -Key -EEPROMKeymap::getKey (uint8_t layer, byte row, byte col) { - Key key; +Key EEPROMKeymap::getKey(uint8_t layer, byte row, byte col) { + Key key; - if (layer >= maxLayers) - return Key_NoKey; + if (layer >= max_layers_) + return Key_NoKey; - uint16_t pos = ((layer * ROWS * COLS) + (row * COLS) + col) * 2; + uint16_t pos = ((layer * ROWS * COLS) + (row * COLS) + col) * 2; - key.flags = EEPROM.read (keymapBase + pos); - key.keyCode = EEPROM.read (keymapBase + pos + 1); + key.flags = EEPROM.read(keymap_base_ + pos); + key.keyCode = EEPROM.read(keymap_base_ + pos + 1); - return key; + return key; } -Key -EEPROMKeymap::getKeyOverride (uint8_t layer, byte row, byte col) { - Key key; +Key EEPROMKeymap::getKeyOverride(uint8_t layer, byte row, byte col) { + Key key; - key = getKey (layer, row, col); - if (key == Key_Transparent) - key = Layer.getKeyFromPROGMEM (layer, row, col); - return key; + key = getKey(layer, row, col); + if (key == Key_Transparent) + key = Layer.getKeyFromPROGMEM(layer, row, col); + return key; } -uint16_t -EEPROMKeymap::base (void) { - return keymapBase; +uint16_t EEPROMKeymap::keymap_base(void) { + return keymap_base_; } -void -EEPROMKeymap::updateKey (uint16_t basePos, Key key) { - EEPROM.update (keymapBase + basePos * 2, key.flags); - EEPROM.update (keymapBase + basePos * 2 + 1, key.keyCode); +void EEPROMKeymap::updateKey(uint16_t base_pos, Key key) { + EEPROM.update(keymap_base_ + base_pos * 2, key.flags); + EEPROM.update(keymap_base_ + base_pos * 2 + 1, key.keyCode); } -Key -EEPROMKeymap::parseKey (void) { - Key key; +Key EEPROMKeymap::parseKey(void) { + Key key; - key.raw = Serial.parseInt (); + key.raw = Serial.parseInt(); - return key; + return key; } -void -EEPROMKeymap::printKey (Key k) { - ::Focus.printNumber (k.raw); +void EEPROMKeymap::printKey(Key k) { + ::Focus.printNumber(k.raw); } -bool -EEPROMKeymap::focusKeymap (const char *command) { - if (strcmp_P (command, PSTR ("keymap.map")) != 0) - return false; - - if (Serial.peek () == '\n') { - for (uint8_t layer = 0; layer < maxLayers; layer++) { - for (uint8_t row = 0; row < ROWS; row++) { - for (uint8_t col = 0; col < COLS; col++) { - Key k = getKey (layer, row, col); - - printKey (k); - ::Focus.printSpace (); - } - } - } - Serial.println (); - } else { - uint16_t i = 0; - while ((Serial.peek () != '\n') && (i < ROWS * COLS * maxLayers)) { - updateKey (i, parseKey ()); - i++; +bool EEPROMKeymap::focusKeymap(const char *command) { + if (strcmp_P(command, PSTR("keymap.map")) != 0) + return false; + + if (Serial.peek() == '\n') { + for (uint8_t layer = 0; layer < max_layers_; layer++) { + for (uint8_t row = 0; row < ROWS; row++) { + for (uint8_t col = 0; col < COLS; col++) { + Key k = getKey(layer, row, col); + + printKey(k); + ::Focus.printSpace(); } + } } + Serial.println(); + } else { + uint16_t i = 0; + while ((Serial.peek() != '\n') && (i < ROWS * COLS * max_layers_)) { + updateKey(i, parseKey()); + i++; + } + } - return true; + return true; } -bool -EEPROMKeymap::focusKeymapTransfer (const char *command) { - if (strcmp_P (command, PSTR ("keymap.transfer")) != 0) - return false; +bool EEPROMKeymap::focusKeymapTransfer(const char *command) { + if (strcmp_P(command, PSTR("keymap.transfer")) != 0) + return false; - uint8_t layer = Serial.parseInt (); + uint8_t layer = Serial.parseInt(); - for (uint8_t row = 0; row < ROWS; row++) { - for (uint8_t col = 0; col < COLS; col++) { - Key k = Layer.getKeyFromPROGMEM (layer, row, col); - uint16_t pos = ((layer * ROWS * COLS) + (row * COLS) + col); + for (uint8_t row = 0; row < ROWS; row++) { + for (uint8_t col = 0; col < COLS; col++) { + Key k = Layer.getKeyFromPROGMEM(layer, row, col); + uint16_t pos =((layer * ROWS * COLS) + (row * COLS) + col); - updateKey (pos, k); - } + updateKey(pos, k); } + } - return true; + return true; } -}; +} -KaleidoscopePlugins::EEPROMKeymap EEPROMKeymap; +kaleidoscope::EEPROMKeymap EEPROMKeymap; diff --git a/src/Kaleidoscope/EEPROM-Keymap.h b/src/Kaleidoscope/EEPROM-Keymap.h index 511cab35..b1e7de81 100644 --- a/src/Kaleidoscope/EEPROM-Keymap.h +++ b/src/Kaleidoscope/EEPROM-Keymap.h @@ -21,31 +21,32 @@ #include #include -namespace KaleidoscopePlugins { +namespace kaleidoscope { class EEPROMKeymap : public KaleidoscopePlugin { - public: - EEPROMKeymap (void); + public: + EEPROMKeymap(void); - virtual void begin (void) final; + static void max_layers(uint8_t max); - static void reserveSpace (uint8_t layers); - static uint16_t base (void); + void begin(void) final; - static Key getKey (uint8_t layer, byte row, byte col); - static Key getKeyOverride (uint8_t layer, byte row, byte col); + static uint16_t keymap_base(void); - static bool focusKeymap (const char *command); - static bool focusKeymapTransfer (const char *command); + static Key getKey(uint8_t layer, byte row, byte col); + static Key getKeyOverride(uint8_t layer, byte row, byte col); - static void updateKey (uint16_t basePos, Key key); + static bool focusKeymap(const char *command); + static bool focusKeymapTransfer(const char *command); - private: - static uint16_t keymapBase; - static uint8_t maxLayers; + static void updateKey(uint16_t base_pos, Key key); - static Key parseKey (void); - static void printKey (Key key); + private: + static uint16_t keymap_base_; + static uint8_t max_layers_; + + static Key parseKey(void); + static void printKey(Key key); }; }; -extern KaleidoscopePlugins::EEPROMKeymap EEPROMKeymap; +extern kaleidoscope::EEPROMKeymap EEPROMKeymap;