Compare commits

..

491 Commits

Author SHA1 Message Date
Ben Meadors
2baaad8298 I swear 2023-01-27 11:19:45 -06:00
Ben Meadors
2e8832babb Trunk, you got a big storm coming, honey 2023-01-27 10:22:17 -06:00
Ben Meadors
ed155476ac Merge pull request #2210 from meshtastic/heap-reboot
move temporary reboot code to blink thread
2023-01-27 08:21:49 -06:00
Thomas Göttgens
61028293b8 move temporary reboot code to blink thread 2023-01-27 14:46:53 +01:00
Ben Meadors
d14bd652eb Merge pull request #2204 from meshtastic/rak-4631-fix
Potential fix for TX problem in RAK-4631 cores and other SX126X ant switch issues
2023-01-25 16:17:07 -06:00
Ben Meadors
cb3d5a5748 Comment about external PA module boards 2023-01-25 15:48:42 -06:00
Ben Meadors
d51aa60864 Missed one 2023-01-25 15:03:59 -06:00
Ben Meadors
9b18d5d85f Fmt 2023-01-25 14:59:12 -06:00
Ben Meadors
25096c5c63 Use radiolib native tx/rx_en switch control 2023-01-25 14:58:50 -06:00
Ben Meadors
f1fd41a378 Add to Eink target as well 2023-01-25 11:48:11 -06:00
Ben Meadors
ca91447c0e For science! 2023-01-25 10:10:09 -06:00
Ben Meadors
4a0f3f31cb Merge pull request #2201 from folkertvanheusden/xmodem-check
code reduction
2023-01-24 15:14:03 -06:00
folkert van heusden
f07963e802 Small tweak that reduces the number of lines of code in
XModemAdapter::check to 1. It should be functionally the same.
2023-01-24 21:30:16 +01:00
Ben Meadors
cb8532f2df Protos 2023-01-24 12:16:01 -06:00
Ben Meadors
0b1e1687ae Merge pull request #2157 from andrew-moroz/sx126x-rx-boosted-gain
sx126x-rx-boosted-gain: add support for setting Rx gain mode on SX126x chipsets
2023-01-24 11:54:16 -06:00
Ben Meadors
006cddd5cb Merge branch 'master' into sx126x-rx-boosted-gain 2023-01-24 10:04:31 -06:00
Ben Meadors
4d7e3329d9 Merge pull request #2185 from code8buster/gps-fixedposboot
GPS acquisiton on boot only
2023-01-24 10:04:06 -06:00
Ben Meadors
9e8342eb8f Merge branch 'master' into gps-fixedposboot 2023-01-24 10:01:53 -06:00
Thomas Göttgens
afb4d141dc remove double endif 2023-01-23 22:42:32 +01:00
Thomas Göttgens
19d864b5ce Also reboot if no heap debugging enabled 2023-01-23 22:42:32 +01:00
Thomas Göttgens
e8186f7dba how did that sneak in? 2023-01-23 21:57:41 +01:00
Thomas Göttgens
81854a173a fix #2109 json mqtt on secondary channel 2023-01-23 21:57:41 +01:00
Thomas Göttgens
083dcef9d6 don't define default pins for these. 2023-01-23 17:18:19 +01:00
Ben Meadors
5f0662d47d Merge branch 'master' into gps-fixedposboot 2023-01-23 06:35:53 -06:00
Ben Meadors
76022b65c6 Merge pull request #2192 from meshtastic/xmodem-fix
tryfix: also clear the second buffer.
2023-01-23 06:35:38 -06:00
Ben Meadors
2df81810ec Merge branch 'master' into sx126x-rx-boosted-gain 2023-01-23 06:06:22 -06:00
Thomas Göttgens
efa1445df4 Merge branch 'master' into gps-fixedposboot 2023-01-23 12:48:23 +01:00
code8buster
53d096b58e Disable the GPS thread after factory reset has been requested 2023-01-23 06:34:28 -05:00
Thomas Göttgens
4da1fb8e27 there's a special place in hell for include paths... 2023-01-23 06:34:10 -05:00
Thomas Göttgens
8e0dcb09e8 tempfix: reboot ESP Node if heap runs low.
fixes #2165
2023-01-23 06:34:10 -05:00
Thomas Göttgens
014946ad0e tryfix: also clear the second buffer.
Todo: do we really need 2 buffers here?
2023-01-23 12:29:10 +01:00
Thomas Göttgens
3aebb1ffb3 there's a special place in hell for include paths... 2023-01-23 12:27:16 +01:00
Thomas Göttgens
3b80421403 tempfix: reboot ESP Node if heap runs low.
fixes #2165
2023-01-23 12:27:16 +01:00
Thomas Göttgens
255d433ebf Merge branch 'master' into gps-fixedposboot 2023-01-23 11:16:19 +01:00
Ben Meadors
2c1b7840c5 Make this pr great again 2023-01-23 09:22:40 +01:00
Thomas Göttgens
e9acf413fb After thoroughly reading schematics and documentation, i conclude that this is theoretically the right definition for this hookup. 2023-01-23 09:22:40 +01:00
Ben Meadors
7c60896072 Merge branch 'master' into gps-fixedposboot 2023-01-22 20:55:49 -06:00
Ben Meadors
1941d196bb Additional docker tags 2023-01-22 13:52:01 -06:00
Thomas Göttgens
3120744716 Missed one :-) 2023-01-22 18:58:14 +01:00
Ben Meadors
2ecf273cf3 Merge pull request #2189 from meshtastic/xmodem-fix-2
Xmodem fix 2
2023-01-22 09:12:51 -06:00
Ben Meadors
50cee4a6c8 Oops! 2023-01-22 08:51:30 -06:00
Ben Meadors
ac6d4e33d4 Format 2023-01-22 08:49:06 -06:00
Ben Meadors
4c9f0b2646 Just start a new PR. Conflicts were too wild 2023-01-22 08:48:31 -06:00
Ben Meadors
fab663d1b7 Merge branch 'master' into gps-fixedposboot 2023-01-21 20:34:41 -06:00
Ben Meadors
fc5e80a5cc Merge pull request #2172 from meshtastic/stm32wl-wip
Stm32wl wip
2023-01-21 20:29:36 -06:00
Ben Meadors
266c61065d I swear I did this before you butthole 2023-01-21 19:51:24 -06:00
Ben Meadors
e2e7658789 w/e 2023-01-21 19:24:33 -06:00
Thomas Göttgens
a421edce49 Merge branch 'master' into stm32wl-wip 2023-01-21 21:55:09 +01:00
Ben Meadors
3f3a4ce44c Merge pull request #2187 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-21 14:49:56 -06:00
caveman99
8aab63dace [create-pull-request] automated change 2023-01-21 20:37:04 +00:00
Thomas Göttgens
aac9b5db30 and the saga continues 2023-01-21 21:23:24 +01:00
Thomas Göttgens
6f30a84afc dayum! 2023-01-21 21:23:24 +01:00
Thomas Göttgens
c53c87499b missed a few 2023-01-21 21:23:24 +01:00
Thomas Göttgens
cdf379616c whatever makes trunk happy. 2023-01-21 21:23:24 +01:00
Thomas Göttgens
6fdb93cd16 re-add namespacing in protobufs. Let's see what i missed. Portduino likely ...
Checking in generated on purpose.
2023-01-21 21:23:24 +01:00
Thomas Göttgens
ab3446faed Back out changes to non-source files 2023-01-21 21:23:24 +01:00
Thomas Göttgens
9ebe24e680 that didn't hurt at all 2023-01-21 21:23:24 +01:00
Thomas Göttgens
811ac15a81 even those were formatted. 2023-01-21 21:23:24 +01:00
Thomas Göttgens
51b2c431d9 trunk roundhouse kick 2023-01-21 21:23:24 +01:00
Thomas Göttgens
6cf18b7d07 trunk recommended this change ¯\_(ツ)_/¯ 2023-01-21 21:23:24 +01:00
code8buster
52e8dc7317 just do sleep through the observer like I have been 2023-01-21 08:33:43 -05:00
GUVWAF
d8e644191b Merge pull request #2184 from GUVWAF/trunk
Make Trunk happy
2023-01-21 13:27:30 +01:00
code8buster
fdc47728af Put GPS thread to sleep post factory reset request 2023-01-21 07:21:23 -05:00
code8buster
54b4b67e5c add logic for GPS single acquisition on bootup fixed-position 2023-01-21 07:21:23 -05:00
GUVWAF
bcf24b8187 Make Trunk happy 2023-01-21 13:01:19 +01:00
GUVWAF
c628c70db2 Merge pull request #2179 from nukevoid/master
Fix vulnerability with "h.from == 0"
2023-01-21 12:37:50 +01:00
Nukevoid
7f9e638140 Merge branch 'master' into master 2023-01-21 02:18:33 +02:00
a_filonichev
5a2ad03294 Merge branch 'master' of https://github.com/nukevoid/firmware 2023-01-20 23:41:23 +02:00
a_filonichev
a584cac827 fix rxGood counter 2023-01-20 23:41:05 +02:00
Thomas Göttgens
8f5338dc85 Merge pull request #2174 from meshtastic/SH1107
Sh1107 support (128x128)
2023-01-20 22:15:02 +01:00
Thomas Göttgens
8c434c7084 Merge branch 'SH1107' of github.com:meshtastic/firmware into SH1107 2023-01-20 21:54:03 +01:00
Thomas Göttgens
88c84dd806 trunk again 2023-01-20 21:53:34 +01:00
Ben Meadors
f9f083da51 Merge branch 'master' into SH1107 2023-01-20 14:44:19 -06:00
Nukevoid
481880872c Merge branch 'master' into master 2023-01-20 19:03:37 +02:00
Thomas Göttgens
0eaf0747f4 fix building other screen adapters 2023-01-20 16:34:39 +01:00
Ben Meadors
9a7121d8c9 Merge pull request #2175 from GUVWAF/printFixes
Fix two print format specifiers
2023-01-20 09:26:39 -06:00
Thomas Göttgens
cbd6a0065b trunk format 2023-01-20 15:04:09 +01:00
Thomas Göttgens
50f72b0ea0 add the possibility to #define USE_SH1107 to fix boards to this display. 2023-01-20 15:04:09 +01:00
Thomas Göttgens
74ec5e8a5c add support for 128x128 b/w display GME128128-01-IIC 2023-01-20 15:04:09 +01:00
Thomas Göttgens
bec0cda175 Merge branch 'master' into printFixes 2023-01-20 14:32:03 +01:00
Ben Meadors
ca298d8a7d Merge branch 'master' into sx126x-rx-boosted-gain 2023-01-20 07:08:53 -06:00
a_filonichev
3eaa054c68 Fix vulnerability with "h.from == 0"
// altered packed with "from == 0" can do Remote Node Administration without permission
2023-01-20 01:38:13 +02:00
Thomas Göttgens
48ea836a5c Merge pull request #2177 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-19 15:46:06 +01:00
caveman99
fda1e29c4d [create-pull-request] automated change 2023-01-19 14:14:12 +00:00
GUVWAF
836559cda1 Fix two print format specifiers 2023-01-19 15:01:44 +01:00
Thomas Göttgens
c04980084a Fix line endings at LF and make windows proto generation work again. needs cygwin64 in path 2023-01-19 14:04:31 +01:00
Thomas Göttgens
111ec56028 Merge pull request #2173 from meshtastic/triple-double
Double click sends ad-hoc position, triple turns off gps
2023-01-19 08:20:53 +01:00
Ben Meadors
384eac9a87 Format plz 2023-01-18 21:13:31 -06:00
Ben Meadors
6a5e0edb60 Double click sends ad-hoc position, triple turns off gps 2023-01-18 21:02:45 -06:00
Ben Meadors
9d47f7a531 Format 2023-01-18 20:03:10 -06:00
Ben Meadors
660a73d58c Stuff 2023-01-18 19:45:39 -06:00
Ben Meadors
412fbea978 WIP 2023-01-18 19:24:18 -06:00
Ben Meadors
293625924d Merge branch 'master' into sx126x-rx-boosted-gain 2023-01-18 16:57:41 -06:00
Ben Meadors
4cfedc4b57 Kill it and grill it 2023-01-18 16:34:21 -06:00
Ben Meadors
cd57df3f4f Update main_matrix.yml 2023-01-18 16:18:01 -06:00
Ben Meadors
6c41960919 Remove simulator for now 2023-01-18 15:55:58 -06:00
Ben Meadors
48609b5bdd Merge pull request #2170 from meshtastic/device-metadata-enhanced
Add role and position flags to metadata
2023-01-18 15:16:40 -06:00
Ben Meadors
dad8e2bf6a Merge branch 'master' into device-metadata-enhanced 2023-01-18 15:16:20 -06:00
Ben Meadors
9cda2e9058 Add role and position flags to metadata 2023-01-18 15:15:02 -06:00
Ben Meadors
72dad37138 Merge pull request #2169 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-18 15:12:44 -06:00
thebentern
ee25a488ef [create-pull-request] automated change 2023-01-18 21:12:03 +00:00
Ben Meadors
9046dacec8 I don't like this formatting but I need trunk to STFU 2023-01-18 14:51:48 -06:00
Ben Meadors
b218ea9ec7 Hopefully ignore generated files 2023-01-18 11:04:06 -06:00
Ben Meadors
6f70d39bae Merge pull request #2166 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-18 10:22:33 -06:00
thebentern
80f259cc6c [create-pull-request] automated change 2023-01-18 16:19:47 +00:00
Ben Meadors
36b3bf2211 Strip namspace prefix 2023-01-18 10:16:15 -06:00
Ben Meadors
92525587e1 Merge pull request #2164 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-18 09:00:17 -06:00
thebentern
5189e328b6 [create-pull-request] automated change 2023-01-18 14:57:44 +00:00
Ben Meadors
4d4af7de59 generated paths experiment 2023-01-18 08:56:47 -06:00
Ben Meadors
1b932c6bbe Fix scripts patch and remove files in previous dir 2023-01-18 07:53:19 -06:00
Ben Meadors
4065fb1709 Merge pull request #2162 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-18 07:43:35 -06:00
thebentern
cf39628222 [create-pull-request] automated change 2023-01-18 13:42:53 +00:00
Ben Meadors
d7fa8fea8d Update protos path for generator scripts 2023-01-18 07:39:05 -06:00
Sacha Weatherstone
db3d66544d Setup Trunk (#2143)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-01-17 17:35:26 +11:00
Andrew Moroz
0a2539650e sx126x-rx-boosted-gain: add support for setting Rx gain mode on SX126x chipsets 2023-01-17 00:56:15 -05:00
Thomas Göttgens
d35b619063 Merge pull request #2112 from meshtastic/xmodem-proto
Add Chunked File Transfer to API
2023-01-16 20:36:09 +01:00
Thomas Göttgens
0e51a42ce2 Merge branch 'master' into xmodem-proto 2023-01-16 20:11:02 +01:00
Ben Meadors
d5f7d741c3 Merge pull request #2153 from meshtastic/develop
Develop to master
2023-01-16 13:00:15 -06:00
Ben Meadors
cc0cccbd1b Coerce int 2023-01-16 12:26:10 -06:00
Ben Meadors
6c388e0da8 Merge branch 'master' into develop 2023-01-16 11:10:08 -06:00
Thomas Göttgens
9f3c09cf40 adapt to new proto names 2023-01-16 18:09:17 +01:00
Ben Meadors
34b2d51113 Patch locked_to 2023-01-16 11:05:36 -06:00
Thomas Göttgens
1dbd0f8dd1 Merge branch 'develop' of github.com:meshtastic/firmware into develop 2023-01-16 17:56:57 +01:00
Thomas Göttgens
0f4306158c fix S&F Problem 2023-01-16 17:56:48 +01:00
Thomas Göttgens
d5a3acb83a Trigger rebuild 2023-01-16 17:55:17 +01:00
Krezalis
efbdb273c3 Update RadioInterface.cpp 2023-01-16 17:55:17 +01:00
Krezalis
011013ab1a Update RadioInterface.cpp 2023-01-16 17:55:17 +01:00
Krezalis
49279e56d0 Update RadioInterface.cpp 2023-01-16 17:55:17 +01:00
Krezalis
1cfda77356 Add 868 MHz Ukrainian Band 2023-01-16 17:55:17 +01:00
caveman99
f4779bd93f [create-pull-request] automated change 2023-01-16 17:51:45 +01:00
garthvh
e95db927ac [create-pull-request] automated change 2023-01-16 14:54:50 +01:00
Ben Meadors
a4d3fa55db Remove HAS_GPS for WSLv3 2023-01-16 14:54:50 +01:00
Thomas Göttgens
59ee0fb012 put legacy S&F call back in, till Apps support it. 2023-01-16 14:53:27 +01:00
Thomas Göttgens
5831124f1d Store and Forward: don't try to store a message if PSRAM is not initialized! 2023-01-16 14:53:27 +01:00
Thomas Göttgens
2b9f01f0e4 fix cppcheck 2023-01-16 11:08:48 +01:00
Thomas Göttgens
aca1241a7f Having a first stab at flawfinder errors 2023-01-16 10:55:40 +01:00
Thomas Göttgens
da0440ba17 Merge pull request #2145 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-15 21:21:38 +01:00
garthvh
85dd606423 [create-pull-request] automated change 2023-01-15 16:52:29 +00:00
Ben Meadors
7e27729dae Remove HAS_GPS for WSLv3 2023-01-15 08:24:20 -06:00
Ben Meadors
d49f19a67c Merge pull request #2137 from meshtastic/cherrypick-serialfix
re-merge fixes by @lesykm
2023-01-12 12:16:53 -06:00
Ben Meadors
5520d68b34 Merge pull request #2136 from meshtastic/serial-fix
re-merge fixes by @lesykm
2023-01-12 12:16:40 -06:00
Thomas Göttgens
c33569f833 re-merge fixes by @lesykm 2023-01-12 12:15:12 -06:00
Thomas Göttgens
8db3f317ab re-merge fixes by @lesykm 2023-01-12 19:08:41 +01:00
Ben Meadors
a3636ae8a1 Merge pull request #2133 from meshtastic/master
Master downstream merge
2023-01-12 10:22:56 -06:00
Ben Meadors
7936c7c8ae Remove the D! 2023-01-12 10:07:17 -06:00
Ben Meadors
2f3f19fda7 Merge pull request #2132 from meshtastic/develop
Remove DEBUG_HEAP flag from esp32 pio config on release
2023-01-12 09:37:33 -06:00
Ben Meadors
c89ca50cc4 Remove DEBUG_HEAP flag from esp32 pio config on release 2023-01-12 09:33:55 -06:00
Thomas Göttgens
867e55b9e7 sync mqtt with develop 2023-01-12 16:09:03 +01:00
Ben Meadors
28b1616630 Merge pull request #2131 from meshtastic/develop
Develop to master for 2.0.13 release candidate
2023-01-12 08:37:11 -06:00
Thomas Göttgens
42122f3d0f Merge branch 'master' into develop 2023-01-12 15:01:56 +01:00
Ben Meadors
f905763161 Merge pull request #2129 from meshtastic/nice-duty-cycle
Chance calculation for Nice TX. Still same value but dynamically based on duty cycle.
2023-01-12 07:20:29 -06:00
Thomas Göttgens
bd2b766a36 Rename to make function clearer 2023-01-12 14:03:06 +01:00
Thomas Göttgens
bd51cbd721 Chance calculation for Nice TX. Still same value but dynamically based on duty cycle. 2023-01-12 09:15:54 +00:00
Thomas Göttgens
5e66dd0dad File Transfer: add debug logging and allocate memory used. 2023-01-12 10:00:52 +01:00
Thomas Göttgens
80d1a993dd Merge branch 'develop' of github.com:meshtastic/firmware into xmodem-proto 2023-01-12 10:00:04 +01:00
Ben Meadors
e3fd17772d Merge pull request #2127 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-11 19:40:51 -06:00
thebentern
440b965e71 [create-pull-request] automated change 2023-01-12 01:38:21 +00:00
Ben Meadors
cf0fb13a12 Merge pull request #2126 from GUVWAF/TxAirLim
Don't send NodeInfo and DeviceTelemetry at high Tx air utilization
2023-01-11 19:26:40 -06:00
GUVWAF
c0166773e8 Portduino can handle this 2023-01-11 21:53:23 +01:00
GUVWAF
fc775012ea Don't send NodeInfo and DeviceTelemetry at high Tx air util
Also move airtime checking to airtime class
2023-01-11 21:52:19 +01:00
Ben Meadors
d7a71e46aa Merge pull request #2125 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-11 14:36:10 -06:00
thebentern
721f87af7e [create-pull-request] automated change 2023-01-11 20:35:13 +00:00
Ben Meadors
a354cebd88 Update protos ref 2023-01-11 14:28:10 -06:00
Ben Meadors
97680ca730 Merge pull request #2123 from meshtastic/time
Allow time from phone to be sent to the mesh
2023-01-11 09:11:45 -06:00
Ben Meadors
17a2589b35 Allow time from phone to be sent to the mesh 2023-01-11 07:50:07 -06:00
Thomas Göttgens
4f71ab07c9 2.0.12 is out already. Bump develop too. 2023-01-11 14:33:54 +01:00
Ben Meadors
1f6a8eae86 Merge pull request #2121 from GUVWAF/NAKtoAPI
Send NAK to API only upon duty cycle limit
2023-01-10 14:20:51 -06:00
GUVWAF
ab9d0ba543 Report actual RoutingError 2023-01-10 21:12:40 +01:00
GUVWAF
e13fb9919e Send NAK only to the API upon duty cycle limit 2023-01-10 21:12:17 +01:00
GUVWAF
a3b93a4dcf Better not to compare float directly 2023-01-10 21:10:09 +01:00
Thomas Göttgens
6b0f18e1e4 Merge pull request #2113 from meshtastic/mqtt-fix
Find the downlink channel to post packet to.
2023-01-10 20:49:18 +01:00
Thomas Göttgens
312ef790fc Merge pull request #2119 from meshtastic/rak-shutdown-rail
Turn of 3.3v rail on RAK-4631 on shutdown
2023-01-10 19:03:03 +01:00
Ben Meadors
713f7d5996 Turn of 3.3v rail on RAK-4631 on shutdown 2023-01-10 07:36:19 -06:00
Ben Meadors
3985008e06 Merge pull request #2116 from meshtastic/rak4631-radiofix 2023-01-09 22:13:46 -06:00
Thomas Göttgens
8f2155f8f9 Merge branch 'develop' into mqtt-fix 2023-01-09 23:28:08 +01:00
Thomas Göttgens
1fc5d70221 let the library handle the reconnect, manually do it after 5 seconds 2023-01-09 23:26:47 +01:00
Ben Meadors
e7d425ef6e Until we figure out what's going on 2023-01-09 16:19:42 -06:00
Thomas Göttgens
c63536d948 switch to 16 bit packet number 2023-01-09 20:23:32 +01:00
Thomas Göttgens
9c1cfe9358 Merge pull request #2114 from meshtastic/refactor-apiserver
make a template class for API Server
2023-01-09 20:11:01 +01:00
Thomas Göttgens
971565aed3 Merge branch 'develop' into xmodem-proto 2023-01-09 20:08:37 +01:00
Thomas Göttgens
3a6e3464e6 notify phoneAPI about new packages to process 2023-01-09 20:06:11 +01:00
Thomas Göttgens
0181e186ac Merge pull request #2106 from meshtastic/assert-cleanup
initial cleanup work
2023-01-09 19:45:23 +01:00
Thomas Göttgens
86748bf88e fix building portduino and make cppcheck happy 2023-01-09 19:23:41 +01:00
Thomas Göttgens
5fd00b2538 - make a template class for API Server
- Skip a lot of duplicate code
- add a hexDump output - might come in handy
- refactor directory names
- remove unused debugOut that was generating template errors
2023-01-09 17:03:52 +01:00
Thomas Göttgens
5cec370cf5 getByName was not used anywhere in the code so that change is safe.
Please TEST this as i don't have a working Json setup in mqtt at the moment.
2023-01-09 11:28:21 +01:00
Thomas Göttgens
fce52e16e3 update license. This is only loosely based on Xmodem. 2023-01-08 18:34:56 +01:00
Thomas Göttgens
0e7797f3bb Adding to generated for now, protobuf PR will come when it works ... :-) 2023-01-08 18:15:51 +01:00
Thomas Göttgens
81ee6dd799 first crash from stress test 2023-01-07 23:40:47 +01:00
Thomas Göttgens
49172e416e Merge pull request #2108 from markbirss/develop
Add initial support for BETAFPV ELRS Micro TX Module 2.4G with ESP32 CPU
2023-01-07 22:50:04 +01:00
Ben Meadors
57f185c26b Merge pull request #2104 from meshtastic/hydra-gps
Hydra gps troubleshooting
2023-01-07 14:51:46 -06:00
Thomas Göttgens
3a8ffe7ac2 ah feck 2023-01-07 15:43:17 +01:00
Thomas Göttgens
d8b85f9a09 fingers crossed 2023-01-07 15:24:46 +01:00
Mark Trevor Birss
4d7402839e Update platformio.ini 2023-01-07 16:00:27 +02:00
Thomas Göttgens
8465467aa8 2nd batch 2023-01-07 14:57:00 +01:00
Thomas Göttgens
2a0b8093ea freakin' nitpickin' cpp_check 2023-01-07 13:59:40 +01:00
Thomas Göttgens
96fa5dafb8 fixing portduino 2023-01-07 13:36:02 +01:00
Thomas Göttgens
be2d3f7769 fix leak 2023-01-07 13:28:36 +01:00
Thomas Göttgens
b283e526bf fix for nRF52 and Portduino 2023-01-07 13:25:29 +01:00
Thomas Göttgens
03c5dfc7a8 initial cleanup work 2023-01-07 13:16:58 +01:00
Mark Trevor Birss
52cfd62031 Update SX128xInterface.cpp 2023-01-07 14:05:16 +02:00
Mark Trevor Birss
c98dc4cae0 Update variant.h 2023-01-07 13:48:35 +02:00
Mark Trevor Birss
f21212dd3e Update platformio.ini 2023-01-07 13:23:33 +02:00
Mark Trevor Birss
0e0ccad489 Update variant.h 2023-01-07 13:22:32 +02:00
Mark Trevor Birss
9f1c77da76 Create variant.h 2023-01-07 13:01:14 +02:00
Mark Trevor Birss
7c1c49b8ab Create platformio.ini 2023-01-07 13:00:50 +02:00
Ben Meadors
f4099261df Hydra gps troubleshooting 2023-01-06 15:04:11 -06:00
Thomas Göttgens
450e7362f6 Merge pull request #2103 from kn6plv/fix-multicast-macaddress
Make sure we dont use a multicast MAC for ethernet
2023-01-06 12:43:48 +01:00
Tim Wilkinson
0b9c8e62ea Make sure we dont use a multicast MAC for ethernet 2023-01-05 22:31:57 -08:00
Ben Meadors
09efbb75b1 Merge pull request #2099 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-04 11:22:59 -06:00
thebentern
e5d9f1f946 [create-pull-request] automated change 2023-01-04 16:13:43 +00:00
Thomas Göttgens
2400dd43b3 Merge pull request #2098 from meshtastic/hotfix-02
External Notification Hotfix
2023-01-04 15:31:28 +01:00
Thomas Göttgens
988d5af69b Merge pull request #2097 from meshtastic/hotfix-01
External Notification Hotfix
2023-01-04 15:31:02 +01:00
Thomas Göttgens
78b6916b1b External Notification Hotfix 2023-01-04 14:49:04 +01:00
Thomas Göttgens
9740f0a505 External Notification Hotfix 2023-01-04 14:45:28 +01:00
Thomas Göttgens
b64a74c0c5 add heap debugging back in too 2023-01-04 14:43:23 +01:00
Thomas Göttgens
d9f0dc7ea4 add MQTT outqueue back in (still broken) 2023-01-04 14:41:58 +01:00
pavelb-techspark
30ae4c2a38 Add QueueStatus sending to the firmware (#1820)
* Yank mqtt service envelope queue

* trybuildfix mqtt system

* removed too much

* no excessive heap debugging on release builds

* send QueueStatus messages

The QueueStatus message is sent as a response to the attempt to queue
an outgoing MeshPacket and contains statuses of the last queue
attempt, TX Queue space and capacity and MeshPacket.id that was
queued.

When TX Queue changes status from completely full to at least
a single slot free a QueueStatus message is also sent to notify
that user can queue more messages.

Signed-off-by: Pavel Boldin <pavel.b@techspark.engineering>

* WIP: update protobufs

Signed-off-by: Pavel Boldin <pavel.b@techspark.engineering>

* update protobufs

* regen protos

Signed-off-by: Pavel Boldin <pavel.b@techspark.engineering>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Sacha Weatherstone <sachaw100@hotmail.com>
2023-01-04 23:56:52 +11:00
Thomas Göttgens
d077be1496 add a possibility to flush the serial TX buffer on the console. 2023-01-04 10:37:27 +01:00
Thomas Göttgens
4f26a2a74a Update Unishox to latest V2 code, change is only cosmetic 2023-01-04 10:35:52 +01:00
thebentern
41f9636ba3 [create-pull-request] automated change 2023-01-04 10:35:07 +01:00
Ben Meadors
b544163c3f Merge pull request #2095 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-03 19:25:51 -06:00
thebentern
6d989a29dd [create-pull-request] automated change 2023-01-03 22:34:34 +00:00
Ben Meadors
8914d1a184 Merge pull request #2094 from meshtastic/yank-mqtt-queue
Yank mqtt service envelope queue
2023-01-03 15:46:50 -06:00
Thomas Göttgens
1cfc7b800b Merge branch 'master' into yank-mqtt-queue 2023-01-03 22:38:01 +01:00
Thomas Göttgens
cab5fcf5ae no excessive heap debugging on release builds 2023-01-03 22:35:24 +01:00
Thomas Göttgens
cad5c9b70c removed too much 2023-01-03 22:17:04 +01:00
Thomas Göttgens
5867038abf trybuildfix mqtt system 2023-01-03 22:09:35 +01:00
Ben Meadors
42b24d4510 Yank mqtt service envelope queue 2023-01-03 14:32:28 -06:00
Ben Meadors
d750109d00 Merge pull request #2093 from meshtastic/develop
Merge develop to master
2023-01-03 13:55:24 -06:00
Ben Meadors
7f0a8d329f Merge pull request #2092 from meshtastic/develop-2-master
Develop -> Master merge branch
2023-01-03 12:53:35 -06:00
Thomas Göttgens
64895cc7eb remove Merge duplication 2023-01-03 19:21:11 +01:00
Thomas Göttgens
52903f83e3 remove Merge duplication 2023-01-03 19:19:11 +01:00
Ben Meadors
e0002ef2d5 Merge remote-tracking branch 'origin/master' into develop-2-master 2023-01-03 11:34:53 -06:00
Ben Meadors
021fc8235c Renamed eth_mode to address_mode 2023-01-03 06:24:47 -06:00
Ben Meadors
0305c7394f Merge pull request #2089 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-01-03 06:22:21 -06:00
thebentern
bca70d10d0 [create-pull-request] automated change 2023-01-03 12:20:39 +00:00
Sacha Weatherstone
1077846e8d Update README.md 2023-01-02 16:44:38 +11:00
Sacha Weatherstone
63c8ca9ca5 Update README.md 2023-01-02 16:44:05 +11:00
Thomas Göttgens
523b132100 Merge pull request #2086 from caveman99/develop
Fix External Notification Cutoff on nRF52
2023-01-01 21:30:30 +01:00
Thomas Göttgens
2d62cbe345 I am dumb. 2023-01-01 21:08:07 +01:00
Ben Meadors
b55fe549e3 Update CI badge 2022-12-31 20:10:44 -06:00
Thomas Göttgens
9a04aaa811 Merge pull request #2074 from meshtastic/nice-threads
a lot of thread housekeeping
2022-12-30 20:58:09 +01:00
Thomas Göttgens
092a753a6f yea, well 2022-12-30 20:27:35 +01:00
Thomas Göttgens
8a9af37d82 Merge branch 'develop' into nice-threads 2022-12-30 20:18:19 +01:00
Thomas Göttgens
74e6eb34bd Merge pull request #2082 from joshpirihi/develop
Increase MQTT buffer size
2022-12-30 20:13:10 +01:00
joshpirihi
11f1508d85 Merge branch 'meshtastic:develop' into develop 2022-12-31 06:40:25 +13:00
Joshua Pirihi
19436b7d54 Increase MQTT buffer size 2022-12-31 06:40:02 +13:00
Ben Meadors
69ff724f0f Merge pull request #2081 from meshtastic/log-levels
Created more structured enterprisey logging with levels
2022-12-30 11:30:23 -06:00
Ben Meadors
3d3aba584e Include 2022-12-30 10:56:57 -06:00
Ben Meadors
ef1fb877ba Prefix log levels 2022-12-30 10:47:31 -06:00
Ben Meadors
f1cdfd163d Replaced all of the logging with proper log levels 2022-12-30 10:27:07 -06:00
Thomas Göttgens
8364c2b147 more verbose thread debug 2022-12-30 17:03:48 +01:00
Ben Meadors
8193215294 Trace 2022-12-30 08:14:37 -06:00
Thomas Göttgens
e73ae7cdac woops - was too fast there 2022-12-30 14:53:34 +01:00
Thomas Göttgens
65aad62702 tryfix - no mqtt if no mqtt wanted... 2022-12-30 14:51:00 +01:00
Ben Meadors
3eefd46ca1 Log levels log function 2022-12-30 07:48:59 -06:00
Thomas Göttgens
115cb05d3b less verbose logging and heap free printing 2022-12-30 14:22:08 +01:00
Thomas Göttgens
44d5c69ba8 Merge pull request #2080 from GUVWAF/abortErr
Bug fix: report actual Routing_Error upon abort
2022-12-30 14:09:15 +01:00
GUVWAF
5ccd66864b Report actual Routing_Error upon abort 2022-12-30 13:45:02 +01:00
Ben Meadors
0b5cae5393 Log levels refactoring 2022-12-29 20:41:37 -06:00
Ben Meadors
be91b08b3e Missed one 2022-12-29 18:49:40 -06:00
Ben Meadors
c7c5671cca More disables 2022-12-29 18:48:33 -06:00
Ben Meadors
979d12d607 Here we go 2022-12-29 16:59:52 -06:00
Ben Meadors
110c80d045 Make disable return an int32_t for runOnce usage 2022-12-29 16:54:39 -06:00
Ben Meadors
38a1315599 Refactor OSThread consumers to use disable() 2022-12-29 16:26:25 -06:00
Ben Meadors
8ebe0edc5a Merge pull request #2075 from meshtastic/load-save-proto
add storage for ringtone
2022-12-29 15:50:16 -06:00
Thomas Göttgens
a8f93d5f47 Heap Debugging and Thread Disable 2022-12-29 22:42:05 +01:00
Ben Meadors
96c272d3d1 Merge pull request #2077 from meshtastic/remotehardware-config
add RemoteHardware (and the missing S&F config)
2022-12-29 15:33:47 -06:00
Thomas Göttgens
45e6e86ff9 - add RemoteHardware (and the missing S&F config) in
- make the config boundaries automatic
2022-12-29 21:35:32 +01:00
Thomas Göttgens
f73b8661de Wait for 5 seconds for serial port on ESP32-S2/3 too... 2022-12-29 21:34:18 +01:00
Thomas Göttgens
3c5710e65b - add storage for ringtone
- Refactor file load and save
- fix a size error in Canned Messages
2022-12-29 16:53:36 +01:00
Thomas Göttgens
4e4a74379e fix copy/paste error 2022-12-29 15:48:02 +01:00
Thomas Göttgens
41a1dfec79 a lot of thread housekeeping. Switch them off when not needed / disabled. 2022-12-29 15:45:49 +01:00
Thomas Göttgens
1a949b7ca6 Plumbing for new display layout protos 2022-12-29 15:44:22 +01:00
Thomas Göttgens
840079c25b build SX1280 on Master too 2022-12-29 14:26:21 +01:00
Thomas Göttgens
887405cc08 update protobufs on develop 2022-12-29 14:18:33 +01:00
Thomas Göttgens
d633212f70 2.0.11-dev 2022-12-29 14:11:57 +01:00
Thomas Göttgens
02def448bc Merge pull request #2073 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-29 14:08:38 +01:00
thebentern
7baf30dcb8 [create-pull-request] automated change 2022-12-29 12:51:16 +00:00
Ben Meadors
e09b12ca58 Merge pull request #2072 from meshtastic/hotfix-01
Hotfix for user button not working
2022-12-29 06:22:58 -06:00
Thomas Göttgens
1736dada7d hotfix for user button. Also update version number on develop 2022-12-29 11:56:47 +01:00
Thomas Göttgens
7f3a624ee3 Hotfix for user button not working 2022-12-29 11:55:19 +01:00
Thomas Göttgens
475c87b0e4 Merge pull request #2071 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-28 23:18:19 +01:00
thebentern
541f4aa998 [create-pull-request] automated change 2022-12-28 21:27:27 +00:00
Thomas Göttgens
ab6c4e61a6 Build and Check the SX1280 Boards too 2022-12-28 16:20:23 +01:00
Thomas Göttgens
6ea0963f4b fix master too 2022-12-28 16:03:34 +01:00
Thomas Göttgens
259d442d8f how did that happen? 2022-12-28 15:50:47 +01:00
Thomas Göttgens
b134f0bb46 missed one 2022-12-28 15:45:46 +01:00
Thomas Göttgens
63cf01223c Merge pull request #2070 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-28 15:43:40 +01:00
caveman99
2505bdbc21 [create-pull-request] automated change 2022-12-28 14:42:46 +00:00
Thomas Göttgens
d9d8c7eb74 I think this will fix portduino... 2022-12-28 15:41:58 +01:00
Thomas Göttgens
3b19040590 protobuf update 2022-12-28 15:37:17 +01:00
Thomas Göttgens
14be4ee9f0 Release Develop to Master 2022-12-28 15:31:04 +01:00
Thomas Göttgens
94cb100e3f Master to Develop 2022-12-28 15:30:23 +01:00
Ben Meadors
f632933b93 Merge pull request #2069 from GUVWAF/wantAckDM
Flood ACKs on DM back to original sender
2022-12-28 08:00:52 -06:00
Thomas Göttgens
e25d05689b Updates to external notification and radiolib for SX128x. Rip out Godmode again for these 2022-12-28 14:57:40 +01:00
GUVWAF
5c859da4e4 Remove unnecessary changes 2022-12-28 14:40:10 +01:00
GUVWAF
6c5602e88d Cleanup 2022-12-28 14:13:48 +01:00
GUVWAF
b4735f4224 Don't resend ACK every time you receive the packet 2022-12-28 14:13:48 +01:00
GUVWAF
3b9b33a5ee Use hopLimit setting for ACKs as well 2022-12-28 14:13:14 +01:00
Thomas Göttgens
430908f5d6 TLORA_T3_S3 2022-12-28 13:56:56 +01:00
Thomas Göttgens
6f6ca64cfd potential bugfix for nag cutoff 2022-12-27 21:51:35 +01:00
Thomas Göttgens
d0243d2cd0 Merge pull request #2067 from miaoski/sht31
Support SHT31 temperature sensor
2022-12-27 21:11:30 +01:00
Thomas Göttgens
796e58161d Merge branch 'master' into sht31 2022-12-27 13:58:44 +01:00
Thomas Göttgens
e56f17c658 Merge pull request #2068 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-27 13:58:27 +01:00
caveman99
b808ffa9ab [create-pull-request] automated change 2022-12-27 12:53:56 +00:00
miaoski
506bae4a8b Support SHT31 temperature sensor 2022-12-27 19:39:51 +08:00
Thomas Göttgens
f6ee6265e6 Merge pull request #2063 from lewisxhe/master
Fixed<t-beam-s3-core>display model is SH1106
2022-12-25 13:32:29 +01:00
Thomas Göttgens
7539d92857 Merge branch 'master' into master 2022-12-25 13:03:27 +01:00
Thomas Göttgens
21fff392b4 Backport RP2040 update 2022-12-25 13:02:40 +01:00
Thomas Göttgens
580ec590fa something broke pico toolchain. 'twasn'tme .. 2022-12-25 13:01:39 +01:00
lewis
5c9996dfa1 Fixed<t-beam-s3-core>display model is SH1106 2022-12-25 19:01:04 +08:00
Thomas Göttgens
34f9324766 Merge pull request #2061 from meshtastic/protobuf-04
Protobuf 04
2022-12-23 13:03:00 +01:00
Thomas Göttgens
3f988c8b69 something broke pico toolchain. 'twasn'tme .. 2022-12-23 11:41:58 +01:00
Thomas Göttgens
2ac2b6d1b6 replace PB03 compat macros with the real deal. 2022-12-23 10:00:34 +01:00
Thomas Göttgens
b8657158be Remove unused parameter on save 2022-12-23 09:45:56 +01:00
Thomas Göttgens
70f5f8301b added this in back by mistake 2022-12-23 09:01:59 +01:00
Thomas Göttgens
adb8d773d4 Merge pull request #2060 from meshtastic/protobuf-serial
ProtobufAPI in SerialModule
2022-12-22 20:29:01 +01:00
Thomas Göttgens
a289406863 refactor classes to accomodate SerialModule 2022-12-22 18:24:42 +01:00
Thomas Göttgens
1a3f2a8ab5 don't touch that code if you don't even know about "Serial2" 2022-12-22 17:43:55 +01:00
Thomas Göttgens
23d6b815f5 WIP: ProtobufAPI in SerialModule 2022-12-22 17:25:15 +01:00
Mykhailo Lesyk
e1feb5eb30 [modules][serial] switch simple mode from ascii to bytes 2022-12-22 14:55:32 +01:00
thebentern
cb8247559d [create-pull-request] automated change 2022-12-22 14:55:32 +01:00
Ben Meadors
28b954017f Copy pasta 2022-12-22 14:55:32 +01:00
Ben Meadors
16d826d6c7 Move to upstream espressif arduino 2022-12-22 14:55:32 +01:00
Thomas Göttgens
2f7c18303d Merge pull request #2058 from lesykm/serial-module-simple-mode-binary
[modules][serial] switch simple mode from ascii to bytes
2022-12-22 10:46:41 +01:00
Mykhailo Lesyk
b9df41c55f [modules][serial] switch simple mode from ascii to bytes 2022-12-21 22:37:30 -08:00
Thomas Göttgens
4801260440 Merge pull request #2055 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-21 20:30:14 +01:00
thebentern
606262e55d [create-pull-request] automated change 2022-12-21 18:54:52 +00:00
Thomas Göttgens
0064d18e64 remember to save your work before committing next time 2022-12-21 18:39:34 +01:00
Thomas Göttgens
6f5a6d5cb4 consolidate code and add missing message. 2022-12-21 17:56:34 +01:00
Thomas Göttgens
e0194528dd S&F WIP 2022-12-21 15:22:38 +01:00
Thomas Göttgens
30240ac14b fix cppcheck complaints 2022-12-21 15:13:16 +01:00
Ben Meadors
090e1660fe Merge pull request #2053 from meshtastic/upstream-heltec
Move to upstream espressif arduino
2022-12-21 07:47:27 -06:00
Ben Meadors
92c9b34d4f Copy pasta 2022-12-21 07:46:59 -06:00
Thomas Göttgens
fb41b0f5c8 update generated protos 2022-12-21 14:45:33 +01:00
Ben Meadors
3f50371ff3 Merge branch 'master' into upstream-heltec 2022-12-21 07:45:18 -06:00
Thomas Göttgens
812b321154 update protobufs 2022-12-21 14:44:13 +01:00
Ben Meadors
815f9bfc5f Move to upstream espressif arduino 2022-12-21 07:41:26 -06:00
Thomas Göttgens
86ff23d13c Merge pull request #2051 from meshtastic/master-next
moving a lot of stuff from develop into Master
2022-12-21 14:35:19 +01:00
Thomas Göttgens
201b786f77 fix RAK build 2022-12-21 14:06:02 +01:00
Thomas Göttgens
8074955841 Merge pull request #2052 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-21 13:56:37 +01:00
caveman99
0992093f4d [create-pull-request] automated change 2022-12-21 12:55:50 +00:00
Thomas Göttgens
6978e57991 fix nrf52 build 2022-12-21 13:49:26 +01:00
Thomas Göttgens
755c0b7008 use nanopb 0.4.7 2022-12-21 13:37:38 +01:00
Thomas Göttgens
7396d0f241 Cherry Picking Stuff from develop... 2022-12-21 13:36:38 +01:00
Thomas Göttgens
220859d0aa Merge pull request #2019 from code8buster/gps-toggle-final
Adds a flag to turn the GPS power rail off entirely on tbeam
2022-12-21 13:28:32 +01:00
Thomas Göttgens
941786669b fix compiler warnings 2022-12-21 13:28:29 +01:00
Thomas Göttgens
4eb620d47b Heap Debug: only show if delta occurs 2022-12-21 13:28:29 +01:00
Thomas Göttgens
9794995d7a fix building DIY-1 target 2022-12-21 13:28:29 +01:00
Thomas Göttgens
055146602a support ESP32-S2 CPUs
Note: these don't have Bluetooth and only a single physical core.
2022-12-21 13:28:28 +01:00
Thomas Göttgens
86d7860d86 made a nice PTT/RECV screen for audio module. And cleaned up screen graphics a bit. 2022-12-21 13:28:28 +01:00
Thomas Göttgens
0f2d0d1f07 change on screen graphics to support bicolor screens 2022-12-21 13:28:28 +01:00
Thomas Göttgens
ab6a5a5e07 if we get different frames than our own transmission setup, decode and play them anyway 2022-12-21 13:28:28 +01:00
Thomas Göttgens
44a33ed463 add IO7 to RAK pinouts - only comments changed 2022-12-21 13:28:28 +01:00
Thomas Göttgens
fab08b6451 fix building for screenless devices 2022-12-21 13:28:28 +01:00
Thomas Göttgens
d9cd3dd3e1 Change Boot Message format 2022-12-21 13:28:25 +01:00
Thomas Göttgens
c75ea87f6b Format received message screen like sender in canned messages. 2022-12-21 13:28:25 +01:00
Thomas Göttgens
706ddf6e95 show appropriate message when going into OTA mode 2022-12-21 13:28:25 +01:00
Thomas Göttgens
aec091e7aa manual master merge
# Conflicts:
#	src/Power.cpp
2022-12-21 13:28:25 +01:00
Thomas Göttgens
cea8393a7f Merge pull request #2026 from GUVWAF/develop
TraceRouteModule
2022-12-21 13:27:12 +01:00
Thomas Göttgens
8f94463eac send a 4 byte magic header including the codec version 2022-12-21 13:27:00 +01:00
Thomas Göttgens
a0f5e44967 Audio Module is finished for regression tests. 2022-12-21 13:27:00 +01:00
Thomas Göttgens
feb7181767 debug print thread count. max_threads is 32 2022-12-21 13:27:00 +01:00
Thomas Göttgens
a0c1e9cdc6 Still WIP, but first working version of audio. I2S works good, analogue not so much. 2022-12-21 13:27:00 +01:00
Thomas Göttgens
7d1b6f63b5 Definition cleanup and AudioModule WIP 2022-12-21 13:27:00 +01:00
Thomas Göttgens
ab6b6514cb this define is arch specific 2022-12-21 13:26:59 +01:00
Thomas Göttgens
0e6285edf2 add temp code for heap debugging. Disable -DDEBUG_HEAP for release builds.
DEBUG_MSG output only for now.
2022-12-21 13:26:59 +01:00
Thomas Göttgens
8b58eaac20 fix compile
# Conflicts:
#	protobufs
2022-12-21 13:26:59 +01:00
Thomas Göttgens
8cbf292373 WIP: add digital audio. Needs a proto change, so checking in generated files for now.
# Conflicts:
#	src/mesh/generated/localonly.pb.h
#	src/mesh/generated/module_config.pb.h
2022-12-21 13:26:44 +01:00
Thomas Göttgens
80d0b63c3a hopefully fix compilation errors 2022-12-21 13:26:13 +01:00
Thomas Göttgens
f5120a29ec WIP: audio module still does not work, but enabled for all regions where audio is permitted.
# Conflicts:
#	variants/tlora_v2_1_18/platformio.ini
2022-12-21 13:26:13 +01:00
Thomas Göttgens
efc3f4c0ee remove a few DSR Router bits for S&F Module 2022-12-21 13:25:12 +01:00
Thomas Göttgens
bd2bfd6822 update board definition, update copy/paste errors, fix SX1280. 2022-12-21 13:25:12 +01:00
Thomas Göttgens
e40625d2ad fix protobufs 2022-12-21 13:10:45 +01:00
Thomas Göttgens
eae347ddac visual indicator for S&F Plugin 'Router on Network'. 2022-12-21 13:00:15 +01:00
Thomas Göttgens
ae2ca1d89c WIP: S&F Progress 2022-12-21 12:57:42 +01:00
Thomas Göttgens
34c73da886 update to nanopb 0.4.7 2022-12-21 12:55:12 +01:00
Thomas Göttgens
88c3ab2636 Merge pull request #2050 from lesykm/serial-module-simple-mode-fix
[modules][serial] fix simple module ability to send
2022-12-21 12:43:13 +01:00
Thomas Göttgens
6a5dd26907 need to trigger new CI run 2022-12-21 12:24:38 +01:00
Mykhailo Lesyk
4de557b4db [modules][serial] fix simple module ability to send 2022-12-21 01:35:19 -08:00
Thomas Göttgens
d9eb9758e2 add bold print to canned messages freetext 2022-12-18 14:47:28 +01:00
Thomas Göttgens
d566457f0c Merge remote-tracking branch 'remotes/origin/master' into develop 2022-12-18 14:07:20 +01:00
Thomas Göttgens
79ff0659c0 Merge pull request #2019 from code8buster/gps-toggle-final
Adds a flag to turn the GPS power rail off entirely on tbeam
2022-12-17 23:32:20 +01:00
Thomas Göttgens
af9d4328eb Merge pull request #2046 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-17 18:42:25 +01:00
caveman99
8c66940b78 [create-pull-request] automated change 2022-12-17 17:41:39 +00:00
Thomas Göttgens
c577e09183 Merge branch 'develop' into gps-toggle-final 2022-12-16 20:58:53 +01:00
Thomas Göttgens
4a6f269b4b Merge pull request #2010 from meshtastic/store-forward
start rearranging the S&F Module
2022-12-16 20:54:02 +01:00
Thomas Göttgens
bbaeeb7ce9 fixing portduino is getting old ... 2022-12-16 20:46:43 +01:00
Thomas Göttgens
54686905dc remove duplicate block of predefined messages 2022-12-16 20:33:09 +01:00
Thomas Göttgens
3cde75f97b Audio Module: format messages better 2022-12-16 20:30:54 +01:00
Thomas Göttgens
6c84b3f01c forgot variable define for heap debug 2022-12-16 20:28:50 +01:00
Thomas Göttgens
68f6cfde0c Improve Wifi Reconnect handling and add outgoing queue for MQTT packets to bridge short connection issues. 2022-12-16 20:28:28 +01:00
Thomas Göttgens
1c8181dc75 fix compiler warnings 2022-12-16 20:26:22 +01:00
Thomas Göttgens
270746e303 Heap Debug: only show if delta occurs 2022-12-16 20:25:51 +01:00
Thomas Göttgens
72f1416b30 add variant comment about radiolib 2022-12-16 20:21:56 +01:00
code8buster
a788f16e91 Potentially stop bad things happening on devices without a PMU 2022-12-15 12:02:04 -05:00
code8buster
f2229e6977 Decrease click time window to avoid spurious double press detections while cycling windows quickly, build power toggle by default 2022-12-15 11:08:37 -05:00
Thomas Göttgens
05f81922e6 Merge pull request #2040 from D4rk4/master
Disable deep sleep for nRF  and force shutdown for RAK463x on discharged battery
2022-12-15 11:21:26 +01:00
code8buster
06be74ae7c Added indicative text to screen for disabled GPS, made sleep methods private again 2022-12-14 19:58:15 -05:00
Dmitry Galenko
72504a5e8b Merge branch 'master' into master 2022-12-14 20:27:20 +01:00
Thomas Göttgens
e8c034e988 Merge pull request #2041 from markbirss/master
Fix power enable pin used for e-Ink
2022-12-14 17:39:13 +01:00
Dmitry Galenko
aa19718ba4 Change condition for low-voltage killswitch 2022-12-14 17:26:55 +01:00
Mark Trevor Birss
088ab106dd Update variant.h 2022-12-14 17:57:02 +02:00
Mark Trevor Birss
110c3f619a Update variant.h 2022-12-14 17:56:44 +02:00
Dmitry Galenko
d1cc503ca8 Disable shutdown for non ESP32 boards 2022-12-14 14:36:15 +01:00
Thomas Göttgens
eae7f8a786 fix building DIY-1 target 2022-12-14 14:33:59 +01:00
Thomas Göttgens
bb24b86018 support ESP32-S2 CPUs
Note: these don't have Bluetooth and only a single physical core.
2022-12-14 13:32:26 +01:00
Thomas Göttgens
d3b3a4c148 fix build error 2022-12-14 10:29:45 +01:00
Dmitry Galenko
46f1cee2a8 Fix missed braces and etc 2022-12-14 10:21:11 +01:00
Dmitry Galenko
0386af721d Merge branch 'meshtastic:master' into master 2022-12-14 09:45:35 +01:00
Thomas Göttgens
de6b752db8 Merge pull request #2039 from ghostop14/master
Enable GPS capabilities on heltec V3
2022-12-14 09:38:06 +01:00
Dmitry Galenko
92fd5511ec Disable nRF sleep on discharge 2022-12-14 09:36:25 +01:00
code8buster
8507125e98 Remove extraneous flag, use gps_enabled. Ensure factory reset is not triggered while chip is off and gps_enabled=0 2022-12-13 17:23:58 -05:00
ghostop14
59ec7f31ab Enable GPS capabilities on heltec V3 2022-12-13 12:31:39 -05:00
Thomas Göttgens
627b21f3f2 made a nice PTT/RECV screen for audio module. And cleaned up screen graphics a bit. 2022-12-13 17:31:01 +01:00
Thomas Göttgens
64cc6e0b91 change on screen graphics to support bicolor screens 2022-12-13 12:33:51 +01:00
Ben Meadors
779d2352bd Merge pull request #2037 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-12 16:29:39 -06:00
thebentern
0162db12b8 [create-pull-request] automated change 2022-12-12 19:23:34 +00:00
Ben Meadors
91ff7b9032 Merge pull request #2036 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-12 12:18:06 -06:00
thebentern
643f99f577 [create-pull-request] automated change 2022-12-12 18:06:11 +00:00
Ben Meadors
152288b4cc Merge pull request #2025 from meshtastic/power-fsm-experiment
Power FSM experiment
2022-12-12 12:01:00 -06:00
Ben Meadors
45b518baf2 Move sds transition back into esp32 only 2022-12-12 10:24:51 -06:00
Thomas Göttgens
24cc479f95 if we get different frames than our own transmission setup, decode and play them anyway 2022-12-11 23:12:00 +01:00
Thomas Göttgens
5fbc630061 add IO7 to RAK pinouts - only comments changed 2022-12-11 21:17:46 +01:00
Ben Meadors
0c65c73f90 Merge branch 'master' into power-fsm-experiment 2022-12-09 19:50:26 -06:00
Thomas Göttgens
95eca75336 fix building for screenless devices 2022-12-09 11:27:12 +01:00
Thomas Göttgens
0f0dbc3274 reboot nrf52 on critical error 8 2022-12-09 11:18:43 +01:00
Thomas Göttgens
edb674759f fixes critical error 8 does not reboot on nrf52 2022-12-09 11:15:49 +01:00
Thomas Göttgens
e3d8c5c7a6 Change Boot Message format 2022-12-08 21:48:01 +01:00
Thomas Göttgens
f3d6f26a28 Format received message screen like sender in canned messages. 2022-12-08 17:34:14 +01:00
Thomas Göttgens
1a0d51495d show appropriate message when going into OTA mode 2022-12-08 17:17:48 +01:00
Thomas Göttgens
32d9a397aa Toggle up to 3 pins after output_ms till nag_timeout or user button press happens 2022-12-08 16:27:56 +01:00
Thomas Göttgens
60e6dc1134 update protobufs manually 2022-12-08 10:43:18 +01:00
Thomas Göttgens
06d34daeab Merge branch 'master' into power-fsm-experiment 2022-12-08 10:18:01 +01:00
Thomas Göttgens
a00187b97f manual master merge 2022-12-06 16:56:38 +01:00
Thomas Göttgens
ba1f68d758 Merge pull request #2027 from lewisxhe/master
Fix the charging parmas error of tbeam-s3core and change the default USB mode
2022-12-06 16:39:38 +01:00
Thomas Göttgens
d4c0977a70 Merge branch 'master' into master 2022-12-06 15:49:32 +01:00
Thomas Göttgens
1a19d71e95 Merge pull request #2023 from meshtastic/2022-bug-recording-critical-error-11-at-srcmeshradiolibinterfacecpp389
Add debug output
2022-12-06 15:48:57 +01:00
Thomas Göttgens
21c10934fc Merge pull request #2018 from arduionoGP/patch-3
Update MQTT.cpp
2022-12-06 15:47:30 +01:00
Thomas Göttgens
13cca91097 Merge branch 'master' into patch-3 2022-12-06 14:09:29 +01:00
Thomas Göttgens
b335b1c66b Merge branch 'master' into 2022-bug-recording-critical-error-11-at-srcmeshradiolibinterfacecpp389 2022-12-06 14:08:48 +01:00
Thomas Göttgens
a42a9bf4fe Merge pull request #2026 from GUVWAF/develop
TraceRouteModule
2022-12-06 14:08:04 +01:00
Thomas Göttgens
cc2653bfb5 Merge pull request #2029 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-12-06 14:05:51 +01:00
caveman99
fc5bf5a68f [create-pull-request] automated change 2022-12-06 13:03:26 +00:00
Thomas Göttgens
0f7e6b8964 update submodule protobufs to latest 2022-12-06 13:55:43 +01:00
lewishe
63d7338311 fix tbeams3-core PMU charging cut-off voltage 2022-12-06 11:01:14 +08:00
lewishe
37f716d27b Change tbeams3-core the default USB mode to TinyUSB 2022-12-06 10:58:59 +08:00
GUVWAF
03bfdec1e1 TraceRouteModule 2022-12-05 20:38:06 +01:00
Ben Meadors
0f2a835359 Remove hard coded !isPowered 2022-12-05 10:13:19 -06:00
Thomas Göttgens
2a84d39e40 Always do battery resampling if we use the ADC. Improves reading a lot. 2022-12-05 16:40:23 +01:00
Ben Meadors
b14289e976 More cleanup 2022-12-05 08:35:54 -06:00
Ben Meadors
1fef6f0656 Clean up on battery shutdown condition 2022-12-05 07:37:01 -06:00
Thomas Göttgens
183ec2124f Add debug output 2022-12-05 11:48:46 +01:00
Ben Meadors
aeb9bfa063 Return false 2022-12-04 20:41:00 -06:00
arduinoGP
b84c7ae49b Oops, added time to the Pos 2022-12-04 19:41:58 -05:00
Thomas Göttgens
61598c5942 Merge pull request #2020 from meshtastic/serial-textmessage
Serial textmessage mode
2022-12-04 23:53:29 +01:00
Ben Meadors
a3a24e0216 Don't put newlines in the text buffer 2022-12-04 16:03:57 -06:00
Ben Meadors
31ec2da0e9 Text message mode for serial 2022-12-04 15:40:28 -06:00
code8buster
53da7cb036 Add initialized value to constructor 2022-12-04 02:38:14 -05:00
code8buster
911083c49d Adds a flag to turn the GPS power rail off entirely on tbeam 2022-12-04 01:57:00 -05:00
arduinoGP
27a10b395f Update MQTT.cpp
(First real try at writing meaningful C++ but it seems to work.)
Allows sending JSON Position data from MQTT broker for broadcast to a LORA mesh via gateway device.
The new type is "sendposition". Valid envelope looks like:
{
    "sender": "someSender",
    "type": "sendposition",
    "payload": {
        "latitude_i": 399600000,
        "longitude_i": -862600000,
        "altitude": 100
    }
}
This complements the "sendtext" type envelope.
2022-12-04 00:00:43 -05:00
Ben Meadors
b1f3e117d1 Merge pull request #2015 from meshtastic/master
Fix shell scripts for both linux and darwin
2022-12-03 08:25:29 -06:00
Ben Meadors
7570cdbd22 Fix shell scripts for both linux and darwin 2022-12-03 08:24:11 -06:00
Thomas Göttgens
28ff2efdef Merge branch 'develop' of github.com:meshtastic/firmware into develop 2022-12-02 13:44:47 +01:00
Thomas Göttgens
bb1a9192eb send a 4 byte magic header including the codec version 2022-12-02 13:44:36 +01:00
Ben Meadors
1787e2c775 Merge pull request #2014 from meshtastic/master
Downstream
2022-12-02 06:38:41 -06:00
Thomas Göttgens
470e711383 Audio Module is finished for regression tests. 2022-12-02 12:58:26 +01:00
Thomas Göttgens
eb4f682ad1 debug print thread count. max_threads is 32 2022-12-02 12:20:21 +01:00
Thomas Göttgens
4b63730efb Still WIP, but first working version of audio. I2S works good, analogue not so much. 2022-12-02 00:30:31 +01:00
Thomas Göttgens
c857474116 Merge pull request #2013 from arduionoGP/patch-2
Update MQTT.cpp
2022-12-01 22:17:35 +01:00
arduinoGP
8ff5dacc3c Update MQTT.cpp
case Portnum_POSITION_APP adjusted so the various options allways get encoded into JSON as long as lat and long are present. There are circumstances where timestamp, time, or altitude might be missing and this causes silent failures of JSON encoding..
2022-12-01 15:44:47 -05:00
Thomas Göttgens
fb89828990 Definition cleanup and AudioModule WIP 2022-12-01 17:47:04 +01:00
Thomas Göttgens
c7529f9a3e fix platform define here too 2022-11-30 10:23:54 +01:00
Thomas Göttgens
dbefa71bc8 this define is arch specific 2022-11-30 10:04:54 +01:00
Thomas Göttgens
7907404028 start rearranging the S&F Module 2022-11-30 09:57:10 +01:00
Thomas Göttgens
72e17b558c add temp code for heap debugging. Disable -DDEBUG_HEAP for release builds.
DEBUG_MSG output only for now.
2022-11-30 09:52:28 +01:00
Thomas Göttgens
628028475c fix compile 2022-11-29 17:45:57 +01:00
Thomas Göttgens
05e992ad67 WIP: add digital audio. Needs a proto change, so checking in generated files for now. 2022-11-29 17:19:10 +01:00
Thomas Göttgens
bba6bf387e hopefully fix compilation errors 2022-11-29 14:35:46 +01:00
Thomas Göttgens
4d32f7c5ad WIP: audio module still does not work, but enabled for all regions where audio is permitted. 2022-11-29 11:22:18 +01:00
Thomas Göttgens
0dff05e881 Merge pull request #1998 from GUVWAF/dutyCycleLimit
Completely refrain from transmitting if duty cycle limit exceeded
2022-11-29 11:06:31 +01:00
Thomas Göttgens
f3c5a01daf remove a few DSR Router bits for S&F Module 2022-11-28 21:58:30 +01:00
GUVWAF
7ca104cef6 Override duty cycle if user is_licensed 2022-11-27 16:53:02 +01:00
Thomas Göttgens
fe95247d56 Merge pull request #2002 from meshtastic/master
Start new develop cycle
2022-11-27 15:05:27 +01:00
Ben Meadors
f1179d31ba Fixed shell scripts 2022-11-27 07:40:40 -06:00
Thomas Göttgens
c7681cb24d update board definition, update copy/paste errors, fix SX1280. 2022-11-27 14:03:50 +01:00
Ben Meadors
abe60b96f1 Merge pull request #2001 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-27 06:11:39 -06:00
thebentern
206520f179 [create-pull-request] automated change 2022-11-27 02:16:21 +00:00
GUVWAF
330ac3be68 Update generated protobufs 2022-11-26 21:07:36 +01:00
GUVWAF
3b1e34efa1 Refrain from transmitting if duty cycle exceeded 2022-11-26 21:05:37 +01:00
394 changed files with 14164 additions and 11933 deletions

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
* text=auto eol=lf
*.{cmd,[cC][mM][dD]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf
*.{sh,[sS][hH]} text eol=lf

View File

@@ -1,5 +1,5 @@
name: 'Setup Build Base Composite Action' name: "Setup Build Base Composite Action"
description: 'Base build actions for Meshtastic Platform IO steps' description: "Base build actions for Meshtastic Platform IO steps"
runs: runs:
using: "composite" using: "composite"

View File

@@ -29,6 +29,13 @@ jobs:
tar -xf build.tar -C data/static tar -xf build.tar -C data/static
rm build.tar rm build.tar
- name: Remove debug flags for release
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
- name: Build ESP32 - name: Build ESP32
run: bin/build-esp32.sh ${{ inputs.board }} run: bin/build-esp32.sh ${{ inputs.board }}

View File

@@ -32,6 +32,7 @@ jobs:
- board: station-g1 - board: station-g1
- board: m5stack-coreink - board: m5stack-coreink
- board: tbeam-s3-core - board: tbeam-s3-core
- board: tlora-t3s3-v1
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -40,6 +41,9 @@ jobs:
id: base id: base
uses: ./.github/actions/setup-base uses: ./.github/actions/setup-base
- name: Trunk Check
uses: trunk-io/trunk-action@v1
- name: Check ${{ matrix.board }} - name: Check ${{ matrix.board }}
run: bin/check-all.sh ${{ matrix.board }} run: bin/check-all.sh ${{ matrix.board }}
@@ -53,6 +57,7 @@ jobs:
- board: tlora-v1 - board: tlora-v1
- board: tlora_v1_3 - board: tlora_v1_3
- board: tlora-v2-1-1.6 - board: tlora-v2-1-1.6
- board: tlora-v2-1-1.8
- board: tbeam - board: tbeam
- board: heltec-v1 - board: heltec-v1
- board: heltec-v2.0 - board: heltec-v2.0
@@ -67,6 +72,7 @@ jobs:
- board: m5stack-core - board: m5stack-core
- board: m5stack-coreink - board: m5stack-coreink
- board: tbeam-s3-core - board: tbeam-s3-core
- board: tlora-t3s3-v1
uses: ./.github/workflows/build_esp32.yml uses: ./.github/workflows/build_esp32.yml
with: with:
board: ${{ matrix.board }} board: ${{ matrix.board }}
@@ -106,14 +112,14 @@ jobs:
uses: ./.github/actions/setup-base uses: ./.github/actions/setup-base
# We now run integration test before other build steps (to quickly see runtime failures) # We now run integration test before other build steps (to quickly see runtime failures)
- name: Build for native #- name: Build for native
run: platformio run -e native # run: platformio run -e native
- name: Integration test #- name: Integration test
run: | # run: |
.pio/build/native/program & #.pio/build/native/program
sleep 20 # 5 seconds was not enough #& sleep 20 # 5 seconds was not enough
echo "Simulator started, launching python test..." #echo "Simulator started, launching python test..."
python3 -c 'from meshtastic.test import testSimulator; testSimulator()' #python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
- name: Build Native - name: Build Native
run: bin/build-native.sh run: bin/build-native.sh
@@ -131,19 +137,26 @@ jobs:
release/device-*.bat release/device-*.bat
- name: Docker login - name: Docker login
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: docker/login-action@v2 uses: docker/login-action@v2
with: with:
username: meshtastic username: meshtastic
password: ${{ secrets.DOCKER_TOKEN }} password: ${{ secrets.DOCKER_TOKEN }}
- name: Docker setup - name: Docker setup
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: Docker build and push - name: Docker build and push tagged versions
if: ${{ github.event_name == 'workflow_dispatch' }} if: ${{ github.event_name == 'workflow_dispatch' }}
uses: docker/build-push-action@v3 uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile
push: true
tags: meshtastic/device-simulator:${{ steps.version.outputs.version }}
- name: Docker build and push
if: github.ref == 'refs/heads/master'
uses: docker/build-push-action@v3
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile

19
.github/workflows/nightly.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: Nightly
on:
schedule:
- cron: 0 8 * * 1-5
workflow_dispatch: {}
jobs:
trunk_check:
name: Trunk Check Upload
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Trunk Check
uses: trunk-io/trunk-action@v1
with:
trunk-token: ${{ secrets.TRUNK_TOKEN }}

View File

@@ -22,8 +22,8 @@ jobs:
- name: flawfinder_scan - name: flawfinder_scan
uses: david-a-wheeler/flawfinder@2.0.19 uses: david-a-wheeler/flawfinder@2.0.19
with: with:
arguments: '--sarif ./' arguments: "--sarif ./"
output: 'flawfinder_report.sarif' output: "flawfinder_report.sarif"
# step 3 # step 3
- name: save report as pipeline artifact - name: save report as pipeline artifact

View File

@@ -6,17 +6,15 @@ on:
branches: branches:
- master - master
schedule: schedule:
- cron: '0 1 * * 6' - cron: "0 1 * * 6"
jobs: jobs:
semgrep-full: semgrep-full:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: returntocorp/semgrep image: returntocorp/semgrep
steps: steps:
# step 1 # step 1
- name: clone application source code - name: clone application source code
uses: actions/checkout@v3 uses: actions/checkout@v3

View File

@@ -1,17 +1,14 @@
--- ---
name: Semgrep Differential Scan name: Semgrep Differential Scan
on: on: pull_request
pull_request
jobs: jobs:
semgrep-diff: semgrep-diff:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: returntocorp/semgrep image: returntocorp/semgrep
steps: steps:
# step 1 # step 1
- name: clone application source code - name: clone application source code
uses: actions/checkout@v3 uses: actions/checkout@v3

View File

@@ -17,9 +17,9 @@ jobs:
- name: Download nanopb - name: Download nanopb
run: | run: |
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.7-linux-x86.tar.gz
tar xvzf nanopb-0.4.6-linux-x86.tar.gz tar xvzf nanopb-0.4.7-linux-x86.tar.gz
mv nanopb-0.4.6-linux-x86 nanopb-0.4.6 mv nanopb-0.4.7-linux-x86 nanopb-0.4.7
- name: Re-generate protocol buffers - name: Re-generate protocol buffers
run: | run: |

1
.gitignore vendored
View File

@@ -29,3 +29,4 @@ __pycache__
venv/ venv/
release/ release/
.vscode/extensions.json

7
.trunk/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
*out
*logs
*actions
*notifications
plugins
user_trunk.yaml
user.yaml

View File

@@ -0,0 +1,4 @@
# Following source doesn't work in most setups
ignored:
- SC1090
- SC1091

View File

@@ -0,0 +1,10 @@
# Autoformatter friendly markdownlint config (all formatting rules disabled)
default: true
blank_lines: false
bullet: false
html: false
indentation: false
line_length: false
spaces: false
url: false
whitespace: false

View File

@@ -0,0 +1,7 @@
enable=all
source-path=SCRIPTDIR
disable=SC2154
# If you're having issues with shellcheck following source, disable the errors via:
# disable=SC1090
# disable=SC1091

View File

@@ -0,0 +1,14 @@
module.exports = {
plugins: [
{
name: "preset-default",
params: {
overrides: {
removeViewBox: false, // https://github.com/svg/svgo/issues/1128
sortAttrs: true,
removeOffCanvasPaths: true,
},
},
},
],
};

33
.trunk/trunk.yaml Normal file
View File

@@ -0,0 +1,33 @@
version: 0.1
cli:
version: 1.3.1
plugins:
sources:
- id: trunk
ref: v0.0.8
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- git-diff-check
- gitleaks@8.15.2
- clang-format@14.0.0
- prettier@2.8.3
disabled:
- shellcheck@0.9.0
- shfmt@3.5.0
- oxipng@8.0.0
- actionlint@1.6.22
- markdownlint@0.33.0
- hadolint@2.12.0
- svgo@3.0.2
runtimes:
enabled:
- go@1.18.3
- node@18.12.1
actions:
disabled:
- trunk-announce
- trunk-check-pre-push
- trunk-fmt-pre-commit
enabled:
- trunk-upgrade-available

View File

@@ -2,10 +2,8 @@
// See http://go.microsoft.com/fwlink/?LinkId=827846 // See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format // for the documentation about the extensions.json format
"recommendations": [ "recommendations": [
"ms-vscode.cpptools",
"platformio.platformio-ide", "platformio.platformio-ide",
"xaver.clang-format" "trunk.io"
], ],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
} }

80
.vscode/settings.json vendored
View File

@@ -1,80 +1,4 @@
{ {
"files.associations": { "editor.formatOnSave": true,
"type_traits": "cpp", "editor.defaultFormatter": "trunk.io"
"array": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"memory": "cpp",
"new": "cpp",
"ostream": "cpp",
"numeric": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"utility": "cpp",
"typeinfo": "cpp",
"string": "cpp",
"*.xbm": "cpp",
"list": "cpp",
"atomic": "cpp",
"memory_resource": "cpp",
"optional": "cpp",
"string_view": "cpp",
"cassert": "cpp",
"iterator": "cpp",
"shared_mutex": "cpp",
"iostream": "cpp",
"esp_nimble_hci.h": "c",
"map": "cpp",
"random": "cpp",
"*.tpp": "cpp"
},
"cSpell.words": [
"Blox",
"EINK",
"HFSR",
"Meshtastic",
"NEMAGPS",
"NMEAGPS",
"RDEF",
"Ublox",
"bkpt",
"cfsr",
"descs",
"ocrypto",
"protobufs",
"wifi"
],
"C_Cpp.dimInactiveRegions": true,
"cmake.configureOnOpen": true,
"protoc": {
"compile_on_save": false,
}
} }

4
.vscode/tasks.json vendored
View File

@@ -4,9 +4,7 @@
{ {
"type": "PlatformIO", "type": "PlatformIO",
"task": "Build", "task": "Build",
"problemMatcher": [ "problemMatcher": ["$platformio"],
"$platformio"
],
"group": { "group": {
"kind": "build", "kind": "build",
"isDefault": true "isDefault": true

View File

@@ -1,7 +1,7 @@
# Meshtastic Firmware # Meshtastic Firmware
![GitHub release downloads](https://img.shields.io/github/downloads/meshtastic/firmware/total) ![GitHub release downloads](https://img.shields.io/github/downloads/meshtastic/firmware/total)
[![CI](https://img.shields.io/github/workflow/status/meshtastic/firmware/CI?label=actions&logo=github&color=yellow)](https://github.com/meshtastic/firmware/actions/workflows/main_matrix.yml) [![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/firmware/main_matrix.yml?branch=master&label=actions&logo=github&color=yellow)](https://github.com/meshtastic/firmware/actions/workflows/ci.yml)
[![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/firmware)](https://cla-assistant.io/meshtastic/firmware) [![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/firmware)](https://cla-assistant.io/meshtastic/firmware)
[![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/) [![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/)
[![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss) [![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)

View File

@@ -26,6 +26,7 @@ build_flags =
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2 -DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING -DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
-DDEBUG_HEAP
lib_deps = lib_deps =
${arduino_base.lib_deps} ${arduino_base.lib_deps}
@@ -34,6 +35,7 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0 h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1
lib_ignore = lib_ignore =
segger_rtt segger_rtt

47
arch/esp32/esp32s2.ini Normal file
View File

@@ -0,0 +1,47 @@
[esp32s2_base]
extends = arduino_base
platform = platformio/espressif32@^5.2.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<nimble/>
upload_speed = 961200
monitor_speed = 115200
debug_init_break = tbreak setup
monitor_filters = esp32_exception_decoder
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_flags =
${arduino_base.build_flags}
-Wall
-Wextra
-Isrc/platform/esp32
-std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
-DAXP_DEBUG_PORT=Serial
-DCONFIG_BT_NIMBLE_ENABLED
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
-DHAS_BLUETOOTH=0
-DDEBUG_HEAP
lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1
lib_ignore =
segger_rtt
ESP32 BLE Arduino
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
board_build.partitions = partition-table.csv

View File

@@ -26,6 +26,7 @@ build_flags =
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2 -DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING -DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
-DDEBUG_HEAP
lib_deps = lib_deps =
${arduino_base.lib_deps} ${arduino_base.lib_deps}
@@ -34,6 +35,7 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0 h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1
lib_ignore = lib_ignore =
segger_rtt segger_rtt

View File

@@ -8,7 +8,7 @@ build_flags =
${arduino_base.build_flags} -Wno-unused-variable ${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/nrf52 -Isrc/platform/nrf52
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040> -<mesh/eth/> ${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040> -<mesh/eth/>
lib_ignore = lib_ignore =
BluetoothOTA BluetoothOTA

View File

@@ -1,6 +1,8 @@
; Common settings for rp2040 Processor based targets ; Common settings for rp2040 Processor based targets
[rp2040_base] [rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#5ce1a228e7cae453f366deb8962252b9b7356bbc platform = https://github.com/maxgerhardt/platform-raspberrypi.git#20c7dbfcfe6677c5305fa28ecf5e3870321cb157
platform_packages =
earlephilhower/toolchain-rp2040-earlephilhower@^5.100300.221223
extends = arduino_base extends = arduino_base
board_build.core = earlephilhower board_build.core = earlephilhower
board_build.filesystem_size = 0.5m board_build.filesystem_size = 0.5m
@@ -10,7 +12,7 @@ build_flags =
-D__PLAT_RP2040__ -D__PLAT_RP2040__
# -D _POSIX_THREADS # -D _POSIX_THREADS
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> ${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
lib_ignore = lib_ignore =
BluetoothOTA BluetoothOTA
lib_deps = lib_deps =

View File

@@ -10,7 +10,7 @@ build_flags =
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support # Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK # -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> ${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b

View File

@@ -45,7 +45,7 @@ shift "$((OPTIND-1))"
shift shift
} }
if [ -f "${FILENAME}" ] && [[ "${FILENAME}" != *"update"* ]]; then if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
echo "Trying to flash ${FILENAME}, but first erasing and writing system information" echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
"$PYTHON" -m esptool erase_flash "$PYTHON" -m esptool erase_flash
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME} "$PYTHON" -m esptool write_flash 0x00 ${FILENAME}

View File

@@ -43,7 +43,7 @@ shift "$((OPTIND-1))"
shift shift
} }
if [ -f "${FILENAME}" ] && [[ $FILENAME == *"update"* ]]; then if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
printf "Trying to flash update ${FILENAME}" printf "Trying to flash update ${FILENAME}"
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME} $PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
else else

View File

@@ -1 +1,5 @@
cd protobufs && ..\nanopb-0.4.6\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs *.proto cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto
@REM cd ../src/mesh/generated/meshtastic
@REM sed -i 's/#include "meshtastic/#include "./g' *
@REM sed -i 's/meshtastic_//g' *

View File

@@ -2,13 +2,18 @@
set -e set -e
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.6 to be located in the" echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.7 to be located in the"
echo "firmware root directory if the following step fails, you should download the correct" echo "firmware root directory if the following step fails, you should download the correct"
echo "prebuilt binaries for your computer into nanopb-0.4.6" echo "prebuilt binaries for your computer into nanopb-0.4.7"
# the nanopb tool seems to require that the .options file be in the current directory! # the nanopb tool seems to require that the .options file be in the current directory!
cd protobufs cd protobufs
../nanopb-0.4.6/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../protobufs *.proto ../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated/ -I=../protobufs meshtastic/*.proto
# 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 "Regenerating protobuf documentation - if you see an error message"
#echo "you can ignore it unless doing a new protobuf release to github." #echo "you can ignore it unless doing a new protobuf release to github."

View File

@@ -7,12 +7,7 @@
"cpu": "cortex-m4", "cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA", "extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA",
"f_cpu": "64000000L", "f_cpu": "64000000L",
"hwids": [ "hwids": [["0x239A", "0x4405"]],
[
"0x239A",
"0x4405"
]
],
"usb_product": "TTGO_eink", "usb_product": "TTGO_eink",
"mcu": "nrf52840", "mcu": "nrf52840",
"variant": "eink0.1", "variant": "eink0.1",
@@ -30,19 +25,13 @@
"settings_addr": "0xFF000" "settings_addr": "0xFF000"
} }
}, },
"connectivity": [ "connectivity": ["bluetooth"],
"bluetooth"
],
"debug": { "debug": {
"jlink_device": "nRF52840_xxAA", "jlink_device": "nRF52840_xxAA",
"onboard_tools": [ "onboard_tools": ["jlink"],
"jlink"
],
"svd_path": "nrf52840.svd" "svd_path": "nrf52840.svd"
}, },
"frameworks": [ "frameworks": ["arduino"],
"arduino"
],
"name": "TTGO eink (Adafruit BSP)", "name": "TTGO eink (Adafruit BSP)",
"upload": { "upload": {
"maximum_ram_size": 248832, "maximum_ram_size": 248832,
@@ -50,11 +39,7 @@
"require_upload_port": true, "require_upload_port": true,
"speed": 115200, "speed": 115200,
"protocol": "jlink", "protocol": "jlink",
"protocols": [ "protocols": ["jlink", "nrfjprog", "stlink"]
"jlink",
"nrfjprog",
"stlink"
]
}, },
"url": "FIXME", "url": "FIXME",
"vendor": "TTGO" "vendor": "TTGO"

View File

@@ -9,9 +9,7 @@
"product_line": "STM32WLE5xx" "product_line": "STM32WLE5xx"
}, },
"debug": { "debug": {
"default_tools": [ "default_tools": ["stlink"],
"stlink"
],
"jlink_device": "STM32WLE5CC", "jlink_device": "STM32WLE5CC",
"openocd_target": "stm32wlx", "openocd_target": "stm32wlx",
"svd_path": "STM32WLE5_CM4.svd" "svd_path": "STM32WLE5_CM4.svd"
@@ -22,9 +20,7 @@
"maximum_ram_size": 65536, "maximum_ram_size": 65536,
"maximum_size": 262144, "maximum_size": 262144,
"protocol": "cmsis-dap", "protocol": "cmsis-dap",
"protocols": [ "protocols": ["cmsis-dap"]
"cmsis-dap"
]
}, },
"url": "https://www.st.com/en/microcontrollers-microprocessors/stm32wl-series.html", "url": "https://www.st.com/en/microcontrollers-microprocessors/stm32wl-series.html",
"vendor": "ST" "vendor": "ST"

View File

@@ -19,16 +19,12 @@
"sd_fwid": "0x00B7" "sd_fwid": "0x00B7"
} }
}, },
"connectivity": [ "connectivity": ["bluetooth"],
"bluetooth"
],
"debug": { "debug": {
"jlink_device": "nRF52832_xxAA", "jlink_device": "nRF52832_xxAA",
"svd_path": "nrf52.svd" "svd_path": "nrf52.svd"
}, },
"frameworks": [ "frameworks": ["arduino"],
"arduino"
],
"name": "lora ISP4520", "name": "lora ISP4520",
"upload": { "upload": {
"maximum_ram_size": 65536, "maximum_ram_size": 65536,
@@ -36,12 +32,7 @@
"require_upload_port": true, "require_upload_port": true,
"speed": 115200, "speed": 115200,
"protocol": "nrfutil", "protocol": "nrfutil",
"protocols": [ "protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"]
"jlink",
"nrfjprog",
"nrfutil",
"stlink"
]
}, },
"url": "", "url": "",
"vendor": "PsiSoft" "vendor": "PsiSoft"

View File

@@ -8,22 +8,10 @@
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA", "extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
"f_cpu": "64000000L", "f_cpu": "64000000L",
"hwids": [ "hwids": [
[ ["0x239A", "0x8029"],
"0x239A", ["0x239A", "0x0029"],
"0x8029" ["0x239A", "0x002A"],
], ["0x239A", "0x802A"]
[
"0x239A",
"0x0029"
],
[
"0x239A",
"0x002A"
],
[
"0x239A",
"0x802A"
]
], ],
"usb_product": "PCA10059", "usb_product": "PCA10059",
"mcu": "nrf52840", "mcu": "nrf52840",
@@ -41,28 +29,19 @@
"settings_addr": "0xFF000" "settings_addr": "0xFF000"
} }
}, },
"connectivity": [ "connectivity": ["bluetooth"],
"bluetooth"
],
"debug": { "debug": {
"jlink_device": "nRF52840_xxAA", "jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd" "svd_path": "nrf52840.svd"
}, },
"frameworks": [ "frameworks": ["arduino"],
"arduino"
],
"name": "nRF52840 Dongle", "name": "nRF52840 Dongle",
"upload": { "upload": {
"maximum_ram_size": 248832, "maximum_ram_size": 248832,
"maximum_size": 815104, "maximum_size": 815104,
"speed": 115200, "speed": 115200,
"protocol": "nrfutil", "protocol": "nrfutil",
"protocols": [ "protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"jlink",
"nrfjprog",
"nrfutil",
"stlink"
],
"use_1200bps_touch": true, "use_1200bps_touch": true,
"require_upload_port": true, "require_upload_port": true,
"wait_for_upload_port": true "wait_for_upload_port": true

View File

@@ -43,5 +43,4 @@
}, },
"url": "https://meshtastic.org/", "url": "https://meshtastic.org/",
"vendor": "Nordic Semi" "vendor": "Nordic Semi"
} }

View File

@@ -7,12 +7,7 @@
"cpu": "cortex-m4", "cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA", "extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA",
"f_cpu": "64000000L", "f_cpu": "64000000L",
"hwids": [ "hwids": [["0x239A", "0x4405"]],
[
"0x239A",
"0x4405"
]
],
"usb_product": "TTGO_eink", "usb_product": "TTGO_eink",
"mcu": "nrf52840", "mcu": "nrf52840",
"variant": "t-echo", "variant": "t-echo",
@@ -30,31 +25,20 @@
"settings_addr": "0xFF000" "settings_addr": "0xFF000"
} }
}, },
"connectivity": [ "connectivity": ["bluetooth"],
"bluetooth"
],
"debug": { "debug": {
"jlink_device": "nRF52840_xxAA", "jlink_device": "nRF52840_xxAA",
"onboard_tools": [ "onboard_tools": ["jlink"],
"jlink"
],
"svd_path": "nrf52840.svd" "svd_path": "nrf52840.svd"
}, },
"frameworks": [ "frameworks": ["arduino"],
"arduino"
],
"name": "TTGO eink (Adafruit BSP)", "name": "TTGO eink (Adafruit BSP)",
"upload": { "upload": {
"maximum_ram_size": 248832, "maximum_ram_size": 248832,
"maximum_size": 815104, "maximum_size": 815104,
"speed": 115200, "speed": 115200,
"protocol": "nrfutil", "protocol": "nrfutil",
"protocols": [ "protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"jlink",
"nrfjprog",
"nrfutil",
"stlink"
],
"use_1200bps_touch": true, "use_1200bps_touch": true,
"require_upload_port": true, "require_upload_port": true,
"wait_for_upload_port": true "wait_for_upload_port": true

View File

@@ -1,6 +1,6 @@
{ {
"build": { "build": {
"arduino":{ "arduino": {
"ldscript": "esp32s3_out.ld" "ldscript": "esp32s3_out.ld"
}, },
"core": "esp32", "core": "esp32",
@@ -8,33 +8,22 @@
"-DBOARD_HAS_PSRAM", "-DBOARD_HAS_PSRAM",
"-DLILYGO_TBEAM_S3_CORE", "-DLILYGO_TBEAM_S3_CORE",
"-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_DFU_ON_BOOT=1", "-DARDUINO_USB_MODE=0",
"-DARDUINO_USB_MSC_ON_BOOT=1",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1", "-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1" "-DARDUINO_EVENT_RUNNING_CORE=1"
], ],
"f_cpu": "240000000L", "f_cpu": "240000000L",
"f_flash": "80000000L", "f_flash": "80000000L",
"flash_mode": "dio", "flash_mode": "dio",
"hwids": [ "hwids": [["0X303A", "0x1001"]],
[
"0X303A",
"0x1001"
]
],
"mcu": "esp32s3", "mcu": "esp32s3",
"variant": "tbeam-s3-core" "variant": "tbeam-s3-core"
}, },
"connectivity": [ "connectivity": ["wifi"],
"wifi"
],
"debug": { "debug": {
"openocd_target": "esp32s3.cfg" "openocd_target": "esp32s3.cfg"
}, },
"frameworks": [ "frameworks": ["arduino"],
"arduino"
],
"name": "LilyGo TBeam-S3-Core", "name": "LilyGo TBeam-S3-Core",
"upload": { "upload": {
"flash_size": "8MB", "flash_size": "8MB",

37
boards/tlora-t3s3-v1.json Normal file
View File

@@ -0,0 +1,37 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld"
},
"core": "esp32",
"extra_flags": [
"-DLILYGO_T3S3_V1",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "dio",
"hwids": [["0X303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "tlora-t3s3-v1"
},
"connectivity": ["wifi"],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "LilyGo TLora-T3S3-V1",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 327680,
"maximum_size": 4194304,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},
"url": "http://www.lilygo.cn/",
"vendor": "LilyGo"
}

View File

@@ -1,6 +1,6 @@
{ {
"build": { "build": {
"arduino":{ "arduino": {
"ldscript": "esp32_out.ld" "ldscript": "esp32_out.ld"
}, },
"core": "esp32", "core": "esp32",
@@ -11,26 +11,14 @@
"mcu": "esp32", "mcu": "esp32",
"variant": "WisCore_RAK11200_Board" "variant": "WisCore_RAK11200_Board"
}, },
"connectivity": [ "connectivity": ["wifi", "bluetooth", "ethernet", "can"],
"wifi", "frameworks": ["arduino", "espidf"],
"bluetooth",
"ethernet",
"can"
],
"frameworks": [
"arduino",
"espidf"
],
"name": "WisCore RAK11200 Board", "name": "WisCore RAK11200 Board",
"upload": { "upload": {
"flash_size": "4MB", "flash_size": "4MB",
"maximum_ram_size": 327680, "maximum_ram_size": 327680,
"maximum_size": 4194304, "maximum_size": 4194304,
"protocols": [ "protocols": ["esptool", "espota", "ftdi"],
"esptool",
"espota",
"ftdi"
],
"require_upload_port": true, "require_upload_port": true,
"speed": 460800 "speed": 460800
}, },

View File

@@ -8,22 +8,10 @@
"extra_flags": "-DNRF52832_XXAA -DNRF52", "extra_flags": "-DNRF52832_XXAA -DNRF52",
"f_cpu": "64000000L", "f_cpu": "64000000L",
"hwids": [ "hwids": [
[ ["0x239A", "0x8029"],
"0x239A", ["0x239A", "0x0029"],
"0x8029" ["0x239A", "0x002A"],
], ["0x239A", "0x802A"]
[
"0x239A",
"0x0029"
],
[
"0x239A",
"0x002A"
],
[
"0x239A",
"0x802A"
]
], ],
"usb_product": "Feather nRF52832 Express", "usb_product": "Feather nRF52832 Express",
"mcu": "nrf52832", "mcu": "nrf52832",
@@ -41,17 +29,12 @@
"variant": "nrf52_adafruit_feather" "variant": "nrf52_adafruit_feather"
} }
}, },
"connectivity": [ "connectivity": ["bluetooth"],
"bluetooth"
],
"debug": { "debug": {
"jlink_device": "nRF52832_xxAA", "jlink_device": "nRF52832_xxAA",
"svd_path": "nrf52.svd" "svd_path": "nrf52.svd"
}, },
"frameworks": [ "frameworks": ["arduino", "zephyr"],
"arduino",
"zephyr"
],
"name": "Adafruit Bluefruit nRF52832 Feather", "name": "Adafruit Bluefruit nRF52832 Feather",
"upload": { "upload": {
"maximum_ram_size": 65536, "maximum_ram_size": 65536,
@@ -59,12 +42,7 @@
"require_upload_port": true, "require_upload_port": true,
"speed": 115200, "speed": 115200,
"protocol": "nrfutil", "protocol": "nrfutil",
"protocols": [ "protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"]
"jlink",
"nrfjprog",
"nrfutil",
"stlink"
]
}, },
"url": "https://www.adafruit.com/product/3406", "url": "https://www.adafruit.com/product/3406",
"vendor": "Adafruit" "vendor": "Adafruit"

View File

@@ -8,22 +8,10 @@
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA", "extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
"f_cpu": "64000000L", "f_cpu": "64000000L",
"hwids": [ "hwids": [
[ ["0x239A", "0x8029"],
"0x239A", ["0x239A", "0x0029"],
"0x8029" ["0x239A", "0x002A"],
], ["0x239A", "0x802A"]
[
"0x239A",
"0x0029"
],
[
"0x239A",
"0x002A"
],
[
"0x239A",
"0x802A"
]
], ],
"usb_product": "WisCore RAK4631 Board", "usb_product": "WisCore RAK4631 Board",
"mcu": "nrf52840", "mcu": "nrf52840",
@@ -41,28 +29,19 @@
"settings_addr": "0xFF000" "settings_addr": "0xFF000"
} }
}, },
"connectivity": [ "connectivity": ["bluetooth"],
"bluetooth"
],
"debug": { "debug": {
"jlink_device": "nRF52840_xxAA", "jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd" "svd_path": "nrf52840.svd"
}, },
"frameworks": [ "frameworks": ["arduino"],
"arduino"
],
"name": "WisCore RAK4631 Board", "name": "WisCore RAK4631 Board",
"upload": { "upload": {
"maximum_ram_size": 248832, "maximum_ram_size": 248832,
"maximum_size": 815104, "maximum_size": 815104,
"speed": 115200, "speed": 115200,
"protocol": "nrfutil", "protocol": "nrfutil",
"protocols": [ "protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"jlink",
"nrfjprog",
"nrfutil",
"stlink"
],
"use_1200bps_touch": true, "use_1200bps_touch": true,
"require_upload_port": true, "require_upload_port": true,
"wait_for_upload_port": true "wait_for_upload_port": true

View File

@@ -10,7 +10,6 @@
;default_envs = heltec-v2.0 ;default_envs = heltec-v2.0
;default_envs = heltec-v2.1 ;default_envs = heltec-v2.1
;default_envs = tlora-v1 ;default_envs = tlora-v1
;default_envs = tlora-v1
;default_envs = tlora_v1_3 ;default_envs = tlora_v1_3
;default_envs = tlora-v2 ;default_envs = tlora-v2
;default_envs = tlora-v2-1-1.6 ;default_envs = tlora-v2-1-1.6
@@ -40,7 +39,7 @@ extra_scripts = bin/platformio-custom.py
; The Radiolib stuff will speed up building considerably. Exclud all the stuff we dont need. ; The Radiolib stuff will speed up building considerably. Exclud all the stuff we dont need.
build_flags = -Wno-missing-field-initializers build_flags = -Wno-missing-field-initializers
-Wno-format -Wno-format
-Isrc -Isrc/mesh -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map -Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
-DUSE_THREAD_NAMES -DUSE_THREAD_NAMES
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS -DTINYGPS_OPTION_NO_CUSTOM_FIELDS
-DPB_ENABLE_MALLOC=1 -DPB_ENABLE_MALLOC=1
@@ -59,14 +58,15 @@ build_flags = -Wno-missing-field-initializers
monitor_speed = 115200 monitor_speed = 115200
lib_deps = lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git#53580644255b48ebb7a737343c6b4e71c7e11cf2 ; ESP8266_SSD1306 https://github.com/meshtastic/esp8266-oled-ssd1306.git#da1ede4dfcd91074283b029080759fd744120909 ; ESP8266_SSD1306
mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4 https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3 https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
nanopb/Nanopb@^0.4.6 nanopb/Nanopb@^0.4.6
erriez/ErriezCRC32@^1.0.1 erriez/ErriezCRC32@^1.0.1
jgromes/RadioLib@^5.5.0 ; jgromes/RadioLib@^5.5.1
https://github.com/jgromes/RadioLib.git#7a25b27c3183ffe3627c5c221243c378d8951da7
; Used for the code analysis in PIO Home / Inspect ; Used for the code analysis in PIO Home / Inspect
check_tool = cppcheck check_tool = cppcheck
@@ -82,6 +82,7 @@ framework = arduino
lib_deps = lib_deps =
${env.lib_deps} ${env.lib_deps}
mprograms/QMC5883LCompass@^1.1.1 mprograms/QMC5883LCompass@^1.1.1
end2endzone/NonBlockingRTTTL@^1.3.0
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76 https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0 build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
@@ -107,3 +108,4 @@ lib_deps =
adafruit/Adafruit INA219@^1.2.0 adafruit/Adafruit INA219@^1.2.0
adafruit/Adafruit SHTC3 Library@^1.0.0 adafruit/Adafruit SHTC3 Library@^1.0.0
adafruit/Adafruit LPS2X@^2.0.4 adafruit/Adafruit LPS2X@^2.0.4
adafruit/Adafruit SHT31 Library@^2.2.0

View File

@@ -1,5 +1,5 @@
#include "configuration.h"
#include "BluetoothCommon.h" #include "BluetoothCommon.h"
#include "configuration.h"
// NRF52 wants these constants as byte arrays // NRF52 wants these constants as byte arrays
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER // Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER

View File

@@ -51,6 +51,7 @@ class ButtonThread : public concurrency::OSThread
pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE); pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE);
#endif #endif
userButton.attachClick(userButtonPressed); userButton.attachClick(userButtonPressed);
userButton.setClickTicks(300);
userButton.attachDuringLongPress(userButtonPressedLong); userButton.attachDuringLongPress(userButtonPressedLong);
userButton.attachDoubleClick(userButtonDoublePressed); userButton.attachDoubleClick(userButtonDoublePressed);
userButton.attachMultiClick(userButtonMultiPressed); userButton.attachMultiClick(userButtonMultiPressed);
@@ -97,8 +98,8 @@ class ButtonThread : public concurrency::OSThread
userButtonTouch.tick(); userButtonTouch.tick();
canSleep &= userButtonTouch.isIdle(); canSleep &= userButtonTouch.isIdle();
#endif #endif
// if (!canSleep) DEBUG_MSG("Supressing sleep!\n"); // if (!canSleep) LOG_DEBUG("Supressing sleep!\n");
// else DEBUG_MSG("sleep ok\n"); // else LOG_DEBUG("sleep ok\n");
return 5; return 5;
} }
@@ -107,22 +108,21 @@ class ButtonThread : public concurrency::OSThread
static void touchPressed() static void touchPressed()
{ {
screen->forceDisplay(); screen->forceDisplay();
DEBUG_MSG("touch press!\n"); LOG_DEBUG("touch press!\n");
} }
static void userButtonPressed() static void userButtonPressed()
{ {
// DEBUG_MSG("press!\n"); // LOG_DEBUG("press!\n");
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
if ((BUTTON_PIN != moduleConfig.canned_message.inputbroker_pin_press) || if ((BUTTON_PIN != moduleConfig.canned_message.inputbroker_pin_press) || !moduleConfig.canned_message.enabled) {
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }
#endif #endif
} }
static void userButtonPressedLong() static void userButtonPressedLong()
{ {
// DEBUG_MSG("Long press!\n"); // LOG_DEBUG("Long press!\n");
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
screen->adjustBrightness(); screen->adjustBrightness();
#endif #endif
@@ -138,7 +138,7 @@ class ButtonThread : public concurrency::OSThread
// may wake the board immediatedly. // may wake the board immediatedly.
if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) { if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) {
screen->startShutdownScreen(); screen->startShutdownScreen();
DEBUG_MSG("Shutdown from long press"); LOG_INFO("Shutdown from long press");
playBeep(); playBeep();
#ifdef PIN_LED1 #ifdef PIN_LED1
ledOff(PIN_LED1); ledOff(PIN_LED1);
@@ -153,7 +153,7 @@ class ButtonThread : public concurrency::OSThread
} }
#endif #endif
} else { } else {
// DEBUG_MSG("Long press %u\n", (millis() - longPressTime)); // LOG_DEBUG("Long press %u\n", (millis() - longPressTime));
} }
} }
@@ -162,19 +162,28 @@ class ButtonThread : public concurrency::OSThread
#if defined(USE_EINK) && defined(PIN_EINK_EN) #if defined(USE_EINK) && defined(PIN_EINK_EN)
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW); digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
#endif #endif
}
static void userButtonMultiPressed()
{
screen->print("Sent ad-hoc ping\n"); screen->print("Sent ad-hoc ping\n");
service.refreshMyNodeInfo(); service.refreshMyNodeInfo();
service.sendNetworkPing(NODENUM_BROADCAST, true); service.sendNetworkPing(NODENUM_BROADCAST, true);
} }
static void userButtonMultiPressed()
{
#if defined(GPS_POWER_TOGGLE)
if (config.position.gps_enabled) {
LOG_DEBUG("Flag set to false for gps power\n");
} else {
LOG_DEBUG("Flag set to true to restore power\n");
}
config.position.gps_enabled = !(config.position.gps_enabled);
doGPSpowersave(config.position.gps_enabled);
#endif
}
static void userButtonPressedLongStart() static void userButtonPressedLongStart()
{ {
if (millis() > 30 * 1000) { if (millis() > 30 * 1000) {
DEBUG_MSG("Long press start!\n"); LOG_DEBUG("Long press start!\n");
longPressTime = millis(); longPressTime = millis();
} }
} }
@@ -182,7 +191,7 @@ class ButtonThread : public concurrency::OSThread
static void userButtonPressedLongStop() static void userButtonPressedLongStop()
{ {
if (millis() > 30 * 1000) { if (millis() > 30 * 1000) {
DEBUG_MSG("Long press stop!\n"); LOG_DEBUG("Long press stop!\n");
longPressTime = 0; longPressTime = 0;
if (shutdown_on_long_stop) { if (shutdown_on_long_stop) {
playShutdownMelody(); playShutdownMelody();

View File

@@ -13,17 +13,33 @@
#define SERIAL_BAUD 115200 // Serial debug baud rate #define SERIAL_BAUD 115200 // Serial debug baud rate
#endif #endif
#define MESHTASTIC_LOG_LEVEL_DEBUG "DEBUG"
#define MESHTASTIC_LOG_LEVEL_INFO "INFO "
#define MESHTASTIC_LOG_LEVEL_WARN "WARN "
#define MESHTASTIC_LOG_LEVEL_ERROR "ERROR"
#define MESHTASTIC_LOG_LEVEL_TRACE "TRACE"
#include "SerialConsole.h" #include "SerialConsole.h"
#define DEBUG_PORT (*console) // Serial debug port #define DEBUG_PORT (*console) // Serial debug port
#ifdef USE_SEGGER #ifdef USE_SEGGER
#define DEBUG_MSG(...) SEGGER_RTT_printf(0, __VA_ARGS__) #define LOG_DEBUG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#define LOG_INFO(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#define LOG_WARN(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#define LOG_ERROR(...) SEGGER_RTT_printf(0, __VA_ARGS__)
#else #else
#ifdef DEBUG_PORT #ifdef DEBUG_PORT
#define DEBUG_MSG(...) DEBUG_PORT.logDebug(__VA_ARGS__) #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__)
#define LOG_ERROR(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_ERROR, __VA_ARGS__)
#define LOG_TRACE(...) DEBUG_PORT.log(MESHTASTIC_LOG_TRACE, __VA_ARGS__)
#else #else
#define DEBUG_MSG(...) #define LOG_DEBUG(...)
#define LOG_INFO(...)
#define LOG_WARN(...)
#define LOG_ERROR(...)
#endif #endif
#endif #endif

View File

@@ -1,33 +1,31 @@
#include "configuration.h"
#include "FSCommon.h" #include "FSCommon.h"
#include "configuration.h"
#ifdef HAS_SDCARD #ifdef HAS_SDCARD
#include <SPI.h>
#include <SD.h> #include <SD.h>
#include <SPI.h>
#ifdef SDCARD_USE_SPI1 #ifdef SDCARD_USE_SPI1
SPIClass SPI1(HSPI); SPIClass SPI1(HSPI);
#define SDHandler SPI1 #define SDHandler SPI1
#endif #endif
#endif // HAS_SDCARD
#endif //HAS_SDCARD bool copyFile(const char *from, const char *to)
bool copyFile(const char* from, const char* to)
{ {
#ifdef FSCom #ifdef FSCom
unsigned char cbuffer[16]; unsigned char cbuffer[16];
File f1 = FSCom.open(from, FILE_O_READ); File f1 = FSCom.open(from, FILE_O_READ);
if (!f1){ if (!f1) {
DEBUG_MSG("Failed to open source file %s\n", from); LOG_ERROR("Failed to open source file %s\n", from);
return false; return false;
} }
File f2 = FSCom.open(to, FILE_O_WRITE); File f2 = FSCom.open(to, FILE_O_WRITE);
if (!f2) { if (!f2) {
DEBUG_MSG("Failed to open destination file %s\n", to); LOG_ERROR("Failed to open destination file %s\n", to);
return false; return false;
} }
@@ -42,106 +40,106 @@ bool copyFile(const char* from, const char* to)
#endif #endif
} }
bool renameFile(const char* pathFrom, const char* pathTo) bool renameFile(const char *pathFrom, const char *pathTo)
{ {
#ifdef FSCom #ifdef FSCom
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
// rename was fixed for ESP32 IDF LittleFS in April // rename was fixed for ESP32 IDF LittleFS in April
return FSCom.rename(pathFrom, pathTo); return FSCom.rename(pathFrom, pathTo);
#else #else
if (copyFile(pathFrom, pathTo) && FSCom.remove(pathFrom) ) { if (copyFile(pathFrom, pathTo) && FSCom.remove(pathFrom)) {
return true; return true;
} else{ } else {
return false; return false;
} }
#endif #endif
#endif #endif
} }
void listDir(const char * dirname, uint8_t levels, boolean del = false) void listDir(const char *dirname, uint8_t levels, boolean del = false)
{ {
#ifdef FSCom #ifdef FSCom
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)) #if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
char buffer[255]; char buffer[255];
#endif #endif
File root = FSCom.open(dirname, FILE_O_READ); File root = FSCom.open(dirname, FILE_O_READ);
if(!root){ if (!root) {
return; return;
} }
if(!root.isDirectory()){ if (!root.isDirectory()) {
return; return;
} }
File file = root.openNextFile(); File file = root.openNextFile();
while(file){ while (file) {
if(file.isDirectory() && !String(file.name()).endsWith(".")) { if (file.isDirectory() && !String(file.name()).endsWith(".")) {
if(levels){ if (levels) {
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
listDir(file.path(), levels -1, del); listDir(file.path(), levels - 1, del);
if(del) { if (del) {
DEBUG_MSG("Removing %s\n", file.path()); LOG_DEBUG("Removing %s\n", file.path());
strcpy(buffer, file.path()); strncpy(buffer, file.path(), sizeof(buffer));
file.close(); file.close();
FSCom.rmdir(buffer); FSCom.rmdir(buffer);
} else { } else {
file.close(); file.close();
} }
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)) #elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
listDir(file.name(), levels -1, del); listDir(file.name(), levels - 1, del);
if(del) { if (del) {
DEBUG_MSG("Removing %s\n", file.name()); LOG_DEBUG("Removing %s\n", file.name());
strcpy(buffer, file.name()); strncpy(buffer, file.name(), sizeof(buffer));
file.close(); file.close();
FSCom.rmdir(buffer); FSCom.rmdir(buffer);
} else { } else {
file.close(); file.close();
} }
#else #else
listDir(file.name(), levels -1, del); listDir(file.name(), levels - 1, del);
file.close(); file.close();
#endif #endif
} }
} else { } else {
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
if(del) { if (del) {
DEBUG_MSG("Deleting %s\n", file.path()); LOG_DEBUG("Deleting %s\n", file.path());
strcpy(buffer, file.path()); strncpy(buffer, file.path(), sizeof(buffer));
file.close(); file.close();
FSCom.remove(buffer); FSCom.remove(buffer);
} else { } else {
DEBUG_MSG(" %s (%i Bytes)\n", file.path(), file.size()); LOG_DEBUG(" %s (%i Bytes)\n", file.path(), file.size());
file.close(); file.close();
} }
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)) #elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
if(del) { if (del) {
DEBUG_MSG("Deleting %s\n", file.name()); LOG_DEBUG("Deleting %s\n", file.name());
strcpy(buffer, file.name()); strncpy(buffer, file.name(), sizeof(buffer));
file.close(); file.close();
FSCom.remove(buffer); FSCom.remove(buffer);
} else { } else {
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size()); LOG_DEBUG(" %s (%i Bytes)\n", file.name(), file.size());
file.close(); file.close();
} }
#else #else
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size()); LOG_DEBUG(" %s (%i Bytes)\n", file.name(), file.size());
file.close(); file.close();
#endif #endif
} }
file = root.openNextFile(); file = root.openNextFile();
} }
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
if(del) { if (del) {
DEBUG_MSG("Removing %s\n", root.path()); LOG_DEBUG("Removing %s\n", root.path());
strcpy(buffer, root.path()); strncpy(buffer, root.path(), sizeof(buffer));
root.close(); root.close();
FSCom.rmdir(buffer); FSCom.rmdir(buffer);
} else { } else {
root.close(); root.close();
} }
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)) #elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
if(del) { if (del) {
DEBUG_MSG("Removing %s\n", root.name()); LOG_DEBUG("Removing %s\n", root.name());
strcpy(buffer, root.name()); strncpy(buffer, root.name(), sizeof(buffer));
root.close(); root.close();
FSCom.rmdir(buffer); FSCom.rmdir(buffer);
} else { } else {
@@ -153,7 +151,7 @@ void listDir(const char * dirname, uint8_t levels, boolean del = false)
#endif #endif
} }
void rmDir(const char * dirname) void rmDir(const char *dirname)
{ {
#ifdef FSCom #ifdef FSCom
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO)) #if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
@@ -168,52 +166,47 @@ void rmDir(const char * dirname)
void fsInit() void fsInit()
{ {
#ifdef FSCom #ifdef FSCom
if (!FSBegin()) if (!FSBegin()) {
{ LOG_ERROR("Filesystem mount Failed.\n");
DEBUG_MSG("ERROR filesystem mount Failed. Formatting...\n"); // assert(0); This auto-formats the partition, so no need to fail here.
assert(0); // FIXME - report failure to phone
} }
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
DEBUG_MSG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes()); LOG_DEBUG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
#else #else
DEBUG_MSG("Filesystem files:\n"); LOG_DEBUG("Filesystem files:\n");
#endif #endif
listDir("/", 10); listDir("/", 10);
#endif #endif
} }
void setupSDCard() void setupSDCard()
{ {
#ifdef HAS_SDCARD #ifdef HAS_SDCARD
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI); SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
if (!SD.begin(SDCARD_CS, SDHandler)) { if (!SD.begin(SDCARD_CS, SDHandler)) {
DEBUG_MSG("No SD_MMC card detected\n"); LOG_DEBUG("No SD_MMC card detected\n");
return ; return;
} }
uint8_t cardType = SD.cardType(); uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) { if (cardType == CARD_NONE) {
DEBUG_MSG("No SD_MMC card attached\n"); LOG_DEBUG("No SD_MMC card attached\n");
return ; return;
} }
DEBUG_MSG("SD_MMC Card Type: "); LOG_DEBUG("SD_MMC Card Type: ");
if (cardType == CARD_MMC) { if (cardType == CARD_MMC) {
DEBUG_MSG("MMC\n"); LOG_DEBUG("MMC\n");
} else if (cardType == CARD_SD) { } else if (cardType == CARD_SD) {
DEBUG_MSG("SDSC\n"); LOG_DEBUG("SDSC\n");
} else if (cardType == CARD_SDHC) { } else if (cardType == CARD_SDHC) {
DEBUG_MSG("SDHC\n"); LOG_DEBUG("SDHC\n");
} else { } else {
DEBUG_MSG("UNKNOWN\n"); LOG_DEBUG("UNKNOWN\n");
} }
uint64_t cardSize = SD.cardSize() / (1024 * 1024); uint64_t cardSize = SD.cardSize() / (1024 * 1024);
DEBUG_MSG("SD Card Size: %lluMB\n", cardSize); LOG_DEBUG("SD Card Size: %lluMB\n", cardSize);
DEBUG_MSG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024)); LOG_DEBUG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024));
DEBUG_MSG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024)); LOG_DEBUG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024));
#endif #endif
} }

View File

@@ -17,7 +17,7 @@
// RP2040 // RP2040
#include "LittleFS.h" #include "LittleFS.h"
#define FSCom LittleFS #define FSCom LittleFS
#define FSBegin() FSCom.begin() #define FSBegin() FSCom.begin() // set autoformat
#define FILE_O_WRITE "w" #define FILE_O_WRITE "w"
#define FILE_O_READ "r" #define FILE_O_READ "r"
#endif #endif
@@ -26,7 +26,7 @@
// ESP32 version // ESP32 version
#include "LittleFS.h" #include "LittleFS.h"
#define FSCom LittleFS #define FSCom LittleFS
#define FSBegin() FSCom.begin(true) #define FSBegin() FSCom.begin(true) // format on failure
#define FILE_O_WRITE "w" #define FILE_O_WRITE "w"
#define FILE_O_READ "r" #define FILE_O_READ "r"
#endif #endif
@@ -35,13 +35,13 @@
// NRF52 version // NRF52 version
#include "InternalFileSystem.h" #include "InternalFileSystem.h"
#define FSCom InternalFS #define FSCom InternalFS
#define FSBegin() FSCom.begin() #define FSBegin() FSCom.begin() // InternalFS formats on failure
using namespace Adafruit_LittleFS_Namespace; using namespace Adafruit_LittleFS_Namespace;
#endif #endif
void fsInit(); void fsInit();
bool copyFile(const char* from, const char* to); bool copyFile(const char *from, const char *to);
bool renameFile(const char* pathFrom, const char* pathTo); bool renameFile(const char *pathFrom, const char *pathTo);
void listDir(const char * dirname, uint8_t levels, boolean del); void listDir(const char *dirname, uint8_t levels, boolean del);
void rmDir(const char * dirname); void rmDir(const char *dirname);
void setupSDCard(); void setupSDCard();

View File

@@ -20,16 +20,19 @@ class GPSStatus : public Status
bool hasLock = false; // default to false, until we complete our first read bool hasLock = false; // default to false, until we complete our first read
bool isConnected = false; // Do we have a GPS we are talking to bool isConnected = false; // Do we have a GPS we are talking to
Position p = Position_init_default; bool isPowerSaving = false; // Are we in power saving state
meshtastic_Position p = meshtastic_Position_init_default;
public: public:
GPSStatus() { statusType = STATUS_TYPE_GPS; } GPSStatus() { statusType = STATUS_TYPE_GPS; }
// preferred method // preferred method
GPSStatus(bool hasLock, bool isConnected, const Position &pos) : Status() GPSStatus(bool hasLock, bool isConnected, bool isPowerSaving, const meshtastic_Position &pos) : Status()
{ {
this->hasLock = hasLock; this->hasLock = hasLock;
this->isConnected = isConnected; this->isConnected = isConnected;
this->isPowerSaving = isPowerSaving;
// all-in-one struct copy // all-in-one struct copy
this->p = pos; this->p = pos;
@@ -44,13 +47,15 @@ class GPSStatus : public Status
bool getIsConnected() const { return isConnected; } bool getIsConnected() const { return isConnected; }
bool getIsPowerSaving() const { return isPowerSaving; }
int32_t getLatitude() const int32_t getLatitude() const
{ {
if (config.position.fixed_position) { if (config.position.fixed_position) {
#ifdef GPS_EXTRAVERBOSE #ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("WARNING: Using fixed latitude\n"); LOG_WARN("Using fixed latitude\n");
#endif #endif
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.latitude_i; return node->position.latitude_i;
} else { } else {
return p.latitude_i; return p.latitude_i;
@@ -61,9 +66,9 @@ class GPSStatus : public Status
{ {
if (config.position.fixed_position) { if (config.position.fixed_position) {
#ifdef GPS_EXTRAVERBOSE #ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("WARNING: Using fixed longitude\n"); LOG_WARN("Using fixed longitude\n");
#endif #endif
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.longitude_i; return node->position.longitude_i;
} else { } else {
return p.longitude_i; return p.longitude_i;
@@ -74,31 +79,40 @@ class GPSStatus : public Status
{ {
if (config.position.fixed_position) { if (config.position.fixed_position) {
#ifdef GPS_EXTRAVERBOSE #ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("WARNING: Using fixed altitude\n"); LOG_WARN("Using fixed altitude\n");
#endif #endif
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); meshtastic_NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.altitude; return node->position.altitude;
} else { } else {
return p.altitude; 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 bool matches(const GPSStatus *newStatus) const
{ {
#ifdef GPS_EXTRAVERBOSE #ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("GPSStatus.match() new pos@%x to old pos@%x\n", newStatus->p.pos_timestamp, p.pos_timestamp); LOG_DEBUG("GPSStatus.match() new pos@%x to old pos@%x\n", newStatus->p.pos_timestamp, p.pos_timestamp);
#endif #endif
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected || return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected ||
newStatus->p.latitude_i != p.latitude_i || newStatus->p.longitude_i != p.longitude_i || newStatus->isPowerSaving != isPowerSaving || newStatus->p.latitude_i != p.latitude_i ||
newStatus->p.altitude != p.altitude || newStatus->p.altitude_hae != p.altitude_hae || newStatus->p.longitude_i != p.longitude_i || newStatus->p.altitude != p.altitude ||
newStatus->p.PDOP != p.PDOP || newStatus->p.ground_track != p.ground_track || newStatus->p.altitude_hae != p.altitude_hae || newStatus->p.PDOP != p.PDOP ||
newStatus->p.ground_speed != p.ground_speed || newStatus->p.ground_track != p.ground_track || newStatus->p.ground_speed != p.ground_speed ||
newStatus->p.sats_in_view != p.sats_in_view); newStatus->p.sats_in_view != p.sats_in_view);
} }
@@ -109,7 +123,7 @@ class GPSStatus : public Status
if (isDirty && p.timestamp && (newStatus->p.timestamp == p.timestamp)) { if (isDirty && p.timestamp && (newStatus->p.timestamp == p.timestamp)) {
// We can NEVER be in two locations at the same time! (also PR #886) // We can NEVER be in two locations at the same time! (also PR #886)
DEBUG_MSG("BUG!! positional timestamp unchanged from prev solution\n"); LOG_ERROR("BUG: Positional timestamp unchanged from prev solution\n");
} }
initialized = true; initialized = true;
@@ -121,11 +135,11 @@ class GPSStatus : public Status
if (isDirty) { if (isDirty) {
if (hasLock) { if (hasLock) {
// In debug logs, identify position by @timestamp:stage (stage 3 = notify) // In debug logs, identify position by @timestamp:stage (stage 3 = notify)
DEBUG_MSG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, speed=%.2f, sats=%d\n", p.timestamp, LOG_DEBUG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, speed=%.2f, sats=%d\n", p.timestamp,
p.latitude_i * 1e-7, p.longitude_i * 1e-7, p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5, p.latitude_i * 1e-7, p.longitude_i * 1e-7, p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
p.ground_speed * 1e-2, p.sats_in_view); p.ground_speed * 1e-2, p.sats_in_view);
} else } else
DEBUG_MSG("No GPS lock\n"); LOG_DEBUG("No GPS lock\n");
onNewStatus.notifyObservers(this); onNewStatus.notifyObservers(this);
} }
return 0; return 0;

View File

@@ -1,16 +1,18 @@
#pragma once #pragma once
#include <Arduino.h>
#include "Status.h" #include "Status.h"
#include "configuration.h" #include "configuration.h"
#include <Arduino.h>
namespace meshtastic { namespace meshtastic
{
/// Describes the state of the NodeDB system. /// Describes the state of the NodeDB system.
class NodeStatus : public Status class NodeStatus : public Status
{ {
private: private:
CallbackObserver<NodeStatus, const NodeStatus *> statusObserver = CallbackObserver<NodeStatus, const NodeStatus *>(this, &NodeStatus::updateStatus); CallbackObserver<NodeStatus, const NodeStatus *> statusObserver =
CallbackObserver<NodeStatus, const NodeStatus *>(this, &NodeStatus::updateStatus);
uint8_t numOnline = 0; uint8_t numOnline = 0;
uint8_t numTotal = 0; uint8_t numTotal = 0;
@@ -20,10 +22,8 @@ namespace meshtastic {
public: public:
bool forceUpdate = false; bool forceUpdate = false;
NodeStatus() { NodeStatus() { statusType = STATUS_TYPE_NODE; }
statusType = STATUS_TYPE_NODE; NodeStatus(uint8_t numOnline, uint8_t numTotal, bool forceUpdate = false) : Status()
}
NodeStatus( uint8_t numOnline, uint8_t numTotal, bool forceUpdate = false ) : Status()
{ {
this->forceUpdate = forceUpdate; this->forceUpdate = forceUpdate;
this->numOnline = numOnline; this->numOnline = numOnline;
@@ -32,34 +32,20 @@ namespace meshtastic {
NodeStatus(const NodeStatus &); NodeStatus(const NodeStatus &);
NodeStatus &operator=(const NodeStatus &); NodeStatus &operator=(const NodeStatus &);
void observe(Observable<const NodeStatus *> *source) void observe(Observable<const NodeStatus *> *source) { statusObserver.observe(source); }
{
statusObserver.observe(source);
}
uint8_t getNumOnline() const uint8_t getNumOnline() const { return numOnline; }
{
return numOnline;
}
uint8_t getNumTotal() const uint8_t getNumTotal() const { return numTotal; }
{
return numTotal;
}
uint8_t getLastNumTotal() const uint8_t getLastNumTotal() const { return lastNumTotal; }
{
return lastNumTotal;
}
bool matches(const NodeStatus *newStatus) const bool matches(const NodeStatus *newStatus) const
{ {
return ( return (newStatus->getNumOnline() != numOnline || newStatus->getNumTotal() != numTotal);
newStatus->getNumOnline() != numOnline ||
newStatus->getNumTotal() != numTotal
);
} }
int updateStatus(const NodeStatus *newStatus) { int updateStatus(const NodeStatus *newStatus)
{
// Only update the status if values have actually changed // Only update the status if values have actually changed
lastNumTotal = numTotal; lastNumTotal = numTotal;
bool isDirty; bool isDirty;
@@ -69,15 +55,14 @@ namespace meshtastic {
numOnline = newStatus->getNumOnline(); numOnline = newStatus->getNumOnline();
numTotal = newStatus->getNumTotal(); numTotal = newStatus->getNumTotal();
} }
if(isDirty || newStatus->forceUpdate) { if (isDirty || newStatus->forceUpdate) {
DEBUG_MSG("Node status update: %d online, %d total\n", numOnline, numTotal); LOG_DEBUG("Node status update: %d online, %d total\n", numOnline, numTotal);
onNewStatus.notifyObservers(this); onNewStatus.notifyObservers(this);
} }
return 0; return 0;
} }
};
}; } // namespace meshtastic
}
extern meshtastic::NodeStatus *nodeStatus; extern meshtastic::NodeStatus *nodeStatus;

View File

@@ -1,5 +1,5 @@
#include "configuration.h"
#include "OSTimer.h" #include "OSTimer.h"
#include "configuration.h"
/** /**
* Schedule a callback to run. The callback must _not_ block, though it is called from regular thread level (not ISR) * Schedule a callback to run. The callback must _not_ block, though it is called from regular thread level (not ISR)

View File

@@ -1,3 +1,2 @@
#include "configuration.h"
#include "Observer.h" #include "Observer.h"
#include "configuration.h"

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#include <assert.h>
#include <list> #include <list>
template <class T> class Observable; template <class T> class Observable;

View File

@@ -1,16 +1,16 @@
#include "power.h" #include "power.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "PowerFSM.h" #include "PowerFSM.h"
#include "buzz/buzz.h"
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#include "sleep.h" #include "sleep.h"
#include "utils.h" #include "utils.h"
#include "buzz/buzz.h"
#ifdef HAS_PMU #ifdef HAS_PMU
#include "XPowersLibInterface.hpp"
#include "XPowersAXP2101.tpp"
#include "XPowersAXP192.tpp" #include "XPowersAXP192.tpp"
#include "XPowersAXP2101.tpp"
#include "XPowersLibInterface.hpp"
XPowersLibInterface *PMU = NULL; XPowersLibInterface *PMU = NULL;
#else #else
// Copy of the base class defined in axp20x.h. // Copy of the base class defined in axp20x.h.
@@ -102,26 +102,26 @@ class AnalogBatteryLevel : public HasBatteryLevel
#define ADC_MULTIPLIER 2.0 #define ADC_MULTIPLIER 2.0
#endif #endif
#ifndef BATTERY_SENSE_SAMPLES
#define BATTERY_SENSE_SAMPLES 30
#endif
#ifdef BATTERY_PIN #ifdef BATTERY_PIN
// Override variant or default ADC_MULTIPLIER if we have the override pref // Override variant or default ADC_MULTIPLIER if we have the override pref
float operativeAdcMultiplier = config.power.adc_multiplier_override > 0 float operativeAdcMultiplier =
? config.power.adc_multiplier_override config.power.adc_multiplier_override > 0 ? config.power.adc_multiplier_override : ADC_MULTIPLIER;
: ADC_MULTIPLIER;
// Do not call analogRead() often. // Do not call analogRead() often.
const uint32_t min_read_interval = 5000; const uint32_t min_read_interval = 5000;
if (millis() - last_read_time_ms > min_read_interval) { if (millis() - last_read_time_ms > min_read_interval) {
last_read_time_ms = millis(); last_read_time_ms = millis();
#ifdef BATTERY_SENSE_SAMPLES // Set the number of samples, it has an effect of increasing sensitivity, especially in complex electromagnetic
//Set the number of samples, it has an effect of increasing sensitivity, especially in complex electromagnetic environment. // environment.
uint32_t raw = 0; uint32_t raw = 0;
for(uint32_t i=0; i<BATTERY_SENSE_SAMPLES;i++){ for (uint32_t i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
raw += analogRead(BATTERY_PIN); raw += analogRead(BATTERY_PIN);
} }
raw = raw/BATTERY_SENSE_SAMPLES; raw = raw / BATTERY_SENSE_SAMPLES;
#else
uint32_t raw = analogRead(BATTERY_PIN);
#endif
float scaled; float scaled;
#ifndef VBAT_RAW_TO_SCALED #ifndef VBAT_RAW_TO_SCALED
@@ -129,7 +129,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
#else #else
scaled = VBAT_RAW_TO_SCALED(raw); // defined in variant.h scaled = VBAT_RAW_TO_SCALED(raw); // defined in variant.h
#endif #endif
// DEBUG_MSG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled)); // LOG_DEBUG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
last_read_value = scaled; last_read_value = scaled;
return scaled; return scaled;
} else { } else {
@@ -143,15 +143,24 @@ class AnalogBatteryLevel : public HasBatteryLevel
/** /**
* return true if there is a battery installed in this unit * return true if there is a battery installed in this unit
*/ */
virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; } virtual bool isBatteryConnect() override
{
return getBatteryPercent() != -1;
}
/// If we see a battery voltage higher than physics allows - assume charger is pumping /// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power /// in power
virtual bool isVbusIn() override { return getBattVoltage() > chargingVolt; } virtual bool isVbusIn() override
{
return getBattVoltage() > chargingVolt;
}
/// Assume charging if we have a battery and external power is connected. /// Assume charging if we have a battery and external power is connected.
/// we can't be smart enough to say 'full'? /// we can't be smart enough to say 'full'?
virtual bool isCharging() override { return isBatteryConnect() && isVbusIn(); } virtual bool isCharging() override
{
return isBatteryConnect() && isVbusIn();
}
private: private:
/// If we see a battery voltage higher than physics allows - assume charger is pumping /// If we see a battery voltage higher than physics allows - assume charger is pumping
@@ -182,12 +191,15 @@ Power::Power() : OSThread("Power")
{ {
statusHandler = {}; statusHandler = {};
low_voltage_counter = 0; low_voltage_counter = 0;
#ifdef DEBUG_HEAP
lastheap = ESP.getFreeHeap();
#endif
} }
bool Power::analogInit() bool Power::analogInit()
{ {
#ifdef BATTERY_PIN #ifdef BATTERY_PIN
DEBUG_MSG("Using analog input %d for battery level\n", BATTERY_PIN); LOG_DEBUG("Using analog input %d for battery level\n", BATTERY_PIN);
// disable any internal pullups // disable any internal pullups
pinMode(BATTERY_PIN, INPUT); pinMode(BATTERY_PIN, INPUT);
@@ -235,12 +247,12 @@ void Power::shutdown()
{ {
screen->setOn(false); screen->setOn(false);
#if defined(USE_EINK) && defined(PIN_EINK_EN) #if defined(USE_EINK) && defined(PIN_EINK_EN)
digitalWrite(PIN_EINK_EN, LOW); //power off backlight first digitalWrite(PIN_EINK_EN, LOW); // power off backlight first
#endif #endif
#ifdef HAS_PMU #ifdef HAS_PMU
DEBUG_MSG("Shutting down\n"); LOG_INFO("Shutting down\n");
if(PMU) { if (PMU) {
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF); PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
PMU->shutdown(); PMU->shutdown();
} }
@@ -280,9 +292,26 @@ void Power::readPowerStatus()
const PowerStatus powerStatus2 = const PowerStatus powerStatus2 =
PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() ? OptTrue : OptFalse, PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() ? OptTrue : OptFalse,
batteryLevel->isCharging() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent); batteryLevel->isCharging() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
DEBUG_MSG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(), LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(),
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent()); powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
newStatus.notifyObservers(&powerStatus2); newStatus.notifyObservers(&powerStatus2);
#ifdef DEBUG_HEAP
if (lastheap != ESP.getFreeHeap()) {
LOG_DEBUG("Threads running:");
int running = 0;
for (int i = 0; i < MAX_THREADS; i++) {
auto thread = concurrency::mainController.get(i);
if ((thread != nullptr) && (thread->enabled)) {
LOG_DEBUG(" %s", thread->ThreadName.c_str());
running++;
}
}
LOG_DEBUG("\n");
LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads\n", ESP.getFreeHeap(), ESP.getHeapSize(),
ESP.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
lastheap = ESP.getFreeHeap();
}
#endif
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row // If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row
// Supect fluctuating voltage on the RAK4631 to force it to deep sleep even if battery is at 85% after only a few days // Supect fluctuating voltage on the RAK4631 to force it to deep sleep even if battery is at 85% after only a few days
@@ -290,8 +319,12 @@ void Power::readPowerStatus()
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) { if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) { if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) {
low_voltage_counter++; low_voltage_counter++;
if (low_voltage_counter > 3) LOG_DEBUG("Warning RAK4631 Low voltage counter: %d/10\n", low_voltage_counter);
powerFSM.trigger(EVENT_LOW_BATTERY); if (low_voltage_counter > 10) {
// We can't trigger deep sleep on NRF52, it's freezing the board
// powerFSM.trigger(EVENT_LOW_BATTERY);
LOG_DEBUG("Low voltage detected, but not triggering deep sleep\n");
}
} else { } else {
low_voltage_counter = 0; low_voltage_counter = 0;
} }
@@ -315,17 +348,17 @@ int32_t Power::runOnce()
#ifdef HAS_PMU #ifdef HAS_PMU
// WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll // WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll
// the IRQ status by reading the registers over I2C // the IRQ status by reading the registers over I2C
if(PMU) { if (PMU) {
PMU->getIrqStatus(); PMU->getIrqStatus();
if(PMU->isVbusRemoveIrq()){ if (PMU->isVbusRemoveIrq()) {
DEBUG_MSG("USB unplugged\n"); LOG_INFO("USB unplugged\n");
powerFSM.trigger(EVENT_POWER_DISCONNECTED); powerFSM.trigger(EVENT_POWER_DISCONNECTED);
} }
if (PMU->isVbusInsertIrq()) { if (PMU->isVbusInsertIrq()) {
DEBUG_MSG("USB plugged In\n"); LOG_INFO("USB plugged In\n");
powerFSM.trigger(EVENT_POWER_CONNECTED); powerFSM.trigger(EVENT_POWER_CONNECTED);
} }
@@ -333,20 +366,20 @@ int32_t Power::runOnce()
Other things we could check if we cared... Other things we could check if we cared...
if (PMU->isBatChagerStartIrq()) { if (PMU->isBatChagerStartIrq()) {
DEBUG_MSG("Battery start charging\n"); LOG_DEBUG("Battery start charging\n");
} }
if (PMU->isBatChagerDoneIrq()) { if (PMU->isBatChagerDoneIrq()) {
DEBUG_MSG("Battery fully charged\n"); LOG_DEBUG("Battery fully charged\n");
} }
if (PMU->isBatInsertIrq()) { if (PMU->isBatInsertIrq()) {
DEBUG_MSG("Battery inserted\n"); LOG_DEBUG("Battery inserted\n");
} }
if (PMU->isBatRemoveIrq()) { if (PMU->isBatRemoveIrq()) {
DEBUG_MSG("Battery removed\n"); LOG_DEBUG("Battery removed\n");
} }
*/ */
if (PMU->isPekeyLongPressIrq()) { if (PMU->isPekeyLongPressIrq()) {
DEBUG_MSG("PEK long button press\n"); LOG_DEBUG("PEK long button press\n");
screen->setOn(false); screen->setOn(false);
} }
@@ -372,7 +405,7 @@ bool Power::axpChipInit()
#ifdef HAS_PMU #ifdef HAS_PMU
TwoWire * w = NULL; TwoWire *w = NULL;
// Use macro to distinguish which wire is used by PMU // Use macro to distinguish which wire is used by PMU
#ifdef PMU_USE_WIRE1 #ifdef PMU_USE_WIRE1
@@ -388,22 +421,22 @@ bool Power::axpChipInit()
if (!PMU) { if (!PMU) {
PMU = new XPowersAXP2101(*w); PMU = new XPowersAXP2101(*w);
if (!PMU->init()) { if (!PMU->init()) {
DEBUG_MSG("Warning: Failed to find AXP2101 power management\n"); LOG_WARN("Failed to find AXP2101 power management\n");
delete PMU; delete PMU;
PMU = NULL; PMU = NULL;
} else { } else {
DEBUG_MSG("AXP2101 PMU init succeeded, using AXP2101 PMU\n"); LOG_INFO("AXP2101 PMU init succeeded, using AXP2101 PMU\n");
} }
} }
if (!PMU) { if (!PMU) {
PMU = new XPowersAXP192(*w); PMU = new XPowersAXP192(*w);
if (!PMU->init()) { if (!PMU->init()) {
DEBUG_MSG("Warning: Failed to find AXP192 power management\n"); LOG_WARN("Failed to find AXP192 power management\n");
delete PMU; delete PMU;
PMU = NULL; PMU = NULL;
} else { } else {
DEBUG_MSG("AXP192 PMU init succeeded, using AXP192 PMU\n"); LOG_INFO("AXP192 PMU init succeeded, using AXP192 PMU\n");
} }
} }
@@ -427,7 +460,6 @@ bool Power::axpChipInit()
PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300); PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300);
PMU->enablePowerOutput(XPOWERS_LDO2); PMU->enablePowerOutput(XPOWERS_LDO2);
// oled module power channel, // oled module power channel,
// disable it will cause abnormal communication between boot and AXP power supply, // disable it will cause abnormal communication between boot and AXP power supply,
// do not turn it off // do not turn it off
@@ -435,26 +467,27 @@ bool Power::axpChipInit()
// enable oled power // enable oled power
PMU->enablePowerOutput(XPOWERS_DCDC1); PMU->enablePowerOutput(XPOWERS_DCDC1);
// gnss module power channel - now turned on in setGpsPower // gnss module power channel - now turned on in setGpsPower
PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300); PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300);
// PMU->enablePowerOutput(XPOWERS_LDO3); // PMU->enablePowerOutput(XPOWERS_LDO3);
// protected oled power source
//protected oled power source
PMU->setProtectedChannel(XPOWERS_DCDC1); PMU->setProtectedChannel(XPOWERS_DCDC1);
//protected esp32 power source // protected esp32 power source
PMU->setProtectedChannel(XPOWERS_DCDC3); PMU->setProtectedChannel(XPOWERS_DCDC3);
//disable not use channel // disable not use channel
PMU->disablePowerOutput(XPOWERS_DCDC2); PMU->disablePowerOutput(XPOWERS_DCDC2);
//disable all axp chip interrupt // disable all axp chip interrupt
PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ); PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ);
// Set constant current charging current // Set constant current charging current
PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_450MA); PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_450MA);
// Set up the charging voltage
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
} else if (PMU->getChipModel() == XPOWERS_AXP2101) { } else if (PMU->getChipModel() == XPOWERS_AXP2101) {
// t-beam s3 core // t-beam s3 core
@@ -494,22 +527,23 @@ bool Power::axpChipInit()
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300); // PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// PMU->enablePowerOutput(XPOWERS_DCDC4); // PMU->enablePowerOutput(XPOWERS_DCDC4);
//not use channel // not use channel
PMU->disablePowerOutput(XPOWERS_DCDC2); //not elicited PMU->disablePowerOutput(XPOWERS_DCDC2); // not elicited
PMU->disablePowerOutput(XPOWERS_DCDC5); //not elicited PMU->disablePowerOutput(XPOWERS_DCDC5); // not elicited
PMU->disablePowerOutput(XPOWERS_DLDO1); //Invalid power channel, it does not exist PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_DLDO2); //Invalid power channel, it does not exist PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_VBACKUP); PMU->disablePowerOutput(XPOWERS_VBACKUP);
//disable all axp chip interrupt // disable all axp chip interrupt
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
//Set the constant current charging current of AXP2101, temporarily use 500mA by default // Set the constant current charging current of AXP2101, temporarily use 500mA by default
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA); PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
// Set up the charging voltage
PMU->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
} }
PMU->clearIrqStatus(); PMU->clearIrqStatus();
// TBeam1.1 /T-Beam S3-Core has no external TS detection, // TBeam1.1 /T-Beam S3-Core has no external TS detection,
@@ -520,54 +554,66 @@ bool Power::axpChipInit()
PMU->enableVbusVoltageMeasure(); PMU->enableVbusVoltageMeasure();
PMU->enableBattVoltageMeasure(); PMU->enableBattVoltageMeasure();
DEBUG_MSG("=======================================================================\n"); LOG_DEBUG("=======================================================================\n");
if (PMU->isChannelAvailable(XPOWERS_DCDC1)) { if (PMU->isChannelAvailable(XPOWERS_DCDC1)) {
DEBUG_MSG("DC1 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC1)); LOG_DEBUG("DC1 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_DCDC1));
} }
if (PMU->isChannelAvailable(XPOWERS_DCDC2)) { if (PMU->isChannelAvailable(XPOWERS_DCDC2)) {
DEBUG_MSG("DC2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC2)); LOG_DEBUG("DC2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_DCDC2));
} }
if (PMU->isChannelAvailable(XPOWERS_DCDC3)) { if (PMU->isChannelAvailable(XPOWERS_DCDC3)) {
DEBUG_MSG("DC3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC3)); LOG_DEBUG("DC3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_DCDC3));
} }
if (PMU->isChannelAvailable(XPOWERS_DCDC4)) { if (PMU->isChannelAvailable(XPOWERS_DCDC4)) {
DEBUG_MSG("DC4 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC4)); LOG_DEBUG("DC4 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_DCDC4));
} }
if (PMU->isChannelAvailable(XPOWERS_LDO2)) { if (PMU->isChannelAvailable(XPOWERS_LDO2)) {
DEBUG_MSG("LDO2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO2)); LOG_DEBUG("LDO2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO2) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_LDO2));
} }
if (PMU->isChannelAvailable(XPOWERS_LDO3)) { if (PMU->isChannelAvailable(XPOWERS_LDO3)) {
DEBUG_MSG("LDO3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO3)); LOG_DEBUG("LDO3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO3) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_LDO3));
} }
if (PMU->isChannelAvailable(XPOWERS_ALDO1)) { if (PMU->isChannelAvailable(XPOWERS_ALDO1)) {
DEBUG_MSG("ALDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO1)); LOG_DEBUG("ALDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_ALDO1));
} }
if (PMU->isChannelAvailable(XPOWERS_ALDO2)) { if (PMU->isChannelAvailable(XPOWERS_ALDO2)) {
DEBUG_MSG("ALDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO2)); LOG_DEBUG("ALDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_ALDO2));
} }
if (PMU->isChannelAvailable(XPOWERS_ALDO3)) { if (PMU->isChannelAvailable(XPOWERS_ALDO3)) {
DEBUG_MSG("ALDO3: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO3)); LOG_DEBUG("ALDO3: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_ALDO3));
} }
if (PMU->isChannelAvailable(XPOWERS_ALDO4)) { if (PMU->isChannelAvailable(XPOWERS_ALDO4)) {
DEBUG_MSG("ALDO4: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO4)); LOG_DEBUG("ALDO4: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_ALDO4));
} }
if (PMU->isChannelAvailable(XPOWERS_BLDO1)) { if (PMU->isChannelAvailable(XPOWERS_BLDO1)) {
DEBUG_MSG("BLDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO1)); LOG_DEBUG("BLDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_BLDO1));
} }
if (PMU->isChannelAvailable(XPOWERS_BLDO2)) { if (PMU->isChannelAvailable(XPOWERS_BLDO2)) {
DEBUG_MSG("BLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO2)); LOG_DEBUG("BLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-",
PMU->getPowerChannelVoltage(XPOWERS_BLDO2));
} }
DEBUG_MSG("=======================================================================\n"); LOG_DEBUG("=======================================================================\n");
//Set up the charging voltage, AXP2101/AXP192 4.2V gear is the same
// XPOWERS_AXP192_CHG_VOL_4V2 = XPOWERS_AXP2101_CHG_VOL_4V2
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
// We can safely ignore this approach for most (or all) boards because MCU turned off
// earlier than battery discharged to 2.6V.
//
// Unfortanly for now we can't use this killswitch for RAK4630-based boards because they have a bug with
// battery voltage measurement. Probably it sometimes drops to low values.
#ifndef RAK4630
// Set PMU shutdown voltage at 2.6V to maximize battery utilization // Set PMU shutdown voltage at 2.6V to maximize battery utilization
PMU->setSysPowerDownVoltage(2600); PMU->setSysPowerDownVoltage(2600);
#endif
#ifdef PMU_IRQ #ifdef PMU_IRQ
uint64_t pmuIrqMask = 0; uint64_t pmuIrqMask = 0;

View File

@@ -11,12 +11,12 @@
/// Should we behave as if we have AC power now? /// Should we behave as if we have AC power now?
static bool isPowered() static bool isPowered()
{ {
// Circumvent the battery sensing logic and assumes constant power if no battery pin or power mgmt IC // Circumvent the battery sensing logic and assumes constant power if no battery pin or power mgmt IC
#if !defined(BATTERY_PIN) && !defined(HAS_AXP192) && !defined(HAS_AXP2101) #if !defined(BATTERY_PIN) && !defined(HAS_AXP192) && !defined(HAS_AXP2101)
return true; return true;
#endif #endif
bool isRouter = (config.device.role == Config_DeviceConfig_Role_ROUTER ? 1 : 0); bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
// If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON // If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON
// We assume routers might be powered all the time, but from a low current (solar) source // We assume routers might be powered all the time, but from a low current (solar) source
@@ -32,16 +32,16 @@ static bool isPowered()
static void sdsEnter() static void sdsEnter()
{ {
DEBUG_MSG("Enter state: SDS\n"); LOG_INFO("Enter state: SDS\n");
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw // FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
doDeepSleep(config.power.sds_secs * 1000); doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs));
} }
extern Power *power; extern Power *power;
static void shutdownEnter() static void shutdownEnter()
{ {
DEBUG_MSG("Enter state: SHUTDOWN\n"); LOG_INFO("Enter state: SHUTDOWN\n");
power->shutdown(); power->shutdown();
} }
@@ -51,16 +51,16 @@ static uint32_t secsSlept;
static void lsEnter() static void lsEnter()
{ {
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", config.power.ls_secs); LOG_INFO("lsEnter begin, ls_secs=%u\n", config.power.ls_secs);
screen->setOn(false); screen->setOn(false);
secsSlept = 0; // How long have we been sleeping this time secsSlept = 0; // How long have we been sleeping this time
// DEBUG_MSG("lsEnter end\n"); // LOG_INFO("lsEnter end\n");
} }
static void lsIdle() static void lsIdle()
{ {
// DEBUG_MSG("lsIdle begin ls_secs=%u\n", getPref_ls_secs()); // LOG_INFO("lsIdle begin ls_secs=%u\n", getPref_ls_secs());
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
@@ -82,7 +82,7 @@ static void lsIdle()
wakeCause2 = doLightSleep(1); // leave led on for 1ms wakeCause2 = doLightSleep(1); // leave led on for 1ms
secsSlept += sleepTime; secsSlept += sleepTime;
// DEBUG_MSG("sleeping, flash led!\n"); // LOG_INFO("sleeping, flash led!\n");
break; break;
case ESP_SLEEP_WAKEUP_UART: case ESP_SLEEP_WAKEUP_UART:
@@ -93,7 +93,7 @@ static void lsIdle()
default: default:
// We woke for some other reason (button press, device interrupt) // We woke for some other reason (button press, device interrupt)
// uint64_t status = esp_sleep_get_ext1_wakeup_status(); // uint64_t status = esp_sleep_get_ext1_wakeup_status();
DEBUG_MSG("wakeCause2 %d\n", wakeCause2); LOG_INFO("wakeCause2 %d\n", wakeCause2);
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
bool pressed = !digitalRead(BUTTON_PIN); bool pressed = !digitalRead(BUTTON_PIN);
@@ -117,7 +117,7 @@ static void lsIdle()
} else { } else {
// Time to stop sleeping! // Time to stop sleeping!
setLed(false); setLed(false);
DEBUG_MSG("reached ls_secs, servicing loop()\n"); LOG_INFO("Reached ls_secs, servicing loop()\n");
powerFSM.trigger(EVENT_WAKE_TIMER); powerFSM.trigger(EVENT_WAKE_TIMER);
} }
#endif #endif
@@ -125,7 +125,7 @@ static void lsIdle()
static void lsExit() static void lsExit()
{ {
DEBUG_MSG("Exit state: LS\n"); LOG_INFO("Exit state: LS\n");
// setGPSPower(true); // restore GPS power // setGPSPower(true); // restore GPS power
if (gps) if (gps)
gps->forceWake(true); gps->forceWake(true);
@@ -133,7 +133,7 @@ static void lsExit()
static void nbEnter() static void nbEnter()
{ {
DEBUG_MSG("Enter state: NB\n"); LOG_INFO("Enter state: NB\n");
screen->setOn(false); screen->setOn(false);
setBluetoothEnable(false); setBluetoothEnable(false);
@@ -148,7 +148,7 @@ static void darkEnter()
static void serialEnter() static void serialEnter()
{ {
DEBUG_MSG("Enter state: SERIAL\n"); LOG_INFO("Enter state: SERIAL\n");
setBluetoothEnable(false); setBluetoothEnable(false);
screen->setOn(true); screen->setOn(true);
screen->print("Serial connected\n"); screen->print("Serial connected\n");
@@ -161,10 +161,10 @@ static void serialExit()
static void powerEnter() static void powerEnter()
{ {
DEBUG_MSG("Enter state: POWER\n"); LOG_INFO("Enter state: POWER\n");
if (!isPowered()) { if (!isPowered()) {
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things // If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
DEBUG_MSG("Loss of power in Powered\n"); LOG_INFO("Loss of power in Powered\n");
powerFSM.trigger(EVENT_POWER_DISCONNECTED); powerFSM.trigger(EVENT_POWER_DISCONNECTED);
} else { } else {
screen->setOn(true); screen->setOn(true);
@@ -177,7 +177,7 @@ static void powerIdle()
{ {
if (!isPowered()) { if (!isPowered()) {
// If we got here, we are in the wrong state // If we got here, we are in the wrong state
DEBUG_MSG("Loss of power in Powered\n"); LOG_INFO("Loss of power in Powered\n");
powerFSM.trigger(EVENT_POWER_DISCONNECTED); powerFSM.trigger(EVENT_POWER_DISCONNECTED);
} }
} }
@@ -191,7 +191,7 @@ static void powerExit()
static void onEnter() static void onEnter()
{ {
DEBUG_MSG("Enter state: ON\n"); LOG_INFO("Enter state: ON\n");
screen->setOn(true); screen->setOn(true);
setBluetoothEnable(true); setBluetoothEnable(true);
@@ -199,7 +199,8 @@ static void onEnter()
uint32_t now = millis(); uint32_t now = millis();
if ((now - lastPingMs) > 30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state if ((now - lastPingMs) >
30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state
if (displayedNodeNum) if (displayedNodeNum)
service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node
lastPingMs = now; lastPingMs = now;
@@ -221,7 +222,7 @@ static void screenPress()
static void bootEnter() static void bootEnter()
{ {
DEBUG_MSG("Enter state: BOOT\n"); LOG_INFO("Enter state: BOOT\n");
} }
State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN"); State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN");
@@ -237,10 +238,10 @@ Fsm powerFSM(&stateBOOT);
void PowerFSM_setup() void PowerFSM_setup()
{ {
bool isRouter = (config.device.role == Config_DeviceConfig_Role_ROUTER ? 1 : 0); bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool hasPower = isPowered(); bool hasPower = isPowered();
DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower ? 1 : 0); LOG_INFO("PowerFSM init, USB power=%d\n", hasPower ? 1 : 0);
powerFSM.add_timed_transition(&stateBOOT, hasPower ? &statePOWER : &stateON, 3 * 1000, NULL, "boot timeout"); powerFSM.add_timed_transition(&stateBOOT, hasPower ? &statePOWER : &stateON, 3 * 1000, NULL, "boot timeout");
// wake timer expired or a packet arrived // wake timer expired or a packet arrived
@@ -249,7 +250,8 @@ void PowerFSM_setup()
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from // We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from
// light sleep we _always_ transition to NB or dark and // light sleep we _always_ transition to NB or dark and
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, exiting light sleep"); powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL,
"Received packet, exiting light sleep");
powerFSM.add_transition(&stateNB, &stateNB, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, resetting win wake"); powerFSM.add_transition(&stateNB, &stateNB, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, resetting win wake");
// Handle press events - note: we ignore button presses when in API mode // Handle press events - note: we ignore button presses when in API mode
@@ -258,7 +260,8 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press"); powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_PRESS, screenPress, "Press"); powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_PRESS, screenPress, "Press");
powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers
powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress, "Press"); // Allow button to work while in serial API powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress,
"Press"); // Allow button to work while in serial API
// Handle critically low power battery by forcing deep sleep // Handle critically low power battery by forcing deep sleep
powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat"); powerFSM.add_transition(&stateBOOT, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
@@ -324,31 +327,28 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone"); powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
// each time we get a new update packet make sure we are staying in the ON state so the screen stays awake (also we don't powerFSM.add_timed_transition(&stateON, &stateDARK,
// shutdown bluetooth if is_router) getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update"); "Screen-on timeout");
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
powerFSM.add_timed_transition(&stateON, &stateDARK, getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, "Screen-on timeout");
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
State *lowPowerState = &stateLS;
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
State *lowPowerState = &stateLS;
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally) // We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
// See: https://github.com/meshtastic/firmware/issues/1071 // See: https://github.com/meshtastic/firmware/issues/1071
if (isRouter || config.power.is_power_saving) { if (isRouter || config.power.is_power_saving) {
powerFSM.add_timed_transition(&stateNB, &stateLS, getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, "Min wake timeout"); powerFSM.add_timed_transition(&stateNB, &stateLS,
powerFSM.add_timed_transition(&stateDARK, &stateLS, getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, "Bluetooth timeout"); getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
"Min wake timeout");
powerFSM.add_timed_transition(&stateDARK, &stateLS,
getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs),
NULL, "Bluetooth timeout");
} }
#elif defined (ARCH_NRF52)
lowPowerState = &stateDARK;
#endif
if (config.power.sds_secs != UINT32_MAX) if (config.power.sds_secs != UINT32_MAX)
powerFSM.add_timed_transition(lowPowerState, &stateSDS, config.power.sds_secs * 1000, NULL, "mesh timeout"); powerFSM.add_timed_transition(lowPowerState, &stateSDS, getConfiguredOrDefaultMs(config.power.sds_secs), NULL,
"mesh timeout");
#endif
powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state
} }

View File

@@ -19,7 +19,7 @@
#define EVENT_POWER_CONNECTED 13 #define EVENT_POWER_CONNECTED 13
#define EVENT_POWER_DISCONNECTED 14 #define EVENT_POWER_DISCONNECTED 14
#define EVENT_FIRMWARE_UPDATE 15 // We just received a new firmware update packet from the phone #define EVENT_FIRMWARE_UPDATE 15 // We just received a new firmware update packet from the phone
#define EVENT_SHUTDOWN 16 //force a full shutdown now (not just sleep) #define EVENT_SHUTDOWN 16 // force a full shutdown now (not just sleep)
#define EVENT_INPUT 17 // input broker wants something, we need to wake up and enable screen #define EVENT_INPUT 17 // input broker wants something, we need to wake up and enable screen
extern Fsm powerFSM; extern Fsm powerFSM;

View File

@@ -26,11 +26,10 @@ class PowerFSMThread : public OSThread
if (powerStatus->getHasUSB()) { if (powerStatus->getHasUSB()) {
timeLastPowered = millis(); timeLastPowered = millis();
} else if (config.power.on_battery_shutdown_after_secs > 0 && } else if (config.power.on_battery_shutdown_after_secs > 0 && config.power.on_battery_shutdown_after_secs != UINT32_MAX &&
millis() > millis() > (timeLastPowered +
timeLastPowered + getConfiguredOrDefaultMs(
(1000 * config.power.on_battery_shutdown_after_secs))) { // shutdown after 30 minutes unpowered
config.power.on_battery_shutdown_after_secs)) { // shutdown after 30 minutes unpowered
powerFSM.trigger(EVENT_SHUTDOWN); powerFSM.trigger(EVENT_SHUTDOWN);
} }

View File

@@ -82,7 +82,7 @@ class PowerStatus : public Status
isCharging = newStatus->isCharging; isCharging = newStatus->isCharging;
} }
if (isDirty) { if (isDirty) {
// DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent); // LOG_DEBUG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent);
onNewStatus.notifyObservers(this); onNewStatus.notifyObservers(this);
} }
return 0; return 0;

View File

@@ -1,13 +1,12 @@
#include "configuration.h"
#include "RedirectablePrint.h" #include "RedirectablePrint.h"
#include "RTC.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "RTC.h"
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
// #include "wifi/WiFiServerAPI.h" #include "configuration.h"
#include <assert.h> #include <assert.h>
#include <cstring>
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#include <cstring>
/** /**
* A printer that doesn't go anywhere * A printer that doesn't go anywhere
@@ -27,10 +26,6 @@ size_t RedirectablePrint::write(uint8_t c)
SEGGER_RTT_PutChar(SEGGER_STDOUT_CH, c); SEGGER_RTT_PutChar(SEGGER_STDOUT_CH, c);
#endif #endif
// FIXME - clean this up, the whole relationship of this class to SerialConsole to TCP/bluetooth debug log output is kinda messed up. But for now, just have this hack to
// optionally send chars to TCP also
//WiFiServerPort::debugOut(c);
if (!config.has_lora || config.device.serial_enabled) if (!config.has_lora || config.device.serial_enabled)
dest->write(c); dest->write(c);
@@ -47,7 +42,8 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg)
size_t len = vsnprintf(printBuf, sizeof(printBuf), format, copy); size_t len = vsnprintf(printBuf, sizeof(printBuf), format, copy);
va_end(copy); va_end(copy);
// If the resulting string is longer than sizeof(printBuf)-1 characters, the remaining characters are still counted for the return value // If the resulting string is longer than sizeof(printBuf)-1 characters, the remaining characters are still counted for the
// return value
if (len > sizeof(printBuf) - 1) { if (len > sizeof(printBuf) - 1) {
len = sizeof(printBuf) - 1; len = sizeof(printBuf) - 1;
@@ -58,7 +54,7 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg)
return len; return len;
} }
size_t RedirectablePrint::logDebug(const char *format, ...) size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
{ {
size_t r = 0; size_t r = 0;
@@ -86,9 +82,9 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
r += printf("%02d:%02d:%02d %u ", hour, min, sec, millis() / 1000); r += printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
} else } else
r += printf("??:??:?? %u ", millis() / 1000); r += printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
auto thread = concurrency::OSThread::currentThread; auto thread = concurrency::OSThread::currentThread;
if (thread) { if (thread) {
@@ -99,7 +95,6 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
print("] "); print("] ");
} }
} }
r += vprintf(format, arg); r += vprintf(format, arg);
va_end(arg); va_end(arg);
@@ -109,3 +104,35 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
return r; return r;
} }
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");
for (uint16_t i = 0; i < len; i += 16) {
if (i % 128 == 0)
log(logLevel, " +------------------------------------------------+ +----------------+\n");
char s[] = "| | | |\n";
uint8_t ix = 1, iy = 52;
for (uint8_t j = 0; j < 16; j++) {
if (i + j < len) {
uint8_t c = buf[i + j];
s[ix++] = alphabet[(c >> 4) & 0x0F];
s[ix++] = alphabet[c & 0x0F];
ix++;
if (c > 31 && c < 128)
s[iy++] = c;
else
s[iy++] = '.';
}
}
uint8_t index = i / 16;
if (i < 256)
log(logLevel, " ");
log(logLevel, "%02x", index);
log(logLevel, ".");
log(logLevel, s);
}
log(logLevel, " +------------------------------------------------+ +----------------+\n");
}

View File

@@ -33,14 +33,13 @@ class RedirectablePrint : public Print
* If the provide format string ends with a newline we assume it is the final print of a single * If the provide format string ends with a newline we assume it is the final print of a single
* log message. Otherwise we assume more prints will come before the log message ends. This * log message. Otherwise we assume more prints will come before the log message ends. This
* allows you to call logDebug a few times to build up a single log message line if you wish. * allows you to call logDebug a few times to build up a single log message line if you wish.
*
* FIXME, eventually add log levels (INFO, WARN, ERROR) and subsystems. Move into
* a different class.
*/ */
size_t logDebug(const char * format, ...) __attribute__ ((format (printf, 2, 3))); size_t log(const char *logLevel, const char *format, ...) __attribute__((format(printf, 3, 4)));
/** like printf but va_list based */ /** like printf but va_list based */
size_t vprintf(const char *format, va_list arg); size_t vprintf(const char *format, va_list arg);
void hexDump(const char *logLevel, unsigned char *buf, uint16_t len);
}; };
class NoopPrint : public Print class NoopPrint : public Print

View File

@@ -1,5 +1,5 @@
#include "configuration.h"
#include "SPILock.h" #include "SPILock.h"
#include "configuration.h"
#include <Arduino.h> #include <Arduino.h>
#include <assert.h> #include <assert.h>

View File

@@ -20,12 +20,10 @@ void consolePrintf(const char *format, ...)
va_start(arg, format); va_start(arg, format);
console->vprintf(format, arg); console->vprintf(format, arg);
va_end(arg); va_end(arg);
#ifdef ARCH_ESP32
console->flush(); console->flush();
#endif
} }
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port) SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), concurrency::OSThread("SerialConsole")
{ {
assert(!console); assert(!console);
console = this; console = this;
@@ -33,7 +31,7 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
// setDestination(&noopPrint); for testing, try turning off 'all' debug output and see what leaks // setDestination(&noopPrint); for testing, try turning off 'all' debug output and see what leaks
Port.begin(SERIAL_BAUD); Port.begin(SERIAL_BAUD);
#ifdef ARCH_NRF52 #if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
time_t timeout = millis(); time_t timeout = millis();
while (!Port) { while (!Port) {
if ((millis() - timeout) < 5000) { if ((millis() - timeout) < 5000) {
@@ -46,6 +44,15 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
emitRebooted(); emitRebooted();
} }
int32_t SerialConsole::runOnce()
{
return runOncePart();
}
void SerialConsole::flush()
{
Port.flush();
}
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages // For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
bool SerialConsole::checkIsConnected() bool SerialConsole::checkIsConnected()
@@ -68,7 +75,7 @@ bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
canWrite = true; canWrite = true;
return StreamAPI::handleToRadio(buf, len); return StreamAPI::handleToRadio(buf, len);
}else{ } else {
return false; return false;
} }
} }

View File

@@ -6,7 +6,7 @@
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs * Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs). * (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
*/ */
class SerialConsole : public StreamAPI, public RedirectablePrint class SerialConsole : public StreamAPI, public RedirectablePrint, private concurrency::OSThread
{ {
public: public:
SerialConsole(); SerialConsole();
@@ -24,8 +24,11 @@ class SerialConsole : public StreamAPI, public RedirectablePrint
return RedirectablePrint::write(c); return RedirectablePrint::write(c);
} }
protected: virtual int32_t runOnce() override;
void flush();
protected:
/// Check the current underlying physical link to see if the client is currently connected /// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() override; virtual bool checkIsConnected() override;
}; };

View File

@@ -8,16 +8,16 @@
#define STATUS_TYPE_GPS 2 #define STATUS_TYPE_GPS 2
#define STATUS_TYPE_NODE 3 #define STATUS_TYPE_NODE 3
namespace meshtastic namespace meshtastic
{ {
// A base class for observable status // A base class for observable status
class Status class Status
{ {
protected: protected:
// Allows us to observe an Observable // Allows us to observe an Observable
CallbackObserver<Status, const Status *> statusObserver = CallbackObserver<Status, const Status *>(this, &Status::updateStatus); CallbackObserver<Status, const Status *> statusObserver =
CallbackObserver<Status, const Status *>(this, &Status::updateStatus);
bool initialized = false; bool initialized = false;
// Workaround for no typeid support // Workaround for no typeid support
int statusType = 0; int statusType = 0;
@@ -29,9 +29,9 @@ namespace meshtastic
// Enable polymorphism ? // Enable polymorphism ?
virtual ~Status() = default; virtual ~Status() = default;
Status() { Status()
if (!statusType)
{ {
if (!statusType) {
statusType = STATUS_TYPE_BASE; statusType = STATUS_TYPE_BASE;
} }
} }
@@ -41,32 +41,16 @@ namespace meshtastic
Status &operator=(const Status &) = delete; Status &operator=(const Status &) = delete;
// Start observing a source of data // Start observing a source of data
void observe(Observable<const Status *> *source) void observe(Observable<const Status *> *source) { statusObserver.observe(source); }
{
statusObserver.observe(source);
}
// Determines whether or not existing data matches the data in another Status instance // Determines whether or not existing data matches the data in another Status instance
bool matches(const Status *otherStatus) const bool matches(const Status *otherStatus) const { return true; }
{
return true;
}
bool isInitialized() const bool isInitialized() const { return initialized; }
{
return initialized;
}
int getStatusType() const int getStatusType() const { return statusType; }
{
return statusType;
}
// Called when the Observable we're observing generates a new notification // Called when the Observable we're observing generates a new notification
int updateStatus(const Status *newStatus) int updateStatus(const Status *newStatus) { return 0; }
{
return 0;
}
};
}; };
}; // namespace meshtastic

View File

@@ -10,18 +10,18 @@ void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
{ {
if (reportType == TX_LOG) { if (reportType == TX_LOG) {
DEBUG_MSG("AirTime - Packet transmitted : %ums\n", airtime_ms); LOG_DEBUG("AirTime - Packet transmitted : %ums\n", airtime_ms);
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms; this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
myNodeInfo.air_period_tx[0] = myNodeInfo.air_period_tx[0] + airtime_ms; myNodeInfo.air_period_tx[0] = myNodeInfo.air_period_tx[0] + airtime_ms;
this->utilizationTX[this->getPeriodUtilHour()] = this->utilizationTX[this->getPeriodUtilHour()] + airtime_ms; this->utilizationTX[this->getPeriodUtilHour()] = this->utilizationTX[this->getPeriodUtilHour()] + airtime_ms;
} else if (reportType == RX_LOG) { } else if (reportType == RX_LOG) {
DEBUG_MSG("AirTime - Packet received : %ums\n", airtime_ms); LOG_DEBUG("AirTime - Packet received : %ums\n", airtime_ms);
this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms; this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms;
myNodeInfo.air_period_rx[0] = myNodeInfo.air_period_rx[0] + airtime_ms; myNodeInfo.air_period_rx[0] = myNodeInfo.air_period_rx[0] + airtime_ms;
} else if (reportType == RX_ALL_LOG) { } else if (reportType == RX_ALL_LOG) {
DEBUG_MSG("AirTime - Packet received (noise?) : %ums\n", airtime_ms); LOG_DEBUG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms; this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
} }
@@ -34,11 +34,13 @@ uint8_t AirTime::currentPeriodIndex()
return ((getSecondsSinceBoot() / SECONDS_PER_PERIOD) % PERIODS_TO_LOG); return ((getSecondsSinceBoot() / SECONDS_PER_PERIOD) % PERIODS_TO_LOG);
} }
uint8_t AirTime::getPeriodUtilMinute() { uint8_t AirTime::getPeriodUtilMinute()
{
return (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS; return (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS;
} }
uint8_t AirTime::getPeriodUtilHour() { uint8_t AirTime::getPeriodUtilHour()
{
return (getSecondsSinceBoot() / 60) % MINUTES_IN_HOUR; return (getSecondsSinceBoot() / 60) % MINUTES_IN_HOUR;
} }
@@ -46,7 +48,7 @@ void AirTime::airtimeRotatePeriod()
{ {
if (this->airtimes.lastPeriodIndex != this->currentPeriodIndex()) { if (this->airtimes.lastPeriodIndex != this->currentPeriodIndex()) {
DEBUG_MSG("Rotating airtimes to a new period = %u\n", this->currentPeriodIndex()); LOG_DEBUG("Rotating airtimes to a new period = %u\n", this->currentPeriodIndex());
for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) { for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) {
this->airtimes.periodTX[i + 1] = this->airtimes.periodTX[i]; this->airtimes.periodTX[i + 1] = this->airtimes.periodTX[i];
@@ -101,7 +103,7 @@ float AirTime::channelUtilizationPercent()
uint32_t sum = 0; uint32_t sum = 0;
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) { for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
sum += this->channelUtilization[i]; sum += this->channelUtilization[i];
// DEBUG_MSG("ChanUtilArray %u %u\n", i, this->channelUtilization[i]); // LOG_DEBUG("ChanUtilArray %u %u\n", i, this->channelUtilization[i]);
} }
return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100; return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100;
@@ -117,9 +119,46 @@ float AirTime::utilizationTXPercent()
return (float(sum) / float(MS_IN_HOUR)) * 100; return (float(sum) / float(MS_IN_HOUR)) * 100;
} }
AirTime::AirTime() : concurrency::OSThread("AirTime"),airtimes({}) { bool AirTime::isTxAllowedChannelUtil(bool polite)
{
uint8_t percentage = (polite ? polite_channel_util_percent : max_channel_util_percent);
if (channelUtilizationPercent() < percentage) {
return true;
} else {
LOG_WARN("Channel utilization is >%d percent. Skipping this opportunity to send.\n", percentage);
return false;
}
} }
bool AirTime::isTxAllowedAirUtil()
{
if (!config.lora.override_duty_cycle && myRegion->dutyCycle < 100) {
if (utilizationTXPercent() < myRegion->dutyCycle * polite_duty_cycle_percent / 100) {
return true;
} else {
LOG_WARN("Tx air utilization is >%f percent. Skipping this opportunity to send.\n",
myRegion->dutyCycle * polite_duty_cycle_percent / 100);
return false;
}
}
return true;
}
// Get the amount of minutes we have to be silent before we can send again
uint8_t AirTime::getSilentMinutes(float txPercent, float dutyCycle)
{
float newTxPercent = txPercent;
for (int8_t i = MINUTES_IN_HOUR - 1; i >= 0; --i) {
newTxPercent -= ((float)this->utilizationTX[i] / (MS_IN_MINUTE * MINUTES_IN_HOUR / 100));
if (newTxPercent < dutyCycle)
return MINUTES_IN_HOUR - 1 - i;
}
return MINUTES_IN_HOUR;
}
AirTime::AirTime() : concurrency::OSThread("AirTime"), airtimes({}) {}
int32_t AirTime::runOnce() int32_t AirTime::runOnce()
{ {
secSinceBoot++; secSinceBoot++;
@@ -174,14 +213,14 @@ int32_t AirTime::runOnce()
// Update channel_utilization every second. // Update channel_utilization every second.
myNodeInfo.air_util_tx = airTime->utilizationTXPercent(); myNodeInfo.air_util_tx = airTime->utilizationTXPercent();
} }
/* /*
DEBUG_MSG("utilPeriodTX %d TX Airtime %3.2f%\n", utilPeriodTX, airTime->utilizationTXPercent()); LOG_DEBUG("utilPeriodTX %d TX Airtime %3.2f%\n", utilPeriodTX, airTime->utilizationTXPercent());
for (uint32_t i = 0; i < MINUTES_IN_HOUR; i++) { for (uint32_t i = 0; i < MINUTES_IN_HOUR; i++) {
DEBUG_MSG( LOG_DEBUG(
"%d,", this->utilizationTX[i] "%d,", this->utilizationTX[i]
); );
} }
DEBUG_MSG("\n"); LOG_DEBUG("\n");
*/ */
return (1000 * 1); return (1000 * 1);
} }

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "MeshRadio.h"
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
#include "configuration.h" #include "configuration.h"
#include <Arduino.h> #include <Arduino.h>
@@ -29,9 +30,9 @@
#define PERIODS_TO_LOG 8 #define PERIODS_TO_LOG 8
#define MINUTES_IN_HOUR 60 #define MINUTES_IN_HOUR 60
#define SECONDS_IN_MINUTE 60 #define SECONDS_IN_MINUTE 60
#define MS_IN_MINUTE (SECONDS_IN_MINUTE * 1000)
#define MS_IN_HOUR (MINUTES_IN_HOUR * SECONDS_IN_MINUTE * 1000) #define MS_IN_HOUR (MINUTES_IN_HOUR * SECONDS_IN_MINUTE * 1000)
enum reportTypes { TX_LOG, RX_LOG, RX_ALL_LOG }; enum reportTypes { TX_LOG, RX_LOG, RX_ALL_LOG };
void logAirtime(reportTypes reportType, uint32_t airtime_ms); void logAirtime(reportTypes reportType, uint32_t airtime_ms);
@@ -57,12 +58,18 @@ class AirTime : private concurrency::OSThread
uint32_t getSecondsPerPeriod(); uint32_t getSecondsPerPeriod();
uint32_t getSecondsSinceBoot(); uint32_t getSecondsSinceBoot();
uint32_t *airtimeReport(reportTypes reportType); uint32_t *airtimeReport(reportTypes reportType);
uint8_t getSilentMinutes(float txPercent, float dutyCycle);
bool isTxAllowedChannelUtil(bool polite = false);
bool isTxAllowedAirUtil();
private: private:
bool firstTime = true; bool firstTime = true;
uint8_t lastUtilPeriod = 0; uint8_t lastUtilPeriod = 0;
uint8_t lastUtilPeriodTX = 0; uint8_t lastUtilPeriodTX = 0;
uint32_t secSinceBoot = 0; uint32_t secSinceBoot = 0;
uint8_t max_channel_util_percent = 40;
uint8_t polite_channel_util_percent = 25;
uint8_t polite_duty_cycle_percent = 50; // half of Duty Cycle allowance is ok for metadata
struct airtimeStruct { struct airtimeStruct {
uint32_t periodTX[PERIODS_TO_LOG]; // AirTime transmitted uint32_t periodTX[PERIODS_TO_LOG]; // AirTime transmitted

View File

@@ -1,6 +1,6 @@
#include "buzz.h" #include "buzz.h"
#include "configuration.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "configuration.h"
#if !defined(ARCH_ESP32) && !defined(ARCH_RP2040) && !defined(ARCH_PORTDUINO) #if !defined(ARCH_ESP32) && !defined(ARCH_RP2040) && !defined(ARCH_PORTDUINO)
#include "Tone.h" #include "Tone.h"
@@ -33,7 +33,8 @@ struct ToneDuration {
const int DURATION_1_8 = 125; // 1/8 note const int DURATION_1_8 = 125; // 1/8 note
const int DURATION_1_4 = 250; // 1/4 note const int DURATION_1_4 = 250; // 1/4 note
void playTones(const ToneDuration *tone_durations, int size) { void playTones(const ToneDuration *tone_durations, int size)
{
#ifdef PIN_BUZZER #ifdef PIN_BUZZER
if (!config.device.buzzer_gpio) if (!config.device.buzzer_gpio)
config.device.buzzer_gpio = PIN_BUZZER; config.device.buzzer_gpio = PIN_BUZZER;
@@ -48,22 +49,20 @@ void playTones(const ToneDuration *tone_durations, int size) {
} }
} }
void playBeep()
void playBeep() { {
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4}}; ToneDuration melody[] = {{NOTE_B3, DURATION_1_4}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration)); playTones(melody, sizeof(melody) / sizeof(ToneDuration));
} }
void playStartMelody() { void playStartMelody()
ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8}, {
{NOTE_AS3, DURATION_1_8}, ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8}, {NOTE_AS3, DURATION_1_8}, {NOTE_CS4, DURATION_1_4}};
{NOTE_CS4, DURATION_1_4}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration)); playTones(melody, sizeof(melody) / sizeof(ToneDuration));
} }
void playShutdownMelody() { void playShutdownMelody()
ToneDuration melody[] = {{NOTE_CS4, DURATION_1_8}, {
{NOTE_AS3, DURATION_1_8}, ToneDuration melody[] = {{NOTE_CS4, DURATION_1_8}, {NOTE_AS3, DURATION_1_8}, {NOTE_FS3, DURATION_1_4}};
{NOTE_FS3, DURATION_1_4}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration)); playTones(melody, sizeof(melody) / sizeof(ToneDuration));
} }

View File

@@ -1,5 +1,5 @@
#include "configuration.h"
#include "concurrency/BinarySemaphoreFreeRTOS.h" #include "concurrency/BinarySemaphoreFreeRTOS.h"
#include "configuration.h"
#include <assert.h> #include <assert.h>
#ifdef HAS_FREE_RTOS #ifdef HAS_FREE_RTOS

View File

@@ -1,18 +1,14 @@
#include "configuration.h"
#include "concurrency/BinarySemaphorePosix.h" #include "concurrency/BinarySemaphorePosix.h"
#include "configuration.h"
#ifndef HAS_FREE_RTOS #ifndef HAS_FREE_RTOS
namespace concurrency namespace concurrency
{ {
BinarySemaphorePosix::BinarySemaphorePosix() BinarySemaphorePosix::BinarySemaphorePosix() {}
{
}
BinarySemaphorePosix::~BinarySemaphorePosix() BinarySemaphorePosix::~BinarySemaphorePosix() {}
{
}
/** /**
* Returns false if we timed out * Returns false if we timed out
@@ -23,13 +19,9 @@ bool BinarySemaphorePosix::take(uint32_t msec)
return false; return false;
} }
void BinarySemaphorePosix::give() void BinarySemaphorePosix::give() {}
{
}
IRAM_ATTR void BinarySemaphorePosix::giveFromISR(BaseType_t *pxHigherPriorityTaskWoken) IRAM_ATTR void BinarySemaphorePosix::giveFromISR(BaseType_t *pxHigherPriorityTaskWoken) {}
{
}
} // namespace concurrency } // namespace concurrency

View File

@@ -1,5 +1,5 @@
#include "configuration.h"
#include "concurrency/InterruptableDelay.h" #include "concurrency/InterruptableDelay.h"
#include "configuration.h"
namespace concurrency namespace concurrency
{ {
@@ -13,12 +13,12 @@ InterruptableDelay::~InterruptableDelay() {}
*/ */
bool InterruptableDelay::delay(uint32_t msec) bool InterruptableDelay::delay(uint32_t msec)
{ {
// DEBUG_MSG("delay %u ", msec); // LOG_DEBUG("delay %u ", msec);
// sem take will return false if we timed out (i.e. were not interrupted) // sem take will return false if we timed out (i.e. were not interrupted)
bool r = semaphore.take(msec); bool r = semaphore.take(msec);
// DEBUG_MSG("interrupt=%d\n", r); // LOG_DEBUG("interrupt=%d\n", r);
return !r; return !r;
} }

View File

@@ -2,7 +2,6 @@
#include "../freertosinc.h" #include "../freertosinc.h"
#ifdef HAS_FREE_RTOS #ifdef HAS_FREE_RTOS
#include "concurrency/BinarySemaphoreFreeRTOS.h" #include "concurrency/BinarySemaphoreFreeRTOS.h"
#define BinarySemaphore BinarySemaphoreFreeRTOS #define BinarySemaphore BinarySemaphoreFreeRTOS

View File

@@ -1,5 +1,5 @@
#include "configuration.h"
#include "Lock.h" #include "Lock.h"
#include "configuration.h"
#include <cassert> #include <cassert>
namespace concurrency namespace concurrency

View File

@@ -1,7 +1,8 @@
#include "configuration.h"
#include "LockGuard.h" #include "LockGuard.h"
#include "configuration.h"
namespace concurrency { namespace concurrency
{
LockGuard::LockGuard(Lock *lock) : lock(lock) LockGuard::LockGuard(Lock *lock) : lock(lock)
{ {

View File

@@ -2,7 +2,8 @@
#include "Lock.h" #include "Lock.h"
namespace concurrency { namespace concurrency
{
/** /**
* @brief RAII lock guard * @brief RAII lock guard

View File

@@ -1,7 +1,6 @@
#include "configuration.h"
#include "NotifiedWorkerThread.h" #include "NotifiedWorkerThread.h"
#include "configuration.h"
#include "main.h" #include "main.h"
#include <assert.h>
namespace concurrency namespace concurrency
{ {
@@ -33,11 +32,11 @@ IRAM_ATTR bool NotifiedWorkerThread::notifyCommon(uint32_t v, bool overwrite)
notification = v; notification = v;
if (debugNotification) if (debugNotification)
DEBUG_MSG("setting notification %d\n", v); LOG_DEBUG("setting notification %d\n", v);
return true; return true;
} else { } else {
if (debugNotification) if (debugNotification)
DEBUG_MSG("dropping notification %d\n", v); LOG_DEBUG("dropping notification %d\n", v);
return false; return false;
} }
} }
@@ -66,7 +65,7 @@ bool NotifiedWorkerThread::notifyLater(uint32_t delay, uint32_t v, bool overwrit
if (didIt) { // If we didn't already have something queued, override the delay to be larger if (didIt) { // If we didn't already have something queued, override the delay to be larger
setIntervalFromNow(delay); // a new version of setInterval relative to the current time setIntervalFromNow(delay); // a new version of setInterval relative to the current time
if (debugNotification) if (debugNotification)
DEBUG_MSG("delaying notification %u\n", delay); LOG_DEBUG("delaying notification %u\n", delay);
} }
return didIt; return didIt;
@@ -81,8 +80,6 @@ void NotifiedWorkerThread::checkNotification()
} }
} }
int32_t NotifiedWorkerThread::runOnce() int32_t NotifiedWorkerThread::runOnce()
{ {
enabled = false; // Only run once per notification enabled = false; // Only run once per notification

View File

@@ -41,9 +41,9 @@ class NotifiedWorkerThread : public OSThread
/// just calls checkNotification() /// just calls checkNotification()
virtual int32_t runOnce() override; virtual int32_t runOnce() override;
/// Sometimes we might want to check notifications independently of when our thread was getting woken up (i.e. if we are about to change /// Sometimes we might want to check notifications independently of when our thread was getting woken up (i.e. if we are about
/// radio transmit/receive modes we want to handle any pending interrupts first). You can call this method and if any notifications are currently /// to change radio transmit/receive modes we want to handle any pending interrupts first). You can call this method and if
/// pending they will be handled immediately. /// any notifications are currently pending they will be handled immediately.
void checkNotification(); void checkNotification();
private: private:

View File

@@ -1,5 +1,5 @@
#include "configuration.h"
#include "OSThread.h" #include "OSThread.h"
#include "configuration.h"
#include <assert.h> #include <assert.h>
namespace concurrency namespace concurrency
@@ -61,21 +61,31 @@ bool OSThread::shouldRun(unsigned long time)
bool r = Thread::shouldRun(time); bool r = Thread::shouldRun(time);
if (showRun && r) if (showRun && r)
DEBUG_MSG("Thread %s: run\n", ThreadName.c_str()); LOG_DEBUG("Thread %s: run\n", ThreadName.c_str());
if (showWaiting && enabled && !r) if (showWaiting && enabled && !r)
DEBUG_MSG("Thread %s: wait %lu\n", ThreadName.c_str(), interval); LOG_DEBUG("Thread %s: wait %lu\n", ThreadName.c_str(), interval);
if (showDisabled && !enabled) if (showDisabled && !enabled)
DEBUG_MSG("Thread %s: disabled\n", ThreadName.c_str()); LOG_DEBUG("Thread %s: disabled\n", ThreadName.c_str());
return r; return r;
} }
void OSThread::run() void OSThread::run()
{ {
#ifdef DEBUG_HEAP
auto heap = ESP.getFreeHeap();
#endif
currentThread = this; currentThread = this;
auto newDelay = runOnce(); auto newDelay = runOnce();
#ifdef DEBUG_HEAP
auto newHeap = ESP.getFreeHeap();
if (newHeap < heap)
LOG_DEBUG("------ Thread %s leaked heap %d -> %d (%d) ------\n", ThreadName.c_str(), heap, newHeap, newHeap - heap);
if (heap < newHeap)
LOG_DEBUG("++++++ Thread %s freed heap %d -> %d (%d) ++++++\n", ThreadName.c_str(), heap, newHeap, newHeap - heap);
#endif
runned(); runned();
@@ -85,6 +95,14 @@ void OSThread::run()
currentThread = NULL; currentThread = NULL;
} }
int32_t OSThread::disable()
{
enabled = false;
setInterval(INT32_MAX);
return INT32_MAX;
}
/** /**
* This flag is set **only** when setup() starts, to provide a way for us to check for sloppy static constructor calls. * This flag is set **only** when setup() starts, to provide a way for us to check for sloppy static constructor calls.
* Call assertIsSetup() to force a crash if someone tries to create an instance too early. * Call assertIsSetup() to force a crash if someone tries to create an instance too early.

View File

@@ -53,6 +53,8 @@ class OSThread : public Thread
static void setup(); static void setup();
int32_t disable();
/** /**
* Wait a specified number msecs starting from the current time (rather than the last time we were run) * Wait a specified number msecs starting from the current time (rather than the last time we were run)
*/ */

View File

@@ -27,10 +27,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <Arduino.h> #include <Arduino.h>
#ifdef RV3028_RTC #ifdef RV3028_RTC
#include "Melopero_RV3028.h" #include "Melopero_RV3028.h"
#endif #endif
#ifdef PCF8563_RTC #ifdef PCF8563_RTC
#include "pcf8563.h" #include "pcf8563.h"
#endif #endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -42,7 +42,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#error APP_VERSION must be set by the build environment #error APP_VERSION must be set by the build environment
#endif #endif
// FIXME: This is still needed by the Bluetooth Stack and needs to be replaced by something better. Remnant of the old versioning system. // FIXME: This is still needed by the Bluetooth Stack and needs to be replaced by something better. Remnant of the old versioning
// system.
#ifndef HW_VERSION #ifndef HW_VERSION
#define HW_VERSION "1.0" #define HW_VERSION "1.0"
#endif #endif
@@ -64,13 +65,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Nop definition for these attributes that are specific to ESP32 // Nop definition for these attributes that are specific to ESP32
#ifndef EXT_RAM_ATTR #ifndef EXT_RAM_ATTR
#define EXT_RAM_ATTR #define EXT_RAM_ATTR
#endif #endif
#ifndef IRAM_ATTR #ifndef IRAM_ATTR
#define IRAM_ATTR #define IRAM_ATTR
#endif #endif
#ifndef RTC_DATA_ATTR #ifndef RTC_DATA_ATTR
#define RTC_DATA_ATTR #define RTC_DATA_ATTR
#endif #endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -114,6 +115,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SHTC3_ADDR 0x70 #define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C #define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D #define LPS22HB_ADDR_ALT 0x5D
#define SHT31_ADDR 0x44
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Security // Security
@@ -141,42 +143,42 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Step #3: mop up with disabled values for HAS_ options not handled by the above two */ /* Step #3: mop up with disabled values for HAS_ options not handled by the above two */
#ifndef HAS_WIFI #ifndef HAS_WIFI
#define HAS_WIFI 0 #define HAS_WIFI 0
#endif #endif
#ifndef HAS_ETHERNET #ifndef HAS_ETHERNET
#define HAS_ETHERNET 0 #define HAS_ETHERNET 0
#endif #endif
#ifndef HAS_SCREEN #ifndef HAS_SCREEN
#define HAS_SCREEN 0 #define HAS_SCREEN 0
#endif #endif
#ifndef HAS_WIRE #ifndef HAS_WIRE
#define HAS_WIRE 0 #define HAS_WIRE 0
#endif #endif
#ifndef HAS_GPS #ifndef HAS_GPS
#define HAS_GPS 0 #define HAS_GPS 0
#endif #endif
#ifndef HAS_BUTTON #ifndef HAS_BUTTON
#define HAS_BUTTON 0 #define HAS_BUTTON 0
#endif #endif
#ifndef HAS_TELEMETRY #ifndef HAS_TELEMETRY
#define HAS_TELEMETRY 0 #define HAS_TELEMETRY 0
#endif #endif
#ifndef HAS_RADIO #ifndef HAS_RADIO
#define HAS_RADIO 0 #define HAS_RADIO 0
#endif #endif
#ifndef HAS_RTC #ifndef HAS_RTC
#define HAS_RTC 0 #define HAS_RTC 0
#endif #endif
#ifndef HAS_CPU_SHUTDOWN #ifndef HAS_CPU_SHUTDOWN
#define HAS_CPU_SHUTDOWN 0 #define HAS_CPU_SHUTDOWN 0
#endif #endif
#ifndef HAS_BLUETOOTH #ifndef HAS_BLUETOOTH
#define HAS_BLUETOOTH 0 #define HAS_BLUETOOTH 0
#endif #endif
#include "RF95Configuration.h"
#include "DebugConfiguration.h" #include "DebugConfiguration.h"
#include "RF95Configuration.h"
#ifndef HW_VENDOR #ifndef HW_VENDOR
#error HW_VENDOR must be defined #error HW_VENDOR must be defined
#endif #endif

View File

@@ -3,13 +3,13 @@
uint32_t axpDebugRead() uint32_t axpDebugRead()
{ {
axp.debugCharging(); axp.debugCharging();
DEBUG_MSG("vbus current %f\n", axp.getVbusCurrent()); LOG_DEBUG("vbus current %f\n", axp.getVbusCurrent());
DEBUG_MSG("charge current %f\n", axp.getBattChargeCurrent()); LOG_DEBUG("charge current %f\n", axp.getBattChargeCurrent());
DEBUG_MSG("bat voltage %f\n", axp.getBattVoltage()); LOG_DEBUG("bat voltage %f\n", axp.getBattVoltage());
DEBUG_MSG("batt pct %d\n", axp.getBattPercentage()); LOG_DEBUG("batt pct %d\n", axp.getBattPercentage());
DEBUG_MSG("is battery connected %d\n", axp.isBatteryConnect()); LOG_DEBUG("is battery connected %d\n", axp.isBatteryConnect());
DEBUG_MSG("is USB connected %d\n", axp.isVBUSPlug()); LOG_DEBUG("is USB connected %d\n", axp.isVBUSPlug());
DEBUG_MSG("is charging %d\n", axp.isChargeing()); LOG_DEBUG("is charging %d\n", axp.isChargeing());
return 30 * 1000; return 30 * 1000;
} }

View File

@@ -7,41 +7,48 @@
void d_writeCommand(uint8_t c) void d_writeCommand(uint8_t c)
{ {
SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, LOW); if (PIN_EINK_DC >= 0)
if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW); digitalWrite(PIN_EINK_DC, LOW);
if (PIN_EINK_CS >= 0)
digitalWrite(PIN_EINK_CS, LOW);
SPI1.transfer(c); SPI1.transfer(c);
if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH); if (PIN_EINK_CS >= 0)
if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, HIGH); digitalWrite(PIN_EINK_CS, HIGH);
if (PIN_EINK_DC >= 0)
digitalWrite(PIN_EINK_DC, HIGH);
SPI1.endTransaction(); SPI1.endTransaction();
} }
void d_writeData(uint8_t d) void d_writeData(uint8_t d)
{ {
SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW); if (PIN_EINK_CS >= 0)
digitalWrite(PIN_EINK_CS, LOW);
SPI1.transfer(d); SPI1.transfer(d);
if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH); if (PIN_EINK_CS >= 0)
digitalWrite(PIN_EINK_CS, HIGH);
SPI1.endTransaction(); SPI1.endTransaction();
} }
unsigned long d_waitWhileBusy(uint16_t busy_time) unsigned long d_waitWhileBusy(uint16_t busy_time)
{ {
if (PIN_EINK_BUSY >= 0) if (PIN_EINK_BUSY >= 0) {
{
delay(1); // add some margin to become active delay(1); // add some margin to become active
unsigned long start = micros(); unsigned long start = micros();
while (1) while (1) {
{ if (digitalRead(PIN_EINK_BUSY) != HIGH)
if (digitalRead(PIN_EINK_BUSY) != HIGH) break; break;
delay(1); delay(1);
if (digitalRead(PIN_EINK_BUSY) != HIGH) break; if (digitalRead(PIN_EINK_BUSY) != HIGH)
if (micros() - start > 10000000) break; break;
if (micros() - start > 10000000)
break;
} }
unsigned long elapsed = micros() - start; unsigned long elapsed = micros() - start;
(void) start; (void)start;
return elapsed; return elapsed;
} } else
else return busy_time; return busy_time;
} }
void scanEInkDevice(void) void scanEInkDevice(void)
@@ -51,10 +58,10 @@ void scanEInkDevice(void)
d_writeData(0x83); d_writeData(0x83);
d_writeCommand(0x20); d_writeCommand(0x20);
eink_found = (d_waitWhileBusy(150) > 0) ? true : false; eink_found = (d_waitWhileBusy(150) > 0) ? true : false;
if(eink_found) if (eink_found)
DEBUG_MSG("EInk display found\n"); LOG_DEBUG("EInk display found\n");
else else
DEBUG_MSG("EInk display not found\n"); LOG_DEBUG("EInk display not found\n");
SPI1.end(); SPI1.end();
} }
#endif #endif

View File

@@ -1,7 +1,7 @@
#include "../configuration.h" #include "../configuration.h"
#include "../main.h" #include "../main.h"
#include "mesh/generated/meshtastic/telemetry.pb.h"
#include <Wire.h> #include <Wire.h>
#include "mesh/generated/telemetry.pb.h"
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp // AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS #ifndef XPOWERS_AXP192_AXP2101_ADDRESS
@@ -15,43 +15,44 @@ void printATECCInfo()
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) #if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
atecc.readConfigZone(false); atecc.readConfigZone(false);
DEBUG_MSG("ATECC608B Serial Number: "); LOG_DEBUG("ATECC608B Serial Number: ");
for (int i = 0 ; i < 9 ; i++) { for (int i = 0; i < 9; i++) {
DEBUG_MSG("%02x",atecc.serialNumber[i]); LOG_DEBUG("%02x", atecc.serialNumber[i]);
} }
DEBUG_MSG(", Rev Number: "); LOG_DEBUG(", Rev Number: ");
for (int i = 0 ; i < 4 ; i++) { for (int i = 0; i < 4; i++) {
DEBUG_MSG("%02x",atecc.revisionNumber[i]); LOG_DEBUG("%02x", atecc.revisionNumber[i]);
} }
DEBUG_MSG("\n"); LOG_DEBUG("\n");
DEBUG_MSG("ATECC608B Config %s",atecc.configLockStatus ? "Locked" : "Unlocked"); LOG_DEBUG("ATECC608B Config %s", atecc.configLockStatus ? "Locked" : "Unlocked");
DEBUG_MSG(", Data %s",atecc.dataOTPLockStatus ? "Locked" : "Unlocked"); LOG_DEBUG(", Data %s", atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
DEBUG_MSG(", Slot 0 %s\n",atecc.slot0LockStatus ? "Locked" : "Unlocked"); LOG_DEBUG(", Slot 0 %s\n", atecc.slot0LockStatus ? "Locked" : "Unlocked");
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) { if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
if (atecc.generatePublicKey() == false) { if (atecc.generatePublicKey() == false) {
DEBUG_MSG("ATECC608B Error generating public key\n"); LOG_DEBUG("ATECC608B Error generating public key\n");
} else { } else {
DEBUG_MSG("ATECC608B Public Key: "); LOG_DEBUG("ATECC608B Public Key: ");
for (int i = 0 ; i < 64 ; i++) { for (int i = 0; i < 64; i++) {
DEBUG_MSG("%02x",atecc.publicKey64Bytes[i]); LOG_DEBUG("%02x", atecc.publicKey64Bytes[i]);
} }
DEBUG_MSG("\n"); LOG_DEBUG("\n");
} }
} }
#endif #endif
} }
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length) { uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length)
{
uint16_t value = 0x00; uint16_t value = 0x00;
Wire.beginTransmission(address); Wire.beginTransmission(address);
Wire.write(reg); Wire.write(reg);
Wire.endTransmission(); Wire.endTransmission();
delay(20); delay(20);
Wire.requestFrom(address, length); Wire.requestFrom(address, length);
DEBUG_MSG("Wire.available() = %d\n", Wire.available()); LOG_DEBUG("Wire.available() = %d\n", Wire.available());
if (Wire.available() == 2) { if (Wire.available() == 2) {
// Read MSB, then LSB // Read MSB, then LSB
value = (uint16_t)Wire.read() << 8; value = (uint16_t)Wire.read() << 8;
@@ -81,12 +82,12 @@ uint8_t oled_probe(byte addr)
if (r == 0x08 || r == 0x00) { if (r == 0x08 || r == 0x00) {
o_probe = 2; // SH1106 o_probe = 2; // SH1106
} else if ( r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) { } else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
o_probe = 1; // SSD1306 o_probe = 1; // SSD1306
} }
c++; c++;
} while ((r != r_prev) && (c < 4)); } while ((r != r_prev) && (c < 4));
DEBUG_MSG("0x%x subtype probed in %i tries \n", r, c); LOG_DEBUG("0x%x subtype probed in %i tries \n", r, c);
return o_probe; return o_probe;
} }
@@ -99,7 +100,7 @@ void scanI2Cdevice()
Wire.beginTransmission(addr); Wire.beginTransmission(addr);
err = Wire.endTransmission(); err = Wire.endTransmission();
if (err == 0) { if (err == 0) {
DEBUG_MSG("I2C device found at address 0x%x\n", addr); LOG_DEBUG("I2C device found at address 0x%x\n", addr);
nDevices++; nDevices++;
@@ -107,38 +108,38 @@ void scanI2Cdevice()
screen_found = addr; screen_found = addr;
screen_model = oled_probe(addr); screen_model = oled_probe(addr);
if (screen_model == 1) { if (screen_model == 1) {
DEBUG_MSG("ssd1306 display found\n"); LOG_INFO("ssd1306 display found\n");
} else if (screen_model == 2) { } else if (screen_model == 2) {
DEBUG_MSG("sh1106 display found\n"); LOG_INFO("sh1106 display found\n");
} else { } else {
DEBUG_MSG("unknown display found\n"); LOG_INFO("unknown display found\n");
} }
} }
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) #if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
if (addr == ATECC608B_ADDR) { if (addr == ATECC608B_ADDR) {
keystore_found = addr; keystore_found = addr;
if (atecc.begin(keystore_found) == true) { if (atecc.begin(keystore_found) == true) {
DEBUG_MSG("ATECC608B initialized\n"); LOG_INFO("ATECC608B initialized\n");
} else { } else {
DEBUG_MSG("ATECC608B initialization failed\n"); LOG_WARN("ATECC608B initialization failed\n");
} }
printATECCInfo(); printATECCInfo();
} }
#endif #endif
#ifdef RV3028_RTC #ifdef RV3028_RTC
if (addr == RV3028_RTC){ if (addr == RV3028_RTC) {
rtc_found = addr; rtc_found = addr;
DEBUG_MSG("RV3028 RTC found\n"); LOG_INFO("RV3028 RTC found\n");
Melopero_RV3028 rtc; Melopero_RV3028 rtc;
rtc.initI2C(); rtc.initI2C();
rtc.writeToRegister(0x35,0x07); // no Clkout rtc.writeToRegister(0x35, 0x07); // no Clkout
rtc.writeToRegister(0x37,0xB4); rtc.writeToRegister(0x37, 0xB4);
} }
#endif #endif
#ifdef PCF8563_RTC #ifdef PCF8563_RTC
if (addr == PCF8563_RTC){ if (addr == PCF8563_RTC) {
rtc_found = addr; rtc_found = addr;
DEBUG_MSG("PCF8563 RTC found\n"); LOG_INFO("PCF8563 RTC found\n");
} }
#endif #endif
if (addr == CARDKB_ADDR) { if (addr == CARDKB_ADDR) {
@@ -146,82 +147,86 @@ void scanI2Cdevice()
// Do we have the RAK14006 instead? // Do we have the RAK14006 instead?
registerValue = getRegisterValue(addr, 0x04, 1); registerValue = getRegisterValue(addr, 0x04, 1);
if (registerValue == 0x02) { // KEYPAD_VERSION if (registerValue == 0x02) { // KEYPAD_VERSION
DEBUG_MSG("RAK14004 found\n"); LOG_INFO("RAK14004 found\n");
kb_model = 0x02; kb_model = 0x02;
} else { } else {
DEBUG_MSG("m5 cardKB found\n"); LOG_INFO("m5 cardKB found\n");
kb_model = 0x00; kb_model = 0x00;
} }
} }
if (addr == ST7567_ADDRESS) { if (addr == ST7567_ADDRESS) {
screen_found = addr; screen_found = addr;
DEBUG_MSG("st7567 display found\n"); LOG_INFO("st7567 display found\n");
} }
#ifdef HAS_PMU #ifdef HAS_PMU
if (addr == XPOWERS_AXP192_AXP2101_ADDRESS) { if (addr == XPOWERS_AXP192_AXP2101_ADDRESS) {
pmu_found = true; pmu_found = true;
DEBUG_MSG("axp192/axp2101 PMU found\n"); LOG_INFO("axp192/axp2101 PMU found\n");
} }
#endif #endif
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) { if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
if (registerValue == 0x61) { if (registerValue == 0x61) {
DEBUG_MSG("BME-680 sensor found at address 0x%x\n", (uint8_t)addr); LOG_INFO("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BME680] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BME680] = addr;
} else if (registerValue == 0x60) { } else if (registerValue == 0x60) {
DEBUG_MSG("BME-280 sensor found at address 0x%x\n", (uint8_t)addr); LOG_INFO("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BME280] = addr;
} else { } else {
DEBUG_MSG("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr); LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BMP280] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BMP280] = addr;
} }
} }
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) { if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
registerValue = getRegisterValue(addr, 0xFE, 2); registerValue = getRegisterValue(addr, 0xFE, 2);
DEBUG_MSG("Register MFG_UID: 0x%x\n", registerValue); LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
if (registerValue == 0x5449) { if (registerValue == 0x5449) {
DEBUG_MSG("INA260 sensor found at address 0x%x\n", (uint8_t)addr); LOG_INFO("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_INA260] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] = addr;
} else { // Assume INA219 if INA260 ID is not found } else { // Assume INA219 if INA260 ID is not found
DEBUG_MSG("INA219 sensor found at address 0x%x\n", (uint8_t)addr); LOG_INFO("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_INA219] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] = addr;
} }
} }
if (addr == MCP9808_ADDR) { if (addr == MCP9808_ADDR) {
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MCP9808] = addr;
DEBUG_MSG("MCP9808 sensor found\n"); LOG_INFO("MCP9808 sensor found\n");
}
if (addr == SHT31_ADDR) {
LOG_INFO("SHT31 sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_SHT31] = addr;
} }
if (addr == SHTC3_ADDR) { if (addr == SHTC3_ADDR) {
DEBUG_MSG("SHTC3 sensor found\n"); LOG_INFO("SHTC3 sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_SHTC3] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_SHTC3] = addr;
} }
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) { if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
DEBUG_MSG("LPS22HB sensor found\n"); LOG_INFO("LPS22HB sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_LPS22] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_LPS22] = addr;
} }
// High rate sensors, will be processed internally // High rate sensors, will be processed internally
if (addr == QMC6310_ADDR) { if (addr == QMC6310_ADDR) {
DEBUG_MSG("QMC6310 Highrate 3-Axis magnetic sensor found\n"); LOG_INFO("QMC6310 Highrate 3-Axis magnetic sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC6310] = addr;
} }
if (addr == QMI8658_ADDR) { if (addr == QMI8658_ADDR) {
DEBUG_MSG("QMI8658 Highrate 6-Axis inertial measurement sensor found\n"); LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMI8658] = addr;
} }
if (addr == QMC5883L_ADDR) { if (addr == QMC5883L_ADDR) {
DEBUG_MSG("QMC5883L Highrate 3-Axis magnetic sensor found\n"); LOG_INFO("QMC5883L Highrate 3-Axis magnetic sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_QMC5883L] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC5883L] = addr;
} }
} else if (err == 4) { } else if (err == 4) {
DEBUG_MSG("Unknow error at address 0x%x\n", addr); LOG_ERROR("Unknow error at address 0x%x\n", addr);
} }
} }
if (nDevices == 0) if (nDevices == 0)
DEBUG_MSG("No I2C devices found\n"); LOG_INFO("No I2C devices found\n");
else else
DEBUG_MSG("%i I2C devices found\n",nDevices); LOG_INFO("%i I2C devices found\n", nDevices);
} }
#else #else
void scanI2Cdevice() {} void scanI2Cdevice() {}

View File

@@ -2,10 +2,11 @@
#include <Arduino.h> #include <Arduino.h>
#include "mesh/generated/mesh.pb.h" // For CriticalErrorCode #include "mesh/generated/meshtastic/mesh.pb.h" // For CriticalErrorCode
/// A macro that include filename and line /// A macro that include filename and line
#define RECORD_CRITICALERROR(code) recordCriticalError(code, __LINE__, __FILE__) #define RECORD_CRITICALERROR(code) recordCriticalError(code, __LINE__, __FILE__)
/// Record an error that should be reported via analytics /// Record an error that should be reported via analytics
void recordCriticalError(CriticalErrorCode code = CriticalErrorCode_UNSPECIFIED, uint32_t address = 0, const char *filename = NULL); void recordCriticalError(meshtastic_CriticalErrorCode code = meshtastic_CriticalErrorCode_UNSPECIFIED, uint32_t address = 0,
const char *filename = NULL);

View File

@@ -3,7 +3,6 @@
#include "RTC.h" #include "RTC.h"
#include "configuration.h" #include "configuration.h"
#include "sleep.h" #include "sleep.h"
#include <assert.h>
// If we have a serial GPS port it will not be null // If we have a serial GPS port it will not be null
#ifdef GPS_SERIAL_NUM #ifdef GPS_SERIAL_NUM
@@ -22,7 +21,8 @@ GPS *gps;
/// only init that port once. /// only init that port once.
static bool didSerialInit; static bool didSerialInit;
bool GPS::getACK(uint8_t c, uint8_t i) { bool GPS::getACK(uint8_t c, uint8_t i)
{
uint8_t b; uint8_t b;
uint8_t ack = 0; uint8_t ack = 0;
const uint8_t ackP[2] = {c, i}; const uint8_t ackP[2] = {c, i};
@@ -51,8 +51,7 @@ bool GPS::getACK(uint8_t c, uint8_t i) {
b = _serial_gps->read(); b = _serial_gps->read();
if (b == buf[ack]) { if (b == buf[ack]) {
ack++; ack++;
} } else {
else {
ack = 0; ack = 0;
} }
} }
@@ -79,13 +78,13 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
int c = _serial_gps->read(); int c = _serial_gps->read();
switch (ubxFrameCounter) { switch (ubxFrameCounter) {
case 0: case 0:
//ubxFrame 'μ' // ubxFrame 'μ'
if (c == 0xB5) { if (c == 0xB5) {
ubxFrameCounter++; ubxFrameCounter++;
} }
break; break;
case 1: case 1:
//ubxFrame 'b' // ubxFrame 'b'
if (c == 0x62) { if (c == 0x62) {
ubxFrameCounter++; ubxFrameCounter++;
} else { } else {
@@ -93,7 +92,7 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
} }
break; break;
case 2: case 2:
//Class // Class
if (c == requestedClass) { if (c == requestedClass) {
ubxFrameCounter++; ubxFrameCounter++;
} else { } else {
@@ -101,7 +100,7 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
} }
break; break;
case 3: case 3:
//Message ID // Message ID
if (c == requestedID) { if (c == requestedID) {
ubxFrameCounter++; ubxFrameCounter++;
} else { } else {
@@ -109,12 +108,12 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
} }
break; break;
case 4: case 4:
//Payload lenght lsb // Payload lenght lsb
needRead = c; needRead = c;
ubxFrameCounter++; ubxFrameCounter++;
break; break;
case 5: case 5:
//Payload lenght msb // Payload lenght msb
needRead |= (c << 8); needRead |= (c << 8);
ubxFrameCounter++; ubxFrameCounter++;
break; break;
@@ -150,20 +149,20 @@ bool GPS::setupGPS()
_serial_gps->setRxBufferSize(2048); // the default is 256 _serial_gps->setRxBufferSize(2048); // the default is 256
#endif #endif
// if the overrides are not dialled in, set them from the board definitions, if they exist // if the overrides are not dialled in, set them from the board definitions, if they exist
#if defined(GPS_RX_PIN) #if defined(GPS_RX_PIN)
if (!config.position.rx_gpio) if (!config.position.rx_gpio)
config.position.rx_gpio = GPS_RX_PIN; config.position.rx_gpio = GPS_RX_PIN;
#endif #endif
#if defined(GPS_TX_PIN) #if defined(GPS_TX_PIN)
if (!config.position.tx_gpio) if (!config.position.tx_gpio)
config.position.tx_gpio = GPS_TX_PIN; config.position.tx_gpio = GPS_TX_PIN;
#endif #endif
// ESP32 has a special set of parameters vs other arduino ports // ESP32 has a special set of parameters vs other arduino ports
#if defined(ARCH_ESP32) #if defined(ARCH_ESP32)
if(config.position.rx_gpio) if (config.position.rx_gpio)
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, config.position.rx_gpio, config.position.tx_gpio); _serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, config.position.rx_gpio, config.position.tx_gpio);
#else #else
_serial_gps->begin(GPS_BAUDRATE); _serial_gps->begin(GPS_BAUDRATE);
@@ -174,13 +173,13 @@ if (!config.position.tx_gpio)
*/ */
gnssModel = probe(); gnssModel = probe();
if(gnssModel == GNSS_MODEL_MTK){ if (gnssModel == GNSS_MODEL_MTK) {
/* /*
* t-beam-s3-core uses the same L76K GNSS module as t-echo. * t-beam-s3-core uses the same L76K GNSS module as t-echo.
* Unlike t-echo, L76K uses 9600 baud rate for communication by default. * Unlike t-echo, L76K uses 9600 baud rate for communication by default.
* */ * */
// _serial_gps->begin(9600); //The baud rate of 9600 has been initialized at the beginning of setupGPS, this line is the redundant part // _serial_gps->begin(9600); //The baud rate of 9600 has been initialized at the beginning of setupGPS, this line
// delay(250); // is the redundant part delay(250);
// Initialize the L76K Chip, use GPS + GLONASS // Initialize the L76K Chip, use GPS + GLONASS
_serial_gps->write("$PCAS04,5*1C\r\n"); _serial_gps->write("$PCAS04,5*1C\r\n");
@@ -192,7 +191,7 @@ if (!config.position.tx_gpio)
_serial_gps->write("$PCAS11,3*1E\r\n"); _serial_gps->write("$PCAS11,3*1E\r\n");
delay(250); delay(250);
}else if(gnssModel == GNSS_MODEL_UBLOX){ } else if (gnssModel == GNSS_MODEL_UBLOX) {
/* /*
tips: NMEA Only should not be set here, otherwise initializing Ublox gnss module again after tips: NMEA Only should not be set here, otherwise initializing Ublox gnss module again after
@@ -203,7 +202,7 @@ if (!config.position.tx_gpio)
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF}; 0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF};
_serial_gps->write(_message_nmea, sizeof(_message_nmea)); _serial_gps->write(_message_nmea, sizeof(_message_nmea));
if (!getACK(0x06, 0x00)) { if (!getACK(0x06, 0x00)) {
DEBUG_MSG("WARNING: Unable to enable NMEA Mode.\n"); LOG_WARN("Unable to enable NMEA Mode.\n");
return true; return true;
} }
*/ */
@@ -211,50 +210,56 @@ if (!config.position.tx_gpio)
// ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid // ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid
// disable GGL // disable GGL
byte _message_GGL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x05, 0x3A}; byte _message_GGL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01,
0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x05, 0x3A};
_serial_gps->write(_message_GGL, sizeof(_message_GGL)); _serial_gps->write(_message_GGL, sizeof(_message_GGL));
if (!getACK(0x06, 0x01)) { if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to disable NMEA GGL.\n"); LOG_WARN("Unable to disable NMEA GGL.\n");
return true; return true;
} }
// disable GSA // disable GSA
byte _message_GSA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x06, 0x41}; byte _message_GSA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02,
0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x06, 0x41};
_serial_gps->write(_message_GSA, sizeof(_message_GSA)); _serial_gps->write(_message_GSA, sizeof(_message_GSA));
if (!getACK(0x06, 0x01)) { if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to disable NMEA GSA.\n"); LOG_WARN("Unable to disable NMEA GSA.\n");
return true; return true;
} }
// disable GSV // disable GSV
byte _message_GSV[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x07, 0x48}; byte _message_GSV[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03,
0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x07, 0x48};
_serial_gps->write(_message_GSV, sizeof(_message_GSV)); _serial_gps->write(_message_GSV, sizeof(_message_GSV));
if (!getACK(0x06, 0x01)) { if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to disable NMEA GSV.\n"); LOG_WARN("Unable to disable NMEA GSV.\n");
return true; return true;
} }
// disable VTG // disable VTG
byte _message_VTG[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x09, 0x56}; byte _message_VTG[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05,
0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x09, 0x56};
_serial_gps->write(_message_VTG, sizeof(_message_VTG)); _serial_gps->write(_message_VTG, sizeof(_message_VTG));
if (!getACK(0x06, 0x01)) { if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to disable NMEA VTG.\n"); LOG_WARN("Unable to disable NMEA VTG.\n");
return true; return true;
} }
// enable RMC // enable RMC
byte _message_RMC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x09, 0x54}; byte _message_RMC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x09, 0x54};
_serial_gps->write(_message_RMC, sizeof(_message_RMC)); _serial_gps->write(_message_RMC, sizeof(_message_RMC));
if (!getACK(0x06, 0x01)) { if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to enable NMEA RMC.\n"); LOG_WARN("Unable to enable NMEA RMC.\n");
return true; return true;
} }
// enable GGA // enable GGA
byte _message_GGA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x38}; byte _message_GGA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x38};
_serial_gps->write(_message_GGA, sizeof(_message_GGA)); _serial_gps->write(_message_GGA, sizeof(_message_GGA));
if (!getACK(0x06, 0x01)) { if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to enable NMEA GGA.\n"); LOG_WARN("Unable to enable NMEA GGA.\n");
} }
} }
} }
@@ -270,21 +275,31 @@ bool GPS::setup()
pinMode(PIN_GPS_EN, OUTPUT); pinMode(PIN_GPS_EN, OUTPUT);
#endif #endif
#ifdef HAS_PMU
if (config.position.gps_enabled) {
setGPSPower(true);
}
#endif
#ifdef PIN_GPS_RESET #ifdef PIN_GPS_RESET
digitalWrite(PIN_GPS_RESET, 1); // assert for 10ms digitalWrite(PIN_GPS_RESET, 1); // assert for 10ms
pinMode(PIN_GPS_RESET, OUTPUT); pinMode(PIN_GPS_RESET, OUTPUT);
delay(10); delay(10);
digitalWrite(PIN_GPS_RESET, 0); digitalWrite(PIN_GPS_RESET, 0);
#endif #endif
setAwake(true); // Wake GPS power before doing any init setAwake(true); // Wake GPS power before doing any init
bool ok = setupGPS(); bool ok = setupGPS();
if (ok) { if (ok) {
notifySleepObserver.observe(&notifySleep); notifySleepObserver.observe(&notifySleep);
notifyDeepSleepObserver.observe(&notifyDeepSleep); notifyDeepSleepObserver.observe(&notifyDeepSleep);
notifyGPSSleepObserver.observe(&notifyGPSSleep);
} }
if (config.position.gps_enabled == false && config.position.fixed_position == false) {
setAwake(false);
doGPSpowersave(false);
}
return ok; return ok;
} }
@@ -293,6 +308,7 @@ GPS::~GPS()
// we really should unregister our sleep observer // we really should unregister our sleep observer
notifySleepObserver.unobserve(&notifySleep); notifySleepObserver.unobserve(&notifySleep);
notifyDeepSleepObserver.unobserve(&notifyDeepSleep); notifyDeepSleepObserver.unobserve(&notifyDeepSleep);
notifyGPSSleepObserver.observe(&notifyGPSSleep);
} }
bool GPS::hasLock() bool GPS::hasLock()
@@ -351,12 +367,12 @@ void GPS::setNumSatellites(uint8_t n)
void GPS::setAwake(bool on) void GPS::setAwake(bool on)
{ {
if (!wakeAllowed && on) { if (!wakeAllowed && on) {
DEBUG_MSG("Inhibiting because !wakeAllowed\n"); LOG_WARN("Inhibiting because !wakeAllowed\n");
on = false; on = false;
} }
if (isAwake != on) { if (isAwake != on) {
DEBUG_MSG("WANT GPS=%d\n", on); LOG_DEBUG("WANT GPS=%d\n", on);
if (on) { if (on) {
lastWakeStartMsec = millis(); lastWakeStartMsec = millis();
wake(); wake();
@@ -387,7 +403,8 @@ uint32_t GPS::getSleepTime() const
uint32_t t = config.position.gps_update_interval; uint32_t t = config.position.gps_update_interval;
bool gps_enabled = config.position.gps_enabled; bool gps_enabled = config.position.gps_enabled;
if (!gps_enabled) // We'll not need the GPS thread to wake up again after first acq. with fixed position.
if (!gps_enabled || config.position.fixed_position)
t = UINT32_MAX; // Sleep forever now t = UINT32_MAX; // Sleep forever now
if (t == UINT32_MAX) if (t == UINT32_MAX)
@@ -402,10 +419,10 @@ void GPS::publishUpdate()
shouldPublish = false; shouldPublish = false;
// In debug logs, identify position by @timestamp:stage (stage 2 = publish) // In debug logs, identify position by @timestamp:stage (stage 2 = publish)
DEBUG_MSG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n", p.timestamp, hasValidLocation, hasLock()); LOG_DEBUG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n", p.timestamp, hasValidLocation, hasLock());
// Notify any status instances that are observing us // Notify any status instances that are observing us
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), p); const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p);
newStatus.notifyObservers(&status); newStatus.notifyObservers(&status);
} }
} }
@@ -416,12 +433,13 @@ int32_t GPS::runOnce()
// if we have received valid NMEA claim we are connected // if we have received valid NMEA claim we are connected
setConnected(); setConnected();
} else { } else {
if(gnssModel == GNSS_MODEL_UBLOX){ if ((config.position.gps_enabled == 1) && (gnssModel == GNSS_MODEL_UBLOX)) {
// reset the GPS on next bootup // reset the GPS on next bootup
if(devicestate.did_gps_reset && (millis() > 60000) && !hasFlow()) { if (devicestate.did_gps_reset && (millis() > 60000) && !hasFlow()) {
DEBUG_MSG("GPS is not communicating, trying factory reset on next bootup.\n"); LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
devicestate.did_gps_reset = false; devicestate.did_gps_reset = false;
nodeDB.saveDeviceStateToDisk(); nodeDB.saveDeviceStateToDisk();
disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
} }
} }
} }
@@ -437,7 +455,7 @@ int32_t GPS::runOnce()
// While we are awake // While we are awake
if (isAwake) { if (isAwake) {
// DEBUG_MSG("looking for location\n"); // LOG_DEBUG("looking for location\n");
if ((now - lastWhileActiveMsec) > 5000) { if ((now - lastWhileActiveMsec) > 5000) {
lastWhileActiveMsec = now; lastWhileActiveMsec = now;
whileActive(); whileActive();
@@ -452,7 +470,7 @@ int32_t GPS::runOnce()
bool gotLoc = lookForLocation(); bool gotLoc = lookForLocation();
if (gotLoc && !hasValidLocation) { // declare that we have location ASAP if (gotLoc && !hasValidLocation) { // declare that we have location ASAP
DEBUG_MSG("hasValidLocation RISING EDGE\n"); LOG_DEBUG("hasValidLocation RISING EDGE\n");
hasValidLocation = true; hasValidLocation = true;
shouldPublish = true; shouldPublish = true;
} }
@@ -463,15 +481,15 @@ int32_t GPS::runOnce()
bool tooLong = wakeTime != UINT32_MAX && (now - lastWakeStartMsec) > wakeTime; bool tooLong = wakeTime != UINT32_MAX && (now - lastWakeStartMsec) > wakeTime;
// Once we get a location we no longer desperately want an update // Once we get a location we no longer desperately want an update
// DEBUG_MSG("gotLoc %d, tooLong %d, gotTime %d\n", gotLoc, tooLong, gotTime); // LOG_DEBUG("gotLoc %d, tooLong %d, gotTime %d\n", gotLoc, tooLong, gotTime);
if ((gotLoc && gotTime) || tooLong) { if ((gotLoc && gotTime) || tooLong) {
if (tooLong) { if (tooLong) {
// we didn't get a location during this ack window, therefore declare loss of lock // we didn't get a location during this ack window, therefore declare loss of lock
if (hasValidLocation) { if (hasValidLocation) {
DEBUG_MSG("hasValidLocation FALLING EDGE (last read: %d)\n", gotLoc); LOG_DEBUG("hasValidLocation FALLING EDGE (last read: %d)\n", gotLoc);
} }
p = Position_init_default; p = meshtastic_Position_init_default;
hasValidLocation = false; hasValidLocation = false;
} }
@@ -483,6 +501,14 @@ int32_t GPS::runOnce()
// If state has changed do a publish // If state has changed do a publish
publishUpdate(); publishUpdate();
if (!(fixeddelayCtr >= 20) && config.position.fixed_position && hasValidLocation) {
fixeddelayCtr++;
// LOG_DEBUG("Our delay counter is %d\n", fixeddelayCtr);
if (fixeddelayCtr >= 20) {
doGPSpowersave(false);
forceWake(false);
}
}
// 9600bps is approx 1 byte per msec, so considering our buffer size we never need to wake more often than 200ms // 9600bps is approx 1 byte per msec, so considering our buffer size we never need to wake more often than 200ms
// if not awake we can run super infrquently (once every 5 secs?) to see if we need to wake. // if not awake we can run super infrquently (once every 5 secs?) to see if we need to wake.
return isAwake ? GPS_THREAD_INTERVAL : 5000; return isAwake ? GPS_THREAD_INTERVAL : 5000;
@@ -491,7 +517,7 @@ int32_t GPS::runOnce()
void GPS::forceWake(bool on) void GPS::forceWake(bool on)
{ {
if (on) { if (on) {
DEBUG_MSG("Allowing GPS lock\n"); LOG_DEBUG("Allowing GPS lock\n");
// lastSleepStartMsec = 0; // Force an update ASAP // lastSleepStartMsec = 0; // Force an update ASAP
wakeAllowed = true; wakeAllowed = true;
} else { } else {
@@ -506,7 +532,7 @@ void GPS::forceWake(bool on)
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs /// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
int GPS::prepareSleep(void *unused) int GPS::prepareSleep(void *unused)
{ {
DEBUG_MSG("GPS prepare sleep!\n"); LOG_INFO("GPS prepare sleep!\n");
forceWake(false); forceWake(false);
return 0; return 0;
@@ -515,9 +541,10 @@ int GPS::prepareSleep(void *unused)
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs /// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
int GPS::prepareDeepSleep(void *unused) int GPS::prepareDeepSleep(void *unused)
{ {
DEBUG_MSG("GPS deep sleep!\n"); LOG_INFO("GPS deep sleep!\n");
// For deep sleep we also want abandon any lock attempts (because we want minimum power) // For deep sleep we also want abandon any lock attempts (because we want minimum power)
getSleepTime();
setAwake(false); setAwake(false);
return 0; return 0;
@@ -537,7 +564,7 @@ GnssModel_t GPS::probe()
* The GNSS module information variable is temporarily placed inside the function body, * The GNSS module information variable is temporarily placed inside the function body,
* if it needs to be used elsewhere, it can be moved to the outside * if it needs to be used elsewhere, it can be moved to the outside
* */ * */
struct uBloxGnssModelInfo info ; struct uBloxGnssModelInfo info;
memset(&info, 0, sizeof(struct uBloxGnssModelInfo)); memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
@@ -554,22 +581,21 @@ GnssModel_t GPS::probe()
// Get module info , If the correct header is returned, // Get module info , If the correct header is returned,
// it can be determined that it is the MTK chip // it can be determined that it is the MTK chip
int index = ver.indexOf("$"); int index = ver.indexOf("$");
if(index != -1){ if (index != -1) {
ver = ver.substring(index); ver = ver.substring(index);
if (ver.startsWith("$GPTXT,01,01,02")) { if (ver.startsWith("$GPTXT,01,01,02")) {
DEBUG_MSG("L76K GNSS init succeeded, using L76K GNSS Module\n"); LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n");
return GNSS_MODEL_MTK; return GNSS_MODEL_MTK;
} }
} }
} }
} }
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30}; uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30};
_serial_gps->write(cfg_rate, sizeof(cfg_rate)); _serial_gps->write(cfg_rate, sizeof(cfg_rate));
// Check that the returned response class and message ID are correct // Check that the returned response class and message ID are correct
if (!getAck(buffer, 256, 0x06, 0x08)) { if (!getAck(buffer, 256, 0x06, 0x08)) {
DEBUG_MSG("Warning: Failed to find UBlox & MTK GNSS Module\n"); LOG_WARN("Failed to find UBlox & MTK GNSS Module\n");
return GNSS_MODEL_UNKONW; return GNSS_MODEL_UNKONW;
} }
@@ -600,29 +626,29 @@ GnssModel_t GPS::probe()
break; break;
} }
DEBUG_MSG("Module Info : \n"); LOG_DEBUG("Module Info : \n");
DEBUG_MSG("Soft version: %s\n",info.swVersion); LOG_DEBUG("Soft version: %s\n", info.swVersion);
DEBUG_MSG("Hard version: %s\n",info.hwVersion); LOG_DEBUG("Hard version: %s\n", info.hwVersion);
DEBUG_MSG("Extensions:%d\n",info.extensionNo); LOG_DEBUG("Extensions:%d\n", info.extensionNo);
for (int i = 0; i < info.extensionNo; i++) { for (int i = 0; i < info.extensionNo; i++) {
DEBUG_MSG(" %s\n",info.extension[i]); LOG_DEBUG(" %s\n", info.extension[i]);
} }
memset(buffer,0,sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
//tips: extensionNo field is 0 on some 6M GNSS modules // tips: extensionNo field is 0 on some 6M GNSS modules
for (int i = 0; i < info.extensionNo; ++i) { for (int i = 0; i < info.extensionNo; ++i) {
if (!strncmp(info.extension[i], "OD=", 3)) { if (!strncmp(info.extension[i], "OD=", 3)) {
strcpy((char *)buffer, &(info.extension[i][3])); strncpy((char *)buffer, &(info.extension[i][3]), sizeof(buffer));
DEBUG_MSG("GetModel:%s\n",(char *)buffer); LOG_DEBUG("GetModel:%s\n", (char *)buffer);
} }
} }
} }
if (strlen((char*)buffer)) { if (strlen((char *)buffer)) {
DEBUG_MSG("UBlox GNSS init succeeded, using UBlox %s GNSS Module\n" , buffer); LOG_INFO("UBlox GNSS init succeeded, using UBlox %s GNSS Module\n", buffer);
}else{ } else {
DEBUG_MSG("UBlox GNSS init succeeded, using UBlox GNSS Module\n"); LOG_INFO("UBlox GNSS init succeeded, using UBlox GNSS Module\n");
} }
return GNSS_MODEL_UBLOX; return GNSS_MODEL_UBLOX;
@@ -641,9 +667,9 @@ GPS *createGps()
#else #else
if (config.position.gps_enabled) { if (config.position.gps_enabled) {
#ifdef GPS_ALTITUDE_HAE #ifdef GPS_ALTITUDE_HAE
DEBUG_MSG("Using HAE altitude model\n"); LOG_DEBUG("Using HAE altitude model\n");
#else #else
DEBUG_MSG("Using MSL altitude model\n"); LOG_DEBUG("Using MSL altitude model\n");
#endif #endif
if (GPS::_serial_gps) { if (GPS::_serial_gps) {
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just // Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
@@ -652,6 +678,10 @@ GPS *createGps()
new_gps->setup(); new_gps->setup();
return new_gps; return new_gps;
} }
} else {
GPS *new_gps = new NMEAGPS();
new_gps->setup();
return new_gps;
} }
return nullptr; return nullptr;
#endif #endif

View File

@@ -4,19 +4,18 @@
#include "Observer.h" #include "Observer.h"
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
struct uBloxGnssModelInfo { struct uBloxGnssModelInfo {
char swVersion[30]; char swVersion[30];
char hwVersion[10]; char hwVersion[10];
uint8_t extensionNo; uint8_t extensionNo;
char extension[10][30]; char extension[10][30];
} ; };
typedef enum{ typedef enum {
GNSS_MODEL_MTK, GNSS_MODEL_MTK,
GNSS_MODEL_UBLOX, GNSS_MODEL_UBLOX,
GNSS_MODEL_UNKONW, GNSS_MODEL_UNKONW,
}GnssModel_t; } GnssModel_t;
// Generate a string representation of DOP // Generate a string representation of DOP
const char *getDOPString(uint32_t dop); const char *getDOPString(uint32_t dop);
@@ -49,12 +48,13 @@ class GPS : private concurrency::OSThread
CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep); CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep);
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep); CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
CallbackObserver<GPS, void *> notifyGPSSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
public: public:
/** If !NULL we will use this serial port to construct our GPS */ /** If !NULL we will use this serial port to construct our GPS */
static HardwareSerial *_serial_gps; static HardwareSerial *_serial_gps;
Position p = Position_init_default; meshtastic_Position p = meshtastic_Position_init_default;
GPS() : concurrency::OSThread("GPS") {} GPS() : concurrency::OSThread("GPS") {}
@@ -77,6 +77,8 @@ class GPS : private concurrency::OSThread
/// Return true if we are connected to a GPS /// Return true if we are connected to a GPS
bool isConnected() const { return hasGPS; } bool isConnected() const { return hasGPS; }
bool isPowerSaving() const { return !config.position.gps_enabled; }
/** /**
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP * Restart our lock attempt - try to get and broadcast a GPS reading ASAP
* called after the CPU wakes from light-sleep state * called after the CPU wakes from light-sleep state
@@ -166,12 +168,15 @@ class GPS : private concurrency::OSThread
int getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID); int getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID);
// delay counter to allow more sats before fixed position stops GPS thread
uint8_t fixeddelayCtr = 0;
protected: protected:
GnssModel_t gnssModel = GNSS_MODEL_UNKONW; GnssModel_t gnssModel = GNSS_MODEL_UNKONW;
}; };
// Creates an instance of the GPS class. // Creates an instance of the GPS class.
// Returns the new instance or null if the GPS is not present. // Returns the new instance or null if the GPS is not present.
GPS* createGps(); GPS *createGps();
extern GPS *gps; extern GPS *gps;

View File

@@ -1,21 +1,25 @@
#include "GeoCoord.h" #include "GeoCoord.h"
GeoCoord::GeoCoord() { GeoCoord::GeoCoord()
{
_dirty = true; _dirty = true;
} }
GeoCoord::GeoCoord (int32_t lat, int32_t lon, int32_t alt) : _latitude(lat), _longitude(lon), _altitude(alt) { GeoCoord::GeoCoord(int32_t lat, int32_t lon, int32_t alt) : _latitude(lat), _longitude(lon), _altitude(alt)
{
GeoCoord::setCoords(); GeoCoord::setCoords();
} }
GeoCoord::GeoCoord (float lat, float lon, int32_t alt) : _altitude(alt) { GeoCoord::GeoCoord(float lat, float lon, int32_t alt) : _altitude(alt)
{
// Change decimial reprsentation to int32_t. I.e., 12.345 becomes 123450000 // Change decimial reprsentation to int32_t. I.e., 12.345 becomes 123450000
_latitude = int32_t(lat * 1e+7); _latitude = int32_t(lat * 1e+7);
_longitude = int32_t(lon * 1e+7); _longitude = int32_t(lon * 1e+7);
GeoCoord::setCoords(); GeoCoord::setCoords();
} }
GeoCoord::GeoCoord(double lat, double lon, int32_t alt): _altitude(alt) { GeoCoord::GeoCoord(double lat, double lon, int32_t alt) : _altitude(alt)
{
// Change decimial reprsentation to int32_t. I.e., 12.345 becomes 123450000 // Change decimial reprsentation to int32_t. I.e., 12.345 becomes 123450000
_latitude = int32_t(lat * 1e+7); _latitude = int32_t(lat * 1e+7);
_longitude = int32_t(lon * 1e+7); _longitude = int32_t(lon * 1e+7);
@@ -23,7 +27,8 @@ GeoCoord::GeoCoord(double lat, double lon, int32_t alt): _altitude(alt) {
} }
// Initialize all the coordinate systems // Initialize all the coordinate systems
void GeoCoord::setCoords() { void GeoCoord::setCoords()
{
double lat = _latitude * 1e-7; double lat = _latitude * 1e-7;
double lon = _longitude * 1e-7; double lon = _longitude * 1e-7;
GeoCoord::latLongToDMS(lat, lon, _dms); GeoCoord::latLongToDMS(lat, lon, _dms);
@@ -34,9 +39,10 @@ void GeoCoord::setCoords() {
_dirty = false; _dirty = false;
} }
void GeoCoord::updateCoords(int32_t lat, int32_t lon, int32_t alt) { void GeoCoord::updateCoords(int32_t lat, int32_t lon, int32_t alt)
{
// If marked dirty or new coordiantes // If marked dirty or new coordiantes
if(_dirty || _latitude != lat || _longitude != lon || _altitude != alt) { if (_dirty || _latitude != lat || _longitude != lon || _altitude != alt) {
_dirty = true; _dirty = true;
_latitude = lat; _latitude = lat;
_longitude = lon; _longitude = lon;
@@ -45,25 +51,26 @@ void GeoCoord::updateCoords(int32_t lat, int32_t lon, int32_t alt) {
} }
} }
void GeoCoord::updateCoords(const double lat, const double lon, const int32_t alt) { void GeoCoord::updateCoords(const double lat, const double lon, const int32_t alt)
{
int32_t iLat = lat * 1e+7; int32_t iLat = lat * 1e+7;
int32_t iLon = lon * 1e+7; int32_t iLon = lon * 1e+7;
// If marked dirty or new coordiantes // If marked dirty or new coordiantes
if(_dirty || _latitude != iLat || _longitude != iLon || _altitude != alt) { if (_dirty || _latitude != iLat || _longitude != iLon || _altitude != alt) {
_dirty = true; _dirty = true;
_latitude = iLat; _latitude = iLat;
_longitude = iLon; _longitude = iLon;
_altitude = alt; _altitude = alt;
setCoords(); setCoords();
} }
} }
void GeoCoord::updateCoords(const float lat, const float lon, const int32_t alt) { void GeoCoord::updateCoords(const float lat, const float lon, const int32_t alt)
{
int32_t iLat = lat * 1e+7; int32_t iLat = lat * 1e+7;
int32_t iLon = lon * 1e+7; int32_t iLon = lon * 1e+7;
// If marked dirty or new coordiantes // If marked dirty or new coordiantes
if(_dirty || _latitude != iLat || _longitude != iLon || _altitude != alt) { if (_dirty || _latitude != iLat || _longitude != iLon || _altitude != alt) {
_dirty = true; _dirty = true;
_latitude = iLat; _latitude = iLat;
_longitude = iLon; _longitude = iLon;
@@ -76,9 +83,12 @@ void GeoCoord::updateCoords(const float lat, const float lon, const int32_t alt)
* Converts lat long coordinates from decimal degrees to degrees minutes seconds format. * Converts lat long coordinates from decimal degrees to degrees minutes seconds format.
* DD°MM'SS"C DDD°MM'SS"C * DD°MM'SS"C DDD°MM'SS"C
*/ */
void GeoCoord::latLongToDMS(const double lat, const double lon, DMS &dms) { void GeoCoord::latLongToDMS(const double lat, const double lon, DMS &dms)
if (lat < 0) dms.latCP = 'S'; {
else dms.latCP = 'N'; if (lat < 0)
dms.latCP = 'S';
else
dms.latCP = 'N';
double latDeg = lat; double latDeg = lat;
@@ -90,8 +100,10 @@ void GeoCoord::latLongToDMS(const double lat, const double lon, DMS &dms) {
dms.latMin = floor(latMin); dms.latMin = floor(latMin);
dms.latSec = (latMin - dms.latMin) * 60; dms.latSec = (latMin - dms.latMin) * 60;
if (lon < 0) dms.lonCP = 'W'; if (lon < 0)
else dms.lonCP = 'E'; dms.lonCP = 'W';
else
dms.lonCP = 'E';
double lonDeg = lon; double lonDeg = lon;
@@ -108,52 +120,64 @@ void GeoCoord::latLongToDMS(const double lat, const double lon, DMS &dms) {
* Converts lat long coordinates to UTM. * Converts lat long coordinates to UTM.
* based on this: https://github.com/walvok/LatLonToUTM/blob/master/latlon_utm.ino * based on this: https://github.com/walvok/LatLonToUTM/blob/master/latlon_utm.ino
*/ */
void GeoCoord::latLongToUTM(const double lat, const double lon, UTM &utm) { void GeoCoord::latLongToUTM(const double lat, const double lon, UTM &utm)
{
const std::string latBands = "CDEFGHJKLMNPQRSTUVWXX"; const std::string latBands = "CDEFGHJKLMNPQRSTUVWXX";
utm.zone = int((lon + 180)/6 + 1); utm.zone = int((lon + 180) / 6 + 1);
utm.band = latBands[int(lat/8 + 10)]; utm.band = latBands[int(lat / 8 + 10)];
double a = 6378137; // WGS84 - equatorial radius double a = 6378137; // WGS84 - equatorial radius
double k0 = 0.9996; // UTM point scale on the central meridian double k0 = 0.9996; // UTM point scale on the central meridian
double eccSquared = 0.00669438; // eccentricity squared double eccSquared = 0.00669438; // eccentricity squared
double lonTemp = (lon + 180) - int((lon + 180)/360) * 360 - 180; //Make sure the longitude is between -180.00 .. 179.9 double lonTemp = (lon + 180) - int((lon + 180) / 360) * 360 - 180; // Make sure the longitude is between -180.00 .. 179.9
double latRad = toRadians(lat); double latRad = toRadians(lat);
double lonRad = toRadians(lonTemp); double lonRad = toRadians(lonTemp);
// Special Zones for Norway and Svalbard // Special Zones for Norway and Svalbard
if( lat >= 56.0 && lat < 64.0 && lonTemp >= 3.0 && lonTemp < 12.0 ) // Norway if (lat >= 56.0 && lat < 64.0 && lonTemp >= 3.0 && lonTemp < 12.0) // Norway
utm.zone = 32; utm.zone = 32;
if( lat >= 72.0 && lat < 84.0 ) { // Svalbard if (lat >= 72.0 && lat < 84.0) { // Svalbard
if ( lonTemp >= 0.0 && lonTemp < 9.0 ) utm.zone = 31; if (lonTemp >= 0.0 && lonTemp < 9.0)
else if( lonTemp >= 9.0 && lonTemp < 21.0 ) utm.zone = 33; utm.zone = 31;
else if( lonTemp >= 21.0 && lonTemp < 33.0 ) utm.zone = 35; else if (lonTemp >= 9.0 && lonTemp < 21.0)
else if( lonTemp >= 33.0 && lonTemp < 42.0 ) utm.zone = 37; utm.zone = 33;
else if (lonTemp >= 21.0 && lonTemp < 33.0)
utm.zone = 35;
else if (lonTemp >= 33.0 && lonTemp < 42.0)
utm.zone = 37;
} }
double lonOrigin = (utm.zone - 1)*6 - 180 + 3; // puts origin in middle of zone double lonOrigin = (utm.zone - 1) * 6 - 180 + 3; // puts origin in middle of zone
double lonOriginRad = toRadians(lonOrigin); double lonOriginRad = toRadians(lonOrigin);
double eccPrimeSquared = (eccSquared)/(1 - eccSquared); double eccPrimeSquared = (eccSquared) / (1 - eccSquared);
double N = a/sqrt(1 - eccSquared*sin(latRad)*sin(latRad)); double N = a / sqrt(1 - eccSquared * sin(latRad) * sin(latRad));
double T = tan(latRad)*tan(latRad); double T = tan(latRad) * tan(latRad);
double C = eccPrimeSquared*cos(latRad)*cos(latRad); double C = eccPrimeSquared * cos(latRad) * cos(latRad);
double A = cos(latRad)*(lonRad - lonOriginRad); double A = cos(latRad) * (lonRad - lonOriginRad);
double M = a*((1 - eccSquared/4 - 3*eccSquared*eccSquared/64 - 5*eccSquared*eccSquared*eccSquared/256)*latRad double M =
- (3*eccSquared/8 + 3*eccSquared*eccSquared/32 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(2*latRad) a * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256) * latRad -
+ (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(4*latRad) (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 + 45 * eccSquared * eccSquared * eccSquared / 1024) *
- (35*eccSquared*eccSquared*eccSquared/3072)*sin(6*latRad)); sin(2 * latRad) +
utm.easting = (double)(k0*N*(A+(1-T+C)*pow(A, 3)/6 + (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120) (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * sin(4 * latRad) -
+ 500000.0); (35 * eccSquared * eccSquared * eccSquared / 3072) * sin(6 * latRad));
utm.northing = (double)(k0*(M+N*tan(latRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24 utm.easting = (double)(k0 * N *
+ (61-58*T+T*T+600*C-330*eccPrimeSquared)*A*A*A*A*A*A/720))); (A + (1 - T + C) * pow(A, 3) / 6 +
(5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A / 120) +
500000.0);
utm.northing =
(double)(k0 * (M + N * tan(latRad) *
(A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24 +
(61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) * A * A * A * A * A * A / 720)));
if(lat < 0) if (lat < 0)
utm.northing += 10000000.0; //10000000 meter offset for southern hemisphere utm.northing += 10000000.0; // 10000000 meter offset for southern hemisphere
} }
// Converts lat long coordinates to an MGRS. // Converts lat long coordinates to an MGRS.
void GeoCoord::latLongToMGRS(const double lat, const double lon, MGRS &mgrs) { void GeoCoord::latLongToMGRS(const double lat, const double lon, MGRS &mgrs)
const std::string e100kLetters[3] = { "ABCDEFGH", "JKLMNPQR", "STUVWXYZ" }; {
const std::string n100kLetters[2] = { "ABCDEFGHJKLMNPQRSTUV", "FGHJKLMNPQRSTUVABCDE" }; const std::string e100kLetters[3] = {"ABCDEFGH", "JKLMNPQR", "STUVWXYZ"};
const std::string n100kLetters[2] = {"ABCDEFGHJKLMNPQRSTUV", "FGHJKLMNPQRSTUVABCDE"};
UTM utm; UTM utm;
latLongToUTM(lat, lon, utm); latLongToUTM(lat, lon, utm);
mgrs.zone = utm.zone; mgrs.zone = utm.zone;
@@ -161,7 +185,7 @@ void GeoCoord::latLongToMGRS(const double lat, const double lon, MGRS &mgrs) {
double col = floor(utm.easting / 100000); double col = floor(utm.easting / 100000);
mgrs.east100k = e100kLetters[(mgrs.zone - 1) % 3][col - 1]; mgrs.east100k = e100kLetters[(mgrs.zone - 1) % 3][col - 1];
double row = (int32_t)floor(utm.northing / 100000.0) % 20; double row = (int32_t)floor(utm.northing / 100000.0) % 20;
mgrs.north100k = n100kLetters[(mgrs.zone-1)%2][row]; mgrs.north100k = n100kLetters[(mgrs.zone - 1) % 2][row];
mgrs.easting = (int32_t)utm.easting % 100000; mgrs.easting = (int32_t)utm.easting % 100000;
mgrs.northing = (int32_t)utm.northing % 100000; mgrs.northing = (int32_t)utm.northing % 100000;
} }
@@ -170,7 +194,8 @@ void GeoCoord::latLongToMGRS(const double lat, const double lon, MGRS &mgrs) {
* Converts lat long coordinates to Ordnance Survey Grid Reference (UK National Grid Ref). * Converts lat long coordinates to Ordnance Survey Grid Reference (UK National Grid Ref).
* Based on: https://www.movable-type.co.uk/scripts/latlong-os-gridref.html * Based on: https://www.movable-type.co.uk/scripts/latlong-os-gridref.html
*/ */
void GeoCoord::latLongToOSGR(const double lat, const double lon, OSGR &osgr) { void GeoCoord::latLongToOSGR(const double lat, const double lon, OSGR &osgr)
{
const char letter[] = "ABCDEFGHJKLMNOPQRSTUVWXYZ"; // No 'I' in OSGR const char letter[] = "ABCDEFGHJKLMNOPQRSTUVWXYZ"; // No 'I' in OSGR
double a = 6377563.396; // Airy 1830 semi-major axis double a = 6377563.396; // Airy 1830 semi-major axis
double b = 6356256.909; // Airy 1830 semi-minor axis double b = 6356256.909; // Airy 1830 semi-minor axis
@@ -179,8 +204,8 @@ void GeoCoord::latLongToOSGR(const double lat, const double lon, OSGR &osgr) {
double lambda0 = toRadians(-2); double lambda0 = toRadians(-2);
double n0 = -100000; double n0 = -100000;
double e0 = 400000; double e0 = 400000;
double e2 = 1 - (b*b)/(a*a); // eccentricity squared double e2 = 1 - (b * b) / (a * a); // eccentricity squared
double n = (a - b)/(a + b); double n = (a - b) / (a + b);
double osgb_Latitude; double osgb_Latitude;
double osgb_Longitude; double osgb_Longitude;
@@ -190,32 +215,33 @@ void GeoCoord::latLongToOSGR(const double lat, const double lon, OSGR &osgr) {
double v = a * f0 / sqrt(1 - e2 * sin(phi) * sin(phi)); double v = a * f0 / sqrt(1 - e2 * sin(phi) * sin(phi));
double rho = a * f0 * (1 - e2) / pow(1 - e2 * sin(phi) * sin(phi), 1.5); double rho = a * f0 * (1 - e2) / pow(1 - e2 * sin(phi) * sin(phi), 1.5);
double eta2 = v / rho - 1; double eta2 = v / rho - 1;
double mA = (1 + n + (5/4)*n*n + (5/4)*n*n*n) * (phi - phi0); double mA = (1 + n + (5 / 4) * n * n + (5 / 4) * n * n * n) * (phi - phi0);
double mB = (3*n + 3*n*n + (21/8)*n*n*n) * sin(phi - phi0) * cos(phi + phi0); double mB = (3 * n + 3 * n * n + (21 / 8) * n * n * n) * sin(phi - phi0) * cos(phi + phi0);
// loss of precision in mC & mD due to floating point rounding can cause innaccuracy of northing by a few meters // loss of precision in mC & mD due to floating point rounding can cause innaccuracy of northing by a few meters
double mC = (15/8*n*n + 15/8*n*n*n) * sin(2*(phi - phi0)) * cos(2*(phi + phi0)); double mC = (15 / 8 * n * n + 15 / 8 * n * n * n) * sin(2 * (phi - phi0)) * cos(2 * (phi + phi0));
double mD = (35/24)*n*n*n * sin(3*(phi - phi0)) * cos(3*(phi + phi0)); double mD = (35 / 24) * n * n * n * sin(3 * (phi - phi0)) * cos(3 * (phi + phi0));
double m = b*f0*(mA - mB + mC - mD); double m = b * f0 * (mA - mB + mC - mD);
double cos3Phi = cos(phi)*cos(phi)*cos(phi); double cos3Phi = cos(phi) * cos(phi) * cos(phi);
double cos5Phi = cos3Phi*cos(phi)*cos(phi); double cos5Phi = cos3Phi * cos(phi) * cos(phi);
double tan2Phi = tan(phi)*tan(phi); double tan2Phi = tan(phi) * tan(phi);
double tan4Phi = tan2Phi*tan2Phi; double tan4Phi = tan2Phi * tan2Phi;
double I = m + n0; double I = m + n0;
double II = (v/2)*sin(phi)*cos(phi); double II = (v / 2) * sin(phi) * cos(phi);
double III = (v/24)*sin(phi)*cos3Phi*(5 - tan2Phi + 9*eta2); double III = (v / 24) * sin(phi) * cos3Phi * (5 - tan2Phi + 9 * eta2);
double IIIA = (v/720)*sin(phi)*cos5Phi*(61 - 58*tan2Phi + tan4Phi); double IIIA = (v / 720) * sin(phi) * cos5Phi * (61 - 58 * tan2Phi + tan4Phi);
double IV = v*cos(phi); double IV = v * cos(phi);
double V = (v/6)*cos3Phi*(v/rho - tan2Phi); double V = (v / 6) * cos3Phi * (v / rho - tan2Phi);
double VI = (v/120)*cos5Phi*(5 - 18*tan2Phi + tan4Phi + 14*eta2 - 58*tan2Phi*eta2); double VI = (v / 120) * cos5Phi * (5 - 18 * tan2Phi + tan4Phi + 14 * eta2 - 58 * tan2Phi * eta2);
double deltaLambda = lambda - lambda0; double deltaLambda = lambda - lambda0;
double deltaLambda2 = deltaLambda*deltaLambda; double deltaLambda2 = deltaLambda * deltaLambda;
double northing = I + II*deltaLambda2 + III*deltaLambda2*deltaLambda2 + IIIA*deltaLambda2*deltaLambda2*deltaLambda2; double northing =
double easting = e0 + IV*deltaLambda + V*deltaLambda2*deltaLambda + VI*deltaLambda2*deltaLambda2*deltaLambda; I + II * deltaLambda2 + III * deltaLambda2 * deltaLambda2 + IIIA * deltaLambda2 * deltaLambda2 * deltaLambda2;
double easting = e0 + IV * deltaLambda + V * deltaLambda2 * deltaLambda + VI * deltaLambda2 * deltaLambda2 * deltaLambda;
if (easting < 0 || easting > 700000 || northing < 0 || northing > 1300000) // Check if out of boundaries if (easting < 0 || easting > 700000 || northing < 0 || northing > 1300000) // Check if out of boundaries
osgr = { 'I', 'I', 0, 0 }; osgr = {'I', 'I', 0, 0};
else { else {
uint32_t e100k = floor(easting / 100000); uint32_t e100k = floor(easting / 100000);
uint32_t n100k = floor(northing / 100000); uint32_t n100k = floor(northing / 100000);
@@ -232,7 +258,8 @@ void GeoCoord::latLongToOSGR(const double lat, const double lon, OSGR &osgr) {
* Converts lat long coordinates to Open Location Code. * Converts lat long coordinates to Open Location Code.
* Based on: https://github.com/google/open-location-code/blob/main/c/src/olc.c * Based on: https://github.com/google/open-location-code/blob/main/c/src/olc.c
*/ */
void GeoCoord::latLongToOLC(double lat, double lon, OLC &olc) { void GeoCoord::latLongToOLC(double lat, double lon, OLC &olc)
{
char tempCode[] = "1234567890abc"; char tempCode[] = "1234567890abc";
const char kAlphabet[] = "23456789CFGHJMPQRVWX"; const char kAlphabet[] = "23456789CFGHJMPQRVWX";
double latitude; double latitude;
@@ -304,14 +331,15 @@ void GeoCoord::latLongToOLC(double lat, double lon, OLC &olc) {
} }
// Converts the coordinate in WGS84 datum to the OSGB36 datum. // Converts the coordinate in WGS84 datum to the OSGB36 datum.
void GeoCoord::convertWGS84ToOSGB36(const double lat, const double lon, double &osgb_Latitude, double &osgb_Longitude) { void GeoCoord::convertWGS84ToOSGB36(const double lat, const double lon, double &osgb_Latitude, double &osgb_Longitude)
{
// Convert lat long to cartesian // Convert lat long to cartesian
double phi = toRadians(lat); double phi = toRadians(lat);
double lambda = toRadians(lon); double lambda = toRadians(lon);
double h = 0.0; // No OSTN height data used, some loss of accuracy (up to 5m) double h = 0.0; // No OSTN height data used, some loss of accuracy (up to 5m)
double wgsA = 6378137; // WGS84 datum semi major axis double wgsA = 6378137; // WGS84 datum semi major axis
double wgsF = 1 / 298.257223563; // WGS84 datum flattening double wgsF = 1 / 298.257223563; // WGS84 datum flattening
double ecc = 2*wgsF - wgsF*wgsF; double ecc = 2 * wgsF - wgsF * wgsF;
double vee = wgsA / sqrt(1 - ecc * pow(sin(phi), 2)); double vee = wgsA / sqrt(1 - ecc * pow(sin(phi), 2));
double wgsX = (vee + h) * cos(phi) * cos(lambda); double wgsX = (vee + h) * cos(phi) * cos(lambda);
double wgsY = (vee + h) * cos(phi) * sin(lambda); double wgsY = (vee + h) * cos(phi) * sin(lambda);
@@ -321,28 +349,29 @@ void GeoCoord::convertWGS84ToOSGB36(const double lat, const double lon, double &
double tx = -446.448; // x shift in meters double tx = -446.448; // x shift in meters
double ty = 125.157; // y shift in meters double ty = 125.157; // y shift in meters
double tz = -542.060; // z shift in meters double tz = -542.060; // z shift in meters
double s = 20.4894/1e6 + 1; // scale normalized parts per million to (s + 1) double s = 20.4894 / 1e6 + 1; // scale normalized parts per million to (s + 1)
double rx = toRadians(-0.1502/3600); // x rotation normalize arcseconds to radians double rx = toRadians(-0.1502 / 3600); // x rotation normalize arcseconds to radians
double ry = toRadians(-0.2470/3600); // y rotation normalize arcseconds to radians double ry = toRadians(-0.2470 / 3600); // y rotation normalize arcseconds to radians
double rz = toRadians(-0.8421/3600); // z rotation normalize arcseconds to radians double rz = toRadians(-0.8421 / 3600); // z rotation normalize arcseconds to radians
double osgbX = tx + wgsX*s - wgsY*rz + wgsZ*ry; double osgbX = tx + wgsX * s - wgsY * rz + wgsZ * ry;
double osgbY = ty + wgsX*rz + wgsY*s - wgsZ*rx; double osgbY = ty + wgsX * rz + wgsY * s - wgsZ * rx;
double osgbZ = tz - wgsX*ry + wgsY*rx + wgsZ*s; double osgbZ = tz - wgsX * ry + wgsY * rx + wgsZ * s;
// Convert cartesian to lat long // Convert cartesian to lat long
double airyA = 6377563.396; // Airy1830 datum semi major axis double airyA = 6377563.396; // Airy1830 datum semi major axis
double airyB = 6356256.909; // Airy1830 datum semi minor axis double airyB = 6356256.909; // Airy1830 datum semi minor axis
double airyF = 1/ 299.3249646; // Airy1830 datum flattening double airyF = 1 / 299.3249646; // Airy1830 datum flattening
double airyEcc = 2*airyF - airyF*airyF; double airyEcc = 2 * airyF - airyF * airyF;
double airyEcc2 = airyEcc / (1 - airyEcc); double airyEcc2 = airyEcc / (1 - airyEcc);
double p = sqrt(osgbX*osgbX + osgbY*osgbY); double p = sqrt(osgbX * osgbX + osgbY * osgbY);
double R = sqrt(p*p + osgbZ*osgbZ); double R = sqrt(p * p + osgbZ * osgbZ);
double tanBeta = (airyB*osgbZ) / (airyA*p) * (1 + airyEcc2*airyB/R); double tanBeta = (airyB * osgbZ) / (airyA * p) * (1 + airyEcc2 * airyB / R);
double sinBeta = tanBeta / sqrt(1 + tanBeta*tanBeta); double sinBeta = tanBeta / sqrt(1 + tanBeta * tanBeta);
double cosBeta = sinBeta / tanBeta; double cosBeta = sinBeta / tanBeta;
osgb_Latitude = atan2(osgbZ + airyEcc2*airyB*sinBeta*sinBeta*sinBeta, p - airyEcc*airyA*cosBeta*cosBeta*cosBeta); // leave in radians osgb_Latitude = atan2(osgbZ + airyEcc2 * airyB * sinBeta * sinBeta * sinBeta,
p - airyEcc * airyA * cosBeta * cosBeta * cosBeta); // leave in radians
osgb_Longitude = atan2(osgbY, osgbX); // leave in radians osgb_Longitude = atan2(osgbY, osgbX); // leave in radians
//osgb height = p*cos(osgb.latitude) + osgbZ*sin(osgb.latitude) - // osgb height = p*cos(osgb.latitude) + osgbZ*sin(osgb.latitude) -
//(airyA*airyA/(airyA / sqrt(1 - airyEcc*sin(osgb.latitude)*sin(osgb.latitude)))); // Not used, no OSTN data //(airyA*airyA/(airyA / sqrt(1 - airyEcc*sin(osgb.latitude)*sin(osgb.latitude)))); // Not used, no OSTN data
} }
@@ -399,10 +428,11 @@ float GeoCoord::bearing(double lat1, double lon1, double lat2, double lon2)
* The range in meters * The range in meters
* @return range in radians on a great circle * @return range in radians on a great circle
*/ */
float GeoCoord::rangeMetersToRadians(double range_meters) { float GeoCoord::rangeMetersToRadians(double range_meters)
{
// 1 nm is 1852 meters // 1 nm is 1852 meters
double distance_nm = range_meters * 1852; double distance_nm = range_meters * 1852;
return (PI / (180 * 60)) *distance_nm; return (PI / (180 * 60)) * distance_nm;
} }
/** /**
@@ -412,20 +442,25 @@ float GeoCoord::rangeMetersToRadians(double range_meters) {
* The range in radians * The range in radians
* @return Range in meters on a great circle * @return Range in meters on a great circle
*/ */
float GeoCoord::rangeRadiansToMeters(double range_radians) { float GeoCoord::rangeRadiansToMeters(double range_radians)
{
double distance_nm = ((180 * 60) / PI) * range_radians; double distance_nm = ((180 * 60) / PI) * range_radians;
// 1 meter is 0.000539957 nm // 1 meter is 0.000539957 nm
return distance_nm * 0.000539957; return distance_nm * 0.000539957;
} }
// Find distance from point to passed in point // Find distance from point to passed in point
int32_t GeoCoord::distanceTo(const GeoCoord& pointB) { int32_t GeoCoord::distanceTo(const GeoCoord &pointB)
return latLongToMeter(this->getLatitude() * 1e-7, this->getLongitude() * 1e-7, pointB.getLatitude() * 1e-7, pointB.getLongitude() * 1e-7); {
return latLongToMeter(this->getLatitude() * 1e-7, this->getLongitude() * 1e-7, pointB.getLatitude() * 1e-7,
pointB.getLongitude() * 1e-7);
} }
// Find bearing from point to passed in point // Find bearing from point to passed in point
int32_t GeoCoord::bearingTo(const GeoCoord& pointB) { int32_t GeoCoord::bearingTo(const GeoCoord &pointB)
return bearing(this->getLatitude() * 1e-7, this->getLongitude() * 1e-7, pointB.getLatitude() * 1e-7, pointB.getLongitude() * 1e-7); {
return bearing(this->getLatitude() * 1e-7, this->getLongitude() * 1e-7, pointB.getLatitude() * 1e-7,
pointB.getLongitude() * 1e-7);
} }
/** /**
@@ -436,8 +471,9 @@ int32_t GeoCoord::bearingTo(const GeoCoord& pointB) {
* @param range_meters * @param range_meters
* range in meters * range in meters
* @return GeoCoord object of point at bearing and range from initial point * @return GeoCoord object of point at bearing and range from initial point
*/ */
std::shared_ptr<GeoCoord> GeoCoord::pointAtDistance(double bearing, double range_meters) { std::shared_ptr<GeoCoord> GeoCoord::pointAtDistance(double bearing, double range_meters)
{
double range_radians = rangeMetersToRadians(range_meters); double range_radians = rangeMetersToRadians(range_meters);
double lat1 = this->getLatitude() * 1e-7; double lat1 = this->getLatitude() * 1e-7;
double lon1 = this->getLongitude() * 1e-7; double lon1 = this->getLongitude() * 1e-7;
@@ -446,5 +482,4 @@ std::shared_ptr<GeoCoord> GeoCoord::pointAtDistance(double bearing, double range
double lon = fmod(lon1 - dlon + PI, 2 * PI) - PI; double lon = fmod(lon1 - dlon + PI, 2 * PI) - PI;
return std::make_shared<GeoCoord>(double(lat), double(lon), this->getAltitude()); return std::make_shared<GeoCoord>(double(lat), double(lon), this->getAltitude());
} }

View File

@@ -1,20 +1,21 @@
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <string>
#include <cstring>
#include <cstdint> #include <cstdint>
#include <cstring>
#include <math.h> #include <math.h>
#include <stdint.h>
#include <stdexcept>
#include <memory> #include <memory>
#include <stdexcept>
#include <stdint.h>
#include <string>
#define PI 3.1415926535897932384626433832795 #define PI 3.1415926535897932384626433832795
#define OLC_CODE_LEN 11 #define OLC_CODE_LEN 11
// Helper functions // Helper functions
// Raises a number to an exponent, handling negative exponents. // Raises a number to an exponent, handling negative exponents.
static inline double pow_neg(double base, double exponent) { static inline double pow_neg(double base, double exponent)
{
if (exponent == 0) { if (exponent == 0) {
return 1; return 1;
} else if (exponent > 0) { } else if (exponent > 0) {
@@ -35,8 +36,7 @@ static inline double toDegrees(double r)
// GeoCoord structs/classes // GeoCoord structs/classes
// A struct to hold the data for a DMS coordinate. // A struct to hold the data for a DMS coordinate.
struct DMS struct DMS {
{
uint8_t latDeg; uint8_t latDeg;
uint8_t latMin; uint8_t latMin;
uint32_t latSec; uint32_t latSec;
@@ -48,8 +48,7 @@ struct DMS
}; };
// A struct to hold the data for a UTM coordinate, this is also used when creating an MGRS coordinate. // A struct to hold the data for a UTM coordinate, this is also used when creating an MGRS coordinate.
struct UTM struct UTM {
{
uint8_t zone; uint8_t zone;
char band; char band;
uint32_t easting; uint32_t easting;
@@ -57,8 +56,7 @@ struct UTM
}; };
// A struct to hold the data for a MGRS coordinate. // A struct to hold the data for a MGRS coordinate.
struct MGRS struct MGRS {
{
uint8_t zone; uint8_t zone;
char band; char band;
char east100k; char east100k;
@@ -80,7 +78,8 @@ struct OLC {
char code[OLC_CODE_LEN + 1]; // +1 for null termination char code[OLC_CODE_LEN + 1]; // +1 for null termination
}; };
class GeoCoord { class GeoCoord
{
private: private:
int32_t _latitude = 0; int32_t _latitude = 0;
int32_t _longitude = 0; int32_t _longitude = 0;
@@ -119,8 +118,8 @@ class GeoCoord {
static float rangeMetersToRadians(double range_meters); static float rangeMetersToRadians(double range_meters);
// Point to point conversions // Point to point conversions
int32_t distanceTo(const GeoCoord& pointB); int32_t distanceTo(const GeoCoord &pointB);
int32_t bearingTo(const GeoCoord& pointB); int32_t bearingTo(const GeoCoord &pointB);
std::shared_ptr<GeoCoord> pointAtDistance(double bearing, double range); std::shared_ptr<GeoCoord> pointAtDistance(double bearing, double range);
// Lat lon alt getters // Lat lon alt getters
@@ -159,6 +158,5 @@ class GeoCoord {
uint32_t getOSGRNorthing() const { return _osgr.northing; } uint32_t getOSGRNorthing() const { return _osgr.northing; }
// OLC getter // OLC getter
void getOLCCode(char* code) { strncpy(code, _olc.code, OLC_CODE_LEN + 1); } // +1 for null termination void getOLCCode(char *code) { strncpy(code, _olc.code, OLC_CODE_LEN + 1); } // +1 for null termination
}; };

View File

@@ -1,6 +1,6 @@
#include "configuration.h"
#include "NMEAGPS.h" #include "NMEAGPS.h"
#include "RTC.h" #include "RTC.h"
#include "configuration.h"
#include <TinyGPS++.h> #include <TinyGPS++.h>
@@ -20,19 +20,18 @@ static int32_t toDegInt(RawDegrees d)
bool NMEAGPS::factoryReset() bool NMEAGPS::factoryReset()
{ {
#ifdef PIN_GPS_REINIT #ifdef PIN_GPS_REINIT
//The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW // The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW
digitalWrite(PIN_GPS_REINIT, 0); digitalWrite(PIN_GPS_REINIT, 0);
pinMode(PIN_GPS_REINIT, OUTPUT); pinMode(PIN_GPS_REINIT, OUTPUT);
delay(150); //The L76K datasheet calls for at least 100MS delay delay(150); // The L76K datasheet calls for at least 100MS delay
digitalWrite(PIN_GPS_REINIT, 1); digitalWrite(PIN_GPS_REINIT, 1);
#endif #endif
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's UBLOX. // send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's UBLOX.
// Factory Reset // Factory Reset
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E}; _serial_gps->write(_message_reset, sizeof(_message_reset));
_serial_gps->write(_message_reset,sizeof(_message_reset));
delay(1000); delay(1000);
return true; return true;
} }
@@ -53,9 +52,9 @@ bool NMEAGPS::setupGPS()
// see NMEAGPS.h // see NMEAGPS.h
gsafixtype.begin(reader, NMEA_MSG_GXGSA, 2); gsafixtype.begin(reader, NMEA_MSG_GXGSA, 2);
gsapdop.begin(reader, NMEA_MSG_GXGSA, 15); gsapdop.begin(reader, NMEA_MSG_GXGSA, 15);
DEBUG_MSG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP\n"); LOG_DEBUG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP\n");
#else #else
DEBUG_MSG("GxGSA NOT available\n"); LOG_DEBUG("GxGSA NOT available\n");
#endif #endif
return true; return true;
@@ -84,8 +83,9 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
t.tm_mon = d.month() - 1; t.tm_mon = d.month() - 1;
t.tm_year = d.year() - 1900; t.tm_year = d.year() - 1900;
t.tm_isdst = false; t.tm_isdst = false;
if (t.tm_mon > -1){ if (t.tm_mon > -1) {
DEBUG_MSG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min,
t.tm_sec);
perhapsSetRTC(RTCQualityGPS, t); perhapsSetRTC(RTCQualityGPS, t);
return true; return true;
} else } else
@@ -109,16 +109,15 @@ bool NMEAGPS::lookForLocation()
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS #ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
fixType = atoi(gsafixtype.value()); // will set to zero if no data fixType = atoi(gsafixtype.value()); // will set to zero if no data
// DEBUG_MSG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType); // LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
#endif #endif
// check if GPS has an acceptable lock // check if GPS has an acceptable lock
if (! hasLock()) if (!hasLock())
return false; return false;
#ifdef GPS_EXTRAVERBOSE #ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d\n", LOG_DEBUG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d\n", reader.location.age(),
reader.location.age(),
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS #ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
gsafixtype.age(), gsafixtype.age(),
#else #else
@@ -130,19 +129,17 @@ bool NMEAGPS::lookForLocation()
// check if a complete GPS solution set is available for reading // check if a complete GPS solution set is available for reading
// tinyGPSDatum::age() also includes isValid() test // tinyGPSDatum::age() also includes isValid() test
// FIXME // FIXME
if (! ((reader.location.age() < GPS_SOL_EXPIRY_MS) && if (!((reader.location.age() < GPS_SOL_EXPIRY_MS) &&
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS #ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
(gsafixtype.age() < GPS_SOL_EXPIRY_MS) && (gsafixtype.age() < GPS_SOL_EXPIRY_MS) &&
#endif #endif
(reader.time.age() < GPS_SOL_EXPIRY_MS) && (reader.time.age() < GPS_SOL_EXPIRY_MS) && (reader.date.age() < GPS_SOL_EXPIRY_MS))) {
(reader.date.age() < GPS_SOL_EXPIRY_MS))) LOG_WARN("SOME data is TOO OLD: LOC %u, TIME %u, DATE %u\n", reader.location.age(), reader.time.age(), reader.date.age());
{
DEBUG_MSG("SOME data is TOO OLD: LOC %u, TIME %u, DATE %u\n", reader.location.age(), reader.time.age(), reader.date.age());
return false; return false;
} }
// Is this a new point or are we re-reading the previous one? // Is this a new point or are we re-reading the previous one?
if (! reader.location.isUpdated()) if (!reader.location.isUpdated())
return false; return false;
// We know the solution is fresh and valid, so just read the data // We know the solution is fresh and valid, so just read the data
@@ -151,24 +148,24 @@ bool NMEAGPS::lookForLocation()
// Bail out EARLY to avoid overwriting previous good data (like #857) // Bail out EARLY to avoid overwriting previous good data (like #857)
if (toDegInt(loc.lat) > 900000000) { if (toDegInt(loc.lat) > 900000000) {
#ifdef GPS_EXTRAVERBOSE #ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("Bail out EARLY on LAT %i\n",toDegInt(loc.lat)); LOG_DEBUG("Bail out EARLY on LAT %i\n", toDegInt(loc.lat));
#endif #endif
return false; return false;
} }
if (toDegInt(loc.lng) > 1800000000) { if (toDegInt(loc.lng) > 1800000000) {
#ifdef GPS_EXTRAVERBOSE #ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("Bail out EARLY on LNG %i\n",toDegInt(loc.lng)); LOG_DEBUG("Bail out EARLY on LNG %i\n", toDegInt(loc.lng));
#endif #endif
return false; return false;
} }
p.location_source = Position_LocSource_LOC_INTERNAL; p.location_source = meshtastic_Position_LocSource_LOC_INTERNAL;
// Dilution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it // Dilution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS #ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
p.HDOP = reader.hdop.value(); p.HDOP = reader.hdop.value();
p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value()); p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value());
// DEBUG_MSG("PDOP=%d, HDOP=%d\n", p.PDOP, p.HDOP); // LOG_DEBUG("PDOP=%d, HDOP=%d\n", p.PDOP, p.HDOP);
#else #else
// FIXME! naive PDOP emulation (assumes VDOP==HDOP) // FIXME! naive PDOP emulation (assumes VDOP==HDOP)
// correct formula is PDOP = SQRT(HDOP^2 + VDOP^2) // correct formula is PDOP = SQRT(HDOP^2 + VDOP^2)
@@ -210,10 +207,10 @@ bool NMEAGPS::lookForLocation()
if (reader.course.isUpdated() && reader.course.isValid()) { if (reader.course.isUpdated() && reader.course.isValid()) {
if (reader.course.value() < 36000) { // sanity check if (reader.course.value() < 36000) { // sanity check
p.ground_track = reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5 p.ground_track =
reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5
} else { } else {
DEBUG_MSG("BOGUS course.value() REJECTED: %d\n", LOG_WARN("BOGUS course.value() REJECTED: %d\n", reader.course.value());
reader.course.value());
} }
} }
@@ -224,7 +221,6 @@ bool NMEAGPS::lookForLocation()
return true; return true;
} }
bool NMEAGPS::hasLock() bool NMEAGPS::hasLock()
{ {
// Using GPGGA fix quality indicator // Using GPGGA fix quality indicator
@@ -251,7 +247,7 @@ bool NMEAGPS::whileIdle()
// First consume any chars that have piled up at the receiver // First consume any chars that have piled up at the receiver
while (_serial_gps->available() > 0) { while (_serial_gps->available() > 0) {
int c = _serial_gps->read(); int c = _serial_gps->read();
// DEBUG_MSG("%c", c); // LOG_DEBUG("%c", c);
isValid |= reader.encode(c); isValid |= reader.encode(c);
} }

View File

@@ -16,22 +16,18 @@
* ------------------------------------------- * -------------------------------------------
*/ */
uint32_t printWPL(char *buf, const Position &pos, const char *name) uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name)
{ {
GeoCoord geoCoord(pos.latitude_i,pos.longitude_i,pos.altitude); GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
uint32_t len = sprintf(buf, "$GNWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", uint32_t len = snprintf(buf, bufsz, "$GNWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", geoCoord.getDMSLatDeg(),
geoCoord.getDMSLatDeg(), (abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLatCP(), geoCoord.getDMSLonCP(), name);
geoCoord.getDMSLonDeg(),
(abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(),
name);
uint32_t chk = 0; uint32_t chk = 0;
for (uint32_t i = 1; i < len; i++) { for (uint32_t i = 1; i < len; i++) {
chk ^= buf[i]; chk ^= buf[i];
} }
len += sprintf(buf + len, "*%02X\r\n", chk); len += snprintf(buf + len, bufsz - len, "*%02X\r\n", chk);
return len; return len;
} }
@@ -51,40 +47,26 @@ uint32_t printWPL(char *buf, const Position &pos, const char *name)
* 8 Horizontal Dilution of precision (meters) * 8 Horizontal Dilution of precision (meters)
* 9 Antenna Altitude above/below mean-sea-level (geoid) (in meters) * 9 Antenna Altitude above/below mean-sea-level (geoid) (in meters)
* 10 Units of antenna altitude, meters * 10 Units of antenna altitude, meters
* 11 Geoidal separation, the difference between the WGS-84 earth ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid * 11 Geoidal separation, the difference between the WGS-84 earth ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level
* 12 Units of geoidal separation, meters * below ellipsoid 12 Units of geoidal separation, meters 13 Age of differential GPS data, time in seconds since last SC104 type 1
* 13 Age of differential GPS data, time in seconds since last SC104 type 1 or 9 update, null field when DGPS is not used * or 9 update, null field when DGPS is not used 14 Differential reference station ID, 0000-1023 15 Checksum
* 14 Differential reference station ID, 0000-1023
* 15 Checksum
* ------------------------------------------- * -------------------------------------------
*/ */
uint32_t printGGA(char *buf, const Position &pos) uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos)
{ {
GeoCoord geoCoord(pos.latitude_i,pos.longitude_i,pos.altitude); GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
uint32_t len = sprintf(buf, "$GNGGA,%06u.%03u,%02d%07.4f,%c,%03d%07.4f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d", uint32_t len =
pos.time / 1000, snprintf(buf, bufsz, "$GNGGA,%06u.%03u,%02d%07.4f,%c,%03d%07.4f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d", pos.time / 1000,
pos.time % 1000, pos.time % 1000, geoCoord.getDMSLatDeg(), (abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLatDeg(), geoCoord.getDMSLatCP(), geoCoord.getDMSLonDeg(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6, geoCoord.getDMSLonCP(), pos.fix_type,
geoCoord.getDMSLatCP(), pos.sats_in_view, pos.HDOP, geoCoord.getAltitude(), 'M', pos.altitude_geoidal_separation, 'M', 0, 0);
geoCoord.getDMSLonDeg(),
(abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(),
pos.fix_type,
pos.sats_in_view,
pos.HDOP,
geoCoord.getAltitude(),
'M',
pos.altitude_geoidal_separation,
'M',
0,
0);
uint32_t chk = 0; uint32_t chk = 0;
for (uint32_t i = 1; i < len; i++) { for (uint32_t i = 1; i < len; i++) {
chk ^= buf[i]; chk ^= buf[i];
} }
len += sprintf(buf + len, "*%02X\r\n", chk); len += snprintf(buf + len, bufsz - len, "*%02X\r\n", chk);
return len; return len;
} }

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <Arduino.h>
#include "main.h" #include "main.h"
#include <Arduino.h>
uint32_t printWPL(char *buf, const Position &pos, const char *name); uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const char *name);
uint32_t printGGA(char *buf, const Position &pos); uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos);

View File

@@ -20,7 +20,7 @@ void readFromRTC()
{ {
struct timeval tv; /* btw settimeofday() is helpfull here too*/ struct timeval tv; /* btw settimeofday() is helpfull here too*/
#ifdef RV3028_RTC #ifdef RV3028_RTC
if(rtc_found == RV3028_RTC) { if (rtc_found == RV3028_RTC) {
uint32_t now = millis(); uint32_t now = millis();
Melopero_RV3028 rtc; Melopero_RV3028 rtc;
rtc.initI2C(); rtc.initI2C();
@@ -33,7 +33,7 @@ void readFromRTC()
t.tm_sec = rtc.getSecond(); t.tm_sec = rtc.getSecond();
tv.tv_sec = mktime(&t); tv.tv_sec = mktime(&t);
tv.tv_usec = 0; tv.tv_usec = 0;
DEBUG_MSG("Read RTC time from RV3028 as %ld\n", tv.tv_sec); LOG_DEBUG("Read RTC time from RV3028 as %ld\n", tv.tv_sec);
timeStartMsec = now; timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec; zeroOffsetSecs = tv.tv_sec;
if (currentQuality == RTCQualityNone) { if (currentQuality == RTCQualityNone) {
@@ -41,7 +41,7 @@ void readFromRTC()
} }
} }
#elif defined(PCF8563_RTC) #elif defined(PCF8563_RTC)
if(rtc_found == PCF8563_RTC) { if (rtc_found == PCF8563_RTC) {
uint32_t now = millis(); uint32_t now = millis();
PCF8563_Class rtc; PCF8563_Class rtc;
#ifdef RTC_USE_WIRE1 #ifdef RTC_USE_WIRE1
@@ -59,7 +59,7 @@ void readFromRTC()
t.tm_sec = tc.second; t.tm_sec = tc.second;
tv.tv_sec = mktime(&t); tv.tv_sec = mktime(&t);
tv.tv_usec = 0; tv.tv_usec = 0;
DEBUG_MSG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec); LOG_DEBUG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec);
timeStartMsec = now; timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec; zeroOffsetSecs = tv.tv_sec;
if (currentQuality == RTCQualityNone) { if (currentQuality == RTCQualityNone) {
@@ -69,7 +69,7 @@ void readFromRTC()
#else #else
if (!gettimeofday(&tv, NULL)) { if (!gettimeofday(&tv, NULL)) {
uint32_t now = millis(); uint32_t now = millis();
DEBUG_MSG("Read RTC time as %ld\n", tv.tv_sec); LOG_DEBUG("Read RTC time as %ld\n", tv.tv_sec);
timeStartMsec = now; timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec; zeroOffsetSecs = tv.tv_sec;
} }
@@ -86,13 +86,12 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
if (q > currentQuality) { if (q > currentQuality) {
currentQuality = q; currentQuality = q;
shouldSet = true; shouldSet = true;
DEBUG_MSG("Upgrading time to RTC %ld secs (quality %d)\n", tv->tv_sec, q); LOG_DEBUG("Upgrading time to RTC %ld secs (quality %d)\n", tv->tv_sec, q);
} else if(q == RTCQualityGPS && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) { } 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 // Every 12 hrs we will slam in a new GPS time, to correct for local RTC clock drift
shouldSet = true; shouldSet = true;
DEBUG_MSG("Reapplying external time to correct clock drift %ld secs\n", tv->tv_sec); LOG_DEBUG("Reapplying external time to correct clock drift %ld secs\n", tv->tv_sec);
} } else
else
shouldSet = false; shouldSet = false;
if (shouldSet) { if (shouldSet) {
@@ -104,15 +103,16 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
// If this platform has a setable RTC, set it // If this platform has a setable RTC, set it
#ifdef RV3028_RTC #ifdef RV3028_RTC
if(rtc_found == RV3028_RTC) { if (rtc_found == RV3028_RTC) {
Melopero_RV3028 rtc; Melopero_RV3028 rtc;
rtc.initI2C(); rtc.initI2C();
tm *t = localtime(&tv->tv_sec); tm *t = localtime(&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); 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);
DEBUG_MSG("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); 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);
} }
#elif defined(PCF8563_RTC) #elif defined(PCF8563_RTC)
if(rtc_found == PCF8563_RTC) { if (rtc_found == PCF8563_RTC) {
PCF8563_Class rtc; PCF8563_Class rtc;
#ifdef RTC_USE_WIRE1 #ifdef RTC_USE_WIRE1
rtc.begin(Wire1); rtc.begin(Wire1);
@@ -121,7 +121,8 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
#endif #endif
tm *t = localtime(&tv->tv_sec); tm *t = localtime(&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); rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
DEBUG_MSG("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); 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);
} }
#elif defined(ARCH_ESP32) #elif defined(ARCH_ESP32)
settimeofday(tv, NULL); settimeofday(tv, NULL);
@@ -149,9 +150,9 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
tv.tv_sec = res; tv.tv_sec = res;
tv.tv_usec = 0; // time.centisecond() * (10 / 1000); tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
// DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec); // LOG_DEBUG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
if (t.tm_year < 0 || t.tm_year >= 300) { if (t.tm_year < 0 || t.tm_year >= 300) {
// DEBUG_MSG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec); // LOG_DEBUG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
return false; return false;
} else { } else {
return perhapsSetRTC(q, &tv); return perhapsSetRTC(q, &tv);
@@ -160,7 +161,7 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
uint32_t getTime() uint32_t getTime()
{ {
return (((uint32_t) millis() - timeStartMsec) / 1000) + zeroOffsetSecs; return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
} }
uint32_t getValidTime(RTCQuality minQuality) uint32_t getValidTime(RTCQuality minQuality)

View File

@@ -1,11 +1,11 @@
#include "configuration.h" #include "configuration.h"
#ifdef USE_EINK #ifdef USE_EINK
#include "main.h"
#include "EInkDisplay2.h" #include "EInkDisplay2.h"
#include "SPILock.h"
#include <SPI.h>
#include "GxEPD2_BW.h" #include "GxEPD2_BW.h"
#include "SPILock.h"
#include "main.h"
#include <SPI.h>
#define COLORED GxEPD_BLACK #define COLORED GxEPD_BLACK
#define UNCOLORED GxEPD_WHITE #define UNCOLORED GxEPD_WHITE
@@ -14,62 +14,63 @@
#define TECHO_DISPLAY_MODEL GxEPD2_154_D67 #define TECHO_DISPLAY_MODEL GxEPD2_154_D67
#elif defined(RAK4630) #elif defined(RAK4630)
//GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give partial update support // GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give partial update
// support
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN #define TECHO_DISPLAY_MODEL GxEPD2_213_BN
//4.2 inch 300x400 - GxEPD2_420_M01 // 4.2 inch 300x400 - GxEPD2_420_M01
//#define TECHO_DISPLAY_MODEL GxEPD2_420_M01 //#define TECHO_DISPLAY_MODEL GxEPD2_420_M01
//2.9 inch 296x128 - GxEPD2_290_T5D // 2.9 inch 296x128 - GxEPD2_290_T5D
//#define TECHO_DISPLAY_MODEL GxEPD2_290_T5D //#define TECHO_DISPLAY_MODEL GxEPD2_290_T5D
//1.54 inch 200x200 - GxEPD2_154_M09 // 1.54 inch 200x200 - GxEPD2_154_M09
//#define TECHO_DISPLAY_MODEL GxEPD2_154_M09 //#define TECHO_DISPLAY_MODEL GxEPD2_154_M09
#elif defined(PCA10059) #elif defined(PCA10059)
//4.2 inch 300x400 - GxEPD2_420_M01 // 4.2 inch 300x400 - GxEPD2_420_M01
#define TECHO_DISPLAY_MODEL GxEPD2_420_M01 #define TECHO_DISPLAY_MODEL GxEPD2_420_M01
#elif defined(M5_COREINK) #elif defined(M5_COREINK)
//M5Stack CoreInk // M5Stack CoreInk
//1.54 inch 200x200 - GxEPD2_154_M09 // 1.54 inch 200x200 - GxEPD2_154_M09
#define TECHO_DISPLAY_MODEL GxEPD2_154_M09 #define TECHO_DISPLAY_MODEL GxEPD2_154_M09
#endif #endif
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay; GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl) EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model)
{ {
#if defined(TTGO_T_ECHO) #if defined(TTGO_T_ECHO)
setGeometry(GEOMETRY_RAWMODE, TECHO_DISPLAY_MODEL::WIDTH, TECHO_DISPLAY_MODEL::HEIGHT); setGeometry(GEOMETRY_RAWMODE, TECHO_DISPLAY_MODEL::WIDTH, TECHO_DISPLAY_MODEL::HEIGHT);
#elif defined(RAK4630) #elif defined(RAK4630)
//GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 // GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122
setGeometry(GEOMETRY_RAWMODE, 250, 122); setGeometry(GEOMETRY_RAWMODE, 250, 122);
//GxEPD2_420_M01 // GxEPD2_420_M01
//setGeometry(GEOMETRY_RAWMODE, 300, 400); // setGeometry(GEOMETRY_RAWMODE, 300, 400);
//GxEPD2_290_T5D // GxEPD2_290_T5D
//setGeometry(GEOMETRY_RAWMODE, 296, 128); // setGeometry(GEOMETRY_RAWMODE, 296, 128);
//GxEPD2_154_M09 // GxEPD2_154_M09
//setGeometry(GEOMETRY_RAWMODE, 200, 200); // setGeometry(GEOMETRY_RAWMODE, 200, 200);
#elif defined(PCA10059) #elif defined(PCA10059)
//GxEPD2_420_M01 // GxEPD2_420_M01
setGeometry(GEOMETRY_RAWMODE, 300, 400); setGeometry(GEOMETRY_RAWMODE, 300, 400);
#elif defined(M5_COREINK) #elif defined(M5_COREINK)
//M5Stack_CoreInk 200x200 // M5Stack_CoreInk 200x200
//1.54 inch 200x200 - GxEPD2_154_M09 // 1.54 inch 200x200 - GxEPD2_154_M09
setGeometry(GEOMETRY_RAWMODE, EPD_HEIGHT, EPD_WIDTH); setGeometry(GEOMETRY_RAWMODE, EPD_HEIGHT, EPD_WIDTH);
#endif #endif
// setGeometry(GEOMETRY_RAWMODE, 128, 64); // old resolution // setGeometry(GEOMETRY_RAWMODE, 128, 64); // old resolution
// setGeometry(GEOMETRY_128_64); // We originally used this because I wasn't sure if rawmode worked - it does // setGeometry(GEOMETRY_128_64); // We originally used this because I wasn't sure if rawmode worked - it does
} }
@@ -103,36 +104,36 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
} }
} }
DEBUG_MSG("Updating E-Paper... "); LOG_DEBUG("Updating E-Paper... ");
#if defined(TTGO_T_ECHO) #if defined(TTGO_T_ECHO)
// ePaper.Reset(); // wake the screen from sleep // ePaper.Reset(); // wake the screen from sleep
adafruitDisplay->display(false); // FIXME, use partial update mode adafruitDisplay->display(false); // FIXME, use partial update mode
#elif defined(RAK4630) #elif defined(RAK4630)
//RAK14000 2.13 inch b/w 250x122 actually now does support partial updates // RAK14000 2.13 inch b/w 250x122 actually now does support partial updates
//Full update mode (slow) // Full update mode (slow)
//adafruitDisplay->display(false); // FIXME, use partial update mode // adafruitDisplay->display(false); // FIXME, use partial update mode
//Only enable for e-Paper with support for partial updates and comment out above adafruitDisplay->display(false); // Only enable for e-Paper with support for partial updates and comment out above adafruitDisplay->display(false);
// 1.54 inch 200x200 - GxEPD2_154_M09 // 1.54 inch 200x200 - GxEPD2_154_M09
// 2.13 inch 250x122 - GxEPD2_213_BN // 2.13 inch 250x122 - GxEPD2_213_BN
// 2.9 inch 296x128 - GxEPD2_290_T5D // 2.9 inch 296x128 - GxEPD2_290_T5D
// 4.2 inch 300x400 - GxEPD2_420_M01 // 4.2 inch 300x400 - GxEPD2_420_M01
adafruitDisplay->nextPage(); adafruitDisplay->nextPage();
#elif defined(PCA10059) || defined(M5_COREINK) #elif defined(PCA10059) || defined(M5_COREINK)
adafruitDisplay->nextPage(); adafruitDisplay->nextPage();
#endif #endif
// Put screen to sleep to save power (possibly not necessary because we already did poweroff inside of display) // Put screen to sleep to save power (possibly not necessary because we already did poweroff inside of display)
adafruitDisplay->hibernate(); adafruitDisplay->hibernate();
DEBUG_MSG("done\n"); LOG_DEBUG("done\n");
return true; return true;
} else { } else {
// DEBUG_MSG("Skipping eink display\n"); // LOG_DEBUG("Skipping eink display\n");
return false; return false;
} }
} }
@@ -162,7 +163,7 @@ void EInkDisplay::setDetected(uint8_t detected)
// Connect to the display // Connect to the display
bool EInkDisplay::connect() bool EInkDisplay::connect()
{ {
DEBUG_MSG("Doing EInk init\n"); LOG_INFO("Doing EInk init\n");
#ifdef PIN_EINK_PWR_ON #ifdef PIN_EINK_PWR_ON
digitalWrite(PIN_EINK_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals digitalWrite(PIN_EINK_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals
@@ -175,17 +176,16 @@ bool EInkDisplay::connect()
pinMode(PIN_EINK_EN, OUTPUT); pinMode(PIN_EINK_EN, OUTPUT);
#endif #endif
#if defined(TTGO_T_ECHO) #if defined(TTGO_T_ECHO)
{ {
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1); auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1);
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel); adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init(); adafruitDisplay->init();
adafruitDisplay->setRotation(3); adafruitDisplay->setRotation(3);
} }
#elif defined(RAK4630) #elif defined(RAK4630)
{ {
if (eink_found) { if (eink_found) {
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY); auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
@@ -193,23 +193,23 @@ bool EInkDisplay::connect()
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0)); adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
//RAK14000 2.13 inch b/w 250x122 does actually now support partial updates // RAK14000 2.13 inch b/w 250x122 does actually now support partial updates
adafruitDisplay->setRotation(3); adafruitDisplay->setRotation(3);
//Partial update support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2 // Partial update support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2
//adafruitDisplay->setRotation(1); // adafruitDisplay->setRotation(1);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight); adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
} else { } else {
(void)adafruitDisplay; (void)adafruitDisplay;
} }
} }
#elif defined(PCA10059) #elif defined(PCA10059)
{ {
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY); auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel); adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0)); adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
adafruitDisplay->setRotation(3); adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight); adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
} }
#elif defined(M5_COREINK) #elif defined(M5_COREINK)
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY); auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel); adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
@@ -218,11 +218,10 @@ bool EInkDisplay::connect()
adafruitDisplay->setPartialWindow(0, 0, EPD_WIDTH, EPD_HEIGHT); adafruitDisplay->setPartialWindow(0, 0, EPD_WIDTH, EPD_HEIGHT);
#endif #endif
// adafruitDisplay->setFullWindow();
//adafruitDisplay->setFullWindow(); // adafruitDisplay->fillScreen(UNCOLORED);
//adafruitDisplay->fillScreen(UNCOLORED); // adafruitDisplay->drawCircle(100, 100, 20, COLORED);
//adafruitDisplay->drawCircle(100, 100, 20, COLORED); // adafruitDisplay->display(false);
//adafruitDisplay->display(false);
return true; return true;
} }

View File

@@ -22,7 +22,7 @@ class EInkDisplay : public OLEDDisplay
/* constructor /* constructor
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
*/ */
EInkDisplay(uint8_t address, int sda, int scl); EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model);
// Write the buffer to the display memory (for eink we only do this occasionally) // Write the buffer to the display memory (for eink we only do this occasionally)
virtual void display(void) override; virtual void display(void) override;
@@ -50,5 +50,3 @@ class EInkDisplay : public OLEDDisplay
// Connect to the display // Connect to the display
virtual bool connect() override; virtual bool connect() override;
}; };

View File

@@ -33,7 +33,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "main.h" #include "main.h"
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
#include "mesh/Channels.h" #include "mesh/Channels.h"
#include "mesh/generated/deviceonly.pb.h" #include "mesh/generated/meshtastic/deviceonly.pb.h"
#include "modules/ExternalNotificationModule.h"
#include "modules/TextMessageModule.h" #include "modules/TextMessageModule.h"
#include "sleep.h" #include "sleep.h"
#include "target_specific.h" #include "target_specific.h"
@@ -42,6 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
#include "mesh/http/WiFiAPClient.h" #include "mesh/http/WiFiAPClient.h"
#include "modules/esp32/StoreForwardModule.h"
#endif #endif
#ifdef OLED_RU #ifdef OLED_RU
@@ -95,17 +97,17 @@ static uint16_t displayWidth, displayHeight;
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) #if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
// The screen is bigger so use bigger fonts // The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 #define FONT_SMALL ArialMT_Plain_16 // Height: 19
#define FONT_MEDIUM ArialMT_Plain_24 #define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
#define FONT_LARGE ArialMT_Plain_24 #define FONT_LARGE ArialMT_Plain_24 // Height: 28
#else #else
#ifdef OLED_RU #ifdef OLED_RU
#define FONT_SMALL ArialMT_Plain_10_RU #define FONT_SMALL ArialMT_Plain_10_RU
#else #else
#define FONT_SMALL ArialMT_Plain_10 #define FONT_SMALL ArialMT_Plain_10 // Height: 13
#endif #endif
#define FONT_MEDIUM ArialMT_Plain_16 #define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
#define FONT_LARGE ArialMT_Plain_24 #define FONT_LARGE ArialMT_Plain_24 // Height: 28
#endif #endif
#define fontHeight(font) ((font)[1] + 1) // height is position 1 #define fontHeight(font) ((font)[1] + 1) // height is position 1
@@ -116,7 +118,6 @@ static uint16_t displayWidth, displayHeight;
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2) #define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
/** /**
* Draw the icon with extra info printed around the corners * Draw the icon with extra info printed around the corners
*/ */
@@ -274,9 +275,9 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
} else { } else {
// otherwise, just display the module frame that's aligned with the current frame // otherwise, just display the module frame that's aligned with the current frame
module_frame = state->currentFrame; module_frame = state->currentFrame;
// DEBUG_MSG("Screen is not in transition. Frame: %d\n\n", module_frame); // LOG_DEBUG("Screen is not in transition. Frame: %d\n\n", module_frame);
} }
// DEBUG_MSG("Drawing Module Frame %d\n\n", module_frame); // LOG_DEBUG("Drawing Module Frame %d\n\n", module_frame);
MeshModule &pi = *moduleFrames.at(module_frame); MeshModule &pi = *moduleFrames.at(module_frame);
pi.drawFrame(display, state, x, y); pi.drawFrame(display, state, x, y);
} }
@@ -290,7 +291,7 @@ static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state,
display->drawString(x_offset + x, y_offset + y, "Bluetooth"); display->drawString(x_offset + x, y_offset + y, "Bluetooth");
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_MEDIUM -4 : y_offset + FONT_HEIGHT_MEDIUM + 5; y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_MEDIUM - 4 : y_offset + FONT_HEIGHT_MEDIUM + 5;
display->drawString(x_offset + x, y_offset + y, "Enter this code"); display->drawString(x_offset + x, y_offset + y, "Enter this code");
display->setFont(FONT_LARGE); display->setFont(FONT_LARGE);
@@ -329,11 +330,9 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
display->drawString(64 + x, y, "Updating"); display->drawString(64 + x, y, "Updating");
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
if ((millis() / 1000) % 2) { display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ."); display->drawStringMaxWidth(0 + x, 2 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(),
} else { "Please be patient and do not power off.");
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
}
} }
/// Draw the last text message we received /// Draw the last text message we received
@@ -353,10 +352,9 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
} }
// Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward module are enabled // Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward module are enabled
static bool shouldDrawMessage(const MeshPacket *packet) static bool shouldDrawMessage(const meshtastic_MeshPacket *packet)
{ {
return packet->from != 0 && !moduleConfig.range_test.enabled && return packet->from != 0 && !moduleConfig.range_test.enabled && !moduleConfig.store_forward.enabled;
!moduleConfig.store_forward.enabled;
} }
/// Draw the last text message we received /// Draw the last text message we received
@@ -364,25 +362,30 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
{ {
displayedNodeNum = 0; // Not currently showing a node pane displayedNodeNum = 0; // Not currently showing a node pane
MeshPacket &mp = devicestate.rx_text_message; // the max length of this buffer is much longer than we can possibly print
NodeInfo *node = nodeDB.getNode(getFrom(&mp)); static char tempBuf[237];
// DEBUG_MSG("drawing text message from 0x%x: %s\n", mp.from,
meshtastic_MeshPacket &mp = devicestate.rx_text_message;
meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp));
// LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from,
// mp.decoded.variant.data.decoded.bytes); // mp.decoded.variant.data.decoded.bytes);
// Demo for drawStringMaxWidth: // Demo for drawStringMaxWidth:
// with the third parameter you can define the width after which words will // with the third parameter you can define the width after which words will
// be wrapped. Currently only spaces and "-" are allowed for wrapping // be wrapped. Currently only spaces and "-" are allowed for wrapping
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_MEDIUM);
String sender = (node && node->has_user) ? node->user.short_name : "???";
display->drawString(0 + x, 0 + y, sender);
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
// the max length of this buffer is much longer than we can possibly print display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
static char tempBuf[96]; display->setColor(BLACK);
snprintf(tempBuf, sizeof(tempBuf), " %s", mp.decoded.payload.bytes); }
display->drawStringf(0 + x, 0 + y, tempBuf, "From: %s", (node && node->has_user) ? node->user.short_name : "???");
display->drawStringMaxWidth(4 + x, 10 + y, SCREEN_WIDTH - (6 + x), tempBuf); if (config.display.heading_bold) {
display->drawStringf(1 + x, 0 + y, tempBuf, "From: %s", (node && node->has_user) ? node->user.short_name : "???");
}
display->setColor(WHITE);
snprintf(tempBuf, sizeof(tempBuf), "%s", mp.decoded.payload.bytes);
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), tempBuf);
} }
/// Draw a series of fields in a column, wrapping to multiple colums if needed /// Draw a series of fields in a column, wrapping to multiple colums if needed
@@ -395,6 +398,10 @@ static void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char *
int xo = x, yo = y; int xo = x, yo = y;
while (*f) { while (*f) {
display->drawString(xo, yo, *f); display->drawString(xo, yo, *f);
if ((display->getColor() == BLACK) && config.display.heading_bold)
display->drawString(xo + 1, yo, *f);
display->setColor(WHITE);
yo += FONT_HEIGHT_SMALL; yo += FONT_HEIGHT_SMALL;
if (yo > SCREEN_HEIGHT - FONT_HEIGHT_SMALL) { if (yo > SCREEN_HEIGHT - FONT_HEIGHT_SMALL) {
xo += SCREEN_WIDTH / 2; xo += SCREEN_WIDTH / 2;
@@ -462,9 +469,15 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *nodeStatus) static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *nodeStatus)
{ {
char usersString[20]; char usersString[20];
sprintf(usersString, "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal()); snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
display->drawFastImage(x, y + 3, 8, 8, imgUser);
#else
display->drawFastImage(x, y, 8, 8, imgUser); display->drawFastImage(x, y, 8, 8, imgUser);
#endif
display->drawString(x + 10, y - 2, usersString); display->drawString(x + 10, y - 2, usersString);
if (config.display.heading_bold)
display->drawString(x + 11, y - 2, usersString);
} }
// Draw GPS status summary // Draw GPS status summary
@@ -473,15 +486,21 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
if (config.position.fixed_position) { if (config.position.fixed_position) {
// GPS coordinates are currently fixed // GPS coordinates are currently fixed
display->drawString(x - 1, y - 2, "Fixed GPS"); display->drawString(x - 1, y - 2, "Fixed GPS");
if (config.display.heading_bold)
display->drawString(x, y - 2, "Fixed GPS");
return; return;
} }
if (!gps->getIsConnected()) { if (!gps->getIsConnected()) {
display->drawString(x, y - 2, "No GPS"); display->drawString(x, y - 2, "No GPS");
if (config.display.heading_bold)
display->drawString(x + 1, y - 2, "No GPS");
return; return;
} }
display->drawFastImage(x, y, 6, 8, gps->getHasLock() ? imgPositionSolid : imgPositionEmpty); display->drawFastImage(x, y, 6, 8, gps->getHasLock() ? imgPositionSolid : imgPositionEmpty);
if (!gps->getHasLock()) { if (!gps->getHasLock()) {
display->drawString(x + 8, y - 2, "No sats"); display->drawString(x + 8, y - 2, "No sats");
if (config.display.heading_bold)
display->drawString(x + 9, y - 2, "No sats");
return; return;
} else { } else {
char satsString[3]; char satsString[3];
@@ -501,11 +520,30 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
display->drawFastImage(x + 24, y, 8, 8, imgSatellite); display->drawFastImage(x + 24, y, 8, 8, imgSatellite);
// Draw the number of satellites // Draw the number of satellites
sprintf(satsString, "%u", gps->getNumSatellites()); snprintf(satsString, sizeof(satsString), "%u", gps->getNumSatellites());
display->drawString(x + 34, y - 2, satsString); display->drawString(x + 34, y - 2, satsString);
if (config.display.heading_bold)
display->drawString(x + 35, y - 2, satsString);
} }
} }
// Draw status when gps is disabled by PMU
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
{
#ifdef HAS_PMU
String displayLine = "GPS disabled";
int16_t xPos = display->getStringWidth(displayLine);
if (!config.position.gps_enabled) {
display->drawString(x + xPos, y, displayLine);
#ifdef GPS_POWER_TOGGLE
display->drawString(x + xPos, y - 2 + FONT_HEIGHT_SMALL, " by button");
#endif
// display->drawString(x + xPos, y + 2, displayLine);
}
#endif
}
static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps) static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
{ {
String displayLine = ""; String displayLine = "";
@@ -518,7 +556,7 @@ static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GP
} else { } else {
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude())); geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
displayLine = "Altitude: " + String(geoCoord.getAltitude()) + "m"; displayLine = "Altitude: " + String(geoCoord.getAltitude()) + "m";
if (config.display.units == Config_DisplayConfig_DisplayUnits_IMPERIAL) if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL)
displayLine = "Altitude: " + String(geoCoord.getAltitude() * METERS_TO_FEET) + "ft"; displayLine = "Altitude: " + String(geoCoord.getAltitude() * METERS_TO_FEET) + "ft";
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine); display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
} }
@@ -540,25 +578,26 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude())); geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
if (gpsFormat != Config_DisplayConfig_GpsCoordinateFormat_DMS) { if (gpsFormat != meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) {
char coordinateLine[22]; char coordinateLine[22];
if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_DEC) { // Decimal Degrees if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC) { // Decimal Degrees
sprintf(coordinateLine, "%f %f", geoCoord.getLatitude() * 1e-7, geoCoord.getLongitude() * 1e-7); snprintf(coordinateLine, sizeof(coordinateLine), "%f %f", geoCoord.getLatitude() * 1e-7,
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_UTM) { // Universal Transverse Mercator geoCoord.getLongitude() * 1e-7);
sprintf(coordinateLine, "%2i%1c %06u %07u", geoCoord.getUTMZone(), geoCoord.getUTMBand(), } else if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_UTM) { // Universal Transverse Mercator
snprintf(coordinateLine, sizeof(coordinateLine), "%2i%1c %06u %07u", geoCoord.getUTMZone(), geoCoord.getUTMBand(),
geoCoord.getUTMEasting(), geoCoord.getUTMNorthing()); geoCoord.getUTMEasting(), geoCoord.getUTMNorthing());
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_MGRS) { // Military Grid Reference System } else if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MGRS) { // Military Grid Reference System
sprintf(coordinateLine, "%2i%1c %1c%1c %05u %05u", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(), snprintf(coordinateLine, sizeof(coordinateLine), "%2i%1c %1c%1c %05u %05u", geoCoord.getMGRSZone(),
geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(), geoCoord.getMGRSBand(), geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k(),
geoCoord.getMGRSNorthing()); geoCoord.getMGRSEasting(), geoCoord.getMGRSNorthing());
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_OLC) { // Open Location Code } else if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OLC) { // Open Location Code
geoCoord.getOLCCode(coordinateLine); geoCoord.getOLCCode(coordinateLine);
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_OSGR) { // Ordnance Survey Grid Reference } else if (gpsFormat == meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR) { // Ordnance Survey Grid Reference
if (geoCoord.getOSGRE100k() == 'I' || geoCoord.getOSGRN100k() == 'I') // OSGR is only valid around the UK region if (geoCoord.getOSGRE100k() == 'I' || geoCoord.getOSGRN100k() == 'I') // OSGR is only valid around the UK region
sprintf(coordinateLine, "%s", "Out of Boundary"); snprintf(coordinateLine, sizeof(coordinateLine), "%s", "Out of Boundary");
else else
sprintf(coordinateLine, "%1c%1c %05u %05u", geoCoord.getOSGRE100k(), geoCoord.getOSGRN100k(), snprintf(coordinateLine, sizeof(coordinateLine), "%1c%1c %05u %05u", geoCoord.getOSGRE100k(),
geoCoord.getOSGREasting(), geoCoord.getOSGRNorthing()); geoCoord.getOSGRN100k(), geoCoord.getOSGREasting(), geoCoord.getOSGRNorthing());
} }
// If fixed position, display text "Fixed GPS" alternating with the coordinates. // If fixed position, display text "Fixed GPS" alternating with the coordinates.
@@ -575,10 +614,10 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
} else { } else {
char latLine[22]; char latLine[22];
char lonLine[22]; char lonLine[22];
sprintf(latLine, "%2i° %2i' %2u\" %1c", geoCoord.getDMSLatDeg(), geoCoord.getDMSLatMin(), geoCoord.getDMSLatSec(), snprintf(latLine, sizeof(latLine), "%2i° %2i' %2u\" %1c", geoCoord.getDMSLatDeg(), geoCoord.getDMSLatMin(),
geoCoord.getDMSLatCP()); geoCoord.getDMSLatSec(), geoCoord.getDMSLatCP());
sprintf(lonLine, "%3i° %2i' %2u\" %1c", geoCoord.getDMSLonDeg(), geoCoord.getDMSLonMin(), geoCoord.getDMSLonSec(), snprintf(lonLine, sizeof(lonLine), "%3i° %2i' %2u\" %1c", geoCoord.getDMSLonDeg(), geoCoord.getDMSLonMin(),
geoCoord.getDMSLonCP()); geoCoord.getDMSLonSec(), geoCoord.getDMSLonCP());
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(latLine))) / 2, y - FONT_HEIGHT_SMALL * 1, latLine); display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(latLine))) / 2, y - FONT_HEIGHT_SMALL * 1, latLine);
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(lonLine))) / 2, y, lonLine); display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(lonLine))) / 2, y, lonLine);
} }
@@ -614,8 +653,8 @@ class Point
void scale(float f) void scale(float f)
{ {
//We use -f here to counter the flip that happens // We use -f here to counter the flip that happens
//on the y axis when drawing and rotating on screen // on the y axis when drawing and rotating on screen
x *= f; x *= f;
y *= -f; y *= -f;
} }
@@ -660,7 +699,7 @@ static float estimatedHeading(double lat, double lon)
/// Sometimes we will have Position objects that only have a time, so check for /// Sometimes we will have Position objects that only have a time, so check for
/// valid lat/lon /// valid lat/lon
static bool hasPosition(NodeInfo *n) static bool hasPosition(meshtastic_NodeInfo *n)
{ {
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
} }
@@ -668,17 +707,22 @@ static bool hasPosition(NodeInfo *n)
static uint16_t getCompassDiam(OLEDDisplay *display) static uint16_t getCompassDiam(OLEDDisplay *display)
{ {
uint16_t diam = 0; uint16_t diam = 0;
uint16_t offset = 0;
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT)
offset = FONT_HEIGHT_SMALL;
// get the smaller of the 2 dimensions and subtract 20 // get the smaller of the 2 dimensions and subtract 20
if(display->getWidth() > display->getHeight()) { if (display->getWidth() > (display->getHeight() - offset)) {
diam = display->getHeight(); diam = display->getHeight() - offset;
// if 2/3 of the other size would be smaller, use that // if 2/3 of the other size would be smaller, use that
if (diam > (display->getWidth() * 2 / 3)) { if (diam > (display->getWidth() * 2 / 3)) {
diam = display->getWidth() * 2 / 3; diam = display->getWidth() * 2 / 3;
} }
} else { } else {
diam = display->getWidth(); diam = display->getWidth();
if (diam > (display->getHeight() * 2 / 3)) { if (diam > ((display->getHeight() - offset) * 2 / 3)) {
diam = display->getHeight() * 2 / 3; diam = (display->getHeight() - offset) * 2 / 3;
} }
} }
@@ -712,8 +756,8 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
// Draw north // Draw north
static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading) static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
{ {
//If north is supposed to be at the top of the compass we want rotation to be +0 // If north is supposed to be at the top of the compass we want rotation to be +0
if(config.display.compass_north_top) if (config.display.compass_north_top)
myHeading = -0; myHeading = -0;
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f); Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f);
@@ -742,7 +786,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
prevFrame = state->currentFrame; prevFrame = state->currentFrame;
nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes(); nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes();
NodeInfo *n = nodeDB.getNodeByIndex(nodeIndex); meshtastic_NodeInfo *n = nodeDB.getNodeByIndex(nodeIndex);
if (n->num == nodeDB.getNodeNum()) { if (n->num == nodeDB.getNodeNum()) {
// Don't show our node, just skip to next // Don't show our node, just skip to next
nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes(); nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes();
@@ -751,13 +795,17 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
displayedNodeNum = n->num; displayedNodeNum = n->num;
} }
NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex); meshtastic_NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex);
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
// The coordinates define the left starting point of the text // The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
}
const char *username = node->has_user ? node->user.long_name : "Unknown Name"; const char *username = node->has_user ? node->user.long_name : "Unknown Name";
static char signalStr[20]; static char signalStr[20];
@@ -783,27 +831,34 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
} }
static char distStr[20]; static char distStr[20];
strcpy(distStr, "? km"); // might not have location data strncpy(distStr, "? km", sizeof(distStr)); // might not have location data
NodeInfo *ourNode = nodeDB.getNode(nodeDB.getNodeNum()); meshtastic_NodeInfo *ourNode = nodeDB.getNode(nodeDB.getNodeNum());
const char *fields[] = {username, distStr, signalStr, lastStr, NULL}; const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
int16_t compassX = 0, compassY = 0;
// coordinates for the center of the compass/circle // coordinates for the center of the compass/circle
int16_t compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5, compassY = y + SCREEN_HEIGHT / 2; if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5;
compassY = y + SCREEN_HEIGHT / 2;
} else {
compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5;
compassY = y + FONT_HEIGHT_SMALL + (SCREEN_HEIGHT - FONT_HEIGHT_SMALL) / 2;
}
bool hasNodeHeading = false; bool hasNodeHeading = false;
if (ourNode && hasPosition(ourNode)) { if (ourNode && hasPosition(ourNode)) {
Position &op = ourNode->position; meshtastic_Position &op = ourNode->position;
float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i)); float myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
drawCompassNorth(display, compassX, compassY, myHeading); drawCompassNorth(display, compassX, compassY, myHeading);
if (hasPosition(node)) { if (hasPosition(node)) {
// display direction toward node // display direction toward node
hasNodeHeading = true; hasNodeHeading = true;
Position &p = node->position; meshtastic_Position &p = node->position;
float d = float d =
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
if (config.display.units == Config_DisplayConfig_DisplayUnits_IMPERIAL) { if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
if (d < (2 * MILES_TO_FEET)) if (d < (2 * MILES_TO_FEET))
snprintf(distStr, sizeof(distStr), "%.0f ft", d * METERS_TO_FEET); snprintf(distStr, sizeof(distStr), "%.0f ft", d * METERS_TO_FEET);
else else
@@ -819,45 +874,26 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
GeoCoord::bearing(DegD(op.latitude_i), DegD(op.longitude_i), DegD(p.latitude_i), DegD(p.longitude_i)); GeoCoord::bearing(DegD(op.latitude_i), DegD(op.longitude_i), DegD(p.latitude_i), DegD(p.longitude_i));
// If the top of the compass is a static north then bearingToOther can be drawn on the compass directly // If the top of the compass is a static north then bearingToOther can be drawn on the compass directly
// If the top of the compass is not a static north we need adjust bearingToOther based on heading // If the top of the compass is not a static north we need adjust bearingToOther based on heading
if(!config.display.compass_north_top) if (!config.display.compass_north_top)
bearingToOther -= myHeading; bearingToOther -= myHeading;
drawNodeHeading(display, compassX, compassY, bearingToOther); drawNodeHeading(display, compassX, compassY, bearingToOther);
} }
} }
if (!hasNodeHeading) if (!hasNodeHeading) {
// direction to node is unknown so display question mark // direction to node is unknown so display question mark
// Debug info for gps lock errors // Debug info for gps lock errors
// DEBUG_MSG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node)); // LOG_DEBUG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node));
display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?"); display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?");
}
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2); display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
display->setColor(BLACK);
}
// Must be after distStr is populated // Must be after distStr is populated
drawColumns(display, x, y, fields); drawColumns(display, x, y, fields);
} }
#if 0
void _screen_header()
{
if (!disp)
return;
// Message count
//snprintf(buffer, sizeof(buffer), "#%03d", ttn_get_count() % 1000);
//display->setTextAlignment(TEXT_ALIGN_LEFT);
//display->drawString(0, 2, buffer);
// Datetime
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(display->getWidth()/2, 2, gps.getTimeStr());
// Satellite count
display->setTextAlignment(TEXT_ALIGN_RIGHT);
char buffer[10];
display->drawString(display->getWidth() - SATELLITE_IMAGE_WIDTH - 4, 2, itoa(gps.satellites.value(), buffer, 10));
display->drawXbm(display->getWidth() - SATELLITE_IMAGE_WIDTH, 0, SATELLITE_IMAGE_WIDTH, SATELLITE_IMAGE_HEIGHT, SATELLITE_IMAGE);
}
#endif
// #ifdef RAK4630 // #ifdef RAK4630
// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), // Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl),
// dispdev_oled(address, sda, scl), ui(&dispdev) // dispdev_oled(address, sda, scl), ui(&dispdev)
@@ -872,7 +908,11 @@ void _screen_header()
// } // }
// } // }
// #else // #else
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev) Screen::Screen(uint8_t address, int sda, int scl)
: OSThread("Screen"), cmdQueue(32),
dispdev(address, sda, scl,
screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 ? GEOMETRY_128_128 : GEOMETRY_128_64),
ui(&dispdev)
{ {
address_found = address; address_found = address;
cmdQueue.setReader(this); cmdQueue.setReader(this);
@@ -900,14 +940,14 @@ void Screen::handleSetOn(bool on)
if (on != screenOn) { if (on != screenOn) {
if (on) { if (on) {
DEBUG_MSG("Turning on screen\n"); LOG_INFO("Turning on screen\n");
dispdev.displayOn(); dispdev.displayOn();
dispdev.displayOn(); dispdev.displayOn();
enabled = true; enabled = true;
setInterval(0); // Draw ASAP setInterval(0); // Draw ASAP
runASAP = true; runASAP = true;
} else { } else {
DEBUG_MSG("Turning off screen\n"); LOG_INFO("Turning off screen\n");
dispdev.displayOff(); dispdev.displayOff();
enabled = false; enabled = false;
} }
@@ -922,6 +962,8 @@ void Screen::setup()
useDisplay = true; useDisplay = true;
#ifdef AutoOLEDWire_h #ifdef AutoOLEDWire_h
if (screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107)
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1106;
dispdev.setDetected(screen_model); dispdev.setDetected(screen_model);
#endif #endif
@@ -964,8 +1006,8 @@ void Screen::setup()
#ifdef SCREEN_MIRROR #ifdef SCREEN_MIRROR
dispdev.mirrorScreen(); dispdev.mirrorScreen();
#else #else
// Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically flip it. // Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically
// If you have a headache now, you're welcome. // flip it. If you have a headache now, you're welcome.
if (!config.display.flip_screen) { if (!config.display.flip_screen) {
dispdev.flipScreenVertically(); dispdev.flipScreenVertically();
} }
@@ -974,7 +1016,7 @@ void Screen::setup()
// Get our hardware ID // Get our hardware ID
uint8_t dmac[6]; uint8_t dmac[6];
getMacAddr(dmac); getMacAddr(dmac);
sprintf(ourId, "%02x%02x", dmac[4], dmac[5]); snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
// Turn on the display. // Turn on the display.
handleSetOn(true); handleSetOn(true);
@@ -1020,7 +1062,7 @@ int32_t Screen::runOnce()
// serialSinceMsec adjusts for additional serial wait time during nRF52 bootup // serialSinceMsec adjusts for additional serial wait time during nRF52 bootup
static bool showingBootScreen = true; static bool showingBootScreen = true;
if (showingBootScreen && (millis() > (logo_timeout + serialSinceMsec))) { if (showingBootScreen && (millis() > (logo_timeout + serialSinceMsec))) {
DEBUG_MSG("Done with boot screen...\n"); LOG_INFO("Done with boot screen...\n");
stopBootScreen(); stopBootScreen();
showingBootScreen = false; showingBootScreen = false;
} }
@@ -1029,7 +1071,7 @@ int32_t Screen::runOnce()
if (strlen(oemStore.oem_text) > 0) { if (strlen(oemStore.oem_text) > 0) {
static bool showingOEMBootScreen = true; static bool showingOEMBootScreen = true;
if (showingOEMBootScreen && (millis() > ((logo_timeout / 2) + serialSinceMsec))) { if (showingOEMBootScreen && (millis() > ((logo_timeout / 2) + serialSinceMsec))) {
DEBUG_MSG("Switch to OEM screen...\n"); LOG_INFO("Switch to OEM screen...\n");
// Change frames. // Change frames.
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen}; static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]); static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
@@ -1043,7 +1085,7 @@ int32_t Screen::runOnce()
} }
#ifndef DISABLE_WELCOME_UNSET #ifndef DISABLE_WELCOME_UNSET
if (showingNormalScreen && config.lora.region == Config_LoRaConfig_RegionCode_UNSET) { if (showingNormalScreen && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
setWelcomeFrames(); setWelcomeFrames();
} }
#endif #endif
@@ -1062,7 +1104,13 @@ int32_t Screen::runOnce()
handleSetOn(false); handleSetOn(false);
break; break;
case Cmd::ON_PRESS: case Cmd::ON_PRESS:
// If a nag notification is running, stop it
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
externalNotificationModule->stopNow();
} else {
// Don't advance the screen if we just wanted to switch off the nag notification
handleOnPress(); handleOnPress();
}
break; break;
case Cmd::START_BLUETOOTH_PIN_SCREEN: case Cmd::START_BLUETOOTH_PIN_SCREEN:
handleStartBluetoothPinScreen(cmd.bluetooth_pin); handleStartBluetoothPinScreen(cmd.bluetooth_pin);
@@ -1085,7 +1133,7 @@ int32_t Screen::runOnce()
handleRebootScreen(); handleRebootScreen();
break; break;
default: default:
DEBUG_MSG("BUG: invalid cmd\n"); LOG_ERROR("Invalid screen cmd\n");
} }
} }
@@ -1116,12 +1164,12 @@ int32_t Screen::runOnce()
// standard screen loop handling here // standard screen loop handling here
if (config.display.auto_screen_carousel_secs > 0 && if (config.display.auto_screen_carousel_secs > 0 &&
(millis() - lastScreenTransition) > (config.display.auto_screen_carousel_secs * 1000)) { (millis() - lastScreenTransition) > (config.display.auto_screen_carousel_secs * 1000)) {
DEBUG_MSG("LastScreenTransition exceeded %ums transitioning to next frame\n", (millis() - lastScreenTransition)); LOG_DEBUG("LastScreenTransition exceeded %ums transitioning to next frame\n", (millis() - lastScreenTransition));
handleOnPress(); handleOnPress();
} }
} }
// DEBUG_MSG("want fps %d, fixed=%d\n", targetFramerate, // LOG_DEBUG("want fps %d, fixed=%d\n", targetFramerate,
// ui.getUiState()->frameState); If we are scrolling we need to be called // ui.getUiState()->frameState); If we are scrolling we need to be called
// soon, otherwise just 1 fps (to save CPU) We also ask to be called twice // soon, otherwise just 1 fps (to save CPU) We also ask to be called twice
// as fast as we really need so that any rounding errors still result with // as fast as we really need so that any rounding errors still result with
@@ -1152,7 +1200,7 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat
void Screen::setSSLFrames() void Screen::setSSLFrames()
{ {
if (address_found) { if (address_found) {
// DEBUG_MSG("showing SSL frames\n"); // LOG_DEBUG("showing SSL frames\n");
static FrameCallback sslFrames[] = {drawSSLScreen}; static FrameCallback sslFrames[] = {drawSSLScreen};
ui.setFrames(sslFrames, 1); ui.setFrames(sslFrames, 1);
ui.update(); ui.update();
@@ -1164,7 +1212,7 @@ void Screen::setSSLFrames()
void Screen::setWelcomeFrames() void Screen::setWelcomeFrames()
{ {
if (address_found) { if (address_found) {
// DEBUG_MSG("showing Welcome frames\n"); // LOG_DEBUG("showing Welcome frames\n");
ui.disableAllIndicators(); ui.disableAllIndicators();
static FrameCallback welcomeFrames[] = {drawWelcomeScreen}; static FrameCallback welcomeFrames[] = {drawWelcomeScreen};
@@ -1176,13 +1224,13 @@ void Screen::setWelcomeFrames()
// restore our regular frame list // restore our regular frame list
void Screen::setFrames() void Screen::setFrames()
{ {
DEBUG_MSG("showing standard frames\n"); LOG_DEBUG("showing standard frames\n");
showingNormalScreen = true; showingNormalScreen = true;
moduleFrames = MeshModule::GetMeshModulesWithUIFrames(); moduleFrames = MeshModule::GetMeshModulesWithUIFrames();
DEBUG_MSG("Showing %d module frames\n", moduleFrames.size()); LOG_DEBUG("Showing %d module frames\n", moduleFrames.size());
int totalFrameCount = MAX_NUM_NODES + NUM_EXTRA_FRAMES + moduleFrames.size(); int totalFrameCount = MAX_NUM_NODES + NUM_EXTRA_FRAMES + moduleFrames.size();
DEBUG_MSG("Total frame count: %d\n", totalFrameCount); LOG_DEBUG("Total frame count: %d\n", totalFrameCount);
// We don't show the node info our our node (if we have it yet - we should) // We don't show the node info our our node (if we have it yet - we should)
size_t numnodes = nodeStatus->getNumTotal(); size_t numnodes = nodeStatus->getNumTotal();
@@ -1201,7 +1249,7 @@ void Screen::setFrames()
normalFrames[numframes++] = drawModuleFrame; normalFrames[numframes++] = drawModuleFrame;
} }
DEBUG_MSG("Added modules. numframes: %d\n", numframes); LOG_DEBUG("Added modules. numframes: %d\n", numframes);
// If we have a critical fault, show it first // If we have a critical fault, show it first
if (myNodeInfo.error_code) if (myNodeInfo.error_code)
@@ -1234,7 +1282,7 @@ void Screen::setFrames()
} }
#endif #endif
DEBUG_MSG("Finished building frames. numframes: %d\n", numframes); LOG_DEBUG("Finished building frames. numframes: %d\n", numframes);
ui.setFrames(normalFrames, numframes); ui.setFrames(normalFrames, numframes);
ui.enableAllIndicators(); ui.enableAllIndicators();
@@ -1247,7 +1295,7 @@ void Screen::setFrames()
void Screen::handleStartBluetoothPinScreen(uint32_t pin) void Screen::handleStartBluetoothPinScreen(uint32_t pin)
{ {
DEBUG_MSG("showing bluetooth screen\n"); LOG_DEBUG("showing bluetooth screen\n");
showingNormalScreen = false; showingNormalScreen = false;
static FrameCallback btFrames[] = {drawFrameBluetooth}; static FrameCallback btFrames[] = {drawFrameBluetooth};
@@ -1261,7 +1309,7 @@ void Screen::handleStartBluetoothPinScreen(uint32_t pin)
void Screen::handleShutdownScreen() void Screen::handleShutdownScreen()
{ {
DEBUG_MSG("showing shutdown screen\n"); LOG_DEBUG("showing shutdown screen\n");
showingNormalScreen = false; showingNormalScreen = false;
static FrameCallback shutdownFrames[] = {drawFrameShutdown}; static FrameCallback shutdownFrames[] = {drawFrameShutdown};
@@ -1273,7 +1321,7 @@ void Screen::handleShutdownScreen()
void Screen::handleRebootScreen() void Screen::handleRebootScreen()
{ {
DEBUG_MSG("showing reboot screen\n"); LOG_DEBUG("showing reboot screen\n");
showingNormalScreen = false; showingNormalScreen = false;
static FrameCallback rebootFrames[] = {drawFrameReboot}; static FrameCallback rebootFrames[] = {drawFrameReboot};
@@ -1285,7 +1333,7 @@ void Screen::handleRebootScreen()
void Screen::handleStartFirmwareUpdateScreen() void Screen::handleStartFirmwareUpdateScreen()
{ {
DEBUG_MSG("showing firmware screen\n"); LOG_DEBUG("showing firmware screen\n");
showingNormalScreen = false; showingNormalScreen = false;
static FrameCallback btFrames[] = {drawFrameFirmware}; static FrameCallback btFrames[] = {drawFrameFirmware};
@@ -1316,7 +1364,7 @@ void Screen::handlePrint(const char *text)
{ {
// the string passed into us probably has a newline, but that would confuse the logging system // the string passed into us probably has a newline, but that would confuse the logging system
// so strip it // so strip it
DEBUG_MSG("Screen: %.*s\n", strlen(text) - 1, text); LOG_DEBUG("Screen: %.*s\n", strlen(text) - 1, text);
if (!useDisplay || !showingNormalScreen) if (!useDisplay || !showingNormalScreen)
return; return;
@@ -1357,6 +1405,11 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// The coordinates define the left starting point of the text // The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
}
char channelStr[20]; char channelStr[20];
{ {
concurrency::LockGuard guard(&lock); concurrency::LockGuard guard(&lock);
@@ -1365,19 +1418,80 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
} }
// Display power status // Display power status
if (powerStatus->getHasBattery()) if (powerStatus->getHasBattery()) {
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
drawBattery(display, x, y + 2, imgBattery, powerStatus); drawBattery(display, x, y + 2, imgBattery, powerStatus);
else if (powerStatus->knowsUSB()) } else {
drawBattery(display, x + 1, y + 3, imgBattery, powerStatus);
}
} else if (powerStatus->knowsUSB()) {
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower); display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
} else {
display->drawFastImage(x + 1, y + 3, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
}
}
// Display nodes status // Display nodes status
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus); drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus);
} else {
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus);
}
// Display GPS status // Display GPS status
if (!config.position.gps_enabled) {
int16_t yPos = y + 2;
#ifdef GPS_POWER_TOGGLE
yPos = (y + 10 + FONT_HEIGHT_SMALL);
#endif
drawGPSpowerstat(display, x, yPos, gpsStatus);
} else {
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus); drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus);
} else {
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 3, gpsStatus);
}
}
display->setColor(WHITE);
// Draw the channel name // Draw the channel name
display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr); display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
// Draw our hardware ID to assist with bluetooth pairing // Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
display->drawFastImage(x + SCREEN_WIDTH - (10) - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo); if (moduleConfig.store_forward.enabled) {
#ifdef ARCH_ESP32
if (millis() - storeForwardModule->lastHeartbeat >
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8,
imgQuestion);
#endif
} else {
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL1);
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 13 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 11, 8,
imgSF);
#endif
}
#endif
} else {
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL1);
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL2);
#else
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
#endif
}
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId); display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId);
// Draw any log messages // Draw any log messages
@@ -1404,14 +1518,29 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
// The coordinates define the left starting point of the text // The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
}
if (WiFi.status() != WL_CONNECTED) { if (WiFi.status() != WL_CONNECTED) {
display->drawString(x, y, String("WiFi: Not Connected")); display->drawString(x, y, String("WiFi: Not Connected"));
if (config.display.heading_bold)
display->drawString(x + 1, y, String("WiFi: Not Connected"));
} else { } else {
display->drawString(x, y, String("WiFi: Connected")); display->drawString(x, y, String("WiFi: Connected"));
if (config.display.heading_bold)
display->drawString(x + 1, y, String("WiFi: Connected"));
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())), y, display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())), y,
"RSSI " + String(WiFi.RSSI())); "RSSI " + String(WiFi.RSSI()));
if (config.display.heading_bold) {
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())) - 1, y,
"RSSI " + String(WiFi.RSSI()));
} }
}
display->setColor(WHITE);
/* /*
- WL_CONNECTED: assigned when connected to a WiFi network; - WL_CONNECTED: assigned when connected to a WiFi network;
@@ -1521,6 +1650,11 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// The coordinates define the left starting point of the text // The coordinates define the left starting point of the text
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
}
char batStr[20]; char batStr[20];
if (powerStatus->getHasBattery()) { if (powerStatus->getHasBattery()) {
int batV = powerStatus->getBatteryVoltageMv() / 1000; int batV = powerStatus->getBatteryVoltageMv() / 1000;
@@ -1531,33 +1665,37 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// Line 1 // Line 1
display->drawString(x, y, batStr); display->drawString(x, y, batStr);
if (config.display.heading_bold)
display->drawString(x + 1, y, batStr);
} else { } else {
// Line 1 // Line 1
display->drawString(x, y, String("USB")); display->drawString(x, y, String("USB"));
if (config.display.heading_bold)
display->drawString(x + 1, y, String("USB"));
} }
auto mode = ""; auto mode = "";
switch (config.lora.modem_preset) { switch (config.lora.modem_preset) {
case Config_LoRaConfig_ModemPreset_SHORT_SLOW: case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
mode = "ShortS"; mode = "ShortS";
break; break;
case Config_LoRaConfig_ModemPreset_SHORT_FAST: case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST:
mode = "ShortF"; mode = "ShortF";
break; break;
case Config_LoRaConfig_ModemPreset_MEDIUM_SLOW: case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
mode = "MedS"; mode = "MedS";
break; break;
case Config_LoRaConfig_ModemPreset_MEDIUM_FAST: case meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
mode = "MedF"; mode = "MedF";
break; break;
case Config_LoRaConfig_ModemPreset_LONG_SLOW: case meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW:
mode = "LongS"; mode = "LongS";
break; break;
case Config_LoRaConfig_ModemPreset_LONG_FAST: case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
mode = "LongF"; mode = "LongF";
break; break;
case Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW: case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
mode = "VeryL"; mode = "VeryL";
break; break;
default: default:
@@ -1566,6 +1704,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
} }
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode); display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
if (config.display.heading_bold)
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode) - 1, y, mode);
// Line 2 // Line 2
uint32_t currentMillis = millis(); uint32_t currentMillis = millis();
@@ -1578,6 +1718,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// minutes %= 60; // minutes %= 60;
// hours %= 24; // hours %= 24;
display->setColor(WHITE);
// Show uptime as days, hours, minutes OR seconds // Show uptime as days, hours, minutes OR seconds
String uptime; String uptime;
if (days >= 2) if (days >= 2)
@@ -1611,17 +1753,19 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// Display Channel Utilization // Display Channel Utilization
char chUtil[13]; char chUtil[13];
sprintf(chUtil, "ChUtil %2.0f%%", airTime->channelUtilizationPercent()); snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil); display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
if (config.position.gps_enabled) {
// Line 3 // Line 3
if (config.display.gps_format != if (config.display.gps_format !=
Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude
drawGPSAltitude(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus); drawGPSAltitude(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus);
// Line 4 // Line 4
drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus); drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus);
} else {
drawGPSpowerstat(display, x - (SCREEN_WIDTH / 4), y + FONT_HEIGHT_SMALL * 2, gpsStatus);
}
/* Display a heartbeat pixel that blinks every time the frame is redrawn */ /* Display a heartbeat pixel that blinks every time the frame is redrawn */
#ifdef SHOW_REDRAWS #ifdef SHOW_REDRAWS
if (heartbeat) if (heartbeat)
@@ -1649,7 +1793,7 @@ void Screen::adjustBrightness()
int Screen::handleStatusUpdate(const meshtastic::Status *arg) int Screen::handleStatusUpdate(const meshtastic::Status *arg)
{ {
// DEBUG_MSG("Screen got status update %d\n", arg->getStatusType()); // LOG_DEBUG("Screen got status update %d\n", arg->getStatusType());
switch (arg->getStatusType()) { switch (arg->getStatusType()) {
case STATUS_TYPE_NODE: case STATUS_TYPE_NODE:
if (showingNormalScreen && nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) { if (showingNormalScreen && nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
@@ -1662,7 +1806,7 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
return 0; return 0;
} }
int Screen::handleTextMessage(const MeshPacket *packet) int Screen::handleTextMessage(const meshtastic_MeshPacket *packet)
{ {
if (showingNormalScreen) { if (showingNormalScreen) {
setFrames(); // Regen the list of screens (will show new text message) setFrames(); // Regen the list of screens (will show new text message)

View File

@@ -10,19 +10,20 @@ namespace graphics
class Screen class Screen
{ {
public: public:
explicit Screen(char){} explicit Screen(char) {}
void onPress() {} void onPress() {}
void setup() {} void setup() {}
void setOn(bool) {} void setOn(bool) {}
void print(const char*){} void print(const char *) {}
void adjustBrightness(){} void adjustBrightness() {}
void doDeepSleep() {} void doDeepSleep() {}
void forceDisplay() {} void forceDisplay() {}
void startBluetoothPinScreen(uint32_t pin) {} void startBluetoothPinScreen(uint32_t pin) {}
void stopBluetoothPinScreen() {} void stopBluetoothPinScreen() {}
void startRebootScreen() {} void startRebootScreen() {}
void startFirmwareUpdateScreen() {}
}; };
} } // namespace graphics
#else #else
#include <cstring> #include <cstring>
@@ -33,7 +34,7 @@ class Screen
#ifdef USE_ST7567 #ifdef USE_ST7567
#include <ST7567Wire.h> #include <ST7567Wire.h>
#elif defined(USE_SH1106) #elif defined(USE_SH1106) || defined(USE_SH1107)
#include <SH1106Wire.h> #include <SH1106Wire.h>
#elif defined(USE_SSD1306) #elif defined(USE_SSD1306)
#include <SSD1306Wire.h> #include <SSD1306Wire.h>
@@ -48,9 +49,9 @@ class Screen
#include "commands.h" #include "commands.h"
#include "concurrency/LockGuard.h" #include "concurrency/LockGuard.h"
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
#include "mesh/MeshModule.h"
#include "power.h" #include "power.h"
#include <string> #include <string>
#include "mesh/MeshModule.h"
// 0 to 255, though particular variants might define different defaults // 0 to 255, though particular variants might define different defaults
#ifndef BRIGHTNESS_DEFAULT #ifndef BRIGHTNESS_DEFAULT
@@ -109,8 +110,8 @@ class Screen : public concurrency::OSThread
CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate); CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate);
CallbackObserver<Screen, const meshtastic::Status *> nodeStatusObserver = CallbackObserver<Screen, const meshtastic::Status *> nodeStatusObserver =
CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate); CallbackObserver<Screen, const meshtastic::Status *>(this, &Screen::handleStatusUpdate);
CallbackObserver<Screen, const MeshPacket *> textMessageObserver = CallbackObserver<Screen, const meshtastic_MeshPacket *> textMessageObserver =
CallbackObserver<Screen, const MeshPacket *>(this, &Screen::handleTextMessage); CallbackObserver<Screen, const meshtastic_MeshPacket *>(this, &Screen::handleTextMessage);
CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver = CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver =
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent); CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
@@ -131,7 +132,8 @@ class Screen : public concurrency::OSThread
void setOn(bool on) void setOn(bool on)
{ {
if (!on) if (!on)
handleSetOn(false); // We handle off commands immediately, because they might be called because the CPU is shutting down handleSetOn(
false); // We handle off commands immediately, because they might be called because the CPU is shutting down
else else
enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF}); enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF});
} }
@@ -231,18 +233,22 @@ class Screen : public concurrency::OSThread
return (uint8_t)(ch | 0xC0); return (uint8_t)(ch | 0xC0);
} }
// map UTF-8 cyrillic chars to it Windows-1251 (CP-1251) ASCII codes // map UTF-8 cyrillic chars to it Windows-1251 (CP-1251) ASCII codes
// note: in this case we must use compatible font - provided ArialMT_Plain_10/16/24 by 'ThingPulse/esp8266-oled-ssd1306' library // note: in this case we must use compatible font - provided ArialMT_Plain_10/16/24 by 'ThingPulse/esp8266-oled-ssd1306'
// have empty chars for non-latin ASCII symbols // library have empty chars for non-latin ASCII symbols
case 0xD0: { case 0xD0: {
SKIPREST = false; SKIPREST = false;
if (ch == 129) return (uint8_t)(168); // Ё if (ch == 129)
if (ch > 143 && ch < 192) return (uint8_t)(ch + 48); return (uint8_t)(168); // Ё
if (ch > 143 && ch < 192)
return (uint8_t)(ch + 48);
break; break;
} }
case 0xD1: { case 0xD1: {
SKIPREST = false; SKIPREST = false;
if (ch == 145) return (uint8_t)(184); // ё if (ch == 145)
if (ch > 127 && ch < 144) return (uint8_t)(ch + 112); return (uint8_t)(184); // ё
if (ch > 127 && ch < 144)
return (uint8_t)(ch + 112);
break; break;
} }
} }
@@ -267,7 +273,7 @@ class Screen : public concurrency::OSThread
DebugInfo *debug_info() { return &debugInfo; } DebugInfo *debug_info() { return &debugInfo; }
int handleStatusUpdate(const meshtastic::Status *arg); int handleStatusUpdate(const meshtastic::Status *arg);
int handleTextMessage(const MeshPacket *arg); int handleTextMessage(const meshtastic_MeshPacket *arg);
int handleUIFrameEvent(const UIFrameEvent *arg); int handleUIFrameEvent(const UIFrameEvent *arg);
/// Used to force (super slow) eink displays to draw critical frames /// Used to force (super slow) eink displays to draw critical frames
@@ -341,10 +347,7 @@ class Screen : public concurrency::OSThread
/// Display device /// Display device
// #ifdef RAK4630 #if defined(USE_SH1106) || defined(USE_SH1107)
// EInkDisplay dispdev;
// AutoOLEDWire dispdev_oled;
#ifdef USE_SH1106
SH1106Wire dispdev; SH1106Wire dispdev;
#elif defined(USE_SSD1306) #elif defined(USE_SSD1306)
SSD1306Wire dispdev; SSD1306Wire dispdev;

View File

@@ -8,7 +8,7 @@
static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl) TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, uint8_t screen_model)
{ {
#ifdef SCREEN_ROTATE #ifdef SCREEN_ROTATE
setGeometry(GEOMETRY_RAWMODE, TFT_HEIGHT, TFT_WIDTH); setGeometry(GEOMETRY_RAWMODE, TFT_HEIGHT, TFT_WIDTH);
@@ -22,7 +22,7 @@ void TFTDisplay::display(void)
{ {
concurrency::LockGuard g(spiLock); concurrency::LockGuard g(spiLock);
uint16_t x,y; uint16_t x, y;
for (y = 0; y < displayHeight; y++) { for (y = 0; y < displayHeight; y++) {
for (x = 0; x < displayWidth; x++) { for (x = 0; x < displayWidth; x++) {
@@ -59,7 +59,7 @@ void TFTDisplay::setDetected(uint8_t detected)
bool TFTDisplay::connect() bool TFTDisplay::connect()
{ {
concurrency::LockGuard g(spiLock); concurrency::LockGuard g(spiLock);
DEBUG_MSG("Doing TFT init\n"); LOG_INFO("Doing TFT init\n");
#ifdef TFT_BL #ifdef TFT_BL
digitalWrite(TFT_BL, HIGH); digitalWrite(TFT_BL, HIGH);

View File

@@ -18,7 +18,7 @@ class TFTDisplay : public OLEDDisplay
/* constructor /* constructor
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
*/ */
TFTDisplay(uint8_t address, int sda, int scl); TFTDisplay(uint8_t address, int sda, int scl, uint8_t screen_model);
// Write the buffer to the display memory // Write the buffer to the display memory
virtual void display(void) override; virtual void display(void) override;

View File

@@ -6,42 +6,27 @@ const uint8_t SATELLITE_IMAGE[] PROGMEM = {0x00, 0x08, 0x00, 0x1C, 0x00, 0x0E, 0
0xF8, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC8, 0x01, 0x9C, 0x54, 0xF8, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC8, 0x01, 0x9C, 0x54,
0x0E, 0x52, 0x07, 0x48, 0x02, 0x26, 0x00, 0x10, 0x00, 0x0E}; 0x0E, 0x52, 0x07, 0x48, 0x02, 0x26, 0x00, 0x10, 0x00, 0x0E};
const uint8_t imgSatellite[] PROGMEM = { 0x70, 0x71, 0x22, 0xFA, 0xFA, 0x22, 0x71, 0x70 }; const uint8_t imgSatellite[] PROGMEM = {0x70, 0x71, 0x22, 0xFA, 0xFA, 0x22, 0x71, 0x70};
const uint8_t imgUSB[] PROGMEM = { 0x60, 0x60, 0x30, 0x18, 0x18, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x24, 0x24, 0x24, 0x3C }; const uint8_t imgUSB[] PROGMEM = {0x60, 0x60, 0x30, 0x18, 0x18, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x24, 0x24, 0x24, 0x3C};
const uint8_t imgPower[] PROGMEM = { 0x40, 0x40, 0x40, 0x58, 0x48, 0x08, 0x08, 0x08, 0x1C, 0x22, 0x22, 0x41, 0x7F, 0x22, 0x22, 0x22 }; const uint8_t imgPower[] PROGMEM = {0x40, 0x40, 0x40, 0x58, 0x48, 0x08, 0x08, 0x08,
const uint8_t imgUser[] PROGMEM = { 0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3C }; 0x1C, 0x22, 0x22, 0x41, 0x7F, 0x22, 0x22, 0x22};
const uint8_t imgPositionEmpty[] PROGMEM = { 0x20, 0x30, 0x28, 0x24, 0x42, 0xFF }; const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3C};
const uint8_t imgPositionSolid[] PROGMEM = { 0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF }; const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
const uint8_t imgInfo[] PROGMEM = { 0xFF, 0x81, 0x81, 0xB5, 0xB5, 0x81, 0x81, 0xFF }; const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
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};
const uint8_t imgInfoL1[] PROGMEM = {0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff};
const uint8_t imgInfoL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
const uint8_t imgSFL1[] PROGMEM = {0xb6, 0x8f, 0x19, 0x11, 0x31, 0xe3, 0xc2, 0x01,
0x01, 0xf9, 0xf9, 0x89, 0x89, 0x89, 0x09, 0xeb};
const uint8_t imgSFL2[] PROGMEM = {0x0e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08,
0x00, 0x0f, 0x0f, 0x00, 0x08, 0x08, 0x08, 0x0f};
#else
const uint8_t imgInfo[] PROGMEM = {0xff, 0x81, 0x00, 0xfb, 0xfb, 0x00, 0x81, 0xff};
const uint8_t imgQuestion[] PROGMEM = {0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1, 0xdf};
const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
#endif
#include "img/icon.xbm" #include "img/icon.xbm"
// We now programmatically draw our compass
#if 0
const
#include "img/compass.xbm"
#endif
#if 0
const uint8_t activeSymbol[] PROGMEM = {
B00000000,
B00000000,
B00011000,
B00100100,
B01000010,
B01000010,
B00100100,
B00011000
};
const uint8_t inactiveSymbol[] PROGMEM = {
B00000000,
B00000000,
B00000000,
B00000000,
B00011000,
B00011000,
B00000000,
B00000000
};
#endif

View File

@@ -1,28 +0,0 @@
#define compass_width 48
#define compass_height 48
static char compass_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x01, 0x00,
0x00, 0xC0, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00,
0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xFC, 0x07, 0xE0, 0x3F, 0x00,
0x00, 0xFE, 0x01, 0x80, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x80, 0x3F, 0x00, 0x00, 0xFC, 0x01,
0x80, 0x1F, 0x00, 0x00, 0xF8, 0x01, 0x80, 0x0F, 0x00, 0x00, 0xF0, 0x01,
0xC0, 0x0F, 0x00, 0x00, 0xF0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F, 0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F,
0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F, 0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F,
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x0F, 0x00, 0x00, 0xF0, 0x03,
0x80, 0x0F, 0x00, 0x00, 0xF0, 0x01, 0x80, 0x1F, 0x00, 0x00, 0xF8, 0x01,
0x80, 0x3F, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x01, 0x80, 0x7F, 0x00,
0x00, 0xFC, 0x07, 0xE0, 0x3F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00,
0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x03, 0x00,
0x00, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

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