Compare commits

...

45 Commits

Author SHA1 Message Date
Thomas Göttgens
d657177f0e Merge branch 'master' into store-and-forward 2025-07-13 18:18:19 +02:00
Thomas Göttgens
d3fc155186 Merge branch 'master' into store-and-forward 2025-06-25 20:16:49 +02:00
Thomas Göttgens
3fb4ab35f1 Merge branch 'master' into store-and-forward 2025-05-24 22:06:23 +02:00
Woutvstk
6d8bedb027 Clean up unused macros and outdated comments (#6520)
* Updating comments and removing residue

* Some more unused macros
2025-04-08 08:27:47 -05:00
Ben Meadors
aca9ceebfa Merge branch 'master' into store-and-forward 2025-04-07 08:42:41 -05:00
Ben Meadors
9dee6030e4 Merge branch 'master' into store-and-forward 2025-04-07 08:33:52 -05:00
Thomas Göttgens
0d19f766e8 fix build errors 2025-04-07 13:00:28 +02:00
Thomas Göttgens
91986db1b0 Merge branch 'master' into store-and-forward 2025-04-07 09:27:53 +02:00
Thomas Göttgens
1e54d3bfc7 Merge branch 'master' into store-and-forward 2025-03-31 11:25:28 +02:00
Ben Meadors
b2401100de Merge branch 'master' into store-and-forward 2025-03-30 20:36:00 -05:00
Woutvstk
7e7792aa51 Changed SD library for nrf52 and got S&F working (#6382)
- Changed library from deprecated arduino SD library to wrapper of SdFat library
- Fixed some bugs in the S&F code for SD card storage
Now the S&F functionality works on nrf52 (tested on rak4631 with RAK15002)
2025-03-29 13:15:21 +01:00
Ben Meadors
d237d4f311 Merge branch 'master' into store-and-forward 2025-03-28 06:17:28 -05:00
Thomas Göttgens
9f2a3fd23b Merge pull request #6132 from Woutvstk/retry-fix-wrongly-removed-spi1-rak4631 2025-03-02 13:27:10 +01:00
Thomas Göttgens
61901c37bb Merge branch 'store-and-forward' into retry-fix-wrongly-removed-spi1-rak4631 2025-03-02 13:26:14 +01:00
Thomas Göttgens
64f8203abc Merge branch 'master' into store-and-forward 2025-03-02 12:05:49 +01:00
Woutvstk
f0ca0b947c trunk fmt 2025-02-25 16:04:59 +01:00
Woutvstk
db376532ad Add SPIM3/SPIM2 for SPI/SPI1 selection
The SPIM3 is faster (max 32Mhz) than SPIM2 (max 8Mhz)
Default is SPI_32MHZ_INTERFACE  0 in SPI library
2025-02-25 15:22:03 +01:00
Woutvstk
372b62aa35 remove second initSPI() (#6140) 2025-02-24 19:45:44 +08:00
Woutvstk
95fe4aed04 trunk fmt 2025-02-23 18:17:24 +01:00
Woutvstk
b19d358dcc redid the reorganisation of the SPI definitions 2025-02-23 17:23:35 +01:00
Woutvstk
4ec0134606 Revert "Rak4631 remove spi1 (#6042)"
This reverts commit 9b46cb4ef0.
2025-02-23 16:56:39 +01:00
Woutvstk
5aa4946e6f Revert "Reorganize spi definitions for use with sd cards ESP32/NRF52 (#6080)"
This reverts commit 443922b947.
2025-02-23 16:56:22 +01:00
Thomas Göttgens
e67b84ee06 Merge branch 'master' into store-and-forward 2025-02-19 13:22:11 +01:00
Woutvstk
443922b947 Reorganize spi definitions for use with sd cards ESP32/NRF52 (#6080)
Changed variant files of hardware that uses HAS_SDCARD.
Reorganised SPIClass definitions in FSCommon
2025-02-18 09:08:03 +01:00
Thomas Göttgens
35fc93752e Merge branch 'master' into store-and-forward 2025-02-17 15:57:31 +01:00
Woutvstk
a6aa84431c added quotes against linking issues in platformio.ini issue #5898 (#5966) 2025-01-31 07:08:57 -06:00
Thomas Göttgens
9ab50d5feb Merge branch 'master' into store-and-forward 2025-01-18 14:11:59 +01:00
Thomas Göttgens
45ff66e713 Merge branch 'master' into store-and-forward 2025-01-05 23:26:32 +01:00
Thomas Göttgens
f7feea63f7 Attempt to merge 2025-01-05 21:34:38 +01:00
Thomas Göttgens
7c08ff35f3 Merge branch 'master' into store-and-forward 2025-01-05 21:20:44 +01:00
Woutvstk
96277ed804 First attempt to adding hardware support for NRF52 SPI SD Card (#5561)
* First attempt to adding hardware support for NRF52 SPI SD Card using arduino SD library
My first time contributing to an open source project so not very confident in what i'm doing.

Changes to
FSCommon:
initializing SD library for NRF52. Progress: No compile error, but SD card does not get initialized properly yet
added ifdef ARCH_ESP32 conditions around esp32 SD library functions

memget: added ifdef conditional statements

StoreForwardModule.cpp: added ifdef conditional statements

Rak4631 platfromIO.ini and variant.h:
added arduino-libraries/SD@^1.3.0 library to libdeps
defined HAS_SDCARD and SPI pins

Arduino SD library. Made changes to library because using namespace SDLIB in header file caused ambiguity problems
Not sure this is the right way of adding a library, also, how do i implement changes to the library permanently to the project?

Am I going somewhat in the right direction with these changes? Tell me your thoughts, thanks

* replaced arduino SD library to custom fork.
A "using namespace" statement in the header file was to messy to work around.
NRF52 SD card initialisation added

* updated library reference
added card size and type function to SD library
added populateSDCard for NRF52

* Changed NRF52 SD object from SDFilesystem to SD

Changed NRF52 SD object from SDFilesystem to SD for more compatibility with esp32 SD library. Some functions are still different but most used open, read, write and close are the same.

* Removed duplicate ESP32/NRF52 SD card access code

Mainly made changes to the custom arduino SD library to make it compatible with the esp32 SD library already used in the store and forward code.
With these compatible function names and return, I removed some duplicate code.

* trunk fmt and pin SD library to commit hash

* print this out on ESP32 anyway

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2025-01-05 21:19:16 +01:00
Thomas Göttgens
37a03c2ef9 Merge branch 'master' into store-and-forward 2024-12-29 22:41:38 +01:00
Thomas Göttgens
ef602a7d81 Merge branch 'master' into store-and-forward 2024-12-12 16:40:27 +01:00
Thomas Göttgens
1f1d785ca5 Merge branch 'master' into store-and-forward 2024-12-09 13:53:33 +01:00
Thomas Göttgens
37da78aec2 Merge branch 'master' into store-and-forward 2024-11-24 15:52:25 +01:00
Thomas Göttgens
beb69e93d0 Merge branch 'master' into store-and-forward 2024-11-03 15:15:44 +01:00
Thomas Göttgens
5d25c304ad Merge branch 'master' into store-and-forward 2024-11-02 16:38:36 +01:00
Thomas Göttgens
fbe6a3c4d2 Merge branch 'master' into store-and-forward 2024-10-28 12:11:46 +01:00
Thomas Göttgens
91933c66f3 missed one. 2024-10-27 17:31:10 +01:00
Thomas Göttgens
a13a299b92 next one - fix compilation for Portduino 2024-10-26 14:39:12 +02:00
Thomas Göttgens
94155f170e fix compilation, double macros resolved 2024-10-26 13:58:29 +02:00
Thomas Göttgens
840996c755 fix build for portduino 2024-10-26 13:41:31 +02:00
Thomas Göttgens
1027b45ee9 Merge branch 'store-and-forward' of https://github.com/meshtastic/firmware into store-and-forward 2024-10-26 13:39:44 +02:00
Thomas Göttgens
7532052edc Use SD card as store&forward memory 2024-10-26 12:21:18 +02:00
Thomas Göttgens
b1125513f3 Use SD card as store&forward memory 2024-10-16 21:11:24 +02:00
24 changed files with 625 additions and 90 deletions

View File

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

View File

@@ -62,6 +62,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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
@@ -1230,6 +1236,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<wifi_err_reason_t>(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());

View File

@@ -700,6 +700,8 @@ void setup()
i2cScanner.reset();
#endif
// initSPI() must have called at this point (must be before screen and lora)
#ifdef HAS_SDCARD
setupSDCard();
#endif
@@ -792,7 +794,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);

View File

@@ -57,6 +57,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
@@ -73,6 +75,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

View File

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

View File

@@ -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<meshtastic_QueueStatus> &queueStatusPool;
extern Allocator<meshtastic_MqttClientProxyMessage> &mqttClientProxyMessagePool;

View File

@@ -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 <ErriezCRC32.h>
#include <algorithm>
#include <pb_decode.h>
@@ -32,8 +35,6 @@
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
#include "SPILock.h"
#include "modules/StoreForwardModule.h"
#include <Preferences.h>
#include <esp_efuse.h>
#include <esp_efuse_table.h>
@@ -42,8 +43,10 @@
#include <soc/soc.h>
#endif
#ifdef ARCH_PORTDUINO
#include "SPILock.h"
#include "modules/StoreForwardModule.h"
#ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif

View File

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

View File

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

View File

@@ -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,6 +161,7 @@ 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->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 &&
@@ -142,7 +169,34 @@ uint32_t StoreForwardModule::getNumAvailablePackets(NodeNum dest, uint32_t last_
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,13 +241,14 @@ 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
}
}
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;
@@ -202,8 +257,31 @@ void StoreForwardModule::historyAdd(const meshtastic_MeshPacket &mp)
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);
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,6 +314,8 @@ 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->storageType == StorageType::ST_PSRAM) {
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.
@@ -261,6 +341,7 @@ meshtastic_MeshPacket *StoreForwardModule::preparePayload(NodeNum dest, uint32_t
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;
@@ -281,6 +362,61 @@ meshtastic_MeshPacket *StoreForwardModule::preparePayload(NodeNum dest, uint32_t
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;

View File

@@ -9,6 +9,11 @@
#include <functional>
#include <unordered_map>
#ifdef HAS_SDCARD
#include "SPILock.h"
#include <SD.h>
#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<meshtastic_StoreAndForward>
{
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.

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,7 +4,7 @@
// #define HAS_SCREEN 0
// #define HAS_SDCARD
// #define SDCARD_USE_SPI1
// #define SDCARD_USE_HSPI
// #define USE_SSD1306

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
#define HAS_SDCARD
#define SDCARD_USE_SPI1
#define SDCARD_USE_HSPI
// Display (E-Ink)
#define PIN_EINK_CS 15

View File

@@ -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
#define SDCARD_USE_HSPI

View File

@@ -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.
-DRADIOLIB_EXCLUDE_SX128X=1
-DRADIOLIB_EXCLUDE_SX126X=1
-DRADIOLIB_EXCLUDE_LR11X0=1
upload_speed = 115200

View File

@@ -23,3 +23,14 @@
#endif
#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

View File

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