The Model01.h required some reordering of header includes
and some forward defines of certain types that are
used in property classes.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
This method is now implemented in the LED driver
base class based on the LED driver properties.Removed method
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Kaleidoscope's device API defines two types to be exported
as kaleidoscope::Device and kaleidoscope::DeviceProps.
The newly introduced macro EXPORT_DEVICE can be used
to export those two type names conveniently.
The macro also serves the purpose to only export a type named
kaleidoscope::Device in non-virtual device builds. In virtual
builds, a homonymous type is exported by the virtual device header
Virtual.h.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
We'd like to be able to run custom code whenever the led mode changes, reliably,
without having to resort to checking the mode every cycle. For this purpose, we
introduce the `onLEDModeChange()` handler plugins can hook into. It will be
called every time `LEDControl.set_mode()` is called, even if that just sets the
mode to the currently active one.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
LED driver properties now can re-define an array
for their individual mapping from key offsets to LED indices.
This array is both constexpr (can be used at compiletime) and
stored in PROGMEM. The latter is used by the LED driver base
class to map key offsets to LED ids at runtime.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Using call by reference in FocusSerial::send(...) and
FocusSerial::sendRaw(...) causes linker errors due to
undefined symbols if constexpr constants are passed to the
methods.
This is because if a constexpr value is bound to a reference
this is the same as taking the address of the value. Thus,
the compiler has to generate an instance. Some constants
like e.g. FocusSerial::NEWLINE do not come with an
instance.
This seems not to cause problems with avr-gcc up to now
but generates linker errors during virtual compiles with later gcc
versions (e.g. gcc 8.3.0).
This change does not incur any additional overhead as
all version of FocusSerial's send methods are already inlined,
and the templated versions root to the non-template versions of the send
methods that only accept call-by-value anyway.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Up to now, the device header was included by several files
via the command
This commit introduces a build type selection header
kaleidoscope/device/device.h that enables to
either directly include the device header or
to first include the 'physical' device header
and then the 'virtual' device header.
This is meant for the virtual device to be able
to be defined depending on the properties of the
physical device.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
Plugin Kaleidoscope-HardwareVirtual is now obsolete.
Everything device related has been incorporated in the
core repo as a virtual device in kaleidoscope/devices/virtual.
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
The MCU family is called `ATmega`. not `ATMega`, so correct all occurrences of
it, while we still can. Also renamed `kaleidoscope::driver::keyscanner::AVR` to
`kaleidoscope::driver::keyscanner::ATmega`.
As a side-effect, this fixes compilation under the Arduino IDE, which defines
`AVR` as a symbol.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Unions are a C-reminiscense that are better avoided in modern C++.
They cause specific problems due to their nature of representing
independent types. The way they are used in Kaleidoscope, they
can easily be replaced by a class.
This enables it to properly work with Key objects in constexpr context
where with the old union-based implementation the compiler reported
errors when one Key was constructed based on a key_code/flags pair and
another one through raw-data. In such a case, the compiler assumes that
both Key instances represent something entirely different. This is
because unions were never meant for type conversions and the C++
standard considers their use for that purpose as undefined behavior.
The new class provides accessor methods for raw-data access and for
key_code/flags-data access.
This is a breaking change as it is is not possible to replace direct
member access patterns like
key.raw = 0xFFFF;
based on the raw-accessors.
For the .keyCode and .flags members, proxy objects are used
to enable the generation of suitable deprecations warnings.
All direct access via .raw, .keyCode and .flags have been replaced
throughout Kaleidoscope.
Information on how to upgrade is provided in UPGRADING.md
Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
We have a few AVR-specific things which do not have a guard yet, and cause
issues on other architectures. This adds those missing guards to the following
places:
- The `kaleidoscope::Hardware` base class, which is deprecated, but still
exists. As such, it needs to be restricted to AVR devices only (since that's all
it supported, non-AVR devices should use the new APIs).
- `device/keyboardio/twi` are only used by the Imago at the moment, and is
AVR-specific, so guard that too.
- Removed an unneeded include from `driver::bootloader::None`, because it
doesn't need `<avr/wdt.h>`.
- `plugin::FirmwareDump` is now restricted to AVR, because that's the only
architecture we support dumping the firmware on.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The `AVREEPROM` storage is AVR-specific, and it depends on features and headers
that may not make sense elsewhere. As such, guard it with an `#ifdef`, to only
compile it for AVR-based devices.
Fixes#718.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
This implements a new plugin, `PersistentLEDMode`, whose single purpose is to
store the current LED mode to storage, whenever it changes. Since we can't hook
into led mode change events yet, we abuse the `afterEachCycle()` hook to compare
the current led mode to what we think it is, and store it if it changes.
This is obviously not very elegant, but the best we can do right now.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Having to recompile and re-flash firmware to set the idle timeout of the plugin
isn't a fun or desired experience. It's fine when one already figured out the
timeout they want, and have no desire to change it. For everyone else, being
able to configure it at run-time via Focus, and have it persist to EEPROM is a
much nicer experience.
This change adds an alternative version of the plugin, `PersistentIdleLEDs`, a
subclass of the original one. This one provides the focus command and
persistence. It's a child class, because that results in a smaller footprint
than a separate plugin that calls the `IdleLEDs` object.
The code borrows from - but is not wire-compatible with - Dygma's implementation
by @mattvenn.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
The new device APIs were built on top of composition (instead of inheritance,
like the former one). At the highest level, we have `kaleidoscope::device::Base`
and `kaleidoscope::device::BaseProps`. The latter is a set of overrideable
properties, components that make up the device: the key scanner, LEDs, MCU, and
so on.
Many components - like the key scanner and LEDs - also come in a similar setup:
the base class and properties, because this allows us to make them fairly
efficient templates.
All of the existing devices have been ported to the new APIs. While the old
`Hardware` base class remains - for now, and deprecated - it is not guaranteed
to work.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Deprecate Model01-TestMode, in favour of the newer HardwareTestMode plugin. We
also turn it into a no-op, so that we don't need to update it for API changes
coming in the near future.
The Model01 example has been updated to use the newer HardwareTestMode instead.
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>
Some boards used to provide the device object under an alias named after the
device itself. For the sake of consistency, we do not want to provide these
aliases in the future. As such, deprecate them, and update all users to use
`KeyboardHardware` instead.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Instead of having to include `device/key_indexes.h` from every single hardware
plugin, include it from `Kaleidoscope.h` instead. This also allows us to get rid
of the redundant `KeyAddr` typedef, by including `kaleidoscope/KeyAddr.h` from
`key_indexes.h` instead.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
Move all the hardware plugins from the `kaleidoscope::hardware` namespace to
`kaleidoscope::device`, in perparation for deeper changes to come later.
This is merely a restructuring, there are no functional changes. The one
breaking change is that `ATMegaKeyboard` moved too, and we do not provide any
backward compatibility there.
Signed-off-by: Gergely Nagy <algernon@keyboard.io>
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>