Merge remote-tracking branch 'origin/2.5-changes' into 2.5-changes

This commit is contained in:
Jonathan Bennett 2024-08-14 18:56:41 -05:00
commit 36f1a62b0b
40 changed files with 548 additions and 207 deletions

View File

@ -0,0 +1,208 @@
/*
* lfs utility functions
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
// MESHTASTIC/@geeksville note: This file is copied from the Adafruit nrf52 arduino lib. And we use a special -include in
// nrf52.ini to load it before EVERY file we do this hack because the default definitions for LFS_ASSERT are quite poor and we
// don't want to fork the adafruit lib (again) and send in a PR that they probably won't merge anyways. This file might break if
// they ever update lfs.util on their side, in which case we'll need to update this file to match their new version. The version
// this is a copy from is almost exactly
// https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/c25d93268a3b9c23e9a1ccfcaf9b208beca624ca/libraries/Adafruit_LittleFS/src/littlefs/lfs_util.h
#ifndef LFS_UTIL_H
#define LFS_UTIL_H
// Users can override lfs_util.h with their own configuration by defining
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
//
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
// provided by the config file. To start I would suggest copying lfs_util.h and
// modifying as needed.
#ifdef LFS_CONFIG
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
#define LFS_STRINGIZE2(x) #x
#include LFS_STRINGIZE(LFS_CONFIG)
#else
// System includes
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#ifndef LFS_NO_MALLOC
#include <stdlib.h>
#endif
#ifndef LFS_NO_ASSERT
#include <assert.h>
#endif
#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR)
#include <stdio.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Macros, may be replaced by system specific wrappers. Arguments to these
// macros must not have side-effects as the macros can be removed for a smaller
// code footprint
// Logging functions
#ifndef LFS_NO_DEBUG
void logLegacy(const char *level, const char *fmt, ...);
#define LFS_DEBUG(fmt, ...) logLegacy("DEBUG", "lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
#define LFS_DEBUG(fmt, ...)
#endif
#ifndef LFS_NO_WARN
#define LFS_WARN(fmt, ...) logLegacy("WARN", "lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
#define LFS_WARN(fmt, ...)
#endif
#ifndef LFS_NO_ERROR
#define LFS_ERROR(fmt, ...) logLegacy("ERROR", "lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
#else
#define LFS_ERROR(fmt, ...)
#endif
// Runtime assertions
#ifndef LFS_NO_ASSERT
#define LFS_ASSERT(test) assert(test)
#else
extern void lfs_assert(const char *reason);
#define LFS_ASSERT(test) \
if (!(test)) \
lfs_assert(#test)
#endif
// Builtin functions, these may be replaced by more efficient
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
// expensive basic C implementation for debugging purposes
// Min/max functions for unsigned 32-bit numbers
static inline uint32_t lfs_max(uint32_t a, uint32_t b)
{
return (a > b) ? a : b;
}
static inline uint32_t lfs_min(uint32_t a, uint32_t b)
{
return (a < b) ? a : b;
}
// Find the next smallest power of 2 less than or equal to a
static inline uint32_t lfs_npw2(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return 32 - __builtin_clz(a - 1);
#else
uint32_t r = 0;
uint32_t s;
a -= 1;
s = (a > 0xffff) << 4;
a >>= s;
r |= s;
s = (a > 0xff) << 3;
a >>= s;
r |= s;
s = (a > 0xf) << 2;
a >>= s;
r |= s;
s = (a > 0x3) << 1;
a >>= s;
r |= s;
return (r | (a >> 1)) + 1;
#endif
}
// Count the number of trailing binary zeros in a
// lfs_ctz(0) may be undefined
static inline uint32_t lfs_ctz(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
return __builtin_ctz(a);
#else
return lfs_npw2((a & -a) + 1) - 1;
#endif
}
// Count the number of binary ones in a
static inline uint32_t lfs_popc(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return __builtin_popcount(a);
#else
a = a - ((a >> 1) & 0x55555555);
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
#endif
}
// Find the sequence comparison of a and b, this is the distance
// between a and b ignoring overflow
static inline int lfs_scmp(uint32_t a, uint32_t b)
{
return (int)(unsigned)(a - b);
}
// Convert from 32-bit little-endian to native order
static inline uint32_t lfs_fromle32(uint32_t a)
{
#if !defined(LFS_NO_INTRINSICS) && ((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \
(defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
return a;
#elif !defined(LFS_NO_INTRINSICS) && \
((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
return __builtin_bswap32(a);
#else
return (((uint8_t *)&a)[0] << 0) | (((uint8_t *)&a)[1] << 8) | (((uint8_t *)&a)[2] << 16) | (((uint8_t *)&a)[3] << 24);
#endif
}
// Convert to 32-bit little-endian from native order
static inline uint32_t lfs_tole32(uint32_t a)
{
return lfs_fromle32(a);
}
// Calculate CRC-32 with polynomial = 0x04c11db7
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
// Allocate memory, only used if buffers are not provided to littlefs
static inline void *lfs_malloc(size_t size)
{
#ifndef LFS_NO_MALLOC
extern void *pvPortMalloc(size_t xWantedSize);
return pvPortMalloc(size);
#else
(void)size;
return NULL;
#endif
}
// Deallocate memory, only used if buffers are not provided to littlefs
static inline void lfs_free(void *p)
{
#ifndef LFS_NO_MALLOC
extern void vPortFree(void *pv);
vPortFree(p);
#else
(void)p;
#endif
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
#endif

View File

@ -2,9 +2,13 @@
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
platform = platformio/nordicnrf52@^10.5.0
extends = arduino_base
platform_packages =
; our custom Git version until they merge our PR
framework-arduinoadafruitnrf52 @ https://github.com/geeksville/Adafruit_nRF52_Arduino.git
build_type = debug
build_flags =
build_flags =
-include arch/nrf52/cpp_overrides/lfs_util.h
${arduino_base.build_flags}
-DSERIAL_BUFFER_SIZE=1024
-Wno-unused-variable

View File

@ -12,6 +12,7 @@ build_flags =
-flto
-Isrc/platform/stm32wl -g
-DMESHTASTIC_MINIMIZE_BUILD
-DMESHTASTIC_EXCLUDE_GPS
-DDEBUG_MUTE
; -DVECT_TAB_OFFSET=0x08000000
-DconfigUSE_CMSIS_RTOS_V2=1
@ -21,7 +22,7 @@ build_flags =
-fdata-sections
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> -<mesh/raspihttp>
board_upload.offset_address = 0x08000000
upload_protocol = stlink
@ -33,4 +34,4 @@ lib_deps =
lib_ignore =
https://github.com/mathertel/OneButton@~2.6.1
Wire
Wire

View File

@ -5,16 +5,24 @@ Import("env")
# NOTE: This is not currently used, but can serve as an example on how to write extra_scripts
print("Current CLI targets", COMMAND_LINE_TARGETS)
print("Current Build targets", BUILD_TARGETS)
print("CPP defs", env.get("CPPDEFINES"))
# print("Current CLI targets", COMMAND_LINE_TARGETS)
# print("Current Build targets", BUILD_TARGETS)
# print("CPP defs", env.get("CPPDEFINES"))
# print(env.Dump())
# Adafruit.py in the platformio build tree is a bit naive and always enables their USB stack for building. We don't want this.
# So come in after that python script has run and disable it. This hack avoids us having to fork that big project and send in a PR
# which might not be accepted. -@geeksville
env["CPPDEFINES"].remove("USBCON")
env["CPPDEFINES"].remove("USE_TINYUSB")
lib_builders = env.get("__PIO_LIB_BUILDERS", None)
if lib_builders is not None:
print("Disabling Adafruit USB stack")
for k in lib_builders:
if k.name == "Adafruit TinyUSB Library":
libenv = k.env
# print(f"{k.name }: { libenv.Dump() } ")
# libenv["CPPDEFINES"].remove("USBCON")
libenv["CPPDEFINES"].remove("USE_TINYUSB")
# Custom actions when building program/firmware
# env.AddPreAction("buildprog", callback...)

View File

@ -18,10 +18,7 @@ import subprocess
import sys
from platformio.project.exception import PlatformioException
from platformio.public import (
DeviceMonitorFilterBase,
load_build_metadata,
)
from platformio.public import DeviceMonitorFilterBase, load_build_metadata
# By design, __init__ is called inside miniterm and we can't pass context to it.
# pylint: disable=attribute-defined-outside-init
@ -32,7 +29,7 @@ IS_WINDOWS = sys.platform.startswith("win")
class Esp32C3ExceptionDecoder(DeviceMonitorFilterBase):
NAME = "esp32_c3_exception_decoder"
PCADDR_PATTERN = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE)
PCADDR_PATTERN = re.compile(r"0x4[0-9a-f]{7}", re.IGNORECASE)
def __call__(self):
self.buffer = ""
@ -75,14 +72,14 @@ See https://docs.platformio.org/page/projectconf/build_configurations.html
% self.__class__.__name__
)
return False
if not os.path.isfile(self.addr2line_path):
sys.stderr.write(
"%s: disabling, addr2line at %s does not exist\n"
% (self.__class__.__name__, self.addr2line_path)
)
return False
return True
except PlatformioException as e:
sys.stderr.write(
@ -117,7 +114,7 @@ See https://docs.platformio.org/page/projectconf/build_configurations.html
trace = self.get_backtrace(m)
if len(trace) != "":
text = text[: last] + trace + text[last :]
text = text[:last] + trace + text[last:]
last += len(trace)
return text
@ -125,14 +122,10 @@ See https://docs.platformio.org/page/projectconf/build_configurations.html
def get_backtrace(self, match):
trace = "\n"
enc = "mbcs" if IS_WINDOWS else "utf-8"
args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path]
args = [self.addr2line_path, "-fipC", "-e", self.firmware_path]
try:
addr = match.group()
output = (
subprocess.check_output(args + [addr])
.decode(enc)
.strip()
)
output = subprocess.check_output(args + [addr]).decode(enc).strip()
output = output.replace(
"\n", "\n "
) # newlines happen with inlined methods

@ -1 +1 @@
Subproject commit 0c052b5d25fe8ed74c675178702f20a3fbc29afa
Subproject commit 8b5b2faf662b364754809f923271022f4f1492ed

View File

@ -26,6 +26,16 @@ SOFTWARE.*/
#include "DebugConfiguration.h"
/// A C wrapper for LOG_DEBUG that can be used from arduino C libs that don't know about C++ or meshtastic
extern "C" void logLegacy(const char *level, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (console)
console->vprintf(level, fmt, args);
va_end(args);
}
#if HAS_NETWORKING
Syslog::Syslog(UDP &client)
@ -169,4 +179,4 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
return true;
}
#endif
#endif

View File

@ -62,6 +62,9 @@
#endif
#endif
/// A C wrapper for LOG_DEBUG that can be used from arduino C libs that don't know about C++ or meshtastic
extern "C" void logLegacy(const char *level, const char *fmt, ...);
#define SYSLOG_NILVALUE "-"
#define SYSLOG_CRIT 2 /* critical conditions */

View File

@ -48,6 +48,15 @@ void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input)
}
#endif
bool lfs_assert_failed =
false; // Note: we use this global on all platforms, though it can only be set true on nrf52 (in our modified lfs_util.h)
extern "C" void lfs_assert(const char *reason)
{
LOG_ERROR("LFS assert: %s\n", reason);
lfs_assert_failed = true;
}
/**
* @brief Copies a file from one location to another.
*
@ -199,7 +208,7 @@ std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
* @param levels The number of levels of subdirectories to list.
* @param del Whether or not to delete the contents of the directory after listing.
*/
void listDir(const char *dirname, uint8_t levels, bool del = false)
void listDir(const char *dirname, uint8_t levels, bool del)
{
#ifdef FSCom
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
@ -214,7 +223,9 @@ void listDir(const char *dirname, uint8_t levels, bool del = false)
}
File file = root.openNextFile();
while (file) {
while (
file &&
file.name()[0]) { // This file.name() check is a workaround for a bug in the Adafruit LittleFS nrf52 glue (see issue 4395)
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
if (levels) {
#ifdef ARCH_ESP32
@ -313,62 +324,6 @@ void rmDir(const char *dirname)
#endif
}
bool fsCheck()
{
#if defined(ARCH_NRF52)
size_t write_size = 0;
size_t read_size = 0;
char buf[32] = {0};
Adafruit_LittleFS_Namespace::File file(FSCom);
const char *text = "meshtastic fs test";
size_t text_length = strlen(text);
const char *filename = "/meshtastic.txt";
LOG_DEBUG("Try create file .\n");
if (file.open(filename, FILE_O_WRITE)) {
write_size = file.write(text);
} else {
LOG_DEBUG("Open file failed .\n");
goto FORMAT_FS;
}
if (write_size != text_length) {
LOG_DEBUG("Text bytes do not match .\n");
file.close();
goto FORMAT_FS;
}
file.close();
if (!file.open(filename, FILE_O_READ)) {
LOG_DEBUG("Open file failed .\n");
goto FORMAT_FS;
}
read_size = file.readBytes(buf, text_length);
if (read_size != text_length) {
LOG_DEBUG("Text bytes do not match .\n");
file.close();
goto FORMAT_FS;
}
if (memcmp(buf, text, text_length) != 0) {
LOG_DEBUG("The written bytes do not match the read bytes .\n");
file.close();
goto FORMAT_FS;
}
return true;
FORMAT_FS:
LOG_DEBUG("Format FS ....\n");
FSCom.format();
FSCom.begin();
return false;
#else
return true;
#endif
}
void fsInit()
{
#ifdef FSCom
@ -378,35 +333,6 @@ void fsInit()
}
#if defined(ARCH_ESP32)
LOG_DEBUG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
#elif defined(ARCH_NRF52)
/*
* nRF52840 has a certain chance of automatic formatting failure.
* Try to create a file after initializing the file system. If the creation fails,
* it means that the file system is not working properly. Please format it manually again.
* To check the normality of the file system, you need to disable the LFS_NO_ASSERT assertion.
* Otherwise, the assertion will be entered at the moment of reading or opening, and the FS will not be formatted.
* */
bool ret = false;
uint8_t retry = 3;
while (retry--) {
ret = fsCheck();
if (ret) {
LOG_DEBUG("File system check is OK.\n");
break;
}
delay(10);
}
// It may not be possible to reach this step.
// Add a loop here to prevent unpredictable situations from happening.
// Can add a screen to display error status later.
if (!ret) {
while (1) {
LOG_ERROR("The file system is damaged and cannot proceed to the next step.\n");
delay(1000);
}
}
#else
LOG_DEBUG("Filesystem files:\n");
#endif

View File

@ -51,9 +51,13 @@ using namespace Adafruit_LittleFS_Namespace;
#endif
void fsInit();
void fsListFiles();
bool copyFile(const char *from, const char *to);
bool renameFile(const char *pathFrom, const char *pathTo);
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
void listDir(const char *dirname, uint8_t levels, bool del);
void listDir(const char *dirname, uint8_t levels, bool del = false);
void rmDir(const char *dirname);
void setupSDCard();
void setupSDCard();
extern bool lfs_assert_failed; // Note: we use this global on all platforms, though it can only be set true on nrf52 (in our
// modified lfs_util.h)

View File

@ -11,6 +11,9 @@ static File openFile(const char *filename, bool fullAtomic)
String filenameTmp = filename;
filenameTmp += ".tmp";
// clear any previous LFS errors
lfs_assert_failed = false;
return FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
}
@ -73,6 +76,9 @@ bool SafeFile::close()
/// Read our (closed) tempfile back in and compare the hash
bool SafeFile::testReadback()
{
bool lfs_failed = lfs_assert_failed;
lfs_assert_failed = false;
String filenameTmp = filename;
filenameTmp += ".tmp";
auto f2 = FSCom.open(filenameTmp.c_str(), FILE_O_READ);
@ -93,7 +99,7 @@ bool SafeFile::testReadback()
return false;
}
return true;
return !lfs_failed;
}
#endif

View File

@ -810,6 +810,13 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
powerState = newState;
LOG_INFO("GPS power state moving from %s to %s\n", getGPSPowerStateString(oldState), getGPSPowerStateString(newState));
#ifdef HELTEC_MESH_NODE_T114
if ((oldState == GPS_OFF || oldState == GPS_HARDSLEEP) && (newState != GPS_OFF && newState != GPS_HARDSLEEP)) {
_serial_gps->begin(serialSpeeds[speedSelect]);
} else if ((newState == GPS_OFF || newState == GPS_HARDSLEEP) && (oldState != GPS_OFF && oldState != GPS_HARDSLEEP)) {
_serial_gps->end();
}
#endif
switch (newState) {
case GPS_ACTIVE:
case GPS_IDLE:
@ -1220,6 +1227,14 @@ GnssModel_t GPS::probe(int serialSpeed)
return GNSS_MODEL_UC6580;
}
clearBuffer();
_serial_gps->write("$PDTINFO\r\n");
delay(750);
if (getACK("UM600", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("UM600 detected, using UC6580 Module\n");
return GNSS_MODEL_UC6580;
}
// Get version information for ATGM336H
clearBuffer();
_serial_gps->write("$PCAS06,1*1A\r\n");
@ -1822,4 +1837,4 @@ void GPS::toggleGpsMode()
enable();
}
}
#endif // Exclude GPS
#endif // Exclude GPS

View File

@ -6,6 +6,7 @@
#include <time.h>
static RTCQuality currentQuality = RTCQualityNone;
uint32_t lastSetFromPhoneNtpOrGps = 0;
RTCQuality getRTCQuality()
{
@ -121,6 +122,9 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
if (shouldSet) {
currentQuality = q;
lastSetMsec = now;
if (currentQuality >= RTCQualityNTP) {
lastSetFromPhoneNtpOrGps = now;
}
// This delta value works on all platforms
timeStartMsec = now;

View File

@ -24,6 +24,8 @@ enum RTCQuality {
RTCQuality getRTCQuality();
extern uint32_t lastSetFromPhoneNtpOrGps;
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate = false);
bool perhapsSetRTC(RTCQuality q, struct tm &t);

View File

@ -1591,6 +1591,9 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
dispdev->displayOn();
#ifdef USE_ST7789
pinMode(VTFT_CTRL, OUTPUT);
digitalWrite(VTFT_CTRL, LOW);
ui->init();
#ifdef ESP_PLATFORM
analogWrite(VTFT_LEDA, BRIGHTNESS_DEFAULT);
#else
@ -1609,10 +1612,21 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
#endif
LOG_INFO("Turning off screen\n");
dispdev->displayOff();
#ifdef USE_ST7789
pinMode(VTFT_LEDA, OUTPUT);
digitalWrite(VTFT_LEDA, !TFT_BACKLIGHT_ON);
SPI1.end();
#if defined(ARCH_ESP32)
pinMode(VTFT_LEDA, ANALOG);
pinMode(VTFT_CTRL, ANALOG);
pinMode(ST7789_RESET, ANALOG);
pinMode(ST7789_RS, ANALOG);
pinMode(ST7789_NSS, ANALOG);
#else
nrf_gpio_cfg_default(VTFT_LEDA);
nrf_gpio_cfg_default(VTFT_CTRL);
nrf_gpio_cfg_default(ST7789_RESET);
nrf_gpio_cfg_default(ST7789_RS);
nrf_gpio_cfg_default(ST7789_NSS);
#endif
#endif
#ifdef T_WATCH_S3

View File

@ -319,6 +319,14 @@ void setup()
digitalWrite(RESET_OLED, 1);
#endif
#ifdef SENSOR_POWER_CTRL_PIN
pinMode(SENSOR_POWER_CTRL_PIN, OUTPUT);
digitalWrite(SENSOR_POWER_CTRL_PIN, SENSOR_POWER_ON);
#endif
#ifdef SENSOR_GPS_CONFLICT
bool sensor_detected = false;
#endif
#ifdef PERIPHERAL_WARMUP_MS
// Some peripherals may require additional time to stabilize after power is connected
// e.g. I2C on Heltec Vision Master
@ -458,6 +466,9 @@ void setup()
LOG_INFO("No I2C devices found\n");
} else {
LOG_INFO("%i I2C devices found\n", i2cCount);
#ifdef SENSOR_GPS_CONFLICT
sensor_detected = true;
#endif
}
#ifdef ARCH_ESP32
@ -703,17 +714,24 @@ void setup()
#if !MESHTASTIC_EXCLUDE_GPS
// If we're taking on the repeater role, ignore GPS
if (HAS_GPS) {
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
gps = GPS::createGps();
if (gps) {
gpsStatus->observe(&gps->newStatus);
} else {
LOG_DEBUG("Running without GPS.\n");
#ifdef SENSOR_GPS_CONFLICT
if (sensor_detected == false) {
#endif
if (HAS_GPS) {
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
gps = GPS::createGps();
if (gps) {
gpsStatus->observe(&gps->newStatus);
} else {
LOG_DEBUG("Running without GPS.\n");
}
}
}
#ifdef SENSOR_GPS_CONFLICT
}
#endif
#endif
nodeStatus->observe(&nodeDB->newStatus);

View File

@ -55,7 +55,7 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod
p->decoded.request_id = idFrom;
p->channel = chIndex;
if (err != meshtastic_Routing_Error_NONE)
LOG_ERROR("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
LOG_WARN("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
return p;
}

View File

@ -57,27 +57,6 @@ meshtastic_ChannelFile channelFile;
meshtastic_OEMStore oemStore;
static bool hasOemStore = false;
// These are not publically exposed - copied from InternalFileSystem.cpp
// #define FLASH_NRF52_PAGE_SIZE 4096
// #define LFS_FLASH_TOTAL_SIZE (7*FLASH_NRF52_PAGE_SIZE)
// #define LFS_BLOCK_SIZE 128
/// List all files in the FS and test write and readback.
/// Useful for filesystem stress testing - normally stripped from build by the linker.
void flashTest()
{
auto filesManifest = getFiles("/", 5);
uint32_t totalSize = 0;
for (size_t i = 0; i < filesManifest.size(); i++) {
LOG_INFO("File %s (size %d)\n", filesManifest[i].file_name, filesManifest[i].size_bytes);
totalSize += filesManifest[i].size_bytes;
}
LOG_INFO("%d files (total size %u)\n", filesManifest.size(), totalSize);
// LOG_INFO("Filesystem block size %u, total bytes %u", LFS_FLASH_TOTAL_SIZE, LFS_BLOCK_SIZE);
nodeDB->saveToDisk();
}
bool meshtastic_DeviceState_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field)
{
if (ostream) {
@ -145,6 +124,12 @@ NodeDB::NodeDB()
// Include our owner in the node db under our nodenum
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
if (!config.has_security) {
config.has_security = true;
config.security.serial_enabled = config.device.serial_enabled;
config.security.bluetooth_logging_enabled = config.bluetooth.device_logging_enabled;
config.security.is_managed = config.device.is_managed;
}
#if !(MESHTASTIC_EXCLUDE_PKI)
// Calculate Curve25519 public and private keys
printBytes("Old Pubkey", config.security.public_key.bytes, 32);
@ -155,10 +140,6 @@ NodeDB::NodeDB()
crypto->setDHPrivateKey(config.security.private_key.bytes);
} else {
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN)
config.has_security = true;
config.security.serial_enabled = config.device.serial_enabled;
config.security.bluetooth_logging_enabled = config.bluetooth.device_logging_enabled;
config.security.is_managed = config.device.is_managed;
LOG_INFO("Generating new PKI keys\n");
crypto->generateKeyPair(config.security.public_key.bytes, config.security.private_key.bytes);
config.security.public_key.size = 32;
@ -573,10 +554,21 @@ void NodeDB::cleanupMeshDB()
{
int newPos = 0, removed = 0;
for (int i = 0; i < numMeshNodes; i++) {
if (meshNodes->at(i).has_user)
if (meshNodes->at(i).has_user) {
if (meshNodes->at(i).user.public_key.size > 0) {
for (int j = 0; j < numMeshNodes; j++) {
if (meshNodes->at(i).user.public_key.bytes[j] != 0) {
break;
}
if (j == 31) {
meshNodes->at(i).user.public_key.size = 0;
}
}
}
meshNodes->at(newPos++) = meshNodes->at(i);
else
} else {
removed++;
}
}
numMeshNodes -= removed;
std::fill(devicestate.node_db_lite.begin() + numMeshNodes, devicestate.node_db_lite.begin() + numMeshNodes + removed,
@ -603,8 +595,16 @@ void NodeDB::installDefaultDeviceState()
// Set default owner name
pickNewNodeNum(); // based on macaddr now
#ifdef CONFIG_OWNER_LONG_NAME_USERPREFS
snprintf(owner.long_name, sizeof(owner.long_name), CONFIG_OWNER_LONG_NAME_USERPREFS);
#else
snprintf(owner.long_name, sizeof(owner.long_name), "Meshtastic %02x%02x", ourMacAddr[4], ourMacAddr[5]);
#endif
#ifdef CONFIG_OWNER_SHORT_NAME_USERPREFS
snprintf(owner.short_name, sizeof(owner.short_name), CONFIG_OWNER_SHORT_NAME_USERPREFS);
#else
snprintf(owner.short_name, sizeof(owner.short_name), "%02x%02x", ourMacAddr[4], ourMacAddr[5]);
#endif
snprintf(owner.id, sizeof(owner.id), "!%08x", getNodeNum()); // Default node ID now based on nodenum
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
}
@ -649,11 +649,6 @@ LoadFileResult NodeDB::loadProto(const char *filename, size_t protoSize, size_t
LoadFileResult state = LoadFileResult::OTHER_FAILURE;
#ifdef FSCom
if (!FSCom.exists(filename)) {
LOG_INFO("File %s not found\n", filename);
return LoadFileResult::NOT_FOUND;
}
auto f = FSCom.open(filename, FILE_O_READ);
if (f) {
@ -1182,4 +1177,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
LOG_ERROR("A critical failure occurred, portduino is exiting...");
exit(2);
#endif
}
}

View File

@ -283,6 +283,9 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
if (s.want_response)
out += DEBUG_PORT.mt_sprintf(" WANTRESP");
if (p->pki_encrypted)
out += DEBUG_PORT.mt_sprintf(" PKI");
if (s.source != 0)
out += DEBUG_PORT.mt_sprintf(" source=%08x", s.source);

View File

@ -4,6 +4,7 @@
#include "MeshTypes.h"
#include "configuration.h"
#include "mesh-pb-constants.h"
#include "modules/NodeInfoModule.h"
// ReliableRouter::ReliableRouter() {}
@ -109,13 +110,24 @@ void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
LOG_DEBUG("Some other module has replied to this message, no need for a 2nd ack\n");
} else if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, p->hop_start, p->hop_limit);
} else if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag && p->channel == 0 &&
(nodeDB->getMeshNode(p->from) != nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
// This looks like it might be a PKI packet from an unknown node, so send PKI_UNKNOWN_PUBKEY
sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(),
p->hop_start, p->hop_limit);
} else {
// Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(), p->hop_start,
p->hop_limit);
}
}
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && c &&
c->error_reason == meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY) {
if (owner.public_key.size == 32) {
LOG_INFO("This seems like a remote PKI decrypt failure, so send a NodeInfo");
nodeInfoModule->sendOurNodeInfo(p->from, false, p->channel, true);
}
}
// We consider an ack to be either a !routing packet with a request ID or a routing packet with !error
PacketId ackId = ((c && c->error_reason == meshtastic_Routing_Error_NONE) || !c) ? p->decoded.request_id : 0;

View File

@ -415,6 +415,8 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
{
concurrency::LockGuard g(cryptLock);
int16_t hash;
// If the packet is not yet encrypted, do so now
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded);
@ -460,31 +462,56 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
// printBytes("plaintext", bytes, numbytes);
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
auto hash = channels.setActiveByIndex(chIndex);
if (hash < 0)
// No suitable channel could be found for sending
return meshtastic_Routing_Error_NO_CHANNEL;
// Now that we are encrypting the packet channel should be the hash (no longer the index)
p->channel = hash;
#if !(MESHTASTIC_EXCLUDE_PKI)
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->to);
if (!owner.is_licensed && p->to != NODENUM_BROADCAST && node != nullptr && node->user.public_key.size > 0 &&
numbytes <= MAX_RHPACKETLEN - 8 && p->decoded.portnum != meshtastic_PortNum_TRACEROUTE_APP &&
if (!owner.is_licensed && config.security.private_key.size == 32 && p->to != NODENUM_BROADCAST && node != nullptr &&
node->user.public_key.size > 0 && p->decoded.portnum != meshtastic_PortNum_TRACEROUTE_APP &&
p->decoded.portnum != meshtastic_PortNum_NODEINFO_APP && p->decoded.portnum != meshtastic_PortNum_ROUTING_APP &&
p->decoded.portnum != meshtastic_PortNum_POSITION_APP) {
LOG_DEBUG("Using PKI!\n");
if (numbytes + 8 > MAX_RHPACKETLEN)
return meshtastic_Routing_Error_TOO_LARGE;
if (p->pki_encrypted && !memfll(p->public_key.bytes, 0, 32) &&
memcmp(p->public_key.bytes, node->user.public_key.bytes, 32) != 0) {
LOG_WARN("Client public key for client differs from requested! Requested 0x%02x, but stored key begins 0x%02x\n",
*p->public_key.bytes, *node->user.public_key.bytes);
return meshtastic_Routing_Error_PKI_FAILED;
}
crypto->encryptCurve25519(p->to, getFrom(p), p->id, numbytes, bytes, ScratchEncrypted);
numbytes += 8;
memcpy(p->encrypted.bytes, ScratchEncrypted, numbytes);
p->channel = 0;
p->pki_encrypted = true;
} else {
if (p->pki_encrypted == true) {
// Client specifically requested PKI encryption
return meshtastic_Routing_Error_PKI_FAILED;
}
hash = channels.setActiveByIndex(chIndex);
// Now that we are encrypting the packet channel should be the hash (no longer the index)
p->channel = hash;
if (hash < 0) {
// No suitable channel could be found for sending
return meshtastic_Routing_Error_NO_CHANNEL;
}
crypto->encryptPacket(getFrom(p), p->id, numbytes, bytes);
memcpy(p->encrypted.bytes, bytes, numbytes);
}
#else
if (p->pki_encrypted == true) {
// Client specifically requested PKI encryption
return meshtastic_Routing_Error_PKI_FAILED;
}
hash = channels.setActiveByIndex(chIndex);
// Now that we are encrypting the packet channel should be the hash (no longer the index)
p->channel = hash;
if (hash < 0) {
// No suitable channel could be found for sending
return meshtastic_Routing_Error_NO_CHANNEL;
}
crypto->encryptPacket(getFrom(p), p->id, numbytes, bytes);
memcpy(p->encrypted.bytes, bytes, numbytes);
#endif

View File

@ -180,6 +180,13 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_SENSECAP_INDICATOR = 70,
/* Seeed studio T1000-E tracker card. NRF52840 w/ LR1110 radio, GPS, button, buzzer, and sensors. */
meshtastic_HardwareModel_TRACKER_T1000_E = 71,
/* RAK3172 STM32WLE5 Module (https://store.rakwireless.com/products/wisduo-lpwan-module-rak3172) */
meshtastic_HardwareModel_RAK3172 = 72,
/* Seeed Studio Wio-E5 (either mini or Dev kit) using STM32WL chip. */
meshtastic_HardwareModel_WIO_E5 = 73,
/* RadioMaster 900 Bandit, https://www.radiomasterrc.com/products/bandit-expresslrs-rf-module
SSD1306 OLED and No GPS */
meshtastic_HardwareModel_RADIOMASTER_900_BANDIT = 74,
/* ------------------------------------------------------------------------------------------------------------------------------------------
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.
------------------------------------------------------------------------------------------------------------------------------------------ */
@ -293,7 +300,11 @@ typedef enum _meshtastic_Routing_Error {
meshtastic_Routing_Error_BAD_REQUEST = 32,
/* The application layer service on the remote node received your request, but considered your request not authorized
(i.e you did not send the request on the required bound channel) */
meshtastic_Routing_Error_NOT_AUTHORIZED = 33
meshtastic_Routing_Error_NOT_AUTHORIZED = 33,
/* The client specified a PKI transport, but the node was unable to send the packet using PKI (and did not send the message at all) */
meshtastic_Routing_Error_PKI_FAILED = 34,
/* The receiving node does not have a Public Key to decode with */
meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY = 35
} meshtastic_Routing_Error;
/* The priority of this message for sending.
@ -986,8 +997,8 @@ extern "C" {
#define _meshtastic_Position_AltSource_ARRAYSIZE ((meshtastic_Position_AltSource)(meshtastic_Position_AltSource_ALT_BAROMETRIC+1))
#define _meshtastic_Routing_Error_MIN meshtastic_Routing_Error_NONE
#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_NOT_AUTHORIZED
#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_NOT_AUTHORIZED+1))
#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY
#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY+1))
#define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET
#define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX

View File

@ -63,7 +63,13 @@ typedef enum _meshtastic_TelemetrySensorType {
/* DFRobot Lark Weather station (temperature, humidity, pressure, wind speed and direction) */
meshtastic_TelemetrySensorType_DFROBOT_LARK = 24,
/* NAU7802 Scale Chip or compatible */
meshtastic_TelemetrySensorType_NAU7802 = 25
meshtastic_TelemetrySensorType_NAU7802 = 25,
/* BMP3XX High accuracy temperature and pressure */
meshtastic_TelemetrySensorType_BMP3XX = 26,
/* ICM-20948 9-Axis digital motion processor */
meshtastic_TelemetrySensorType_ICM20948 = 27,
/* MAX17048 1S lipo battery sensor (voltage, state of charge, time to go) */
meshtastic_TelemetrySensorType_MAX17048 = 28
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@ -237,8 +243,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_NAU7802
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_NAU7802+1))
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_MAX17048
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_MAX17048+1))

View File

@ -64,4 +64,13 @@ void printBytes(const char *label, const uint8_t *p, size_t numbytes)
for (size_t i = 0; i < numbytes; i++)
LOG_DEBUG("%02x ", p[i]);
LOG_DEBUG("\n");
}
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes)
{
for (int i = 0; i < numbytes; i++) {
if (mem[i] != find)
return false;
}
return true;
}

View File

@ -14,4 +14,7 @@ template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi
char *strnstr(const char *s, const char *find, size_t slen);
#endif
void printBytes(const char *label, const uint8_t *p, size_t numbytes);
void printBytes(const char *label, const uint8_t *p, size_t numbytes);
// is the memory region filled with a single character?
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes);

View File

@ -32,19 +32,22 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
return false; // Let others look at this message also if they want
}
void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t channel)
void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t channel, bool _shorterTimeout)
{
// cancel any not yet sent (now stale) position packets
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
service->cancelSending(prevPacketId);
shorterTimeout = _shorterTimeout;
meshtastic_MeshPacket *p = allocReply();
if (p) { // Check whether we didn't ignore it
p->to = dest;
p->decoded.want_response = (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
wantReplies;
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
if (_shorterTimeout)
p->priority = meshtastic_MeshPacket_Priority_DEFAULT;
else
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
if (channel > 0) {
LOG_DEBUG("sending ourNodeInfo to channel %d\n", channel);
p->channel = channel;
@ -53,6 +56,7 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
prevPacketId = p->id;
service->sendToMesh(p);
shorterTimeout = false;
}
}
@ -65,10 +69,14 @@ meshtastic_MeshPacket *NodeInfoModule::allocReply()
}
uint32_t now = millis();
// If we sent our NodeInfo less than 5 min. ago, don't send it again as it may be still underway.
if (lastSentToMesh && (now - lastSentToMesh) < (5 * 60 * 1000)) {
if (!shorterTimeout && lastSentToMesh && (now - lastSentToMesh) < (5 * 60 * 1000)) {
LOG_DEBUG("Skip sending NodeInfo since we just sent it less than 5 minutes ago.\n");
ignoreRequest = true; // Mark it as ignored for MeshModule
return NULL;
} else if (shorterTimeout && lastSentToMesh && (now - lastSentToMesh) < (60 * 1000)) {
LOG_DEBUG("Skip sending actively requested NodeInfo since we just sent it less than 60 seconds ago.\n");
ignoreRequest = true; // Mark it as ignored for MeshModule
return NULL;
} else {
ignoreRequest = false; // Don't ignore requests anymore
meshtastic_User &u = owner;

View File

@ -20,7 +20,8 @@ class NodeInfoModule : public ProtobufModule<meshtastic_User>, private concurren
/**
* Send our NodeInfo into the mesh
*/
void sendOurNodeInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0);
void sendOurNodeInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0,
bool _shorterTimeout = false);
protected:
/** Called to handle a particular incoming message
@ -38,6 +39,7 @@ class NodeInfoModule : public ProtobufModule<meshtastic_User>, private concurren
private:
uint32_t lastSentToMesh = 0; // Last time we sent our NodeInfo to the mesh
bool shorterTimeout = false;
};
extern NodeInfoModule *nodeInfoModule;

View File

@ -90,7 +90,6 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
// will always be an equivalent or lesser RTCQuality (RTCQualityNTP or RTCQualityNet).
force = true;
#endif
// Set from phone RTC Quality to RTCQualityNTP since it should be approximately so
trySetRtc(p, isLocal, force);
}
@ -126,14 +125,26 @@ void PositionModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic
void PositionModule::trySetRtc(meshtastic_Position p, bool isLocal, bool forceUpdate)
{
if (hasQualityTimesource() && !isLocal) {
LOG_DEBUG("Ignoring time from mesh because we have a GPS, RTC, or Phone/NTP time source in the past day\n");
return;
}
struct timeval tv;
uint32_t secs = p.time;
tv.tv_sec = secs;
tv.tv_usec = 0;
perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv, forceUpdate);
}
bool PositionModule::hasQualityTimesource()
{
bool setFromPhoneOrNtpToday = (millis() - lastSetFromPhoneNtpOrGps) <= (SEC_PER_DAY * 1000UL);
bool hasGpsOrRtc = (gps && gps->isConnected()) || (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
return hasGpsOrRtc || setFromPhoneOrNtpToday;
}
meshtastic_MeshPacket *PositionModule::allocReply()
{
if (precision == 0) {

View File

@ -60,6 +60,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
void trySetRtc(meshtastic_Position p, bool isLocal, bool forceUpdate = false);
uint32_t precision;
void sendLostAndFoundText();
bool hasQualityTimesource();
const uint32_t minimumTimeThreshold =
Default::getConfiguredOrDefaultMsScaled(config.position.broadcast_smart_minimum_interval_secs, 30, numOnlineNodes);

View File

@ -228,6 +228,9 @@ void cpuDeepSleep(uint32_t msecToWake)
// FIXME change polarity in hw so we can wake on ANY_HIGH instead - that would allow us to use all three buttons (instead
// of just the first) gpio_pullup_en((gpio_num_t)BUTTON_PIN);
#ifdef ESP32S3_WAKE_TYPE
esp_sleep_enable_ext1_wakeup(gpioMask, ESP32S3_WAKE_TYPE);
#else
#if SOC_PM_SUPPORT_EXT_WAKEUP
#ifdef CONFIG_IDF_TARGET_ESP32
// ESP_EXT1_WAKEUP_ALL_LOW has been deprecated since esp-idf v5.4 for any other target.
@ -236,6 +239,8 @@ void cpuDeepSleep(uint32_t msecToWake)
esp_sleep_enable_ext1_wakeup(gpioMask, ESP_EXT1_WAKEUP_ANY_LOW);
#endif
#endif
#endif // #end ESP32S3_WAKE_TYPE
#endif
// We want RTC peripherals to stay on

View File

@ -198,8 +198,13 @@ void NRF52Bluetooth::shutdown()
{
// Shutdown bluetooth for minimum power draw
LOG_INFO("Disable NRF52 bluetooth\n");
if (connectionHandle != 0) {
Bluefruit.disconnect(connectionHandle);
uint8_t connection_num = Bluefruit.connected();
if (connection_num) {
for (uint8_t i = 0; i < connection_num; i++) {
LOG_INFO("NRF52 bluetooth disconnecting handle %d\n", i);
Bluefruit.disconnect(i);
}
delay(100); // wait for ondisconnect;
}
Bluefruit.Advertising.stop();
}

View File

@ -251,6 +251,12 @@ void cpuDeepSleep(uint32_t msecToWake)
nrf_gpio_cfg_default(WB_I2C1_SCL);
nrf_gpio_cfg_default(WB_I2C1_SDA);
#endif
#endif
#ifdef HELTEC_MESH_NODE_T114
nrf_gpio_cfg_default(PIN_GPS_PPS);
detachInterrupt(PIN_GPS_PPS);
detachInterrupt(PIN_BUTTON1);
#endif
// Sleepy trackers or sensors can low power "sleep"
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event

View File

@ -9,12 +9,18 @@
#ifndef HAS_RADIO
#define HAS_RADIO 1
#endif
#ifndef HAS_TELEMETRY
#define HAS_TELEMETRY 1
#endif
//
// set HW_VENDOR
//
#ifndef HW_VENDOR
#ifdef _VARIANT_WIOE5_
#define HW_VENDOR meshtastic_HardwareModel_WIO_E5
#elif defined(_VARIANT_RAK3172_)
#define HW_VENDOR meshtastic_HardwareModel_RAK3172
#else
#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW
#endif
@ -22,4 +28,4 @@
#define SX126X_CS 1000
#define SX126X_DIO1 1001
#define SX126X_RESET 1003
#define SX126X_BUSY 1004
#define SX126X_BUSY 1004

View File

@ -278,6 +278,13 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
digitalWrite(LORA_CS, HIGH);
gpio_hold_en((gpio_num_t)LORA_CS);
}
#if defined(I2C_SDA)
Wire.end();
pinMode(I2C_SDA, ANALOG);
pinMode(I2C_SCL, ANALOG);
#endif
#endif
#ifdef HAS_PMU

View File

@ -19,6 +19,9 @@
// #define CHANNEL_0_NAME_USERPREFS "DEFCONnect"
// #define CHANNEL_0_PRECISION_USERPREFS 13
// #define CONFIG_OWNER_LONG_NAME_USERPREFS "My Long Name"
// #define CONFIG_OWNER_SHORT_NAME_USERPREFS "MLN"
// #define SPLASH_TITLE_USERPREFS "DEFCONtastic"
// #define icon_width 34
// #define icon_height 29

View File

@ -40,3 +40,13 @@
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define I2C_SDA 1
#define I2C_SCL 2
#define HAS_SCREEN 0
#define SENSOR_POWER_CTRL_PIN 21
#define SENSOR_POWER_ON 1
#define SENSOR_GPS_CONFLICT
#define ESP32S3_WAKE_TYPE ESP_EXT1_WAKEUP_ANY_HIGH

View File

@ -146,7 +146,7 @@ No longer populated on PCB
#define GPS_L76K
#define PIN_GPS_RESET (32 + 6) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
// #define PIN_GPS_RESET (32 + 6) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
#define GPS_RESET_MODE LOW
#define PIN_GPS_EN (21)
#define GPS_EN_ACTIVE HIGH

View File

@ -6,6 +6,7 @@ board_check = true
build_flags = ${nrf52840_base.build_flags} -Ivariants/rak2560 -D RAK_4631
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-DMESHTASTIC_EXCLUDE_GPS=1
-DHAS_RAKPROT=1 ; Define if RAk OneWireSerial is used (disables GPS)
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak2560> +<mesh/eth/> +<mesh/api/> +<mqtt/>
lib_deps =

View File

@ -227,7 +227,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
// #define GPS_TX_PIN PIN_SERIAL2_TX
// #define PIN_GPS_EN PIN_3V3_EN
// Disable GPS
#define MESHTASTIC_EXCLUDE_GPS 1
// #define MESHTASTIC_EXCLUDE_GPS 1
// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press
// RAK12002 RTC Module

View File

@ -3,29 +3,23 @@
extends = nrf52840_base
board = wio-sdk-wm1110
extra_scripts =
bin/platformio-custom.py
extra_scripts/disable_adafruit_usb.py
# Remove adafruit USB serial from the build (it is incompatible with using the ch340 serial chip on this board)
build_unflags = ${nrf52840_base:build_unflags} -DUSBCON -DUSE_TINYUSB
build_flags = ${nrf52840_base.build_flags} -Ivariants/wio-sdk-wm1110 -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DWIO_WM1110
-L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-DCFG_TUD_CDC=0
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/wio-sdk-wm1110>
lib_deps =
${nrf52840_base.lib_deps}
debug_tool = jlink
;debug_tool = stlink
;debug_speed = 4000
; No need to reflash if the binary hasn't changed
debug_load_mode = modified
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
upload_protocol = nrfutil
;upload_protocol = stlink
; we prefer to stop in setup() because we are an 'ardiuno' app
debug_init_break = tbreak setup
; we need to turn off BLE/soft device if we are debugging otherwise it will watchdog reset us.
debug_extra_cmds =
echo Running .gdbinit script
commands 1
set useSoftDevice = false
end
;debug_tool = jlink
debug_tool = stlink
; No need to reflash if the binary hasn't changed
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
;upload_protocol = nrfutil
;upload_protocol = stlink