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
38 changed files with 648 additions and 315 deletions

View File

@@ -26,7 +26,6 @@ build_flags = -Wno-missing-field-initializers
-DUSE_THREAD_NAMES
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
-DPB_ENABLE_MALLOC=1
-DRADIOLIB_LOW_LEVEL=1
-DRADIOLIB_EXCLUDE_CC1101=1
-DRADIOLIB_EXCLUDE_NRF24=1
-DRADIOLIB_EXCLUDE_RF69=1

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

@@ -214,8 +214,6 @@ bool pauseBluetoothLogging = false;
bool pmu_found;
uint8_t pa_fan_percentage = 50;
#if !MESHTASTIC_EXCLUDE_I2C
// Array map of sensor types with i2c address and wire as we'll find in the i2c scan
std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1] = {};
@@ -702,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
@@ -794,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);
@@ -1377,36 +1376,16 @@ void setup()
mqttInit();
#endif
#ifdef RADIO_FAN_EN
// Ability to disable FAN if PIN has been set with RADIO_FAN_EN.
#ifdef RF95_FAN_EN
// Ability to disable FAN if PIN has been set with RF95_FAN_EN.
// Make sure LoRa has been started before disabling FAN.
#ifdef RADIO_FAN_PWM
#if defined(ARCH_ESP32)
// Set up PWM at Channel 1 at 25KHz, using 8-bit resolution
// Turn ON/OFF fan to the specified value if enabled by config.
// code by https://github.com/gjelsoe/
if (ledcSetup(1, 25000, 8)) {
ledcAttachPin(RADIO_FAN_EN, 1);
LOG_INFO("PWM init C1 P%d\n", RADIO_FAN_EN);
// Set PWM duty cycle based on fan disabled state
ledcWrite(1, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
} else {
LOG_WARN("PWM init fail P%d\n", RADIO_FAN_EN);
}
#elif defined(ARCH_NRF52)
pinMode(RADIO_FAN_EN, OUTPUT);
analogWrite(RADIO_FAN_EN, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#endif
#else
// Set up as ON/OFF switch of fan
pinMode(RADIO_FAN_EN, OUTPUT);
digitalWrite(RADIO_FAN_EN, LOW ^ 0);
#endif
if (config.lora.pa_fan_disabled)
digitalWrite(RF95_FAN_EN, LOW ^ 0);
#endif
#ifndef ARCH_PORTDUINO
// Initialize Wifi
// Initialize Wifi
#if HAS_WIFI
initWifi();
#endif

View File

@@ -78,8 +78,6 @@ extern uint32_t shutdownAtMsec;
extern uint32_t serialSinceMsec;
extern uint8_t pa_fan_percentage;
// If a thread does something that might need for it to be rescheduled ASAP it can set this flag
// This will suppress the current delay and instead try to run ASAP.
extern bool runASAP;

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

@@ -3,7 +3,6 @@
#include "Throttle.h"
#include "configuration.h"
#include "error.h"
#include "main.h"
#include "mesh/NodeDB.h"
#ifdef LR11X0_DIO_AS_RF_SWITCH
#include "rfswitch.h"
@@ -55,8 +54,6 @@ template <typename T> bool LR11x0Interface<T>::init()
digitalWrite(LR11X0_POWER_EN, HIGH);
#endif
enableFan();
#if ARCH_PORTDUINO
float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000;
// FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE

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

@@ -154,7 +154,10 @@ bool RF95Interface::init()
digitalWrite(RF95_TXEN, 0);
#endif
enableFan();
#ifdef RF95_FAN_EN
pinMode(RF95_FAN_EN, OUTPUT);
digitalWrite(RF95_FAN_EN, 1);
#endif
#ifdef RF95_RXEN
pinMode(RF95_RXEN, OUTPUT);
@@ -182,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
@@ -327,7 +330,10 @@ bool RF95Interface::sleep()
// put chipset into sleep mode
setStandby(); // First cancel any active receiving/sending
lora->sleep();
disableFan();
#ifdef RF95_FAN_EN
digitalWrite(RF95_FAN_EN, 0);
#endif
return true;
}

View File

@@ -531,37 +531,4 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
return res == RADIOLIB_ERR_NONE;
}
}
void RadioLibInterface::enableFan()
{
#ifdef RADIO_FAN_EN
#ifdef RADIO_FAN_PWM
#if defined(ARCH_ESP32)
ledcWrite(1, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#elif defined(ARCH_NRF52)
analogWrite(RADIO_FAN_EN, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#endif
#else
pinMode(RADIO_FAN_EN, OUTPUT);
digitalWrite(RADIO_FAN_EN, 1);
#endif
#endif
}
void RadioLibInterface::disableFan()
{
#ifdef RADIO_FAN_EN
#ifdef RADIO_FAN_PWM
#if defined(ARCH_ESP32)
ledcWrite(1, 0);
#elif defined(ARCH_NRF52)
analogWrite(RADIO_FAN_EN, 0);
#endif
#else
pinMode(RADIO_FAN_EN, OUTPUT);
digitalWrite(RADIO_FAN_EN, 0);
#endif
#endif
}

View File

@@ -146,9 +146,6 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
/** Attempt to find a packet in the TxQueue. Returns true if the packet was found. */
virtual bool findInTxQueue(NodeNum from, PacketId id) override;
void enableFan();
void disableFan();
private:
/** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually
* doing the transmit */

View File

@@ -52,8 +52,6 @@ template <typename T> bool SX126xInterface<T>::init()
pinMode(SX126X_POWER_EN, OUTPUT);
#endif
enableFan();
#if ARCH_PORTDUINO
tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000;
if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) {

View File

@@ -35,7 +35,10 @@ template <typename T> bool SX128xInterface<T>::init()
digitalWrite(SX128X_POWER_EN, HIGH);
#endif
enableFan();
#ifdef RF95_FAN_EN
pinMode(RF95_FAN_EN, OUTPUT);
digitalWrite(RF95_FAN_EN, 1);
#endif
#if ARCH_PORTDUINO
if (settingsMap[rxen_pin] != RADIOLIB_NC) {

View File

@@ -706,21 +706,13 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
requiresReboot = false;
}
#ifdef RADIO_FAN_EN
#ifdef RADIO_FAN_PWM
#if defined(ARCH_ESP32)
ledcWrite(1, c.payload_variant.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#elif defined(ARCH_NFR52)
analogWrite(RADIO_FAN_EN, c.payload_variant.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55));
#endif
#else
#ifdef RF95_FAN_EN
// Turn PA off if disabled by config
if (c.payload_variant.lora.pa_fan_disabled) {
digitalWrite(RADIO_FAN_EN, LOW ^ 0);
digitalWrite(RF95_FAN_EN, LOW ^ 0);
} else {
digitalWrite(RADIO_FAN_EN, HIGH ^ 0);
digitalWrite(RF95_FAN_EN, HIGH ^ 0);
}
#endif
#endif
config.lora = c.payload_variant.lora;
// If we're setting region for the first time, init the region

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

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

@@ -12,7 +12,7 @@
#define LORA_MISO 19
#define LORA_MOSI 23
#define LORA_CS 5
#define RADIO_FAN_EN 17
#define RF95_FAN_EN 17
// #define LED_PIN 16 // This is a LED_WS2812 not a standard LED
#define HAS_NEOPIXEL // Enable the use of neopixels

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

@@ -46,8 +46,7 @@
FAN is active at 250mW on it's ExpressLRS Firmware.
This FAN has TACHO signal on Pin 27 for use with PWM.
*/
#define RADIO_FAN_EN 2
#define RADIO_FAN_PWM
#define RF95_FAN_EN 2
/*
LED PIN setup and it has a NeoPixel LED.

View File

@@ -32,7 +32,7 @@
This unit has a FAN built-in.
FAN is active at 250mW on it's ExpressLRS Firmware.
*/
#define RADIO_FAN_EN 2
#define RF95_FAN_EN 2
/*
LED PIN setup.

View File

@@ -1,20 +0,0 @@
[env:radiomaster_nomad_gemini]
extends = esp32_base
board = esp32doit-devkit-v1
build_flags =
${esp32_base.build_flags}
-DRADIOMASTER_NOMAD_GEMINI
-DPRIVATE_HW
-DVTABLES_IN_FLASH=1
-DCONFIG_DISABLE_HAL_LOCKS=1
-O2
-Ivariants/radiomaster_nomad_gemini
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
-DMESHTASTIC_EXCLUDE_I2C=1
-DRADIOLIB_EXCLUDE_SX128X=1
-DRADIOLIB_EXCLUDE_SX127X=1
-DRADIOLIB_EXCLUDE_SX126X=1
board_build.f_cpu = 240000000L
upload_protocol = esptool
lib_deps =
${esp32_base.lib_deps}

View File

@@ -1,56 +0,0 @@
#include "RadioLib.h"
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_LR11X0_DIO7,
RADIOLIB_LR11X0_DIO8, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6 DIO7 DIO8
{LR11x0::MODE_STBY, {LOW, LOW, LOW, LOW}}, {LR11x0::MODE_RX, {LOW, LOW, HIGH, LOW}},
{LR11x0::MODE_TX, {LOW, LOW, LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, LOW, LOW, HIGH}},
{LR11x0::MODE_TX_HF, {LOW, HIGH, LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW, LOW, LOW}},
{LR11x0::MODE_WIFI, {HIGH, LOW, LOW, LOW}}, END_OF_MODE_TABLE,
};
/*
DIO5: RXEN 2.4GHz
DIO6: TXEN 2.4GHz
DIO7: RXEN 900MHz
DIO8: TXEN 900MHz
"radio_dcdc": true,
"radio_rfo_hf": true,
"power_apc2": 26,
"power_min": 0,
"power_high": 6,
"power_max": 6,
"power_default": 3,
"power_control": 3, POWER_OUTPUT_DACWRITE // use internal dacWrite function to set value on GPIO_PIN_RFamp_APC2
[0, 1, 2, 3, 4, 5, 6 ] // 0-6
"power_values": [120, 120, 120, 120, 120, 120, 95] // DAC Value
"power_values2": [-17, -16, -14, -11, -7, -3, 5 ] // 900M
"power_values_dual": [-18, -14, -8, -6, -2, 3, 5 ] // 2.4G
// default value 0 means direct!
#define POWER_OUTPUT_DACWRITE (hardware_int(HARDWARE_power_control)==3)
#define POWER_OUTPUT_VALUES hardware_i16_array(HARDWARE_power_values)
#define POWER_OUTPUT_VALUES_COUNT hardware_int(HARDWARE_power_values_count)
#define POWER_OUTPUT_VALUES2 hardware_i16_array(HARDWARE_power_values2)
#define POWER_OUTPUT_VALUES_DUAL hardware_i16_array(HARDWARE_power_values_dual)
#define POWER_OUTPUT_VALUES_DUAL_COUNT hardware_int(HARDWARE_power_values_dual_count)
#define GPIO_PIN_FAN_EN hardware_pin(HARDWARE_misc_fan_en)
case PWR_10mW: return 10;
case PWR_25mW: return 14;
case PWR_50mW: return 17;
case PWR_100mW: return 20;
case PWR_250mW: return 24;
case PWR_500mW: return 27;
case PWR_1000mW: return 30;
95 -> +25dBm
120 -> +24dBm
*/

View File

@@ -1,60 +0,0 @@
#define HAS_SCREEN 0
#define HAS_WIRE 0
#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define PIN_SPI_MISO 33
#define PIN_SPI_MOSI 32
#define PIN_SPI_SCK 25
#define PIN_SPI_NSS 27
#define LORA_RESET 15
#define LORA_DIO1 37
#define LORA_DIO2 36
#define LORA_SCK PIN_SPI_SCK
#define LORA_MISO PIN_SPI_MISO
#define LORA_MOSI PIN_SPI_MOSI
#define LORA_CS PIN_SPI_NSS
// supported modules list
#define USE_LR1121
#define LR1121_IRQ_PIN LORA_DIO1
#define LR1121_NRESET_PIN LORA_RESET
#define LR1121_BUSY_PIN LORA_DIO2
#define LR1121_SPI_NSS_PIN LORA_CS
#define LR1121_SPI_SCK_PIN LORA_SCK
#define LR1121_SPI_MOSI_PIN LORA_MOSI
#define LR1121_SPI_MISO_PIN LORA_MISO
// this is correct and sets the cap for the Sub-GHz part
#define LR1110_MAX_POWER 5
// 2.4G Part
#define LR1120_MAX_POWER 5
#define POWER_SHIFT -20
// not yet implemented
#define JANUS_RADIO
#define LR1121_IRQ2_PIN 34
#define LR1121_NRESET2_PIN 21
#define LR1121_BUSY2_PIN 39
#define LR1121_SPI_NSS2_PIN 13
// TODO: check if this is correct
// #define LR11X0_DIO3_TCXO_VOLTAGE 1.6
#define LR11X0_DIO_AS_RF_SWITCH
#define HAS_NEOPIXEL // Enable the use of neopixels
#define NEOPIXEL_COUNT 2 // How many neopixels are connected
#define NEOPIXEL_DATA 22 // GPIO pin used to send data to the neopixels
#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // Type of neopixels in use
#define ENABLE_AMBIENTLIGHTING // Turn on Ambient Lighting
#define BUTTON_PIN 34
#define BUTTON_NEED_PULLUP
#undef EXT_NOTIFY_OUT
#define RADIO_FAN_EN 2

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

View File

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

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