diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp
index f215be80f..371a93c11 100644
--- a/src/FSCommon.cpp
+++ b/src/FSCommon.cpp
@@ -23,11 +23,16 @@ SPIClass SPI_HSPI(HSPI);
#else
#define SDHandler SPI
#endif
-
+#elif defined(ARCH_NRF52)
+#if defined(SDCARD_USE_SPI1)
+#define SDHandler SPI1
+#elif defined(SDCARD_USE_SPI)
+#define SDHandler SPI
+#endif // NRF52 SPI or SPI1
+#endif // ESP32/NRF52
#ifndef SD_SPI_FREQUENCY
#define SD_SPI_FREQUENCY 4000000U
#endif
-
#endif // HAS_SDCARD
/**
@@ -309,7 +314,13 @@ void setupSDCard()
{
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
concurrency::LockGuard g(spiLock);
+#if (defined(ARCH_ESP32) || defined(ARCH_NRF52))
+#if (defined(ARCH_ESP32))
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
+#elif (defined(ARCH_NRF52))
+ SDHandler.begin();
+#endif
+
if (!SD.begin(SDCARD_CS, SDHandler, SD_SPI_FREQUENCY)) {
LOG_DEBUG("No SD_MMC card detected");
return;
@@ -319,20 +330,23 @@ void setupSDCard()
LOG_DEBUG("No SD_MMC card attached");
return;
}
- LOG_DEBUG("SD_MMC Card Type: ");
if (cardType == CARD_MMC) {
- LOG_DEBUG("MMC");
+ LOG_DEBUG("SD_MMC Card Type: MMC");
} else if (cardType == CARD_SD) {
- LOG_DEBUG("SDSC");
+ LOG_DEBUG("SD_MMC Card Type: SDSC");
} else if (cardType == CARD_SDHC) {
- LOG_DEBUG("SDHC");
+ LOG_DEBUG("SD_MMC Card Type: SDHC");
} else {
- LOG_DEBUG("UNKNOWN");
+ LOG_DEBUG("SD_MMC Card Type: UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
LOG_DEBUG("SD Card Size: %lu MB", (uint32_t)cardSize);
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
- LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
+ LOG_INFO("Now scanning free clusters on SD card, this may take some time...");
+ delay(100); // let serial print the above statement properly
+ LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024))); // This might take some time during boot
+
+#endif
#endif
}
\ No newline at end of file
diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index b9c9e2fbf..44dedefb1 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -62,6 +62,9 @@ along with this program. If not, see .
#include "modules/ExternalNotificationModule.h"
#include "modules/TextMessageModule.h"
#include "modules/WaypointModule.h"
+#if !MESHTASTIC_EXCLUDE_STOREFORWARD
+#include "modules/StoreForwardModule.h"
+#endif
#include "sleep.h"
#include "target_specific.h"
@@ -76,10 +79,13 @@ extern uint16_t TFT_MESH;
#endif
#ifdef ARCH_ESP32
+<<<<<<< store-and-forward
+#include "esp_task_wdt.h"
+=======
+>>>>>>> master
#endif
#if ARCH_PORTDUINO
-#include "modules/StoreForwardModule.h"
#include "platform/portduino/PortduinoGlue.h"
#endif
@@ -1227,6 +1233,327 @@ void Screen::setFastFramerate()
runASAP = true;
}
+<<<<<<< store-and-forward
+void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
+{
+ display->setFont(FONT_SMALL);
+
+ // The coordinates define the left starting point of the text
+ display->setTextAlignment(TEXT_ALIGN_LEFT);
+
+ if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
+ display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
+ display->setColor(BLACK);
+ }
+
+ char channelStr[20];
+ {
+ concurrency::LockGuard guard(&lock);
+ snprintf(channelStr, sizeof(channelStr), "#%s", channels.getName(channels.getPrimaryIndex()));
+ }
+
+ // Display power status
+ if (powerStatus->getHasBattery()) {
+ if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
+ drawBattery(display, x, y + 2, imgBattery, powerStatus);
+ } else {
+ drawBattery(display, x + 1, y + 3, imgBattery, powerStatus);
+ }
+ } else if (powerStatus->knowsUSB()) {
+ if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
+ display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
+ } else {
+ display->drawFastImage(x + 1, y + 3, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
+ }
+ }
+ // Display nodes status
+ if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
+ drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus);
+ } else {
+ drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus);
+ }
+#if HAS_GPS
+ // Display GPS status
+ if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
+ drawGPSpowerstat(display, x, y + 2, gpsStatus);
+ } else {
+ if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
+ drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus);
+ } else {
+ drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 3, gpsStatus);
+ }
+ }
+#endif
+ display->setColor(WHITE);
+ // Draw the channel name
+ display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
+#if !MESHTASTIC_EXCLUDE_STOREFORWARD
+ // Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
+ if (moduleConfig.store_forward.enabled) {
+ if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat,
+ (storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit
+#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
+ defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
+ !defined(DISPLAY_FORCE_SMALL_FONTS)
+ display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
+ imgQuestionL1);
+ display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
+ imgQuestionL2);
+#else
+ display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8,
+ imgQuestion);
+#endif
+ } else {
+#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
+ defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \
+ !defined(DISPLAY_FORCE_SMALL_FONTS)
+ display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
+ imgSFL1);
+ display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8,
+ imgSFL2);
+#else
+ display->drawFastImage(x + SCREEN_WIDTH - 13 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 11, 8,
+ imgSF);
+#endif
+ }
+#else
+ // No store and forward, show a exclamation mark
+ if (false) {
+#endif
+ } else {
+ // TODO: Raspberry Pi supports more than just the one screen size
+#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
+ defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
+ !defined(DISPLAY_FORCE_SMALL_FONTS)
+ display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
+ imgInfoL1);
+ display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
+ imgInfoL2);
+#else
+ display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
+#endif
+ }
+
+ display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId);
+
+ // Draw any log messages
+ display->drawLogBuffer(x, y + (FONT_HEIGHT_SMALL * 2));
+
+ /* Display a heartbeat pixel that blinks every time the frame is redrawn */
+#ifdef SHOW_REDRAWS
+ if (heartbeat)
+ display->setPixel(0, 0);
+ heartbeat = !heartbeat;
+#endif
+}
+
+// Jm
+void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
+{
+#if HAS_WIFI && !defined(ARCH_PORTDUINO)
+ const char *wifiName = config.network.wifi_ssid;
+
+ display->setFont(FONT_SMALL);
+
+ // The coordinates define the left starting point of the text
+ display->setTextAlignment(TEXT_ALIGN_LEFT);
+
+ if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
+ display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
+ display->setColor(BLACK);
+ }
+
+ if (WiFi.status() != WL_CONNECTED) {
+ display->drawString(x, y, String("WiFi: Not Connected"));
+ if (config.display.heading_bold)
+ display->drawString(x + 1, y, String("WiFi: Not Connected"));
+ } else {
+ display->drawString(x, y, String("WiFi: Connected"));
+ if (config.display.heading_bold)
+ display->drawString(x + 1, y, String("WiFi: Connected"));
+
+ display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())), y,
+ "RSSI " + String(WiFi.RSSI()));
+ if (config.display.heading_bold) {
+ display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())) - 1, y,
+ "RSSI " + String(WiFi.RSSI()));
+ }
+ }
+
+ display->setColor(WHITE);
+
+ /*
+ - WL_CONNECTED: assigned when connected to a WiFi network;
+ - WL_NO_SSID_AVAIL: assigned when no SSID are available;
+ - WL_CONNECT_FAILED: assigned when the connection fails for all the attempts;
+ - WL_CONNECTION_LOST: assigned when the connection is lost;
+ - WL_DISCONNECTED: assigned when disconnected from a network;
+ - WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and remains active until the number of
+ attempts expires (resulting in WL_CONNECT_FAILED) or a connection is established (resulting in WL_CONNECTED);
+ - WL_SCAN_COMPLETED: assigned when the scan networks is completed;
+ - WL_NO_SHIELD: assigned when no WiFi shield is present;
+
+ */
+ if (WiFi.status() == WL_CONNECTED) {
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.localIP().toString().c_str()));
+ } else if (WiFi.status() == WL_NO_SSID_AVAIL) {
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "SSID Not Found");
+ } else if (WiFi.status() == WL_CONNECTION_LOST) {
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Lost");
+ } else if (WiFi.status() == WL_CONNECT_FAILED) {
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
+ } else if (WiFi.status() == WL_IDLE_STATUS) {
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting");
+ }
+#ifdef ARCH_ESP32
+ else {
+ // Codes:
+ // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1,
+ WiFi.disconnectReasonName(static_cast(getWifiDisconnectReason())));
+ }
+#else
+ else {
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Unkown status: " + String(WiFi.status()));
+ }
+#endif
+
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
+
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 3, "http://meshtastic.local");
+
+ /* Display a heartbeat pixel that blinks every time the frame is redrawn */
+#ifdef SHOW_REDRAWS
+ if (heartbeat)
+ display->setPixel(0, 0);
+ heartbeat = !heartbeat;
+#endif
+#endif
+}
+
+void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
+{
+ display->setFont(FONT_SMALL);
+
+ // The coordinates define the left starting point of the text
+ display->setTextAlignment(TEXT_ALIGN_LEFT);
+
+ if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
+ display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
+ display->setColor(BLACK);
+ }
+
+ char batStr[20];
+ if (powerStatus->getHasBattery()) {
+ int batV = powerStatus->getBatteryVoltageMv() / 1000;
+ int batCv = (powerStatus->getBatteryVoltageMv() % 1000) / 10;
+
+ snprintf(batStr, sizeof(batStr), "B %01d.%02dV %3d%% %c%c", batV, batCv, powerStatus->getBatteryChargePercent(),
+ powerStatus->getIsCharging() ? '+' : ' ', powerStatus->getHasUSB() ? 'U' : ' ');
+
+ // Line 1
+ display->drawString(x, y, batStr);
+ if (config.display.heading_bold)
+ display->drawString(x + 1, y, batStr);
+ } else {
+ // Line 1
+ display->drawString(x, y, String("USB"));
+ if (config.display.heading_bold)
+ display->drawString(x + 1, y, String("USB"));
+ }
+
+ // auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, true);
+
+ // display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
+ // if (config.display.heading_bold)
+ // display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode) - 1, y, mode);
+
+ uint32_t currentMillis = millis();
+ uint32_t seconds = currentMillis / 1000;
+ uint32_t minutes = seconds / 60;
+ uint32_t hours = minutes / 60;
+ uint32_t days = hours / 24;
+ // currentMillis %= 1000;
+ // seconds %= 60;
+ // minutes %= 60;
+ // hours %= 24;
+
+ // Show uptime as days, hours, minutes OR seconds
+ std::string uptime = screen->drawTimeDelta(days, hours, minutes, seconds);
+
+ // Line 1 (Still)
+ display->drawString(x + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
+ if (config.display.heading_bold)
+ display->drawString(x - 1 + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
+
+ display->setColor(WHITE);
+
+ // Setup string to assemble analogClock string
+ std::string analogClock = "";
+
+ uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone
+ if (rtc_sec > 0) {
+ long hms = rtc_sec % SEC_PER_DAY;
+ // hms += tz.tz_dsttime * SEC_PER_HOUR;
+ // hms -= tz.tz_minuteswest * SEC_PER_MIN;
+ // mod `hms` to ensure in positive range of [0...SEC_PER_DAY)
+ hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;
+
+ // Tear apart hms into h:m:s
+ int hour = hms / SEC_PER_HOUR;
+ int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
+ int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
+
+ char timebuf[12];
+
+ if (config.display.use_12h_clock) {
+ std::string meridiem = "am";
+ if (hour >= 12) {
+ if (hour > 12)
+ hour -= 12;
+ meridiem = "pm";
+ }
+ if (hour == 00) {
+ hour = 12;
+ }
+ snprintf(timebuf, sizeof(timebuf), "%d:%02d:%02d%s", hour, min, sec, meridiem.c_str());
+ } else {
+ snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d", hour, min, sec);
+ }
+ analogClock += timebuf;
+ }
+
+ // Line 2
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1, analogClock.c_str());
+
+ // Display Channel Utilization
+ char chUtil[13];
+ snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
+ display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
+
+#if HAS_GPS
+ if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
+ // Line 3
+ if (config.display.gps_format !=
+ meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude
+ drawGPSAltitude(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
+
+ // Line 4
+ drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus);
+ } else {
+ drawGPSpowerstat(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
+ }
+#endif
+/* Display a heartbeat pixel that blinks every time the frame is redrawn */
+#ifdef SHOW_REDRAWS
+ if (heartbeat)
+ display->setPixel(0, 0);
+ heartbeat = !heartbeat;
+#endif
+}
+
+=======
+>>>>>>> master
int Screen::handleStatusUpdate(const meshtastic::Status *arg)
{
// LOG_DEBUG("Screen got status update %d", arg->getStatusType());
diff --git a/src/main.cpp b/src/main.cpp
index c37001307..a114682f7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -686,6 +686,8 @@ void setup()
i2cScanner.reset();
#endif
+ // initSPI() must have called at this point (must be before screen and lora)
+
#ifdef HAS_SDCARD
setupSDCard();
#endif
@@ -778,7 +780,6 @@ void setup()
drv.setMode(DRV2605_MODE_INTTRIG);
#endif
- // Init our SPI controller (must be before screen and lora)
#ifdef ARCH_RP2040
#ifdef HW_SPI1_DEVICE
SPI1.setSCK(LORA_SCK);
diff --git a/src/memGet.cpp b/src/memGet.cpp
index e8cd177dd..a54b45d49 100644
--- a/src/memGet.cpp
+++ b/src/memGet.cpp
@@ -67,6 +67,8 @@ uint32_t MemGet::getFreePsram()
{
#ifdef ARCH_ESP32
return ESP.getFreePsram();
+#elif (defined(HAS_SDCARD) && defined(ARCH_ESP32))
+ return SD.totalBytes() - SD.usedBytes();
#elif defined(ARCH_PORTDUINO)
return 4194252;
#else
@@ -83,6 +85,8 @@ uint32_t MemGet::getPsramSize()
{
#ifdef ARCH_ESP32
return ESP.getPsramSize();
+#elif (defined(HAS_SDCARD) && defined(ARCH_ESP32))
+ return SD.totalBytes();
#elif defined(ARCH_PORTDUINO)
return 4194252;
#else
diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp
index 297c7b2ed..7aaab9f3c 100644
--- a/src/mesh/MeshService.cpp
+++ b/src/mesh/MeshService.cpp
@@ -283,7 +283,6 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
{
perhapsDecode(p);
-#ifdef ARCH_ESP32
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
if (moduleConfig.store_forward.enabled && storeForwardModule->isServer() &&
p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP) {
@@ -291,7 +290,6 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
fromNum++; // Notify observers for packet from radio
return;
}
-#endif
#endif
if (toPhoneQueue.numFree() == 0) {
diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h
index e2e430c03..e0e9c22b9 100644
--- a/src/mesh/MeshService.h
+++ b/src/mesh/MeshService.h
@@ -13,11 +13,9 @@
#if defined(ARCH_PORTDUINO)
#include "../platform/portduino/SimRadio.h"
#endif
-#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
#include "modules/StoreForwardModule.h"
#endif
-#endif
extern Allocator &queueStatusPool;
extern Allocator &mqttClientProxyMessagePool;
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 185ea0744..f5126d4b9 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -22,6 +22,9 @@
#include "mesh-pb-constants.h"
#include "meshUtils.h"
#include "modules/NeighborInfoModule.h"
+// #if !MESHTASTIC_EXCLUDE_STOREFORWARD
+// #include "modules/StoreForwardModule.h"
+// #endif
#include
#include
#include
@@ -32,8 +35,6 @@
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
-#include "SPILock.h"
-#include "modules/StoreForwardModule.h"
#include
#include
#include
@@ -42,8 +43,10 @@
#include
#endif
-#ifdef ARCH_PORTDUINO
+#include "SPILock.h"
#include "modules/StoreForwardModule.h"
+
+#ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp
index 97f21fc34..57eac10af 100644
--- a/src/mesh/RF95Interface.cpp
+++ b/src/mesh/RF95Interface.cpp
@@ -185,7 +185,7 @@ bool RF95Interface::init()
#endif
if (res == RADIOLIB_ERR_NONE)
- res = lora->setCRC(RADIOLIB_SX126X_LORA_CRC_ON);
+ res = lora->setCRC(true);
if (res == RADIOLIB_ERR_NONE)
startReceive(); // start receiving
diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp
index 3528f57f5..18a4170c0 100644
--- a/src/modules/Modules.cpp
+++ b/src/modules/Modules.cpp
@@ -75,7 +75,6 @@
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
#include "modules/GenericThreadModule.h"
#endif
-
#ifdef ARCH_ESP32
#if defined(USE_SX1280) && !MESHTASTIC_EXCLUDE_AUDIO
#include "modules/esp32/AudioModule.h"
@@ -83,9 +82,6 @@
#if !MESHTASTIC_EXCLUDE_PAXCOUNTER
#include "modules/esp32/PaxcounterModule.h"
#endif
-#if !MESHTASTIC_EXCLUDE_STOREFORWARD
-#include "modules/StoreForwardModule.h"
-#endif
#endif
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
@@ -253,7 +249,7 @@ void setupModules()
paxcounterModule = new PaxcounterModule();
#endif
#endif
-#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
+#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) || defined(HAS_SDCARD)
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
storeForwardModule = new StoreForwardModule();
#endif
diff --git a/src/modules/StoreForwardModule.cpp b/src/modules/StoreForwardModule.cpp
index 0a6e1b4c4..994d08cfc 100644
--- a/src/modules/StoreForwardModule.cpp
+++ b/src/modules/StoreForwardModule.cpp
@@ -32,7 +32,7 @@ StoreForwardModule *storeForwardModule;
int32_t StoreForwardModule::runOnce()
{
-#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
+#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) || defined(HAS_SDCARD)
if (moduleConfig.store_forward.enabled && is_server) {
// Send out the message queue.
if (this->busy) {
@@ -89,6 +89,32 @@ void StoreForwardModule::populatePSRAM()
LOG_DEBUG("After PSRAM init: heap %d/%d PSRAM %d/%d", memGet.getFreeHeap(), memGet.getHeapSize(), memGet.getFreePsram(),
memGet.getPsramSize());
LOG_DEBUG("numberOfPackets for packetHistory - %u", numberOfPackets);
+ this->storageType = StorageType::ST_PSRAM;
+}
+
+/**
+ * if we have an SDCARD, format it for store&forward use
+ */
+void StoreForwardModule::populateSDCard()
+{
+#if defined(HAS_SDCARD)
+#if (defined(ARCH_ESP32) || defined(ARCH_NRF52))
+ spiLock->lock();
+ if (SD.cardType() != CARD_NONE) {
+ if (!SD.exists("/storeforward")) {
+ LOG_INFO("Creating StoreForward directory");
+ SD.mkdir("/storeforward");
+ }
+ this->storageType = StorageType::ST_SDCARD;
+ uint32_t numberOfPackets = (this->records ? this->records : (((SD.totalBytes() / 3) * 2) / sizeof(PacketHistoryStruct)));
+ this->records = numberOfPackets;
+ // only allocate space for one temp copy
+ this->packetHistory = (PacketHistoryStruct *)malloc(sizeof(PacketHistoryStruct));
+ LOG_DEBUG("numberOfPackets for packetHistory - %u", numberOfPackets);
+ }
+ spiLock->unlock();
+#endif // ARCH_ESP32 || ARCH_NRF52
+#endif // HAS_SDCARD
}
/**
@@ -135,14 +161,42 @@ uint32_t StoreForwardModule::getNumAvailablePackets(NodeNum dest, uint32_t last_
lastRequest.emplace(dest, 0);
}
for (uint32_t i = lastRequest[dest]; i < this->packetHistoryTotalCount; i++) {
- if (this->packetHistory[i].time && (this->packetHistory[i].time > last_time)) {
- // Client is only interested in packets not from itself and only in broadcast packets or packets towards it.
- if (this->packetHistory[i].from != dest &&
- (this->packetHistory[i].to == NODENUM_BROADCAST || this->packetHistory[i].to == dest)) {
- count++;
+ if (this->storageType == StorageType::ST_PSRAM) {
+ if (this->packetHistory[i].time && (this->packetHistory[i].time > last_time)) {
+ // Client is only interested in packets not from itself and only in broadcast packets or packets towards it.
+ if (this->packetHistory[i].from != dest &&
+ (this->packetHistory[i].to == NODENUM_BROADCAST || this->packetHistory[i].to == dest)) {
+ count++;
+ }
}
+ } else if (this->storageType == StorageType::ST_SDCARD) {
+#if defined(HAS_SDCARD)
+#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
+ spiLock->lock();
+ auto handler = SD.open("/storeforward/" + String(i), FILE_READ);
+ if (handler) {
+ if (handler.read((uint8_t *)&this->packetHistory[0], sizeof(PacketHistoryStruct)) !=
+ sizeof(PacketHistoryStruct)) {
+ LOG_ERROR("SD card reading error");
+ }
+ handler.close();
+ if (this->packetHistory[0].time && (this->packetHistory[0].time > last_time)) {
+
+ // Client is only interested in packets not from itself and only in broadcast packets or packets towards it.
+ if (this->packetHistory[0].from != dest &&
+ (this->packetHistory[0].to == NODENUM_BROADCAST || this->packetHistory[0].to == dest)) {
+ count++;
+ }
+ }
+ }
+ spiLock->unlock();
+#endif
+#endif
+ } else {
+ LOG_ERROR("S&F: Unknown storage type");
}
}
+
return count;
}
@@ -187,23 +241,47 @@ void StoreForwardModule::historyAdd(const meshtastic_MeshPacket &mp)
const auto &p = mp.decoded;
if (this->packetHistoryTotalCount == this->records) {
- LOG_WARN("S&F - PSRAM Full. Starting overwrite");
+ LOG_WARN("S&F - Storage Full. Starting overwrite");
this->packetHistoryTotalCount = 0;
for (auto &i : lastRequest) {
i.second = 0; // Clear the last request index for each client device
}
}
- this->packetHistory[this->packetHistoryTotalCount].time = getTime();
- this->packetHistory[this->packetHistoryTotalCount].to = mp.to;
- this->packetHistory[this->packetHistoryTotalCount].channel = mp.channel;
- this->packetHistory[this->packetHistoryTotalCount].from = getFrom(&mp);
- this->packetHistory[this->packetHistoryTotalCount].id = mp.id;
- this->packetHistory[this->packetHistoryTotalCount].reply_id = p.reply_id;
- this->packetHistory[this->packetHistoryTotalCount].emoji = (bool)p.emoji;
- this->packetHistory[this->packetHistoryTotalCount].payload_size = p.payload.size;
- memcpy(this->packetHistory[this->packetHistoryTotalCount].payload, p.payload.bytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
-
+ if (this->storageType == StorageType::ST_PSRAM) {
+ this->packetHistory[this->packetHistoryTotalCount].time = getTime();
+ this->packetHistory[this->packetHistoryTotalCount].to = mp.to;
+ this->packetHistory[this->packetHistoryTotalCount].channel = mp.channel;
+ this->packetHistory[this->packetHistoryTotalCount].from = getFrom(&mp);
+ this->packetHistory[this->packetHistoryTotalCount].id = mp.id;
+ this->packetHistory[this->packetHistoryTotalCount].reply_id = p.reply_id;
+ this->packetHistory[this->packetHistoryTotalCount].emoji = (bool)p.emoji;
+ this->packetHistory[this->packetHistoryTotalCount].payload_size = p.payload.size;
+ memcpy(this->packetHistory[this->packetHistoryTotalCount].payload, p.payload.bytes,
+ meshtastic_Constants_DATA_PAYLOAD_LEN);
+ } else if (this->storageType == StorageType::ST_SDCARD) {
+// Save to SDCARD
+#if defined(HAS_SDCARD)
+#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
+ this->packetHistory[0].time = getTime();
+ this->packetHistory[0].to = mp.to;
+ this->packetHistory[0].channel = mp.channel;
+ this->packetHistory[0].from = getFrom(&mp);
+ this->packetHistory[0].id = mp.id;
+ this->packetHistory[0].reply_id = p.reply_id;
+ this->packetHistory[0].emoji = (bool)p.emoji;
+ this->packetHistory[0].payload_size = p.payload.size;
+ memcpy(this->packetHistory[0].payload, p.payload.bytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
+ spiLock->lock();
+ auto handler = SD.open("/storeforward/" + String(this->packetHistoryTotalCount), FILE_WRITE, true);
+ handler.write((uint8_t *)&this->packetHistory[0], sizeof(PacketHistoryStruct));
+ handler.close();
+ spiLock->unlock();
+#endif
+#endif
+ } else {
+ LOG_ERROR("S&F: Unknown storage type");
+ }
this->packetHistoryTotalCount++;
}
@@ -236,50 +314,108 @@ bool StoreForwardModule::sendPayload(NodeNum dest, uint32_t last_time)
meshtastic_MeshPacket *StoreForwardModule::preparePayload(NodeNum dest, uint32_t last_time, bool local)
{
for (uint32_t i = lastRequest[dest]; i < this->packetHistoryTotalCount; i++) {
- if (this->packetHistory[i].time && (this->packetHistory[i].time > last_time)) {
- /* Copy the messages that were received by the server in the last msAgo
- to the packetHistoryTXQueue structure.
- Client not interested in packets from itself and only in broadcast packets or packets towards it. */
- if (this->packetHistory[i].from != dest &&
- (this->packetHistory[i].to == NODENUM_BROADCAST || this->packetHistory[i].to == dest)) {
+ if (this->storageType == StorageType::ST_PSRAM) {
- meshtastic_MeshPacket *p = allocDataPacket();
+ if (this->packetHistory[i].time && (this->packetHistory[i].time > last_time)) {
+ /* Copy the messages that were received by the server in the last msAgo
+ to the packetHistoryTXQueue structure.
+ Client not interested in packets from itself and only in broadcast packets or packets towards it. */
+ if (this->packetHistory[i].from != dest &&
+ (this->packetHistory[i].to == NODENUM_BROADCAST || this->packetHistory[i].to == dest)) {
- p->to = local ? this->packetHistory[i].to : dest; // PhoneAPI can handle original `to`
- p->from = this->packetHistory[i].from;
- p->id = this->packetHistory[i].id;
- p->channel = this->packetHistory[i].channel;
- p->decoded.reply_id = this->packetHistory[i].reply_id;
- p->rx_time = this->packetHistory[i].time;
- p->decoded.emoji = (uint32_t)this->packetHistory[i].emoji;
+ meshtastic_MeshPacket *p = allocDataPacket();
- // Let's assume that if the server received the S&F request that the client is in range.
- // TODO: Make this configurable.
- p->want_ack = false;
+ p->to = local ? this->packetHistory[i].to : dest; // PhoneAPI can handle original `to`
+ p->from = this->packetHistory[i].from;
+ p->id = this->packetHistory[i].id;
+ p->channel = this->packetHistory[i].channel;
+ p->decoded.reply_id = this->packetHistory[i].reply_id;
+ p->rx_time = this->packetHistory[i].time;
+ p->decoded.emoji = (uint32_t)this->packetHistory[i].emoji;
+
+ // Let's assume that if the server received the S&F request that the client is in range.
+ // TODO: Make this configurable.
+ p->want_ack = false;
+
+ if (local) { // PhoneAPI gets normal TEXT_MESSAGE_APP
+ p->decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
+ memcpy(p->decoded.payload.bytes, this->packetHistory[i].payload, this->packetHistory[i].payload_size);
+ p->decoded.payload.size = this->packetHistory[i].payload_size;
- if (local) { // PhoneAPI gets normal TEXT_MESSAGE_APP
- p->decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
- memcpy(p->decoded.payload.bytes, this->packetHistory[i].payload, this->packetHistory[i].payload_size);
- p->decoded.payload.size = this->packetHistory[i].payload_size;
- } else {
- meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero;
- sf.which_variant = meshtastic_StoreAndForward_text_tag;
- sf.variant.text.size = this->packetHistory[i].payload_size;
- memcpy(sf.variant.text.bytes, this->packetHistory[i].payload, this->packetHistory[i].payload_size);
- if (this->packetHistory[i].to == NODENUM_BROADCAST) {
- sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_TEXT_BROADCAST;
} else {
- sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_TEXT_DIRECT;
+ meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero;
+ sf.which_variant = meshtastic_StoreAndForward_text_tag;
+ sf.variant.text.size = this->packetHistory[i].payload_size;
+ memcpy(sf.variant.text.bytes, this->packetHistory[i].payload, this->packetHistory[i].payload_size);
+ if (this->packetHistory[i].to == NODENUM_BROADCAST) {
+ sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_TEXT_BROADCAST;
+ } else {
+ sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_TEXT_DIRECT;
+ }
+
+ p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes),
+ &meshtastic_StoreAndForward_msg, &sf);
}
- p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes),
- &meshtastic_StoreAndForward_msg, &sf);
+ lastRequest[dest] = i + 1; // Update the last request index for the client device
+
+ return p;
}
-
- lastRequest[dest] = i + 1; // Update the last request index for the client device
-
- return p;
}
+ } else if (this->storageType == StorageType::ST_SDCARD) {
+#if defined(HAS_SDCARD)
+#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
+ spiLock->lock();
+ auto handler = SD.open("/storeforward/" + String(i), FILE_READ);
+ if (handler) {
+ handler.read((uint8_t *)&this->packetHistory[0], sizeof(PacketHistoryStruct));
+ handler.close();
+ spiLock->unlock();
+ if (this->packetHistory[0].time && (this->packetHistory[0].time > last_time)) {
+ if (this->packetHistory[0].from != dest &&
+ (this->packetHistory[0].to == NODENUM_BROADCAST || this->packetHistory[0].to == dest)) {
+
+ meshtastic_MeshPacket *p = allocDataPacket();
+
+ p->to = local ? this->packetHistory[0].to : dest; // PhoneAPI can handle original `to`
+ p->from = this->packetHistory[0].from;
+ p->channel = this->packetHistory[0].channel;
+ p->rx_time = this->packetHistory[0].time;
+
+ // Let's assume that if the server received the S&F request that the client is in range.
+ p->want_ack = false;
+
+ if (local) { // PhoneAPI gets normal TEXT_MESSAGE_APP
+ p->decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP;
+ memcpy(p->decoded.payload.bytes, this->packetHistory[0].payload, this->packetHistory[0].payload_size);
+ p->decoded.payload.size = this->packetHistory[0].payload_size;
+ } else {
+ meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero;
+ sf.which_variant = meshtastic_StoreAndForward_text_tag;
+ sf.variant.text.size = this->packetHistory[0].payload_size;
+ memcpy(sf.variant.text.bytes, this->packetHistory[0].payload, this->packetHistory[0].payload_size);
+ if (this->packetHistory[0].to == NODENUM_BROADCAST) {
+ sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_TEXT_BROADCAST;
+ } else {
+ sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_TEXT_DIRECT;
+ }
+
+ p->decoded.payload.size = pb_encode_to_bytes(
+ p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_StoreAndForward_msg, &sf);
+ }
+
+ lastRequest[dest] = i + 1; // Update the last request index for the client device
+
+ return p;
+ }
+ }
+ } else {
+ spiLock->unlock();
+ }
+#endif
+#endif
+ } else {
+ LOG_ERROR("S&F: Unknown storage type");
}
}
return nullptr;
@@ -383,7 +519,7 @@ void StoreForwardModule::statsSend(uint32_t to)
*/
ProcessMessage StoreForwardModule::handleReceived(const meshtastic_MeshPacket &mp)
{
-#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
+#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) || defined(HAS_SDCARD)
if (moduleConfig.store_forward.enabled) {
if ((mp.decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP) && is_server) {
@@ -562,7 +698,7 @@ StoreForwardModule::StoreForwardModule()
ProtobufModule("StoreForward", meshtastic_PortNum_STORE_FORWARD_APP, &meshtastic_StoreAndForward_msg)
{
-#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
+#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) || defined(HAS_SDCARD)
isPromiscuous = true; // Brown chicken brown cow
@@ -613,7 +749,14 @@ StoreForwardModule::StoreForwardModule()
} else {
LOG_INFO("S&F: device doesn't have PSRAM, Disable");
}
-
+#ifdef HAS_SDCARD
+ // If we have an SDCARD, format it for store&forward use
+ if (SD.cardType() != CARD_NONE) {
+ this->populateSDCard();
+ LOG_INFO("S&F: SDCARD initialized");
+ is_server = true;
+ }
+#endif
// Client
} else {
is_client = true;
diff --git a/src/modules/StoreForwardModule.h b/src/modules/StoreForwardModule.h
index 30db1625c..1e65c1cb0 100644
--- a/src/modules/StoreForwardModule.h
+++ b/src/modules/StoreForwardModule.h
@@ -9,6 +9,11 @@
#include
#include
+#ifdef HAS_SDCARD
+#include "SPILock.h"
+#include
+#endif
+
struct PacketHistoryStruct {
uint32_t time;
uint32_t to;
@@ -21,6 +26,9 @@ struct PacketHistoryStruct {
pb_size_t payload_size;
};
+// enum for the storage type
+enum StorageType { ST_PSRAM, ST_SDCARD };
+
class StoreForwardModule : private concurrency::OSThread, public ProtobufModule
{
bool busy = 0;
@@ -83,6 +91,10 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule<
private:
void populatePSRAM();
+ void populateSDCard();
+
+ // Storage Type
+ StorageType storageType = ST_PSRAM;
// S&F Defaults
uint32_t historyReturnMax = 25; // Return maximum of 25 records by default.
diff --git a/src/xmodem.h b/src/xmodem.h
index 4cfcb43e1..1e7b7a94f 100644
--- a/src/xmodem.h
+++ b/src/xmodem.h
@@ -61,7 +61,9 @@ class XModemAdapter
uint16_t packetno = 0;
-#if defined(ARCH_NRF52) || defined(ARCH_STM32WL)
+#if defined(ARCH_NRF52)
+ Adafruit_LittleFS_Namespace::File file = Adafruit_LittleFS_Namespace::File(FSCom);
+#elif defined(ARCH_STM32WL)
File file = File(FSCom);
#else
File file;
diff --git a/variants/CDEBYTE_EoRa-S3/variant.h b/variants/CDEBYTE_EoRa-S3/variant.h
index 5da99667b..854996332 100644
--- a/variants/CDEBYTE_EoRa-S3/variant.h
+++ b/variants/CDEBYTE_EoRa-S3/variant.h
@@ -6,7 +6,7 @@
// SD card - TODO: test, currently untested, copied from T3S3 variant
#define HAS_SDCARD
-#define SDCARD_USE_SPI1
+#define SDCARD_USE_HSPI
// TODO: rename this to make this SD-card specific
#define SPI_CS 13
#define SPI_SCK 14
diff --git a/variants/bpi_picow_esp32_s3/variant.h b/variants/bpi_picow_esp32_s3/variant.h
index d8d9413d7..fc9064436 100644
--- a/variants/bpi_picow_esp32_s3/variant.h
+++ b/variants/bpi_picow_esp32_s3/variant.h
@@ -5,7 +5,7 @@
// #define HAS_SCREEN 0
// #define HAS_SDCARD
-// #define SDCARD_USE_SPI1
+// #define SDCARD_USE_HSPI
#define USE_SSD1306
#define I2C_SDA 12
diff --git a/variants/dreamcatcher/variant.h b/variants/dreamcatcher/variant.h
index 7835979e1..1e04a2b26 100644
--- a/variants/dreamcatcher/variant.h
+++ b/variants/dreamcatcher/variant.h
@@ -70,7 +70,7 @@
#endif
#define HAS_SDCARD // Have SPI interface SD card slot
-#define SDCARD_USE_SPI1
+#define SDCARD_USE_HSPI
#define LORA_RESET 3
#define LORA_SCK 12
diff --git a/variants/my_esp32s3_diy_eink/variant.h b/variants/my_esp32s3_diy_eink/variant.h
index 024f912dd..c60e2b0ce 100644
--- a/variants/my_esp32s3_diy_eink/variant.h
+++ b/variants/my_esp32s3_diy_eink/variant.h
@@ -4,7 +4,7 @@
// #define HAS_SCREEN 0
// #define HAS_SDCARD
-// #define SDCARD_USE_SPI1
+// #define SDCARD_USE_HSPI
// #define USE_SSD1306
diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini
index ee134e87a..bdb04ff71 100644
--- a/variants/rak4631/platformio.ini
+++ b/variants/rak4631/platformio.ini
@@ -20,6 +20,8 @@ lib_deps =
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2
beegee-tokyo/RAK12035_SoilMoisture@^1.0.4
https://github.com/RAKWireless/RAK12034-BMX160/archive/dcead07ffa267d3c906e9ca4a1330ab989e957e2.zip
+ https://github.com/Woutvstk/SdFat_wrapper25.git#6f8f48d56c15cbeac753560dfeede4a487f81f4c
+
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds
diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h
index f5ec11ef2..bf93fade2 100644
--- a/variants/rak4631/variant.h
+++ b/variants/rak4631/variant.h
@@ -113,11 +113,14 @@ static const uint8_t AREF = PIN_AREF;
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 2
+#define SPI_32MHZ_INTERFACE 0 // 0: use SPIM3 for SPI and SPIM2 for SPI1; 1: the opposite
+// SPI pins for SX1262
#define PIN_SPI_MISO (45)
#define PIN_SPI_MOSI (44)
#define PIN_SPI_SCK (43)
+// SPI1 pins for external(rak4630) spi (incl. SDCard)
#define PIN_SPI1_MISO (29) // (0 + 29)
#define PIN_SPI1_MOSI (30) // (0 + 30)
#define PIN_SPI1_SCK (3) // (0 + 3)
@@ -127,6 +130,19 @@ static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
+// SD card SPI pin definitions
+
+#define HAS_SDCARD 1
+#define SDCARD_USE_SPI1 1
+
+#define SDCARD_CS (26)
+
+// Some settings for the SdFat library to optimize flash usage
+#define SDFAT_FILE_TYPE 1 // only support FAT16/FAT32, not exFAT
+#define CHECK_FLASH_PROGRAMMING \
+ 0 // this reduces flash usage but may cause higher power usage when sd card is idle TODO:Check if power usage is higher
+#define MAINTAIN_FREE_CLUSTER_COUNT 1 // maintain free cluster count
+
/*
* eink display pins
*/
diff --git a/variants/tbeam-s3-core/variant.h b/variants/tbeam-s3-core/variant.h
index dabd52980..70323ab1e 100644
--- a/variants/tbeam-s3-core/variant.h
+++ b/variants/tbeam-s3-core/variant.h
@@ -56,7 +56,7 @@
#define GPS_1PPS_PIN 6
#define HAS_SDCARD // Have SPI interface SD card slot
-#define SDCARD_USE_SPI1
+#define SDCARD_USE_HSPI
// PCF8563 RTC Module
// #define PCF8563_RTC 0x51 //Putting definitions in variant. h does not compile correctly
diff --git a/variants/tlora_t3s3_epaper/variant.h b/variants/tlora_t3s3_epaper/variant.h
index 1ed505420..ca1edb0e8 100644
--- a/variants/tlora_t3s3_epaper/variant.h
+++ b/variants/tlora_t3s3_epaper/variant.h
@@ -1,5 +1,5 @@
#define HAS_SDCARD
-#define SDCARD_USE_SPI1
+#define SDCARD_USE_HSPI
// Display (E-Ink)
#define PIN_EINK_CS 15
diff --git a/variants/tlora_t3s3_v1/variant.h b/variants/tlora_t3s3_v1/variant.h
index babe44a58..63caaaf12 100644
--- a/variants/tlora_t3s3_v1/variant.h
+++ b/variants/tlora_t3s3_v1/variant.h
@@ -1,5 +1,5 @@
#define HAS_SDCARD
-#define SDCARD_USE_SPI1
+#define SDCARD_USE_HSPI
#define USE_SSD1306
@@ -76,4 +76,4 @@
#endif
#define HAS_SDCARD // Have SPI interface SD card slot
-#define SDCARD_USE_SPI1
\ No newline at end of file
+#define SDCARD_USE_HSPI
\ No newline at end of file
diff --git a/variants/tlora_v2_1_16/platformio.ini b/variants/tlora_v2_1_16/platformio.ini
index 4253cc6af..04828dca3 100644
--- a/variants/tlora_v2_1_16/platformio.ini
+++ b/variants/tlora_v2_1_16/platformio.ini
@@ -3,6 +3,11 @@ extends = esp32_base
board = ttgo-lora32-v21
board_check = true
build_flags =
- ${esp32_base.build_flags} -D TLORA_V2_1_16 -I variants/tlora_v2_1_16
+ ${esp32_base.build_flags}
+ -D TLORA_V2_1_16
+ -I variants/tlora_v2_1_16
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-upload_speed = 115200
\ No newline at end of file
+ -DRADIOLIB_EXCLUDE_SX128X=1
+ -DRADIOLIB_EXCLUDE_SX126X=1
+ -DRADIOLIB_EXCLUDE_LR11X0=1
+upload_speed = 115200
diff --git a/variants/tlora_v2_1_16/variant.h b/variants/tlora_v2_1_16/variant.h
index 48c069ab7..9607620ea 100644
--- a/variants/tlora_v2_1_16/variant.h
+++ b/variants/tlora_v2_1_16/variant.h
@@ -22,4 +22,15 @@
#define LORA_DIO1 33 // https://www.thethingsnetwork.org/forum/t/big-esp32-sx127x-topic-part-3/18436
#endif
-#define LORA_DIO2 32 // Not really used
\ No newline at end of file
+#define LORA_DIO2 32 // Not really used
+
+/*
+ * Use SD Card for Store and Forward
+ */
+#define HAS_SDCARD
+#define SDCARD_USE_HSPI
+#define SPI_MOSI 15
+#define SPI_MISO 2
+#define SPI_SCK 14
+#define SPI_CS 13
+#define SDCARD_CS SPI_CS
\ No newline at end of file
diff --git a/variants/unphone/variant.h b/variants/unphone/variant.h
index e186b5740..510fd86fd 100644
--- a/variants/unphone/variant.h
+++ b/variants/unphone/variant.h
@@ -51,6 +51,9 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
+// #define HAS_SDCARD 1 // causes hang if defined
+#define SDCARD_USE_HSPI
+
#define SD_SPI_FREQUENCY 25000000
#define SDCARD_CS 43