Merge branch 'master' into XEdDSA

This commit is contained in:
Jonathan Bennett
2025-08-19 14:42:09 -05:00
committed by GitHub
37 changed files with 758 additions and 88 deletions
+8
View File
@@ -89,14 +89,22 @@ class BluetoothStatus : public Status
case ConnectionState::CONNECTED:
LOG_DEBUG("BluetoothStatus CONNECTED");
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, LOW);
#else
digitalWrite(BLE_LED, HIGH);
#endif
#endif
break;
case ConnectionState::DISCONNECTED:
LOG_DEBUG("BluetoothStatus DISCONNECTED");
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, HIGH);
#else
digitalWrite(BLE_LED, LOW);
#endif
#endif
break;
}
+4
View File
@@ -140,6 +140,10 @@ bool playNextLeadUpNote()
playTones(&note, 1); // Play single note using existing playTones function
leadUpNoteIndex++;
if (leadUpNoteIndex >= leadUpNotesCount) {
return false; // this was the final note
}
return true; // Note was played (playTones handles buzzer availability internally)
}
+2 -2
View File
@@ -140,13 +140,13 @@ bool EInkDisplay::connect()
#endif
#endif
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1)
#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE)
{
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init();
#ifdef ELECROW_ThinkNode_M1
#if defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE)
adafruitDisplay->setRotation(4);
#else
adafruitDisplay->setRotation(3);
+10 -12
View File
@@ -365,9 +365,6 @@ void Screen::doDeepSleep()
{
#ifdef USE_EINK
setOn(false, graphics::UIRenderer::drawDeepSleepFrame);
#ifdef PIN_EINK_EN
digitalWrite(PIN_EINK_EN, LOW); // power off backlight
#endif
#else
// Without E-Ink display:
setOn(false);
@@ -391,8 +388,12 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
dispdev->displayOn();
#endif
#ifdef ELECROW_ThinkNode_M5
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
#ifdef PIN_EINK_EN
if (uiconfig.screen_brightness == 1)
digitalWrite(PIN_EINK_EN, HIGH);
#elif defined(PCA_PIN_EINK_EN)
if (uiconfig.screen_brightness == 1)
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
#endif
#if defined(ST7789_CS) && \
@@ -424,13 +425,10 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
// eInkScreensaver parameter is usually NULL (default argument), default frame used instead
setScreensaverFrames(einkScreensaver);
#endif
#ifdef ELECROW_ThinkNode_M1
if (digitalRead(PIN_EINK_EN) == HIGH) {
digitalWrite(PIN_EINK_EN, LOW);
}
#endif
#ifdef ELECROW_ThinkNode_M5
#ifdef PIN_EINK_EN
digitalWrite(PIN_EINK_EN, LOW);
#elif defined(PCA_PIN_EINK_EN)
io.digitalWrite(PCA_PIN_EINK_EN, LOW);
#endif
@@ -694,7 +692,7 @@ int32_t Screen::runOnce()
#ifndef DISABLE_WELCOME_UNSET
if (!NotificationRenderer::isOverlayBannerShowing() && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
menuHandler::LoraRegionPicker(0);
menuHandler::OnboardMessage();
}
#endif
if (!NotificationRenderer::isOverlayBannerShowing() && rebootAtMsec != 0) {
+23 -3
View File
@@ -849,9 +849,29 @@ static LGFX *tft = nullptr;
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
class PanelInit_ST7701 : public lgfx::Panel_ST7701
{
public:
const uint8_t *getInitCommands(uint8_t listno) const override
{
// 180 degree hw rotation: vertical flip, horizontal flip
static constexpr const uint8_t list1[] = {0x36, 1, 0x10, // MADCTL for vertical flip
0xFF, 5, 0x77, 0x01, 0x00, 0x00, 0x10, // Command2 BK0 SEL
0xC7, 1, 0x04, // SDIR: X-direction Control (Horizontal Flip)
0xFF, 5, 0x77, 0x01, 0x00, 0x00, 0x00, // Command2 BK0 DIS
0xFF, 0xFF};
switch (listno) {
case 1:
return list1;
default:
return lgfx::Panel_ST7701::getInitCommands(listno);
}
}
};
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ST7701 _panel_instance;
PanelInit_ST7701 _panel_instance;
lgfx::Bus_RGB _bus_instance;
lgfx::Light_PWM _light_instance;
lgfx::Touch_FT5x06 _touch_instance;
@@ -1184,9 +1204,9 @@ bool TFTDisplay::connect()
attachInterrupt(digitalPinToInterrupt(SCREEN_TOUCH_INT), rak14014_tpIntHandle, FALLING);
#elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2)
tft->setRotation(1); // T-Deck has the TFT in landscape
#elif defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR)
#elif defined(T_WATCH_S3)
tft->setRotation(2); // T-Watch S3 left-handed orientation
#elif ARCH_PORTDUINO
#elif ARCH_PORTDUINO || defined(SENSECAP_INDICATOR)
tft->setRotation(0); // use config.yaml to set rotation
#else
tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
+39 -3
View File
@@ -26,6 +26,27 @@ menuHandler::screenMenus menuHandler::menuQueue = menu_none;
bool test_enabled = false;
uint8_t test_count = 0;
void menuHandler::OnboardMessage()
{
static const char *optionsArray[] = {"OK", "Got it!"};
enum optionsNumbers { OK, got };
BannerOverlayOptions bannerOptions;
#if HAS_TFT
bannerOptions.message = "Welcome to Meshtastic!\nSwipe to navigate and\nlong press to select\nor open a menu.";
#elif defined(BUTTON_PIN)
bannerOptions.message = "Welcome to Meshtastic!\nClick to navigate and\nlong press to select\nor open a menu.";
#else
bannerOptions.message = "Welcome to Meshtastic!\nUse the Select button\nto open menus\nand make selections.";
#endif
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 2;
bannerOptions.bannerCallback = [](int selected) -> void {
menuHandler::menuQueue = menuHandler::no_timeout_lora_picker;
screen->runNow();
};
screen->showOverlayBanner(bannerOptions);
}
void menuHandler::LoraRegionPicker(uint32_t duration)
{
static const char *optionsArray[] = {"Back",
@@ -301,7 +322,7 @@ void menuHandler::homeBaseMenu()
static int optionsEnumArray[enumEnd] = {Back};
int options = 1;
#ifdef PIN_EINK_EN
#if defined(PIN_EINK_EN) || defined(PCA_PIN_EINK_EN)
optionsArray[options] = "Toggle Backlight";
optionsEnumArray[options++] = Backlight;
#else
@@ -325,12 +346,24 @@ void menuHandler::homeBaseMenu()
bannerOptions.optionsCount = options;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == Backlight) {
#ifdef PIN_EINK_EN
if (digitalRead(PIN_EINK_EN) == HIGH) {
#if defined(PIN_EINK_EN)
if (uiconfig.screen_brightness == 1) {
uiconfig.screen_brightness = 0;
digitalWrite(PIN_EINK_EN, LOW);
} else {
uiconfig.screen_brightness = 1;
digitalWrite(PIN_EINK_EN, HIGH);
}
saveUIConfig();
#elif defined(PCA_PIN_EINK_EN)
if (uiconfig.screen_brightness == 1) {
uiconfig.screen_brightness = 0;
io.digitalWrite(PCA_PIN_EINK_EN, LOW);
} else {
uiconfig.screen_brightness = 1;
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
}
saveUIConfig();
#endif
} else if (selected == Sleep) {
screen->setOn(false);
@@ -1103,6 +1136,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
case lora_picker:
LoraRegionPicker();
break;
case no_timeout_lora_picker:
LoraRegionPicker(0);
break;
case TZ_picker:
TZPicker();
break;
+2
View File
@@ -10,6 +10,7 @@ class menuHandler
enum screenMenus {
menu_none,
lora_picker,
no_timeout_lora_picker,
TZ_picker,
twelve_hour_picker,
clock_face_picker,
@@ -41,6 +42,7 @@ class menuHandler
};
static screenMenus menuQueue;
static void OnboardMessage();
static void LoraRegionPicker(uint32_t duration = 30000);
static void handleMenuSwitch(OLEDDisplay *display);
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
+6 -1
View File
@@ -383,7 +383,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
uint8_t firstOptionToShow = 0;
if (alertBannerOptions > 0) {
if (curSelected > 1 && alertBannerOptions > visibleTotalLines - lineCount) {
if (visibleTotalLines - lineCount == 1) {
firstOptionToShow = curSelected;
} else if (curSelected > 1 && alertBannerOptions > visibleTotalLines - lineCount) {
if (curSelected > alertBannerOptions - visibleTotalLines + lineCount)
firstOptionToShow = alertBannerOptions - visibleTotalLines + lineCount;
else
@@ -392,6 +394,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
firstOptionToShow = 0;
}
}
// Useful log line for troubleshooting:
/* LOG_WARN("alertBannerOptions: %u, curSelected: %u, visibleTotalLines: %u, lineCount: %u, firstOptionToShow: %u",
alertBannerOptions, curSelected, visibleTotalLines, lineCount, firstOptionToShow); */
for (int i = firstOptionToShow; i < alertBannerOptions && linesShown < visibleTotalLines; i++, linesShown++) {
if (i == curSelected) {
+9 -5
View File
@@ -92,8 +92,11 @@ bool ButtonThread::initButton(const ButtonConfig &config)
if (config.shortLong != INPUT_BROKER_NONE) {
_shortLong = config.shortLong;
}
#ifdef USE_EINK
userButton.setDebounceMs(0);
#else
userButton.setDebounceMs(1);
#endif
userButton.setPressMs(_longPressTime);
if (screen) {
@@ -137,8 +140,7 @@ int32_t ButtonThread::runOnce()
}
// Progressive lead-up sound system
if (buttonCurrentlyPressed && (millis() - buttonPressStartTime) >= BUTTON_LEADUP_MS &&
(millis() - buttonPressStartTime) < _longLongPressTime) {
if (buttonCurrentlyPressed && (millis() - buttonPressStartTime) >= BUTTON_LEADUP_MS) {
// Start the progressive sequence if not already active
if (!leadUpSequenceActive) {
@@ -150,13 +152,14 @@ int32_t ButtonThread::runOnce()
else if ((millis() - lastLeadUpNoteTime) >= 400) { // 400ms interval between notes
if (playNextLeadUpNote()) {
lastLeadUpNoteTime = millis();
} else {
leadUpPlayed = true;
}
}
}
// Reset when button is released
if (!buttonCurrentlyPressed && buttonWasPressed) {
leadUpPlayed = false;
leadUpSequenceActive = false;
resetLeadUpSequence();
}
@@ -253,12 +256,13 @@ int32_t ButtonThread::runOnce()
LOG_INFO("LONG PRESS RELEASE AFTER %u MILLIS", millis() - buttonPressStartTime);
if (millis() > 30000 && _longLongPress != INPUT_BROKER_NONE &&
(millis() - buttonPressStartTime) >= _longLongPressTime) {
(millis() - buttonPressStartTime) >= _longLongPressTime && leadUpPlayed) {
evt.inputEvent = _longLongPress;
this->notifyObservers(&evt);
}
// Reset combination tracking
waitingForLongPress = false;
leadUpPlayed = false;
break;
}
+1 -1
View File
@@ -92,7 +92,7 @@ class ButtonThread : public Observable<const InputEvent *>, public concurrency::
voidFuncPtr _intRoutine = nullptr;
uint16_t _longPressTime = 500;
uint16_t _longLongPressTime = 5000;
uint16_t _longLongPressTime = 3900;
int _pinNum = 0;
bool _activeLow = true;
bool _touchQuirk = false;
+4 -1
View File
@@ -304,7 +304,6 @@ void setup()
Wire.begin(48, 47);
io.pinMode(PCA_PIN_EINK_EN, OUTPUT);
io.pinMode(PCA_PIN_POWER_EN, OUTPUT);
io.digitalWrite(PCA_PIN_EINK_EN, HIGH);
io.digitalWrite(PCA_PIN_POWER_EN, HIGH);
// io.pinMode(C2_PIN, OUTPUT);
#endif
@@ -326,8 +325,12 @@ void setup()
#ifdef BLE_LED
pinMode(BLE_LED, OUTPUT);
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, HIGH);
#else
digitalWrite(BLE_LED, LOW);
#endif
#endif
#if defined(T_DECK)
// GPIO10 manages all peripheral power supplies
+6 -9
View File
@@ -6,6 +6,10 @@
#include "mesh/NodeDB.h"
#ifdef LR11X0_DIO_AS_RF_SWITCH
#include "rfswitch.h"
#elif ARCH_PORTDUINO
#include "PortduinoGlue.h"
#define rfswitch_dio_pins portduino_config.rfswitch_dio_pins
#define rfswitch_table portduino_config.rfswitch_table
#else
static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
@@ -14,10 +18,6 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
};
#endif
#ifdef ARCH_PORTDUINO
#include "PortduinoGlue.h"
#endif
// 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
@@ -117,17 +117,14 @@ template <typename T> bool LR11x0Interface<T>::init()
#ifdef LR11X0_DIO_AS_RF_SWITCH
bool dioAsRfSwitch = true;
#elif defined(ARCH_PORTDUINO)
bool dioAsRfSwitch = false;
if (settingsMap[dio2_as_rf_switch]) {
dioAsRfSwitch = true;
}
bool dioAsRfSwitch = portduino_config.has_rfswitch_table;
#else
bool dioAsRfSwitch = false;
#endif
if (dioAsRfSwitch) {
lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
LOG_DEBUG("Set DIO RF switch", res);
LOG_DEBUG("Set DIO RF switch");
}
if (res == RADIOLIB_ERR_NONE) {
+21 -12
View File
@@ -1616,24 +1616,33 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
// Alert the user if a remote node is advertising public key that matches our own
if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0 && !duplicateWarned) {
duplicateWarned = true;
char warning[] = "Remote device %s has advertised your public key. This may indicate a compromised key. You may need "
"to regenerate your public keys.";
LOG_WARN(warning, p.long_name);
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
sprintf(cn->message, warning, p.long_name);
service->sendClientNotification(cn);
if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0) {
if (!duplicateWarned) {
duplicateWarned = true;
char warning[] =
"Remote device %s has advertised your public key. This may indicate a compromised key. You may need "
"to regenerate your public keys.";
LOG_WARN(warning, p.long_name);
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING;
cn->time = getValidTime(RTCQualityFromNet);
sprintf(cn->message, warning, p.long_name);
service->sendClientNotification(cn);
}
return false;
}
}
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
if (info->user.public_key.size == 32) { // if we have a key for this user already, don't overwrite with a new one
// if the key doesn't match, don't update nodeDB at all.
if (p.public_key.size != 32 || (memcmp(p.public_key.bytes, info->user.public_key.bytes, 32) != 0)) {
LOG_WARN("Public Key mismatch, dropping NodeInfo");
return false;
}
LOG_INFO("Public Key set for node, not updating!");
// we copy the key into the incoming packet, to prevent overwrite
p.public_key.size = 32;
memcpy(p.public_key.bytes, info->user.public_key.bytes, 32);
} else if (p.public_key.size > 0) {
} else if (p.public_key.size == 32) {
LOG_INFO("Update Node Pubkey!");
}
#endif
+6 -6
View File
@@ -192,12 +192,6 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
size_t PhoneAPI::getFromRadio(uint8_t *buf)
{
if (!available()) {
return 0;
}
// In case we send a FromRadio packet
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
// Respond to heartbeat by sending queue status
if (heartbeatReceived) {
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
@@ -209,6 +203,12 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
return numbytes;
}
if (!available()) {
return 0;
}
// In case we send a FromRadio packet
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
// Advance states as needed
switch (state) {
case STATE_SEND_NOTHING:
+4 -2
View File
@@ -548,8 +548,10 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
// is not in the local nodedb
// First, only PKC encrypt packets we are originating
if (isFromUs(p) &&
// Don't use PKC with simulator
radioType != SIM_RADIO &&
#if ARCH_PORTDUINO
// Sim radio via the cli flag skips PKC
!portduino_config.force_simradio &&
#endif
// Don't use PKC with Ham mode
!owner.is_licensed &&
// Don't use PKC if it's not explicitly requested and a non-primary channel is requested
+2
View File
@@ -270,6 +270,8 @@ typedef enum _meshtastic_HardwareModel {
/* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices.
https://heltec.org/project/meshsolar/ */
meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108,
/* Lilygo T-Echo Lite */
meshtastic_HardwareModel_T_ECHO_LITE = 109,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
+5 -3
View File
@@ -99,7 +99,9 @@ typedef enum _meshtastic_TelemetrySensorType {
/* Sensirion SFA30 Formaldehyde sensor */
meshtastic_TelemetrySensorType_SFA30 = 42,
/* SEN5X PM SENSORS */
meshtastic_TelemetrySensorType_SEN5X = 43
meshtastic_TelemetrySensorType_SEN5X = 43,
/* TSL2561 light sensor */
meshtastic_TelemetrySensorType_TSL2561 = 44
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@@ -434,8 +436,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SEN5X
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SEN5X+1))
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_TSL2561
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_TSL2561+1))
+7 -7
View File
@@ -60,7 +60,7 @@
SerialModule *serialModule;
SerialModuleRadio *serialModuleRadio;
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
#if defined(TTGO_T_ECHO) || defined(T_ECHO_LITE) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
defined(ELECROW_ThinkNode_M5)
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {}
static Print *serialPrint = &Serial;
@@ -179,8 +179,8 @@ int32_t SerialModule::runOnce()
Serial.begin(baud);
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
}
#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
!defined(ELECROW_ThinkNode_M5)
#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
@@ -236,8 +236,8 @@ int32_t SerialModule::runOnce()
}
}
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \
!defined(ELECROW_ThinkNode_M5)
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
processWXSerial();
@@ -496,8 +496,8 @@ ParsedLine parseLine(const char *line)
*/
void SerialModule::processWXSerial()
{
#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && \
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
static unsigned int lastAveraged = 0;
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
static double dir_sum_sin = 0;
+4 -1
View File
@@ -223,9 +223,12 @@ void NimbleBluetooth::deinit()
LOG_INFO("Disable bluetooth until reboot");
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, HIGH);
#else
digitalWrite(BLE_LED, LOW);
#endif
#endif
NimBLEDevice::deinit();
#endif
}
+2
View File
@@ -60,6 +60,8 @@
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
#elif defined(TTGO_T_ECHO)
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
#elif defined(T_ECHO_LITE)
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE
#elif defined(ELECROW_ThinkNode_M1)
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
#elif defined(NANO_G2_ULTRA)
+45 -3
View File
@@ -29,11 +29,11 @@
std::map<configNames, int> settingsMap;
std::map<configNames, std::string> settingsStrings;
portduino_config_struct portduino_config;
std::ofstream traceFile;
Ch341Hal *ch341Hal = nullptr;
char *configPath = nullptr;
char *optionMac = nullptr;
bool forceSimulated = false;
bool verboseEnabled = false;
const char *argp_program_version = optstr(APP_VERSION);
@@ -66,7 +66,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
configPath = arg;
break;
case 's':
forceSimulated = true;
portduino_config.force_simradio = true;
break;
case 'h':
optionMac = arg;
@@ -189,7 +189,7 @@ void portduinoSetup()
YAML::Node yamlConfig;
if (forceSimulated == true) {
if (portduino_config.force_simradio == true) {
settingsMap[use_simradio] = true;
} else if (configPath != nullptr) {
if (loadConfig(configPath)) {
@@ -553,6 +553,48 @@ bool loadConfig(const char *configPath)
}
}
}
if (yamlConfig["Lora"]["rfswitch_table"]) {
portduino_config.has_rfswitch_table = true;
portduino_config.rfswitch_table[0].mode = LR11x0::MODE_STBY;
portduino_config.rfswitch_table[1].mode = LR11x0::MODE_RX;
portduino_config.rfswitch_table[2].mode = LR11x0::MODE_TX;
portduino_config.rfswitch_table[3].mode = LR11x0::MODE_TX_HP;
portduino_config.rfswitch_table[4].mode = LR11x0::MODE_TX_HF;
portduino_config.rfswitch_table[5].mode = LR11x0::MODE_GNSS;
portduino_config.rfswitch_table[6].mode = LR11x0::MODE_WIFI;
portduino_config.rfswitch_table[7] = END_OF_MODE_TABLE;
for (int i = 0; i < 5; i++) {
// set up the pin array first
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO5")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO5;
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO6")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO6;
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO7")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO7;
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO8")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO8;
if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as<std::string>("") == "DIO10")
portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO10;
// now fill in the table
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_STBY"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[0].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_RX"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[1].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[2].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HP"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[3].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HF"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[4].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_GNSS"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[5].values[i] = HIGH;
if (yamlConfig["Lora"]["rfswitch_table"]["MODE_WIFI"][i].as<std::string>("") == "HIGH")
portduino_config.rfswitch_table[6].values[i] = HIGH;
}
}
}
if (yamlConfig["GPIO"]) {
settingsMap[userButtonPin] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
+10 -1
View File
@@ -3,6 +3,8 @@
#include <map>
#include <unordered_map>
#include "LR11x0Interface.h"
#include "Module.h"
#include "platform/portduino/USBHal.h"
// Product strings for auto-configuration
@@ -126,4 +128,11 @@ bool loadConfig(const char *configPath);
static bool ends_with(std::string_view str, std::string_view suffix);
void getMacAddr(uint8_t *dmac);
bool MAC_from_string(std::string mac_str, uint8_t *dmac);
std::string exec(const char *cmd);
std::string exec(const char *cmd);
extern struct portduino_config_struct {
bool has_rfswitch_table = false;
uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
Module::RfSwitchMode_t rfswitch_table[8];
bool force_simradio = false;
} portduino_config;