2025-01-28 20:30:15 +11:00
|
|
|
#include <Arduino.h> // needed for PlatformIO
|
|
|
|
|
#include <Mesh.h>
|
2025-05-29 13:06:24 -07:00
|
|
|
#include "MyMesh.h"
|
2025-03-04 23:09:43 +11:00
|
|
|
|
2025-01-28 20:30:15 +11:00
|
|
|
// Believe it or not, this std C function is busted on some platforms!
|
|
|
|
|
static uint32_t _atoi(const char* sp) {
|
|
|
|
|
uint32_t n = 0;
|
|
|
|
|
while (*sp && *sp >= '0' && *sp <= '9') {
|
|
|
|
|
n *= 10;
|
|
|
|
|
n += (*sp++ - '0');
|
|
|
|
|
}
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-11 09:26:32 +02:00
|
|
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
2025-05-29 13:06:24 -07:00
|
|
|
#include <InternalFileSystem.h>
|
2025-08-02 08:31:23 +10:00
|
|
|
#if defined(QSPIFLASH)
|
|
|
|
|
#include <CustomLFS_QSPIFlash.h>
|
2025-08-22 13:09:54 +10:00
|
|
|
DataStore store(InternalFS, QSPIFlash, rtc_clock);
|
2025-07-29 20:06:35 +10:00
|
|
|
#else
|
|
|
|
|
#if defined(EXTRAFS)
|
|
|
|
|
#include <CustomLFS.h>
|
|
|
|
|
CustomLFS ExtraFS(0xD4000, 0x19000, 128);
|
2025-08-22 13:09:54 +10:00
|
|
|
DataStore store(InternalFS, ExtraFS, rtc_clock);
|
2025-07-29 20:06:35 +10:00
|
|
|
#else
|
|
|
|
|
DataStore store(InternalFS, rtc_clock);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2025-04-21 21:17:03 +01:00
|
|
|
#elif defined(RP2040_PLATFORM)
|
2025-05-29 13:06:24 -07:00
|
|
|
#include <LittleFS.h>
|
2025-06-06 21:35:54 +10:00
|
|
|
DataStore store(LittleFS, rtc_clock);
|
2025-05-29 13:06:24 -07:00
|
|
|
#elif defined(ESP32)
|
|
|
|
|
#include <SPIFFS.h>
|
2025-06-06 21:35:54 +10:00
|
|
|
DataStore store(SPIFFS, rtc_clock);
|
2025-02-01 12:43:06 +11:00
|
|
|
#endif
|
2025-01-28 20:30:15 +11:00
|
|
|
|
|
|
|
|
#ifdef ESP32
|
2025-03-03 13:26:37 +01:00
|
|
|
#ifdef WIFI_SSID
|
|
|
|
|
#include <helpers/esp32/SerialWifiInterface.h>
|
|
|
|
|
SerialWifiInterface serial_interface;
|
|
|
|
|
#ifndef TCP_PORT
|
|
|
|
|
#define TCP_PORT 5000
|
|
|
|
|
#endif
|
|
|
|
|
#elif defined(BLE_PIN_CODE)
|
2025-01-28 23:26:55 +11:00
|
|
|
#include <helpers/esp32/SerialBLEInterface.h>
|
|
|
|
|
SerialBLEInterface serial_interface;
|
2025-04-01 11:32:04 +02:00
|
|
|
#elif defined(SERIAL_RX)
|
|
|
|
|
#include <helpers/ArduinoSerialInterface.h>
|
|
|
|
|
ArduinoSerialInterface serial_interface;
|
|
|
|
|
HardwareSerial companion_serial(1);
|
2025-01-28 23:26:55 +11:00
|
|
|
#else
|
|
|
|
|
#include <helpers/ArduinoSerialInterface.h>
|
|
|
|
|
ArduinoSerialInterface serial_interface;
|
|
|
|
|
#endif
|
2025-04-21 21:17:03 +01:00
|
|
|
#elif defined(RP2040_PLATFORM)
|
|
|
|
|
//#ifdef WIFI_SSID
|
|
|
|
|
// #include <helpers/rp2040/SerialWifiInterface.h>
|
|
|
|
|
// SerialWifiInterface serial_interface;
|
|
|
|
|
// #ifndef TCP_PORT
|
|
|
|
|
// #define TCP_PORT 5000
|
|
|
|
|
// #endif
|
|
|
|
|
// #elif defined(BLE_PIN_CODE)
|
|
|
|
|
// #include <helpers/rp2040/SerialBLEInterface.h>
|
|
|
|
|
// SerialBLEInterface serial_interface;
|
|
|
|
|
#if defined(SERIAL_RX)
|
|
|
|
|
#include <helpers/ArduinoSerialInterface.h>
|
|
|
|
|
ArduinoSerialInterface serial_interface;
|
|
|
|
|
HardwareSerial companion_serial(1);
|
|
|
|
|
#else
|
|
|
|
|
#include <helpers/ArduinoSerialInterface.h>
|
|
|
|
|
ArduinoSerialInterface serial_interface;
|
|
|
|
|
#endif
|
2025-01-29 00:02:05 +11:00
|
|
|
#elif defined(NRF52_PLATFORM)
|
2026-05-20 18:20:10 +02:00
|
|
|
#ifdef DUAL_SERIAL
|
|
|
|
|
#include <helpers/nrf52/DualSerialInterface.h>
|
|
|
|
|
DualSerialInterface serial_interface;
|
|
|
|
|
#elif defined(BLE_PIN_CODE)
|
2025-02-12 18:40:00 +11:00
|
|
|
#include <helpers/nrf52/SerialBLEInterface.h>
|
|
|
|
|
SerialBLEInterface serial_interface;
|
2025-01-29 00:02:05 +11:00
|
|
|
#else
|
|
|
|
|
#include <helpers/ArduinoSerialInterface.h>
|
|
|
|
|
ArduinoSerialInterface serial_interface;
|
|
|
|
|
#endif
|
2025-05-11 09:26:32 +02:00
|
|
|
#elif defined(STM32_PLATFORM)
|
|
|
|
|
#include <helpers/ArduinoSerialInterface.h>
|
|
|
|
|
ArduinoSerialInterface serial_interface;
|
2025-01-28 20:30:15 +11:00
|
|
|
#else
|
2025-01-28 23:26:55 +11:00
|
|
|
#error "need to define a serial interface"
|
2025-01-28 20:30:15 +11:00
|
|
|
#endif
|
|
|
|
|
|
2025-05-29 13:06:24 -07:00
|
|
|
/* GLOBAL OBJECTS */
|
|
|
|
|
#ifdef DISPLAY_CLASS
|
|
|
|
|
#include "UITask.h"
|
2025-08-08 20:01:31 +10:00
|
|
|
UITask ui_task(&board, &serial_interface);
|
2025-05-29 13:06:24 -07:00
|
|
|
#endif
|
2025-08-16 20:04:54 +10:00
|
|
|
|
|
|
|
|
StdRNG fast_rng;
|
|
|
|
|
SimpleMeshTables tables;
|
|
|
|
|
MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables, store
|
|
|
|
|
#ifdef DISPLAY_CLASS
|
|
|
|
|
, &ui_task
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
|
2025-05-29 13:06:24 -07:00
|
|
|
/* END GLOBAL OBJECTS */
|
|
|
|
|
|
2025-01-28 20:30:15 +11:00
|
|
|
void halt() {
|
|
|
|
|
while (1) ;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-07 12:24:06 +02:00
|
|
|
/* WIFI RECONNECT TRACKERS */
|
|
|
|
|
#if defined(ESP32) && defined(WIFI_SSID)
|
|
|
|
|
bool wifi_needs_reconnect = false;
|
|
|
|
|
unsigned long last_wifi_reconnect_attempt = 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-01-28 20:30:15 +11:00
|
|
|
void setup() {
|
|
|
|
|
Serial.begin(115200);
|
|
|
|
|
|
|
|
|
|
board.begin();
|
|
|
|
|
|
2025-05-19 14:16:55 +10:00
|
|
|
#ifdef DISPLAY_CLASS
|
2025-03-16 13:42:36 +11:00
|
|
|
DisplayDriver* disp = NULL;
|
|
|
|
|
if (display.begin()) {
|
|
|
|
|
disp = &display;
|
2025-04-01 15:50:24 +13:00
|
|
|
disp->startFrame();
|
2025-08-08 20:01:31 +10:00
|
|
|
#ifdef ST7789
|
|
|
|
|
disp->setTextSize(2);
|
|
|
|
|
#endif
|
|
|
|
|
disp->drawTextCentered(disp->width() / 2, 28, "Loading...");
|
2025-04-01 15:50:24 +13:00
|
|
|
disp->endFrame();
|
2025-03-16 13:42:36 +11:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-04-01 16:10:12 +13:00
|
|
|
if (!radio_init()) { halt(); }
|
|
|
|
|
|
2026-05-01 14:47:07 +10:00
|
|
|
fast_rng.begin(radio_driver.getRngSeed());
|
2025-04-01 16:10:12 +13:00
|
|
|
|
2025-05-11 09:26:32 +02:00
|
|
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
2025-08-22 13:09:54 +10:00
|
|
|
InternalFS.begin();
|
2025-08-02 08:31:23 +10:00
|
|
|
#if defined(QSPIFLASH)
|
|
|
|
|
if (!QSPIFlash.begin()) {
|
2025-07-29 20:06:35 +10:00
|
|
|
// debug output might not be available at this point, might be too early. maybe should fall back to InternalFS here?
|
2025-08-02 08:31:23 +10:00
|
|
|
MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: failed to initialize");
|
2025-07-29 20:06:35 +10:00
|
|
|
} else {
|
2025-08-02 08:31:23 +10:00
|
|
|
MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: initialized successfully");
|
2025-07-29 20:06:35 +10:00
|
|
|
}
|
|
|
|
|
#else
|
2025-08-22 13:09:54 +10:00
|
|
|
#if defined(EXTRAFS)
|
2025-07-29 20:06:35 +10:00
|
|
|
ExtraFS.begin();
|
2025-08-22 13:09:54 +10:00
|
|
|
#endif
|
2025-07-29 20:06:35 +10:00
|
|
|
#endif
|
2025-06-06 15:30:35 +10:00
|
|
|
store.begin();
|
|
|
|
|
the_mesh.begin(
|
2025-05-19 14:16:55 +10:00
|
|
|
#ifdef DISPLAY_CLASS
|
2025-03-16 13:42:36 +11:00
|
|
|
disp != NULL
|
|
|
|
|
#else
|
|
|
|
|
false
|
|
|
|
|
#endif
|
|
|
|
|
);
|
2025-01-28 20:30:15 +11:00
|
|
|
|
2026-05-20 18:20:10 +02:00
|
|
|
#ifdef DUAL_SERIAL
|
|
|
|
|
serial_interface.begin(BLE_NAME_PREFIX, the_mesh.getNodePrefs()->node_name, the_mesh.getBLEPin(), Serial);
|
|
|
|
|
#elif defined(BLE_PIN_CODE)
|
2026-01-23 15:53:58 +11:00
|
|
|
serial_interface.begin(BLE_NAME_PREFIX, the_mesh.getNodePrefs()->node_name, the_mesh.getBLEPin());
|
2025-02-12 18:40:00 +11:00
|
|
|
#else
|
|
|
|
|
serial_interface.begin(Serial);
|
|
|
|
|
#endif
|
2025-02-14 10:46:40 +11:00
|
|
|
the_mesh.startInterface(serial_interface);
|
2025-04-21 21:17:03 +01:00
|
|
|
#elif defined(RP2040_PLATFORM)
|
|
|
|
|
LittleFS.begin();
|
2025-06-06 15:30:35 +10:00
|
|
|
store.begin();
|
|
|
|
|
the_mesh.begin(
|
2025-05-19 14:16:55 +10:00
|
|
|
#ifdef DISPLAY_CLASS
|
2025-04-21 21:17:03 +01:00
|
|
|
disp != NULL
|
|
|
|
|
#else
|
|
|
|
|
false
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
//#ifdef WIFI_SSID
|
|
|
|
|
// WiFi.begin(WIFI_SSID, WIFI_PWD);
|
|
|
|
|
// serial_interface.begin(TCP_PORT);
|
|
|
|
|
// #elif defined(BLE_PIN_CODE)
|
|
|
|
|
// char dev_name[32+16];
|
|
|
|
|
// sprintf(dev_name, "%s%s", BLE_NAME_PREFIX, the_mesh.getNodeName());
|
|
|
|
|
// serial_interface.begin(dev_name, the_mesh.getBLEPin());
|
|
|
|
|
#if defined(SERIAL_RX)
|
|
|
|
|
companion_serial.setPins(SERIAL_RX, SERIAL_TX);
|
|
|
|
|
companion_serial.begin(115200);
|
|
|
|
|
serial_interface.begin(companion_serial);
|
|
|
|
|
#else
|
|
|
|
|
serial_interface.begin(Serial);
|
|
|
|
|
#endif
|
|
|
|
|
the_mesh.startInterface(serial_interface);
|
2025-01-28 20:30:15 +11:00
|
|
|
#elif defined(ESP32)
|
|
|
|
|
SPIFFS.begin(true);
|
2025-06-06 15:30:35 +10:00
|
|
|
store.begin();
|
|
|
|
|
the_mesh.begin(
|
2025-05-19 14:16:55 +10:00
|
|
|
#ifdef DISPLAY_CLASS
|
2025-03-16 13:42:36 +11:00
|
|
|
disp != NULL
|
|
|
|
|
#else
|
|
|
|
|
false
|
|
|
|
|
#endif
|
|
|
|
|
);
|
2025-01-28 20:30:15 +11:00
|
|
|
|
2025-03-03 13:26:37 +01:00
|
|
|
#ifdef WIFI_SSID
|
2026-01-30 15:07:40 +11:00
|
|
|
board.setInhibitSleep(true); // prevent sleep when WiFi is active
|
2026-05-07 12:24:06 +02:00
|
|
|
WiFi.setAutoReconnect(true);
|
|
|
|
|
|
|
|
|
|
WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info){
|
|
|
|
|
if (event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) {
|
|
|
|
|
WIFI_DEBUG_PRINTLN("WiFi disconnected. Flagging for reconnect...");
|
|
|
|
|
wifi_needs_reconnect = true;
|
|
|
|
|
} else if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) {
|
|
|
|
|
WIFI_DEBUG_PRINTLN("WiFi connected successfully!");
|
|
|
|
|
wifi_needs_reconnect = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-03-03 13:26:37 +01:00
|
|
|
WiFi.begin(WIFI_SSID, WIFI_PWD);
|
|
|
|
|
serial_interface.begin(TCP_PORT);
|
|
|
|
|
#elif defined(BLE_PIN_CODE)
|
2026-01-23 15:53:58 +11:00
|
|
|
serial_interface.begin(BLE_NAME_PREFIX, the_mesh.getNodePrefs()->node_name, the_mesh.getBLEPin());
|
2025-04-01 11:32:04 +02:00
|
|
|
#elif defined(SERIAL_RX)
|
|
|
|
|
companion_serial.setPins(SERIAL_RX, SERIAL_TX);
|
|
|
|
|
companion_serial.begin(115200);
|
|
|
|
|
serial_interface.begin(companion_serial);
|
2025-01-28 23:26:55 +11:00
|
|
|
#else
|
|
|
|
|
serial_interface.begin(Serial);
|
|
|
|
|
#endif
|
2025-02-14 10:46:40 +11:00
|
|
|
the_mesh.startInterface(serial_interface);
|
2025-01-28 20:30:15 +11:00
|
|
|
#else
|
|
|
|
|
#error "need to define filesystem"
|
|
|
|
|
#endif
|
2025-03-04 23:09:43 +11:00
|
|
|
|
2026-05-10 18:23:25 +02:00
|
|
|
store.restoreRTCTime();
|
2025-05-03 13:14:03 +10:00
|
|
|
sensors.begin();
|
|
|
|
|
|
2026-03-13 15:12:59 -05:00
|
|
|
#if ENV_INCLUDE_GPS == 1
|
|
|
|
|
the_mesh.applyGpsPrefs();
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-05-19 14:16:55 +10:00
|
|
|
#ifdef DISPLAY_CLASS
|
2026-05-16 23:15:29 +02:00
|
|
|
// Apply saved brightness as soon as prefs are available so the tail of
|
|
|
|
|
// the loading screen is not stuck at full brightness.
|
|
|
|
|
if (disp && the_mesh.getNodePrefs())
|
|
|
|
|
disp->setBrightness(the_mesh.getNodePrefs()->display_brightness);
|
2025-06-19 17:26:58 +02:00
|
|
|
ui_task.begin(disp, &sensors, the_mesh.getNodePrefs()); // still want to pass this in as dependency, as prefs might be moved
|
2025-03-04 23:09:43 +11:00
|
|
|
#endif
|
2026-05-10 18:45:35 +02:00
|
|
|
|
|
|
|
|
#ifdef NRF52_PLATFORM
|
|
|
|
|
NRF_WDT->CONFIG = 0x01; // run during sleep; pause during debug halt
|
|
|
|
|
NRF_WDT->CRV = 32768*30-1; // 30 second timeout
|
|
|
|
|
NRF_WDT->RREN = 0x01; // enable reload register 0
|
|
|
|
|
NRF_WDT->TASKS_START = 1;
|
|
|
|
|
#endif
|
2026-05-25 09:50:28 -04:00
|
|
|
board.onBootComplete();
|
2025-01-28 20:30:15 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void loop() {
|
2026-05-10 18:45:35 +02:00
|
|
|
#ifdef NRF52_PLATFORM
|
|
|
|
|
NRF_WDT->RR[0] = 0x6E524635UL; // pet watchdog
|
|
|
|
|
#endif
|
2025-01-28 20:30:15 +11:00
|
|
|
the_mesh.loop();
|
2025-05-03 13:14:03 +10:00
|
|
|
sensors.loop();
|
2025-06-21 20:48:28 +10:00
|
|
|
#ifdef DISPLAY_CLASS
|
|
|
|
|
ui_task.loop();
|
|
|
|
|
#endif
|
2025-10-30 16:45:50 +11:00
|
|
|
rtc_clock.tick();
|
2026-05-07 12:24:06 +02:00
|
|
|
|
Merge upstream/main (v1.16.0) into wio-unified
Merge 254 upstream commits. Highlights relevant to the Wio fork: native
NRF52 companion power-saving (sleep when !hasPendingWork), preamble 16->32
for SF<9, generic sensor-registration model, CMD_SEND_RAW_PACKET, isEink()
display abstraction, KEEP_DISPLAY_ON_USB, contacts-sync/transient fixes.
Conflicts resolved (11 files):
- buzzer.h/.cpp: keep NRF52 include guard + our begin()->startup(); fold in
upstream doc comment.
- platformio (wio + eink): keep our slim env layout, add upstream kiss_modem
env (+ debug_tool=stlink on eink ble).
- GxEPDDisplay.h: take upstream isEink() override.
- EnvironmentSensorManager.h: take upstream's wider #if guard.
- DataStore.cpp: take upstream saveContacts(filter) signature, keep our
::openWrite (member openWrite would shadow the global 2-arg overload).
- main.cpp: keep our watchdog init + add board.onBootComplete(); adopt
upstream's `if(!hasPendingWork()) sleep` loop.
- MyMesh.h: version -> v1.16-solo.0, build date 6 Jun 2026.
- MyMesh.cpp: keep both CMD codes (SCREENSHOT 66 + RAW_PACKET 65), both field
inits, both handlers, our screenshot fns + upstream saveContacts/save_filter,
upstream hasPendingWork() + our MyMeshBot include.
- UITask.cpp: keep our solo splash/clock page/snprintf/buzzer init; merge
auto-off (+ opt-in KEEP_DISPLAY_ON_USB); merge low-batt shutdown (our EMA +
prefs threshold + upstream's !isExternalPowered() guard and eink-aware delay).
Post-merge drift fixes (upstream API/architecture changes, not conflicts):
- applyTxPower(): radio_set_tx_power() removed upstream -> radio_driver.setTxPower().
- Sensor refactor dropped the per-sensor *_initialized flags our
getAvailableLPPTypes() relied on; removed that override and the SENSORS page
now derives available LPP types from the populated sensors_lpp buffer.
README kept ours via .gitattributes merge=ours. Builds verified on all 5 Wio
envs (dual, eink dual, radio_ble, dual_dev, eink_dual_dev). Not yet
hardware-verified.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 17:21:41 +02:00
|
|
|
// CPU sleeps until next interrupt (radio, timer, BLE) — but only when the
|
|
|
|
|
// mesh has no pending work, so queued TX/processing isn't delayed.
|
2026-04-10 10:45:26 +07:00
|
|
|
if (!the_mesh.hasPendingWork()) {
|
|
|
|
|
#if defined(NRF52_PLATFORM)
|
|
|
|
|
board.sleep(0); // nrf ignores seconds param, sleeps whenever possible
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-07 12:24:06 +02:00
|
|
|
#if defined(ESP32) && defined(WIFI_SSID)
|
|
|
|
|
// Safely attempt to reconnect every 10 seconds if flagged
|
|
|
|
|
if (wifi_needs_reconnect && (millis() - last_wifi_reconnect_attempt > 10000)) {
|
2026-04-10 10:45:26 +07:00
|
|
|
WIFI_DEBUG_PRINTLN("Attempting manual WiFi reconnect...");
|
|
|
|
|
WiFi.disconnect();
|
|
|
|
|
WiFi.reconnect();
|
|
|
|
|
last_wifi_reconnect_attempt = millis();
|
2026-05-07 12:24:06 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
2025-01-28 20:30:15 +11:00
|
|
|
}
|