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 <algernon@keyboard.io>
pull/1189/head
Gergely Nagy 3 years ago
parent 6f11d89152
commit 07dcf1dc9b
No known key found for this signature in database
GPG Key ID: AC1E90BAC433F68F

@ -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 <Kaleidoscope-EEPROM-Settings.h> // for EEPROMSettings
#include <Kaleidoscope-FocusSerial.h> // for Focus
#include <stdint.h> // 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

@ -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

Loading…
Cancel
Save