diff --git a/.gitignore b/.gitignore index d07ebf6..94818e5 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ # Emacs dir locals (optional) .dir-locals.el +/hold/ +.platformio_local/ + diff --git a/docs/microreticulum_firmware_migration.md b/docs/microreticulum_firmware_migration.md index be912f7..d7c2584 100644 --- a/docs/microreticulum_firmware_migration.md +++ b/docs/microreticulum_firmware_migration.md @@ -29,6 +29,9 @@ so this repo consumes existing T-Beam SUPREME integration instead of duplicating - integration paths (from `microReticulum_Firmware`) 6. After parity validation, remove or archive `external/microReticulum`. +Step-2 inventory output: +- `docs/microreticulum_firmware_step2_adoption_matrix.md` + ## Validation Checklist - Build passes for all key exercises. - SD/RTC/GPS startup behavior remains stable. diff --git a/docs/microreticulum_firmware_step2_adoption_matrix.md b/docs/microreticulum_firmware_step2_adoption_matrix.md new file mode 100644 index 0000000..ea614d8 --- /dev/null +++ b/docs/microreticulum_firmware_step2_adoption_matrix.md @@ -0,0 +1,62 @@ +# Step 2 Adoption Matrix + +## Scope +Repository: `microReticulumTbeam` +Submodule source: `external/microReticulum_Firmware` + +## What Step 2 Means +Identify and wire the first low-risk points where this repo should consume existing board-integration logic from `microReticulum_Firmware`, instead of maintaining duplicate local assumptions. + +## High-Value Upstream Sources +- `external/microReticulum_Firmware/Boards.h` + - T-Beam Supreme pin map and feature flags. + - Includes SD pins (`SD_CS=47`, `SD_CLK=36`, `SD_MISO=37`, `SD_MOSI=35`), PMU I2C pins (`I2C_SDA=42`, `I2C_SCL=41`), LoRa pins. +- `external/microReticulum_Firmware/Power.h` + - AXP2101 setup sequence for T-Beam Supreme (`BOARD_TBEAM_S_V1`), including SD rail (BLDO1), ALDO rails, charging config. +- `external/microReticulum_Firmware/platformio.ini` + - `env:ttgo-t-beam-supreme` build model and dependency pattern. + +## Local Targets And First Consumers +1. `firmware/fieldtest_beacon/src/main.cpp` +- Why first: this is the integration entry point, not just a smoke test. +- Step-2 change made: SD CS now comes from `Boards.h` instead of hardcoded `10`. + +2. `exercises/04_SD_card/src/main.cpp` +- Why second: duplicates PMU + SD pin assumptions already present upstream. +- Planned consume-first item: PMU rail setup pattern from `Power.h`. + +3. `exercises/05_SD_Card_Watcher/src/main.cpp` +- Why third: extends `04` and should share the same PMU/pin source strategy. +- Planned consume-first item: same board/power source as `04`. + +4. `exercises/06_RTC_check/src/main.cpp` +- Why fourth: depends on PMU + I2C pin assumptions that overlap upstream. +- Planned consume-first item: board I2C pin source and PMU readiness sequence. + +## Current Wiring Done +- Added submodule: + - `external/microReticulum_Firmware` +- Wired one concrete consumer: + - `firmware/fieldtest_beacon/src/main.cpp` now includes `Boards.h` and uses `SD_CS`. + - `firmware/fieldtest_beacon/platformio.ini` now includes `external/microReticulum_Firmware` headers and sets `BOARD_MODEL=BOARD_TBEAM_S_V1`. +- Added local adapter: + - `shared/boards/tbeam_supreme_adapter.h` + - Exposes board pins and PMU setup based on upstream T-Beam Supreme definitions. +- Refactored exercises to consume adapter: + - `exercises/04_SD_card` + - `exercises/05_SD_Card_Watcher` + - `exercises/06_RTC_check` + +## Validation Status +- `firmware/fieldtest_beacon` now builds after adding required deps: + - `ArduinoJson` 7.x + - `MsgPack` + - `Crypto` (provides `Ed25519.h` and `Curve25519.h`) +- `exercises/04_SD_card` builds. +- `exercises/05_SD_Card_Watcher` builds. +- `exercises/06_RTC_check` builds. + +## Next Step Candidate +Reduce macro redefinition warnings emitted by `Boards.h` in adapter consumers: +- Option A: small local board-map header with only required constants copied from upstream board model. +- Option B: upstream contribution to make board capability macros conditional/override-safe. diff --git a/exercises/04_SD_card/platformio.ini b/exercises/04_SD_card/platformio.ini index 91402fe..500e012 100644 --- a/exercises/04_SD_card/platformio.ini +++ b/exercises/04_SD_card/platformio.ini @@ -12,16 +12,13 @@ board = esp32-s3-devkitc-1 monitor_speed = 115200 lib_deps = lewisxhe/XPowersLib@0.3.3 + Wire ; SD pins based on T-Beam S3 core pin mapping build_flags = - -D SD_SCK=36 - -D SD_MISO=37 - -D SD_MOSI=35 - -D SD_CS=47 - -D IMU_CS=34 - -D I2C_SDA1=42 - -D I2C_SCL1=41 + -I ../../shared/boards + -I ../../external/microReticulum_Firmware + -D BOARD_MODEL=BOARD_TBEAM_S_V1 -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1 diff --git a/exercises/04_SD_card/src/main.cpp b/exercises/04_SD_card/src/main.cpp index 0ddf800..3b64391 100644 --- a/exercises/04_SD_card/src/main.cpp +++ b/exercises/04_SD_card/src/main.cpp @@ -6,30 +6,7 @@ #include #include #include -#include -#include - -#ifndef SD_SCK -#define SD_SCK 36 -#endif -#ifndef SD_MISO -#define SD_MISO 37 -#endif -#ifndef SD_MOSI -#define SD_MOSI 35 -#endif -#ifndef SD_CS -#define SD_CS 47 -#endif -#ifndef IMU_CS -#define IMU_CS 34 -#endif -#ifndef I2C_SDA1 -#define I2C_SDA1 42 -#endif -#ifndef I2C_SCL1 -#define I2C_SCL1 41 -#endif +#include "tbeam_supreme_adapter.h" static SPIClass sdSpiH(HSPI); static SPIClass sdSpiF(FSPI); @@ -44,32 +21,7 @@ static const char* kNestedTestFile = "/test/testsub1/testsubsub1/Exercise_04_tes static const char* kPayload = "This is a test"; static bool initPmuForSdPower() { - Wire1.begin(I2C_SDA1, I2C_SCL1); - - if (!g_pmu) { - g_pmu = new XPowersAXP2101(Wire1); - } - - if (!g_pmu->init()) { - Serial.println("PMU: AXP2101 init failed (SD power rail may be off)"); - return false; - } - - // Mirror Meshtastic tbeam-s3-core power setup needed for peripherals. - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); // GNSS - g_pmu->enablePowerOutput(XPOWERS_ALDO4); - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); // LoRa - g_pmu->enablePowerOutput(XPOWERS_ALDO3); - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); // sensor/rtc path - g_pmu->enablePowerOutput(XPOWERS_ALDO2); - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); // IMU/OLED path - g_pmu->enablePowerOutput(XPOWERS_ALDO1); - g_pmu->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); // SD card rail - g_pmu->enablePowerOutput(XPOWERS_BLDO1); - - Serial.printf("PMU: AXP2101 ready, BLDO1(SD)=%s\r\n", - g_pmu->isPowerChannelEnable(XPOWERS_BLDO1) ? "ON" : "OFF"); - return g_pmu->isPowerChannelEnable(XPOWERS_BLDO1); + return tbeam_supreme::initPmuForPeripherals(g_pmu, &Serial); } static const char* cardTypeToString(uint8_t type) { @@ -87,16 +39,16 @@ static bool tryMountWithBus(SPIClass& bus, const char* busName, uint32_t hz) { delay(10); // Keep inactive devices deselected on shared bus lines. - pinMode(SD_CS, OUTPUT); - digitalWrite(SD_CS, HIGH); - pinMode(IMU_CS, OUTPUT); - digitalWrite(IMU_CS, HIGH); + pinMode(tbeam_supreme::sdCs(), OUTPUT); + digitalWrite(tbeam_supreme::sdCs(), HIGH); + pinMode(tbeam_supreme::imuCs(), OUTPUT); + digitalWrite(tbeam_supreme::imuCs(), HIGH); - bus.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS); + bus.begin(tbeam_supreme::sdSck(), tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi(), tbeam_supreme::sdCs()); delay(2); Serial.printf("SD: trying bus=%s freq=%lu Hz\r\n", busName, (unsigned long)hz); - if (!SD.begin(SD_CS, bus, hz)) { + if (!SD.begin(tbeam_supreme::sdCs(), bus, hz)) { Serial.println("SD: mount failed (possible non-FAT format, power, or bus issue)"); return false; } @@ -231,8 +183,11 @@ void setup() { Serial.println("\r\n=================================================="); Serial.println("Exercise 04: SD card test loop"); Serial.println("=================================================="); - Serial.printf("Pins: CS=%d SCK=%d MISO=%d MOSI=%d\r\n", SD_CS, SD_SCK, SD_MISO, SD_MOSI); - Serial.printf("PMU I2C: SDA1=%d SCL1=%d\r\n", I2C_SDA1, I2C_SCL1); + Serial.printf("Pins: CS=%d SCK=%d MISO=%d MOSI=%d\r\n", + tbeam_supreme::sdCs(), tbeam_supreme::sdSck(), + tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi()); + Serial.printf("PMU I2C: SDA1=%d SCL1=%d\r\n", + tbeam_supreme::i2cSda(), tbeam_supreme::i2cScl()); Serial.println("Note: SD must be FAT16/FAT32 for Arduino SD library.\r\n"); initPmuForSdPower(); diff --git a/exercises/05_SD_Card_Watcher/platformio.ini b/exercises/05_SD_Card_Watcher/platformio.ini index 91402fe..500e012 100644 --- a/exercises/05_SD_Card_Watcher/platformio.ini +++ b/exercises/05_SD_Card_Watcher/platformio.ini @@ -12,16 +12,13 @@ board = esp32-s3-devkitc-1 monitor_speed = 115200 lib_deps = lewisxhe/XPowersLib@0.3.3 + Wire ; SD pins based on T-Beam S3 core pin mapping build_flags = - -D SD_SCK=36 - -D SD_MISO=37 - -D SD_MOSI=35 - -D SD_CS=47 - -D IMU_CS=34 - -D I2C_SDA1=42 - -D I2C_SCL1=41 + -I ../../shared/boards + -I ../../external/microReticulum_Firmware + -D BOARD_MODEL=BOARD_TBEAM_S_V1 -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1 diff --git a/exercises/05_SD_Card_Watcher/src/main.cpp b/exercises/05_SD_Card_Watcher/src/main.cpp index fc51cc7..dd778d7 100644 --- a/exercises/05_SD_Card_Watcher/src/main.cpp +++ b/exercises/05_SD_Card_Watcher/src/main.cpp @@ -7,30 +7,7 @@ #include #include #include -#include -#include - -#ifndef SD_SCK -#define SD_SCK 36 -#endif -#ifndef SD_MISO -#define SD_MISO 37 -#endif -#ifndef SD_MOSI -#define SD_MOSI 35 -#endif -#ifndef SD_CS -#define SD_CS 47 -#endif -#ifndef IMU_CS -#define IMU_CS 34 -#endif -#ifndef I2C_SDA1 -#define I2C_SDA1 42 -#endif -#ifndef I2C_SCL1 -#define I2C_SCL1 41 -#endif +#include "tbeam_supreme_adapter.h" static SPIClass sdSpiH(HSPI); static SPIClass sdSpiF(FSPI); @@ -78,32 +55,7 @@ static void logf(const char* fmt, ...) { } static bool initPmuForSdPower() { - Wire1.begin(I2C_SDA1, I2C_SCL1); - - if (!g_pmu) { - g_pmu = new XPowersAXP2101(Wire1); - } - - if (!g_pmu->init()) { - logf("PMU: AXP2101 init failed (SD power rail may be off)"); - return false; - } - - // Mirror Meshtastic tbeam-s3-core power setup needed for peripherals. - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); // GNSS - g_pmu->enablePowerOutput(XPOWERS_ALDO4); - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); // LoRa - g_pmu->enablePowerOutput(XPOWERS_ALDO3); - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); // sensor/rtc path - g_pmu->enablePowerOutput(XPOWERS_ALDO2); - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); // IMU/OLED path - g_pmu->enablePowerOutput(XPOWERS_ALDO1); - g_pmu->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); // SD card rail - g_pmu->enablePowerOutput(XPOWERS_BLDO1); - - logf("PMU: AXP2101 ready, BLDO1(SD)=%s", - g_pmu->isPowerChannelEnable(XPOWERS_BLDO1) ? "ON" : "OFF"); - return g_pmu->isPowerChannelEnable(XPOWERS_BLDO1); + return tbeam_supreme::initPmuForPeripherals(g_pmu, &Serial); } static const char* cardTypeToString(uint8_t type) { @@ -121,18 +73,18 @@ static bool tryMountWithBus(SPIClass& bus, const char* busName, uint32_t hz, boo delay(10); // Keep inactive devices deselected on shared bus lines. - pinMode(SD_CS, OUTPUT); - digitalWrite(SD_CS, HIGH); - pinMode(IMU_CS, OUTPUT); - digitalWrite(IMU_CS, HIGH); + pinMode(tbeam_supreme::sdCs(), OUTPUT); + digitalWrite(tbeam_supreme::sdCs(), HIGH); + pinMode(tbeam_supreme::imuCs(), OUTPUT); + digitalWrite(tbeam_supreme::imuCs(), HIGH); - bus.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS); + bus.begin(tbeam_supreme::sdSck(), tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi(), tbeam_supreme::sdCs()); delay(2); if (verbose) { logf("SD: trying bus=%s freq=%lu Hz", busName, (unsigned long)hz); } - if (!SD.begin(SD_CS, bus, hz)) { + if (!SD.begin(tbeam_supreme::sdCs(), bus, hz)) { if (verbose) { logf("SD: mount failed (possible non-FAT format, power, or bus issue)"); } @@ -321,8 +273,11 @@ void setup() { Serial.println("\r\n=================================================="); Serial.println("Exercise 05: SD Card Watcher"); Serial.println("=================================================="); - Serial.printf("Pins: CS=%d SCK=%d MISO=%d MOSI=%d\r\n", SD_CS, SD_SCK, SD_MISO, SD_MOSI); - Serial.printf("PMU I2C: SDA1=%d SCL1=%d\r\n", I2C_SDA1, I2C_SCL1); + Serial.printf("Pins: CS=%d SCK=%d MISO=%d MOSI=%d\r\n", + tbeam_supreme::sdCs(), tbeam_supreme::sdSck(), + tbeam_supreme::sdMiso(), tbeam_supreme::sdMosi()); + Serial.printf("PMU I2C: SDA1=%d SCL1=%d\r\n", + tbeam_supreme::i2cSda(), tbeam_supreme::i2cScl()); Serial.println("Note: SD must be FAT16/FAT32 for Arduino SD library.\r\n"); initPmuForSdPower(); diff --git a/exercises/06_RTC_check/platformio.ini b/exercises/06_RTC_check/platformio.ini index 472385a..178384b 100644 --- a/exercises/06_RTC_check/platformio.ini +++ b/exercises/06_RTC_check/platformio.ini @@ -14,8 +14,9 @@ lib_deps = lewisxhe/XPowersLib@0.3.3 build_flags = - -D I2C_SDA1=42 - -D I2C_SCL1=41 + -I ../../shared/boards + -I ../../external/microReticulum_Firmware + -D BOARD_MODEL=BOARD_TBEAM_S_V1 -D RTC_I2C_ADDR=0x51 -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1 diff --git a/exercises/06_RTC_check/src/main.cpp b/exercises/06_RTC_check/src/main.cpp index fe5f7d3..3024133 100644 --- a/exercises/06_RTC_check/src/main.cpp +++ b/exercises/06_RTC_check/src/main.cpp @@ -4,14 +4,8 @@ #include #include -#include +#include "tbeam_supreme_adapter.h" -#ifndef I2C_SDA1 -#define I2C_SDA1 42 -#endif -#ifndef I2C_SCL1 -#define I2C_SCL1 41 -#endif #ifndef RTC_I2C_ADDR #define RTC_I2C_ADDR 0x51 #endif @@ -50,26 +44,7 @@ static void logf(const char* fmt, ...) { } static bool initPmuForRtc() { - Wire1.begin(I2C_SDA1, I2C_SCL1); - - if (!g_pmu) { - g_pmu = new XPowersAXP2101(Wire1); - } - - if (!g_pmu->init()) { - logf("PMU: AXP2101 init failed"); - return false; - } - - // Keep RTC/I2C-related rails on, matching tbeam-s3-core behavior. - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); - g_pmu->enablePowerOutput(XPOWERS_ALDO2); - g_pmu->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); - g_pmu->enablePowerOutput(XPOWERS_ALDO1); - - logf("PMU: AXP2101 ready, ALDO2=%s", - g_pmu->isPowerChannelEnable(XPOWERS_ALDO2) ? "ON" : "OFF"); - return true; + return tbeam_supreme::initPmuForPeripherals(g_pmu, &Serial); } static bool rtcRead(RtcDateTime& out, bool& lowVoltageFlag) { @@ -206,7 +181,8 @@ void setup() { Serial.println("\r\n=================================================="); Serial.println("Exercise 06: RTC check (PCF8563)"); Serial.println("=================================================="); - Serial.printf("RTC I2C: SDA1=%d SCL1=%d ADDR=0x%02X\r\n", I2C_SDA1, I2C_SCL1, RTC_I2C_ADDR); + Serial.printf("RTC I2C: SDA1=%d SCL1=%d ADDR=0x%02X\r\n", + tbeam_supreme::i2cSda(), tbeam_supreme::i2cScl(), RTC_I2C_ADDR); initPmuForRtc(); diff --git a/firmware/fieldtest_beacon/platformio.ini b/firmware/fieldtest_beacon/platformio.ini index 5453277..1716089 100644 --- a/firmware/fieldtest_beacon/platformio.ini +++ b/firmware/fieldtest_beacon/platformio.ini @@ -15,8 +15,13 @@ monitor_speed = 115200 ; Pull in microReticulum from your repo tree build_flags = -I ../../external/microReticulum/src + -I ../../external/microReticulum_Firmware + -D BOARD_MODEL=BOARD_TBEAM_S_V1 -D FIELDTEST_BEACON=1 lib_deps = + bblanchon/ArduinoJson@~7.4.2 + hideakitai/MsgPack@~0.4.2 + rweather/Crypto@^0.4.0 ; SD stack usually comes with Arduino core ; Add your LoRa radio library here (RadioLib, SX126x-Arduino, etc.) diff --git a/firmware/fieldtest_beacon/src/main.cpp b/firmware/fieldtest_beacon/src/main.cpp index ede2bf8..27d38ec 100644 --- a/firmware/fieldtest_beacon/src/main.cpp +++ b/firmware/fieldtest_beacon/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "Boards.h" // Include microReticulum headers from your external tree #include "Identity.h" @@ -24,8 +25,8 @@ static uint32_t g_iter = 0; static uint32_t g_next_tx = 0; static File g_log; -// TODO: replace with your board’s SD CS pin if not default -static const int SD_CS_PIN = 10; +// Source board pin mapping from microReticulum_Firmware board definitions. +static const int SD_CS_PIN = SD_CS; // Simple line logger (append-only) static void log_line(const String& line) { diff --git a/shared/boards/tbeam_supreme_adapter.h b/shared/boards/tbeam_supreme_adapter.h new file mode 100644 index 0000000..132f025 --- /dev/null +++ b/shared/boards/tbeam_supreme_adapter.h @@ -0,0 +1,71 @@ +#pragma once + +#include +#include +#include +#include "Boards.h" + +namespace tbeam_supreme { + +inline int i2cSda() { return I2C_SDA; } +inline int i2cScl() { return I2C_SCL; } +inline int sdSck() { return SD_CLK; } +inline int sdMiso() { return SD_MISO; } +inline int sdMosi() { return SD_MOSI; } +inline int sdCs() { return SD_CS; } +inline int imuCs() { return IMU_CS; } + +inline bool initPmuForPeripherals(XPowersLibInterface*& pmu, Print* out = nullptr) { + if (BOARD_MODEL != BOARD_TBEAM_S_V1) { + if (out) out->println("PMU adapter: BOARD_MODEL is not T-Beam Supreme"); + return false; + } + + Wire1.begin(i2cSda(), i2cScl()); + + if (!pmu) { + pmu = new XPowersAXP2101(Wire1); + } + + if (!pmu->init()) { + if (out) out->println("PMU adapter: AXP2101 init failed"); + return false; + } + + // Match microReticulum_Firmware tbeam supreme rail setup. + pmu->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); + pmu->enablePowerOutput(XPOWERS_ALDO4); + pmu->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); + pmu->enablePowerOutput(XPOWERS_ALDO3); + pmu->setPowerChannelVoltage(XPOWERS_DCDC3, 3300); + pmu->enablePowerOutput(XPOWERS_DCDC3); + pmu->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); + pmu->enablePowerOutput(XPOWERS_ALDO2); + pmu->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); + pmu->enablePowerOutput(XPOWERS_ALDO1); + pmu->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); + pmu->enablePowerOutput(XPOWERS_BLDO1); + + pmu->disablePowerOutput(XPOWERS_DCDC2); + pmu->disablePowerOutput(XPOWERS_DCDC5); + pmu->disablePowerOutput(XPOWERS_DLDO1); + pmu->disablePowerOutput(XPOWERS_DLDO2); + pmu->disablePowerOutput(XPOWERS_VBACKUP); + + pmu->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2); + pmu->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA); + pmu->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); + pmu->clearIrqStatus(); + pmu->disableTSPinMeasure(); + pmu->enableVbusVoltageMeasure(); + pmu->enableBattVoltageMeasure(); + + if (out) { + out->printf("PMU adapter: AXP2101 ready, BLDO1(SD)=%s\r\n", + pmu->isPowerChannelEnable(XPOWERS_BLDO1) ? "ON" : "OFF"); + } + + return pmu->isPowerChannelEnable(XPOWERS_BLDO1); +} + +} // namespace tbeam_supreme