Also, change the update interval value from a preprocessor macro to a static
constexpr uint8_t variable.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Alos, don't bother to set `start_time` in `onSetup()`; it's
unnecessary. Instead, call `findLed()` there.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Also, instead of using `end_time_ == 0` as a special value to indicate that no
timers need to be checked, us `last_key_left_` & `last_key_right_`. This avoids
the bug that could occur when `millis()` returns 0 (which is unlikely, but
possible).
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
In addition, the interval `syncDelay` was changed from a two-byte integer to a
one-byte integer, because LED update intervals longer than 255ms would be
user-visible.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Reading a word and then assigning to a byte does not make sense.
Changed to reading a byte instead.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
After changing the linker command line in platform.txt
in a way that linker error problems are fixed, this
statement is no more needed.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
This is necessary if a plugin wants to define an alternative
layer system/keymap system/key lookup system which goes without using the
KEYMAP(...) macro.
Before this change, not using the KEYMAP(...) macro in the sketch
resulted in a linker error due to a missing symbol.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
New `PER_KEY_DATA` and `PER_KEY_DATA_STACKED` macros
were introduced that can be used to feed keymap associated
information to functions, constructors or to initialize the
keymap. The user accessed macros `KEYMAP` and `KEYMAP_STACKED`
are now wrappers that pass `XXX` as default value for unused keys.
The new keymap array is named `keymap_linear`. The old symbol
name is now used for a deprecated compatibility wrapper data structure.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Before this change the preprocessor choked on macros or function macros
being passed to DEFINE_HAS_MEMBER_TRAITS. That made it impossible to
generate template class names that e.g. make use of the __COUNTER__
macro.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Added a version of the standard library type_traits header with
slight modifications for avr-gcc.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
This commit does the following:
* factor out class AccessTransientLEDMode to an individual file
* factor out class LEDModeInterface to individual files
* fix the file header comment in LEDMode.h
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
* a class Bitfield that does the general bit handling.
* a utility function generateBitfield that simplifies bitfield
creation
* function macros KEYMAP_BITFIELD and KEYMAP_BITFIELD_STACKED that
enable definitions of keymap bitfields in the same way as keymaps are
defined
All exported functions live in namespace kaleidoscope::bitfields.
Please note, that KEYMAP_BITFIELD is only defined if a keyboard
hardware defines a
KEYMAP_GENERIC macro and KEYMAP_BITFIELD_STACKED only if the
hardware header defines
KEYMAP_STACKED_GENERIC (not all keyboard hardwares define both).
Expected side effects:
As all symbols and macros are newly introduced, nothing is expected
to break.
Signed-off-by: Jesse Vincent <jesse@keyboard.io>
This adds a function to help plugins that use timeouts to efficiently and
correctly check those timeouts by comparing the elapsed time to a timeout
interval without errors due to overflow. It uses the same time value as the
existing `millisAtCycleStart()`, which should be used to set the "start"
timestamp.
Closes#178.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This commit does the following:
* factor out class AccessTransientLEDMode to an individual file
* factor out class LEDModeInterface to individual files
* fix the file header comment in LEDMode.h
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
The cubic acceleration function used to approximate a sine wave produced some
noticeable jumps when beginning to accelerate the mouse cursor movement (several
1s, followed by several 4s, then 7s, with no intermediate values). This
parabolic function produces smoother mouse cursor motion, without any sudden
jumps in speed.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
This PR introduces the concept of dynamic LED modes. Those are LED modes whose class instances
have a restricted lifetime that lasts only as long as a LED mode is active. By this means
it is possible to support a greater amount of LED modes - especially RAM-hungry ones - in the same firmware build. The amount of RAM used to store dynamic LED modes is now bounded
by the maximum size (`sizeof(...)`) of the largest dynamic LED mode.
Old-style LED modes are furtheron called _static_ in the terminology of this PR. They are still supported and blend in nicely with the newly introduced dynamic LED modes.
All changes are entirely backward compatible. No user sketches or existing user plugins require changes.
The greatest benefit of this change is that it drastically reduces the consumption of RAM
when multiple complex LED modes are used. Currently the most complex stock LED mode is
the wavepool effect. Its plugin requires around 140 bytes of RAM that are statically allocated and cannot be shared with any other features.
With this change it becomes possible to have a large number of such resource-hungry LED modes in parallel without a significant gain in RAM consumption.
For the stock firmware this change means a small (~30 byte) growth in terms of PROGMEM. On the other hand it reduces the amount of statically consumed RAM by ~90 bytes. As the current atmel architectures come with around ten times as much PROGMEM as RAM, this means a great improvement as RAM is the more critical resource.
If the wavepool effect, a especially RAM-hungry LED mode is added to the stock firmware,
the saving of RAM increases to 160 bytes which is almost 8% of RAM of the Keyboardio Model01.
A new interface class `LEDModeInterface` was introduced that those plugins
that export dynamic LED modes inherit from. To remain backward compatible, the `LEDMode` class that all pre-existing LED mode plugins inherited from is also derived from `LEDModeInterface`.
The new interface class currently lives in header `LEDMode.h` (see information about this new header below). This is because `LEDMode` and `LEDModeInterface` will
always be used together by dynamic LED modes. Thus, an extra header for `LEDModeInterface` would only mean extra include work for users writing plugins.
Those plugins that export dynamic LED modes must furtheron provide a exported type `DynamicLEDMode`.
This can either be done by defining a nested class of that name or by typedef-ing a class that is defined at global scope to `DynamicLEDMode`. See the modified stock LED modes for examples.
Some of those plugins that export dynamic led modes require access to their particular
dynamic LED mode. By adding the macro `ACCESS_THIS_LED_MODE` to the plugin class definition,
additional data and methods (an integer `led_mode_id_) are synthesized, that enable the plugin class to gain access to their particular dynamic LED mode instance (as long as it is active).
The synthesized integer member `led_mode_id_` can be used to query if the currently active LED mode is the oned handled by the plugin class instance (note that there might be more than one plugin instance of the same class and thus also several dynamic LED modes, see e.g. the solid color LED mode).
A query in the plugin's event handler e.g. looks as follows.
```cpp
if (::LEDControl.get_mode_index() != led_mode_id_)
return EventHandlerResult::OK;
```
All stock LED modes have been adapted to export dynamic LED modes (if possible).
This does not apply to all of them as for some the transition would have provided no gain.
It would even have meant a deterioration of resource consumption for those few pre-existing stock LED mode plugins that hardly have no (static) data-members at all (like e.g. `LEDOff`).
To reduce the amount of compile unit and header interdependencies, the class `LEDMode` has been moved to a header/implementation file of its own.
The `LEDControl` class now does not have a static array anymore to store LED mode pointers.
Instead, it delegates the core LED mode handling to a newly introduced `LEDModeManager` class
that lives in internal namespace. The `LEDModeManager` class is there to restrict access
to LED modes but also to wrap up core LED mode handling. If this functionality would
have been added to class `LEDControl`, far too much of the internals of LED mode handling would have been exposed to users through header `LEDControl.h`.
The new internal header `array_like_storage.h` contains a template class that is used to generate
array-like storages. Here array-like means that the contained pieces of information
are stored contiguously in memory in the same way as they would be when defining
language intrinsic (C-style) arrays. This type of storage is especially useful to generate array-like data struktures
in PROGMEM at compile time based on a list of global objects or POD data. By casting the array-like storage's address
to the content's pointer type, an array-like indexed access is possible.
In this PR an array-like data structure is used to generate a PROGMEM
array of LED mode factories. Array-like data structures could also become useful in other places and for future applications.
The most complex part of the implementation of the new LED mode handling is wrapped up in
`LEDModeManager.h` and `LEDModeManager.cpp` to hide it from users' site.
There, recursive template classes are used to setup an array-like data structure of `LEDModeFactory` instances in PROGMEM. Each of the stored `LEDModeFactory`s are associated with one LED mode-plugin as specified in the sketch. The template mechanism filters out any other plugins unrelated to LED modes. `LEDModeFactory`s thereby handle both static and dynamic LED modes.
Class `LEDModeManager` provides access to the LED mode factories and LED modes in general. It exports methods to query the number of LED modes and to activate a LED mode by its mode-ID. Most of this is only available to `LEDControl` that represents the actual user interface.
When a dynamic LED mode is activated, a dedicated `LEDModeFactory` generates an instance of the dynamic LED mode class in the
LED mode buffer. This buffer is shared by all dynamic LED modes. Its size has been determined at compile time by examining all exported dynamic LED mode types and determining the maximum necessary amount of RAM to store any of those.
All LED mode handling related data structures are generated at compile time, based on
the list of plugins that are passed to `KALEIDOSCOPE_INIT_PLUGINS(...)`. This function macro invokes a new function macro `_INIT_LED_MODE_MANAGER` from `LEDModeManager.h` that handles the LED mode related stuff.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
A traits class that is used to check if a class implements a
method with a given signature was already used by
the eventhandler signature check. It has now been moved to
its own traits header (macro name is DEFINE_HAS_METHOD_TRAITS).
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
This is a short-term solution for the problem of qukeys rollover from
mod-flagged keys. When flushing its queue, Qukeys stashes a copy of the
current keyboard HID report, and bases the new (usually mid-cycle) report on
the previous one, because it's complete, unlike the partial current report. This
prevents bugs where it would cause undesired repeats of keys scanned later in
the cycle, but results in a bypassing of the system in the HIDAdaptor that masks
modifier flags when rolling over to a key without those flags.
By first storing a copy of the previous key report's modifiers byte and then
restoring it after the report for a released qukey is sent, we remove any
modifier flags it added to that report, so the next key in the queue (if any)
won't base it's report on those modifiers (which would normally be masked by the
HIDAdaptor).
This is a temporary fix. The real fix will probably involve changes to both
KeyboardioHID and the HIDAdaptor, and will allow Qukeys to stop accessing the
HID reports, which really ought to be private member variables of the Keyboard
class.
Fixes#619.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>