Skip to content

Conversation

@EvyBongers
Copy link
Contributor

Quick attempt to implement focus support in ColormapOverlay. I feel this should work, but I don't have my keyboard with me right now, so any debugging I'll have to do later.

}

EventHandlerResult ColormapOverlay::onFocusEvent(const char *input) {
return ::LEDPaletteTheme.themeFocusEvent(input, PSTR("colormap.overlay"), map_base_, no_themes_);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

colormap.overlay seems like the most logical focus command to me. Let me know what you think.

@obra
Copy link
Member

obra commented Jul 29, 2024

@EvyBongers did you end up testing this on hardware?

@EvyBongers
Copy link
Contributor Author

I completely forgot about this. I'll see about testing it today

@EvyBongers
Copy link
Contributor Author

EvyBongers commented Nov 13, 2024

So, I finally got around to testing this. The command returns the palette indexes as expected, but setting the indexes doesn't yet work 🤔

@EvyBongers EvyBongers marked this pull request as draft November 13, 2024 14:35
@EvyBongers
Copy link
Contributor Author

So, I dug a little deeper to see what I was missing. I thought I had a quick fix by calling on ::LEDPaletteTheme.themeFocusEvent(), but the internal logic of the plugin never actually used LEDPaletteTheme to store its data because it was never intended to work as a theme.
Looking at #1416, it seems to me that the third PR that we discussed there was never created, so unless we want so implement a read only version here, this effort is going to have to wait until EEPROM support is added to Colormap-Overlay.

The confusing part is that Colormap-Overlay (seemed to) need to call ::LEDPaletteTheme.reserveThemes() in order to work with the palette, even though it never uses any of the theme logic. It's been ages since I implemented that part and I don't remember why I needed to add that call to reserve themes nor whether it's actually needed for the plugin to work with the palette at all.

Closing this for now

@EvyBongers EvyBongers closed this Nov 13, 2024
@EvyBongers EvyBongers reopened this Nov 13, 2024
@EvyBongers
Copy link
Contributor Author

Reopened because EEPROM supports needs to be added anyway and EEPROM and focus support should land together.

@EvyBongers EvyBongers changed the title Add focus support to ColormapOverlay Add EEPROM and focus support to ColormapOverlay Nov 13, 2024
@EvyBongers
Copy link
Contributor Author

Just found a comment about this on Discord. Cross-posting to have all of this together.

#1434 will need quite a bit of work yet, I think. My first attempt to make focus work for colormap overlay settings simply passed through the handling of the focus event to ::LEDPaletteTheme.themeFocusEvent(). I had a proper look at that today and I'm pretty sure that isn't going to work, or at least it isn't sufficient. That's partly because (iirc) I needed to reserve at least one theme to get ::LEDPaletteTheme.lookupPaletteColor() to work. However, the plugin doesn't store any other data in a theme. That means that I will either have to find a way to have the plugin work with themes or I'm gonna have to implement a second or different means for handing the focus command

@EvyBongers EvyBongers force-pushed the feat/ColormapOverlay/Focus branch from 41ea3cb to 912fc39 Compare November 13, 2024 16:12
@EvyBongers
Copy link
Contributor Author

EvyBongers commented Mar 4, 2025

@obra I'm continued worked on this and I have a feeling I'm getting close to having a first draft that can actually compile, but I just found that my idea of using -1 for keys that don't have an overlay color isn't actually supported by FocusSerial at this point. See my comments here: Colormap-Overlay.cpp#L117-L120

At first glance it looks like implementing this in FocusSerial is as easy adding this bit of code. Can I add that as part of this PR, or would you prefer having a separate PR for that?

  void read(int8_t &i8) {
    i8 = Runtime.serialPort().parseInt();
  }
  void read(int16_t &i16) {
    i16 = Runtime.serialPort().parseInt();
  }

@obra
Copy link
Member

obra commented Mar 4, 2025 via email

@EvyBongers EvyBongers force-pushed the feat/ColormapOverlay/Focus branch from 8db2812 to 2a6ac62 Compare March 9, 2025 12:39
Signed-off-by: Evy Bongers <[email protected]>
@EvyBongers EvyBongers force-pushed the feat/ColormapOverlay/Focus branch from 5113820 to 22d8790 Compare March 11, 2025 17:46
@obra
Copy link
Member

obra commented Mar 11, 2025 via email

@EvyBongers EvyBongers marked this pull request as ready for review March 12, 2025 13:55
Copy link
Contributor Author

@EvyBongers EvyBongers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionally it now works in that the numpad keys in the default firmware always light up, regardless of the assigned keys and that the overlay colors can be changed/disabled over focus.

One thing I noticed is that, if an effect is active on layer 0, that effect keeps playing on all keys not in the numpad. To work around this, I could change the default sketch to apply color index 22 (for example, 16-22 should be black once users upgrade), so that this doesn't happen.

However, that isn't the only way the sketch now differs from the Numpad plugin. My tests showed that, when changing from the numpad back to layer 0, the overlay colors persisted until the point that the active color mode applied a different color. That is:

  • With any mode that lights all leds, the leds follow the color mode logic and the colors applied by Colormap-Overlay don't persist.
  • with modes like stalker of chase, the red color persists until the effect hits those keys and changes the leds
  • with LEDOff the color of the overlay persists indefinitely

Please let me know what you think about this, as well as the comments I left on my TODOs

namespace plugin {
uint16_t ColormapOverlay::map_base_;
uint16_t ColormapOverlay::overlays_base_;
uint8_t ColormapOverlay::max_overlays_ = 64; // TODO(EvyBongers): figure this out. How determine a good maximum?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@obra do you have a way to determine a good value here, or is this pure guess work?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to be setting it to layer_count? that might (or might not) need an accessor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

layer_count is far too few, as an overlay only applies to a single key. Of course we could set it to layer_count * Runtime.device().numKeys(), but if anyone is gonna need that number of overlays, they're better off using Colormap rather than ColormapOverlay.

uint8_t layer_ = (i - key_index_) / Runtime.device().numKeys();

overlays_[overlay_count_] = Overlay(layer_, KeyAddr(key_index_), color_index_);
overlay_count_++; // TODO(EvyBongers): how to make sure that we don't exceed max_overlays_
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to communicate over focus that an error occurred? I could just break the loop when the limit is reached, but I wonder if there are ways to report back why it happens. Of course, if the limit above were to be set to max_layers * numKeys this wouldn't happen, but that doesn't make any sense because if you're gonna set led colors on every key you should be using Colormap instead of Colormap-Overlay

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there isn't currently. There should be.

@obra
Copy link
Member

obra commented Apr 11, 2025

Functionally it now works in that the numpad keys in the default firmware always light up, regardless of the assigned keys and that the overlay colors can be changed/disabled over focus.

One thing I noticed is that, if an effect is active on layer 0, that effect keeps playing on all keys not in the numpad. To work around this, I could change the default sketch to apply color index 22 (for example, 16-22 should be black once users upgrade), so that this doesn't happen.

I don't really feel strongly here.

However, that isn't the only way the sketch now differs from the Numpad plugin. My tests showed that, when changing from the numpad back to layer 0, the overlay colors persisted until the point that the active color mode applied a different color. That is:

This one, you should be able to fix by forcing the active led mode to do a full repaint, no?

  • With any mode that lights all leds, the leds follow the color mode logic and the colors applied by Colormap-Overlay don't persist.
  • with modes like stalker of chase, the red color persists until the effect hits those keys and changes the leds
  • with LEDOff the color of the overlay persists indefinitely

Please let me know what you think about this, as well as the comments I left on my TODOs

Comment on lines +151 to +153
// TODO(anyone): For now we just break the loop. Once focus implements
// support for reporting back errors, this should report why we break
// the loop
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a TODO to follow up on this discussion: #1434 (comment)

Overlay *overlays_;
uint8_t overlay_count_;
static uint16_t overlays_base_;
static const uint8_t max_overlays_ = 64; // TODO(EvyBongers): figure this out. How determine a good maximum?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following up on #1434 (comment):

layer_count is far too few, as an overlay only applies to a single key. We could set it to layer_count * Runtime.device().numKeys(), but if anyone is gonna need that number of overlays, they're better off using Colormap rather than ColormapOverlay.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I think that starting at a fixed # like 64 seems fine. if we find folks needing it increased, we can do that.

if (color_index_ >= 0 && color_index_ < ::LEDPaletteTheme.getPaletteSize() &&
color_index_ != no_color_overlay) {
count++;
count++; // TODO(EvyBongers): how to make sure that we don't exceed max_overlays_
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per your suggestion, I added a static_assert in the method above, but since I need to count the number if overlays here, it seems impossible to use that here. Any ideas on how I could validate that here? Or should I move the logic for finding all specified overlays to the macro below?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have an obvious answer for you here. What happens if you just return when they've gone over the limit?

Comment on lines +52 to +53
// When settings are invalid, better to clean it all up to prevent unwanted things from happening
::EEPROMSettings.invalidate();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re: #1434 (comment)

Is this the correct way to handle this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe so. the seal is taken care of automatically. and isValid is a whole-system level thing.
This should be the right pattern

EventHandlerResult Keyclick::onSetup() {
  // Request storage space and load settings
  bool success = ::EEPROMSettings.requestSliceAndLoadData(&settings_base_, &settings_);

  // If settings weren't loaded successfully, use defaults
  if (!success) {
    settings_.enabled = true;
    settings_.version = 0x01;
    updateSettings();
  }

@EvyBongers
Copy link
Contributor Author

This one, you should be able to fix by forcing the active led mode to do a full repaint, no?

Just implemented this and verified that it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants