Skip to content

Commit

Permalink
Merge branch 'meshtastic:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Mictronics authored Jan 30, 2025
2 parents 20d92f3 + b5cad2b commit bb7d9c0
Show file tree
Hide file tree
Showing 30 changed files with 225 additions and 89 deletions.
4 changes: 3 additions & 1 deletion bin/config-dist.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ Lora:
# TXen: x # TX and RX enable pins
# RXen: x

# SX126X_MAX_POWER: 8 # Limit the output power to 8 dBm, useful for amped nodes

# spiSpeed: 2000000

### Set default/fallback gpio chip to use in /dev/. Defaults to 0.
Expand Down Expand Up @@ -188,4 +190,4 @@ General:
MaxMessageQueue: 100
ConfigDirectory: /etc/meshtasticd/config.d/
# MACAddress: AA:BB:CC:DD:EE:FF
# MACAddressSource: eth0
# MACAddressSource: eth0
3 changes: 3 additions & 0 deletions bin/config.d/lora-MeshAdv-900M30S.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ Lora:
TXen: 13
RXen: 12
DIO3_TCXO_VOLTAGE: true
# Only for E22-900M33S:
# Limit the output power to 8 dBm
# SX126X_MAX_POWER: 8
2 changes: 1 addition & 1 deletion bin/platformio-custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def esp32_create_combined_bin(source, target, env):
for pref in userPrefs:
if userPrefs[pref].startswith("{"):
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])
elif userPrefs[pref] == "true" or userPrefs[pref] == "false":
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
Expand Down
22 changes: 11 additions & 11 deletions src/RedirectablePrint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,17 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
}
if (color && logLevel != nullptr) {
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)
Print::write("\u001b[32m", 6);
Print::write("\u001b[32m", 5);
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)
Print::write("\u001b[31m", 6);
Print::write("\u001b[31m", 5);
}
len = Print::write(printBuf, len);
if (color && logLevel != nullptr) {
Print::write("\u001b[0m", 5);
Print::write("\u001b[0m", 4);
}
return len;
}
Expand All @@ -107,15 +107,15 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
// include the header
if (color) {
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)
Print::write("\u001b[32m", 6);
Print::write("\u001b[32m", 5);
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)
Print::write("\u001b[31m", 6);
Print::write("\u001b[31m", 5);
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
Expand Down Expand Up @@ -393,4 +393,4 @@ std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...)
break;
}
return std::string(formatted.get());
}
}
91 changes: 79 additions & 12 deletions src/graphics/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static bool heartbeat = false;

#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)
{
#if defined(OLED_PL) || defined(OLED_UA) || defined(OLED_RU) || defined(OLED_CS)
Expand Down Expand Up @@ -162,11 +162,7 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl

display->setFont(FONT_MEDIUM);
display->setTextAlignment(TEXT_ALIGN_LEFT);
#ifdef USERPREFS_SPLASH_TITLE
const char *title = USERPREFS_SPLASH_TITLE;
#else
const char *title = "meshtastic.org";
#endif
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
display->setFont(FONT_SMALL);

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

#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)
{
uint16_t x_offset = display->width() / 2;
Expand Down Expand Up @@ -1658,6 +1704,10 @@ void Screen::setup()
// Set the utf8 conversion function
dispdev->setFontTableLookupFunction(customFontTableLookup);

#ifdef USERPREFS_OEM_TEXT
logo_timeout *= 2; // Double the time if we have a custom logo
#endif

// Add frames.
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST);
alertFrames[0] = [this](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
Expand Down Expand Up @@ -1803,6 +1853,22 @@ int32_t Screen::runOnce()
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
if (showingNormalScreen && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
setWelcomeFrames();
Expand Down Expand Up @@ -2662,13 +2728,14 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)

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) {
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;
Expand Down Expand Up @@ -2755,4 +2822,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN
#endif // HAS_SCREEN
38 changes: 18 additions & 20 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,6 @@ AccelerometerThread *accelerometerThread = nullptr;
AudioThread *audioThread = nullptr;
#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;

volatile static const char slipstreamTZString[] = USERPREFS_TZ_STRING;
Expand Down Expand Up @@ -928,43 +924,45 @@ void setup()

#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)) {
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
auto *sxIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
#ifdef SX126X_DIO3_TCXO_VOLTAGE
sxIf->setTCXOVoltage(SX126X_DIO3_TCXO_VOLTAGE);
#endif
if (!sxIf->init()) {
LOG_WARN("No SX1262 radio");
delete rIf;
rIf = NULL;
delete sxIf;
} else {
LOG_INFO("SX1262 init success");
rIf = sxIf;
radioType = SX1262_RADIO;
}
}
#endif

#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && defined(TCXO_OPTIONAL)
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
// Try using the specified TCXO voltage
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) {
LOG_WARN("No SX1262 radio with TCXO, Vref %f V", tcxoVoltage);
delete rIf;
rIf = NULL;
tcxoVoltage = 0; // if it fails, set the TCXO voltage to zero for the next attempt
// try using the specified TCXO voltage
auto *sxIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
sxIf->setTCXOVoltage(SX126X_DIO3_TCXO_VOLTAGE);
if (!sxIf->init()) {
LOG_WARN("No SX1262 radio with TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE);
delete sxIf;
} 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;
}
}

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);
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;
rIf = NULL;
tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; // if it fails, set the TCXO voltage back for the next radio search
} else {
LOG_INFO("SX1262 init success, XTAL, Vref %f V", tcxoVoltage);
LOG_INFO("SX1262 init success, XTAL, Vref 0.0V");
radioType = SX1262_RADIO;
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/mesh/LR11x0Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
// 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
#define LR1110_MAX_POWER 22
#endif

// the 2.4G part maxes at 13dBm

#if ARCH_PORTDUINO
#define LR1120_MAX_POWER settingsMap[lr1120_max_power]
#endif
#ifndef LR1120_MAX_POWER
#define LR1120_MAX_POWER 13
#endif
Expand Down
10 changes: 10 additions & 0 deletions src/mesh/MeshModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
std::vector<MeshModule *> *MeshModule::modules;

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
Expand All @@ -35,6 +36,15 @@ MeshModule::~MeshModule()
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,
uint8_t hopLimit)
{
Expand Down
9 changes: 9 additions & 0 deletions src/mesh/MeshModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <OLEDDisplayUi.h>
#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
*
* Use ProcessMessage::CONTINUE to allows other modules to process a message.
Expand Down Expand Up @@ -119,6 +122,12 @@ class MeshModule
*/
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.
*/
Expand Down
5 changes: 4 additions & 1 deletion src/mesh/RF95Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include "PortduinoGlue.h"
#endif

#if ARCH_PORTDUINO
#define RF95_MAX_POWER settingsMap[rf95_max_power]
#endif
#ifndef RF95_MAX_POWER
#define RF95_MAX_POWER 20
#endif
Expand Down Expand Up @@ -337,4 +340,4 @@ bool RF95Interface::sleep()

return true;
}
#endif
#endif
Loading

0 comments on commit bb7d9c0

Please sign in to comment.