Modified by ChatGPT for migration to microRecticulum_Firmware, not verified by me... yet, but I am preserving to document this stage.

This commit is contained in:
John Poole 2026-02-14 10:10:31 -08:00
commit 432f17b2be
12 changed files with 188 additions and 162 deletions

3
.gitignore vendored
View file

@ -14,3 +14,6 @@
# Emacs dir locals (optional)
.dir-locals.el
/hold/
.platformio_local/

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -6,30 +6,7 @@
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <XPowersLib.h>
#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();

View file

@ -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

View file

@ -7,30 +7,7 @@
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <XPowersLib.h>
#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();

View file

@ -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

View file

@ -4,14 +4,8 @@
#include <Arduino.h>
#include <Wire.h>
#include <XPowersLib.h>
#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();

View file

@ -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.)

View file

@ -6,6 +6,7 @@
#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#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 boards 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) {

View file

@ -0,0 +1,71 @@
#pragma once
#include <Arduino.h>
#include <Wire.h>
#include <XPowersLib.h>
#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