diff --git a/exercises/07_SD_Startup_Watcher/lib/startup_sd/StartupSdManager.cpp b/exercises/07_SD_Startup_Watcher/lib/startup_sd/StartupSdManager.cpp index a77f92e..5cc77ed 100644 --- a/exercises/07_SD_Startup_Watcher/lib/startup_sd/StartupSdManager.cpp +++ b/exercises/07_SD_Startup_Watcher/lib/startup_sd/StartupSdManager.cpp @@ -71,11 +71,6 @@ void StartupSdManager::update() { bool mounted = mountPreferred(false); if (!mounted && (uint32_t)(now - lastFullScanMs_) >= cfg_.fullScanIntervalMs) { lastFullScanMs_ = now; - if (cfg_.recoveryRailCycleOnFullScan) { - logf("Watcher: recovery rail cycle before full scan"); - cycleSdRail(cfg_.recoveryRailOffMs, cfg_.recoveryRailOnSettleMs); - delay(150); - } logf("Watcher: preferred probe failed, running full scan"); mounted = mountCardFullScan(); } diff --git a/exercises/07_SD_Startup_Watcher/lib/startup_sd/StartupSdManager.h b/exercises/07_SD_Startup_Watcher/lib/startup_sd/StartupSdManager.h index be9ef27..095f857 100644 --- a/exercises/07_SD_Startup_Watcher/lib/startup_sd/StartupSdManager.h +++ b/exercises/07_SD_Startup_Watcher/lib/startup_sd/StartupSdManager.h @@ -23,9 +23,6 @@ using SdStatusCallback = void (*)(SdEvent event, const char* message); struct SdWatcherConfig { bool enableSdRailCycle = true; bool enablePinDumps = true; - bool recoveryRailCycleOnFullScan = true; - uint32_t recoveryRailOffMs = 250; - uint32_t recoveryRailOnSettleMs = 700; uint32_t startupWarmupMs = 1500; uint32_t pollIntervalAbsentMs = 1000; uint32_t pollIntervalMountedMs = 2000; diff --git a/exercises/08_SystemStartup/README.md b/exercises/08_SystemStartup/README.md deleted file mode 100644 index c9b1a8d..0000000 --- a/exercises/08_SystemStartup/README.md +++ /dev/null @@ -1,43 +0,0 @@ -## Exercise 08: SystemStartup Package Scaffold - -This exercise starts a reusable `SystemStartup` package that is intended to be shared by future exercises and field firmware. - -Current package responsibilities: - -1. Initialize OLED and show boot/status messages. -2. Initialize SD startup watcher. -3. Keep SD monitoring active in `loop()` with a single call. - -Current integration pattern: - -```cpp -#include "SystemStartup.h" - -static SystemStartup g_systemStartup(Serial); - -void setup() { - Serial.begin(115200); - g_systemStartup.begin(); -} - -void loop() { - g_systemStartup.update(); - delay(10); -} -``` - -This is the foundation for adding more startup subsystems (RTC sync/check, etc.) behind the same `begin()/update()` API. - -## Build - -```bash -source /home/jlpoole/rnsenv/bin/activate -pio run -e node_a -``` - -## Upload - -```bash -source /home/jlpoole/rnsenv/bin/activate -pio run -e node_a -t upload --upload-port /dev/ttyACM0 -``` diff --git a/exercises/08_SystemStartup/lib/startup_sd/StartupSdManager.cpp b/exercises/08_SystemStartup/lib/startup_sd/StartupSdManager.cpp deleted file mode 100644 index 1e8791c..0000000 --- a/exercises/08_SystemStartup/lib/startup_sd/StartupSdManager.cpp +++ /dev/null @@ -1,360 +0,0 @@ -#include "StartupSdManager.h" - -#include -#include "driver/gpio.h" - -StartupSdManager::StartupSdManager(Print& serial) : serial_(serial) {} - -bool StartupSdManager::begin(const SdWatcherConfig& cfg, SdStatusCallback callback) { - cfg_ = cfg; - callback_ = callback; - - forceSpiDeselected(); - dumpSdPins("very-early"); - - if (!initPmuForSdPower()) { - return false; - } - - cycleSdRail(); - delay(cfg_.startupWarmupMs); - - bool warmMounted = false; - for (uint8_t i = 0; i < 3; ++i) { - if (mountPreferred(false)) { - warmMounted = true; - break; - } - delay(200); - } - - // Some cards need a longer power/settle window after cold boot. - // Before declaring ABSENT, retry with extended settle and a full scan. - if (!warmMounted) { - logf("Watcher: startup preferred mount failed, retrying with extended settle"); - cycleSdRail(400, 1200); - delay(cfg_.startupWarmupMs + 1500); - warmMounted = mountCardFullScan(); - } - - if (warmMounted) { - setStateMounted(); - } else { - setStateAbsent(); - } - return true; -} - -void StartupSdManager::update() { - const uint32_t now = millis(); - const uint32_t pollInterval = - (watchState_ == SdWatchState::MOUNTED) ? cfg_.pollIntervalMountedMs : cfg_.pollIntervalAbsentMs; - - if ((uint32_t)(now - lastPollMs_) < pollInterval) { - return; - } - lastPollMs_ = now; - - if (watchState_ == SdWatchState::MOUNTED) { - if (verifyMountedCard()) { - presentVotes_ = 0; - absentVotes_ = 0; - return; - } - - if (mountPreferred(false) && verifyMountedCard()) { - presentVotes_ = 0; - absentVotes_ = 0; - return; - } - - absentVotes_++; - presentVotes_ = 0; - if (absentVotes_ >= cfg_.votesToAbsent) { - setStateAbsent(); - absentVotes_ = 0; - } - return; - } - - bool mounted = mountPreferred(false); - if (!mounted && (uint32_t)(now - lastFullScanMs_) >= cfg_.fullScanIntervalMs) { - lastFullScanMs_ = now; - if (cfg_.recoveryRailCycleOnFullScan) { - logf("Watcher: recovery rail cycle before full scan"); - cycleSdRail(cfg_.recoveryRailOffMs, cfg_.recoveryRailOnSettleMs); - delay(150); - } - logf("Watcher: preferred probe failed, running full scan"); - mounted = mountCardFullScan(); - } - - if (mounted) { - presentVotes_++; - absentVotes_ = 0; - if (presentVotes_ >= cfg_.votesToPresent) { - setStateMounted(); - presentVotes_ = 0; - } - } else { - absentVotes_++; - presentVotes_ = 0; - if (absentVotes_ >= cfg_.votesToAbsent) { - setStateAbsent(); - absentVotes_ = 0; - } - } -} - -bool StartupSdManager::consumeMountedEvent() { - bool out = mountedEventPending_; - mountedEventPending_ = false; - return out; -} - -bool StartupSdManager::consumeRemovedEvent() { - bool out = removedEventPending_; - removedEventPending_ = false; - return out; -} - -void StartupSdManager::logf(const char* fmt, ...) { - char msg[196]; - va_list args; - va_start(args, fmt); - vsnprintf(msg, sizeof(msg), fmt, args); - va_end(args); - serial_.printf("[%10lu][%06lu] %s\r\n", - (unsigned long)millis(), - (unsigned long)logSeq_++, - msg); -} - -void StartupSdManager::notify(SdEvent event, const char* message) { - if (callback_ != nullptr) { - callback_(event, message); - } -} - -void StartupSdManager::forceSpiDeselected() { - pinMode(tbeam_supreme::sdCs(), OUTPUT); - digitalWrite(tbeam_supreme::sdCs(), HIGH); - pinMode(tbeam_supreme::imuCs(), OUTPUT); - digitalWrite(tbeam_supreme::imuCs(), HIGH); -} - -void StartupSdManager::dumpSdPins(const char* tag) { - if (!cfg_.enablePinDumps) { - (void)tag; - return; - } - - const gpio_num_t cs = (gpio_num_t)tbeam_supreme::sdCs(); - const gpio_num_t sck = (gpio_num_t)tbeam_supreme::sdSck(); - const gpio_num_t miso = (gpio_num_t)tbeam_supreme::sdMiso(); - const gpio_num_t mosi = (gpio_num_t)tbeam_supreme::sdMosi(); - logf("PINS(%s): CS=%d SCK=%d MISO=%d MOSI=%d", - tag, gpio_get_level(cs), gpio_get_level(sck), gpio_get_level(miso), gpio_get_level(mosi)); -} - -bool StartupSdManager::initPmuForSdPower() { - if (!tbeam_supreme::initPmuForPeripherals(pmu_, &serial_)) { - logf("ERROR: PMU init failed"); - return false; - } - return true; -} - -void StartupSdManager::cycleSdRail(uint32_t offMs, uint32_t onSettleMs) { - if (!cfg_.enableSdRailCycle) { - return; - } - if (!pmu_) { - logf("SD rail cycle skipped: pmu=null"); - return; - } - - forceSpiDeselected(); - pmu_->disablePowerOutput(XPOWERS_BLDO1); - delay(offMs); - pmu_->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); - pmu_->enablePowerOutput(XPOWERS_BLDO1); - delay(onSettleMs); -} - -bool StartupSdManager::tryMountWithBus(SPIClass& bus, const char* busName, uint32_t hz, bool verbose) { - SD.end(); - bus.end(); - delay(10); - forceSpiDeselected(); - - bus.begin(tbeam_supreme::sdSck(), tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi(), tbeam_supreme::sdCs()); - digitalWrite(tbeam_supreme::sdCs(), HIGH); - delay(2); - for (int i = 0; i < 10; i++) { - bus.transfer(0xFF); - } - delay(2); - - if (verbose) { - logf("SD: trying bus=%s freq=%lu Hz", busName, (unsigned long)hz); - } - - if (!SD.begin(tbeam_supreme::sdCs(), bus, hz)) { - if (verbose) { - logf("SD: mount failed (possible non-FAT format, power, or bus issue)"); - } - return false; - } - - if (SD.cardType() == CARD_NONE) { - SD.end(); - return false; - } - - sdSpi_ = &bus; - sdBusName_ = busName; - sdFreq_ = hz; - return true; -} - -bool StartupSdManager::mountPreferred(bool verbose) { - return tryMountWithBus(sdSpiH_, "HSPI", 400000, verbose); -} - -bool StartupSdManager::mountCardFullScan() { - const uint32_t freqs[] = {400000, 1000000, 4000000, 10000000}; - - for (uint8_t i = 0; i < (sizeof(freqs) / sizeof(freqs[0])); ++i) { - if (tryMountWithBus(sdSpiH_, "HSPI", freqs[i], true)) { - logf("SD: card detected and mounted"); - return true; - } - } - for (uint8_t i = 0; i < (sizeof(freqs) / sizeof(freqs[0])); ++i) { - if (tryMountWithBus(sdSpiF_, "FSPI", freqs[i], true)) { - logf("SD: card detected and mounted"); - return true; - } - } - - logf("SD: begin() failed on all bus/frequency attempts"); - return false; -} - -bool StartupSdManager::verifyMountedCard() { - File root = SD.open("/", FILE_READ); - if (!root) { - return false; - } - root.close(); - return true; -} - -const char* StartupSdManager::cardTypeToString(uint8_t type) { - switch (type) { - case CARD_MMC: - return "MMC"; - case CARD_SD: - return "SDSC"; - case CARD_SDHC: - return "SDHC/SDXC"; - default: - return "UNKNOWN"; - } -} - -void StartupSdManager::printCardInfo() { - uint8_t cardType = SD.cardType(); - uint64_t cardSizeMB = SD.cardSize() / (1024ULL * 1024ULL); - uint64_t totalMB = SD.totalBytes() / (1024ULL * 1024ULL); - uint64_t usedMB = SD.usedBytes() / (1024ULL * 1024ULL); - - logf("SD type: %s", cardTypeToString(cardType)); - logf("SD size: %llu MB", cardSizeMB); - logf("FS total: %llu MB", totalMB); - logf("FS used : %llu MB", usedMB); - logf("SPI bus: %s @ %lu Hz", sdBusName_, (unsigned long)sdFreq_); -} - -bool StartupSdManager::ensureDirRecursive(const char* path) { - String full(path); - if (!full.startsWith("/")) { - full = "/" + full; - } - - int start = 1; - while (start > 0 && start < (int)full.length()) { - int slash = full.indexOf('/', start); - String partial = (slash < 0) ? full : full.substring(0, slash); - if (!SD.exists(partial.c_str()) && !SD.mkdir(partial.c_str())) { - logf("ERROR: mkdir failed for %s", partial.c_str()); - return false; - } - if (slash < 0) { - break; - } - start = slash + 1; - } - - return true; -} - -bool StartupSdManager::rewriteFile(const char* path, const char* payload) { - if (SD.exists(path) && !SD.remove(path)) { - logf("ERROR: failed to erase %s", path); - return false; - } - - File f = SD.open(path, FILE_WRITE); - if (!f) { - logf("ERROR: failed to create %s", path); - return false; - } - - size_t wrote = f.println(payload); - f.close(); - if (wrote == 0) { - logf("ERROR: write failed for %s", path); - return false; - } - return true; -} - -void StartupSdManager::permissionsDemo(const char* path) { - logf("Permissions demo: FAT has no Unix chmod/chown, use open mode only."); - File r = SD.open(path, FILE_READ); - if (!r) { - logf("Could not open %s as FILE_READ", path); - return; - } - size_t writeInReadMode = r.print("attempt write while opened read-only"); - if (writeInReadMode == 0) { - logf("As expected, FILE_READ write was blocked."); - } else { - logf("NOTE: FILE_READ write returned %u (unexpected)", (unsigned)writeInReadMode); - } - r.close(); -} - -void StartupSdManager::setStateMounted() { - if (watchState_ != SdWatchState::MOUNTED) { - logf("EVENT: card inserted/mounted"); - mountedEventPending_ = true; - notify(SdEvent::CARD_MOUNTED, "SD card mounted"); - } - watchState_ = SdWatchState::MOUNTED; -} - -void StartupSdManager::setStateAbsent() { - if (watchState_ == SdWatchState::MOUNTED) { - logf("EVENT: card removed/unavailable"); - removedEventPending_ = true; - notify(SdEvent::CARD_REMOVED, "SD card removed"); - } else if (watchState_ != SdWatchState::ABSENT) { - logf("EVENT: no card detected"); - notify(SdEvent::NO_CARD, "Missing SD card or invalid FAT16/FAT32 format"); - } - SD.end(); - watchState_ = SdWatchState::ABSENT; -} diff --git a/exercises/08_SystemStartup/lib/startup_sd/StartupSdManager.h b/exercises/08_SystemStartup/lib/startup_sd/StartupSdManager.h deleted file mode 100644 index be9ef27..0000000 --- a/exercises/08_SystemStartup/lib/startup_sd/StartupSdManager.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "tbeam_supreme_adapter.h" - -enum class SdWatchState : uint8_t { - UNKNOWN = 0, - ABSENT, - MOUNTED -}; - -enum class SdEvent : uint8_t { - NO_CARD, - CARD_MOUNTED, - CARD_REMOVED -}; - -using SdStatusCallback = void (*)(SdEvent event, const char* message); - -struct SdWatcherConfig { - bool enableSdRailCycle = true; - bool enablePinDumps = true; - bool recoveryRailCycleOnFullScan = true; - uint32_t recoveryRailOffMs = 250; - uint32_t recoveryRailOnSettleMs = 700; - uint32_t startupWarmupMs = 1500; - uint32_t pollIntervalAbsentMs = 1000; - uint32_t pollIntervalMountedMs = 2000; - uint32_t fullScanIntervalMs = 10000; - uint8_t votesToPresent = 2; - uint8_t votesToAbsent = 5; -}; - -class StartupSdManager { - public: - explicit StartupSdManager(Print& serial = Serial); - - bool begin(const SdWatcherConfig& cfg, SdStatusCallback callback = nullptr); - void update(); - - bool isMounted() const { return watchState_ == SdWatchState::MOUNTED; } - SdWatchState state() const { return watchState_; } - - bool consumeMountedEvent(); - bool consumeRemovedEvent(); - - void printCardInfo(); - bool ensureDirRecursive(const char* path); - bool rewriteFile(const char* path, const char* payload); - void permissionsDemo(const char* path); - - private: - void logf(const char* fmt, ...); - void notify(SdEvent event, const char* message); - void forceSpiDeselected(); - void dumpSdPins(const char* tag); - bool initPmuForSdPower(); - void cycleSdRail(uint32_t offMs = 250, uint32_t onSettleMs = 600); - bool tryMountWithBus(SPIClass& bus, const char* busName, uint32_t hz, bool verbose); - bool mountPreferred(bool verbose); - bool mountCardFullScan(); - bool verifyMountedCard(); - const char* cardTypeToString(uint8_t type); - void setStateMounted(); - void setStateAbsent(); - - Print& serial_; - SdWatcherConfig cfg_{}; - SdStatusCallback callback_ = nullptr; - - SPIClass sdSpiH_{HSPI}; - SPIClass sdSpiF_{FSPI}; - SPIClass* sdSpi_ = nullptr; - const char* sdBusName_ = "none"; - uint32_t sdFreq_ = 0; - XPowersLibInterface* pmu_ = nullptr; - - SdWatchState watchState_ = SdWatchState::UNKNOWN; - uint8_t presentVotes_ = 0; - uint8_t absentVotes_ = 0; - uint32_t lastPollMs_ = 0; - uint32_t lastFullScanMs_ = 0; - uint32_t logSeq_ = 0; - - bool mountedEventPending_ = false; - bool removedEventPending_ = false; -}; diff --git a/exercises/08_SystemStartup/lib/startup_sd/library.json b/exercises/08_SystemStartup/lib/startup_sd/library.json deleted file mode 100644 index 4978fdd..0000000 --- a/exercises/08_SystemStartup/lib/startup_sd/library.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "startup_sd", - "version": "0.1.0", - "dependencies": [ - { - "name": "XPowersLib" - }, - { - "name": "Wire" - } - ] -} diff --git a/exercises/08_SystemStartup/lib/system_startup/SystemStartup.cpp b/exercises/08_SystemStartup/lib/system_startup/SystemStartup.cpp deleted file mode 100644 index 3a82e1f..0000000 --- a/exercises/08_SystemStartup/lib/system_startup/SystemStartup.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "SystemStartup.h" - -#include -#include - -#ifndef OLED_SDA -#define OLED_SDA 17 -#endif - -#ifndef OLED_SCL -#define OLED_SCL 18 -#endif - -#ifndef OLED_ADDR -#define OLED_ADDR 0x3C -#endif - -static const bool kEnableOled = true; - -static U8G2_SH1106_128X64_NONAME_F_HW_I2C g_oled(U8G2_R0, /* reset=*/U8X8_PIN_NONE); -static SystemStartup* g_activeSystemStartup = nullptr; - -static void forceSpiDeselectedEarly() { - pinMode(tbeam_supreme::sdCs(), OUTPUT); - digitalWrite(tbeam_supreme::sdCs(), HIGH); - pinMode(tbeam_supreme::imuCs(), OUTPUT); - digitalWrite(tbeam_supreme::imuCs(), HIGH); -} - -SystemStartup::SystemStartup(Print& serial) : serial_(serial), sd_(serial) {} - -bool SystemStartup::begin(const SystemStartupConfig& cfg, SystemEventCallback callback) { - cfg_ = cfg; - callback_ = callback; - g_activeSystemStartup = this; - - // Match Exercise 05 behavior: deselect SPI devices immediately at startup. - forceSpiDeselectedEarly(); - - if (kEnableOled) { - Wire.begin(OLED_SDA, OLED_SCL); - g_oled.setI2CAddress(OLED_ADDR << 1); - g_oled.begin(); - } - - emit(SystemEvent::BOOTING, "System startup booting"); - oledShow3("System Startup", "Booting..."); - - serial_.printf("Sleeping for %lu ms to allow Serial Monitor connection...\r\n", - (unsigned long)cfg_.serialDelayMs); - delay(cfg_.serialDelayMs); - - return sd_.begin(cfg_.sd, &SystemStartup::onSdEventThunk); -} - -void SystemStartup::update() { - sd_.update(); -} - -void SystemStartup::onSdEventThunk(SdEvent event, const char* message) { - if (g_activeSystemStartup != nullptr) { - g_activeSystemStartup->onSdEvent(event, message); - } -} - -void SystemStartup::onSdEvent(SdEvent event, const char* message) { - if (event == SdEvent::NO_CARD) { - oledShow3("SD missing or", "invalid FAT16/32", "Insert/format card"); - emit(SystemEvent::SD_MISSING, message); - } else if (event == SdEvent::CARD_MOUNTED) { - oledShow3("SD card ready", "Mounted OK"); - emit(SystemEvent::SD_READY, message); - } else if (event == SdEvent::CARD_REMOVED) { - oledShow3("SD card removed", "Please re-insert"); - emit(SystemEvent::SD_REMOVED, message); - } -} - -void SystemStartup::emit(SystemEvent event, const char* message) { - serial_.printf("[SYSTEM] %s\r\n", message); - if (callback_ != nullptr) { - callback_(event, message); - } -} - -void SystemStartup::oledShow3(const char* l1, const char* l2, const char* l3) { - if (!kEnableOled) { - return; - } - g_oled.clearBuffer(); - g_oled.setFont(u8g2_font_6x10_tf); - if (l1) g_oled.drawUTF8(0, 16, l1); - if (l2) g_oled.drawUTF8(0, 32, l2); - if (l3) g_oled.drawUTF8(0, 48, l3); - g_oled.sendBuffer(); -} diff --git a/exercises/08_SystemStartup/lib/system_startup/SystemStartup.h b/exercises/08_SystemStartup/lib/system_startup/SystemStartup.h deleted file mode 100644 index cd83857..0000000 --- a/exercises/08_SystemStartup/lib/system_startup/SystemStartup.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include "StartupSdManager.h" - -// Convenience alias so sketches can use System.println(...) style logging. -// Arduino exposes Serial, not System, so map System -> Serial. -#ifndef System -#define System Serial -#endif - -enum class SystemEvent : uint8_t { - BOOTING = 0, - SD_MISSING, - SD_READY, - SD_REMOVED -}; - -using SystemEventCallback = void (*)(SystemEvent event, const char* message); - -struct SystemStartupConfig { - uint32_t serialDelayMs = 5000; - SdWatcherConfig sd{}; -}; - -class SystemStartup { - public: - explicit SystemStartup(Print& serial = Serial); - - bool begin(const SystemStartupConfig& cfg = SystemStartupConfig{}, SystemEventCallback callback = nullptr); - void update(); - - bool isSdMounted() const { return sd_.isMounted(); } - StartupSdManager& sdManager() { return sd_; } - - private: - static void onSdEventThunk(SdEvent event, const char* message); - void onSdEvent(SdEvent event, const char* message); - void emit(SystemEvent event, const char* message); - void oledShow3(const char* l1, const char* l2 = nullptr, const char* l3 = nullptr); - - Print& serial_; - SystemStartupConfig cfg_{}; - SystemEventCallback callback_ = nullptr; - StartupSdManager sd_; -}; diff --git a/exercises/08_SystemStartup/lib/system_startup/library.json b/exercises/08_SystemStartup/lib/system_startup/library.json deleted file mode 100644 index 0c2c1cf..0000000 --- a/exercises/08_SystemStartup/lib/system_startup/library.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "system_startup", - "version": "0.1.0", - "dependencies": [ - { - "name": "startup_sd" - }, - { - "name": "U8g2" - }, - { - "name": "Wire" - } - ] -} diff --git a/exercises/08_SystemStartup/platformio.ini b/exercises/08_SystemStartup/platformio.ini deleted file mode 100644 index e760c56..0000000 --- a/exercises/08_SystemStartup/platformio.ini +++ /dev/null @@ -1,37 +0,0 @@ -; 20260213 ChatGPT -; $Id$ -; $HeadURL$ - -[platformio] -default_envs = node_a - -[env] -platform = espressif32 -framework = arduino -board = esp32-s3-devkitc-1 -monitor_speed = 115200 -lib_deps = - lewisxhe/XPowersLib@0.3.3 - Wire - olikraus/U8g2@^2.36.4 - -; SD pins based on T-Beam S3 core pin mapping -build_flags = - -I ../../shared/boards - -I ../../external/microReticulum_Firmware - -D BOARD_MODEL=BOARD_TBEAM_S_V1 - -D OLED_SDA=17 - -D OLED_SCL=18 - -D OLED_ADDR=0x3C - -D ARDUINO_USB_MODE=1 - -D ARDUINO_USB_CDC_ON_BOOT=1 - -[env:node_a] -build_flags = - ${env.build_flags} - -D NODE_LABEL=\"A\" - -[env:node_b] -build_flags = - ${env.build_flags} - -D NODE_LABEL=\"B\" diff --git a/exercises/08_SystemStartup/src/main.cpp b/exercises/08_SystemStartup/src/main.cpp deleted file mode 100644 index 5f766e7..0000000 --- a/exercises/08_SystemStartup/src/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// 20260216 ChatGPT -// $Id$ -// $HeadURL$ - -#include -#include "SystemStartup.h" - -static SystemStartup g_systemStartup(Serial); - -void setup() { - Serial.begin(115200); - System.println("Example 08: setup() called. About to call g_systemStartup.begin()."); - g_systemStartup.begin(); - System.println("After g_systemStartup() in setup()."); -} - -void loop() { - g_systemStartup.update(); - System.println("Example 08 loop() called and after g_systemStartup.update()."); - delay(1000); -} diff --git a/exercises/README.md b/exercises/README.md index 2f7f118..a6b703a 100644 --- a/exercises/README.md +++ b/exercises/README.md @@ -45,8 +45,6 @@ Exercise 06: RTC check (PCF8563) read/set and persistence validation Exercise 07: SD startup watcher library harness with hot-insert detection -Exercise 08: SystemStartup package scaffold (shared begin/update API) - Each exercise is self-contained: its own platformio.ini