mirror of
https://github.com/meshtastic/firmware.git
synced 2025-07-30 02:15:41 +00:00
Merge d657177f0e
into 5d98f7e307
This commit is contained in:
commit
acdedd84a2
@ -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
|
||||
}
|
@ -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
|
||||
|
||||
@ -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<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());
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// #define HAS_SCREEN 0
|
||||
// #define HAS_SDCARD
|
||||
// #define SDCARD_USE_SPI1
|
||||
// #define SDCARD_USE_HSPI
|
||||
|
||||
// #define USE_SSD1306
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
#define HAS_SDCARD
|
||||
#define SDCARD_USE_SPI1
|
||||
#define SDCARD_USE_HSPI
|
||||
|
||||
// Display (E-Ink)
|
||||
#define PIN_EINK_CS 15
|
||||
|
@ -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
|
@ -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
|
||||
-DRADIOLIB_EXCLUDE_SX128X=1
|
||||
-DRADIOLIB_EXCLUDE_SX126X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
upload_speed = 115200
|
||||
|
@ -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
|
||||
#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
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user