Skip to content

Fix Display Out enable bit, charge-state caps, IP5306 voltage steps and PowerHub power-off - #403

Merged
lovyan03 merged 2 commits into
m5stack:developfrom
ainyan03:api_fixes_0_3_0
Oct 15, 2026
Merged

lovyan03 merged 2 commits into
m5stack:developfrom
ainyan03:api_fixes_0_3_0

Conversation

@ainyan03

Copy link
Copy Markdown
Contributor

Use a single enable bit for the Unit PoE-P4 display output

  • The Display Out enable required both the new unit_poep4_display_out (bit 9) and the deprecated unit_poep4_hdmi (bit 10). After cfg.external_display_value = 0, setting only the new name left the output disabled, and a raw mask with only bit 9 (the 0.2.26 meaning) no longer enabled it.
  • Bit 9 is now the only enable bit (the 0.2.26 layout). Breaking: the bitfield external_display.unit_poep4_hdmi is removed, so code that writes it fails to compile; use external_display.unit_poep4_display_out. cfg.unit_poep4_hdmi (the config structure) is unchanged.

Power

  • getChargeStateCaps() returns charge_state_set_t by value, like the other two capability getters. Empty before M5.begin(), on unsupported models, and while the PMIC identity is unconfirmed.
  • IP5306 setChargeVoltage() selects and reports the nominal steps 4200 / 4300 / 4350 / 4400 mV (the AXP192 / AXP2101 convention). The previous comparison with boosted values selected one step lower (4300 → 4.2 V step). Requests of 4400 mV or more now reach the 4.4 V step, which the 0.2.26 clamp never selected.
  • PowerHub: an accepted power-off request cannot be withdrawn, so the flag recording it now stays set for the boot, and timerSleep() refuses before touching the RTC, wake sources or display. A retry can no longer clear the alarm that a delayed power-off needs.
  • PowerHub: registers 0x01-0x05 (outputs and voltage / current measurement) are saved before the power-off request and restored when the device keeps running, so battery and charge readings keep working afterwards.

Testing

  • Local build matrix of the versions used by this repository's CI (Arduino 2.x / 3.x, ESP-IDF 4.4 to 6.1, all chips): all passed. CI on the fork: passed.
  • M5Stack Core BASIC v2.7 (IP5306): setChargeVoltage() with 4100 / 4200 / 4299 / 4300 / 4350 / 4400 / 4500 mV gave the expected nominal step and CHG_CTL2 value (0x02 / 0x02 / 0x02 / 0x05 / 0x09 / 0x0D / 0x0D).
  • PowerHub: timerSleep(time) powered off and woke at the alarm. The path where the device keeps running (failed or timed-out request) could not be produced on hardware and was checked by review.

The Display Out enable was split into two bitfields (the new
unit_poep4_display_out at bit 9 and the deprecated unit_poep4_hdmi at
bit 10) and required both to be set. Clearing external_display_value
and then setting only the new name therefore left the output disabled,
and a raw mask with only bit 9 set (the 0.2.26 meaning) no longer
enabled it either.

Bit 9 is now the only enable bit, which restores the 0.2.26 raw-mask
layout. The legacy bitfield external_display.unit_poep4_hdmi is removed,
so code that still writes it fails to compile instead of silently
losing its effect. Replace it with external_display.unit_poep4_display_out.
The config structure member cfg.unit_poep4_hdmi is unchanged.
…-off retry

getChargeStateCaps() now returns the set by value, like
getChargeControlCaps() and getPowerOutputCaps(). The set is empty before
M5.begin() completes, on unsupported models, and while the PMIC identity
is unconfirmed; getChargeState() reports not_initialized, unsupported or
io_error respectively.

IP5306 setChargeVoltage() selects and reports the nominal steps 4200 /
4300 / 4350 / 4400 mV, like the AXP192 / AXP2101 paths. Comparing the
requests with the boosted values selected one step lower than requested
(4300 gave the 4.2 V step). 0.2.26 clamped requests at the equivalent of
4360 mV, so the 4.4 V step was unreachable; requests of 4400 mV or more
now select it. The register values and the datasheet boost are unchanged.

On PowerHub an accepted power-off request cannot be withdrawn and may
still complete after timerSleep() has returned. The flag that records
it now stays set for the rest of the boot, and timerSleep() refuses
before touching the RTC, the ESP wake sources or the display, so a
retry can no longer clear the alarm that a delayed power-off needs.

PowerHub power-off cleared registers 0x01-0x05 (outputs and the voltage
/ current measurement) and did not restore them when the device kept
running, so battery and charge readings stayed broken afterwards. The
values are saved before the request and written back when it fails or
times out; if they could not be read, only the measurement enable is
restored.
@lovyan03
lovyan03 merged commit 2c71cbd into m5stack:develop Oct 15, 2026
30 checks passed
@ainyan03
ainyan03 deleted the api_fixes_0_3_0 branch October 15, 2026 02:07
@ainyan03 ainyan03 mentioned this pull request Oct 20, 2026
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