Merge branch 'meshtastic:master' into master

This commit is contained in:
Mictronics 2025-01-30 18:15:33 +01:00 committed by GitHub
commit bb7d9c0f15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 225 additions and 89 deletions

View File

@ -78,6 +78,8 @@ Lora:
# TXen: x # TX and RX enable pins # TXen: x # TX and RX enable pins
# RXen: x # RXen: x
# SX126X_MAX_POWER: 8 # Limit the output power to 8 dBm, useful for amped nodes
# spiSpeed: 2000000 # spiSpeed: 2000000
### Set default/fallback gpio chip to use in /dev/. Defaults to 0. ### Set default/fallback gpio chip to use in /dev/. Defaults to 0.
@ -188,4 +190,4 @@ General:
MaxMessageQueue: 100 MaxMessageQueue: 100
ConfigDirectory: /etc/meshtasticd/config.d/ ConfigDirectory: /etc/meshtasticd/config.d/
# MACAddress: AA:BB:CC:DD:EE:FF # MACAddress: AA:BB:CC:DD:EE:FF
# MACAddressSource: eth0 # MACAddressSource: eth0

View File

@ -7,3 +7,6 @@ Lora:
TXen: 13 TXen: 13
RXen: 12 RXen: 12
DIO3_TCXO_VOLTAGE: true DIO3_TCXO_VOLTAGE: true
# Only for E22-900M33S:
# Limit the output power to 8 dBm
# SX126X_MAX_POWER: 8

View File

@ -102,7 +102,7 @@ pref_flags = []
for pref in userPrefs: for pref in userPrefs:
if userPrefs[pref].startswith("{"): if userPrefs[pref].startswith("{"):
pref_flags.append("-D" + pref + "=" + userPrefs[pref]) pref_flags.append("-D" + pref + "=" + userPrefs[pref])
elif userPrefs[pref].replace(".", "").isdigit(): elif userPrefs[pref].lstrip("-").replace(".", "").isdigit():
pref_flags.append("-D" + pref + "=" + userPrefs[pref]) pref_flags.append("-D" + pref + "=" + userPrefs[pref])
elif userPrefs[pref] == "true" or userPrefs[pref] == "false": elif userPrefs[pref] == "true" or userPrefs[pref] == "false":
pref_flags.append("-D" + pref + "=" + userPrefs[pref]) pref_flags.append("-D" + pref + "=" + userPrefs[pref])

View File

@ -79,17 +79,17 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
} }
if (color && logLevel != nullptr) { if (color && logLevel != nullptr) {
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
Print::write("\u001b[34m", 6); Print::write("\u001b[34m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
Print::write("\u001b[32m", 6); Print::write("\u001b[32m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
Print::write("\u001b[33m", 6); Print::write("\u001b[33m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
Print::write("\u001b[31m", 6); Print::write("\u001b[31m", 5);
} }
len = Print::write(printBuf, len); len = Print::write(printBuf, len);
if (color && logLevel != nullptr) { if (color && logLevel != nullptr) {
Print::write("\u001b[0m", 5); Print::write("\u001b[0m", 4);
} }
return len; return len;
} }
@ -107,15 +107,15 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
// include the header // include the header
if (color) { if (color) {
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
Print::write("\u001b[34m", 6); Print::write("\u001b[34m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
Print::write("\u001b[32m", 6); Print::write("\u001b[32m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
Print::write("\u001b[33m", 6); Print::write("\u001b[33m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
Print::write("\u001b[31m", 6); Print::write("\u001b[31m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0)
Print::write("\u001b[35m", 6); Print::write("\u001b[35m", 5);
} }
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile
@ -393,4 +393,4 @@ std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...)
break; break;
} }
return std::string(formatted.get()); return std::string(formatted.get());
} }

View File

@ -123,7 +123,7 @@ static bool heartbeat = false;
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2) #define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
/// Check if the display can render a string (detect special chars; emoji) // Check if the display can render a string (detect special chars; emoji)
static bool haveGlyphs(const char *str) static bool haveGlyphs(const char *str)
{ {
#if defined(OLED_PL) || defined(OLED_UA) || defined(OLED_RU) || defined(OLED_CS) #if defined(OLED_PL) || defined(OLED_UA) || defined(OLED_RU) || defined(OLED_CS)
@ -162,11 +162,7 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
display->setFont(FONT_MEDIUM); display->setFont(FONT_MEDIUM);
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
#ifdef USERPREFS_SPLASH_TITLE
const char *title = USERPREFS_SPLASH_TITLE;
#else
const char *title = "meshtastic.org"; const char *title = "meshtastic.org";
#endif
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title); display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
@ -185,6 +181,56 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code
} }
#ifdef USERPREFS_OEM_TEXT
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
static const uint8_t xbm[] = USERPREFS_OEM_IMAGE_DATA;
display->drawXbm(x + (SCREEN_WIDTH - USERPREFS_OEM_IMAGE_WIDTH) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - USERPREFS_OEM_IMAGE_HEIGHT) / 2 + 2, USERPREFS_OEM_IMAGE_WIDTH,
USERPREFS_OEM_IMAGE_HEIGHT, xbm);
switch (USERPREFS_OEM_FONT_SIZE) {
case 0:
display->setFont(FONT_SMALL);
break;
case 2:
display->setFont(FONT_LARGE);
break;
default:
display->setFont(FONT_MEDIUM);
break;
}
display->setTextAlignment(TEXT_ALIGN_LEFT);
const char *title = USERPREFS_OEM_TEXT;
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
display->setFont(FONT_SMALL);
// Draw region in upper left
if (upperMsg)
display->drawString(x + 0, y + 0, upperMsg);
// Draw version and shortname in upper right
char buf[25];
snprintf(buf, sizeof(buf), "%s\n%s", xstr(APP_VERSION_SHORT), haveGlyphs(owner.short_name) ? owner.short_name : "");
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(x + SCREEN_WIDTH, y + 0, buf);
screen->forceDisplay();
display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code
}
static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// Draw region in upper left
const char *region = myRegion ? myRegion->name : NULL;
drawOEMIconScreen(region, display, state, x, y);
}
#endif
void Screen::drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message) void Screen::drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message)
{ {
uint16_t x_offset = display->width() / 2; uint16_t x_offset = display->width() / 2;
@ -1658,6 +1704,10 @@ void Screen::setup()
// Set the utf8 conversion function // Set the utf8 conversion function
dispdev->setFontTableLookupFunction(customFontTableLookup); dispdev->setFontTableLookupFunction(customFontTableLookup);
#ifdef USERPREFS_OEM_TEXT
logo_timeout *= 2; // Double the time if we have a custom logo
#endif
// Add frames. // Add frames.
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST);
alertFrames[0] = [this](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void { alertFrames[0] = [this](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
@ -1803,6 +1853,22 @@ int32_t Screen::runOnce()
showingBootScreen = false; showingBootScreen = false;
} }
#ifdef USERPREFS_OEM_TEXT
static bool showingOEMBootScreen = true;
if (showingOEMBootScreen && (millis() > ((logo_timeout / 2) + serialSinceMsec))) {
LOG_INFO("Switch to OEM screen...");
// Change frames.
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
ui->setFrames(bootOEMFrames, bootOEMFrameCount);
ui->update();
#ifndef USE_EINK
ui->update();
#endif
showingOEMBootScreen = false;
}
#endif
#ifndef DISABLE_WELCOME_UNSET #ifndef DISABLE_WELCOME_UNSET
if (showingNormalScreen && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) { if (showingNormalScreen && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
setWelcomeFrames(); setWelcomeFrames();
@ -2662,13 +2728,14 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
int Screen::handleTextMessage(const meshtastic_MeshPacket *packet) int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
{ {
// If auto carousel is disabled -> return 0 and skip new messages handling
if (config.display.auto_screen_carousel_secs == 0)
return 0;
// Handle focus change based on message type
if (showingNormalScreen) { if (showingNormalScreen) {
setFrames(packet->from == 0 ? FOCUS_PRESERVE : FOCUS_TEXTMESSAGE); // Outgoing message
if (packet->from == 0)
setFrames(FOCUS_PRESERVE); // Return to same frame (quietly hiding the rx text message frame)
// Incoming message
else
setFrames(FOCUS_TEXTMESSAGE); // Focus on the new message
} }
return 0; return 0;
@ -2755,4 +2822,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
} // namespace graphics } // namespace graphics
#else #else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {} graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN #endif // HAS_SCREEN

View File

@ -115,10 +115,6 @@ AccelerometerThread *accelerometerThread = nullptr;
AudioThread *audioThread = nullptr; AudioThread *audioThread = nullptr;
#endif #endif
#if defined(TCXO_OPTIONAL)
float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; // if TCXO is optional, put this here so it can be changed further down.
#endif
using namespace concurrency; using namespace concurrency;
volatile static const char slipstreamTZString[] = USERPREFS_TZ_STRING; volatile static const char slipstreamTZString[] = USERPREFS_TZ_STRING;
@ -928,13 +924,16 @@ void setup()
#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && !defined(TCXO_OPTIONAL) && RADIOLIB_EXCLUDE_SX126X != 1 #if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && !defined(TCXO_OPTIONAL) && RADIOLIB_EXCLUDE_SX126X != 1
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) { if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY); auto *sxIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) { #ifdef SX126X_DIO3_TCXO_VOLTAGE
sxIf->setTCXOVoltage(SX126X_DIO3_TCXO_VOLTAGE);
#endif
if (!sxIf->init()) {
LOG_WARN("No SX1262 radio"); LOG_WARN("No SX1262 radio");
delete rIf; delete sxIf;
rIf = NULL;
} else { } else {
LOG_INFO("SX1262 init success"); LOG_INFO("SX1262 init success");
rIf = sxIf;
radioType = SX1262_RADIO; radioType = SX1262_RADIO;
} }
} }
@ -942,29 +941,28 @@ void setup()
#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && defined(TCXO_OPTIONAL) #if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && defined(TCXO_OPTIONAL)
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) { if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
// Try using the specified TCXO voltage // try using the specified TCXO voltage
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY); auto *sxIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) { sxIf->setTCXOVoltage(SX126X_DIO3_TCXO_VOLTAGE);
LOG_WARN("No SX1262 radio with TCXO, Vref %f V", tcxoVoltage); if (!sxIf->init()) {
delete rIf; LOG_WARN("No SX1262 radio with TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE);
rIf = NULL; delete sxIf;
tcxoVoltage = 0; // if it fails, set the TCXO voltage to zero for the next attempt
} else { } else {
LOG_WARN("SX1262 init success, TCXO, Vref %f V", tcxoVoltage); LOG_INFO("SX1262 init success, TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE);
rIf = sxIf;
radioType = SX1262_RADIO; radioType = SX1262_RADIO;
} }
} }
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) { if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
// If specified TCXO voltage fails, attempt to use DIO3 as a reference instea // If specified TCXO voltage fails, attempt to use DIO3 as a reference instead
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY); rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) { if (!rIf->init()) {
LOG_WARN("No SX1262 radio with XTAL, Vref %f V", tcxoVoltage); LOG_WARN("No SX1262 radio with XTAL, Vref 0.0V");
delete rIf; delete rIf;
rIf = NULL; rIf = NULL;
tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; // if it fails, set the TCXO voltage back for the next radio search
} else { } else {
LOG_INFO("SX1262 init success, XTAL, Vref %f V", tcxoVoltage); LOG_INFO("SX1262 init success, XTAL, Vref 0.0V");
radioType = SX1262_RADIO; radioType = SX1262_RADIO;
} }
} }

View File

@ -20,12 +20,18 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not // Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and LR11x0 power config forgotten) // specified (may be dangerous if using external PA and LR11x0 power config forgotten)
#if ARCH_PORTDUINO
#define LR1110_MAX_POWER settingsMap[lr1110_max_power]
#endif
#ifndef LR1110_MAX_POWER #ifndef LR1110_MAX_POWER
#define LR1110_MAX_POWER 22 #define LR1110_MAX_POWER 22
#endif #endif
// the 2.4G part maxes at 13dBm // the 2.4G part maxes at 13dBm
#if ARCH_PORTDUINO
#define LR1120_MAX_POWER settingsMap[lr1120_max_power]
#endif
#ifndef LR1120_MAX_POWER #ifndef LR1120_MAX_POWER
#define LR1120_MAX_POWER 13 #define LR1120_MAX_POWER 13
#endif #endif

View File

@ -10,6 +10,7 @@
std::vector<MeshModule *> *MeshModule::modules; std::vector<MeshModule *> *MeshModule::modules;
const meshtastic_MeshPacket *MeshModule::currentRequest; const meshtastic_MeshPacket *MeshModule::currentRequest;
uint8_t MeshModule::numPeriodicModules = 0;
/** /**
* If any of the current chain of modules has already sent a reply, it will be here. This is useful to allow * If any of the current chain of modules has already sent a reply, it will be here. This is useful to allow
@ -35,6 +36,15 @@ MeshModule::~MeshModule()
modules->erase(it); modules->erase(it);
} }
// ⚠️ **Only call once** to set the initial delay before a module starts broadcasting periodically
int32_t MeshModule::setStartDelay()
{
int32_t startDelay = MESHMODULE_MIN_BROADCAST_DELAY_MS + numPeriodicModules * MESHMODULE_BROADCAST_SPACING_MS;
numPeriodicModules++;
return startDelay;
}
meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex, meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex,
uint8_t hopLimit) uint8_t hopLimit)
{ {

View File

@ -9,6 +9,9 @@
#include <OLEDDisplayUi.h> #include <OLEDDisplayUi.h>
#endif #endif
#define MESHMODULE_MIN_BROADCAST_DELAY_MS 30 * 1000 // Min. delay after boot before sending first broadcast by any module
#define MESHMODULE_BROADCAST_SPACING_MS 15 * 1000 // Initial spacing between broadcasts of different modules
/** handleReceived return enumeration /** handleReceived return enumeration
* *
* Use ProcessMessage::CONTINUE to allows other modules to process a message. * Use ProcessMessage::CONTINUE to allows other modules to process a message.
@ -119,6 +122,12 @@ class MeshModule
*/ */
static const meshtastic_MeshPacket *currentRequest; static const meshtastic_MeshPacket *currentRequest;
// We keep track of the number of modules that send a periodic broadcast to schedule them spaced out over time
static uint8_t numPeriodicModules;
// Set the start delay for module that broadcasts periodically
int32_t setStartDelay();
/** /**
* If your handler wants to send a response, simply set currentReply and it will be sent at the end of response handling. * If your handler wants to send a response, simply set currentReply and it will be sent at the end of response handling.
*/ */

View File

@ -9,6 +9,9 @@
#include "PortduinoGlue.h" #include "PortduinoGlue.h"
#endif #endif
#if ARCH_PORTDUINO
#define RF95_MAX_POWER settingsMap[rf95_max_power]
#endif
#ifndef RF95_MAX_POWER #ifndef RF95_MAX_POWER
#define RF95_MAX_POWER 20 #define RF95_MAX_POWER 20
#endif #endif
@ -337,4 +340,4 @@ bool RF95Interface::sleep()
return true; return true;
} }
#endif #endif

View File

@ -11,6 +11,9 @@
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not // Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and SX126x power config forgotten) // specified (may be dangerous if using external PA and SX126x power config forgotten)
#if ARCH_PORTDUINO
#define SX126X_MAX_POWER settingsMap[sx126x_max_power]
#endif
#ifndef SX126X_MAX_POWER #ifndef SX126X_MAX_POWER
#define SX126X_MAX_POWER 22 #define SX126X_MAX_POWER 22
#endif #endif
@ -50,22 +53,13 @@ template <typename T> bool SX126xInterface<T>::init()
#endif #endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000;
if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) { if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) {
digitalWrite(settingsMap[sx126x_ant_sw_pin], HIGH); digitalWrite(settingsMap[sx126x_ant_sw_pin], HIGH);
pinMode(settingsMap[sx126x_ant_sw_pin], OUTPUT); pinMode(settingsMap[sx126x_ant_sw_pin], OUTPUT);
} }
// FIXME: correct logic to default to not using TCXO if no voltage is specified for SX126X_DIO3_TCXO_VOLTAGE
#elif !defined(SX126X_DIO3_TCXO_VOLTAGE)
float tcxoVoltage =
0; // "TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip." per
// https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/SX126x/SX126x.h#L471C26-L471C104
// (DIO3 is free to be used as an IRQ)
#elif !defined(TCXO_OPTIONAL)
float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE;
// (DIO3 is not free to be used as an IRQ)
#endif #endif
if (tcxoVoltage == 0) if (tcxoVoltage == 0.0)
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage"); LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage");
else else
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V", tcxoVoltage); LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V", tcxoVoltage);
@ -83,7 +77,7 @@ template <typename T> bool SX126xInterface<T>::init()
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO); int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO);
// \todo Display actual typename of the adapter, not just `SX126x` // \todo Display actual typename of the adapter, not just `SX126x`
LOG_INFO("SX126x init result %d", res); LOG_INFO("SX126x init result %d", res);
if (res == RADIOLIB_ERR_CHIP_NOT_FOUND) if (res == RADIOLIB_ERR_CHIP_NOT_FOUND || res == RADIOLIB_ERR_SPI_CMD_FAILED)
return false; return false;
LOG_INFO("Frequency set to %f", getFreq()); LOG_INFO("Frequency set to %f", getFreq());
@ -342,4 +336,4 @@ template <typename T> bool SX126xInterface<T>::sleep()
return true; return true;
} }
#endif #endif

View File

@ -28,8 +28,11 @@ template <class T> class SX126xInterface : public RadioLibInterface
bool isIRQPending() override { return lora.getIrqFlags() != 0; } bool isIRQPending() override { return lora.getIrqFlags() != 0; }
void setTCXOVoltage(float voltage) { tcxoVoltage = voltage; }
protected: protected:
float currentLimit = 140; // Higher OCP limit for SX126x PA float currentLimit = 140; // Higher OCP limit for SX126x PA
float tcxoVoltage = 0.0;
/** /**
* Specific module instance * Specific module instance

View File

@ -10,6 +10,9 @@
#endif #endif
// Particular boards might define a different max power based on what their hardware can do // Particular boards might define a different max power based on what their hardware can do
#if ARCH_PORTDUINO
#define SX128X_MAX_POWER settingsMap[sx128x_max_power]
#endif
#ifndef SX128X_MAX_POWER #ifndef SX128X_MAX_POWER
#define SX128X_MAX_POWER 13 #define SX128X_MAX_POWER 13
#endif #endif
@ -315,4 +318,4 @@ template <typename T> bool SX128xInterface<T>::sleep()
return true; return true;
} }
#endif #endif

View File

@ -81,7 +81,7 @@ int32_t DetectionSensorModule::runOnce()
} }
LOG_INFO("Detection Sensor Module: init"); LOG_INFO("Detection Sensor Module: init");
return DELAYED_INTERVAL; return setStartDelay();
} }
// LOG_DEBUG("Detection Sensor Module: Current pin state: %i", digitalRead(moduleConfig.detection_sensor.monitor_pin)); // LOG_DEBUG("Detection Sensor Module: Current pin state: %i", digitalRead(moduleConfig.detection_sensor.monitor_pin));
@ -161,4 +161,4 @@ bool DetectionSensorModule::hasDetectionEvent()
bool currentState = digitalRead(moduleConfig.detection_sensor.monitor_pin); bool currentState = digitalRead(moduleConfig.detection_sensor.monitor_pin);
// LOG_DEBUG("Detection Sensor Module: Current state: %i", currentState); // LOG_DEBUG("Detection Sensor Module: Current state: %i", currentState);
return (moduleConfig.detection_sensor.detection_trigger_type & 1) ? currentState : !currentState; return (moduleConfig.detection_sensor.detection_trigger_type & 1) ? currentState : !currentState;
} }

View File

@ -97,8 +97,9 @@ NodeInfoModule::NodeInfoModule()
: ProtobufModule("nodeinfo", meshtastic_PortNum_NODEINFO_APP, &meshtastic_User_msg), concurrency::OSThread("NodeInfo") : ProtobufModule("nodeinfo", meshtastic_PortNum_NODEINFO_APP, &meshtastic_User_msg), concurrency::OSThread("NodeInfo")
{ {
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
setIntervalFromNow(30 *
1000); // Send our initial owner announcement 30 seconds after we start (to give network time to setup) setIntervalFromNow(setStartDelay()); // Send our initial owner announcement 30 seconds
// after we start (to give network time to setup)
} }
int32_t NodeInfoModule::runOnce() int32_t NodeInfoModule::runOnce()
@ -112,4 +113,4 @@ int32_t NodeInfoModule::runOnce()
sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies) sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
} }
return Default::getConfiguredOrDefaultMs(config.device.node_info_broadcast_secs, default_node_info_broadcast_secs); return Default::getConfiguredOrDefaultMs(config.device.node_info_broadcast_secs, default_node_info_broadcast_secs);
} }

View File

@ -28,8 +28,9 @@ PositionModule::PositionModule()
nodeStatusObserver.observe(&nodeStatus->onNewStatus); nodeStatusObserver.observe(&nodeStatus->onNewStatus);
if (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER && if (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) config.device.role != meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) {
setIntervalFromNow(60 * 1000); setIntervalFromNow(setStartDelay());
}
// Power saving trackers should clear their position on startup to avoid waking up and sending a stale position // Power saving trackers should clear their position on startup to avoid waking up and sending a stale position
if ((config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER || if ((config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
@ -160,7 +161,8 @@ bool PositionModule::hasGPS()
#endif #endif
} }
meshtastic_MeshPacket *PositionModule::allocReply() // Allocate a packet with our position data if we have one
meshtastic_MeshPacket *PositionModule::allocPositionPacket()
{ {
if (precision == 0) { if (precision == 0) {
LOG_DEBUG("Skip location send because precision is set to 0!"); LOG_DEBUG("Skip location send because precision is set to 0!");
@ -262,7 +264,8 @@ meshtastic_MeshPacket *PositionModule::allocReply()
p.has_ground_speed = true; p.has_ground_speed = true;
} }
LOG_INFO("Position reply: time=%i lat=%i lon=%i", p.time, p.latitude_i, p.longitude_i); LOG_INFO("Position packet: time=%i lat=%i lon=%i", p.time, p.latitude_i, p.longitude_i);
lastSentToMesh = millis();
// TAK Tracker devices should send their position in a TAK packet over the ATAK port // TAK Tracker devices should send their position in a TAK packet over the ATAK port
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) if (config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)
@ -271,6 +274,16 @@ meshtastic_MeshPacket *PositionModule::allocReply()
return allocDataProtobuf(p); return allocDataProtobuf(p);
} }
meshtastic_MeshPacket *PositionModule::allocReply()
{
if (lastSentToMesh && Throttle::isWithinTimespanMs(lastSentToMesh, 3 * 60 * 1000)) {
LOG_DEBUG("Skip Position reply since we sent it <3min ago");
ignoreRequest = true; // Mark it as ignored for MeshModule
return nullptr;
}
return allocPositionPacket();
}
meshtastic_MeshPacket *PositionModule::allocAtakPli() meshtastic_MeshPacket *PositionModule::allocAtakPli()
{ {
LOG_INFO("Send TAK PLI packet"); LOG_INFO("Send TAK PLI packet");
@ -333,9 +346,9 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
precision = 0; precision = 0;
} }
meshtastic_MeshPacket *p = allocReply(); meshtastic_MeshPacket *p = allocPositionPacket();
if (p == nullptr) { if (p == nullptr) {
LOG_DEBUG("allocReply returned a nullptr"); LOG_DEBUG("allocPositionPacket returned a nullptr");
return; return;
} }

View File

@ -55,6 +55,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
virtual int32_t runOnce() override; virtual int32_t runOnce() override;
private: private:
meshtastic_MeshPacket *allocPositionPacket();
struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition); struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition);
meshtastic_MeshPacket *allocAtakPli(); meshtastic_MeshPacket *allocAtakPli();
void trySetRtc(meshtastic_Position p, bool isLocal, bool forceUpdate = false); void trySetRtc(meshtastic_Position p, bool isLocal, bool forceUpdate = false);
@ -62,6 +63,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
void sendLostAndFoundText(); void sendLostAndFoundText();
bool hasQualityTimesource(); bool hasQualityTimesource();
bool hasGPS(); bool hasGPS();
uint32_t lastSentToMesh = 0; // Last time we sent our position to the mesh
const uint32_t minimumTimeThreshold = const uint32_t minimumTimeThreshold =
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30); Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);

View File

@ -50,12 +50,12 @@ int32_t AirQualityTelemetryModule::runOnce()
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].first = found.address.address; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].first = found.address.address;
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].second = nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].second =
i2cScanner->fetchI2CBus(found.address); i2cScanner->fetchI2CBus(found.address);
return 1000; return setStartDelay();
} }
#endif #endif
return disable(); return disable();
} }
return 1000; return setStartDelay();
} }
return disable(); return disable();
} else { } else {

View File

@ -18,7 +18,7 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
uptimeWrapCount = 0; uptimeWrapCount = 0;
uptimeLastMs = millis(); uptimeLastMs = millis();
nodeStatusObserver.observe(&nodeStatus->onNewStatus); nodeStatusObserver.observe(&nodeStatus->onNewStatus);
setIntervalFromNow(45 * 1000); // Wait until NodeInfo is sent setIntervalFromNow(setStartDelay()); // Wait until NodeInfo is sent
} }
virtual bool wantUIFrame() { return false; } virtual bool wantUIFrame() { return false; }
@ -62,4 +62,4 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
uint32_t uptimeWrapCount; uint32_t uptimeWrapCount;
uint32_t uptimeLastMs; uint32_t uptimeLastMs;
}; };

View File

@ -107,8 +107,6 @@ int32_t EnvironmentTelemetryModule::runOnce()
if (moduleConfig.telemetry.environment_measurement_enabled) { if (moduleConfig.telemetry.environment_measurement_enabled) {
LOG_INFO("Environment Telemetry: init"); LOG_INFO("Environment Telemetry: init");
// it's possible to have this module enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled
#ifdef SENSECAP_INDICATOR #ifdef SENSECAP_INDICATOR
result = indicatorSensor.runOnce(); result = indicatorSensor.runOnce();
#endif #endif
@ -171,7 +169,9 @@ int32_t EnvironmentTelemetryModule::runOnce()
#endif #endif
#endif #endif
} }
return result; // it's possible to have this module enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled
return result == UINT32_MAX ? disable() : setStartDelay();
} else { } else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever // if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.environment_measurement_enabled) { if (!moduleConfig.telemetry.environment_measurement_enabled) {

View File

@ -62,7 +62,7 @@ int32_t HealthTelemetryModule::runOnce()
if (max30102Sensor.hasSensor()) if (max30102Sensor.hasSensor())
result = max30102Sensor.runOnce(); result = max30102Sensor.runOnce();
} }
return result; return result == UINT32_MAX ? disable() : setStartDelay();
} else { } else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever // if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.health_measurement_enabled) { if (!moduleConfig.telemetry.health_measurement_enabled) {

View File

@ -65,7 +65,7 @@ int32_t PowerTelemetryModule::runOnce()
if (max17048Sensor.hasSensor() && !max17048Sensor.isInitialized()) if (max17048Sensor.hasSensor() && !max17048Sensor.isInitialized())
result = max17048Sensor.runOnce(); result = max17048Sensor.runOnce();
} }
return result; return result == UINT32_MAX ? disable() : setStartDelay();
#else #else
return disable(); return disable();
#endif #endif

View File

@ -217,6 +217,7 @@ bool isPrivateIpAddress(const IPAddress &ip)
{.network = 169u << 24 | 254 << 16, .mask = 0xffff0000}, // 169.254.0.0/16 {.network = 169u << 24 | 254 << 16, .mask = 0xffff0000}, // 169.254.0.0/16
{.network = 10u << 24, .mask = 0xff000000}, // 10.0.0.0/8 {.network = 10u << 24, .mask = 0xff000000}, // 10.0.0.0/8
{.network = 127u << 24 | 1, .mask = 0xffffffff}, // 127.0.0.1/32 {.network = 127u << 24 | 1, .mask = 0xffffffff}, // 127.0.0.1/32
{.network = 100u << 24 | 64 << 16, .mask = 0xffc00000}, // 100.64.0.0/10
}; };
const uint32_t addr = ntohl(ip); const uint32_t addr = ntohl(ip);
for (const auto &cidrRange : privateCidrRanges) { for (const auto &cidrRange : privateCidrRanges) {

View File

@ -369,6 +369,12 @@ bool loadConfig(const char *configPath)
} }
} }
settingsMap[sx126x_max_power] = yamlConfig["Lora"]["SX126X_MAX_POWER"].as<int>(22);
settingsMap[sx128x_max_power] = yamlConfig["Lora"]["SX128X_MAX_POWER"].as<int>(13);
settingsMap[lr1110_max_power] = yamlConfig["Lora"]["LR1110_MAX_POWER"].as<int>(22);
settingsMap[lr1120_max_power] = yamlConfig["Lora"]["LR1120_MAX_POWER"].as<int>(13);
settingsMap[rf95_max_power] = yamlConfig["Lora"]["RF95_MAX_POWER"].as<int>(20);
settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false); settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<float>(0) * 1000; settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<float>(0) * 1000;
if (settingsMap[dio3_tcxo_voltage] == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false)) { if (settingsMap[dio3_tcxo_voltage] == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false)) {
@ -569,4 +575,4 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac)
} else { } else {
return false; return false;
} }
} }

View File

@ -27,6 +27,11 @@ enum configNames {
sx126x_ant_sw_pin, sx126x_ant_sw_pin,
sx126x_ant_sw_line, sx126x_ant_sw_line,
sx126x_ant_sw_gpiochip, sx126x_ant_sw_gpiochip,
sx126x_max_power,
sx128x_max_power,
lr1110_max_power,
lr1120_max_power,
rf95_max_power,
dio2_as_rf_switch, dio2_as_rf_switch,
dio3_tcxo_voltage, dio3_tcxo_voltage,
use_rf95, use_rf95,
@ -94,4 +99,4 @@ int initGPIOPin(int pinNum, std::string gpioChipname, int line);
bool loadConfig(const char *configPath); bool loadConfig(const char *configPath);
static bool ends_with(std::string_view str, std::string_view suffix); static bool ends_with(std::string_view str, std::string_view suffix);
void getMacAddr(uint8_t *dmac); void getMacAddr(uint8_t *dmac);
bool MAC_from_string(std::string mac_str, uint8_t *dmac); bool MAC_from_string(std::string mac_str, uint8_t *dmac);

View File

@ -29,9 +29,13 @@
// "USERPREFS_FIXED_GPS_LON": "2.294508368", // "USERPREFS_FIXED_GPS_LON": "2.294508368",
// "USERPREFS_LORACONFIG_CHANNEL_NUM": "31", // "USERPREFS_LORACONFIG_CHANNEL_NUM": "31",
// "USERPREFS_LORACONFIG_MODEM_PRESET": "meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST", // "USERPREFS_LORACONFIG_MODEM_PRESET": "meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST",
// "USERPREFS_SPLASH_TITLE": "DEFCONtastic",
"USERPREFS_TZ_STRING": "tzplaceholder " "USERPREFS_TZ_STRING": "tzplaceholder "
// "USERPREFS_USE_ADMIN_KEY_0": "{ 0xcd, 0xc0, 0xb4, 0x3c, 0x53, 0x24, 0xdf, 0x13, 0xca, 0x5a, 0xa6, 0x0c, 0x0d, 0xec, 0x85, 0x5a, 0x4c, 0xf6, 0x1a, 0x96, 0x04, 0x1a, 0x3e, 0xfc, 0xbb, 0x8e, 0x33, 0x71, 0xe5, 0xfc, 0xff, 0x3c }", // "USERPREFS_USE_ADMIN_KEY_0": "{ 0xcd, 0xc0, 0xb4, 0x3c, 0x53, 0x24, 0xdf, 0x13, 0xca, 0x5a, 0xa6, 0x0c, 0x0d, 0xec, 0x85, 0x5a, 0x4c, 0xf6, 0x1a, 0x96, 0x04, 0x1a, 0x3e, 0xfc, 0xbb, 0x8e, 0x33, 0x71, 0xe5, 0xfc, 0xff, 0x3c }",
// "USERPREFS_USE_ADMIN_KEY_1": "{}", // "USERPREFS_USE_ADMIN_KEY_1": "{}",
// "USERPREFS_USE_ADMIN_KEY_2": "{}" // "USERPREFS_USE_ADMIN_KEY_2": "{}",
} // "USERPREFS_OEM_TEXT": "Caterham Car Club",
// "USERPREFS_OEM_FONT_SIZE": "0",
// "USERPREFS_OEM_IMAGE_WIDTH": "50",
// "USERPREFS_OEM_IMAGE_HEIGHT": "28",
// "USERPREFS_OEM_IMAGE_DATA": "{ 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF, 0x61, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF, 0x67, 0x00, 0x00, 0x00, 0x18, 0x1F, 0xF0, 0x67, 0x00, 0x00, 0x00, 0x30, 0x1F, 0xF8, 0x33, 0x00, 0x00, 0x00, 0x30, 0x00, 0xFC, 0x31, 0x00, 0x00, 0x00, 0x60, 0x00, 0xFE, 0x18, 0x00, 0x00, 0x00, 0x60, 0x00, 0x7E, 0x18, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x3F, 0x0C, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x80, 0x81, 0x1F, 0x06, 0x00, 0x00, 0x00, 0x80, 0xC1, 0x0F, 0x06, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x8F, 0x01, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xC7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00}"
}

View File

@ -183,8 +183,7 @@ settings.
*/ */
#define SX126X_DIO3_TCXO_VOLTAGE 1.8 #define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL #define TCXO_OPTIONAL // make it so that the firmware can try both TCXO and XTAL
extern float tcxoVoltage; // make this available everywhere
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -14,7 +14,9 @@ lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
zinggjm/GxEPD2@^1.5.1 zinggjm/GxEPD2@^1.5.1
adafruit/Adafruit NeoPixel @ ^1.12.0 adafruit/Adafruit NeoPixel @ ^1.12.0
build_unflags = -DARDUINO_USB_MODE=1 build_unflags =
${esp32s3_base.build_unflags}
-DARDUINO_USB_MODE=1
build_flags = build_flags =
;${esp32_base.build_flags} -D MY_ESP32S3_DIY -I variants/my_esp32s3_diy_eink ;${esp32_base.build_flags} -D MY_ESP32S3_DIY -I variants/my_esp32s3_diy_eink
${esp32_base.build_flags} -D PRIVATE_HW -I variants/my_esp32s3_diy_eink ${esp32_base.build_flags} -D PRIVATE_HW -I variants/my_esp32s3_diy_eink

View File

@ -13,7 +13,9 @@ platform_packages =
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
adafruit/Adafruit NeoPixel @ ^1.12.0 adafruit/Adafruit NeoPixel @ ^1.12.0
build_unflags = -DARDUINO_USB_MODE=1 build_unflags =
${esp32s3_base.build_unflags}
-DARDUINO_USB_MODE=1
build_flags = build_flags =
;${esp32_base.build_flags} -D MY_ESP32S3_DIY -I variants/my_esp32s3_diy_oled ;${esp32_base.build_flags} -D MY_ESP32S3_DIY -I variants/my_esp32s3_diy_oled
${esp32_base.build_flags} -D PRIVATE_HW -I variants/my_esp32s3_diy_oled ${esp32_base.build_flags} -D PRIVATE_HW -I variants/my_esp32s3_diy_oled

View File

@ -70,5 +70,8 @@
#define SX126X_RESET LORA_RESET #define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO2_AS_RF_SWITCH
#define TCXO_OPTIONAL // handle Indicator V1 and V2
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define USE_VIRTUAL_KEYBOARD 1 #define USE_VIRTUAL_KEYBOARD 1
#define DISPLAY_CLOCK_FRAME 1 #define DISPLAY_CLOCK_FRAME 1