Compare commits

..

484 Commits

Author SHA1 Message Date
Thomas Göttgens
2740a56944 tryfix: init change for BME680 (#3965) 2024-05-31 19:46:42 -05:00
fzellini
ffff2a03fc dragino trackerd (#4002)
* added AHTx0 sensor

* AHT10 definition in protobuf

* AHT10 definition in protobuf

* protobufs

* Management of AHT20+BMP280 module

* missing newline in log

* missing newline in log

* dragino trackerd support

* dragino trackerd support

* revert back .gitmodules

* reverted gitignore

* merged telemetry.pb.h

* merged telemetry.pb.h

* removed extra script, now bin version works

* reverted

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-31 13:05:40 -05:00
Ben Meadors
4fa2427b8c Trunk variants 2024-05-31 11:18:06 -05:00
fzellini
eddda3ca43 added AHTx0 sensor (#3977)
* added AHTx0 sensor

* AHT10 definition in protobuf

* AHT10 definition in protobuf

* protobufs

* Management of AHT20+BMP280 module

* missing newline in log

* missing newline in log

* reverted

* reverted .gitignore

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-31 11:17:53 -05:00
Ben Meadors
17142f8778 Add support for RadioMaster Bandit Nano (#4005)
* Add support for RadioMaster Bandit Nano

* Add fan to init and sleep
2024-05-31 10:56:04 -05:00
jonagnew
953aa4d091 Tracker v1.1 - fix pin 3 description in variant.h (#3990)
Schematic shows the following:
Pin 3 is Vext on v1.1 - HIGH enables LDO for Vext rail which goes to:
 GPS UC6580: GPS V_DET(8), VDD_IO(7), DCDC_IN(21), pulls up RESETN(17), D_SEL(33) and BOOT_MODE(34) through 10kR 
GPS LNA SW7125DE: VCC(4), pulls up SHDN(5) through 10kR
OLED: VDD, LEDA (through diode)

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-31 10:55:20 -05:00
Aaron.Lee
b9edc7563b Update the Heltec board battery level read accuracy. (#3955)
* Update variant.h

Update the Heltec board battery voltage read parameter.

* Update variant.h

Update the Heltec board battery voltage read parameter.

* Update variant.h

Update the Heltec board battery voltage read parameter.

* Update variant.h

Update the Heltec board battery voltage read parameter.
2024-05-31 10:55:05 -05:00
github-actions[bot]
c88278724c [create-pull-request] automated change (#4003)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-05-31 07:15:41 -05:00
Jonathan Bennett
54bccb898e Run tzset() and localtime() in getTZOffset() to ensure proper timezone offset (#3999)
* Run tzset() and localtime() in getTZOffset() to ensure proper timezone offset

* Try #2 to fix timezone/DST
2024-05-31 07:15:16 -05:00
Jonathan Bennett
8d90c496d0 Don't send potentially bogus timestamps with fixed location (#4001) 2024-05-31 07:14:33 -05:00
Ben Meadors
10e3040494 Add support for to_callsign on GeoChats for ATAK (#3996) 2024-05-30 18:49:08 -05:00
Mike
f138eaa970 Fix original esp32 boot init panic (#3985)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-30 10:59:10 -05:00
github-actions[bot]
cd8a7e44a8 [create-pull-request] automated change (#3992)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-05-30 09:08:32 -05:00
Ben Meadors
0b48663cbc Don't alloc NodeInfo replies when channel utilization is > 40% (#3991)
* Don't alloc NodeInfo replies when channel utilization is > 40%

* Commit

* Logs
2024-05-30 08:49:01 -05:00
Ben Meadors
af9d825266 Send own node-info earlier and move others to the end of want-config flow (#3949)
* Send own node-info earlier and move others to the end of want-config flow

* Special nonce skips other nodeinfos

* Missed it
2024-05-28 19:25:19 -05:00
Neil Hao
038413f46f User experience improvement - app battery icon (#3979)
* 'app_battery_icon'

* Undo VS automatic modifications to this file

* 'app_battery_icon_2'
2024-05-28 06:30:15 -05:00
andrew-moroz
77cf5c6200 Fix time updates from client device and potentially incorrect UI frame receiving 'toggle watch face' button tap (#3974) 2024-05-26 07:04:31 -05:00
Mike
aa33ad1d58 Fix memory leak when there's no display (#3972) 2024-05-26 06:42:44 -05:00
Jonathan Bennett
34553c9714 Bump portduino to pick up improvements to reboot() (#3975) 2024-05-26 06:42:23 -05:00
capslockapocalypse
2233507667 Added "Hops away" on display (#3934)
* Added "Hops away" on display

Added in logic that displays "hops away" instead of signal strength when the node is more than 0 hops away.

* Added comment

* Update extensions.json to same as master

* attempt 2 at reverting extensions JSON

* Attempt 3 at getting extensions right

* Take 4. should be reverting to before my edits

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-24 08:08:21 -05:00
Thomas Göttgens
9a38a4b024 Merge pull request #3966 from andrew-moroz/t-watch-fix
t-watch-fix: Fully insulate T-Watch free text updates from other hardware platforms
2024-05-24 08:57:37 +02:00
Andrew Moroz
1d288414a5 t-watch-fix: Fully insulate T-Watch free text updates from other hardware platforms 2024-05-24 00:02:03 -04:00
andrew-moroz
2f9dc813d3 t-watch-updates: Add canned message free text via touch keyboard and watch face frames to T-Watch S3 (#3941)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-23 07:21:27 -05:00
github-actions[bot]
1a253dccc3 [create-pull-request] automated change (#3964)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-05-23 07:20:13 -05:00
Ben Meadors
7d873eb06b Add exclude emoji macro 2024-05-22 20:40:26 -05:00
868meshbot
1631462db1 Oled screen emojis (#3940)
* Update images.h

Add some fun emojis

* Update Screen.cpp

Update Screen.cpp to display single emojis on the OLED of devices, if a single known emoji is detected

* Update images.h

add ? ! fog emojis

* Update Screen.cpp

add logic for new emojis

* Update Screen.cpp

correct formatting

* Update images.h

correct formatting

* Update Screen.cpp

change formatting via trunk application

* Update images.h

change formatting based on trunk application

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-22 19:28:30 -05:00
Jonathan Bennett
7bcb8f1fee Portduino: Catch the keyboard power button and initiate poweroff (#3953) 2024-05-22 07:54:06 -05:00
Mike
0c9da9aec7 Update platformio/espressif32 to the latest 6.7.0 (#3899)
* Bump platfomio/espressif32 version to latest 6.7.0

* Fix deprecated constants

* Remove pin defs already defined by the framework

* ESP_EXT1_WAKEUP_ALL_LOW is deprecated for any target except esp32

* Enable LTO and use newlib nano flavor

* Make trunk happy

* Respect build_unflags of base env

* Recover float printfing

* Disable BLE_SM_PAIR_AUTHREQ_SC

* Distribute BLE_SM_PAIR_KEY_DIST_ID too

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-21 21:02:09 -05:00
todd-herbert
a12b9922ed Screen changes from time deltas to timestamps after 15 minutes (#3935)
* E-Ink displays sometimes use timestamp instead of delta

* Allow users to disable E-Ink screensaver

* Clarify variable's purpose

* Operator order oopsie

* Picky print problem

* Implement for all display, not just E-Ink

* Align "unknown age" behavior with existing code

* One more use of timestamp, if screen is wide enough
2024-05-21 16:00:04 -05:00
todd-herbert
cdf86f4166 Change NRF_APM USB detection code (#3939) 2024-05-21 15:58:05 -05:00
github-actions[bot]
040b851615 [create-pull-request] automated change (#3950)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2024-05-21 14:40:31 -05:00
Jonathan Bennett
d19607ba98 Look in the right place for .debs 2024-05-21 11:23:29 -05:00
Jonathan Bennett
b829ee795d re-add .deb download to build 2024-05-21 10:37:26 -05:00
Ben Meadors
2fdc2e2c3c Perhaps a wildcard shall I seek 2024-05-21 09:07:47 -05:00
Ben Meadors
b9a6d21dff Add EoRA-S3 2024-05-21 07:45:24 -05:00
Ben Meadors
8c5dee5881 Remove download 2024-05-21 07:04:18 -05:00
Ben Meadors
55d46bae92 Update build_raspbian_armv7l.yml 2024-05-21 06:56:16 -05:00
Jonathan Bennett
ed8abea11b Add final debug call for Portduino reboot (#3945) 2024-05-21 00:09:33 -05:00
Ben Meadors
5f107569f3 Put T-Beam supreme back to the future (#3944) 2024-05-20 19:48:10 -05:00
Ben Meadors
b68ef3d98a Revert "Fix TBeam Supreme woes (and upgrade platform)" (#3943) 2024-05-20 19:34:51 -05:00
Jonathan Bennett
34aec70998 No need to build Raspbian arm64 twice: Part 2 2024-05-19 23:44:12 -05:00
Jonathan Bennett
e8cdac8fa0 No need to build Raspbian arm64 twice 2024-05-19 23:31:33 -05:00
Jonathan Bennett
afae3a488e Move Raspbian Arm64 to new build scheme 2024-05-19 23:29:43 -05:00
Jonathan Bennett
85e238ca76 Better names for .deb artifacts 2024-05-19 21:12:47 -05:00
Jonathan Bennett
45b05c9896 Revert "Use the right arch name for armv7l builds"
This reverts commit 7d1a925892.
2024-05-19 20:39:11 -05:00
Jonathan Bennett
7d1a925892 Use the right arch name for armv7l builds 2024-05-19 20:16:33 -05:00
Jonathan Bennett
72fb8a30a1 No sudo on debian docker 2024-05-19 18:18:03 -05:00
Jonathan Bennett
1c67f491d4 Add deps install for armv7l builds 2024-05-19 18:13:12 -05:00
Jonathan Bennett
f7a4cd33b4 Add armv7 builds 2024-05-19 18:00:06 -05:00
Jorropo
3719ddac03 automatically propose to setup virtualenv if platformio is having issues in native build (#3923) 2024-05-19 07:25:05 -05:00
Ben Meadors
4a05874dba Try-fix: Remove logging of actual payload strings (and compressed) for TAK packets (#3922)
* Remove logging of actual payload strings (and compressed) for TAK packets

* Don't assert / reboot. Log error and skip decode
2024-05-19 07:24:10 -05:00
Jonathan Bennett
84d3117a7a Lock Portduino to MAGIC_USB_BATTERY_LEVEL for now (#3894) 2024-05-18 12:21:35 -05:00
Thomas Göttgens
300b26c6b5 Merge pull request #3925 from meshtastic/init-variant
PLEASE TEST move the power rail init earlier in the startup process on 4630
2024-05-18 15:33:06 +02:00
Thomas Göttgens
cf0424922a target does not use the powerrail 2024-05-18 10:48:57 +02:00
Thomas Göttgens
7ef9fec446 PLEASE TEST move the power rail init earlier in the startup process on 4630 2024-05-18 10:48:57 +02:00
Thomas Göttgens
2244b0efec Merge pull request #3930 from meshtastic/screen-pinning
remove screen pinning for pico targets
2024-05-18 10:43:45 +02:00
Thomas Göttgens
108dfdc2ec update trunk 2024-05-18 10:41:32 +02:00
Thomas Göttgens
b161649989 remove screen pinning for pico targets 2024-05-18 10:22:07 +02:00
Jonathan Bennett
a2284e3d52 DEBIAN is case sensitive 2024-05-17 03:32:11 -05:00
Thomas Göttgens
ce40f91613 Merge pull request #3924 from meshtastic/Stop-overwriting-my-config
debconf expects absolute paths.
2024-05-17 09:36:52 +02:00
Jonathan Bennett
314d2e2da1 debconf expects absolute paths. 2024-05-17 02:34:18 -05:00
Ben Meadors
b4a7e78d18 Don't reboot for certain config prefs and make accelerometer thread re-entrant (#3889)
* Don't reboot for certain config prefs and make accelerometer thread re-entrant

* WHOOPS

* Don't reboot for LED heartbeat and button press

* Remove TZ
2024-05-16 17:27:36 -05:00
todd-herbert
f3cf9a5e71 Adjust refresh for Heltec Wireless Paper V1.1 (#3913) 2024-05-16 15:37:09 -05:00
Thomas Göttgens
8e35e19fda Merge pull request #3915 from meshtastic/libpax-rssi
implements #3885
2024-05-16 21:20:33 +02:00
Thomas Göttgens
14839bd9ba Merge branch 'master' into libpax-rssi 2024-05-16 19:44:24 +02:00
Thomas Göttgens
f109bc25c9 Merge pull request #3918 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-05-16 19:44:03 +02:00
caveman99
0976705f25 [create-pull-request] automated change 2024-05-16 17:43:23 +00:00
Thomas Göttgens
14392c22fd Merge pull request #3912 from meshtastic/fix-tbeam-s3
Fix TBeam Supreme woes (and upgrade platform)
2024-05-16 17:38:13 +02:00
Thomas Göttgens
10010baacc Merge pull request #3917 from rcarteraz/patch-1
remove has screen = 0 from wsl variant
2024-05-16 17:37:37 +02:00
Thomas Göttgens
8c327cc573 Merge pull request #3904 from meshtastic/lib-update
update sensor libs
2024-05-16 17:37:07 +02:00
Thomas Göttgens
4087bd93a9 Axe trunk from check
We run that anyway as a separate job No need to run it in the matrix.
2024-05-16 17:35:14 +02:00
rcarteraz
57575f8e49 remove has screen = 0 2024-05-16 08:11:46 -07:00
Thomas Göttgens
d02e12a424 fix include path 2024-05-16 17:03:04 +02:00
Thomas Göttgens
fce281f54c update sensor libs 2024-05-16 17:03:04 +02:00
Thomas Göttgens
d95e3acab3 implements #3885 2024-05-16 15:52:22 +02:00
Ben Meadors
cc864291c2 Merge branch 'master' into fix-tbeam-s3 2024-05-16 07:49:09 -05:00
Thomas Göttgens
c04c589ae7 Merge pull request #3906 from Jorropo/remove-unused-imports/platformio-custom
bin: remove unused imports from platformio-custom.py
2024-05-16 14:47:29 +02:00
Ben Meadors
51d2795b26 Fix TBeam Supreme woes (and upgrade platform) 2024-05-16 07:46:47 -05:00
Jorropo
04837b3302 bin: remove unused imports from platformio-custom.py 2024-05-16 02:39:42 +02:00
Henrik Witt-Hansen
1d42a6c48f Fix static ip assignment on wifi for rp2040 (#3896)
by rearranging the arguments to match the expected input order.
The lwip library makes an internal reorder or the arguments
depending on the netmask to work with both ESP and Arduino
platforms.

The input order was incorrect when running on an rp2040 device.

Co-authored-by: Henrik Witt-Hansen <henrik@hardttoolkit.org>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-15 18:54:51 -05:00
Thomas Göttgens
4cd70f3cbd Merge pull request #3903 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-05-16 01:31:26 +02:00
caveman99
c18b4920ae [create-pull-request] automated change 2024-05-15 23:28:03 +00:00
Thomas Göttgens
eeb9a368f0 Merge pull request #3902 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-05-16 01:17:56 +02:00
Thomas Göttgens
306b8d3205 Merge branch 'master' into create-pull-request/patch 2024-05-16 01:17:37 +02:00
Thomas Göttgens
0c9eadc507 Resync 2024-05-16 01:16:05 +02:00
caveman99
fe2356ae87 [create-pull-request] automated change 2024-05-15 23:12:12 +00:00
Thomas Göttgens
c57d45ba52 Merge pull request #3893 from Dr-Gandalf/feature/veml7700
Implementation of the sensor VEML7700
2024-05-16 01:11:35 +02:00
Thomas Göttgens
fc03eee4d9 Merge branch 'master' into feature/veml7700 2024-05-16 01:09:38 +02:00
Thomas Göttgens
53dea44983 Revert "Merge pull request #3898 from meshtastic/create-pull-request/patch"
This reverts commit 938aba481a, reversing
changes made to 7810e59b0c.
2024-05-16 01:08:52 +02:00
Thomas Göttgens
3342395a0b fix generated files 2024-05-16 01:04:38 +02:00
Thomas Göttgens
6dbc858102 Revert "tryfix proto conflict"
This reverts commit 79628c73cd.
2024-05-16 00:26:01 +02:00
Thomas Göttgens
79628c73cd tryfix proto conflict 2024-05-16 00:23:51 +02:00
Thomas Göttgens
eaa7fcf3dc Revert "Updated protobufs submodule"
This reverts commit 022e1f472d.
2024-05-16 00:23:03 +02:00
Thomas Göttgens
861bec05f4 Merge pull request #3901 from Jorropo/remove-unused-import
bin: remove unused import in buildinfo.py
2024-05-15 23:56:46 +02:00
Jorge Castillo
ce25381f67 fix unrelated change 2024-05-15 17:13:28 -04:00
Jorge Castillo
e08c808c3f fix log line 2024-05-15 17:06:23 -04:00
Jorropo
9e8ca69a11 bin: remove unused import in buildinfo.py
This was originally added in b1c30f0650 and it now do nothing since 361556a6a7 because it now use readprops.
2024-05-15 23:00:12 +02:00
Ken McGuire
bd9156de24 GPS Chechsum failures (#3900)
* Portduino multiple logging levels

* Fixes based on GPSFan work

* Fix derped logic

* Correct size field for AID message

* Reformat to add comments, beginning of GPS rework

* Update PM2 message for Neo-6

* Correct ECO mode logic as ECO mode is only for Neo-6

* Cleanup ubx.h add a few more comments

* GPS rework, changes for M8 and stub for M10

* Add VALSET commands for u-blox M10 receivers

* Add VALSET commands for u-blox M10 receivers
tweak M8 commands
add comments for VALSET configuration commands

* Add commands to init M10 receivers,
tweak the M8 init sequence, this is a WIP as there are still some issues during init.
Add M10 version of PMREQ.

* Add wakeup source of uartrx to PMREQ_10
The M10 does not respond to commands when asleep,
may need to do this for the M8 as well

* Enable NMEA messages on USB port.
Normally, it is a good idea to disable messages on unused ports.
Native Linux needs to be able to use GNSS modules connected via
via either serial or USB.
In the future I2C connections may be required, but are not enabled for now.

* Save the config for all u-blox receiver types.
The M10 supports this command in addition to saving using
the VALSET commands for the RAM & BBR layers.

* Address Issue #3779 RAK12500 GPS Checksum failures
Remove NMEA sentences that are not processed by TinyGPS++ or Meshtastic.

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-15 12:12:46 -05:00
Thomas Göttgens
938aba481a Merge pull request #3898 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-05-15 14:48:12 +02:00
caveman99
419820f483 [create-pull-request] automated change 2024-05-15 12:47:31 +00:00
Thomas Göttgens
73087f667a Merge branch 'master' into feature/veml7700 2024-05-15 12:27:11 +02:00
Thomas Göttgens
7810e59b0c Merge pull request #3895 from meshtastic/fix-guards
fix native compilation for linux PCs
2024-05-15 12:25:21 +02:00
Thomas Göttgens
64dc6cc215 trunk fmt 2024-05-15 12:24:42 +02:00
mverch67
33812a2082 update portduino-framework 2024-05-15 11:18:39 +02:00
Thomas Göttgens
78a1b6a9a8 unrelated change, i just noticed this problem... 2024-05-15 09:59:46 +02:00
mverch67
49a9aa3e36 fix native compilation for linux PCs 2024-05-15 08:10:52 +02:00
Jorge Castillo
8d89e78bbf Merge branch 'master' into feature/veml7700 2024-05-14 19:00:32 -04:00
Jorge Castillo
0aa449bca9 Fix unnecessary code block removal in EnvironmentTelemetryModule 2024-05-14 18:47:20 -04:00
Jorge Castillo
a3e47b8d9b merge master in to veml7700 2024-05-14 17:40:34 -04:00
Jorge Castillo
022e1f472d Updated protobufs submodule 2024-05-14 17:00:33 -04:00
Jorge Castillo
77e76bc92b Fix VEML7700Sensor readings and update protobuf and MQTT JSON 2024-05-14 16:42:23 -04:00
Thomas Göttgens
5da798c625 Merge pull request #3891 from 2itea/master
Change SHT4X sensors library from Sensirion to Adafruit
2024-05-14 21:50:20 +02:00
pr000t
15178da566 Change SHT4X sensors library from Sensirion to Adafruit 2024-05-14 21:07:44 +02:00
Thomas Göttgens
c12b9b928b Merge pull request #3890 from GUVWAF/rp2040heap
RP2040: Add `getFreeHeap()` and `getHeapSize()` support
2024-05-14 19:38:06 +02:00
GUVWAF
1f9ff68f1d RP2040: Add getFreeHeap() and getHeapSize() support 2024-05-14 19:04:31 +02:00
Thomas Göttgens
3b5d4e92c5 add psram flag on RAK11200 board definition (#3887) 2024-05-14 13:48:26 +02:00
todd-herbert
2388eb91ae Fix immediate wake from deepsleep for some devices (#3884)
Affects ESP32 boards without an external pull-up on the defined user-button pin.
2024-05-14 06:46:03 -05:00
todd-herbert
a9a208de73 Implement "Flip screen" setting for E-Ink displays (#3871) 2024-05-13 06:42:41 -05:00
Thomas Göttgens
078f33ff78 Re-add missing files (#3873) 2024-05-13 11:45:22 +02:00
Thomas Göttgens
4d8c98c23d Update CI runner versions from Node 16 to 20. (#3872) 2024-05-13 10:47:40 +02:00
Thomas Göttgens
859fd7c251 Generate the build matrix from the variant files (#3870) 2024-05-12 22:43:47 +02:00
Thomas Göttgens
5de0c71a3e add bobricius tracksenger variants (#3866) 2024-05-11 19:50:54 -05:00
Thomas Göttgens
96b5bd2fd0 unphone has a display, don't default BLE PIN to 123456 (#3865)
fixes #3822
2024-05-11 08:20:11 -05:00
Thomas Göttgens
d8d831b27a Revert "exclude serial module for T-Echo, saves 3000 bytes"
This reverts commit 38347fa6db.
2024-05-11 14:19:53 +02:00
Thomas Göttgens
6ee995e262 Merge pull request #3818 from lewisxhe/master
Enhanced t-echo file system integrity check
2024-05-11 12:55:06 +02:00
Thomas Göttgens
c6f028a5f3 Merge branch 'master' into master 2024-05-11 11:58:43 +02:00
Thomas Göttgens
42cb9b854c Merge pull request #3859 from meshtastic/debug-mute
add optional define DEBUG_MUTE
2024-05-11 11:57:46 +02:00
Thomas Göttgens
e28f869d35 Merge pull request #3860 from meshtastic/exclude-serial
exclude serial module for T-Echo, saves 3000 bytes
2024-05-11 11:57:28 +02:00
Thomas Göttgens
ef1f2e47c3 Merge pull request #3858 from Jorropo/github/linux-native
.github: add Linux Native and other as platform to Feature Request
2024-05-11 10:05:20 +02:00
Thomas Göttgens
3b6ce29cca add the now common RP2040 2024-05-11 10:05:03 +02:00
Thomas Göttgens
38347fa6db exclude serial module for T-Echo, saves 3000 bytes 2024-05-11 10:03:13 +02:00
Thomas Göttgens
86b14793de add optional define DEBUG_MUTE
This shaves roughly 60k from firmware builds by not including the Logging Ressource strings. Define in variant.h or architecture.h

Stats from T-ECHO compiles:
Before:
Flash: [========  ]  81.5% (used 664700 bytes from 815104 bytes)
After:
Flash: [=======   ]  74.5% (used 606924 bytes from 815104 bytes)
2024-05-11 09:46:39 +02:00
Jorropo
58484d7fe5 .github: add Linux Native and other as platform to Feature Request 2024-05-11 02:10:23 +02:00
github-actions[bot]
69d765622f [create-pull-request] automated change (#3846)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-05-10 08:16:49 -05:00
Ben Meadors
f06c56a51b Removing release build type due to huge amount of flash utilization 2024-05-10 07:14:28 -05:00
Ben Meadors
ac22a503de Revert "Revert "Add Sensirion SHT4X sensors (#3792)" (#3845)" (#3850)
This reverts commit 5d9800b7c2.
2024-05-10 07:13:12 -05:00
Jonathan Bennett
676319a9ca Implement chunked SPI transfer for ch341 (#3847)
This seems to fix the ch341 quirk where large packets fail to send. As it can be problematic for other radios, we gate it behind "ch341_quirk" in the config.
2024-05-10 04:36:20 -05:00
Ben Meadors
5d9800b7c2 Revert "Add Sensirion SHT4X sensors (#3792)" (#3845)
This reverts commit 5371f134ba.
2024-05-09 21:25:36 -05:00
Jonathan Bennett
0c89aff0f6 Enable telemetry and power telemetry on the native target 2024-05-09 15:45:16 -05:00
todd-herbert
5e160b21c7 T-Echo screen and button performance (#3840)
* Make button timing configurable per variant

* Adjust button timing for T-Echo
Easier multi-clicks for features like "toggle backlight" (4x click)

* Fewer full-refreshes for T-Echo display
Disables ghost pixel tracking: T-Echo ghost pixels are fairly faint.
2024-05-09 08:14:58 -05:00
Jorge Castillo
39336847ad add veml7700 readings to protobuf and to the mqtt json + fix the readigns validator code in env telemetry 2024-05-08 22:14:55 -04:00
todd-herbert
75dc8cccec Button ISR runs thread asap (#3801) 2024-05-08 16:08:24 -05:00
Nicholas Baddorf
147de75a02 Added modifier key combination to allow keyboard shortcuts on t-deck (#3668)
* Updated kbI2cBase.cpp

Updated keyboard settings for t-deck to allow a modifier key to trigger 'tab', mute notifications, or quit. To trigger the modifier press the shift key and mic (0) button at the same time. Then press q (quit), m (mute), or t (tab).

* Update kbI2cBase.cpp

* fixed formatting issues in kbI2cBase.cpp

* Removed keyboard shortcut code that doesnt work

alt+t does not work on a t-deck so I removed it to avoid confusion.

* Updated kbI2cBase.cpp

Updated keyboard settings for t-deck to allow a modifier key to trigger 'tab', mute notifications, or quit. To trigger the modifier press the shift key and mic (0) button at the same time. Then press q (quit), m (mute), or t (tab).

* Update kbI2cBase.cpp

* fixed formatting issues in kbI2cBase.cpp

* Removed keyboard shortcut code that doesnt work

alt+t does not work on a t-deck so I removed it to avoid confusion.

* Changed modifier key to alt+c

* Added screen brightness functionality

Use modifier key with o(+) to increase brightness or i(-) to decrease.

Currently there are 4 levels of brightness, (L, ML, MH, H). I would like to add a popup message to tell you the brightness.

* Added checks to disable screen brightness changes on unsupported hardware

* Setting the brightness code to work on only applicable devices

* Added "function symbol" display to bottom right corner of screen. Now shows when mute is active or modifier key is pressed. Also fixed some other minor issues.

* commented out a log

* Reworked how modifier functions worked, added

I wasn’t  happy with my previous implementation, and I think it would have caused issues with other devices. This should work on all devices.

* Added back the function I moved causing issue with versions

* Fixed the version conflicts, everything seems to work fine now

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-05-08 07:37:50 -05:00
pr000t
5371f134ba Add Sensirion SHT4X sensors (#3792)
* add Sensirion SHT4X sensors

* Update platformio.ini

Fix lib version

* Delete src/mesh/generated/meshtastic/telemetry.pb.h

* Revert "Delete src/mesh/generated/meshtastic/telemetry.pb.h"

This reverts commit 8e5e6a9f6ff4e31ed32775741c03a855e663a5de.

* remove modification on generated file

* Update ScanI2CTwoWire.cpp

Fix copy/paste issue

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-05-08 07:02:53 -05:00
Max
8105c0440a New variants PROMICRO_DIY (#3788)
* New variants PROMICRO_DIY

* Renaming and cleanup

* Renaming - phase 2

* nrf52_promicro: Trunk formatting

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-05-08 06:53:13 -05:00
lewisxhe
6c75f2e627 Move LFS_NO_ASSERT to nrf52.ini 2024-05-08 08:51:24 +08:00
lewisxhe
5aef921962 Merge branch 'master' of https://github.com/lewisxhe/firmware 2024-05-08 08:49:23 +08:00
lewisxhe
8c3b9a6139 Move LFS_NO_ASSERT to nrf52.ini 2024-05-08 08:46:08 +08:00
lewisxhe
73ab43c67a Change to LOG_ERROR 2024-05-08 08:45:24 +08:00
Jorge Castillo
23466b5a5f regenerated files 2024-05-07 18:07:24 -04:00
Jorge Castillo
f19aa49eb2 add veml7700 2024-05-07 16:11:41 -04:00
lewisxhe
1d583341e4 trunk fmt 2024-05-07 16:20:43 +02:00
lewisxhe
8e7ede16ef Remove debug wait 2024-05-07 16:20:43 +02:00
lewisxhe
8886d2df55 Enhanced t-echo file system integrity check 2024-05-07 16:20:43 +02:00
Ben Meadors
cbf20e4cee Default to new vendor ntp pool (#3819) 2024-05-07 07:57:30 -05:00
lewisxhe
81ecd6d926 trunk fmt 2024-05-07 14:33:16 +08:00
lewisxhe
b63997b36f Remove debug wait 2024-05-07 13:42:00 +08:00
lewisxhe
76adcbb46b Enhanced t-echo file system integrity check 2024-05-07 11:57:49 +08:00
Jonathan Bennett
c009c0db1e Elimate non-text output for Portduino 2024-05-06 22:27:12 -05:00
Ben Meadors
2c99f11073 Revert "set USB_CDC_ON_BOOT, udate arduinoespressif32 to 2.0.15 (#3764)" (#3809)
This reverts commit 71400103b3.
2024-05-06 17:35:38 -05:00
Ben Meadors
0d57d29cbd Send fixed position to mesh after setting it (#3803) 2024-05-06 14:51:19 -05:00
Thomas Göttgens
353c7e07d1 Wiphone (#3793)
* add wiphone, still WIP

* (very preliminary) wiphone support

* undo config changes

* revert extensions.json

* eh?
2024-05-06 06:48:57 -05:00
HarukiToreda
77a66e1dce Fix for EnvironmentTelemetry Screen (#3785)
* Update EnvironmentTelemetry.cpp

* Update EnvironmentTelemetry.cpp

Corrected lines I deleted by mistake

* trunk fmt

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-05-06 06:47:34 -05:00
Thomas Göttgens
e98c3bf5d0 Merge pull request #3802 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-05-06 13:39:44 +02:00
caveman99
5e9d48d0d7 [create-pull-request] automated change 2024-05-06 11:37:03 +00:00
Thomas Göttgens
8e91f895a6 Merge pull request #3800 from oseiler2/fix/RCWL9620-MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
Add MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR exclusion to RCWL9620
2024-05-06 12:06:17 +02:00
Oliver Seiler
b155a5b6dc rearrange includes 2024-05-06 12:15:49 +12:00
Oliver Seiler
2c30923e3e add MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR exclusion to RCWL9620 2024-05-06 11:25:18 +12:00
Thomas Göttgens
0afe2d459f Merge pull request #3790 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-05-05 17:34:07 +02:00
caveman99
0b239e618d [create-pull-request] automated change 2024-05-05 15:32:28 +00:00
Thomas Göttgens
e9ebdfeff2 Merge pull request #3787 from GUVWAF/ccToPhoneErr
Check if packet is not released before CC to phone
2024-05-05 16:47:11 +02:00
GUVWAF
6fb7d7f2d7 Check if packet is not released before CC to phone 2024-05-05 13:49:50 +02:00
tuxphone
70712d859c Enable compiling with gccnoneeabi 12.3.1 for nRF52 targets, additional small fixes (#3778)
* Fix type of nodeNum

Type of nodeNum is NodeNum, not uint

* typo

fixed typo "resumeAdverising()"

* fix missing #include "time.h"

Missing include breaks compilation with gccnoneeabi 12.3.1 for nrf52 targets on windows hosts.

* change type uint to unsigned int

uint is not a standard type. Using uint breaks compilation with gccnoneeabi 12.3.1 for nRF52 targets on windows hosts.

* fix type of channel_num

Type of channel_num should be uint32_t (as this is the type of hash() and numChannels).

Using uint non-standard type uint breaks compilation with gccnoneeabi 12.3.1 for nRF52 targets on windows hosts.

* Update nrf52.ini

Default build type should be "release" as this is the default of platformio.

* Update GPS.cpp

uint to unsigned int
2024-05-03 15:49:22 -05:00
Thomas Göttgens
4d9081b3b1 Merge pull request #3678 from meshtastic/RCWL-9620
Support radar sensor RCWL-9620 on i2c
2024-05-03 20:37:27 +02:00
Thomas Göttgens
7643a1acb1 Merge branch 'RCWL-9620' of github.com:meshtastic/firmware into RCWL-9620 2024-05-03 20:05:24 +02:00
Thomas Göttgens
61216e579e there 2024-05-03 19:25:37 +02:00
Thomas Göttgens
e31bb2d513 Merge branch 'master' into RCWL-9620 2024-05-03 16:00:08 +02:00
Thomas Göttgens
a8c38c4580 Merge pull request #3775 from lewisxhe/master
Fix the infinite restart caused by unformatted t-echo fs file system
2024-05-03 15:59:07 +02:00
Thomas Göttgens
85e0372d26 darn you, trunk. foiled my cunning plan. 2024-05-03 15:58:16 +02:00
Thomas Göttgens
53bd9de9b8 Merge branch 'master' into RCWL-9620 2024-05-03 15:12:51 +02:00
Thomas Göttgens
13ad524538 make clang-format happy again. Also fix assorted variable shrouding and logic bleeps 2024-05-03 15:10:57 +02:00
Thomas Göttgens
5f90f45ac4 trunk fmt 2024-05-03 15:04:11 +02:00
lewisxhe
dc0593c5a7 Fix the infinite restart caused by unformatted t-echo fs file system 2024-05-03 15:04:11 +02:00
Thomas Göttgens
df3cceb108 Merge pull request #3776 from oseiler2/fix/MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
Fix #MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
2024-05-03 15:02:47 +02:00
Thomas Göttgens
827dcfca4a trunk fmt 2024-05-03 14:26:57 +02:00
Thomas Göttgens
9fb6148aff Merge branch 'master' into RCWL-9620 2024-05-03 12:28:08 +02:00
Oliver Seiler
6c1377aa39 fix case statement 2024-05-03 18:59:33 +12:00
Oliver Seiler
077ca5919a MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR refinements 2024-05-03 14:15:13 +12:00
Oliver Seiler
668b716119 move QMC5883LCompass dependency to environmental_base 2024-05-03 14:15:13 +12:00
Oliver Seiler
eaa7e21bc7 exclude AccelerometerThread when MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR is set 2024-05-03 14:15:13 +12:00
Oliver Seiler
be0e882be1 exclude sensors when MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR set 2024-05-03 14:15:13 +12:00
github-actions[bot]
09080d76ad [create-pull-request] automated change (#3773)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-05-02 20:46:22 -05:00
Ben Meadors
d490a332a7 Update version.properties 2024-05-02 19:11:35 -05:00
todd-herbert
5dfa4b837f Ensure LED is off when disabling heartbeat (#3772) 2024-05-02 19:11:13 -05:00
github-actions[bot]
9501f3bda9 [create-pull-request] automated change (#3771)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-05-02 16:17:41 -05:00
Jonathan Bennett
b69a1cada9 Portduino bump to pick up minor fix (#3770) 2024-05-02 13:54:50 -05:00
Jonathan Bennett
06e7d2b845 Track actual GPIO values, not just the enum values (#3768)
* Track actual GPIO values, not just the enum values

* trunk
2024-05-02 13:39:28 -05:00
Oliver Seiler
71400103b3 set USB_CDC_ON_BOOT, udate arduinoespressif32 to 2.0.15 (#3764) 2024-05-02 13:39:18 -05:00
Thomas Göttgens
40e361e6d0 Merge pull request #3763 from lewisxhe/master
Fix t-echo gps failure
2024-05-02 15:13:43 +02:00
lewisxhe
d1b6f11429 Fix t-echo gps failure 2024-05-02 14:39:58 +02:00
todd-herbert
0527fb10ce Init. battery voltage from ADC reading, instead of fixed value (#3761) 2024-05-02 07:14:44 -05:00
Andrew Yong
5f929a8024 Publish fixed position updates and consider changes in only altitude as an updated point (#3758)
* AdminModule: Publish fixed position updates

Enabled GPS thread when fixed position is updated, to let the GPS thread run once and publish the new fixed position.

Signed-off-by: Andrew Yong <me@ndoo.sg>

* GPS: Consider changes in only altitude as an updated point

Signed-off-by: Andrew Yong <me@ndoo.sg>

---------

Signed-off-by: Andrew Yong <me@ndoo.sg>
2024-05-02 07:13:36 -05:00
Thomas Göttgens
4f54862d63 Merge pull request #3765 from meshtastic/twc-mesh-buildfix
fix building new TWC_mesh_v4 board
2024-05-02 13:30:49 +02:00
Thomas Göttgens
0f4ac94559 fix building new TWC_mesh_v4 board 2024-05-02 12:48:50 +02:00
Jonathan Bennett
45c1b46bd0 Move native to spi_host to indicate spidev for LovyanGFX 2024-05-01 13:21:23 -05:00
Jonathan Bennett
5095efc55f Pick up support for more than 64 GPIO lines under Portduino 2024-05-01 13:21:23 -05:00
Ben Meadors
ec92f7a5a3 Remove phone nodenum warning and empty else clause (#3756) 2024-05-01 08:27:43 -05:00
Ben Meadors
57da37cfbc Position module should enforce precision for phone originated position packets (#3752) 2024-05-01 08:05:26 -05:00
github-actions[bot]
3619ac87b8 [create-pull-request] automated change (#3754)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-30 20:14:38 -05:00
GUVWAF
e51ee91c39 Optimization: stop relaying when reply is received (#3753) 2024-04-30 20:07:15 -05:00
todd-herbert
21311bbeda T-Echo touch button no longer requires "wake on tap or motion" (#3745) 2024-04-29 08:54:57 -05:00
Ben Meadors
472db5b237 Merge branch 'master' into RCWL-9620 2024-04-28 07:05:54 -05:00
Andrew Yong
18e69a0906 Update Heltec HT-C62 variant based on HT-DEV-ESP board (#3731)
* I2C is not defined in the reference schematic nor HT-DEV-ESP board, remove definition accordingly
* There is no screen in the the reference schematic nor HT-DEV-ESP board, change definition accordingly
* BUTTON_PIN has a 10 kOhm pullup resistor on HT-DEV-ESP, turning off redundant internal pullup should save some power
* LED is connected to GPIO2 on HT-DEV-ESP and is not inverted, update definition accordingly
* Remove redundant undef lines for LoRa pins

Above changes were built and flashed to my [HT-DEV-ESP_V2 board purchased from Heltec's Taobao store](https://item.taobao.com/item.htm?id=521590063077).

Signed-off-by: Andrew Yong <me@ndoo.sg>
2024-04-28 06:49:26 -05:00
David Ellefsen
93f77ea7d2 Update TinyGPSPlus version (#3727)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-27 19:50:15 -05:00
Mike
ee4c4ae6c9 Allow setting hopLimit for MQTT json sendtext and sendposition (#3735)
* Fix channel name extraction

* Allow setting hopLimit for mqtt sendtext and sendposition
2024-04-27 18:15:54 -05:00
Ben Meadors
6cc7dee95c Tradunkadunk 2024-04-27 11:12:52 -05:00
HarukiToreda
38c4d35a7b Add Notification on device screen following feature toggle (#3627)
* Update CannedMessageModule.h

* Update CannedMessageModule.cpp

* Update CannedMessageModule.cpp

hopefully this fixes the errors on Trunk

* Update CannedMessageModule.cpp

Changed "Ping Broadcasted" with "Telemetry Update Sent"

* tryfix: disable tempmessage again after 2 seconds

* fix 2s showtime

* Put spelling fix back

* Fix build

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-27 11:08:25 -05:00
Ben Meadors
e683d8f552 Rebrand "send network ping" to more honest "try send position" with better output (#3737) 2024-04-27 08:55:04 -05:00
jcyrio
e66aec8223 fix typo in comment (#3726) 2024-04-27 08:54:06 -05:00
Oliver Seiler
a06a01d25e fix #if HAS_TELEMETRY when set to 0 (#3733) 2024-04-27 06:35:44 -05:00
Andrew Yong
f8c3f43ea6 Fix xiao_ble variant build error due to undefined BATTERY_SENSE_RESOLUTION_BITS (#3732)
Define BATTERY_SENSE_RESOLUTION_BITS based on [amoroz's snippet on the Meshtastic forum](https://meshtastic.discourse.group/t/new-1w-diy-variant-xiao-nrf52840-ebyte-e22-900m30s/7904/10).

Fixes following build error:

```
src/Power.cpp: In member function 'virtual uint16_t AnalogBatteryLevel::getBattVoltage()':
src/Power.cpp:224:79: error: 'BATTERY_SENSE_RESOLUTION_BITS' was not declared in this scope
             scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
```

Signed-off-by: Andrew Yong <me@ndoo.sg>
2024-04-27 06:17:17 -05:00
todd-herbert
dfcabba0b2 Prevent overflow when calculating timezones (#3730) 2024-04-26 20:43:09 -05:00
Thomas Göttgens
827bacdfc8 Merge pull request #3723 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-04-25 23:46:43 +02:00
thebentern
5806a266d3 [create-pull-request] automated change 2024-04-25 20:19:54 +00:00
Jonathan Bennett
30fbcabf84 add conffiles to .deb packaging (#3722) 2024-04-25 14:23:38 -05:00
Arkadiusz Miśkiewicz
c14043f196 Split warning into two messages, so we know which one is the case. (#3710) 2024-04-25 06:47:39 -05:00
Jonathan Bennett
e3610a2eb1 Move to lovyangfx develop for Native 2024-04-24 13:17:43 -05:00
Oleksandr Podolchak
9baccc80d8 Add SX1268 modules support for linux-native (#3702)
* Add portduino Ebyte E22 XXXM30S/XXXM33S (sx1268) module support

* Add Ebyte E22 XXXM3XS module config

* Update comment for sx1268 module

* Address review comments

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-24 08:41:01 -05:00
Gareth Coleman
ac16ccf40c fix for unPhone hangs during boot without sd card present (#3709)
* work around sd card hang if not present

* comment out the define for HAS_SDCARD
2024-04-24 06:41:05 -05:00
Ben Meadors
1c0227f90c Merge branch 'master' into RCWL-9620 2024-04-23 14:19:08 -05:00
Jonathan Bennett
57d296e0db Add better support for the Adafruit PiTFT 2.8 for Native (#3704)
* Add better support for the Adafruit PiTFT 2.8 for Native

* native: Make touch i2c address configurable

* Bump portduino to pick up I2C features

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-23 14:18:51 -05:00
SCWhite
9c9d126f6b [BOARD] Add new variant: TWC_Mesh (#3705)
* add new variant: TWC_mesh_v4

* fix trunk format

* fix format under wsl

* change board to TWC_mesh_v4

* change platformio & variant.h properly

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-23 14:09:28 -05:00
github-actions[bot]
27f0e42d2f [create-pull-request] automated change (#3708)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-23 13:32:33 -05:00
todd-herbert
4599534616 Terminate an async-full-refresh when caught by determineMode() instead of onNotify() (#3706) 2024-04-23 12:00:48 -05:00
Tom Fifield
7acaec8ef5 Add power limit for TW region (#3701)
The TW region had now power limit set, so defaulted to 16dBm.

The relevant regulation is section 5.8.1 of the Low-power Radio-frequency Devices Technical Regulations, which notes the limits of  0.5W (27dBM) indoor or coastal, 1.0W (30dBM) outdoor.

This patch updates the power limit to 27dbM, using the the lower limit specified in the regulations to be conservative.

Regulation references:
https://www.ncc.gov.tw/english/files/23070/102_5190_230703_1_doc_C.PDF (latest English version)
https://gazette.nat.gov.tw/egFront/e_detail.do?metaid=147283 (latest Chinese version, February 2024)
2024-04-23 07:11:22 -05:00
Nicholas Baddorf
d0e81b9151 Fixed node and channel selection for t-deck (#3695)
This enables the node and channel selection to be accessed by pressing the tab shortcut and then swiping between nodes or pressing tab again to change channels.

(To access the tab function look at my other pull request https://github.com/meshtastic/firmware/pull/3668)

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-23 07:09:26 -05:00
Thomas Göttgens
c6e940af81 Merge branch 'master' into RCWL-9620 2024-04-23 14:04:22 +02:00
Thomas Göttgens
3302fbcc53 Merge pull request #3647 from garethhcoleman/RGBLED
Support for generic 4pin RGB LEDs (both CC and CA) and NeoPixels, also RGB LED and vibration notification support for unPhone
2024-04-23 13:57:23 +02:00
Gareth Coleman
ccbf635eef corrected a bit of overzealous tidying 2024-04-22 17:21:41 +01:00
Gareth Coleman
6669b22db3 tidied up, prob broke everything 2024-04-22 16:37:05 +01:00
Gareth Coleman
ec2b854ea2 oops missed the extern enabling little chap 2024-04-22 14:44:59 +01:00
Gareth Coleman
378a2d723e Merge branch 'RGBLED' of github.com:garethhcoleman/firmware into RGBLED 2024-04-22 14:43:07 +01:00
Gareth Coleman
5dd08e9533 added NeoPixel support using Adafruit library 2024-04-22 14:42:52 +01:00
Gareth Coleman
125add9792 Merge branch 'master' into RGBLED 2024-04-22 14:42:14 +01:00
Andrew Yong
250cf16bf8 Add ability to turn off heartbeat LED blinking (#3674)
* Add ability to turn off status LED blinking

Fixes #3635 and depends on [protobufs PR #485](https://github.com/meshtastic/protobufs/pull/485)

Signed-off-by: Andrew Yong <me@ndoo.sg>

* led_heartbeat_disabled

* trunk

---------

Signed-off-by: Andrew Yong <me@ndoo.sg>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-22 08:21:50 -05:00
Thomas Göttgens
8b5fad21b0 Merge pull request #3693 from titan098/updates_for_esp32s2_build
Updates for esp32s2 builds
2024-04-22 13:56:14 +02:00
David Ellefsen
30d4c3a945 Updates for esp32s2 build 2024-04-22 11:01:13 +02:00
Gareth Coleman
45fd5e25ac Merge branch 'master' into RGBLED 2024-04-22 09:15:44 +01:00
Thomas Göttgens
ac6a668362 Merge pull request #3697 from meshtastic/nrf52-signfix
fix signedness warnings of NRF52 toolchain
2024-04-22 10:13:38 +02:00
Thomas Göttgens
f47b40cf68 fix signedness warnings of NRF52 toolchain 2024-04-22 09:49:06 +02:00
quimnut
fd9461505f adjust adc for rak11310 devices (#3698) 2024-04-21 19:51:02 -05:00
Ben Meadors
84edaabfe9 Merge branch 'master' into RGBLED 2024-04-21 14:46:18 -05:00
Ben Meadors
048f0a1601 Merge branch 'master' into RCWL-9620 2024-04-21 14:41:49 -05:00
Nicholas Baddorf
4a48a3fb52 Fixed bug making t-deck reboot when muted (#3694) 2024-04-21 14:41:22 -05:00
Ben Meadors
39bbf0d352 Added more clear RTC handling and quality logging (#3691)
* Also refresh timestamp for "timeonly" fixed position nodes

* Added more clear RTC quality handling

* Fix clock drift from Phone GPS / NTP too
2024-04-21 14:40:47 -05:00
Ben Meadors
675d8fe089 Merge branch 'master' into RCWL-9620 2024-04-21 12:37:38 -05:00
Mictronics
0406be82d2 Use correct format specifier and fixed typo. (#3696)
* Fix LED pinout for T-Echo board marked v1.0, date 2021-6-28

* Merge PR #420

* Fixed double and missing Default class.

* Use correct format specifier and fixed typo.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-21 12:36:37 -05:00
Ric In New Mexico
679e068e19 Missing break in INA3221 i2c scan (#3692)
* INA3221 Mis-identification fix

* Missing break in INA3221 i2c scan
2024-04-21 12:35:42 -05:00
Thomas Göttgens
952393ca0f Merge branch 'master' into RCWL-9620 2024-04-21 18:34:40 +02:00
Thomas Göttgens
a231cd2ad0 derp... 2024-04-21 16:35:41 +02:00
Ben Meadors
ac87c0065f Also refresh timestamp for "timeonly" fixed position nodes (#3689) 2024-04-21 08:45:36 -05:00
S5NC
9822a85274 Add board and variant definitions for EBYTE_ESP32-S3 (#2882)
* Create ESP32-S3-WROOM-1-N4.json

* Create pins_arduino.h

* Create platformio.ini

* Create variant.h

* Update mesh.pb.h

* Update architecture.h

* Update mesh.pb.h

* Update variant.h

* Update variant.h

Add example schematic

* Update architecture.h

* Revert update architecture.h

* Create variant.h

* Create pins_arduino.h

* Create platformio.ini

* Delete variants/E22-900M_S3 directory

* Update architecture.h

* Update variant.h

* Update platformio.ini

* Update variant.h

* Update variant.h

* Update architecture.h

* Update platformio.ini

* Update architecture.h

* Update ESP32-S3-WROOM-1-N4.json

* Update platformio.ini

* Update ESP32-S3-WROOM-1-N4.json

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update pins_arduino.h

* Update architecture.h

* add SX1268 allow

* GPS

* Commit

* Whitespace

* Update variant.h

* Update variant.h

* trunk

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: S5NC <>
2024-04-21 08:40:23 -05:00
Thomas Göttgens
a957065fe8 Merge branch 'master' into RCWL-9620 2024-04-21 14:47:29 +02:00
Ben Meadors
41f3557491 Refactor smart position to use throttle helper (#3671)
* Added one minute throttling to NodeDB

* Derp

* Refactor smart-position to use throttle
2024-04-21 07:42:36 -05:00
Thomas Göttgens
402b0d7e0b ditch that no-good m5 dependancy and do it ourself 2024-04-21 14:39:55 +02:00
Thomas Göttgens
13ebda6b2f Merge branch 'RCWL-9620' of github.com:meshtastic/firmware into RCWL-9620 2024-04-21 14:35:32 +02:00
Ben Meadors
1dd19cec6e Merge branch 'master' into RCWL-9620 2024-04-21 07:34:11 -05:00
Ben Meadors
df718ab294 Merge branch 'master' into RGBLED 2024-04-21 07:31:54 -05:00
todd-herbert
dfc43bae18 Fix crash on shutdown, if Bluetooth not enabled (#3686)
Previously attempted to call deinit method for a nullptr
2024-04-21 07:25:58 -05:00
todd-herbert
f6cfdfe881 (ESP-32S) Fix "critical error 3" after deep-sleep (#3685) 2024-04-21 07:25:12 -05:00
S5NC
820c5dc8c5 Update architecture.h (#3688) 2024-04-21 07:24:39 -05:00
Thomas Göttgens
1f9c295c9e Merge branch 'RCWL-9620' of github.com:meshtastic/firmware into RCWL-9620 2024-04-21 13:48:08 +02:00
Thomas Göttgens
5218aaafcf Change name 2024-04-21 11:41:52 +02:00
Thomas Göttgens
c480f0870c Support radar sensor RCWL-9620 on i2c 2024-04-21 11:41:52 +02:00
Gareth Coleman
9e4ef92e6d lets just define it without guards! 2024-04-21 09:16:50 +01:00
Gareth Coleman
cf65661c7c another silly error 2024-04-21 08:59:40 +01:00
Gareth Coleman
fb7a878d94 tweaked guards to allow various combinations of RGB leds 2024-04-21 08:24:51 +01:00
github-actions[bot]
e72792afc8 [create-pull-request] automated change (#3683)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-20 15:58:42 -05:00
Ric In New Mexico
ec39e1136a INA3221 Mis-identification fix (#3681) 2024-04-20 15:58:21 -05:00
Thomas Göttgens
94e1f016e5 Change name 2024-04-20 20:49:57 +02:00
Thomas Göttgens
9170fe0580 Support radar sensor RCWL-9620 on i2c 2024-04-20 20:30:22 +02:00
Thomas Göttgens
ef9808cdd6 Merge pull request #3680 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-04-20 20:25:14 +02:00
caveman99
0972a8dccb [create-pull-request] automated change 2024-04-20 18:24:40 +00:00
github-actions[bot]
419eb13968 [create-pull-request] automated change (#3679)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-20 09:56:55 -05:00
github-actions[bot]
e7828c4c64 [create-pull-request] automated change (#3676)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-20 07:36:53 -05:00
Manuel
44aa248099 added new display parameters (#3670) 2024-04-19 19:27:13 -05:00
Gareth Coleman
e0513d4078 ahem, another minor edit to have another go at CI 2024-04-19 09:27:10 +01:00
Gareth Coleman
2100f3135e minor edit to have another go at CI 2024-04-19 09:25:38 +01:00
Gareth Coleman
2f36d4990e Merge branch 'master' into RGBLED 2024-04-19 08:12:13 +01:00
github-actions[bot]
65bde8538f [create-pull-request] automated change (#3663)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-18 20:33:23 -05:00
github-actions[bot]
7a3570aecf [create-pull-request] automated change (#3662)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-18 18:29:50 -05:00
Gareth Coleman
4a471ded79 Merge branch 'RGBLED' of github.com:garethhcoleman/firmware into RGBLED 2024-04-19 00:28:39 +01:00
Gareth Coleman
eea85d26ca oh god the bugs, they are everywhere, I feel so dirty... 2024-04-19 00:28:20 +01:00
GUVWAF
64edfb76e0 Uplink to MQTT after potentially altering content (#3646)
Mainly for traceroute module now

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-18 17:44:13 -05:00
Gareth Coleman
8ac308e73b Merge branch 'master' into RGBLED 2024-04-18 23:12:08 +01:00
Gareth Coleman
0ae7674982 I'm sure there's a cleverer way to do this, but I'm stupid and I didn't find it after a few minutes of searching stack overflow 2024-04-18 22:18:50 +01:00
GUVWAF
e4b5f2ce14 NeighborInfo: Only keep neighbors in RAM (#3660)
* NeighborInfo: Only keep neighbors in RAM
It fills up quickly when nodes are running >=2.3

* Defer first transmission as it's usually empty

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-18 16:16:50 -05:00
Gareth Coleman
7d77b23eb6 support for generic 4 pin CC and CA RGB LEDS 2024-04-18 22:00:33 +01:00
Gareth Coleman
a149999cec tidy up first 2024-04-18 20:57:03 +01:00
Ben Meadors
78d915b454 Merge branch 'master' into RGBLED 2024-04-18 14:44:53 -05:00
GUVWAF
4c0b7ea409 StoreForward: Remove assert when receiving unhandled case (#3661) 2024-04-18 14:28:11 -05:00
Ben Meadors
425a715995 Added one minute throttling to NodeDB save to disk (#3648)
* Added one minute throttling to NodeDB

* Derp
2024-04-18 14:20:39 -05:00
Ben Meadors
2e13aeeacb Merge branch 'master' into RGBLED 2024-04-18 07:32:25 -05:00
todd-herbert
747c713ba9 (ESP32) Fix bluetooth after light-sleep; de-init for deep sleep (#3655) 2024-04-18 07:27:18 -05:00
Gareth Coleman
4b5549be8f added vibration notifications 2024-04-18 09:22:31 +01:00
Gareth Coleman
172d271b0b Merge branch 'master' into RGBLED 2024-04-18 07:11:49 +01:00
Oliver Seiler
2e14234b77 don't enable the CDC interface already at boot (#3652)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-17 16:55:47 -05:00
Jonathan Bennett
d47e9bed19 Add multiple SPI devices for Radio, Display, and Touchscreen (#3638)
This changeset gives us the ability to specify a separate SPI device for the LoRa, Display, and Touchscreen. The changes in Portduino also add support for specifying a new SPI speed for each transaction. All together, this means that we can let the Linux OS manage the CS lines, and also get much faster SPI speeds, leading to better framerates.

* Add multiple SPI devices to put Radio, Display, and Touchscreen on each their own

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-17 14:25:52 -05:00
GUVWAF
bc085ab840 Fix #3641: Always set MAC when picking new NodeNum (#3651)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-17 07:07:40 -05:00
Ben Meadors
2450031b1b Add device metrics uptime to MQTT JSON (#3643)
* Add device metrics uptime to MQTT JSON

* Cast a spell
2024-04-17 07:00:18 -05:00
Ben Meadors
2cd877d2eb Merge branch 'master' into RGBLED 2024-04-16 20:37:02 -05:00
GUVWAF
c34956e9d8 Cosmetics: rename remaining plugins → modules and less errors (#3645) 2024-04-16 17:47:56 -05:00
Gareth Coleman
afb4de21d9 yet another random edit, think i'm brushing the touchpad or perhaps my computer is possessed by the devil determined to make me look foolish 2024-04-16 22:37:57 +01:00
Gareth Coleman
86223d8806 Merge branch 'RGBLED' of github.com:garethhcoleman/firmware into RGBLED 2024-04-16 21:41:57 +01:00
Gareth Coleman
0632b96fcb just tiny tweak to minimise changes 2024-04-16 21:40:13 +01:00
Gareth Coleman
dcfc9c9f03 Merge branch 'meshtastic:master' into RGBLED 2024-04-16 21:29:12 +01:00
Gareth Coleman
8a3322fbcb rgb led support for unPhone 2024-04-16 21:28:12 +01:00
David Ellefsen
55c9c3b298 Support for the ATGM336H series of GPS modules (#3610)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-16 09:03:51 -05:00
Andrew Yong
9599549477 Add configuration option for LoRa Region Code override for region-locked builds/variants (#3540)
The main use case for this will be to create a custom Heltec WiFi LoRa 32 V3 SG_923 variant, which will be pre-flashed and sent for regulatory approval for retail sale.

Signed-off-by: Andrew Yong <me@ndoo.sg>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-16 09:03:36 -05:00
S5NC
e813703bf5 Add support for CDEBYTE_EoRa-S3 (#3613)
* Create CDEBYTE_EoRa-S3.json

* Update CDEBYTE_EoRa-S3.json

* Update architecture.h

* Create variant.h

* Create platformio.ini

* Create pins_arduino.h

* Update variant.h

* Update variant.h

* Update variant.h

* Trunk format

* update variant.h

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: S5NC <>
2024-04-16 09:00:16 -05:00
github-actions[bot]
699ea74672 [create-pull-request] automated change (#3642)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-16 08:01:32 -05:00
todd-herbert
a01069a549 No more printing power-state changes to screen (#3640) 2024-04-16 07:36:14 -05:00
Gareth Coleman
3413b9da41 Fixed XPT2046 syntax and using unPhone library to clean up support (#3631)
* Fixed XPT2046 syntax and using unPhone library to clean up main and TFTDisplay.

* strange extra edits removed wtf
2024-04-16 07:29:08 -05:00
Jonathan Bennett
7d3175dc83 More useful default input device for Pi 400 (#3639) 2024-04-16 07:22:31 -05:00
github-actions[bot]
441638c2eb [create-pull-request] automated change (#3636)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-15 20:23:49 -05:00
Ben Meadors
2f9b68e08b File management changes (Part 2 - Reboot instead of reformat NRF52 after two failed file saves) (#3630)
* Add LoadFileState to differentiate types of success / failures

* Try rebooting NRF52s with multiple failed saves

* Trunkate
2024-04-15 16:36:22 -05:00
Ben Meadors
27ae4399bc Zero hop always for connected node (#3634) 2024-04-15 16:35:52 -05:00
Gareth Coleman
385d7296fe strange extra edits removed wtf 2024-04-15 17:37:39 +01:00
Gareth Coleman
d1cd686644 Fixed XPT2046 syntax and using unPhone library to clean up main and TFTDisplay. 2024-04-15 17:24:08 +01:00
Gareth Coleman
1291da746b Support for alt I2C address for LSM6DS3 sensor, identification of TCA9555 IO Expander, resolve serial hang issue (#3622)
* basic identification of TCA9555

* recognise LSM6DS3 on alt address

* keep variant.h changes out of this PR

* 2nd attempt to keep variant.h changes out of this PR

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-15 07:30:45 -05:00
Ben Meadors
2803fa964e Add LoadFileState to differentiate types of success / failures (#3625) 2024-04-15 07:22:05 -05:00
todd-herbert
1d97544041 Wireless Paper: Fix BLE after Lightsleep (#3629)
* NimBLE deinit for deep-sleep only

* Optionally disable blink during light-sleep

* Advised to revert "blink disable"
This reverts commit 66347ce19b.
2024-04-15 06:50:42 -05:00
Jonathan Bennett
5b52c31a76 Fix HAS_WIRE logic in main 2024-04-14 16:44:28 -05:00
Jonathan Bennett
00d4c011c7 Fix sx126x error log logic 2024-04-14 16:44:28 -05:00
Jonathan Bennett
1447148811 Make sure settingsStrings get initialized 2024-04-14 16:44:28 -05:00
Ben Meadors
4f205718f0 Device telemetry uptime in seconds (#3614) 2024-04-14 10:27:01 -05:00
Manuel
5047468d9f fix/enhancement: TFT device powersave (part 3) (#3600)
* fix: device TFT powersave (part 3)

* trunk fmt

* trunk fmt

* undo bluetooth deinit from #3596

* revert code for heltec tracker

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-14 09:11:27 -05:00
Manuel
ec3971bce5 fix upDown ISR (#3612) 2024-04-14 08:11:22 -05:00
Jonathan Bennett
0a246bfe9b Add more useful error output in radio interfaces (#3615)
* Add more useful error output in radio interfaces

* trunk
2024-04-14 00:29:42 -05:00
Jonathan Bennett
f1a1834ee2 Update portduino to include SPI and setSetial fixes (#3611) 2024-04-13 16:14:15 -05:00
Ben Meadors
2a6e26620e Auto-favorite our node (#3609) 2024-04-12 20:17:25 -05:00
Jonathan Bennett
3f45c2d4f0 Fix another LOG_DEBUG message that should be LOG_ERROR (#3607) 2024-04-12 14:14:56 -05:00
Jonathan Bennett
11adfe05ce Drop unishox2 functions from Router (#3606) 2024-04-12 14:06:05 -05:00
Ben Meadors
b4009f9f2f New fixed copy-pasted more corrector hash 2024-04-12 11:49:35 -05:00
Jonathan Bennett
917b739e62 Update TinyGPS version to un-derped commit 2024-04-12 11:29:08 -05:00
Ben Meadors
2c4db16336 TinyGPSAltitude support for negative altitude (#3605) 2024-04-12 10:49:14 -05:00
Manuel
4c9646f7d9 fix: device sleep (part 1) (#3590)
* fix sleep part 1

* always show wakeup reason in debug log

* fix screen turn on issue

* avoid unnecessary reboot when entering light sleep

* set DIO1 based on radio type

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-12 10:01:24 -05:00
Oliver Seiler
8fd32f3452 enable USB CDC (#3597) 2024-04-12 07:19:48 -05:00
todd-herbert
178877f2d9 Enable T-Echo touch button by default (#3604)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-12 07:18:36 -05:00
Jonathan Bennett
6de0363eea Pin RadioLib to 6.5.x (#3601) 2024-04-12 07:17:43 -05:00
Gareth Coleman
f4a2023dba LSM6DS3TR-C support (#3593)
* started work on pulling in the unphone library and dependencies, to do e.g. power switch management and etc.; currently failing at Adafruit_ImageReader

* now compiles with unphoneLibrary included

* successfully pulled in unphone library to manage power switch and init vibe motor and etc.
doesnt print to serial tho...

* simplified the build a bit; when doing meshtastic do not depend on the MCCI lora libs etc., then also no need to config them via build flags

* version that doesnt trigger brownout

* cleaned up initVariant a little

* note re. GPS

* back to mesh upstream version

* this time we're back to mesh upstream version

* getting LSM6DS3TRC driver installed

* shake to wake works, set threshold quite low may need increasing

* whats the crack with these end of file changes?

* paramatize the wake threshold

* try to get the PR to just include real changes

* got the right config item and also not giving compiler messages

* moved the lib_deps for the LSM6DS3TRC driver from our variant platformio.ini to the main one in root so all boards have it

* stuupid error #define-ing

---------

Co-authored-by: Hamish Cunningham <hamish@gate.ac.uk>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-11 19:40:14 -05:00
Manuel
927d07e2c6 fix: device PMU shutdown (part 2) (#3596)
* fix: device PMU shutdown (part 2)

* fix error + enable nimble deinit
2024-04-11 19:39:07 -05:00
github-actions[bot]
a4a8556aa2 [create-pull-request] automated change (#3595)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-11 07:41:37 -05:00
todd-herbert
8e29efcb50 Fix button interrupt after light sleep (#3587)
* Make ButtonThread instance extern
Previously was a static local instance in setup(). Now declared in ButtonThread.cpp, accessible via extern declaration in ButtonThread.

* Extract attachInterrupt() calls to public method; create matching method for detachInterrupt()

* Change suspension of button interrupts for light-sleep

* Fix declaration for ARCH_PORTDUINO

* Remove LOG_DEBUG used during testing

* Don't assume device has a button..

* Guard entire constructor code

* Don't use BUTTON_PIN with ARCH_PORTDUINO

---------

Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
2024-04-11 07:02:50 -05:00
GUVWAF
3bee6ce9c3 Only set NodeNum based on MAC if it's still zero (#3585)
* Only set NodeNum based on MAC if it's still zero

* Already declared
2024-04-10 11:29:29 -05:00
Thomas Göttgens
fcab20fb3b Merge pull request #3580 from meshtastic/add-iaq
add BME680 IAQ reading
2024-04-09 21:55:42 +02:00
Thomas Göttgens
2d81c97b98 fix #2586 (lower IAQ quality for saving to 2 and rework save logic) 2024-04-09 21:20:36 +02:00
Thomas Göttgens
cfd98b2c91 add BME680 IAQ reading. Range is from 0 (clean) - 500 (extremely polluted) 2024-04-09 21:20:36 +02:00
rcarteraz
6e7405e56b add unphone (#3584) 2024-04-09 12:26:03 -05:00
rcarteraz
77082e35f5 Add unPhone to S3 build scripts (#3583)
* add unphone to s3 devices

* add unphone
2024-04-09 11:37:38 -05:00
github-actions[bot]
daa64b055a [create-pull-request] automated change (#3579)
Co-authored-by: caveman99 <caveman99@users.noreply.github.com>
2024-04-09 08:00:19 -05:00
Thomas Göttgens
ec74fba2bd update to nanopb 0.4.8 and fix proto regen script (#3578)
* update to nanopb 0.4.8 and fix proto regen script

* trunk, damnit
2024-04-09 07:40:55 -05:00
github-actions[bot]
e89575bfd1 [create-pull-request] automated change (#3577)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-08 18:43:10 -05:00
Thomas Göttgens
ea61808fd9 tryfix: use UTC on Phone API (#3576) 2024-04-08 17:26:23 -05:00
Thomas Göttgens
b14ac777f1 Merge pull request #3570 from meshtastic/local-time-display
display log and onscreen times in local timezone
2024-04-08 09:18:41 +02:00
Thomas Göttgens
65e5bdc212 display log and onscreen times in local timezone 2024-04-08 00:10:54 +02:00
Jonathan Bennett
aa3280c18c add trunk ignore for docker chmod (#3568)
* add trunk ignore for docker chmod

* Fix incorrect comment type
2024-04-07 17:08:17 -05:00
Jonathan Bennett
68e657fd07 Actually fix Docker - hopefully 2024-04-07 15:52:43 -05:00
Jonathan Bennett
47b8f7b6c6 Don't forget to change directory owner 2024-04-07 14:34:19 -05:00
Jonathan Bennett
fde20db95f move chmod -t to root section 2024-04-07 14:22:39 -05:00
Jonathan Bennett
40a7fd145a Update Dockerfile to remove sticky bit during build (#3567)
* Update Dockerfile to remove sticky bit during build

* no sudo?
2024-04-07 14:15:03 -05:00
Thomas Göttgens
33842b67e8 Merge pull request #3565 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-04-07 16:00:03 +02:00
caveman99
2db061ded9 [create-pull-request] automated change 2024-04-07 13:58:58 +00:00
Thomas Göttgens
1baad2875a Add keymappings for several utility functions (#3536)
* - map fn+m to mute and unmute the external notification module
- map fn+t to be an alternative for the TAB key

* add whitelist to inputbroker

* (maybe) sweet-talking t-deck into tabbing...

* now for real - back in Kansas

* More fancy mappings

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-06 19:12:57 -05:00
Jared Quinn
0e9f1beb40 Native Linux Build (ARM support and webserver deps) (#3506)
* Added webserver libraries to build libs

* Revert "Added webserver libraries to build libs"

This reverts commit bcc72a06b9.

* Added piwebserver library dependencies to native build

* Add webserver libraries to apt install for native build

* Revert additional libraries added by mistake

* Address trunk check issues on Dockerfile

* Ignore linter checks for pinning build packages and apt-get

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-06 10:32:15 -05:00
Jonathan Bennett
03f60dcb49 Make instructions clearer in config.yaml comments (#3559) 2024-04-06 08:04:49 -05:00
todd-herbert
5b5f9c62b5 Remap backlight toggle and touch button (#3560)
* Update E-Ink display after sending adhoc ping or disable/enable GPS

* Resume display updates when touch button pressed

* Use touch hold as modifier; change double-click behavior for user button

* Fix preprocessor exclusions

* Purge backlight behavior

* Distinguish between 3x and 4x multi-presses

* Touch button considers "Wake screen on tap or motion" user-setting

* Don't assume device has BUTTON_PIN

* Rename misleading method
2024-04-06 08:04:26 -05:00
Ric In New Mexico
577de1e517 Merge pull request #3557 from fuutott/master
Update platformio.ini
2024-04-05 14:56:38 -06:00
fuutott
f6e6f975c0 Update platformio.ini
should be dash instead of underscore
2024-04-05 14:58:00 +01:00
Gareth Coleman
902f38238d This change to the I2C Scan is to distinguish between two devices (#3554)
sharing the same I2C address, the QMI8658 IMU and BQ24295 PMU.
2024-04-05 07:20:22 -05:00
Thomas Göttgens
9b2d862b7d Merge pull request #3544 from garethhcoleman/unphone
New device unPhone using HX8357D LCD and XPT2046 touchscreen
2024-04-04 12:47:12 +02:00
Gareth Coleman
4cdfae71cf first attempt at getting trunk to do linting 2024-04-04 11:00:10 +02:00
Gareth Coleman
be889015f7 New device unPhone using HX8357D LCD and XPT2046 touchscreen 2024-04-04 11:00:10 +02:00
Thomas Göttgens
f0b6ff9b2d Merge pull request #3545 from todd-herbert/paper-deepsleep-current
Reduce deep-sleep current for Heltec Wireless Paper
2024-04-04 10:59:20 +02:00
Todd Herbert
30ebb6ae46 use BUTTON_PIN macro 2024-04-04 17:18:40 +13:00
Todd Herbert
d1db51830b set GPIOs for sleep 2024-04-04 17:05:12 +13:00
Todd Herbert
eb0e705ba9 de-init bluetooth 2024-04-04 17:04:10 +13:00
github-actions[bot]
46ad4bf0e5 [create-pull-request] automated change (#3542)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-04-03 08:47:47 -05:00
todd-herbert
a570e50aca Disable holds / isolations on RTC IO pads after deep sleep (#3539)
* disable holds on RTC IO pads after deep sleep

* Don't assume SOC_RTCIO_HOLD_SUPPORTED
2024-04-03 06:59:53 -05:00
AeroXuk
2caed6d29c Feature parity between Pico and Pico W (#3538) 2024-04-02 15:36:15 -05:00
todd-herbert
f2ed0f7c8c Fix Light-sleep for ESP32 (#3521)
* Change wakeup source from EXT0 to GPIO

* Avoid ISR issue on wake

* Detect press from wake reason, instead of digitalRead

* Missing #ifdef

Risky phone-typed commit

* Fix PowerFSM timed transition preventing light sleep
Addresses https://github.com/meshtastic/firmware/issues/3517

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-02 14:55:48 -05:00
Jonathan Bennett
8bb562c5fa Add spiTransfer function to Native to support Linux-managed CS (#3524)
* Add spiTransfer function to Native to support Linux-managed CS

* Trunk

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-04-01 18:31:36 -05:00
rcarteraz
15501e84dd Add Station-G2 to install scripts (#3525)
* add station g2 to device-install.bat

* add station-g2 to device-install.sh

* remove extra space
2024-04-01 05:53:19 -05:00
GUVWAF
a4c22321fc Don't save Neighbors to flash when receiving (#3519)
* Don't save Neighbors to flash when receiving

* Move `shouldSave` to `saveProtoForModule()`

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-31 08:03:29 -05:00
todd-herbert
46a63bf293 Handle edge cases for E-Ink screensaver (#3518)
* remove redundant logic

* Handle special screens for old EInkDisplayClass

* Handle special screens for EInkDynamicDisplay class

* Join an async refresh in progress to avoid skipping screensaver

* attempt trunk fix
2024-03-31 07:04:05 -05:00
Jorropo
279464f96d linux-native: only install linux native deps (#3510)
This is a couple times faster because platformio checks all environment sequentially.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-29 07:42:20 -05:00
Jorropo
3cf6c47bab replace arch with uname -m for arch linux (#3508)
From the manpage:
> arch - print machine hardware name (same as uname -m)

Arch Linux does not have the `arch` alias, only `uname`, so use `uname` to fix this issue:
> ```
> ./bin/build-native.sh: line 18: arch: command not found
> ```

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2024-03-29 01:01:40 -05:00
Jonathan Bennett
64fd866494 Make native honor HAS_SCREEN 0 (#3509)
This allows easier building of the native target without the LovyanGFX libraries.
2024-03-29 00:03:19 -05:00
github-actions[bot]
7b391d1a9f [create-pull-request] automated change (#3507)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-28 19:27:34 -05:00
todd-herbert
8187fa7115 E-Ink Screensaver (#3477)
* fix Wireless Paper double-clear screen at boot

* log when flooded with "responsive" frames

* show the "resuming" screen when waking from deep-sleep

* rename drawDeepSleepScreen
avoid future confusion with "Screen Paused" screen

* show a screensaver frame when screen off
The frame shown during deep sleep is now also passed through showScreensaverFrames()

* Add macros for E-Ink color values.
OLEDDISPLAY_COLOR is inverted. Result of light-mode on E-Ink vs dark-mode on OLED?

* adapt drawDeepSleepScreen to new screensaver convention

* Mark Wireless Paper V1.1 as having problems with ghosting
Any other issues can be marked in a similar way, then handled in code where relevant

* Change screensaver from fullscreen logo to overlay

* identify "quirks" rather than "problems"

* move async refresh polling from display() to a NotifiedWorkerThread

* Prevent skipping of deep-sleep screen
(Hopefully)

* Redesign screensaver overlay
Now displays short name

* Optimize refresh for different displays

* Support older EInkDisplay class

* Don't assume text alignment

* fix spelling of a quirk macro
(No impact to code, but avoids future issues)

* Handle impossibly unlikely millis() overflow error
Should have just let it go, but here we are..

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-28 18:31:11 -05:00
Ben Meadors
daa4d387c6 Don't reboot for non-radio lora config changes (#3505) 2024-03-28 18:14:15 -05:00
Ben Meadors
4c2d5c6a89 Reorder structs to fix build 2024-03-28 07:16:07 -05:00
github-actions[bot]
b5ec35ec78 [create-pull-request] automated change (#3502)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-28 06:44:34 -05:00
Ben Meadors
5732eed86b Fixed position admin messages (#3490)
* Bespoke admin messages for setting and clearing fixed positions

* Add guards against remote admin messages setting things

* Flip ifs
2024-03-26 07:29:07 -05:00
Jonathan Bennett
1542afb847 Add libulfius2.7 to .deb debendencies (#3494) 2024-03-26 00:58:47 -05:00
Jim Whitelaw
acc32916c3 Add multiple configuration options for a minimized build (GPS,WiFi,BT,MQTT,Screen). (#3469)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-25 06:33:57 -05:00
github-actions[bot]
728b58fb94 [create-pull-request] automated change (#3489)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-24 18:50:26 -05:00
GUVWAF
77fb230baa Native: fail-safes for simulated node without config file (#3486)
* LinuxInput: only close if file descriptor is assigned

* Native: set some defaults if no configuration file found
2024-03-24 13:42:32 -05:00
Thomas Göttgens
b960dc1b41 Add Shutdown and reboot to CardKB and friends (#3487)
* Add Shutdown and reboot to CardKB and friends

* aw shucks
2024-03-24 13:41:45 -05:00
code8buster
5f529f7ca3 Remove unused defines from nrf52 variants (#3482)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-24 13:41:28 -05:00
github-actions[bot]
b4dbc2b4bf [create-pull-request] automated change (#3485)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-24 12:44:44 -05:00
Ben Meadors
63df972d42 Revert "[create-pull-request] automated change (#3483)" (#3484)
This reverts commit c87fdfece7.
2024-03-24 08:11:47 -05:00
github-actions[bot]
c87fdfece7 [create-pull-request] automated change (#3483)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-23 19:47:43 -05:00
GUVWAF
381d5230b8 Merge pull request #3480 from GUVWAF/logsMapReport
Don't spam logs if no position with map reporting (2)
2024-03-23 20:12:25 +01:00
GUVWAF
a7c005ccdf Merge branch 'meshtastic:master' into logsMapReport 2024-03-23 19:36:21 +01:00
GUVWAF
71ca6f768f Actually update last_report_to_map 2024-03-23 19:35:12 +01:00
GUVWAF
4cce4c7c93 Set unused header bytes to zero for future use (#3479) 2024-03-23 12:38:29 -05:00
Jonathan Bennett
9e8860d188 Crash fix and remove hard-coded path from PiWebServer (#3478)
* Remove hard-coded path from PiWebServer

* Bump portduino to pick up crash fix

* Remove PiWebServer non-ASCII debug output

* Trunk formatting
2024-03-23 12:29:05 -05:00
GUVWAF
d30d6bd3eb Fix #3452: only alter received packet if port number matches (#3474)
* Use `alterReceivedProtobuf()` for NeighborInfo and Traceroute
`alterReceived()` should never return NULL
Traceroute should be promiscuous

* Remove extensive logging from NeighborInfo module
2024-03-23 07:31:58 -05:00
Ben Meadors
94e4301f2f Add set and remove favorite nodes admin commands (#3471) 2024-03-22 10:53:18 -05:00
Ben Meadors
54818b5f8d Enforce consistent polite channel utilization limits except for Sensor role (#3467) 2024-03-22 07:25:00 -05:00
github-actions[bot]
c77c58d656 [create-pull-request] automated change (#3470)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-22 07:24:10 -05:00
Ben Meadors
794e99c2f9 Log warning cleanup and truth (#3466) 2024-03-21 20:45:48 -05:00
Ben Meadors
7aa013a716 Skip favorite nodes when clearing out oldest in NodeDB (#3464)
* Skip favorite nodes when clearing out oldest in NodeDB

* We should actually map between the types
2024-03-21 19:51:02 -05:00
github-actions[bot]
a57f7730ea [create-pull-request] automated change (#3463)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-21 18:55:50 -05:00
Jonathan Bennett
35754d661d Make MAX_NUM_NODES configurable in variant.h (#3453)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-21 18:26:37 -05:00
Jonathan Bennett
79cfb1e876 Revert "Bump actions to node 20 (#3461)" (#3462)
This reverts commit defeb8e52b.

As per https://github.com/actions/upload-artifact/issues/478 the new version of upload-artifact includes a breaking change.
2024-03-21 16:50:44 -05:00
GUVWAF
155df45d92 Add sanity check for map report interval and position precision (#3459)
* Add sanity check for map report interval and position precision

* Use new `Default::` methods
2024-03-21 16:20:20 -05:00
Jonathan Bennett
907d075917 Revert previous attempt 2024-03-21 16:17:13 -05:00
Jonathan Bennett
9c88906acc Remove double run of build-raspbian 2024-03-21 16:14:45 -05:00
Jonathan Bennett
defeb8e52b Bump actions to node 20 (#3461) 2024-03-21 15:24:57 -05:00
Ben Meadors
6dd337a651 Clear local position on nodedb-reset (#3451)
* Clear local position on nodedb-reset

* NodeDB pointer now, yo

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2024-03-21 14:43:10 -05:00
GUVWAF
0a7ddb7594 Let NeighborInfo Module ignore packets coming from MQTT (#3457) 2024-03-21 14:42:53 -05:00
GUVWAF
4debcd5ccd Set default position precision of mapReport to 14 (#3456) 2024-03-21 14:35:17 -05:00
Jonathan Bennett
fd26914d88 move nodeDB::init code into nodeDB constructor (#3455) 2024-03-21 13:14:02 -05:00
Jonathan Bennett
dfcd0d14f6 Add MaxNodes to Native config (#3427)
* Add MaxNodes to Native

* It compiles...

* Convert nodedb to use new

* Closer but still broken.

* Finally working

* Remove unintended lines

* Don't include a pointer

* Capitalization matters.

* avoid rename in protocol regen

* When trimming the nodeDB, start with a cleanup

* Remove extra cleanupMeshDB() call for now

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-21 09:06:37 -05:00
Jim Whitelaw
f4095ce00d Adds configuration option to exclude the webserver on esp32. (#3369)
* Adds configuration option to not build/include the webserver.

* Adds configuration option to not build/include the webserver.

* Keep initApiServer when excluding webserver

* fixes for failed formatting check

* Once more with feeling! Fix for regression.

* Fix includes for ARCH_ESP32

* Format changes from trunk

* Merge updates from origin

* Revert "Format changes from trunk"

This reverts commit 436e631774.

* jeez!

* tryfix proto conflict

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2024-03-21 06:34:34 -05:00
Mictronics
7aa21f6e3f Fixed double and missing Default class. (#3448)
* Fix LED pinout for T-Echo board marked v1.0, date 2021-6-28

* Merge PR #420

* Fixed double and missing Default class.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-20 10:58:48 -05:00
github-actions[bot]
5e832e2fc6 [create-pull-request] automated change (#3444)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-19 12:02:29 -05:00
Ben Meadors
4fa7f5a748 Fix devicestate persistence bug 2024-03-19 10:31:31 -05:00
Manuel
a6625998f5 fix compiler warnings in NodeDB.h (#3439)
* fix warnings on arm

* make trunk+compiler happy
2024-03-19 06:22:45 -05:00
Manuel
711b85cfe8 fix WLAN crash (#3435)
* fix WLAN crash

* link to commit in arduinothread

* revert usb mode
2024-03-18 15:42:44 -05:00
github-actions[bot]
b98176e73e [create-pull-request] automated change (#3434)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-18 07:33:01 -05:00
Ben Meadors
aae49f5ecf Remove confusing channel suffix (#3432)
* Remove confusing channel suffix

* Missed it
2024-03-17 08:38:49 -05:00
Ben Meadors
0d1d79b6d1 Extract default intervals and coalesce methods into their own file / static class methods (#3425)
* Extract default intervals and coalesce methods into their own file / static class methods

* Missed pax

* Still managed to miss one
2024-03-17 08:18:30 -05:00
Ben Meadors
bb57ccfc9e Remove devicestate no_save (#3424) 2024-03-17 08:16:22 -05:00
Ben Meadors
e27f029d09 Bump minimum NodeInfo send to 5 minutes (#3423)
* Bump minimum NodeInfo send to 3 minutes

* 5
2024-03-16 19:56:42 -05:00
Thomas Göttgens
13cc1b0252 (3/3) Add variant for pico with waveshare and GPS hat (#3412)
* (3/3) Add variant for pico with waveshare and GPS hat, utilizing slow clock.

* Not everybody has Serial2

* Trunk

* Push it real gud

* No init

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-16 10:01:43 -05:00
github-actions[bot]
54a2a4bcc6 [create-pull-request] automated change (#3422)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-16 07:39:28 -05:00
David Ellefsen
611f291d4d Factory reset GNSS_MODEL_MTK GPS modules with PCAS10,3 (#3388)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-15 19:19:50 -05:00
Ben Meadors
9586606229 Handle for heartbeat toradio packets (#3420) 2024-03-15 18:40:48 -05:00
github-actions[bot]
0de36fbfb0 [create-pull-request] automated change (#3419)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-15 17:12:45 -05:00
Andre K
0dda20bc35 fix for I2C scan getting stuck (#3375)
* refactor: add delay for T-Echo peripherals setup

* comment out `PIN_POWER_EN1`
2024-03-15 17:12:30 -05:00
Ben Meadors
52cfec29fc More comprehensive client proxy queue guards (#3414)
* More comprehensive MQTT thread and queue guards

* Consolidate logic

* Remove channel check

* Check for map_reporting_enabled as well

* Update message

* Remove channel check from here as well

* One liner

* Start the mqtt thread back up when channels change and we want mqtt
2024-03-15 16:17:47 -05:00
Thomas Göttgens
4d0d82f7e7 Merge pull request #3411 from meshtastic/rp2040-slowclock
(2/3) Add Slow Clock Support for RP2040 platform.
2024-03-15 20:56:50 +01:00
Thomas Göttgens
34bc22f94d (2/3) Add Slow Clock Support for RP2040 platform. This will disable USB Softserial. 2024-03-15 20:16:36 +01:00
Thomas Göttgens
cb3740708b Merge pull request #3410 from meshtastic/gnss-l76b
(1/3) Support L76B GNSS chip found on pico waveshare shield.
2024-03-15 20:16:06 +01:00
Thomas Göttgens
e8ec167854 Merge branch 'gnss-l76b' of github.com:meshtastic/firmware into gnss-l76b 2024-03-15 19:48:19 +01:00
Thomas Göttgens
b900415218 that should work now 2024-03-15 19:47:47 +01:00
Thomas Göttgens
2eb78fec53 Merge branch 'master' into gnss-l76b 2024-03-15 19:39:47 +01:00
Thomas Göttgens
da7cd5fc7f new Accelerometer lib (#3413)
* new Accelerometer lib

* Use our fork till upstreasm merges changes.

* that PR escalated quickly

* resurrect display flip
2024-03-15 10:45:14 -05:00
Thomas Göttgens
b06c77d46f don't fix this to a hardware model. 2024-03-15 16:43:39 +01:00
Thomas Göttgens
cbc0aa16c5 fix compilation 2024-03-15 16:37:47 +01:00
github-actions[bot]
876a0520a9 [create-pull-request] automated change (#3418)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-15 08:09:48 -05:00
Thomas Göttgens
50cc4cfcf1 We don't use Lorawan (#3417)
#warning "Persistent storage not supported!" [-Wcpp]
2024-03-15 08:07:54 -05:00
Ben Meadors
ec6bdeed81 NodeInfo broadcast ensure default on 0 and enforce 1 hour minimum (#3415)
* NodeInfo broadcasts ensure defaults on 0 and enforce 1 hour minumum

* Doh!

* Hey that's not on config!
2024-03-15 07:12:03 -05:00
Ben Meadors
a085c3ddb3 Try-fix router missed messages (#3405) 2024-03-14 17:00:57 -05:00
Thomas Göttgens
58cdf360f8 (1/3) Support L76B GNSS chip found on pico waveshare shield. Original work by @Mictronics 2024-03-14 16:18:33 +01:00
Ben Meadors
9c37e57e75 Only allow phone to set time for fixed positions (#3403) 2024-03-13 20:27:26 -05:00
Andre K
9d2fcbe1e1 use decoded packets in public MQTT range test/detection sensor filter (#3404)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2024-03-13 18:24:49 -05:00
Ben Meadors
3995e2f708 Remove bunk code 2024-03-13 15:06:52 -05:00
github-actions[bot]
216f85ff22 [create-pull-request] automated change (#3397)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2024-03-13 09:02:48 -05:00
Ben Meadors
2efe436102 Update nrf52 platform and consolidate Adafruit Bus IO (#3393) 2024-03-13 07:20:51 -05:00
Thomas Göttgens
fb16390205 Merge pull request #3395 from tavdog/patch_buzzer_no_turnoff_off_by_one_error
fix off by one error
2024-03-13 09:23:14 +01:00
Tavis
333c3c1c9e fix off by one error
buzzer is index 2, but loop was 0-1 so buzzer never got turned off.
2024-03-12 21:42:08 -10:00
GUVWAF
724fa38a55 Fix T-LoRa V2.1-6 with TCXO init (#3392) 2024-03-12 16:42:34 -05:00
Wolfgang Nagele
38ea681433 Fix LTO discharge curve (#3385)
* Fix LTO discharge curve

* Remove duplicate info
2024-03-12 16:42:21 -05:00
Wolfgang Nagele
ee685b4ed7 Check AQ_SET_PIN instead of EINK dependency (#3387) 2024-03-12 13:03:04 -05:00
Thomas Herrmann
cf11807f97 use priority background for low priority messages (#3381) 2024-03-12 12:21:09 -05:00
Wolfgang Nagele
7f063fbf81 Support external charge detection (#3386)
* Support external charge detection

* trunk fmt
2024-03-12 11:55:31 -05:00
Thomas Göttgens
6215495ccc Merge pull request #3379 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2024-03-12 10:26:17 +01:00
GUVWAF
045dda64e7 Merge pull request #3383 from AeroXuk/patch-1
Fix for incorrect mapTopic mqtt path
2024-03-12 08:39:30 +01:00
AeroXuk
affbd7f2b9 Update MQTT.cpp
Bug fix for #3382
2024-03-12 02:13:52 +00:00
thebentern
f9bf9e2dcc [create-pull-request] automated change 2024-03-11 21:43:46 +00:00
386 changed files with 9018 additions and 2721 deletions

View File

@@ -16,6 +16,9 @@ body:
options:
- NRF52
- ESP32
- RP2040
- Linux Native
- other
validations:
required: true
- type: textarea

View File

@@ -5,7 +5,7 @@ runs:
using: "composite"
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: "recursive"
ref: ${{github.event.pull_request.head.ref}}
@@ -30,12 +30,12 @@ runs:
sudo apt-get install -y libyaml-cpp-dev
- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v3
uses: actions/cache@v4
id: cache-pip # needed in if test
with:
path: ~/.cache/pip

View File

@@ -11,13 +11,13 @@ jobs:
build-esp32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
@@ -41,7 +41,7 @@ jobs:
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: firmware.bin
@@ -54,9 +54,10 @@ jobs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/*.bin
release/*.elf

View File

@@ -13,13 +13,13 @@ jobs:
build-esp32-c3:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
@@ -41,7 +41,7 @@ jobs:
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: firmware-c3.bin
@@ -54,9 +54,10 @@ jobs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/*.bin
release/*.elf

View File

@@ -11,13 +11,13 @@ jobs:
build-esp32-s3:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
@@ -39,7 +39,7 @@ jobs:
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/firmware-ota
file: firmware-s3.bin
@@ -52,9 +52,10 @@ jobs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/*.bin
release/*.elf

View File

@@ -11,7 +11,7 @@ jobs:
build-nrf52:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
@@ -24,9 +24,10 @@ jobs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/*.uf2
release/*.elf

View File

@@ -10,8 +10,13 @@ jobs:
build-raspbian:
runs-on: [self-hosted, linux, ARM64]
steps:
- name: Install libbluetooth
shell: bash
run: |
apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
@@ -37,9 +42,10 @@ jobs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/meshtasticd_linux_aarch64
bin/config-dist.yaml

View File

@@ -0,0 +1,51 @@
name: Build Raspbian Arm
on: workflow_call
permissions:
contents: write
packages: write
jobs:
build-raspbian-armv7l:
runs-on: [self-hosted, linux, ARM]
steps:
- name: Install libbluetooth
shell: bash
run: |
apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
- 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: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
pip install -U meshtastic --pre
- name: Upgrade platformio
shell: bash
run: |
pio upgrade
- name: Build Raspbian
run: bin/build-native.sh
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-raspbian-armv7l-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/meshtasticd_linux_armv7l
bin/config-dist.yaml

View File

@@ -11,7 +11,7 @@ jobs:
build-rpi2040:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
@@ -24,9 +24,10 @@ jobs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/*.uf2
release/*.elf

View File

@@ -8,7 +8,7 @@ on:
branches: [master, develop]
paths-ignore:
- "**.md"
- "version.properties"
- version.properties
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
pull_request_target:
@@ -20,144 +20,99 @@ on:
workflow_dispatch:
jobs:
check:
setup:
strategy:
fail-fast: false
matrix:
include:
- board: rak11200
- board: tlora-v2-1-1_6
- board: tbeam
- board: heltec-v2_1
- board: meshtastic-diy-v1
- board: rak4631
- board: t-echo
- board: station-g2
- board: m5stack-coreink
- board: tbeam-s3-core
- board: tlora-t3s3-v1
- board: t-watch-s3
- board: t-deck
#- board: rak11310
arch: [esp32, esp32s3, esp32c3, nrf52840, rp2040, check]
runs-on: ubuntu-latest
steps:
- id: checkout
uses: actions/checkout@v4
name: Checkout base
- id: jsonStep
run: |
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
echo "$TARGETS"
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
outputs:
esp32: ${{ steps.jsonStep.outputs.esp32 }}
esp32s3: ${{ steps.jsonStep.outputs.esp32s3 }}
esp32c3: ${{ steps.jsonStep.outputs.esp32c3 }}
nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
check: ${{ steps.jsonStep.outputs.check }}
check:
needs: setup
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.setup.outputs.check) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Trunk Check
if: ${{ github.event_name != 'workflow_dispatch' }}
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
- name: Check ${{ matrix.board }}
run: bin/check-all.sh ${{ matrix.board }}
build-esp32:
needs: setup
strategy:
fail-fast: false
matrix:
include:
- board: rak11200
- board: tlora-v2
- board: tlora-v1
- board: tlora_v1_3
- board: tlora-v2-1-1_6
- board: tlora-v2-1-1_6-tcxo
- board: tlora-v2-1-1_8
- board: tbeam
- board: heltec-v2_0
- board: heltec-v2_1
- board: tbeam0_7
- board: meshtastic-diy-v1
- board: hydra
- board: meshtastic-dr-dev
- board: nano-g1
- board: station-g1
- board: m5stack-core
- board: m5stack-coreink
- board: nano-g1-explorer
- board: chatter2
matrix: ${{ fromJson(needs.setup.outputs.esp32) }}
uses: ./.github/workflows/build_esp32.yml
with:
board: ${{ matrix.board }}
build-esp32-s3:
needs: setup
strategy:
fail-fast: false
matrix:
include:
- board: heltec-v3
- board: heltec-wsl-v3
- board: heltec-wireless-tracker
- board: heltec-wireless-tracker-V1-0
- board: heltec-wireless-paper-v1_0
- board: heltec-wireless-paper #v1.1
- board: tbeam-s3-core
- board: tlora-t3s3-v1
- board: t-watch-s3
- board: t-deck
- board: picomputer-s3
- board: station-g2
matrix: ${{ fromJson(needs.setup.outputs.esp32s3) }}
uses: ./.github/workflows/build_esp32_s3.yml
with:
board: ${{ matrix.board }}
build-esp32-c3:
needs: setup
strategy:
fail-fast: false
matrix:
include:
- board: heltec-ht62-esp32c3-sx1262
matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
uses: ./.github/workflows/build_esp32_c3.yml
with:
board: ${{ matrix.board }}
build-nrf52:
needs: setup
strategy:
fail-fast: false
matrix:
include:
- board: rak4631
- board: rak4631_eink
- board: monteops_hw1
- board: t-echo
- board: canaryone
- board: pca10059_diy_eink
- board: feather_diy
- board: nano-g2-ultra
matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
uses: ./.github/workflows/build_nrf52.yml
with:
board: ${{ matrix.board }}
build-rpi2040:
needs: setup
strategy:
fail-fast: false
matrix:
include:
- board: pico
- board: picow
- board: rak11310
- board: senselora_rp2040
- board: rp2040-lora
matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
uses: ./.github/workflows/build_rpi2040.yml
with:
board: ${{ matrix.board }}
build-raspbian:
strategy:
fail-fast: false
max-parallel: 1
uses: ./.github/workflows/build_raspbian.yml
package-raspbian:
uses: ./.github/workflows/package_raspbian.yml
package-raspbian-armv7l:
uses: ./.github/workflows/package_raspbian_armv7l.yml
build-native:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build base
id: base
uses: ./.github/actions/setup-base
@@ -180,27 +135,27 @@ jobs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-native-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/device-*.sh
release/device-*.bat
- name: Docker login
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: meshtastic
password: ${{ secrets.DOCKER_TOKEN }}
- name: Docker setup
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Docker build and push tagged versions
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: docker/build-push-action@v3
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
@@ -209,7 +164,7 @@ jobs:
- 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@v3
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
@@ -221,7 +176,7 @@ jobs:
needs: [check]
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
@@ -237,21 +192,22 @@ jobs:
build-esp32-s3,
build-esp32-c3,
build-nrf52,
build-raspbian,
build-native,
build-rpi2040,
package-raspbian,
package-raspbian-armv7l,
]
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
path: ./
merge-multiple: true
- name: Display structure of downloaded files
run: ls -R
@@ -261,25 +217,30 @@ jobs:
id: version
- name: Move files up
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./*esp32c3*/bleota-c3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase_v2.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat ./firmware-raspbian-*/release/meshtasticd_linux_aarch64 ./firmware-raspbian-*/bin/config-dist.yaml
run: mv -b -t ./ ./release/meshtasticd_linux_aarch64 ./release/meshtasticd_linux_armv7l ./bin/config-dist.yaml
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-${{ steps.version.outputs.version }}
overwrite: true
path: |
./*.bin
./*.uf2
./firmware-*.bin
./firmware-*.uf2
./firmware-*-ota.zip
./device-*.sh
./device-*.bat
./meshtasticd_linux_arm64
./meshtasticd_linux_*
./config-dist.yaml
./littlefs-*.bin
./bleota*bin
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 90
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: firmware-${{ steps.version.outputs.version }}
merge-multiple: true
path: ./output
# For diagnostics
@@ -295,9 +256,10 @@ jobs:
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: debug-elfs-${{ steps.version.outputs.version }}.zip
overwrite: true
path: ./*.elf
retention-days: 30
@@ -319,10 +281,10 @@ jobs:
needs: [gather-artifacts, after-checks]
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x
@@ -330,14 +292,17 @@ jobs:
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: firmware-${{ steps.version.outputs.version }}
merge-multiple: true
path: ./output
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: artifact-deb
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
merge-multiple: true
path: ./output
- name: Display structure of downloaded files
run: ls -R
@@ -350,9 +315,10 @@ jobs:
- name: Zip firmware
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
name: debug-elfs-${{ steps.version.outputs.version }}.zip
merge-multiple: true
path: ./elfs
- name: Zip Elfs
@@ -395,22 +361,32 @@ jobs:
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip
- name: Add raspbian .deb
- name: Add raspbian aarch64 .deb
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
asset_content_type: application/vnd.debian.binary-package
- name: Add raspbian armv7l .deb
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
asset_name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
asset_content_type: application/vnd.debian.binary-package
- name: Bump version.properties
run: >-
bin/bump_version.py
- name: Create version.properties pull request
uses: peter-evans/create-pull-request@v3
uses: peter-evans/create-pull-request@v6
with:
add-paths: |
version.properties

View File

@@ -11,7 +11,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Trunk Check
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b

View File

@@ -17,14 +17,14 @@ jobs:
needs: build-raspbian
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
@@ -36,15 +36,17 @@ jobs:
id: version
- name: Download artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
merge-multiple: true
- name: Display structure of downloaded files
run: ls -R
- name: build .debpkg
run: |
mkdir -p .debpkg/DEBIAN
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
mkdir -p .debpkg/usr/sbin
mkdir -p .debpkg/etc/meshtasticd
@@ -55,6 +57,8 @@ jobs:
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
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
- uses: jiro4989/build-deb-action@v3
with:
@@ -63,11 +67,12 @@ jobs:
maintainer: Jonathan Bennett
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
arch: arm64
depends: libyaml-cpp0.7, openssl
depends: libyaml-cpp0.7, openssl, libulfius2.7
desc: Native Linux Meshtastic binary.
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: artifact-deb
name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
overwrite: true
path: |
./*.deb

View File

@@ -0,0 +1,78 @@
name: Package Raspbian
on:
workflow_call:
workflow_dispatch:
permissions:
contents: write
packages: write
jobs:
build-raspbian_armv7l:
uses: ./.github/workflows/build_raspbian_armv7l.yml
package-raspbian_armv7l:
runs-on: ubuntu-latest
needs: build-raspbian_armv7l
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: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: firmware-raspbian-armv7l-${{ steps.version.outputs.version }}.zip
merge-multiple: true
- name: Display structure of downloaded files
run: ls -R
- name: build .debpkg
run: |
mkdir -p .debpkg/DEBIAN
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
mkdir -p .debpkg/usr/sbin
mkdir -p .debpkg/etc/meshtasticd
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
cp release/meshtasticd_linux_armv7l .debpkg/usr/sbin/meshtasticd
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
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
- uses: jiro4989/build-deb-action@v3
with:
package: meshtasticd
package_root: .debpkg
maintainer: Jonathan Bennett
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
arch: armhf
depends: libyaml-cpp0.7, openssl, libulfius2.7
desc: Native Linux Meshtastic binary.
- uses: actions/upload-artifact@v4
with:
name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
overwrite: true
path: |
./*.deb

View File

@@ -16,7 +16,7 @@ jobs:
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v3
uses: actions/checkout@v4
# step 2
- name: flawfinder_scan
@@ -27,14 +27,15 @@ jobs:
# step 3
- name: save report as pipeline artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: flawfinder_report.sarif
overwrite: true
path: flawfinder_report.sarif
# step 4
- name: publish code scanning alerts
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: flawfinder_report.sarif
category: flawfinder

View File

@@ -17,7 +17,7 @@ jobs:
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v3
uses: actions/checkout@v4
# step 2
- name: full scan
@@ -29,14 +29,15 @@ jobs:
# step 3
- name: save report as pipeline artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: report.sarif
overwrite: true
path: report.sarif
# step 4
- name: publish code scanning alerts
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: report.sarif
category: semgrep

View File

@@ -11,7 +11,7 @@ jobs:
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

View File

@@ -16,7 +16,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Trunk Check
uses: trunk-io/trunk-action@v1

View File

@@ -7,7 +7,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true
@@ -17,16 +17,16 @@ jobs:
- name: Download nanopb
run: |
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.7-linux-x86.tar.gz
tar xvzf nanopb-0.4.7-linux-x86.tar.gz
mv nanopb-0.4.7-linux-x86 nanopb-0.4.7
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.8-linux-x86.tar.gz
tar xvzf nanopb-0.4.8-linux-x86.tar.gz
mv nanopb-0.4.8-linux-x86 nanopb-0.4.8
- name: Re-generate protocol buffers
run: |
./bin/regen-protos.sh
- name: Create pull request
uses: peter-evans/create-pull-request@v3
uses: peter-evans/create-pull-request@v6
with:
add-paths: |
protobufs

View File

@@ -1,32 +1,32 @@
version: 0.1
cli:
version: 1.20.1
version: 1.22.1
plugins:
sources:
- id: trunk
ref: v1.4.4
ref: v1.5.0
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- trufflehog@3.68.5
- trufflehog@3.76.3
- yamllint@1.35.1
- bandit@1.7.7
- checkov@3.2.32
- bandit@1.7.8
- checkov@3.2.95
- terrascan@1.19.1
- trivy@0.49.1
- trivy@0.51.1
#- trufflehog@3.63.2-rc0
- taplo@0.8.1
- ruff@0.3.1
- ruff@0.4.4
- isort@5.13.2
- markdownlint@0.39.0
- oxipng@9.0.0
- svgo@3.2.0
- actionlint@1.6.27
- markdownlint@0.40.0
- oxipng@9.1.1
- svgo@3.3.2
- actionlint@1.7.0
- flake8@7.0.0
- hadolint@2.12.0
- shfmt@3.6.0
- shellcheck@0.9.0
- black@24.2.0
- shellcheck@0.10.0
- black@24.4.2
- git-diff-check
- gitleaks@8.18.2
- clang-format@16.0.3

View File

@@ -1,4 +1,4 @@
FROM debian:bullseye-slim AS builder
FROM debian:bookworm-slim AS builder
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
@@ -11,31 +11,45 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Install build deps
USER root
RUN apt-get update && \
apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev
# create a non-priveleged user & group
# 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
WORKDIR /tmp/firmware
RUN python3 -m venv /tmp/firmware
RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14
# 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 source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh
RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
##### PRODUCTION BUILD #############
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/*
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
USER mesh
RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -qO /tmp/get-platformio.py && \
chmod +x /tmp/get-platformio.py && \
python3 /tmp/get-platformio.py && \
git clone https://github.com/meshtastic/firmware --recurse-submodules /tmp/firmware && \
cd /tmp/firmware && \
chmod +x /tmp/firmware/bin/build-native.sh && \
source ~/.platformio/penv/bin/activate && \
./bin/build-native.sh
FROM frolvlad/alpine-glibc:glibc-2.31
RUN apk --update add --no-cache g++ shadow && \
groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
COPY --from=builder /tmp/firmware/release/meshtasticd_linux_x86_64 /home/mesh/
USER mesh
WORKDIR /home/mesh
CMD sh -cx "./meshtasticd_linux_x86_64 --hwid '${HWID:-$RANDOM}'"
COPY --from=builder /tmp/firmware/release/meshtasticd /home/mesh/
HEALTHCHECK NONE
VOLUME /home/mesh/data
CMD [ "sh", "-cx", "./meshtasticd -d /home/mesh/data --hwid=${HWID:-$RANDOM}" ]
HEALTHCHECK NONE

View File

@@ -1,7 +1,8 @@
; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base]
extends = arduino_base
platform = platformio/espressif32@6.3.2 # This is a temporary fix to the S3-based devices bluetooth issues until we can determine what within ESP-IDF changed and can develop a suitable patch.
custom_esp32_kind = esp32
platform = platformio/espressif32@6.7.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
@@ -15,8 +16,10 @@ board_build.filesystem = littlefs
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
build_unflags = -fno-lto
build_flags =
${arduino_base.build_flags}
-flto
-Wall
-Wextra
-Isrc/platform/esp32

View File

@@ -1,5 +1,6 @@
[esp32c3_base]
extends = esp32_base
custom_esp32_kind = esp32c3
monitor_speed = 115200
monitor_filters = esp32_c3_exception_decoder

View File

@@ -1,15 +1,19 @@
[esp32s2_base]
extends = esp32_base
custom_esp32_kind = esp32s2
build_src_filter =
${esp32_base.build_src_filter} -<nimble/> -<mesh/raspihttp>
${esp32_base.build_src_filter} - <libpax/> -<nimble/> -<mesh/raspihttp>
monitor_speed = 115200
build_flags =
${esp32_base.build_flags}
-DHAS_BLUETOOTH=0
-DMESHTASTIC_EXCLUDE_PAXCOUNTER
-DMESHTASTIC_EXCLUDE_BLUETOOTH
lib_ignore =
${esp32_base.lib_ignore}
NimBLE-Arduino
NimBLE-Arduino
libpax

View File

@@ -1,5 +1,6 @@
[esp32s3_base]
extends = esp32_base
custom_esp32_kind = esp32s3
monitor_speed = 115200

View File

@@ -1,14 +1,15 @@
[nrf52_base]
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
platform = platformio/nordicnrf52@^10.1.0
platform = platformio/nordicnrf52@^10.4.0
extends = arduino_base
build_type = debug ; I'm debugging with ICE a lot now
build_type = debug
build_flags =
${arduino_base.build_flags}
-DSERIAL_BUFFER_SIZE=1024
-Wno-unused-variable
-Isrc/platform/nrf52
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>

View File

@@ -1,6 +1,6 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base]
platform = https://github.com/meshtastic/platform-native.git#a28dd5a9ccd5c48a9bede46037855ff83915d74b
platform = https://github.com/meshtastic/platform-native.git#ad8112adf82ce1f5b917092cf32be07a077801a0
framework = arduino
build_src_filter =
@@ -24,7 +24,7 @@ lib_deps =
${env.lib_deps}
${networking_base.lib_deps}
rweather/Crypto@^0.4.0
lovyan03/LovyanGFX@^1.1.12
https://github.com/lovyan03/LovyanGFX.git#5a39989aa2c9492572255b22f033843ec8900233
build_flags =
${arduino_base.build_flags}
@@ -34,4 +34,4 @@ build_flags =
-DPORTDUINO_LINUX_HARDWARE
-lbluetooth
-lgpiod
-lyaml-cpp
-lyaml-cpp

View File

@@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#612de5399d68b359053f1307ed223d400aea975c
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#60d6ae81fcc73c34b1493ca9e261695e471bc0c2
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.6.2
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.7.2
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m

View File

@@ -2,6 +2,17 @@
set -e
platformioFailed() {
[[ $VIRTUAL_ENV != "" ]] && exit 1 # don't hint at virtualenv if it's already in use
echo -e "\nThere were issues running platformio and you are not using a virtual environment." \
"\nYou may try setting up virtualenv and downloading the latest platformio from pip:" \
"\n\tvirtualenv venv" \
"\n\tsource venv/bin/activate" \
"\n\tpip install platformio" \
"\n\t./bin/build-native.sh # retry building"
exit 1
}
VERSION=$(bin/buildinfo.py long)
SHORT_VERSION=$(bin/buildinfo.py short)
@@ -13,8 +24,8 @@ mkdir -p $OUTDIR/
rm -r $OUTDIR/* || true
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio pkg update
pio run --environment native
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(arch)"
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

View File

@@ -1,9 +1,8 @@
#!/usr/bin/env python3
import configparser
import sys
from readprops import readProps
verObj = readProps('version.properties')
verObj = readProps("version.properties")
propName = sys.argv[1]
print(f"{verObj[propName]}")

View File

@@ -1,5 +1,6 @@
### Define your devices here using Broadcom pin numbering
### Uncomment the block that corresponds to your hardware
### Including the "Module:" line!
---
Lora:
# Module: sx1262 # Waveshare SX126X XXXM
@@ -37,11 +38,22 @@ Lora:
# Busy: 20
# Reset: 18
# Module: sx1268 # SX1268-based modules, tested with Ebyte E22 400M33S
# CS: 21
# IRQ: 16
# Busy: 20
# Reset: 18
# TXen: 6
# RXen: 12
# DIO3_TCXO_VOLTAGE: true
# DIO3_TCXO_VOLTAGE: true # the Waveshare Core1262 and others are known to need this setting
# 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
### Set gpio chip to use in /dev/. Defaults to 0.
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
# gpiochip: 4
@@ -95,23 +107,29 @@ Display:
# Panel: ILI9341
# CS: 8
# DC: 25
# Backlight: 2
# Width: 320
# Height: 240
# Width: 240
# Height: 320
# Rotate: true
Touchscreen:
# Module: STMPE610
### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching.
# Module: STMPE610 # Option 1 for Adafruit PiTFT 2.8
# CS: 7
# IRQ: 24
# Module: XPT2046
# Module: FT5x06 # Option 2 for Adafruit PiTFT 2.8
# IRQ: 24
# I2CAddr: 0x38
# Module: XPT2046 # Waveshare 2.8inch
# CS: 7
# IRQ: 17
### Configure device for direct keyboard input
Input:
# KeyboardDevice: /dev/input/event0
# KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd
###
@@ -121,3 +139,6 @@ Logging:
Webserver:
# Port: 443 # Port for Webserver & Webservices
# RootPath: /usr/share/doc/meshtasticd/web # Root Dir of WebServer
General:
MaxNodes: 200

View File

@@ -32,7 +32,7 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
%PYTHON% -m esptool --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: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
) else (

View File

@@ -52,7 +52,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
"$PYTHON" -m esptool erase_flash
"$PYTHON" -m esptool 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"*}" ]; then
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
else

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""Generate the CI matrix"""
"""Generate the CI matrix."""
import configparser
import json
@@ -34,5 +34,10 @@ for subdir, dirs, files in os.walk(rootdir):
outlist.append(section)
else:
outlist.append(section)
if "board_check" in config[config[c].name]:
if (config[config[c].name]["board_check"] == "true") & (
"check" in options
):
outlist.append(section)
print(json.dumps(outlist))

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
cp "release/meshtasticd_linux_$(arch)" /usr/sbin/meshtasticd
cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd
mkdir /etc/meshtasticd
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml

View File

@@ -1,13 +1,14 @@
import subprocess
import configparser
import traceback
# trunk-ignore-all(ruff/F821)
# trunk-ignore-all(flake8/F821): For SConstruct imports
import sys
from os.path import join
from readprops import readProps
Import("env")
platform = env.PioPlatform()
def esp32_create_combined_bin(source, target, env):
# this sub is borrowed from ESPEasy build toolchain. It's licensed under GPL V3
# https://github.com/letscontrolit/ESPEasy/blob/mega/tools/pio/post_esp32.py
@@ -20,8 +21,8 @@ def esp32_create_combined_bin(source, target, env):
firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin")
chip = env.get("BOARD_MCU")
flash_size = env.BoardConfig().get("upload.flash_size")
flash_freq = env.BoardConfig().get("build.f_flash", '40m')
flash_freq = flash_freq.replace('000000L', 'm')
flash_freq = env.BoardConfig().get("build.f_flash", "40m")
flash_freq = flash_freq.replace("000000L", "m")
flash_mode = env.BoardConfig().get("build.flash_mode", "dio")
memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi")
if flash_mode == "qio" or flash_mode == "qout":
@@ -51,23 +52,42 @@ def esp32_create_combined_bin(source, target, env):
print(f" - {hex(app_offset)} | {firmware_name}")
cmd += [hex(app_offset), firmware_name]
print('Using esptool.py arguments: %s' % ' '.join(cmd))
print("Using esptool.py arguments: %s" % " ".join(cmd))
esptool.main(cmd)
if (platform.name == "espressif32"):
if platform.name == "espressif32":
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
import esptool
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
esp32_kind = env.GetProjectOption("custom_esp32_kind")
if esp32_kind == "esp32":
# Free up some IRAM by removing auxiliary SPI flash chip drivers.
# Wrapped stub symbols are defined in src/platform/esp32/iram-quirk.c.
env.Append(
LINKFLAGS=[
"-Wl,--wrap=esp_flash_chip_gd",
"-Wl,--wrap=esp_flash_chip_issi",
"-Wl,--wrap=esp_flash_chip_winbond",
]
)
else:
# For newer ESP32 targets, using newlib nano works better.
env.Append(LINKFLAGS=["--specs=nano.specs", "-u", "_printf_float"])
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"])
# General options that are passed to the C and C++ compilers
projenv.Append(CCFLAGS=[
"-DAPP_VERSION=" + verObj['long'],
"-DAPP_VERSION_SHORT=" + verObj['short']
])
projenv.Append(
CCFLAGS=[
"-DAPP_VERSION=" + verObj["long"],
"-DAPP_VERSION_SHORT=" + verObj["short"],
]
)

View File

@@ -1 +1 @@
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --experimental_allow_proto3_optional --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto
cd protobufs && ..\nanopb-0.4.8\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated" -I=..\protobufs\ ..\protobufs\meshtastic\*.proto

View File

@@ -2,19 +2,10 @@
set -e
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.7 to be located in the"
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.8 to be located in the"
echo "firmware root directory if the following step fails, you should download the correct"
echo "prebuilt binaries for your computer into nanopb-0.4.7"
echo "prebuilt binaries for your computer into nanopb-0.4.8"
# the nanopb tool seems to require that the .options file be in the current directory!
cd protobufs
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated/ -I=../protobufs meshtastic/*.proto --experimental_allow_proto3_optional
# cd ../src/mesh/generated/meshtastic
# sed -i 's/#include "meshtastic/#include "./g' -- *
# sed -i 's/meshtastic_//g' -- *
#echo "Regenerating protobuf documentation - if you see an error message"
#echo "you can ignore it unless doing a new protobuf release to github."
#bin/regen-docs.sh
../nanopb-0.4.8/generator-bin/protoc --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:../src/mesh/generated/" -I=../protobufs meshtastic/*.proto

View File

@@ -0,0 +1,38 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld"
},
"core": "esp32",
"extra_flags": [
"-D CDEBYTE_EORA_S3",
"-D ARDUINO_USB_CDC_ON_BOOT=1",
"-D ARDUINO_USB_MODE=0",
"-D ARDUINO_RUNNING_CORE=1",
"-D ARDUINO_EVENT_RUNNING_CORE=1",
"-D BOARD_HAS_PSRAM"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "dio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "CDEBYTE_EoRa-S3"
},
"connectivity": ["wifi"],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "CDEBYTE EoRa-S3",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 327680,
"maximum_size": 4194304,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},
"url": "https://www.cdebyte.com/Module-Testkits-EoRaPI",
"vendor": "CDEBYTE"
}

View File

@@ -0,0 +1,39 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld"
},
"core": "esp32",
"extra_flags": [
"-D ARDUINO_USB_CDC_ON_BOOT=0",
"-D ARDUINO_USB_MSC_ON_BOOT=0",
"-D ARDUINO_USB_DFU_ON_BOOT=0",
"-D ARDUINO_USB_MODE=0",
"-D ARDUINO_RUNNING_CORE=1",
"-D ARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "ESP32-S3-WROOM-1-N4"
},
"connectivity": ["wifi"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "ESP32-S3-WROOM-1-N4 (4 MB Flash, No PSRAM)",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 524288,
"maximum_size": 4194304,
"require_upload_port": true,
"speed": 921600
},
"url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf",
"vendor": "Espressif"
}

View File

@@ -0,0 +1,52 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x00B3"],
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "ProMicro compatible nRF52840",
"mcu": "nrf52840",
"variant": "promicro_diy",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
},
"frameworks": ["arduino"],
"name": "ProMicro compatible nRF52840",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["nrfutil", "jlink", "nrfjprog", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.nologo.tech/product/otherboard/NRF52840.html",
"vendor": "Nologo"
}

34
boards/wiphone.json Normal file
View File

@@ -0,0 +1,34 @@
{
"build": {
"arduino": {
"ldscript": "esp32_out.ld",
"partitions": "default_16MB.csv"
},
"core": "esp32",
"extra_flags": [
"-DARDUINO_WIPHONE14",
"-DBOARD_HAS_PSRAM",
"-mfix-esp32-psram-cache-issue",
"-mfix-esp32-psram-cache-strategy=memw"
],
"f_cpu": "240000000L",
"f_flash": "40000000L",
"flash_mode": "dio",
"mcu": "esp32",
"variant": "wiphone",
"board": "WiPhone"
},
"connectivity": ["wifi", "bluetooth"],
"frameworks": ["arduino", "espidf"],
"name": "WIPhone Integrated 1.4",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 532480,
"maximum_size": 6553600,
"maximum_data_size": 4521984,
"require_upload_port": true,
"speed": 921600
},
"url": "https://www.wiphone.io/",
"vendor": "HackEDA"
}

View File

@@ -4,7 +4,7 @@
"ldscript": "esp32_out.ld"
},
"core": "esp32",
"extra_flags": "-DARDUINO_ESP32_DEV",
"extra_flags": ["-DBOARD_HAS_PSRAM", "-DARDUINO_ESP32_DEV"],
"f_cpu": "240000000L",
"f_flash": "40000000L",
"flash_mode": "dio",

View File

@@ -69,17 +69,18 @@ build_flags = -Wno-missing-field-initializers
-DRADIOLIB_EXCLUDE_PAGER
-DRADIOLIB_EXCLUDE_FSK4
-DRADIOLIB_EXCLUDE_APRS
-DRADIOLIB_EXCLUDE_LORAWAN
monitor_speed = 115200
lib_deps =
jgromes/RadioLib@^6.4.0
jgromes/RadioLib@~6.5.0
https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#2044b2c51e91ab4cd8cc93b15e40658cd808dd06
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
nanopb/Nanopb@^0.4.7
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
nanopb/Nanopb@^0.4.8
erriez/ErriezCRC32@^1.0.1
; Used for the code analysis in PIO Home / Inspect
@@ -95,7 +96,6 @@ check_flags =
framework = arduino
lib_deps =
${env.lib_deps}
mprograms/QMC5883LCompass@^1.2.0
end2endzone/NonBlockingRTTTL@^1.3.0
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
@@ -113,12 +113,12 @@ lib_deps =
; (not included in native / portduino)
[environmental_base]
lib_deps =
adafruit/Adafruit BusIO@^1.11.4
adafruit/Adafruit BusIO@^1.15.0
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
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
boschsensortec/BME68x Sensor Library@^1.1.40407
adafruit/Adafruit MCP9808 Library@^2.0.0
https://github.com/KodinLanewave/INA3221@^1.0.0
@@ -130,4 +130,9 @@ lib_deps =
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
adafruit/Adafruit MPU6050@^2.2.4
adafruit/Adafruit LIS3DH@^1.2.4
https://github.com/lewisxhe/BMA423_Library@^0.0.1
adafruit/Adafruit AHTX0@^2.0.5
lewisxhe/SensorLib@^0.2.0
adafruit/Adafruit LSM6DS@^4.7.2
mprograms/QMC5883LCompass@^1.2.0
adafruit/Adafruit VEML7700 Library@^2.1.6
adafruit/Adafruit SHT4x Library@^1.0.4

View File

@@ -1,22 +1,24 @@
#pragma once
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#include "PowerFSM.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include "main.h"
#include "power.h"
#include <Adafruit_LIS3DH.h>
#include <Adafruit_LSM6DS3TRC.h>
#include <Adafruit_MPU6050.h>
#include <Arduino.h>
#include <SensorBMA423.hpp>
#include <Wire.h>
#include <bma.h>
BMA423 bmaSensor;
bool BMA_IRQ = false;
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
#define ACCELEROMETER_CLICK_THRESHOLD 40
uint16_t readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len)
static inline int readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
{
Wire.beginTransmission(address);
Wire.write(reg);
@@ -29,7 +31,7 @@ uint16_t readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len)
return 0; // Pass
}
uint16_t writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len)
static inline int writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
{
Wire.beginTransmission(address);
Wire.write(reg);
@@ -37,8 +39,6 @@ uint16_t writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len
return (0 != Wire.endTransmission());
}
namespace concurrency
{
class AccelerometerThread : public concurrency::OSThread
{
public:
@@ -49,90 +49,22 @@ class AccelerometerThread : public concurrency::OSThread
disable();
return;
}
acceleremoter_type = type;
if (!config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
LOG_DEBUG("AccelerometerThread disabling due to no interested configurations\n");
disable();
return;
}
acceleremoter_type = type;
LOG_DEBUG("AccelerometerThread initializing\n");
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
LOG_DEBUG("MPU6050 initializing\n");
// setup motion detection
mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
mpu.setMotionDetectionThreshold(1);
mpu.setMotionDetectionDuration(20);
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
mpu.setInterruptPinPolarity(true);
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
LOG_DEBUG("LIS3DH initializing\n");
lis.setRange(LIS3DH_RANGE_2_G);
// Adjust threshold, higher numbers are less sensitive
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.begin(readRegister, writeRegister, delay)) {
LOG_DEBUG("BMA423 initializing\n");
Acfg cfg;
cfg.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
cfg.range = BMA4_ACCEL_RANGE_2G;
cfg.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
cfg.perf_mode = BMA4_CONTINUOUS_MODE;
bmaSensor.setAccelConfig(cfg);
bmaSensor.enableAccel();
struct bma4_int_pin_config pin_config;
pin_config.edge_ctrl = BMA4_LEVEL_TRIGGER;
pin_config.lvl = BMA4_ACTIVE_HIGH;
pin_config.od = BMA4_PUSH_PULL;
pin_config.output_en = BMA4_OUTPUT_ENABLE;
pin_config.input_en = BMA4_INPUT_DISABLE;
// The correct trigger interrupt needs to be configured as needed
bmaSensor.setINTPinConfig(pin_config, BMA4_INTR1_MAP);
#ifdef BMA423_INT
pinMode(BMA4XX_INT, INPUT);
attachInterrupt(
BMA4XX_INT,
[] {
// Set interrupt to set irq value to true
BMA_IRQ = true;
},
RISING); // Select the interrupt mode according to the actual circuit
#endif
struct bma423_axes_remap remap_data;
#ifdef T_WATCH_S3
remap_data.x_axis = 1;
remap_data.x_axis_sign = 0;
remap_data.y_axis = 0;
remap_data.y_axis_sign = 0;
remap_data.z_axis = 2;
remap_data.z_axis_sign = 1;
#else
remap_data.x_axis = 0;
remap_data.x_axis_sign = 1;
remap_data.y_axis = 1;
remap_data.y_axis_sign = 0;
remap_data.z_axis = 2;
remap_data.z_axis_sign = 1;
#endif
// Need to raise the wrist function, need to set the correct axis
bmaSensor.setRemapAxes(&remap_data);
// sensor.enableFeature(BMA423_STEP_CNTR, true);
bmaSensor.enableFeature(BMA423_TILT, true);
bmaSensor.enableFeature(BMA423_WAKEUP, true);
// sensor.resetStepCounter();
// Turn on feature interrupt
bmaSensor.enableStepCountInterrupt();
bmaSensor.enableTiltInterrupt();
// It corresponds to isDoubleClick interrupt
bmaSensor.enableWakeupInterrupt();
}
init();
}
void start()
{
init();
setIntervalFromNow(0);
};
protected:
int32_t runOnce() override
{
@@ -150,17 +82,84 @@ class AccelerometerThread : public concurrency::OSThread
buttonPress();
return 500;
}
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.getINT()) {
if (bmaSensor.isTilt() || bmaSensor.isDoubleClick()) {
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.readIrqStatus() != DEV_WIRE_NONE) {
if (bmaSensor.isTilt() || bmaSensor.isDoubleTap()) {
wakeScreen();
return 500;
}
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.shake()) {
wakeScreen();
return 500;
}
return ACCELEROMETER_CHECK_INTERVAL_MS;
}
private:
void init()
{
LOG_DEBUG("AccelerometerThread initializing\n");
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
LOG_DEBUG("MPU6050 initializing\n");
// setup motion detection
mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
mpu.setMotionDetectionThreshold(1);
mpu.setMotionDetectionDuration(20);
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
mpu.setInterruptPinPolarity(true);
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
LOG_DEBUG("LIS3DH initializing\n");
lis.setRange(LIS3DH_RANGE_2_G);
// Adjust threshold, higher numbers are less sensitive
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 &&
bmaSensor.begin(accelerometer_found.address, &readRegister, &writeRegister)) {
LOG_DEBUG("BMA423 initializing\n");
bmaSensor.configAccelerometer(bmaSensor.RANGE_2G, bmaSensor.ODR_100HZ, bmaSensor.BW_NORMAL_AVG4,
bmaSensor.PERF_CONTINUOUS_MODE);
bmaSensor.enableAccelerometer();
bmaSensor.configInterrupt(BMA4_LEVEL_TRIGGER, BMA4_ACTIVE_HIGH, BMA4_PUSH_PULL, BMA4_OUTPUT_ENABLE,
BMA4_INPUT_DISABLE);
#ifdef BMA423_INT
pinMode(BMA4XX_INT, INPUT);
attachInterrupt(
BMA4XX_INT,
[] {
// Set interrupt to set irq value to true
BMA_IRQ = true;
},
RISING); // Select the interrupt mode according to the actual circuit
#endif
#ifdef T_WATCH_S3
// Need to raise the wrist function, need to set the correct axis
bmaSensor.setReampAxes(bmaSensor.REMAP_TOP_LAYER_RIGHT_CORNER);
#else
bmaSensor.setReampAxes(bmaSensor.REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER);
#endif
// bmaSensor.enableFeature(bmaSensor.FEATURE_STEP_CNTR, true);
bmaSensor.enableFeature(bmaSensor.FEATURE_TILT, true);
bmaSensor.enableFeature(bmaSensor.FEATURE_WAKEUP, true);
// bmaSensor.resetPedometer();
// Turn on feature interrupt
bmaSensor.enablePedometerIRQ();
bmaSensor.enableTiltIRQ();
// It corresponds to isDoubleClick interrupt
bmaSensor.enableWakeupIRQ();
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.begin_I2C(accelerometer_found.address)) {
LOG_DEBUG("LSM6DS3 initializing\n");
// Default threshold of 2G, less sensitive options are 4, 8 or 16G
lsm.setAccelRange(LSM6DS_ACCEL_RANGE_2_G);
#ifndef LSM6DS3_WAKE_THRESH
#define LSM6DS3_WAKE_THRESH 20
#endif
lsm.enableWakeup(config.display.wake_on_tap_or_motion, 1, LSM6DS3_WAKE_THRESH);
// Duration is number of occurances needed to trigger, higher threshold is less sensitive
}
}
void wakeScreen()
{
if (powerFSM.getState() == &stateDARK) {
@@ -178,6 +177,9 @@ class AccelerometerThread : public concurrency::OSThread
ScanI2C::DeviceType acceleremoter_type;
Adafruit_MPU6050 mpu;
Adafruit_LIS3DH lis;
Adafruit_LSM6DS3TRC lsm;
SensorBMA423 bmaSensor;
bool BMA_IRQ = false;
};
} // namespace concurrency
#endif

View File

@@ -5,6 +5,16 @@
NCP5623 rgb;
#endif
#ifdef HAS_NEOPIXEL
#include <graphics/NeoPixel.h>
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE);
#endif
#ifdef UNPHONE
#include "unPhone.h"
extern unPhone unphone;
#endif
namespace concurrency
{
class AmbientLightingThread : public concurrency::OSThread
@@ -27,15 +37,31 @@ class AmbientLightingThread : public concurrency::OSThread
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\n");
disable();
return;
}
LOG_DEBUG("AmbientLightingThread initializing\n");
#ifdef HAS_NCP5623
if (_type == ScanI2C::NCP5623) {
rgb.begin();
#endif
#ifdef RGBLED_RED
pinMode(RGBLED_RED, OUTPUT);
pinMode(RGBLED_GREEN, OUTPUT);
pinMode(RGBLED_BLUE, OUTPUT);
#endif
#ifdef HAS_NEOPIXEL
pixels.begin(); // Initialise the pixel(s)
pixels.clear(); // Set all pixel colors to 'off'
pixels.setBrightness(moduleConfig.ambient_lighting.current);
#endif
setLighting();
#endif
#ifdef HAS_NCP5623
}
#endif
}
@@ -43,16 +69,17 @@ class AmbientLightingThread : public concurrency::OSThread
protected:
int32_t runOnce() override
{
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
#ifdef HAS_NCP5623
if (_type == ScanI2C::NCP5623 && moduleConfig.ambient_lighting.led_state) {
#endif
setLighting();
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
} else {
return disable();
#ifdef HAS_NCP5623
}
#else
return disable();
#endif
#endif
return disable();
}
private:
@@ -65,9 +92,36 @@ 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 Ambient lighting w/ current=%d, red=%d, green=%d, blue=%d\n",
LOG_DEBUG("Initializing NCP5623 Ambient lighting w/ current=%d, red=%d, green=%d, blue=%d\n",
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,
moduleConfig.ambient_lighting.blue),
0, NEOPIXEL_COUNT);
pixels.show();
LOG_DEBUG("Initializing NeoPixel Ambient lighting w/ brightness(current)=%d, red=%d, green=%d, blue=%d\n",
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue);
#endif
#ifdef RGBLED_CA
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\n",
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\n",
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\n", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
}
};

View File

@@ -1,10 +1,12 @@
#include "ButtonThread.h"
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_GPS
#include "GPS.h"
#endif
#include "MeshService.h"
#include "PowerFSM.h"
#include "RadioLibInterface.h"
#include "buzz.h"
#include "graphics/Screen.h"
#include "main.h"
#include "modules/ExternalNotificationModule.h"
#include "power.h"
@@ -21,18 +23,24 @@
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)
OneButton ButtonThread::userButton; // Get reference to static member
#endif
ButtonThread::ButtonThread() : OSThread("Button")
{
#if defined(ARCH_PORTDUINO) || defined(BUTTON_PIN)
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
#if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
userButton = OneButton(settingsMap[user], true, true);
this->userButton = OneButton(settingsMap[user], true, true);
LOG_DEBUG("Using GPIO%02d for button\n", settingsMap[user]);
}
#elif defined(BUTTON_PIN)
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN;
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
this->userButton = OneButton(pin, true, true);
LOG_DEBUG("Using GPIO%02d for button\n", pin);
#endif
@@ -41,31 +49,20 @@ ButtonThread::ButtonThread() : OSThread("Button")
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(pin, INPUT_PULLUP_SENSE);
#endif
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
userButton.attachClick(userButtonPressed);
userButton.setClickMs(250);
userButton.setPressMs(c_longPressTime);
userButton.setClickMs(BUTTON_CLICK_MS);
userButton.setPressMs(BUTTON_LONGPRESS_MS);
userButton.setDebounceMs(1);
userButton.attachDoubleClick(userButtonDoublePressed);
userButton.attachMultiClick(userButtonMultiPressed);
userButton.attachMultiClick(userButtonMultiPressed, this); // Reference to instance: get click count from non-static OneButton
#ifndef T_DECK // T-Deck immediately wakes up after shutdown, so disable this function
userButton.attachLongPressStart(userButtonPressedLongStart);
userButton.attachLongPressStop(userButtonPressedLongStop);
#endif
#if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
wakeOnIrq(settingsMap[user], FALLING);
#else
static OneButton *pBtn = &userButton; // only one instance of ButtonThread is created, so static is safe
attachInterrupt(
pin,
[]() {
BaseType_t higherWake = 0;
mainDelay.interruptFromISR(&higherWake);
pBtn->tick();
},
CHANGE);
#endif
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
#ifdef INPUT_PULLUP_SENSE
@@ -73,19 +70,21 @@ ButtonThread::ButtonThread() : OSThread("Button")
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
#endif
userButtonAlt.attachClick(userButtonPressed);
userButtonAlt.setClickMs(250);
userButtonAlt.setPressMs(c_longPressTime);
userButtonAlt.setClickMs(BUTTON_CLICK_MS);
userButtonAlt.setPressMs(BUTTON_LONGPRESS_MS);
userButtonAlt.setDebounceMs(1);
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
userButtonAlt.attachLongPressStart(userButtonPressedLongStart);
userButtonAlt.attachLongPressStop(userButtonPressedLongStop);
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
#endif
#ifdef BUTTON_PIN_TOUCH
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
userButtonTouch.attachClick(touchPressed);
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
userButtonTouch.setPressMs(BUTTON_TOUCH_MS);
userButtonTouch.attachLongPressStart(touchPressedLongStart); // Better handling with longpress than click?
#endif
attachButtonInterrupts();
#endif
}
@@ -136,25 +135,44 @@ int32_t ButtonThread::runOnce()
case BUTTON_EVENT_DOUBLE_PRESSED: {
LOG_BUTTON("Double press!\n");
#if defined(USE_EINK) && defined(PIN_EINK_EN)
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
#endif
service.refreshLocalMeshNode();
service.sendNetworkPing(NODENUM_BROADCAST, true);
if (screen)
screen->print("Sent ad-hoc ping\n");
auto sentPosition = service.trySendPosition(NODENUM_BROADCAST, true);
if (screen) {
if (sentPosition)
screen->print("Sent ad-hoc position\n");
else
screen->print("Sent ad-hoc nodeinfo\n");
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
}
break;
}
case BUTTON_EVENT_MULTI_PRESSED: {
LOG_BUTTON("Multi press!\n");
if (!config.device.disable_triple_click && (gps != nullptr)) {
gps->toggleGpsMode();
if (screen)
screen->forceDisplay();
}
LOG_BUTTON("Mulitipress! %hux\n", multipressClickCount);
switch (multipressClickCount) {
#if HAS_GPS
// 3 clicks: toggle GPS
case 3:
if (!config.device.disable_triple_click && (gps != nullptr)) {
gps->toggleGpsMode();
if (screen)
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
}
break;
#endif
#if defined(USE_EINK) && defined(PIN_EINK_EN) // i.e. T-Echo
// 4 clicks: toggle backlight
case 4:
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
break;
#endif
// No valid multipress action
default:
break;
} // end switch: click count
break;
}
} // end multipress event
case BUTTON_EVENT_LONG_PRESSED: {
LOG_BUTTON("Long press!\n");
@@ -174,21 +192,85 @@ int32_t ButtonThread::runOnce()
power->shutdown();
break;
}
case BUTTON_EVENT_TOUCH_PRESSED: {
#ifdef BUTTON_PIN_TOUCH
case BUTTON_EVENT_TOUCH_LONG_PRESSED: {
LOG_BUTTON("Touch press!\n");
if (screen)
if (screen) {
// Wake if asleep
if (powerFSM.getState() == &stateDARK)
powerFSM.trigger(EVENT_PRESS);
// Update display (legacy behaviour)
screen->forceDisplay();
}
break;
}
#endif // BUTTON_PIN_TOUCH
default:
break;
}
btnEvent = BUTTON_EVENT_NONE;
}
runASAP = false;
return 50;
}
/*
* Attach (or re-attach) hardware interrupts for buttons
* Public method. Used outside class when waking from MCU sleep
*/
void ButtonThread::attachButtonInterrupts()
{
#if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
wakeOnIrq(settingsMap[user], FALLING);
#elif defined(BUTTON_PIN)
// Interrupt for user button, during normal use. Improves responsiveness.
attachInterrupt(
config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN,
[]() {
BaseType_t higherWake = 0;
mainDelay.interruptFromISR(&higherWake);
ButtonThread::userButton.tick();
runASAP = true;
},
CHANGE);
#endif
#ifdef BUTTON_PIN_ALT
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
#endif
#ifdef BUTTON_PIN_TOUCH
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
#endif
}
/*
* Detach the "normal" button interrupts.
* Public method. Used before attaching a "wake-on-button" interrupt for MCU sleep
*/
void ButtonThread::detachButtonInterrupts()
{
#if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
detachInterrupt(settingsMap[user]);
#elif defined(BUTTON_PIN)
detachInterrupt(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
#endif
#ifdef BUTTON_PIN_ALT
detachInterrupt(BUTTON_PIN_ALT);
#endif
#ifdef BUTTON_PIN_TOUCH
detachInterrupt(BUTTON_PIN_TOUCH);
#endif
}
/**
* Watch a GPIO and if we get an IRQ, wake the main thread.
* Use to add wake on button press
@@ -200,10 +282,30 @@ void ButtonThread::wakeOnIrq(int irq, int mode)
[] {
BaseType_t higherWake = 0;
mainDelay.interruptFromISR(&higherWake);
runASAP = true;
},
FALLING);
}
// Static callback
void ButtonThread::userButtonMultiPressed(void *callerThread)
{
// Grab click count from non-static button, while the info is still valid
ButtonThread *thread = (ButtonThread *)callerThread;
thread->storeClickCount();
// Then handle later, in the usual way
btnEvent = BUTTON_EVENT_MULTI_PRESSED;
}
// Non-static method, runs during callback. Grabs info while still valid
void ButtonThread::storeClickCount()
{
#ifdef BUTTON_PIN
multipressClickCount = userButton.getNumberClicks();
#endif
}
void ButtonThread::userButtonPressedLongStart()
{
if (millis() > c_holdOffTime) {

View File

@@ -4,11 +4,22 @@
#include "concurrency/OSThread.h"
#include "configuration.h"
#ifndef BUTTON_CLICK_MS
#define BUTTON_CLICK_MS 250
#endif
#ifndef BUTTON_LONGPRESS_MS
#define BUTTON_LONGPRESS_MS 5000
#endif
#ifndef BUTTON_TOUCH_MS
#define BUTTON_TOCH_MS 400
#endif
class ButtonThread : public concurrency::OSThread
{
public:
static const uint32_t c_longPressTime = 5000; // shutdown after 5s
static const uint32_t c_holdOffTime = 30000; // hold off 30s after boot
static const uint32_t c_holdOffTime = 30000; // hold off 30s after boot
enum ButtonEventType {
BUTTON_EVENT_NONE,
@@ -17,15 +28,18 @@ class ButtonThread : public concurrency::OSThread
BUTTON_EVENT_MULTI_PRESSED,
BUTTON_EVENT_LONG_PRESSED,
BUTTON_EVENT_LONG_RELEASED,
BUTTON_EVENT_TOUCH_PRESSED
BUTTON_EVENT_TOUCH_LONG_PRESSED,
};
ButtonThread();
int32_t runOnce() override;
void attachButtonInterrupts();
void detachButtonInterrupts();
void storeClickCount();
private:
#ifdef BUTTON_PIN
OneButton userButton;
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
static OneButton userButton; // Static - accessed from an interrupt
#endif
#ifdef BUTTON_PIN_ALT
OneButton userButtonAlt;
@@ -33,20 +47,22 @@ class ButtonThread : public concurrency::OSThread
#ifdef BUTTON_PIN_TOUCH
OneButton userButtonTouch;
#endif
#if defined(ARCH_PORTDUINO)
OneButton userButton;
#endif
// set during IRQ
static volatile ButtonEventType btnEvent;
// Store click count during callback, for later use
volatile int multipressClickCount = 0;
static void wakeOnIrq(int irq, int mode);
// IRQ callbacks
static void touchPressed() { btnEvent = BUTTON_EVENT_TOUCH_PRESSED; }
static void userButtonPressed() { btnEvent = BUTTON_EVENT_PRESSED; }
static void userButtonDoublePressed() { btnEvent = BUTTON_EVENT_DOUBLE_PRESSED; }
static void userButtonMultiPressed() { btnEvent = BUTTON_EVENT_MULTI_PRESSED; }
static void userButtonMultiPressed(void *callerThread); // Retrieve click count from non-static Onebutton while still valid
static void userButtonPressedLongStart();
static void userButtonPressedLongStop();
static void touchPressedLongStart() { btnEvent = BUTTON_EVENT_TOUCH_LONG_PRESSED; }
};
extern ButtonThread *buttonThread;

View File

@@ -36,7 +36,7 @@
#define LOG_CRIT(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#define LOG_TRACE(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#else
#ifdef DEBUG_PORT
#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__)

View File

@@ -205,6 +205,62 @@ void rmDir(const char *dirname)
#endif
}
bool fsCheck()
{
#if defined(ARCH_NRF52)
size_t write_size = 0;
size_t read_size = 0;
char buf[32] = {0};
Adafruit_LittleFS_Namespace::File file(FSCom);
const char *text = "meshtastic fs test";
size_t text_length = strlen(text);
const char *filename = "/meshtastic.txt";
LOG_DEBUG("Try create file .\n");
if (file.open(filename, FILE_O_WRITE)) {
write_size = file.write(text);
} else {
LOG_DEBUG("Open file failed .\n");
goto FORMAT_FS;
}
if (write_size != text_length) {
LOG_DEBUG("Text bytes do not match .\n");
file.close();
goto FORMAT_FS;
}
file.close();
if (!file.open(filename, FILE_O_READ)) {
LOG_DEBUG("Open file failed .\n");
goto FORMAT_FS;
}
read_size = file.readBytes(buf, text_length);
if (read_size != text_length) {
LOG_DEBUG("Text bytes do not match .\n");
file.close();
goto FORMAT_FS;
}
if (memcmp(buf, text, text_length) != 0) {
LOG_DEBUG("The written bytes do not match the read bytes .\n");
file.close();
goto FORMAT_FS;
}
return true;
FORMAT_FS:
LOG_DEBUG("Format FS ....\n");
FSCom.format();
FSCom.begin();
return false;
#else
return true;
#endif
}
void fsInit()
{
#ifdef FSCom
@@ -212,8 +268,37 @@ void fsInit()
LOG_ERROR("Filesystem mount Failed.\n");
// assert(0); This auto-formats the partition, so no need to fail here.
}
#ifdef ARCH_ESP32
#if defined(ARCH_ESP32)
LOG_DEBUG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
#elif defined(ARCH_NRF52)
/*
* nRF52840 has a certain chance of automatic formatting failure.
* Try to create a file after initializing the file system. If the creation fails,
* it means that the file system is not working properly. Please format it manually again.
* To check the normality of the file system, you need to disable the LFS_NO_ASSERT assertion.
* Otherwise, the assertion will be entered at the moment of reading or opening, and the FS will not be formatted.
* */
bool ret = false;
uint8_t retry = 3;
while (retry--) {
ret = fsCheck();
if (ret) {
LOG_DEBUG("File system check is OK.\n");
break;
}
delay(10);
}
// It may not be possible to reach this step.
// Add a loop here to prevent unpredictable situations from happening.
// Can add a screen to display error status later.
if (!ret) {
while (1) {
LOG_ERROR("The file system is damaged and cannot proceed to the next step.\n");
delay(1000);
}
}
#else
LOG_DEBUG("Filesystem files:\n");
#endif

View File

@@ -4,8 +4,6 @@
#include "configuration.h"
#include <Arduino.h>
extern NodeDB nodeDB;
namespace meshtastic
{
@@ -55,7 +53,7 @@ class GPSStatus : public Status
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed latitude\n");
#endif
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
return node->position.latitude_i;
} else {
return p.latitude_i;
@@ -68,7 +66,7 @@ class GPSStatus : public Status
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed longitude\n");
#endif
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
return node->position.longitude_i;
} else {
return p.longitude_i;
@@ -81,27 +79,18 @@ class GPSStatus : public Status
#ifdef GPS_EXTRAVERBOSE
LOG_WARN("Using fixed altitude\n");
#endif
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
return node->position.altitude;
} else {
return p.altitude;
}
}
uint32_t getDOP() const
{
return p.PDOP;
}
uint32_t getDOP() const { return p.PDOP; }
uint32_t getHeading() const
{
return p.ground_track;
}
uint32_t getHeading() const { return p.ground_track; }
uint32_t getNumSatellites() const
{
return p.sats_in_view;
}
uint32_t getNumSatellites() const { return p.sats_in_view; }
bool matches(const GPSStatus *newStatus) const
{
@@ -149,4 +138,4 @@ class GPSStatus : public Status
} // namespace meshtastic
extern meshtastic::GPSStatus *gpsStatus;
extern meshtastic::GPSStatus *gpsStatus;

View File

@@ -24,11 +24,13 @@
#include "nrfx_power.h"
#endif
#ifdef DEBUG_HEAP_MQTT
#if defined(DEBUG_HEAP_MQTT) && !MESHTASTIC_EXCLUDE_MQTT
#include "mqtt/MQTT.h"
#include "target_specific.h"
#if !MESTASTIC_EXCLUDE_WIFI
#include <WiFi.h>
#endif
#endif
#ifndef DELAY_FOREVER
#define DELAY_FOREVER portMAX_DELAY
@@ -48,13 +50,26 @@ RTC_NOINIT_ATTR uint64_t RTC_reg_b;
esp_adc_cal_characteristics_t *adc_characs = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
#ifndef ADC_ATTENUATION
static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_atten_t atten = ADC_ATTEN_DB_12;
#else
static const adc_atten_t atten = ADC_ATTENUATION;
#endif
#endif // BATTERY_PIN && ARCH_ESP32
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
#ifdef EXT_CHRG_DETECT
#ifndef EXT_CHRG_DETECT_MODE
static const uint8_t ext_chrg_detect_mode = INPUT;
#else
static const uint8_t ext_chrg_detect_mode = EXT_CHRG_DETECT_MODE;
#endif
#ifndef EXT_CHRG_DETECT_VALUE
static const uint8_t ext_chrg_detect_value = HIGH;
#else
static const uint8_t ext_chrg_detect_value = EXT_CHRG_DETECT_VALUE;
#endif
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor;
INA3221Sensor ina3221Sensor;
@@ -169,7 +184,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual uint16_t getBattVoltage() override
{
#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasINA()) {
LOG_DEBUG("Using INA on I2C addr 0x%x for device battery voltage\n", config.power.device_battery_ina_address);
return getINAVoltage();
@@ -208,7 +223,17 @@ class AnalogBatteryLevel : public HasBatteryLevel
raw = raw / BATTERY_SENSE_SAMPLES;
scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
#endif
last_read_value += (scaled - last_read_value) * 0.5; // Virtual LPF
if (!initial_read_done) {
// Flush the smoothing filter with an ADC reading, if the reading is plausibly correct
if (scaled > last_read_value)
last_read_value = scaled;
initial_read_done = true;
} else {
// Already initialized - filter this reading
last_read_value += (scaled - last_read_value) * 0.5; // Virtual LPF
}
// LOG_DEBUG("battery gpio %d raw val=%u scaled=%u filtered=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled), (uint32_t)
// (last_read_value));
}
@@ -322,7 +347,14 @@ class AnalogBatteryLevel : public HasBatteryLevel
/// Assume charging if we have a battery and external power is connected.
/// we can't be smart enough to say 'full'?
virtual bool isCharging() override { return isBatteryConnect() && isVbusIn(); }
virtual bool isCharging() override
{
#ifdef EXT_CHRG_DETECT
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
#else
return isBatteryConnect() && isVbusIn();
#endif
}
private:
/// If we see a battery voltage higher than physics allows - assume charger is pumping
@@ -335,10 +367,12 @@ class AnalogBatteryLevel : public HasBatteryLevel
const float noBatVolt = (OCV[NUM_OCV_POINTS - 1] - 500) * NUM_CELLS;
// Start value from minimum voltage for the filter to not start from 0
// that could trigger some events.
// This value is over-written by the first ADC reading, it the voltage seems reasonable.
bool initial_read_done = false;
float last_read_value = (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS);
uint32_t last_read_time_ms = 0;
#if defined(HAS_TELEMETRY) && !defined(ARCH_PORTDUINO)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
uint16_t getINAVoltage()
{
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
@@ -389,6 +423,9 @@ bool Power::analogInit()
#ifdef EXT_PWR_DETECT
pinMode(EXT_PWR_DETECT, INPUT);
#endif
#ifdef EXT_CHRG_DETECT
pinMode(EXT_CHRG_DETECT, ext_chrg_detect_mode);
#endif
#ifdef BATTERY_PIN
LOG_DEBUG("Using analog input %d for battery level\n", BATTERY_PIN);
@@ -475,12 +512,7 @@ void Power::shutdown()
{
LOG_INFO("Shutting down\n");
#ifdef HAS_PMU
if (pmu_found == true) {
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
PMU->shutdown();
}
#elif defined(ARCH_NRF52) || defined(ARCH_ESP32)
#if defined(ARCH_NRF52) || defined(ARCH_ESP32)
#ifdef PIN_LED1
ledOff(PIN_LED1);
#endif
@@ -523,14 +555,24 @@ void Power::readPowerStatus()
#ifdef NRF_APM // Section of code detects USB power on the RAK4631 and updates the power states. Takes 20 seconds or so to detect
// changes.
static nrfx_power_usb_state_t prev_nrf_usb_state = (nrfx_power_usb_state_t)-1; // -1 so that state detected at boot
nrfx_power_usb_state_t nrf_usb_state = nrfx_power_usbstatus_get();
if (nrf_usb_state == NRFX_POWER_USB_STATE_DISCONNECTED) {
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
NRF_USB = OptFalse;
} else {
powerFSM.trigger(EVENT_POWER_CONNECTED);
NRF_USB = OptTrue;
// If state changed
if (nrf_usb_state != prev_nrf_usb_state) {
// If changed to DISCONNECTED
if (nrf_usb_state == NRFX_POWER_USB_STATE_DISCONNECTED) {
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
NRF_USB = OptFalse;
}
// If changed to CONNECTED / READY
else {
powerFSM.trigger(EVENT_POWER_CONNECTED);
NRF_USB = OptTrue;
}
// Cache the current state
prev_nrf_usb_state = nrf_usb_state;
}
#endif
// Notify any status instances that are observing us

View File

@@ -8,6 +8,7 @@
* actions to be taken upon entering or exiting each state.
*/
#include "PowerFSM.h"
#include "Default.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "configuration.h"
@@ -16,6 +17,10 @@
#include "sleep.h"
#include "target_specific.h"
#ifndef SLEEP_TIME
#define SLEEP_TIME 30
#endif
/// Should we behave as if we have AC power now?
static bool isPowered()
{
@@ -45,7 +50,7 @@ static void sdsEnter()
{
LOG_DEBUG("Enter state: SDS\n");
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs), false);
doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false);
}
extern Power *power;
@@ -80,7 +85,7 @@ static void lsIdle()
// If some other service would stall sleep, don't let sleep happen yet
if (doPreflightSleep()) {
// Briefly come out of sleep long enough to blink the led once every few seconds
uint32_t sleepTime = 30;
uint32_t sleepTime = SLEEP_TIME;
setLed(false); // Never leave led on while in light sleep
esp_sleep_source_t wakeCause2 = doLightSleep(sleepTime * 1000LL);
@@ -102,9 +107,7 @@ static void lsIdle()
break;
default:
// We woke for some other reason (button press, device interrupt)
// uint64_t status = esp_sleep_get_ext1_wakeup_status();
LOG_INFO("wakeCause2 %d\n", wakeCause2);
// We woke for some other reason (button press, device IRQ interrupt)
#ifdef BUTTON_PIN
bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
@@ -182,10 +185,12 @@ static void powerEnter()
screen->setOn(true);
setBluetoothEnable(true);
// within enter() the function getState() returns the state we came from
if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 &&
// Mothballed: print change of power-state to device screen
/* if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 &&
strcmp(powerFSM.getState()->name, "DARK") != 0) {
screen->print("Powered...\n");
}
}*/
}
}
@@ -202,8 +207,10 @@ static void powerExit()
{
screen->setOn(true);
setBluetoothEnable(true);
if (!isPowered())
screen->print("Unpowered...\n");
// Mothballed: print change of power-state to device screen
/*if (!isPowered())
screen->print("Unpowered...\n");*/
}
static void onEnter()
@@ -245,7 +252,6 @@ Fsm powerFSM(&stateBOOT);
void PowerFSM_setup()
{
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool isInfrastructureRole = isRouter || config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER;
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
@@ -342,15 +348,18 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
powerFSM.add_timed_transition(&stateON, &stateDARK,
getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
"Screen-on timeout");
powerFSM.add_timed_transition(&statePOWER, &stateDARK,
getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
"Screen-on timeout");
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
"Screen-on timeout");
#ifdef USE_EINK
// Allow E-Ink devices to suppress the screensaver, if screen timeout set to 0
if (config.display.screen_on_secs > 0)
#endif
{
powerFSM.add_timed_transition(&stateON, &stateDARK,
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs),
NULL, "Screen-on timeout");
powerFSM.add_timed_transition(&statePOWER, &stateDARK,
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs),
NULL, "Screen-on timeout");
}
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
#ifdef ARCH_ESP32
@@ -358,13 +367,27 @@ void PowerFSM_setup()
// 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) {
powerFSM.add_timed_transition(&stateNB, isInfrastructureRole ? &stateSDS : &stateLS,
getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
powerFSM.add_timed_transition(&stateNB, &stateLS,
Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
"Min wake timeout");
powerFSM.add_timed_transition(&stateDARK, isInfrastructureRole ? &stateSDS : &stateLS,
getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs),
NULL, "Bluetooth timeout");
// If ESP32 and using power-saving, timer mover from DARK to light-sleep
// Also serves purpose of the old DARK to DARK transition(?) See https://github.com/meshtastic/firmware/issues/3517
powerFSM.add_timed_transition(
&stateDARK, &stateLS,
Default::getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL,
"Bluetooth timeout");
} else {
// If ESP32, but not using power-saving, check periodically if config has drifted out of stateDark
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs),
NULL, "Screen-on timeout");
}
#else
// If not ESP32, light-sleep not used. Check periodically if config has drifted out of stateDark
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
"Screen-on timeout");
#endif
powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state

View File

@@ -1,3 +1,4 @@
#include "Default.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "concurrency/OSThread.h"
@@ -28,7 +29,7 @@ class PowerFSMThread : public OSThread
timeLastPowered = millis();
} else if (config.power.on_battery_shutdown_after_secs > 0 && config.power.on_battery_shutdown_after_secs != UINT32_MAX &&
millis() > (timeLastPowered +
getConfiguredOrDefaultMs(
Default::getConfiguredOrDefaultMs(
config.power.on_battery_shutdown_after_secs))) { // shutdown after 30 minutes unpowered
powerFSM.trigger(EVENT_SHUTDOWN);
}

View File

@@ -59,9 +59,18 @@ class PowerStatus : public Status
int getBatteryVoltageMv() const { return batteryVoltageMv; }
/**
* Note: 0% battery means 'unknown/this board doesn't have a battery installed'
* Note: for boards with battery pin or PMU, 0% battery means 'unknown/this board doesn't have a battery installed'
*/
#if defined(HAS_PMU) || defined(BATTERY_PIN)
uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 0; }
#endif
/**
* Note: for boards without battery pin and PMU, 101% battery means 'the board is using external power'
*/
#if !defined(HAS_PMU) && !defined(BATTERY_PIN)
uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 101; }
#endif
bool matches(const PowerStatus *newStatus) const
{

View File

@@ -99,7 +99,7 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
// If we are the first message on a report, include the header
if (!isContinuationMessage) {
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile
if (rtc_sec > 0) {
long hms = rtc_sec % SEC_PER_DAY;
// hms += tz.tz_dsttime * SEC_PER_HOUR;
@@ -182,11 +182,11 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len)
{
const char alphabet[17] = "0123456789abcdef";
log(logLevel, " +------------------------------------------------+ +----------------+\n");
log(logLevel, " |.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f | | ASCII |\n");
log(logLevel, " +------------------------------------------------+ +----------------+\n");
log(logLevel, " |.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f | | ASCII |\n");
for (uint16_t i = 0; i < len; i += 16) {
if (i % 128 == 0)
log(logLevel, " +------------------------------------------------+ +----------------+\n");
log(logLevel, " +------------------------------------------------+ +----------------+\n");
char s[] = "| | | |\n";
uint8_t ix = 1, iy = 52;
for (uint8_t j = 0; j < 16; j++) {
@@ -208,7 +208,7 @@ void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16
log(logLevel, ".");
log(logLevel, s);
}
log(logLevel, " +------------------------------------------------+ +----------------+\n");
log(logLevel, " +------------------------------------------------+ +----------------+\n");
}
std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...)

View File

@@ -2,8 +2,13 @@
#include "NodeDB.h"
#include "PowerFSM.h"
#include "configuration.h"
#include "time.h"
#ifdef RP2040_SLOW_CLOCK
#define Port Serial2
#else
#define Port Serial
#endif
// Defaulting to the formerly removed phone_timeout_secs value of 15 minutes
#define SERIAL_CONNECTION_TIMEOUT (15 * 60) * 1000UL
@@ -31,6 +36,10 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con
canWrite = false; // We don't send packets to our port until it has talked to us first
// setDestination(&noopPrint); for testing, try turning off 'all' debug output and see what leaks
#ifdef RP2040_SLOW_CLOCK
Port.setTX(SERIAL2_TX);
Port.setRX(SERIAL2_RX);
#endif
Port.begin(SERIAL_BAUD);
#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040)
time_t timeout = millis();
@@ -42,7 +51,9 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con
}
}
#endif
#if !ARCH_PORTDUINO
emitRebooted();
#endif
}
int32_t SerialConsole::runOnce()
@@ -64,7 +75,7 @@ bool SerialConsole::checkIsConnected()
/**
* we override this to notice when we've received a protobuf over the serial
* stream. Then we shunt off debug serial output.
* stream. Then we shut off debug serial output.
*/
bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
{

View File

@@ -74,6 +74,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define RTC_DATA_ATTR
#endif
// -----------------------------------------------------------------------------
// Regulatory overrides for producing regional builds
// -----------------------------------------------------------------------------
// Define if region should override user saved region
// #define LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_SG_923
// -----------------------------------------------------------------------------
// Feature toggles
// -----------------------------------------------------------------------------
@@ -111,6 +118,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MCP9808_ADDR 0x18
#define INA_ADDR 0x40
#define INA_ADDR_ALTERNATE 0x41
#define INA_ADDR_WAVESHARE_UPS 0x43
#define INA3221_ADDR 0x42
#define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B
@@ -118,8 +126,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D
#define SHT31_ADDR 0x44
#define SHT31_4x_ADDR 0x44
#define PMSA0031_ADDR 0x12
#define AHT10_ADDR 0x38
#define RCWL9620_ADDR 0x57
#define VEML7700_ADDR 0x10
// -----------------------------------------------------------------------------
// ACCELEROMETER
@@ -127,6 +138,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MPU6050_ADDR 0x68
#define LIS3DH_ADR 0x18
#define BMA423_ADDR 0x19
#define LSM6DS3_ADDR 0x6A
// -----------------------------------------------------------------------------
// LED
@@ -136,9 +148,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------
#define ATECC608B_ADDR 0x35
// -----------------------------------------------------------------------------
// IO Expander
// -----------------------------------------------------------------------------
#define TCA9555_ADDR 0x26
// -----------------------------------------------------------------------------
// GPS
// -----------------------------------------------------------------------------
@@ -160,19 +176,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
also enable HAS_ option not specifically disabled by variant.h */
#include "architecture.h"
#ifndef DEFAULT_REBOOT_SECONDS
#define DEFAULT_REBOOT_SECONDS 7
#endif
#ifndef DEFAULT_SHUTDOWN_SECONDS
#define DEFAULT_SHUTDOWN_SECONDS 2
#endif
/* Step #3: mop up with disabled values for HAS_ options not handled by the above two */
// -----------------------------------------------------------------------------
// GPS
// -----------------------------------------------------------------------------
#ifndef GPS_BAUDRATE
#define GPS_BAUDRATE 9600
#endif
#ifndef GPS_THREAD_INTERVAL
#define GPS_THREAD_INTERVAL 100
#endif
#ifndef HAS_WIFI
#define HAS_WIFI 0
#endif
@@ -223,7 +236,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#error HW_VENDOR must be defined
#endif
// global switch to turn off all optional modules for a minimzed build
// -----------------------------------------------------------------------------
// Global switches to turn off features for a minimized build
// -----------------------------------------------------------------------------
// #define MESHTASTIC_MINIMIZE_BUILD 1
#ifdef MESHTASTIC_MINIMIZE_BUILD
#define MESHTASTIC_EXCLUDE_MODULES 1
#define MESHTASTIC_EXCLUDE_WIFI 1
#define MESHTASTIC_EXCLUDE_BLUETOOTH 1
#define MESHTASTIC_EXCLUDE_GPS 1
#define MESHTASTIC_EXCLUDE_SCREEN 1
#define MESHTASTIC_EXCLUDE_MQTT 1
#endif
// Turn off all optional modules
#ifdef MESHTASTIC_EXCLUDE_MODULES
#define MESHTASTIC_EXCLUDE_AUDIO 1
#define MESHTASTIC_EXCLUDE_DETECTIONSENSOR 1
@@ -242,3 +269,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MESHTASTIC_EXCLUDE_INPUTBROKER 1
#define MESHTASTIC_EXCLUDE_SERIAL 1
#endif
// // Turn off wifi even if HW supports wifi (webserver relies on wifi and is also disabled)
#ifdef MESHTASTIC_EXCLUDE_WIFI
#define MESHTASTIC_EXCLUDE_WEBSERVER 1
#undef HAS_WIFI
#define HAS_WIFI 0
#endif
// // Turn off Bluetooth
#ifdef MESHTASTIC_EXCLUDE_BLUETOOTH
#undef HAS_BLUETOOTH
#define HAS_BLUETOOTH 0
#endif
// // Turn off GPS
#ifdef MESHTASTIC_EXCLUDE_GPS
#undef HAS_GPS
#define HAS_GPS 0
#undef MESHTASTIC_EXCLUDE_RANGETEST
#define MESHTASTIC_EXCLUDE_RANGETEST 1
#endif
// Turn off Screen
#ifdef MESHTASTIC_EXCLUDE_SCREEN
#undef HAS_SCREEN
#define HAS_SCREEN 0
#endif

View File

@@ -0,0 +1,5 @@
#pragma once
enum LoRaRadioType { NO_RADIO, STM32WLx_RADIO, SIM_RADIO, RF95_RADIO, SX1262_RADIO, SX1268_RADIO, LLCC68_RADIO, SX1280_RADIO };
extern LoRaRadioType radioType;

View File

@@ -36,8 +36,8 @@ ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
{
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423};
return firstOfOrNONE(3, types);
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3};
return firstOfOrNONE(4, types);
}
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const

View File

@@ -29,6 +29,7 @@ class ScanI2C
INA3221,
MCP9808,
SHT31,
SHT4X,
SHTC3,
LPS22HB,
QMC6310,
@@ -38,9 +39,13 @@ class ScanI2C
MPU6050,
LIS3DH,
BMA423,
#ifdef HAS_NCP5623
BQ24295,
LSM6DS3,
TCA9555,
VEML7700,
RCWL9620,
NCP5623,
#endif
AHT10
} DeviceType;
// typedef uint8_t DeviceAddress;

View File

@@ -183,8 +183,13 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
case ATECC608B_ADDR:
type = ATECC608B;
if (atecc.begin(addr.address) == true) {
#ifdef RP2040_SLOW_CLOCK
if (atecc.begin(addr.address, Wire, Serial2) == true)
#else
if (atecc.begin(addr.address) == true)
#endif
{
LOG_INFO("ATECC608B initialized\n");
} else {
LOG_WARN("ATECC608B initialization failed\n");
@@ -251,9 +256,15 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
type = BMP_280;
}
break;
#ifndef HAS_NCP5623
case AHT10_ADDR:
LOG_INFO("AHT10 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = AHT10;
break;
#endif
case INA_ADDR:
case INA_ADDR_ALTERNATE:
case INA_ADDR_WAVESHARE_UPS:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
if (registerValue == 0x5449) {
@@ -265,8 +276,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
}
break;
case INA3221_ADDR:
LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = INA3221;
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
if (registerValue == 0x5449) {
LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = INA3221;
} else { // Unknown device
LOG_INFO("No INA3221 found at address 0x%x\n", (uint8_t)addr.address);
}
break;
case MCP9808_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
@@ -280,19 +297,51 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
break;
SCAN_SIMPLE_CASE(SHT31_ADDR, SHT31, "SHT31 sensor found\n")
case SHT31_4x_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2);
if (registerValue == 0x11a2) {
type = SHT4X;
LOG_INFO("SHT4X sensor found\n");
} else {
type = SHT31;
LOG_INFO("SHT31 sensor found\n");
}
break;
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found\n")
SCAN_SIMPLE_CASE(RCWL9620_ADDR, RCWL9620, "RCWL9620 sensor found\n")
case LPS22HB_ADDR_ALT:
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found\n")
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found\n")
SCAN_SIMPLE_CASE(QMI8658_ADDR, QMI8658, "QMI8658 Highrate 6-Axis inertial measurement sensor found\n")
case QMI8658_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0A), 1); // get ID
if (registerValue == 0xC0) {
type = BQ24295;
LOG_INFO("BQ24295 PMU found\n");
break;
}
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID
if (registerValue == 0x6A) {
type = LSM6DS3;
LOG_INFO("LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address);
} else {
type = QMI8658;
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n");
}
break;
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n")
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n");
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found\n");
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found\n");
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found\n");
default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);

View File

@@ -1,9 +1,14 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_GPS
#include "Default.h"
#include "GPS.h"
#include "NodeDB.h"
#include "RTC.h"
#include "configuration.h"
#include "main.h" // pmu_found
#include "sleep.h"
#include "cas.h"
#include "ubx.h"
#ifdef ARCH_PORTDUINO
@@ -48,6 +53,28 @@ void GPS::UBXChecksum(uint8_t *message, size_t length)
message[length - 1] = CK_B;
}
// Calculate the checksum for a CAS packet
void GPS::CASChecksum(uint8_t *message, size_t length)
{
uint32_t cksum = ((uint32_t)message[5] << 24); // Message ID
cksum += ((uint32_t)message[4]) << 16; // Class
cksum += message[2]; // Payload Len
// Iterate over the payload as a series of uint32_t's and
// accumulate the cksum
uint32_t const *payload = (uint32_t *)(message + 6);
for (size_t i = 0; i < (length - 10) / 4; i++) {
uint32_t pl = payload[i];
cksum += pl;
}
// Place the checksum values in the message
message[length - 4] = (cksum & 0xFF);
message[length - 3] = (cksum & (0xFF << 8)) >> 8;
message[length - 2] = (cksum & (0xFF << 16)) >> 16;
message[length - 1] = (cksum & (0xFF << 24)) >> 24;
}
// Function to create a ublox packet for editing in memory
uint8_t GPS::makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg)
{
@@ -69,6 +96,41 @@ uint8_t GPS::makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_siz
return (payload_size + 8);
}
// Function to create a CAS packet for editing in memory
uint8_t GPS::makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg)
{
// General CAS structure
// | H1 | H2 | payload_len | cls | msg | Payload ... | Checksum |
// Size: | 1 | 1 | 2 | 1 | 1 | payload_len | 4 |
// Pos: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 ... | 6 + payload_len ... |
// |------|------|-------------|------|------|------|--------------|---------------------------|
// | 0xBA | 0xCE | 0xXX | 0xXX | 0xXX | 0xXX | 0xXX | 0xXX ... | 0xXX | 0xXX | 0xXX | 0xXX |
// Construct the CAS packet
UBXscratch[0] = 0xBA; // header 1 (0xBA)
UBXscratch[1] = 0xCE; // header 2 (0xCE)
UBXscratch[2] = payload_size; // length 1
UBXscratch[3] = 0; // length 2
UBXscratch[4] = class_id; // class
UBXscratch[5] = msg_id; // id
UBXscratch[6 + payload_size] = 0x00; // Checksum
UBXscratch[7 + payload_size] = 0x00;
UBXscratch[8 + payload_size] = 0x00;
UBXscratch[9 + payload_size] = 0x00;
for (int i = 0; i < payload_size; i++) {
UBXscratch[6 + i] = pgm_read_byte(&msg[i]);
}
CASChecksum(UBXscratch, (payload_size + 10));
#if defined(GPS_DEBUG) && defined(DEBUG_PORT)
LOG_DEBUG("Constructed CAS packet: \n");
DEBUG_PORT.hexDump(MESHTASTIC_LOG_LEVEL_DEBUG, UBXscratch, payload_size + 10);
#endif
return (payload_size + 10);
}
GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
{
uint8_t buffer[768] = {0};
@@ -78,6 +140,7 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
while (millis() < startTimeout) {
if (_serial_gps->available()) {
b = _serial_gps->read();
#ifdef GPS_DEBUG
LOG_DEBUG("%02X", (char *)buffer);
#endif
@@ -101,6 +164,67 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
return GNSS_RESPONSE_NONE;
}
GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
{
uint32_t startTime = millis();
uint8_t buffer[CAS_ACK_NACK_MSG_SIZE] = {0};
uint8_t bufferPos = 0;
// CAS-ACK-(N)ACK structure
// | H1 | H2 | Payload Len | cls | msg | Payload | Checksum (4) |
// | | | | | | Cls | Msg | Reserved | |
// |------|------|-------------|------|------|------|------|-------------|---------------------------|
// ACK-NACK| 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x00 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
// ACK-ACK | 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x01 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
while (millis() - startTime < waitMillis) {
if (_serial_gps->available()) {
buffer[bufferPos++] = _serial_gps->read();
// keep looking at the first two bytes of buffer until
// we have found the CAS frame header (0xBA, 0xCE), if not
// keep reading bytes until we find a frame header or we run
// out of time.
if ((bufferPos == 2) && !(buffer[0] == 0xBA && buffer[1] == 0xCE)) {
buffer[0] = buffer[1];
buffer[1] = 0;
bufferPos = 1;
}
}
// we have read all the bytes required for the Ack/Nack (14-bytes)
// and we must have found a frame to get this far
if (bufferPos == sizeof(buffer) - 1) {
uint8_t msg_cls = buffer[4]; // message class should be 0x05
uint8_t msg_msg_id = buffer[5]; // message id should be 0x00 or 0x01
uint8_t payload_cls = buffer[6]; // payload class id
uint8_t payload_msg = buffer[7]; // payload message id
// 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.\n", class_id, msg_id, millis() - startTime);
#endif
return GNSS_RESPONSE_OK;
}
// 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.\n", class_id, msg_id, millis() - startTime);
#endif
return GNSS_RESPONSE_NAK;
}
// This isn't the frame we are looking for, clear the buffer
// and try again until we run out of time.
memset(buffer, 0x0, sizeof(buffer));
bufferPos = 0;
}
}
return GNSS_RESPONSE_NONE;
}
GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
{
uint8_t b;
@@ -290,6 +414,53 @@ bool GPS::setup()
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
_serial_gps->write("$PCAS11,3*1E\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_MTK_L76B) {
// Waveshare Pico-GPS hat uses the L76B with 9600 baud
// Initialize the L76B Chip, use GPS + GLONASS
// See note in L76_Series_GNSS_Protocol_Specification, chapter 3.29
_serial_gps->write("$PMTK353,1,1,0,0,0*2B\r\n");
// Above command will reset the GPS and takes longer before it will accept new commands
delay(1000);
// only ask for RMC and GGA (GNRMC and GNGGA)
// See note in L76_Series_GNSS_Protocol_Specification, chapter 2.1
_serial_gps->write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n");
delay(250);
// Enable SBAS
_serial_gps->write("$PMTK301,2*2E\r\n");
delay(250);
// Enable PPS for 2D/3D fix only
_serial_gps->write("$PMTK285,3,100*3F\r\n");
delay(250);
// Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s)
_serial_gps->write("$PMTK886,1*29\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_ATGM336H) {
// Set the intial configuration of the device - these _should_ work for most AT6558 devices
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");
}
// 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");
}
// Set the NEMA output messages
// Ask for only RMC and GGA
uint8_t fields[] = {CAS_NEMA_RMC, CAS_NEMA_GGA};
for (unsigned int i = 0; i < sizeof(fields); i++) {
// Construct a CAS-CFG-MSG packet
uint8_t cas_cfg_msg_packet[] = {0x4e, fields[i], 0x01, 0x00};
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\n", fields[i]);
}
}
} else if (gnssModel == GNSS_MODEL_UC6580) {
// The Unicore UC6580 can use a lot of sat systems, enable it to
// use GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS
@@ -301,6 +472,9 @@ bool GPS::setup()
// Turn off GSV messages, we don't really care about which and where the sats are, maybe someday.
_serial_gps->write("$CFGMSG,0,3,0\r\n");
delay(250);
// Turn off GSA messages, TinyGPS++ doesn't use this message.
_serial_gps->write("$CFGMSG,0,2,0\r\n");
delay(250);
// Turn off NOTICE __TXT messages, these may provide Unicore some info but we don't care.
_serial_gps->write("$CFGMSG,6,0,0\r\n");
delay(250);
@@ -475,7 +649,6 @@ bool GPS::setup()
}
}
}
} else {
// LOG_INFO("u-blox M10 hardware found.\n");
delay(1000);
@@ -625,17 +798,27 @@ void GPS::setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime)
return;
}
#endif
#ifdef PIN_GPS_STANDBY // Specifically the standby pin for L76K and clones
#ifdef PIN_GPS_STANDBY // Specifically the standby pin for L76B, L76K and clones
if (on) {
LOG_INFO("Waking GPS\n");
pinMode(PIN_GPS_STANDBY, OUTPUT);
// Some PCB's use an inverse logic due to a transistor driver
// Example for this is the Pico-Waveshare Lora+GPS HAT
#ifdef PIN_GPS_STANDBY_INVERTED
digitalWrite(PIN_GPS_STANDBY, 0);
#else
digitalWrite(PIN_GPS_STANDBY, 1);
#endif
return;
} else {
LOG_INFO("GPS entering sleep\n");
// notifyGPSSleep.notifyObservers(NULL);
pinMode(PIN_GPS_STANDBY, OUTPUT);
#ifdef PIN_GPS_STANDBY_INVERTED
digitalWrite(PIN_GPS_STANDBY, 1);
#else
digitalWrite(PIN_GPS_STANDBY, 0);
#endif
return;
}
#endif
@@ -729,7 +912,7 @@ uint32_t GPS::getWakeTime() const
if (t == UINT32_MAX)
return t; // already maxint
return getConfiguredOrDefaultMs(t, default_broadcast_interval_secs);
return Default::getConfiguredOrDefaultMs(t, default_broadcast_interval_secs);
}
/** Get how long we should sleep between aqusition attempts in msecs
@@ -745,7 +928,7 @@ uint32_t GPS::getSleepTime() const
if (t == UINT32_MAX)
return t; // already maxint
return t * 1000;
return Default::getConfiguredOrDefaultMs(t, default_gps_update_interval);
}
void GPS::publishUpdate()
@@ -785,7 +968,7 @@ int32_t GPS::runOnce()
LOG_WARN("GPS FactoryReset requested\n");
if (gps->factoryReset()) { // If we don't succeed try again next time
devicestate.did_gps_reset = true;
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
nodeDB->saveToDisk(SEGMENT_DEVICESTATE);
}
}
GPSInitFinished = true;
@@ -805,7 +988,7 @@ int32_t GPS::runOnce()
if (devicestate.did_gps_reset && (millis() - lastWakeStartMsec > 60000) && !hasFlow()) {
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
devicestate.did_gps_reset = false;
nodeDB.saveDeviceStateToDisk();
nodeDB->saveDeviceStateToDisk();
return disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
}
}
@@ -916,10 +1099,18 @@ GnssModel_t GPS::probe(int serialSpeed)
uint8_t buffer[768] = {0};
delay(100);
// Close all NMEA sentences , Only valid for MTK platform
// Close all NMEA sentences, valid for L76K, ATGM336H (and likely other AT6558 devices)
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
delay(20);
// Get version information
clearBuffer();
_serial_gps->write("$PCAS06,1*1A\r\n");
if (getACK("$GPTXT,01,01,02,HW=ATGM336H", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("ATGM336H GNSS init succeeded, using ATGM336H Module\n");
return GNSS_MODEL_ATGM336H;
}
// Get version information
clearBuffer();
_serial_gps->write("$PCAS06,0*1B\r\n");
@@ -928,6 +1119,18 @@ GnssModel_t GPS::probe(int serialSpeed)
return GNSS_MODEL_MTK;
}
// Close all NMEA sentences, valid for L76B MTK platform (Waveshare Pico GPS)
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
delay(20);
// Get version information
clearBuffer();
_serial_gps->write("$PMTK605*31\r\n");
if (getACK("Quectel-L76B", 500) == GNSS_RESPONSE_OK) {
LOG_INFO("L76B GNSS init succeeded, using L76B GNSS Module\n");
return GNSS_MODEL_MTK_L76B;
}
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
UBXChecksum(cfg_rate, sizeof(cfg_rate));
clearBuffer();
@@ -1109,7 +1312,6 @@ GPS *GPS::createGps()
LOG_DEBUG("Using GPIO%d for GPS RX\n", new_gps->rx_gpio);
LOG_DEBUG("Using GPIO%d for GPS TX\n", new_gps->tx_gpio);
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, new_gps->rx_gpio, new_gps->tx_gpio);
#else
_serial_gps->begin(GPS_BAUDRATE);
#endif
@@ -1168,7 +1370,21 @@ bool GPS::factoryReset()
// 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\n");
_serial_gps->write("$PCAS10,3*1F\r\n");
delay(100);
} else if (gnssModel == GNSS_MODEL_ATGM336H) {
LOG_INFO("Factory Reset via CAS-CFG-RST\n");
uint8_t msglen = makeCASPacket(0x06, 0x02, sizeof(_message_CAS_CFG_RST_FACTORY), _message_CAS_CFG_RST_FACTORY);
_serial_gps->write(UBXscratch, msglen);
delay(100);
} else {
// fire this for good measure, if we have an L76B - won't harm other devices.
_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
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
@@ -1228,7 +1444,7 @@ bool GPS::lookForLocation()
#ifndef TINYGPS_OPTION_NO_STATISTICS
if (reader.failedChecksum() > lastChecksumFailCount) {
LOG_WARN("Warning, %u new GPS checksum failures, for a total of %u.\n", reader.failedChecksum() - lastChecksumFailCount,
LOG_WARN("%u new GPS checksum failures, for a total of %u.\n", reader.failedChecksum() - lastChecksumFailCount,
reader.failedChecksum());
lastChecksumFailCount = reader.failedChecksum();
}
@@ -1254,7 +1470,7 @@ bool GPS::lookForLocation()
#endif // GPS_EXTRAVERBOSE
// Is this a new point or are we re-reading the previous one?
if (!reader.location.isUpdated())
if (!reader.location.isUpdated() && !reader.altitude.isUpdated())
return false;
// check if a complete GPS solution set is available for reading
@@ -1327,7 +1543,7 @@ bool GPS::lookForLocation()
t.tm_mon = reader.date.month() - 1;
t.tm_year = reader.date.year() - 1900;
t.tm_isdst = false;
p.timestamp = mktime(&t);
p.timestamp = gm_mktime(&t);
// Nice to have, if available
if (reader.satellites.isUpdated()) {
@@ -1371,7 +1587,7 @@ bool GPS::hasFlow()
bool GPS::whileIdle()
{
int charsInBuf = 0;
unsigned int charsInBuf = 0;
bool isValid = false;
if (!isAwake) {
clearBuffer();
@@ -1431,4 +1647,5 @@ void GPS::toggleGpsMode()
LOG_DEBUG("Flag set to true to restore power. GpsMode: ENABLED\n");
enable();
}
}
}
#endif // Exclude GPS

View File

@@ -1,4 +1,6 @@
#pragma once
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_GPS
#include "GPSStatus.h"
#include "Observer.h"
@@ -21,10 +23,12 @@ struct uBloxGnssModelInfo {
};
typedef enum {
GNSS_MODEL_ATGM336H,
GNSS_MODEL_MTK,
GNSS_MODEL_UBLOX,
GNSS_MODEL_UC6580,
GNSS_MODEL_UNKNOWN,
GNSS_MODEL_MTK_L76B
} GnssModel_t;
typedef enum {
@@ -92,8 +96,11 @@ class GPS : private concurrency::OSThread
public:
/** If !NULL we will use this serial port to construct our GPS */
#if defined(RPI_PICO_WAVESHARE)
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[];
@@ -133,6 +140,11 @@ class GPS : private concurrency::OSThread
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[];
meshtastic_Position p = meshtastic_Position_init_default;
GPS() : concurrency::OSThread("GPS") {}
@@ -174,6 +186,7 @@ class GPS : private concurrency::OSThread
// 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};
@@ -184,6 +197,8 @@ class GPS : private concurrency::OSThread
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);
/**
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
*
@@ -243,6 +258,7 @@ class GPS : private concurrency::OSThread
// Calculate checksum
void UBXChecksum(uint8_t *message, size_t length);
void CASChecksum(uint8_t *message, size_t length);
/** Get how long we should stay looking for each aquisition
*/
@@ -270,4 +286,5 @@ class GPS : private concurrency::OSThread
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
};
extern GPS *gps;
extern GPS *gps;
#endif // Exclude GPS

View File

@@ -1,3 +1,4 @@
#if !MESHTASTIC_EXCLUDE_GPS
#include "NMEAWPL.h"
#include "GeoCoord.h"
#include "RTC.h"
@@ -74,10 +75,10 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const
uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos)
{
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
tm *t = localtime((time_t *)&pos.timestamp);
tm *t = gmtime((time_t *)&pos.timestamp);
if (getRTCQuality() > 0) { // use the device clock if we got time from somewhere. If not, use the GPS timestamp.
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
t = localtime((time_t *)&rtc_sec);
t = gmtime((time_t *)&rtc_sec);
}
uint32_t len = snprintf(
@@ -93,4 +94,6 @@ uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos)
}
len += snprintf(buf + len, bufsz - len, "*%02X\r\n", chk);
return len;
}
}
#endif

View File

@@ -40,7 +40,7 @@ void readFromRTC()
t.tm_hour = rtc.getHour();
t.tm_min = rtc.getMinute();
t.tm_sec = rtc.getSecond();
tv.tv_sec = mktime(&t);
tv.tv_sec = gm_mktime(&t);
tv.tv_usec = 0;
LOG_DEBUG("Read RTC time from RV3028 as %ld\n", tv.tv_sec);
timeStartMsec = now;
@@ -68,7 +68,7 @@ void readFromRTC()
t.tm_hour = tc.hour;
t.tm_min = tc.minute;
t.tm_sec = tc.second;
tv.tv_sec = mktime(&t);
tv.tv_sec = gm_mktime(&t);
tv.tv_usec = 0;
LOG_DEBUG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec);
timeStartMsec = now;
@@ -96,21 +96,27 @@ void readFromRTC()
*
* If we haven't yet set our RTC this boot, set it from a GPS derived time
*/
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
{
static uint32_t lastSetMsec = 0;
uint32_t now = millis();
bool shouldSet;
if (q > currentQuality) {
if (forceUpdate) {
shouldSet = true;
LOG_DEBUG("Upgrading time to quality %d\n", q);
} else if (q == RTCQualityGPS && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
// Every 12 hrs we will slam in a new GPS time, to correct for local RTC clock drift
LOG_DEBUG("Overriding current RTC quality (%s) with incoming time of RTC quality of %s\n", RtcName(currentQuality),
RtcName(q));
} else if (q > currentQuality) {
shouldSet = true;
LOG_DEBUG("Upgrading time to quality %s\n", RtcName(q));
} else if (q >= RTCQualityNTP && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
// Every 12 hrs we will slam in a new GPS 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\n", tv->tv_sec);
} else
} else {
shouldSet = false;
LOG_DEBUG("Current RTC quality: %s. Ignoring time of RTC quality of %s\n", RtcName(currentQuality), RtcName(q));
}
if (shouldSet) {
currentQuality = q;
@@ -128,7 +134,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
#else
rtc.initI2C();
#endif
tm *t = localtime(&tv->tv_sec);
tm *t = gmtime(&tv->tv_sec);
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
@@ -142,7 +148,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
#else
rtc.begin();
#endif
tm *t = localtime(&tv->tv_sec);
tm *t = gmtime(&tv->tv_sec);
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
@@ -162,6 +168,24 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
}
}
const char *RtcName(RTCQuality quality)
{
switch (quality) {
case RTCQualityNone:
return "None";
case RTCQualityDevice:
return "Device";
case RTCQualityFromNet:
return "Net";
case RTCQualityNTP:
return "NTP";
case RTCQualityGPS:
return "GPS";
default:
return "Unknown";
}
}
/**
* Sets the RTC time if the provided time is of higher quality than the current RTC time.
*
@@ -175,7 +199,9 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
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).
*/
time_t res = mktime(&t);
// horrible hack to make mktime TZ agnostic - best practise according to
// https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html
time_t res = gm_mktime(&t);
struct timeval tv;
tv.tv_sec = res;
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
@@ -189,14 +215,32 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
}
}
/**
* Returns the timezone offset in seconds.
*
* @return The timezone offset in seconds.
*/
int32_t getTZOffset()
{
time_t now = getTime(false);
struct tm *gmt;
gmt = gmtime(&now);
gmt->tm_isdst = -1;
return (int32_t)difftime(now, mktime(gmt));
}
/**
* Returns the current time in seconds since the Unix epoch (January 1, 1970).
*
* @return The current time in seconds since the Unix epoch.
*/
uint32_t getTime()
uint32_t getTime(bool local)
{
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
if (local) {
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs + getTZOffset();
} else {
return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
}
}
/**
@@ -205,7 +249,19 @@ uint32_t getTime()
* @param minQuality The minimum quality of the RTC time required for it to be considered valid.
* @return The current time from the RTC if it meets the minimum quality requirement, or 0 if the time is not valid.
*/
uint32_t getValidTime(RTCQuality minQuality)
uint32_t getValidTime(RTCQuality minQuality, bool local)
{
return (currentQuality >= minQuality) ? getTime() : 0;
return (currentQuality >= minQuality) ? getTime(local) : 0;
}
time_t gm_mktime(struct tm *tm)
{
setenv("TZ", "GMT0", 1);
time_t res = mktime(tm);
if (*config.device.tzdef) {
setenv("TZ", config.device.tzdef, 1);
} else {
setenv("TZ", "UTC0", 1);
}
return res;
}

View File

@@ -25,17 +25,22 @@ enum RTCQuality {
RTCQuality getRTCQuality();
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv);
bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate = false);
bool perhapsSetRTC(RTCQuality q, struct tm &t);
/// Return a string name for the quality
const char *RtcName(RTCQuality quality);
/// Return time since 1970 in secs. While quality is RTCQualityNone we will be returning time based at zero
uint32_t getTime();
uint32_t getTime(bool local = false);
/// Return time since 1970 in secs. If quality is RTCQualityNone return zero
uint32_t getValidTime(RTCQuality minQuality);
uint32_t getValidTime(RTCQuality minQuality, bool local = false);
void readFromRTC();
time_t gm_mktime(struct tm *tm);
#define SEC_PER_DAY 86400
#define SEC_PER_HOUR 3600
#define SEC_PER_MIN 60

63
src/gps/cas.h Normal file
View File

@@ -0,0 +1,63 @@
#pragma once
// CASIC binary message definitions
// Reference: https://www.icofchina.com/d/file/xiazai/2020-09-22/20f1b42b3a11ac52089caf3603b43fb5.pdf
// ATGM33H-5N: https://www.icofchina.com/pro/mokuai/2016-08-01/4.html
// (https://www.icofchina.com/d/file/xiazai/2016-12-05/b5c57074f4b1fcc62ba8c7868548d18a.pdf)
// NEMA (Class ID - 0x4e) message IDs
#define CAS_NEMA_GGA 0x00
#define CAS_NEMA_GLL 0x01
#define CAS_NEMA_GSA 0x02
#define CAS_NEMA_GSV 0x03
#define CAS_NEMA_RMC 0x04
#define CAS_NEMA_VTG 0x05
#define CAS_NEMA_GST 0x07
#define CAS_NEMA_ZDA 0x08
#define CAS_NEMA_DHV 0x0D
// Size of a CAS-ACK-(N)ACK message (14 bytes)
#define CAS_ACK_NACK_MSG_SIZE 0x0E
// CFG-RST (0x06, 0x02)
// Factory reset
const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = {
0xFF, 0x03, // Fields to clear
0x01, // Reset Mode: Controlled Software reset
0x03 // Startup Mode: 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[] = {
0xE8, 0x03, // Update Rate: 0x03E8 = 1000ms
0x00, 0x00 // Reserved
};
// CFG-NAVX (0x06, 0x07)
// 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[] = {
0x03, 0x01, 0x00, 0x00, // Update Mask: Dynamic Mode, Fix Mode, Nav Settings
0x03, // Dynamic Mode: Automotive
0x03, // Fix Mode: Auto 2D/3D
0x00, // Min SV
0x00, // Max SVs
0x00, // Min CNO
0x00, // Reserved1
0x00, // Init 3D fix
0x00, // Min Elevation
0x00, // Dr Limit
0x07, // Nav System: 2^0 = GPS, 2^1 = BDS 2^2 = GLONASS: 2^3
// 3=GPS+BDS, 7=GPS+BDS+GLONASS
0x00, 0x00, // Rollover Week
0x00, 0x00, 0x00, 0x00, // Fix Altitude
0x00, 0x00, 0x00, 0x00, // Fix Height Error
0x00, 0x00, 0x00, 0x00, // PDOP Maximum
0x00, 0x00, 0x00, 0x00, // TDOP Maximum
0x00, 0x00, 0x00, 0x00, // Position Accuracy Max
0x00, 0x00, 0x00, 0x00, // Time Accuracy Max
0x00, 0x00, 0x00, 0x00 // Static Hold Threshold
};

View File

@@ -206,14 +206,14 @@ const uint8_t GPS::_message_GLL[] = {
0x00 // Reserved
};
// Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
// 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[] = {
0xF0, 0x02, // NMEA ID for GSA
0x00, // Rate for DDC
0x01, // Rate for UART1
0x00, // Rate for UART1
0x00, // Rate for UART2
0x01, // Rate for USB usefull for native linux
0x00, // Rate for USB usefull for native linux
0x00, // Rate for SPI
0x00 // Reserved
};
@@ -402,23 +402,28 @@ const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00,
// BBR layer config message:
// b5 62 06 8a 09 00 00 02 00 00 07 00 92 20 06 5a 58
// Turn NMEA GSA, GGA, RMC messages on:
// Ram layer config message:
// b5 62 06 8a 13 00 00 01 00 00 c0 00 91 20 01 bb 00 91 20 01 ac 00 91 20 01 e1 3b
// BBR layer config message:
// b5 62 06 8a 13 00 00 02 00 00 c0 00 91 20 01 bb 00 91 20 01 ac 00 91 20 01 e2 4d
// Turn NMEA GGA, RMC messages on:
// Layer config messages:
// RAM:
// b5 62 06 8a 0e 00 00 01 00 00 bb 00 91 20 01 ac 00 91 20 01 6a 8f
// BBR:
// b5 62 06 8a 0e 00 00 02 00 00 bb 00 91 20 01 ac 00 91 20 01 6b 9c
// FLASH:
// 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};
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x01, 0xbb,
0x00, 0x91, 0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x01, 0xbb,
0x00, 0x91, 0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
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};
/*
Operational issues with the M10:

View File

@@ -62,12 +62,19 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
return false;
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
const bool flipped = config.display.flip_screen;
for (uint32_t y = 0; y < displayHeight; y++) {
for (uint32_t x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient
auto b = buffer[x + (y / 8) * displayWidth];
auto isset = b & (1 << (y & 7));
adafruitDisplay->drawPixel(x, y, isset ? GxEPD_BLACK : GxEPD_WHITE);
// Handle flip here, rather than with setRotation(),
// Avoids issues when display width is not a multiple of 8
if (flipped)
adafruitDisplay->drawPixel((displayWidth - 1) - x, (displayHeight - 1) - y, isset ? GxEPD_BLACK : GxEPD_WHITE);
else
adafruitDisplay->drawPixel(x, y, isset ? GxEPD_BLACK : GxEPD_WHITE);
}
}
@@ -151,31 +158,12 @@ bool EInkDisplay::connect()
#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_WIRELESS_PAPER)
{
// Is this a normal boot, or a wake from deep sleep?
esp_sleep_wakeup_cause_t wakeReason = esp_sleep_get_wakeup_cause();
// If waking from sleep, need to reverse rtc_gpio_isolate(), called in cpuDeepSleep()
// Otherwise, SPI won't work
if (wakeReason != ESP_SLEEP_WAKEUP_UNDEFINED) {
// HSPI + other display pins
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_SCLK);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_DC);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_RES);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_BUSY);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_CS);
rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_MOSI);
}
// Start HSPI
hspi = new SPIClass(HSPI);
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
// Enable VExt (ACTIVE LOW)
// Unsure if called elsewhere first?
delay(100);
pinMode(Vext, OUTPUT);
digitalWrite(Vext, LOW);
delay(100);
// VExt already enabled in setup()
// RTC GPIO hold disabled in setup()
// Create GxEPD2 objects
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi);
@@ -184,7 +172,6 @@ bool EInkDisplay::connect()
// Init GxEPD2
adafruitDisplay->init();
adafruitDisplay->setRotation(3);
adafruitDisplay->clearScreen(); // Clearing now, so the boot logo will draw nice and smoothe (fast refresh)
}
#elif defined(PCA10059)
{

View File

@@ -5,7 +5,7 @@
// Constructor
EInkDynamicDisplay::EInkDynamicDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
: EInkDisplay(address, sda, scl, geometry, i2cBus)
: EInkDisplay(address, sda, scl, geometry, i2cBus), NotifiedWorkerThread("EInkDynamicDisplay")
{
// If tracking ghost pixels, grab memory
#ifdef EINK_LIMIT_GHOSTING_PX
@@ -112,12 +112,15 @@ void EInkDynamicDisplay::endOrDetach()
// If the GxEPD2 version reports that it has the async modifications
#ifdef HAS_EINK_ASYNCFULL
if (previousRefresh == FULL) {
asyncRefreshRunning = true; // Set the flag - picked up at start of determineMode(), next loop.
asyncRefreshRunning = true; // Set the flag - checked in determineMode(); cleared by onNotify()
if (previousFrameFlags & BLOCKING)
awaitRefresh();
else
LOG_DEBUG("Async full-refresh begins\n");
else {
// Async begins
LOG_DEBUG("Async full-refresh begins (dropping frames)\n");
notifyLater(intervalPollAsyncRefresh, DUE_POLL_ASYNCREFRESH, true); // Hand-off to NotifiedWorkerThread
}
}
// Fast Refresh
@@ -141,7 +144,7 @@ bool EInkDynamicDisplay::determineMode()
checkInitialized();
checkForPromotion();
#if defined(HAS_EINK_ASYNCFULL)
checkAsyncFullRefresh();
checkBusyAsyncRefresh();
#endif
checkRateLimiting();
@@ -252,6 +255,7 @@ void EInkDynamicDisplay::checkRateLimiting()
if (now - previousRunMs < EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000) {
refresh = SKIPPED;
reason = EXCEEDED_RATELIMIT_FAST;
LOG_DEBUG("refresh=SKIPPED, reason=EXCEEDED_RATELIMIT_FAST, frameFlags=0x%x\n", frameFlags);
return;
}
}
@@ -447,9 +451,67 @@ void EInkDynamicDisplay::resetGhostPixelTracking()
}
#endif // EINK_LIMIT_GHOSTING_PX
// Handle any asyc tasks
void EInkDynamicDisplay::onNotify(uint32_t notification)
{
// Which task
switch (notification) {
case DUE_POLL_ASYNCREFRESH:
pollAsyncRefresh();
break;
}
}
#ifdef HAS_EINK_ASYNCFULL
// Check the status of an "async full-refresh", and run the finish-up code if the hardware is ready
void EInkDynamicDisplay::checkAsyncFullRefresh()
// Public: wait for an refresh already in progress, then run the post-update code. See Screen::setScreensaverFrames()
void EInkDynamicDisplay::joinAsyncRefresh()
{
// If no async refresh running, nothing to do
if (!asyncRefreshRunning)
return;
LOG_DEBUG("Joining an async refresh in progress\n");
// Continually poll the BUSY pin
while (adafruitDisplay->epd2.isBusy())
yield();
// If asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done
adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code
EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override)
asyncRefreshRunning = false; // Unset the flag
LOG_DEBUG("Refresh complete\n");
// Note: this code only works because of a modification to meshtastic/GxEPD2.
// It is only equipped to intercept calls to nextPage()
}
// Called from NotifiedWorkerThread. Run the post-update code if the hardware is ready
void EInkDynamicDisplay::pollAsyncRefresh()
{
// In theory, this condition should never be met
if (!asyncRefreshRunning)
return;
// Still running, check back later
if (adafruitDisplay->epd2.isBusy()) {
// Schedule next call of pollAsyncRefresh()
NotifiedWorkerThread::notifyLater(intervalPollAsyncRefresh, DUE_POLL_ASYNCREFRESH, true);
return;
}
// If asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done
adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code
EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override)
asyncRefreshRunning = false; // Unset the flag
LOG_DEBUG("Async full-refresh complete\n");
// Note: this code only works because of a modification to meshtastic/GxEPD2.
// It is only equipped to intercept calls to nextPage()
}
// Check the status of "async full-refresh"; skip if running
void EInkDynamicDisplay::checkBusyAsyncRefresh()
{
// No refresh taking place, continue with determineMode()
if (!asyncRefreshRunning)
@@ -473,14 +535,9 @@ void EInkDynamicDisplay::checkAsyncFullRefresh()
return;
}
// If we asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done
adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code
EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override)
asyncRefreshRunning = false; // Unset the flag
LOG_DEBUG("Async full-refresh complete\n");
// Note: this code only works because of a modification to meshtastic/GxEPD2.
// It is only equipped to intercept calls to nextPage()
// Async refresh appears to have stopped, but wasn't caught by onNotify()
else
pollAsyncRefresh(); // Check (and terminate) the async refresh manually
}
// Hold control while an async refresh runs

View File

@@ -6,6 +6,7 @@
#include "EInkDisplay2.h"
#include "GxEPD2_BW.h"
#include "concurrency/NotifiedWorkerThread.h"
/*
Derives from the EInkDisplay adapter class.
@@ -14,7 +15,7 @@
(Full, Fast, Skip)
*/
class EInkDynamicDisplay : public EInkDisplay
class EInkDynamicDisplay : public EInkDisplay, protected concurrency::NotifiedWorkerThread
{
public:
// Constructor
@@ -61,13 +62,20 @@ class EInkDynamicDisplay : public EInkDisplay
REDRAW_WITH_FULL,
};
void configForFastRefresh(); // GxEPD2 code to set fast-refresh
void configForFullRefresh(); // GxEPD2 code to set full-refresh
bool determineMode(); // Assess situation, pick a refresh type
void applyRefreshMode(); // Run any relevant GxEPD2 code, so next update will use correct refresh type
void adjustRefreshCounters(); // Update fastRefreshCount
bool update(); // Trigger the display update - determine mode, then call base class
void endOrDetach(); // Run the post-update code, or delegate it off to checkAsyncFullRefresh()
enum notificationTypes : uint8_t { // What was onNotify() called for
NONE = 0, // This behavior (NONE=0) is fixed by NotifiedWorkerThread class
DUE_POLL_ASYNCREFRESH = 1,
};
const uint32_t intervalPollAsyncRefresh = 100;
void onNotify(uint32_t notification) override; // Handle any async tasks - overrides NotifiedWorkerThread
void configForFastRefresh(); // GxEPD2 code to set fast-refresh
void configForFullRefresh(); // GxEPD2 code to set full-refresh
bool determineMode(); // Assess situation, pick a refresh type
void applyRefreshMode(); // Run any relevant GxEPD2 code, so next update will use correct refresh type
void adjustRefreshCounters(); // Update fastRefreshCount
bool update(); // Trigger the display update - determine mode, then call base class
void endOrDetach(); // Run the post-update code, or delegate it off to checkBusyAsyncRefresh()
// Checks as part of determineMode()
void checkInitialized(); // Is this the very first frame?
@@ -101,6 +109,7 @@ class EInkDynamicDisplay : public EInkDisplay
refreshTypes currentConfig = FULL; // Which refresh type is GxEPD2 currently configured for
// Optional - track ghosting, pixel by pixel
// May 2024: no longer used by any display. Kept for possible future use.
#ifdef EINK_LIMIT_GHOSTING_PX
void countGhostPixels(); // Count any pixels which have moved from black to white since last full-refresh
void checkExcessiveGhosting(); // Check if ghosting exceeds defined limit
@@ -111,17 +120,30 @@ class EInkDynamicDisplay : public EInkDisplay
// Conditional - async full refresh - only with modified meshtastic/GxEPD2
#if defined(HAS_EINK_ASYNCFULL)
void checkAsyncFullRefresh(); // Check the status of "async full-refresh"; run the post-update code if the hardware is ready
void awaitRefresh(); // Hold control while an async refresh runs
void endUpdate() override {} // Disable base-class behavior of running post-update immediately after forceDisplay()
bool asyncRefreshRunning = false; // Flag, checked by checkAsyncFullRefresh()
public:
void joinAsyncRefresh(); // Main thread joins an async refresh already in progress. Blocks, then runs post-update code
protected:
void pollAsyncRefresh(); // Run the post-update code if the hardware is ready
void checkBusyAsyncRefresh(); // Check if display is busy running an async full-refresh (rejecting new frames)
void awaitRefresh(); // Hold control while an async refresh runs
void endUpdate() override {} // Disable base-class behavior of running post-update immediately after forceDisplay()
bool asyncRefreshRunning = false; // Flag, checked by checkBusyAsyncRefresh()
#else
public:
void joinAsyncRefresh() {} // Dummy method
protected:
void pollAsyncRefresh() {} // Dummy method. In theory, not reachable
#endif
};
// Tidier calls to addFrameFlag() from outside class
// Hide the ugly casts used in Screen.cpp
#define EINK_ADD_FRAMEFLAG(display, flag) static_cast<EInkDynamicDisplay *>(display)->addFrameFlag(EInkDynamicDisplay::flag)
#define EINK_JOIN_ASYNCREFRESH(display) static_cast<EInkDynamicDisplay *>(display)->joinAsyncRefresh()
#else // !USE_EINK_DYNAMICDISPLAY
// Dummy-macro, removes the need for include guards
#define EINK_ADD_FRAMEFLAG(display, flag)
#define EINK_JOIN_ASYNCREFRESH(display)
#endif

4
src/graphics/NeoPixel.h Normal file
View File

@@ -0,0 +1,4 @@
#ifdef HAS_NEOPIXEL
#include <Adafruit_NeoPixel.h>
extern Adafruit_NeoPixel pixels;
#endif

View File

@@ -0,0 +1,4 @@
struct PointStruct {
int x;
int y;
};

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@ class Screen
void setOn(bool) {}
void print(const char *) {}
void doDeepSleep() {}
void forceDisplay() {}
void forceDisplay(bool forceUiUpdate = false) {}
void startBluetoothPinScreen(uint32_t pin) {}
void stopBluetoothPinScreen() {}
void startRebootScreen() {}
@@ -48,6 +48,7 @@ class Screen
#include "EInkDisplay2.h"
#include "EInkDynamicDisplay.h"
#include "PointStruct.h"
#include "TFTDisplay.h"
#include "TypedQueue.h"
#include "commands.h"
@@ -73,6 +74,14 @@ class Screen
#define MILES_TO_FEET 5280
#endif
// Intuitive colors. E-Ink display is inverted from OLED(?)
#define EINK_BLACK OLEDDISPLAY_COLOR::WHITE
#define EINK_WHITE OLEDDISPLAY_COLOR::BLACK
// Base segment dimensions for T-Watch segmented display
#define SEGMENT_WIDTH 16
#define SEGMENT_HEIGHT 4
namespace graphics
{
@@ -125,6 +134,8 @@ class Screen : public concurrency::OSThread
public:
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
~Screen();
Screen(const Screen &) = delete;
Screen &operator=(const Screen &) = delete;
@@ -137,14 +148,14 @@ class Screen : public concurrency::OSThread
// Not thread safe - must be called before any other methods are called.
void setup();
/// Turns the screen on/off.
void setOn(bool on)
/// Turns the screen on/off. Optionally, pass a custom screensaver frame for E-Ink
void setOn(bool on, FrameCallback einkScreensaver = NULL)
{
if (!on)
handleSetOn(
false); // We handle off commands immediately, because they might be called because the CPU is shutting down
// We handle off commands immediately, because they might be called because the CPU is shutting down
handleSetOn(false, einkScreensaver);
else
enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF});
enqueueCmd(ScreenCmd{.cmd = Cmd::SET_ON});
}
/**
@@ -160,9 +171,6 @@ class Screen : public concurrency::OSThread
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
void showNextFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_NEXT_FRAME}); }
// Implementation to Adjust Brightness
uint8_t brightness = BRIGHTNESS_DEFAULT;
/// Starts showing the Bluetooth PIN screen.
//
// Switches over to a static frame showing the Bluetooth pairing screen
@@ -196,6 +204,13 @@ class Screen : public concurrency::OSThread
enqueueCmd(cmd);
}
// functions for display brightness
void increaseBrightness();
void decreaseBrightness();
void setFunctionSymbal(std::string sym);
void removeFunctionSymbal(std::string sym);
/// Stops showing the bluetooth PIN screen.
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
@@ -312,13 +327,18 @@ class Screen : public concurrency::OSThread
int handleInputEvent(const InputEvent *arg);
/// Used to force (super slow) eink displays to draw critical frames
void forceDisplay();
void forceDisplay(bool forceUiUpdate = false);
/// Draws our SSL cert screen during boot (called from WebServer)
void setSSLFrames();
void setWelcomeFrames();
#ifdef USE_EINK
/// Draw an image to remain on E-Ink display after screen off
void setScreensaverFrames(FrameCallback einkScreensaver = NULL);
#endif
protected:
/// Updates the UI.
//
@@ -340,7 +360,7 @@ class Screen : public concurrency::OSThread
bool enqueueCmd(const ScreenCmd &cmd)
{
if (!useDisplay)
return true; // claim success if our display is not in use
return false; // not enqueued if our display is not in use
else {
bool success = cmdQueue.enqueue(cmd, 0);
enabled = true; // handle ASAP (we are the registered reader for cmdQueue, but might have been disabled)
@@ -349,7 +369,7 @@ class Screen : public concurrency::OSThread
}
// Implementations of various commands, called from doTask().
void handleSetOn(bool on);
void handleSetOn(bool on, FrameCallback einkScreensaver = NULL);
void handleOnPress();
void handleShowNextFrame();
void handleShowPrevFrame();
@@ -374,6 +394,27 @@ class Screen : public concurrency::OSThread
static void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
#ifdef T_WATCH_S3
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);
static void drawSegmentedDisplayCharacter(OLEDDisplay *display, int x, int y, uint8_t number, float scale = 1);
static void drawHorizontalSegment(OLEDDisplay *display, int x, int y, int width, int height);
static void drawVerticalSegment(OLEDDisplay *display, int x, int y, int width, int height);
static void drawSegmentedDisplayColon(OLEDDisplay *display, int x, int y, float scale = 1);
static void drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode = true, float scale = 1);
static void drawBluetoothConnectedIcon(OLEDDisplay *display, int16_t x, int16_t y);
// Whether we are showing the digital watch face or the analog one
bool digitalWatchFace = true;
#endif
/// Queue of commands to execute in doTask.
TypedQueue<ScreenCmd> cmdQueue;
/// Whether we are using a display
@@ -384,6 +425,9 @@ class Screen : public concurrency::OSThread
// Bluetooth PIN screen)
bool showingNormalScreen = false;
// Implementation to Adjust Brightness
uint8_t brightness = BRIGHTNESS_DEFAULT; // H = 254, MH = 192, ML = 130 L = 103
/// Holds state for debug information
DebugInfo debugInfo;

View File

@@ -8,7 +8,7 @@
#include "graphics/fonts/OLEDDisplayFontsUA.h"
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 // Height: 19

View File

@@ -8,6 +8,12 @@
#define TFT_BACKLIGHT_ON HIGH
#endif
#ifdef GPIO_EXTENDER
#include <SparkFunSX1509.h>
#include <Wire.h>
extern SX1509 gpioExtender;
#endif
#ifndef TFT_MESH
#define TFT_MESH COLOR565(0x67, 0xEA, 0x94)
#endif
@@ -333,7 +339,7 @@ static LGFX *tft = nullptr;
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
#elif ARCH_PORTDUINO
#elif ARCH_PORTDUINO && HAS_SCREEN != 0
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
class LGFX : public lgfx::LGFX_Device
@@ -356,6 +362,7 @@ class LGFX : public lgfx::LGFX_Device
_panel_instance = new lgfx::Panel_ILI9341;
auto buscfg = _bus_instance.config();
buscfg.spi_mode = 0;
buscfg.spi_host = settingsMap[displayspidev];
buscfg.pin_dc = settingsMap[displayDC]; // Set SPI DC pin number (-1 = disable)
@@ -381,6 +388,8 @@ class LGFX : public lgfx::LGFX_Device
_touch_instance = new lgfx::Touch_XPT2046;
} else if (settingsMap[touchscreenModule] == stmpe610) {
_touch_instance = new lgfx::Touch_STMPE610;
} else if (settingsMap[touchscreenModule] == ft5x06) {
_touch_instance = new lgfx::Touch_FT5x06;
}
auto touch_cfg = _touch_instance->config();
@@ -392,6 +401,11 @@ class LGFX : public lgfx::LGFX_Device
touch_cfg.pin_int = settingsMap[touchscreenIRQ];
touch_cfg.bus_shared = true;
touch_cfg.offset_rotation = 1;
if (settingsMap[touchscreenI2CAddr] != -1) {
touch_cfg.i2c_addr = settingsMap[touchscreenI2CAddr];
} else {
touch_cfg.spi_host = settingsMap[touchscreenspidev];
}
_touch_instance->config(touch_cfg);
_panel_instance->setTouch(_touch_instance);
@@ -402,13 +416,103 @@ class LGFX : public lgfx::LGFX_Device
};
static LGFX *tft = nullptr;
#elif defined(HX8357_CS)
#include <LovyanGFX.hpp> // Graphics and font library for HX8357 driver chip
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_HX8357D _panel_instance;
lgfx::Bus_SPI _bus_instance;
#if defined(USE_XPT2046)
lgfx::Touch_XPT2046 _touch_instance;
#endif
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || ARCH_PORTDUINO
public:
LGFX(void)
{
// Panel_HX8357D
{
// configure SPI
auto cfg = _bus_instance.config();
cfg.spi_host = HX8357_SPI_HOST;
cfg.spi_mode = 0;
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
// 80MHz by an integer)
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
// SPI_DMA_CH_AUTO=auto setting)
cfg.pin_sclk = HX8357_SCK; // Set SPI SCLK pin number
cfg.pin_mosi = HX8357_MOSI; // Set SPI MOSI pin number
cfg.pin_miso = HX8357_MISO; // Set SPI MISO pin number (-1 = disable)
cfg.pin_dc = HX8357_RS; // Set SPI DC pin number (-1 = disable)
_bus_instance.config(cfg); // applies the set value to the bus.
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
}
{
// Set the display panel control.
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.
cfg.pin_cs = HX8357_CS; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = HX8357_RESET; // Pin number where RST is connected (-1 = disable)
cfg.pin_busy = HX8357_BUSY; // Pin number where BUSY is connected (-1 = disable)
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is upside down)
cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = TFT_INVERT; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit = false;
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
_panel_instance.config(cfg);
}
#if defined(USE_XPT2046)
{
// Configure settings for touch control.
auto touch_cfg = _touch_instance.config();
touch_cfg.pin_cs = TOUCH_CS;
touch_cfg.x_min = 0;
touch_cfg.x_max = TFT_HEIGHT - 1;
touch_cfg.y_min = 0;
touch_cfg.y_max = TFT_WIDTH - 1;
touch_cfg.pin_int = -1;
touch_cfg.bus_shared = true;
touch_cfg.offset_rotation = 1;
_touch_instance.config(touch_cfg);
_panel_instance.setTouch(&_touch_instance);
}
#endif
setPanel(&_panel_instance);
}
};
static LGFX *tft = nullptr;
#endif
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || defined(HX8357_CS) || \
(ARCH_PORTDUINO && HAS_SCREEN != 0)
#include "SPILock.h"
#include "TFTDisplay.h"
#include <SPI.h>
#ifdef UNPHONE
#include "unPhone.h"
extern unPhone unphone;
#endif
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
{
LOG_DEBUG("TFTDisplay!\n");
@@ -474,8 +578,10 @@ void TFTDisplay::sendCommand(uint8_t com)
#elif defined(ST7735_BL_V05)
pinMode(ST7735_BL_V05, OUTPUT);
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
#endif
#if defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
tft->wakeup();
tft->powerSaveOff();
#elif defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
#endif
@@ -486,9 +592,11 @@ void TFTDisplay::sendCommand(uint8_t com)
#ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, LOW);
#endif
#ifdef UNPHONE
unphone.backlight(true); // using unPhone library
#endif
#ifdef RAK14014
#elif !defined(M5STACK)
#elif !defined(M5STACK) && !defined(ST7789_CS) // T-Deck gets brightness set in Screen.cpp in the handleSetOn function
tft->setBrightness(172);
#endif
break;
@@ -503,16 +611,22 @@ void TFTDisplay::sendCommand(uint8_t com)
#elif defined(ST7735_BL_V05)
pinMode(ST7735_BL_V05, OUTPUT);
digitalWrite(ST7735_BL_V05, !TFT_BACKLIGHT_ON);
#endif
#if defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
tft->sleep();
tft->powerSaveOn();
#elif defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON);
#endif
#ifdef VTFT_CTRL_V03
digitalWrite(VTFT_CTRL_V03, HIGH);
#endif
#ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, HIGH);
#endif
#ifdef UNPHONE
unphone.backlight(false); // using unPhone library
#endif
#ifdef RAK14014
#elif !defined(M5STACK)
tft->setBrightness(0);
@@ -526,6 +640,12 @@ void TFTDisplay::sendCommand(uint8_t com)
// Drop all other commands to device (we just update the buffer)
}
void TFTDisplay::setDisplayBrightness(uint8_t _brightness)
{
tft->setBrightness(_brightness);
LOG_DEBUG("Brightness is set to value: %i \n", _brightness);
}
void TFTDisplay::flipScreenVertically()
{
#if defined(T_WATCH_S3)
@@ -584,6 +704,10 @@ bool TFTDisplay::connect()
pinMode(ST7735_BL_V05, OUTPUT);
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
#endif
#ifdef UNPHONE
unphone.backlight(true); // using unPhone library
LOG_INFO("Power to TFT Backlight\n");
#endif
tft->init();

View File

@@ -30,6 +30,9 @@ class TFTDisplay : public OLEDDisplay
static bool hasTouch(void);
static bool getTouch(int16_t *x, int16_t *y);
// Functions for changing display brightness
void setDisplayBrightness(uint8_t);
/**
* shim to make the abstraction happy
*

View File

@@ -14,7 +14,14 @@ 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};
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
#ifdef T_WATCH_S3
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};
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \
ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
@@ -30,4 +37,171 @@ const uint8_t imgQuestion[] PROGMEM = {0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1,
const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
#endif
#include "img/icon.xbm"
#ifndef EXCLUDE_EMOJI
#define thumbs_height 25
#define thumbs_width 25
static unsigned char thumbup[] PROGMEM = {
0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00,
0xC0, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00,
0x0C, 0xCE, 0x7F, 0x00, 0x04, 0x20, 0x80, 0x00, 0x02, 0x20, 0x80, 0x00, 0x02, 0x60, 0xC0, 0x00, 0x01, 0xF8, 0xFF, 0x01,
0x01, 0x08, 0x00, 0x01, 0x01, 0x08, 0x00, 0x01, 0x01, 0xF8, 0xFF, 0x00, 0x01, 0x10, 0x80, 0x00, 0x01, 0x18, 0x80, 0x00,
0x02, 0x30, 0xC0, 0x00, 0x06, 0xE0, 0x3F, 0x00, 0x0C, 0x20, 0x30, 0x00, 0x38, 0x20, 0x10, 0x00, 0xE0, 0xCF, 0x1F, 0x00,
};
static unsigned char thumbdown[] PROGMEM = {
0xE0, 0xCF, 0x1F, 0x00, 0x38, 0x20, 0x10, 0x00, 0x0C, 0x20, 0x30, 0x00, 0x06, 0xE0, 0x3F, 0x00, 0x02, 0x30, 0xC0, 0x00,
0x01, 0x18, 0x80, 0x00, 0x01, 0x10, 0x80, 0x00, 0x01, 0xF8, 0xFF, 0x00, 0x01, 0x08, 0x00, 0x01, 0x01, 0x08, 0x00, 0x01,
0x01, 0xF8, 0xFF, 0x01, 0x02, 0x60, 0xC0, 0x00, 0x02, 0x20, 0x80, 0x00, 0x04, 0x20, 0x80, 0x00, 0x0C, 0xCE, 0x7F, 0x00,
0x18, 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00,
0x80, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
};
#define question_height 25
#define question_width 25
static unsigned char question[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0xE0, 0xFF, 0x07, 0x00,
0xE0, 0xC3, 0x0F, 0x00, 0xF0, 0x81, 0x0F, 0x00, 0xF0, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x80, 0x0F, 0x00,
0x00, 0xC0, 0x0F, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x00,
0x00, 0x3C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define bang_height 30
#define bang_width 30
static unsigned char bang[] PROGMEM = {
0xFF, 0x0F, 0xFC, 0x3F, 0xFF, 0x0F, 0xFC, 0x3F, 0xFF, 0x0F, 0xFC, 0x3F, 0xFF, 0x07, 0xF8, 0x3F, 0xFF, 0x07, 0xF8, 0x3F,
0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F,
0xFE, 0x03, 0xF0, 0x1F, 0xFE, 0x03, 0xF0, 0x1F, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x03, 0xF0, 0x0F,
0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x01, 0xE0, 0x0F, 0xFC, 0x01, 0xE0, 0x0F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xC0, 0x03, 0xFC, 0x03, 0xF0, 0x0F, 0xFE, 0x03, 0xF0, 0x1F,
0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFC, 0x03, 0xF0, 0x0F, 0xF8, 0x01, 0xE0, 0x07,
};
#define haha_height 30
#define haha_width 30
static unsigned char haha[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x00,
0x00, 0xFC, 0x0F, 0x00, 0x00, 0x1F, 0x3E, 0x00, 0x80, 0x03, 0x70, 0x00, 0xC0, 0x01, 0xE0, 0x00, 0xC0, 0x00, 0xC2, 0x00,
0x60, 0x00, 0x03, 0x00, 0x60, 0x00, 0xC1, 0x1F, 0x60, 0x80, 0x8F, 0x31, 0x30, 0x0E, 0x80, 0x31, 0x30, 0x10, 0x30, 0x1F,
0x30, 0x08, 0x58, 0x00, 0x30, 0x04, 0x6C, 0x03, 0x60, 0x00, 0xF3, 0x01, 0x60, 0xC0, 0xFC, 0x01, 0x80, 0x38, 0xBF, 0x01,
0xE0, 0xC5, 0xDF, 0x00, 0xB0, 0xF9, 0xEF, 0x00, 0x30, 0xF1, 0x73, 0x00, 0xB0, 0x1D, 0x3E, 0x00, 0xF0, 0xFD, 0x0F, 0x00,
0xE0, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define wave_icon_height 30
#define wave_icon_width 30
static unsigned char wave_icon[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xC0, 0x00,
0x00, 0x0C, 0x9C, 0x01, 0x80, 0x17, 0x20, 0x01, 0x80, 0x26, 0x46, 0x02, 0x80, 0x44, 0x88, 0x02, 0xC0, 0x89, 0x8A, 0x02,
0x40, 0x93, 0x8B, 0x02, 0x40, 0x26, 0x13, 0x00, 0x80, 0x44, 0x16, 0x00, 0xC0, 0x89, 0x24, 0x00, 0x40, 0x93, 0x60, 0x00,
0x40, 0x26, 0x40, 0x00, 0x80, 0x0C, 0x80, 0x00, 0x00, 0x09, 0x80, 0x00, 0x00, 0x02, 0x80, 0x00, 0x40, 0x06, 0x80, 0x00,
0x50, 0x0C, 0x80, 0x00, 0x50, 0x08, 0x40, 0x00, 0x90, 0x10, 0x20, 0x00, 0xB0, 0x21, 0x10, 0x00, 0x20, 0x47, 0x18, 0x00,
0x40, 0x80, 0x0F, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define cowboy_height 30
#define cowboy_width 30
static unsigned char cowboy[] PROGMEM = {
0x00, 0xF0, 0x03, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0xFE, 0x1F, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x3C, 0xFE, 0x1F, 0x0F,
0xFE, 0xFE, 0xDF, 0x1F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F,
0x3E, 0xC0, 0x00, 0x1F, 0x1E, 0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x0E, 0x1C, 0x04, 0x00, 0x0E, 0x1C, 0x00,
0x04, 0x0E, 0x1C, 0x08, 0x04, 0x0E, 0x1C, 0x08, 0x04, 0x04, 0x08, 0x08, 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x08,
0x8C, 0x07, 0x70, 0x0C, 0x88, 0xFC, 0x4F, 0x04, 0x88, 0x01, 0x40, 0x04, 0x90, 0xFF, 0x7F, 0x02, 0x30, 0x03, 0x30, 0x03,
0x60, 0x0E, 0x9C, 0x01, 0xC0, 0xF8, 0xC7, 0x00, 0x80, 0x01, 0x60, 0x00, 0x00, 0x0E, 0x1C, 0x00, 0x00, 0xF8, 0x07, 0x00,
};
#define deadmau5_height 30
#define deadmau5_width 60
static unsigned char deadmau5[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00,
0x00, 0xFC, 0x03, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0x3F, 0x00,
0xE0, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0x7F, 0x00, 0xF0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x07,
0xFC, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x00,
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0x3F, 0xFC,
0x0F, 0xFF, 0x7F, 0x00, 0xC0, 0xFF, 0x1F, 0xF8, 0x0F, 0xFC, 0x3F, 0x00, 0x80, 0xFF, 0x0F, 0xF8, 0x1F, 0xFC, 0x1F, 0x00,
0x00, 0xFF, 0x0F, 0xFC, 0x3F, 0xFC, 0x0F, 0x00, 0x00, 0xF8, 0x1F, 0xFF, 0xFF, 0xFE, 0x01, 0x00, 0x00, 0x00, 0xFC, 0xFF,
0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x07, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define sun_width 30
#define sun_height 30
static unsigned char sun[] PROGMEM = {
0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x30, 0xC0, 0x00, 0x03,
0x70, 0x00, 0x80, 0x03, 0xF0, 0x00, 0xC0, 0x03, 0xF0, 0xF8, 0xC7, 0x03, 0xE0, 0xFC, 0xCF, 0x01, 0x00, 0xFE, 0x1F, 0x00,
0x00, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x8E, 0xFF, 0x7F, 0x1C, 0x9F, 0xFF, 0x7F, 0x3E,
0x9F, 0xFF, 0x7F, 0x3E, 0x8E, 0xFF, 0x7F, 0x1C, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x3F, 0x00,
0x00, 0xFE, 0x1F, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0xC0, 0xF9, 0xE7, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0xF0, 0x01, 0xE0, 0x03,
0xF0, 0xC0, 0xC0, 0x03, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xC0, 0x00, 0x00,
};
#define rain_width 30
#define rain_height 30
static unsigned char rain[] PROGMEM = {
0xC0, 0x0F, 0xC0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x03, 0x38, 0x00,
0x00, 0x0E, 0x0C, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x20,
0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x30, 0x02, 0x00,
0x00, 0x10, 0x06, 0x00, 0x00, 0x08, 0xFC, 0xFF, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0x01, 0x80, 0x00, 0x01, 0x00,
0xC0, 0xC0, 0x81, 0x03, 0xA0, 0x60, 0xC1, 0x03, 0x90, 0x20, 0x41, 0x01, 0xF0, 0xE0, 0xC0, 0x01, 0x60, 0x4C,
0x98, 0x00, 0x00, 0x0E, 0x1C, 0x00, 0x00, 0x0B, 0x12, 0x00, 0x00, 0x09, 0x1A, 0x00, 0x00, 0x06, 0x0E, 0x00,
};
#define cloud_height 30
#define cloud_width 30
static unsigned char cloud[] PROGMEM = {
0x00, 0x80, 0x07, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x70, 0x30, 0x00, 0x00, 0x10, 0x60, 0x00, 0x80, 0x1F, 0x40, 0x00,
0xC0, 0x0F, 0xC0, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x60, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x01,
0x20, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x10,
0x02, 0x00, 0x00, 0x30, 0x03, 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, 0x01, 0x00, 0x00, 0x30, 0x03, 0x00, 0x00, 0x10,
0x02, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x0C, 0xFC, 0xFF, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0x03,
};
#define fog_height 25
#define fog_width 25
static unsigned char fog[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x3C, 0x00, 0xFE, 0x01, 0xFF, 0x00, 0x87, 0xC7, 0xC3, 0x01, 0x03, 0xFE, 0x80, 0x01,
0x00, 0x38, 0x00, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0xFF, 0x83, 0xFF, 0x01, 0x03, 0xFF, 0x81, 0x01, 0x00, 0x7C, 0x00, 0x00,
0xF8, 0x00, 0x3E, 0x00, 0xFE, 0x01, 0xFF, 0x00, 0x87, 0xC7, 0xC3, 0x01, 0x03, 0xFE, 0x80, 0x01, 0x00, 0x38, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define devil_height 30
#define devil_width 30
static unsigned char devil[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x10, 0x03, 0xC0, 0x01, 0x38, 0x07, 0x7C, 0x0F, 0x38, 0x1F, 0x03, 0x30, 0x1E,
0xFE, 0x01, 0xE0, 0x1F, 0x7E, 0x00, 0x80, 0x1F, 0x3C, 0x00, 0x00, 0x0F, 0x1C, 0x00, 0x00, 0x0E, 0x18, 0x00, 0x00, 0x06,
0x08, 0x00, 0x00, 0x04, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x0E, 0x1C, 0x0C,
0x0C, 0x18, 0x06, 0x0C, 0x0C, 0x1C, 0x06, 0x0C, 0x0C, 0x1C, 0x0E, 0x0C, 0x0C, 0x1C, 0x0E, 0x0C, 0x0C, 0x0C, 0x06, 0x0C,
0x08, 0x00, 0x00, 0x06, 0x18, 0x02, 0x10, 0x06, 0x10, 0x0C, 0x0C, 0x03, 0x30, 0xF8, 0x07, 0x03, 0x60, 0xE0, 0x80, 0x01,
0xC0, 0x00, 0xC0, 0x00, 0x80, 0x01, 0x70, 0x00, 0x00, 0x06, 0x1C, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define heart_height 30
#define heart_width 30
static unsigned char heart[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0xF0, 0x00, 0xF8, 0x0F, 0xFC, 0x07, 0xFC, 0x1F, 0x06, 0x0E, 0xFE, 0x3F, 0x03, 0x18,
0xFE, 0xFF, 0x7F, 0x10, 0xFF, 0xFF, 0xFF, 0x31, 0xFF, 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0xFF, 0x37, 0xFF, 0xFF, 0xFF, 0x37,
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF, 0xFF, 0x1F,
0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0x03,
0xE0, 0xFF, 0xFF, 0x01, 0xC0, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, 0xFE, 0x1F, 0x00,
0x00, 0xFC, 0x0F, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
};
#define poo_width 30
#define poo_height 30
static unsigned char poo[] PROGMEM = {
0x00, 0x1C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xEC, 0x01, 0x00, 0x00, 0x8C, 0x07, 0x00, 0x00, 0x0C, 0x06, 0x00,
0x00, 0x24, 0x0C, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, 0x1F, 0x08, 0x00, 0xC0, 0x0F, 0x08, 0x00, 0xC0, 0x00, 0x3C, 0x00,
0x60, 0x00, 0x7C, 0x00, 0x60, 0x00, 0xC6, 0x00, 0x20, 0x00, 0xCB, 0x00, 0xA0, 0xC7, 0xFF, 0x00, 0xE0, 0x7F, 0xF7, 0x00,
0xF0, 0x18, 0xE3, 0x03, 0x78, 0x18, 0x41, 0x03, 0x6C, 0x9B, 0x5D, 0x06, 0x64, 0x9B, 0x5D, 0x04, 0x44, 0x1A, 0x41, 0x04,
0x4C, 0xD8, 0x63, 0x06, 0xF8, 0xFC, 0x36, 0x06, 0xFE, 0x0F, 0x9C, 0x1F, 0x07, 0x03, 0xC0, 0x30, 0x03, 0x00, 0x78, 0x20,
0x01, 0x00, 0x1F, 0x20, 0x03, 0xE0, 0x03, 0x20, 0x07, 0x7E, 0x04, 0x30, 0xFE, 0x0F, 0xFC, 0x1F, 0xF0, 0x00, 0xF0, 0x0F,
};
#endif
#include "img/icon.xbm"

View File

@@ -8,6 +8,8 @@ typedef struct _InputEvent {
const char *source;
char inputEvent;
char kbchar;
uint16_t touchX;
uint16_t touchY;
} InputEvent;
class InputBroker : public Observable<const InputEvent *>
{

View File

@@ -24,7 +24,8 @@ LinuxInput::LinuxInput(const char *name) : concurrency::OSThread(name)
void LinuxInput::deInit()
{
close(fd);
if (fd >= 0)
close(fd);
}
int32_t LinuxInput::runOnce()
@@ -154,6 +155,9 @@ int32_t LinuxInput::runOnce()
case KEY_ENTER: // Enter
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;
case KEY_POWER:
system("poweroff");
break;
default: // all other keys
if (keymap[code]) {
e.inputEvent = ANYKEY;

View File

@@ -38,7 +38,7 @@ class LinuxInput : public Observable<const InputEvent *>, public concurrency::OS
int queue_progress = 0;
struct epoll_event events[MAX_EVENTS];
int fd;
int fd = -1;
int ret;
uint8_t report[8];
int epollfd;

View File

@@ -3,6 +3,7 @@
#include "InputBroker.h"
#include "concurrency/OSThread.h"
#include "mesh/NodeDB.h"
#include "time.h"
typedef struct _TouchEvent {
const char *source;

View File

@@ -4,7 +4,7 @@
#include "configuration.h"
#include "modules/ExternalNotificationModule.h"
#ifdef ARCH_PORTDUINO
#if ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
@@ -49,6 +49,10 @@ void TouchScreenImpl1::onEvent(const TouchEvent &event)
{
InputEvent e;
e.source = event.source;
e.touchX = event.x;
e.touchY = event.y;
switch (event.touchEvent) {
case TOUCH_ACTION_LEFT: {
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT);

View File

@@ -1,7 +1,7 @@
#include "UpDownInterruptBase.h"
#include "configuration.h"
UpDownInterruptBase::UpDownInterruptBase(const char *name)
UpDownInterruptBase::UpDownInterruptBase(const char *name) : concurrency::OSThread(name)
{
this->_originName = name;
}
@@ -24,31 +24,48 @@ void UpDownInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinPress,
attachInterrupt(this->_pinUp, onIntUp, RISING);
LOG_DEBUG("Up/down/press GPIO initialized (%d, %d, %d)\n", this->_pinUp, this->_pinDown, pinPress);
this->setInterval(100);
}
int32_t UpDownInterruptBase::runOnce()
{
InputEvent e;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
if (this->action == UPDOWN_ACTION_PRESSED) {
LOG_DEBUG("GPIO event Press\n");
e.inputEvent = this->_eventPressed;
} else if (this->action == UPDOWN_ACTION_UP) {
LOG_DEBUG("GPIO event Up\n");
e.inputEvent = this->_eventUp;
} else if (this->action == UPDOWN_ACTION_DOWN) {
LOG_DEBUG("GPIO event Down\n");
e.inputEvent = this->_eventDown;
}
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
e.source = this->_originName;
e.kbchar = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
this->notifyObservers(&e);
}
this->action = UPDOWN_ACTION_NONE;
return 100;
}
void UpDownInterruptBase::intPressHandler()
{
InputEvent e;
e.source = this->_originName;
LOG_DEBUG("GPIO event Press\n");
e.inputEvent = this->_eventPressed;
this->notifyObservers(&e);
this->action = UPDOWN_ACTION_PRESSED;
}
void UpDownInterruptBase::intDownHandler()
{
InputEvent e;
e.source = this->_originName;
LOG_DEBUG("GPIO event Down\n");
e.inputEvent = this->_eventDown;
this->notifyObservers(&e);
this->action = UPDOWN_ACTION_DOWN;
}
void UpDownInterruptBase::intUpHandler()
{
InputEvent e;
e.source = this->_originName;
LOG_DEBUG("GPIO event Up\n");
e.inputEvent = this->_eventUp;
this->notifyObservers(&e);
this->action = UPDOWN_ACTION_UP;
}

View File

@@ -3,7 +3,7 @@
#include "InputBroker.h"
#include "mesh/NodeDB.h"
class UpDownInterruptBase : public Observable<const InputEvent *>
class UpDownInterruptBase : public Observable<const InputEvent *>, public concurrency::OSThread
{
public:
explicit UpDownInterruptBase(const char *name);
@@ -13,6 +13,13 @@ class UpDownInterruptBase : public Observable<const InputEvent *>
void intDownHandler();
void intUpHandler();
int32_t runOnce() override;
protected:
enum UpDownInterruptBaseActionType { UPDOWN_ACTION_NONE, UPDOWN_ACTION_PRESSED, UPDOWN_ACTION_UP, UPDOWN_ACTION_DOWN };
volatile UpDownInterruptBaseActionType action = UPDOWN_ACTION_NONE;
private:
uint8_t _pinDown = 0;
uint8_t _pinUp = 0;

View File

@@ -1,5 +1,4 @@
#include "kbI2cBase.h"
#include "configuration.h"
#include "detect/ScanI2C.h"
@@ -138,6 +137,9 @@ int32_t KbI2cBase::runOnce()
break;
case 0x13: // Code scanner says the SYM key is 0x13
is_sym = !is_sym;
e.inputEvent = ANYKEY;
e.kbchar =
is_sym ? 0xf1 : 0xf2; // send 0xf1 to tell CannedMessages to display that the modifier key is active
break;
case 0x0a: // apparently Enter on Q10 is a line feed instead of carriage return
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
@@ -193,6 +195,75 @@ int32_t KbI2cBase::runOnce()
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.source = this->_originName;
switch (c) {
case 0x71: // This is the button q. If modifier and q pressed, it cancels the input
if (is_sym) {
is_sym = false;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
}
break;
case 0x74: // letter t. if modifier and t pressed call 'tab'
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0x09; // TAB Scancode
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
}
break;
case 0x6d: // letter m. Modifier makes it mute notifications
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0xac; // mute notifications
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
}
break;
case 0x6f: // letter o(+). Modifier makes screen increase in brightness
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0x11; // Increase Brightness code
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
}
break;
case 0x69: // letter i(-). Modifier makes screen decrease in brightness
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0x12; // Decrease Brightness code
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
}
break;
case 0x20: // Space. Send network ping like double press does
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0xaf; // (fn + space)
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
}
break;
case 0x67: // letter g. toggle gps
if (is_sym) {
is_sym = false;
e.inputEvent = ANYKEY;
e.kbchar = 0x9e;
} else {
e.inputEvent = ANYKEY;
e.kbchar = c;
}
break;
case 0x1b: // ESC
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
break;
@@ -216,6 +287,22 @@ int32_t KbI2cBase::runOnce()
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = 0xb7;
break;
case 0xc: // Modifier key: 0xc is alt+c (Other options could be: 0xea = shift+mic button or 0x4 shift+$(speaker))
// toggle moddifiers button.
is_sym = !is_sym;
e.inputEvent = ANYKEY;
e.kbchar = is_sym ? 0xf1 : 0xf2; // send 0xf1 to tell CannedMessages to display that the modifier key is active
break;
case 0x90: // fn+r
case 0x91: // fn+t
case 0x9b: // fn+s
case 0xac: // fn+m
case 0x9e: // fn+g
case 0xaf: // fn+space
// just pass those unmodified
e.inputEvent = ANYKEY;
e.kbchar = c;
break;
case 0x0d: // Enter
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;
@@ -229,6 +316,7 @@ int32_t KbI2cBase::runOnce()
}
e.inputEvent = ANYKEY;
e.kbchar = c;
is_sym = false;
break;
}

View File

@@ -1,4 +1,7 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_GPS
#include "GPS.h"
#endif
#include "MeshRadio.h"
#include "MeshService.h"
#include "NodeDB.h"
@@ -6,7 +9,7 @@
#include "ReliableRouter.h"
#include "airtime.h"
#include "buzz.h"
#include "configuration.h"
#include "error.h"
#include "power.h"
// #include "debug.h"
@@ -33,10 +36,14 @@
// #include <driver/rtc_io.h>
#ifdef ARCH_ESP32
#if !MESHTASTIC_EXCLUDE_WEBSERVER
#include "mesh/http/WebServer.h"
#endif
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
#include "nimble/NimbleBluetooth.h"
NimbleBluetooth *nimbleBluetooth;
#endif
#endif
#ifdef ARCH_NRF52
#include "NRF52Bluetooth.h"
@@ -52,16 +59,22 @@ NRF52Bluetooth *nrf52Bluetooth;
#include "mesh/api/ethServerAPI.h"
#include "mesh/eth/ethClient.h"
#endif
#if !MESHTASTIC_EXCLUDE_MQTT
#include "mqtt/MQTT.h"
#endif
#include "LLCC68Interface.h"
#include "RF95Interface.h"
#include "SX1262Interface.h"
#include "SX1268Interface.h"
#include "SX1280Interface.h"
#include "detect/LoRaRadioType.h"
#ifdef ARCH_STM32WL
#include "STM32WLE5JCInterface.h"
#endif
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
#include "platform/portduino/SimRadio.h"
#endif
@@ -78,11 +91,13 @@ NRF52Bluetooth *nrf52Bluetooth;
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
#include "ButtonThread.h"
#endif
#include "PowerFSMThread.h"
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#include "AccelerometerThread.h"
#include "AmbientLightingThread.h"
AccelerometerThread *accelerometerThread;
#endif
#ifdef HAS_I2S
@@ -129,6 +144,9 @@ ATECCX08A atecc;
Adafruit_DRV2605 drv;
#endif
// Global LoRa radio type
LoRaRadioType radioType = NO_RADIO;
bool isVibrating = false;
bool eink_found = true;
@@ -162,6 +180,11 @@ const char *getDeviceName()
static int32_t ledBlinker()
{
// Still set up the blinking (heartbeat) interval but skip code path below, so LED will blink if
// config.device.led_heartbeat_disabled is changed
if (config.device.led_heartbeat_disabled)
return 1000;
static bool ledOn;
ledOn ^= 1;
@@ -175,10 +198,6 @@ uint32_t timeLastPowered = 0;
static Periodic *ledPeriodic;
static OSThread *powerFSMthread;
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
static OSThread *buttonThread;
#endif
static OSThread *accelerometerThread;
static OSThread *ambientLightingThread;
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
@@ -223,7 +242,12 @@ void setup()
#if defined(TTGO_T_ECHO) && defined(PIN_POWER_EN)
pinMode(PIN_POWER_EN, OUTPUT);
digitalWrite(PIN_POWER_EN, HIGH);
digitalWrite(PIN_POWER_EN1, INPUT);
// digitalWrite(PIN_POWER_EN1, INPUT);
#endif
#if defined(LORA_TCXO_GPIO)
pinMode(LORA_TCXO_GPIO, OUTPUT);
digitalWrite(LORA_TCXO_GPIO, HIGH);
#endif
#if defined(VEXT_ENABLE_V03)
@@ -318,7 +342,7 @@ void setup()
Wire.begin(I2C_SDA, I2C_SCL);
#elif defined(ARCH_PORTDUINO)
if (settingsStrings[i2cdev] != "") {
LOG_INFO("Using %s as I2C device.\n", settingsStrings[i2cdev]);
LOG_INFO("Using %s as I2C device.\n", settingsStrings[i2cdev].c_str());
Wire.begin(settingsStrings[i2cdev].c_str());
} else {
LOG_INFO("No I2C device configured, skipping.\n");
@@ -336,18 +360,11 @@ void setup()
delay(1);
#endif
#ifdef RAK4630
#ifdef PIN_3V3_EN
// We need to enable 3.3V periphery in order to scan it
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
#endif
#ifndef USE_EINK
#ifdef AQ_SET_PIN
// RAK-12039 set pin for Air quality sensor
pinMode(AQ_SET_PIN, OUTPUT);
digitalWrite(AQ_SET_PIN, HIGH);
#endif
#endif
#ifdef T_DECK
// enable keyboard
@@ -368,7 +385,7 @@ void setup()
// We need to scan here to decide if we have a screen for nodeDB.init() and because power has been applied to
// accessories
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
#ifdef HAS_WIRE
#if HAS_WIRE
LOG_INFO("Scanning for i2c devices...\n");
#endif
@@ -514,6 +531,10 @@ void setup()
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10)
i2cScanner.reset();
@@ -521,10 +542,6 @@ void setup()
setupSDCard();
#endif
#ifdef RAK4630
// scanEInkDevice();
#endif
// LED init
#ifdef LED_PIN
@@ -549,7 +566,7 @@ void setup()
// We do this as early as possible because this loads preferences from flash
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
nodeDB.init();
nodeDB = new NodeDB;
// If we're taking on the repeater role, use flood router and turn off 3V3_S rail because peripherals are not needed
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
@@ -580,7 +597,7 @@ void setup()
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // keep dimension of 128x64
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (acc_info.type != ScanI2C::DeviceType::NONE) {
config.display.wake_on_tap_or_motion = true;
moduleConfig.external_notification.enabled = true;
@@ -588,7 +605,9 @@ void setup()
}
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if defined(HAS_NEOPIXEL) || defined(UNPHONE) || defined(RGBLED_RED)
ambientLightingThread = new AmbientLightingThread(ScanI2C::DeviceType::NONE);
#elif !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
if (rgb_found.type != ScanI2C::DeviceType::NONE) {
ambientLightingThread = new AmbientLightingThread(rgb_found.type);
}
@@ -611,39 +630,51 @@ void setup()
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
SPI1.begin(false);
#else // HW_SPI1_DEVICE
#else // HW_SPI1_DEVICE
SPI.setSCK(LORA_SCK);
SPI.setTX(LORA_MOSI);
SPI.setRX(LORA_MISO);
SPI.begin(false);
#endif // HW_SPI1_DEVICE
#elif ARCH_PORTDUINO
SPI.begin(settingsStrings[spidev].c_str());
#endif // HW_SPI1_DEVICE
#elif !defined(ARCH_ESP32) // ARCH_RP2040
SPI.begin();
#else
// ESP32
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
LOG_WARN("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
LOG_DEBUG("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
SPI.setFrequency(4000000);
#endif
// Initialize the screen first so we can show the logo while we start up everything else.
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
// setup TZ prior to time actions.
if (*config.device.tzdef) {
setenv("TZ", config.device.tzdef, 1);
} else {
setenv("TZ", "GMT0", 1);
}
tzset();
LOG_DEBUG("Set Timezone to %s\n", getenv("TZ"));
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
#if !MESHTASTIC_EXCLUDE_GPS
// If we're taking on the repeater role, ignore GPS
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
gps = GPS::createGps();
if (HAS_GPS) {
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
gps = GPS::createGps();
if (gps) {
gpsStatus->observe(&gps->newStatus);
} else {
LOG_DEBUG("Running without GPS.\n");
}
}
}
if (gps) {
gpsStatus->observe(&gps->newStatus);
} else {
LOG_DEBUG("Running without GPS.\n");
}
nodeStatus->observe(&nodeDB.newStatus);
#endif
nodeStatus->observe(&nodeDB->newStatus);
#ifdef HAS_I2S
LOG_DEBUG("Starting audio thread\n");
@@ -655,6 +686,12 @@ void setup()
// Now that the mesh service is created, create any modules
setupModules();
#ifdef LED_PIN
// Turn LED off after boot, if heartbeat by config
if (config.device.led_heartbeat_disabled)
digitalWrite(LED_PIN, LOW ^ LED_INVERTED);
#endif
// Do this after service.init (because that clears error_code)
#ifdef HAS_PMU
if (!pmu_found)
@@ -663,7 +700,7 @@ void setup()
// Don't call screen setup until after nodedb is setup (because we need
// the current region name)
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(HX8357_CS)
screen->setup();
#elif defined(ARCH_PORTDUINO)
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
@@ -691,7 +728,8 @@ void setup()
if (settingsMap[use_sx1262]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate sx1262 radio on SPI port %s\n", settingsStrings[spidev].c_str());
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
LockingArduinoHal *RadioLibHAL =
new LockingArduinoHal(SPI, spiSettings, (settingsMap[ch341Quirk] ? settingsMap[busy] : RADIOLIB_NC));
rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
@@ -705,7 +743,8 @@ void setup()
} else if (settingsMap[use_rf95]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate rf95 radio on SPI port %s\n", settingsStrings[spidev].c_str());
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
LockingArduinoHal *RadioLibHAL =
new LockingArduinoHal(SPI, spiSettings, (settingsMap[ch341Quirk] ? settingsMap[busy] : RADIOLIB_NC));
rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
@@ -732,6 +771,21 @@ void setup()
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n");
}
}
} else if (settingsMap[use_sx1268]) {
if (!rIf) {
LOG_DEBUG("Attempting to activate sx1268 radio on SPI port %s\n", settingsStrings[spidev].c_str());
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
rIf = new SX1268Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset],
settingsMap[busy]);
if (!rIf->init()) {
LOG_ERROR("Failed to find SX1268 radio\n");
delete rIf;
rIf = NULL;
exit(EXIT_FAILURE);
} else {
LOG_INFO("SX1268 Radio init succeeded, using SX1268 radio\n");
}
}
}
#elif defined(HW_SPI1_DEVICE)
@@ -750,6 +804,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("STM32WL Radio init succeeded, using STM32WL radio\n");
radioType = STM32WLx_RADIO;
}
}
#endif
@@ -763,6 +818,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("Using SIMULATED radio!\n");
radioType = SIM_RADIO;
}
}
#endif
@@ -776,6 +832,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("RF95 Radio init succeeded, using RF95 radio\n");
radioType = RF95_RADIO;
}
}
#endif
@@ -789,6 +846,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n");
radioType = SX1262_RADIO;
}
}
#endif
@@ -802,6 +860,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("SX1268 Radio init succeeded, using SX1268 radio\n");
radioType = SX1268_RADIO;
}
}
#endif
@@ -815,6 +874,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("LLCC68 Radio init succeeded, using LLCC68 radio\n");
radioType = LLCC68_RADIO;
}
}
#endif
@@ -828,6 +888,7 @@ void setup()
rIf = NULL;
} else {
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n");
radioType = SX1280_RADIO;
}
}
#endif
@@ -837,7 +898,7 @@ void setup()
if ((config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (!rIf->wideLora())) {
LOG_WARN("Radio chip does not support 2.4GHz LoRa. Reverting to unset.\n");
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
nodeDB.saveToDisk(SEGMENT_CONFIG);
nodeDB->saveToDisk(SEGMENT_CONFIG);
if (!rIf->reconfigure()) {
LOG_WARN("Reconfigure failed, rebooting\n");
screen->startRebootScreen();
@@ -845,9 +906,12 @@ void setup()
}
}
#if !MESHTASTIC_EXCLUDE_MQTT
mqttInit();
#endif
#ifndef ARCH_PORTDUINO
// Initialize Wifi
#if HAS_WIFI
initWifi();
@@ -859,7 +923,7 @@ void setup()
#endif
#endif
#ifdef ARCH_ESP32
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WEBSERVER
// Start web server thread.
webServerThread = new WebServerThread();
#endif

View File

@@ -22,6 +22,11 @@ extern NimbleBluetooth *nimbleBluetooth;
extern NRF52Bluetooth *nrf52Bluetooth;
#endif
#if ARCH_PORTDUINO
extern HardwareSPI *DisplaySPI;
extern HardwareSPI *LoraSPI;
#endif
extern ScanI2C::DeviceAddress screen_found;
extern ScanI2C::DeviceAddress cardkb_found;
extern uint8_t kb_model;
@@ -48,12 +53,18 @@ extern Adafruit_DRV2605 drv;
extern AudioThread *audioThread;
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#include "AccelerometerThread.h"
extern AccelerometerThread *accelerometerThread;
#endif
extern bool isVibrating;
extern int TCPPort; // set by Portduino
// Global Screen singleton.
extern graphics::Screen *screen;
// extern Observable<meshtastic::PowerStatus> newPowerStatus; //TODO: move this to main-esp32.cpp somehow or a helper class
// extern meshtastic::PowerStatus *powerStatus;

View File

@@ -22,6 +22,8 @@ uint32_t MemGet::getFreeHeap()
return ESP.getFreeHeap();
#elif defined(ARCH_NRF52)
return dbgHeapFree();
#elif defined(ARCH_RP2040)
return rp2040.getFreeHeap();
#else
// this platform does not have heap management function implemented
return UINT32_MAX;
@@ -38,6 +40,8 @@ uint32_t MemGet::getHeapSize()
return ESP.getHeapSize();
#elif defined(ARCH_NRF52)
return dbgHeapTotal();
#elif defined(ARCH_RP2040)
return rp2040.getTotalHeap();
#else
// this platform does not have heap management function implemented
return UINT32_MAX;

View File

@@ -7,6 +7,10 @@
#include <assert.h>
#if !MESHTASTIC_EXCLUDE_MQTT
#include "mqtt/MQTT.h"
#endif
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128)
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01};
@@ -16,7 +20,9 @@ Channels channels;
const char *Channels::adminChannel = "admin";
const char *Channels::gpioChannel = "gpio";
const char *Channels::serialChannel = "serial";
#if !MESHTASTIC_EXCLUDE_MQTT
const char *Channels::mqttChannel = "mqtt";
#endif
uint8_t xorHash(const uint8_t *p, size_t len)
{
@@ -193,6 +199,12 @@ void Channels::onConfigChanged()
if (ch.role == meshtastic_Channel_Role_PRIMARY)
primaryIndex = i;
}
#if !MESHTASTIC_EXCLUDE_MQTT
if (channels.anyMqttEnabled() && mqtt && !mqtt->isEnabled()) {
LOG_DEBUG("MQTT is enabled on at least one channel, so set MQTT thread to run immediately\n");
mqtt->start();
}
#endif
}
meshtastic_Channel &Channels::getByIndex(ChannelIndex chIndex)
@@ -237,6 +249,16 @@ void Channels::setChannel(const meshtastic_Channel &c)
old = c; // slam in the new settings/role
}
bool Channels::anyMqttEnabled()
{
for (int i = 0; i < getNumChannels(); i++)
if (channelFile.channels[i].role != meshtastic_Channel_Role_DISABLED && channelFile.channels[i].has_settings &&
(channelFile.channels[i].settings.downlink_enabled || channelFile.channels[i].settings.uplink_enabled))
return true;
return false;
}
const char *Channels::getName(size_t chIndex)
{
// Convert the short "" representation for Default into a usable string
@@ -274,40 +296,6 @@ bool Channels::hasDefaultChannel()
return false;
}
/**
* Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs.
* The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why they
their nodes
* aren't talking to each other.
*
* This string is of the form "#name-X".
*
* Where X is either:
* (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together,
*
* This function will also need to be implemented in GUI apps that talk to the radio.
*
* https://github.com/meshtastic/firmware/issues/269
*/
const char *Channels::getPrimaryName()
{
static char buf[32];
char suffix;
// auto channelSettings = getPrimary();
// if (channelSettings.psk.size != 1) {
// We have a standard PSK, so generate a letter based hash.
uint8_t code = getHash(primaryIndex);
suffix = 'A' + (code % 26);
/* } else {
suffix = '0' + channelSettings.psk.bytes[0];
} */
snprintf(buf, sizeof(buf), "#%s-%c", getName(primaryIndex), suffix);
return buf;
}
/** Given a channel hash setup crypto for decoding that channel (or the primary channel if that channel is unsecured)
*
* This method is called before decoding inbound packets

View File

@@ -61,25 +61,6 @@ class Channels
ChannelIndex getNumChannels() { return channelFile.channels_count; }
/**
* Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different
PSKs.
* The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why
they their nodes
* aren't talking to each other.
*
* This string is of the form "#name-X".
*
* Where X is either:
* (for custom PSKS) a letter from A to Z (base26), and formed by xoring all the bytes of the PSK together,
* OR (for the standard minimially secure PSKs) a number from 0 to 9.
*
* This function will also need to be implemented in GUI apps that talk to the radio.
*
* https://github.com/meshtastic/firmware/issues/269
*/
const char *getPrimaryName();
/// Called by NodeDB on initial boot when the radio config settings are unset. Set a default single channel config.
void initDefaults();
@@ -105,6 +86,9 @@ class Channels
// Returns true if we can be reached via a channel with the default settings given a region and modem preset
bool hasDefaultChannel();
// Returns true if any of our channels have enabled MQTT uplink or downlink
bool anyMqttEnabled();
private:
/** Given a channel index, change to use the crypto key specified by that index
*

23
src/mesh/Default.cpp Normal file
View File

@@ -0,0 +1,23 @@
#include "Default.h"
uint32_t Default::getConfiguredOrDefaultMs(uint32_t configuredInterval)
{
if (configuredInterval > 0)
return configuredInterval * 1000;
return default_broadcast_interval_secs * 1000;
}
uint32_t Default::getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval)
{
if (configuredInterval > 0)
return configuredInterval * 1000;
return defaultInterval * 1000;
}
uint32_t Default::getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue)
{
if (configured > 0)
return configured;
return defaultValue;
}

31
src/mesh/Default.h Normal file
View File

@@ -0,0 +1,31 @@
#pragma once
#include <NodeDB.h>
#include <cstdint>
#define ONE_DAY 24 * 60 * 60
#define ONE_MINUTE_MS 60 * 1000
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
#define default_ls_secs IF_ROUTER(ONE_DAY, 5 * 60)
#define default_min_wake_secs 10
#define default_screen_on_secs IF_ROUTER(1, 60 * 10)
#define default_node_info_broadcast_secs 3 * 60 * 60
#define min_node_info_broadcast_secs 60 * 60 // No regular broadcasts of more than once an hour
#define default_mqtt_address "mqtt.meshtastic.org"
#define default_mqtt_username "meshdev"
#define default_mqtt_password "large4cats"
#define default_mqtt_root "msh"
#define IF_ROUTER(routerVal, normalVal) \
((config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) ? (routerVal) : (normalVal))
class Default
{
public:
static uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval);
static uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval);
static uint32_t getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue);
};

View File

@@ -35,11 +35,10 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
{
bool isAck =
((c && c->error_reason == meshtastic_Routing_Error_NONE)); // consider only ROUTING_APP message without error as ACK
if (isAck && p->to != getNodeNum()) {
// do not flood direct message that is ACKed
LOG_DEBUG("Receiving an ACK not for me, but don't need to rebroadcast this direct message anymore.\n");
bool isAckorReply = (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) && (p->decoded.request_id != 0);
if (isAckorReply && p->to != getNodeNum() && p->to != NODENUM_BROADCAST) {
// do not flood direct message that is ACKed or replied to
LOG_DEBUG("Receiving an ACK or reply not for me, but don't need to rebroadcast this direct message anymore.\n");
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
}
if ((p->to != getNodeNum()) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
@@ -49,15 +48,6 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
tosend->hop_limit--; // bump down the hop count
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
// If it is a traceRoute request, update the route that it went via me
if (traceRouteModule && traceRouteModule->wantPacket(p))
traceRouteModule->updateRoute(tosend);
// If it is a neighborInfo packet, update last_sent_by_id
if (neighborInfoModule && neighborInfoModule->wantPacket(p))
neighborInfoModule->updateLastSentById(tosend);
}
LOG_INFO("Rebroadcasting received floodmsg to neighbors\n");
// Note: we are careful to resend using the original senders node id
// We are careful not to call our hooked version of send() - because we don't want to check this again

View File

@@ -2,8 +2,6 @@
#include "PacketHistory.h"
#include "Router.h"
#include "modules/NeighborInfoModule.h"
#include "modules/TraceRouteModule.h"
/**
* This is a mixin that extends Router with the ability to do Naive Flooding (in the standard mesh protocol sense)

View File

@@ -12,7 +12,7 @@ const meshtastic_MeshPacket *MeshModule::currentRequest;
/**
* If any of the current chain of modules has already sent a reply, it will be here. This is useful to allow
* the RoutingPlugin to avoid sending redundant acks
* the RoutingModule to avoid sending redundant acks
*/
meshtastic_MeshPacket *MeshModule::currentReply;
@@ -40,7 +40,7 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod
c.error_reason = err;
c.which_variant = meshtastic_Routing_error_reason_tag;
// Now that we have moded sendAckNak up one level into the class hierarchy we can no longer assume we are a RoutingPlugin
// Now that we have moded sendAckNak up one level into the class hierarchy we can no longer assume we are a RoutingModule
// So we manually call pb_encode_to_bytes and specify routing port number
// auto p = allocDataProtobuf(c);
meshtastic_MeshPacket *p = router->allocForSending();
@@ -54,7 +54,8 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod
p->to = to;
p->decoded.request_id = idFrom;
p->channel = chIndex;
LOG_ERROR("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
if (err != meshtastic_Routing_Error_NONE)
LOG_ERROR("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
return p;
}
@@ -68,7 +69,7 @@ meshtastic_MeshPacket *MeshModule::allocErrorResponse(meshtastic_Routing_Error e
return r;
}
void MeshModule::callPlugins(meshtastic_MeshPacket &mp, RxSource src)
void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
{
// LOG_DEBUG("In call modules\n");
bool moduleFound = false;
@@ -81,7 +82,7 @@ void MeshModule::callPlugins(meshtastic_MeshPacket &mp, RxSource src)
bool ignoreRequest = false; // No module asked to ignore the request yet
// Was this message directed to us specifically? Will be false if we are sniffing someone elses packets
auto ourNodeNum = nodeDB.getNodeNum();
auto ourNodeNum = nodeDB->getNodeNum();
bool toUs = mp.to == NODENUM_BROADCAST || mp.to == ourNodeNum;
for (auto i = modules->begin(); i != modules->end(); ++i) {
@@ -258,7 +259,7 @@ void MeshModule::observeUIEvents(Observer<const UIFrameEvent *> *observer)
}
}
AdminMessageHandleResult MeshModule::handleAdminMessageForAllPlugins(const meshtastic_MeshPacket &mp,
AdminMessageHandleResult MeshModule::handleAdminMessageForAllModules(const meshtastic_MeshPacket &mp,
meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response)
{
@@ -279,4 +280,4 @@ AdminMessageHandleResult MeshModule::handleAdminMessageForAllPlugins(const mesht
}
}
return handled;
}
}

View File

@@ -64,11 +64,11 @@ class MeshModule
/** For use only by MeshService
*/
static void callPlugins(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
static void callModules(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
static std::vector<MeshModule *> GetMeshModulesWithUIFrames();
static void observeUIEvents(Observer<const UIFrameEvent *> *observer);
static AdminMessageHandleResult handleAdminMessageForAllPlugins(const meshtastic_MeshPacket &mp,
static AdminMessageHandleResult handleAdminMessageForAllModules(const meshtastic_MeshPacket &mp,
meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response);
#if HAS_SCREEN
@@ -195,4 +195,4 @@ class MeshModule
/** set the destination and packet parameters of packet p intended as a reply to a particular "to" packet
* This ensures that if the request packet was sent reliably, the reply is sent that way as well.
*/
void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to);
void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to);

View File

@@ -1,10 +1,11 @@
#include "configuration.h"
#include <assert.h>
#include <string>
#if !MESHTASTIC_EXCLUDE_GPS
#include "GPS.h"
#endif
#include "../concurrency/Periodic.h"
#include "BluetoothCommon.h" // needed for updateBatteryLevel, FIXME, eventually when we pull mesh out into a lib we shouldn't be whacking bluetooth from here
#include "GPS.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
@@ -15,8 +16,10 @@
#include "modules/NodeInfoModule.h"
#include "modules/PositionModule.h"
#include "power.h"
#include <assert.h>
#include <string>
#ifdef ARCH_ESP32
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
#include "nimble/NimbleBluetooth.h"
#endif
@@ -72,22 +75,23 @@ void MeshService::init()
{
// moved much earlier in boot (called from setup())
// nodeDB.init();
#if HAS_GPS
if (gps)
gpsObserver.observe(&gps->newStatus);
#endif
}
int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
{
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
nodeDB->updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
mp->decoded.portnum == meshtastic_PortNum_TELEMETRY_APP && mp->decoded.request_id > 0) {
LOG_DEBUG(
"Received telemetry response. Skip sending our NodeInfo because this potentially a Repeater which will ignore our "
"request for its NodeInfo.\n");
} else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getMeshNode(mp->from)->has_user &&
} else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user &&
nodeInfoModule) {
LOG_INFO("Heard a node on channel %d we don't know, sending NodeInfo and asking for a response.\n", mp->channel);
nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel);
@@ -120,10 +124,10 @@ bool MeshService::reloadConfig(int saveWhat)
// If we can successfully set this radio to these settings, save them to disk
// This will also update the region as needed
bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings
bool didReset = nodeDB->resetRadioConfig(); // Don't let the phone send us fatally bad settings
configChanged.notifyObservers(NULL); // This will cause radio hardware to change freqs etc
nodeDB.saveToDisk(saveWhat);
nodeDB->saveToDisk(saveWhat);
return didReset;
}
@@ -133,7 +137,7 @@ void MeshService::reloadOwner(bool shouldSave)
{
// LOG_DEBUG("reloadOwner()\n");
// update our local data directly
nodeDB.updateUser(nodeDB.getNodeNum(), owner);
nodeDB->updateUser(nodeDB->getNodeNum(), owner);
assert(nodeInfoModule);
// update everyone else and save to disk
if (nodeInfoModule && shouldSave) {
@@ -188,12 +192,7 @@ void MeshService::handleToRadio(meshtastic_MeshPacket &p)
return;
}
#endif
if (p.from != 0) { // We don't let phones assign nodenums to their sent messages
LOG_WARN("phone tried to pick a nodenum, we don't allow that.\n");
p.from = 0;
} else {
// p.from = nodeDB.getNodeNum();
}
p.from = 0; // We don't let phones assign nodenums to their sent messages
if (p.id == 0)
p.id = generatePacketId(); // If the phone didn't supply one, then pick one
@@ -217,7 +216,7 @@ void MeshService::handleToRadio(meshtastic_MeshPacket &p)
/** Attempt to cancel a previously sent packet from this _local_ node. Returns true if a packet was found we could cancel */
bool MeshService::cancelSending(PacketId id)
{
return router->cancelSending(nodeDB.getNodeNum(), id);
return router->cancelSending(nodeDB->getNodeNum(), id);
}
ErrorCode MeshService::sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id)
@@ -245,7 +244,7 @@ ErrorCode MeshService::sendQueueStatusToPhone(const meshtastic_QueueStatus &qs,
void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPhone)
{
uint32_t mesh_packet_id = p->id;
nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
nodeDB->updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
// Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it
ErrorCode res = router->sendLocal(p, src);
@@ -258,28 +257,32 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh
LOG_DEBUG("Can't send status to phone");
}
if (ccToPhone) {
if (res == ERRNO_OK && ccToPhone) { // Check if p is not released in case it couldn't be sent
sendToPhone(packetPool.allocCopy(*p));
}
}
void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
bool MeshService::trySendPosition(NodeNum dest, bool wantReplies)
{
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
assert(node);
if (hasValidPosition(node)) {
#if HAS_GPS
if (positionModule) {
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
positionModule->sendOurPosition(dest, wantReplies, node->channel);
return true;
}
} else {
#endif
if (nodeInfoModule) {
LOG_INFO("Sending nodeinfo ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
nodeInfoModule->sendOurNodeInfo(dest, wantReplies, node->channel);
}
}
return false;
}
void MeshService::sendToPhone(meshtastic_MeshPacket *p)
@@ -320,7 +323,7 @@ void MeshService::sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage
meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode()
{
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
assert(node);
// We might not have a position yet for our local node, in that case, at least try to send the time
@@ -344,6 +347,7 @@ meshtastic_NodeInfoLite *MeshService::refreshLocalMeshNode()
return node;
}
#if HAS_GPS
int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
{
// Update our local node info with our position (even if we don't decide to update anyone else)
@@ -359,7 +363,7 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
LOG_DEBUG("onGPSchanged() - lost validLocation\n");
#endif
}
// Used fixed position if configured regalrdless of GPS lock
// Used fixed position if configured regardless of GPS lock
if (config.position.fixed_position) {
LOG_WARN("Using fixed position\n");
pos = TypeConversions::ConvertToPosition(node->position);
@@ -373,11 +377,11 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
pos.longitude_i, pos.altitude);
// Update our current position in the local DB
nodeDB.updatePosition(nodeDB.getNodeNum(), pos, RX_SRC_LOCAL);
nodeDB->updatePosition(nodeDB->getNodeNum(), pos, RX_SRC_LOCAL);
return 0;
}
#endif
bool MeshService::isToPhoneQueueEmpty()
{
return toPhoneQueue.isEmpty();

Some files were not shown because too many files have changed in this diff Show More