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