From a3491308588bbcf1ac57c84f3324ab0a8e6c746b Mon Sep 17 00:00:00 2001 From: John Poole Date: Sat, 14 Feb 2026 13:55:41 -0800 Subject: [PATCH] my changes, untested, before ChatGTP complete revision... for posterity --- exercises/05_SD_Card_Watcher/src/main.cpp | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/exercises/05_SD_Card_Watcher/src/main.cpp b/exercises/05_SD_Card_Watcher/src/main.cpp index dd778d7..81f14ee 100644 --- a/exercises/05_SD_Card_Watcher/src/main.cpp +++ b/exercises/05_SD_Card_Watcher/src/main.cpp @@ -54,6 +54,66 @@ static void logf(const char* fmt, ...) { Serial.printf("[%10lu][%06lu] %s\r\n", (unsigned long)millis(), (unsigned long)g_logSeq++, msg); } +static void dumpPmu(const char* tag, XPowersLibInterface* pmu) { + if (!pmu) { + logf("PMU(%s): pmu=null", tag); + return; + } + + bool bldo1 = pmu->isPowerChannelEnable(XPOWERS_BLDO1); + + // These should work because your adapter calls: + // enableVbusVoltageMeasure() and enableBattVoltageMeasure() + int vbus = pmu->getVbusVoltage(); + int batt = pmu->getBattVoltage(); + + logf("PMU(%s): BLDO1(SD)=%s VBUS=%dmV VBAT=%dmV", + tag, bldo1 ? "ON" : "OFF", vbus, batt); +} + +static void cycleSdRail(XPowersLibInterface* pmu, + uint32_t off_ms = 250, + uint32_t on_settle_ms = 600) { + if (!pmu) return; + + dumpPmu("pre-sd-cycle", pmu); + + // Make sure CS is HIGH while we yank power. + pinMode(tbeam_supreme::sdCs(), OUTPUT); + digitalWrite(tbeam_supreme::sdCs(), HIGH); + + pmu->disablePowerOutput(XPOWERS_BLDO1); + delay(off_ms); + + pmu->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); // reaffirm + pmu->enablePowerOutput(XPOWERS_BLDO1); + delay(on_settle_ms); + + dumpPmu("post-sd-cycle", pmu); +} + +static void dumpSdPins(const char* tag) { + const int CS = tbeam_supreme::sdCs(); + const int SCK = tbeam_supreme::sdSck(); + const int MISO = tbeam_supreme::sdMiso(); + const int MOSI = tbeam_supreme::sdMosi(); + + // Try to make floating lines visible. + pinMode(CS, INPUT_PULLUP); + pinMode(SCK, INPUT_PULLUP); + pinMode(MISO, INPUT_PULLUP); + pinMode(MOSI, INPUT_PULLUP); + + delay(2); + + logf("PINS(%s): CS=%d SCK=%d MISO=%d MOSI=%d", + tag, + digitalRead(CS), + digitalRead(SCK), + digitalRead(MISO), + digitalRead(MOSI)); +} + static bool initPmuForSdPower() { return tbeam_supreme::initPmuForPeripherals(g_pmu, &Serial); } @@ -79,6 +139,17 @@ static bool tryMountWithBus(SPIClass& bus, const char* busName, uint32_t hz, boo digitalWrite(tbeam_supreme::imuCs(), HIGH); bus.begin(tbeam_supreme::sdSck(), tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi(), tbeam_supreme::sdCs()); + // SD SPI reset ritual: CS high + >= 74 clocks with MOSI high. + digitalWrite(tbeam_supreme::sdCs(), HIGH); + delay(2); + for (int i = 0; i < 10; i++) { + bus.transfer(0xFF); // 8 clocks each => 80 clocks + } + delay(2); + + // Snapshot pins after clocks. + dumpSdPins("after-idle-clocks"); + delay(2); if (verbose) { @@ -267,6 +338,16 @@ static void setStateAbsent() { void setup() { Serial.begin(115200); Serial.println("[WATCHER: startup]"); + // Force all SPI devices deselected ASAP (before any delays). + pinMode(tbeam_supreme::sdCs(), OUTPUT); + digitalWrite(tbeam_supreme::sdCs(), HIGH); + + pinMode(tbeam_supreme::imuCs(), OUTPUT); + digitalWrite(tbeam_supreme::imuCs(), HIGH); + Serial.println("calling dumpSdPins early to check for floating pins before PMU config"); + dumpSdPins("very-early"); + + Serial.println("Sleeping for 5 seconds to allow Serial Monitor connection..."); delay(5000); // Time to open Serial Monitor after reset @@ -293,11 +374,13 @@ void setup() { } delay(200); } + dumpSdPins("pre-warmup-mount"); if (warmMounted) { logf("Watcher: startup warmup mount succeeded"); setStateMounted(); } else { logf("Watcher: startup warmup did not mount card"); + dumpSdPins("warmup-mount-failed"); setStateAbsent(); } }