Introduce an MCU driver, with a few convenience methods to disable JTAG or clock
division. Both of these were re-implemented by various hardware plugins on their
own, this collapses them into a common implementation.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
If we found no modifiers on the current layer, force a re-scan. This way we'll
scan the keymap without having to change layers first. We can't do the same
thing at `onSetup()` time, because that's too early, so we do a check in
`beforeReportingState()`.
Fixes#608.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
OneShot keys were failing to activate on the first press because of how the timeout was
implemented. Most of the time, at the end of a cycle, `should_cancel_` was being set to
`true` because the current time was being compared to the last time a OneShot key was
activated, regardless of whether or not a OneShot key was active. As a result, OneShot
keys that were pressed for the first time in a while would fail to register as OneShots.
This change prevents checking the timeout unless there is an active OneShot key.
Fixes#603.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This should stop layers from getting stuck on when a release delay is in use. Instead of
recording the keycode of the key that will be released, I now have Qukeys just use the
key's coordinates, and have it do a lookup in `Layer.live_composite_keymap_` the usual
way.
I also stopped overloading the `key_queue[x].start_time` and instead record the release
delay time in a separate variable. This greatly simplifies the timeout math, and saves
another good-sized chunk of PROGMEM, as well as avoiding timeout-conflict bugs.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Now, when we flush a key from the queue, we just insert whatever its final `Key` value
should be into `Layer.live_composite_keymap_`, obviating the need to independently track
whether a flushed qukey is in its primary or alternate state. We can also get rid of all
the code for correcting `mapped_key`, because once a key has been flushed, it won't show
up as a qukey (or DualUse key) any longer.
This substantially reduces PROGMEM usage (~300 bytes) and reduces RAM usage by 8
bytes (for the Model01 hardware).
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
With qukey defined with an alternate `Key` value of `ShiftToLayer(N)`, we need a way to
send the toggle-off event in order to get the layer to deactivate. Since the physical key
was already released, we need to keep track of the delayed-release qukey, and send the
appropriate release event after the rest of the queue has been flushed.
This change records the delayed key at the time of the delay, and sends the release event
after the ensuing key has been flushed from the queue.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
With the changes to the updating of `Layer.live_composite_keymap_`, the code that changes
the `mapped_key` values for keys that have been flushed from the queue is unnecessary.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
SpaceCadet was sending a keyswitch event with the row & column coordinates of the wrong
key. The coordinates were coming from the keypress, but the injected event was for a
previously-pressed (different) key that's still held. With the mutable
`live_composite_keymap_[]` change, this meant that pressing (and holding) `shift` then
another key would result in only a single character, rather than a repeating
character. Regardless of the minor bug, using the row & col for the event was still
logically incorrect here.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
An `EPHEMERAL` keyswitch event is one that gets ignored by updates to
`live_composite_keymap_[]`, and thus doesn't change the keymap at all. This is useful for
a plugin that needs to retain its own key type in the keymap in order to do something
particular when it toggles off, but needs to inject an event with a different `Key` value,
with real key coordinates.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
If we're sending injected events with `UNKNOWN_KEYSWITCH_LOCATION` instead of
the (row,col) of the OneShot key, there's no need for the function that does this
conversion.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
With the changes to live_composite_keymap_, OneShot keys were no longer working. OneShot
modifiers would get stuck on, because the entry for the `OSM` key would get changed to the
modifier key value, and when the key was released, it wouldn't be processed by the OneShot
plugin, which would continue to re-apply the modifier indefinitely. At the same time,
OneShot layers wouldn't work at all, because the key would get changed to the layer shift
key, which would then turn the layer off when it was released.
This change fixes the problem by injecting keyswitch events from OneShot without physical
key coordinates, so nothing in `live_composite_keymap_` can get updated from it. OneShot
wants the `Key` entries there to remain as OneShot keys, not as whatever they're changed
to, so this is the most appropriate way I can think of to fix the issue.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
If `handleKeyswitchEvent()` is called with a `mappedKey` other than `Key_NoKey`, update
`live_composite_keymap_` with the specified `mappedKey` instead of doing a keymap lookup
on active layers. This allows a plugin to call `handleKeyswitchEvent()` and specify what
the `Key` value should be, and not have to separately track what value to change it to
every cycle.
This is especially important when there's a layer change. In particular, this is the
simplest way to allow Qukeys to use `ShiftToLayer()` keys that work properly.
Fixes#501.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This adds a new version of `updateLiveCompositeKeymap()` which takes three parameters:
row, column, and a `Key` value. Instead of looking up the value to update in the key map,
it just updates `live_composite_keymap_` with the specified `Key` value.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Instead of trying to be clever by checking if a mask applies to a layer index,
just check if the layer is higher or equal (or lower, as appropriate) than our
`IGNORE_HARDCODED_LAYER` value.
This addresses keyboardio/Chrysalis#341.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Since LED modes only send updates to the hardware at `syncDelay` intervals, calling
`update()` on the active mode every cycle doesn't make animations any smoother.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This decreases the rate at which LEDs get updated from ~60Hz to ~30Hz, which should be
fast enough that human eyes won't be able to tell the difference.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
The LED-Stalker plugin was looping through its table of `step` values (one for each key)
on every call to `update()`, and calling `compute()` on every value there, but those table
entries were only updated once every 50ms (by default), resulting in a lot of repeated
computation. This resulted in the mean idle cycle time increasing from 565µs to 1317µs on
the Model01 with an (almost) unmodified standard sketch.
This change moves the check for the timeout before the loop through the `step` values, and
aborts processing there if not enough time has elapsed. The resulting mean idle cycle time
becomes 577µs -- an almost negligible increase. It also reduces the PROGMEM footprint by
44 bytes.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This commit silences a warning due to an undefined variable.
A first attemt to locally supress the warning using compiler pragmas was
unsuccessfull due to a compiler bug in all gcc versions. This bug
in all gcc versions below 6.1 makes local diagnostics suppression useless.
As future versions of Arduino will ship with later versions of gcc
from a certain point on, the supplied warning suppression macros will become useful
to avoid the necessity to set global compiler flags like -Wno... and to
enable more precise warning suppression.
The new header file comes with an example that explains how to use
the suppression mechanism.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Various old methods provided by `Layer` have been deprecated for a while, and
were scheduled to be removed by February 14, 2019. We're past that, so lets
remove them.
Fixes#577.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
On AVR8, 16-bit bit-operations are expensive. Switch from using 3 16-bit
bitfields to using a 16-element array of a carefully constructed struct.
This saves us almost 300 bytes of PROGMEM at the cost of 10 bytes of memory.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
I tried to be smart and use `sizeof()` instead of hard-coding the array size,
but I used it wrong, and we iterated to 32 instead of 16, overflowing the array
and looking at parts of the memory we had no business looking at. This resulted
in `isPressed()` and `isSticky()` always being true.
Instead of trying to be clever, use `OneShot::ONESHOT_KEY_COUNT` throughout,
which is a constexpr defined at 16, the number of oneshot keys we have.
Fixes#572.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In `beforeReportingState()` and `afterEachCycle()` we used to return early if no
OneShots were active. This was easy to do when we were using a bitfield, we'd
just tested for non-zero. Since we're using an array now, this check is more
expensive, and the extra work negates any benefit of returning early.
For this reason, these early returns are removed.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Now that we're using a struct with descriptive member names, drop the helper
macros that made using bitfield manipulation readable. The code's readable
without them by now.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
On AVR8, 16-bit bit-operations are expensive. Switch from using 4(!) 16-bit
bitfields to using a 16-element array of a carefully constructed struct.
This saves us about 242 PROGMEM at the cost of 8 bytes of memory, and a tiny
performance hit.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
We want to be able to notice when the layout of the EEPROM *settings*
changed (which the CRC does not cover). For this reason, we're repurposing the
existing version setting, which wasn't widely used: it is now internal.
We use the version to determine whether the EEPROM has been written to yet, or
if it is uninitialized. This helps us make sure we're starting up with sensible
defaults.
Fixes#559, and fixes#558.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Previously we requested a slice in `onSetup()`, but this had a major,
problematic implication: if we went from a sketch with `EEPROM-Keymap`, but
withot `LED-Palette-Theme` enabled to one with it, the EEPROM layout was not
compatible, no matter what the order of plugins in `KALEIDOSCOPE_INIT_PLUGINS`
were. This happened because `EEPROM-Keymap` requested space *after* `onSetup()`
already ran.
To fix this issue, request a slice in `.reserveThemes`, only if we didn't
request a slice yet. This way the EEPROM layout is decided by the order of
initialization in `setup()`, and we do not sneakily steal a slice in
`onSetup()`.
This is required to address keyboardio/Chrysalis#270.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of having a single `keymap.map` Focus command that tries to be smart
about what layers it presents, we should have two separate commands: one to
query the defaults (PROGMEM), and one to get/set the custom keymap (EEPROM).
This makes `keymap.map` and `keymap.roLayers` obsolete, and they're now removed.
Furthermore, having to specify whether the EEPROM keymap extends the built-in
one or not proved to be unflexible. So we re-purposed the highest bit of the
first EEPROM byte, to signal whether we should use EEPROM layers only or not.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
We want to give the hardware enough time to give us a stable read of the pins.
If we unroll the loop, we will not have that. In practice, this leads to entire
rows or columns behaving erratically.
To fix that, we tell the compiler not to unroll loops in the `readCols()`
method (it's free to unroll them elsewhere). This makes the function a tiny bit
slower, but gives us a stable read.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Counting cycles is an incredibly unreliable way of timing animations. Use timers
instead.
Fixes#545.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
When not using the `CRGB()` macro, colors may end up being different than
intended if the board we're running on implements RGB order differently.
Fixes#548.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Since `Focus.send()` does not send a newline implicitly, we should do so
explicitly. Introduce `Focus.NEWLINE` to help with this, and not have many
copies of `'\n'` lying around.
Fixes#544.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The KBD4x has a set of WS2812 LEDs, which are very picky about timing. To make
them happy (even though we do not use them yet), we need to disable clock
division at startup.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
We deprecated a number of interfaces, which were scheduled to be removed on the
14th of January. Lets remove them now.
Incidentally, we had a number of places where we used the old names internally
too, and this has been corrected as well now.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
EEPROM defaults to `0xff` when uninitialized, which means we'd start off with a
bright white palette. That's a problem, because it draws a lot of power,
especially when all keys are lit bright. For this reason, flip the bits when
reading or storing palette colors, so the default `0xff` becomes `0x00`, black.
Fixes#529.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Brace-initialization has issues, especially with newer compilers that try to do
more, and better optimizations. To allow them to do these, we should be striving
for better type safety. For this reason, use the new Key() constructors to
initialize the various key defines. This gives the compiler much better hints.
The code becomes much more readable too.
This is fully backwards compatible, we're not removing any existing interface,
just using a newly introduced one. The old ways still work. They might produce
warnings with newer compilers, but they did so before anyway.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
We need to guard the `k` argument, place it within parens, to make sure it is
treated as a single argument, even if it expands to something that would be
ambigous. This is required, because most - if not all - keys are defined as a
list casted to `Key`, which the pre-processor would misinterpret without the
extra parens.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
To make it easier to create custom shortcuts, that do not interfere with system
ones, an old trick is to use many modifiers. To make this easier, Ctrl+Shift+Alt
is commonly abbreviated as "Meh", while Ctrl+Shift+Alt+GUI is often called
"Hyper". To support this, we offer the `Key_Meh` and `Key_Hyper` aliases, along
with `MEH(k)` and `HYPER(k)` to go with them.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
We should be using a different variant of the `default_layer()` method to query
the default layer instead of abusing 0xff as a special valie.
Fixes#522.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Add `REDIAL` to `kaleidoscope::ranges`, so the plugin can define `Key_Redial`
itself, and won't need `Redial.key` to be set in the user sketch either. This is
a breaking change, but one that's easy to upgrade to, hence no effort was made
to make it at least partially backwards-compatible.
Fixes#519.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
When selecting a new default layer via Focus, we should be moving there too,
because there may be no other way to switch to the new layer, and having to
reboot the keyboard for changes to take effect is not our desired behaviour.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
When sending `Key`s, there's no need for an extra separator, because
`send(key.raw)` will send one anyway. Not sending one results in 10 bytes less
PROGMEM used, and plenty of bytes less spent over the wire.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
When we use `lookup()`, we're looking up from the cache, not from the active
layer. If the cache gets updated later than we're called, we won't notice. So do
an explicit lookup.
Fixes#507.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Due to the plugin needing a key coordinate -> geometric space mapping, it
depends on the keyboard used. As such, restrict it to the Keyboard.io Model01,
for which the mapping was set up.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
While the rainbow colors are great, some may want to restrict the colors to a
single hue. For this purpose, the `ripple_hue` property was introduced. It
defaults to `Wavepool.rainbow_hue` (a special value that tells the plugin to use
multiple hues).
Inspired by @bjc's ToyKeeper/Kaleidoscope-LED-Wavepool#8.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Based largely on ToyKeeper/Kaleidoscope-LED-Wavepool#8, this smooths out the hue
transitions, so that the ripple is a nice rainbow, without oddly flashing colors
while cycling through the effect.
Thanks @bjc for the change!
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Methods that originate from the `kaleidoscope::Hardware` base class need not be
documented every time they're being overridden. That leads to duplication, and
higher chance of documentation going stale. As such, remove such cases, and rely
on the base class having plenty of documentation instead.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Since all implementations of detachFromHost/attachToHost are the same for all
our current keyboards, move it to the base class as a default.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This is basically the old Kaleidoscope-Hardware plugin pulled in, and made into
a base class. The purpose is documentation (#167) mostly. The base class has
default implementations for all methods (most do nothing), and can be overridden
by derived classes. Since the hardware object is always going to be called
through `KeyboardHardware`, which has the exact type of the hardware, we do not
need to use virtual functions. The derived class will just shadow the default
implementations.
All hardware plugins were updated to use this (directly or indirectly). The
resulting compiled binary is the same, but we were able to remove a few
boilerplate lines from here and there.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In general, we want method names to be verbs, because they convey actions. The
`Layer.on()`, `Layer.off()`, etc family of functions weren't like that. It
wasn't immediately obvious that they turn layers on and off.
Furthermore, `Layer.next()` and `Layer.previous()` were even more confusing,
because one could easily think they implied moving to the selected layers, while
in practice, they just activated them.
All of these have new names, that better describe what they do. The old names
are still present, but emit a deprecation warning.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In the original `KeyboardioFirmware`, this was used to store the default keymap
index in EEPROM. When we removed the EEPROM storage, it was meant to be used by
sketches to set a default layer (the minimum layer one can switch to), which was
not nearly as useful. Even worse, the behaviour was complicated to reason about,
and it wasn't used anyway.
For these reasons, it is now deprecated, and will eventually be removed.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
As the name implies, this makes it possible to set all leds to the same color
depending on which layer is the topmost active one.
Fixes#492.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The ATMega32u4 chip Splitography does not have the JTAG interface disabled in
fuses, so we must do so from the firmware. Otherwise PIN_F4 - PIN_F7 would not
be usable for I/O.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
To work around an issue on OSX, initalize Serial as the very first thing in
`Kaleidoscope.setup`. This is a - hopefully - temporary workaround, until we can
track down the real issue.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Based on a discussion on Discord, this implements a simple plugin that can
temporarily disable the Windows (GUI) keys.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
When I did the GPLv3+ -> GPLv3-only change, and assigned my copyright to
Keyboard.io, some of the plugins were missed. This updates those too.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Make it possible to use the plugin for all known Atreus variants: the post-2016
PCB with A* and the FalbaTech handwired one with a Teensy (these two were the
only supported ones until now), the pre-2016 PCB with A*, and the legacy Teensy2
variant.
Fixes#430.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The pin list (and consequently the key layout list) was rearranged in the early
days of the plugin for more optimal scanning code. With -O3 and moving to
`ATMegaKeyboard`, that optimization is no longer relevant. This restores the pin
list and the layout to its original order, the order at which the hardware is
laid out.
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>
Improved the ATMega parts of row toggling, similar to how `ATMegaKeyboard` does
it, and separated it from selecting extender rows. This results in a tiny
increase in speed, and better clarity.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of only reporting the state when the timer triggers, report it every
loop, even if it is unchanged.
This is based on a similar change to `ATMegaKeyboard`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Set the previous key state when reporting the state to Kaleidoscope, instead of
on every read. This eliminates a possible chatter bug. Idea taken from a similar
change made to `ATMegaKeyboard`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Based on the change made to `ATMegaKeyboard`, apply the same treatment to the
`ErgoDoxScanner` too, and run debouncing only 3 times per 5ms, which is closer
to what switch manufacturers recommend.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Keys normally only change when switching layers, so instead of going through
every key in every cycle to look for modifiers, do that once, when layers
change (using the new `onLayerChange` event), and store the coordinates of keys
we consider modifiers in an array (currently limited to 16 items).
Then, when we want to highlight them, go over this array only, significantly
reducing the work we need to do. In a typical case, on a full-size keyboard, one
would have eight modifiers and a few layer keys, so instead of going through a
hundred keys, we go through sixteen at most, but usually considerably less.
This fixes#403, at the cost of noticeably higher PROGMEM and RAM use.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of tracking layer changes ourselves, use the new `onLayerChange` event
to do that for us. This makes the code a tiny bit easier to follow.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The intent is to make it easier for plugins to detect layer changes and schedule
work accordingly. There event receives no arguments, the current state can
always be queried with `Layer.getLayerState()`, and if a plugin requires the old
state too, they can track that on their own.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
If we wish to support hardware that has LEDs, we should not define the `cRGB`
struct and the `CRGB` macro unconditionally. Define them only if the macro is
undefined. This way any hardware that has LEDs, and still wishes to use
`ATMegaKeyboard` as a base can define the macro prior to including the header.
Such hardware will override the LED functions anyway, so there's nothing else we
need to do to support such a scenario.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Sometimes we'd like to be in control of when reports are sent during macro
playback. This implements a way to achieve that.
Fixes#368.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of guarding the ATMegaKeyboard files with an `#if` that hard-coded which
keyboards are based on the class, guard them with
`KALEIDOSCOPE_WITH_ATMEGA_KEYBOARD`, set by the main hardware headers. Those
headers get included early, and are as such, a perfect way to guard these
things.
This way if we add a new keyboard using the base class, we don't have to modify
the base class itself, and the new hardware plugin can be entirely self-contained.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Since `keyIndex` is pretty much the same for all boards, it makes sense to have
it in `key_indexes.h`. To be able to do that, we need to implement it as a
macro, otherwise `HARDWARE_IMPLEMENTATION` can't be resolved. With a macro, it
is evaluated on call-sites, where the compiler can resolve that symbol.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Whenever calling a function implemented by the class, call it through
`KeyboardHardware`, so they can be overridden.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Both the Atreus and the Planck ports use very similar architecture, lift out the
common parts into a base class.
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
Instead of having a separate function for selecting and unselecting rows, have
only one that toggles them - we only ever want to toggle them anyway. While
there, optimize it slightly, by not toggling `DDRD`: if we set those in `setup`,
they'll remain set, and there's no need to toggle them.
This makes the code cleaner and smaller, at the cost of four bytes of RAM.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In certain cases we need to delay the unicode input sequence, otherwise the host
is unable to process the input properly. Introduce the `.input_delay()`
setter/getter for this purpose. We're defaulting to zero (no delay) nevertheless.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Based on work by Shriramana Sharma (@jamadagni) in
keyboardio/Kaleidoscope-LEDControl#27, this adds an optional `phase_offset`
argument to `breath_computer`. This allows one to have multiple breath effects
active at the same time, at different phases.
To make these synchronized, use `Kaleidoscope.millisAtCycleStart()` instead of
`millis()`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Initially, we were using `uint8_t` as the type for led indexes, which could not
go below zero, so we only needed one half of a bounds check. Since we switched
to a signed int, we need to check the other half of the boundaries: if the index
is below zero.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Based on the work of Shriramana Sharma (@jamadagni) in
keyboardio/Kaleidoscope-OneShot#45, this implements finer stickability controls
for `OneShot`, allowing one to set stickability on a per-key basis. The old
`.double_tap_sticky` and `.double_tap_sticky_layers` properties still work, but
are deprecated.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
When calculating `end_time`, explicitly cast `idle_time_limit` to 32 bits,
otherwise the `idle_time_limit * 1000` operation will be done on 16 bits, which
would overflow at about 65 seconds. With the cast, the operation will use all 32
bits, and we avoid the overflow.
Many thanks to @nevd for the report and the help in debugging & testing the fix.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Suggested by `nev` on Discord, this plugin will turn the LEDs off after a
configurable idle time, and back on on the next keypress.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
When `LEDControl` is paused, we want to pause not just the LED modes, but *all*
LED operations. The easiest way to do this is to not sync them.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This is pretty much the same thing as keyboardio/Kaleidoscope-OneShot#23 by
@jamesnvc, except that it also changes the `isLayerKey()` macro, which was
otherwise unused.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
To make the interaction with plugins that work on top of LEDModes (such as
`ActiveModColor`), we need a `refreshAt()` method. For AlphaSquare, we'll return
black when a pixel has timed out, or if a key is not part of the currently lit
symbol.
Fixes#401.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of remembering a key whenever a new one toggles on, remember only when
Redial itself is not held. We keep track of the last pressed key while Redial is
held, though, so we can update the key to redial when we're released ourselves.
This should fix#396.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
A long-long time ago, Kaleidoscope used to call `onKeyswitchEvent` (or rather,
it's then-current incarnation) even when keys were idle. For a number of
plugins, this was a case they didn't want to handle, and bailed out early.
When we changed Kaleidoscope to not call the event handlers for idle keys, these
plugins weren't modified at the same time, and the superfluous check remained,
making the firmware both larger and marginally slower.
Since the event handlers are never called when idle, it is safe to remove these
checks.
Affected plugins are `Leader`, `OneShot`, and `TapDance`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
EscapeOneShot needs to stop bailing out early when a oneshot is pressed (sticky
appears pressed), and continue with its process if there's a sticky oneshot.
This makes stickies cancelable via the EscapeOneShot plugin.
For this to work, OneShot needed an `.isSticky()` method, much like
`.isActive()` and `.isPressed()`.
Fixes#413 and likely addresses part of #408 too.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Way back when, in order to fix the issue explained in
keyboardio/Kaleidoscope-OneShot#4, we made it so that keys that interrupt a
OneShot will be masked (unless certain conditions are met). Since then, we
changed how keys are looked up, and the original problem is no longer present.
This makes the masking unnecessary.
Begin unnecessary is good news, because that masking prevented key repeat for
keys on a one-shot layer (even when the OSL key was held).
Fixes#415.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This allows us to do `i < LED_COUNT` comparisons on boards with no LEDs. All
places that did this comparison have been updated to use `int8_t`, as were all
places that use a LED index.
Together with the previous commits, fixes#385.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
LED related functions should be as close to no-op on LED-less hardware as
possible. For this reason, guard all relevant points with an early exit in the
LED-less case.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Intended to make it easier for LED-using code to bail out early, this simple
constant will tell us whether the board has LEDs or if it does not.
Because this will be used regularly, by code not close to the hardware,
`Kaleidoscope.has_leds` is an alias to `KeyboardHardware.has_leds`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In an attempt to move away from magic, global defines, move the `ROWS`, `COLS`,
and `LED_COUNT` defines to the hardware class. Backwards-compatible defines are
provided by `<Kaleidoscope.h>`.
This is just a first step, no users are updated just yet.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
With moving to a monorepo, the plugin will always be compiled, so we want to
guard ourselves, to only compile when building for the ErgoDox. We do this with
an `#ifdef ARDUINO_AVR_ERGODOX` guard.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Hardware-EZ-ErgoDox.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
With moving to a monorepo, the plugin will always be compiled, so we want to
guard ourselves, to only compile when building for the Atreus. We do this with
an `#ifdef ARDUINO_AVR_ATREUS` guard.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/HostOS.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
The `Kaleidoscope/HostOS-select.h` remains in place, for compatibility reasons.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/TypingBreaks.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Unicode.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Syster.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Redial.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LED-ActiveModColor.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Qukeys.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/TapDance.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/SpaceCadet.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/ShapeShifter.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LEDEffects.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This replaces the former `bootAnimation()` method with a plugin that does
something very similar, without locking up the keyboard for the duration of the
animation, and scans the keymap instead of using hard-coded coordinates.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In the Model01 header, we have a set of LED coordinates, based on key
labels (`LED_Q`, `LED_A`, etc). These aren't generally useful, the only user was
the ancient `bootAnimation`. With that gone, lets get rid of these too.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This boot animation has not been used for a long time, and chances are, noone
even noticed its here. It's a neat thing, but gets old very fast, and locks up
the keyboard during the animation.
Considering these, lets drop it.
Fixes#366.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Moved all files but `LEDControl.c` and `LEDControl.h` to
`src/kaleidoscope/plugin/LEDControl`, to not pollute the `kaleidoscope/plugin`
directory needlessly, with headers that should not be explicitly included.
Also updated the documentation and the warnings emitted to make it clear that
the use of `LED-Off.h` and `LEDUtils.h` is deprecated in favour of just using
`<Kaleidoscope-LEDControl.h>`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move auxiliary files to `src/kaleidoscope/plugin/MouseKeys` to not pollute the
`kaleidoscope/plugin` directory with headers not meant to be included directly.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Moved most files to `src/kaleidoscope/plugin/LED-AlphaSquare`, leaving only the
main one on the outside. This is to decrease the number of files in
`src/kaleidoscope/plugins` and not pollute the namespace needlessly.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
With Kaleidoscope core's layout rearranged, we should include
`kaleidoscope/macro_helpers.h` instead of `macro_helpers.h`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Merged `EEPROM-Settings-Focus` into `EEPROM-Settings` itself: there's no reason
they should be separate. Also moved the CRC headers to
`kaleidoscope/plugin/EEPROM-Settings/` to not pollute the plugin namespace.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LEDControl.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/MouseKeys.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/NumPad.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/MagicCombo.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/EEPROM-Settings.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LED-Stalker.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LEDEffect-Rainbow.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LEDEffect-Chase.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LEDEffect-Breathe.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LEDEffect-BootGreeting.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Hardware-Model01.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Model01-TestMode.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Macros.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LEDEffect-SolidColor.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LED-AlphaSquare.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Leader.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/GhostInTheFirmware.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/FocusSerial.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
This also merges the former `UPGRADING.md` into `doc/plugin/FocusSerial.md`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Lots of things were already under the `kaleidoscope` namespace, but were in the
"wrong" directory. This big patchset moves everything under `kaleidoscope/`, and
namespaces `Layers_`. There are a few un-namespaced things, but because their
use is so widespread, and they're used so commonly, we don't want to namespace
those (like `handleKeyswitchEvent`), at least not yet.
As a minor side-effect, this moves a few global statics that were once in
`Layers.cpp` into the `Layer_` class itself, for clarity and encapsulation.
Non-namespaced headers that were used outside of Kaleidoscope itself will still
work, but will emit a compile-time warning.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The `FingerprintUSBHost` library isn't the most reliable thing, so instead of
setting false expectations, remove auto-detection instead. This makes the plugin
a whole lost simpler, and depend on one less library.
Fixes#9.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/USB-Quirks.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/TopsyTurvy.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Steno.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/OneShot.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/LED-Palette-Theme.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/HostPowerManagement.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Heatmap.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/FingerPainter.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Escape-OneShot.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/EEPROM-Keymap-Programmer.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/EEPROM-Keymap.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Cycle.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/Colormap.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move the documentation to `doc/plugin/CycleTimeReport.md`, sources under
`src/kaleidoscope/plugin/` (appropriately namespaced). This is in preparation of
merging plugins into a single monorepo.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
If we have key coordinates set, we don't need to search the keymap, we can just
use the coordinates as-is.
Fixes#10.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The plugin is much less useful without EEPROM storage, even confusing when using
the Focus commands. As such, enable the storage unconditionally. This makes the
`enableEEPROM` method obsolete, so we mark that as deprecated.
Based on, and fixes#12 by Matt Venn <matt@mattvenn.net>.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Several define directives could be replaced by constexpr variable
definitions. This adds type safety with no overhead costs.
Signed-off-by: Max Görner <max@familie-goerner.eu>
When a Focus command changes either the palette, or the theme, call
`LEDControl.refreshAll()` to repaint the LEDs. This way we don't have to force a
repaint some other way, and changes take effect immediately, as they should.
Fixes#8.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
If we received a `colormap.map` command via Focus, refresh the colormap. It
might be in response to a query (ie, no change), but this should happen
infrequently enough for us to don't care about that inefficiency.
On the other hand, refreshing on `colormap.map` means that if the colors do
change, that's immediately reflected on the keyboard. Right now, if we change
the colormap, it doesn't activate until we change layers, cycle LED themes, or
otherwise force a refresh.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of a low-level interface where one has to set the EEPROM-stored layers
and the lookup method separately, introduce a `setup` method that combines the
two in a much easier to grasp interface. It takes a layer number, and an
optional mode, and sets things up accordingly.
With this new setup procedure comes a new way of how the plugin works: instead
of being able to override the keymap in EEPROM, we extend it (or use a custom
implementation, for advanced use-cases). The default layer can still be set via
Focus, thus effectively overriding the keymap in PROGMEM. To better support
this, a new Focus command is introduced too: `keymap.roLayers`, which returns
the number of layers in PROGMEM.
The `keymap.transfer` Focus command is removed, because it can be done much more
reliably from the host side, building on top of `keymap.map`.
The rest of the lower-level interface is still there, though undocumented, for
advanced use-cases the new simplified setup does not fit.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
With upcoming EEPROMKeymap changes, saving the default layer will become an
important part of the keyboard settings. The new `default_layer` method provides
a way to set it programmatically, while the `settings.defaultLayer` Focus
command allows the user to set it via Focus.
The default layer - if set - is activated when the settings are sealed, either
directly or automatically.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This removes the `magic` field from the beginning of the header. It was
originally meant to signal if the EEPROM we're dealing with is new, or if it has
been set up with `EEPROMSettings` before. But as `EEPROMSettings` is pretty much
the only way we deal with EEPROM, there's not much need for that.
With the removal, we do need a way to update the CRC bits on first use, so we
use the `version` field instead: if it is `0xff`, we update the CRC, and
consider the settings valid. This means that until the version is set, the
EEPROM layout is considered flexible, and verification is essentially disabled.
Once the version is set, we can validate.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>