In the past, we were using `Focus.handleHelp()` to see if we're handling a
`help` command, and print the commands supported by the handler. We also used
`strcmp_P` directly to compare (parts of) our input against command supported by
the handler. This approach works, but had multiple major disadvantages: it
duplicated strings between `handleHelp` and the `strcmp_P` calls, and it relied
on fragile substring pointers to save space.
To replace all that, this patch implements a different approach. Help handling
is split between a check (`Focus.inputMatchesHelp()`) and a
reply (`Focus.printHelp()`), the latter of which takes a list of `PSTR()`
strings, rather than one single string. This allows us to reuse the same
strings for comparing against the handler's input.
The new approach no longer uses the fragile substring pointers, nor does it use
`strcmp_P` directly, but goes through a wrapper (`Focus.inputMatchesCommand()`)
instead.
These changes lead to a more readable pattern. While we do use longer strings as
a result, there is less duplication, and the new patterns also require less
code, so we end up with saving space, at least on AVR devices.
The old methods are still available and usable, but they're deprecated.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This applies to turning off formatting of keymaps. There were a few files that
were missing these comments, so those were added where necessary, as well.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This mini plugin is an example of how to suppress a held `shift` key from a
Macros sequence. In this case, it's to enable a macro that types an accented
character using a dead key (where the dead key must be entered without the
`shift` modifier held).
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This example sketch is now a fairly good demonstration of the power and
simplicity of the new KeyEvent handlers, and an example of a custom plugin
written directly in the sketch file.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Previously, we used index-ordering for layers, meaning, we looked keys up based
on the index of active layers. This turned out to be confusing, and in many
cases, limiting, since we couldn't easily shift to a lower layer from a higher
one. As such, index-ordering required careful planning of one's layers, and a
deeper understanding of the system.
This patch switches us to activation-ordering: the layer subsystem now keeps
track of the order in which layers are activated, and uses that order to look
keys up, instead of the index of layers. This makes it easier to understand how
the system works, and allows us to shift to lower layers too.
It does require a bit more resources, since we can't just store a bitmap of
active layers, but need 32 bytes to store the order. We still keep the bitmap,
to make `Layer.isActive()` fast: looking up a bit in the bitmap is more
efficient than walking the active layer array, and this function is often used
in cases where speed matters.
As a side effect of the switch, a number of methods were deprecated, and similar
ones with more appropriate names were introduced. See the updated `UPGRADING.md`
document for more details.
Plugins that used the deprecated methods were updated to use the new ones.
Fixes#857.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This reverts commit c917acb8a1, because that
introduced breaking changes, and we want to address the problem in a different
way instead.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This introduces a new plugin - `FlashHelper` - to aid with firmware-assisted
flashing. During the flashing process, this plugin can temporarily disable the
`Prog` key.
Addresses the firmware part of keyboardio/Chrysalis#509.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This adds `LEDControl.disable()` and `LEDControl.enable()` which disable and
enable LED operations, respectively. These are meant to replace the current
`LEDControl.paused` property (which is getting deprecated with this change), and
do some additional work on top of just disabling or re-enabling future updates
and sync. Namely, `disable()` will also turn LEDs off, while `enable()` will
refresh them all, too.
We also add a dedicated `Key_LEDToggle` key to disable/enable LEDs. This is
useful when one wants to turn LEDs off, without changing active LED mode to
`LEDOff`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The `MACRO(...)` macro stores the macro in progmem, and as such, needs to use
constants only. Rework the logic in `macroAppSwitch()` so that we keep that
requirement.
For some reason, the previous version of the code worked with gcc 5.4, but not
with gcc 7+, and the latter is right to complain.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of using `Kaleidoscope.serialPort()` in every example, introduce a
helper variable in some cases, to make the coder nicer to read.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of having to define `HARDWARE_IMPLEMENTATION` to the class name of the
device, and define `KeyboardHardware` from within the plugin, let all devices
set `kaleidoscope::Device` to their own class via a typedef. Furthermore,
instead of `KeyboardHardware`, use `Kaleidoscope.device()` instead. This makes
device plugins a little bit simpler, and our naming more consistent.
Because some parts of the firmware need to access the device object before the
`Kaleidoscope` object is available, we can't make it a member of that. For this
reason, the device object is `kaleidoscope_internal::device`, and
`Kaleidoscope.device()` wraps it. In general, the wrapper should be used. But if
access to the device is required before `Kaleidoscope` is available, then that's
also available.
The `Kaleidoscope` object grew a few more wrappers: `storage()` and
`serialPort()`, so that one doesn't need to use `Kaleidoscope.device()`
directly, but can use the wrappers, which are noticably shorter to write.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In preparation for making Serial access configurable on a per-board basis,
introduce `KeyboardHardware.serialPort()`, which - for the time being - returns
the Serial object.
All users of Serial have been updated to use the new API.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This implements a new plugin for Dynamic (EEPROM-stored) macros. Unlike the
Macros plugin, these macros are stored in EEPROM, and can't run custom code,
only the steps outlined in the Macros documentation.
The plugin provides two Focus commands (`macros.map` and `macros.trigger`) to
get or set the dynamic macros, and to trigger one without having to place them
on the keymap.
Fixes#370.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Introduce a couple of helper methods that make it easier to work with Focus.
These abstract away the dependency on Serial as a side-effect. The intent is
that all traffic will go through Focus.
Fixes#476.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>