I’m starting to test out some existing plugins in my firmware customization quest–mostly LEDEffects so far, but I do have plans to start making more practical firmware customizations.
I’ve developed a list of things I think I’ll want, and I’m wondering if plugins for them already exist, or other pointers on how to achieve them. Can y’all fine people suggest approaches to the following?
LEDEffect-FunctionalColor is something I want to use as I start messing around with changing key layouts, but I’d like it to only be in effect on certain layers. For example, I’d like some pretty LED effect on the PRIMARY layer, but FunctionalColor on the FUNCTION layer to remind me what I’ve changed there.
LEDEffects on idle timers. I’d like to have an LEDEffect activate as a “screen saver”, only coming on after X minutes of idle time. And then maybe off after Y > X minutes. (IdleLEDs can do the second part, of course.)
I’m planning a function-lock, for times when I use a Fn-key-heavy program. I’m guessing the NumPad is a good model for this?
You can kinda make this work with some custom code in your sketch, but there’s no generic API or anything to do it out of the box. I’d go with writing a simple plugin (contained within your sketch) that simply changes the led effect when layers change. Something like this:
namespace kaleidoscope {
class LayerEffects: public kaleidoscope::Plugin {
public:
EventHandlerResult onLayerChange() {
if (Layer.isActive(FUNCTION)) {
FunctionalColorEffect.activate();
} else if (Layer.mostRecent() == 0) {
SomePrettyLEDEffect.activate();
}
}
};
}
kaleidoscope::LayerEffects LayerEffects;
No solution for this yet out of the box, yet. You can copy IdleLEDs, and change it slightly to apply a specific LED effect rather than turning LEDs off. Or we could shake up the plugin a bit, and make it possible to use custom actions on timeout. That would allow you to implement both the screen saver, and the led off parts without modifying Kaleidoscope core, or copying a plugin.
I had the exact same desire for a “screen saver” effect, so I went ahead and copied IdleLEDs, did a little tinkering, and came up with the code below, which is working in my sketch on my Model 100.
// Show a "screen saver" LED effect after some amount of idle time,
// then "wake up" next time a key is pressed by restoring the previous effect.
// Based heavily on the IdleLEDs plugin.
class ScreenSaverLEDs : public kaleidoscope::Plugin {
public:
static uint32_t idle_time_limit;
static uint32_t idleTimeoutSeconds();
static void setIdleTimeoutSeconds(uint32_t new_limit);
static kaleidoscope::plugin::LEDMode* screenSaverLEDEffect();
static void setScreenSaverLEDEffect(kaleidoscope::plugin::LEDMode& mode);
kaleidoscope::EventHandlerResult beforeEachCycle();
kaleidoscope::EventHandlerResult onKeyEvent(KeyEvent &event);
private:
static bool idle_;
static uint32_t start_time_;
static kaleidoscope::plugin::LEDMode* saver_mode_;
static uint8_t normal_mode_index_;
};
uint32_t ScreenSaverLEDs::idle_time_limit = 600000; // 10 minutes
uint32_t ScreenSaverLEDs::start_time_ = 0;
bool ScreenSaverLEDs::idle_;
kaleidoscope::plugin::LEDMode* ScreenSaverLEDs::saver_mode_ = nullptr;
uint8_t ScreenSaverLEDs::normal_mode_index_;
uint32_t ScreenSaverLEDs::idleTimeoutSeconds() {
return idle_time_limit / 1000;
}
void ScreenSaverLEDs::setIdleTimeoutSeconds(uint32_t new_limit) {
idle_time_limit = new_limit * 1000;
}
kaleidoscope::plugin::LEDMode* ScreenSaverLEDs::screenSaverLEDEffect() {
return saver_mode_;
}
void ScreenSaverLEDs::setScreenSaverLEDEffect(kaleidoscope::plugin::LEDMode& mode) {
saver_mode_ = &mode;
}
kaleidoscope::EventHandlerResult ScreenSaverLEDs::beforeEachCycle() {
if (idle_time_limit == 0)
return kaleidoscope::EventHandlerResult::OK;
if (!idle_ && saver_mode_ &&
kaleidoscope::Runtime.hasTimeExpired(start_time_, idle_time_limit)) {
normal_mode_index_ = ::LEDControl.get_mode_index();
saver_mode_->activate();
idle_ = true;
}
return kaleidoscope::EventHandlerResult::OK;
}
kaleidoscope::EventHandlerResult ScreenSaverLEDs::onKeyEvent(KeyEvent &event) {
if (idle_) {
::LEDControl.set_mode(normal_mode_index_);
idle_ = false;
}
start_time_ = kaleidoscope::Runtime.millisAtCycleStart();
return kaleidoscope::EventHandlerResult::OK;
}
ScreenSaverLEDs ScreenSaverLEDs;
Here’s how I use it in setup. If anyone else wants to use this thing, then this is the only part that you should need to customize. Just specify whatever values you want to use for the timeout and the screen saver LED effect.
ScreenSaverLEDs.setIdleTimeoutSeconds(10 * 60);
//ScreenSaverLEDs.setIdleTimeoutSeconds(5); // for testing
ScreenSaverLEDs.setScreenSaverLEDEffect(LEDDigitalRainEffect);
You’ll also obviously need to include ScreenSaverLEDs in KALEIDOSCOPE_INIT_PLUGINS, and probably relatively early, as recommended in the IdleLEDs documentation.
I wrote a plugin myself, that does switch LEDEffect on layer changes, so you might have a look at my sketch for inspiration.
The plugin does not only switch ledEffects ob layer change. You can also change the effect, when a layer is active and this is stored for later use. E.g. when I switch to Game-Layer the Wave-Effect is being used. When i the cycle through the effects (to like solid red), it keeps that information. Even after switching back to normal and coming back. It is not stored in eprom yet - but that might be a useful extension.
I like the Idle-Effect also, but in my sketch I just switch off LEDs. Did not think about this brilliant idea - thanks a lot for the inspiration.
Blockquote
No solution for this yet out of the box, yet. You can copy IdleLEDs, and change it slightly to apply a specific LED effect rather than turning LEDs off. Or we could shake up the plugin a bit, and make it possible to use custom actions on timeout. That would allow you to implement both the screen saver, and the led off parts without modifying Kaleidoscope core, or copying a plugin.
That would be a great idea. If we could separate the timeout part of a plugin, maybe even things like IdleLeds could be implemented using this new plugin, and users could turn on and off other plugins programmatically, switch to layers, activate modal keys.
If/when I have some time, this is one plugin I’d like to create.
Yay, I’m glad that my tinkering was also useful for someone else.
Agreed that this would be the more ideal thing to have, and the screen saver functionality could also definitely be implemented using it. Unfortunately the time/reward ratio is too high for me to take a stab at it anytime soon.