From 311a6761d826ca9e9dc57dfd164382544c505fb0 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Thu, 7 Nov 2019 18:10:06 +0100 Subject: [PATCH] IdleLEDs: Optional support for EEPROM-Storage & Focus 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 --- doc/plugin/IdleLEDs.md | 50 ++++++++++++++++++++++++++-- examples/LEDs/IdleLEDs/IdleLEDs.ino | 12 +++++-- src/kaleidoscope/plugin/IdleLEDs.cpp | 47 +++++++++++++++++++++++++- src/kaleidoscope/plugin/IdleLEDs.h | 15 ++++++++- 4 files changed, 116 insertions(+), 8 deletions(-) diff --git a/doc/plugin/IdleLEDs.md b/doc/plugin/IdleLEDs.md index 3d71d9da..6f059dfc 100644 --- a/doc/plugin/IdleLEDs.md +++ b/doc/plugin/IdleLEDs.md @@ -34,10 +34,35 @@ Because the plugin needs to know about key events, it is best to make it one of the first plugins, so it can catch all of them, before any other plugin would have a chance to consume key events. +It is also possible to enable run-time configuration via he `Focus` plugin, and +persistent storage of such settings. To do that, one has to use the +`PersistentIdleLEDs` object instead, provided by the plugin: + +```c++ +#include +#include +#include +#include +#include +#include + +KALEIDOSCOPE_INIT_PLUGINS( + EEPROMSettings, + Focus, + LEDControl, + PersistentIdleLEDs, + LEDEffectRainbowWave +); + +void setup (void) { + Kaleidoscope.setup (); +} +``` + ## Plugin Properties -The plugin provides a single object, `IdleLEDs`, with the following properties -and methods. +The plugin provides two objects, `IdleLEDs`, and `PersistentIdleLEDs`, both with +the following properties and methods. ### `.idle_time_limit` @@ -48,7 +73,9 @@ and methods. > Defaults to 600000 milliseconds (10 minutes). > Provided for compatibility reasons. It is recommended to use one of the -> methods below instead of setting this property directly. +> methods below instead of setting this property directly. If using +> `PersistentIdleLEDs`, setting this property will not persist the value to +> storage. Use `.seetIdleTimeoutSeconds()` if persistence is desired. ### `.idleTimeoutSeconds()` @@ -61,10 +88,27 @@ and methods. > Sets the amount of time (in seconds) that can pass without a single key being > pressed before the plugin considers the keyboard idle and turns off the LEDs. +## Focus commands + +The plugin provides a single [Focus][FocusSerial] command, but only when using +the `PersistentIdleLEDs` variant: + + [FocusSerial]: FocusSerial.md + +### `idleleds.time_limit [seconds]` + +> Sets the idle time limit to `seconds`, when called with an argument. Returns +> the current limit (in seconds) when called without any. + ## Dependencies * [Kaleidoscope-LEDControl](LEDControl.md) +### Optional dependencies + +* [Kaleidoscope-EEPROM-Settings](EEPROM-Settings.md) +* [FocusSerial](FocusSerial.md) + ## Further reading Starting from the [example][plugin:example] is the recommended way of getting diff --git a/examples/LEDs/IdleLEDs/IdleLEDs.ino b/examples/LEDs/IdleLEDs/IdleLEDs.ino index 25b9791e..a4f5d686 100644 --- a/examples/LEDs/IdleLEDs/IdleLEDs.ino +++ b/examples/LEDs/IdleLEDs/IdleLEDs.ino @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- * Kaleidoscope-Idle-LEDs -- Turn off the LEDs when the keyboard's idle - * Copyright (C) 2018 Keyboard.io, Inc + * Copyright (C) 2018, 2019 Keyboard.io, Inc * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include // *INDENT-OFF* @@ -43,14 +45,18 @@ KEYMAPS( // *INDENT-ON* KALEIDOSCOPE_INIT_PLUGINS(LEDControl, - IdleLEDs, + EEPROMSettings, + Focus, + PersistentIdleLEDs, LEDRainbowWaveEffect, LEDOff); void setup() { + KeyboardHardware.serialPort().begin(9600); + Kaleidoscope.setup(); - IdleLEDs.setIdleTimeoutSeconds(300); // 5 minutes + PersistentIdleLEDs.setIdleTimeoutSeconds(300); // 5 minutes LEDRainbowWaveEffect.activate(); } diff --git a/src/kaleidoscope/plugin/IdleLEDs.cpp b/src/kaleidoscope/plugin/IdleLEDs.cpp index 0489bd30..e45813b8 100644 --- a/src/kaleidoscope/plugin/IdleLEDs.cpp +++ b/src/kaleidoscope/plugin/IdleLEDs.cpp @@ -1,6 +1,7 @@ /* -*- mode: c++ -*- * Kaleidoscope-Idle-LEDs -- Turn off the LEDs when the keyboard's idle - * Copyright (C) 2018 Keyboard.io, Inc + * Copyright (C) 2018, 2019 Keyboard.io, Inc + * Copyright (C) 2019 Dygma, Inc * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software @@ -17,6 +18,8 @@ #include #include +#include +#include namespace kaleidoscope { namespace plugin { @@ -56,7 +59,49 @@ EventHandlerResult IdleLEDs::onKeyswitchEvent(Key &mapped_key, KeyAddr key_addr, return EventHandlerResult::OK; } +uint16_t PersistentIdleLEDs::settings_base_; + +EventHandlerResult PersistentIdleLEDs::onSetup() { + settings_base_ = ::EEPROMSettings.requestSlice(sizeof(uint16_t)); + + // If idleTime is max, assume that EEPROM is uninitialized, and store the + // defaults. + uint16_t idle_time; + KeyboardHardware.storage().get(settings_base_, idle_time); + if (idle_time == 0xffff) { + KeyboardHardware.storage().put(settings_base_, idle_time_limit); + } + setIdleTimeoutSeconds(idle_time); + + return EventHandlerResult::OK; +} + +void PersistentIdleLEDs::setIdleTimeoutSeconds(uint32_t new_limit) { + IdleLEDs::setIdleTimeoutSeconds(new_limit); + KeyboardHardware.storage().put(settings_base_, (uint16_t)new_limit); +} + +EventHandlerResult PersistentIdleLEDs::onFocusEvent(const char *command) { + const char *cmd = PSTR("idleleds.time_limit"); + + if (::Focus.handleHelp(command, cmd)) + return EventHandlerResult::OK; + + if (strcmp_P(command, cmd) != 0) + return EventHandlerResult::OK; + + if (::Focus.isEOL()) { + ::Focus.send(idleTimeoutSeconds()); + } else { + uint16_t idle_time; + ::Focus.read(idle_time); + setIdleTimeoutSeconds(idle_time); + } + return EventHandlerResult::EVENT_CONSUMED; +} + } } kaleidoscope::plugin::IdleLEDs IdleLEDs; +kaleidoscope::plugin::PersistentIdleLEDs PersistentIdleLEDs; diff --git a/src/kaleidoscope/plugin/IdleLEDs.h b/src/kaleidoscope/plugin/IdleLEDs.h index 8722cf83..1a4e3e92 100644 --- a/src/kaleidoscope/plugin/IdleLEDs.h +++ b/src/kaleidoscope/plugin/IdleLEDs.h @@ -1,6 +1,7 @@ /* -*- mode: c++ -*- * Kaleidoscope-Idle-LEDs -- Turn off the LEDs when the keyboard's idle - * Copyright (C) 2018 Keyboard.io, Inc + * Copyright (C) 2018, 2019 Keyboard.io, Inc + * Copyright (C) 2019 Dygma, Inc * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software @@ -37,7 +38,19 @@ class IdleLEDs: public kaleidoscope::Plugin { private: static uint32_t start_time_; }; + +class PersistentIdleLEDs : public IdleLEDs { + public: + EventHandlerResult onSetup(); + EventHandlerResult onFocusEvent(const char *command); + + static void setIdleTimeoutSeconds(uint32_t new_limit); + private: + static uint16_t settings_base_; +}; + } } extern kaleidoscope::plugin::IdleLEDs IdleLEDs; +extern kaleidoscope::plugin::PersistentIdleLEDs PersistentIdleLEDs;