zmk icon indicating copy to clipboard operation
zmk copied to clipboard

Experimental: Automatic power domain handling for displays/RGB

Open petejohanson opened this issue 1 year ago • 13 comments

This is the initial draft of the experimental work to add automatic power domain handling to ZMK.

Ideally, this will allow for boards/shields that contain one or more power domains to have those power domains automatically enabled whenever a device on that domain (e.g. display, or RGB LEDs) is used by a particular subsystem in ZMK.

To do this:

  • One or more power domains will be added to the board/shield. Example from the nice_nano_v2.dts:
	core_power_domain: core_power_domain {
		compatible = "power-domain-gpio";
		off-on-delay-us = <50000>;
		enable-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
		zephyr,pm-device-runtime-auto;
	};
  • Complete boards might reference the power domain for other nodes explicitly, e.g.:
&arduino_spi {
	status = "okay";

	led_strip: ws2812@0 {
		compatible = "worldsemi,ws2812-spi";

               ...

		power-domain = <&rgb_power>;
		zephyr,pm-device-runtime-auto;
	};
};
  • OR for shield that build for generic boards like the nano, that board will set a new chosen node zmk,default-power-domain, and enable the ZMK_POWER_DOMAINS_DYNAMIC_DEFAULT. This will cause subsystems like our display or RGB underglow code to auto-assign the respective peripherals to that chosen PD. By doing so, the only thing shields possible need to do is set a new higher default value for the PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM Kconfig symbol and it will "just work' if they are built with a board that supports power domains.

At runtime, the power will only be enabled when a device on that PD is requested used.

In addition, I've included the necessary driver fixes for the Zephyr ssd1306 and ls0xx drivers to add PM hooks to re-init the device when is us turned back on.

Changes

This PR encompasses:

  • ZMK changes for the higher level app code to get/put appropriately, board additions to nano, shield tweaks for ZMK Uno, Corne, Kyria, Lily58, Sofle: https://github.com/petejohanson/zmk/tree/power/domains-and-device-runtime
  • Zephyr changes: https://github.com/petejohanson/zephyr/tree/v3.2-device-power-management (on top of 3.2 since that's what ZMK is on)
  • LVGL init tweaks to get/put: https://github.com/petejohanson/lvgl/tree/device-power-management-on-init

TODO:

  • [ ] Lots of testing.
  • [ ] Docs
  • [ ] Figure out what, if anything, to do with &ext_power behavior with this new system. It may be a no-op, or maybe could be made to request the default/assigned power domain when toggled on, to force on VCC. Turning it "off" ould just release the request, and if no other device is active on the power domain, it would then turn of VCC.
  • [ ] Test experience w/ the new feature disabled, to be sure there's an escape hatch for anyone wanting the old/existing behavior.

petejohanson avatar Apr 24 '23 08:04 petejohanson

Tested with Corne, n!ce nano v2, OLED and RGB. Can confirm when LEDs and OLEDs are off that VCC pin on OLED reads 0.0v. Also can toggle LEDs off and on without the OLED being disabled. Did find one issue. if you toggle the RGB off, it will turn itself back on the next time you wake the OLEDs from sleep.

jeff-comley avatar May 18 '23 02:05 jeff-comley

Just tested with a Lily58 Pro and it worked perfectly. I'm able to have my RGBs and LEDs on now, when previously only the RGBs would work.

https://github.com/Kyle-Mendes/lily58/commit/e773695102d84da4bd5c0bf71a6f561154e3a478

Kyle-Mendes avatar Jun 13 '23 15:06 Kyle-Mendes

I tried installing a nice!view display on an Aurora Corne with this PR, and the display remained blank. Is the ls0xx driver going to need explicit PM support added in zephyr as well in order for nice!view displays to work with power domains?

SethMilliken avatar Sep 11 '23 06:09 SethMilliken

I tried installing a nice!view display on an Aurora Corne with this PR, and the display remained blank. Is the ls0xx driver going to need explicit PM support added in zephyr as well in order for nice!view displays to work with power domains?

Yes, this still needs driver work for the ls0xx driver. I'm planning on doing that work in the next week or two.

petejohanson avatar Sep 11 '23 22:09 petejohanson

Just rebased everything, and also pushed driver changes to ls0xx driver to properly handle PM hook, and suspend/resume of the EXT COM pin toggle thread as needed.

petejohanson avatar Oct 21 '23 06:10 petejohanson

Just rebased everything, and also pushed driver changes to ls0xx driver to properly handle PM hook, and suspend/resume of the EXT COM pin toggle thread as needed.

Hi @petejohanson!

I can confirm that the changes work on Leeloo v2.1 and Leeloo-Micro v1.1; RGB LEDs on rgb_power, and nice!view Displays on core_power_domain.

Thank you for all your work on this change!

ClicketySplit avatar Oct 21 '23 09:10 ClicketySplit

I've just updated this for the Zephyr 3.5 update.

petejohanson avatar Feb 11 '24 16:02 petejohanson

Hello,

i am very interested in this feature, as i have built a keyboard that can control power to RGB and OLED/display seperately using transistors. Is there an estimate when this feature will be merged? Is there anything I can do to help/support?

Thanks, for the awesome work!

fouf96 avatar Mar 28 '24 17:03 fouf96

Hey hey @petejohanson,

Some context: @fouf96 and I have been testing your branch to enable OLED and underglow RGB LEDs via distinct MOSFETS and were successful so far in building and testing the general functionality (see comment from @fouf96 above). The idea is that we try to circumvent the issues with the supermini leakage using these MOSFETS to toggle OLED and LEDs completely off from the circuit, However, we are still investigating the pull down when the EXT_VCC is toggled off (will keep u all posted).

Question: When we tried to set up the UNDERGLOW configs, we noticed that they are not picked up during the build. With the main ZMK branch they work however. It seems that there is some issue in the branch with using those settings. Do you have any idea?

the settings that do not work are:

  • CONFIG_ZMK_RGB_UNDERGLOW_EFF_START=0
  • CONFIG_ZMK_RGB_UNDERGLOW_HUE_START (unclear whether non functional)
  • CONFIG_ZMK_RGB_UNDERGLOW_SAT_START (unclear whether non functional)
  • CONFIG_ZMK_RGB_UNDERGLOW_BRT_START (unclear whether non functional)

particularly CONFIG_ZMK_RGB_UNDERGLOW_EFF_START, it keeps either breath or spectrum effect instead of a constant color. it also seems that we can not set a color at the start (but that might be due to the effect fooling us :D ). The breathing also appears if we do not specify the EFF_START in the config while it should default to 0 according to the documentation

link to the config repo: https://github.com/fouf96/zmk-config

Tworck avatar Apr 04 '24 15:04 Tworck

When we tried to set up the UNDERGLOW configs, we noticed that they are not picked up during the build. With the main ZMK branch they work however. It seems that there is some issue in the branch with using those settings. Do you have any idea?

I would wager this has nothing to do with the power management changes here. As documented in https://zmk.dev/docs/config/underglow these settings don't have an effect if you changed them via &rgb_ug bindings and they got persisted to flash.

caksoylar avatar Apr 04 '24 16:04 caksoylar

@petejohanson

We have investigated further. @caksoylar Regarding your remark with settings being persisted to flash: we don't have any rgb behavior on the keymap, we are just trying to modify the rgb configuration by changing the .conf/kconfig and then reflashing. Nevertheless, we think you pointed us in the right direction:

  1. Observation (status quo): Changing some of the settings in the .conf file (https://github.com/fouf96/zmk-config/blob/main/config/west.yml) do not take effect. We are not triggering any rgb behavior by pressing keys.

  2. Observation: Building shield settings_reset for nice_nano_v2 with the same setup and flashing settings_reset before flashing new firmware -> change of settings in .conf do not take effect.

  3. Observation: Using a seperate, old repository (https://github.com/fouf96/zmk_chocofy_tukon), that builds from the main zmk branch and we know is functional -> change of settings in .conf do not take effect.

  4. Observation: Using the settings_reset firmware built from the old repository in oberservation 3: now changes take effect , but each time a .conf setting is changed, settings_reset firmware built the from the main zmk branch needs to be flashed beforehand.

I am unclear what the conclusion is...

  1. the settings_reset firmware in the power/domains-and-device-runtime branch does not work correctly?
  2. settings are persisted "wrongly" in the power/domains-and-device-runtime? ...if we change .conf and build on the main zmk branch, the we have the same issue. I think a safe conclusion is that we do not really understand how kconfigs are persisted when flashing, and especially what symbols are overwritten and which are not.
  3. we are still doing something wrong?

happy to get feedback - we are super confused :)

fouf96 avatar Apr 05 '24 13:04 fouf96

the settings_reset firmware in the power/domains-and-device-runtime branch does not work correctly?

The functionality for the settings reset to reset everything (and not just BLE pairings) is recent in #2072 and that branch doesn't have that.

settings are persisted "wrongly" in the power/domains-and-device-runtime? ...if we change .conf and build on the main zmk branch, the we have the same issue. I think a safe conclusion is that we do not really understand how kconfigs are persisted when flashing, and especially what symbols are overwritten and which are not.

I don't know how the code works, but I suspect settings are maybe persisted to flash on boot (and then reused on next boot) even if you don't manually use the bindings? Then that might be considered a bug, and there are already similar issues that are reported and PRs filed for.

If it were me, at the end of the day I'd either look into PRs or understand the code and try to debug, or use the bindings/Kconfig to set a known state and not worry about the *_START settings too much.

caksoylar avatar Apr 05 '24 22:04 caksoylar

Hello again,   We (@Tworck ) have been running this branch for the past few weeks now and want to share a few observations (which might or might not be bugs).   Context: We are currently running on this zmk-config https://github.com/fouf96/zmk-config/tree/manual-miryoku. We have a custom split keyboard that uses two MOSFETS to open/close the connection to Ground for the RGB backlight and the OLED screen separately. We are using the supermini as board. Unfortunately, we had to work around from directly building from miryoku. As this caused the left/central half keyboard to freeze within a few minutes after reset. For the time being, we have manually extracted the keymap that is being generated by miryoku repo and plugged it into our .keymap file. This makes us suspect that miryoku is changing something in the device tree which is causing the issue. With our workaround, the firmware is running relatively stable. There are a few freezes, especially after not using the keyboards a few hours with certain preconditions. We are currently not able to pin point how to reliably reproduce this issue.   Anyways, for now we would like to focus on observation regarding the RGB backlight:  

  1. &rgb_ug RGB_TOG does not toggle power-domain on left/central half: When turning the backlight off using the &rgb_ug RGB_TOG behavior, the backlight on both halves of the keyboard is turned off. But only the power domain pin on the right half of the keyboard is turned to 0V/off. The power domain pin on the left half stays at 3.2V/on. Note that key/behavior &rgb_ug RGB_TOG is on right half.
  2. Toggle off RGB is not persistent: When turning the backlight off using the &rgb_ug RGB_TOG behavior, the RGB backlight turns back on when waking the keyboard from sleep. We think this is what @jeff-comley meant in his comment.
  3. Automatic RGB off, when disconnecting from USB is not persistent: When disconnecting the keyboard from USB power, the RGB backlight automatically turns off. This is great, as it prevents accidentally draining the battery. Unfortunately, similar to point 2. the RGB backlight turns back on when waking the keyboard from sleep, while still running on battery. Also note that disconnecting the USB power does not toggle off the RGB power domain.
  4. Sleep turns on RGB power domain: When the keyboard goes to sleep, both the OLED and the RGB backlight turn off. When measuring the Voltage at the respective power domain pins, that switches the MOSFET off: The OLED power domain pin is 0V/off. The RGB power domain pin is 3.2V/on. The latter is not the intended behavior. Even more interestingly: When powering off the RGB backlight using the &rgb_ug RGB_TOG behavior the respective power domain pin measures 0V/off. When the keyboard goes to sleep the RGB power domain pin is turned on/it measures 3.2V. This is not the case for the OLED power pin. --> Going to sleep turns on the RGB power domain.
  5. Confusing sleep behavior: When the keyboard goes to sleep, the RGB backlight, as well as the OLED automatically turn off. This is the intended behavior. After waiting some time the RGB backlight turns back without doing anything. Effects like breathing etc. are active too. The OLED does not turn back on.   Additionally sometimes the behavior becomes buggy and suddenly RGB power domain behavior is not reproducible. A reset resolves this issue.   We also have the impression that testing wired vs. non-wired changes the observations. Have a spreadsheet that documents state and behavior. Its quite big, but we can share it, if there is any interest. Note that some information in the table might be faulty, due to above issue with the behavior becoming buggy.   We are not sure whether the issue lies in our zmk-config or these are bugs with the power domains feature. We have not tested what the standard behavior on the zmk main branch would be (as far as this would be applicable).   We would be happy to hear any kind of input and thank you for the awesome work.

Edit: We just measured power-domain behavior when starting from a wireless state, i.e.: disconnecting USB cables from both halves and then resetting each half. Now the power-domain behavior is entirely as expected. Point 1 & 4 no longer apply. Have not tested point 5 yet. … Now we are super confused. Connecting to wired somehow breaks power-domains?   As a side note: we do not have any wired connection between the two keyboard halves. Instead, both halves are connected to the computer directly. Not sure whether this is causing an issue? We removed it, because it can't be used for charging purposes on a nice nano like boards anyways.

fouf96 avatar May 25 '24 16:05 fouf96