From 8bf1a20e56147b65c6a3ab1242577889e83b73c2 Mon Sep 17 00:00:00 2001 From: ainyan03 Date: Thu, 20 Aug 2026 20:42:56 +0900 Subject: [PATCH] Stop reporting a finished charge as an ongoing one on the IP5306 The register document describes two flags for this part: REG_READ0 bit3 to tell charging from discharging, and REG_READ1 bit3 to tell whether the cell has already been filled. Only the first was read. It stays set once charging is enabled and a supply is present - the completed charge included - so a finished charge was reported as an ongoing one, and so was a board running with no cell installed. Read both. They sit at adjacent addresses, but the document only ever shows a single-byte read and never states that the address auto-increments, so they are read separately rather than resting on unspecified behaviour. Measured on a Core BASIC v2.7 across every branch: supply removed (70=16 -> false), charging (70=19 71=70 -> true), charge disabled (70=11 -> false), and charge complete (71=A8 -> false, where the earlier form stayed true). Behaviour change: isCharging() now returns false once the cell is full, where it used to stay true for as long as a supply was present. Callers that watched for the transition as a sign that external power was lost will see it at full charge instead; the library has no way to express "full" through this return type yet. --- src/utility/power/IP5306_Class.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/utility/power/IP5306_Class.cpp b/src/utility/power/IP5306_Class.cpp index 208863c..8a20379 100644 --- a/src/utility/power/IP5306_Class.cpp +++ b/src/utility/power/IP5306_Class.cpp @@ -104,9 +104,30 @@ namespace m5 } bool IP5306_Class::isCharging(void) - { + { /// This needs both of the flags the datasheet describes, not one of them: + /// REG_READ0 bit3 tells charging from discharging, and REG_READ1 bit3 + /// tells whether the cell has already been filled. Only the first was + /// read. It stays set once charging is enabled and a supply is present - + /// the completed charge included - so a finished charge was reported as an + /// ongoing one, as was a board running with no cell installed at all. + /// + /// The two sit at adjacent addresses but are read separately on purpose. + /// The register document only ever shows a single-byte read and nowhere + /// states that the address auto-increments, so reading both in one + /// transaction would rest on behaviour that is not specified. + /// + /// Two limits worth knowing. The full flag has no defined reset value, so + /// shortly after power-up it can read as full before the charger has + /// settled, and nothing here can tell that from a real full charge. And a + /// failed read is reported the same way as "not charging", because this + /// return type has no room to say that the question could not be answered. std::uint8_t val = 0; - return (readRegister(REG_READ0, &val, 1)) && (val & 0x08); + if (!readRegister(REG_READ0, &val, 1)) { return false; } + /// discharging: either charging is disabled or there is no supply + if (!(val & 0x08)) { return false; } + if (!readRegister(REG_READ1, &val, 1)) { return false; } + /// already full, so nothing is going into the cell + return !(val & 0x08); } bool IP5306_Class::setPowerBoostKeepOn(bool en) {