From 82a70ee1c5f5a23db0ecc7cf7b6cc57856399a66 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 22 Oct 2018 12:18:10 +0200 Subject: [PATCH] docs: Introduce NEWS.md, merge all upgrade notes into UPGRADING.md For easier navigation of changes, this introduces `NEWS.md`, a high-level overview of important or otherwise noteworthy changes. It is a short list only, with just the bare minimum of details. The new `UPGRADING.md` on the other hand, is a much more detailed document, and contains the upgrade notes from plugins too. The plugin docs now document the current version of the plugins only. The intent is to have both a short overview (`NEWS.md`), and a detailed guide (`UPGRADING.md`). The former will contain historical entries too, while the later is meant to be an upgrade guide from the previous version to the most recent one, with old notes eventually removed. Fixes #436. Signed-off-by: Gergely Nagy --- NEWS.md | 82 +++++ UPGRADING.md | 494 ++++++++++++++++++++++++----- doc/plugin/FocusSerial.md | 198 +----------- doc/plugin/GhostInTheFirmware.md | 7 - doc/plugin/HostOS.md | 12 - doc/plugin/LED-AlphaSquare.md | 7 - doc/plugin/LEDControl.md | 13 - doc/plugin/LEDEffect-SolidColor.md | 7 - doc/plugin/Leader.md | 7 - doc/plugin/MagicCombo.md | 115 ------- doc/plugin/Qukeys.md | 6 - doc/plugin/ShapeShifter.md | 8 - doc/plugin/SpaceCadet.md | 7 - doc/plugin/Syster.md | 7 - doc/plugin/TapDance.md | 7 - doc/plugin/TriColor.md | 6 +- doc/plugin/TypingBreaks.md | 15 - 17 files changed, 508 insertions(+), 490 deletions(-) create mode 100644 NEWS.md diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 00000000..37e2af8b --- /dev/null +++ b/NEWS.md @@ -0,0 +1,82 @@ +# Kaleidoscope v2.0 + +> Currently at 1.92-beta, in development! + +See [UPGRADING.md](UPGRADING.md) for more detailed instructions about upgrading from earlier versions (even earlier betas). This is just a list of noteworthy changes. + +* [New features](#new-features) +* [Breaking changes](#breaking-changes) +* [Bugfixes](#bugfixes) + +## New features + +### KALEIDOSCOPE_API_VERSION bump + +`KALEIDOSCOPE_API_VERSION` has been bumped to **2** due to the plugin API +changes mentioned below. It does not mean that version two of the API is final, +though. The bump is there so plugins can check it, and make compile-time +decisions based on it. Such as whether to compile for the version one, or for +the version two API. + +The API version will remain the same, even if we introduce breaking changes - +until a stable release is made from the v2 branch. From that point onwards, the +API version will change with further breaking changes. + +### New plugin API + +A new plugin API was introduced in May 2018, which replaces the old system. The new system is hopefully easier to use and develop for: + + - It does not require one to register / use hooks anymore. Implementing the interface provided by `kaleidoscope::Plugin` is all that is required. + - The new system has more hook points, and the method names are much more clear now. + +Plugins under Keyboardio control have all been updated to use the new API, and they no longer support the older one. + +See [UPGRADING.md](UPGRADING.md#new-plugin-api) for more information. + +### Transition to a monorepo + +We heard a lot of complaints that while the plugin architecture of Kaleidoscope is great, having so many plugins scattered around in dozens of repositories is a huge barrier of entry for potential contributors, and a significant pain point for end-users to update. For these reasons and more, we merged almost all plugins into the Kaleidoscope repository. + +While at first it may seem that this is a move towards a monolithic architecture, rest assured, it is not. The plugin APIs are still a core part of Kaleidoscope, it isn't going anywhere. We merely rearranged the sources, is all. Nothing else changes. + +Some headers and names did change, however, see [UPGRADING.md](UPGRADING.md#source-code-and-namespace-rearrangement) for more information. + +### Bidirectional communication for plugins + +The bi-directional communication protocol formerly implemented by `Kaleidoscope-Focus` has been partially pulled into core, using the new plugin system mentioned above. The new system makes it a lot easier for both end-users and developers to use the feature. + +See [UPGRADING.md](UPGRADING.md#bidirectional-communication-for-plugins) for more information. + +### Consistent timing + +Numerous plugins use timers, most of them directly calling `millis()`. This has the disadvantage that calls within a main loop cycle will be inconsistent, which makes timing synchronization across plugins hard. The newly introduced `Kaleidoscope.millisAtCycleStart()` function helps dealing with this issue. + +See [UPGRADING.md](UPGRADING.md#consistent-timing) for more information. + +### USB detach / attach + +It is now possible to detach, and re-attach the USB link from/to the host, without resetting the device. The intent of this feature (as implemented by the `Kaleidoscope.detachFromHost()` and `Kaleidoscope.attachToHost()` methods) is to allow configuration changes without rebooting. + +See the [Kaleidoscope-USB-Quirks][plugin:USB-Quirks] plugin for a use-case. + + [plugin:USB-Quirks]: https://github.com/keyboardio/Kaleidoscope-USB-Quirks + +## Breaking changes + +### The `RxCy` macros and peeking into the keyswitch state + +The `RxCy` macros changed from being indexes into a per-hand bitmap to being an index across the whole keyboard. This mostly affected the [MagicCombo](doc/plugin/MagicCombo.md) plugin. + +Please see the [relevant upgrade notes](UPGRADING.md#the-rxcy-macros-and-peeking-into-the-keyswitch-state) for more information. + +## Bugfixes + +We fixed way too many issues to list here, so we're going to narrow it down to the most important, most visible ones. + +### Support for BIOSes, EFI, login prompts, etc + +Keyboards report keys pressed to the host via either of two protocols: the boot protocol, or the report protocol. The boot protocol is the simpler, and it is what older BIOSes, EFI, and certain OS login prompts (or hard disk password prompts and the like) require. Until recently, the firmware wasn't able to provide this protocol, only the more advanced report one, which is required for N-key roll-over. + +We now support the boot protocol, and on operating systems that fully conform to the USB specification, this works automatically. For all others, one can implement a way to force one mode or the other. See the [factory firmware][Model01-Firmware] for an example how to achieve this. + + [Model01-Firmware]: https://github.com/keyboardio/Model01-Firmware diff --git a/UPGRADING.md b/UPGRADING.md index af69f8ca..78316787 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,56 +1,299 @@ -Kaleidoscope upgrade notes -========================== +As the firmware evolves, there are - and will be - APIs that we deprecate, and +eventually remove. We are constantly adding new features and plugins too. + +This document lists noteworthy new features for the *current* release, with examples of use. Another section provides a short guide for upgrading from deprecated APIs. For deprecations, their planned removal date is also listed. + +If any of this does not make sense to you, or you have trouble updating your .ino sketch or custom plugins, do not hesitate to write us at help@keyboard.io, we can help you fix it. -Noteworthy features -------------------- +* [Upgrade notes](#upgrade-notes) + + [New features](#new-features) + - [New plugin API](#new-plugin-api) + - [Bidirectional communication for plugins](#bidirectional-communication-for-plugins) + - [Consistent timing](#consistent-timing) + + [Breaking changes](#breaking-changes) + - [The `RxCy` macros and peeking into the keyswitch state](#the-rxcy-macros-and-peeking-into-the-keyswitch-state) + - [HostOS](#hostos) + - [MagicCombo](#magiccombo) + - [TypingBreaks](#typingbreaks) + + [Deprecated APIs and their replacements](#deprecated-apis-and-their-replacements) + - [Source code and namespace rearrangement](#source-code-and-namespace-rearrangement) +* [Removed APIs](#removed-apis) + +# Upgrade notes + +## New features ### New plugin API -A new plugin API was introduced in May 2018, which replaces the old system -(which still continues to work, but see below). The new system is hopefully -easier to use and develop for: +#### For end-users + +With the next version of `Kaleidoscope`, we are introducing a new plugin API. It's more efficient, smaller, and uses less resources than the previous one, while being more extensible, and a lot easier to use as well. But all of this matters little when one's not all that interested in writing plugins. However, the new plugin API comes with breaking changes, and one will need to update their own sketch too. + +To achieve all of the above, we had to change how plugins are initialized. Instead of using `Kaleidoscope.use()` in the `setup()` method of one's sketch, the plugins must now be initialized with `KALEIDOSCOPE_INIT_PLUGINS()`, outside of the `setup()` method. While `use()` was expecting pointers (`&Plugin`), `_INIT_PLUGINS()` expects references (`Plugin`). + +The conversion should be simple, and all of the official plugins have been updated already to use the new API, so they're safe to use this way. Some third-party plugins may still use the older API, they will need to be updated. + +To make things clear, here's an example of how to migrate from the old way to the new: + +```c++ +// Old way +void setup() { + Kaleidoscope.use(&LEDControl, + &Macros, + &OneShot, + &MouseKeys, + &LEDOff, + &LEDRainbowEffect); + Kaleidoscope.setup(); +``` + +```c++ +// New way +KALEIDOSCOPE_INIT_PLUGINS(LEDControl, + Macros, + OneShot, + MouseKeys, + LEDOff, + LEDRainbowEffect); +void setup() { + Kaleidoscope.setup(); +} +``` + +One thing to keep in mind is that with the old interface, plugins were able to automatically pull in their dependencies. This is not possible with the new interface, and one is required to initialize dependencies manually. Please consult the documentation of the plugins you use, to discover their dependencies - if any - and add them to the list if need be. You only need to add each dependency once. + +#### For developers - - It does not require one to register / use hooks anymore. Implementing the - interface provided by `kaleidoscope::Plugin` is all that is required. - - The new system has more hook points, and the method names are much more clear - now. +Developing plugins should be considerably simpler now, there is no need to register hooks, just implement the parts of the `kaleidoscope::Plugin` interface that make sense for a particular plugin. + +In practice, this boils down to implementing one or more of the following hook points: + +- `onSetup()`: Called once during device bootup, at the end of the `setup()` method. It takes no arguments, and must return `kaleidoscope::EventHandlerResult::OK`. +- `beforeEachCycle()`: Called once, at the beginning of each cycle of the main loop. This is similar to the old "loop hook" with its `post_clear` argument set to false. Takes no arguments, must return `kaleidoscope::EventHandlerResult::OK`. +- `onKeyswitchEvent`: Called for every non-idle key event. This replaces the old "event handler hook". It takes a key reference, coordinates, and a key state. The key reference can be updated to change the key being processed, so that any plugin that processes it further, will see the updated key. Can return `kaleidoscope::EventHandlerResult::OK` to let other plugins process the event further, or `kaleidoscope::EventHandlerResult::EVENT_CONSUMED` to stop processing. +- `onFocusEvent`: Used to implement [bi-directional communication](#bidirectional-communication-for-plugins). This is called whenever the firmware receives a command from the host. The only argument is the command name. Can return `kaleidoscope::EventHandlerResult::OK` to let other plugins process the event further, or `kaleidoscope::EventHandlerResult::EVENT_CONSUMED` to stop processing. +- `beforeReportingState`: Called without arguments, just before sending the keyboard and mouse reports to the host. Must return `kaleidoscope::EventHandlerResult::OK`. +- `afterEachCycle`: Called without arguments at the very end of each cycle. This is the replacement for the "loop hook" with its `post_clear` argument set. ### Bidirectional communication for plugins -Formerly the `Kaleidoscope-Focus` plugin implemented a way for plugins to -register hooks that respond to commands sent from the host. A part of this has -been pulled into Kaleidoscope itself, in the form of the new `onFocusEvent` -hook. For most intents and purposes, this hook works similar to how focus hooks -worked previously, but has the advantage of not having to explicitly register -them: if you use a plugin that supports this feature, and you have the new -`Kaleidoscope-FocusSerial` plugin enabled, the commands will be made available. +#### For end-users + +Whereas one would have used `Focus.addHook()` to register a new focus command, with the new architecture, one needs to add the object implementing the command to their list of plugins in `KALEIDOSCOPE_INIT_PLUGINS()`. A number of plugins that used to provide optional Focus commands now provide them by default. Some still provide optional ones, and we must transition to the new way. + +For example, where one would have written the following before: + +```c++ +Focus.addHook(FOCUS_HOOK_LEDCONTROL); +``` + +...we need to add the appropriate object to the plugin list: + +```c++ +KALEIDOSCOPE_INIT_PLUGINS(LEDControl, + FocusLEDCommand) +``` + +#### For developers + +Upgrading from `Focus` to `onFocusEvent` and `FocusSerial` is a reasonably simple process, the interface is quite similar. Nevertheless, we present a step-by-step guide here, covering two use cases: one where we wish to always provide a Focus command when both our plugin and `FocusSerial` are enabled; and another where we only wish to provide the command when explicitly asked to do so. + +##### The most trivial example + +The biggest difference between `Focus` and `onFocusEvent` is that the former required explicit registering of hooks, while the latter does it automatically: every plugin that implements the `onFocusEvent` method will be part of the system. As a consequence, only plugins are able to supply new commands: there is no explicit registration, thus, no way to inject a command that isn't part of a plugin. This also means that these functions now return `kaleidoscope::EventHandlerResult` instead of `bool`. Lets see a trivial example! + +###### Focus + +```c++ +bool exampleFocusHook(const char *command) { + if (strcmp_P(command, PSTR("example")) != 0) + return false; + + Serial.println(F("This is an example response. Hello world!")); + + return true; +} + +KALEIDOSCOPE_INIT_PLUGINS(Focus) + +void setup() { + Serial.begin(9600); + Kaleidoscope.setup(); + Focus.addHook(FOCUS_HOOK(exampleFocusHook, "example")); +} +``` + +###### onFocusEvent + +```c++ +namespace kaleidoscope { +class FocusExampleCommand : public Plugin { + public: + FocusExampleCommand() {} + + EventHandlerResult onFocusEvent(const char *command) { + if (strcmp_P(command, PSTR("example")) != 0) + return EventHandlerResult::OK; + + Serial.println(F("This is an example response. Hello world!")); + return EventHandlerResult::EVENT_CONSUMED; + } +}; +} + +kaleidoscope::FocusExampleCommand FocusExampleCommand; + +KALEIDOSCOPE_INIT_PLUGINS(Focus, FocusExampleCommand); + +void setup() { + Kaleidoscope.setup(); +} +``` + +###### Summary + +The new version is slightly more verbose for the trivial use case, because we have to wrap it up in an object. But other than that, the changes are minimal, and we don't need to explicitly register it! + +Observe that the return values changed: with `Focus`, if we wanted other hooks to have a chance at processing the same command, the hook returned `false`; if we wanted to stop processing, and consider it consumed, it returned `true`. With the new system, this is more descriptive with the `EventHandlerResult::OK` and `EventHandlerResult::EVENT_CONSUMED` return values. + +##### A stateful example + +Perhaps a better example that shows the quality of life improvements the new system brings is the case where the command needs access to either plugin state, or plugin methods. With the former system, the focus hooks needed to be static methods, and needed to be public. This is not necessarily the case now, because `onFocusEvent` is a non-static object method. It has full access to plugin internals! + +###### Focus + +```c++ +namespace kaleidoscope { +class ExamplePlugin : public Plugin { + public: + ExamplePlugin(); + + static bool exampleToggle() { + example_toggle_ = !example_toggle_; + return example_toggle_; + } + + static bool focusHook(const char *command) { + if (strcmp_P(command, PSTR("example.toggle")) != 0) + return false; + + ::Focus.printBool(exampleToggle()); + return true; + } + + private: + static bool example_toggle_; +}; +} + +kaleidoscope::ExamplePlugin ExamplePlugin; + +KALEIDOSCOPE_PLUGIN_INIT(Focus, ExamplePlugin) + +void setup() { + Serial.begin(9600); + Kaleidoscope.setup(); + + Focus.addHook(FOCUS_HOOK(ExamplePlugin.focusHook, "example.toggle")); +} +``` + +###### onFocusEvent -This drastically simplifies both the plugins that wish to implement this, and the user sketches, which no longer need to explicitly register the focus hooks. +```c++ +namespace kaleidoscope { +class ExamplePlugin : public Plugin { + public: + ExamplePlugin(); + + EventHandlerResult onFocusEvent(const char *command) { + if (strcmp_P(command, PSTR("example.toggle")) != 0) + return EventHandlerResult::OK; + + example_toggle_ = !example_toggle_; + ::Focus.printBool(example_toggle_); + + return EventHandlerResult::EVENT_CONSUMED; + } + + private: + static bool example_toggle_; +}; +} + +kaleidoscope::ExamplePlugin ExamplePlugin; + +KALEIDOSCOPE_PLUGIN_INIT(Focus, ExamplePlugin) + +void setup() { + Kaleidoscope.setup(); +} +``` + +###### Summary + +It's just another plugin, with just another event handler method implemented, nothing more. No need to explicitly register the focus hook, no need to provide access to private variables - we can just keep them private. + +##### Optional commands + +Optional commands are something that were perhaps easier with the `Focus` method: one just didn't register them. With `onFocusEvent`, we need to do a bit more than that, and move the command to a separate plugin, if we do not wish to enable it in every case. This adds a bit of overhead, but still less than `Focus` did. + +###### Focus + +```c++ +bool exampleOptionalHook(const char *command) { + if (strcmp_P(command, PSTR("optional")) != 0) + return false; -### Kaleidoscope.millisAtCycleStart() + Serial.println(Layer.getLayerState(), BIN); + return true; +} + +KALEIDOSCOPE_INIT_PLUGINS(Focus) + +void setup() { + Kaleidoscope.setup(); +} +``` + +Do note that we do not register the `exampleOptionalHook` here! As such, because it is unused code, it will get optimized out during compilation. While this is a simplistic example, the optional hook might have been part of a class, that provides other hooks. + +###### onFocusEvent + +```c++ +namespace kaleidoscope { +class ExampleOptionalCommand : public Plugin { + public: + ExampleOptionalCommand() {} + + EventHandlerResult onFocusEvent(const char *command) { + if (strcmp_P(command, PSTR("optional")) != 0) + return EventHandlerResult::OK; + + Serial.println(Layer.getLayerState(), BIN); + return EventHandlerResult::EVENT_CONSUMED; + } +}; +} + +KALEIDOSCOPE_INIT_PLUGINS(Focus) + +void setup() { + Kaleidoscope.setup(); +} +``` -Many plugins use timers, and most of them will call `millis()`, which isn't -wrong, but isn't the most efficient either. While `millis()` isn't terribly -expensive, it's not cheap either. For most cases, we do not need an exact timer, -and one updated once per cycle is enough - which is what `.millisAtCycleStart()` -is. Having a timer that is consistent throughout the whole cycle may also be -beneficial. +###### Summary -While `millis()` should continue to work forever, plugins and user code should, -as a general rule, use `Kaleidoscope.millisAtCycleStart()` rather than -`millis()`. +The trick here is to move optional commands out into a separate plugin. It's a bit more boilerplate, but not by much. -### Kaleidoscope.detachFromHost() and Kaleidoscope.attachToHost() +### Consistent timing -These two require changes to the Hardware plugins, as they wrap functionality -provided by it. The intent of these methods is to allow one to apply some -configuration changes between detach and attach - because we only sever the link -between device and host, power remains connected, and the device does not -reboot. A quick way to re-initialize the endpoints. +As an end-user, there's nothing one needs to do. Consistent timing helpers are primarily for plugin use. -See the [Kaleidoscope-USB-Quirks][plugin:USB-Quirks] plugin for a use-case. +As a developer, one can continue using `millis()`, but migrating to `Kaleidoscope.millisAtCycleStart()` is recommended. The new method will return the same value for the duration of the main loop cycle, making time-based synchronization between plugins a lot easier. - [plugin:USB-Quirks]: https://github.com/keyboardio/Kaleidoscope-USB-Quirks +## Breaking changes ### The `RxCy` macros and peeking into the keyswitch state @@ -60,53 +303,158 @@ together to check against the keyswitch state of a given hand. Instead, the `kaleidoscope::hid::getKeyswitchStateAtPosition()` method can be used to check the state of a keyswitch at a given row and column; or at a given index. -### KALEIDOSCOPE_API_VERSION bump +### HostOS -`KALEIDOSCOPE_API_VERSION` has been bumped to **2** due to the plugin API -changes. It does not mean that version two of the API is final, though. The bump -is there so plugins can check it, and make compile-time decisions based on it. -Such as whether to compile for the version one, or for the version two API. +Prior versions of `HostOS` used to include a way to auto-detect the host +operating system. This code was brittle, unreliable, and rather big too. For +these reasons, this functionality was removed. The `autoDetect()` method is now +a no-op, and is deprecated. +Furthermore, `HostOS` now depends on `Kaleidoscope-EEPROM-Settings`, that plugin +should be initialized first. -The API version will remain the same, even if we introduce breaking changes - -until a stable release is made from the v2 branch. From that point onwards, the -API version will change with further breaking changes. +The deprecated `autoDetect()` method will be removed by **2019-01-14**. -### New source code layout +### MagicCombo -The sources were rearranged so that most of them live under `src/kaleidoscope`, -with only the main header, `Kaleidoscope.h` out in `src/`. Some select headers -that were used by plugins in the wild also remained in `src/`, but now emit a -warning. If you were including anything other than `Kaleidoscope.h` which was -not namespaced, please update the include, and either add the namespace prefix, -or consider removing the include altogether. Most - if not all - parts of -Kaleidoscope are included via `Kaleidoscope.h` by design, so there should not be -a need for any extra includes. +To make `MagicCombo` more portable, and easier to use, we had to break the API previously provided, there was no way to maintain backwards compatibility. This document is an attempt at guiding you through the process of migrating from the earlier API to the current one. -Deprecated APIs and their replacements --------------------------------------- +Migration should be a straightforward process, but if you get stuck, please feel free to [open an issue][gh:issues], or start a thread on the [forums][forums], and we'll help you with it. -As the firmware evolves, there are - and will be - APIs that we deprecate, and -eventually remove. This document is a short guide that lists the deprecations - -along with when it happened, and when the functionality will be removed -, -suggested upgrade paths, and any other information that may be useful. + [gh:issues]: https://github.com/keyboardio/Kaleidoscope/issues + [forums]: https://community.keyboard.io/ + +Trying to use the old API errors out with a helpful error message, but as the old API is deprecated, this will be removed by **2019-01-14**. + +#### The old API + +```c++ +void magicComboActions(uint8_t combo_index, uint32_t left_hand, uint32_t right_hand) { + switch (combo_index) { + case 0: + Macros.type(PSTR("It's a kind of magic!")); + break; + } +} + +static const kaleidoscope::MagicCombo::combo_t magic_combos[] PROGMEM = { + { + R3C6, // left palm key + R3C9 // right palm key + }, + {0, 0} +}; + +void setup() { + Kaleidoscope.setup(); + + MagicCombo.magic_combos = magic_combos; +} +``` + +Previously, we used a global, overrideable function (`magicComboActions`) to run +the actions of all magic combos, similar to how macros are set up to work. +Unlike macros, magic combos can't be defined in the keymap, due to technical +reasons, so we had to use a separate list - `magic_combos` in our example. We +also needed to tell `MagicCombo` to use this list, which is what we've done in +`setup()`. + +#### The new API + +```c++ +void kindOfMagic(uint8_t combo_index) { + Macros.type(PSTR("It's a kind of magic!")); +} + +USE_MAGIC_COMBOS({ + .action = kindOfMagic, + .keys = {R3C6, R3C9} // Left Fn + Right Fn +}); +``` + +The new API is much shorter, and is inspired by the way the [Leader][leader] +plugin works: instead of having a list, and a dispatching function like +`magicComboActions`, we include the action method in the list too! + + [leader]: doc/plugin/Leader.md + +We also don't make a difference between left- and right-hand anymore, you can +just list keys for either in the same list. This will be very handy for +non-split keyboards. + +#### Migration + +First of all, we'll need to split up `magicComboActions` into separate +functions. Each function should have a unique name, but their shape is always +the same: + +```c++ +void someFunction(uint8_t combo_index) { + // Do some action here +} +``` + +Copy the body of each `case` statement of `magicComboActions`, and copy them one +by one into appropriately named functions of the above shape. You can name your +functions anything you want, the only constraint is that they need to be valid +C++ function names. The plugin itself does nothing with the name, we'll +reference them later in the `USE_MAGIC_COMBOS` helper macro. + +Once `magicComboActions` is split up, we need to migrate the `magic_combos` list +to the new format. That list had to be terminated by a `{0, 0}` entry, the new +method does not require such a sentinel at the end. + +For each entry in `magic_combos`, add an entry to `USE_MAGIC_COMBOS`, with the +following structure: + +```c++ +{.action = theActionFunction, + .keys = { /* list of keys */ }} +``` + +The list of keys are the same `RxCy` constants you used for `magic_combos`, with +the left- and right hands combined. The action, `theActionFunction`, is the +function you extracted the magic combo action to. It's the function that has the +same body as the `case` statement in `magicComboActions` had. + +And this is all there is to it. + +If your actions made use of the `left_hand` or `right_hand` arguments of +`magicComboActions`, the same information is still available. But that's a bit +more involved to get to, out of scope for this simple migration guide. Please +open an issue, or ask for help on the forums, and we'll help you. + +### TypingBreaks + +Older versions of the plugin used to provide EEPROM storage for the settings only optionally, when it was explicitly enabled via the `TypingBreaks.enableEEPROM()` method. Similarly, the Focus hooks were optional too. + +Both of them are unconditionally enabled now, because they add so much to the plugin. This means that any calls to `TypingBreaks.enableEEPROM()` can be safely removed, the method is deprecated, a no-op by now. The method will be removed by **2019-01-14**. + +Storing the settable settings in EEPROM makes it depend on `Kaleidoscope-EEPROM-Settings`, which should be initialized before this plugin is. + +## Deprecated APIs and their replacements -If any of this does not make sense to you, or you have trouble updating your -.ino sketch, do not hesitate to write us at help@keyboard.io, we can help you -fix it. +### Source code and namespace rearrangement -### To be removed by 2019-01-14 +With the move towards a monorepo-based source, some headers have moved to a new location, and plenty of plugins moved to a new namespace (`kaleidoscope::plugin`). This means that the old headers, and some old names are deprecated. Unless noted otherwise, the old names still work, but will likely emit a warning, and the compatibility shims will be removed by **2019-01-14**. -Any headers provided by the firmware other than `Kaleidoscope.h` (currently -`layers.h`, `key_defs_keymaps.h` and `macro_helpers.h`) are obsolete, and will -be removed. +The following headers and names have changed: -One should not need to use `key_defs_keymaps.h` and `layers.h`, as -`Kaleidoscope.h` includes them anyway, and the same goes for `macro_helpers.h`. -If one absolutely must, use `kaleidoscope/key_defs_keymaps.h` and -`kaleidoscope/macro_helpers.h` instead. +- `layers.h`, `key_defs_keymaps.h` and `macro_helpers.h` are obsolete, and should not be included in the first place, as `Kaleidoscope.h` will pull them in. In the rare case that one needs them, prefixing them with `kaleidoscope/` is the way to go. Of the various headers provided under the `kaleidoscope/` space, only `kaleidoscope/macro_helpers.h` should be included directly, and only by hardware plugins that can't pull `Kaleidoscope.h` in due to circular dependencies. +- `LED-Off.h`, provided by [LEDControl](doc/plugin/LEDControl.md) is obsolete, the `LEDOff` LED mode is automatically provided by `Kaleidoscope-LEDControl.h`. The `LED-Off.h` includes can be safely removed. +- `LEDUtils.h` is automatically pulled in by `Kaleiodscope-LEDControl.h`, too, and there's no need to directly include it anymore. +- Plugins that implement LED modes should subclass `kaleidoscope::plugin::LEDMode` instead of `kaleidoscope::LEDMode`. +- [GhostInTheFirmware](doc/plugin/GhostInTheFirmware.md) had the `kaleidoscope::GhostInTheFirmware::GhostKey` type replaced by `kaleidoscope::plugin::GhostInTheFirmware::GhostKey`. +- [HostOS](doc/plugin/HostOS.md) no longer provides the `Kaleidoscope/HostOS-select.h` header, and there is no backwards compatibility header either. +- [Leader](doc/plugin/Leader.md) had the `kaleidoscope::Leader::dictionary_t` type replaced by `kaleidoscope::plugin::Leader::dictionary_t`. +- [LED-AlphaSquare](doc/plugin/LED-AlphaSquare.md) used to provide extra symbol graphics in the `kaleidoscope::alpha_square::symbols` namespace. This is now replaced by `kaleidoscope::plugin::alpha_square::symbols`. +- [LEDEffect-SolidColor](doc/plugin/LEDEffect-SolidColor.md) replaced the base class - `kaleidoscope::LEDSolidColor` - with `kaleidoscope::plugin::LEDSolidColor`. +- [Qukeys](doc/plugin/Qukeys.md) had the `kaleidoscope::Qukey` type replaced by `kaleidoscope::plugin::Qukey`. +- [ShapeShifter](doc/plugin/ShateShifter.md) had the `kaleidoscope::ShapeShifter::dictionary_t` type replaced by `kaleidoscope::plugin::ShapeShifter::dictionary_t`. +- [SpaceCadet](doc/plugin/SpaceCadet.md) had the `kaleidoscope::SpaceCadet::KeyBinding` type replaced by `kaleidoscope::plugin::SpaceCadet::KeyBinding`. +- [Syster](doc/plugin/Syster.md) had the `kaleidoscope::Syster::action_t` type replaced by `kaleidoscope::plugin::Syster::action_t`. +- [TapDance](doc/plugin/TapDance.md) had the `kaleidoscope::TapDance::ActionType` type replaced by `kaleidoscope::plugin::TapDance::ActionType`. -Deprecated and removed APIs ---------------------------- +# Removed APIs ### Removed on 2018-08-20 diff --git a/doc/plugin/FocusSerial.md b/doc/plugin/FocusSerial.md index 8b94a81f..3689b9e8 100644 --- a/doc/plugin/FocusSerial.md +++ b/doc/plugin/FocusSerial.md @@ -2,10 +2,10 @@ Bidirectional communication for Kaleidoscope. With this plugin enabled, plugins that implement the `onFocusEvent` hook will start responding to Focus commands sent via `Serial`, allowing bidirectional communication between firmware and host. -This plugin is an upgrade of the former [Kaleidoscope-Focus][kaleidoscope:focus] plugin. See the [UPGRADING][upgrading] section for information about how to transition to the new system. +This plugin is an upgrade of the former [Kaleidoscope-Focus][kaleidoscope:focus] plugin. See the [UPGRADING.md][upgrading] document for information about how to transition to the new system. [kaleidoscope:focus]: Focus.md - [upgrading]: #upgrading-from-focus-to-onfocusevent--focusserial + [upgrading]: ../../UPGRADING.md#bidirectional-communication-for-plugins ## Using the plugin @@ -96,197 +96,3 @@ the keyboard responds. Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/FocusSerial/FocusSerial.ino - -Upgrading from Focus to onFocusEvent + FocusSerial -================================================== - -Upgrading from `Focus` to `onFocusEvent` and `FocusSerial` is a reasonably simple process, the interface is quite similar. Nevertheless, we present a step-by-step guide here, covering two use cases: one where we wish to always provide a Focus command when both our plugin and `FocusSerial` are enabled; and another where we only wish to provide the command when explicitly asked to do so. - -## The most trivial example - -The biggest difference between `Focus` and `onFocusEvent` is that the former required explicit registering of hooks, while the latter does it automatically: every plugin that implements the `onFocusEvent` method will be part of the system. As a consequence, only plugins are able to supply new commands: there is no explicit registration, thus, no way to inject a command that isn't part of a plugin. This also means that these functions now return `kaleidoscope::EventHandlerResult` instead of `bool`. Lets see a trivial example! - -### Focus - -```c++ -bool exampleFocusHook(const char *command) { - if (strcmp_P(command, PSTR("example")) != 0) - return false; - - Serial.println(F("This is an example response. Hello world!")); - - return true; -} - -KALEIDOSCOPE_INIT_PLUGINS(Focus) - -void setup() { - Serial.begin(9600); - Kaleidoscope.setup(); - Focus.addHook(FOCUS_HOOK(exampleFocusHook, "example")); -} -``` - -### onFocusEvent - -```c++ -namespace kaleidoscope { -class FocusExampleCommand : public Plugin { - public: - FocusExampleCommand() {} - - EventHandlerResult onFocusEvent(const char *command) { - if (strcmp_P(command, PSTR("example")) != 0) - return EventHandlerResult::OK; - - Serial.println(F("This is an example response. Hello world!")); - return EventHandlerResult::EVENT_CONSUMED; - } -}; -} - -kaleidoscope::FocusExampleCommand FocusExampleCommand; - -KALEIDOSCOPE_INIT_PLUGINS(Focus, FocusExampleCommand); - -void setup() { - Kaleidoscope.setup(); -} -``` - -### Summary - -The new version is slightly more verbose for the trivial use case, because we have to wrap it up in an object. But other than that, the changes are minimal, and we don't need to explicitly register it! - -Observe that the return values changed: with `Focus`, if we wanted other hooks to have a chance at processing the same command, the hook returned `false`; if we wanted to stop processing, and consider it consumed, it returned `true`. With the new system, this is more descriptive with the `EventHandlerResult::OK` and `EventHandlerResult::EVENT_CONSUMED` return values. - -## A stateful example - -Perhaps a better example that shows the quality of life improvements the new system brings is the case where the command needs access to either plugin state, or plugin methods. With the former system, the focus hooks needed to be static methods, and needed to be public. This is not necessarily the case now, because `onFocusEvent` is a non-static object method. It has full access to plugin internals! - -### Focus - -```c++ -namespace kaleidoscope { -class ExamplePlugin : public Plugin { - public: - ExamplePlugin(); - - static bool exampleToggle() { - example_toggle_ = !example_toggle_; - return example_toggle_; - } - - static bool focusHook(const char *command) { - if (strcmp_P(command, PSTR("example.toggle")) != 0) - return false; - - ::Focus.printBool(exampleToggle()); - return true; - } - - private: - static bool example_toggle_; -}; -} - -kaleidoscope::ExamplePlugin ExamplePlugin; - -KALEIDOSCOPE_PLUGIN_INIT(Focus, ExamplePlugin) - -void setup() { - Serial.begin(9600); - Kaleidoscope.setup(); - - Focus.addHook(FOCUS_HOOK(ExamplePlugin.focusHook, "example.toggle")); -} -``` - -### onFocusEvent - -```c++ -namespace kaleidoscope { -class ExamplePlugin : public Plugin { - public: - ExamplePlugin(); - - EventHandlerResult onFocusEvent(const char *command) { - if (strcmp_P(command, PSTR("example.toggle")) != 0) - return EventHandlerResult::OK; - - example_toggle_ = !example_toggle_; - ::Focus.printBool(example_toggle_); - - return EventHandlerResult::EVENT_CONSUMED; - } - - private: - static bool example_toggle_; -}; -} - -kaleidoscope::ExamplePlugin ExamplePlugin; - -KALEIDOSCOPE_PLUGIN_INIT(Focus, ExamplePlugin) - -void setup() { - Kaleidoscope.setup(); -} -``` - -### Summary - -It's just another plugin, with just another event handler method implemented, nothing more. No need to explicitly register the focus hook, no need to provide access to private variables - we can just keep them private. - -## Optional commands - -Optional commands are something that were perhaps easier with the `Focus` method: one just didn't register them. With `onFocusEvent`, we need to do a bit more than that, and move the command to a separate plugin, if we do not wish to enable it in every case. This adds a bit of overhead, but still less than `Focus` did. - -### Focus - -```c++ -bool exampleOptionalHook(const char *command) { - if (strcmp_P(command, PSTR("optional")) != 0) - return false; - - Serial.println(Layer.getLayerState(), BIN); - return true; -} - -KALEIDOSCOPE_INIT_PLUGINS(Focus) - -void setup() { - Kaleidoscope.setup(); -} -``` - -Do note that we do not register the `exampleOptionalHook` here! As such, because it is unused code, it will get optimized out during compilation. While this is a simplistic example, the optional hook might have been part of a class, that provides other hooks. - -### onFocusEvent - -```c++ -namespace kaleidoscope { -class ExampleOptionalCommand : public Plugin { - public: - ExampleOptionalCommand() {} - - EventHandlerResult onFocusEvent(const char *command) { - if (strcmp_P(command, PSTR("optional")) != 0) - return EventHandlerResult::OK; - - Serial.println(Layer.getLayerState(), BIN); - return EventHandlerResult::EVENT_CONSUMED; - } -}; -} - -KALEIDOSCOPE_INIT_PLUGINS(Focus) - -void setup() { - Kaleidoscope.setup(); -} -``` - -### Summary - -The trick here is to move optional commands out into a separate plugin. It's a bit more boilerplate, but not by much. diff --git a/doc/plugin/GhostInTheFirmware.md b/doc/plugin/GhostInTheFirmware.md index 33df6769..cfded92a 100644 --- a/doc/plugin/GhostInTheFirmware.md +++ b/doc/plugin/GhostInTheFirmware.md @@ -75,10 +75,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/GhostInTheFirmware/GhostInTheFirmware.ino - -## Upgrading - -Previous versions of `GhostInTheFirmware` used -`kaleidoscope::GhostInTheFirmware::GhostKey` as a type for defining keys. In -newer versions, this is `kaleidoscope::plugin::GhostInTheFirmware::GhostKey`. -The old name still works, but will be removed by 2019-01-14. diff --git a/doc/plugin/HostOS.md b/doc/plugin/HostOS.md index 7aabb0de..8b7f6884 100644 --- a/doc/plugin/HostOS.md +++ b/doc/plugin/HostOS.md @@ -82,15 +82,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the extension. [plugin:example]: ../../examples/HostOS/HostOS.ino - -## Upgrading - -Prior versions of `HostOS` used to include a way to auto-detect the host -operating system. This code was brittle, unreliable, and rather big too. For -these reasons, this functionality was removed. The `autoDetect()` method is now -a no-op, and is deprecated. The `Kaleidoscope/HostOS-select.h` header is -similarly obsolete, and has even been removed (for unrelated reasons). The -`autoDetect()` method will be removed by 2019-01-14. - -Furthermore, `HostOS` now depends on `Kaleidoscope-EEPROM-Settings`, that plugin -should be initialized first. diff --git a/doc/plugin/LED-AlphaSquare.md b/doc/plugin/LED-AlphaSquare.md index cb9384f9..12eced9a 100644 --- a/doc/plugin/LED-AlphaSquare.md +++ b/doc/plugin/LED-AlphaSquare.md @@ -100,10 +100,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/LED-AlphaSquare/LED-AlphaSquare.ino - -## Upgrading - -Former versions of the plugin used to have extra symbols in the -`kaleidoscope::alpha_square::symbols` namespace, while current versions have -them under `kaleidoscope::plugin::alpha_square::symbols`. The old name is -deprecated, and will be removed by 2019-01-14. diff --git a/doc/plugin/LEDControl.md b/doc/plugin/LEDControl.md index 2a99e8d2..675d2c9a 100644 --- a/doc/plugin/LEDControl.md +++ b/doc/plugin/LEDControl.md @@ -4,16 +4,3 @@ This is a plugin for [Kaleidoscope][fw], for controlling the LEDs, and LED effects. [fw]: https://github.com/keyboardio/Kaleidoscope - -## Upgrading - -The `LEDUtils.h` and `LED-Off.h` headers are now included by default when using -``, and their explicit use is therefore deprecated. -The includes can be safely removed. - -Compatibility headers are in place for both, but will be removed by 2019-01-14. - -Furthermore, to implement LED modes, one should use -`kaleidoscope::plugin::LEDMode` as a base class now, instead of the former -`kaleidoscope::LEDMode`. There is a backwards compatible typedef, but like the -headers, it will be removed by 2019-01-14. diff --git a/doc/plugin/LEDEffect-SolidColor.md b/doc/plugin/LEDEffect-SolidColor.md index 963bf0f2..685ef48c 100644 --- a/doc/plugin/LEDEffect-SolidColor.md +++ b/doc/plugin/LEDEffect-SolidColor.md @@ -24,10 +24,3 @@ void setup() { ## Dependencies * [Kaleidoscope-LEDControl](LEDControl.md) - -## Upgrading - -Previous versions of `LEDEffect-SolidColor` used `kaleidoscope::LEDSolidColor` -as a class for defining solid-color effects. This is called -`kaleidoscope::plugin::LEDSolidColor` now. The old name still works, but is -deprecated, and will be removed by 2019-01-14. diff --git a/doc/plugin/Leader.md b/doc/plugin/Leader.md index 85f7ed74..26b62b1b 100644 --- a/doc/plugin/Leader.md +++ b/doc/plugin/Leader.md @@ -98,10 +98,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/Leader/Leader.ino - -## Upgrading - -Previous versions of `Leader` used `kaleidoscope::Leader::dictionary_t` as a -type for defining the dictionary. In newer versions, this is -`kaleidoscope::plugin::Leader::dictionary_t`. The old name still works, but will -be removed by 2019-01-14. diff --git a/doc/plugin/MagicCombo.md b/doc/plugin/MagicCombo.md index 6a3256e6..139ca26f 100644 --- a/doc/plugin/MagicCombo.md +++ b/doc/plugin/MagicCombo.md @@ -68,118 +68,3 @@ started with the plugin. ![rxcy layout](../model01_coordinates.png) [plugin:example]: ../../examples/MagicCombo/MagicCombo.ino - -## Upgrading - -To make `MagicCombo` more portable, and easier to use, we had to break the API -previously provided, there was no way to maintain backwards compatibility. This -document is an attempt at guiding you through the process of migrating from the -earlier API to the current one. - -Migration should be a straightforward process, but if you get stuck, please feel -free to [open an issue][gh:issues], or start a thread on the [forums][forums], -and we'll help you with it. - - [gh:issues]: https://github.com/keyboardio/Kaleidoscope/issues - [forums]: https://community.keyboard.io/ - -Trying to use the old API errors out with a helpful error message, but as the -old API is deprecated, this will be removed by 2019-01-14. - -## The old API - -```c++ -void magicComboActions(uint8_t combo_index, uint32_t left_hand, uint32_t right_hand) { - switch (combo_index) { - case 0: - Macros.type(PSTR("It's a kind of magic!")); - break; - } -} - -static const kaleidoscope::MagicCombo::combo_t magic_combos[] PROGMEM = { - { - R3C6, // left palm key - R3C9 // right palm key - }, - {0, 0} -}; - -void setup() { - Kaleidoscope.setup(); - - MagicCombo.magic_combos = magic_combos; -} -``` - -Previously, we used a global, overrideable function (`magicComboActions`) to run -the actions of all magic combos, similar to how macros are set up to work. -Unlike macros, magic combos can't be defined in the keymap, due to technical -reasons, so we had to use a separate list - `magic_combos` in our example. We -also needed to tell `MagicCombo` to use this list, which is what we've done in -`setup()`. - -## The new API - -```c++ -void kindOfMagic(uint8_t combo_index) { - Macros.type(PSTR("It's a kind of magic!")); -} - -USE_MAGIC_COMBOS({ - .action = kindOfMagic, - .keys = {R3C6, R3C9} // Left Fn + Right Fn -}); -``` - -The new API is much shorter, and is inspired by the way the [Leader][leader] -plugin works: instead of having a list, and a dispatching function like -`magicComboActions`, we include the action method in the list too! - - [leader]: Leader.md - -We also don't make a difference between left- and right-hand anymore, you can -just list keys for either in the same list. This will be very handy for -non-split keyboards. - -## Migration - -First of all, we'll need to split up `magicComboActions` into separate -functions. Each function should have a unique name, but their shape is always -the same: - -```c++ -void someFunction(uint8_t combo_index) { - // Do some action here -} -``` - -Copy the body of each `case` statement of `magicComboActions`, and copy them one -by one into appropriately named functions of the above shape. You can name your -functions anything you want, the only constraint is that they need to be valid -C++ function names. The plugin itself does nothing with the name, we'll -reference them later in the `USE_MAGIC_COMBOS` helper macro. - -Once `magicComboActions` is split up, we need to migrate the `magic_combos` list -to the new format. That list had to be terminated by a `{0, 0}` entry, the new -method does not require such a sentinel at the end. - -For each entry in `magic_combos`, add an entry to `USE_MAGIC_COMBOS`, with the -following structure: - -```c++ -{.action = theActionFunction, - .keys = { /* list of keys */ }} -``` - -The list of keys are the same `RxCy` constants you used for `magic_combos`, with -the left- and right hands combined. The action, `theActionFunction`, is the -function you extracted the magic combo action to. It's the function that has the -same body as the `case` statement in `magicComboActions` had. - -And this is all there is to it. - -If your actions made use of the `left_hand` or `right_hand` arguments of -`magicComboActions`, the same information is still available. But that's a bit -more involved to get to, out of scope for this simple migration guide. Please -open an issue, or ask for help on the forums, and we'll help you. diff --git a/doc/plugin/Qukeys.md b/doc/plugin/Qukeys.md index af98afff..7ec30bf5 100644 --- a/doc/plugin/Qukeys.md +++ b/doc/plugin/Qukeys.md @@ -150,9 +150,3 @@ limit, you won't get any unintended alternate keycodes. The [example][plugin:example] can help to learn how to use this plugin. [plugin:example]: ../../examples/Qukeys/Qukeys.ino - -## Upgrading - -Previous versions of `Qukeys` used `kaleidoscope::Qukey` objects within the -`QUKEYS` macro. In newer versions, this is `kaleidoscope::plugin::Qukey` -instead. The old name still works, but will be removed by 2019-01-14. diff --git a/doc/plugin/ShapeShifter.md b/doc/plugin/ShapeShifter.md index 2dd55c97..f5874fb1 100644 --- a/doc/plugin/ShapeShifter.md +++ b/doc/plugin/ShapeShifter.md @@ -59,11 +59,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/ShapeShifter/ShapeShifter.ino - -## Upgrading - -Previous versions of `ShapeShifter` used -`kaleidoscope::ShapeShifter::dictionary_t` as a type for defining the -dictionary. In newer versions, this is -`kaleidoscope::plugin::ShapeShifter::dictionary_t`. The old name still works, -but will be removed by 2019-01-14. diff --git a/doc/plugin/SpaceCadet.md b/doc/plugin/SpaceCadet.md index 545108dd..6906f73f 100644 --- a/doc/plugin/SpaceCadet.md +++ b/doc/plugin/SpaceCadet.md @@ -155,10 +155,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/SpaceCadet/SpaceCadet.ino - -## Upgrading - -Previous versions of `SpaceCadet` used -`kaleidoscope::SpaceCadet::KeyBinding` as a type for defining keybindings. In newer versions, this is -`kaleidoscope::plugin::SpaceCadet::KeyBinding`. The old name still works, -but will be removed by 2019-01-14. diff --git a/doc/plugin/Syster.md b/doc/plugin/Syster.md index 5d23f93c..9eee3a07 100644 --- a/doc/plugin/Syster.md +++ b/doc/plugin/Syster.md @@ -95,10 +95,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/Syster/Syster.ino - -## Upgrading - -Previous versions of `Syster` used `kaleidoscope::Syster::action_t` as the type -of Syster actions. In newer versions, this is -`kaleidoscope::plugin::Syster::action_t`. The old name still works, but will be -removed by 2019-01-14. diff --git a/doc/plugin/TapDance.md b/doc/plugin/TapDance.md index 99ad7bed..45e7ae2a 100644 --- a/doc/plugin/TapDance.md +++ b/doc/plugin/TapDance.md @@ -144,10 +144,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/TapDance/TapDance.ino - -## Upgrading - -Previous versions of `TapDance` used `kaleidoscope::TapDance::ActionType` as the -type of TapDance actions. In newer versions, this is -`kaleidoscope::plugin::TapDance::ActionType`. The old name still works, but will -be removed by 2019-01-14. diff --git a/doc/plugin/TriColor.md b/doc/plugin/TriColor.md index d653e36e..5a80623a 100644 --- a/doc/plugin/TriColor.md +++ b/doc/plugin/TriColor.md @@ -25,9 +25,9 @@ Then, we simply create a new instance of the `TriColor` class, with appropriate colors set for the constructor: ```c++ -kaleidoscope::TriColor BlackAndWhiteEffect (CRGB(0x00, 0x00, 0x00), - CRGB(0xff, 0xff, 0xff), - CRGB(0x80, 0x80, 0x80)); +kaleidoscope::plugin::TriColor BlackAndWhiteEffect (CRGB(0x00, 0x00, 0x00), + CRGB(0xff, 0xff, 0xff), + CRGB(0x80, 0x80, 0x80)); ``` The first argument is the base color, the second is for modifiers and special diff --git a/doc/plugin/TypingBreaks.md b/doc/plugin/TypingBreaks.md index 9c671127..c8ad6d31 100644 --- a/doc/plugin/TypingBreaks.md +++ b/doc/plugin/TypingBreaks.md @@ -106,18 +106,3 @@ Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. [plugin:example]: ../../examples/TypingBreaks/TypingBreaks.ino - -## Upgrading - -Older versions of the plugin used to provide EEPROM storage for the settings -only optionally, when it was explicitly enabled via the -`TypingBreaks.enableEEPROM()` method. Similarly, the Focus hooks were optional -too. - -Both of them are unconditionally enabled now, because they add so much to the -plugin. This means that any calls to `TypingBreaks.enableEEPROM()` can be safely -removed, the method is a no-op by now. - -Storing the settable settings in EEPROM makes it depend on -`Kaleidoscope-EEPROM-Settings`, which should be initialized before this plugin -is.