Instead of trying to include an uint16_t in an array of uint8_ts, add the flags
and the rawKey separately. Without this, macro playback would not work, because
the sequence would be corrupt.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The reason it was removed before no longer applies, and enabling it saves
noticeable amounts of size when using KeyboardioFirmware as a library.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The main thing here is `Macros_::play`, which takes a list of bytes from
PROGMEM, and plays a macro. The array is always a command, followed by
arguments, and the size of the argument depends on the command: key presses and
releases take a 16-bit argument, and the event is injected into the event
handler flow. Waiting and interval change take a 8-bit time. Helpers are
provided to make it a little bit easier to construct a macro.
Of course, the `macroAction` method may do any other side effects, and is not
restricted to returning a sequence of commands.
Fixes#5.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of hardcoding the macro actions into the core firmware, use a
`macroAction` function that is marked weak. This makes it possible to override
the function from Sketches, and implement the handlers there.
While there, also made sure that the `macroAction` is always called, with
`keyState` argument appropriately set. With this, macro actions can trigger on
keyup, or while held, or anytime the implementor wants, not just on keypress.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Because the animation saves if it has been run, it may do so during
factory testing. But running it every time is annoying, too. So as per
@obra's request, the code for the animation is kept, but removed from
the default sketch.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of having a previousState and a currentState, of which at most
two bits are used, use a single byte. This saves us a lot of code space,
and makes a number of things easier, too.
The helpers were redone as macros, since they are just bit checks now.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
They are not used anywhere, and as such, are a distraction. The states
will be reworked into something similar that was now dropped, but that's
a separate patch.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
To make the code in the keyswitch state checking functions clearer, use
a macro instead of repeating the same constant everywhere.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of abusing `Key_NoKey`, use the new `INJECTED` flag in
`handle_key_event` and `handle_key_event_default` to check if the event
is an original, or an injected one.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The INJECTED flag can be used by handlers to determine where the event
originated from: as a result of a direct keypress, or if it was injected
into the event loop some other way.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
When one adds or removes a layer from a keymap, the keymap size has to
be adjusted in the call to `Keyboardio.setup()`. This is easy to forget,
so as a helper, introduce `KEYMAP_SIZE`, a macro that automatically
computes the size at compile time.
This way, one does not need to remember to update the size anywhere.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The mousekeys are not specific to the Model01, name it after Keyboardio
instead, as suggested by @obra.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Save the seen state in EEPROM, so that the boot animation is displayed
only on first boot, and not every time the keyboard boots, or is plugged
in.
This way, we still have a nice welcome animation on first boot, but it
won't become an annoying delay every time the keyboard boots.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
The primary reason for the move is to be able to disable mouse keys
completely, and not even compile them in. For this to work, it needs to
be in a separate library, otherwise it will always be included, even if
not active.
So, this patch turns mouse-keys into a simple plugin, included with the
core firmware! This makes the default event handler a bit simpler, the
code marginally smaller, and the feature completely optional.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
With the BootAnimation not functioning as a LED effect anymore, ship a
dedicated off effect.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Having the boot animation as a LED effect, making it function as an
"off" state, while a novel idea, is confusing. For this reason, make it
just a simple function we can call from the Sketch's `setup()` method.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
For those who'd like to work with C arrays, instead of generating
layouts from some other source, the `KEYMAP` macro makes it easier to
define a layer. The parameters in the macro arguments are arranged in
such a way that they can be formatted in a way that matches each hand
more closely. Similarly, a `KEYMAP_STACKED` is introduced, where the
hands are under each other, not side-by-side.
This is just aesthetics, for the C-savvier users.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
It would be nice if LED effects could be activated via their object, not
just their number, so that one could write - say, in a macro -
`myEffect.activate()`, and have it become the active mode.
To implement this, `LEDControl_` gains an `activate` method, that takes
a pointer, finds it in the mode array, and switches to its index (if
found). `LEDMode` gains an `activate` method too, which uses
`LEDControl`s new method of the same name to activate itself.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
While this function had a declaration in the header, it lacked an
implementation. With this patch, `key_led_map` moves to the cpp from the
header, and the function gains an implementation.
An additional helper, `led_set_crgb_at(row, col, color)` is added too,
similarly to the other arities.
This makes it a lot easier to address LEDs when knowing the key
position.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Recreate LEDControl as a class with pluggable parts, similar in vein to
the event handler and loop hooks. Except in this case, only the current
effect runs at any one time, the current one.
All existing effects were separated out into plugins, and the default
firmware example was updated too. All of them were pretty trivial, save
the special NumLock effect: that one also installs a loop hook, and
switches the LED mode if need be. Its setup function also skips to the
next effect, if the mode was selected manually.
Behaviour should be the same as before, but LED effects are now
pluggable, at the cost of some code and data size increase.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Instead of not handling the case where the LED index is out of range,
and thus producing a warning, return a black color instead. It's as good
as anything else, but at least gets rid of the warning.
And, it goes hand-in-hand with the set counterpart, which, in a similar
case, does nothing: thus the out-of-range LED remains black forever.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
After writing the row to Serial, return false, so that the key will be
further processed by the next handler. Also fixes a compile-time warning
with -Wall.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
Do the mappedKey lookup earlier, in handle_key_event, so that if any of
our handlers need to look at the mapped key, they do not have to look it
up themselves. This simplifies plugged hooks considerably, as they can
always assume that the mapped key they receive is correct. They still
receive enough information to do the lookup themselves, though, if they
ever need that.
Additionally, in handle_key_event_default, baseKey is only looked up if
mappedKey was NoKey. This is so that hooks can defer to this function,
via handle_key_event, setting their own mappedKey, without having to
worry about setting a row/col that would map to a special key on the
base layer.
Fixes#39.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
To make replacing work sanely, we first NULL out both the eventHandlers
and loopHooks arrays in the Keyboardio_ constructor. This allows the
replace functions to just run through the whole array, and either see
hook pointers there, or NULL. So they don't need to be afraid of garbage
being there.
This makes the replacing very easy: run through the array, and replace
the first occurrence of the old hook with the new. This further
simplifies addition: the old hook we pass in, will be NULL. If we run
out of space, it silently fails, like before.
Replacing hooks is important for cases where one wants to build features
that can be toggled off, or their behaviour otherwise changed at
run-time. In this case, the most efficent way is to replace the hook,
which is what these new helpers allow us to do.
This closes#36.
Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>