From 07dcf1dc9be5845ffaab5f409b67f8ccf5e9b5a2 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sun, 29 May 2022 14:16:11 +0200 Subject: [PATCH] PersistentLEDMode: Add a Focus hook, and a way to disable the auto-save We'd like to be able to set the default LED mode via Focus, so it can be configured via Chrysalis. However, we may not want auto-save, so make that configurable too. To preserve the EEPROM layout, the highest bit of the previous led mode index setting was repurposed for the auto save setting. This lets us set the default mode to anything between 0 and 126 (or 127, if auto save is turned off). While there, we also add an `onNameQuery` handler, to make it easier for Chrysalis to detect if the plugin is available. This addresses the Kaleidoscope parts of keyboardio/Chrysalis#846. Signed-off-by: Gergely Nagy --- .../kaleidoscope/plugin/PersistentLEDMode.cpp | 89 ++++++++++++++++--- .../kaleidoscope/plugin/PersistentLEDMode.h | 14 ++- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/plugins/Kaleidoscope-PersistentLEDMode/src/kaleidoscope/plugin/PersistentLEDMode.cpp b/plugins/Kaleidoscope-PersistentLEDMode/src/kaleidoscope/plugin/PersistentLEDMode.cpp index ce378411..be2d4f17 100644 --- a/plugins/Kaleidoscope-PersistentLEDMode/src/kaleidoscope/plugin/PersistentLEDMode.cpp +++ b/plugins/Kaleidoscope-PersistentLEDMode/src/kaleidoscope/plugin/PersistentLEDMode.cpp @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- * kaleidoscope::plugin::PersistentLEDMode -- Persist the current LED mode to Storage - * Copyright (C) 2019 Keyboard.io, Inc. + * Copyright (C) 2019-2022 Keyboard.io, Inc. * Copyright (C) 2019 Dygma, Inc. * * This program is free software: you can redistribute it and/or modify it under @@ -19,6 +19,7 @@ #include "kaleidoscope/plugin/PersistentLEDMode.h" #include // for EEPROMSettings +#include // for Focus #include // for uint8_t, uint16_t #include "kaleidoscope/Runtime.h" // for Runtime, Runtime_ @@ -30,34 +31,98 @@ namespace kaleidoscope { namespace plugin { uint16_t PersistentLEDMode::settings_base_; -uint8_t PersistentLEDMode::cached_mode_index_; +struct PersistentLEDMode::settings PersistentLEDMode::settings_; EventHandlerResult PersistentLEDMode::onSetup() { - settings_base_ = ::EEPROMSettings.requestSlice(sizeof(cached_mode_index_)); + settings_base_ = ::EEPROMSettings.requestSlice(sizeof(settings_)); - Runtime.storage().get(settings_base_, cached_mode_index_); + Runtime.storage().get(settings_base_, settings_); - // If the index is max, assume an uninitialized EEPROM, and don't set the LED - // mode. We don't change the cached index here, `onLEDModeChange()` will do - // that whenever a led mode change happens. - if (cached_mode_index_ != 0xff) + // If our slice is uninitialized, then return early, without touching the + // current mode. We want auto_save by default, but because EEPROM is + // uninitialized (0xff), that'll be set anyway, so we don't need to. This + // saves us a storage commit. + if (Runtime.storage().isSliceUninitialized(settings_base_, sizeof(settings_))) return EventHandlerResult::OK; - ::LEDControl.set_mode(cached_mode_index_); + ::LEDControl.set_mode(settings_.default_mode_index); return EventHandlerResult::OK; } EventHandlerResult PersistentLEDMode::onLEDModeChange() { - if (cached_mode_index_ == ::LEDControl.get_mode_index()) + if (!settings_.auto_save) return EventHandlerResult::OK; - cached_mode_index_ = ::LEDControl.get_mode_index(); - Runtime.storage().put(settings_base_, cached_mode_index_); + if (settings_.default_mode_index == ::LEDControl.get_mode_index()) + return EventHandlerResult::OK; + + settings_.default_mode_index = ::LEDControl.get_mode_index(); + Runtime.storage().put(settings_base_, settings_); Runtime.storage().commit(); + return EventHandlerResult::OK; } +EventHandlerResult PersistentLEDMode::onFocusEvent(const char *command) { + enum { + AUTO_SAVE, + DEFAULT_MODE, + } sub_command; + + if (::Focus.handleHelp(command, PSTR("led_mode.default\nled_mode.auto_save"))) + return EventHandlerResult::OK; + + if (strncmp_P(command, PSTR("led_mode."), 9) != 0) + return EventHandlerResult::OK; + + if (strcmp_P(command + 9, PSTR("default")) == 0) + sub_command = DEFAULT_MODE; + else if (strcmp_P(command + 9, PSTR("auto_save")) == 0) + sub_command = AUTO_SAVE; + else + return EventHandlerResult::OK; + + switch (sub_command) { + case DEFAULT_MODE: { + if (::Focus.isEOL()) { + ::Focus.send(settings_.default_mode_index); + } else { + uint8_t idx; + ::Focus.read(idx); + settings_.default_mode_index = idx; + ::LEDControl.set_mode(idx); + Runtime.storage().put(settings_base_, settings_); + Runtime.storage().commit(); + } + break; + } + + case AUTO_SAVE: { + if (::Focus.isEOL()) { + ::Focus.send(settings_.auto_save); + } else { + uint8_t v; + ::Focus.read(v); + setAutoSave(v != 0); + } + break; + } + } + + return EventHandlerResult::EVENT_CONSUMED; +} + +void PersistentLEDMode::setAutoSave(bool state) { + settings_.auto_save = state; + Runtime.storage().put(settings_base_, settings_); + Runtime.storage().commit(); +} + +EventHandlerResult PersistentLEDMode::onNameQuery() { + return ::Focus.sendName(F("PersistentLEDMode")); +} + } // namespace plugin } // namespace kaleidoscope diff --git a/plugins/Kaleidoscope-PersistentLEDMode/src/kaleidoscope/plugin/PersistentLEDMode.h b/plugins/Kaleidoscope-PersistentLEDMode/src/kaleidoscope/plugin/PersistentLEDMode.h index 2254f6ac..47f6ffb5 100644 --- a/plugins/Kaleidoscope-PersistentLEDMode/src/kaleidoscope/plugin/PersistentLEDMode.h +++ b/plugins/Kaleidoscope-PersistentLEDMode/src/kaleidoscope/plugin/PersistentLEDMode.h @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- * kaleidoscope::plugin::PersistentLEDMode -- Persist the current LED mode to Storage - * Copyright (C) 2019 Keyboard.io, Inc. + * Copyright (C) 2019-2022 Keyboard.io, Inc. * Copyright (C) 2019 Dygma, Inc. * * This program is free software: you can redistribute it and/or modify it under @@ -31,11 +31,21 @@ class PersistentLEDMode : public kaleidoscope::Plugin { PersistentLEDMode() {} EventHandlerResult onSetup(); + EventHandlerResult onNameQuery(); EventHandlerResult onLEDModeChange(); + EventHandlerResult onFocusEvent(const char *command); + + void setAutoSave(bool state); + bool getAutoSave() { + return settings_.auto_save == 1; + } private: static uint16_t settings_base_; - static uint8_t cached_mode_index_; + static struct settings { + uint8_t auto_save : 1; + uint8_t default_mode_index : 7; + } settings_; }; } // namespace plugin