mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-15 22:37:35 +00:00
Compare commits
269 Commits
v2.5.9.936
...
v2.5.18.89
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89ebafc8b8 | ||
|
|
43d6b31603 | ||
|
|
31a5b9c122 | ||
|
|
ad726ad684 | ||
|
|
b2808063d0 | ||
|
|
2b33be2fea | ||
|
|
5133117936 | ||
|
|
e5accf4e1d | ||
|
|
26a4d6c87a | ||
|
|
ae93f3fa3f | ||
|
|
ed39d14c85 | ||
|
|
8f8e304216 | ||
|
|
cd198fcf3f | ||
|
|
b1d25ac7b7 | ||
|
|
b12ac6d564 | ||
|
|
33d2f78d21 | ||
|
|
b12aa3f360 | ||
|
|
d87b7e49e4 | ||
|
|
cc357df489 | ||
|
|
1281da627e | ||
|
|
835344074c | ||
|
|
13960874ae | ||
|
|
a7d9e8107a | ||
|
|
fbdd6e7223 | ||
|
|
175ff218f1 | ||
|
|
57af51cc18 | ||
|
|
b4b2fd6122 | ||
|
|
143e1d1a0d | ||
|
|
32719f69c9 | ||
|
|
6a2a4ffa2a | ||
|
|
80fc0f2bda | ||
|
|
fa1a1fd869 | ||
|
|
2fd5a4848a | ||
|
|
f4cff33450 | ||
|
|
1c8b165408 | ||
|
|
8e6ef4ea04 | ||
|
|
fb7866fca7 | ||
|
|
d9b287880f | ||
|
|
f39a9c5083 | ||
|
|
398d29064e | ||
|
|
df63423cdc | ||
|
|
9a10907a2d | ||
|
|
5fed679d33 | ||
|
|
58d80b8557 | ||
|
|
960626e498 | ||
|
|
658459aaf3 | ||
|
|
e1de439a7f | ||
|
|
827553f4c7 | ||
|
|
445c641004 | ||
|
|
7075a05bcd | ||
|
|
63091b7838 | ||
|
|
8c6eec52f2 | ||
|
|
68413486e3 | ||
|
|
af79970ad7 | ||
|
|
4edeca5f84 | ||
|
|
b0e3039732 | ||
|
|
92511ab10b | ||
|
|
b0a4087a0c | ||
|
|
1b2fc00b99 | ||
|
|
69d01a8088 | ||
|
|
09c082fd00 | ||
|
|
020e9102a8 | ||
|
|
2d45afafe5 | ||
|
|
56002155c6 | ||
|
|
547a57256d | ||
|
|
ea72abff22 | ||
|
|
4024bfdeeb | ||
|
|
6d8be13266 | ||
|
|
4a1239f811 | ||
|
|
44cf6d388e | ||
|
|
c3f89a6db8 | ||
|
|
332dbaf573 | ||
|
|
92225eb6c3 | ||
|
|
03770b799f | ||
|
|
1790407078 | ||
|
|
7dd3629501 | ||
|
|
cabeb40c30 | ||
|
|
761a99d241 | ||
|
|
cf46e675ca | ||
|
|
438f627e9b | ||
|
|
0e3dae4fec | ||
|
|
d0e3427ec7 | ||
|
|
f3850ee73b | ||
|
|
3ae85e2c82 | ||
|
|
f81d3b045d | ||
|
|
59ed5c9049 | ||
|
|
4a34bf648f | ||
|
|
b99e57a6fa | ||
|
|
46eab20a90 | ||
|
|
39b5fb041e | ||
|
|
fc16d93421 | ||
|
|
bac9fec17f | ||
|
|
de774188c9 | ||
|
|
c3d60342f4 | ||
|
|
d3e3985e39 | ||
|
|
8eca6a2df8 | ||
|
|
e4f53677fc | ||
|
|
10e10450cf | ||
|
|
f846503cbf | ||
|
|
85b2bad275 | ||
|
|
7ad137b56a | ||
|
|
57ea6a265e | ||
|
|
d00e0f6911 | ||
|
|
594af0cacd | ||
|
|
9f4c8a2804 | ||
|
|
43b8972171 | ||
|
|
fe8e0713cc | ||
|
|
ac6b6c8d83 | ||
|
|
79da2365f0 | ||
|
|
b5777beb7d | ||
|
|
5ad30a55ea | ||
|
|
060a3bde4d | ||
|
|
8df7a035e2 | ||
|
|
b00c05012d | ||
|
|
0832388482 | ||
|
|
601d912c6f | ||
|
|
502a83bb8a | ||
|
|
474f9b5bfb | ||
|
|
fe86c40145 | ||
|
|
09286a3beb | ||
|
|
ae4f54224e | ||
|
|
d5af8f0a97 | ||
|
|
58c957f2c7 | ||
|
|
7c2b6778cb | ||
|
|
0048e3cdcb | ||
|
|
6018c0a830 | ||
|
|
37da78919a | ||
|
|
ad9d7a4972 | ||
|
|
932966b896 | ||
|
|
4d69159e75 | ||
|
|
f2ee0df015 | ||
|
|
fcfb197571 | ||
|
|
dd7140b7a1 | ||
|
|
fadcbd597f | ||
|
|
14b9a1a929 | ||
|
|
c51a7b98bd | ||
|
|
fdec95f9c1 | ||
|
|
e6fb6b115a | ||
|
|
d5bb32ff93 | ||
|
|
f5058a9cbb | ||
|
|
dbc5ec27f7 | ||
|
|
1089469f82 | ||
|
|
fd98e9f553 | ||
|
|
ccfc9e5dd9 | ||
|
|
1752caaf19 | ||
|
|
364dead3aa | ||
|
|
154864dfbf | ||
|
|
2ca3cdf837 | ||
|
|
485c371de4 | ||
|
|
a255da3cf5 | ||
|
|
d65dc497f2 | ||
|
|
c641bfd53c | ||
|
|
b947b123fc | ||
|
|
df1f66a6b9 | ||
|
|
70336f7f4f | ||
|
|
de76caca32 | ||
|
|
89469fcb88 | ||
|
|
a8357ebd52 | ||
|
|
0d1f9e915f | ||
|
|
1a06f88dfb | ||
|
|
a174ec7cf9 | ||
|
|
37b29f6899 | ||
|
|
74d0c58576 | ||
|
|
ca3d8da128 | ||
|
|
be6348388e | ||
|
|
fdc473e5fa | ||
|
|
add70b5229 | ||
|
|
1b99543a15 | ||
|
|
90a3050c1f | ||
|
|
9545a10361 | ||
|
|
d4d89447bd | ||
|
|
81172574a4 | ||
|
|
295278bb12 | ||
|
|
ec6949fdc0 | ||
|
|
f4908fadd6 | ||
|
|
528e177c62 | ||
|
|
73430cb582 | ||
|
|
3a66c738bd | ||
|
|
ea150c32f3 | ||
|
|
ac804818de | ||
|
|
8fcfe7f28b | ||
|
|
e866734a25 | ||
|
|
2ec3958cd8 | ||
|
|
f4b0e19a65 | ||
|
|
a49f080bd2 | ||
|
|
e65a754430 | ||
|
|
a84324c4fa | ||
|
|
ff33a27789 | ||
|
|
51ea7ac627 | ||
|
|
606c2e8eb0 | ||
|
|
762ccdc1b9 | ||
|
|
0acccdfe2d | ||
|
|
0e4f7003c7 | ||
|
|
40bc04b521 | ||
|
|
eb8d38a7e9 | ||
|
|
3d5eb34c5c | ||
|
|
3a9a4bbb92 | ||
|
|
6eba2789d0 | ||
|
|
9b4c260a92 | ||
|
|
667b4ef0f2 | ||
|
|
db76561930 | ||
|
|
7bad070891 | ||
|
|
6365fcfdc6 | ||
|
|
ab2cbada75 | ||
|
|
875b8641d3 | ||
|
|
67c2c516a0 | ||
|
|
623203ca3b | ||
|
|
f28f0a9d90 | ||
|
|
893efe4f11 | ||
|
|
2c2213ef9b | ||
|
|
439c1dec08 | ||
|
|
aa184e6d8b | ||
|
|
2eea412f1c | ||
|
|
b0a5a26f58 | ||
|
|
a815a770b4 | ||
|
|
286f3c6458 | ||
|
|
b506f6dcb0 | ||
|
|
bd3755bb33 | ||
|
|
73e2e25eb1 | ||
|
|
3bd3911913 | ||
|
|
982190936d | ||
|
|
8498b175e7 | ||
|
|
255713d23d | ||
|
|
8e2a3e5728 | ||
|
|
f769c50fa5 | ||
|
|
7ba6d97e99 | ||
|
|
f3b698905d | ||
|
|
50dac38a1b | ||
|
|
bf944e78d8 | ||
|
|
e71be778dd | ||
|
|
276067065e | ||
|
|
a628c93125 | ||
|
|
03aaaafa13 | ||
|
|
0a82fd28b3 | ||
|
|
89c186e662 | ||
|
|
8c99f913c1 | ||
|
|
d00acc5d7b | ||
|
|
9415254dda | ||
|
|
448c754882 | ||
|
|
da7424a604 | ||
|
|
1bec23b6bb | ||
|
|
bee474ee54 | ||
|
|
93bc61c855 | ||
|
|
0fc5c9b0d7 | ||
|
|
b0c924f185 | ||
|
|
8801bc5ce9 | ||
|
|
cf476eb87c | ||
|
|
ba2f25293b | ||
|
|
2d4d36c605 | ||
|
|
cbe74009a9 | ||
|
|
701421b50a | ||
|
|
336cdc0efe | ||
|
|
a1ac358b0a | ||
|
|
8462d65f76 | ||
|
|
10dd8af614 | ||
|
|
9c06c492d9 | ||
|
|
7e3c369e87 | ||
|
|
732cf4832a | ||
|
|
545ebf9b17 | ||
|
|
7912c214c7 | ||
|
|
600208ab0b | ||
|
|
462a0718cf | ||
|
|
aae346aef7 | ||
|
|
28b469dbf0 | ||
|
|
5f6e19d971 | ||
|
|
0726eaa678 | ||
|
|
50fb575caa | ||
|
|
cc59a50cba | ||
|
|
b3ba23b4e8 |
183
.devcontainer/99-platformio-udev.rules
Normal file
183
.devcontainer/99-platformio-udev.rules
Normal file
@@ -0,0 +1,183 @@
|
||||
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#####################################################################################
|
||||
#
|
||||
# INSTALLATION
|
||||
#
|
||||
# Please visit > https://docs.platformio.org/en/latest/core/installation/udev-rules.html
|
||||
#
|
||||
#####################################################################################
|
||||
|
||||
#
|
||||
# Boards
|
||||
#
|
||||
|
||||
# CP210X USB UART
|
||||
ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea[67][013]", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="80a9", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# FT231XS USB UART
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Prolific Technology, Inc. PL2303 Serial Port
|
||||
ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# QinHeng Electronics HL-340 USB-Serial adapter
|
||||
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
# QinHeng Electronics CH343 USB-Serial adapter
|
||||
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d3", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
# QinHeng Electronics CH9102 USB-Serial adapter
|
||||
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Arduino boards
|
||||
ATTRS{idVendor}=="2341", ATTRS{idProduct}=="[08][023]*", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="[08][02]*", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Arduino SAM-BA
|
||||
ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="6124", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{MTP_NO_PROBE}="1"
|
||||
|
||||
# Digistump boards
|
||||
ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0753", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Maple with DFU
|
||||
ATTRS{idVendor}=="1eaf", ATTRS{idProduct}=="000[34]", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# USBtiny
|
||||
ATTRS{idProduct}=="0c9f", ATTRS{idVendor}=="1781", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# USBasp V2.0
|
||||
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05dc", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Teensy boards
|
||||
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789A]?", ENV{MTP_NO_PROBE}="1"
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789ABCD]?", MODE:="0666"
|
||||
KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", MODE:="0666"
|
||||
|
||||
# TI Stellaris Launchpad
|
||||
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# TI MSP430 Launchpad
|
||||
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="f432", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# GD32V DFU Bootloader
|
||||
ATTRS{idVendor}=="28e9", ATTRS{idProduct}=="0189", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# FireBeetle-ESP32
|
||||
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7522", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Wio Terminal
|
||||
ATTRS{idVendor}=="2886", ATTRS{idProduct}=="[08]02d", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Raspberry Pi Pico
|
||||
ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="[01]*", MODE:="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# AIR32F103
|
||||
ATTRS{idVendor}=="0d28", ATTRS{idProduct}=="0204", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# STM32 virtual COM port
|
||||
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
#
|
||||
# Debuggers
|
||||
#
|
||||
|
||||
# Black Magic Probe
|
||||
SUBSYSTEM=="tty", ATTRS{interface}=="Black Magic GDB Server", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
SUBSYSTEM=="tty", ATTRS{interface}=="Black Magic UART Port", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# opendous and estick
|
||||
ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Original FT232/FT245/FT2232/FT232H/FT4232
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="60[01][104]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# DISTORTEC JTAG-lock-pick Tiny 2
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# TUMPA, TUMPA Lite
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a9[89]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# XDS100v2
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE)
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca[01]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# TI/Luminary Stellaris Evaluation Board FTDI (several)
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd[9a]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# egnite Turtelizer 2
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Section5 ICEbear
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c14[01]", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Amontec JTAGkey and JTAGkey-tiny
|
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# TI ICDI
|
||||
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# STLink probes
|
||||
ATTRS{idVendor}=="0483", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Hilscher NXHX Boards
|
||||
ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Hitex probes
|
||||
ATTRS{idVendor}=="0640", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Altera USB Blaster
|
||||
ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Amontec JTAGkey-HiSpeed
|
||||
ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# SEGGER J-Link
|
||||
ATTRS{idVendor}=="1366", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Raisonance RLink
|
||||
ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Debug Board for Neo1973
|
||||
ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Olimex probes
|
||||
ATTRS{idVendor}=="15ba", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# USBprog with OpenOCD firmware
|
||||
ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
|
||||
ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Marvell Sheevaplug
|
||||
ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Keil Software, Inc. ULink
|
||||
ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2710", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# CMSIS-DAP compatible adapters
|
||||
ATTRS{product}=="*CMSIS-DAP*", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Atmel AVR Dragon
|
||||
ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2107", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Espressif USB JTAG/serial debug unit
|
||||
ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# Zephyr framework USB CDC-ACM
|
||||
ATTRS{idVendor}=="2fe3", ATTRS{idProduct}=="0100", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
@@ -1,6 +1,9 @@
|
||||
FROM mcr.microsoft.com/devcontainers/cpp:1-debian-12
|
||||
|
||||
# [Optional] Uncomment this section to install additional packages.
|
||||
USER root
|
||||
|
||||
# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore(hadolint/DL3008): Use latest version of packages
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-get -y install --no-install-recommends \
|
||||
ca-certificates \
|
||||
@@ -20,6 +23,16 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
python3-wheel \
|
||||
wget \
|
||||
zip \
|
||||
usbutils \
|
||||
hwdata \
|
||||
gpg \
|
||||
gnupg2 \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pipx install platformio==6.1.15
|
||||
RUN pipx install platformio==6.1.15
|
||||
|
||||
COPY 99-platformio-udev.rules /etc/udev/rules.d/99-platformio-udev.rules
|
||||
|
||||
USER vscode
|
||||
|
||||
HEALTHCHECK NONE
|
||||
@@ -13,13 +13,24 @@
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": ["ms-vscode.cpptools", "platformio.platformio-ide"]
|
||||
"extensions": [
|
||||
"ms-vscode.cpptools",
|
||||
"platformio.platformio-ide",
|
||||
"Trunk.io"
|
||||
],
|
||||
"unwantedRecommendations": ["ms-azuretools.vscode-docker"],
|
||||
"settings": {
|
||||
"extensions.ignoreRecommendations": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [4403],
|
||||
|
||||
// Use "--device=" to make a local device available inside the container.
|
||||
// "runArgs": ["--device=/dev/ttyACM0"],
|
||||
|
||||
// Run commands to prepare the container for use
|
||||
"postCreateCommand": ".devcontainer/setup.sh"
|
||||
}
|
||||
|
||||
4
.env.example
Normal file
4
.env.example
Normal file
@@ -0,0 +1,4 @@
|
||||
# Absolute path to the local meshtastic config.yaml file
|
||||
CONFIG_PATH=/path/to/meshtastic/config.yaml
|
||||
# USB device to passthrough (`lsusb -t`: look for `ch341`)
|
||||
USB_DEVICE=/dev/bus/usb/001/037
|
||||
1
.github/actions/build-variant/action.yml
vendored
1
.github/actions/build-variant/action.yml
vendored
@@ -51,6 +51,7 @@ runs:
|
||||
file: build.tar
|
||||
target: build.tar
|
||||
token: ${{ inputs.github_token }}
|
||||
version: tags/v2.5.3
|
||||
|
||||
- name: Unpack web ui
|
||||
if: inputs.include-web-ui == 'true'
|
||||
|
||||
51
.github/workflows/build_docker.yml
vendored
Normal file
51
.github/workflows/build_docker.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Build Docker
|
||||
|
||||
on: workflow_call
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-native:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Docker login
|
||||
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: meshtastic
|
||||
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
|
||||
|
||||
- name: Docker setup
|
||||
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Docker build and push tagged versions
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: meshtastic/meshtasticd:${{ steps.version.outputs.version }}
|
||||
|
||||
- name: Docker build and push
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: meshtastic/meshtasticd:latest
|
||||
3
.github/workflows/build_esp32.yml
vendored
3
.github/workflows/build_esp32.yml
vendored
@@ -7,6 +7,8 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-esp32:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -24,6 +26,7 @@ jobs:
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
./arch/esp32/esp32c6.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware.bin
|
||||
ota-firmware-target: release/bleota.bin
|
||||
|
||||
2
.github/workflows/build_esp32_c3.yml
vendored
2
.github/workflows/build_esp32_c3.yml
vendored
@@ -26,10 +26,12 @@ jobs:
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
./arch/esp32/esp32c6.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware-c3.bin
|
||||
ota-firmware-target: release/bleota-c3.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
include-web-ui: true
|
||||
arch: esp32c3
|
||||
|
||||
1
.github/workflows/build_esp32_c6.yml
vendored
1
.github/workflows/build_esp32_c6.yml
vendored
@@ -33,4 +33,5 @@ jobs:
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
include-web-ui: true
|
||||
arch: esp32c6
|
||||
|
||||
3
.github/workflows/build_esp32_s3.yml
vendored
3
.github/workflows/build_esp32_s3.yml
vendored
@@ -7,6 +7,8 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-esp32-s3:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -24,6 +26,7 @@ jobs:
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
./arch/esp32/esp32c6.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware-s3.bin
|
||||
ota-firmware-target: release/bleota-s3.bin
|
||||
|
||||
35
.github/workflows/build_native.yml
vendored
35
.github/workflows/build_native.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -50,36 +50,3 @@ jobs:
|
||||
path: |
|
||||
release/meshtasticd_linux_x86_64
|
||||
bin/config-dist.yaml
|
||||
|
||||
- name: Docker login
|
||||
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
uses: docker/login-action@v3
|
||||
continue-on-error: true # FIXME: Failing docker login auth
|
||||
with:
|
||||
username: meshtastic
|
||||
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
|
||||
|
||||
- name: Docker setup
|
||||
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
continue-on-error: true # FIXME: Failing docker login auth
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Docker build and push tagged versions
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
continue-on-error: true # FIXME: Failing docker login auth
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: meshtastic/device-simulator:${{ steps.version.outputs.version }}
|
||||
|
||||
- name: Docker build and push
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
continue-on-error: true # FIXME: Failing docker login auth
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: meshtastic/device-simulator:latest
|
||||
|
||||
4
.github/workflows/build_raspbian.yml
vendored
4
.github/workflows/build_raspbian.yml
vendored
@@ -13,8 +13,8 @@ jobs:
|
||||
- name: Install libbluetooth
|
||||
shell: bash
|
||||
run: |
|
||||
apt-get update -y --fix-missing
|
||||
apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
4
.github/workflows/build_raspbian_armv7l.yml
vendored
4
.github/workflows/build_raspbian_armv7l.yml
vendored
@@ -13,8 +13,8 @@ jobs:
|
||||
- name: Install libbluetooth
|
||||
shell: bash
|
||||
run: |
|
||||
apt-get update -y --fix-missing
|
||||
apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||
sudo apt-get update -y --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
11
.github/workflows/main_matrix.yml
vendored
11
.github/workflows/main_matrix.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
else
|
||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
|
||||
fi
|
||||
echo "Name: ${{ github.ref_name }} Base: ${{ github.base_ref }} Head: ${{ github.head_ref }} Ref: ${{ github.ref }} Targets: $TARGETS"
|
||||
echo "Name: ${{ github.ref_name }} Base: ${{ github.base_ref }} } Ref: ${{ github.ref }} Targets: $TARGETS"
|
||||
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
|
||||
outputs:
|
||||
esp32: ${{ steps.jsonStep.outputs.esp32 }}
|
||||
@@ -137,6 +137,11 @@ jobs:
|
||||
package-native:
|
||||
uses: ./.github/workflows/package_amd64.yml
|
||||
|
||||
build-docker:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/workflows/build_docker.yml
|
||||
secrets: inherit
|
||||
|
||||
after-checks:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
@@ -203,6 +208,7 @@ jobs:
|
||||
./device-*.sh
|
||||
./device-*.bat
|
||||
./littlefs-*.bin
|
||||
./littlefswebui-*.bin
|
||||
./bleota*bin
|
||||
./Meshtastic_nRF52_factory_erase*.uf2
|
||||
retention-days: 30
|
||||
@@ -245,7 +251,8 @@ jobs:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
outputs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
needs: [
|
||||
needs:
|
||||
[
|
||||
gather-artifacts,
|
||||
package-raspbian,
|
||||
package-raspbian-armv7l,
|
||||
|
||||
19
.github/workflows/package_amd64.yml
vendored
19
.github/workflows/package_amd64.yml
vendored
@@ -47,21 +47,30 @@ jobs:
|
||||
- name: build .debpkg
|
||||
run: |
|
||||
mkdir -p .debpkg/DEBIAN
|
||||
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
|
||||
mkdir -p .debpkg/usr/share/meshtasticd/web
|
||||
mkdir -p .debpkg/usr/sbin
|
||||
mkdir -p .debpkg/etc/meshtasticd
|
||||
mkdir -p .debpkg/etc/meshtasticd/config.d
|
||||
mkdir -p .debpkg/etc/meshtasticd/available.d
|
||||
mkdir -p .debpkg/usr/lib/systemd/system/
|
||||
tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
|
||||
tar -xf build.tar -C .debpkg/usr/share/meshtasticd/web
|
||||
shopt -s dotglob nullglob
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then mv .debpkg/usr/share/meshtasticd/web/build/* .debpkg/usr/share/meshtasticd/web/; fi
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/meshtasticd/web/build; fi
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/meshtasticd/web/ -r
|
||||
cp release/meshtasticd_linux_x86_64 .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
|
||||
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||
chmod +x .debpkg/DEBIAN/conffiles
|
||||
# Transition /usr/share/doc/meshtasticd to /usr/share/meshtasticd
|
||||
echo "rm -rf /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/preinst
|
||||
chmod +x .debpkg/DEBIAN/preinst
|
||||
echo "ln -sf /usr/share/meshtasticd /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/postinst
|
||||
chmod +x .debpkg/DEBIAN/postinst
|
||||
|
||||
- uses: jiro4989/build-deb-action@v3
|
||||
with:
|
||||
@@ -70,7 +79,7 @@ jobs:
|
||||
maintainer: Jonathan Bennett
|
||||
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||
arch: amd64
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
|
||||
desc: Native Linux Meshtastic binary.
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
|
||||
19
.github/workflows/package_raspbian.yml
vendored
19
.github/workflows/package_raspbian.yml
vendored
@@ -47,21 +47,30 @@ jobs:
|
||||
- name: build .debpkg
|
||||
run: |
|
||||
mkdir -p .debpkg/DEBIAN
|
||||
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
|
||||
mkdir -p .debpkg/usr/share/meshtasticd/web
|
||||
mkdir -p .debpkg/usr/sbin
|
||||
mkdir -p .debpkg/etc/meshtasticd
|
||||
mkdir -p .debpkg/etc/meshtasticd/config.d
|
||||
mkdir -p .debpkg/etc/meshtasticd/available.d
|
||||
mkdir -p .debpkg/usr/lib/systemd/system/
|
||||
tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
|
||||
tar -xf build.tar -C .debpkg/usr/share/meshtasticd/web
|
||||
shopt -s dotglob nullglob
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then mv .debpkg/usr/share/meshtasticd/web/build/* .debpkg/usr/share/meshtasticd/web/; fi
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/meshtasticd/web/build; fi
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/meshtasticd/web/ -r
|
||||
cp release/meshtasticd_linux_aarch64 .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
|
||||
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||
chmod +x .debpkg/DEBIAN/conffiles
|
||||
# Transition /usr/share/doc/meshtasticd to /usr/share/meshtasticd
|
||||
echo "rm -rf /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/preinst
|
||||
chmod +x .debpkg/DEBIAN/preinst
|
||||
echo "ln -sf /usr/share/meshtasticd /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/postinst
|
||||
chmod +x .debpkg/DEBIAN/postinst
|
||||
|
||||
- uses: jiro4989/build-deb-action@v3
|
||||
with:
|
||||
@@ -70,7 +79,7 @@ jobs:
|
||||
maintainer: Jonathan Bennett
|
||||
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||
arch: arm64
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
|
||||
desc: Native Linux Meshtastic binary.
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
|
||||
19
.github/workflows/package_raspbian_armv7l.yml
vendored
19
.github/workflows/package_raspbian_armv7l.yml
vendored
@@ -47,21 +47,30 @@ jobs:
|
||||
- name: build .debpkg
|
||||
run: |
|
||||
mkdir -p .debpkg/DEBIAN
|
||||
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
|
||||
mkdir -p .debpkg/usr/share/meshtasticd/web
|
||||
mkdir -p .debpkg/usr/sbin
|
||||
mkdir -p .debpkg/etc/meshtasticd
|
||||
mkdir -p .debpkg/etc/meshtasticd/config.d
|
||||
mkdir -p .debpkg/etc/meshtasticd/available.d
|
||||
mkdir -p .debpkg/usr/lib/systemd/system/
|
||||
tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web
|
||||
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
|
||||
tar -xf build.tar -C .debpkg/usr/share/meshtasticd/web
|
||||
shopt -s dotglob nullglob
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then mv .debpkg/usr/share/meshtasticd/web/build/* .debpkg/usr/share/meshtasticd/web/; fi
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/meshtasticd/web/build; fi
|
||||
if [ -d .debpkg/usr/share/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/meshtasticd/web/.DS_Store; fi
|
||||
gunzip .debpkg/usr/share/meshtasticd/web/ -r
|
||||
cp release/meshtasticd_linux_armv7l .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/
|
||||
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
|
||||
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||
chmod +x .debpkg/DEBIAN/conffiles
|
||||
# Transition /usr/share/doc/meshtasticd to /usr/share/meshtasticd
|
||||
echo "rm -rf /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/preinst
|
||||
chmod +x .debpkg/DEBIAN/preinst
|
||||
echo "ln -sf /usr/share/meshtasticd /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/postinst
|
||||
chmod +x .debpkg/DEBIAN/postinst
|
||||
|
||||
- uses: jiro4989/build-deb-action@v3
|
||||
with:
|
||||
@@ -70,7 +79,7 @@ jobs:
|
||||
maintainer: Jonathan Bennett
|
||||
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||
arch: armhf
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
||||
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
|
||||
desc: Native Linux Meshtastic binary.
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
|
||||
22
.github/workflows/stale_bot.yml
vendored
Normal file
22
.github/workflows/stale_bot.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: process stale Issues and PR's
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0 6 * * *
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
stale_issues:
|
||||
name: Close Stale Issues
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Stale PR+Issues
|
||||
uses: actions/stale@v9.0.0
|
||||
with:
|
||||
exempt-issue-labels: pinned,3.0
|
||||
exempt-pr-labels: pinned,3.0
|
||||
38
.github/workflows/tests.yml
vendored
38
.github/workflows/tests.yml
vendored
@@ -8,12 +8,15 @@ on:
|
||||
jobs:
|
||||
test-simulator:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
LCOV_CAPTURE_FLAGS: --quiet --capture --include "${PWD}/src/*" --exclude '*/src/mesh/generated/*' --directory .pio/build/coverage/src --base-directory "${PWD}"
|
||||
steps:
|
||||
- name: Install libbluetooth
|
||||
- name: Install libs needed for native build
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
|
||||
sudo apt-get install -y lcov
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -24,7 +27,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
pip install -U platformio adafruit-nrfutil dotmap
|
||||
pip install -U meshtastic --pre
|
||||
|
||||
- name: Upgrade platformio
|
||||
@@ -36,17 +39,25 @@ jobs:
|
||||
run: bin/build-native.sh
|
||||
|
||||
# We now run integration test before other build steps (to quickly see runtime failures)
|
||||
- name: Build for native
|
||||
run: platformio run -e native
|
||||
- name: Build for native/coverage
|
||||
run: |
|
||||
platformio run -e coverage
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --initial --output-file coverage_base.info
|
||||
|
||||
- name: Integration test
|
||||
run: |
|
||||
.pio/build/native/program & sleep 10 # 5 seconds was not enough
|
||||
.pio/build/coverage/program &
|
||||
PID=$!
|
||||
timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done"
|
||||
echo "Simulator started, launching python test..."
|
||||
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
|
||||
wait
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info
|
||||
|
||||
- name: PlatformIO Tests
|
||||
run: platformio test -e native --junit-output-path testreport.xml
|
||||
run: |
|
||||
platformio test -e coverage --junit-output-path testreport.xml
|
||||
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name tests --output-file coverage_tests.info
|
||||
|
||||
- name: Test Report
|
||||
uses: dorny/test-reporter@v1.9.1
|
||||
@@ -56,6 +67,19 @@ jobs:
|
||||
path: testreport.xml
|
||||
reporter: java-junit
|
||||
|
||||
- name: Generate Code Coverage Report
|
||||
run: |
|
||||
lcov --quiet --add-tracefile coverage_base.info --add-tracefile coverage_integration.info --add-tracefile coverage_tests.info --output-file coverage_src.info
|
||||
mkdir code-coverage-report
|
||||
genhtml --quiet --legend --prefix "${PWD}" coverage_src.info --output-directory code-coverage-report
|
||||
mv coverage_*.info code-coverage-report
|
||||
|
||||
- name: Save Code Coverage Report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: code-coverage-report
|
||||
path: code-coverage-report
|
||||
|
||||
hardware-tests:
|
||||
runs-on: test-runner
|
||||
steps:
|
||||
|
||||
43
.github/workflows/trunk_format_pr.yml
vendored
Normal file
43
.github/workflows/trunk_format_pr.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
name: Run Trunk Fmt on PR Comment
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
trunk-fmt:
|
||||
if: github.event.issue.pull_request != null && contains(github.event.comment.body, 'trunk fmt')
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Install trunk
|
||||
run: curl https://get.trunk.io -fsSL | bash
|
||||
|
||||
- name: Run Trunk Fmt
|
||||
run: trunk fmt
|
||||
|
||||
- name: Commit and push changes
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add .
|
||||
git commit -m "Add firmware version ${{ steps.version.outputs.version }}"
|
||||
git push
|
||||
|
||||
- name: Comment on PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
github.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '`trunk fmt` has been run on this PR.'
|
||||
})
|
||||
6
.github/workflows/update_protobufs.yml
vendored
6
.github/workflows/update_protobufs.yml
vendored
@@ -17,9 +17,9 @@ jobs:
|
||||
|
||||
- name: Download nanopb
|
||||
run: |
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.9-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.9-linux-x86.tar.gz
|
||||
mv nanopb-0.4.9-linux-x86 nanopb-0.4.9
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.9.1-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.9.1-linux-x86.tar.gz
|
||||
mv nanopb-0.4.9.1-linux-x86 nanopb-0.4.9
|
||||
|
||||
- name: Re-generate protocol buffers
|
||||
run: |
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
version: 0.1
|
||||
cli:
|
||||
version: 1.22.7
|
||||
version: 1.22.8
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.6.4
|
||||
ref: v1.6.6
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- trufflehog@3.82.12
|
||||
- prettier@3.4.2
|
||||
- trufflehog@3.86.1
|
||||
- yamllint@1.35.1
|
||||
- bandit@1.7.10
|
||||
- checkov@3.2.256
|
||||
- bandit@1.8.0
|
||||
- checkov@3.2.334
|
||||
- terrascan@1.19.9
|
||||
- trivy@0.55.2
|
||||
- trivy@0.58.0
|
||||
#- trufflehog@3.63.2-rc0
|
||||
- taplo@0.9.3
|
||||
- ruff@0.7.0
|
||||
- ruff@0.8.3
|
||||
- isort@5.13.2
|
||||
- markdownlint@0.42.0
|
||||
- oxipng@9.1.2
|
||||
- markdownlint@0.43.0
|
||||
- oxipng@9.1.3
|
||||
- svgo@3.3.2
|
||||
- actionlint@1.7.3
|
||||
- actionlint@1.7.4
|
||||
- flake8@7.1.1
|
||||
- hadolint@2.12.0
|
||||
- hadolint@2.12.1-beta
|
||||
- shfmt@3.6.0
|
||||
- shellcheck@0.10.0
|
||||
- black@24.10.0
|
||||
- git-diff-check
|
||||
- gitleaks@8.21.1
|
||||
- gitleaks@8.21.2
|
||||
- clang-format@16.0.3
|
||||
- prettier@3.3.3
|
||||
#- prettier@3.3.3
|
||||
ignore:
|
||||
- linters: [ALL]
|
||||
paths:
|
||||
@@ -39,7 +40,7 @@ runtimes:
|
||||
enabled:
|
||||
- python@3.10.8
|
||||
- go@1.21.0
|
||||
- node@18.12.1
|
||||
- node@18.20.5
|
||||
actions:
|
||||
disabled:
|
||||
- trunk-announce
|
||||
|
||||
4
CODE_OF_CONDUCT.md
Normal file
4
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
The Meshtastic Firmware project is subject to the code of conduct for the parent project, which can be found here:
|
||||
https://meshtastic.org/docs/legal/conduct/
|
||||
72
Dockerfile
72
Dockerfile
@@ -1,32 +1,29 @@
|
||||
FROM debian:bookworm-slim AS builder
|
||||
# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore-all(hadolint/DL3008): Use latest version of apt packages for buildchain
|
||||
# trunk-ignore-all(trivy/DS002): We must run as root for this container
|
||||
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
|
||||
|
||||
FROM python:3.12-bookworm AS builder
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Etc/UTC
|
||||
|
||||
# http://bugs.python.org/issue19846
|
||||
# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.
|
||||
ENV LANG C.UTF-8
|
||||
|
||||
# Install build deps
|
||||
USER root
|
||||
|
||||
# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y wget python3 python3-pip python3-wheel python3-venv g++ zip git \
|
||||
ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev \
|
||||
libulfius-dev liborcania-dev libssl-dev pkg-config && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/* && mkdir /tmp/firmware
|
||||
|
||||
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh && chown mesh:mesh /tmp/firmware
|
||||
USER mesh
|
||||
# Install Dependencies
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y wget g++ zip git ca-certificates \
|
||||
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev \
|
||||
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/* && \
|
||||
pip install --no-cache-dir -U platformio==6.1.16 && \
|
||||
mkdir /tmp/firmware
|
||||
|
||||
# Copy source code
|
||||
WORKDIR /tmp/firmware
|
||||
RUN python3 -m venv /tmp/firmware
|
||||
RUN bash -o pipefail -c "source bin/activate; pip3 install --no-cache-dir -U platformio==6.1.15"
|
||||
# trunk-ignore(terrascan/AC_DOCKER_00024): We would actually like these files to be owned by mesh tyvm
|
||||
COPY --chown=mesh:mesh . /tmp/firmware
|
||||
RUN bash -o pipefail -c "source ./bin/activate && bash ./bin/build-native.sh"
|
||||
RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||
COPY . /tmp/firmware
|
||||
|
||||
# Build
|
||||
RUN bash ./bin/build-native.sh && \
|
||||
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||
|
||||
|
||||
##### PRODUCTION BUILD #############
|
||||
@@ -35,20 +32,25 @@ FROM debian:bookworm-slim
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Etc/UTC
|
||||
|
||||
# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||
# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain
|
||||
RUN apt-get update && apt-get --no-install-recommends -y install libc-bin libc6 libgpiod2 libyaml-cpp0.7 libulfius2.7 liborcania2.3 libssl3 && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
# nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root
|
||||
USER root
|
||||
|
||||
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
||||
USER mesh
|
||||
RUN apt-get update && apt-get --no-install-recommends -y install libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libulfius2.7 libusb-1.0-0-dev liborcania2.3 libssl3 && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/* \
|
||||
&& mkdir -p /var/lib/meshtasticd \
|
||||
&& mkdir -p /etc/meshtasticd/config.d
|
||||
|
||||
WORKDIR /home/mesh
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /home/mesh/
|
||||
# Fetch compiled binary from the builder
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
|
||||
# Copy config templates
|
||||
COPY ./bin/config.d /etc/meshtasticd/available.d
|
||||
|
||||
RUN mkdir data
|
||||
VOLUME /home/mesh/data
|
||||
WORKDIR /var/lib/meshtasticd
|
||||
VOLUME /var/lib/meshtasticd
|
||||
|
||||
CMD [ "sh", "-cx", "./meshtasticd -d /home/mesh/data --hwid=${HWID:-$RANDOM}" ]
|
||||
# Expose Meshtastic TCP API port from the host
|
||||
EXPOSE 4403
|
||||
|
||||
HEALTHCHECK NONE
|
||||
CMD [ "sh", "-cx", "meshtasticd -d /var/lib/meshtasticd" ]
|
||||
|
||||
HEALTHCHECK NONE
|
||||
42
alpine.Dockerfile
Normal file
42
alpine.Dockerfile
Normal file
@@ -0,0 +1,42 @@
|
||||
# trunk-ignore-all(trivy/DS002): We must run as root for this container
|
||||
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
|
||||
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
|
||||
|
||||
FROM python:3.12-alpine3.21 AS builder
|
||||
|
||||
ENV PIP_ROOT_USER_ACTION=ignore
|
||||
RUN apk add bash g++ libstdc++-dev linux-headers zip git ca-certificates libgpiod-dev yaml-cpp-dev bluez-dev \
|
||||
libusb-dev i2c-tools-dev openssl-dev pkgconf argp-standalone && \
|
||||
pip install --no-cache-dir -U platformio==6.1.16 && \
|
||||
mkdir /tmp/firmware
|
||||
|
||||
WORKDIR /tmp/firmware
|
||||
COPY . /tmp/firmware
|
||||
|
||||
# Create small package (no debugging symbols)
|
||||
# Add `argp` for musl
|
||||
ENV PLATFORMIO_BUILD_FLAGS="-Os -ffunction-sections -fdata-sections -Wl,--gc-sections -largp"
|
||||
|
||||
RUN bash ./bin/build-native.sh && \
|
||||
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||
|
||||
# ##### PRODUCTION BUILD #############
|
||||
|
||||
FROM alpine:3.21
|
||||
|
||||
# nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root
|
||||
USER root
|
||||
|
||||
RUN apk add libstdc++ libgpiod yaml-cpp libusb i2c-tools \
|
||||
&& mkdir -p /var/lib/meshtasticd \
|
||||
&& mkdir -p /etc/meshtasticd/config.d
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
|
||||
|
||||
WORKDIR /var/lib/meshtasticd
|
||||
VOLUME /var/lib/meshtasticd
|
||||
|
||||
EXPOSE 4403
|
||||
|
||||
CMD [ "sh", "-cx", "meshtasticd --fsdir=/var/lib/meshtasticd" ]
|
||||
|
||||
HEALTHCHECK NONE
|
||||
@@ -31,7 +31,7 @@ build_flags =
|
||||
-DCONFIG_BT_NIMBLE_ENABLED
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120
|
||||
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DSERIAL_BUFFER_SIZE=4096
|
||||
-DLIBPAX_ARDUINO
|
||||
@@ -43,9 +43,10 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.2
|
||||
https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
|
||||
https://github.com/dbinfrago/libpax.git#3cdc0371c375676a97967547f4065607d4c53fd1
|
||||
lewisxhe/XPowersLib@^0.2.6
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
@@ -23,6 +23,7 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
lewisxhe/XPowersLib@^0.2.6
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
[nrf52_base]
|
||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||
platform = platformio/nordicnrf52@^10.5.0
|
||||
platform = platformio/nordicnrf52@^10.7.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
|
||||
toolchain-gccarmnoneeabi@~1.90301.0
|
||||
|
||||
build_type = debug
|
||||
build_flags =
|
||||
@@ -14,14 +15,18 @@ build_flags =
|
||||
-Wno-unused-variable
|
||||
-Isrc/platform/nrf52
|
||||
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
|
||||
-DMESHTASTIC_EXCLUDE_AUDIO=1
|
||||
-DMESHTASTIC_EXCLUDE_PAXCOUNTER=1
|
||||
-DMAX_NUM_NODES=80
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
||||
|
||||
lib_deps=
|
||||
${arduino_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
lvgl
|
||||
lvgl
|
||||
@@ -1,6 +1,6 @@
|
||||
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native.git#6b3796d697481c8f6e3f4aa5c111bd9979f29e64
|
||||
platform = https://github.com/meshtastic/platform-native.git#562d189828f09fbf4c4093b3c0104bae9d8e9ff9
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
@@ -23,8 +23,10 @@ build_src_filter =
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
https://github.com/lovyan03/LovyanGFX.git#1401c28a47646fe00538d487adcb2eb3c72de805
|
||||
https://github.com/pine64/libch341-spi-userspace#a9b17e3452f7fb747000d9b4ad4409155b39f6ef
|
||||
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
@@ -32,6 +34,10 @@ build_flags =
|
||||
-Isrc/platform/portduino
|
||||
-DRADIOLIB_EEPROM_UNSUPPORTED
|
||||
-DPORTDUINO_LINUX_HARDWARE
|
||||
-lpthread
|
||||
-lstdc++fs
|
||||
-lbluetooth
|
||||
-lgpiod
|
||||
-lyaml-cpp
|
||||
-li2c
|
||||
-std=c++17
|
||||
@@ -1,8 +1,8 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2040_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico >=4.2.1
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.0.3
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#6024e9a7e82a72e38dd90f42029ba3748835eb2e ; 4.3.0 with fix MDNS
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -22,4 +22,5 @@ lib_ignore =
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto
|
||||
@@ -1,8 +1,8 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2350_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9e55f6db5c56b9867c69fe473f388beea4546672
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico >=4.2.1
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#a6ab6e1f95bc1428d667d55ea7173c0744acc03c ; 4.0.2+
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#6024e9a7e82a72e38dd90f42029ba3748835eb2e ; 4.3.0 with fix MDNS
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -21,4 +21,5 @@ lib_ignore =
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
rweather/Crypto
|
||||
${radiolib_base.lib_deps}
|
||||
rweather/Crypto
|
||||
@@ -30,8 +30,9 @@ upload_protocol = stlink
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
charlesbaynham/OSFS@^1.2.3
|
||||
jgromes/RadioLib@7.0.2
|
||||
https://github.com/caveman99/Crypto.git#f61ae26a53f7a2d0ba5511625b8bf8eff3a35d5e
|
||||
|
||||
lib_ignore =
|
||||
mathertel/OneButton@~2.6.1
|
||||
mathertel/OneButton@2.6.1
|
||||
Wire
|
||||
33
bin/base64_to_hex.py
Normal file
33
bin/base64_to_hex.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import sys
|
||||
import base64
|
||||
|
||||
def base64_to_hex_string(b64_string):
|
||||
try:
|
||||
# Decode the Base64 string to raw bytes
|
||||
decoded_bytes = base64.b64decode(b64_string)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Invalid Base64 input: {e}")
|
||||
|
||||
# Check if the decoded result is exactly 32 bytes
|
||||
if len(decoded_bytes) != 32:
|
||||
raise ValueError("Decoded Base64 input must be exactly 32 bytes.")
|
||||
|
||||
# Convert each byte to its hex representation
|
||||
hex_values = [f"0x{byte:02x}" for byte in decoded_bytes]
|
||||
|
||||
# Join the formatted hex values with commas
|
||||
formatted_output = "{ " + ", ".join(hex_values) + " };"
|
||||
return formatted_output
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Check if a Base64 string was provided in command line arguments
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python script.py <base64-string>")
|
||||
sys.exit(1)
|
||||
|
||||
b64_string = sys.argv[1]
|
||||
try:
|
||||
formatted_hex = base64_to_hex_string(b64_string)
|
||||
print(formatted_hex)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
@@ -35,6 +35,11 @@ cp $SRCBIN $OUTDIR/$basename-update.bin
|
||||
|
||||
echo "Building Filesystem for ESP32 targets"
|
||||
pio run --environment $1 -t buildfs
|
||||
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefswebui-$VERSION.bin
|
||||
# Remove webserver files from the filesystem and rebuild
|
||||
ls -l data/static # Diagnostic list of files
|
||||
rm -rf data/static
|
||||
pio run --environment $1 -t buildfs
|
||||
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
|
||||
@@ -27,5 +27,4 @@ rm -r $OUTDIR/* || true
|
||||
platformio pkg update --environment native || platformioFailed
|
||||
pio run --environment native || platformioFailed
|
||||
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
cp bin/native-install.* $OUTDIR
|
||||
|
||||
@@ -24,7 +24,7 @@ def write_macros_to_json(macros, output_file):
|
||||
|
||||
def main():
|
||||
header_file = 'userPrefs.h'
|
||||
output_file = 'userPrefs.json'
|
||||
output_file = 'userPrefs.jsonc'
|
||||
# Uncomment all macros in the header file
|
||||
with open(header_file, 'r') as file:
|
||||
lines = file.readlines()
|
||||
|
||||
@@ -12,13 +12,6 @@ Lora:
|
||||
# IRQ: 17
|
||||
# Reset: 22
|
||||
|
||||
# Module: sx1262 # pinedio
|
||||
# CS: 0
|
||||
# IRQ: 10
|
||||
# Busy: 11
|
||||
# DIO2_AS_RF_SWITCH: true
|
||||
# spidev: spidev0.1
|
||||
|
||||
# Module: RF95 # Adafruit RFM9x
|
||||
# Reset: 25
|
||||
# CS: 7
|
||||
@@ -50,8 +43,6 @@ Lora:
|
||||
# TXen: x # TX and RX enable pins
|
||||
# RXen: x
|
||||
|
||||
# ch341_quirk: true # Uncomment this to use the chunked SPI transfer that seems to fix the ch341
|
||||
|
||||
# spiSpeed: 2000000
|
||||
|
||||
### Set gpio chip to use in /dev/. Defaults to 0.
|
||||
@@ -81,17 +72,6 @@ I2C:
|
||||
|
||||
Display:
|
||||
|
||||
### Waveshare 2.8inch RPi LCD
|
||||
# Panel: ST7789
|
||||
# CS: 8
|
||||
# DC: 22 # Data/Command pin
|
||||
# Backlight: 18
|
||||
# Width: 240
|
||||
# Height: 320
|
||||
# Reset: 27
|
||||
# Rotate: true
|
||||
# Invert: true
|
||||
|
||||
### Waveshare 1.44inch LCD HAT
|
||||
# Panel: ST7735S
|
||||
# CS: 8 #Chip Select
|
||||
@@ -148,10 +128,6 @@ Touchscreen:
|
||||
# IRQ: 24
|
||||
# I2CAddr: 0x38
|
||||
|
||||
# Module: XPT2046 # Waveshare 2.8inch
|
||||
# CS: 7
|
||||
# IRQ: 17
|
||||
|
||||
### You can also specify the spi device for the touchscreen to use
|
||||
# spidev: spidev0.0
|
||||
|
||||
@@ -170,9 +146,11 @@ Logging:
|
||||
|
||||
Webserver:
|
||||
# Port: 443 # Port for Webserver & Webservices
|
||||
# RootPath: /usr/share/doc/meshtasticd/web # Root Dir of WebServer
|
||||
# RootPath: /usr/share/meshtasticd/web # Root Dir of WebServer
|
||||
|
||||
General:
|
||||
MaxNodes: 200
|
||||
MaxMessageQueue: 100
|
||||
ConfigDirectory: /etc/meshtasticd/config.d/
|
||||
ConfigDirectory: /etc/meshtasticd/config.d/
|
||||
# MACAddress: AA:BB:CC:DD:EE:FF
|
||||
# MACAddressSource: eth0
|
||||
9
bin/config.d/OpenWRT-One-mikroBUS-LR-IOT-CLICK.yaml
Normal file
9
bin/config.d/OpenWRT-One-mikroBUS-LR-IOT-CLICK.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
## https://www.mikroe.com/lr-iot-click
|
||||
Lora:
|
||||
Module: lr1110 # OpenWRT ONE mikroBUS with LR-IOT-CLICK
|
||||
# CS: 25
|
||||
IRQ: 10
|
||||
Busy: 12
|
||||
# Reset: 2
|
||||
spidev: spidev2.0
|
||||
DIO3_TCXO_VOLTAGE: 1.6
|
||||
8
bin/config.d/OpenWRT_One_mikroBUS_sx1262.yaml
Normal file
8
bin/config.d/OpenWRT_One_mikroBUS_sx1262.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
IRQ: 10
|
||||
Busy: 12
|
||||
# Reset: 2
|
||||
spidev: spidev2.0
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
20
bin/config.d/femtofox/femtofox_LR1121_TCXO.yaml
Normal file
20
bin/config.d/femtofox/femtofox_LR1121_TCXO.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
Lora:
|
||||
## Ebyte E80-900M22S
|
||||
## This is a bit experimental
|
||||
##
|
||||
##
|
||||
Module: lr1121
|
||||
gpiochip: 1 # subtract 32 from the gpio numbers
|
||||
DIO3_TCXO_VOLTAGE: 1.8
|
||||
CS: 16 #pin6 / GPIO48 1C0
|
||||
IRQ: 23 #pin17 / GPIO55 1C7
|
||||
Busy: 22 #pin16 / GPIO54 1C6
|
||||
Reset: 25 #pin13 / GPIO57 1D1
|
||||
|
||||
|
||||
spidev: spidev0.0 #pins are (CS=16, CLK=17, MOSI=18, MISO=19)
|
||||
spiSpeed: 2000000
|
||||
|
||||
General:
|
||||
MACAddressSource: eth0
|
||||
21
bin/config.d/femtofox/femtofox_SX1262_TCXO.yaml
Normal file
21
bin/config.d/femtofox/femtofox_SX1262_TCXO.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
Lora:
|
||||
## Ebyte E22-900M30S, E22-900M22S with or without external RF switching setup
|
||||
## HT-RA62 (Has internal switching, but whatever)
|
||||
## Seeed WIO SX1262 (already has TXEN-DIO2 link, but needs RXEN)
|
||||
## Will work with any module with or without RF switching, and with TCXO
|
||||
Module: sx1262
|
||||
gpiochip: 1 # subtract 32 from the gpio numbers
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
CS: 16 #pin6 / GPIO48 1C0
|
||||
IRQ: 23 #pin17 / GPIO55 1C7
|
||||
Busy: 22 #pin16 / GPIO54 1C6
|
||||
Reset: 25 #pin13 / GPIO57 1D1
|
||||
RXen: 24 #pin12 / GPIO56 1D0 # Not strictly needed for auto-switching, but why complicate things?
|
||||
# TXen: bridge to DIO2 on E22 module
|
||||
spidev: spidev0.0 #pins are (CS=16, CLK=17, MOSI=18, MISO=19)
|
||||
spiSpeed: 2000000
|
||||
|
||||
General:
|
||||
MACAddressSource: eth0
|
||||
21
bin/config.d/femtofox/femtofox_SX1262_XTAL.yaml
Normal file
21
bin/config.d/femtofox/femtofox_SX1262_XTAL.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
Lora:
|
||||
## Ebyte E22-900MM22S with no external RF switching setup
|
||||
## Waveshare SX126X XXXM, AI Thinker RA-01SH
|
||||
## Will work with any module with or without RF switching and no TCXO
|
||||
|
||||
Module: sx1262
|
||||
gpiochip: 1 # subtract 32 from the gpio numbers
|
||||
DIO2_AS_RF_SWITCH: true
|
||||
DIO3_TCXO_VOLTAGE: false
|
||||
CS: 16 #pin6 / GPIO48 1C0
|
||||
IRQ: 23 #pin17 / GPIO55 1C7
|
||||
Busy: 22 #pin16 / GPIO54 1C6
|
||||
Reset: 25 #pin13 / GPIO57 1D1
|
||||
RXen: 24 #pin12 / GPIO56 1D0 # Not strictly needed for auto-switching, but why complicate things?
|
||||
# TXen: bridge to DIO2 on E22 module
|
||||
spidev: spidev0.0 #pins are (CS=16, CLK=17, MOSI=18, MISO=19)
|
||||
spiSpeed: 2000000
|
||||
|
||||
General:
|
||||
MACAddressSource: eth0
|
||||
9
bin/config.d/lora-MeshAdv-900M30S.yaml
Normal file
9
bin/config.d/lora-MeshAdv-900M30S.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
CS: 21
|
||||
IRQ: 16
|
||||
Busy: 20
|
||||
Reset: 18
|
||||
TXen: 13
|
||||
RXen: 12
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
11
bin/config.d/lora-meshstick-1262.yaml
Normal file
11
bin/config.d/lora-meshstick-1262.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
CS: 0
|
||||
IRQ: 6
|
||||
Reset: 2
|
||||
Busy: 4
|
||||
spidev: ch341
|
||||
DIO3_TCXO_VOLTAGE: true
|
||||
# USB_Serialnum: 12345678
|
||||
USB_PID: 0x5512
|
||||
USB_VID: 0x1A86
|
||||
5
bin/config.d/lora-pinedio-usb-sx1262.yaml
Normal file
5
bin/config.d/lora-pinedio-usb-sx1262.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
Lora:
|
||||
Module: sx1262
|
||||
CS: 0
|
||||
IRQ: 10
|
||||
spidev: ch341
|
||||
@@ -1,16 +1,26 @@
|
||||
@ECHO OFF
|
||||
|
||||
set PYTHON=python
|
||||
set WEB_APP=0
|
||||
|
||||
:: Determine the correct esptool command to use
|
||||
where esptool >nul 2>&1
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
set "ESPTOOL_CMD=esptool"
|
||||
) else (
|
||||
set "ESPTOOL_CMD=%PYTHON% -m esptool"
|
||||
)
|
||||
|
||||
goto GETOPTS
|
||||
:HELP
|
||||
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME]
|
||||
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME] [--web]
|
||||
echo Flash image file to device, but first erasing and writing system information
|
||||
echo.
|
||||
echo -h Display this help and exit
|
||||
echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
|
||||
echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%)
|
||||
echo -f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
echo --web Flash WEB APP.
|
||||
goto EOF
|
||||
|
||||
:GETOPTS
|
||||
@@ -19,37 +29,44 @@ if /I "%1"=="--help" goto HELP
|
||||
if /I "%1"=="-F" set "FILENAME=%2" & SHIFT
|
||||
if /I "%1"=="-p" set ESPTOOL_PORT=%2 & SHIFT
|
||||
if /I "%1"=="-P" set PYTHON=%2 & SHIFT
|
||||
if /I "%1"=="--web" set WEB_APP=1 & SHIFT
|
||||
SHIFT
|
||||
IF NOT "__%1__"=="____" goto GETOPTS
|
||||
|
||||
IF "__%FILENAME%__" == "____" (
|
||||
echo "Missing FILENAME"
|
||||
goto HELP
|
||||
goto HELP
|
||||
)
|
||||
IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
||||
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
|
||||
%PYTHON% -m esptool --baud 115200 erase_flash
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||
%ESPTOOL_CMD% --baud 115200 erase_flash
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x00 %FILENAME%
|
||||
|
||||
@REM Account for S3 and C3 board's different OTA partition
|
||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% IF x%FILENAME:station-g2=%==x%FILENAME% IF x%FILENAME:unphone=%==x%FILENAME% (
|
||||
IF x%FILENAME:esp32c3=%==x%FILENAME% (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota.bin
|
||||
) else (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-c3.bin
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota-c3.bin
|
||||
)
|
||||
) else (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
|
||||
) else (
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota-s3.bin
|
||||
)
|
||||
for %%f in (littlefs-*.bin) do (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x300000 %%f
|
||||
IF %WEB_APP%==1 (
|
||||
for %%f in (littlefswebui-*.bin) do (
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
|
||||
)
|
||||
) else (
|
||||
for %%f in (littlefs-*.bin) do (
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
|
||||
)
|
||||
)
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
goto HELP
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
goto HELP
|
||||
)
|
||||
|
||||
:EOF
|
||||
|
||||
@@ -1,22 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
|
||||
WEB_APP=false
|
||||
|
||||
# Determine the correct esptool command to use
|
||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="$PYTHON -m esptool"
|
||||
elif command -v esptool >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="esptool"
|
||||
elif command -v esptool.py >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="esptool.py"
|
||||
else
|
||||
echo "Error: esptool not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
|
||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--web]
|
||||
Flash image file to device, but first erasing and writing system information"
|
||||
|
||||
-h Display this help and exit
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
--web Flash WEB APP.
|
||||
|
||||
EOF
|
||||
}
|
||||
# Preprocess long options like --web
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--web)
|
||||
WEB_APP=true
|
||||
shift # Remove this argument from the list
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
while getopts ":hp:P:f:" opt; do
|
||||
case "${opt}" in
|
||||
@@ -49,19 +72,23 @@ shift "$((OPTIND - 1))"
|
||||
|
||||
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
"$PYTHON" -m esptool erase_flash
|
||||
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||
$ESPTOOL_CMD erase_flash
|
||||
$ESPTOOL_CMD write_flash 0x00 ${FILENAME}
|
||||
# Account for S3 board's different OTA partition
|
||||
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then
|
||||
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||
$ESPTOOL_CMD write_flash 0x260000 bleota.bin
|
||||
else
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota-c3.bin
|
||||
$ESPTOOL_CMD write_flash 0x260000 bleota-c3.bin
|
||||
fi
|
||||
else
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
|
||||
$ESPTOOL_CMD write_flash 0x260000 bleota-s3.bin
|
||||
fi
|
||||
if [ "$WEB_APP" = true ]; then
|
||||
$ESPTOOL_CMD write_flash 0x300000 littlefswebui-*.bin
|
||||
else
|
||||
$ESPTOOL_CMD write_flash 0x300000 littlefs-*.bin
|
||||
fi
|
||||
"$PYTHON" -m esptool write_flash 0x300000 littlefs-*.bin
|
||||
|
||||
else
|
||||
show_help
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
set PYTHON=python
|
||||
|
||||
:: Determine the correct esptool command to use
|
||||
where esptool >nul 2>&1
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
set "ESPTOOL_CMD=esptool"
|
||||
) else (
|
||||
set "ESPTOOL_CMD=%PYTHON% -m esptool"
|
||||
)
|
||||
|
||||
goto GETOPTS
|
||||
:HELP
|
||||
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME]
|
||||
@@ -24,17 +32,17 @@ IF NOT "__%1__"=="____" goto GETOPTS
|
||||
|
||||
IF "__%FILENAME%__" == "____" (
|
||||
echo "Missing FILENAME"
|
||||
goto HELP
|
||||
goto HELP
|
||||
)
|
||||
IF EXIST %FILENAME% IF NOT x%FILENAME:update=%==x%FILENAME% (
|
||||
echo Trying to flash update %FILENAME%
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
|
||||
%ESPTOOL_CMD% --baud 115200 write_flash 0x10000 %FILENAME%
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
goto HELP
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
goto HELP
|
||||
)
|
||||
|
||||
:EOF
|
||||
|
||||
@@ -2,6 +2,18 @@
|
||||
|
||||
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
|
||||
|
||||
# Determine the correct esptool command to use
|
||||
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="$PYTHON -m esptool"
|
||||
elif command -v esptool >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="esptool"
|
||||
elif command -v esptool.py >/dev/null 2>&1; then
|
||||
ESPTOOL_CMD="esptool.py"
|
||||
else
|
||||
echo "Error: esptool not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat << EOF
|
||||
@@ -9,7 +21,7 @@ Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
|
||||
Flash image file to device, leave existing system intact."
|
||||
|
||||
-h Display this help and exit
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-f FILENAME The *update.bin file to flash. Custom to your device type.
|
||||
|
||||
@@ -30,7 +42,7 @@ while getopts ":hp:P:f:" opt; do
|
||||
f) FILENAME=${OPTARG}
|
||||
;;
|
||||
*)
|
||||
echo "Invalid flag."
|
||||
echo "Invalid flag."
|
||||
show_help >&2
|
||||
exit 1
|
||||
;;
|
||||
@@ -45,7 +57,7 @@ shift "$((OPTIND-1))"
|
||||
|
||||
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
|
||||
printf "Trying to flash update ${FILENAME}"
|
||||
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
|
||||
$ESPTOOL_CMD --baud 115200 write_flash 0x10000 ${FILENAME}
|
||||
else
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
||||
import sys
|
||||
from os.path import join
|
||||
import json
|
||||
import re
|
||||
|
||||
from readprops import readProps
|
||||
|
||||
@@ -88,12 +90,39 @@ Import("projenv")
|
||||
|
||||
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
||||
verObj = readProps(prefsLoc)
|
||||
print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"])
|
||||
print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"] + " on " + env.get("PIOENV"))
|
||||
|
||||
jsonLoc = env["PROJECT_DIR"] + "/userPrefs.jsonc"
|
||||
with open(jsonLoc) as f:
|
||||
jsonStr = re.sub("//.*","", f.read(), flags=re.MULTILINE)
|
||||
userPrefs = json.loads(jsonStr)
|
||||
|
||||
pref_flags = []
|
||||
# Pre-process the userPrefs
|
||||
for pref in userPrefs:
|
||||
if userPrefs[pref].startswith("{"):
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref].replace(".", "").isdigit():
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref] == "true" or userPrefs[pref] == "false":
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
elif userPrefs[pref].startswith("meshtastic_"):
|
||||
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
|
||||
# If the value is a string, we need to wrap it in quotes
|
||||
else:
|
||||
pref_flags.append("-D" + pref + "=" + env.StringifyMacro(userPrefs[pref]) + "")
|
||||
|
||||
# General options that are passed to the C and C++ compilers
|
||||
projenv.Append(
|
||||
CCFLAGS=[
|
||||
flags = [
|
||||
"-DAPP_VERSION=" + verObj["long"],
|
||||
"-DAPP_VERSION_SHORT=" + verObj["short"],
|
||||
]
|
||||
)
|
||||
"-DAPP_ENV=" + env.get("PIOENV"),
|
||||
] + pref_flags
|
||||
|
||||
print ("Using flags:")
|
||||
for flag in flags:
|
||||
print(flag)
|
||||
|
||||
projenv.Append(
|
||||
CCFLAGS=flags,
|
||||
)
|
||||
41
boards/esp32-s3-zero.json
Normal file
41
boards/esp32-s3-zero.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"partitions": "default.csv",
|
||||
"memory_type": "qio_qspi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DARDUINO_ESP32S3_DEV",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DBOARD_HAS_PSRAM"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"psram_type": "qio",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "esp32s3"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"platforms": ["espressif32"],
|
||||
"name": "Espressif ESP32-S3-FH4R2 (4 MB QD, 2MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html",
|
||||
"vendor": "Espressif"
|
||||
}
|
||||
42
boards/mesh-tab.json
Normal file
42
boards/mesh-tab.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"partitions": "default_16MB.csv",
|
||||
"memory_type": "qio_qspi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x303A", "0x80D6"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "mesh-tab"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "ESP32-S3 WROOM-1 N16R2 (16 MB FLASH, 2 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://github.com/valzzu/Mesh-Tab",
|
||||
"vendor": "Espressif"
|
||||
}
|
||||
@@ -15,10 +15,12 @@
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"f_boot": "120000000L",
|
||||
"boot": "qio",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x1A86", "0x7523"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "esp32s3r8"
|
||||
"variant": "esp32s3"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
@@ -32,9 +34,9 @@
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"require_upload_port": true,
|
||||
"require_upload_port": false,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"wait_for_upload_port": false,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://www.seeedstudio.com/Indicator-for-Meshtastic.html",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=0"
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
|
||||
@@ -48,6 +48,6 @@
|
||||
"require_upload_port": true,
|
||||
"wait_for_upload_port": true
|
||||
},
|
||||
"url": "FIXME",
|
||||
"vendor": "TTGO"
|
||||
"url": "https://lilygo.cc/products/t-echo-lilygo",
|
||||
"vendor": "LILYGO"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
version: "3.7"
|
||||
# USB-Based Meshtastic container-node!
|
||||
|
||||
# Copy .env.example to .env and set the USB_DEVICE and CONFIG_PATH variables
|
||||
|
||||
services:
|
||||
meshtastic-node:
|
||||
build: .
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 4
|
||||
networks:
|
||||
- mesh
|
||||
container_name: meshtasticd
|
||||
|
||||
networks:
|
||||
mesh:
|
||||
# Pass USB device through to the container
|
||||
devices:
|
||||
- "${USB_DEVICE}"
|
||||
|
||||
# Mount local config file and named volume for data persistence
|
||||
volumes:
|
||||
- "${CONFIG_PATH}:/etc/meshtasticd/config.yaml:ro"
|
||||
- meshtastic_data:/var/lib/meshtasticd
|
||||
|
||||
# Forward the container’s port 4403 to the host
|
||||
ports:
|
||||
- 4403:4403
|
||||
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
meshtastic_data:
|
||||
|
||||
183
platformio.ini
183
platformio.ini
@@ -16,6 +16,7 @@ default_envs = tbeam
|
||||
;default_envs = tlora-v2
|
||||
;default_envs = tlora-v2-1-1_6
|
||||
;default_envs = tlora-v2-1-1_6-tcxo
|
||||
;default_envs = tlora-v3-3-0-tcxo
|
||||
;default_envs = tlora-t3s3-v1
|
||||
;default_envs = t-echo
|
||||
;default_envs = canaryone
|
||||
@@ -29,138 +30,138 @@ default_envs = tbeam
|
||||
;default_envs = rak4631
|
||||
;default_envs = rak4631_eth_gw
|
||||
;default_envs = rak2560
|
||||
;default_envs = rak10701
|
||||
;default_envs = rak_wismeshtap
|
||||
;default_envs = wio-e5
|
||||
;default_envs = radiomaster_900_bandit_nano
|
||||
;default_envs = radiomaster_900_bandit_micro
|
||||
;default_envs = radiomaster_900_bandit
|
||||
;default_envs = heltec_capsule_sensor_v3
|
||||
;default_envs = heltec_vision_master_t190
|
||||
;default_envs = heltec_vision_master_e213
|
||||
;default_envs = heltec_vision_master_e290
|
||||
;default_envs = heltec_mesh_node_t114
|
||||
|
||||
extra_configs =
|
||||
arch/*/*.ini
|
||||
variants/*/platformio.ini
|
||||
arch/*/*.ini
|
||||
variants/*/platformio.ini
|
||||
description = Meshtastic
|
||||
|
||||
[env]
|
||||
test_build_src = true
|
||||
extra_scripts = bin/platformio-custom.py
|
||||
|
||||
; note: we add src to our include search path so that lmic_project_config can override
|
||||
; note: TINYGPS_OPTION_NO_CUSTOM_FIELDS is VERY important. We don't use custom fields and somewhere in that pile
|
||||
; of code is a heap corruption bug!
|
||||
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
|
||||
; The Radiolib stuff will speed up building considerably. Exclud all the stuff we dont need.
|
||||
build_flags = -Wno-missing-field-initializers
|
||||
-Wno-format
|
||||
-Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
|
||||
-DUSE_THREAD_NAMES
|
||||
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
-DPB_ENABLE_MALLOC=1
|
||||
-DRADIOLIB_EXCLUDE_CC1101=1
|
||||
-DRADIOLIB_EXCLUDE_NRF24=1
|
||||
-DRADIOLIB_EXCLUDE_RF69=1
|
||||
-DRADIOLIB_EXCLUDE_SX1231=1
|
||||
-DRADIOLIB_EXCLUDE_SX1233=1
|
||||
-DRADIOLIB_EXCLUDE_SI443X=1
|
||||
-DRADIOLIB_EXCLUDE_RFM2X=1
|
||||
-DRADIOLIB_EXCLUDE_AFSK=1
|
||||
-DRADIOLIB_EXCLUDE_BELL=1
|
||||
-DRADIOLIB_EXCLUDE_HELLSCHREIBER=1
|
||||
-DRADIOLIB_EXCLUDE_MORSE=1
|
||||
-DRADIOLIB_EXCLUDE_RTTY=1
|
||||
-DRADIOLIB_EXCLUDE_SSTV=1
|
||||
-DRADIOLIB_EXCLUDE_AX25=1
|
||||
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE=1
|
||||
-DRADIOLIB_EXCLUDE_BELL=1
|
||||
-DRADIOLIB_EXCLUDE_PAGER=1
|
||||
-DRADIOLIB_EXCLUDE_FSK4=1
|
||||
-DRADIOLIB_EXCLUDE_APRS=1
|
||||
-DRADIOLIB_EXCLUDE_LORAWAN=1
|
||||
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
||||
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
|
||||
#-DBUILD_EPOCH=$UNIX_TIME
|
||||
;-D OLED_PL
|
||||
|
||||
-Wno-format
|
||||
-Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
|
||||
-DUSE_THREAD_NAMES
|
||||
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
-DPB_ENABLE_MALLOC=1
|
||||
-DRADIOLIB_EXCLUDE_CC1101=1
|
||||
-DRADIOLIB_EXCLUDE_NRF24=1
|
||||
-DRADIOLIB_EXCLUDE_RF69=1
|
||||
-DRADIOLIB_EXCLUDE_SX1231=1
|
||||
-DRADIOLIB_EXCLUDE_SX1233=1
|
||||
-DRADIOLIB_EXCLUDE_SI443X=1
|
||||
-DRADIOLIB_EXCLUDE_RFM2X=1
|
||||
-DRADIOLIB_EXCLUDE_AFSK=1
|
||||
-DRADIOLIB_EXCLUDE_BELL=1
|
||||
-DRADIOLIB_EXCLUDE_HELLSCHREIBER=1
|
||||
-DRADIOLIB_EXCLUDE_MORSE=1
|
||||
-DRADIOLIB_EXCLUDE_RTTY=1
|
||||
-DRADIOLIB_EXCLUDE_SSTV=1
|
||||
-DRADIOLIB_EXCLUDE_AX25=1
|
||||
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE=1
|
||||
-DRADIOLIB_EXCLUDE_BELL=1
|
||||
-DRADIOLIB_EXCLUDE_PAGER=1
|
||||
-DRADIOLIB_EXCLUDE_FSK4=1
|
||||
-DRADIOLIB_EXCLUDE_APRS=1
|
||||
-DRADIOLIB_EXCLUDE_LORAWAN=1
|
||||
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
||||
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
|
||||
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
|
||||
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
|
||||
#-DBUILD_EPOCH=$UNIX_TIME
|
||||
;-D OLED_PL
|
||||
|
||||
monitor_speed = 115200
|
||||
monitor_filters = direct
|
||||
|
||||
lib_deps =
|
||||
jgromes/RadioLib@~7.0.2
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
|
||||
mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
||||
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
|
||||
nanopb/Nanopb@^0.4.9
|
||||
erriez/ErriezCRC32@^1.0.1
|
||||
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95
|
||||
mathertel/OneButton@2.6.1
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
||||
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
|
||||
nanopb/Nanopb@0.4.9
|
||||
erriez/ErriezCRC32@1.0.1
|
||||
|
||||
; Used for the code analysis in PIO Home / Inspect
|
||||
check_tool = cppcheck
|
||||
check_skip_packages = yes
|
||||
check_flags =
|
||||
-DAPP_VERSION=1.0.0
|
||||
--suppressions-list=suppressions.txt
|
||||
--inline-suppr
|
||||
-DAPP_VERSION=1.0.0
|
||||
--suppressions-list=suppressions.txt
|
||||
--inline-suppr
|
||||
|
||||
; Common settings for conventional (non Portduino) Arduino targets
|
||||
[arduino_base]
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
|
||||
|
||||
${env.lib_deps}
|
||||
end2endzone/NonBlockingRTTTL@1.3.0
|
||||
build_flags = ${env.build_flags} -Os
|
||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
||||
|
||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||
[networking_base]
|
||||
lib_deps =
|
||||
knolleary/PubSubClient@^2.8
|
||||
arduino-libraries/NTPClient@^3.1.0
|
||||
arcao/Syslog@^2.0.0
|
||||
knolleary/PubSubClient@2.8
|
||||
arduino-libraries/NTPClient@3.1.0
|
||||
arcao/Syslog@2.0.0
|
||||
|
||||
[radiolib_base]
|
||||
lib_deps =
|
||||
jgromes/RadioLib@7.1.0
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
; (not included in native / portduino)
|
||||
[environmental_base]
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@^1.16.1
|
||||
adafruit/Adafruit Unified Sensor@^1.1.11
|
||||
adafruit/Adafruit BMP280 Library@^2.6.8
|
||||
adafruit/Adafruit BMP085 Library@^1.2.4
|
||||
adafruit/Adafruit BME280 Library@^2.2.2
|
||||
adafruit/Adafruit BMP3XX Library@^2.1.5
|
||||
adafruit/Adafruit MCP9808 Library@^2.0.0
|
||||
adafruit/Adafruit INA260 Library@^1.5.0
|
||||
adafruit/Adafruit INA219@^1.2.0
|
||||
adafruit/Adafruit MAX1704X@^1.0.3
|
||||
adafruit/Adafruit SHTC3 Library@^1.0.0
|
||||
adafruit/Adafruit LPS2X@^2.0.4
|
||||
adafruit/Adafruit SHT31 Library@^2.2.2
|
||||
adafruit/Adafruit PM25 AQI Sensor@^1.1.1
|
||||
adafruit/Adafruit MPU6050@^2.2.4
|
||||
adafruit/Adafruit LIS3DH@^1.3.0
|
||||
adafruit/Adafruit AHTX0@^2.0.5
|
||||
adafruit/Adafruit LSM6DS@^4.7.2
|
||||
adafruit/Adafruit VEML7700 Library@^2.1.6
|
||||
adafruit/Adafruit SHT4x Library@^1.0.4
|
||||
adafruit/Adafruit TSL2591 Library@^1.4.5
|
||||
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@^1.0.5
|
||||
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@^1.2.13
|
||||
ClosedCube OPT3001@^1.1.2
|
||||
emotibit/EmotiBit MLX90632@^1.0.8
|
||||
dfrobot/DFRobot_RTU@^1.0.3
|
||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@^1.1.2
|
||||
adafruit/Adafruit MLX90614 Library@^2.1.5
|
||||
adafruit/Adafruit BusIO@1.16.2
|
||||
adafruit/Adafruit Unified Sensor@1.1.14
|
||||
adafruit/Adafruit BMP280 Library@2.6.8
|
||||
adafruit/Adafruit BMP085 Library@1.2.4
|
||||
adafruit/Adafruit BME280 Library@2.2.4
|
||||
adafruit/Adafruit BMP3XX Library@2.1.5
|
||||
adafruit/Adafruit MCP9808 Library@2.0.2
|
||||
adafruit/Adafruit INA260 Library@1.5.2
|
||||
adafruit/Adafruit INA219@1.2.3
|
||||
adafruit/Adafruit MAX1704X@1.0.3
|
||||
adafruit/Adafruit SHTC3 Library@1.0.1
|
||||
adafruit/Adafruit LPS2X@2.0.6
|
||||
adafruit/Adafruit SHT31 Library@2.2.2
|
||||
adafruit/Adafruit PM25 AQI Sensor@1.1.1
|
||||
adafruit/Adafruit MPU6050@2.2.6
|
||||
adafruit/Adafruit LIS3DH@1.3.0
|
||||
adafruit/Adafruit AHTX0@2.0.5
|
||||
adafruit/Adafruit LSM6DS@4.7.3
|
||||
adafruit/Adafruit VEML7700 Library@2.1.6
|
||||
adafruit/Adafruit SHT4x Library@1.0.5
|
||||
adafruit/Adafruit TSL2591 Library@1.4.5
|
||||
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
|
||||
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.2.13
|
||||
ClosedCube OPT3001@1.1.2
|
||||
emotibit/EmotiBit MLX90632@1.0.8
|
||||
adafruit/Adafruit MLX90614 Library@2.1.5
|
||||
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
|
||||
boschsensortec/BME68x Sensor Library@1.1.40407
|
||||
https://github.com/KodinLanewave/INA3221@1.0.1
|
||||
mprograms/QMC5883LCompass@1.2.3
|
||||
dfrobot/DFRobot_RTU@1.0.3
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
|
||||
robtillaart/INA226@0.6.0
|
||||
|
||||
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
|
||||
boschsensortec/BME68x Sensor Library@^1.1.40407
|
||||
https://github.com/KodinLanewave/INA3221@^1.0.1
|
||||
lewisxhe/SensorLib@0.2.0
|
||||
mprograms/QMC5883LCompass@^1.2.0
|
||||
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
|
||||
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
|
||||
; Health Sensor Libraries
|
||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
|
||||
Submodule protobufs updated: 807236815d...c55f120a9c
1
release/latest/.gitignore
vendored
1
release/latest/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
curfirmwareversion.xml
|
||||
@@ -21,7 +21,7 @@ namespace concurrency
|
||||
class AmbientLightingThread : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
|
||||
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLighting")
|
||||
{
|
||||
notifyDeepSleepObserver.observe(¬ifyDeepSleep); // Let us know when shutdown() is issued.
|
||||
|
||||
@@ -42,18 +42,18 @@ class AmbientLightingThread : public concurrency::OSThread
|
||||
#ifdef HAS_NCP5623
|
||||
_type = type;
|
||||
if (_type == ScanI2C::DeviceType::NONE) {
|
||||
LOG_DEBUG("AmbientLightingThread disabling due to no RGB leds found on I2C bus");
|
||||
LOG_DEBUG("AmbientLighting Disable due to no RGB leds found on I2C bus");
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
|
||||
if (!moduleConfig.ambient_lighting.led_state) {
|
||||
LOG_DEBUG("AmbientLightingThread disabling due to moduleConfig.ambient_lighting.led_state OFF");
|
||||
LOG_DEBUG("AmbientLighting Disable due to moduleConfig.ambient_lighting.led_state OFF");
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG("AmbientLightingThread initializing");
|
||||
LOG_DEBUG("AmbientLighting init");
|
||||
#ifdef HAS_NCP5623
|
||||
if (_type == ScanI2C::NCP5623) {
|
||||
rgb.begin();
|
||||
@@ -106,27 +106,27 @@ class AmbientLightingThread : public concurrency::OSThread
|
||||
rgb.setRed(0);
|
||||
rgb.setGreen(0);
|
||||
rgb.setBlue(0);
|
||||
LOG_INFO("Turn Off NCP5623 Ambient lighting.");
|
||||
LOG_INFO("OFF: NCP5623 Ambient lighting");
|
||||
#endif
|
||||
#ifdef HAS_NEOPIXEL
|
||||
pixels.clear();
|
||||
pixels.show();
|
||||
LOG_INFO("Turn Off NeoPixel Ambient lighting.");
|
||||
LOG_INFO("OFF: NeoPixel Ambient lighting");
|
||||
#endif
|
||||
#ifdef RGBLED_CA
|
||||
analogWrite(RGBLED_RED, 255 - 0);
|
||||
analogWrite(RGBLED_GREEN, 255 - 0);
|
||||
analogWrite(RGBLED_BLUE, 255 - 0);
|
||||
LOG_INFO("Turn Off Ambient lighting RGB Common Anode.");
|
||||
LOG_INFO("OFF: Ambient light RGB Common Anode");
|
||||
#elif defined(RGBLED_RED)
|
||||
analogWrite(RGBLED_RED, 0);
|
||||
analogWrite(RGBLED_GREEN, 0);
|
||||
analogWrite(RGBLED_BLUE, 0);
|
||||
LOG_INFO("Turn Off Ambient lighting RGB Common Cathode.");
|
||||
LOG_INFO("OFF: Ambient light RGB Common Cathode");
|
||||
#endif
|
||||
#ifdef UNPHONE
|
||||
unphone.rgb(0, 0, 0);
|
||||
LOG_INFO("Turn Off unPhone Ambient lighting.");
|
||||
LOG_INFO("OFF: unPhone Ambient lighting");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -138,9 +138,8 @@ class AmbientLightingThread : public concurrency::OSThread
|
||||
rgb.setRed(moduleConfig.ambient_lighting.red);
|
||||
rgb.setGreen(moduleConfig.ambient_lighting.green);
|
||||
rgb.setBlue(moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Initializing NCP5623 Ambient lighting w/ current=%d, red=%d, green=%d, blue=%d",
|
||||
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||
moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
|
||||
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
#ifdef HAS_NEOPIXEL
|
||||
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||
@@ -158,7 +157,7 @@ class AmbientLightingThread : public concurrency::OSThread
|
||||
#endif
|
||||
#endif
|
||||
pixels.show();
|
||||
LOG_DEBUG("Initializing NeoPixel Ambient lighting w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
|
||||
LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
|
||||
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||
moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
@@ -166,21 +165,21 @@ class AmbientLightingThread : public concurrency::OSThread
|
||||
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
|
||||
analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
|
||||
analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Initializing Ambient lighting RGB Common Anode w/ red=%d, green=%d, blue=%d",
|
||||
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#elif defined(RGBLED_RED)
|
||||
analogWrite(RGBLED_RED, moduleConfig.ambient_lighting.red);
|
||||
analogWrite(RGBLED_GREEN, moduleConfig.ambient_lighting.green);
|
||||
analogWrite(RGBLED_BLUE, moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Initializing Ambient lighting RGB Common Cathode w/ red=%d, green=%d, blue=%d",
|
||||
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Init Ambient light RGB Common Cathode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
#ifdef UNPHONE
|
||||
unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
LOG_DEBUG("Initializing unPhone Ambient lighting w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
|
||||
LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
|
||||
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
} // namespace concurrency
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
class AudioThread : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
AudioThread() : OSThread("AudioThread") { initOutput(); }
|
||||
AudioThread() : OSThread("Audio") { initOutput(); }
|
||||
|
||||
void beginRttl(const void *data, uint32_t len)
|
||||
{
|
||||
@@ -64,7 +64,7 @@ class AudioThread : public concurrency::OSThread
|
||||
void initOutput()
|
||||
{
|
||||
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
|
||||
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
|
||||
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_MCLK);
|
||||
audioOut->SetGain(0.2);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "ButtonThread.h"
|
||||
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
@@ -26,20 +27,25 @@ using namespace concurrency;
|
||||
ButtonThread *buttonThread; // Declared extern in header
|
||||
volatile ButtonThread::ButtonEventType ButtonThread::btnEvent = ButtonThread::BUTTON_EVENT_NONE;
|
||||
|
||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
|
||||
OneButton ButtonThread::userButton; // Get reference to static member
|
||||
#endif
|
||||
ButtonThread::ButtonThread() : OSThread("Button")
|
||||
{
|
||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
|
||||
|
||||
#if defined(ARCH_PORTDUINO)
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
|
||||
this->userButton = OneButton(settingsMap[user], true, true);
|
||||
LOG_DEBUG("Using GPIO%02d for button", settingsMap[user]);
|
||||
LOG_DEBUG("Use GPIO%02d for button", settingsMap[user]);
|
||||
}
|
||||
#elif defined(BUTTON_PIN)
|
||||
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
|
||||
#if !defined(USERPREFS_BUTTON_PIN)
|
||||
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
|
||||
#endif
|
||||
#ifdef USERPREFS_BUTTON_PIN
|
||||
int pin = config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN; // Resolved button pin
|
||||
#endif
|
||||
#if defined(HELTEC_CAPSULE_SENSOR_V3)
|
||||
this->userButton = OneButton(pin, false, false);
|
||||
#elif defined(BUTTON_ACTIVE_LOW)
|
||||
@@ -47,7 +53,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
||||
#else
|
||||
this->userButton = OneButton(pin, true, true);
|
||||
#endif
|
||||
LOG_DEBUG("Using GPIO%02d for button", pin);
|
||||
LOG_DEBUG("Use GPIO%02d for button", pin);
|
||||
#endif
|
||||
|
||||
#ifdef INPUT_PULLUP_SENSE
|
||||
@@ -59,7 +65,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
|
||||
userButton.attachClick(userButtonPressed);
|
||||
userButton.setClickMs(BUTTON_CLICK_MS);
|
||||
userButton.setPressMs(BUTTON_LONGPRESS_MS);
|
||||
@@ -102,7 +108,7 @@ int32_t ButtonThread::runOnce()
|
||||
// If the button is pressed we suppress CPU sleep until release
|
||||
canSleep = true; // Assume we should not keep the board awake
|
||||
|
||||
#if defined(BUTTON_PIN)
|
||||
#if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN)
|
||||
userButton.tick();
|
||||
canSleep &= userButton.isIdle();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
@@ -130,7 +136,12 @@ int32_t ButtonThread::runOnce()
|
||||
return 50;
|
||||
}
|
||||
#ifdef BUTTON_PIN
|
||||
#if !defined(USERPREFS_BUTTON_PIN)
|
||||
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
|
||||
#endif
|
||||
#if defined(USERPREFS_BUTTON_PIN)
|
||||
if (((config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN) !=
|
||||
#endif
|
||||
moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
|
||||
!moduleConfig.canned_message.enabled) {
|
||||
@@ -244,7 +255,12 @@ void ButtonThread::attachButtonInterrupts()
|
||||
#elif defined(BUTTON_PIN)
|
||||
// Interrupt for user button, during normal use. Improves responsiveness.
|
||||
attachInterrupt(
|
||||
#if !defined(USERPREFS_BUTTON_PIN)
|
||||
config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN,
|
||||
#endif
|
||||
#if defined(USERPREFS_BUTTON_PIN)
|
||||
config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN,
|
||||
#endif
|
||||
[]() {
|
||||
ButtonThread::userButton.tick();
|
||||
runASAP = true;
|
||||
@@ -273,8 +289,13 @@ void ButtonThread::detachButtonInterrupts()
|
||||
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||
detachInterrupt(settingsMap[user]);
|
||||
#elif defined(BUTTON_PIN)
|
||||
#if !defined(USERPREFS_BUTTON_PIN)
|
||||
detachInterrupt(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
|
||||
#endif
|
||||
#if defined(USERPREFS_BUTTON_PIN)
|
||||
detachInterrupt(config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
detachInterrupt(BUTTON_PIN_ALT);
|
||||
@@ -315,7 +336,7 @@ void ButtonThread::userButtonMultiPressed(void *callerThread)
|
||||
// Non-static method, runs during callback. Grabs info while still valid
|
||||
void ButtonThread::storeClickCount()
|
||||
{
|
||||
#ifdef BUTTON_PIN
|
||||
#if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN)
|
||||
multipressClickCount = userButton.getNumberClicks();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
void storeClickCount();
|
||||
|
||||
private:
|
||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
|
||||
static OneButton userButton; // Static - accessed from an interrupt
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#define LOG_CRIT(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_TRACE(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#else
|
||||
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE) && !defined(PIO_UNIT_TESTING)
|
||||
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
|
||||
#define LOG_DEBUG(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#define LOG_INFO(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_INFO, __VA_ARGS__)
|
||||
#define LOG_WARN(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_WARN, __VA_ARGS__)
|
||||
|
||||
@@ -55,6 +55,15 @@ extern "C" void lfs_assert(const char *reason)
|
||||
{
|
||||
LOG_ERROR("LFS assert: %s", reason);
|
||||
lfs_assert_failed = true;
|
||||
|
||||
#ifndef ARCH_PORTDUINO
|
||||
#ifdef FSCom
|
||||
// CORRUPTED FILESYSTEM. This causes bootloop so
|
||||
// might as well try formatting now.
|
||||
LOG_ERROR("Trying FSCom.format()");
|
||||
FSCom.format();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +240,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
|
||||
#ifdef ARCH_ESP32
|
||||
listDir(file.path(), levels - 1, del);
|
||||
if (del) {
|
||||
LOG_DEBUG("Removing %s", file.path());
|
||||
LOG_DEBUG("Remove %s", file.path());
|
||||
strncpy(buffer, file.path(), sizeof(buffer));
|
||||
file.close();
|
||||
FSCom.rmdir(buffer);
|
||||
@@ -241,7 +250,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
|
||||
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||
listDir(file.name(), levels - 1, del);
|
||||
if (del) {
|
||||
LOG_DEBUG("Removing %s", file.name());
|
||||
LOG_DEBUG("Remove %s", file.name());
|
||||
strncpy(buffer, file.name(), sizeof(buffer));
|
||||
file.close();
|
||||
FSCom.rmdir(buffer);
|
||||
@@ -257,7 +266,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
|
||||
} else {
|
||||
#ifdef ARCH_ESP32
|
||||
if (del) {
|
||||
LOG_DEBUG("Deleting %s", file.path());
|
||||
LOG_DEBUG("Delete %s", file.path());
|
||||
strncpy(buffer, file.path(), sizeof(buffer));
|
||||
file.close();
|
||||
FSCom.remove(buffer);
|
||||
@@ -267,7 +276,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
|
||||
}
|
||||
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||
if (del) {
|
||||
LOG_DEBUG("Deleting %s", file.name());
|
||||
LOG_DEBUG("Delete %s", file.name());
|
||||
strncpy(buffer, file.name(), sizeof(buffer));
|
||||
file.close();
|
||||
FSCom.remove(buffer);
|
||||
@@ -284,7 +293,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
|
||||
}
|
||||
#ifdef ARCH_ESP32
|
||||
if (del) {
|
||||
LOG_DEBUG("Removing %s", root.path());
|
||||
LOG_DEBUG("Remove %s", root.path());
|
||||
strncpy(buffer, root.path(), sizeof(buffer));
|
||||
root.close();
|
||||
FSCom.rmdir(buffer);
|
||||
@@ -293,7 +302,7 @@ void listDir(const char *dirname, uint8_t levels, bool del)
|
||||
}
|
||||
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||
if (del) {
|
||||
LOG_DEBUG("Removing %s", root.name());
|
||||
LOG_DEBUG("Remove %s", root.name());
|
||||
strncpy(buffer, root.name(), sizeof(buffer));
|
||||
root.close();
|
||||
FSCom.rmdir(buffer);
|
||||
@@ -329,7 +338,7 @@ void fsInit()
|
||||
{
|
||||
#ifdef FSCom
|
||||
if (!FSBegin()) {
|
||||
LOG_ERROR("Filesystem mount Failed.");
|
||||
LOG_ERROR("Filesystem mount failed");
|
||||
// assert(0); This auto-formats the partition, so no need to fail here.
|
||||
}
|
||||
#if defined(ARCH_ESP32)
|
||||
|
||||
@@ -50,9 +50,6 @@ class GPSStatus : public Status
|
||||
int32_t getLatitude() const
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_WARN("Using fixed latitude");
|
||||
#endif
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
return node->position.latitude_i;
|
||||
} else {
|
||||
@@ -63,9 +60,6 @@ class GPSStatus : public Status
|
||||
int32_t getLongitude() const
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_WARN("Using fixed longitude");
|
||||
#endif
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
return node->position.longitude_i;
|
||||
} else {
|
||||
@@ -76,9 +70,6 @@ class GPSStatus : public Status
|
||||
int32_t getAltitude() const
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_WARN("Using fixed altitude");
|
||||
#endif
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
return node->position.altitude;
|
||||
} else {
|
||||
@@ -94,7 +85,7 @@ class GPSStatus : public Status
|
||||
|
||||
bool matches(const GPSStatus *newStatus) const
|
||||
{
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("GPSStatus.match() new pos@%x to old pos@%x", newStatus->p.timestamp, p.timestamp);
|
||||
#endif
|
||||
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected ||
|
||||
|
||||
@@ -12,7 +12,6 @@ void GpioVirtPin::set(bool value)
|
||||
|
||||
void GpioHwPin::set(bool value)
|
||||
{
|
||||
// if (num == 3) LOG_DEBUG("Setting pin %d to %d", num, value);
|
||||
pinMode(num, OUTPUT);
|
||||
digitalWrite(num, value);
|
||||
}
|
||||
@@ -66,7 +65,7 @@ GpioBinaryTransformer::GpioBinaryTransformer(GpioVirtPin *inPin1, GpioVirtPin *i
|
||||
assert(!inPin2->dependentPin); // We only allow one dependent pin
|
||||
inPin2->dependentPin = this;
|
||||
|
||||
// Don't update at construction time, because various GpioPins might be global constructor based not yet initied because
|
||||
// Don't update at construction time, because various GpioPins might be global constructor based not yet initiated because
|
||||
// order of operations for global constructors is not defined.
|
||||
// update();
|
||||
}
|
||||
@@ -88,7 +87,6 @@ void GpioBinaryTransformer::update()
|
||||
newValue = (GpioVirtPin::PinState)(p1 && p2);
|
||||
break;
|
||||
case Or:
|
||||
// LOG_DEBUG("Doing GPIO OR");
|
||||
newValue = (GpioVirtPin::PinState)(p1 || p2);
|
||||
break;
|
||||
case Xor:
|
||||
@@ -101,4 +99,4 @@ void GpioBinaryTransformer::update()
|
||||
set(newValue);
|
||||
}
|
||||
|
||||
GpioSplitter::GpioSplitter(GpioPin *outPin1, GpioPin *outPin2) : outPin1(outPin1), outPin2(outPin2) {}
|
||||
GpioSplitter::GpioSplitter(GpioPin *outPin1, GpioPin *outPin2) : outPin1(outPin1), outPin2(outPin2) {}
|
||||
|
||||
@@ -72,8 +72,9 @@ static const uint8_t ext_chrg_detect_value = EXT_CHRG_DETECT_VALUE;
|
||||
#endif
|
||||
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
|
||||
INA260Sensor ina260Sensor;
|
||||
INA219Sensor ina219Sensor;
|
||||
INA226Sensor ina226Sensor;
|
||||
INA260Sensor ina260Sensor;
|
||||
INA3221Sensor ina3221Sensor;
|
||||
#endif
|
||||
|
||||
@@ -154,9 +155,16 @@ static void adcEnable()
|
||||
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
|
||||
#ifdef ADC_USE_PULLUP
|
||||
pinMode(ADC_CTRL, INPUT_PULLUP);
|
||||
#else
|
||||
#ifdef HELTEC_V3
|
||||
pinMode(ADC_CTRL, INPUT);
|
||||
uint8_t adc_ctl_enable_value = !(digitalRead(ADC_CTRL));
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, adc_ctl_enable_value);
|
||||
#else
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
|
||||
#endif
|
||||
#endif
|
||||
delay(10);
|
||||
#endif
|
||||
@@ -167,10 +175,14 @@ static void adcDisable()
|
||||
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
|
||||
#ifdef ADC_USE_PULLUP
|
||||
pinMode(ADC_CTRL, INPUT_PULLDOWN);
|
||||
#else
|
||||
#ifdef HELTEC_V3
|
||||
pinMode(ADC_CTRL, ANALOG);
|
||||
#else
|
||||
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -240,7 +252,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && \
|
||||
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
if (hasINA()) {
|
||||
LOG_DEBUG("Using INA on I2C addr 0x%x for device battery voltage", config.power.device_battery_ina_address);
|
||||
return getINAVoltage();
|
||||
}
|
||||
#endif
|
||||
@@ -260,7 +271,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
config.power.adc_multiplier_override > 0 ? config.power.adc_multiplier_override : ADC_MULTIPLIER;
|
||||
// Do not call analogRead() often.
|
||||
const uint32_t min_read_interval = 5000;
|
||||
if (!Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
|
||||
if (!initial_read_done || !Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
|
||||
last_read_time_ms = millis();
|
||||
|
||||
uint32_t raw = 0;
|
||||
@@ -403,7 +414,20 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
#ifdef EXT_CHRG_DETECT
|
||||
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
|
||||
#else
|
||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && \
|
||||
!defined(DISABLE_INA_CHARGING_DETECTION)
|
||||
if (hasINA()) {
|
||||
// get current flow from INA sensor - negative value means power flowing into the battery
|
||||
// default assuming BATTERY+ <--> INA_VIN+ <--> SHUNT RESISTOR <--> INA_VIN- <--> LOAD
|
||||
LOG_DEBUG("Using INA on I2C addr 0x%x for charging detection", config.power.device_battery_ina_address);
|
||||
#if defined(INA_CHARGING_DETECTION_INVERT)
|
||||
return getINACurrent() > 0;
|
||||
#else
|
||||
return getINACurrent() < 0;
|
||||
#endif
|
||||
}
|
||||
return isBatteryConnect() && isVbusIn();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -440,6 +464,9 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
{
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
|
||||
return ina219Sensor.getBusVoltageMv();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA226].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
return ina226Sensor.getBusVoltageMv();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
return ina260Sensor.getBusVoltageMv();
|
||||
@@ -450,6 +477,20 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t getINACurrent()
|
||||
{
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
|
||||
return ina219Sensor.getCurrentMa();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA226].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
return ina226Sensor.getCurrentMa();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA3221].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
return ina3221Sensor.getCurrentMa();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool hasINA()
|
||||
{
|
||||
if (!config.power.device_battery_ina_address) {
|
||||
@@ -459,6 +500,10 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
if (!ina219Sensor.isInitialized())
|
||||
return ina219Sensor.runOnce() > 0;
|
||||
return ina219Sensor.isRunning();
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA226].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
if (!ina226Sensor.isInitialized())
|
||||
return ina226Sensor.runOnce() > 0;
|
||||
} else if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260].first ==
|
||||
config.power.device_battery_ina_address) {
|
||||
if (!ina260Sensor.isInitialized())
|
||||
@@ -500,7 +545,7 @@ bool Power::analogInit()
|
||||
#endif
|
||||
|
||||
#ifdef BATTERY_PIN
|
||||
LOG_DEBUG("Using analog input %d for battery level", BATTERY_PIN);
|
||||
LOG_DEBUG("Use analog input %d for battery level", BATTERY_PIN);
|
||||
|
||||
// disable any internal pullups
|
||||
pinMode(BATTERY_PIN, INPUT);
|
||||
@@ -531,18 +576,18 @@ bool Power::analogInit()
|
||||
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_characs);
|
||||
// show ADC characterization base
|
||||
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
|
||||
LOG_INFO("ADCmod: ADC characterization based on Two Point values stored in eFuse");
|
||||
LOG_INFO("ADC config based on Two Point values stored in eFuse");
|
||||
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
|
||||
LOG_INFO("ADCmod: ADC characterization based on reference voltage stored in eFuse");
|
||||
LOG_INFO("ADC config based on reference voltage stored in eFuse");
|
||||
}
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
// ESP32S3
|
||||
else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP_FIT) {
|
||||
LOG_INFO("ADCmod: ADC Characterization based on Two Point values and fitting curve coefficients stored in eFuse");
|
||||
LOG_INFO("ADC config based on Two Point values and fitting curve coefficients stored in eFuse");
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
LOG_INFO("ADCmod: ADC characterization based on default reference voltage");
|
||||
LOG_INFO("ADC config based on default reference voltage");
|
||||
}
|
||||
#endif // ARCH_ESP32
|
||||
|
||||
@@ -603,7 +648,7 @@ void Power::shutdown()
|
||||
#ifdef PIN_LED3
|
||||
ledOff(PIN_LED3);
|
||||
#endif
|
||||
doDeepSleep(DELAY_FOREVER, false);
|
||||
doDeepSleep(DELAY_FOREVER, false, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -629,7 +674,7 @@ void Power::readPowerStatus()
|
||||
batteryChargePercent = batteryLevel->getBatteryPercent();
|
||||
} else {
|
||||
// If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error
|
||||
// In that case, we compute an estimate of the charge percent based on open circuite voltage table defined
|
||||
// In that case, we compute an estimate of the charge percent based on open circuit voltage table defined
|
||||
// in power.h
|
||||
batteryChargePercent = clamp((int)(((batteryVoltageMv - (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS)) * 1e2) /
|
||||
((OCV[0] * NUM_CELLS) - (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS))),
|
||||
@@ -711,9 +756,9 @@ void Power::readPowerStatus()
|
||||
if (low_voltage_counter > 10) {
|
||||
#ifdef ARCH_NRF52
|
||||
// We can't trigger deep sleep on NRF52, it's freezing the board
|
||||
LOG_DEBUG("Low voltage detected, but not triggering deep sleep");
|
||||
LOG_DEBUG("Low voltage detected, but not trigger deep sleep");
|
||||
#else
|
||||
LOG_INFO("Low voltage detected, triggering deep sleep");
|
||||
LOG_INFO("Low voltage detected, trigger deep sleep");
|
||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
#endif
|
||||
}
|
||||
@@ -805,22 +850,22 @@ bool Power::axpChipInit()
|
||||
if (!PMU) {
|
||||
PMU = new XPowersAXP2101(*w);
|
||||
if (!PMU->init()) {
|
||||
LOG_WARN("Failed to find AXP2101 power management");
|
||||
LOG_WARN("No AXP2101 power management");
|
||||
delete PMU;
|
||||
PMU = NULL;
|
||||
} else {
|
||||
LOG_INFO("AXP2101 PMU init succeeded, using AXP2101 PMU");
|
||||
LOG_INFO("AXP2101 PMU init succeeded");
|
||||
}
|
||||
}
|
||||
|
||||
if (!PMU) {
|
||||
PMU = new XPowersAXP192(*w);
|
||||
if (!PMU->init()) {
|
||||
LOG_WARN("Failed to find AXP192 power management");
|
||||
LOG_WARN("No AXP192 power management");
|
||||
delete PMU;
|
||||
PMU = NULL;
|
||||
} else {
|
||||
LOG_INFO("AXP192 PMU init succeeded, using AXP192 PMU");
|
||||
LOG_INFO("AXP192 PMU init succeeded");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1144,4 +1189,4 @@ bool Power::lipoInit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
|
||||
#ifndef SLEEP_TIME
|
||||
#define SLEEP_TIME 30
|
||||
#endif
|
||||
@@ -53,16 +57,21 @@ static bool isPowered()
|
||||
|
||||
static void sdsEnter()
|
||||
{
|
||||
LOG_DEBUG("Enter state: SDS");
|
||||
LOG_DEBUG("State: SDS");
|
||||
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
|
||||
doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false);
|
||||
doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, false);
|
||||
}
|
||||
|
||||
static void lowBattSDSEnter()
|
||||
{
|
||||
LOG_DEBUG("State: Lower batt SDS");
|
||||
doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, true);
|
||||
}
|
||||
extern Power *power;
|
||||
|
||||
static void shutdownEnter()
|
||||
{
|
||||
LOG_DEBUG("Enter state: SHUTDOWN");
|
||||
LOG_DEBUG("State: SHUTDOWN");
|
||||
power->shutdown();
|
||||
}
|
||||
|
||||
@@ -105,7 +114,7 @@ static void lsIdle()
|
||||
wakeCause2 = doLightSleep(100); // leave led on for 1ms
|
||||
|
||||
secsSlept += sleepTime;
|
||||
// LOG_INFO("sleeping, flash led!");
|
||||
// LOG_INFO("Sleep, flash led!");
|
||||
break;
|
||||
|
||||
case ESP_SLEEP_WAKEUP_UART:
|
||||
@@ -137,7 +146,7 @@ static void lsIdle()
|
||||
} else {
|
||||
// Time to stop sleeping!
|
||||
ledBlink.set(false);
|
||||
LOG_INFO("Reached ls_secs, servicing loop()");
|
||||
LOG_INFO("Reached ls_secs, service loop()");
|
||||
powerFSM.trigger(EVENT_WAKE_TIMER);
|
||||
}
|
||||
#endif
|
||||
@@ -150,7 +159,7 @@ static void lsExit()
|
||||
|
||||
static void nbEnter()
|
||||
{
|
||||
LOG_DEBUG("Enter state: NB");
|
||||
LOG_DEBUG("State: NB");
|
||||
screen->setOn(false);
|
||||
#ifdef ARCH_ESP32
|
||||
// Only ESP32 should turn off bluetooth
|
||||
@@ -168,7 +177,7 @@ static void darkEnter()
|
||||
|
||||
static void serialEnter()
|
||||
{
|
||||
LOG_DEBUG("Enter state: SERIAL");
|
||||
LOG_DEBUG("State: SERIAL");
|
||||
setBluetoothEnable(false);
|
||||
screen->setOn(true);
|
||||
screen->print("Serial connected\n");
|
||||
@@ -183,9 +192,9 @@ static void serialExit()
|
||||
|
||||
static void powerEnter()
|
||||
{
|
||||
// LOG_DEBUG("Enter state: POWER");
|
||||
// LOG_DEBUG("State: POWER");
|
||||
if (!isPowered()) {
|
||||
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
|
||||
// If we got here, we are in the wrong state - we should be in powered, let that state handle things
|
||||
LOG_INFO("Loss of power in Powered");
|
||||
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
||||
} else {
|
||||
@@ -222,7 +231,7 @@ static void powerExit()
|
||||
|
||||
static void onEnter()
|
||||
{
|
||||
LOG_DEBUG("Enter state: ON");
|
||||
LOG_DEBUG("State: ON");
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
}
|
||||
@@ -230,7 +239,7 @@ static void onEnter()
|
||||
static void onIdle()
|
||||
{
|
||||
if (isPowered()) {
|
||||
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
|
||||
// If we got here, we are in the wrong state - we should be in powered, let that state handle things
|
||||
powerFSM.trigger(EVENT_POWER_CONNECTED);
|
||||
}
|
||||
}
|
||||
@@ -242,11 +251,12 @@ static void screenPress()
|
||||
|
||||
static void bootEnter()
|
||||
{
|
||||
LOG_DEBUG("Enter state: BOOT");
|
||||
LOG_DEBUG("State: BOOT");
|
||||
}
|
||||
|
||||
State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN");
|
||||
State stateSDS(sdsEnter, NULL, NULL, "SDS");
|
||||
State stateLowBattSDS(lowBattSDSEnter, NULL, NULL, "SDS");
|
||||
State stateLS(lsEnter, lsIdle, lsExit, "LS");
|
||||
State stateNB(nbEnter, NULL, NULL, "NB");
|
||||
State stateDARK(darkEnter, NULL, NULL, "DARK");
|
||||
@@ -291,12 +301,12 @@ void PowerFSM_setup()
|
||||
"Press"); // Allow button to work while in serial API
|
||||
|
||||
// Handle critically low power battery by forcing deep sleep
|
||||
powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateLS, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateNB, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateDARK, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateBOOT, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateLS, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateNB, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateDARK, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateON, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
powerFSM.add_transition(&stateSERIAL, &stateLowBattSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
|
||||
|
||||
// Handle being told to power off
|
||||
powerFSM.add_transition(&stateBOOT, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
|
||||
@@ -371,9 +381,9 @@ void PowerFSM_setup()
|
||||
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
|
||||
#ifdef ARCH_ESP32
|
||||
// See: https://github.com/meshtastic/firmware/issues/1071
|
||||
// Don't add power saving transitions if we are a power saving tracker or sensor. Sleep will be initiatiated through the
|
||||
// modules
|
||||
if ((isRouter || config.power.is_power_saving) && !isTrackerOrSensor) {
|
||||
// Don't add power saving transitions if we are a power saving tracker or sensor or have Wifi enabled. Sleep will be initiated
|
||||
// through the modules
|
||||
if ((isRouter || config.power.is_power_saving) && !isWifiAvailable() && !isTrackerOrSensor) {
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
||||
Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
|
||||
"Min wake timeout");
|
||||
|
||||
@@ -13,17 +13,17 @@ void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
|
||||
{
|
||||
|
||||
if (reportType == TX_LOG) {
|
||||
LOG_DEBUG("Packet transmitted : %ums", airtime_ms);
|
||||
LOG_DEBUG("Packet TX: %ums", airtime_ms);
|
||||
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
|
||||
air_period_tx[0] = air_period_tx[0] + airtime_ms;
|
||||
|
||||
this->utilizationTX[this->getPeriodUtilHour()] = this->utilizationTX[this->getPeriodUtilHour()] + airtime_ms;
|
||||
} else if (reportType == RX_LOG) {
|
||||
LOG_DEBUG("Packet received : %ums", airtime_ms);
|
||||
LOG_DEBUG("Packet RX: %ums", airtime_ms);
|
||||
this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms;
|
||||
air_period_rx[0] = air_period_rx[0] + airtime_ms;
|
||||
} else if (reportType == RX_ALL_LOG) {
|
||||
LOG_DEBUG("Packet received (noise?) : %ums", airtime_ms);
|
||||
LOG_DEBUG("Packet RX (noise?) : %ums", airtime_ms);
|
||||
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ void AirTime::airtimeRotatePeriod()
|
||||
{
|
||||
|
||||
if (this->airtimes.lastPeriodIndex != this->currentPeriodIndex()) {
|
||||
LOG_DEBUG("Rotating airtimes to a new period = %u", this->currentPeriodIndex());
|
||||
LOG_DEBUG("Rotate airtimes to a new period = %u", this->currentPeriodIndex());
|
||||
|
||||
for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) {
|
||||
this->airtimes.periodTX[i + 1] = this->airtimes.periodTX[i];
|
||||
@@ -105,7 +105,6 @@ float AirTime::channelUtilizationPercent()
|
||||
uint32_t sum = 0;
|
||||
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
|
||||
sum += this->channelUtilization[i];
|
||||
// LOG_DEBUG("ChanUtilArray %u %u", i, this->channelUtilization[i]);
|
||||
}
|
||||
|
||||
return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100;
|
||||
@@ -127,7 +126,7 @@ bool AirTime::isTxAllowedChannelUtil(bool polite)
|
||||
if (channelUtilizationPercent() < percentage) {
|
||||
return true;
|
||||
} else {
|
||||
LOG_WARN("Channel utilization is >%d percent. Skipping this opportunity to send.", percentage);
|
||||
LOG_WARN("Ch. util >%d%%. Skip send", percentage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -138,8 +137,7 @@ bool AirTime::isTxAllowedAirUtil()
|
||||
if (utilizationTXPercent() < myRegion->dutyCycle * polite_duty_cycle_percent / 100) {
|
||||
return true;
|
||||
} else {
|
||||
LOG_WARN("Tx air utilization is >%f percent. Skipping this opportunity to send.",
|
||||
myRegion->dutyCycle * polite_duty_cycle_percent / 100);
|
||||
LOG_WARN("TX air util. >%f%%. Skip send", myRegion->dutyCycle * polite_duty_cycle_percent / 100);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -208,14 +206,5 @@ int32_t AirTime::runOnce()
|
||||
this->utilizationTX[utilPeriodTX] = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
LOG_DEBUG("utilPeriodTX %d TX Airtime %3.2f%", utilPeriodTX, airTime->utilizationTXPercent());
|
||||
for (uint32_t i = 0; i < MINUTES_IN_HOUR; i++) {
|
||||
LOG_DEBUG(
|
||||
"%d,", this->utilizationTX[i]
|
||||
);
|
||||
}
|
||||
LOG_DEBUG("");
|
||||
*/
|
||||
return (1000 * 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ IRAM_ATTR bool NotifiedWorkerThread::notifyCommon(uint32_t v, bool overwrite)
|
||||
|
||||
notification = v;
|
||||
if (debugNotification) {
|
||||
LOG_DEBUG("setting notification %d", v);
|
||||
LOG_DEBUG("Set notification %d", v);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (debugNotification) {
|
||||
LOG_DEBUG("dropping notification %d", v);
|
||||
LOG_DEBUG("Drop notification %d", v);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ bool NotifiedWorkerThread::notifyLater(uint32_t delay, uint32_t v, bool overwrit
|
||||
if (didIt) { // If we didn't already have something queued, override the delay to be larger
|
||||
setIntervalFromNow(delay); // a new version of setInterval relative to the current time
|
||||
if (debugNotification) {
|
||||
LOG_DEBUG("delaying notification %u", delay);
|
||||
LOG_DEBUG("Delay notification %u", delay);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,13 +148,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define NAU7802_ADDR 0x2A
|
||||
#define MAX30102_ADDR 0x57
|
||||
#define MLX90614_ADDR_DEF 0x5A
|
||||
#define CGRADSENS_ADDR 0x66
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ACCELEROMETER
|
||||
// -----------------------------------------------------------------------------
|
||||
#define MPU6050_ADDR 0x68
|
||||
#define STK8BXX_ADR 0x18
|
||||
#define LIS3DH_ADR 0x18
|
||||
#define STK8BXX_ADDR 0x18
|
||||
#define LIS3DH_ADDR 0x18
|
||||
#define LIS3DH_ADDR_ALT 0x19
|
||||
#define BMA423_ADDR 0x19
|
||||
#define LSM6DS3_ADDR 0x6A
|
||||
#define BMX160_ADDR 0x69
|
||||
@@ -169,7 +171,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// -----------------------------------------------------------------------------
|
||||
// Security
|
||||
// -----------------------------------------------------------------------------
|
||||
#define ATECC608B_ADDR 0x35
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// IO Expander
|
||||
@@ -207,6 +208,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef GPS_BAUDRATE
|
||||
#define GPS_BAUDRATE 9600
|
||||
#define GPS_BAUDRATE_FIXED 0
|
||||
#else
|
||||
#define GPS_BAUDRATE_FIXED 1
|
||||
#endif
|
||||
|
||||
/* Step #2: follow with defines common to the architecture;
|
||||
@@ -246,6 +250,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef HAS_SCREEN
|
||||
#define HAS_SCREEN 0
|
||||
#endif
|
||||
#ifndef HAS_TFT
|
||||
#define HAS_TFT 0
|
||||
#endif
|
||||
#ifndef HAS_WIRE
|
||||
#define HAS_WIRE 0
|
||||
#endif
|
||||
@@ -308,6 +315,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MESHTASTIC_EXCLUDE_AUDIO 1
|
||||
#define MESHTASTIC_EXCLUDE_DETECTIONSENSOR 1
|
||||
#define MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR 1
|
||||
#define MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY 1
|
||||
#define MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION 1
|
||||
#define MESHTASTIC_EXCLUDE_PAXCOUNTER 1
|
||||
#define MESHTASTIC_EXCLUDE_POWER_TELEMETRY 1
|
||||
|
||||
@@ -12,7 +12,6 @@ class ScanI2C
|
||||
SCREEN_SH1106,
|
||||
SCREEN_UNKNOWN, // has the same address as the two above but does not respond to the same commands
|
||||
SCREEN_ST7567,
|
||||
ATECC608B,
|
||||
RTC_RV3028,
|
||||
RTC_PCF8563,
|
||||
CARDKB,
|
||||
@@ -63,7 +62,10 @@ class ScanI2C
|
||||
ICM20948,
|
||||
MAX30102,
|
||||
TPS65233,
|
||||
MPR121KB
|
||||
MPR121KB,
|
||||
CGRADSENS,
|
||||
INA226,
|
||||
NXP_SE050,
|
||||
} DeviceType;
|
||||
|
||||
// typedef uint8_t DeviceAddress;
|
||||
@@ -127,4 +129,4 @@ class ScanI2C
|
||||
|
||||
private:
|
||||
bool shouldSuppressScreen = false;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "linux/LinuxHardwareI2C.h"
|
||||
#endif
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include "main.h" // atecc
|
||||
#include "meshUtils.h" // vformat
|
||||
#endif
|
||||
|
||||
@@ -72,10 +71,10 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
|
||||
r &= 0x0f;
|
||||
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
LOG_INFO("sh1106 display found");
|
||||
logFoundDevice("SH1106", (uint8_t)addr.address);
|
||||
o_probe = SCREEN_SH1106; // SH1106
|
||||
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
|
||||
LOG_INFO("ssd1306 display found");
|
||||
logFoundDevice("SSD1306", (uint8_t)addr.address);
|
||||
o_probe = SCREEN_SSD1306; // SSD1306
|
||||
}
|
||||
c++;
|
||||
@@ -84,40 +83,6 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
|
||||
|
||||
return o_probe;
|
||||
}
|
||||
void ScanI2CTwoWire::printATECCInfo() const
|
||||
{
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
atecc.readConfigZone(false);
|
||||
|
||||
std::string atecc_numbers = "ATECC608B Serial Number: ";
|
||||
for (int i = 0; i < 9; i++) {
|
||||
atecc_numbers += vformat("%02x", atecc.serialNumber[i]);
|
||||
}
|
||||
|
||||
atecc_numbers += ", Rev Number: ";
|
||||
for (int i = 0; i < 4; i++) {
|
||||
atecc_numbers += vformat("%02x", atecc.revisionNumber[i]);
|
||||
}
|
||||
LOG_DEBUG(atecc_numbers.c_str());
|
||||
|
||||
LOG_DEBUG("ATECC608B Config %s, Data %s, Slot 0 %s", atecc.configLockStatus ? "Locked" : "Unlocked",
|
||||
atecc.dataOTPLockStatus ? "Locked" : "Unlocked", atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||
|
||||
std::string atecc_publickey = "";
|
||||
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
|
||||
if (atecc.generatePublicKey() == false) {
|
||||
atecc_publickey += "ATECC608B Error generating public key";
|
||||
} else {
|
||||
atecc_publickey += "ATECC608B Public Key: ";
|
||||
for (int i = 0; i < 64; i++) {
|
||||
atecc_publickey += vformat("%02x", atecc.publicKey64Bytes[i]);
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(atecc_publickey.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation ®isterLocation,
|
||||
ScanI2CTwoWire::ResponseWidth responseWidth) const
|
||||
{
|
||||
@@ -129,7 +94,6 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
|
||||
i2cBus->endTransmission();
|
||||
delay(20);
|
||||
i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth);
|
||||
LOG_DEBUG("Wire.available() = %d", i2cBus->available());
|
||||
if (i2cBus->available() == 2) {
|
||||
// Read MSB, then LSB
|
||||
value = (uint16_t)i2cBus->read() << 8;
|
||||
@@ -142,7 +106,7 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
|
||||
|
||||
#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
|
||||
case ADDR: \
|
||||
LOG_INFO(__VA_ARGS__); \
|
||||
logFoundDevice(__VA_ARGS__); \
|
||||
type = T; \
|
||||
break;
|
||||
|
||||
@@ -150,7 +114,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
{
|
||||
concurrency::LockGuard guard((concurrency::Lock *)&lock);
|
||||
|
||||
LOG_DEBUG("Scanning for I2C devices on port %d", port);
|
||||
LOG_DEBUG("Scan for I2C devices on port %d", port);
|
||||
|
||||
uint8_t err;
|
||||
|
||||
@@ -184,50 +148,36 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
|
||||
for (addr.address = 8; addr.address < 120; addr.address++) {
|
||||
if (asize != 0) {
|
||||
if (!in_array(address, asize, addr.address))
|
||||
if (!in_array(address, asize, (uint8_t)addr.address))
|
||||
continue;
|
||||
LOG_DEBUG("Scanning address 0x%x", addr.address);
|
||||
LOG_DEBUG("Scan address 0x%x", (uint8_t)addr.address);
|
||||
}
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
#ifdef ARCH_PORTDUINO
|
||||
if (i2cBus->read() != -1)
|
||||
err = 0;
|
||||
else
|
||||
err = 2;
|
||||
if ((addr.address >= 0x30 && addr.address <= 0x37) || (addr.address >= 0x50 && addr.address <= 0x5F)) {
|
||||
if (i2cBus->read() != -1)
|
||||
err = 0;
|
||||
} else {
|
||||
err = i2cBus->writeQuick((uint8_t)0);
|
||||
}
|
||||
if (err != 0)
|
||||
err = 2;
|
||||
#else
|
||||
err = i2cBus->endTransmission();
|
||||
#endif
|
||||
type = NONE;
|
||||
if (err == 0) {
|
||||
LOG_DEBUG("I2C device found at address 0x%x", addr.address);
|
||||
|
||||
switch (addr.address) {
|
||||
case SSD1306_ADDRESS:
|
||||
type = probeOLED(addr);
|
||||
break;
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
case ATECC608B_ADDR:
|
||||
#ifdef RP2040_SLOW_CLOCK
|
||||
if (atecc.begin(addr.address, Wire, Serial2) == true)
|
||||
#else
|
||||
if (atecc.begin(addr.address) == true)
|
||||
#endif
|
||||
|
||||
{
|
||||
LOG_INFO("ATECC608B initialized");
|
||||
} else {
|
||||
LOG_WARN("ATECC608B initialization failed");
|
||||
}
|
||||
printATECCInfo();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef RV3028_RTC
|
||||
case RV3028_RTC:
|
||||
// foundDevices[addr] = RTC_RV3028;
|
||||
type = RTC_RV3028;
|
||||
LOG_INFO("RV3028 RTC found");
|
||||
logFoundDevice("RV3028", (uint8_t)addr.address);
|
||||
rtc.initI2C(*i2cBus);
|
||||
rtc.writeToRegister(0x35, 0x07); // no Clkout
|
||||
rtc.writeToRegister(0x37, 0xB4);
|
||||
@@ -235,7 +185,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
#endif
|
||||
|
||||
#ifdef PCF8563_RTC
|
||||
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563 RTC found")
|
||||
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563", (uint8_t)addr.address)
|
||||
#endif
|
||||
|
||||
case CARDKB_ADDR:
|
||||
@@ -243,50 +193,50 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);
|
||||
if (registerValue == 0x02) {
|
||||
// KEYPAD_VERSION
|
||||
LOG_INFO("RAK14004 found");
|
||||
logFoundDevice("RAK14004", (uint8_t)addr.address);
|
||||
type = RAK14004;
|
||||
} else {
|
||||
LOG_INFO("m5 cardKB found");
|
||||
logFoundDevice("M5 cardKB", (uint8_t)addr.address);
|
||||
type = CARDKB;
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found");
|
||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found");
|
||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
|
||||
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found");
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address);
|
||||
#ifdef HAS_NCP5623
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found");
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
|
||||
#endif
|
||||
#ifdef HAS_PMU
|
||||
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "axp192/axp2101 PMU found")
|
||||
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "AXP192/AXP2101", (uint8_t)addr.address)
|
||||
#endif
|
||||
case BME_ADDR:
|
||||
case BME_ADDR_ALTERNATE:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
|
||||
switch (registerValue) {
|
||||
case 0x61:
|
||||
LOG_INFO("BME-680 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BME680", (uint8_t)addr.address);
|
||||
type = BME_680;
|
||||
break;
|
||||
case 0x60:
|
||||
LOG_INFO("BME-280 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BME280", (uint8_t)addr.address);
|
||||
type = BME_280;
|
||||
break;
|
||||
case 0x55:
|
||||
LOG_INFO("BMP-085 or BMP-180 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BMP085/BMP180", (uint8_t)addr.address);
|
||||
type = BMP_085;
|
||||
break;
|
||||
default:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); // GET_ID
|
||||
switch (registerValue) {
|
||||
case 0x50: // BMP-388 should be 0x50
|
||||
LOG_INFO("BMP-388 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BMP-388", (uint8_t)addr.address);
|
||||
type = BMP_3XX;
|
||||
break;
|
||||
case 0x58: // BMP-280 should be 0x58
|
||||
default:
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("BMP-280", (uint8_t)addr.address);
|
||||
type = BMP_280;
|
||||
break;
|
||||
}
|
||||
@@ -295,7 +245,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
break;
|
||||
#ifndef HAS_NCP5623
|
||||
case AHT10_ADDR:
|
||||
LOG_INFO("AHT10 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("AHT10", (uint8_t)addr.address);
|
||||
type = AHT10;
|
||||
break;
|
||||
#endif
|
||||
@@ -305,41 +255,65 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA260 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
type = INA260;
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFF), 2);
|
||||
LOG_DEBUG("Register DIE_UID: 0x%x", registerValue);
|
||||
|
||||
if (registerValue == 0x2260) {
|
||||
logFoundDevice("INA226", (uint8_t)addr.address);
|
||||
type = INA226;
|
||||
} else {
|
||||
logFoundDevice("INA260", (uint8_t)addr.address);
|
||||
type = INA260;
|
||||
}
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
LOG_INFO("INA219 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("INA219", (uint8_t)addr.address);
|
||||
type = INA219;
|
||||
}
|
||||
break;
|
||||
case INA3221_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x", registerValue);
|
||||
LOG_DEBUG("Register MFG_UID FE: 0x%x", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA3221 sensor found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("INA3221", (uint8_t)addr.address);
|
||||
type = INA3221;
|
||||
} else {
|
||||
LOG_INFO("DFRobot Lark weather station found at address 0x%x", (uint8_t)addr.address);
|
||||
type = DFROBOT_LARK;
|
||||
/* check the first 2 bytes of the 6 byte response register
|
||||
LARK FW 1.0 should return:
|
||||
RESPONSE_STATUS STATUS_SUCCESS (0x53)
|
||||
RESPONSE_CMD CMD_GET_VERSION (0x05)
|
||||
RESPONSE_LEN_L 0x02
|
||||
RESPONSE_LEN_H 0x00
|
||||
RESPONSE_PAYLOAD 0x01
|
||||
RESPONSE_PAYLOAD+1 0x00
|
||||
*/
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 2);
|
||||
LOG_DEBUG("Register MFG_UID 05: 0x%x", registerValue);
|
||||
if (registerValue == 0x5305) {
|
||||
logFoundDevice("DFRobot Lark", (uint8_t)addr.address);
|
||||
type = DFROBOT_LARK;
|
||||
}
|
||||
// else: probably a RAK12500/UBLOX GPS on I2C
|
||||
}
|
||||
break;
|
||||
case MCP9808_ADDR:
|
||||
// We need to check for STK8BAXX first, since register 0x07 is new data flag for the z-axis and can produce some
|
||||
// weird result. and register 0x00 doesn't seems to be colliding with MCP9808 and LIS3DH chips.
|
||||
{
|
||||
#ifdef HAS_STK8XXX
|
||||
// Check register 0x00 for 0x8700 response to ID STK8BA53 chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 2);
|
||||
if (registerValue == 0x8700) {
|
||||
type = STK8BAXX;
|
||||
LOG_INFO("STK8BAXX accelerometer found");
|
||||
logFoundDevice("STK8BAXX", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check register 0x07 for 0x0400 response to ID MCP9808 chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||
if (registerValue == 0x0400) {
|
||||
type = MCP9808;
|
||||
LOG_INFO("MCP9808 sensor found");
|
||||
logFoundDevice("MCP9808", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -347,7 +321,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
|
||||
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
|
||||
type = LIS3DH;
|
||||
LOG_INFO("LIS3DH accelerometer found");
|
||||
logFoundDevice("LIS3DH", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -355,83 +329,91 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2);
|
||||
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0xe9c) {
|
||||
type = SHT4X;
|
||||
LOG_INFO("SHT4X sensor found");
|
||||
logFoundDevice("SHT4X", (uint8_t)addr.address);
|
||||
} else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) {
|
||||
type = OPT3001;
|
||||
LOG_INFO("OPT3001 light sensor found");
|
||||
logFoundDevice("OPT3001", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = SHT31;
|
||||
LOG_INFO("SHT31 sensor found");
|
||||
logFoundDevice("SHT31", (uint8_t)addr.address);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found")
|
||||
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3", (uint8_t)addr.address)
|
||||
case RCWL9620_ADDR:
|
||||
// get MAX30102 PARTID
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFF), 1);
|
||||
if (registerValue == 0x15) {
|
||||
type = MAX30102;
|
||||
LOG_INFO("MAX30102 Health sensor found");
|
||||
logFoundDevice("MAX30102", (uint8_t)addr.address);
|
||||
break;
|
||||
} else {
|
||||
type = RCWL9620;
|
||||
LOG_INFO("RCWL9620 sensor found");
|
||||
logFoundDevice("RCWL9620", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
|
||||
case LPS22HB_ADDR_ALT:
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found")
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found")
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB", (uint8_t)addr.address)
|
||||
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310", (uint8_t)addr.address)
|
||||
|
||||
case QMI8658_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0A), 1); // get ID
|
||||
if (registerValue == 0xC0) {
|
||||
type = BQ24295;
|
||||
LOG_INFO("BQ24295 PMU found");
|
||||
logFoundDevice("BQ24295", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID
|
||||
if (registerValue == 0x6A) {
|
||||
type = LSM6DS3;
|
||||
LOG_INFO("LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address);
|
||||
logFoundDevice("LSM6DS3", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = QMI8658;
|
||||
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found");
|
||||
logFoundDevice("QMI8658", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found")
|
||||
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found")
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L", (uint8_t)addr.address)
|
||||
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L", (uint8_t)addr.address)
|
||||
#ifdef HAS_QMA6100P
|
||||
SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P accelerometer found")
|
||||
SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P", (uint8_t)addr.address)
|
||||
#else
|
||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found")
|
||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031", (uint8_t)addr.address)
|
||||
#endif
|
||||
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found");
|
||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found");
|
||||
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found");
|
||||
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found");
|
||||
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591 light sensor found");
|
||||
SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001 light sensor found");
|
||||
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632 IR temp sensor found");
|
||||
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802 based scale found");
|
||||
SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U touchscreen found");
|
||||
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048 lipo fuel gauge found");
|
||||
case BMA423_ADDR: // this can also be LIS3DH_ADDR_ALT
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
|
||||
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
|
||||
type = LIS3DH;
|
||||
logFoundDevice("LIS3DH", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = BMA423;
|
||||
logFoundDevice("BMA423", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
|
||||
#ifdef HAS_TPS65233
|
||||
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233 BIAS-T found");
|
||||
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
|
||||
#endif
|
||||
|
||||
case MLX90614_ADDR_DEF:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0e), 1);
|
||||
if (registerValue == 0x5a) {
|
||||
type = MLX90614;
|
||||
LOG_INFO("MLX90614 IR temp sensor found");
|
||||
logFoundDevice("MLX90614", (uint8_t)addr.address);
|
||||
} else {
|
||||
type = MPR121KB;
|
||||
LOG_INFO("MPR121KB keyboard found");
|
||||
logFoundDevice("MPR121KB", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -440,24 +422,57 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
||||
if (registerValue == 0xEA) {
|
||||
type = ICM20948;
|
||||
LOG_INFO("ICM20948 9-dof motion processor found");
|
||||
logFoundDevice("ICM20948", (uint8_t)addr.address);
|
||||
break;
|
||||
} else if (addr.address == BMX160_ADDR) {
|
||||
type = BMX160;
|
||||
LOG_INFO("BMX160 accelerometer found");
|
||||
logFoundDevice("BMX160", (uint8_t)addr.address);
|
||||
break;
|
||||
} else {
|
||||
type = MPU6050;
|
||||
LOG_INFO("MPU6050 accelerometer found");
|
||||
logFoundDevice("MPU6050", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CGRADSENS_ADDR:
|
||||
// Register 0x00 of the RadSens sensor contains is product identifier 0x7D
|
||||
// Undocumented, but some devices return a product identifier of 0x7A
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
||||
if (registerValue == 0x7D || registerValue == 0x7A) {
|
||||
type = CGRADSENS;
|
||||
logFoundDevice("ClimateGuard RadSens", (uint8_t)addr.address);
|
||||
break;
|
||||
} else {
|
||||
LOG_DEBUG("Unexpected Device ID for RadSense: addr=0x%x id=0x%x", CGRADSENS_ADDR, registerValue);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x48: {
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
uint8_t getInfo[] = {0x5A, 0xC0, 0x00, 0xFF, 0xFC};
|
||||
uint8_t expectedInfo[] = {0xa5, 0xE0, 0x00, 0x3F, 0x19};
|
||||
uint8_t info[5];
|
||||
size_t len = 0;
|
||||
i2cBus->write(getInfo, 5);
|
||||
i2cBus->endTransmission();
|
||||
len = i2cBus->readBytes(info, 5);
|
||||
if (len == 5 && memcmp(expectedInfo, info, len) == 0) {
|
||||
LOG_INFO("NXP SE050 crypto chip found");
|
||||
type = NXP_SE050;
|
||||
|
||||
} else {
|
||||
LOG_INFO("FT6336U touchscreen found");
|
||||
type = FT6336U;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_INFO("Device found at address 0x%x was not able to be enumerated", addr.address);
|
||||
LOG_INFO("Device found at address 0x%x was not able to be enumerated", (uint8_t)addr.address);
|
||||
}
|
||||
} else if (err == 4) {
|
||||
LOG_ERROR("Unknown error at address 0x%x", addr.address);
|
||||
LOG_ERROR("Unknown error at address 0x%x", (uint8_t)addr.address);
|
||||
}
|
||||
|
||||
// Check if a type was found for the enumerated device - save, if so
|
||||
@@ -490,4 +505,9 @@ size_t ScanI2CTwoWire::countDevices() const
|
||||
{
|
||||
return foundDevices.size();
|
||||
}
|
||||
#endif
|
||||
|
||||
void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address)
|
||||
{
|
||||
LOG_INFO("%s found at address 0x%x", device, address);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -53,10 +53,10 @@ class ScanI2CTwoWire : public ScanI2C
|
||||
|
||||
concurrency::Lock lock;
|
||||
|
||||
void printATECCInfo() const;
|
||||
|
||||
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
|
||||
|
||||
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
|
||||
|
||||
static void logFoundDevice(const char *device, uint8_t address);
|
||||
};
|
||||
#endif
|
||||
317
src/gps/GPS.cpp
317
src/gps/GPS.cpp
@@ -28,29 +28,43 @@
|
||||
#define GPS_RESET_MODE HIGH
|
||||
#endif
|
||||
|
||||
// Not all platforms have std::size().
|
||||
template <typename T, std::size_t N> std::size_t array_count(const T (&)[N])
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
|
||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
#elif defined(ARCH_RP2040)
|
||||
SerialUART *GPS::_serial_gps = &Serial1;
|
||||
#else
|
||||
HardwareSerial *GPS::_serial_gps = NULL;
|
||||
HardwareSerial *GPS::_serial_gps = nullptr;
|
||||
#endif
|
||||
|
||||
GPS *gps = nullptr;
|
||||
|
||||
GPSUpdateScheduling scheduling;
|
||||
static const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
|
||||
|
||||
static GPSUpdateScheduling scheduling;
|
||||
|
||||
/// Multiple GPS instances might use the same serial port (in sequence), but we can
|
||||
/// only init that port once.
|
||||
static bool didSerialInit;
|
||||
|
||||
struct uBloxGnssModelInfo info;
|
||||
uint8_t uBloxProtocolVersion;
|
||||
static struct uBloxGnssModelInfo {
|
||||
char swVersion[30];
|
||||
char hwVersion[10];
|
||||
uint8_t extensionNo;
|
||||
char extension[10][30];
|
||||
uint8_t protocol_version;
|
||||
} ublox_info;
|
||||
|
||||
#define GPS_SOL_EXPIRY_MS 5000 // in millis. give 1 second time to combine different sentences. NMEA Frequency isn't higher anyway
|
||||
#define NMEA_MSG_GXGSA "GNGSA" // GSA message (GPGSA, GNGSA etc)
|
||||
|
||||
// For logging
|
||||
const char *getGPSPowerStateString(GPSPowerState state)
|
||||
static const char *getGPSPowerStateString(GPSPowerState state)
|
||||
{
|
||||
switch (state) {
|
||||
case GPS_ACTIVE:
|
||||
@@ -69,7 +83,7 @@ const char *getGPSPowerStateString(GPSPowerState state)
|
||||
}
|
||||
}
|
||||
|
||||
void GPS::UBXChecksum(uint8_t *message, size_t length)
|
||||
static void UBXChecksum(uint8_t *message, size_t length)
|
||||
{
|
||||
uint8_t CK_A = 0, CK_B = 0;
|
||||
|
||||
@@ -85,7 +99,7 @@ void GPS::UBXChecksum(uint8_t *message, size_t length)
|
||||
}
|
||||
|
||||
// Calculate the checksum for a CAS packet
|
||||
void GPS::CASChecksum(uint8_t *message, size_t length)
|
||||
static void CASChecksum(uint8_t *message, size_t length)
|
||||
{
|
||||
uint32_t cksum = ((uint32_t)message[5] << 24); // Message ID
|
||||
cksum += ((uint32_t)message[4]) << 16; // Class
|
||||
@@ -156,7 +170,7 @@ uint8_t GPS::makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_siz
|
||||
CASChecksum(UBXscratch, (payload_size + 10));
|
||||
|
||||
#if defined(GPS_DEBUG) && defined(DEBUG_PORT)
|
||||
LOG_DEBUG("Constructed CAS packet: ");
|
||||
LOG_DEBUG("CAS packet: ");
|
||||
DEBUG_PORT.hexDump(MESHTASTIC_LOG_LEVEL_DEBUG, UBXscratch, payload_size + 10);
|
||||
#endif
|
||||
return (payload_size + 10);
|
||||
@@ -237,7 +251,7 @@ GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMilli
|
||||
// Check for an ACK-ACK for the specified class and message id
|
||||
if ((msg_cls == 0x05) && (msg_msg_id == 0x01) && payload_cls == class_id && payload_msg == msg_id) {
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_INFO("Got ACK for class %02X message %02X in %d millis.", class_id, msg_id, millis() - startTime);
|
||||
LOG_INFO("Got ACK for class %02X message %02X in %dms", class_id, msg_id, millis() - startTime);
|
||||
#endif
|
||||
return GNSS_RESPONSE_OK;
|
||||
}
|
||||
@@ -245,7 +259,7 @@ GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMilli
|
||||
// Check for an ACK-NACK for the specified class and message id
|
||||
if ((msg_cls == 0x05) && (msg_msg_id == 0x00) && payload_cls == class_id && payload_msg == msg_id) {
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_WARN("Got NACK for class %02X message %02X in %d millis.", class_id, msg_id, millis() - startTime);
|
||||
LOG_WARN("Got NACK for class %02X message %02X in %dms", class_id, msg_id, millis() - startTime);
|
||||
#endif
|
||||
return GNSS_RESPONSE_NAK;
|
||||
}
|
||||
@@ -286,8 +300,7 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
|
||||
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
|
||||
if (ack > 9) {
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("");
|
||||
LOG_INFO("Got ACK for class %02X message %02X in %d millis.", class_id, msg_id, millis() - startTime);
|
||||
LOG_INFO("Got ACK for class %02X message %02X in %dms", class_id, msg_id, millis() - startTime);
|
||||
#endif
|
||||
return GNSS_RESPONSE_OK; // ACK received
|
||||
}
|
||||
@@ -397,8 +410,7 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
||||
} else {
|
||||
// return payload length
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_INFO("Got ACK for class %02X message %02X in %d millis.", requestedClass, requestedID,
|
||||
millis() - startTime);
|
||||
LOG_INFO("Got ACK for class %02X message %02X in %dms", requestedClass, requestedID, millis() - startTime);
|
||||
#endif
|
||||
return needRead;
|
||||
}
|
||||
@@ -409,36 +421,57 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
||||
}
|
||||
}
|
||||
}
|
||||
// LOG_WARN("No response for class %02X message %02X", requestedClass, requestedID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if GPS_BAUDRATE_FIXED
|
||||
// if GPS_BAUDRATE is specified in variant, only try that.
|
||||
static const int serialSpeeds[1] = {GPS_BAUDRATE};
|
||||
static const int rareSerialSpeeds[1] = {GPS_BAUDRATE};
|
||||
#else
|
||||
static const int serialSpeeds[3] = {9600, 115200, 38400};
|
||||
static const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Setup the GPS based on the model detected.
|
||||
* We detect the GPS by cycling through a set of baud rates, first common then rare.
|
||||
* For each baud rate, we run GPS::Probe to send commands and match the responses
|
||||
* to known GPS responses.
|
||||
* @retval Whether setup reached the end of its potential to configure the GPS.
|
||||
*/
|
||||
bool GPS::setup()
|
||||
{
|
||||
|
||||
if (!didSerialInit) {
|
||||
int msglen = 0;
|
||||
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
|
||||
// if GPS_BAUDRATE is specified in variant (i.e. not 9600), skip to the specified rate.
|
||||
if (speedSelect == 0 && GPS_BAUDRATE != serialSpeeds[speedSelect]) {
|
||||
speedSelect = std::find(serialSpeeds, std::end(serialSpeeds), GPS_BAUDRATE) - serialSpeeds;
|
||||
if (probeTries < 2) {
|
||||
LOG_DEBUG("Probe for GPS at %d", serialSpeeds[speedSelect]);
|
||||
gnssModel = probe(serialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (++speedSelect == array_count(serialSpeeds)) {
|
||||
speedSelect = 0;
|
||||
++probeTries;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG("Probing for GPS at %d", serialSpeeds[speedSelect]);
|
||||
gnssModel = probe(serialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (++speedSelect == sizeof(serialSpeeds) / sizeof(int)) {
|
||||
speedSelect = 0;
|
||||
if (--probeTries == 0) {
|
||||
LOG_WARN("Giving up on GPS probe and setting to 9600.");
|
||||
// Rare Serial Speeds
|
||||
if (probeTries == 2) {
|
||||
LOG_DEBUG("Probe for GPS at %d", rareSerialSpeeds[speedSelect]);
|
||||
gnssModel = probe(rareSerialSpeeds[speedSelect]);
|
||||
if (gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
if (++speedSelect == array_count(rareSerialSpeeds)) {
|
||||
LOG_WARN("Give up on GPS probe and set to %d", GPS_BAUDRATE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (gnssModel != GNSS_MODEL_UNKNOWN) {
|
||||
setConnected();
|
||||
} else {
|
||||
gnssModel = GNSS_MODEL_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gnssModel == GNSS_MODEL_MTK) {
|
||||
@@ -493,14 +526,14 @@ bool GPS::setup()
|
||||
msglen = makeCASPacket(0x06, 0x07, sizeof(_message_CAS_CFG_NAVX_CONF), _message_CAS_CFG_NAVX_CONF);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACKCas(0x06, 0x07, 250) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("ATGM336H - Could not set Configuration");
|
||||
LOG_WARN("ATGM336H: Could not set Config");
|
||||
}
|
||||
|
||||
// Set the update frequence to 1Hz
|
||||
msglen = makeCASPacket(0x06, 0x04, sizeof(_message_CAS_CFG_RATE_1HZ), _message_CAS_CFG_RATE_1HZ);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACKCas(0x06, 0x04, 250) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("ATGM336H - Could not set Update Frequency");
|
||||
LOG_WARN("ATGM336H: Could not set Update Frequency");
|
||||
}
|
||||
|
||||
// Set the NEMA output messages
|
||||
@@ -512,7 +545,7 @@ bool GPS::setup()
|
||||
msglen = makeCASPacket(0x06, 0x01, sizeof(cas_cfg_msg_packet), cas_cfg_msg_packet);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACKCas(0x06, 0x01, 250) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("ATGM336H - Could not enable NMEA MSG: %d", fields[i]);
|
||||
LOG_WARN("ATGM336H: Could not enable NMEA MSG: %d", fields[i]);
|
||||
}
|
||||
}
|
||||
} else if (gnssModel == GNSS_MODEL_UC6580) {
|
||||
@@ -565,20 +598,20 @@ bool GPS::setup()
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "enable NMEA GGA", 500);
|
||||
|
||||
clearBuffer();
|
||||
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_ECO, "enable powersaving ECO mode for Neo-6", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_ECO, "enable powersave ECO mode for Neo-6", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_AID, "disable UBX-AID", 500);
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to save GNSS module configuration.");
|
||||
LOG_WARN("Unable to save GNSS module config");
|
||||
} else {
|
||||
LOG_INFO("GNSS module configuration saved!");
|
||||
LOG_INFO("GNSS module config saved!");
|
||||
}
|
||||
} else if (IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9)) {
|
||||
if (gnssModel == GNSS_MODEL_UBLOX7) {
|
||||
LOG_DEBUG("Setting GPS+SBAS");
|
||||
LOG_DEBUG("Set GPS+SBAS");
|
||||
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
} else { // 8,9
|
||||
@@ -588,12 +621,12 @@ bool GPS::setup()
|
||||
|
||||
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
|
||||
// It's not critical if the module doesn't acknowledge this configuration.
|
||||
LOG_INFO("reconfigure GNSS - defaults maintained. Is this module GPS-only?");
|
||||
LOG_DEBUG("reconfigure GNSS - defaults maintained. Is this module GPS-only?");
|
||||
} else {
|
||||
if (gnssModel == GNSS_MODEL_UBLOX7) {
|
||||
LOG_INFO("GNSS configured for GPS+SBAS.");
|
||||
LOG_INFO("GPS+SBAS configured");
|
||||
} else { // 8,9
|
||||
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS+Galileo.");
|
||||
LOG_INFO("GPS+SBAS+GLONASS+Galileo configured");
|
||||
}
|
||||
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
|
||||
// commands for the M8 it tends to be more... 1 sec should be enough ;>)
|
||||
@@ -623,10 +656,10 @@ bool GPS::setup()
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "enable NMEA RMC", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "enable NMEA GGA", 500);
|
||||
|
||||
if (uBloxProtocolVersion >= 18) {
|
||||
if (ublox_info.protocol_version >= 18) {
|
||||
clearBuffer();
|
||||
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "enable powersaving for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "enable powersave for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500);
|
||||
|
||||
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
|
||||
if (gnssModel == GNSS_MODEL_UBLOX8) {
|
||||
@@ -634,14 +667,14 @@ bool GPS::setup()
|
||||
SEND_UBX_PACKET(0x06, 0x17, _message_NMEA, "enable NMEA 4.10", 500);
|
||||
}
|
||||
} else {
|
||||
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_PSM, "enable powersaving mode for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_PSM, "enable powersave mode for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500);
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to save GNSS module configuration.");
|
||||
LOG_WARN("Unable to save GNSS module config");
|
||||
} else {
|
||||
LOG_INFO("GNSS module configuration saved!");
|
||||
}
|
||||
@@ -661,13 +694,13 @@ bool GPS::setup()
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_TXT_INFO_BBR, "disable Info messages for M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
// Do M10 configuration for Power Management.
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_RAM, "enable powersaving for M10 GPS RAM", 300);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_RAM, "enable powersave for M10 GPS RAM", 300);
|
||||
delay(750);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_BBR, "enable powersaving for M10 GPS BBR", 300);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_BBR, "enable powersave for M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_RAM, "enable Jamming detection M10 GPS RAM", 300);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_RAM, "enable jam detection M10 GPS RAM", 300);
|
||||
delay(750);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_BBR, "enable Jamming detection M10 GPS BBR", 300);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_BBR, "enable jam detection M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
// Here is where the init commands should go to do further M10 initialization.
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_RAM, "disable SBAS M10 GPS RAM", 300);
|
||||
@@ -675,7 +708,8 @@ bool GPS::setup()
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_BBR, "disable SBAS M10 GPS BBR", 300);
|
||||
delay(750); // will cause a receiver restart so wait a bit
|
||||
|
||||
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic sleep.
|
||||
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic
|
||||
// sleep.
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ENABLE_NMEA_BBR, "enable messages for M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
// Next enable wanted NMEA messages in RAM layer
|
||||
@@ -688,7 +722,7 @@ bool GPS::setup()
|
||||
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE_10), _message_SAVE_10);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to save GNSS module configuration.");
|
||||
LOG_WARN("Unable to save GNSS module config");
|
||||
} else {
|
||||
LOG_INFO("GNSS module configuration saved!");
|
||||
}
|
||||
@@ -706,13 +740,14 @@ GPS::~GPS()
|
||||
// we really should unregister our sleep observer
|
||||
notifyDeepSleepObserver.unobserve(¬ifyDeepSleep);
|
||||
}
|
||||
|
||||
// Put the GPS hardware into a specified state
|
||||
void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
|
||||
{
|
||||
// Update the stored GPSPowerstate, and create local copies
|
||||
GPSPowerState oldState = powerState;
|
||||
powerState = newState;
|
||||
LOG_INFO("GPS power state moving from %s to %s", getGPSPowerStateString(oldState), getGPSPowerStateString(newState));
|
||||
LOG_INFO("GPS power state move from %s to %s", getGPSPowerStateString(oldState), getGPSPowerStateString(newState));
|
||||
|
||||
#ifdef HELTEC_MESH_NODE_T114
|
||||
if ((oldState == GPS_OFF || oldState == GPS_HARDSLEEP) && (newState != GPS_OFF && newState != GPS_HARDSLEEP)) {
|
||||
@@ -776,13 +811,14 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
|
||||
void GPS::writePinEN(bool on)
|
||||
{
|
||||
// Abort: if conflict with Canned Messages when using Wisblock(?)
|
||||
if (HW_VENDOR == meshtastic_HardwareModel_RAK4631 && (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
|
||||
if ((HW_VENDOR == meshtastic_HardwareModel_RAK4631 || HW_VENDOR == meshtastic_HardwareModel_WISMESH_TAP) &&
|
||||
(rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
|
||||
return;
|
||||
|
||||
// Write and log
|
||||
enablePin->set(on);
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_DEBUG("Pin EN %s", val == HIGH ? "HIGH" : "LOW");
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("Pin EN %s", on == HIGH ? "HI" : "LOW");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -803,8 +839,8 @@ void GPS::writePinStandby(bool standby)
|
||||
// Write and log
|
||||
pinMode(PIN_GPS_STANDBY, OUTPUT);
|
||||
digitalWrite(PIN_GPS_STANDBY, val);
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_DEBUG("Pin STANDBY %s", val == HIGH ? "HIGH" : "LOW");
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("Pin STANDBY %s", val == HIGH ? "HI" : "LOW");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -836,8 +872,7 @@ void GPS::setPowerPMU(bool on)
|
||||
// t-beam v1.1 GNSS power channel
|
||||
on ? PMU->enablePowerOutput(XPOWERS_LDO3) : PMU->disablePowerOutput(XPOWERS_LDO3);
|
||||
}
|
||||
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("PMU %s", on ? "on" : "off");
|
||||
#endif
|
||||
#endif
|
||||
@@ -854,9 +889,6 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
|
||||
if (on) {
|
||||
gps->_serial_gps->write(0xFF);
|
||||
clearBuffer(); // This often returns old data, so drop it
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_DEBUG("UBLOX: wake");
|
||||
#endif
|
||||
}
|
||||
|
||||
// If putting to sleep
|
||||
@@ -873,23 +905,22 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
|
||||
if (gnssModel != GNSS_MODEL_UBLOX10) {
|
||||
// Encode the sleep time in millis into the packet
|
||||
for (int i = 0; i < 4; i++)
|
||||
gps->_message_PMREQ[0 + i] = sleepMs >> (i * 8);
|
||||
_message_PMREQ[0 + i] = sleepMs >> (i * 8);
|
||||
|
||||
// Record the message length
|
||||
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), gps->_message_PMREQ);
|
||||
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), _message_PMREQ);
|
||||
} else {
|
||||
// Encode the sleep time in millis into the packet
|
||||
for (int i = 0; i < 4; i++)
|
||||
gps->_message_PMREQ_10[4 + i] = sleepMs >> (i * 8);
|
||||
_message_PMREQ_10[4 + i] = sleepMs >> (i * 8);
|
||||
|
||||
// Record the message length
|
||||
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), gps->_message_PMREQ_10);
|
||||
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), _message_PMREQ_10);
|
||||
}
|
||||
|
||||
// Send the UBX packet
|
||||
gps->_serial_gps->write(gps->UBXscratch, msglen);
|
||||
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("UBLOX: sleep for %dmS", sleepMs);
|
||||
#endif
|
||||
}
|
||||
@@ -937,10 +968,10 @@ void GPS::down()
|
||||
#endif
|
||||
|
||||
if (softsleepSupported) {
|
||||
// How long does gps_update_interval need to be, for GPS_HARDSLEEP to become more efficient than GPS_SOFTSLEEP?
|
||||
// Heuristic equation. A compromise manually fitted to power observations from U-blox NEO-6M and M10050
|
||||
// https://www.desmos.com/calculator/6gvjghoumr
|
||||
// This is not particularly accurate, but probably an impromevement over a single, fixed threshold
|
||||
// How long does gps_update_interval need to be, for GPS_HARDSLEEP to become more efficient than
|
||||
// GPS_SOFTSLEEP? Heuristic equation. A compromise manually fitted to power observations from U-blox NEO-6M
|
||||
// and M10050 https://www.desmos.com/calculator/6gvjghoumr This is not particularly accurate, but probably an
|
||||
// improvement over a single, fixed threshold
|
||||
uint32_t hardsleepThreshold = (2750 * pow(predictedSearchDuration / 1000, 1.22));
|
||||
LOG_DEBUG("gps_update_interval >= %us needed to justify hardsleep", hardsleepThreshold / 1000);
|
||||
|
||||
@@ -961,8 +992,7 @@ void GPS::publishUpdate()
|
||||
shouldPublish = false;
|
||||
|
||||
// In debug logs, identify position by @timestamp:stage (stage 2 = publish)
|
||||
LOG_DEBUG("publishing pos@%x:2, hasVal=%d, Sats=%d, GPSlock=%d", p.timestamp, hasValidLocation, p.sats_in_view,
|
||||
hasLock());
|
||||
LOG_DEBUG("Publish pos@%x:2, hasVal=%d, Sats=%d, GPSlock=%d", p.timestamp, hasValidLocation, p.sats_in_view, hasLock());
|
||||
|
||||
// Notify any status instances that are observing us
|
||||
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p);
|
||||
@@ -977,7 +1007,7 @@ int32_t GPS::runOnce()
|
||||
{
|
||||
if (!GPSInitFinished) {
|
||||
if (!_serial_gps || config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
|
||||
LOG_INFO("GPS set to not-present. Skipping probe.");
|
||||
LOG_INFO("GPS set to not-present. Skip probe");
|
||||
return disable();
|
||||
}
|
||||
if (!setup())
|
||||
@@ -996,6 +1026,7 @@ int32_t GPS::runOnce()
|
||||
}
|
||||
}
|
||||
GPSInitFinished = true;
|
||||
publishUpdate();
|
||||
}
|
||||
|
||||
// Repeaters have no need for GPS
|
||||
@@ -1012,7 +1043,7 @@ int32_t GPS::runOnce()
|
||||
GNSS_MODEL_UBLOX10)) {
|
||||
// reset the GPS on next bootup
|
||||
if (devicestate.did_gps_reset && scheduling.elapsedSearchMs() > 60 * 1000UL && !hasFlow()) {
|
||||
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.");
|
||||
LOG_DEBUG("GPS is not found, try factory reset on next boot");
|
||||
devicestate.did_gps_reset = false;
|
||||
nodeDB->saveToDisk(SEGMENT_DEVICESTATE);
|
||||
return disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
|
||||
@@ -1046,10 +1077,9 @@ int32_t GPS::runOnce()
|
||||
|
||||
bool tooLong = scheduling.searchedTooLong();
|
||||
if (tooLong)
|
||||
LOG_WARN("Couldn't publish a valid location: didn't get a GPS lock in time.");
|
||||
LOG_WARN("Couldn't publish a valid location: didn't get a GPS lock in time");
|
||||
|
||||
// Once we get a location we no longer desperately want an update
|
||||
// LOG_DEBUG("gotLoc %d, tooLong %d, gotTime %d", gotLoc, tooLong, gotTime);
|
||||
if ((gotLoc && gotTime) || tooLong) {
|
||||
|
||||
if (tooLong) {
|
||||
@@ -1092,17 +1122,19 @@ int GPS::prepareDeepSleep(void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *PROBE_MESSAGE = "Trying %s (%s)...";
|
||||
const char *DETECTED_MESSAGE = "%s detected, using %s Module";
|
||||
static const char *PROBE_MESSAGE = "Trying %s (%s)...";
|
||||
static const char *DETECTED_MESSAGE = "%s detected, using %s Module";
|
||||
|
||||
#define PROBE_SIMPLE(CHIP, TOWRITE, RESPONSE, DRIVER, TIMEOUT, ...) \
|
||||
LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \
|
||||
clearBuffer(); \
|
||||
_serial_gps->write(TOWRITE "\r\n"); \
|
||||
if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \
|
||||
LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \
|
||||
return DRIVER; \
|
||||
}
|
||||
do { \
|
||||
LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \
|
||||
clearBuffer(); \
|
||||
_serial_gps->write(TOWRITE "\r\n"); \
|
||||
if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \
|
||||
LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \
|
||||
return DRIVER; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
GnssModel_t GPS::probe(int serialSpeed)
|
||||
{
|
||||
@@ -1115,12 +1147,12 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
_serial_gps->begin(serialSpeed);
|
||||
#else
|
||||
if (_serial_gps->baudRate() != serialSpeed) {
|
||||
LOG_DEBUG("Setting Baud to %i", serialSpeed);
|
||||
LOG_DEBUG("Set Baud to %i", serialSpeed);
|
||||
_serial_gps->updateBaudRate(serialSpeed);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
|
||||
memset(&ublox_info, 0, sizeof(ublox_info));
|
||||
uint8_t buffer[768] = {0};
|
||||
delay(100);
|
||||
|
||||
@@ -1165,7 +1197,7 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
// Check that the returned response class and message ID are correct
|
||||
GPS_RESPONSE response = getACK(0x06, 0x08, 750);
|
||||
if (response == GNSS_RESPONSE_NONE) {
|
||||
LOG_WARN("Failed to find GNSS Module (baudrate %d)", serialSpeed);
|
||||
LOG_WARN("No GNSS Module (baudrate %d)", serialSpeed);
|
||||
return GNSS_MODEL_UNKNOWN;
|
||||
} else if (response == GNSS_RESPONSE_FRAME_ERRORS) {
|
||||
LOG_INFO("UBlox Frame Errors (baudrate %d)", serialSpeed);
|
||||
@@ -1185,72 +1217,71 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
|
||||
uint16_t len = getACK(buffer, sizeof(buffer), 0x0A, 0x04, 1200);
|
||||
if (len) {
|
||||
// LOG_DEBUG("monver reply size = %d", len);
|
||||
uint16_t position = 0;
|
||||
for (int i = 0; i < 30; i++) {
|
||||
info.swVersion[i] = buffer[position];
|
||||
ublox_info.swVersion[i] = buffer[position];
|
||||
position++;
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
info.hwVersion[i] = buffer[position];
|
||||
ublox_info.hwVersion[i] = buffer[position];
|
||||
position++;
|
||||
}
|
||||
|
||||
while (len >= position + 30) {
|
||||
for (int i = 0; i < 30; i++) {
|
||||
info.extension[info.extensionNo][i] = buffer[position];
|
||||
ublox_info.extension[ublox_info.extensionNo][i] = buffer[position];
|
||||
position++;
|
||||
}
|
||||
info.extensionNo++;
|
||||
if (info.extensionNo > 9)
|
||||
ublox_info.extensionNo++;
|
||||
if (ublox_info.extensionNo > 9)
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Module Info : ");
|
||||
LOG_DEBUG("Soft version: %s", info.swVersion);
|
||||
LOG_DEBUG("Hard version: %s", info.hwVersion);
|
||||
LOG_DEBUG("Extensions:%d", info.extensionNo);
|
||||
for (int i = 0; i < info.extensionNo; i++) {
|
||||
LOG_DEBUG(" %s", info.extension[i]);
|
||||
LOG_DEBUG("Soft version: %s", ublox_info.swVersion);
|
||||
LOG_DEBUG("Hard version: %s", ublox_info.hwVersion);
|
||||
LOG_DEBUG("Extensions:%d", ublox_info.extensionNo);
|
||||
for (int i = 0; i < ublox_info.extensionNo; i++) {
|
||||
LOG_DEBUG(" %s", ublox_info.extension[i]);
|
||||
}
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
// tips: extensionNo field is 0 on some 6M GNSS modules
|
||||
for (int i = 0; i < info.extensionNo; ++i) {
|
||||
if (!strncmp(info.extension[i], "MOD=", 4)) {
|
||||
strncpy((char *)buffer, &(info.extension[i][4]), sizeof(buffer));
|
||||
} else if (!strncmp(info.extension[i], "PROTVER", 7)) {
|
||||
for (int i = 0; i < ublox_info.extensionNo; ++i) {
|
||||
if (!strncmp(ublox_info.extension[i], "MOD=", 4)) {
|
||||
strncpy((char *)buffer, &(ublox_info.extension[i][4]), sizeof(buffer));
|
||||
} else if (!strncmp(ublox_info.extension[i], "PROTVER", 7)) {
|
||||
char *ptr = nullptr;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
strncpy((char *)buffer, &(info.extension[i][8]), sizeof(buffer));
|
||||
strncpy((char *)buffer, &(ublox_info.extension[i][8]), sizeof(buffer));
|
||||
LOG_DEBUG("Protocol Version:%s", (char *)buffer);
|
||||
if (strlen((char *)buffer)) {
|
||||
uBloxProtocolVersion = strtoul((char *)buffer, &ptr, 10);
|
||||
LOG_DEBUG("ProtVer=%d", uBloxProtocolVersion);
|
||||
ublox_info.protocol_version = strtoul((char *)buffer, &ptr, 10);
|
||||
LOG_DEBUG("ProtVer=%d", ublox_info.protocol_version);
|
||||
} else {
|
||||
uBloxProtocolVersion = 0;
|
||||
ublox_info.protocol_version = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strncmp(info.hwVersion, "00040007", 8) == 0) {
|
||||
if (strncmp(ublox_info.hwVersion, "00040007", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 6", "6");
|
||||
return GNSS_MODEL_UBLOX6;
|
||||
} else if (strncmp(info.hwVersion, "00070000", 8) == 0) {
|
||||
} else if (strncmp(ublox_info.hwVersion, "00070000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 7", "7");
|
||||
return GNSS_MODEL_UBLOX7;
|
||||
} else if (strncmp(info.hwVersion, "00080000", 8) == 0) {
|
||||
} else if (strncmp(ublox_info.hwVersion, "00080000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 8", "8");
|
||||
return GNSS_MODEL_UBLOX8;
|
||||
} else if (strncmp(info.hwVersion, "00190000", 8) == 0) {
|
||||
} else if (strncmp(ublox_info.hwVersion, "00190000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 9", "9");
|
||||
return GNSS_MODEL_UBLOX9;
|
||||
} else if (strncmp(info.hwVersion, "000A0000", 8) == 0) {
|
||||
} else if (strncmp(ublox_info.hwVersion, "000A0000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 10", "10");
|
||||
return GNSS_MODEL_UBLOX10;
|
||||
}
|
||||
}
|
||||
LOG_WARN("Failed to find GNSS Module (baudrate %d)", serialSpeed);
|
||||
LOG_WARN("No GNSS Module (baudrate %d)", serialSpeed);
|
||||
return GNSS_MODEL_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -1293,10 +1324,12 @@ GPS *GPS::createGps()
|
||||
|
||||
if (!GPS_EN_ACTIVE) { // Need to invert the pin before hardware
|
||||
new GpioNotTransformer(
|
||||
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
virtPin,
|
||||
p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
} else {
|
||||
new GpioUnaryTransformer(
|
||||
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
virtPin,
|
||||
p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1311,7 +1344,7 @@ GPS *GPS::createGps()
|
||||
// see NMEAGPS.h
|
||||
gsafixtype.begin(reader, NMEA_MSG_GXGSA, 2);
|
||||
gsapdop.begin(reader, NMEA_MSG_GXGSA, 15);
|
||||
LOG_DEBUG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP");
|
||||
LOG_DEBUG("Use " NMEA_MSG_GXGSA " for 3DFIX and PDOP");
|
||||
#endif
|
||||
|
||||
// Make sure the GPS is awake before performing any init.
|
||||
@@ -1332,8 +1365,8 @@ GPS *GPS::createGps()
|
||||
|
||||
// ESP32 has a special set of parameters vs other arduino ports
|
||||
#if defined(ARCH_ESP32)
|
||||
LOG_DEBUG("Using GPIO%d for GPS RX", new_gps->rx_gpio);
|
||||
LOG_DEBUG("Using GPIO%d for GPS TX", new_gps->tx_gpio);
|
||||
LOG_DEBUG("Use GPIO%d for GPS RX", new_gps->rx_gpio);
|
||||
LOG_DEBUG("Use GPIO%d for GPS TX", new_gps->tx_gpio);
|
||||
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, new_gps->rx_gpio, new_gps->tx_gpio);
|
||||
#elif defined(ARCH_RP2040)
|
||||
_serial_gps->setFIFOSize(256);
|
||||
@@ -1369,26 +1402,22 @@ bool GPS::factoryReset()
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1C, 0xA2};
|
||||
_serial_gps->write(_message_reset1, sizeof(_message_reset1));
|
||||
if (getACK(0x05, 0x01, 10000)) {
|
||||
LOG_INFO(ACK_SUCCESS_MESSAGE);
|
||||
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
|
||||
}
|
||||
delay(100);
|
||||
byte _message_reset2[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA1};
|
||||
_serial_gps->write(_message_reset2, sizeof(_message_reset2));
|
||||
if (getACK(0x05, 0x01, 10000)) {
|
||||
LOG_INFO(ACK_SUCCESS_MESSAGE);
|
||||
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
|
||||
}
|
||||
delay(100);
|
||||
byte _message_reset3[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x1D, 0xB3};
|
||||
_serial_gps->write(_message_reset3, sizeof(_message_reset3));
|
||||
if (getACK(0x05, 0x01, 10000)) {
|
||||
LOG_INFO(ACK_SUCCESS_MESSAGE);
|
||||
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
|
||||
}
|
||||
// Reset device ram to COLDSTART state
|
||||
// byte _message_CFG_RST_COLDSTART[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0xFF, 0xB9, 0x00, 0x00, 0xC6, 0x8B};
|
||||
// _serial_gps->write(_message_CFG_RST_COLDSTART, sizeof(_message_CFG_RST_COLDSTART));
|
||||
// delay(1000);
|
||||
} else if (gnssModel == GNSS_MODEL_MTK) {
|
||||
// send the CAS10 to perform a factory restart of the device (and other device that support PCAS statements)
|
||||
LOG_INFO("GNSS Factory Reset via PCAS10,3");
|
||||
@@ -1404,8 +1433,8 @@ bool GPS::factoryReset()
|
||||
_serial_gps->write("$PMTK104*37\r\n");
|
||||
// No PMTK_ACK for this command.
|
||||
delay(100);
|
||||
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's UBLOX.
|
||||
// Factory Reset
|
||||
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's
|
||||
// UBLOX. Factory Reset
|
||||
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
|
||||
_serial_gps->write(_message_reset, sizeof(_message_reset));
|
||||
@@ -1444,8 +1473,8 @@ bool GPS::lookForTime()
|
||||
auto d = reader.date;
|
||||
if (ti.isValid() && d.isValid()) { // Note: we don't check for updated, because we'll only be called if needed
|
||||
/* Convert to unix time
|
||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
|
||||
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1,
|
||||
1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
*/
|
||||
struct tm t;
|
||||
t.tm_sec = ti.second() + round(ti.age() / 1000);
|
||||
@@ -1500,7 +1529,7 @@ bool GPS::lookForLocation()
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_STATISTICS
|
||||
if (reader.failedChecksum() > lastChecksumFailCount) {
|
||||
LOG_WARN("%u new GPS checksum failures, for a total of %u.", reader.failedChecksum() - lastChecksumFailCount,
|
||||
LOG_WARN("%u new GPS checksum failures, for a total of %u", reader.failedChecksum() - lastChecksumFailCount,
|
||||
reader.failedChecksum());
|
||||
lastChecksumFailCount = reader.failedChecksum();
|
||||
}
|
||||
@@ -1508,14 +1537,13 @@ bool GPS::lookForLocation()
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
fixType = atoi(gsafixtype.value()); // will set to zero if no data
|
||||
// LOG_DEBUG("FIX QUAL=%d, TYPE=%d", fixQual, fixType);
|
||||
#endif
|
||||
|
||||
// check if GPS has an acceptable lock
|
||||
if (!hasLock())
|
||||
return false;
|
||||
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d", reader.location.age(),
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
gsafixtype.age(),
|
||||
@@ -1523,7 +1551,7 @@ bool GPS::lookForLocation()
|
||||
0,
|
||||
#endif
|
||||
reader.date.age(), reader.time.age());
|
||||
#endif // GPS_EXTRAVERBOSE
|
||||
#endif // GPS_DEBUG
|
||||
|
||||
// Is this a new point or are we re-reading the previous one?
|
||||
if (!reader.location.isUpdated() && !reader.altitude.isUpdated())
|
||||
@@ -1546,13 +1574,13 @@ bool GPS::lookForLocation()
|
||||
|
||||
// Bail out EARLY to avoid overwriting previous good data (like #857)
|
||||
if (toDegInt(loc.lat) > 900000000) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("Bail out EARLY on LAT %i", toDegInt(loc.lat));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (toDegInt(loc.lng) > 1800000000) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("Bail out EARLY on LNG %i", toDegInt(loc.lng));
|
||||
#endif
|
||||
return false;
|
||||
@@ -1564,7 +1592,6 @@ bool GPS::lookForLocation()
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
p.HDOP = reader.hdop.value();
|
||||
p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value());
|
||||
// LOG_DEBUG("PDOP=%d, HDOP=%d", p.PDOP, p.HDOP);
|
||||
#else
|
||||
// FIXME! naive PDOP emulation (assumes VDOP==HDOP)
|
||||
// correct formula is PDOP = SQRT(HDOP^2 + VDOP^2)
|
||||
@@ -1654,12 +1681,10 @@ bool GPS::whileActive()
|
||||
}
|
||||
#ifdef SERIAL_BUFFER_SIZE
|
||||
if (_serial_gps->available() >= SERIAL_BUFFER_SIZE - 1) {
|
||||
LOG_WARN("GPS Buffer full with %u bytes waiting. Flushing to avoid corruption.", _serial_gps->available());
|
||||
LOG_WARN("GPS Buffer full with %u bytes waiting. Flush to avoid corruption", _serial_gps->available());
|
||||
clearBuffer();
|
||||
}
|
||||
#endif
|
||||
// if (_serial_gps->available() > 0)
|
||||
// LOG_DEBUG("GPS Bytes Waiting: %u", _serial_gps->available());
|
||||
// First consume any chars that have piled up at the receiver
|
||||
while (_serial_gps->available() > 0) {
|
||||
int c = _serial_gps->read();
|
||||
@@ -1678,7 +1703,9 @@ bool GPS::whileActive()
|
||||
}
|
||||
}
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG(debugmsg.c_str());
|
||||
if (debugmsg != "") {
|
||||
LOG_DEBUG(debugmsg.c_str());
|
||||
}
|
||||
#endif
|
||||
return isValid;
|
||||
}
|
||||
@@ -1707,7 +1734,7 @@ void GPS::toggleGpsMode()
|
||||
{
|
||||
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED;
|
||||
LOG_INFO("User toggled GpsMode. Now DISABLED.");
|
||||
LOG_INFO("User toggled GpsMode. Now DISABLED");
|
||||
playGPSDisableBeep();
|
||||
#ifdef GNSS_AIROHA
|
||||
if (powerState == GPS_ACTIVE) {
|
||||
|
||||
211
src/gps/GPS.h
211
src/gps/GPS.h
@@ -16,13 +16,6 @@
|
||||
#define GPS_EN_ACTIVE 1
|
||||
#endif
|
||||
|
||||
struct uBloxGnssModelInfo {
|
||||
char swVersion[30];
|
||||
char hwVersion[10];
|
||||
uint8_t extensionNo;
|
||||
char extension[10][30];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GNSS_MODEL_ATGM336H,
|
||||
GNSS_MODEL_MTK,
|
||||
@@ -54,9 +47,6 @@ enum GPSPowerState : uint8_t {
|
||||
GPS_OFF // Powered off indefinitely
|
||||
};
|
||||
|
||||
// Generate a string representation of DOP
|
||||
const char *getDOPString(uint32_t dop);
|
||||
|
||||
/**
|
||||
* A gps class that only reads from the GPS periodically and keeps the gps powered down except when reading
|
||||
*
|
||||
@@ -64,101 +54,7 @@ const char *getDOPString(uint32_t dop);
|
||||
*/
|
||||
class GPS : private concurrency::OSThread
|
||||
{
|
||||
TinyGPSPlus reader;
|
||||
uint8_t fixQual = 0; // fix quality from GPGGA
|
||||
uint32_t lastChecksumFailCount = 0;
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
|
||||
// via optional feature "custom fields", currently disabled (bug #525)
|
||||
TinyGPSCustom gsafixtype; // custom extract fix type from GPGSA
|
||||
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
|
||||
uint8_t fixType = 0; // fix type from GPGSA
|
||||
#endif
|
||||
private:
|
||||
const int serialSpeeds[6] = {9600, 115200, 38400, 4800, 57600, 9600};
|
||||
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
|
||||
uint32_t rx_gpio = 0;
|
||||
uint32_t tx_gpio = 0;
|
||||
|
||||
int speedSelect = 0;
|
||||
int probeTries = 2;
|
||||
|
||||
/**
|
||||
* hasValidLocation - indicates that the position variables contain a complete
|
||||
* GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
|
||||
*/
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
|
||||
bool isInPowersave = false;
|
||||
|
||||
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
|
||||
|
||||
bool hasGPS = false; // Do we have a GPS we are talking to
|
||||
|
||||
bool GPSInitFinished = false; // Init thread finished?
|
||||
bool GPSInitStarted = false; // Init thread finished?
|
||||
|
||||
GPSPowerState powerState = GPS_OFF; // GPS_ACTIVE if we want a location right now
|
||||
|
||||
uint8_t numSatellites = 0;
|
||||
|
||||
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
||||
|
||||
public:
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
#if defined(ARCH_RP2040)
|
||||
static SerialUART *_serial_gps;
|
||||
#else
|
||||
static HardwareSerial *_serial_gps;
|
||||
#endif
|
||||
static uint8_t _message_PMREQ[];
|
||||
static uint8_t _message_PMREQ_10[];
|
||||
static const uint8_t _message_CFG_RXM_PSM[];
|
||||
static const uint8_t _message_CFG_RXM_ECO[];
|
||||
static const uint8_t _message_CFG_PM2[];
|
||||
static const uint8_t _message_GNSS_7[];
|
||||
static const uint8_t _message_GNSS_8[];
|
||||
static const uint8_t _message_JAM_6_7[];
|
||||
static const uint8_t _message_JAM_8[];
|
||||
static const uint8_t _message_NAVX5[];
|
||||
static const uint8_t _message_NAVX5_8[];
|
||||
static const uint8_t _message_NMEA[];
|
||||
static const uint8_t _message_DISABLE_TXT_INFO[];
|
||||
static const uint8_t _message_1HZ[];
|
||||
static const uint8_t _message_GLL[];
|
||||
static const uint8_t _message_GSA[];
|
||||
static const uint8_t _message_GSV[];
|
||||
static const uint8_t _message_VTG[];
|
||||
static const uint8_t _message_RMC[];
|
||||
static const uint8_t _message_AID[];
|
||||
static const uint8_t _message_GGA[];
|
||||
static const uint8_t _message_PMS[];
|
||||
static const uint8_t _message_SAVE[];
|
||||
static const uint8_t _message_SAVE_10[];
|
||||
|
||||
// VALSET Commands for M10
|
||||
static const uint8_t _message_VALSET_PM[];
|
||||
static const uint8_t _message_VALSET_PM_RAM[];
|
||||
static const uint8_t _message_VALSET_PM_BBR[];
|
||||
static const uint8_t _message_VALSET_ITFM_RAM[];
|
||||
static const uint8_t _message_VALSET_ITFM_BBR[];
|
||||
static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[];
|
||||
static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[];
|
||||
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[];
|
||||
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[];
|
||||
static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[];
|
||||
static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[];
|
||||
static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[];
|
||||
static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[];
|
||||
|
||||
// CASIC commands for ATGM336H
|
||||
static const uint8_t _message_CAS_CFG_RST_FACTORY[];
|
||||
static const uint8_t _message_CAS_CFG_NAVX_CONF[];
|
||||
static const uint8_t _message_CAS_CFG_RATE_1HZ[];
|
||||
|
||||
const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
|
||||
|
||||
meshtastic_Position p = meshtastic_Position_init_default;
|
||||
|
||||
/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
|
||||
@@ -168,8 +64,6 @@ class GPS : private concurrency::OSThread
|
||||
*/
|
||||
GpioVirtPin *enablePin = NULL;
|
||||
|
||||
GPS() : concurrency::OSThread("GPS") {}
|
||||
|
||||
virtual ~GPS();
|
||||
|
||||
/** We will notify this observable anytime GPS state has changed meaningfully */
|
||||
@@ -206,21 +100,6 @@ class GPS : private concurrency::OSThread
|
||||
// Empty the input buffer as quickly as possible
|
||||
void clearBuffer();
|
||||
|
||||
// Create a ublox packet for editing in memory
|
||||
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
|
||||
uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
|
||||
|
||||
// scratch space for creating ublox packets
|
||||
uint8_t UBXscratch[250] = {0};
|
||||
|
||||
int rebootsSeen = 0;
|
||||
|
||||
int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
|
||||
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
|
||||
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
|
||||
|
||||
GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
|
||||
|
||||
virtual bool factoryReset();
|
||||
|
||||
// Creates an instance of the GPS class.
|
||||
@@ -233,20 +112,8 @@ class GPS : private concurrency::OSThread
|
||||
// Let the GPS hardware save power between updates
|
||||
void down();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
||||
* Override this method to check for new locations
|
||||
*
|
||||
* @return true if we've acquired a time
|
||||
*/
|
||||
|
||||
/**
|
||||
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
|
||||
* Override this method to check for new locations
|
||||
*
|
||||
* @return true if we've acquired a new location
|
||||
*/
|
||||
private:
|
||||
GPS() : concurrency::OSThread("GPS") {}
|
||||
|
||||
/// Record that we have a GPS
|
||||
void setConnected();
|
||||
@@ -273,15 +140,74 @@ class GPS : private concurrency::OSThread
|
||||
*/
|
||||
virtual bool lookForLocation();
|
||||
|
||||
private:
|
||||
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
|
||||
|
||||
TinyGPSPlus reader;
|
||||
uint8_t fixQual = 0; // fix quality from GPGGA
|
||||
uint32_t lastChecksumFailCount = 0;
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
// (20210908) TinyGps++ can only read the GPGSA "FIX TYPE" field
|
||||
// via optional feature "custom fields", currently disabled (bug #525)
|
||||
TinyGPSCustom gsafixtype; // custom extract fix type from GPGSA
|
||||
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
|
||||
uint8_t fixType = 0; // fix type from GPGSA
|
||||
#endif
|
||||
|
||||
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
|
||||
uint32_t rx_gpio = 0;
|
||||
uint32_t tx_gpio = 0;
|
||||
|
||||
uint8_t speedSelect = 0;
|
||||
uint8_t probeTries = 0;
|
||||
|
||||
/**
|
||||
* hasValidLocation - indicates that the position variables contain a complete
|
||||
* GPS location, valid and fresh (< gps_update_interval + position_broadcast_secs)
|
||||
*/
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
|
||||
bool isInPowersave = false;
|
||||
|
||||
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
|
||||
|
||||
bool hasGPS = false; // Do we have a GPS we are talking to
|
||||
|
||||
bool GPSInitFinished = false; // Init thread finished?
|
||||
bool GPSInitStarted = false; // Init thread finished?
|
||||
|
||||
GPSPowerState powerState = GPS_OFF; // GPS_ACTIVE if we want a location right now
|
||||
|
||||
uint8_t numSatellites = 0;
|
||||
|
||||
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
||||
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
#if defined(ARCH_RP2040)
|
||||
static SerialUART *_serial_gps;
|
||||
#else
|
||||
static HardwareSerial *_serial_gps;
|
||||
#endif
|
||||
|
||||
// Create a ublox packet for editing in memory
|
||||
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
|
||||
uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
|
||||
|
||||
// scratch space for creating ublox packets
|
||||
uint8_t UBXscratch[250] = {0};
|
||||
|
||||
int rebootsSeen = 0;
|
||||
|
||||
int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
|
||||
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
|
||||
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
|
||||
|
||||
GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
|
||||
|
||||
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
|
||||
/// always returns 0 to indicate okay to sleep
|
||||
int prepareDeepSleep(void *unused);
|
||||
|
||||
// Calculate checksum
|
||||
void UBXChecksum(uint8_t *message, size_t length);
|
||||
void CASChecksum(uint8_t *message, size_t length);
|
||||
|
||||
/** Set power with EN pin, if relevant
|
||||
*/
|
||||
void writePinEN(bool on);
|
||||
@@ -310,11 +236,6 @@ class GPS : private concurrency::OSThread
|
||||
|
||||
// delay counter to allow more sats before fixed position stops GPS thread
|
||||
uint8_t fixeddelayCtr = 0;
|
||||
|
||||
const char *powerStateToString();
|
||||
|
||||
protected:
|
||||
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
|
||||
};
|
||||
|
||||
extern GPS *gps;
|
||||
|
||||
@@ -49,7 +49,7 @@ uint32_t GPSUpdateScheduling::msUntilNextSearch()
|
||||
}
|
||||
|
||||
// How long have we already been searching?
|
||||
// Used to abort a search in progress, if it runs unnaceptably long
|
||||
// Used to abort a search in progress, if it runs unacceptably long
|
||||
uint32_t GPSUpdateScheduling::elapsedSearchMs()
|
||||
{
|
||||
// If searching
|
||||
@@ -98,7 +98,7 @@ void GPSUpdateScheduling::updateLockTimePrediction()
|
||||
|
||||
// Ignore the first lock-time: likely to be long, will skew data
|
||||
|
||||
// Second locktime: likely stable. Use to intialize the smoothing filter
|
||||
// Second locktime: likely stable. Use to initialize the smoothing filter
|
||||
if (searchCount == 1)
|
||||
predictedMsToGetLock = lockTime;
|
||||
|
||||
@@ -106,9 +106,9 @@ void GPSUpdateScheduling::updateLockTimePrediction()
|
||||
else if (searchCount > 1)
|
||||
predictedMsToGetLock = (lockTime * weighting) + (predictedMsToGetLock * (1 - weighting));
|
||||
|
||||
searchCount++; // Only tracked so we can diregard initial lock-times
|
||||
searchCount++; // Only tracked so we can disregard initial lock-times
|
||||
|
||||
LOG_DEBUG("Predicting %us to get next lock", predictedMsToGetLock / 1000);
|
||||
LOG_DEBUG("Predict %us to get next lock", predictedMsToGetLock / 1000);
|
||||
}
|
||||
|
||||
// How long do we expect to spend searching for a lock?
|
||||
|
||||
@@ -574,3 +574,23 @@ const char *GeoCoord::degreesToBearing(unsigned int degrees)
|
||||
else
|
||||
return "N";
|
||||
}
|
||||
|
||||
double GeoCoord::pow_neg(double base, double exponent)
|
||||
{
|
||||
if (exponent == 0) {
|
||||
return 1;
|
||||
} else if (exponent > 0) {
|
||||
return pow(base, exponent);
|
||||
}
|
||||
return 1 / pow(base, -exponent);
|
||||
}
|
||||
|
||||
double GeoCoord::toRadians(double deg)
|
||||
{
|
||||
return deg * PI / 180;
|
||||
}
|
||||
|
||||
double GeoCoord::toDegrees(double r)
|
||||
{
|
||||
return r * 180 / PI;
|
||||
}
|
||||
@@ -13,28 +13,6 @@
|
||||
#define OLC_CODE_LEN 11
|
||||
#define DEG_CONVERT (180 / PI)
|
||||
|
||||
// Helper functions
|
||||
// Raises a number to an exponent, handling negative exponents.
|
||||
static inline double pow_neg(double base, double exponent)
|
||||
{
|
||||
if (exponent == 0) {
|
||||
return 1;
|
||||
} else if (exponent > 0) {
|
||||
return pow(base, exponent);
|
||||
}
|
||||
return 1 / pow(base, -exponent);
|
||||
}
|
||||
|
||||
static inline double toRadians(double deg)
|
||||
{
|
||||
return deg * PI / 180;
|
||||
}
|
||||
|
||||
static inline double toDegrees(double r)
|
||||
{
|
||||
return r * 180 / PI;
|
||||
}
|
||||
|
||||
// GeoCoord structs/classes
|
||||
// A struct to hold the data for a DMS coordinate.
|
||||
struct DMS {
|
||||
@@ -120,6 +98,11 @@ class GeoCoord
|
||||
static unsigned int bearingToDegrees(const char *bearing);
|
||||
static const char *degreesToBearing(unsigned int degrees);
|
||||
|
||||
// Raises a number to an exponent, handling negative exponents.
|
||||
static double pow_neg(double base, double exponent);
|
||||
static double toRadians(double deg);
|
||||
static double toDegrees(double r);
|
||||
|
||||
// Point to point conversions
|
||||
int32_t distanceTo(const GeoCoord &pointB);
|
||||
int32_t bearingTo(const GeoCoord &pointB);
|
||||
@@ -162,4 +145,4 @@ class GeoCoord
|
||||
|
||||
// OLC getter
|
||||
void getOLCCode(char *code) { strncpy(code, _olc.code, OLC_CODE_LEN + 1); } // +1 for null termination
|
||||
};
|
||||
};
|
||||
@@ -23,7 +23,7 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, c
|
||||
{
|
||||
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
|
||||
char type = isCaltopoMode ? 'P' : 'N';
|
||||
uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
|
||||
uint32_t len = snprintf(buf, bufsz, "\r\n$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
|
||||
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(),
|
||||
geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
|
||||
geoCoord.getDMSLonCP(), name);
|
||||
|
||||
@@ -112,7 +112,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
|
||||
uint32_t printableEpoch = tv->tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||
#ifdef BUILD_EPOCH
|
||||
if (tv->tv_sec < BUILD_EPOCH) {
|
||||
LOG_WARN("Ignoring time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
|
||||
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -120,21 +120,21 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
|
||||
bool shouldSet;
|
||||
if (forceUpdate) {
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Overriding current RTC quality (%s) with incoming time of RTC quality of %s", RtcName(currentQuality),
|
||||
LOG_DEBUG("Override current RTC quality (%s) with incoming time of RTC quality of %s", RtcName(currentQuality),
|
||||
RtcName(q));
|
||||
} else if (q > currentQuality) {
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Upgrading time to quality %s", RtcName(q));
|
||||
LOG_DEBUG("Upgrade time to quality %s", RtcName(q));
|
||||
} else if (q == RTCQualityGPS) {
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Reapplying GPS time: %ld secs", printableEpoch);
|
||||
LOG_DEBUG("Reapply GPS time: %ld secs", printableEpoch);
|
||||
} else if (q == RTCQualityNTP && !Throttle::isWithinTimespanMs(lastSetMsec, (12 * 60 * 60 * 1000UL))) {
|
||||
// Every 12 hrs we will slam in a new NTP or Phone GPS / NTP time, to correct for local RTC clock drift
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Reapplying external time to correct clock drift %ld secs", printableEpoch);
|
||||
LOG_DEBUG("Reapply external time to correct clock drift %ld secs", printableEpoch);
|
||||
} else {
|
||||
shouldSet = false;
|
||||
LOG_DEBUG("Current RTC quality: %s. Ignoring time of RTC quality of %s", RtcName(currentQuality), RtcName(q));
|
||||
LOG_DEBUG("Current RTC quality: %s. Ignore time of RTC quality of %s", RtcName(currentQuality), RtcName(q));
|
||||
}
|
||||
|
||||
if (shouldSet) {
|
||||
@@ -230,7 +230,7 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
|
||||
|
||||
// LOG_DEBUG("Got time from GPS month=%d, year=%d, unixtime=%ld", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
if (t.tm_year < 0 || t.tm_year >= 300) {
|
||||
// LOG_DEBUG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
// LOG_DEBUG("Ignore invalid GPS month=%d, year=%d, unixtime=%ld", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
return false;
|
||||
} else {
|
||||
return perhapsSetRTC(q, &tv);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
// CFG-RST (0x06, 0x02)
|
||||
// Factory reset
|
||||
const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = {
|
||||
static const uint8_t _message_CAS_CFG_RST_FACTORY[] = {
|
||||
0xFF, 0x03, // Fields to clear
|
||||
0x01, // Reset Mode: Controlled Software reset
|
||||
0x03 // Startup Mode: Factory
|
||||
@@ -30,7 +30,7 @@ const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = {
|
||||
// CFG_RATE (0x06, 0x01)
|
||||
// 1HZ update rate, this should always be the case after
|
||||
// factory reset but update it regardless
|
||||
const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = {
|
||||
static const uint8_t _message_CAS_CFG_RATE_1HZ[] = {
|
||||
0xE8, 0x03, // Update Rate: 0x03E8 = 1000ms
|
||||
0x00, 0x00 // Reserved
|
||||
};
|
||||
@@ -39,7 +39,7 @@ const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = {
|
||||
// Initial ATGM33H-5N configuration, Updates for Dynamic Mode, Fix Mode, and SV system
|
||||
// Qwirk: The ATGM33H-5N-31 should only support GPS+BDS, however it will happily enable
|
||||
// and use GPS+BDS+GLONASS iff the correct CFG_NAVX command is used.
|
||||
const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = {
|
||||
static const uint8_t _message_CAS_CFG_NAVX_CONF[] = {
|
||||
0x03, 0x01, 0x00, 0x00, // Update Mask: Dynamic Mode, Fix Mode, Nav Settings
|
||||
0x03, // Dynamic Mode: Automotive
|
||||
0x03, // Fix Mode: Auto 2D/3D
|
||||
@@ -60,4 +60,4 @@ const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = {
|
||||
0x00, 0x00, 0x00, 0x00, // Position Accuracy Max
|
||||
0x00, 0x00, 0x00, 0x00, // Time Accuracy Max
|
||||
0x00, 0x00, 0x00, 0x00 // Static Hold Threshold
|
||||
};
|
||||
};
|
||||
|
||||
114
src/gps/ubx.h
114
src/gps/ubx.h
@@ -1,20 +1,22 @@
|
||||
const char *failMessage = "Unable to %s";
|
||||
static const char *failMessage = "Unable to %s";
|
||||
|
||||
#define SEND_UBX_PACKET(TYPE, ID, DATA, ERRMSG, TIMEOUT) \
|
||||
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
|
||||
_serial_gps->write(UBXscratch, msglen); \
|
||||
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
|
||||
LOG_WARN(failMessage, #ERRMSG); \
|
||||
}
|
||||
do { \
|
||||
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
|
||||
_serial_gps->write(UBXscratch, msglen); \
|
||||
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
|
||||
LOG_WARN(failMessage, #ERRMSG); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Power Management
|
||||
|
||||
uint8_t GPS::_message_PMREQ[] PROGMEM = {
|
||||
static uint8_t _message_PMREQ[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds)
|
||||
0x02, 0x00, 0x00, 0x00 // Bitfield, set backup = 1
|
||||
};
|
||||
|
||||
uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
|
||||
static uint8_t _message_PMREQ_10[] PROGMEM = {
|
||||
0x00, // version (0 for this version)
|
||||
0x00, 0x00, 0x00, // Reserved 1
|
||||
0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds)
|
||||
@@ -22,18 +24,18 @@ uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
|
||||
0x08, 0x00, 0x00, 0x00 // wakeupSources Wake on uartrx
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = {
|
||||
static const uint8_t _message_CFG_RXM_PSM[] PROGMEM = {
|
||||
0x08, // Reserved
|
||||
0x01 // Power save mode
|
||||
};
|
||||
|
||||
// only for Neo-6
|
||||
const uint8_t GPS::_message_CFG_RXM_ECO[] PROGMEM = {
|
||||
static const uint8_t _message_CFG_RXM_ECO[] PROGMEM = {
|
||||
0x08, // Reserved
|
||||
0x04 // eco mode
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
|
||||
static const uint8_t _message_CFG_PM2[] PROGMEM = {
|
||||
0x01, // version
|
||||
0x00, // Reserved 1, set to 0x06 by u-Center
|
||||
0x00, // Reserved 2
|
||||
@@ -58,7 +60,7 @@ const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
|
||||
// Constallation setup, none required for Neo-6
|
||||
|
||||
// For Neo-7 GPS & SBAS
|
||||
const uint8_t GPS::_message_GNSS_7[] = {
|
||||
static const uint8_t _message_GNSS_7[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
||||
@@ -76,7 +78,7 @@ const uint8_t GPS::_message_GNSS_7[] = {
|
||||
// There is also a possibility that the module may be GPS-only.
|
||||
|
||||
// For M8 GPS, GLONASS, Galileo, SBAS, QZSS
|
||||
const uint8_t GPS::_message_GNSS_8[] = {
|
||||
static const uint8_t _message_GNSS_8[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
|
||||
@@ -90,7 +92,7 @@ const uint8_t GPS::_message_GNSS_8[] = {
|
||||
};
|
||||
/*
|
||||
// For M8 GPS, GLONASS, BeiDou, SBAS, QZSS
|
||||
const uint8_t GPS::_message_GNSS_8_B[] = {
|
||||
static const uint8_t _message_GNSS_8_B[] = {
|
||||
0x00, // msgVer (0 for this version)
|
||||
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
|
||||
0xff, // numTrkChUse (max number of channels to use, 0xff = max available) read only for protocol >23
|
||||
@@ -105,7 +107,7 @@ const uint8_t GPS::_message_GNSS_8_B[] = {
|
||||
*/
|
||||
|
||||
// For M8 we want to enable NMEA version 4.10 messages to allow for Galileo and or BeiDou
|
||||
const uint8_t GPS::_message_NMEA[]{
|
||||
static const uint8_t _message_NMEA[]{
|
||||
0x00, // filter flags
|
||||
0x41, // NMEA Version
|
||||
0x00, // Max number of SVs to report per TaklerId
|
||||
@@ -121,13 +123,13 @@ const uint8_t GPS::_message_NMEA[]{
|
||||
// Enable jamming/interference monitor
|
||||
|
||||
// For Neo-6, Max-7 and Neo-7
|
||||
const uint8_t GPS::_message_JAM_6_7[] = {
|
||||
static const uint8_t _message_JAM_6_7[] = {
|
||||
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable = 1, reserved bits 0x16B156
|
||||
0x1e, 0x03, 0x00, 0x00 // config2 antennaSetting Unknown = 0, reserved 3, = 0x00,0x00, reserved 2 = 0x31E
|
||||
};
|
||||
|
||||
// For M8
|
||||
const uint8_t GPS::_message_JAM_8[] = {
|
||||
static const uint8_t _message_JAM_8[] = {
|
||||
0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable1 = 1, reserved bits 0x16B156
|
||||
0x1e, 0x43, 0x00, 0x00 // config2 antennaSetting Unknown = 0, enable2 = 1, generalBits = 0x31E
|
||||
};
|
||||
@@ -137,7 +139,7 @@ const uint8_t GPS::_message_JAM_8[] = {
|
||||
// ToDo: check UBX-MON-VER for module type and protocol version
|
||||
|
||||
// For the Neo-6
|
||||
const uint8_t GPS::_message_NAVX5[] = {
|
||||
static const uint8_t _message_NAVX5[] = {
|
||||
0x00, 0x00, // msgVer (0 for this version)
|
||||
0x4c, 0x66, // mask1
|
||||
0x00, 0x00, 0x00, 0x00, // Reserved 0
|
||||
@@ -166,7 +168,7 @@ const uint8_t GPS::_message_NAVX5[] = {
|
||||
0x00, 0x00, 0x00, 0x00 // Reserved 4
|
||||
};
|
||||
// For the M8
|
||||
const uint8_t GPS::_message_NAVX5_8[] = {
|
||||
static const uint8_t _message_NAVX5_8[] = {
|
||||
0x02, 0x00, // msgVer (2 for this version)
|
||||
0x4c, 0x66, // mask1
|
||||
0x00, 0x00, 0x00, 0x00, // mask2
|
||||
@@ -197,7 +199,7 @@ const uint8_t GPS::_message_NAVX5_8[] = {
|
||||
// Additionally, for some new modules like the M9/M10, an update rate lower than 5Hz
|
||||
// is recommended to avoid a known issue with satellites disappearing.
|
||||
// The module defaults for M8, M9, M10 are the same as we use here so no update is necessary
|
||||
const uint8_t GPS::_message_1HZ[] = {
|
||||
static const uint8_t _message_1HZ[] = {
|
||||
0xE8, 0x03, // Measurement Rate (1000ms for 1Hz)
|
||||
0x01, 0x00, // Navigation rate, always 1 in GPS mode
|
||||
0x01, 0x00 // Time reference
|
||||
@@ -205,7 +207,7 @@ const uint8_t GPS::_message_1HZ[] = {
|
||||
|
||||
// Disable GLL. GLL - Geographic position (latitude and longitude), which provides the current geographical
|
||||
// coordinates.
|
||||
const uint8_t GPS::_message_GLL[] = {
|
||||
static const uint8_t _message_GLL[] = {
|
||||
0xF0, 0x01, // NMEA ID for GLL
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -217,7 +219,7 @@ const uint8_t GPS::_message_GLL[] = {
|
||||
|
||||
// Disable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
|
||||
// the DOP (Dilution of Precision)
|
||||
const uint8_t GPS::_message_GSA[] = {
|
||||
static const uint8_t _message_GSA[] = {
|
||||
0xF0, 0x02, // NMEA ID for GSA
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -228,7 +230,7 @@ const uint8_t GPS::_message_GSA[] = {
|
||||
};
|
||||
|
||||
// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view.
|
||||
const uint8_t GPS::_message_GSV[] = {
|
||||
static const uint8_t _message_GSV[] = {
|
||||
0xF0, 0x03, // NMEA ID for GSV
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -240,7 +242,7 @@ const uint8_t GPS::_message_GSV[] = {
|
||||
|
||||
// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to
|
||||
// the ground.
|
||||
const uint8_t GPS::_message_VTG[] = {
|
||||
static const uint8_t _message_VTG[] = {
|
||||
0xF0, 0x05, // NMEA ID for VTG
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -251,7 +253,7 @@ const uint8_t GPS::_message_VTG[] = {
|
||||
};
|
||||
|
||||
// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data.
|
||||
const uint8_t GPS::_message_RMC[] = {
|
||||
static const uint8_t _message_RMC[] = {
|
||||
0xF0, 0x04, // NMEA ID for RMC
|
||||
0x00, // Rate for DDC
|
||||
0x01, // Rate for UART1
|
||||
@@ -262,7 +264,7 @@ const uint8_t GPS::_message_RMC[] = {
|
||||
};
|
||||
|
||||
// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data.
|
||||
const uint8_t GPS::_message_GGA[] = {
|
||||
static const uint8_t _message_GGA[] = {
|
||||
0xF0, 0x00, // NMEA ID for GGA
|
||||
0x00, // Rate for DDC
|
||||
0x01, // Rate for UART1
|
||||
@@ -274,7 +276,7 @@ const uint8_t GPS::_message_GGA[] = {
|
||||
|
||||
// Disable UBX-AID-ALPSRV as it may confuse TinyGPS. The Neo-6 seems to send this message
|
||||
// whether the AID Autonomous is enabled or not
|
||||
const uint8_t GPS::_message_AID[] = {
|
||||
static const uint8_t _message_AID[] = {
|
||||
0x0B, 0x32, // NMEA ID for UBX-AID-ALPSRV
|
||||
0x00, // Rate for DDC
|
||||
0x00, // Rate for UART1
|
||||
@@ -287,7 +289,7 @@ const uint8_t GPS::_message_AID[] = {
|
||||
// Turn off TEXT INFO Messages for all but M10 series
|
||||
|
||||
// B5 62 06 02 0A 00 01 00 00 00 03 03 00 03 03 00 1F 20
|
||||
const uint8_t GPS::_message_DISABLE_TXT_INFO[] = {
|
||||
static const uint8_t _message_DISABLE_TXT_INFO[] = {
|
||||
0x01, // Protocol ID for NMEA
|
||||
0x00, 0x00, 0x00, // Reserved
|
||||
0x03, // I2C
|
||||
@@ -310,7 +312,7 @@ const uint8_t GPS::_message_DISABLE_TXT_INFO[] = {
|
||||
// and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise,
|
||||
// it must be set to '0'.
|
||||
// This command applies to M8 products
|
||||
const uint8_t GPS::_message_PMS[] = {
|
||||
static const uint8_t _message_PMS[] = {
|
||||
0x00, // Version (0)
|
||||
0x03, // Power setup value 3 = Agresssive 1Hz
|
||||
0x00, 0x00, // period: not applicable, set to 0
|
||||
@@ -318,14 +320,14 @@ const uint8_t GPS::_message_PMS[] = {
|
||||
0x00, 0x00 // reserved, generated by u-center
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_SAVE[] = {
|
||||
static const uint8_t _message_SAVE[] = {
|
||||
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
|
||||
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
|
||||
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
|
||||
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_SAVE_10[] = {
|
||||
static const uint8_t _message_SAVE_10[] = {
|
||||
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
|
||||
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
|
||||
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
|
||||
@@ -375,12 +377,12 @@ LIMITPEAKCURRENT L 1
|
||||
// b5 62 06 8a 26 00 00 02 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
|
||||
// 10 01 8c 03
|
||||
*/
|
||||
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
static const uint8_t _message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
static const uint8_t _message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
|
||||
/*
|
||||
CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM and one for BBR
|
||||
@@ -394,10 +396,10 @@ CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM an
|
||||
|
||||
b5 62 06 8a 0e 00 00 01 00 00 0d 00 41 10 01 13 00 41 10 01 63 c6
|
||||
*/
|
||||
const uint8_t GPS::_message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41,
|
||||
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41,
|
||||
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
|
||||
static const uint8_t _message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41,
|
||||
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
|
||||
static const uint8_t _message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41,
|
||||
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
|
||||
|
||||
// Turn off all NMEA messages:
|
||||
// Ram layer config message:
|
||||
@@ -407,13 +409,13 @@ const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0
|
||||
// BBR layer config message:
|
||||
// b5 62 06 8a 13 00 00 02 00 00 ca 00 91 20 00 c5 00 91 20 00 b1 00 91 20 00 f8 4e
|
||||
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_NMEA_RAM[] = {
|
||||
static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[] = {
|
||||
/*0x00, 0x01, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00 */
|
||||
0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91,
|
||||
0x20, 0x00, 0xac, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00, 0xbb, 0x00, 0x91, 0x20, 0x00};
|
||||
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5,
|
||||
0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00};
|
||||
static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5,
|
||||
0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00};
|
||||
|
||||
// Turn off text info messages:
|
||||
// Ram layer config message:
|
||||
@@ -432,17 +434,17 @@ const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00,
|
||||
// b5 62 06 8a 0e 00 00 04 00 00 bb 00 91 20 01 ac 00 91 20 01 6d b6
|
||||
// Doing this for the FLASH layer isn't really required since we save the config to flash later
|
||||
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
|
||||
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
|
||||
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
|
||||
|
||||
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xbb, 0x00, 0x91,
|
||||
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xbb, 0x00, 0x91,
|
||||
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31,
|
||||
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
|
||||
const uint8_t GPS::_message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31,
|
||||
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
|
||||
static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xbb, 0x00, 0x91,
|
||||
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
|
||||
static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xbb, 0x00, 0x91,
|
||||
0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
|
||||
static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31,
|
||||
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
|
||||
static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31,
|
||||
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
|
||||
|
||||
/*
|
||||
Operational issues with the M10:
|
||||
@@ -462,7 +464,7 @@ the PM config. Lets try without it.
|
||||
PMREQ sort of works with SBAS, but the awake time is too short to re-acquire any SBAS sats.
|
||||
The defination of "Got Fix" doesn't seem to include SBAS. Much more too this...
|
||||
Even if it was, it can take minutes (up to 12.5),
|
||||
even under good sat visability conditions to re-acquire the SBAS data.
|
||||
even under good sat visibility conditions to re-acquire the SBAS data.
|
||||
|
||||
Another effect fo the quick transition to sleep is that no other sats will be acquired so the
|
||||
sat count will tend to remain at what the initial fix was.
|
||||
@@ -475,4 +477,4 @@ b5 62 06 8a 0e 00 00 01 00 00 20 00 31 10 00 05 00 31 10 00 46 87
|
||||
|
||||
BBR layer config message:
|
||||
b5 62 06 8a 0e 00 00 02 00 00 20 00 31 10 00 05 00 31 10 00 47 94
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -79,7 +79,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
}
|
||||
|
||||
// Trigger the refresh in GxEPD2
|
||||
LOG_DEBUG("Updating E-Paper");
|
||||
LOG_DEBUG("Update E-Paper");
|
||||
adafruitDisplay->nextPage();
|
||||
|
||||
// End the update process
|
||||
@@ -123,7 +123,7 @@ void EInkDisplay::setDetected(uint8_t detected)
|
||||
// Connect to the display - variant specific
|
||||
bool EInkDisplay::connect()
|
||||
{
|
||||
LOG_INFO("Doing EInk init");
|
||||
LOG_INFO("Do EInk init");
|
||||
|
||||
#ifdef PIN_EINK_EN
|
||||
// backlight power, HIGH is backlight on, LOW is off
|
||||
|
||||
@@ -119,7 +119,7 @@ void EInkDynamicDisplay::endOrDetach()
|
||||
awaitRefresh();
|
||||
else {
|
||||
// Async begins
|
||||
LOG_DEBUG("Async full-refresh begins (dropping frames)");
|
||||
LOG_DEBUG("Async full-refresh begins (drop frames)");
|
||||
notifyLater(intervalPollAsyncRefresh, DUE_POLL_ASYNCREFRESH, true); // Hand-off to NotifiedWorkerThread
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,7 @@ bool EInkDynamicDisplay::determineMode()
|
||||
checkFastRequested();
|
||||
|
||||
if (refresh == UNSPECIFIED)
|
||||
LOG_WARN("There was a flaw in the determineMode() logic.");
|
||||
LOG_WARN("There was a flaw in the determineMode() logic");
|
||||
|
||||
// -- Decision has been reached --
|
||||
applyRefreshMode();
|
||||
@@ -469,7 +469,7 @@ void EInkDynamicDisplay::joinAsyncRefresh()
|
||||
if (!asyncRefreshRunning)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Joining an async refresh in progress");
|
||||
LOG_DEBUG("Join an async refresh in progress");
|
||||
|
||||
// Continually poll the BUSY pin
|
||||
while (adafruitDisplay->epd2.isBusy())
|
||||
|
||||
@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "Screen.h"
|
||||
#include "../userPrefs.h"
|
||||
#include "PowerMon.h"
|
||||
#include "Throttle.h"
|
||||
#include "configuration.h"
|
||||
@@ -101,9 +100,9 @@ std::vector<MeshModule *> moduleFrames;
|
||||
static char ourId[5];
|
||||
|
||||
// vector where symbols (string) are displayed in bottom corner of display.
|
||||
std::vector<std::string> functionSymbals;
|
||||
// string displayed in bottom right corner of display. Created from elements in functionSymbals vector
|
||||
std::string functionSymbalString = "";
|
||||
std::vector<std::string> functionSymbol;
|
||||
// string displayed in bottom right corner of display. Created from elements in functionSymbol vector
|
||||
std::string functionSymbolString = "";
|
||||
|
||||
#if HAS_GPS
|
||||
// GeoCoord object for the screen
|
||||
@@ -127,7 +126,7 @@ static bool heartbeat = false;
|
||||
/// Check if the display can render a string (detect special chars; emoji)
|
||||
static bool haveGlyphs(const char *str)
|
||||
{
|
||||
#if defined(OLED_PL) || defined(OLED_UA) || defined(OLED_RU)
|
||||
#if defined(OLED_PL) || defined(OLED_UA) || defined(OLED_RU) || defined(OLED_CS)
|
||||
// Don't want to make any assumptions about custom language support
|
||||
return true;
|
||||
#endif
|
||||
@@ -242,11 +241,11 @@ static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
// draw overlay in bottom right corner of screen to show when notifications are muted or modifier key is active
|
||||
static void drawFunctionOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
|
||||
{
|
||||
// LOG_DEBUG("Drawing function overlay");
|
||||
if (functionSymbals.begin() != functionSymbals.end()) {
|
||||
// LOG_DEBUG("Draw function overlay");
|
||||
if (functionSymbol.begin() != functionSymbol.end()) {
|
||||
char buf[64];
|
||||
display->setFont(FONT_SMALL);
|
||||
snprintf(buf, sizeof(buf), "%s", functionSymbalString.c_str());
|
||||
snprintf(buf, sizeof(buf), "%s", functionSymbolString.c_str());
|
||||
display->drawString(SCREEN_WIDTH - display->getStringWidth(buf), SCREEN_HEIGHT - FONT_HEIGHT_SMALL, buf);
|
||||
}
|
||||
}
|
||||
@@ -260,7 +259,7 @@ static void drawDeepSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state,
|
||||
EINK_ADD_FRAMEFLAG(display, COSMETIC);
|
||||
EINK_ADD_FRAMEFLAG(display, BLOCKING);
|
||||
|
||||
LOG_DEBUG("Drawing deep sleep screen");
|
||||
LOG_DEBUG("Draw deep sleep screen");
|
||||
|
||||
// Display displayStr on the screen
|
||||
drawIconScreen("Sleeping", display, state, x, y);
|
||||
@@ -269,7 +268,7 @@ static void drawDeepSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state,
|
||||
/// Used on eink displays when screen updates are paused
|
||||
static void drawScreensaverOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
|
||||
{
|
||||
LOG_DEBUG("Drawing screensaver overlay");
|
||||
LOG_DEBUG("Draw screensaver overlay");
|
||||
|
||||
EINK_ADD_FRAMEFLAG(display, COSMETIC); // Take the opportunity for a full-refresh
|
||||
|
||||
@@ -337,7 +336,7 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
|
||||
module_frame = state->currentFrame;
|
||||
// LOG_DEBUG("Screen is not in transition. Frame: %d", module_frame);
|
||||
}
|
||||
// LOG_DEBUG("Drawing Module Frame %d", module_frame);
|
||||
// LOG_DEBUG("Draw Module Frame %d", module_frame);
|
||||
MeshModule &pi = *moduleFrames.at(module_frame);
|
||||
pi.drawFrame(display, state, x, y);
|
||||
}
|
||||
@@ -396,7 +395,7 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
|
||||
display->drawFastImage(x, y, 16, 8, imgBuffer);
|
||||
}
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
|
||||
void Screen::drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode, float scale)
|
||||
{
|
||||
@@ -912,7 +911,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
|
||||
const meshtastic_MeshPacket &mp = devicestate.rx_text_message;
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(getFrom(&mp));
|
||||
// LOG_DEBUG("drawing text message from 0x%x: %s", mp.from,
|
||||
// LOG_DEBUG("Draw text message from 0x%x: %s", mp.from,
|
||||
// mp.decoded.variant.data.decoded.bytes);
|
||||
|
||||
// Demo for drawStringMaxWidth:
|
||||
@@ -958,55 +957,65 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
|
||||
display->setColor(WHITE);
|
||||
#ifndef EXCLUDE_EMOJI
|
||||
if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44D") == 0) {
|
||||
const char *msg = reinterpret_cast<const char *>(mp.decoded.payload.bytes);
|
||||
if (strcmp(msg, "\U0001F44D") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
|
||||
thumbup);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44E") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F44E") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
|
||||
thumbdown);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "❓") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F60A") == 0 || strcmp(msg, "\U0001F600") == 0 || strcmp(msg, "\U0001F642") == 0 ||
|
||||
strcmp(msg, "\U0001F609") == 0 ||
|
||||
strcmp(msg, "\U0001F601") == 0) { // matches 5 different common smileys, so that the phone user doesn't have to
|
||||
// remember which one is compatible
|
||||
display->drawXbm(x + (SCREEN_WIDTH - smiley_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - smiley_height) / 2 + 2 + 5, smiley_width, smiley_height,
|
||||
smiley);
|
||||
} else if (strcmp(msg, "❓") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - question_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - question_height) / 2 + 2 + 5, question_width, question_height,
|
||||
question);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "‼️") == 0) {
|
||||
} else if (strcmp(msg, "‼️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - bang_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - bang_height) / 2 + 2 + 5,
|
||||
bang_width, bang_height, bang);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F4A9") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F4A9") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - poo_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - poo_height) / 2 + 2 + 5,
|
||||
poo_width, poo_height, poo);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\xa4\xa3") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F923") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - haha_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - haha_height) / 2 + 2 + 5,
|
||||
haha_width, haha_height, haha);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44B") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F44B") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - wave_icon_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - wave_icon_height) / 2 + 2 + 5, wave_icon_width,
|
||||
wave_icon_height, wave_icon);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F920") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F920") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - cowboy_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cowboy_height) / 2 + 2 + 5, cowboy_width, cowboy_height,
|
||||
cowboy);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F42D") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F42D") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - deadmau5_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - deadmau5_height) / 2 + 2 + 5, deadmau5_width, deadmau5_height,
|
||||
deadmau5);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
|
||||
} else if (strcmp(msg, "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - sun_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - sun_height) / 2 + 2 + 5,
|
||||
sun_width, sun_height, sun);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\u2614") == 0) {
|
||||
} else if (strcmp(msg, "\u2614") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - rain_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - rain_height) / 2 + 2 + 10,
|
||||
rain_width, rain_height, rain);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "☁️") == 0) {
|
||||
} else if (strcmp(msg, "☁️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - cloud_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cloud_height) / 2 + 2 + 5, cloud_width, cloud_height, cloud);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "🌫️") == 0) {
|
||||
} else if (strcmp(msg, "🌫️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - fog_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - fog_height) / 2 + 2 + 5,
|
||||
fog_width, fog_height, fog);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\x98\x88") == 0) {
|
||||
} else if (strcmp(msg, "\U0001F608") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - devil_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "♥️") == 0) {
|
||||
} else if (strcmp(msg, "♥️") == 0 || strcmp(msg, "\U0001F9E1") == 0 || strcmp(msg, "\U00002763") == 0 ||
|
||||
strcmp(msg, "\U00002764") == 0 || strcmp(msg, "\U0001F495") == 0 || strcmp(msg, "\U0001F496") == 0 ||
|
||||
strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F496") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart);
|
||||
} else {
|
||||
@@ -1410,7 +1419,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
}
|
||||
bool hasNodeHeading = false;
|
||||
|
||||
if (ourNode && (hasValidPosition(ourNode) || screen->hasHeading())) {
|
||||
if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) {
|
||||
const meshtastic_PositionLite &op = ourNode->position;
|
||||
float myHeading;
|
||||
if (screen->hasHeading())
|
||||
@@ -1419,7 +1428,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
myHeading = screen->estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
screen->drawCompassNorth(display, compassX, compassY, myHeading);
|
||||
|
||||
if (hasValidPosition(node)) {
|
||||
if (nodeDB->hasValidPosition(node)) {
|
||||
// display direction toward node
|
||||
hasNodeHeading = true;
|
||||
const meshtastic_PositionLite &p = node->position;
|
||||
@@ -1499,7 +1508,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif ARCH_PORTDUINO
|
||||
if (settingsMap[displayPanel] != no_screen) {
|
||||
LOG_DEBUG("Making TFTDisplay!");
|
||||
LOG_DEBUG("Make TFTDisplay!");
|
||||
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
} else {
|
||||
@@ -1546,7 +1555,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
|
||||
|
||||
if (on != screenOn) {
|
||||
if (on) {
|
||||
LOG_INFO("Turning on screen");
|
||||
LOG_INFO("Turn on screen");
|
||||
powerMon->setState(meshtastic_PowerMon_State_Screen_On);
|
||||
#ifdef T_WATCH_S3
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
||||
@@ -1581,7 +1590,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
|
||||
// eInkScreensaver parameter is usually NULL (default argument), default frame used instead
|
||||
setScreensaverFrames(einkScreensaver);
|
||||
#endif
|
||||
LOG_INFO("Turning off screen");
|
||||
LOG_INFO("Turn off screen");
|
||||
dispdev->displayOff();
|
||||
#ifdef USE_ST7789
|
||||
SPI1.end();
|
||||
@@ -1709,7 +1718,7 @@ void Screen::setup()
|
||||
#endif
|
||||
serialSinceMsec = millis();
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
#if ARCH_PORTDUINO && !HAS_TFT
|
||||
if (settingsMap[touchscreenModule]) {
|
||||
touchScreenImpl1 =
|
||||
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
|
||||
@@ -1789,7 +1798,7 @@ int32_t Screen::runOnce()
|
||||
// serialSinceMsec adjusts for additional serial wait time during nRF52 bootup
|
||||
static bool showingBootScreen = true;
|
||||
if (showingBootScreen && (millis() > (logo_timeout + serialSinceMsec))) {
|
||||
LOG_INFO("Done with boot screen...");
|
||||
LOG_INFO("Done with boot screen");
|
||||
stopBootScreen();
|
||||
showingBootScreen = false;
|
||||
}
|
||||
@@ -1885,7 +1894,7 @@ int32_t Screen::runOnce()
|
||||
EINK_ADD_FRAMEFLAG(dispdev, COSMETIC);
|
||||
#endif
|
||||
|
||||
LOG_DEBUG("LastScreenTransition exceeded %ums transitioning to next frame", (millis() - lastScreenTransition));
|
||||
LOG_DEBUG("LastScreenTransition exceeded %ums transition to next frame", (millis() - lastScreenTransition));
|
||||
handleOnPress();
|
||||
}
|
||||
}
|
||||
@@ -1921,7 +1930,7 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat
|
||||
void Screen::setSSLFrames()
|
||||
{
|
||||
if (address_found.address) {
|
||||
// LOG_DEBUG("showing SSL frames");
|
||||
// LOG_DEBUG("Show SSL frames");
|
||||
static FrameCallback sslFrames[] = {drawSSLScreen};
|
||||
ui->setFrames(sslFrames, 1);
|
||||
ui->update();
|
||||
@@ -1933,7 +1942,7 @@ void Screen::setSSLFrames()
|
||||
void Screen::setWelcomeFrames()
|
||||
{
|
||||
if (address_found.address) {
|
||||
// LOG_DEBUG("showing Welcome frames");
|
||||
// LOG_DEBUG("Show Welcome frames");
|
||||
static FrameCallback frames[] = {drawWelcomeScreen};
|
||||
setFrameImmediateDraw(frames);
|
||||
}
|
||||
@@ -1999,7 +2008,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
uint8_t originalPosition = ui->getUiState()->currentFrame;
|
||||
FramesetInfo fsi; // Location of specific frames, for applying focus parameter
|
||||
|
||||
LOG_DEBUG("showing standard frames");
|
||||
LOG_DEBUG("Show standard frames");
|
||||
showingNormalScreen = true;
|
||||
|
||||
#ifdef USE_EINK
|
||||
@@ -2012,7 +2021,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
#endif
|
||||
|
||||
moduleFrames = MeshModule::GetMeshModulesWithUIFrames();
|
||||
LOG_DEBUG("Showing %d module frames", moduleFrames.size());
|
||||
LOG_DEBUG("Show %d module frames", moduleFrames.size());
|
||||
#ifdef DEBUG_PORT
|
||||
int totalFrameCount = MAX_NUM_NODES + NUM_EXTRA_FRAMES + moduleFrames.size();
|
||||
LOG_DEBUG("Total frame count: %d", totalFrameCount);
|
||||
@@ -2058,7 +2067,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
focus = FOCUS_FAULT; // Change our "focus" parameter, to ensure we show the fault frame
|
||||
}
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame;
|
||||
#endif
|
||||
|
||||
@@ -2094,7 +2103,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
#endif
|
||||
|
||||
fsi.frameCount = numframes; // Total framecount is used to apply FOCUS_PRESERVE
|
||||
LOG_DEBUG("Finished building frames. numframes: %d", numframes);
|
||||
LOG_DEBUG("Finished build frames. numframes: %d", numframes);
|
||||
|
||||
ui->setFrames(normalFrames, numframes);
|
||||
ui->enableAllIndicators();
|
||||
@@ -2175,13 +2184,13 @@ void Screen::dismissCurrentFrame()
|
||||
bool dismissed = false;
|
||||
|
||||
if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) {
|
||||
LOG_INFO("Dismissing Text Message");
|
||||
LOG_INFO("Dismiss Text Message");
|
||||
devicestate.has_rx_text_message = false;
|
||||
dismissed = true;
|
||||
}
|
||||
|
||||
else if (currentFrame == framesetInfo.positions.waypoint && devicestate.has_rx_waypoint) {
|
||||
LOG_DEBUG("Dismissing Waypoint");
|
||||
LOG_DEBUG("Dismiss Waypoint");
|
||||
devicestate.has_rx_waypoint = false;
|
||||
dismissed = true;
|
||||
}
|
||||
@@ -2193,7 +2202,7 @@ void Screen::dismissCurrentFrame()
|
||||
|
||||
void Screen::handleStartFirmwareUpdateScreen()
|
||||
{
|
||||
LOG_DEBUG("showing firmware screen");
|
||||
LOG_DEBUG("Show firmware screen");
|
||||
showingNormalScreen = false;
|
||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame
|
||||
|
||||
@@ -2242,24 +2251,24 @@ void Screen::decreaseBrightness()
|
||||
/* TO DO: add little popup in center of screen saying what brightness level it is set to*/
|
||||
}
|
||||
|
||||
void Screen::setFunctionSymbal(std::string sym)
|
||||
void Screen::setFunctionSymbol(std::string sym)
|
||||
{
|
||||
if (std::find(functionSymbals.begin(), functionSymbals.end(), sym) == functionSymbals.end()) {
|
||||
functionSymbals.push_back(sym);
|
||||
functionSymbalString = "";
|
||||
for (auto symbol : functionSymbals) {
|
||||
functionSymbalString = symbol + " " + functionSymbalString;
|
||||
if (std::find(functionSymbol.begin(), functionSymbol.end(), sym) == functionSymbol.end()) {
|
||||
functionSymbol.push_back(sym);
|
||||
functionSymbolString = "";
|
||||
for (auto symbol : functionSymbol) {
|
||||
functionSymbolString = symbol + " " + functionSymbolString;
|
||||
}
|
||||
setFastFramerate();
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::removeFunctionSymbal(std::string sym)
|
||||
void Screen::removeFunctionSymbol(std::string sym)
|
||||
{
|
||||
functionSymbals.erase(std::remove(functionSymbals.begin(), functionSymbals.end(), sym), functionSymbals.end());
|
||||
functionSymbalString = "";
|
||||
for (auto symbol : functionSymbals) {
|
||||
functionSymbalString = symbol + " " + functionSymbalString;
|
||||
functionSymbol.erase(std::remove(functionSymbol.begin(), functionSymbol.end(), sym), functionSymbol.end());
|
||||
functionSymbolString = "";
|
||||
for (auto symbol : functionSymbol) {
|
||||
functionSymbolString = symbol + " " + functionSymbolString;
|
||||
}
|
||||
setFastFramerate();
|
||||
}
|
||||
@@ -2674,7 +2683,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
if (event->action == UIFrameEvent::Action::REGENERATE_FRAMESET)
|
||||
setFrames(FOCUS_MODULE);
|
||||
|
||||
// Regenerate the frameset, while attempting to maintain focus on the current frame
|
||||
// Regenerate the frameset, while Attempt to maintain focus on the current frame
|
||||
else if (event->action == UIFrameEvent::Action::REGENERATE_FRAMESET_BACKGROUND)
|
||||
setFrames(FOCUS_PRESERVE);
|
||||
|
||||
@@ -2689,7 +2698,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
int Screen::handleInputEvent(const InputEvent *event)
|
||||
{
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
// For the T-Watch, intercept touches to the 'toggle digital/analog watch face' button
|
||||
uint8_t watchFaceFrame = error_code ? 1 : 0;
|
||||
|
||||
@@ -2747,4 +2756,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
|
||||
} // namespace graphics
|
||||
#else
|
||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||
#endif // HAS_SCREEN
|
||||
#endif // HAS_SCREEN
|
||||
|
||||
@@ -24,8 +24,8 @@ class Screen
|
||||
void startFirmwareUpdateScreen() {}
|
||||
void increaseBrightness() {}
|
||||
void decreaseBrightness() {}
|
||||
void setFunctionSymbal(std::string) {}
|
||||
void removeFunctionSymbal(std::string) {}
|
||||
void setFunctionSymbol(std::string) {}
|
||||
void removeFunctionSymbol(std::string) {}
|
||||
void startAlert(const char *) {}
|
||||
void endAlert() {}
|
||||
};
|
||||
@@ -282,8 +282,8 @@ class Screen : public concurrency::OSThread
|
||||
void increaseBrightness();
|
||||
void decreaseBrightness();
|
||||
|
||||
void setFunctionSymbal(std::string sym);
|
||||
void removeFunctionSymbal(std::string sym);
|
||||
void setFunctionSymbol(std::string sym);
|
||||
void removeFunctionSymbol(std::string sym);
|
||||
|
||||
/// Stops showing the boot screen.
|
||||
void stopBootScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BOOT_SCREEN}); }
|
||||
@@ -327,10 +327,15 @@ class Screen : public concurrency::OSThread
|
||||
SKIPREST = false;
|
||||
return (uint8_t)ch;
|
||||
}
|
||||
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte char formats
|
||||
if (ch == 0xC2)
|
||||
if (ch == 0xC2 || ch == 0xC3)
|
||||
return (uint8_t)0;
|
||||
|
||||
#if defined(OLED_PL)
|
||||
@@ -422,6 +427,86 @@ class Screen : public concurrency::OSThread
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82 || ch == 0xD0 || ch == 0xD1)
|
||||
return (uint8_t)0;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OLED_CS)
|
||||
|
||||
switch (last) {
|
||||
case 0xC2: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)ch;
|
||||
}
|
||||
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
}
|
||||
|
||||
case 0xC4: {
|
||||
SKIPREST = false;
|
||||
if (ch == 140)
|
||||
return (uint8_t)(129); // Č
|
||||
if (ch == 141)
|
||||
return (uint8_t)(138); // č
|
||||
if (ch == 142)
|
||||
return (uint8_t)(130); // Ď
|
||||
if (ch == 143)
|
||||
return (uint8_t)(139); // ď
|
||||
if (ch == 154)
|
||||
return (uint8_t)(131); // Ě
|
||||
if (ch == 155)
|
||||
return (uint8_t)(140); // ě
|
||||
// Slovak specific glyphs
|
||||
if (ch == 185)
|
||||
return (uint8_t)(147); // Ĺ
|
||||
if (ch == 186)
|
||||
return (uint8_t)(148); // ĺ
|
||||
if (ch == 189)
|
||||
return (uint8_t)(149); // Ľ
|
||||
if (ch == 190)
|
||||
return (uint8_t)(150); // ľ
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xC5: {
|
||||
SKIPREST = false;
|
||||
if (ch == 135)
|
||||
return (uint8_t)(132); // Ň
|
||||
if (ch == 136)
|
||||
return (uint8_t)(141); // ň
|
||||
if (ch == 152)
|
||||
return (uint8_t)(133); // Ř
|
||||
if (ch == 153)
|
||||
return (uint8_t)(142); // ř
|
||||
if (ch == 160)
|
||||
return (uint8_t)(134); // Š
|
||||
if (ch == 161)
|
||||
return (uint8_t)(143); // š
|
||||
if (ch == 164)
|
||||
return (uint8_t)(135); // Ť
|
||||
if (ch == 165)
|
||||
return (uint8_t)(144); // ť
|
||||
if (ch == 174)
|
||||
return (uint8_t)(136); // Ů
|
||||
if (ch == 175)
|
||||
return (uint8_t)(145); // ů
|
||||
if (ch == 189)
|
||||
return (uint8_t)(137); // Ž
|
||||
if (ch == 190)
|
||||
return (uint8_t)(146); // ž
|
||||
// Slovak specific glyphs
|
||||
if (ch == 148)
|
||||
return (uint8_t)(151); // Ŕ
|
||||
if (ch == 149)
|
||||
return (uint8_t)(152); // ŕ
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte char formats
|
||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0xC4 || ch == 0xC5)
|
||||
return (uint8_t)0;
|
||||
|
||||
#endif
|
||||
|
||||
// If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the
|
||||
@@ -549,7 +634,7 @@ class Screen : public concurrency::OSThread
|
||||
|
||||
static void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
static void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
static void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
#include "graphics/fonts/OLEDDisplayFontsUA.h"
|
||||
#endif
|
||||
|
||||
#ifdef OLED_CS
|
||||
#include "graphics/fonts/OLEDDisplayFontsCS.h"
|
||||
#endif
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
@@ -27,14 +31,34 @@
|
||||
#define FONT_SMALL ArialMT_Plain_10_RU
|
||||
#else
|
||||
#ifdef OLED_UA
|
||||
#define FONT_SMALL ArialMT_Plain_10_UA
|
||||
#define FONT_SMALL ArialMT_Plain_10_UA // Height: 13
|
||||
#else
|
||||
#ifdef OLED_CS
|
||||
#define FONT_SMALL ArialMT_Plain_10_CS
|
||||
#else
|
||||
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef OLED_UA
|
||||
#define FONT_MEDIUM ArialMT_Plain_16_UA // Height: 19
|
||||
#else
|
||||
#ifdef OLED_CS
|
||||
#define FONT_MEDIUM ArialMT_Plain_16_CS
|
||||
#else
|
||||
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
|
||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||
#endif
|
||||
#endif
|
||||
#ifdef OLED_UA
|
||||
#define FONT_LARGE ArialMT_Plain_24_UA // Height: 28
|
||||
#else
|
||||
#ifdef OLED_CS
|
||||
#define FONT_LARGE ArialMT_Plain_24_CS // Height: 28
|
||||
#else
|
||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _fontHeight(font) ((font)[1] + 1) // height is position 1
|
||||
|
||||
@@ -347,7 +347,7 @@ static LGFX *tft = nullptr;
|
||||
#include <TFT_eSPI.h> // Graphics and font library for ILI9342 driver chip
|
||||
|
||||
static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
|
||||
#elif ARCH_PORTDUINO && HAS_SCREEN != 0
|
||||
#elif ARCH_PORTDUINO && HAS_SCREEN != 0 && !HAS_TFT
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
@@ -823,7 +823,7 @@ void TFTDisplay::setDetected(uint8_t detected)
|
||||
bool TFTDisplay::connect()
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
LOG_INFO("Doing TFT init");
|
||||
LOG_INFO("Do TFT init");
|
||||
#ifdef RAK14014
|
||||
tft = new TFT_eSPI;
|
||||
#else
|
||||
|
||||
1863
src/graphics/fonts/OLEDDisplayFontsCS.cpp
Normal file
1863
src/graphics/fonts/OLEDDisplayFontsCS.cpp
Normal file
File diff suppressed because it is too large
Load Diff
16
src/graphics/fonts/OLEDDisplayFontsCS.h
Normal file
16
src/graphics/fonts/OLEDDisplayFontsCS.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef OLEDDISPLAYFONTSCS_h
|
||||
#define OLEDDISPLAYFONTSCS_h
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <Arduino.h>
|
||||
#elif __MBED__
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Localization for Czech and Slovak language containing glyphs with diacritic.
|
||||
*/
|
||||
extern const uint8_t ArialMT_Plain_10_CS[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_16_CS[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_24_CS[] PROGMEM;
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,4 +8,6 @@
|
||||
#endif
|
||||
|
||||
extern const uint8_t ArialMT_Plain_10_UA[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_16_UA[] PROGMEM;
|
||||
extern const uint8_t ArialMT_Plain_24_UA[] PROGMEM;
|
||||
#endif
|
||||
@@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
|
||||
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
|
||||
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(DISPLAY_CLOCK_FRAME)
|
||||
const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0xe3, 0x1f,
|
||||
0xf3, 0x3f, 0x33, 0x30, 0x33, 0x33, 0x33, 0x33, 0x03, 0x33, 0xff, 0x33,
|
||||
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};
|
||||
@@ -56,6 +56,16 @@ static unsigned char thumbdown[] PROGMEM = {
|
||||
0x80, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#define smiley_height 30
|
||||
#define smiley_width 30
|
||||
static unsigned char smiley[] PROGMEM = {
|
||||
0x00, 0xfe, 0x0f, 0x00, 0x80, 0x01, 0x30, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x02,
|
||||
0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x10, 0x02, 0x0e, 0x0e, 0x10, 0x02, 0x09, 0x12, 0x10,
|
||||
0x01, 0x09, 0x12, 0x20, 0x01, 0x0f, 0x1e, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
|
||||
0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x81, 0x00, 0x20, 0x20,
|
||||
0x82, 0x00, 0x20, 0x10, 0x02, 0x01, 0x10, 0x10, 0x04, 0x02, 0x08, 0x08, 0x04, 0xfc, 0x07, 0x08, 0x08, 0x00, 0x00, 0x04,
|
||||
0x10, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x40, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x30, 0x00, 0x00, 0xfe, 0x0f, 0x00};
|
||||
|
||||
#define question_height 25
|
||||
#define question_width 25
|
||||
static unsigned char question[] PROGMEM = {
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
#define _MPR121_REG_CONFIG1 0x5C
|
||||
#define _MPR121_REG_CONFIG2 0x5D
|
||||
#define _MPR121_REG_ELECTRODE_CONFIG 0x5E
|
||||
#define _MPR121_REG_AUTOCONF_CTRL0 0x7B
|
||||
#define _MPR121_REG_AUTOCONF_CTRL1 0x7C
|
||||
#define _MPR121_REG_SOFT_RESET 0x80
|
||||
|
||||
#define _KEY_MASK 0x0FFF // Key mask for the first 12 bits
|
||||
@@ -87,7 +89,7 @@ uint8_t MPR121_KeyMap[12] = {2, 5, 8, 11, 1, 4, 7, 10, 0, 3, 6, 9};
|
||||
|
||||
MPR121Keyboard::MPR121Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr)
|
||||
{
|
||||
// LOG_DEBUG("MPR121 @ %02x\n", m_addr);
|
||||
// LOG_DEBUG("MPR121 @ %02x", m_addr);
|
||||
state = Init;
|
||||
last_key = -1;
|
||||
last_tap = 0L;
|
||||
@@ -116,7 +118,7 @@ void MPR121Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
|
||||
|
||||
void MPR121Keyboard::reset()
|
||||
{
|
||||
LOG_DEBUG("MPR121 Resetting...");
|
||||
LOG_DEBUG("MPR121 Reset");
|
||||
// Trigger a MPR121 Soft Reset
|
||||
if (m_wire) {
|
||||
m_wire->beginTransmission(m_addr);
|
||||
@@ -136,14 +138,14 @@ void MPR121Keyboard::reset()
|
||||
// Set touch release thresholds
|
||||
for (uint8_t i = 0; i < 12; i++) {
|
||||
// Set touch threshold
|
||||
writeRegister(_MPR121_REG_TOUCH_THRESHOLD + (i * 2), 15);
|
||||
writeRegister(_MPR121_REG_TOUCH_THRESHOLD + (i * 2), 10);
|
||||
delay(20);
|
||||
// Set release threshold
|
||||
writeRegister(_MPR121_REG_RELEASE_THRESHOLD + (i * 2), 7);
|
||||
writeRegister(_MPR121_REG_RELEASE_THRESHOLD + (i * 2), 5);
|
||||
delay(20);
|
||||
}
|
||||
// Configure filtering and baseline registers
|
||||
writeRegister(_MPR121_REG_MAX_HALF_DELTA_RISING, 0x01);
|
||||
writeRegister(_MPR121_REG_MAX_HALF_DELTA_RISING, 0x05);
|
||||
delay(20);
|
||||
writeRegister(_MPR121_REG_MAX_HALF_DELTA_FALLING, 0x01);
|
||||
delay(20);
|
||||
@@ -153,7 +155,7 @@ void MPR121Keyboard::reset()
|
||||
delay(20);
|
||||
writeRegister(_MPR121_REG_NOISE_HALF_DELTA_TOUCHED, 0x00);
|
||||
delay(20);
|
||||
writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_RISING, 0x0e);
|
||||
writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_RISING, 0x05);
|
||||
delay(20);
|
||||
writeRegister(_MPR121_REG_NOISE_COUNT_LIMIT_FALLING, 0x01);
|
||||
delay(20);
|
||||
@@ -165,20 +167,21 @@ void MPR121Keyboard::reset()
|
||||
delay(20);
|
||||
writeRegister(_MPR121_REG_FILTER_DELAY_COUNT_TOUCHED, 0x00);
|
||||
delay(20);
|
||||
// Set Debounce to 0x02
|
||||
writeRegister(_MPR121_REG_DEBOUNCE, 0x00);
|
||||
writeRegister(_MPR121_REG_AUTOCONF_CTRL0, 0x04); // Auto-config enable
|
||||
delay(20);
|
||||
// Set Filter1 itterations and discharge current 6x and 16uA respectively (0x10)
|
||||
writeRegister(_MPR121_REG_CONFIG1, 0x10);
|
||||
writeRegister(_MPR121_REG_AUTOCONF_CTRL1, 0x00); // Ensure no auto-config interrupt
|
||||
delay(20);
|
||||
// Set CDT to 0.5us, Filter2 itterations to 4x, and Sample interval = 0 (0x20)
|
||||
writeRegister(_MPR121_REG_CONFIG2, 0x20);
|
||||
writeRegister(_MPR121_REG_DEBOUNCE, 0x02);
|
||||
delay(20);
|
||||
writeRegister(_MPR121_REG_CONFIG1, 0x20);
|
||||
delay(20);
|
||||
writeRegister(_MPR121_REG_CONFIG2, 0x21);
|
||||
delay(20);
|
||||
// Enter run mode by Seting partial filter calibration tracking, disable proximity detection, enable 12 channels
|
||||
writeRegister(_MPR121_REG_ELECTRODE_CONFIG,
|
||||
ECR_CALIBRATION_TRACK_FROM_PARTIAL_FILTER | ECR_PROXIMITY_DETECTION_OFF | ECR_TOUCH_DETECTION_12CH);
|
||||
ECR_CALIBRATION_TRACK_FROM_FULL_FILTER | ECR_PROXIMITY_DETECTION_OFF | ECR_TOUCH_DETECTION_12CH);
|
||||
delay(100);
|
||||
LOG_DEBUG("MPR121 Running");
|
||||
LOG_DEBUG("MPR121 Run");
|
||||
state = Idle;
|
||||
}
|
||||
|
||||
@@ -427,4 +430,4 @@ void MPR121Keyboard::writeRegister(uint8_t reg, uint8_t value)
|
||||
if (writeCallback) {
|
||||
writeCallback(m_addr, data[0], &(data[1]), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ int32_t ScanAndSelectInput::runOnce()
|
||||
// If: "no messages added" alert screen currently shown
|
||||
if (alertingNoMessage) {
|
||||
// Dismiss the alert screen several seconds after it appears
|
||||
if (now > alertingSinceMs + durationAlertMs) {
|
||||
if (!Throttle::isWithinTimespanMs(alertingSinceMs, durationAlertMs)) {
|
||||
alertingNoMessage = false;
|
||||
screen->endAlert();
|
||||
}
|
||||
@@ -74,9 +74,9 @@ int32_t ScanAndSelectInput::runOnce()
|
||||
|
||||
// Existing press
|
||||
else {
|
||||
// Duration enough for long press
|
||||
// Longer than shortpress window
|
||||
// Long press not yet fired (prevent repeat firing while held)
|
||||
if (!longPressFired && Throttle::isWithinTimespanMs(downSinceMs, durationLongMs)) {
|
||||
if (!longPressFired && !Throttle::isWithinTimespanMs(downSinceMs, durationLongMs)) {
|
||||
longPressFired = true;
|
||||
longPress();
|
||||
}
|
||||
@@ -91,7 +91,9 @@ int32_t ScanAndSelectInput::runOnce()
|
||||
// Button newly released
|
||||
// Long press event didn't already fire
|
||||
if (held && !longPressFired) {
|
||||
// Duration enough for short press
|
||||
// Duration within shortpress window
|
||||
// - longer than durationShortPress (debounce)
|
||||
// - shorter than durationLongPress
|
||||
if (!Throttle::isWithinTimespanMs(downSinceMs, durationShortMs)) {
|
||||
shortPress();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "TouchScreenBase.h"
|
||||
#include "main.h"
|
||||
|
||||
#if defined(RAK14014) && !defined(MESHTASTIC_EXCLUDE_CANNEDMESSAGES)
|
||||
#include "modules/CannedMessageModule.h"
|
||||
#endif
|
||||
|
||||
#ifndef TIME_LONG_PRESS
|
||||
#define TIME_LONG_PRESS 400
|
||||
#endif
|
||||
@@ -102,12 +106,30 @@ int32_t TouchScreenBase::runOnce()
|
||||
}
|
||||
_touchedOld = touched;
|
||||
|
||||
#if defined RAK14014
|
||||
// Speed up the processing speed of the keyboard in virtual keyboard mode
|
||||
auto state = cannedMessageModule->getRunState();
|
||||
if (state == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
if (_tapped) {
|
||||
_tapped = false;
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
|
||||
LOG_DEBUG("action TAP(%d/%d)", _last_x, _last_y);
|
||||
}
|
||||
} else {
|
||||
if (_tapped && (time_t(millis()) - _start) > TIME_LONG_PRESS - 50) {
|
||||
_tapped = false;
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
|
||||
LOG_DEBUG("action TAP(%d/%d)", _last_x, _last_y);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// fire TAP event when no 2nd tap occured within time
|
||||
if (_tapped && (time_t(millis()) - _start) > TIME_LONG_PRESS - 50) {
|
||||
_tapped = false;
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
|
||||
LOG_DEBUG("action TAP(%d/%d)", _last_x, _last_y);
|
||||
}
|
||||
#endif
|
||||
|
||||
// fire LONG_PRESS event without the need for release
|
||||
if (touched && (time_t(millis()) - _start) > TIME_LONG_PRESS) {
|
||||
@@ -134,4 +156,4 @@ void TouchScreenBase::hapticFeedback()
|
||||
drv.setWaveform(1, 0); // end waveform
|
||||
drv.go();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ void CardKbI2cImpl::init()
|
||||
{
|
||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN)
|
||||
if (cardkb_found.address == 0x00) {
|
||||
LOG_DEBUG("Rescanning for I2C keyboard");
|
||||
LOG_DEBUG("Rescan for I2C keyboard");
|
||||
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR, MPR121_KB_ADDR};
|
||||
uint8_t i2caddr_asize = 4;
|
||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||
@@ -49,10 +49,11 @@ void CardKbI2cImpl::init()
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address);
|
||||
if (cardkb_found.address == 0x00) {
|
||||
disable();
|
||||
return;
|
||||
} else {
|
||||
LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -34,7 +34,7 @@ int32_t KbI2cBase::runOnce()
|
||||
switch (cardkb_found.port) {
|
||||
case ScanI2C::WIRE1:
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
LOG_DEBUG("Using I2C Bus 1 (the second one)");
|
||||
LOG_DEBUG("Use I2C Bus 1 (the second one)");
|
||||
i2cBus = &Wire1;
|
||||
if (cardkb_found.address == BBQ10_KB_ADDR) {
|
||||
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire1);
|
||||
@@ -46,7 +46,7 @@ int32_t KbI2cBase::runOnce()
|
||||
break;
|
||||
#endif
|
||||
case ScanI2C::WIRE:
|
||||
LOG_DEBUG("Using I2C Bus 0 (the first one)");
|
||||
LOG_DEBUG("Use I2C Bus 0 (the first one)");
|
||||
i2cBus = &Wire;
|
||||
if (cardkb_found.address == BBQ10_KB_ADDR) {
|
||||
Q10keyboard.begin(BBQ10_KB_ADDR, &Wire);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user