Compare commits

..

18 Commits

Author SHA1 Message Date
Ben Meadors
e9bde80b57 change tft clear() to fillScreen() (#3077)
Maintains compatability with ESPI driver.

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2024-01-11 10:06:26 -06:00
Mark Trevor Birss
ccb5485510 Add SX1262 to M5Stack CoreInk (#3078)
* Update platformio.ini

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h
2024-01-11 10:06:02 -06:00
Ben Meadors
0d85069bec Heltec paper (#3069)
* Attempts at getting the Heltec Wireless Paper eink operational

* Bogus comment

* Fixing Support For Heltec Wireless Paper

---------

Co-authored-by: NfN Orange <orange@reveb.la>
2024-01-09 19:48:21 -06:00
GUVWAF
77ff1704db Allow button press if CannedMessage updown1 or rotary1 are not enabled (#3067)
`BUTTON_PIN` may be 0, which is equal to `inputbroker_pin_press` by default
2024-01-09 19:45:54 -06:00
GUVWAF
613a2bfb70 Update exception decoder for other platforms (#3070) 2024-01-09 19:45:03 -06:00
Ben Meadors
ea651c2f8f Remove gps_attempt_time and use broadcast interval instead (#3064) 2024-01-07 09:35:19 -06:00
Mictronics
c2afa879b8 Fix LED pinout for T-Echo board marked v1.0, date 2021-6-28 (#3051)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-07 07:40:12 -06:00
Ben Meadors
59253d9c78 Don't reboot after removing node from DB (#3065) 2024-01-07 07:37:13 -06:00
github-actions[bot]
be46f9ea24 [create-pull-request] automated change (#3063)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-06 15:23:40 -06:00
Ben Meadors
674fd32349 RP2040 Enter uf2 DFU mode (#3062)
* Pico enter dfu mode

* Ungaurd pico
2024-01-06 14:39:27 -06:00
Amin Husni
bacc525d0a Add Malaysia Region (#3053)
* Add Malaysia Region

Add frequency for 433MHz and 919MHz with specific power limit and limitation.

* Update RadioInterface.cpp

Formatting issues
2024-01-05 15:37:31 -06:00
github-actions[bot]
aa10a3ec40 [create-pull-request] automated change (#3055)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-01-04 18:54:44 -06:00
Jonathan Bennett
e3c768bf10 Update platformio.ini -- set target default to tbeam (#3054) 2024-01-04 12:22:45 -06:00
GUVWAF
943367edd0 Fix "watch GPIOs" feature of Remote Hardware module (#3047)
* Fix watch GPIO feature of Remote Hardware

* Add Remote Hardware messages to JSON output

* Add curly brackets

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-01-03 15:08:28 -06:00
Jonathan Bennett
4577646f8b Get rid of max-parallel build for rp2040 2023-12-29 17:49:25 -06:00
Jonathan Bennett
1ae02a9a28 Add dependencies for native build 2023-12-29 16:47:42 -06:00
Jonathan Bennett
28951ea1e0 Add libbluetooth-dev to build image 2023-12-29 12:35:42 -06:00
github-actions[bot]
2e9cc73ebb [create-pull-request] automated change (#3046)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-12-27 18:40:54 -06:00
25 changed files with 323 additions and 100 deletions

View File

@@ -16,6 +16,19 @@ runs:
run: | run: |
sudo apt-get install -y cppcheck sudo apt-get install -y cppcheck
- name: Install libbluetooth
shell: bash
run: |
sudo apt-get install -y libbluetooth-dev
- name: Install libgpiod
shell: bash
run: |
sudo apt-get install -y libgpiod-dev
- name: Install libyaml-cpp
shell: bash
run: |
sudo apt-get install -y libyaml-cpp-dev
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:

View File

@@ -120,7 +120,6 @@ jobs:
build-rpi2040: build-rpi2040:
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 2
matrix: matrix:
include: include:
- board: pico - board: pico

View File

@@ -11,19 +11,22 @@ Meshtastic notes:
* version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder * version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder
which adds in ESP32 Backtrace decoding. which adds in ESP32 Backtrace decoding.
* this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin * this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin
* also updated the toolchain name, which will be set according to the platform
To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run: To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run:
$ bin/exception_decoder.py backtrace.txt $ bin/exception_decoder.py backtrace.txt
For a platform other than ESP32, use the -p option, e.g.:
$ bin/exception_decoder.py -p ESP32S3 backtrace.txt
To specify a specific .elf file, use the -e option, e.g.:
$ bin/exception_decoder.py -e firmware.elf backtrace.txt
""" """
import argparse import argparse
import os
import re import re
import subprocess import subprocess
from collections import namedtuple
import sys import sys
from collections import namedtuple
import os
EXCEPTIONS = [ EXCEPTIONS = [
"Illegal instruction", "Illegal instruction",
@@ -55,24 +58,39 @@ EXCEPTIONS = [
"LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING", "LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING",
"reserved", "reserved",
"LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads", "LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads",
"StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores" "StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores",
] ]
PLATFORMS = { PLATFORMS = {
"ESP8266": "lx106", "ESP8266": "xtensa-lx106",
"ESP32": "esp32" "ESP32": "xtensa-esp32",
"ESP32S3": "xtensa-esp32s3",
"ESP32C3": "riscv32-esp",
}
TOOLS = {
"ESP8266": "xtensa",
"ESP32": "xtensa-esp32",
"ESP32S3": "xtensa-esp32s3",
"ESP32C3": "riscv32-esp",
} }
BACKTRACE_REGEX = re.compile(r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b") BACKTRACE_REGEX = re.compile(
r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b"
)
EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$") EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
COUNTER_REGEX = re.compile('^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) ' COUNTER_REGEX = re.compile(
'excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$') "^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) "
"excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$"
)
CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$") CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$")
POINTER_REGEX = re.compile('^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$') POINTER_REGEX = re.compile(
STACK_BEGIN = '>>>stack>>>' "^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$"
STACK_END = '<<<stack<<<' )
STACK_BEGIN = ">>>stack>>>"
STACK_END = "<<<stack<<<"
STACK_REGEX = re.compile( STACK_REGEX = re.compile(
'^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$') "^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$"
)
StackLine = namedtuple("StackLine", ["offset", "content"]) StackLine = namedtuple("StackLine", ["offset", "content"])
@@ -96,15 +114,18 @@ class ExceptionDataParser(object):
self.stack = [] self.stack = []
def _parse_backtrace(self, line): def _parse_backtrace(self, line):
if line.startswith('Backtrace:'): if line.startswith("Backtrace:"):
self.stack = [StackLine(offset=0, content=(addr,)) for addr in BACKTRACE_REGEX.findall(line)] self.stack = [
StackLine(offset=0, content=(addr,))
for addr in BACKTRACE_REGEX.findall(line)
]
return None return None
return self._parse_backtrace return self._parse_backtrace
def _parse_exception(self, line): def _parse_exception(self, line):
match = EXCEPTION_REGEX.match(line) match = EXCEPTION_REGEX.match(line)
if match is not None: if match is not None:
self.exception = int(match.group('exc')) self.exception = int(match.group("exc"))
return self._parse_counters return self._parse_counters
return self._parse_exception return self._parse_exception
@@ -144,14 +165,22 @@ class ExceptionDataParser(object):
if line != STACK_END: if line != STACK_END:
match = STACK_REGEX.match(line) match = STACK_REGEX.match(line)
if match is not None: if match is not None:
self.stack.append(StackLine(offset=match.group("off"), self.stack.append(
content=(match.group("c1"), match.group("c2"), match.group("c3"), StackLine(
match.group("c4")))) offset=match.group("off"),
content=(
match.group("c1"),
match.group("c2"),
match.group("c3"),
match.group("c4"),
),
)
)
return self._parse_stack_line return self._parse_stack_line
return None return None
def parse_file(self, file, platform, stack_only=False): def parse_file(self, file, platform, stack_only=False):
if platform == 'ESP32': if platform != "ESP8266":
func = self._parse_backtrace func = self._parse_backtrace
else: else:
func = self._parse_exception func = self._parse_exception
@@ -175,7 +204,9 @@ class AddressResolver(object):
self._address_map = {} self._address_map = {}
def _lookup(self, addresses): def _lookup(self, addresses):
cmd = [self._tool, "-aipfC", "-e", self._elf] + [addr for addr in addresses if addr is not None] cmd = [self._tool, "-aipfC", "-e", self._elf] + [
addr for addr in addresses if addr is not None
]
if sys.version_info[0] < 3: if sys.version_info[0] < 3:
output = subprocess.check_output(cmd) output = subprocess.check_output(cmd)
@@ -190,19 +221,27 @@ class AddressResolver(object):
match = line_regex.match(line) match = line_regex.match(line)
if match is None: if match is None:
if last is not None and line.startswith('(inlined by)'): if last is not None and line.startswith("(inlined by)"):
line = line [12:].strip() line = line[12:].strip()
self._address_map[last] += ("\n \-> inlined by: " + line) self._address_map[last] += "\n \-> inlined by: " + line
continue continue
if match.group("result") == '?? ??:0': if match.group("result") == "?? ??:0":
continue continue
self._address_map[match.group("addr")] = match.group("result") self._address_map[match.group("addr")] = match.group("result")
last = match.group("addr") last = match.group("addr")
def fill(self, parser): def fill(self, parser):
addresses = [parser.epc1, parser.epc2, parser.epc3, parser.excvaddr, parser.sp, parser.end, parser.offset] addresses = [
parser.epc1,
parser.epc2,
parser.epc3,
parser.excvaddr,
parser.sp,
parser.end,
parser.offset,
]
for line in parser.stack: for line in parser.stack:
addresses.extend(line.content) addresses.extend(line.content)
@@ -257,8 +296,10 @@ def print_stack(lines, resolver):
def print_result(parser, resolver, platform, full=True, stack_only=False): def print_result(parser, resolver, platform, full=True, stack_only=False):
if platform == 'ESP8266' and not stack_only: if platform == "ESP8266" and not stack_only:
print('Exception: {} ({})'.format(parser.exception, EXCEPTIONS[parser.exception])) print(
"Exception: {} ({})".format(parser.exception, EXCEPTIONS[parser.exception])
)
print("") print("")
print_addr("epc1", parser.epc1, resolver) print_addr("epc1", parser.epc1, resolver)
@@ -285,15 +326,33 @@ def print_result(parser, resolver, platform, full=True, stack_only=False):
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(description="decode ESP Stacktraces.") parser = argparse.ArgumentParser(description="decode ESP Stacktraces.")
parser.add_argument("-p", "--platform", help="The platform to decode from", choices=PLATFORMS.keys(), parser.add_argument(
default="ESP32") "-p",
parser.add_argument("-t", "--tool", help="Path to the xtensa toolchain", "--platform",
default="~/.platformio/packages/toolchain-xtensa32/") help="The platform to decode from",
parser.add_argument("-e", "--elf", help="path to elf file", choices=PLATFORMS.keys(),
default=".pio/build/esp32/firmware.elf") default="ESP32",
parser.add_argument("-f", "--full", help="Print full stack dump", action="store_true") )
parser.add_argument("-s", "--stack_only", help="Decode only a stractrace", action="store_true") parser.add_argument(
parser.add_argument("file", help="The file to read the exception data from ('-' for STDIN)", default="-") "-t",
"--tool",
help="Path to the toolchain (without specific platform)",
default="~/.platformio/packages/toolchain-",
)
parser.add_argument(
"-e", "--elf", help="path to elf file", default=".pio/build/tbeam/firmware.elf"
)
parser.add_argument(
"-f", "--full", help="Print full stack dump", action="store_true"
)
parser.add_argument(
"-s", "--stack_only", help="Decode only a stractrace", action="store_true"
)
parser.add_argument(
"file",
help="The file to read the exception data from ('-' for STDIN)",
default="-",
)
return parser.parse_args() return parser.parse_args()
@@ -309,10 +368,12 @@ if __name__ == "__main__":
sys.exit(1) sys.exit(1)
file = open(args.file, "r") file = open(args.file, "r")
addr2line = os.path.join(os.path.abspath(os.path.expanduser(args.tool)), addr2line = os.path.join(
"bin/xtensa-" + PLATFORMS[args.platform] + "-elf-addr2line") os.path.abspath(os.path.expanduser(args.tool + TOOLS[args.platform])),
if os.name == 'nt': "bin/" + PLATFORMS[args.platform] + "-elf-addr2line",
addr2line += '.exe' )
if os.name == "nt":
addr2line += ".exe"
if not os.path.exists(addr2line): if not os.path.exists(addr2line):
print("ERROR: addr2line not found (" + addr2line + ")") print("ERROR: addr2line not found (" + addr2line + ")")

View File

@@ -2,7 +2,7 @@
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[platformio] [platformio]
;default_envs = tbeam default_envs = tbeam
;default_envs = pico ;default_envs = pico
;default_envs = tbeam-s3-core ;default_envs = tbeam-s3-core
;default_envs = tbeam0.7 ;default_envs = tbeam0.7
@@ -27,7 +27,7 @@
;default_envs = m5stack-coreink ;default_envs = m5stack-coreink
;default_envs = rak4631 ;default_envs = rak4631
;default_envs = rak10701 ;default_envs = rak10701
default_envs = wio-e5 ;default_envs = wio-e5
extra_configs = extra_configs =
arch/*/*.ini arch/*/*.ini

View File

@@ -138,6 +138,7 @@ class ButtonThread : public concurrency::OSThread
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) != if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
moduleConfig.canned_message.inputbroker_pin_press) || moduleConfig.canned_message.inputbroker_pin_press) ||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
!moduleConfig.canned_message.enabled) { !moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }
@@ -232,4 +233,4 @@ class ButtonThread : public concurrency::OSThread
} }
}; };
} // namespace concurrency } // namespace concurrency

View File

@@ -596,11 +596,12 @@ void GPS::setAwake(bool on)
*/ */
uint32_t GPS::getWakeTime() const uint32_t GPS::getWakeTime() const
{ {
uint32_t t = config.position.gps_attempt_time; uint32_t t = config.position.position_broadcast_secs;
if (t == UINT32_MAX) if (t == UINT32_MAX)
return t; // already maxint return t; // already maxint
return t * 1000;
return getConfiguredOrDefaultMs(t, default_broadcast_interval_secs);
} }
/** Get how long we should sleep between aqusition attempts in msecs /** Get how long we should sleep between aqusition attempts in msecs

View File

@@ -70,7 +70,7 @@ class GPS : private concurrency::OSThread
/** /**
* hasValidLocation - indicates that the position variables contain a complete * hasValidLocation - indicates that the position variables contain a complete
* GPS location, valid and fresh (< gps_update_interval + gps_attempt_time) * GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
*/ */
bool hasValidLocation = false; // default to false, until we complete our first read bool hasValidLocation = false; // default to false, until we complete our first read

View File

@@ -7,9 +7,9 @@
#include "main.h" #include "main.h"
#include <SPI.h> #include <SPI.h>
// #ifdef HELTEC_WIRELESS_PAPER #ifdef HELTEC_WIRELESS_PAPER
// SPIClass *hspi = NULL; SPIClass *hspi = NULL;
// #endif #endif
#define COLORED GxEPD_BLACK #define COLORED GxEPD_BLACK
#define UNCOLORED GxEPD_WHITE #define UNCOLORED GxEPD_WHITE
@@ -47,7 +47,7 @@
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)
// #define TECHO_DISPLAY_MODEL GxEPD2_213_T5D // #define TECHO_DISPLAY_MODEL GxEPD2_213_T5D
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN #define TECHO_DISPLAY_MODEL GxEPD2_213_FC1
#endif #endif
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay; GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
@@ -71,7 +71,7 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY
// setGeometry(GEOMETRY_RAWMODE, 200, 200); // setGeometry(GEOMETRY_RAWMODE, 200, 200);
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)
// setGeometry(GEOMETRY_RAWMODE, 212, 104); // GxEPD2_213_BN - 2.13 inch b/w 250x122
setGeometry(GEOMETRY_RAWMODE, 250, 122); setGeometry(GEOMETRY_RAWMODE, 250, 122);
#elif defined(MAKERPYTHON) #elif defined(MAKERPYTHON)
// GxEPD2_290_T5D // GxEPD2_290_T5D
@@ -119,7 +119,6 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK); // tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
for (uint32_t y = 0; y < displayHeight; y++) { for (uint32_t y = 0; y < displayHeight; y++) {
for (uint32_t x = 0; x < displayWidth; x++) { for (uint32_t x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient // get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient
auto b = buffer[x + (y / 8) * displayWidth]; auto b = buffer[x + (y / 8) * displayWidth];
auto isset = b & (1 << (y & 7)); auto isset = b & (1 << (y & 7));
@@ -148,7 +147,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
#elif defined(PCA10059) || defined(M5_COREINK) #elif defined(PCA10059) || defined(M5_COREINK)
adafruitDisplay->nextPage(); adafruitDisplay->nextPage();
#elif defined(HELTEC_WIRELESS_PAPER)
adafruitDisplay->nextPage();
#elif defined(PRIVATE_HW) || defined(my) #elif defined(PRIVATE_HW) || defined(my)
adafruitDisplay->nextPage(); adafruitDisplay->nextPage();
@@ -231,13 +231,16 @@ bool EInkDisplay::connect()
} }
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)
{ {
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY); hspi = new SPIClass(HSPI);
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
delay(100);
pinMode(Vext, OUTPUT);
digitalWrite(Vext, LOW);
delay(100);
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi);
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel); adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
// hspi = new SPIClass(HSPI); adafruitDisplay->init();
// hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
adafruitDisplay->init(115200, true, 10, false, SPI, SPISettings(6000000, MSBFIRST, SPI_MODE0));
adafruitDisplay->setRotation(3); adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
} }
#elif defined(PCA10059) #elif defined(PCA10059)
{ {

View File

@@ -425,7 +425,8 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g
void TFTDisplay::display(bool fromBlank) void TFTDisplay::display(bool fromBlank)
{ {
if (fromBlank) if (fromBlank)
tft->clear(); tft->fillScreen(TFT_BLACK);
// tft->clear();
concurrency::LockGuard g(spiLock); concurrency::LockGuard g(spiLock);
uint16_t x, y; uint16_t x, y;

View File

@@ -223,7 +223,6 @@ void NodeDB::installDefaultConfig()
void NodeDB::initConfigIntervals() void NodeDB::initConfigIntervals()
{ {
config.position.gps_update_interval = default_gps_update_interval; config.position.gps_update_interval = default_gps_update_interval;
config.position.gps_attempt_time = default_gps_attempt_time;
config.position.position_broadcast_secs = default_broadcast_interval_secs; config.position.position_broadcast_secs = default_broadcast_interval_secs;
config.power.ls_secs = default_ls_secs; config.power.ls_secs = default_ls_secs;
@@ -301,8 +300,6 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
initModuleConfigIntervals(); initModuleConfigIntervals();
} else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) { } else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
config.display.screen_on_secs = 1; config.display.screen_on_secs = 1;
} else if (role == meshtastic_Config_DeviceConfig_Role_TRACKER) {
config.position.gps_update_interval = 30;
} else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) { } else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) {
moduleConfig.telemetry.environment_measurement_enabled = true; moduleConfig.telemetry.environment_measurement_enabled = true;
moduleConfig.telemetry.environment_update_interval = 300; moduleConfig.telemetry.environment_update_interval = 300;

View File

@@ -179,9 +179,6 @@ extern NodeDB nodeDB;
prefs.gps_update_interval = oneday prefs.gps_update_interval = oneday
prefs.is_power_saving = True prefs.is_power_saving = True
# allow up to five minutes for each new GPS lock attempt
prefs.gps_attempt_time = 300
*/ */
// Our delay functions check for this for times that should never expire // Our delay functions check for this for times that should never expire
@@ -192,7 +189,6 @@ extern NodeDB nodeDB;
#define ONE_DAY 24 * 60 * 60 #define ONE_DAY 24 * 60 * 60
#define default_gps_attempt_time IF_ROUTER(5 * 60, 15 * 60)
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60) #define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60) #define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
#define default_wait_bluetooth_secs IF_ROUTER(1, 60) #define default_wait_bluetooth_secs IF_ROUTER(1, 60)

View File

@@ -107,10 +107,25 @@ const RegionInfo regions[] = {
*/ */
RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false), RDEF(UA_868, 868.0f, 868.6f, 1, 0, 14, true, false, false),
/*
Malaysia
433 - 435 MHz at 100mW, no restrictions.
https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf
*/
RDEF(MY_433, 433.0f, 435.0f, 100, 0, 20, true, false, false),
/*
Malaysia
919 - 923 Mhz at 500mW, no restrictions.
923 - 924 MHz at 500mW with 1% duty cycle OR frequency hopping.
Frequency hopping is used for 919 - 923 MHz.
https://www.mcmc.gov.my/skmmgovmy/media/General/pdf/Short-Range-Devices-Specification.pdf
*/
RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false),
/* /*
2.4 GHZ WLAN Band equivalent. Only for SX128x chips. 2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
*/ */
RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true), RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true),
/* /*

View File

@@ -201,7 +201,11 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
/* Ukraine 433mhz */ /* Ukraine 433mhz */
meshtastic_Config_LoRaConfig_RegionCode_UA_433 = 14, meshtastic_Config_LoRaConfig_RegionCode_UA_433 = 14,
/* Ukraine 868mhz */ /* Ukraine 868mhz */
meshtastic_Config_LoRaConfig_RegionCode_UA_868 = 15 meshtastic_Config_LoRaConfig_RegionCode_UA_868 = 15,
/* Malaysia 433mhz */
meshtastic_Config_LoRaConfig_RegionCode_MY_433 = 16,
/* Malaysia 919mhz */
meshtastic_Config_LoRaConfig_RegionCode_MY_919 = 17
} meshtastic_Config_LoRaConfig_RegionCode; } meshtastic_Config_LoRaConfig_RegionCode;
/* Standard predefined channel settings /* Standard predefined channel settings
@@ -281,10 +285,7 @@ typedef struct _meshtastic_Config_PositionConfig {
or zero for the default of once every 30 seconds or zero for the default of once every 30 seconds
or a very large value (maxint) to update only once at boot. */ or a very large value (maxint) to update only once at boot. */
uint32_t gps_update_interval; uint32_t gps_update_interval;
/* How long should we try to get our position during each gps_update_interval attempt? (in seconds) /* Deprecated in favor of using smart / regular broadcast intervals as implicit attempt time */
Or if zero, use the default of 30 seconds.
If we don't get a new gps fix in that time, the gps will be put into sleep until the next gps_update_rate
window. */
uint32_t gps_attempt_time; uint32_t gps_attempt_time;
/* Bit field of boolean configuration options for POSITION messages /* Bit field of boolean configuration options for POSITION messages
(bitwise OR of PositionFlags) */ (bitwise OR of PositionFlags) */
@@ -525,8 +526,8 @@ extern "C" {
#define _meshtastic_Config_DisplayConfig_DisplayMode_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayMode)(meshtastic_Config_DisplayConfig_DisplayMode_COLOR+1)) #define _meshtastic_Config_DisplayConfig_DisplayMode_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayMode)(meshtastic_Config_DisplayConfig_DisplayMode_COLOR+1))
#define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET #define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_UA_868 #define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_MY_919
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_UA_868+1)) #define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_MY_919+1))
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST #define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE #define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE

View File

@@ -185,12 +185,11 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
case meshtastic_AdminMessage_remove_by_nodenum_tag: { case meshtastic_AdminMessage_remove_by_nodenum_tag: {
LOG_INFO("Client is receiving a remove_nodenum command.\n"); LOG_INFO("Client is receiving a remove_nodenum command.\n");
nodeDB.removeNodeByNum(r->remove_by_nodenum); nodeDB.removeNodeByNum(r->remove_by_nodenum);
reboot(DEFAULT_REBOOT_SECONDS);
break; break;
} }
case meshtastic_AdminMessage_enter_dfu_mode_request_tag: { case meshtastic_AdminMessage_enter_dfu_mode_request_tag: {
LOG_INFO("Client is requesting to enter DFU mode.\n"); LOG_INFO("Client is requesting to enter DFU mode.\n");
#ifdef ARCH_NRF52 #if defined(ARCH_NRF52) || defined(ARCH_RP2040)
enterDfuMode(); enterDfuMode();
#endif #endif
break; break;

View File

@@ -56,7 +56,7 @@ bool RemoteHardwareModule::handleReceivedProtobuf(const meshtastic_MeshPacket &r
LOG_INFO("Received RemoteHardware type=%d\n", p.type); LOG_INFO("Received RemoteHardware type=%d\n", p.type);
switch (p.type) { switch (p.type) {
case meshtastic_HardwareMessage_Type_WRITE_GPIOS: case meshtastic_HardwareMessage_Type_WRITE_GPIOS: {
// Print notification to LCD screen // Print notification to LCD screen
screen->print("Write GPIOs\n"); screen->print("Write GPIOs\n");
@@ -69,6 +69,7 @@ bool RemoteHardwareModule::handleReceivedProtobuf(const meshtastic_MeshPacket &r
pinModes(p.gpio_mask, OUTPUT); pinModes(p.gpio_mask, OUTPUT);
break; break;
}
case meshtastic_HardwareMessage_Type_READ_GPIOS: { case meshtastic_HardwareMessage_Type_READ_GPIOS: {
// Print notification to LCD screen // Print notification to LCD screen
@@ -92,8 +93,9 @@ bool RemoteHardwareModule::handleReceivedProtobuf(const meshtastic_MeshPacket &r
watchGpios = p.gpio_mask; watchGpios = p.gpio_mask;
lastWatchMsec = 0; // Force a new publish soon lastWatchMsec = 0; // Force a new publish soon
previousWatch = previousWatch =
~watchGpios; // generate a 'previous' value which is guaranteed to not match (to force an initial publish) ~watchGpios; // generate a 'previous' value which is guaranteed to not match (to force an initial publish)
enabled = true; // Let our thread run at least once enabled = true; // Let our thread run at least once
setInterval(2000); // Set a new interval so we'll run soon
LOG_INFO("Now watching GPIOs 0x%llx\n", watchGpios); LOG_INFO("Now watching GPIOs 0x%llx\n", watchGpios);
break; break;
} }
@@ -118,6 +120,7 @@ int32_t RemoteHardwareModule::runOnce()
if (now - lastWatchMsec >= WATCH_INTERVAL_MSEC) { if (now - lastWatchMsec >= WATCH_INTERVAL_MSEC) {
uint64_t curVal = digitalReads(watchGpios); uint64_t curVal = digitalReads(watchGpios);
lastWatchMsec = now;
if (curVal != previousWatch) { if (curVal != previousWatch) {
previousWatch = curVal; previousWatch = curVal;
@@ -136,5 +139,5 @@ int32_t RemoteHardwareModule::runOnce()
return disable(); return disable();
} }
return 200; // Poll our GPIOs every 200ms (FIXME, make adjustable via protobuf arg) return 2000; // Poll our GPIOs every 2000ms
} }

View File

@@ -10,6 +10,7 @@
#if defined(ARCH_ESP32) #if defined(ARCH_ESP32)
#include "../mesh/generated/meshtastic/paxcount.pb.h" #include "../mesh/generated/meshtastic/paxcount.pb.h"
#endif #endif
#include "mesh/generated/meshtastic/remote_hardware.pb.h"
#include "sleep.h" #include "sleep.h"
#if HAS_WIFI #if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h" #include "mesh/wifi/WiFiAPClient.h"
@@ -747,6 +748,28 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
break; break;
} }
#endif #endif
case meshtastic_PortNum_REMOTE_HARDWARE_APP: {
meshtastic_HardwareMessage scratch;
meshtastic_HardwareMessage *decoded = NULL;
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_HardwareMessage_msg,
&scratch)) {
decoded = &scratch;
if (decoded->type == meshtastic_HardwareMessage_Type_GPIOS_CHANGED) {
msgType = "gpios_changed";
msgPayload["gpio_value"] = new JSONValue((uint)decoded->gpio_value);
jsonObj["payload"] = new JSONValue(msgPayload);
} else if (decoded->type == meshtastic_HardwareMessage_Type_READ_GPIOS_REPLY) {
msgType = "gpios_read_reply";
msgPayload["gpio_value"] = new JSONValue((uint)decoded->gpio_value);
msgPayload["gpio_mask"] = new JSONValue((uint)decoded->gpio_mask);
jsonObj["payload"] = new JSONValue(msgPayload);
}
} else {
LOG_ERROR("Error decoding protobuf for RemoteHardware message!\n");
}
break;
}
// add more packet types here if needed // add more packet types here if needed
default: default:
break; break;

View File

@@ -35,4 +35,9 @@ void rp2040Setup()
Taken from CPU cycle counter and ROSC oscillator, so should be pretty random. Taken from CPU cycle counter and ROSC oscillator, so should be pretty random.
*/ */
randomSeed(rp2040.hwrand32()); randomSeed(rp2040.hwrand32());
}
void enterDfuMode()
{
reset_usb_boot(0, 0);
} }

View File

@@ -0,0 +1,78 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define WIFI_Kit_32 true
#define DISPLAY_HEIGHT 64
#define DISPLAY_WIDTH 128
#define EXTERNAL_NUM_INTERRUPTS 16
#define NUM_DIGITAL_PINS 40
#define NUM_ANALOG_INPUTS 16
#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1)
#define digitalPinToInterrupt(p) (((p) < 40) ? (p) : -1)
#define digitalPinHasPWM(p) (p < 34)
static const uint8_t LED_BUILTIN = 35;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t KEY_BUILTIN = 0;
static const uint8_t TX = 43;
static const uint8_t RX = 44;
static const uint8_t SDA = 41;
static const uint8_t SCL = 42;
static const uint8_t SS = 8;
static const uint8_t MOSI = 10;
static const uint8_t MISO = 11;
static const uint8_t SCK = 9;
static const uint8_t A0 = 1;
static const uint8_t A1 = 2;
static const uint8_t A2 = 3;
static const uint8_t A3 = 4;
static const uint8_t A4 = 5;
static const uint8_t A5 = 6;
static const uint8_t A6 = 7;
static const uint8_t A7 = 8;
static const uint8_t A8 = 9;
static const uint8_t A9 = 10;
static const uint8_t A10 = 11;
static const uint8_t A11 = 12;
static const uint8_t A12 = 13;
static const uint8_t A13 = 14;
static const uint8_t A14 = 15;
static const uint8_t A15 = 16;
static const uint8_t A16 = 17;
static const uint8_t A17 = 18;
static const uint8_t A18 = 19;
static const uint8_t A19 = 20;
static const uint8_t T1 = 1;
static const uint8_t T2 = 2;
static const uint8_t T3 = 3;
static const uint8_t T4 = 4;
static const uint8_t T5 = 5;
static const uint8_t T6 = 6;
static const uint8_t T7 = 7;
static const uint8_t T8 = 8;
static const uint8_t T9 = 9;
static const uint8_t T10 = 10;
static const uint8_t T11 = 11;
static const uint8_t T12 = 12;
static const uint8_t T13 = 13;
static const uint8_t T14 = 14;
static const uint8_t Vext = 45;
static const uint8_t LED = 18;
static const uint8_t RST_LoRa = 12;
static const uint8_t BUSY_LoRa = 13;
static const uint8_t DIO0 = 14;
#endif /* Pins_Arduino_h */

View File

@@ -5,4 +5,7 @@ build_flags =
${esp32s3_base.build_flags} -D HELTEC_WIRELESS_PAPER -I variants/heltec_wireless_paper ${esp32s3_base.build_flags} -D HELTEC_WIRELESS_PAPER -I variants/heltec_wireless_paper
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
zinggjm/GxEPD2@^1.5.2 https://github.com/ixt/GxEPD2#39f325b677713eb04dfcc83b8e402e77523fb8bf
adafruit/Adafruit BusIO@^1.13.2
lewisxhe/PCF8563_Library@^1.0.1
upload_speed = 115200

View File

@@ -15,7 +15,16 @@
#define PIN_EINK_SCLK 3 #define PIN_EINK_SCLK 3
#define PIN_EINK_MOSI 2 #define PIN_EINK_MOSI 2
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost /*
* SPI interfaces
*/
#define SPI_INTERFACES_COUNT 2
#define PIN_SPI_MISO 10 // MISO P0.17
#define PIN_SPI_MOSI 11 // MOSI P0.15
#define PIN_SPI_SCK 9 // SCK P0.13
#define VEXT_ENABLE 45 // active low, powers the oled display and the lora antenna boost
#define BUTTON_PIN 0 #define BUTTON_PIN 0
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage

View File

@@ -16,11 +16,11 @@ build_flags =
-DM5STACK -DM5STACK
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
zinggjm/GxEPD2@^1.4.9 zinggjm/GxEPD2@^1.5.3
lewisxhe/PCF8563_Library@^1.0.1 lewisxhe/PCF8563_Library@^1.0.1
lib_ignore = lib_ignore =
m5stack-coreink m5stack-coreink
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
board_build.f_cpu = 240000000L board_build.f_cpu = 240000000L
upload_protocol = esptool upload_protocol = esptool
;upload_port = /dev/ttyACM0 upload_port = /dev/ttyACM0

View File

@@ -2,16 +2,12 @@
#define I2C_SDA 21 #define I2C_SDA 21
#define I2C_SCL 22 #define I2C_SCL 22
// 7-07-2023 Or enable Secondary I2C Bus
// #define I2C_SDA1 32
// #define I2C_SCL1 33
#define HAS_GPS 1 #define HAS_GPS 1
#undef GPS_RX_PIN #undef GPS_RX_PIN
#undef GPS_TX_PIN #undef GPS_TX_PIN
// Use Secondary I2C Bus as GPS Serial // Use Secondary I2C Bus as GPS Serial
#define GPS_RX_PIN 33 #define GPS_RX_PIN 33
#define GPS_TX_PIN 32 // #define GPS_TX_PIN 32 (now used by SX1262 BUSY as GPS works with just RX)
// Green LED // Green LED
#define LED_INVERTED 0 #define LED_INVERTED 0
@@ -38,7 +34,9 @@
#undef LORA_MISO #undef LORA_MISO
#undef LORA_MOSI #undef LORA_MOSI
#undef LORA_CS #undef LORA_CS
#define USE_RF95 #define USE_RF95
// #define USE_SX1262
// #define USE_SX1280 // #define USE_SX1280
#ifdef USE_RF95 #ifdef USE_RF95
@@ -52,6 +50,23 @@
#define LORA_DIO2 RADIOLIB_NC #define LORA_DIO2 RADIOLIB_NC
#endif #endif
// https://www.waveshare.com/core1262-868m.htm
#ifdef USE_SX1262
#define LORA_SCK 18
#define LORA_MISO 34
#define LORA_MOSI 23
#define LORA_CS 14
#define LORA_RESET 26
#define LORA_DIO1 25
#define LORA_DIO2 32 // 33 // (13 not working) //BUSY pin on SX1262
#define SX126X_CS LORA_CS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif
#ifdef USE_SX1280 #ifdef USE_SX1280
#define LORA_SCK 18 #define LORA_SCK 18
#define LORA_MISO 34 #define LORA_MISO 34
@@ -90,5 +105,5 @@
// | // |
// GND // GND
// https://github.com/m5stack/M5Core-Ink/blob/master/examples/Basics/FactoryTest/FactoryTest.ino#L58 // https://github.com/m5stack/M5Core-Ink/blob/master/examples/Basics/FactoryTest/FactoryTest.ino#L58
#define ADC_MULTIPLIER 5 // Just a guess for now... more detailed getBatVoltage above #define ADC_MULTIPLIER 5
// https://embeddedexplorer.com/esp32-adc-esp-idf-tutorial/ // https://embeddedexplorer.com/esp32-adc-esp-idf-tutorial/

View File

@@ -43,9 +43,9 @@ extern "C" {
#define NUM_ANALOG_OUTPUTS (0) #define NUM_ANALOG_OUTPUTS (0)
// LEDs // LEDs
#define PIN_LED1 (0 + 14) // 13 red (confirmed on 1.0 board) #define PIN_LED1 (0 + 14) // blue (confirmed on boards marked v1.0, date 2021-6-28)
#define PIN_LED2 (0 + 15) // 14 blue #define PIN_LED2 (32 + 1) // green
#define PIN_LED3 (0 + 13) // 15 green #define PIN_LED3 (32 + 3) // red
#define LED_RED PIN_LED3 #define LED_RED PIN_LED3
#define LED_BLUE PIN_LED1 #define LED_BLUE PIN_LED1
@@ -232,4 +232,4 @@ External serial flash WP25R1635FZUIL0
* Arduino objects - C++ only * Arduino objects - C++ only
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#endif #endif

View File

@@ -1,4 +1,4 @@
[VERSION] [VERSION]
major = 2 major = 2
minor = 2 minor = 2
build = 17 build = 18