mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-20 17:52:35 +00:00
Compare commits
491 Commits
v2.0.6.97f
...
v2.0.14.2b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2baaad8298 | ||
|
|
2e8832babb | ||
|
|
ed155476ac | ||
|
|
61028293b8 | ||
|
|
d14bd652eb | ||
|
|
cb3d5a5748 | ||
|
|
d51aa60864 | ||
|
|
9b18d5d85f | ||
|
|
25096c5c63 | ||
|
|
f1fd41a378 | ||
|
|
ca91447c0e | ||
|
|
4a0f3f31cb | ||
|
|
f07963e802 | ||
|
|
cb8532f2df | ||
|
|
0b1e1687ae | ||
|
|
006cddd5cb | ||
|
|
4d7e3329d9 | ||
|
|
9e8342eb8f | ||
|
|
afb4d141dc | ||
|
|
19d864b5ce | ||
|
|
e8186f7dba | ||
|
|
81854a173a | ||
|
|
083dcef9d6 | ||
|
|
5f0662d47d | ||
|
|
76022b65c6 | ||
|
|
2df81810ec | ||
|
|
efa1445df4 | ||
|
|
53d096b58e | ||
|
|
4da1fb8e27 | ||
|
|
8e0dcb09e8 | ||
|
|
014946ad0e | ||
|
|
3aebb1ffb3 | ||
|
|
3b80421403 | ||
|
|
255d433ebf | ||
|
|
2c1b7840c5 | ||
|
|
e9acf413fb | ||
|
|
7c60896072 | ||
|
|
1941d196bb | ||
|
|
3120744716 | ||
|
|
2ecf273cf3 | ||
|
|
50cee4a6c8 | ||
|
|
ac6d4e33d4 | ||
|
|
4c9f0b2646 | ||
|
|
fab663d1b7 | ||
|
|
fc5e80a5cc | ||
|
|
266c61065d | ||
|
|
e2e7658789 | ||
|
|
a421edce49 | ||
|
|
3f3a4ce44c | ||
|
|
8aab63dace | ||
|
|
aac9b5db30 | ||
|
|
6f30a84afc | ||
|
|
c53c87499b | ||
|
|
cdf379616c | ||
|
|
6fdb93cd16 | ||
|
|
ab3446faed | ||
|
|
9ebe24e680 | ||
|
|
811ac15a81 | ||
|
|
51b2c431d9 | ||
|
|
6cf18b7d07 | ||
|
|
52e8dc7317 | ||
|
|
d8e644191b | ||
|
|
fdc47728af | ||
|
|
54b4b67e5c | ||
|
|
bcf24b8187 | ||
|
|
c628c70db2 | ||
|
|
7f9e638140 | ||
|
|
5a2ad03294 | ||
|
|
a584cac827 | ||
|
|
8f5338dc85 | ||
|
|
8c434c7084 | ||
|
|
88c84dd806 | ||
|
|
f9f083da51 | ||
|
|
481880872c | ||
|
|
0eaf0747f4 | ||
|
|
9a7121d8c9 | ||
|
|
cbd6a0065b | ||
|
|
50f72b0ea0 | ||
|
|
74ec5e8a5c | ||
|
|
bec0cda175 | ||
|
|
ca298d8a7d | ||
|
|
3eaa054c68 | ||
|
|
48ea836a5c | ||
|
|
fda1e29c4d | ||
|
|
836559cda1 | ||
|
|
c04980084a | ||
|
|
111ec56028 | ||
|
|
384eac9a87 | ||
|
|
6a5e0edb60 | ||
|
|
9d47f7a531 | ||
|
|
660a73d58c | ||
|
|
412fbea978 | ||
|
|
293625924d | ||
|
|
4cfedc4b57 | ||
|
|
cd57df3f4f | ||
|
|
6c41960919 | ||
|
|
48609b5bdd | ||
|
|
dad8e2bf6a | ||
|
|
9cda2e9058 | ||
|
|
72dad37138 | ||
|
|
ee25a488ef | ||
|
|
9046dacec8 | ||
|
|
b218ea9ec7 | ||
|
|
6f70d39bae | ||
|
|
80f259cc6c | ||
|
|
36b3bf2211 | ||
|
|
92525587e1 | ||
|
|
5189e328b6 | ||
|
|
4d4af7de59 | ||
|
|
1b932c6bbe | ||
|
|
4065fb1709 | ||
|
|
cf39628222 | ||
|
|
d7fa8fea8d | ||
|
|
db3d66544d | ||
|
|
0a2539650e | ||
|
|
d35b619063 | ||
|
|
0e51a42ce2 | ||
|
|
d5f7d741c3 | ||
|
|
cc0cccbd1b | ||
|
|
6c388e0da8 | ||
|
|
9f3c09cf40 | ||
|
|
34b2d51113 | ||
|
|
1dbd0f8dd1 | ||
|
|
0f4306158c | ||
|
|
d5a3acb83a | ||
|
|
efbdb273c3 | ||
|
|
011013ab1a | ||
|
|
49279e56d0 | ||
|
|
1cfda77356 | ||
|
|
f4779bd93f | ||
|
|
e95db927ac | ||
|
|
a4d3fa55db | ||
|
|
59ee0fb012 | ||
|
|
5831124f1d | ||
|
|
2b9f01f0e4 | ||
|
|
aca1241a7f | ||
|
|
da0440ba17 | ||
|
|
85dd606423 | ||
|
|
7e27729dae | ||
|
|
d49f19a67c | ||
|
|
5520d68b34 | ||
|
|
c33569f833 | ||
|
|
8db3f317ab | ||
|
|
a3636ae8a1 | ||
|
|
7936c7c8ae | ||
|
|
2f3f19fda7 | ||
|
|
c89ca50cc4 | ||
|
|
867e55b9e7 | ||
|
|
28b1616630 | ||
|
|
42122f3d0f | ||
|
|
f905763161 | ||
|
|
bd2b766a36 | ||
|
|
bd51cbd721 | ||
|
|
5e66dd0dad | ||
|
|
80d1a993dd | ||
|
|
e3fd17772d | ||
|
|
440b965e71 | ||
|
|
cf0fb13a12 | ||
|
|
c0166773e8 | ||
|
|
fc775012ea | ||
|
|
d7a71e46aa | ||
|
|
721f87af7e | ||
|
|
a354cebd88 | ||
|
|
97680ca730 | ||
|
|
17a2589b35 | ||
|
|
4f71ab07c9 | ||
|
|
1f6a8eae86 | ||
|
|
ab9d0ba543 | ||
|
|
e13fb9919e | ||
|
|
a3b93a4dcf | ||
|
|
6b0f18e1e4 | ||
|
|
312ef790fc | ||
|
|
713f7d5996 | ||
|
|
3985008e06 | ||
|
|
8f2155f8f9 | ||
|
|
1fc5d70221 | ||
|
|
e7d425ef6e | ||
|
|
c63536d948 | ||
|
|
9c1cfe9358 | ||
|
|
971565aed3 | ||
|
|
3a6e3464e6 | ||
|
|
0181e186ac | ||
|
|
86748bf88e | ||
|
|
5fd00b2538 | ||
|
|
5cec370cf5 | ||
|
|
fce52e16e3 | ||
|
|
0e7797f3bb | ||
|
|
81ee6dd799 | ||
|
|
49172e416e | ||
|
|
57f185c26b | ||
|
|
3a8ffe7ac2 | ||
|
|
d8b85f9a09 | ||
|
|
4d7402839e | ||
|
|
8465467aa8 | ||
|
|
2a0b8093ea | ||
|
|
96fa5dafb8 | ||
|
|
be2d3f7769 | ||
|
|
b283e526bf | ||
|
|
03c5dfc7a8 | ||
|
|
52cfd62031 | ||
|
|
c98dc4cae0 | ||
|
|
f21212dd3e | ||
|
|
0e0ccad489 | ||
|
|
9f1c77da76 | ||
|
|
7c1c49b8ab | ||
|
|
f4099261df | ||
|
|
450e7362f6 | ||
|
|
0b9c8e62ea | ||
|
|
09efbb75b1 | ||
|
|
e5d9f1f946 | ||
|
|
2400dd43b3 | ||
|
|
988d5af69b | ||
|
|
78b6916b1b | ||
|
|
9740f0a505 | ||
|
|
b64a74c0c5 | ||
|
|
d9f0dc7ea4 | ||
|
|
30ae4c2a38 | ||
|
|
d077be1496 | ||
|
|
4f26a2a74a | ||
|
|
41f9636ba3 | ||
|
|
b544163c3f | ||
|
|
6d989a29dd | ||
|
|
8914d1a184 | ||
|
|
1cfc7b800b | ||
|
|
cab5fcf5ae | ||
|
|
cad5c9b70c | ||
|
|
5867038abf | ||
|
|
42b24d4510 | ||
|
|
d750109d00 | ||
|
|
7f0a8d329f | ||
|
|
64895cc7eb | ||
|
|
52903f83e3 | ||
|
|
e0002ef2d5 | ||
|
|
021fc8235c | ||
|
|
0305c7394f | ||
|
|
bca70d10d0 | ||
|
|
1077846e8d | ||
|
|
63c8ca9ca5 | ||
|
|
523b132100 | ||
|
|
2d62cbe345 | ||
|
|
b55fe549e3 | ||
|
|
9a04aaa811 | ||
|
|
092a753a6f | ||
|
|
8a9af37d82 | ||
|
|
74e6eb34bd | ||
|
|
11f1508d85 | ||
|
|
19436b7d54 | ||
|
|
69ff724f0f | ||
|
|
3d3aba584e | ||
|
|
ef1fb877ba | ||
|
|
f1cdfd163d | ||
|
|
8364c2b147 | ||
|
|
8193215294 | ||
|
|
e73ae7cdac | ||
|
|
65aad62702 | ||
|
|
3eefd46ca1 | ||
|
|
115cb05d3b | ||
|
|
44d5c69ba8 | ||
|
|
5ccd66864b | ||
|
|
0b5cae5393 | ||
|
|
be91b08b3e | ||
|
|
c7c5671cca | ||
|
|
979d12d607 | ||
|
|
110c80d045 | ||
|
|
38a1315599 | ||
|
|
8ebe0edc5a | ||
|
|
a8f93d5f47 | ||
|
|
96c272d3d1 | ||
|
|
45e6e86ff9 | ||
|
|
f73b8661de | ||
|
|
3c5710e65b | ||
|
|
4e4a74379e | ||
|
|
41a1dfec79 | ||
|
|
1a949b7ca6 | ||
|
|
840079c25b | ||
|
|
887405cc08 | ||
|
|
d633212f70 | ||
|
|
02def448bc | ||
|
|
7baf30dcb8 | ||
|
|
e09b12ca58 | ||
|
|
1736dada7d | ||
|
|
7f3a624ee3 | ||
|
|
475c87b0e4 | ||
|
|
541f4aa998 | ||
|
|
ab6c4e61a6 | ||
|
|
6ea0963f4b | ||
|
|
259d442d8f | ||
|
|
b134f0bb46 | ||
|
|
63cf01223c | ||
|
|
2505bdbc21 | ||
|
|
d9d8c7eb74 | ||
|
|
3b19040590 | ||
|
|
14be4ee9f0 | ||
|
|
94cb100e3f | ||
|
|
f632933b93 | ||
|
|
e25d05689b | ||
|
|
5c859da4e4 | ||
|
|
6c5602e88d | ||
|
|
b4735f4224 | ||
|
|
3b9b33a5ee | ||
|
|
430908f5d6 | ||
|
|
6f6ca64cfd | ||
|
|
d0243d2cd0 | ||
|
|
796e58161d | ||
|
|
e56f17c658 | ||
|
|
b808ffa9ab | ||
|
|
506bae4a8b | ||
|
|
f6ee6265e6 | ||
|
|
7539d92857 | ||
|
|
21fff392b4 | ||
|
|
580ec590fa | ||
|
|
5c9996dfa1 | ||
|
|
34f9324766 | ||
|
|
3f988c8b69 | ||
|
|
2ac2b6d1b6 | ||
|
|
b8657158be | ||
|
|
70f5f8301b | ||
|
|
adb8d773d4 | ||
|
|
a289406863 | ||
|
|
1a3f2a8ab5 | ||
|
|
23d6b815f5 | ||
|
|
e1feb5eb30 | ||
|
|
cb8247559d | ||
|
|
28b954017f | ||
|
|
16d826d6c7 | ||
|
|
2f7c18303d | ||
|
|
b9df41c55f | ||
|
|
4801260440 | ||
|
|
606262e55d | ||
|
|
0064d18e64 | ||
|
|
6f5a6d5cb4 | ||
|
|
e0194528dd | ||
|
|
30240ac14b | ||
|
|
090e1660fe | ||
|
|
92c9b34d4f | ||
|
|
fb41b0f5c8 | ||
|
|
3f50371ff3 | ||
|
|
812b321154 | ||
|
|
815f9bfc5f | ||
|
|
86ff23d13c | ||
|
|
201b786f77 | ||
|
|
8074955841 | ||
|
|
0992093f4d | ||
|
|
6978e57991 | ||
|
|
755c0b7008 | ||
|
|
7396d0f241 | ||
|
|
220859d0aa | ||
|
|
941786669b | ||
|
|
4eb620d47b | ||
|
|
9794995d7a | ||
|
|
055146602a | ||
|
|
86d7860d86 | ||
|
|
0f2d0d1f07 | ||
|
|
ab6a5a5e07 | ||
|
|
44a33ed463 | ||
|
|
fab08b6451 | ||
|
|
d9cd3dd3e1 | ||
|
|
c75ea87f6b | ||
|
|
706ddf6e95 | ||
|
|
aec091e7aa | ||
|
|
cea8393a7f | ||
|
|
8f94463eac | ||
|
|
a0f5e44967 | ||
|
|
feb7181767 | ||
|
|
a0c1e9cdc6 | ||
|
|
7d1b6f63b5 | ||
|
|
ab6b6514cb | ||
|
|
0e6285edf2 | ||
|
|
8b58eaac20 | ||
|
|
8cbf292373 | ||
|
|
80d0b63c3a | ||
|
|
f5120a29ec | ||
|
|
efc3f4c0ee | ||
|
|
bd2bfd6822 | ||
|
|
e40625d2ad | ||
|
|
eae347ddac | ||
|
|
ae2ca1d89c | ||
|
|
34c73da886 | ||
|
|
88c3ab2636 | ||
|
|
6a5dd26907 | ||
|
|
4de557b4db | ||
|
|
d9eb9758e2 | ||
|
|
d566457f0c | ||
|
|
79ff0659c0 | ||
|
|
af9d4328eb | ||
|
|
8c66940b78 | ||
|
|
c577e09183 | ||
|
|
4a6f269b4b | ||
|
|
bbaeeb7ce9 | ||
|
|
54686905dc | ||
|
|
3cde75f97b | ||
|
|
6c84b3f01c | ||
|
|
68f6cfde0c | ||
|
|
1c8181dc75 | ||
|
|
270746e303 | ||
|
|
72f1416b30 | ||
|
|
a788f16e91 | ||
|
|
f2229e6977 | ||
|
|
05f81922e6 | ||
|
|
06be74ae7c | ||
|
|
72504a5e8b | ||
|
|
e8c034e988 | ||
|
|
aa19718ba4 | ||
|
|
088ab106dd | ||
|
|
110c3f619a | ||
|
|
d1cc503ca8 | ||
|
|
eae7f8a786 | ||
|
|
bb24b86018 | ||
|
|
d3b3a4c148 | ||
|
|
46f1cee2a8 | ||
|
|
0386af721d | ||
|
|
de6b752db8 | ||
|
|
92fd5511ec | ||
|
|
8507125e98 | ||
|
|
59ec7f31ab | ||
|
|
627b21f3f2 | ||
|
|
64cc6e0b91 | ||
|
|
779d2352bd | ||
|
|
0162db12b8 | ||
|
|
91ff7b9032 | ||
|
|
643f99f577 | ||
|
|
152288b4cc | ||
|
|
45b518baf2 | ||
|
|
24cc479f95 | ||
|
|
5fbc630061 | ||
|
|
0c65c73f90 | ||
|
|
95eca75336 | ||
|
|
0f0dbc3274 | ||
|
|
edb674759f | ||
|
|
e3d8c5c7a6 | ||
|
|
f3d6f26a28 | ||
|
|
1a0d51495d | ||
|
|
32d9a397aa | ||
|
|
60e6dc1134 | ||
|
|
06d34daeab | ||
|
|
a00187b97f | ||
|
|
ba1f68d758 | ||
|
|
d4c0977a70 | ||
|
|
1a19d71e95 | ||
|
|
21c10934fc | ||
|
|
13cca91097 | ||
|
|
b335b1c66b | ||
|
|
a42a9bf4fe | ||
|
|
cc2653bfb5 | ||
|
|
fc5bf5a68f | ||
|
|
0f7e6b8964 | ||
|
|
63d7338311 | ||
|
|
37f716d27b | ||
|
|
03bfdec1e1 | ||
|
|
0f2a835359 | ||
|
|
2a84d39e40 | ||
|
|
b14289e976 | ||
|
|
1fef6f0656 | ||
|
|
183ec2124f | ||
|
|
aeb9bfa063 | ||
|
|
b84c7ae49b | ||
|
|
61598c5942 | ||
|
|
a3a24e0216 | ||
|
|
31ec2da0e9 | ||
|
|
53da7cb036 | ||
|
|
911083c49d | ||
|
|
27a10b395f | ||
|
|
b1f3e117d1 | ||
|
|
7570cdbd22 | ||
|
|
28ff2efdef | ||
|
|
bb1a9192eb | ||
|
|
1787e2c775 | ||
|
|
470e711383 | ||
|
|
eb4f682ad1 | ||
|
|
4b63730efb | ||
|
|
c857474116 | ||
|
|
8ff5dacc3c | ||
|
|
fb89828990 | ||
|
|
c7529f9a3e | ||
|
|
dbefa71bc8 | ||
|
|
7907404028 | ||
|
|
72e17b558c | ||
|
|
628028475c | ||
|
|
05e992ad67 | ||
|
|
bba6bf387e | ||
|
|
4d32f7c5ad | ||
|
|
0dff05e881 | ||
|
|
f3c5a01daf | ||
|
|
7ca104cef6 | ||
|
|
fe95247d56 | ||
|
|
f1179d31ba | ||
|
|
c7681cb24d | ||
|
|
abe60b96f1 | ||
|
|
206520f179 | ||
|
|
330ac3be68 | ||
|
|
3b1e34efa1 |
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal 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
|
||||||
4
.github/actions/setup-base/action.yml
vendored
4
.github/actions/setup-base/action.yml
vendored
@@ -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"
|
||||||
|
|||||||
7
.github/workflows/build_esp32.yml
vendored
7
.github/workflows/build_esp32.yml
vendored
@@ -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 }}
|
||||||
|
|
||||||
|
|||||||
35
.github/workflows/main_matrix.yml
vendored
35
.github/workflows/main_matrix.yml
vendored
@@ -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
19
.github/workflows/nightly.yml
vendored
Normal 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 }}
|
||||||
4
.github/workflows/sec_sast_flawfinder.yml
vendored
4
.github/workflows/sec_sast_flawfinder.yml
vendored
@@ -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
|
||||||
|
|||||||
4
.github/workflows/sec_sast_semgrep_cron.yml
vendored
4
.github/workflows/sec_sast_semgrep_cron.yml
vendored
@@ -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
|
||||||
|
|||||||
5
.github/workflows/sec_sast_semgrep_pull.yml
vendored
5
.github/workflows/sec_sast_semgrep_pull.yml
vendored
@@ -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
|
||||||
|
|||||||
6
.github/workflows/update_protobufs.yml
vendored
6
.github/workflows/update_protobufs.yml
vendored
@@ -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
1
.gitignore
vendored
@@ -29,3 +29,4 @@ __pycache__
|
|||||||
|
|
||||||
venv/
|
venv/
|
||||||
release/
|
release/
|
||||||
|
.vscode/extensions.json
|
||||||
|
|||||||
7
.trunk/.gitignore
vendored
Normal file
7
.trunk/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
*out
|
||||||
|
*logs
|
||||||
|
*actions
|
||||||
|
*notifications
|
||||||
|
plugins
|
||||||
|
user_trunk.yaml
|
||||||
|
user.yaml
|
||||||
4
.trunk/configs/.hadolint.yaml
Normal file
4
.trunk/configs/.hadolint.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Following source doesn't work in most setups
|
||||||
|
ignored:
|
||||||
|
- SC1090
|
||||||
|
- SC1091
|
||||||
10
.trunk/configs/.markdownlint.yaml
Normal file
10
.trunk/configs/.markdownlint.yaml
Normal 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
|
||||||
7
.trunk/configs/.shellcheckrc
Normal file
7
.trunk/configs/.shellcheckrc
Normal 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
|
||||||
14
.trunk/configs/svgo.config.js
Normal file
14
.trunk/configs/svgo.config.js
Normal 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
33
.trunk/trunk.yaml
Normal 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
|
||||||
6
.vscode/extensions.json
vendored
6
.vscode/extensions.json
vendored
@@ -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
80
.vscode/settings.json
vendored
@@ -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
4
.vscode/tasks.json
vendored
@@ -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
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Meshtastic Firmware
|
# Meshtastic Firmware
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/meshtastic/firmware/actions/workflows/main_matrix.yml)
|
[](https://github.com/meshtastic/firmware/actions/workflows/ci.yml)
|
||||||
[](https://cla-assistant.io/meshtastic/firmware)
|
[](https://cla-assistant.io/meshtastic/firmware)
|
||||||
[](https://opencollective.com/meshtastic/)
|
[](https://opencollective.com/meshtastic/)
|
||||||
[](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
|
[](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
|
||||||
|
|||||||
@@ -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
47
arch/esp32/esp32s2.ini
Normal 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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 =
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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' *
|
||||||
|
|||||||
@@ -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."
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -43,5 +43,4 @@
|
|||||||
},
|
},
|
||||||
"url": "https://meshtastic.org/",
|
"url": "https://meshtastic.org/",
|
||||||
"vendor": "Nordic Semi"
|
"vendor": "Nordic Semi"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
37
boards/tlora-t3s3-v1.json
Normal 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"
|
||||||
|
}
|
||||||
@@ -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
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Submodule protobufs updated: afa4605699...8cb6ed3c91
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
123
src/FSCommon.cpp
123
src/FSCommon.cpp
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
#include "configuration.h"
|
|
||||||
#include "Observer.h"
|
#include "Observer.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
194
src/Power.cpp
194
src/Power.cpp
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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");
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
42
src/Status.h
42
src/Status.h
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "configuration.h"
|
|
||||||
#include "Lock.h"
|
#include "Lock.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace concurrency
|
namespace concurrency
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
#include "Lock.h"
|
#include "Lock.h"
|
||||||
|
|
||||||
namespace concurrency {
|
namespace concurrency
|
||||||
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief RAII lock guard
|
* @brief RAII lock guard
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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() {}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
166
src/gps/GPS.cpp
166
src/gps/GPS.cpp
@@ -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(¬ifySleep);
|
notifySleepObserver.observe(¬ifySleep);
|
||||||
notifyDeepSleepObserver.observe(¬ifyDeepSleep);
|
notifyDeepSleepObserver.observe(¬ifyDeepSleep);
|
||||||
|
notifyGPSSleepObserver.observe(¬ifyGPSSleep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(¬ifySleep);
|
notifySleepObserver.unobserve(¬ifySleep);
|
||||||
notifyDeepSleepObserver.unobserve(¬ifyDeepSleep);
|
notifyDeepSleepObserver.unobserve(¬ifyDeepSleep);
|
||||||
|
notifyGPSSleepObserver.observe(¬ifyGPSSleep);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
Reference in New Issue
Block a user