When deciding how much data to work with, store the number of LEDs on the board,
not the number of keys. Boards may have less or more LEDs than keys, and since
the plugin is supposed to support theming the LEDs, that number is the one we want.
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>
Instead of directly accessing the EEPROM, do so through
`KeyboardHardware.storage()`, which - for the time being - is a function that
simply returns the `EEPROM` object.
All plugins that were using EEPROM directly were updated, and so was the
EEPROM-Settings documentation.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
We want to keep `key_hue` below 255, without clipping it there, otherwise the
effect will come out glitchy. To achieve that, we simply substract 255 until
we're above the cap. This results in the rainbow being laid out in a kind of
wave.
Previously, we didn't do this in a loop, which only worked when the device had
less than 128 LEDs. For devices with more, we need to do this in a loop, until
we get below the cap.
Based on #664 by @mattvenn.
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>
The correct KeyAddr type is not known to class ATMegaKeyboard
as key matrix dimentions (matrix_rows/matrix_columns) and
type KeyAddr are only defined in derived hardware classes. To deal with
this problem, some of the KeyAddr related methods are moved to
derived hardware classes.
The necessary boilerplate code is synthesized through a macro
ATMEGA_KEYBOARD_MATRIX_ACCESS_METHODS that is automatically included
by all derived classes of class ATMegaKeyboard through the already used
macro ATMEGA_KEYBOARD_CONFIG.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
By forcing an explicit type conversion between
two template class instances of template
MatrixAddr<...>, we prevent undesired implicit
construction of the wrong MatrixAddr type.
Before this change, the following would have been possible
typedef MatrixAddr<5, 5> KeyAddr;
void f(KeyAddr k) {} // uses MatrixAddr<5, 5>
void g() {
typedef MatrixAddr<0, 0> KeyAddr; // Stupid but possible
f(KeyAddr(1, 12)); // Would instantiate MatrixAddr<0, 0> and
// implicitly convert it to MatrixAddr<5, 5>
}
With this commit, the compiler will emit an error and explicit type
conversion is required.
typedef MatrixAddr<5, 5> KeyAddr1;
typedef MatrixAddr<2, 2> KeyAddr2;
void f(KeyAddr1 k) {} // uses MatrixAddr<5, 5>
void g() {
f(KeyAddr1(KeyAddr2(1, 1)); // Now an explicit type conversion is
// required.
}
This commit also introduces a compile time check that prevents
conversion from a matrix type with greater extension to one with
smaller extension.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
The "new" code we've backed out caused all key events to be about key
0,0. I suspect that this is GCC doing something crazy with that one
function. I don't understand what's going on. @noseglasses: any idea?
This introduces two new macro action steps: `MACRO_ACTION_STEP_TAP_SEQUENCE`,
and `MACRO_ACTION_STEP_TAP_CODE_SEQUENCE`. Both of these will tap everything
that follows up to a terminating zero (or in case of the first, double zeroes).
The purpose of these new steps is to allow one to store longer sequences of
tapped input in a more compact manner, without having to prefix each step with
an action.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In `refreshAt()`, we want to use the key address, instead of the LED address.
`LEDControl` will turn the key address into a LED address itself anyway. This
not only makes the code a tiny bit more efficient, but it also fixes
`refreshAt()`, which was refreshing the wrong key since the conversion to
`KeyAddr`.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
In order for the plugin to work without having to switch layers once, it needs
to scan the keymap for modifiers at setup time too. We do this by calling
`onLayerChange()`, which already does that.
Fixes#670.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This is a complete rewrite of Qukeys, in order to implement several improvements
and new features:
- A new KeyAddrEventQueue class has been introduced, in order to store both key
press and release events in the queue.
- The direct dependence on KeyboardioHID is removed by only flushing one event
from the queue per cycle.
- The array of Qukey objects is now stored in PROGMEM instead of SRAM, and is
configured via an array reference template function in order to automatically
ensure the count will be correct.
- There is a new algorithm for determining which state a qukey will collapse
into in the case of rollover from qukey to another key, which should reduce
the rate of errors for "sloppy" typists.
- A Qukey with a primary key value that is a modifier (including layer shift
keys) is treated like a SpaceCadet key, with different semantics. The
alternate (non-modifier) key value is only used if the SpaceCadet key is
pressed and released on its own, without rolling over to any other key.
- The code is generally simpler and easier to understand, with better inline
comments explaining how it all works.
Fixes#626.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Virtual builds use their own versions of pgm_read_...
Some of those caused warnings that needed to be silenced by proper casting.
In one place in LEDEffect-BootAnimation, this reveiled an error where a word was
read and then assinged to a byte value. This was fixed as well.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
This caused a problem with virtual builds. The BootKeyboard
header has to be brought in explicitly.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
In Virtual builds the explicitly defined new operator
collides with that of the standard library. To fix
this, we make the standard library version available.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
This is a macro that defines an invalid key address.
It can furtheron be used as a flag value.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
This class is meant to be used to define different types of matrix based
addresses like, e.g. per key addresses.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Instead of having `Key_mouseL` & `Key_mouseUp` override `Key_mouseR` &
`Key_mouseDn`, respectively, stop mouse movement on a given axis when both keys
are held simultaneously. Doing so will not reset acceleration, so when one of
them is released, the mouse will resume movement at full speed immediately.
Closes#634.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
The method does not access any non-static class inventory.
This change should bring a small performance gain
as not this pointer needs to be passed when the
function is called.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Also, instead of using a special timestamp value of zero to indicate that the
keyboard is , use a new boolean variable to indicate that the keyboard is
locked.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Also, change timestamp from four bytes to two, and instead of using a special
timestamp value of zero to indicate that no timer is running, use
`last_tap_dance_key_`.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Also, change `rainbow_update_delay` from two bytes to one, and use a more
consistent interval by adding it to `rainbow_last_update` after each update,
rather than using the current time.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
Also, change `update_delay_` from two bytes to one, and use a more consistent
interval by adding it to `last_update_` after each update, rather than using the
current time.
Signed-off-by: Michael Richters <gedankenexperimenter@gmail.com>
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>