mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-24 11:40:27 +00:00
Compare commits
32 Commits
v2.4.2.5b4
...
2.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98cb3edff1 | ||
|
|
91d661246a | ||
|
|
a8999d7759 | ||
|
|
1bbc273ba6 | ||
|
|
e37acae405 | ||
|
|
5ff1078c8c | ||
|
|
a577dd4142 | ||
|
|
e0b4a8e31e | ||
|
|
0ebdc7ab0c | ||
|
|
85176756ec | ||
|
|
d398419aef | ||
|
|
efc27f2051 | ||
|
|
837c4e9e7b | ||
|
|
181325103a | ||
|
|
207b9b49a5 | ||
|
|
464f270b12 | ||
|
|
7740b4bccd | ||
|
|
e85a2e827b | ||
|
|
62a0321c7d | ||
|
|
6e8300287b | ||
|
|
f97ae52263 | ||
|
|
c74bce9360 | ||
|
|
6cd1882aaa | ||
|
|
cf392a4c20 | ||
|
|
8daebf80dd | ||
|
|
debf4b934f | ||
|
|
3878e025e4 | ||
|
|
3ab4bebdcb | ||
|
|
e38aca3cba | ||
|
|
d8bdb92efe | ||
|
|
c6a9edf8c7 | ||
|
|
a7da3537e2 |
208
arch/nrf52/cpp_overrides/lfs_util.h
Normal file
208
arch/nrf52/cpp_overrides/lfs_util.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -145,6 +145,7 @@ Input:
|
||||
Logging:
|
||||
LogLevel: info # debug, info, warn, error
|
||||
# TraceFile: /var/log/meshtasticd.json
|
||||
# AsciiLogs: true # default if not specified is !isatty() on stdout
|
||||
|
||||
Webserver:
|
||||
# Port: 443 # Port for Webserver & Webservices
|
||||
@@ -152,4 +153,4 @@ Webserver:
|
||||
|
||||
General:
|
||||
MaxNodes: 200
|
||||
MaxMessageQueue: 100
|
||||
MaxMessageQueue: 100
|
||||
|
||||
@@ -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...)
|
||||
|
||||
@@ -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
|
||||
|
||||
Submodule protobufs updated: d0fe91ab99...666b481ae0
@@ -224,7 +224,6 @@ int32_t ButtonThread::runOnce()
|
||||
btnEvent = BUTTON_EVENT_NONE;
|
||||
}
|
||||
|
||||
runASAP = false;
|
||||
return 50;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,20 @@ SOFTWARE.*/
|
||||
|
||||
#include "DebugConfiguration.h"
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#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, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if (console)
|
||||
console->vprintf(level, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#if HAS_NETWORKING
|
||||
|
||||
Syslog::Syslog(UDP &client)
|
||||
@@ -129,6 +143,11 @@ bool Syslog::vlogf(uint16_t pri, const char *appName, const char *fmt, va_list a
|
||||
inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *message)
|
||||
{
|
||||
int result;
|
||||
#ifdef ARCH_PORTDUINO
|
||||
bool utf = !settingsMap[ascii_logs];
|
||||
#else
|
||||
bool utf = true;
|
||||
#endif
|
||||
|
||||
if (!this->_enabled)
|
||||
return false;
|
||||
@@ -159,7 +178,12 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
|
||||
this->_client->print(this->_deviceHostname);
|
||||
this->_client->print(' ');
|
||||
this->_client->print(appName);
|
||||
this->_client->print(F(" - - - \xEF\xBB\xBF"));
|
||||
this->_client->print(F(" - - - "));
|
||||
if (utf) {
|
||||
this->_client->print(F("\xEF\xBB\xBF"));
|
||||
} else {
|
||||
this->_client->print(F(" "));
|
||||
}
|
||||
this->_client->print(F("["));
|
||||
this->_client->print(int(millis() / 1000));
|
||||
this->_client->print(F("]: "));
|
||||
@@ -169,4 +193,4 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -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 */
|
||||
|
||||
100
src/FSCommon.cpp
100
src/FSCommon.cpp
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -55,6 +55,12 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
|
||||
static char printBuf[160];
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
bool color = !settingsMap[ascii_logs];
|
||||
#else
|
||||
bool color = true;
|
||||
#endif
|
||||
|
||||
va_copy(copy, arg);
|
||||
size_t len = vsnprintf(printBuf, sizeof(printBuf), format, copy);
|
||||
va_end(copy);
|
||||
@@ -70,7 +76,7 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
|
||||
if (!std::isprint(static_cast<unsigned char>(printBuf[f])) && printBuf[f] != '\n')
|
||||
printBuf[f] = '#';
|
||||
}
|
||||
if (logLevel != nullptr) {
|
||||
if (color && logLevel != nullptr) {
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
|
||||
Print::write("\u001b[34m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
|
||||
@@ -81,7 +87,9 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
|
||||
Print::write("\u001b[31m", 6);
|
||||
}
|
||||
len = Print::write(printBuf, len);
|
||||
Print::write("\u001b[0m", 5);
|
||||
if (color && logLevel != nullptr) {
|
||||
Print::write("\u001b[0m", 5);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -91,19 +99,27 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
|
||||
|
||||
// Cope with 0 len format strings, but look for new line terminator
|
||||
bool hasNewline = *format && format[strlen(format) - 1] == '\n';
|
||||
#ifdef ARCH_PORTDUINO
|
||||
bool color = !settingsMap[ascii_logs];
|
||||
#else
|
||||
bool color = true;
|
||||
#endif
|
||||
|
||||
// If we are the first message on a report, include the header
|
||||
if (!isContinuationMessage) {
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
|
||||
Print::write("\u001b[34m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
|
||||
Print::write("\u001b[32m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
|
||||
Print::write("\u001b[33m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
|
||||
Print::write("\u001b[31m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0)
|
||||
Print::write("\u001b[35m", 6);
|
||||
if (color) {
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
|
||||
Print::write("\u001b[34m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
|
||||
Print::write("\u001b[32m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
|
||||
Print::write("\u001b[33m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
|
||||
Print::write("\u001b[31m", 6);
|
||||
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0)
|
||||
Print::write("\u001b[35m", 6);
|
||||
}
|
||||
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile
|
||||
if (rtc_sec > 0) {
|
||||
long hms = rtc_sec % SEC_PER_DAY;
|
||||
@@ -117,17 +133,33 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
|
||||
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
||||
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
|
||||
#ifdef ARCH_PORTDUINO
|
||||
::printf("%s \u001b[0m| %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
||||
::printf("%s ", logLevel);
|
||||
if (color) {
|
||||
::printf("\u001b[0m");
|
||||
}
|
||||
::printf("| %02d:%02d:%02d %u ", hour, min, sec, millis() / 1000);
|
||||
#else
|
||||
printf("%s \u001b[0m| %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
||||
printf("%s ", logLevel);
|
||||
if (color) {
|
||||
printf("\u001b[0m");
|
||||
}
|
||||
printf("| %02d:%02d:%02d %u ", hour, min, sec, millis() / 1000);
|
||||
#endif
|
||||
} else
|
||||
} else {
|
||||
#ifdef ARCH_PORTDUINO
|
||||
::printf("%s \u001b[0m| ??:??:?? %u ", logLevel, millis() / 1000);
|
||||
::printf("%s ", logLevel);
|
||||
if (color) {
|
||||
::printf("\u001b[0m");
|
||||
}
|
||||
::printf("| ??:??:?? %u ", millis() / 1000);
|
||||
#else
|
||||
printf("%s \u001b[0m| ??:??:?? %u ", logLevel, millis() / 1000);
|
||||
printf("%s ", logLevel);
|
||||
if (color) {
|
||||
printf("\u001b[0m");
|
||||
}
|
||||
printf("| ??:??:?? %u ", millis() / 1000);
|
||||
#endif
|
||||
|
||||
}
|
||||
auto thread = concurrency::OSThread::currentThread;
|
||||
if (thread) {
|
||||
print("[");
|
||||
@@ -350,4 +382,4 @@ std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...)
|
||||
break;
|
||||
}
|
||||
return std::string(formatted.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -257,6 +257,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MESHTASTIC_EXCLUDE_POWERMON 1
|
||||
#define MESHTASTIC_EXCLUDE_I2C 1
|
||||
#define MESHTASTIC_EXCLUDE_POWER_FSM 1
|
||||
#define MESHTASTIC_EXCLUDE_TZ 1
|
||||
#endif
|
||||
|
||||
// Turn off all optional modules
|
||||
@@ -312,4 +313,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endif
|
||||
|
||||
#include "DebugConfiguration.h"
|
||||
#include "RF95Configuration.h"
|
||||
#include "RF95Configuration.h"
|
||||
@@ -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
|
||||
@@ -51,7 +51,7 @@ enum GPSPowerState : uint8_t {
|
||||
const char *getDOPString(uint32_t dop);
|
||||
|
||||
/**
|
||||
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
|
||||
* A gps class that only reads from the GPS periodically and keeps the gps powered down except when reading
|
||||
*
|
||||
* When new data is available it will notify observers.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
@@ -256,6 +260,7 @@ uint32_t getValidTime(RTCQuality minQuality, bool local)
|
||||
|
||||
time_t gm_mktime(struct tm *tm)
|
||||
{
|
||||
#if !MESHTASTIC_EXCLUDE_TZ
|
||||
setenv("TZ", "GMT0", 1);
|
||||
time_t res = mktime(tm);
|
||||
if (*config.device.tzdef) {
|
||||
@@ -264,4 +269,7 @@ time_t gm_mktime(struct tm *tm)
|
||||
setenv("TZ", "UTC0", 1);
|
||||
}
|
||||
return res;
|
||||
#else
|
||||
return mktime(tm);
|
||||
#endif
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
260
src/input/ExpressLRSFiveWay.cpp
Normal file
260
src/input/ExpressLRSFiveWay.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
|
||||
#include "ExpressLRSFiveWay.h"
|
||||
|
||||
#ifdef INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE
|
||||
|
||||
static const char inputSourceName[] = "ExpressLRS5Way"; // should match "allow input source" string
|
||||
|
||||
/**
|
||||
* @brief Calculate fuzz: half the distance to the next nearest neighbor for each joystick position.
|
||||
*
|
||||
* The goal is to avoid collisions between joystick positions while still maintaining
|
||||
* the widest tolerance for the analog value.
|
||||
*
|
||||
* Example: {10,50,800,1000,300,1600}
|
||||
* If we just choose the minimum difference for this array the value would
|
||||
* be 40/2 = 20.
|
||||
*
|
||||
* 20 does not leave enough room for the joystick position using 1600 which
|
||||
* could have a +-100 offset.
|
||||
*
|
||||
* Example Fuzz values: {20, 20, 100, 100, 125, 300} now the fuzz for the 1600
|
||||
* position is 300 instead of 20
|
||||
*/
|
||||
void ExpressLRSFiveWay::calcFuzzValues()
|
||||
{
|
||||
for (unsigned int i = 0; i < N_JOY_ADC_VALUES; i++) {
|
||||
uint16_t closestDist = 0xffff;
|
||||
uint16_t ival = joyAdcValues[i];
|
||||
// Find the closest value to ival
|
||||
for (unsigned int j = 0; j < N_JOY_ADC_VALUES; j++) {
|
||||
// Don't compare value with itself
|
||||
if (j == i)
|
||||
continue;
|
||||
uint16_t jval = joyAdcValues[j];
|
||||
if (jval < ival && (ival - jval < closestDist))
|
||||
closestDist = ival - jval;
|
||||
if (jval > ival && (jval - ival < closestDist))
|
||||
closestDist = jval - ival;
|
||||
} // for j
|
||||
|
||||
// And the fuzz is half the distance to the closest value
|
||||
fuzzValues[i] = closestDist / 2;
|
||||
// DBG("joy%u=%u f=%u, ", i, ival, fuzzValues[i]);
|
||||
} // for i
|
||||
}
|
||||
|
||||
int ExpressLRSFiveWay::readKey()
|
||||
{
|
||||
uint16_t value = analogRead(PIN_JOYSTICK);
|
||||
|
||||
constexpr uint8_t IDX_TO_INPUT[N_JOY_ADC_VALUES - 1] = {UP, DOWN, LEFT, RIGHT, OK};
|
||||
for (unsigned int i = 0; i < N_JOY_ADC_VALUES - 1; ++i) {
|
||||
if (value < (joyAdcValues[i] + fuzzValues[i]) && value > (joyAdcValues[i] - fuzzValues[i]))
|
||||
return IDX_TO_INPUT[i];
|
||||
}
|
||||
return NO_PRESS;
|
||||
}
|
||||
|
||||
ExpressLRSFiveWay::ExpressLRSFiveWay() : concurrency::OSThread(inputSourceName)
|
||||
{
|
||||
// ExpressLRS: init values
|
||||
isLongPressed = false;
|
||||
keyInProcess = NO_PRESS;
|
||||
keyDownStart = 0;
|
||||
|
||||
// Express LRS: calculate the threshold for interpreting ADC values as various buttons
|
||||
calcFuzzValues();
|
||||
|
||||
// Meshtastic: register with canned messages
|
||||
inputBroker->registerSource(this);
|
||||
}
|
||||
|
||||
// ExpressLRS: interpret reading as key events
|
||||
void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
|
||||
{
|
||||
*keyValue = NO_PRESS;
|
||||
|
||||
int newKey = readKey();
|
||||
uint32_t now = millis();
|
||||
if (keyInProcess == NO_PRESS) {
|
||||
// New key down
|
||||
if (newKey != NO_PRESS) {
|
||||
keyDownStart = now;
|
||||
// DBGLN("down=%u", newKey);
|
||||
}
|
||||
} else {
|
||||
// if key released
|
||||
if (newKey == NO_PRESS) {
|
||||
// DBGLN("up=%u", keyInProcess);
|
||||
if (!isLongPressed) {
|
||||
if ((now - keyDownStart) > KEY_DEBOUNCE_MS) {
|
||||
*keyValue = keyInProcess;
|
||||
*keyLongPressed = false;
|
||||
}
|
||||
}
|
||||
isLongPressed = false;
|
||||
}
|
||||
// else if the key has changed while down, reset state for next go-around
|
||||
else if (newKey != keyInProcess) {
|
||||
newKey = NO_PRESS;
|
||||
}
|
||||
// else still pressing, waiting for long if not already signaled
|
||||
else if (!isLongPressed) {
|
||||
if ((now - keyDownStart) > KEY_LONG_PRESS_MS) {
|
||||
*keyValue = keyInProcess;
|
||||
*keyLongPressed = true;
|
||||
isLongPressed = true;
|
||||
}
|
||||
}
|
||||
} // if keyInProcess != NO_PRESS
|
||||
|
||||
keyInProcess = newKey;
|
||||
}
|
||||
|
||||
// Meshtastic: runs at regular intervals
|
||||
int32_t ExpressLRSFiveWay::runOnce()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
|
||||
// Dismiss any alert frames after 2 seconds
|
||||
// Feedback for GPS toggle / adhoc ping
|
||||
if (alerting && now > alertingSinceMs + 2000) {
|
||||
alerting = false;
|
||||
screen->endAlert();
|
||||
}
|
||||
|
||||
// Get key events from ExpressLRS code
|
||||
int keyValue;
|
||||
bool longPressed;
|
||||
update(&keyValue, &longPressed);
|
||||
|
||||
// Do something about this key press
|
||||
determineAction((KeyType)keyValue, longPressed ? LONG : SHORT);
|
||||
|
||||
// If there has been recent key activity, poll the joystick slightly more frequently
|
||||
if (now < keyDownStart + (20 * 1000UL)) // Within last 20 seconds
|
||||
return 100;
|
||||
|
||||
// Otherwise, poll slightly less often
|
||||
// Too many missed pressed if much slower than 250ms
|
||||
return 250;
|
||||
}
|
||||
|
||||
// Determine what action to take when a button press is detected
|
||||
// Written verbose for easier remapping by user
|
||||
void ExpressLRSFiveWay::determineAction(KeyType key, PressLength length)
|
||||
{
|
||||
switch (key) {
|
||||
case LEFT:
|
||||
if (inCannedMessageMenu()) // If in canned message menu
|
||||
sendKey(CANCEL); // exit the menu (press imaginary cancel key)
|
||||
else
|
||||
sendKey(LEFT);
|
||||
break;
|
||||
|
||||
case RIGHT:
|
||||
if (inCannedMessageMenu()) // If in canned message menu:
|
||||
sendKey(CANCEL); // exit the menu (press imaginary cancel key)
|
||||
else
|
||||
sendKey(RIGHT);
|
||||
break;
|
||||
|
||||
case UP:
|
||||
if (length == LONG)
|
||||
toggleGPS();
|
||||
else
|
||||
sendKey(UP);
|
||||
break;
|
||||
|
||||
case DOWN:
|
||||
if (length == LONG)
|
||||
sendAdhocPing();
|
||||
else
|
||||
sendKey(DOWN);
|
||||
break;
|
||||
|
||||
case OK:
|
||||
if (length == LONG)
|
||||
shutdown();
|
||||
else
|
||||
click(); // Use instead of sendKey(OK). Works better when canned message module disabled
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Feed input to the canned messages module
|
||||
void ExpressLRSFiveWay::sendKey(KeyType key)
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = inputSourceName;
|
||||
e.inputEvent = key;
|
||||
notifyObservers(&e);
|
||||
}
|
||||
|
||||
// Enable or Disable a connected GPS
|
||||
// Contained as one method for easier remapping of buttons by user
|
||||
void ExpressLRSFiveWay::toggleGPS()
|
||||
{
|
||||
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
|
||||
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
||||
gps->toggleGpsMode();
|
||||
screen->startAlert("GPS Toggled");
|
||||
alerting = true;
|
||||
alertingSinceMs = millis();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Send either node-info or position, on demand
|
||||
// Contained as one method for easier remapping of buttons by user
|
||||
void ExpressLRSFiveWay::sendAdhocPing()
|
||||
{
|
||||
service->refreshLocalMeshNode();
|
||||
bool sentPosition = service->trySendPosition(NODENUM_BROADCAST, true);
|
||||
|
||||
// Show custom alert frame, with multi-line centering
|
||||
screen->startAlert([sentPosition](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||
uint16_t x_offset = display->width() / 2;
|
||||
uint16_t y_offset = 26; // Same constant as the default startAlert frame
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(x_offset + x, y_offset + y, "Sent ad-hoc");
|
||||
display->drawString(x_offset + x, y_offset + FONT_HEIGHT_MEDIUM + y, sentPosition ? "position" : "nodeinfo");
|
||||
});
|
||||
|
||||
alerting = true;
|
||||
alertingSinceMs = millis();
|
||||
}
|
||||
|
||||
// Shutdown the node (enter deep-sleep)
|
||||
// Contained as one method for easier remapping of buttons by user
|
||||
void ExpressLRSFiveWay::shutdown()
|
||||
{
|
||||
LOG_INFO("Shutdown from long press\n");
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
screen->startAlert("Shutting down...");
|
||||
// Don't set alerting = true. We don't want to auto-dismiss this alert.
|
||||
|
||||
playShutdownMelody(); // In case user adds a buzzer
|
||||
|
||||
shutdownAtMsec = millis() + 3000;
|
||||
}
|
||||
|
||||
// Emulate user button, or canned message SELECT
|
||||
// This is necessary as canned message module doesn't translate SELECT to user button presses if the module is disabled
|
||||
// Contained as one method for easier remapping of buttons by user
|
||||
void ExpressLRSFiveWay::click()
|
||||
{
|
||||
if (!moduleConfig.canned_message.enabled)
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
else
|
||||
sendKey(OK);
|
||||
}
|
||||
|
||||
ExpressLRSFiveWay *expressLRSFiveWayInput = nullptr;
|
||||
|
||||
#endif
|
||||
85
src/input/ExpressLRSFiveWay.h
Normal file
85
src/input/ExpressLRSFiveWay.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Input source for Radio Master Bandit Nano, and similar hardware.
|
||||
Devices have a 5-button "resistor ladder" style joystick, read by ADC.
|
||||
These devices do not use the ADC to monitor input voltage.
|
||||
|
||||
Much of this code taken directly from ExpressLRS FiveWayButton class:
|
||||
https://github.com/ExpressLRS/ExpressLRS/tree/d9f56f8bd6f9f7144d5f01caaca766383e1e0950/src/lib/SCREEN/FiveWayButton
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE
|
||||
|
||||
#include <esp_adc_cal.h>
|
||||
#include <soc/adc_channel.h>
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "MeshService.h" // For adhoc ping action
|
||||
#include "buzz.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "graphics/Screen.h" // Feedback for adhoc ping / toggle GPS
|
||||
#include "main.h"
|
||||
#include "modules/CannedMessageModule.h"
|
||||
|
||||
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h" // For toggle GPS action
|
||||
#endif
|
||||
|
||||
class ExpressLRSFiveWay : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||
{
|
||||
private:
|
||||
// Number of values in JOY_ADC_VALUES, if defined
|
||||
// These must be ADC readings for {UP, DOWN, LEFT, RIGHT, ENTER, IDLE}
|
||||
static constexpr size_t N_JOY_ADC_VALUES = 6;
|
||||
static constexpr uint32_t KEY_DEBOUNCE_MS = 25;
|
||||
static constexpr uint32_t KEY_LONG_PRESS_MS = 3000; // How many milliseconds to hold key for a long press
|
||||
|
||||
// This merged an enum used by the ExpressLRS code, with meshtastic canned message values
|
||||
// Key names are kept simple, to allow user customizaton
|
||||
typedef enum {
|
||||
UP = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP,
|
||||
DOWN = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN,
|
||||
LEFT = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT,
|
||||
RIGHT = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT,
|
||||
OK = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT,
|
||||
CANCEL = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL,
|
||||
NO_PRESS = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE
|
||||
} KeyType;
|
||||
|
||||
typedef enum { SHORT, LONG } PressLength;
|
||||
|
||||
// From ExpressLRS
|
||||
int keyInProcess;
|
||||
uint32_t keyDownStart;
|
||||
bool isLongPressed;
|
||||
const uint16_t joyAdcValues[N_JOY_ADC_VALUES] = {JOYSTICK_ADC_VALS};
|
||||
uint16_t fuzzValues[N_JOY_ADC_VALUES];
|
||||
void calcFuzzValues();
|
||||
int readKey();
|
||||
void update(int *keyValue, bool *keyLongPressed);
|
||||
|
||||
// Meshtastic code
|
||||
void determineAction(KeyType key, PressLength length);
|
||||
void sendKey(KeyType key);
|
||||
inline bool inCannedMessageMenu() { return cannedMessageModule->shouldDraw(); }
|
||||
int32_t runOnce() override;
|
||||
|
||||
// Simplified Meshtastic actions, for easier remapping by user
|
||||
void toggleGPS();
|
||||
void sendAdhocPing();
|
||||
void shutdown();
|
||||
void click();
|
||||
|
||||
bool alerting = false; // Is the screen showing an alert frame? Feedback for GPS toggle / adhoc ping actions
|
||||
uint32_t alertingSinceMs = 0; // When did screen begin showing an alert frame? Used to auto-dismiss
|
||||
|
||||
public:
|
||||
ExpressLRSFiveWay();
|
||||
};
|
||||
|
||||
extern ExpressLRSFiveWay *expressLRSFiveWayInput;
|
||||
|
||||
#endif
|
||||
36
src/main.cpp
36
src/main.cpp
@@ -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
|
||||
@@ -689,6 +700,7 @@ void setup()
|
||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||
|
||||
// setup TZ prior to time actions.
|
||||
#if !MESHTASTIC_EXCLUDE_TZ
|
||||
if (*config.device.tzdef) {
|
||||
setenv("TZ", config.device.tzdef, 1);
|
||||
} else {
|
||||
@@ -696,22 +708,30 @@ void setup()
|
||||
}
|
||||
tzset();
|
||||
LOG_DEBUG("Set Timezone to %s\n", getenv("TZ"));
|
||||
#endif
|
||||
|
||||
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
||||
|
||||
#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);
|
||||
|
||||
10
src/main.h
10
src/main.h
@@ -65,12 +65,6 @@ extern bool isVibrating;
|
||||
|
||||
extern int TCPPort; // set by Portduino
|
||||
|
||||
// extern Observable<meshtastic::PowerStatus> newPowerStatus; //TODO: move this to main-esp32.cpp somehow or a helper class
|
||||
|
||||
// extern meshtastic::PowerStatus *powerStatus;
|
||||
// extern meshtastic::GPSStatus *gpsStatus;
|
||||
// extern meshtastic::NodeStatusHandler *nodeStatusHandler;
|
||||
|
||||
// Return a human readable string of the form "Meshtastic_ab13"
|
||||
const char *getDeviceName();
|
||||
|
||||
@@ -91,5 +85,5 @@ void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearB
|
||||
|
||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||
|
||||
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
|
||||
extern SPISettings spiSettings;
|
||||
// We default to 4MHz SPI, SPI mode 0
|
||||
extern SPISettings spiSettings;
|
||||
|
||||
@@ -309,12 +309,14 @@ const char *Channels::getName(size_t chIndex)
|
||||
return channelName;
|
||||
}
|
||||
|
||||
bool Channels::isDefaultChannel(const meshtastic_Channel &ch)
|
||||
bool Channels::isDefaultChannel(ChannelIndex chIndex)
|
||||
{
|
||||
const auto &ch = getByIndex(chIndex);
|
||||
if (ch.settings.psk.size == 1 && ch.settings.psk.bytes[0] == 1) {
|
||||
const char *name = getName(chIndex);
|
||||
const char *presetName = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false);
|
||||
// Check if the name is the default derived from the modem preset
|
||||
if (strcmp(ch.settings.name, presetName) == 0)
|
||||
if (strcmp(name, presetName) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -327,8 +329,7 @@ bool Channels::hasDefaultChannel()
|
||||
return false;
|
||||
// Check if any of the channels are using the default name and PSK
|
||||
for (size_t i = 0; i < getNumChannels(); i++) {
|
||||
const auto &ch = getByIndex(i);
|
||||
if (isDefaultChannel(ch))
|
||||
if (isDefaultChannel(i))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -84,7 +84,7 @@ class Channels
|
||||
int16_t setActiveByIndex(ChannelIndex channelIndex);
|
||||
|
||||
// Returns true if the channel has the default name and PSK
|
||||
bool isDefaultChannel(const meshtastic_Channel &ch);
|
||||
bool isDefaultChannel(ChannelIndex chIndex);
|
||||
|
||||
// Returns true if we can be reached via a channel with the default settings given a region and modem preset
|
||||
bool hasDefaultChannel();
|
||||
@@ -129,4 +129,4 @@ class Channels
|
||||
};
|
||||
|
||||
/// Singleton channel table
|
||||
extern Channels channels;
|
||||
extern Channels channels;
|
||||
@@ -13,7 +13,9 @@
|
||||
#define default_min_wake_secs 10
|
||||
#define default_screen_on_secs IF_ROUTER(1, 60 * 10)
|
||||
#define default_node_info_broadcast_secs 3 * 60 * 60
|
||||
#define default_neighbor_info_broadcast_secs 6 * 60 * 60
|
||||
#define min_node_info_broadcast_secs 60 * 60 // No regular broadcasts of more than once an hour
|
||||
#define min_neighbor_info_broadcast_secs 2 * 60 * 60
|
||||
|
||||
#define default_mqtt_address "mqtt.meshtastic.org"
|
||||
#define default_mqtt_username "meshdev"
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#endif
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
#include "PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
@@ -56,27 +56,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) {
|
||||
@@ -211,7 +190,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||
return didFactoryReset;
|
||||
}
|
||||
|
||||
bool NodeDB::factoryReset()
|
||||
bool NodeDB::factoryReset(bool eraseBleBonds)
|
||||
{
|
||||
LOG_INFO("Performing factory reset!\n");
|
||||
// first, remove the "/prefs" (this removes most prefs)
|
||||
@@ -228,18 +207,21 @@ bool NodeDB::factoryReset()
|
||||
installDefaultChannels();
|
||||
// third, write everything to disk
|
||||
saveToDisk();
|
||||
if (eraseBleBonds) {
|
||||
LOG_INFO("Erasing BLE bonds\n");
|
||||
#ifdef ARCH_ESP32
|
||||
// This will erase what's in NVS including ssl keys, persistent variables and ble pairing
|
||||
nvs_flash_erase();
|
||||
// This will erase what's in NVS including ssl keys, persistent variables and ble pairing
|
||||
nvs_flash_erase();
|
||||
#endif
|
||||
#ifdef ARCH_NRF52
|
||||
Bluefruit.begin();
|
||||
LOG_INFO("Clearing bluetooth bonds!\n");
|
||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||
bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
||||
Bluefruit.Periph.clearBonds();
|
||||
Bluefruit.Central.clearBonds();
|
||||
Bluefruit.begin();
|
||||
LOG_INFO("Clearing bluetooth bonds!\n");
|
||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||
bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
||||
Bluefruit.Periph.clearBonds();
|
||||
Bluefruit.Central.clearBonds();
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -560,8 +542,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));
|
||||
}
|
||||
@@ -606,11 +596,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) {
|
||||
|
||||
@@ -127,7 +127,7 @@ class NodeDB
|
||||
|
||||
void initConfigIntervals(), initModuleConfigIntervals(), resetNodes(), removeNodeByNum(NodeNum nodeNum);
|
||||
|
||||
bool factoryReset();
|
||||
bool factoryReset(bool eraseBleBonds = false);
|
||||
|
||||
LoadFileResult loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields,
|
||||
void *dest_struct);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "meshUtils.h"
|
||||
#include "modules/RoutingModule.h"
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
#include "mqtt/MQTT.h"
|
||||
@@ -188,14 +189,6 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
||||
}
|
||||
}
|
||||
|
||||
void printBytes(const char *label, const uint8_t *p, size_t numbytes)
|
||||
{
|
||||
LOG_DEBUG("%s: ", label);
|
||||
for (size_t i = 0; i < numbytes; i++)
|
||||
LOG_DEBUG("%02x ", p[i]);
|
||||
LOG_DEBUG("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet on a suitable interface. This routine will
|
||||
* later free() the packet to pool. This routine is not allowed to stall.
|
||||
@@ -524,18 +517,26 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
|
||||
}
|
||||
#endif
|
||||
// assert(radioConfig.has_preferences);
|
||||
bool ignore = is_in_repeated(config.lora.ignore_incoming, p->from) || (config.lora.ignore_mqtt && p->via_mqtt);
|
||||
if (is_in_repeated(config.lora.ignore_incoming, p->from)) {
|
||||
LOG_DEBUG("Ignoring incoming message, 0x%x is in our ignore list\n", p->from);
|
||||
packetPool.release(p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ignore) {
|
||||
LOG_DEBUG("Ignoring incoming message, 0x%x is in our ignore list or came via MQTT\n", p->from);
|
||||
} else if (ignore |= shouldFilterReceived(p)) {
|
||||
LOG_DEBUG("Incoming message was filtered 0x%x\n", p->from);
|
||||
if (config.lora.ignore_mqtt && p->via_mqtt) {
|
||||
LOG_DEBUG("Message came in via MQTT from 0x%x\n", p->from);
|
||||
packetPool.release(p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldFilterReceived(p)) {
|
||||
LOG_DEBUG("Incoming message was filtered from 0x%x\n", p->from);
|
||||
packetPool.release(p);
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: we avoid calling shouldFilterReceived if we are supposed to ignore certain nodes - because some overrides might
|
||||
// cache/learn of the existence of nodes (i.e. FloodRouter) that they should not
|
||||
if (!ignore)
|
||||
handleReceived(p);
|
||||
|
||||
handleReceived(p);
|
||||
packetPool.release(p);
|
||||
}
|
||||
|
||||
@@ -168,6 +168,8 @@ typedef struct _meshtastic_AdminMessage {
|
||||
bool begin_edit_settings;
|
||||
/* Commits an open transaction for any edits made to config, module config, owner, and channel settings */
|
||||
bool commit_edit_settings;
|
||||
/* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */
|
||||
int32_t factory_reset_device;
|
||||
/* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
|
||||
Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. */
|
||||
int32_t reboot_ota_seconds;
|
||||
@@ -178,8 +180,8 @@ typedef struct _meshtastic_AdminMessage {
|
||||
int32_t reboot_seconds;
|
||||
/* Tell the node to shutdown in this many seconds (or <0 to cancel shutdown) */
|
||||
int32_t shutdown_seconds;
|
||||
/* Tell the node to factory reset, all device settings will be returned to factory defaults. */
|
||||
int32_t factory_reset;
|
||||
/* Tell the node to factory reset config; all device state and configuration will be returned to factory defaults; BLE bonds will be preserved. */
|
||||
int32_t factory_reset_config;
|
||||
/* Tell the node to reset the nodedb. */
|
||||
int32_t nodedb_reset;
|
||||
};
|
||||
@@ -254,11 +256,12 @@ extern "C" {
|
||||
#define meshtastic_AdminMessage_remove_fixed_position_tag 42
|
||||
#define meshtastic_AdminMessage_begin_edit_settings_tag 64
|
||||
#define meshtastic_AdminMessage_commit_edit_settings_tag 65
|
||||
#define meshtastic_AdminMessage_factory_reset_device_tag 94
|
||||
#define meshtastic_AdminMessage_reboot_ota_seconds_tag 95
|
||||
#define meshtastic_AdminMessage_exit_simulator_tag 96
|
||||
#define meshtastic_AdminMessage_reboot_seconds_tag 97
|
||||
#define meshtastic_AdminMessage_shutdown_seconds_tag 98
|
||||
#define meshtastic_AdminMessage_factory_reset_tag 99
|
||||
#define meshtastic_AdminMessage_factory_reset_config_tag 99
|
||||
#define meshtastic_AdminMessage_nodedb_reset_tag 100
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
@@ -298,11 +301,12 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_fixed_position,set_fixed
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,remove_fixed_position,remove_fixed_position), 42) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_edit_settings), 64) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_seconds,reboot_seconds), 97) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,shutdown_seconds,shutdown_seconds), 98) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset,factory_reset), 99) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_config,factory_reset_config), 99) \
|
||||
X(a, STATIC, ONEOF, INT32, (payload_variant,nodedb_reset,nodedb_reset), 100)
|
||||
#define meshtastic_AdminMessage_CALLBACK NULL
|
||||
#define meshtastic_AdminMessage_DEFAULT NULL
|
||||
|
||||
@@ -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.
|
||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||
|
||||
@@ -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 */
|
||||
@@ -197,8 +203,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))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -56,4 +56,12 @@ char *strnstr(const char *s, const char *find, size_t slen)
|
||||
s--;
|
||||
}
|
||||
return ((char *)s);
|
||||
}
|
||||
|
||||
void printBytes(const char *label, const uint8_t *p, size_t numbytes)
|
||||
{
|
||||
LOG_DEBUG("%s: ", label);
|
||||
for (size_t i = 0; i < numbytes; i++)
|
||||
LOG_DEBUG("%02x ", p[i]);
|
||||
LOG_DEBUG("\n");
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include "DebugConfiguration.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/// C++ v17+ clamp function, limits a given value to a range defined by lo and hi
|
||||
template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi)
|
||||
|
||||
@@ -162,12 +162,18 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
handleGetDeviceMetadata(mp);
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_factory_reset_tag: {
|
||||
LOG_INFO("Initiating factory reset\n");
|
||||
case meshtastic_AdminMessage_factory_reset_config_tag: {
|
||||
LOG_INFO("Initiating factory config reset\n");
|
||||
nodeDB->factoryReset();
|
||||
reboot(DEFAULT_REBOOT_SECONDS);
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_factory_reset_device_tag: {
|
||||
LOG_INFO("Initiating full factory reset\n");
|
||||
nodeDB->factoryReset(true);
|
||||
reboot(DEFAULT_REBOOT_SECONDS);
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_nodedb_reset_tag: {
|
||||
LOG_INFO("Initiating node-db reset\n");
|
||||
nodeDB->resetNodes();
|
||||
@@ -551,6 +557,10 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
||||
case meshtastic_ModuleConfig_neighbor_info_tag:
|
||||
LOG_INFO("Setting module config: Neighbor Info\n");
|
||||
moduleConfig.has_neighbor_info = true;
|
||||
if (moduleConfig.neighbor_info.update_interval < min_neighbor_info_broadcast_secs) {
|
||||
LOG_DEBUG("Tried to set update_interval too low, setting to %d\n", default_neighbor_info_broadcast_secs);
|
||||
moduleConfig.neighbor_info.update_interval = default_neighbor_info_broadcast_secs;
|
||||
}
|
||||
moduleConfig.neighbor_info = c.payload_variant.neighbor_info;
|
||||
break;
|
||||
case meshtastic_ModuleConfig_detection_sensor_tag:
|
||||
@@ -822,7 +832,8 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
|
||||
conn.serial.is_connected = powerFSM.getState() == &stateSERIAL;
|
||||
#else
|
||||
conn.serial.is_connected = powerFSM.getState();
|
||||
#endif conn.serial.baud = SERIAL_BAUD;
|
||||
#endif
|
||||
conn.serial.baud = SERIAL_BAUD;
|
||||
|
||||
r.get_device_connection_status_response = conn;
|
||||
r.which_payload_variant = meshtastic_AdminMessage_get_device_connection_status_response_tag;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
#include "input/ExpressLRSFiveWay.h"
|
||||
#include "input/InputBroker.h"
|
||||
#include "input/RotaryEncoderInterruptImpl1.h"
|
||||
#include "input/ScanAndSelect.h"
|
||||
@@ -176,6 +177,9 @@ void setupModules()
|
||||
trackballInterruptImpl1 = new TrackballInterruptImpl1();
|
||||
trackballInterruptImpl1->init();
|
||||
#endif
|
||||
#ifdef INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE
|
||||
expressLRSFiveWayInput = new ExpressLRSFiveWay();
|
||||
#endif
|
||||
#if HAS_SCREEN && !MESHTASTIC_EXCLUDE_CANNEDMESSAGES
|
||||
cannedMessageModule = new CannedMessageModule();
|
||||
#endif
|
||||
|
||||
@@ -120,8 +120,7 @@ int32_t NeighborInfoModule::runOnce()
|
||||
if (airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) {
|
||||
sendNeighborInfo(NODENUM_BROADCAST, false);
|
||||
}
|
||||
return Default::getConfiguredOrDefaultMsScaled(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs,
|
||||
numOnlineNodes);
|
||||
return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_neighbor_info_broadcast_secs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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,27 @@ 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 =
|
||||
lastSetFromPhoneNtpOrGps == 0 ? false : (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) {
|
||||
@@ -175,7 +187,7 @@ meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
p.longitude_i = localPosition.longitude_i;
|
||||
}
|
||||
p.precision_bits = precision;
|
||||
p.time = localPosition.time;
|
||||
p.time = getValidTime(RTCQualityNTP) > 0 ? getValidTime(RTCQualityNTP) : localPosition.time;
|
||||
|
||||
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) {
|
||||
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
int32_t DeviceTelemetryModule::runOnce()
|
||||
{
|
||||
refreshUptime();
|
||||
bool isImpoliteRole = config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR ||
|
||||
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER;
|
||||
if (((lastSentToMesh == 0) ||
|
||||
((uptimeLastMs - lastSentToMesh) >=
|
||||
Default::getConfiguredOrDefaultMsScaled(moduleConfig.telemetry.device_update_interval,
|
||||
default_telemetry_broadcast_interval_secs, numOnlineNodes))) &&
|
||||
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
|
||||
airTime->isTxAllowedAirUtil() && config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
|
||||
airTime->isTxAllowedChannelUtil(!isImpoliteRole) && airTime->isTxAllowedAirUtil() &&
|
||||
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
|
||||
config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
||||
sendTelemetry();
|
||||
lastSentToMesh = uptimeLastMs;
|
||||
@@ -80,9 +82,8 @@ meshtastic_MeshPacket *DeviceTelemetryModule::allocReply()
|
||||
meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry()
|
||||
{
|
||||
meshtastic_Telemetry t = meshtastic_Telemetry_init_zero;
|
||||
|
||||
t.time = getTime();
|
||||
t.which_variant = meshtastic_Telemetry_device_metrics_tag;
|
||||
t.time = getTime();
|
||||
t.variant.device_metrics.air_util_tx = airTime->utilizationTXPercent();
|
||||
#if ARCH_PORTDUINO
|
||||
t.variant.device_metrics.battery_level = MAGIC_USB_BATTERY_LEVEL;
|
||||
|
||||
@@ -418,6 +418,8 @@ meshtastic_MeshPacket *EnvironmentTelemetryModule::allocReply()
|
||||
bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
{
|
||||
meshtastic_Telemetry m = meshtastic_Telemetry_init_zero;
|
||||
m.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
m.time = getTime();
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
if (t1000xSensor.getMetrics(&m)) {
|
||||
#else
|
||||
|
||||
@@ -222,6 +222,8 @@ meshtastic_MeshPacket *PowerTelemetryModule::allocReply()
|
||||
bool PowerTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
||||
{
|
||||
meshtastic_Telemetry m = meshtastic_Telemetry_init_zero;
|
||||
m.which_variant = meshtastic_Telemetry_power_metrics_tag;
|
||||
m.time = getTime();
|
||||
if (getPowerTelemetry(&m)) {
|
||||
LOG_INFO("(Sending): ch1_voltage=%f, ch1_current=%f, ch2_voltage=%f, ch2_current=%f, "
|
||||
"ch3_voltage=%f, ch3_current=%f\n",
|
||||
|
||||
@@ -382,7 +382,7 @@ ProcessMessage StoreForwardModule::handleReceived(const meshtastic_MeshPacket &m
|
||||
LOG_DEBUG("*** Legacy Request to send\n");
|
||||
|
||||
// Send the last 60 minutes of messages.
|
||||
if (this->busy || channels.isDefaultChannel(channels.getByIndex(mp.channel))) {
|
||||
if (this->busy || channels.isDefaultChannel(mp.channel)) {
|
||||
sendErrorTextMessage(getFrom(&mp), mp.decoded.want_response);
|
||||
} else {
|
||||
storeForwardModule->historySend(historyReturnWindow * 60, getFrom(&mp));
|
||||
@@ -447,7 +447,7 @@ bool StoreForwardModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
|
||||
requests_history++;
|
||||
LOG_INFO("*** Client Request to send HISTORY\n");
|
||||
// Send the last 60 minutes of messages.
|
||||
if (this->busy || channels.isDefaultChannel(channels.getByIndex(mp.channel))) {
|
||||
if (this->busy || channels.isDefaultChannel(mp.channel)) {
|
||||
sendErrorTextMessage(getFrom(&mp), mp.decoded.want_response);
|
||||
} else {
|
||||
if ((p->which_variant == meshtastic_StoreAndForward_history_tag) && (p->variant.history.window > 0)) {
|
||||
|
||||
@@ -26,41 +26,3 @@ void *operator new(size_t size, SimpleAllocator &p)
|
||||
{
|
||||
return p.alloc(size);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This was a dumb idea, turn off for now
|
||||
|
||||
SimpleAllocator *activeAllocator;
|
||||
|
||||
AllocatorScope::AllocatorScope(SimpleAllocator &a)
|
||||
{
|
||||
assert(!activeAllocator);
|
||||
activeAllocator = &a;
|
||||
}
|
||||
|
||||
AllocatorScope::~AllocatorScope()
|
||||
{
|
||||
assert(activeAllocator);
|
||||
activeAllocator = NULL;
|
||||
}
|
||||
|
||||
/// Global new/delete, uses a simple allocator if it is in scope
|
||||
|
||||
void *operator new(size_t sz) throw(std::bad_alloc)
|
||||
{
|
||||
void *mem = activeAllocator ? activeAllocator->alloc(sz) : malloc(sz);
|
||||
if (mem)
|
||||
return mem;
|
||||
else
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void operator delete(void *ptr) throw()
|
||||
{
|
||||
if (activeAllocator)
|
||||
LOG_WARN("Leaking an active allocator object\n"); // We don't properly handle this yet
|
||||
else
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_WIO_WM1110
|
||||
#elif defined(TRACKER_T1000_E)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_TRACKER_T1000_E
|
||||
#elif defined(ME25LS01)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_ME25LS01
|
||||
#elif defined(PRIVATE_HW) || defined(FEATHER_DIY)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_PRIVATE_HW
|
||||
#else
|
||||
@@ -116,4 +118,4 @@
|
||||
#if !defined(PIN_SERIAL_RX) && !defined(NRF52840_XXAA)
|
||||
// No serial ports on this board - ONLY use segger in memory console
|
||||
#define USE_SEGGER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -99,6 +99,7 @@ void portduinoSetup()
|
||||
settingsStrings[spidev] = "";
|
||||
settingsStrings[displayspidev] = "";
|
||||
settingsMap[spiSpeed] = 2000000;
|
||||
settingsMap[ascii_logs] = !isatty(1);
|
||||
|
||||
YAML::Node yamlConfig;
|
||||
|
||||
@@ -152,6 +153,10 @@ void portduinoSetup()
|
||||
settingsMap[logoutputlevel] = level_error;
|
||||
}
|
||||
settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as<std::string>("");
|
||||
if (yamlConfig["Logging"]["AsciiLogs"]) {
|
||||
// Default is !isatty(1) but can be set explicitly in config.yaml
|
||||
settingsMap[ascii_logs] = yamlConfig["Logging"]["AsciiLogs"].as<bool>();
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Lora"]) {
|
||||
settingsMap[use_sx1262] = false;
|
||||
|
||||
@@ -53,7 +53,8 @@ enum configNames {
|
||||
webserverport,
|
||||
webserverrootpath,
|
||||
maxtophone,
|
||||
maxnodes
|
||||
maxnodes,
|
||||
ascii_logs
|
||||
};
|
||||
enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9488, hx8357d };
|
||||
enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
|
||||
@@ -62,4 +63,4 @@ enum { level_error, level_warn, level_info, level_debug, level_trace };
|
||||
extern std::map<configNames, int> settingsMap;
|
||||
extern std::map<configNames, std::string> settingsStrings;
|
||||
extern std::ofstream traceFile;
|
||||
int initGPIOPin(int pinNum, std::string gpioChipname);
|
||||
int initGPIOPin(int pinNum, std::string gpioChipname);
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -126,7 +126,7 @@ extern "C" {
|
||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||
|
||||
// Buzzer
|
||||
#define BUZZER_EN_PIN -1
|
||||
#define PIN_BUZZER (0 + 25)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@@ -136,4 +136,4 @@ extern "C" {
|
||||
* Arduino objects - C++ only
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#endif // _VARIANT_ME25LS01_4Y10TD_
|
||||
#endif // _VARIANT_ME25LS01_4Y10TD_
|
||||
|
||||
@@ -149,7 +149,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||
|
||||
// Buzzer
|
||||
#define BUZZER_EN_PIN -1
|
||||
#define PIN_BUZZER (0 + 25)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@@ -159,4 +159,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
* Arduino objects - C++ only
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#endif // _VARIANT_ME25LS01_4Y10TD__
|
||||
#endif // _VARIANT_ME25LS01_4Y10TD__
|
||||
|
||||
@@ -40,3 +40,14 @@
|
||||
|
||||
#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 PERIPHERAL_WARMUP_MS 100
|
||||
#define SENSOR_GPS_CONFLICT
|
||||
|
||||
#define ESP32S3_WAKE_TYPE ESP_EXT1_WAKEUP_ANY_HIGH
|
||||
@@ -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
|
||||
|
||||
@@ -41,14 +41,11 @@
|
||||
|
||||
/*
|
||||
Five way button when using ADC.
|
||||
2.632V, 2.177V, 1.598V, 1.055V, 0V
|
||||
|
||||
Possible ADC Values:
|
||||
{ UP, DOWN, LEFT, RIGHT, ENTER, IDLE }
|
||||
3227, 0 ,1961, 2668, 1290, 4095
|
||||
https://github.com/ExpressLRS/targets/blob/f3215b5ec891108db1a13523e4163950cfcadaac/TX/Radiomaster%20Bandit.json#L41
|
||||
*/
|
||||
#define BUTTON_PIN 39
|
||||
#define BUTTON_NEED_PULLUP
|
||||
#define INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE
|
||||
#define PIN_JOYSTICK 39
|
||||
#define JOYSTICK_ADC_VALS /*UP*/ 3227, /*DOWN*/ 0, /*LEFT*/ 1961, /*RIGHT*/ 2668, /*OK*/ 1290, /*IDLE*/ 4095
|
||||
|
||||
#define DISPLAY_FLIP_SCREEN
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// rxd = 9
|
||||
|
||||
#define EXT_NOTIFY_OUT 22
|
||||
#define BUTTON_PIN 17
|
||||
#undef BUTTON_PIN // Pin 17 used for antenna switching via DIO4
|
||||
|
||||
#define LED_PIN PIN_LED
|
||||
|
||||
@@ -32,23 +32,28 @@
|
||||
|
||||
// https://www.waveshare.com/rp2040-lora.htm
|
||||
// https://www.waveshare.com/img/devkit/RP2040-LoRa-HF/RP2040-LoRa-HF-details-11.jpg
|
||||
#define LORA_SCK 14 // 10
|
||||
#define LORA_MISO 24 // 12
|
||||
#define LORA_MOSI 15 // 11
|
||||
#define LORA_CS 13 // 3
|
||||
#define LORA_SCK 14 // GPIO14
|
||||
#define LORA_MISO 24 // GPIO24
|
||||
#define LORA_MOSI 15 // GPIO15
|
||||
#define LORA_CS 13 // GPIO13
|
||||
|
||||
#define LORA_DIO0 RADIOLIB_NC
|
||||
#define LORA_RESET 23 // 15
|
||||
#define LORA_DIO1 16 // 20
|
||||
#define LORA_DIO2 18 // 2
|
||||
#define LORA_DIO3 RADIOLIB_NC
|
||||
#define LORA_DIO4 17
|
||||
#define LORA_DIO0 RADIOLIB_NC // No GPIO connection
|
||||
#define LORA_RESET 23 // GPIO23
|
||||
#define LORA_BUSY 18 // GPIO18
|
||||
#define LORA_DIO1 16 // GPIO16
|
||||
#define LORA_DIO2 RADIOLIB_NC // Antenna switching, no GPIO connection
|
||||
#define LORA_DIO3 RADIOLIB_NC // No GPIO connection
|
||||
#define LORA_DIO4 17 // GPIO17
|
||||
|
||||
// On rp2040-lora board the antenna switch is wired and works with complementary-pin control logic.
|
||||
// See PE4259 datasheet page 4
|
||||
|
||||
#ifdef USE_SX1262
|
||||
#define SX126X_CS LORA_CS
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_DIO2
|
||||
#define SX126X_BUSY LORA_BUSY
|
||||
#define SX126X_RESET LORA_RESET
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO2_AS_RF_SWITCH // Antenna switch CTRL
|
||||
#define SX126X_RXEN LORA_DIO4 // Antenna switch !CTRL via GPIO17
|
||||
// #define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 2
|
||||
minor = 4
|
||||
build = 2
|
||||
build = 4
|
||||
|
||||
Reference in New Issue
Block a user