mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-19 16:27:28 +00:00
Compare commits
497 Commits
v1.3.26.00
...
v1.3.44.4f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fa8d02b08 | ||
|
|
43fb0d80f1 | ||
|
|
b25ace14e5 | ||
|
|
8734751bc4 | ||
|
|
5559a1edb0 | ||
|
|
bf503354f3 | ||
|
|
7b10441a28 | ||
|
|
994e396c00 | ||
|
|
6e22ee9061 | ||
|
|
b5fb0f60b0 | ||
|
|
a7fe69ed6b | ||
|
|
7f05298172 | ||
|
|
92a2505056 | ||
|
|
aae9d2fcf6 | ||
|
|
b59e928589 | ||
|
|
1db08b3b0e | ||
|
|
2cf3c105a1 | ||
|
|
505e4e8176 | ||
|
|
49a9973548 | ||
|
|
18af9d734d | ||
|
|
3e22aafea8 | ||
|
|
434db4347b | ||
|
|
b2c3b405b1 | ||
|
|
4bc8f6a6b9 | ||
|
|
4534d17d79 | ||
|
|
f88dde2f60 | ||
|
|
f8982ddaf8 | ||
|
|
784cd8c6f1 | ||
|
|
c3ab8f12cf | ||
|
|
b5adb7babc | ||
|
|
62c809a596 | ||
|
|
d2fe4426c1 | ||
|
|
984f0ca12c | ||
|
|
9d3eba9ea4 | ||
|
|
323f81eaba | ||
|
|
8d0e25fd82 | ||
|
|
20eaddee58 | ||
|
|
30b1bd85d9 | ||
|
|
09cce094d1 | ||
|
|
33a208e3c4 | ||
|
|
dd4c4fba80 | ||
|
|
a17c40ad09 | ||
|
|
9d73e606ac | ||
|
|
da12360105 | ||
|
|
ee1ae627a3 | ||
|
|
137a8dcfdf | ||
|
|
b2d753ed86 | ||
|
|
6e40102f26 | ||
|
|
511fe23b8a | ||
|
|
e433895873 | ||
|
|
5572195af9 | ||
|
|
cb956cd35b | ||
|
|
b551c7738e | ||
|
|
3d45c4dbd8 | ||
|
|
8681489cb7 | ||
|
|
ed328766b2 | ||
|
|
fb852ee6eb | ||
|
|
a6ee708b90 | ||
|
|
c9398e7b8a | ||
|
|
b591e35442 | ||
|
|
e50e15dc04 | ||
|
|
d4e65d8607 | ||
|
|
63ced7da7c | ||
|
|
03868d05db | ||
|
|
186374525a | ||
|
|
f116585c2a | ||
|
|
f4945729bc | ||
|
|
a3c76232c8 | ||
|
|
5bc41118e2 | ||
|
|
9445a96b3a | ||
|
|
a5761069ca | ||
|
|
2d4bfe183c | ||
|
|
bf4115a80f | ||
|
|
b2e84dfd29 | ||
|
|
004f6fa4d6 | ||
|
|
cefd4cd647 | ||
|
|
fd2ae61e3e | ||
|
|
7cda61ca01 | ||
|
|
98e1d52eaa | ||
|
|
1d09beb8a7 | ||
|
|
d44cce2928 | ||
|
|
51b3d4d06e | ||
|
|
a17ddaa951 | ||
|
|
9bd925226c | ||
|
|
e34ada3ff1 | ||
|
|
1ec1ff0773 | ||
|
|
7f935717db | ||
|
|
5b1d3a0c51 | ||
|
|
484f340023 | ||
|
|
ab0cf025c5 | ||
|
|
b384d9ea88 | ||
|
|
bb2094c4de | ||
|
|
6708121ba6 | ||
|
|
46a9bb3f7d | ||
|
|
62498d0935 | ||
|
|
c70184fbed | ||
|
|
4d2cb45f9f | ||
|
|
e5605cc6fe | ||
|
|
f7331a2e41 | ||
|
|
838271a14f | ||
|
|
b6b23907ed | ||
|
|
b240b9a088 | ||
|
|
b3a484f1e5 | ||
|
|
f3042ddf37 | ||
|
|
54816231e9 | ||
|
|
1c168d7d62 | ||
|
|
063c4904ff | ||
|
|
fefcbb147b | ||
|
|
53d48e8f61 | ||
|
|
ce5bce5cdc | ||
|
|
3597685b23 | ||
|
|
dc097c7230 | ||
|
|
b148781e4b | ||
|
|
5d8826e8ef | ||
|
|
39a51c7fbb | ||
|
|
129edde338 | ||
|
|
93cc278eee | ||
|
|
c34198264a | ||
|
|
054b12325d | ||
|
|
0f7a126828 | ||
|
|
7ff72fb981 | ||
|
|
0fe99595a9 | ||
|
|
b2ff628cec | ||
|
|
86a3bd6db8 | ||
|
|
73a5357d0e | ||
|
|
2faf507c0d | ||
|
|
cf124d97b8 | ||
|
|
482c0766af | ||
|
|
7e5a26fde5 | ||
|
|
e85af2f732 | ||
|
|
4df81008bc | ||
|
|
803dc69ccd | ||
|
|
42308cca5b | ||
|
|
ea991a4eee | ||
|
|
04db2d4410 | ||
|
|
076c1ed2ee | ||
|
|
75aa4ea325 | ||
|
|
e54be07dc0 | ||
|
|
d439d00e25 | ||
|
|
c4bea793af | ||
|
|
b53dcb932e | ||
|
|
371428d6ab | ||
|
|
1970d0c00f | ||
|
|
1dd7aa935f | ||
|
|
6b40f9d95c | ||
|
|
b3717d0396 | ||
|
|
82ba95833b | ||
|
|
28384df702 | ||
|
|
aee06f4738 | ||
|
|
ab282765d4 | ||
|
|
5d464badc8 | ||
|
|
68282682de | ||
|
|
2696b04138 | ||
|
|
31dc37150b | ||
|
|
e66d9d0add | ||
|
|
067bde321b | ||
|
|
84ec364ac2 | ||
|
|
32990856e3 | ||
|
|
a1bd5c9ea0 | ||
|
|
51f0e7879a | ||
|
|
0bdb90d133 | ||
|
|
e98c11ff89 | ||
|
|
8f84d7089c | ||
|
|
b0712c4186 | ||
|
|
8f92383ce4 | ||
|
|
c571fc9e24 | ||
|
|
05126bc6dc | ||
|
|
de56a370c6 | ||
|
|
daf189bf4b | ||
|
|
d95ec7e6b9 | ||
|
|
ac235bcabb | ||
|
|
ab4b3a50ee | ||
|
|
7f0fb2a2b6 | ||
|
|
ade1edfdfc | ||
|
|
4723faa95f | ||
|
|
93f83b0fcb | ||
|
|
8f84f7c0a5 | ||
|
|
48e4101f1c | ||
|
|
e6bb79f4c1 | ||
|
|
0bef3464f5 | ||
|
|
3c038a8c50 | ||
|
|
b8eb751316 | ||
|
|
5332db1eca | ||
|
|
9deda962aa | ||
|
|
c53434539b | ||
|
|
7f179deaf3 | ||
|
|
da29fa139f | ||
|
|
1d8a562fd9 | ||
|
|
0dbf97afab | ||
|
|
e5720fba3e | ||
|
|
498ac00b92 | ||
|
|
226a2dfe04 | ||
|
|
7e9a233296 | ||
|
|
ae311c838e | ||
|
|
de769db3bc | ||
|
|
5fa96c7fd1 | ||
|
|
2ee0c9a67a | ||
|
|
347af0210e | ||
|
|
d8455d687c | ||
|
|
34fef4c4e7 | ||
|
|
18bb373219 | ||
|
|
2f74f9ca15 | ||
|
|
5775c390f3 | ||
|
|
80826b8712 | ||
|
|
664d18cf58 | ||
|
|
bc2cddcb11 | ||
|
|
4949bda606 | ||
|
|
b4f75ad042 | ||
|
|
af4d11e17b | ||
|
|
e8f4a8b739 | ||
|
|
fae6693f8f | ||
|
|
0646ecdec4 | ||
|
|
544c89460f | ||
|
|
15089f5b01 | ||
|
|
8ef510035d | ||
|
|
864b1f754c | ||
|
|
883a2ebac0 | ||
|
|
bbe5b2e42c | ||
|
|
1b316b111f | ||
|
|
d0720620e8 | ||
|
|
cf4947d898 | ||
|
|
b5a8efa16b | ||
|
|
b38ae783b9 | ||
|
|
cbd8346c93 | ||
|
|
c0bfb979fd | ||
|
|
7c5a36ce38 | ||
|
|
fc729b0cbb | ||
|
|
0b81a25fda | ||
|
|
011db443ba | ||
|
|
b73e240f4d | ||
|
|
6de77ee310 | ||
|
|
0a8293a2d6 | ||
|
|
d0ad5dd4cf | ||
|
|
ab342ce904 | ||
|
|
140250ef03 | ||
|
|
ed90275370 | ||
|
|
e8b28faaf1 | ||
|
|
afcc7b6a56 | ||
|
|
e27a507a28 | ||
|
|
207f701f0a | ||
|
|
dd8cb1c7fb | ||
|
|
ccf93b8c23 | ||
|
|
4c6f3ead60 | ||
|
|
2d81d359b8 | ||
|
|
1f96d5d957 | ||
|
|
033f45d4da | ||
|
|
ae2c514ee7 | ||
|
|
80ddb81fac | ||
|
|
4bc29200be | ||
|
|
55c55fb705 | ||
|
|
0e2ab75bb0 | ||
|
|
128d20b290 | ||
|
|
ad9cc40b97 | ||
|
|
e0d3ac01b0 | ||
|
|
0f87adad7b | ||
|
|
9481461145 | ||
|
|
accd23eddc | ||
|
|
7c202b6069 | ||
|
|
e93b98ff98 | ||
|
|
b1ac2cf821 | ||
|
|
bfd1fecc2a | ||
|
|
c622a9b4be | ||
|
|
ade66cd8f4 | ||
|
|
397030b5a6 | ||
|
|
adc50f40b1 | ||
|
|
32d92d9b75 | ||
|
|
18f37981bb | ||
|
|
a8711bc54a | ||
|
|
eac2613743 | ||
|
|
4a0c18c4cd | ||
|
|
e376a3a28e | ||
|
|
a6bdff53c9 | ||
|
|
b5c5483ced | ||
|
|
601422e92b | ||
|
|
dbbe5e59ae | ||
|
|
b96dd6d36d | ||
|
|
e6b6e175b8 | ||
|
|
2ff549d458 | ||
|
|
a1230500fd | ||
|
|
17db87e042 | ||
|
|
42d2986cb8 | ||
|
|
cc054a13e2 | ||
|
|
60b4dbfdcd | ||
|
|
c446a0f222 | ||
|
|
f98e96cf1b | ||
|
|
3102777a71 | ||
|
|
ed95f382cf | ||
|
|
7f18c0fb77 | ||
|
|
52e4f93760 | ||
|
|
0167304300 | ||
|
|
7aaca3d486 | ||
|
|
bf3306fbc8 | ||
|
|
e375a8460b | ||
|
|
ff88900982 | ||
|
|
7f293bfda3 | ||
|
|
99de0a76a5 | ||
|
|
47ffb9c70d | ||
|
|
1231f926ea | ||
|
|
e05e888fca | ||
|
|
03580f5be8 | ||
|
|
90dabfea30 | ||
|
|
c8d7b1aba0 | ||
|
|
6065ef3a54 | ||
|
|
86c7eefc91 | ||
|
|
f7b12f0695 | ||
|
|
0c46ad91ef | ||
|
|
96cab75ccd | ||
|
|
a7138b7213 | ||
|
|
11590e33d3 | ||
|
|
a3a92d2d13 | ||
|
|
2088036521 | ||
|
|
7d0e16d1b6 | ||
|
|
35c77ef99c | ||
|
|
9244d03cf9 | ||
|
|
a50a461675 | ||
|
|
f78911666e | ||
|
|
f1e6585726 | ||
|
|
b8f862ac46 | ||
|
|
94a572aee6 | ||
|
|
e87ecc210a | ||
|
|
a9e7a33473 | ||
|
|
5621719eef | ||
|
|
cb3010b58c | ||
|
|
a27a07956f | ||
|
|
285ba9639e | ||
|
|
f54f60c31c | ||
|
|
84e438f72f | ||
|
|
f767fd5075 | ||
|
|
8fb8212434 | ||
|
|
8d5ffb7262 | ||
|
|
70e1a208d5 | ||
|
|
9d3cac7cdb | ||
|
|
84f1edab18 | ||
|
|
221843e176 | ||
|
|
0063ae6512 | ||
|
|
1922034c44 | ||
|
|
7f586f7099 | ||
|
|
0efa1b25c5 | ||
|
|
1b25ea714d | ||
|
|
fd27a40edb | ||
|
|
1013aff9b6 | ||
|
|
d7e5eb4d22 | ||
|
|
9a03b2e49d | ||
|
|
e7831f13c5 | ||
|
|
ddc3727155 | ||
|
|
ef9bfc9104 | ||
|
|
3bb645d4fe | ||
|
|
8f99258fc4 | ||
|
|
b54073a8a1 | ||
|
|
c85e9f53c7 | ||
|
|
4cfc229e77 | ||
|
|
bbd7c5063d | ||
|
|
05df849a6d | ||
|
|
ccbc01a753 | ||
|
|
d6d936b5d2 | ||
|
|
b028af0d82 | ||
|
|
86d3759f55 | ||
|
|
aadaf332cf | ||
|
|
4dea95d03f | ||
|
|
1253abd138 | ||
|
|
80e3cee006 | ||
|
|
ca9113ad05 | ||
|
|
63c8f15d38 | ||
|
|
73a1ea59f4 | ||
|
|
97712a9dc4 | ||
|
|
20e43fcf34 | ||
|
|
f66c8572b4 | ||
|
|
64f852e3f7 | ||
|
|
ea90e4d2de | ||
|
|
dd720f2fe6 | ||
|
|
808fef7e91 | ||
|
|
70e6dc3c67 | ||
|
|
279149e40f | ||
|
|
4588995fba | ||
|
|
11ae248c5e | ||
|
|
a0a5147c42 | ||
|
|
b8aac2c5b6 | ||
|
|
de22f20876 | ||
|
|
9b5211dc65 | ||
|
|
0b4fb72d58 | ||
|
|
7e03019cc4 | ||
|
|
780f4383f4 | ||
|
|
8148f06773 | ||
|
|
d5780af362 | ||
|
|
82ed7a2084 | ||
|
|
dd5fd3744d | ||
|
|
afb5fca6e1 | ||
|
|
95d75fdfee | ||
|
|
029a6b16ba | ||
|
|
9be3099ca6 | ||
|
|
b6126e6e63 | ||
|
|
d6dfdc314e | ||
|
|
78666e9b36 | ||
|
|
3abba0ce39 | ||
|
|
2c8e030b3d | ||
|
|
eed7408f00 | ||
|
|
cabd1eb8c0 | ||
|
|
f46c11a047 | ||
|
|
cdd5e16e25 | ||
|
|
a6c9a819f8 | ||
|
|
2e72397898 | ||
|
|
f554226226 | ||
|
|
2d1897a36f | ||
|
|
fe1ed3f284 | ||
|
|
3251cd510a | ||
|
|
7d0411cd15 | ||
|
|
1d1ccd6b19 | ||
|
|
3b8566747c | ||
|
|
3cc584d855 | ||
|
|
90d3cc2ff8 | ||
|
|
d125b0ec3c | ||
|
|
5e842dd735 | ||
|
|
bbc0baa31d | ||
|
|
31788feab1 | ||
|
|
2c37be58ac | ||
|
|
836782b3c1 | ||
|
|
cfc44cd608 | ||
|
|
519f31ed60 | ||
|
|
e04d6b3f56 | ||
|
|
25c851a929 | ||
|
|
0c8fb6e27f | ||
|
|
8490bdd14e | ||
|
|
22a5cf04d3 | ||
|
|
ddc5a59ece | ||
|
|
6382f67b89 | ||
|
|
401b5d92aa | ||
|
|
572f9f9295 | ||
|
|
96ce40040c | ||
|
|
d0a1aad7d1 | ||
|
|
ab0095cb05 | ||
|
|
591ae7a803 | ||
|
|
de47cc55a0 | ||
|
|
7e6c22f542 | ||
|
|
2fac581fa3 | ||
|
|
1155727a45 | ||
|
|
1c8e64319c | ||
|
|
ca1e687fd4 | ||
|
|
4c215530f6 | ||
|
|
472fb6e5b0 | ||
|
|
00846439d0 | ||
|
|
a10e56265b | ||
|
|
9fe2ddb082 | ||
|
|
a9ad314307 | ||
|
|
688ac3f8ee | ||
|
|
e79ef0dd35 | ||
|
|
9bc2b4d8d7 | ||
|
|
720cd62943 | ||
|
|
4073ba7572 | ||
|
|
39aa7f9880 | ||
|
|
71a9f46451 | ||
|
|
18d5712ecd | ||
|
|
295dca8415 | ||
|
|
7b438cd16b | ||
|
|
d285a2e70a | ||
|
|
2ad9e238e2 | ||
|
|
2d2f306982 | ||
|
|
7afc14991e | ||
|
|
86095323e5 | ||
|
|
01ac8d10b5 | ||
|
|
874d308b50 | ||
|
|
1f8878bd89 | ||
|
|
b39b58c87b | ||
|
|
fab20f5acf | ||
|
|
21f75686a4 | ||
|
|
4ad2e58047 | ||
|
|
e26975ca12 | ||
|
|
47da3b695a | ||
|
|
151321ac3c | ||
|
|
faac761dc0 | ||
|
|
5e2acc43f5 | ||
|
|
25a229ce85 | ||
|
|
41f9541f95 | ||
|
|
d64c552865 | ||
|
|
785c2b32da | ||
|
|
ba9d52da25 | ||
|
|
44ffdc5172 | ||
|
|
edd6f049cf | ||
|
|
97684c6c73 | ||
|
|
ade32b1827 | ||
|
|
69ac8c0353 | ||
|
|
fd27a814b7 | ||
|
|
f0518bc99a | ||
|
|
13a287ce5c | ||
|
|
7e7872605b | ||
|
|
a41735544b | ||
|
|
dcc6a4b5e7 | ||
|
|
c88ba583c6 | ||
|
|
b36cd32c03 | ||
|
|
43733ce150 | ||
|
|
c292e539d4 | ||
|
|
4daf2cc3fa | ||
|
|
9c21064634 | ||
|
|
20d7d1b162 | ||
|
|
97a2bf6221 | ||
|
|
7485c312dd | ||
|
|
6ff5ada7d6 | ||
|
|
cf331dc58b |
177
.github/workflows/main_matrix.yml
vendored
177
.github/workflows/main_matrix.yml
vendored
@@ -5,7 +5,6 @@ on:
|
|||||||
branches: [master]
|
branches: [master]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- "**.md"
|
- "**.md"
|
||||||
- "**.yml"
|
|
||||||
- "version.properties"
|
- "version.properties"
|
||||||
|
|
||||||
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
|
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
|
||||||
@@ -13,7 +12,7 @@ on:
|
|||||||
branches: [master]
|
branches: [master]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- "**.md"
|
- "**.md"
|
||||||
- "**.yml"
|
#- "**.yml"
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
@@ -38,8 +37,11 @@ jobs:
|
|||||||
- board: rak4631_eink
|
- board: rak4631_eink
|
||||||
- board: t-echo
|
- board: t-echo
|
||||||
- board: nano-g1
|
- board: nano-g1
|
||||||
|
- board: station-g1
|
||||||
- board: m5stack-core
|
- board: m5stack-core
|
||||||
- board: m5stack-coreink
|
- board: m5stack-coreink
|
||||||
|
- board: tbeam-s3-core
|
||||||
|
# - board: pico
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -95,8 +97,10 @@ jobs:
|
|||||||
- board: tbeam0.7
|
- board: tbeam0.7
|
||||||
- board: meshtastic-diy-v1
|
- board: meshtastic-diy-v1
|
||||||
- board: nano-g1
|
- board: nano-g1
|
||||||
|
- board: station-g1
|
||||||
- board: m5stack-core
|
- board: m5stack-core
|
||||||
- board: m5stack-coreink
|
- board: m5stack-coreink
|
||||||
|
- board: tbeam-s3-core
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -122,13 +126,12 @@ jobs:
|
|||||||
- name: Upgrade python tools
|
- name: Upgrade python tools
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio adafruit-nrfutil littlefs-python
|
pip install -U platformio adafruit-nrfutil
|
||||||
pip install -U --pre meshtastic
|
|
||||||
|
|
||||||
- name: Upgrade platformio
|
- name: Upgrade platformio
|
||||||
run: |
|
run: |
|
||||||
pio upgrade
|
pio upgrade
|
||||||
|
|
||||||
- name: Pull web ui
|
- name: Pull web ui
|
||||||
uses: dsaltares/fetch-gh-release-asset@master
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
with:
|
with:
|
||||||
@@ -144,7 +147,15 @@ jobs:
|
|||||||
|
|
||||||
- name: Build ESP32
|
- name: Build ESP32
|
||||||
run: bin/build-esp32.sh ${{ matrix.board }}
|
run: bin/build-esp32.sh ${{ matrix.board }}
|
||||||
|
|
||||||
|
- name: Pull OTA Firmware
|
||||||
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
|
with:
|
||||||
|
repo: "meshtastic/Meshtastic-OTA"
|
||||||
|
file: "firmware.bin"
|
||||||
|
target: "release/bleota.bin"
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Get release version string
|
- name: Get release version string
|
||||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||||
id: version
|
id: version
|
||||||
@@ -194,7 +205,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio adafruit-nrfutil
|
pip install -U platformio adafruit-nrfutil
|
||||||
pip install -U --pre meshtastic
|
|
||||||
|
|
||||||
- name: Upgrade platformio
|
- name: Upgrade platformio
|
||||||
run: |
|
run: |
|
||||||
@@ -207,6 +217,61 @@ jobs:
|
|||||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||||
id: version
|
id: version
|
||||||
|
|
||||||
|
- name: Store binaries as an artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
|
||||||
|
path: |
|
||||||
|
release/*.uf2
|
||||||
|
release/*.elf
|
||||||
|
release/*.zip
|
||||||
|
retention-days: 90
|
||||||
|
|
||||||
|
build-rpi2040:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
max-parallel: 2
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- board: pico
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: "recursive"
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- name: Cache python libs
|
||||||
|
uses: actions/cache@v1
|
||||||
|
id: cache-pip # needed in if test
|
||||||
|
with:
|
||||||
|
path: ~/.cache/pip
|
||||||
|
key: ${{ runner.os }}-pip
|
||||||
|
|
||||||
|
- name: Upgrade python tools
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -U platformio adafruit-nrfutil
|
||||||
|
|
||||||
|
- name: Upgrade platformio
|
||||||
|
run: |
|
||||||
|
pio upgrade
|
||||||
|
|
||||||
|
- name: Build Raspberry Pi 2040
|
||||||
|
run: ./bin/build-rpi2040.sh ${{ matrix.board }}
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||||
|
id: version
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
- name: Store binaries as an artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
@@ -242,7 +307,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio adafruit-nrfutil
|
pip install -U platformio adafruit-nrfutil
|
||||||
pip install -U --pre meshtastic
|
pip install -U meshtastic --pre
|
||||||
|
|
||||||
- name: Upgrade platformio
|
- name: Upgrade platformio
|
||||||
run: |
|
run: |
|
||||||
@@ -287,7 +352,7 @@ jobs:
|
|||||||
|
|
||||||
gather-artifacts:
|
gather-artifacts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [build-esp32, build-nrf52, build-native]
|
needs: [build-esp32, build-nrf52, build-native, build-rpi2040]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -304,7 +369,7 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Move files up
|
- name: Move files up
|
||||||
run: mv -b -t ./ ./*tbeam-*/littlefs*.bin ./*tbeam-*/system-info.bin ./**/firmware*.bin ./**/*.uf2 ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat
|
run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat
|
||||||
|
|
||||||
- name: Repackage in single firmware zip
|
- name: Repackage in single firmware zip
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
@@ -313,6 +378,7 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
./*.bin
|
./*.bin
|
||||||
./*.uf2
|
./*.uf2
|
||||||
|
./firmware-*-ota.zip
|
||||||
./meshtasticd_linux_amd64
|
./meshtasticd_linux_amd64
|
||||||
./device-*.sh
|
./device-*.sh
|
||||||
./device-*.bat
|
./device-*.bat
|
||||||
@@ -326,6 +392,11 @@ jobs:
|
|||||||
# For diagnostics
|
# For diagnostics
|
||||||
- name: Show artifacts
|
- name: Show artifacts
|
||||||
run: ls -lR
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Device scripts permissions
|
||||||
|
run: |
|
||||||
|
chmod +x ./output/device-install.sh
|
||||||
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
- name: Zip firmware
|
- name: Zip firmware
|
||||||
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||||
@@ -348,3 +419,89 @@ jobs:
|
|||||||
artifacts-branch: device
|
artifacts-branch: device
|
||||||
artifacts-dir: pr
|
artifacts-dir: pr
|
||||||
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
||||||
|
|
||||||
|
release-artifacts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
needs: [gather-artifacts, after-checks]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.x
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||||
|
id: version
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: firmware-${{ steps.version.outputs.version }}
|
||||||
|
path: ./output
|
||||||
|
|
||||||
|
- name: Device scripts permissions
|
||||||
|
run: |
|
||||||
|
chmod +x ./output/device-install.sh
|
||||||
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
|
- name: Zip firmware
|
||||||
|
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||||
|
path: ./elfs
|
||||||
|
|
||||||
|
- name: Zip Elfs
|
||||||
|
run: zip -j -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs
|
||||||
|
|
||||||
|
# For diagnostics
|
||||||
|
- name: Show artifacts
|
||||||
|
run: ls -lR
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
id: create_release
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
prerelease: true
|
||||||
|
release_name: Meshtastic Device ${{ steps.version.outputs.version }} alpha - Public Preview
|
||||||
|
tag_name: v${{ steps.version.outputs.version }}
|
||||||
|
body: |
|
||||||
|
Autogenerated by github action, developer should edit as required before publishing...
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Add bins to release
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./firmware-${{ steps.version.outputs.version }}.zip
|
||||||
|
asset_name: firmware-${{ steps.version.outputs.version }}.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|
||||||
|
- name: Add debug elfs to release
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||||
|
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|
||||||
|
- name: Bump version.properties
|
||||||
|
run: >-
|
||||||
|
bin/bump_version.py
|
||||||
|
|
||||||
|
- name: Create version.properties pull request
|
||||||
|
uses: peter-evans/create-pull-request@v3
|
||||||
|
with:
|
||||||
|
add-paths: |
|
||||||
|
version.properties
|
||||||
|
|
||||||
|
|||||||
92
.github/workflows/release.yml
vendored
92
.github/workflows/release.yml
vendored
@@ -1,92 +0,0 @@
|
|||||||
name: Make Release
|
|
||||||
on:
|
|
||||||
# Can optionally take parameters from the github UI, more info here https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/#:~:text=You%20can%20now%20create%20workflows,the%20workflow%20is%20run%20on.
|
|
||||||
workflow_dispatch:
|
|
||||||
# inputs:
|
|
||||||
|
|
||||||
# Only want to run if version.properties is bumped in master
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths:
|
|
||||||
- "version.properties"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release-build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: "recursive"
|
|
||||||
|
|
||||||
- name: Setup Python
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
with:
|
|
||||||
python-version: 3.x
|
|
||||||
|
|
||||||
# Will be available in steps.version.outputs.version
|
|
||||||
- name: Get release version string
|
|
||||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
|
||||||
id: version
|
|
||||||
# Note: we don't use caches on release builds because we don't want to accidentally not have a virgin build machine
|
|
||||||
|
|
||||||
- name: Upgrade python tools
|
|
||||||
# We actually want to run this every time
|
|
||||||
# if: steps.cache-pip.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install -U platformio meshtastic adafruit-nrfutil littlefs-python
|
|
||||||
|
|
||||||
- name: Upgrade platformio
|
|
||||||
run: |
|
|
||||||
pio upgrade
|
|
||||||
|
|
||||||
- name: Pull web ui
|
|
||||||
uses: dsaltares/fetch-gh-release-asset@master
|
|
||||||
with:
|
|
||||||
repo: "meshtastic/meshtastic-web"
|
|
||||||
file: "build.tar"
|
|
||||||
target: "build.tar"
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Unpack web ui
|
|
||||||
run: |
|
|
||||||
tar -xf build.tar -C data/static
|
|
||||||
rm build.tar
|
|
||||||
|
|
||||||
- name: Build everything
|
|
||||||
run: bin/build-all.sh
|
|
||||||
|
|
||||||
- name: Create release
|
|
||||||
uses: actions/create-release@v1
|
|
||||||
id: create_release
|
|
||||||
with:
|
|
||||||
draft: true
|
|
||||||
prerelease: true
|
|
||||||
release_name: ${{ steps.version.outputs.version }} alpha
|
|
||||||
tag_name: v${{ steps.version.outputs.version }}
|
|
||||||
body: |
|
|
||||||
Autogenerated by github action, developer should edit as required before publishing...
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
|
|
||||||
- name: Add bins to release
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
asset_path: release/archive/firmware-${{ steps.version.outputs.version }}.zip
|
|
||||||
asset_name: firmware-${{ steps.version.outputs.version }}.zip
|
|
||||||
asset_content_type: application/zip
|
|
||||||
|
|
||||||
- name: Add debug elfs to release
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
asset_path: release/archive/elfs-${{ steps.version.outputs.version }}.zip
|
|
||||||
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
|
||||||
asset_content_type: application/zip
|
|
||||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -52,7 +52,9 @@
|
|||||||
"shared_mutex": "cpp",
|
"shared_mutex": "cpp",
|
||||||
"iostream": "cpp",
|
"iostream": "cpp",
|
||||||
"esp_nimble_hci.h": "c",
|
"esp_nimble_hci.h": "c",
|
||||||
"map": "cpp"
|
"map": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"*.tpp": "cpp"
|
||||||
},
|
},
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"Blox",
|
"Blox",
|
||||||
|
|||||||
53
arch/esp32/esp32.ini
Normal file
53
arch/esp32/esp32.ini
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||||
|
[esp32_base]
|
||||||
|
extends = arduino_base
|
||||||
|
platform = platformio/espressif32@^5.2.0
|
||||||
|
build_src_filter =
|
||||||
|
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
|
||||||
|
upload_speed = 921600
|
||||||
|
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
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${arduino_base.lib_deps}
|
||||||
|
${networking_base.lib_deps}
|
||||||
|
${environmental_base.lib_deps}
|
||||||
|
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
|
||||||
|
h2zero/NimBLE-Arduino@^1.4.0
|
||||||
|
arduino-libraries/NTPClient@^3.1.0
|
||||||
|
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||||
|
|
||||||
|
lib_ignore =
|
||||||
|
segger_rtt
|
||||||
|
ESP32 BLE Arduino
|
||||||
|
|
||||||
|
; leave this commented out to avoid breaking Windows
|
||||||
|
;upload_port = /dev/ttyUSB0
|
||||||
|
;monitor_port = /dev/ttyUSB0
|
||||||
|
|
||||||
|
; Please don't delete these lines. JM uses them.
|
||||||
|
;upload_port = /dev/cu.SLAB_USBtoUART
|
||||||
|
;monitor_port = /dev/cu.SLAB_USBtoUART
|
||||||
|
|
||||||
|
; customize the partition table
|
||||||
|
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||||
|
board_build.partitions = partition-table.csv
|
||||||
46
arch/esp32/esp32s3.ini
Normal file
46
arch/esp32/esp32s3.ini
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
[esp32s3_base]
|
||||||
|
extends = arduino_base
|
||||||
|
platform = platformio/espressif32@^5.2.0
|
||||||
|
build_src_filter =
|
||||||
|
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
|
||||||
|
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
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${arduino_base.lib_deps}
|
||||||
|
${networking_base.lib_deps}
|
||||||
|
${environmental_base.lib_deps}
|
||||||
|
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
|
||||||
|
h2zero/NimBLE-Arduino@^1.4.0
|
||||||
|
arduino-libraries/NTPClient@^3.1.0
|
||||||
|
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
18
arch/nrf52/nrf52.ini
Normal file
18
arch/nrf52/nrf52.ini
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[nrf52_base]
|
||||||
|
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||||
|
platform = platformio/nordicnrf52@^9.4.0
|
||||||
|
|
||||||
|
extends = arduino_base
|
||||||
|
build_type = debug ; I'm debugging with ICE a lot now
|
||||||
|
build_flags =
|
||||||
|
${arduino_base.build_flags} -Wno-unused-variable
|
||||||
|
-Isrc/platform/nrf52
|
||||||
|
build_src_filter =
|
||||||
|
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040>
|
||||||
|
lib_ignore =
|
||||||
|
BluetoothOTA
|
||||||
|
|
||||||
|
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||||
|
[env:feather_nrf52832]
|
||||||
|
extends = nrf52_base
|
||||||
|
board = adafruit_feather_nrf52832
|
||||||
14
arch/nrf52/nrf52840.ini
Normal file
14
arch/nrf52/nrf52840.ini
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[nrf52840_base]
|
||||||
|
extends = nrf52_base
|
||||||
|
build_flags = ${nrf52_base.build_flags}
|
||||||
|
lib_deps =
|
||||||
|
${arduino_base.lib_deps}
|
||||||
|
${environmental_base.lib_deps}
|
||||||
|
https://github.com/Kongduino/Adafruit_nRFCrypto.git#e31a8825ea3300b163a0a3c1ddd5de34e10e1371
|
||||||
|
|
||||||
|
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||||
|
[env:nrf52840dk]
|
||||||
|
extends = nrf52840_base
|
||||||
|
board = nrf52840_dk
|
||||||
|
|
||||||
|
|
||||||
19
arch/portduino/portduino.ini
Normal file
19
arch/portduino/portduino.ini
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||||
|
[portduino_base]
|
||||||
|
build_src_filter =
|
||||||
|
${env.build_src_filter}
|
||||||
|
-<platform/esp32/>
|
||||||
|
-<nimble/>
|
||||||
|
-<platform/nrf52/>
|
||||||
|
-<platform/stm32wl/>
|
||||||
|
-<platform/rp2040>
|
||||||
|
-<mesh/http/>
|
||||||
|
-<modules/esp32>
|
||||||
|
-<modules/Telemetry>
|
||||||
|
+<../variants/portduino>
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
${networking_base.lib_deps}
|
||||||
|
rweather/Crypto@^0.4.0
|
||||||
|
https://github.com/meshtastic/RadioLib.git#5582ac30578ff3f53f20630a00b2a8a4b8f92c74
|
||||||
|
build_flags = ${arduino_base.build_flags} -Isrc/platform/portduino
|
||||||
19
arch/rp2040/rp2040.ini
Normal file
19
arch/rp2040/rp2040.ini
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
; Common settings for rp2040 Processor based targets
|
||||||
|
[rp2040_base]
|
||||||
|
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#5ce1a228e7cae453f366deb8962252b9b7356bbc
|
||||||
|
extends = arduino_base
|
||||||
|
board_build.core = earlephilhower
|
||||||
|
board_build.filesystem_size = 0.5m
|
||||||
|
build_flags =
|
||||||
|
${arduino_base.build_flags} -Wno-unused-variable
|
||||||
|
-Isrc/platform/rp2040
|
||||||
|
-D__PLAT_RP2040__
|
||||||
|
# -D _POSIX_THREADS
|
||||||
|
build_src_filter =
|
||||||
|
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl>
|
||||||
|
lib_ignore =
|
||||||
|
BluetoothOTA
|
||||||
|
lib_deps =
|
||||||
|
${arduino_base.lib_deps}
|
||||||
|
${environmental_base.lib_deps}
|
||||||
|
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||||
18
arch/stm32/stm32wl5e.ini
Normal file
18
arch/stm32/stm32wl5e.ini
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[stm32wl5e_base]
|
||||||
|
platform = platformio/ststm32@^15.4.1
|
||||||
|
board = generic_wl5e
|
||||||
|
framework = arduino
|
||||||
|
build_type = debug
|
||||||
|
build_flags =
|
||||||
|
${arduino_base.build_flags}
|
||||||
|
-Isrc/platform/stm32wl -g
|
||||||
|
-DHAL_SUBGHZ_MODULE_ENABLED
|
||||||
|
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
|
||||||
|
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
|
||||||
|
build_src_filter =
|
||||||
|
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||||
|
lib_ignore =
|
||||||
|
mathertel/OneButton@^2.0.3
|
||||||
BIN
bin/Meshtastic_nRF52_factory_erase.uf2
Normal file
BIN
bin/Meshtastic_nRF52_factory_erase.uf2
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@ set -e
|
|||||||
VERSION=`bin/buildinfo.py long`
|
VERSION=`bin/buildinfo.py long`
|
||||||
SHORT_VERSION=`bin/buildinfo.py short`
|
SHORT_VERSION=`bin/buildinfo.py short`
|
||||||
|
|
||||||
BOARDS_ESP32="rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 m5stack-core m5stack-coreink"
|
BOARDS_ESP32="rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink"
|
||||||
#BOARDS_ESP32=tbeam
|
#BOARDS_ESP32=tbeam
|
||||||
|
|
||||||
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
|
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
|
||||||
@@ -29,13 +29,11 @@ SRCELF=.pio/build/$1/firmware.elf
|
|||||||
cp $SRCELF $OUTDIR/$basename.elf
|
cp $SRCELF $OUTDIR/$basename.elf
|
||||||
|
|
||||||
echo "Copying ESP32 bin file"
|
echo "Copying ESP32 bin file"
|
||||||
SRCBIN=.pio/build/$1/firmware.bin
|
SRCBIN=.pio/build/$1/firmware.factory.bin
|
||||||
cp $SRCBIN $OUTDIR/$basename.bin
|
cp $SRCBIN $OUTDIR/$basename.bin
|
||||||
|
|
||||||
echo "Building Filesystem for ESP32 targets"
|
echo "Building Filesystem for ESP32 targets"
|
||||||
pio run --environment tbeam -t buildfs
|
pio run --environment tbeam -t buildfs
|
||||||
cp .pio/build/tbeam/spiffs.bin $OUTDIR/littlefs-$VERSION.bin
|
cp .pio/build/tbeam/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
|
||||||
cp images/system-info.bin $OUTDIR/system-info.bin
|
|
||||||
|
|
||||||
cp bin/device-install.* $OUTDIR
|
cp bin/device-install.* $OUTDIR
|
||||||
cp bin/device-update.* $OUTDIR
|
cp bin/device-update.* $OUTDIR
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ basename=firmware-$1-$VERSION
|
|||||||
|
|
||||||
pio run --environment $1 # -v
|
pio run --environment $1 # -v
|
||||||
SRCELF=.pio/build/$1/firmware.elf
|
SRCELF=.pio/build/$1/firmware.elf
|
||||||
|
DFUPKG=.pio/build/$1/firmware.zip
|
||||||
cp $SRCELF $OUTDIR/$basename.elf
|
cp $SRCELF $OUTDIR/$basename.elf
|
||||||
|
cp $DFUPKG $OUTDIR/$basename-ota.zip
|
||||||
|
|
||||||
echo "Generating NRF52 uf2 file"
|
echo "Generating NRF52 uf2 file"
|
||||||
SRCHEX=.pio/build/$1/firmware.hex
|
SRCHEX=.pio/build/$1/firmware.hex
|
||||||
@@ -34,3 +36,4 @@ bin/uf2conv.py $SRCHEX -c -o $OUTDIR/$basename.uf2 -f 0xADA52840
|
|||||||
|
|
||||||
cp bin/device-install.* $OUTDIR
|
cp bin/device-install.* $OUTDIR
|
||||||
cp bin/device-update.* $OUTDIR
|
cp bin/device-update.* $OUTDIR
|
||||||
|
cp bin/*.uf2 $OUTDIR
|
||||||
|
|||||||
36
bin/build-rpi2040.sh
Executable file
36
bin/build-rpi2040.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
VERSION=`bin/buildinfo.py long`
|
||||||
|
SHORT_VERSION=`bin/buildinfo.py short`
|
||||||
|
|
||||||
|
OUTDIR=release/
|
||||||
|
|
||||||
|
rm -f $OUTDIR/firmware*
|
||||||
|
rm -r $OUTDIR/* || true
|
||||||
|
|
||||||
|
# Make sure our submodules are current
|
||||||
|
git submodule update
|
||||||
|
|
||||||
|
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||||
|
platformio lib update
|
||||||
|
|
||||||
|
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||||
|
rm -f .pio/build/$1/firmware.*
|
||||||
|
|
||||||
|
# The shell vars the build tool expects to find
|
||||||
|
export APP_VERSION=$VERSION
|
||||||
|
|
||||||
|
basename=firmware-$1-$VERSION
|
||||||
|
|
||||||
|
pio run --environment $1 # -v
|
||||||
|
SRCELF=.pio/build/$1/firmware.elf
|
||||||
|
cp $SRCELF $OUTDIR/$basename.elf
|
||||||
|
|
||||||
|
echo "Copying uf2 file"
|
||||||
|
SRCBIN=.pio/build/$1/firmware.uf2
|
||||||
|
cp $SRCBIN $OUTDIR/$basename.uf2
|
||||||
|
|
||||||
|
cp bin/device-install.* $OUTDIR
|
||||||
|
cp bin/device-update.* $OUTDIR
|
||||||
16
bin/bump_version.py
Executable file
16
bin/bump_version.py
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Bump the version number"""
|
||||||
|
|
||||||
|
lines = None
|
||||||
|
|
||||||
|
with open('version.properties', 'r', encoding='utf-8') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
with open('version.properties', 'w', encoding='utf-8') as f:
|
||||||
|
for line in lines:
|
||||||
|
if line.lstrip().startswith("build = "):
|
||||||
|
words = line.split(" = ")
|
||||||
|
ver = f'build = {int(words[1]) + 1}'
|
||||||
|
f.write(f'{ver}\n')
|
||||||
|
else:
|
||||||
|
f.write(line)
|
||||||
23
bin/check-dependencies.sh
Normal file
23
bin/check-dependencies.sh
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Note: This is a prototype for how we could add static code analysis to the CI.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ $# -gt 0 ]]; then
|
||||||
|
# can override which environment by passing arg
|
||||||
|
BOARDS="$@"
|
||||||
|
else
|
||||||
|
BOARDS="rak4631 rak4631_eink t-echo pca10059_diy_eink pico rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink tbeam-s3-core"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "BOARDS:${BOARDS}"
|
||||||
|
|
||||||
|
CHECK=""
|
||||||
|
for BOARD in $BOARDS; do
|
||||||
|
CHECK="${CHECK} -e ${BOARD}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo $CHECK
|
||||||
|
|
||||||
|
pio pkg outdated -e $CHECK
|
||||||
8
bin/device-install.bat
Normal file → Executable file
8
bin/device-install.bat
Normal file → Executable file
@@ -29,14 +29,14 @@ IF "__%FILENAME%__" == "____" (
|
|||||||
IF EXIST %FILENAME% (
|
IF EXIST %FILENAME% (
|
||||||
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
|
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
|
||||||
%PYTHON% -m esptool --baud 115200 erase_flash
|
%PYTHON% -m esptool --baud 115200 erase_flash
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x1000 system-info.bin
|
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||||
|
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||||
for %%f in (littlefs-*.bin) do (
|
for %%f in (littlefs-*.bin) do (
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00390000 %%f
|
%PYTHON% -m esptool --baud 115200 write_flash 0x300000 %%f
|
||||||
)
|
)
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
|
|
||||||
) else (
|
) else (
|
||||||
echo "Invalid file: %FILENAME%"
|
echo "Invalid file: %FILENAME%"
|
||||||
goto HELP
|
goto HELP
|
||||||
)
|
)
|
||||||
|
|
||||||
:EOF
|
:EOF
|
||||||
|
|||||||
@@ -47,9 +47,10 @@ shift "$((OPTIND-1))"
|
|||||||
if [ -f "${FILENAME}" ]; then
|
if [ -f "${FILENAME}" ]; 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 0x1000 system-info.bin
|
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||||
"$PYTHON" -m esptool write_flash 0x00390000 littlefs-*.bin
|
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||||
"$PYTHON" -m esptool write_flash 0x10000 ${FILENAME}
|
"$PYTHON" -m esptool write_flash 0x300000 littlefs-*.bin
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "Invalid file: ${FILENAME}"
|
echo "Invalid file: ${FILENAME}"
|
||||||
show_help
|
show_help
|
||||||
|
|||||||
6
bin/device-update.bat
Normal file → Executable file
6
bin/device-update.bat
Normal file → Executable file
@@ -28,12 +28,10 @@ IF "__%FILENAME%__" == "____" (
|
|||||||
)
|
)
|
||||||
IF EXIST %FILENAME% (
|
IF EXIST %FILENAME% (
|
||||||
echo Trying to flash update %FILENAME%
|
echo Trying to flash update %FILENAME%
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
|
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||||
echo Erasing the otadata partition, which will turn off flash flippy-flop and force the first image to be used
|
|
||||||
%PYTHON% -m esptool --baud 115200 erase_region 0xe000 0x2000
|
|
||||||
) else (
|
) else (
|
||||||
echo "Invalid file: %FILENAME%"
|
echo "Invalid file: %FILENAME%"
|
||||||
goto HELP
|
goto HELP
|
||||||
)
|
)
|
||||||
|
|
||||||
:EOF
|
:EOF
|
||||||
|
|||||||
@@ -44,9 +44,7 @@ shift "$((OPTIND-1))"
|
|||||||
|
|
||||||
if [ -f "${FILENAME}" ]; then
|
if [ -f "${FILENAME}" ]; then
|
||||||
echo "Trying to flash update ${FILENAME}."
|
echo "Trying to flash update ${FILENAME}."
|
||||||
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
|
$PYTHON -m esptool --baud 115200 write_flash 0x00 ${FILENAME}
|
||||||
echo "Erasing the otadata partition, which will turn off flash flippy-flop and force the first image to be used"
|
|
||||||
$PYTHON -m esptool --baud 115200 erase_region 0xe000 0x2000
|
|
||||||
else
|
else
|
||||||
echo "Invalid file: ${FILENAME}"
|
echo "Invalid file: ${FILENAME}"
|
||||||
show_help
|
show_help
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import getopt
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from littlefs import LittleFS
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
print( "Building LittleFS image..." )
|
|
||||||
|
|
||||||
argList = sys.argv[1:]
|
|
||||||
arxx = { argList[i]: argList[i+1] for i in range(0, len(argList)-1, 2) }
|
|
||||||
|
|
||||||
dataPath = arxx["-c"]
|
|
||||||
blockSize = int(arxx["-b"])
|
|
||||||
blockCount = int(arxx["-s"]) / blockSize
|
|
||||||
|
|
||||||
cwd = os.getcwd()
|
|
||||||
|
|
||||||
os.chdir(dataPath)
|
|
||||||
|
|
||||||
fileList = []
|
|
||||||
dirList = []
|
|
||||||
|
|
||||||
for (dirpath, dirnames, filenames) in os.walk('.'):
|
|
||||||
for f in filenames:
|
|
||||||
if (f[:1] != '.'):
|
|
||||||
fileList.append( os.path.join(dirpath, f) )
|
|
||||||
for d in dirnames:
|
|
||||||
if (d[:1] != '.'):
|
|
||||||
dirList.append( os.path.join(dirpath, d) )
|
|
||||||
|
|
||||||
fs = LittleFS(block_size=blockSize, block_count=blockCount) # create a 448kB partition
|
|
||||||
|
|
||||||
for curDir in dirList:
|
|
||||||
print( "Creating dir " + curDir )
|
|
||||||
fs.mkdir( curDir )
|
|
||||||
|
|
||||||
for curFile in fileList:
|
|
||||||
print( "Adding file " + curFile )
|
|
||||||
with open( curFile, 'rb' ) as f:
|
|
||||||
data = f.read()
|
|
||||||
|
|
||||||
with fs.open( curFile, 'wb') as fh:
|
|
||||||
fh.write( data )
|
|
||||||
|
|
||||||
outName = argList[-1]
|
|
||||||
|
|
||||||
os.chdir(cwd)
|
|
||||||
|
|
||||||
with open(outName, 'wb') as fh:
|
|
||||||
fh.write(fs.context.buffer)
|
|
||||||
@@ -1,24 +1,70 @@
|
|||||||
|
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import configparser
|
import configparser
|
||||||
import traceback
|
import traceback
|
||||||
import sys
|
import sys
|
||||||
|
from os.path import join
|
||||||
from readprops import readProps
|
from readprops import readProps
|
||||||
|
|
||||||
Import("env")
|
Import("env")
|
||||||
env.Replace( MKSPIFFSTOOL=env.get("PROJECT_DIR") + '/bin/mklittlefs.py' )
|
platform = env.PioPlatform()
|
||||||
try:
|
|
||||||
import littlefs
|
def esp32_create_combined_bin(source, target, env):
|
||||||
except ImportError:
|
# this sub is borrowed from ESPEasy build toolchain. It's licensed under GPL V3
|
||||||
env.Execute("$PYTHONEXE -m pip install littlefs-python")
|
# https://github.com/letscontrolit/ESPEasy/blob/mega/tools/pio/post_esp32.py
|
||||||
|
print("Generating combined binary for serial flashing")
|
||||||
|
|
||||||
|
app_offset = 0x10000
|
||||||
|
|
||||||
|
new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin")
|
||||||
|
sections = env.subst(env.get("FLASH_EXTRA_IMAGES"))
|
||||||
|
firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin")
|
||||||
|
chip = env.get("BOARD_MCU")
|
||||||
|
flash_size = env.BoardConfig().get("upload.flash_size")
|
||||||
|
flash_freq = env.BoardConfig().get("build.f_flash", '40m')
|
||||||
|
flash_freq = flash_freq.replace('000000L', 'm')
|
||||||
|
flash_mode = env.BoardConfig().get("build.flash_mode", "dio")
|
||||||
|
memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi")
|
||||||
|
if flash_mode == "qio" or flash_mode == "qout":
|
||||||
|
flash_mode = "dio"
|
||||||
|
if memory_type == "opi_opi" or memory_type == "opi_qspi":
|
||||||
|
flash_mode = "dout"
|
||||||
|
cmd = [
|
||||||
|
"--chip",
|
||||||
|
chip,
|
||||||
|
"merge_bin",
|
||||||
|
"-o",
|
||||||
|
new_file_name,
|
||||||
|
"--flash_mode",
|
||||||
|
flash_mode,
|
||||||
|
"--flash_freq",
|
||||||
|
flash_freq,
|
||||||
|
"--flash_size",
|
||||||
|
flash_size,
|
||||||
|
]
|
||||||
|
|
||||||
|
print(" Offset | File")
|
||||||
|
for section in sections:
|
||||||
|
sect_adr, sect_file = section.split(" ", 1)
|
||||||
|
print(f" - {sect_adr} | {sect_file}")
|
||||||
|
cmd += [sect_adr, sect_file]
|
||||||
|
|
||||||
|
print(f" - {hex(app_offset)} | {firmware_name}")
|
||||||
|
cmd += [hex(app_offset), firmware_name]
|
||||||
|
|
||||||
|
print('Using esptool.py arguments: %s' % ' '.join(cmd))
|
||||||
|
|
||||||
|
esptool.main(cmd)
|
||||||
|
|
||||||
|
if (platform.name == "espressif32"):
|
||||||
|
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
|
||||||
|
import esptool
|
||||||
|
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
|
||||||
|
|
||||||
Import("projenv")
|
Import("projenv")
|
||||||
|
|
||||||
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
||||||
verObj = readProps(prefsLoc)
|
verObj = readProps(prefsLoc)
|
||||||
print("Using meshtastic platformio-custom.py, firmare version " + verObj['long'])
|
print("Using meshtastic platformio-custom.py, firmware version " + verObj['long'])
|
||||||
# print("path is" + ','.join(sys.path))
|
|
||||||
|
|
||||||
# General options that are passed to the C and C++ compilers
|
# General options that are passed to the C and C++ compilers
|
||||||
projenv.Append(CCFLAGS=[
|
projenv.Append(CCFLAGS=[
|
||||||
|
|||||||
@@ -32,6 +32,6 @@ def readProps(prefsLoc):
|
|||||||
# traceback.print_exc()
|
# traceback.print_exc()
|
||||||
verObj['long'] = verObj['short']
|
verObj['long'] = verObj['short']
|
||||||
|
|
||||||
# print("firmare version " + verStr)
|
# print("firmware version " + verStr)
|
||||||
return verObj
|
return verObj
|
||||||
# print("path is" + ','.join(sys.path))
|
# print("path is" + ','.join(sys.path))
|
||||||
|
|||||||
31
boards/generic_wl5e.json
Normal file
31
boards/generic_wl5e.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"core": "stm32",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DSTM32WLxx -DSTM32WLE5xx -DARDUINO_GENERIC_WLE5CCUX",
|
||||||
|
"f_cpu": "48000000L",
|
||||||
|
"mcu": "stm32wle5ccu",
|
||||||
|
"variant": "STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U",
|
||||||
|
"product_line": "STM32WLE5xx"
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"default_tools": [
|
||||||
|
"stlink"
|
||||||
|
],
|
||||||
|
"jlink_device": "STM32WLE5CC",
|
||||||
|
"openocd_target": "stm32wlx",
|
||||||
|
"svd_path": "STM32WLE5_CM4.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "BB-STM32WL",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 65536,
|
||||||
|
"maximum_size": 262144,
|
||||||
|
"protocol": "cmsis-dap",
|
||||||
|
"protocols": [
|
||||||
|
"cmsis-dap"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": "https://www.st.com/en/microcontrollers-microprocessors/stm32wl-series.html",
|
||||||
|
"vendor": "ST"
|
||||||
|
}
|
||||||
48
boards/tbeam-s3-core.json
Normal file
48
boards/tbeam-s3-core.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino":{
|
||||||
|
"ldscript": "esp32s3_out.ld"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DLILYGO_TBEAM_S3_CORE",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_DFU_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_MSC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"hwids": [
|
||||||
|
[
|
||||||
|
"0X303A",
|
||||||
|
"0x1001"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "tbeam-s3-core"
|
||||||
|
},
|
||||||
|
"connectivity": [
|
||||||
|
"wifi"
|
||||||
|
],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": [
|
||||||
|
"arduino"
|
||||||
|
],
|
||||||
|
"name": "LilyGo TBeam-S3-Core",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "8MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 8388608,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "http://www.lilygo.cn/",
|
||||||
|
"vendor": "LilyGo"
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -1,8 +1,8 @@
|
|||||||
# FIXME! using the genpartitions based table doesn't work on TTGO so for now I stay with my old memory map
|
# FIXME! using the genpartitions based table doesn't work on TTGO so for now I stay with my old memory map
|
||||||
# This is a layout for 4MB of flash
|
# This is a layout for 4MB of flash
|
||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, 0x9000, 0x5000,
|
nvs, data, nvs, 0x009000, 0x005000,
|
||||||
otadata, data, ota, 0xe000, 0x2000,
|
otadata, data, ota, 0x00e000, 0x002000,
|
||||||
app0, app, ota_0, 0x10000, 0x1c0000,
|
app, app, ota_0, 0x010000, 0x250000,
|
||||||
app1, app, ota_1, 0x1d0000,0x1c0000,
|
flashApp, app, ota_1, 0x260000, 0x0A0000,
|
||||||
spiffs, data, spiffs, 0x390000,0x070000,
|
spiffs, data, spiffs, 0x300000, 0x100000,
|
||||||
|
106
platformio.ini
106
platformio.ini
@@ -2,7 +2,9 @@
|
|||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
default_envs = tbeam
|
;default_envs = tbeam
|
||||||
|
;default_envs = pico
|
||||||
|
;default_envs = tbeam-s3-core
|
||||||
;default_envs = tbeam0.7
|
;default_envs = tbeam0.7
|
||||||
;default_envs = heltec-v1
|
;default_envs = heltec-v1
|
||||||
;default_envs = heltec-v2.0
|
;default_envs = heltec-v2.0
|
||||||
@@ -21,8 +23,11 @@ default_envs = tbeam
|
|||||||
;default_envs = meshtastic-diy-v1
|
;default_envs = meshtastic-diy-v1
|
||||||
;default_envs = meshtastic-diy-v1.1
|
;default_envs = meshtastic-diy-v1.1
|
||||||
;default_envs = m5stack-coreink
|
;default_envs = m5stack-coreink
|
||||||
|
;default_envs = rak4631
|
||||||
|
|
||||||
extra_configs = variants/*/platformio.ini
|
extra_configs =
|
||||||
|
arch/*/*.ini
|
||||||
|
variants/*/platformio.ini
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
extra_scripts = bin/platformio-custom.py
|
extra_scripts = bin/platformio-custom.py
|
||||||
@@ -43,13 +48,11 @@ 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#53580644255b48ebb7a737343c6b4e71c7e11cf2 ; 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
|
||||||
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||||
https://github.com/meshtastic/arduino-fsm.git
|
https://github.com/meshtastic/TinyGPSPlus.git#2f0d0528d737000043e949f4c3bdfb623cf0b902
|
||||||
https://github.com/meshtastic/TinyGPSPlus.git
|
|
||||||
Wire ; explicitly needed here because the AXP202 library forgets to add it
|
|
||||||
SPI
|
|
||||||
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
|
||||||
|
|
||||||
; Used for the code analysis in PIO Home / Inspect
|
; Used for the code analysis in PIO Home / Inspect
|
||||||
check_tool = cppcheck
|
check_tool = cppcheck
|
||||||
@@ -61,16 +64,18 @@ framework = arduino
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
; Portduino is using meshtastic fork for now
|
; Portduino is using meshtastic fork for now
|
||||||
https://github.com/jgromes/RadioLib.git
|
jgromes/RadioLib@5.4.1
|
||||||
|
https://github.com/caveman99/SparkFun_ATECCX08a_Arduino_Library.git#008e7f9d40bad66b2f7a0074aaac05b7c424339d
|
||||||
|
|
||||||
build_flags = ${env.build_flags} -Os
|
build_flags = ${env.build_flags} -Os
|
||||||
|
-DRADIOLIB_SPI_PARANOID=0
|
||||||
# -DRADIOLIB_GODMODE
|
# -DRADIOLIB_GODMODE
|
||||||
build_src_filter = ${env.build_src_filter} -<portduino/>
|
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
||||||
|
|
||||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||||
[networking_base]
|
[networking_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
PubSubClient
|
knolleary/PubSubClient@^2.8
|
||||||
meshtastic/json11@^1.0.2
|
meshtastic/json11@^1.0.2
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
@@ -78,90 +83,11 @@ lib_deps =
|
|||||||
[environmental_base]
|
[environmental_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
adafruit/Adafruit BusIO@^1.11.4
|
adafruit/Adafruit BusIO@^1.11.4
|
||||||
adafruit/DHT sensor library@^1.4.1
|
|
||||||
adafruit/Adafruit Unified Sensor@^1.1.4
|
adafruit/Adafruit Unified Sensor@^1.1.4
|
||||||
paulstoffregen/OneWire@^2.3.5
|
adafruit/Adafruit BMP280 Library@^2.6.6
|
||||||
robtillaart/DS18B20@^0.1.11
|
|
||||||
adafruit/Adafruit BME280 Library@^2.2.2
|
adafruit/Adafruit BME280 Library@^2.2.2
|
||||||
adafruit/Adafruit BME680 Library@^2.0.1
|
adafruit/Adafruit BME680 Library@^2.0.1
|
||||||
adafruit/Adafruit MCP9808 Library@^2.0.0
|
adafruit/Adafruit MCP9808 Library@^2.0.0
|
||||||
adafruit/Adafruit INA260 Library@^1.5.0
|
adafruit/Adafruit INA260 Library@^1.5.0
|
||||||
adafruit/Adafruit INA219@^1.2.0
|
adafruit/Adafruit INA219@^1.2.0
|
||||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
|
||||||
[esp32_base]
|
|
||||||
extends = arduino_base
|
|
||||||
platform = espressif32@3.5.0
|
|
||||||
build_src_filter =
|
|
||||||
${arduino_base.build_src_filter} -<nrf52/>
|
|
||||||
upload_speed = 115200
|
|
||||||
debug_init_break = tbreak setup
|
|
||||||
|
|
||||||
# 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
|
|
||||||
# -DUSE_NEW_ESP32_BLUETOOTH will enable the new NimBLE C++ api
|
|
||||||
build_flags =
|
|
||||||
${arduino_base.build_flags} -Wall -Wextra -Isrc/esp32 -Isrc/esp32-mfix-esp32-psram-cache-issue -lnimble -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 -DUSE_NEW_ESP32_BLUETOOTH
|
|
||||||
lib_deps =
|
|
||||||
${arduino_base.lib_deps}
|
|
||||||
${networking_base.lib_deps}
|
|
||||||
${environmental_base.lib_deps}
|
|
||||||
https://github.com/meshtastic/esp32_https_server.git
|
|
||||||
h2zero/NimBLE-Arduino@1.3.7
|
|
||||||
arduino-libraries/NTPClient@^3.1.0
|
|
||||||
lorol/LittleFS_esp32@^1.0.6
|
|
||||||
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
|
|
||||||
|
|
||||||
lib_ignore =
|
|
||||||
segger_rtt
|
|
||||||
ESP32 BLE Arduino
|
|
||||||
platform_packages =
|
|
||||||
framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#4cde0f5d412d2695184f32e8a47e9bea57b45276
|
|
||||||
|
|
||||||
; leave this commented out to avoid breaking Windows
|
|
||||||
;upload_port = /dev/ttyUSB0
|
|
||||||
;monitor_port = /dev/ttyUSB0
|
|
||||||
|
|
||||||
; Please don't delete these lines. JM uses them.
|
|
||||||
;upload_port = /dev/cu.SLAB_USBtoUART
|
|
||||||
;monitor_port = /dev/cu.SLAB_USBtoUART
|
|
||||||
|
|
||||||
; customize the partition table
|
|
||||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
|
||||||
board_build.partitions = partition-table.csv
|
|
||||||
|
|
||||||
[nrf52_base]
|
|
||||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
|
||||||
; platform = nordicnrf52 ;pending https://github.com/platformio/builder-framework-arduino-nrf5/pull/7
|
|
||||||
platform = https://github.com/meshtastic/platform-nordicnrf52.git#merge
|
|
||||||
|
|
||||||
extends = arduino_base
|
|
||||||
build_type = debug ; I'm debugging with ICE a lot now
|
|
||||||
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
|
|
||||||
build_flags =
|
|
||||||
${arduino_base.build_flags} -Wno-unused-variable
|
|
||||||
-Isrc/nrf52
|
|
||||||
build_src_filter =
|
|
||||||
${arduino_base.build_src_filter} -<esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/>
|
|
||||||
lib_ignore =
|
|
||||||
BluetoothOTA
|
|
||||||
|
|
||||||
[nrf52840_base]
|
|
||||||
extends = nrf52_base
|
|
||||||
build_flags = ${nrf52_base.build_flags}
|
|
||||||
lib_deps =
|
|
||||||
${arduino_base.lib_deps}
|
|
||||||
${environmental_base.lib_deps}
|
|
||||||
https://github.com/Kongduino/Adafruit_nRFCrypto.git
|
|
||||||
|
|
||||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
|
||||||
[env:nrf52840dk]
|
|
||||||
extends = nrf52840_base
|
|
||||||
board = nrf52840_dk
|
|
||||||
|
|
||||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
|
||||||
[env:feather_nrf52832]
|
|
||||||
extends = nrf52_base
|
|
||||||
board = adafruit_feather_nrf52832
|
|
||||||
|
|||||||
Submodule protobufs updated: c63a16c32f...d3dfaa63a5
@@ -7,7 +7,7 @@ const uint8_t MESH_SERVICE_UUID_16[16u] = {0xfd, 0xea, 0x73, 0xe2, 0xca, 0x5d, 0
|
|||||||
0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b};
|
0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b};
|
||||||
const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1,
|
const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1,
|
||||||
0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7};
|
0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7};
|
||||||
const uint8_t FROMRADIO_UUID_16[16u] = {0xd5, 0x54, 0xe4, 0xc5, 0x25, 0xc5, 0x31, 0xa5,
|
const uint8_t FROMRADIO_UUID_16[16u] = {0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8,
|
||||||
0x55, 0x4a, 0x02, 0xee, 0xc2, 0xbc, 0xa2, 0x8b};
|
0xed, 0x11, 0x93, 0x49, 0x9e, 0xe6, 0x55, 0x2c};
|
||||||
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
|
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
|
||||||
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};
|
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
|
#define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
|
||||||
|
|
||||||
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
|
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
|
||||||
#define FROMRADIO_UUID "8ba2bcc2-ee02-4a55-a531-c525c5e454d5"
|
#define FROMRADIO_UUID "2c55e69e-4993-11ed-b878-0242ac120002"
|
||||||
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
|
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
|
||||||
|
|
||||||
// NRF52 wants these constants as byte arrays
|
// NRF52 wants these constants as byte arrays
|
||||||
|
|||||||
@@ -7,10 +7,6 @@
|
|||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include <OneButton.h>
|
#include <OneButton.h>
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
|
||||||
#include "nimble/BluetoothUtil.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace concurrency
|
namespace concurrency
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -127,25 +123,32 @@ class ButtonThread : public concurrency::OSThread
|
|||||||
static void userButtonPressedLong()
|
static void userButtonPressedLong()
|
||||||
{
|
{
|
||||||
// DEBUG_MSG("Long press!\n");
|
// DEBUG_MSG("Long press!\n");
|
||||||
#ifndef NRF52_SERIES
|
#ifdef ARCH_ESP32
|
||||||
screen->adjustBrightness();
|
screen->adjustBrightness();
|
||||||
#endif
|
#endif
|
||||||
// If user button is held down for 5 seconds, shutdown the device.
|
// If user button is held down for 5 seconds, shutdown the device.
|
||||||
if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) {
|
if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) {
|
||||||
#ifdef TBEAM_V10
|
#ifdef HAS_PMU
|
||||||
if (axp192_found == true) {
|
if (pmu_found == true) {
|
||||||
setLed(false);
|
setLed(false);
|
||||||
power->shutdown();
|
power->shutdown();
|
||||||
}
|
}
|
||||||
#elif NRF52_SERIES
|
#elif defined(ARCH_NRF52)
|
||||||
// Do actual shutdown when button released, otherwise the button release
|
// Do actual shutdown when button released, otherwise the button release
|
||||||
// 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");
|
DEBUG_MSG("Shutdown from long press");
|
||||||
playBeep();
|
playBeep();
|
||||||
|
#ifdef PIN_LED1
|
||||||
ledOff(PIN_LED1);
|
ledOff(PIN_LED1);
|
||||||
|
#endif
|
||||||
|
#ifdef PIN_LED2
|
||||||
ledOff(PIN_LED2);
|
ledOff(PIN_LED2);
|
||||||
|
#endif
|
||||||
|
#ifdef PIN_LED3
|
||||||
|
ledOff(PIN_LED3);
|
||||||
|
#endif
|
||||||
shutdown_on_long_stop = true;
|
shutdown_on_long_stop = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -156,19 +159,19 @@ class ButtonThread : public concurrency::OSThread
|
|||||||
|
|
||||||
static void userButtonDoublePressed()
|
static void userButtonDoublePressed()
|
||||||
{
|
{
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
disablePin();
|
disablePin();
|
||||||
#elif defined(HAS_EINK)
|
#elif defined(USE_EINK)
|
||||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void userButtonMultiPressed()
|
static void userButtonMultiPressed()
|
||||||
{
|
{
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
clearNVS();
|
clearNVS();
|
||||||
#endif
|
#endif
|
||||||
#ifdef NRF52_SERIES
|
#ifdef ARCH_NRF52
|
||||||
clearBonds();
|
clearBonds();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,29 +17,6 @@
|
|||||||
|
|
||||||
#define DEBUG_PORT (*console) // Serial debug port
|
#define DEBUG_PORT (*console) // Serial debug port
|
||||||
|
|
||||||
// What platforms should use SEGGER?
|
|
||||||
#ifdef NRF52_SERIES
|
|
||||||
|
|
||||||
// Always include the SEGGER code on NRF52 - because useful for debugging
|
|
||||||
#include "SEGGER_RTT.h"
|
|
||||||
|
|
||||||
// The channel we send stdout data to
|
|
||||||
#define SEGGER_STDOUT_CH 0
|
|
||||||
|
|
||||||
// Debug printing to segger console
|
|
||||||
#define SEGGER_MSG(...) SEGGER_RTT_printf(SEGGER_STDOUT_CH, __VA_ARGS__)
|
|
||||||
|
|
||||||
// If we are not on a NRF52840 (which has built in USB-ACM serial support) and we don't have serial pins hooked up, then we MUST
|
|
||||||
// use SEGGER for debug output
|
|
||||||
#if !defined(PIN_SERIAL_RX) && !defined(NRF52840_XXAA)
|
|
||||||
// No serial ports on this board - ONLY use segger in memory console
|
|
||||||
#define USE_SEGGER
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_SEGGER
|
#ifdef USE_SEGGER
|
||||||
#define DEBUG_MSG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
#define DEBUG_MSG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
|||||||
170
src/FSCommon.cpp
170
src/FSCommon.cpp
@@ -1,10 +1,58 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "FSCommon.h"
|
#include "FSCommon.h"
|
||||||
|
|
||||||
void listDir(const char * dirname, uint8_t levels)
|
|
||||||
|
bool copyFile(const char* from, const char* to)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
File root = FSCom.open(dirname);
|
unsigned char cbuffer[16];
|
||||||
|
|
||||||
|
File f1 = FSCom.open(from, FILE_O_READ);
|
||||||
|
if (!f1){
|
||||||
|
DEBUG_MSG("Failed to open source file %s\n", from);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
File f2 = FSCom.open(to, FILE_O_WRITE);
|
||||||
|
if (!f2) {
|
||||||
|
DEBUG_MSG("Failed to open destination file %s\n", to);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (f1.available() > 0) {
|
||||||
|
byte i = f1.read(cbuffer, 16);
|
||||||
|
f2.write(cbuffer, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
f2.close();
|
||||||
|
f1.close();
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool renameFile(const char* pathFrom, const char* pathTo)
|
||||||
|
{
|
||||||
|
#ifdef FSCom
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
// rename was fixed for ESP32 IDF LittleFS in April
|
||||||
|
return FSCom.rename(pathFrom, pathTo);
|
||||||
|
#else
|
||||||
|
if (copyFile(pathFrom, pathTo) && FSCom.remove(pathFrom) ) {
|
||||||
|
return true;
|
||||||
|
} else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void listDir(const char * dirname, uint8_t levels, boolean del = false)
|
||||||
|
{
|
||||||
|
#ifdef FSCom
|
||||||
|
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||||
|
char buffer[255];
|
||||||
|
#endif
|
||||||
|
File root = FSCom.open(dirname, FILE_O_READ);
|
||||||
if(!root){
|
if(!root){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -16,55 +64,92 @@ void listDir(const char * dirname, uint8_t levels)
|
|||||||
while(file){
|
while(file){
|
||||||
if(file.isDirectory() && !String(file.name()).endsWith(".")) {
|
if(file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||||
if(levels){
|
if(levels){
|
||||||
listDir(file.name(), levels -1);
|
#ifdef ARCH_ESP32
|
||||||
|
listDir(file.path(), levels -1, del);
|
||||||
|
if(del) {
|
||||||
|
DEBUG_MSG("Removing %s\n", file.path());
|
||||||
|
strcpy(buffer, file.path());
|
||||||
|
file.close();
|
||||||
|
FSCom.rmdir(buffer);
|
||||||
|
} else {
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||||
|
listDir(file.name(), levels -1, del);
|
||||||
|
if(del) {
|
||||||
|
DEBUG_MSG("Removing %s\n", file.name());
|
||||||
|
strcpy(buffer, file.name());
|
||||||
|
file.close();
|
||||||
|
FSCom.rmdir(buffer);
|
||||||
|
} else {
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
listDir(file.name(), levels -1, del);
|
||||||
|
file.close();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size());
|
#ifdef ARCH_ESP32
|
||||||
|
if(del) {
|
||||||
|
DEBUG_MSG("Deleting %s\n", file.path());
|
||||||
|
strcpy(buffer, file.path());
|
||||||
|
file.close();
|
||||||
|
FSCom.remove(buffer);
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG(" %s (%i Bytes)\n", file.path(), file.size());
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||||
|
if(del) {
|
||||||
|
DEBUG_MSG("Deleting %s\n", file.name());
|
||||||
|
strcpy(buffer, file.name());
|
||||||
|
file.close();
|
||||||
|
FSCom.remove(buffer);
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size());
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size());
|
||||||
|
file.close();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
file.close();
|
|
||||||
file = root.openNextFile();
|
file = root.openNextFile();
|
||||||
}
|
}
|
||||||
file.close();
|
#ifdef ARCH_ESP32
|
||||||
|
if(del) {
|
||||||
|
DEBUG_MSG("Removing %s\n", root.path());
|
||||||
|
strcpy(buffer, root.path());
|
||||||
|
root.close();
|
||||||
|
FSCom.rmdir(buffer);
|
||||||
|
} else {
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
|
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||||
|
if(del) {
|
||||||
|
DEBUG_MSG("Removing %s\n", root.name());
|
||||||
|
strcpy(buffer, root.name());
|
||||||
|
root.close();
|
||||||
|
FSCom.rmdir(buffer);
|
||||||
|
} else {
|
||||||
|
root.close();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
root.close();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void rmDir(const char * dirname)
|
void rmDir(const char * dirname)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
File file = FSCom.open(dirname);
|
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||||
if(!file){
|
listDir(dirname, 10, true);
|
||||||
return;
|
#elif defined(ARCH_NRF52)
|
||||||
}
|
// nRF52 implementation of LittleFS has a recursive delete function
|
||||||
if(!file.isDirectory()){
|
FSCom.rmdir_r(dirname);
|
||||||
file.close();
|
#endif
|
||||||
FSCom.remove(file.name());
|
|
||||||
// DEBUG_MSG("Remove FILE %s\n", file.name());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
file.rewindDirectory();
|
|
||||||
while (true) {
|
|
||||||
File entry = file.openNextFile();
|
|
||||||
if (!entry) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
char dirpath[100]; // array to hold the result.
|
|
||||||
strcpy(dirpath, dirname); // copy string one into the result.
|
|
||||||
strcat(dirpath,"/"); // append string two to the result.
|
|
||||||
strcat(dirpath,entry.name()); // append string two to the result.
|
|
||||||
if(entry.isDirectory() && !String(entry.name()).endsWith(".")) {
|
|
||||||
entry.close();
|
|
||||||
// DEBUG_MSG("Descend DIR %s\n", dirpath);
|
|
||||||
rmDir(dirpath);
|
|
||||||
} else {
|
|
||||||
entry.close();
|
|
||||||
// DEBUG_MSG("Remove FILE %s\n", entry.name());
|
|
||||||
FSCom.remove(entry.name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FSCom.rmdir(dirname);
|
|
||||||
// DEBUG_MSG("Remove DIR %s\n", dirname);
|
|
||||||
file.close();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,8 +161,11 @@ void fsInit()
|
|||||||
DEBUG_MSG("ERROR filesystem mount Failed. Formatting...\n");
|
DEBUG_MSG("ERROR filesystem mount Failed. Formatting...\n");
|
||||||
assert(0); // FIXME - report failure to phone
|
assert(0); // FIXME - report failure to phone
|
||||||
}
|
}
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
DEBUG_MSG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
|
||||||
|
#else
|
||||||
DEBUG_MSG("Filesystem files:\n");
|
DEBUG_MSG("Filesystem files:\n");
|
||||||
|
#endif
|
||||||
listDir("/", 10);
|
listDir("/", 10);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,21 +4,34 @@
|
|||||||
|
|
||||||
// Cross platform filesystem API
|
// Cross platform filesystem API
|
||||||
|
|
||||||
#ifdef PORTDUINO
|
#if defined(ARCH_PORTDUINO)
|
||||||
// Portduino version
|
// Portduino version
|
||||||
#include "PortduinoFS.h"
|
#include "PortduinoFS.h"
|
||||||
#define FSCom PortduinoFS
|
#define FSCom PortduinoFS
|
||||||
#define FSBegin() true
|
#define FSBegin() true
|
||||||
#define FILE_O_WRITE "w"
|
#define FILE_O_WRITE "w"
|
||||||
#define FILE_O_READ "r"
|
#define FILE_O_READ "r"
|
||||||
#elif !defined(NO_ESP32)
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARCH_RP2040)
|
||||||
|
// RP2040
|
||||||
|
#include "LittleFS.h"
|
||||||
|
#define FSCom LittleFS
|
||||||
|
#define FSBegin() FSCom.begin()
|
||||||
|
#define FILE_O_WRITE "w"
|
||||||
|
#define FILE_O_READ "r"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARCH_ESP32)
|
||||||
// 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)
|
||||||
#define FILE_O_WRITE "w"
|
#define FILE_O_WRITE "w"
|
||||||
#define FILE_O_READ "r"
|
#define FILE_O_READ "r"
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARCH_NRF52)
|
||||||
// NRF52 version
|
// NRF52 version
|
||||||
#include "InternalFileSystem.h"
|
#include "InternalFileSystem.h"
|
||||||
#define FSCom InternalFS
|
#define FSCom InternalFS
|
||||||
@@ -27,5 +40,7 @@ using namespace Adafruit_LittleFS_Namespace;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void fsInit();
|
void fsInit();
|
||||||
void listDir(const char * dirname, uint8_t levels);
|
bool copyFile(const char* from, const char* to);
|
||||||
|
bool renameFile(const char* pathFrom, const char* pathTo);
|
||||||
|
void listDir(const char * dirname, uint8_t levels, boolean del);
|
||||||
void rmDir(const char * dirname);
|
void rmDir(const char * dirname);
|
||||||
|
|||||||
@@ -25,21 +25,21 @@ class GPSStatus : public Status
|
|||||||
public:
|
public:
|
||||||
GPSStatus() { statusType = STATUS_TYPE_GPS; }
|
GPSStatus() { statusType = STATUS_TYPE_GPS; }
|
||||||
|
|
||||||
// proposed for deprecation
|
// // proposed for deprecation
|
||||||
GPSStatus(bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop,
|
// GPSStatus(bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop,
|
||||||
uint32_t heading, uint32_t numSatellites)
|
// uint32_t heading, uint32_t numSatellites)
|
||||||
: Status()
|
// : Status()
|
||||||
{
|
// {
|
||||||
this->hasLock = hasLock;
|
// this->hasLock = hasLock;
|
||||||
this->isConnected = isConnected;
|
// this->isConnected = isConnected;
|
||||||
|
|
||||||
this->p.latitude_i = latitude;
|
// this->p.latitude_i = latitude;
|
||||||
this->p.longitude_i = longitude;
|
// this->p.longitude_i = longitude;
|
||||||
this->p.altitude = altitude;
|
// this->p.altitude = altitude;
|
||||||
this->p.PDOP = dop;
|
// this->p.PDOP = dop;
|
||||||
this->p.ground_track = heading;
|
// this->p.ground_track = heading;
|
||||||
this->p.sats_in_view = numSatellites;
|
// this->p.sats_in_view = numSatellites;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// preferred method
|
// preferred method
|
||||||
GPSStatus(bool hasLock, bool isConnected, const Position &pos) : Status()
|
GPSStatus(bool hasLock, bool isConnected, const Position &pos) : Status()
|
||||||
@@ -114,6 +114,7 @@ class GPSStatus : public Status
|
|||||||
newStatus->p.latitude_i != p.latitude_i || newStatus->p.longitude_i != p.longitude_i ||
|
newStatus->p.latitude_i != p.latitude_i || newStatus->p.longitude_i != p.longitude_i ||
|
||||||
newStatus->p.altitude != p.altitude || newStatus->p.altitude_hae != p.altitude_hae ||
|
newStatus->p.altitude != p.altitude || newStatus->p.altitude_hae != p.altitude_hae ||
|
||||||
newStatus->p.PDOP != p.PDOP || newStatus->p.ground_track != p.ground_track ||
|
newStatus->p.PDOP != p.PDOP || 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ class GPSStatus : public Status
|
|||||||
// Only update the status if values have actually changed
|
// Only update the status if values have actually changed
|
||||||
bool isDirty = matches(newStatus);
|
bool isDirty = matches(newStatus);
|
||||||
|
|
||||||
if (isDirty && p.pos_timestamp && (newStatus->p.pos_timestamp == p.pos_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");
|
DEBUG_MSG("BUG!! positional timestamp unchanged from prev solution\n");
|
||||||
}
|
}
|
||||||
@@ -136,9 +137,9 @@ 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, sats=%d\n", p.pos_timestamp,
|
DEBUG_MSG("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.sats_in_view);
|
p.ground_speed * 1e-2, p.sats_in_view);
|
||||||
} else
|
} else
|
||||||
DEBUG_MSG("No GPS lock\n");
|
DEBUG_MSG("No GPS lock\n");
|
||||||
onNewStatus.notifyObservers(this);
|
onNewStatus.notifyObservers(this);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ bool scheduleOSCallback(PendableFunction callback, void *param1, uint32_t param2
|
|||||||
return xTimerPendFunctionCall(callback, param1, param2, pdMS_TO_TICKS(delayMsec));
|
return xTimerPendFunctionCall(callback, param1, param2, pdMS_TO_TICKS(delayMsec));
|
||||||
} */
|
} */
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
|
|
||||||
// Super skanky quick hack to use hardware timers of the ESP32
|
// Super skanky quick hack to use hardware timers of the ESP32
|
||||||
static hw_timer_t *timer;
|
static hw_timer_t *timer;
|
||||||
|
|||||||
485
src/Power.cpp
485
src/Power.cpp
@@ -7,12 +7,11 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "buzz/buzz.h"
|
#include "buzz/buzz.h"
|
||||||
|
|
||||||
#ifdef TBEAM_V10
|
#ifdef HAS_PMU
|
||||||
// FIXME. nasty hack cleanup how we load axp192
|
#include "XPowersLibInterface.hpp"
|
||||||
#undef AXP192_SLAVE_ADDRESS
|
#include "XPowersAXP2101.tpp"
|
||||||
#include "axp20x.h"
|
#include "XPowersAXP192.tpp"
|
||||||
|
XPowersLibInterface *PMU = NULL;
|
||||||
AXP20X_Class axp;
|
|
||||||
#else
|
#else
|
||||||
// Copy of the base class defined in axp20x.h.
|
// Copy of the base class defined in axp20x.h.
|
||||||
// I'd rather not inlude axp20x.h as it brings Wire dependency.
|
// I'd rather not inlude axp20x.h as it brings Wire dependency.
|
||||||
@@ -22,20 +21,20 @@ class HasBatteryLevel
|
|||||||
/**
|
/**
|
||||||
* Battery state of charge, from 0 to 100 or -1 for unknown
|
* Battery state of charge, from 0 to 100 or -1 for unknown
|
||||||
*/
|
*/
|
||||||
virtual int getBattPercentage() { return -1; }
|
virtual int getBatteryPercent() { return -1; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The raw voltage of the battery or NAN if unknown
|
* The raw voltage of the battery or NAN if unknown
|
||||||
*/
|
*/
|
||||||
virtual float getBattVoltage() { return NAN; }
|
virtual uint16_t getBattVoltage() { return 0; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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() { return false; }
|
virtual bool isBatteryConnect() { return false; }
|
||||||
|
|
||||||
virtual bool isVBUSPlug() { return false; }
|
virtual bool isVbusIn() { return false; }
|
||||||
virtual bool isChargeing() { return false; }
|
virtual bool isCharging() { return false; }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ Power *power;
|
|||||||
using namespace meshtastic;
|
using namespace meshtastic;
|
||||||
|
|
||||||
#ifndef AREF_VOLTAGE
|
#ifndef AREF_VOLTAGE
|
||||||
#if defined(NRF52_SERIES)
|
#if defined(ARCH_NRF52)
|
||||||
/*
|
/*
|
||||||
* Internal Reference is +/-0.6V, with an adjustable gain of 1/6, 1/5, 1/4,
|
* Internal Reference is +/-0.6V, with an adjustable gain of 1/6, 1/5, 1/4,
|
||||||
* 1/3, 1/2 or 1, meaning 3.6, 3.0, 2.4, 1.8, 1.2 or 0.6V for the ADC levels.
|
* 1/3, 1/2 or 1, meaning 3.6, 3.0, 2.4, 1.8, 1.2 or 0.6V for the ADC levels.
|
||||||
@@ -77,14 +76,14 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
*
|
*
|
||||||
* FIXME - use a lipo lookup table, the current % full is super wrong
|
* FIXME - use a lipo lookup table, the current % full is super wrong
|
||||||
*/
|
*/
|
||||||
virtual int getBattPercentage() override
|
virtual int getBatteryPercent() override
|
||||||
{
|
{
|
||||||
float v = getBattVoltage();
|
float v = getBattVoltage();
|
||||||
|
|
||||||
if (v < noBatVolt)
|
if (v < noBatVolt)
|
||||||
return -1; // If voltage is super low assume no battery installed
|
return -1; // If voltage is super low assume no battery installed
|
||||||
|
|
||||||
#ifndef NRF52_SERIES
|
#ifdef ARCH_ESP32
|
||||||
// This does not work on a RAK4631 with battery connected
|
// This does not work on a RAK4631 with battery connected
|
||||||
if (v > chargingVolt)
|
if (v > chargingVolt)
|
||||||
return 0; // While charging we can't report % full on the battery
|
return 0; // While charging we can't report % full on the battery
|
||||||
@@ -96,7 +95,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
/**
|
/**
|
||||||
* The raw voltage of the batteryin millivolts or NAN if unknown
|
* The raw voltage of the batteryin millivolts or NAN if unknown
|
||||||
*/
|
*/
|
||||||
virtual float getBattVoltage() override
|
virtual uint16_t getBattVoltage() override
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifndef ADC_MULTIPLIER
|
#ifndef ADC_MULTIPLIER
|
||||||
@@ -112,7 +111,18 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
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 environment.
|
||||||
|
uint32_t raw = 0;
|
||||||
|
for(uint32_t i=0; i<BATTERY_SENSE_SAMPLES;i++){
|
||||||
|
raw += analogRead(BATTERY_PIN);
|
||||||
|
}
|
||||||
|
raw = raw/BATTERY_SENSE_SAMPLES;
|
||||||
|
#else
|
||||||
uint32_t raw = analogRead(BATTERY_PIN);
|
uint32_t raw = analogRead(BATTERY_PIN);
|
||||||
|
#endif
|
||||||
|
|
||||||
float scaled;
|
float scaled;
|
||||||
#ifndef VBAT_RAW_TO_SCALED
|
#ifndef VBAT_RAW_TO_SCALED
|
||||||
scaled = 1000.0 * operativeAdcMultiplier * (AREF_VOLTAGE / 1024.0) * raw;
|
scaled = 1000.0 * operativeAdcMultiplier * (AREF_VOLTAGE / 1024.0) * raw;
|
||||||
@@ -126,29 +136,42 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
return last_read_value;
|
return last_read_value;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return NAN;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 getBattPercentage() != -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 isVBUSPlug() 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 isChargeing() override { return isBatteryConnect() && isVBUSPlug(); }
|
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
|
||||||
/// in power
|
/// in power
|
||||||
|
|
||||||
|
#ifndef BAT_FULLVOLT
|
||||||
|
#define BAT_FULLVOLT 4200
|
||||||
|
#endif
|
||||||
|
#ifndef BAT_EMPTYVOLT
|
||||||
|
#define BAT_EMPTYVOLT 3270
|
||||||
|
#endif
|
||||||
|
#ifndef BAT_CHARGINGVOLT
|
||||||
|
#define BAT_CHARGINGVOLT 4210
|
||||||
|
#endif
|
||||||
|
#ifndef BAT_NOBATVOLT
|
||||||
|
#define BAT_NOBATVOLT 2230
|
||||||
|
#endif
|
||||||
|
|
||||||
/// For heltecs with no battery connected, the measured voltage is 2204, so raising to 2230 from 2100
|
/// For heltecs with no battery connected, the measured voltage is 2204, so raising to 2230 from 2100
|
||||||
const float fullVolt = 4200, emptyVolt = 3270, chargingVolt = 4210, noBatVolt = 2230;
|
const float fullVolt = BAT_FULLVOLT, emptyVolt = BAT_EMPTYVOLT, chargingVolt = BAT_CHARGINGVOLT, noBatVolt = BAT_NOBATVOLT;
|
||||||
float last_read_value = 0.0;
|
float last_read_value = 0.0;
|
||||||
uint32_t last_read_time_ms = 0;
|
uint32_t last_read_time_ms = 0;
|
||||||
};
|
};
|
||||||
@@ -169,11 +192,11 @@ bool Power::analogInit()
|
|||||||
// disable any internal pullups
|
// disable any internal pullups
|
||||||
pinMode(BATTERY_PIN, INPUT);
|
pinMode(BATTERY_PIN, INPUT);
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// ESP32 needs special analog stuff
|
// ESP32 needs special analog stuff
|
||||||
adcAttachPin(BATTERY_PIN);
|
adcAttachPin(BATTERY_PIN);
|
||||||
#endif
|
#endif
|
||||||
#ifdef NRF52_SERIES
|
#ifdef ARCH_NRF52
|
||||||
#ifdef VBAT_AR_INTERNAL
|
#ifdef VBAT_AR_INTERNAL
|
||||||
analogReference(VBAT_AR_INTERNAL);
|
analogReference(VBAT_AR_INTERNAL);
|
||||||
#else
|
#else
|
||||||
@@ -197,7 +220,7 @@ bool Power::analogInit()
|
|||||||
|
|
||||||
bool Power::setup()
|
bool Power::setup()
|
||||||
{
|
{
|
||||||
bool found = axp192Init();
|
bool found = axpChipInit();
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
found = analogInit();
|
found = analogInit();
|
||||||
@@ -210,11 +233,15 @@ bool Power::setup()
|
|||||||
|
|
||||||
void Power::shutdown()
|
void Power::shutdown()
|
||||||
{
|
{
|
||||||
#ifdef TBEAM_V10
|
|
||||||
|
|
||||||
|
#ifdef HAS_PMU
|
||||||
DEBUG_MSG("Shutting down\n");
|
DEBUG_MSG("Shutting down\n");
|
||||||
axp.setChgLEDMode(AXP20X_LED_OFF);
|
if(PMU){
|
||||||
axp.shutdown();
|
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
|
||||||
#elif NRF52_SERIES
|
PMU->shutdown();
|
||||||
|
}
|
||||||
|
#elif defined(ARCH_NRF52)
|
||||||
playBeep();
|
playBeep();
|
||||||
ledOff(PIN_LED1);
|
ledOff(PIN_LED1);
|
||||||
ledOff(PIN_LED2);
|
ledOff(PIN_LED2);
|
||||||
@@ -234,8 +261,8 @@ void Power::readPowerStatus()
|
|||||||
if (hasBattery) {
|
if (hasBattery) {
|
||||||
batteryVoltageMv = batteryLevel->getBattVoltage();
|
batteryVoltageMv = batteryLevel->getBattVoltage();
|
||||||
// If the AXP192 returns a valid battery percentage, use it
|
// If the AXP192 returns a valid battery percentage, use it
|
||||||
if (batteryLevel->getBattPercentage() >= 0) {
|
if (batteryLevel->getBatteryPercent() >= 0) {
|
||||||
batteryChargePercent = batteryLevel->getBattPercentage();
|
batteryChargePercent = batteryLevel->getBatteryPercent();
|
||||||
} else {
|
} else {
|
||||||
// If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error
|
// If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error
|
||||||
// In that case, we compute an estimate of the charge percent based on maximum and minimum voltages defined in
|
// In that case, we compute an estimate of the charge percent based on maximum and minimum voltages defined in
|
||||||
@@ -248,15 +275,15 @@ void Power::readPowerStatus()
|
|||||||
|
|
||||||
// Notify any status instances that are observing us
|
// Notify any status instances that are observing us
|
||||||
const PowerStatus powerStatus2 =
|
const PowerStatus powerStatus2 =
|
||||||
PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVBUSPlug() ? OptTrue : OptFalse,
|
PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() ? OptTrue : OptFalse,
|
||||||
batteryLevel->isChargeing() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
|
batteryLevel->isCharging() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
|
||||||
DEBUG_MSG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(),
|
DEBUG_MSG("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);
|
||||||
|
|
||||||
// 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
|
||||||
#ifdef NRF52_SERIES
|
#ifdef ARCH_NRF52
|
||||||
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++;
|
||||||
@@ -282,41 +309,46 @@ int32_t Power::runOnce()
|
|||||||
{
|
{
|
||||||
readPowerStatus();
|
readPowerStatus();
|
||||||
|
|
||||||
#ifdef TBEAM_V10
|
#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
|
||||||
axp.readIRQ();
|
if(PMU){
|
||||||
|
|
||||||
if (axp.isVbusRemoveIRQ()) {
|
PMU->getIrqStatus();
|
||||||
DEBUG_MSG("USB unplugged\n");
|
|
||||||
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
|
||||||
}
|
|
||||||
if (axp.isVbusPlugInIRQ()) {
|
|
||||||
DEBUG_MSG("USB plugged In\n");
|
|
||||||
powerFSM.trigger(EVENT_POWER_CONNECTED);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Other things we could check if we cared...
|
|
||||||
|
|
||||||
if (axp.isChargingIRQ()) {
|
if(PMU->isVbusRemoveIrq()){
|
||||||
DEBUG_MSG("Battery start charging\n");
|
DEBUG_MSG("USB unplugged\n");
|
||||||
|
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PMU->isVbusInsertIrq()) {
|
||||||
|
DEBUG_MSG("USB plugged In\n");
|
||||||
|
powerFSM.trigger(EVENT_POWER_CONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Other things we could check if we cared...
|
||||||
|
|
||||||
|
if (PMU->isBatChagerStartIrq()) {
|
||||||
|
DEBUG_MSG("Battery start charging\n");
|
||||||
|
}
|
||||||
|
if (PMU->isBatChagerDoneIrq()) {
|
||||||
|
DEBUG_MSG("Battery fully charged\n");
|
||||||
|
}
|
||||||
|
if (PMU->isBatInsertIrq()) {
|
||||||
|
DEBUG_MSG("Battery inserted\n");
|
||||||
|
}
|
||||||
|
if (PMU->isBatRemoveIrq()) {
|
||||||
|
DEBUG_MSG("Battery removed\n");
|
||||||
|
}
|
||||||
|
if (PMU->isPekeyShortPressIrq()) {
|
||||||
|
DEBUG_MSG("PEK short button press\n");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
PMU->clearIrqStatus();
|
||||||
}
|
}
|
||||||
if (axp.isChargingDoneIRQ()) {
|
|
||||||
DEBUG_MSG("Battery fully charged\n");
|
|
||||||
}
|
|
||||||
if (axp.isBattPlugInIRQ()) {
|
|
||||||
DEBUG_MSG("Battery inserted\n");
|
|
||||||
}
|
|
||||||
if (axp.isBattRemoveIRQ()) {
|
|
||||||
DEBUG_MSG("Battery removed\n");
|
|
||||||
}
|
|
||||||
if (axp.isPEKShortPressIRQ()) {
|
|
||||||
DEBUG_MSG("PEK short button press\n");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
axp.clearIRQ();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Only read once every 20 seconds once the power status for the app has been initialized
|
// Only read once every 20 seconds once the power status for the app has been initialized
|
||||||
return (statusHandler && statusHandler->isInitialized()) ? (1000 * 20) : RUN_SAME;
|
return (statusHandler && statusHandler->isInitialized()) ? (1000 * 20) : RUN_SAME;
|
||||||
}
|
}
|
||||||
@@ -329,128 +361,239 @@ int32_t Power::runOnce()
|
|||||||
share the same i2c bus, instead use ssd1306 sleep mode DCDC2 -> unused DCDC3 0.7-3.5V @ 700mA max -> ESP32 (keep this on!) LDO1
|
share the same i2c bus, instead use ssd1306 sleep mode DCDC2 -> unused DCDC3 0.7-3.5V @ 700mA max -> ESP32 (keep this on!) LDO1
|
||||||
30mA -> charges GPS backup battery // charges the tiny J13 battery by the GPS to power the GPS ram (for a couple of days), can
|
30mA -> charges GPS backup battery // charges the tiny J13 battery by the GPS to power the GPS ram (for a couple of days), can
|
||||||
not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS
|
not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
bool Power::axp192Init()
|
bool Power::axpChipInit()
|
||||||
{
|
{
|
||||||
#ifdef TBEAM_V10
|
|
||||||
if (axp192_found) {
|
|
||||||
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
|
|
||||||
batteryLevel = &axp;
|
|
||||||
|
|
||||||
DEBUG_MSG("AXP192 Begin PASS\n");
|
#ifdef HAS_PMU
|
||||||
|
|
||||||
// axp.setChgLEDMode(LED_BLINK_4HZ);
|
TwoWire * w = NULL;
|
||||||
DEBUG_MSG("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("----------------------------------------\n");
|
|
||||||
|
|
||||||
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // LORA radio
|
// Use macro to distinguish which wire is used by PMU
|
||||||
// axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // GPS main power - now turned on in setGpsPower
|
#ifdef PMU_USE_WIRE1
|
||||||
axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON);
|
w = &Wire1;
|
||||||
axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON);
|
#else
|
||||||
axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON);
|
w = &Wire;
|
||||||
axp.setDCDC1Voltage(3300); // for the OLED power
|
|
||||||
|
|
||||||
DEBUG_MSG("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
|
|
||||||
DEBUG_MSG("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
|
|
||||||
|
|
||||||
switch (config.power.charge_current) {
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MAUnset:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_450MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA100:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_100MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA190:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_190MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA280:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_280MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA360:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_360MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA450:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_450MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA550:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_550MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA630:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_630MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA700:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_700MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA780:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_780MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA880:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_880MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA960:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_960MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA1000:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1000MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA1080:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1080MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA1160:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1160MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA1240:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1240MA);
|
|
||||||
break;
|
|
||||||
case Config_PowerConfig_ChargeCurrent_MA1320:
|
|
||||||
axp.setChargeControlCur(AXP1XX_CHARGE_CUR_1320MA);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
// Not connected
|
|
||||||
//val = 0xfc;
|
|
||||||
//axp._writeByte(AXP202_VHTF_CHGSET, 1, &val); // Set temperature protection
|
|
||||||
|
|
||||||
//not used
|
|
||||||
//val = 0x46;
|
|
||||||
//axp._writeByte(AXP202_OFF_CTL, 1, &val); // enable bat detection
|
|
||||||
#endif
|
#endif
|
||||||
axp.debugCharging();
|
|
||||||
|
|
||||||
#ifdef PMU_IRQ
|
/**
|
||||||
pinMode(PMU_IRQ, INPUT);
|
* It is not necessary to specify the wire pin,
|
||||||
attachInterrupt(
|
* just input the wire, because the wire has been initialized in main.cpp
|
||||||
PMU_IRQ, [] { pmu_irq = true; }, FALLING);
|
*/
|
||||||
|
if (!PMU) {
|
||||||
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
|
PMU = new XPowersAXP2101(*w);
|
||||||
// we do not look for AXP202_CHARGING_FINISHED_IRQ & AXP202_CHARGING_IRQ because it occurs repeatedly while there is
|
if (!PMU->init()) {
|
||||||
// no battery also it could cause inadvertent waking from light sleep just because the battery filled
|
DEBUG_MSG("Warning: Failed to find AXP2101 power management\n");
|
||||||
// we don't look for AXP202_BATT_REMOVED_IRQ because it occurs repeatedly while no battery installed
|
delete PMU;
|
||||||
// we don't look at AXP202_VBUS_REMOVED_IRQ because we don't have anything hooked to vbus
|
PMU = NULL;
|
||||||
axp.enableIRQ(AXP202_BATT_CONNECT_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_PEK_SHORTPRESS_IRQ, 1);
|
|
||||||
|
|
||||||
axp.clearIRQ();
|
|
||||||
#endif
|
|
||||||
readPowerStatus();
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("AXP192 Begin FAIL\n");
|
DEBUG_MSG("AXP2101 PMU init succeeded, using AXP2101 PMU\n");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
DEBUG_MSG("AXP192 not found\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return axp192_found;
|
if (!PMU) {
|
||||||
|
PMU = new XPowersAXP192(*w);
|
||||||
|
if (!PMU->init()) {
|
||||||
|
DEBUG_MSG("Warning: Failed to find AXP192 power management\n");
|
||||||
|
delete PMU;
|
||||||
|
PMU = NULL;
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG("AXP192 PMU init succeeded, using AXP192 PMU\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PMU) {
|
||||||
|
/*
|
||||||
|
* In XPowersLib, if the XPowersAXPxxx object is released, Wire.end() will be called at the same time.
|
||||||
|
* In order not to affect other devices, if the initialization of the PMU fails, Wire needs to be re-initialized once,
|
||||||
|
* if there are multiple devices sharing the bus.
|
||||||
|
* * */
|
||||||
|
#ifndef PMU_USE_WIRE1
|
||||||
|
w->begin(I2C_SDA, I2C_SCL);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
batteryLevel = PMU;
|
||||||
|
|
||||||
|
if (PMU->getChipModel() == XPOWERS_AXP192) {
|
||||||
|
|
||||||
|
// lora radio power channel
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300);
|
||||||
|
PMU->enablePowerOutput(XPOWERS_LDO2);
|
||||||
|
|
||||||
|
|
||||||
|
// oled module power channel,
|
||||||
|
// disable it will cause abnormal communication between boot and AXP power supply,
|
||||||
|
// do not turn it off
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
|
||||||
|
// enable oled power
|
||||||
|
PMU->enablePowerOutput(XPOWERS_DCDC1);
|
||||||
|
|
||||||
|
|
||||||
|
// gnss module power channel - now turned on in setGpsPower
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300);
|
||||||
|
// PMU->enablePowerOutput(XPOWERS_LDO3);
|
||||||
|
|
||||||
|
|
||||||
|
//protected oled power source
|
||||||
|
PMU->setProtectedChannel(XPOWERS_DCDC1);
|
||||||
|
//protected esp32 power source
|
||||||
|
PMU->setProtectedChannel(XPOWERS_DCDC3);
|
||||||
|
|
||||||
|
//disable not use channel
|
||||||
|
PMU->disablePowerOutput(XPOWERS_DCDC2);
|
||||||
|
|
||||||
|
//disable all axp chip interrupt
|
||||||
|
PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ);
|
||||||
|
|
||||||
|
// Set constant current charging current
|
||||||
|
PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_450MA);
|
||||||
|
|
||||||
|
|
||||||
|
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
|
||||||
|
|
||||||
|
// t-beam s3 core
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gnss module power channel
|
||||||
|
* The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during initialization
|
||||||
|
*/
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
|
||||||
|
PMU->enablePowerOutput(XPOWERS_ALDO4);
|
||||||
|
|
||||||
|
// lora radio power channel
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
|
||||||
|
PMU->enablePowerOutput(XPOWERS_ALDO3);
|
||||||
|
|
||||||
|
// m.2 interface
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
|
||||||
|
PMU->enablePowerOutput(XPOWERS_DCDC3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ALDO2 cannot be turned off.
|
||||||
|
* It is a necessary condition for sensor communication.
|
||||||
|
* It must be turned on to properly access the sensor and screen
|
||||||
|
* It is also responsible for the power supply of PCF8563
|
||||||
|
*/
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
|
||||||
|
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
||||||
|
|
||||||
|
// 6-axis , magnetometer ,bme280 , oled screen power channel
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
|
||||||
|
PMU->enablePowerOutput(XPOWERS_ALDO1);
|
||||||
|
|
||||||
|
// sdcard power channle
|
||||||
|
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
|
||||||
|
PMU->enablePowerOutput(XPOWERS_BLDO1);
|
||||||
|
|
||||||
|
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
|
||||||
|
// PMU->enablePowerOutput(XPOWERS_DCDC4);
|
||||||
|
|
||||||
|
//not use channel
|
||||||
|
PMU->disablePowerOutput(XPOWERS_DCDC2); //not elicited
|
||||||
|
PMU->disablePowerOutput(XPOWERS_DCDC5); //not elicited
|
||||||
|
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_VBACKUP);
|
||||||
|
|
||||||
|
//disable all axp chip interrupt
|
||||||
|
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
|
||||||
|
|
||||||
|
//Set the constant current charging current of AXP2101, temporarily use 500mA by default
|
||||||
|
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PMU->clearIrqStatus();
|
||||||
|
|
||||||
|
// TBeam1.1 /T-Beam S3-Core has no external TS detection,
|
||||||
|
// it needs to be disabled, otherwise it will cause abnormal charging
|
||||||
|
PMU->disableTSPinMeasure();
|
||||||
|
|
||||||
|
// PMU->enableSystemVoltageMeasure();
|
||||||
|
PMU->enableVbusVoltageMeasure();
|
||||||
|
PMU->enableBattVoltageMeasure();
|
||||||
|
|
||||||
|
DEBUG_MSG("=======================================================================\n");
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_DCDC1)) {
|
||||||
|
DEBUG_MSG("DC1 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC1));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_DCDC2)) {
|
||||||
|
DEBUG_MSG("DC2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC2));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_DCDC3)) {
|
||||||
|
DEBUG_MSG("DC3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC3));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_DCDC4)) {
|
||||||
|
DEBUG_MSG("DC4 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC4));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_LDO2)) {
|
||||||
|
DEBUG_MSG("LDO2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO2));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_LDO3)) {
|
||||||
|
DEBUG_MSG("LDO3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO3));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_ALDO1)) {
|
||||||
|
DEBUG_MSG("ALDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO1));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_ALDO2)) {
|
||||||
|
DEBUG_MSG("ALDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO2));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_ALDO3)) {
|
||||||
|
DEBUG_MSG("ALDO3: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO3));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_ALDO4)) {
|
||||||
|
DEBUG_MSG("ALDO4: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO4));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_BLDO1)) {
|
||||||
|
DEBUG_MSG("BLDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO1));
|
||||||
|
}
|
||||||
|
if (PMU->isChannelAvailable(XPOWERS_BLDO2)) {
|
||||||
|
DEBUG_MSG("BLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO2));
|
||||||
|
}
|
||||||
|
DEBUG_MSG("=======================================================================\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);
|
||||||
|
|
||||||
|
// Set PMU shutdown voltage at 2.6V to maximize battery utilization
|
||||||
|
PMU->setSysPowerDownVoltage(2600);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PMU_IRQ
|
||||||
|
uint64_t pmuIrqMask = 0;
|
||||||
|
|
||||||
|
if (PMU->getChipModel() == XPOWERS_AXP192) {
|
||||||
|
pmuIrqMask = XPOWERS_AXP192_VBUS_INSERT_IRQ | XPOWERS_AXP192_BAT_INSERT_IRQ | XPOWERS_AXP192_PKEY_SHORT_IRQ;
|
||||||
|
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
|
||||||
|
pmuIrqMask = XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_PKEY_SHORT_IRQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinMode(PMU_IRQ, INPUT);
|
||||||
|
attachInterrupt(
|
||||||
|
PMU_IRQ, [] { pmu_irq = true; }, FALLING);
|
||||||
|
|
||||||
|
// we do not look for AXPXXX_CHARGING_FINISHED_IRQ & AXPXXX_CHARGING_IRQ because it occurs repeatedly while there is
|
||||||
|
// no battery also it could cause inadvertent waking from light sleep just because the battery filled
|
||||||
|
// we don't look for AXPXXX_BATT_REMOVED_IRQ because it occurs repeatedly while no battery installed
|
||||||
|
// we don't look at AXPXXX_VBUS_REMOVED_IRQ because we don't have anything hooked to vbus
|
||||||
|
PMU->enableIRQ(pmuIrqMask);
|
||||||
|
|
||||||
|
PMU->clearIrqStatus();
|
||||||
|
#endif /*PMU_IRQ*/
|
||||||
|
|
||||||
|
readPowerStatus();
|
||||||
|
|
||||||
|
pmu_found = true;
|
||||||
|
|
||||||
|
return pmu_found;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,11 +12,11 @@
|
|||||||
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(AXP192_SLAVE_ADDRESS)
|
#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 == 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
|
||||||
@@ -34,7 +34,7 @@ static void sdsEnter()
|
|||||||
{
|
{
|
||||||
DEBUG_MSG("Enter state: SDS\n");
|
DEBUG_MSG("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 ? config.power.sds_secs : default_sds_secs * 1000LL);
|
doDeepSleep(config.power.sds_secs * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern Power *power;
|
extern Power *power;
|
||||||
@@ -51,8 +51,7 @@ static uint32_t secsSlept;
|
|||||||
|
|
||||||
static void lsEnter()
|
static void lsEnter()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("lsEnter begin, ls_secs=%u\n",
|
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", config.power.ls_secs);
|
||||||
config.power.ls_secs ? config.power.ls_secs : default_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
|
||||||
|
|
||||||
@@ -63,10 +62,10 @@ static void lsIdle()
|
|||||||
{
|
{
|
||||||
// DEBUG_MSG("lsIdle begin ls_secs=%u\n", getPref_ls_secs());
|
// DEBUG_MSG("lsIdle begin ls_secs=%u\n", getPref_ls_secs());
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
|
|
||||||
// Do we have more sleeping to do?
|
// Do we have more sleeping to do?
|
||||||
if (secsSlept < config.power.ls_secs ? config.power.ls_secs : default_ls_secs * 1000) {
|
if (secsSlept < config.power.ls_secs) {
|
||||||
// Briefly come out of sleep long enough to blink the led once every few seconds
|
// Briefly come out of sleep long enough to blink the led once every few seconds
|
||||||
uint32_t sleepTime = 30;
|
uint32_t sleepTime = 30;
|
||||||
|
|
||||||
@@ -200,8 +199,7 @@ static void onEnter()
|
|||||||
|
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
|
|
||||||
if (now - lastPingMs >
|
if ((now - lastPingMs) > 30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state
|
||||||
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;
|
||||||
@@ -239,10 +237,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 == Config_DeviceConfig_Role_ROUTER ? 1 : 0);
|
||||||
bool hasPower = isPowered();
|
bool hasPower = isPowered();
|
||||||
|
|
||||||
DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower);
|
DEBUG_MSG("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
|
||||||
@@ -251,8 +249,7 @@ 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,
|
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, exiting light sleep");
|
||||||
"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
|
||||||
@@ -261,8 +258,7 @@ 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,
|
powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress, "Press"); // Allow button to work while in serial API
|
||||||
"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");
|
||||||
@@ -333,45 +329,26 @@ void PowerFSM_setup()
|
|||||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||||
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||||
|
|
||||||
powerFSM.add_timed_transition(&stateON, &stateDARK,
|
powerFSM.add_timed_transition(&stateON, &stateDARK, getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, "Screen-on timeout");
|
||||||
config.display.screen_on_secs ? config.display.screen_on_secs
|
|
||||||
: 60 * 1000 * 10,
|
|
||||||
NULL, "Screen-on timeout");
|
|
||||||
|
|
||||||
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
||||||
State *lowPowerState = &stateLS;
|
State *lowPowerState = &stateLS;
|
||||||
|
|
||||||
uint32_t meshSds = 0;
|
#ifdef ARCH_ESP32
|
||||||
|
|
||||||
#ifndef NRF52_SERIES
|
|
||||||
// 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/Meshtastic-device/issues/1071
|
// See: https://github.com/meshtastic/Meshtastic-device/issues/1071
|
||||||
if (isRouter || config.power.is_power_saving) {
|
if (isRouter || config.power.is_power_saving) {
|
||||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
powerFSM.add_timed_transition(&stateNB, &stateLS, getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, "Min wake timeout");
|
||||||
config.power.min_wake_secs ? config.power.min_wake_secs
|
powerFSM.add_timed_transition(&stateDARK, &stateLS, getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, "Bluetooth timeout");
|
||||||
: default_min_wake_secs * 1000,
|
}
|
||||||
NULL, "Min wake timeout");
|
|
||||||
powerFSM.add_timed_transition(&stateDARK, &stateLS,
|
|
||||||
config.power.wait_bluetooth_secs
|
|
||||||
? config.power.wait_bluetooth_secs
|
|
||||||
: default_wait_bluetooth_secs * 1000,
|
|
||||||
NULL, "Bluetooth timeout");
|
|
||||||
meshSds = config.power.mesh_sds_timeout_secs ? config.power.mesh_sds_timeout_secs
|
|
||||||
: default_mesh_sds_timeout_secs;
|
|
||||||
|
|
||||||
} else {
|
#elif defined (ARCH_NRF52)
|
||||||
|
|
||||||
meshSds = UINT32_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
lowPowerState = &stateDARK;
|
lowPowerState = &stateDARK;
|
||||||
meshSds = UINT32_MAX; // Workaround for now: Don't go into deep sleep on the RAK4631
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (meshSds != UINT32_MAX)
|
if (config.power.sds_secs != UINT32_MAX)
|
||||||
powerFSM.add_timed_transition(lowPowerState, &stateSDS, meshSds * 1000, NULL, "mesh timeout");
|
powerFSM.add_timed_transition(lowPowerState, &stateSDS, config.power.sds_secs * 1000, NULL, "mesh timeout");
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "RedirectablePrint.h"
|
#include "RedirectablePrint.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
// #include "wifi/WiFiServerAPI.h"
|
// #include "wifi/WiFiServerAPI.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -30,7 +31,9 @@ size_t RedirectablePrint::write(uint8_t c)
|
|||||||
// optionally send chars to TCP also
|
// optionally send chars to TCP also
|
||||||
//WiFiServerPort::debugOut(c);
|
//WiFiServerPort::debugOut(c);
|
||||||
|
|
||||||
dest->write(c);
|
if (!config.has_lora || config.device.serial_enabled)
|
||||||
|
dest->write(c);
|
||||||
|
|
||||||
return 1; // We always claim one was written, rather than trusting what the
|
return 1; // We always claim one was written, rather than trusting what the
|
||||||
// serial port said (which could be zero)
|
// serial port said (which could be zero)
|
||||||
}
|
}
|
||||||
@@ -38,20 +41,13 @@ size_t RedirectablePrint::write(uint8_t c)
|
|||||||
size_t RedirectablePrint::vprintf(const char *format, va_list arg)
|
size_t RedirectablePrint::vprintf(const char *format, va_list arg)
|
||||||
{
|
{
|
||||||
va_list copy;
|
va_list copy;
|
||||||
|
static char printBuf[160];
|
||||||
|
|
||||||
va_copy(copy, arg);
|
va_copy(copy, arg);
|
||||||
int len = vsnprintf(printBuf, printBufLen, format, copy);
|
int len = vsnprintf(printBuf, sizeof(printBuf), format, copy);
|
||||||
va_end(copy);
|
va_end(copy);
|
||||||
if (len < 0) {
|
|
||||||
va_end(arg);
|
if (len < 0) return 0;
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
if (len >= (int)printBufLen) {
|
|
||||||
delete[] printBuf;
|
|
||||||
printBufLen *= 2;
|
|
||||||
printBuf = new char[printBufLen];
|
|
||||||
len = vsnprintf(printBuf, printBufLen, format, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
len = Print::write(printBuf, len);
|
len = Print::write(printBuf, len);
|
||||||
return len;
|
return len;
|
||||||
|
|||||||
@@ -12,10 +12,6 @@ class RedirectablePrint : public Print
|
|||||||
{
|
{
|
||||||
Print *dest;
|
Print *dest;
|
||||||
|
|
||||||
/// We dynamically grow this scratch buffer if necessary
|
|
||||||
char *printBuf = new char[64];
|
|
||||||
size_t printBufLen = 64;
|
|
||||||
|
|
||||||
/// Used to allow multiple logDebug messages to appear on a single log line
|
/// Used to allow multiple logDebug messages to appear on a single log line
|
||||||
bool isContinuationMessage = false;
|
bool isContinuationMessage = false;
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ 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();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
||||||
@@ -30,7 +33,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 NRF52_SERIES
|
#ifdef ARCH_NRF52
|
||||||
time_t timeout = millis();
|
time_t timeout = millis();
|
||||||
while (!Port) {
|
while (!Port) {
|
||||||
if ((millis() - timeout) < 5000) {
|
if ((millis() - timeout) < 5000) {
|
||||||
@@ -57,10 +60,15 @@ bool SerialConsole::checkIsConnected()
|
|||||||
*/
|
*/
|
||||||
bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
|
bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
|
||||||
{
|
{
|
||||||
// Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets
|
// only talk to the API once the configuration has been loaded and we're sure the serial port is not disabled.
|
||||||
if (!config.device.debug_log_enabled)
|
if (config.has_lora && config.device.serial_enabled) {
|
||||||
setDestination(&noopPrint);
|
// Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets
|
||||||
canWrite = true;
|
if (!config.device.debug_log_enabled)
|
||||||
|
setDestination(&noopPrint);
|
||||||
|
canWrite = true;
|
||||||
|
|
||||||
return StreamAPI::handleToRadio(buf, len);
|
return StreamAPI::handleToRadio(buf, len);
|
||||||
}
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,6 +36,7 @@ struct ToneDuration {
|
|||||||
#define NOTE_A3 220
|
#define NOTE_A3 220
|
||||||
#define NOTE_AS3 233
|
#define NOTE_AS3 233
|
||||||
#define NOTE_B3 247
|
#define NOTE_B3 247
|
||||||
|
#define NOTE_CS4 277
|
||||||
|
|
||||||
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
|
||||||
@@ -65,16 +66,17 @@ void playBeep() { tone(PIN_BUZZER, NOTE_B3, DURATION_1_4); }
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void playStartMelody() {
|
void playStartMelody() {
|
||||||
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4},
|
ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8},
|
||||||
{NOTE_B3, DURATION_1_8},
|
{NOTE_AS3, DURATION_1_8},
|
||||||
{NOTE_B3, DURATION_1_8}};
|
{NOTE_CS4, DURATION_1_4}};
|
||||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void playShutdownMelody() {
|
void playShutdownMelody() {
|
||||||
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4},
|
ToneDuration melody[] = {{NOTE_CS4, DURATION_1_8},
|
||||||
{NOTE_G3, DURATION_1_8},
|
{NOTE_AS3, DURATION_1_8},
|
||||||
{NOTE_D3, DURATION_1_8}};
|
{NOTE_FS3, DURATION_1_4}};
|
||||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -14,4 +14,5 @@ enum class Cmd {
|
|||||||
STOP_BOOT_SCREEN,
|
STOP_BOOT_SCREEN,
|
||||||
PRINT,
|
PRINT,
|
||||||
START_SHUTDOWN_SCREEN,
|
START_SHUTDOWN_SCREEN,
|
||||||
|
START_REBOOT_SCREEN,
|
||||||
};
|
};
|
||||||
@@ -62,79 +62,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
/// Convert a preprocessor name into a quoted string and if that string is empty use "unset"
|
/// Convert a preprocessor name into a quoted string and if that string is empty use "unset"
|
||||||
#define optstr(s) (xstr(s)[0] ? xstr(s) : "unset")
|
#define optstr(s) (xstr(s)[0] ? xstr(s) : "unset")
|
||||||
|
|
||||||
#ifdef PORTDUINO
|
// Nop definition for these attributes that are specific to ESP32
|
||||||
|
#ifndef EXT_RAM_ATTR
|
||||||
#define NO_ESP32 // Don't use ESP32 libs (mainly bluetooth)
|
#define EXT_RAM_ATTR
|
||||||
|
|
||||||
#elif defined(NRF52_SERIES) // All of the NRF52 targets are configured using variant.h, so this section shouldn't need to be
|
|
||||||
// board specific
|
|
||||||
|
|
||||||
//
|
|
||||||
// Standard definitions for NRF52 targets
|
|
||||||
//
|
|
||||||
|
|
||||||
#define NO_ESP32 // Don't use ESP32 libs (mainly bluetooth)
|
|
||||||
|
|
||||||
// We bind to the GPS using variant.h instead for this platform (Serial1)
|
|
||||||
|
|
||||||
#define LED_PIN PIN_LED1 // LED1 on nrf52840-DK
|
|
||||||
|
|
||||||
// If the variant filed defines as standard button
|
|
||||||
#ifdef PIN_BUTTON1
|
|
||||||
#define BUTTON_PIN PIN_BUTTON1
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef IRAM_ATTR
|
||||||
#ifdef PIN_BUTTON2
|
#define IRAM_ATTR
|
||||||
#define BUTTON_PIN_ALT PIN_BUTTON2
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef RTC_DATA_ATTR
|
||||||
#ifdef PIN_BUTTON_TOUCH
|
#define RTC_DATA_ATTR
|
||||||
#define BUTTON_PIN_TOUCH PIN_BUTTON_TOUCH
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
//
|
|
||||||
// Standard definitions for ESP32 targets
|
|
||||||
//
|
|
||||||
|
|
||||||
#define HAS_WIFI
|
|
||||||
|
|
||||||
#define GPS_SERIAL_NUM 1
|
|
||||||
#define GPS_RX_PIN 34
|
|
||||||
#ifdef USE_JTAG
|
|
||||||
#define GPS_TX_PIN -1
|
|
||||||
#else
|
|
||||||
#define GPS_TX_PIN 12
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// LoRa SPI
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// NRF52 boards will define this in variant.h
|
|
||||||
#ifndef RF95_SCK
|
|
||||||
#define RF95_SCK 5
|
|
||||||
#define RF95_MISO 19
|
|
||||||
#define RF95_MOSI 27
|
|
||||||
#define RF95_NSS 18
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TTGO_T_ECHO
|
|
||||||
#define GPS_UBLOX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Standard definitions for !ESP32 targets
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifdef NO_ESP32
|
|
||||||
// Nop definition for these attributes - not used on NRF52
|
|
||||||
#define EXT_RAM_ATTR
|
|
||||||
#define IRAM_ATTR
|
|
||||||
#define RTC_DATA_ATTR
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -145,7 +81,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
// #define DISABLE_NTP
|
// #define DISABLE_NTP
|
||||||
|
|
||||||
// Disable the welcome screen and allow
|
// Disable the welcome screen and allow
|
||||||
#define DISABLE_WELCOME_UNSET
|
//#define DISABLE_WELCOME_UNSET
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// OLED & Input
|
// OLED & Input
|
||||||
@@ -158,19 +94,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
// Define this if you know you have that controller or your "SSD1306" misbehaves.
|
// Define this if you know you have that controller or your "SSD1306" misbehaves.
|
||||||
//#define USE_SH1106
|
//#define USE_SH1106
|
||||||
|
|
||||||
// Flip the screen upside down by default as it makes more sense on T-BEAM
|
|
||||||
// devices. Comment this out to not rotate screen 180 degrees.
|
|
||||||
#define SCREEN_FLIP_VERTICALLY
|
|
||||||
|
|
||||||
// Define if screen should be mirrored left to right
|
// Define if screen should be mirrored left to right
|
||||||
// #define SCREEN_MIRROR
|
// #define SCREEN_MIRROR
|
||||||
|
|
||||||
// The m5stack I2C Keyboard (also RAK14004)
|
// The m5stack I2C Keyboard (also RAK14004)
|
||||||
#define CARDKB_ADDR 0x5F
|
#define CARDKB_ADDR 0x5F
|
||||||
|
|
||||||
// The older M5 Faces I2C Keyboard
|
|
||||||
#define FACESKB_ADDR 0x88
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// SENSOR
|
// SENSOR
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -179,6 +108,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define MCP9808_ADDR 0x18
|
#define MCP9808_ADDR 0x18
|
||||||
#define INA_ADDR 0x40
|
#define INA_ADDR 0x40
|
||||||
#define INA_ADDR_ALTERNATE 0x41
|
#define INA_ADDR_ALTERNATE 0x41
|
||||||
|
#define QMC6310_ADDR 0x1C
|
||||||
|
#define QMI8658_ADDR 0x6B
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Security
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define ATECC608B_ADDR 0x35
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// GPS
|
// GPS
|
||||||
@@ -190,109 +127,43 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define GPS_THREAD_INTERVAL 100
|
#define GPS_THREAD_INTERVAL 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(TBEAM_V10)
|
/* Step #1: offer chance for variant-specific defines */
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_TBEAM
|
|
||||||
|
|
||||||
#elif defined(TBEAM_V07)
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_TBEAM0p7
|
|
||||||
|
|
||||||
#elif defined(DIY_V1)
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_DIY_V1
|
|
||||||
|
|
||||||
#elif defined(RAK_11200)
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_RAK11200
|
|
||||||
|
|
||||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V2)
|
|
||||||
|
|
||||||
#ifdef HELTEC_V2_0
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_HELTEC_V2_0
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HELTEC_V2_1
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_HELTEC_V2_1
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_HELTEC_V1
|
|
||||||
|
|
||||||
#elif defined(TLORA_V1)
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_TLORA_V1
|
|
||||||
|
|
||||||
#elif defined(TLORA_V2)
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_TLORA_V2
|
|
||||||
|
|
||||||
#elif defined(TLORA_V1_3)
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_TLORA_V1_1p3
|
|
||||||
|
|
||||||
#elif defined(TLORA_V2_1_16)
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_TLORA_V2_1_1p6
|
|
||||||
|
|
||||||
#elif defined(GENIEBLOCKS)
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_GENIEBLOCKS
|
|
||||||
|
|
||||||
#elif defined(PRIVATE_HW)
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_PRIVATE_HW
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ARDUINO_NRF52840_PCA10056
|
|
||||||
|
|
||||||
// This string must exactly match the case used in release file names or the android updater won't work
|
|
||||||
#define HW_VENDOR HardwareModel_NRF52840DK
|
|
||||||
|
|
||||||
// This board uses 0 to be mean LED on
|
|
||||||
#undef LED_INVERTED
|
|
||||||
#define LED_INVERTED 1
|
|
||||||
|
|
||||||
#elif defined(ARDUINO_NRF52840_PPR)
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_PPR
|
|
||||||
|
|
||||||
#elif defined(RAK4630)
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_RAK4631
|
|
||||||
|
|
||||||
#elif defined(TTGO_T_ECHO)
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_T_ECHO
|
|
||||||
|
|
||||||
#elif defined(NANO_G1)
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_NANO_G1
|
|
||||||
|
|
||||||
#elif defined(NORDIC_PCA10059)
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_NRF52840_PCA10059
|
|
||||||
|
|
||||||
#elif defined(M5STACK)
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_M5STACK
|
|
||||||
|
|
||||||
#elif NRF52_SERIES
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_NRF52_UNKNOWN
|
|
||||||
|
|
||||||
#elif PORTDUINO
|
|
||||||
|
|
||||||
#define HW_VENDOR HardwareModel_PORTDUINO
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "variant.h"
|
#include "variant.h"
|
||||||
|
|
||||||
|
/* Step #2: follow with defines common to the architecture;
|
||||||
|
also enable HAS_ option not specifically disabled by variant.h */
|
||||||
|
#include "architecture.h"
|
||||||
|
|
||||||
|
/* Step #3: mop up with disabled values for HAS_ options not handled by the above two */
|
||||||
|
|
||||||
|
#ifndef HAS_WIFI
|
||||||
|
#define HAS_WIFI 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAS_SCREEN
|
||||||
|
#define HAS_SCREEN 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAS_WIRE
|
||||||
|
#define HAS_WIRE 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAS_GPS
|
||||||
|
#define HAS_GPS 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAS_BUTTON
|
||||||
|
#define HAS_BUTTON 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAS_TELEMETRY
|
||||||
|
#define HAS_TELEMETRY 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAS_RADIO
|
||||||
|
#define HAS_RADIO 0
|
||||||
|
#endif
|
||||||
|
#ifndef HAS_RTC
|
||||||
|
#define HAS_RTC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "RF95Configuration.h"
|
#include "RF95Configuration.h"
|
||||||
#include "DebugConfiguration.h"
|
#include "DebugConfiguration.h"
|
||||||
|
|
||||||
|
#ifndef HW_VENDOR
|
||||||
|
#error HW_VENDOR must be defined
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
// Placeholder FIXME
|
|
||||||
@@ -3,7 +3,47 @@
|
|||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include "mesh/generated/telemetry.pb.h"
|
#include "mesh/generated/telemetry.pb.h"
|
||||||
|
|
||||||
#ifndef NO_WIRE
|
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
||||||
|
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
|
||||||
|
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAS_WIRE
|
||||||
|
|
||||||
|
void printATECCInfo()
|
||||||
|
{
|
||||||
|
#ifndef ARCH_PORTDUINO
|
||||||
|
atecc.readConfigZone(false);
|
||||||
|
|
||||||
|
DEBUG_MSG("ATECC608B Serial Number: ");
|
||||||
|
for (int i = 0 ; i < 9 ; i++) {
|
||||||
|
DEBUG_MSG("%02x",atecc.serialNumber[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_MSG(", Rev Number: ");
|
||||||
|
for (int i = 0 ; i < 4 ; i++) {
|
||||||
|
DEBUG_MSG("%02x",atecc.revisionNumber[i]);
|
||||||
|
}
|
||||||
|
DEBUG_MSG("\n");
|
||||||
|
|
||||||
|
DEBUG_MSG("ATECC608B Config %s",atecc.configLockStatus ? "Locked" : "Unlocked");
|
||||||
|
DEBUG_MSG(", Data %s",atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
|
||||||
|
DEBUG_MSG(", Slot 0 %s\n",atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||||
|
|
||||||
|
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
|
||||||
|
if (atecc.generatePublicKey() == false) {
|
||||||
|
DEBUG_MSG("ATECC608B Error generating public key\n");
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG("ATECC608B Public Key: ");
|
||||||
|
for (int i = 0 ; i < 64 ; i++) {
|
||||||
|
DEBUG_MSG("%02x",atecc.publicKey64Bytes[i]);
|
||||||
|
}
|
||||||
|
DEBUG_MSG("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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);
|
||||||
@@ -41,7 +81,7 @@ 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 == 0x06 || r == 0x07) {
|
} else if ( r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
|
||||||
o_probe = 1; // SSD1306
|
o_probe = 1; // SSD1306
|
||||||
}
|
}
|
||||||
c++;
|
c++;
|
||||||
@@ -74,6 +114,17 @@ void scanI2Cdevice(void)
|
|||||||
DEBUG_MSG("unknown display found\n");
|
DEBUG_MSG("unknown display found\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifndef ARCH_PORTDUINO
|
||||||
|
if (addr == ATECC608B_ADDR){
|
||||||
|
keystore_found = addr;
|
||||||
|
if (atecc.begin(keystore_found) == true) {
|
||||||
|
DEBUG_MSG("ATECC608B initialized\n");
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG("ATECC608B initialization failed\n");
|
||||||
|
}
|
||||||
|
printATECCInfo();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef RV3028_RTC
|
#ifdef RV3028_RTC
|
||||||
if (addr == RV3028_RTC){
|
if (addr == RV3028_RTC){
|
||||||
rtc_found = addr;
|
rtc_found = addr;
|
||||||
@@ -102,18 +153,14 @@ void scanI2Cdevice(void)
|
|||||||
kb_model = 0x00;
|
kb_model = 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (addr == FACESKB_ADDR) {
|
|
||||||
faceskb_found = addr;
|
|
||||||
DEBUG_MSG("m5 Faces found\n");
|
|
||||||
}
|
|
||||||
if (addr == ST7567_ADDRESS) {
|
if (addr == ST7567_ADDRESS) {
|
||||||
screen_found = addr;
|
screen_found = addr;
|
||||||
DEBUG_MSG("st7567 display found\n");
|
DEBUG_MSG("st7567 display found\n");
|
||||||
}
|
}
|
||||||
#ifdef AXP192_SLAVE_ADDRESS
|
#ifdef HAS_PMU
|
||||||
if (addr == AXP192_SLAVE_ADDRESS) {
|
if (addr == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
||||||
axp192_found = true;
|
pmu_found = true;
|
||||||
DEBUG_MSG("axp192 PMU found\n");
|
DEBUG_MSG("axp192/axp2101 PMU found\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
|
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
|
||||||
@@ -124,6 +171,9 @@ void scanI2Cdevice(void)
|
|||||||
} else if (registerValue == 0x60) {
|
} else if (registerValue == 0x60) {
|
||||||
DEBUG_MSG("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
DEBUG_MSG("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||||
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = addr;
|
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = addr;
|
||||||
|
} else {
|
||||||
|
DEBUG_MSG("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||||
|
nodeTelemetrySensorsMap[TelemetrySensorType_BMP280] = addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
|
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
|
||||||
@@ -141,6 +191,14 @@ void scanI2Cdevice(void)
|
|||||||
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
|
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
|
||||||
DEBUG_MSG("MCP9808 sensor found at address 0x%x\n", (uint8_t)addr);
|
DEBUG_MSG("MCP9808 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||||
}
|
}
|
||||||
|
if(addr == QMC6310_ADDR){
|
||||||
|
DEBUG_MSG("QMC6310 3-Axis magnetic sensor found at address 0x%x\n", (uint8_t)addr);
|
||||||
|
nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr;
|
||||||
|
}
|
||||||
|
if(addr == QMI8658_ADDR){
|
||||||
|
DEBUG_MSG("QMI8658 6-Axis inertial measurement sensor found at address 0x%x\n", (uint8_t)addr);
|
||||||
|
nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr;
|
||||||
|
}
|
||||||
} else if (err == 4) {
|
} else if (err == 4) {
|
||||||
DEBUG_MSG("Unknow error at address 0x%x\n", addr);
|
DEBUG_MSG("Unknow error at address 0x%x\n", addr);
|
||||||
}
|
}
|
||||||
@@ -8,4 +8,4 @@
|
|||||||
#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(CriticalErrorCode code = CriticalErrorCode_UNSPECIFIED, uint32_t address = 0, const char *filename = NULL);
|
||||||
|
|||||||
@@ -1,160 +0,0 @@
|
|||||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
#include "../concurrency/LockGuard.h"
|
|
||||||
#include "../graphics/Screen.h"
|
|
||||||
#include "../main.h"
|
|
||||||
#include "BluetoothSoftwareUpdate.h"
|
|
||||||
#include "NodeDB.h"
|
|
||||||
#include "PowerFSM.h"
|
|
||||||
#include "RadioLibInterface.h"
|
|
||||||
#include "configuration.h"
|
|
||||||
#include "nimble/BluetoothUtil.h"
|
|
||||||
|
|
||||||
#include <CRC32.h>
|
|
||||||
#include <Update.h>
|
|
||||||
|
|
||||||
int16_t updateResultHandle = -1;
|
|
||||||
|
|
||||||
static CRC32 crc;
|
|
||||||
|
|
||||||
static uint32_t updateExpectedSize, updateActualSize;
|
|
||||||
static uint8_t update_result;
|
|
||||||
static uint8_t update_region;
|
|
||||||
|
|
||||||
static concurrency::Lock *updateLock;
|
|
||||||
|
|
||||||
/// Handle writes & reads to total size
|
|
||||||
int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
|
||||||
{
|
|
||||||
concurrency::LockGuard g(updateLock);
|
|
||||||
|
|
||||||
// Check if there is enough to OTA Update
|
|
||||||
chr_readwrite32le(&updateExpectedSize, ctxt);
|
|
||||||
|
|
||||||
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR && updateExpectedSize != 0) {
|
|
||||||
updateActualSize = 0;
|
|
||||||
crc.reset();
|
|
||||||
if (Update.isRunning())
|
|
||||||
Update.abort();
|
|
||||||
bool canBegin = Update.begin(updateExpectedSize, update_region);
|
|
||||||
DEBUG_MSG("Setting region %d update size %u, result %d\n", update_region, updateExpectedSize, canBegin);
|
|
||||||
if (!canBegin) {
|
|
||||||
// Indicate failure by forcing the size to 0 (client will read it back)
|
|
||||||
updateExpectedSize = 0;
|
|
||||||
} else {
|
|
||||||
// This totally breaks abstraction to up up into the app layer for this, but quick hack to make sure we only
|
|
||||||
// talk to one service during the sw update.
|
|
||||||
// DEBUG_MSG("FIXME, crufty shutdown of mesh bluetooth for sw update.");
|
|
||||||
// void stopMeshBluetoothService();
|
|
||||||
// stopMeshBluetoothService();
|
|
||||||
|
|
||||||
screen->startFirmwareUpdateScreen();
|
|
||||||
if (RadioLibInterface::instance)
|
|
||||||
RadioLibInterface::instance->disable(); // FIXME, nasty hack - the RF95 ISR/SPI code on ESP32 can fail while we
|
|
||||||
// are writing flash - shut the radio off during updates
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_BLOCKSIZE_FOR_BT 512
|
|
||||||
|
|
||||||
/// Handle writes to data
|
|
||||||
int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
|
||||||
{
|
|
||||||
concurrency::LockGuard g(updateLock);
|
|
||||||
|
|
||||||
static uint8_t
|
|
||||||
data[MAX_BLOCKSIZE_FOR_BT]; // we temporarily copy here because I'm worried that a fast sender might be able overwrite srcbuf
|
|
||||||
|
|
||||||
uint16_t len = 0;
|
|
||||||
|
|
||||||
auto rc = ble_hs_mbuf_to_flat(ctxt->om, data, sizeof(data), &len);
|
|
||||||
assert(rc == 0);
|
|
||||||
|
|
||||||
// DEBUG_MSG("Writing %u\n", len);
|
|
||||||
crc.update(data, len);
|
|
||||||
Update.write(data, len);
|
|
||||||
updateActualSize += len;
|
|
||||||
powerFSM.trigger(EVENT_FIRMWARE_UPDATE);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handle writes to crc32
|
|
||||||
int update_crc32_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
|
||||||
{
|
|
||||||
concurrency::LockGuard g(updateLock);
|
|
||||||
uint32_t expectedCRC = 0;
|
|
||||||
chr_readwrite32le(&expectedCRC, ctxt);
|
|
||||||
|
|
||||||
uint32_t actualCRC = crc.finalize();
|
|
||||||
DEBUG_MSG("expected CRC %u\n", expectedCRC);
|
|
||||||
|
|
||||||
uint8_t result = 0xff;
|
|
||||||
|
|
||||||
if (updateActualSize != updateExpectedSize) {
|
|
||||||
DEBUG_MSG("Expected %u bytes, but received %u bytes!\n", updateExpectedSize, updateActualSize);
|
|
||||||
result = 0xe1; // FIXME, use real error codes
|
|
||||||
} else if (actualCRC != expectedCRC) // Check the CRC before asking the update to happen.
|
|
||||||
{
|
|
||||||
DEBUG_MSG("Invalid CRC! expected=%u, actual=%u\n", expectedCRC, actualCRC);
|
|
||||||
result = 0xe0; // FIXME, use real error codes
|
|
||||||
} else {
|
|
||||||
if (Update.end()) {
|
|
||||||
if (update_region == U_SPIFFS) {
|
|
||||||
DEBUG_MSG("Filesystem updated!\n");
|
|
||||||
nodeDB.saveToDisk(); // Since we just wiped the filesystem, we need to save our current state
|
|
||||||
} else {
|
|
||||||
DEBUG_MSG("Appload updated, rebooting in 5 seconds!\n");
|
|
||||||
rebootAtMsec = millis() + 5000;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DEBUG_MSG("Error Occurred. Error #: %d\n", Update.getError());
|
|
||||||
}
|
|
||||||
result = Update.getError();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RadioLibInterface::instance)
|
|
||||||
RadioLibInterface::instance->startReceive(); // Resume radio
|
|
||||||
|
|
||||||
assert(updateResultHandle >= 0);
|
|
||||||
update_result = result;
|
|
||||||
DEBUG_MSG("BLE notify update result\n");
|
|
||||||
auto res = ble_gattc_notify(curConnectionHandle, updateResultHandle);
|
|
||||||
assert(res == 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int update_result_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
|
||||||
{
|
|
||||||
return chr_readwrite8(&update_result, sizeof(update_result), ctxt);
|
|
||||||
}
|
|
||||||
|
|
||||||
int update_region_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
|
||||||
{
|
|
||||||
return chr_readwrite8(&update_region, sizeof(update_region), ctxt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
See bluetooth-api.md
|
|
||||||
|
|
||||||
*/
|
|
||||||
void reinitUpdateService()
|
|
||||||
{
|
|
||||||
if (!updateLock)
|
|
||||||
updateLock = new concurrency::Lock();
|
|
||||||
|
|
||||||
auto res = ble_gatts_count_cfg(gatt_update_svcs); // assigns handles? see docstring for note about clearing the handle list
|
|
||||||
// before calling SLEEP SUPPORT
|
|
||||||
assert(res == 0);
|
|
||||||
|
|
||||||
res = ble_gatts_add_svcs(gatt_update_svcs);
|
|
||||||
assert(res == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "nimble/NimbleDefs.h"
|
|
||||||
|
|
||||||
void reinitUpdateService();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
|
||||||
int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
|
||||||
int update_result_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
|
||||||
int update_crc32_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
|
||||||
int update_region_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
|
||||||
|
|
||||||
extern const struct ble_gatt_svc_def gatt_update_svcs[];
|
|
||||||
|
|
||||||
extern const ble_uuid128_t update_result_uuid, update_region_uuid;
|
|
||||||
|
|
||||||
extern int16_t updateResultHandle;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
@@ -1,259 +0,0 @@
|
|||||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
|
|
||||||
#include "configuration.h"
|
|
||||||
#include "ESP32Bluetooth.h"
|
|
||||||
#include "BluetoothCommon.h"
|
|
||||||
#include "PowerFSM.h"
|
|
||||||
#include "sleep.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "mesh/PhoneAPI.h"
|
|
||||||
#include "mesh/mesh-pb-constants.h"
|
|
||||||
#include <NimBLEDevice.h>
|
|
||||||
|
|
||||||
//static BLEService meshBleService = BLEService(BLEUuid(MESH_SERVICE_UUID_16));
|
|
||||||
//static BLECharacteristic fromNum = BLECharacteristic(BLEUuid(FROMNUM_UUID_16));
|
|
||||||
//static BLECharacteristic fromRadio = BLECharacteristic(BLEUuid(FROMRADIO_UUID_16));
|
|
||||||
//static BLECharacteristic toRadio = BLECharacteristic(BLEUuid(TORADIO_UUID_16));
|
|
||||||
|
|
||||||
//static BLEDis bledis; // DIS (Device Information Service) helper class instance
|
|
||||||
//static BLEBas blebas; // BAS (Battery Service) helper class instance
|
|
||||||
//static BLEDfu bledfu; // DFU software update helper service
|
|
||||||
|
|
||||||
// This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in
|
|
||||||
// proccess at once
|
|
||||||
// static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)];
|
|
||||||
static uint8_t fromRadioBytes[FromRadio_size];
|
|
||||||
|
|
||||||
NimBLECharacteristic *FromNumCharacteristic;
|
|
||||||
NimBLEServer *bleServer;
|
|
||||||
|
|
||||||
static bool passkeyShowing;
|
|
||||||
static uint32_t doublepressed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
|
||||||
*/
|
|
||||||
void BluetoothPhoneAPI::onNowHasData(uint32_t fromRadioNum)
|
|
||||||
{
|
|
||||||
PhoneAPI::onNowHasData(fromRadioNum);
|
|
||||||
|
|
||||||
DEBUG_MSG("BLE notify fromNum\n");
|
|
||||||
//fromNum.notify32(fromRadioNum);
|
|
||||||
|
|
||||||
uint8_t val[4];
|
|
||||||
put_le32(val, fromRadioNum);
|
|
||||||
|
|
||||||
std::string fromNumByteString(&val[0], &val[0] + sizeof(val));
|
|
||||||
|
|
||||||
FromNumCharacteristic->setValue(fromNumByteString);
|
|
||||||
FromNumCharacteristic->notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check the current underlying physical link to see if the client is currently connected
|
|
||||||
bool BluetoothPhoneAPI::checkIsConnected() {
|
|
||||||
if (bleServer && bleServer->getConnectedCount() > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhoneAPI *bluetoothPhoneAPI;
|
|
||||||
|
|
||||||
class ESP32BluetoothToRadioCallback : public NimBLECharacteristicCallbacks {
|
|
||||||
virtual void onWrite(NimBLECharacteristic *pCharacteristic) {
|
|
||||||
DEBUG_MSG("To Radio onwrite\n");
|
|
||||||
auto valueString = pCharacteristic->getValue();
|
|
||||||
|
|
||||||
bluetoothPhoneAPI->handleToRadio(reinterpret_cast<const uint8_t*>(&valueString[0]), pCharacteristic->getDataLength());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ESP32BluetoothFromRadioCallback : public NimBLECharacteristicCallbacks {
|
|
||||||
virtual void onRead(NimBLECharacteristic *pCharacteristic) {
|
|
||||||
DEBUG_MSG("From Radio onread\n");
|
|
||||||
size_t numBytes = bluetoothPhoneAPI->getFromRadio(fromRadioBytes);
|
|
||||||
|
|
||||||
std::string fromRadioByteString(fromRadioBytes, fromRadioBytes + numBytes);
|
|
||||||
|
|
||||||
pCharacteristic->setValue(fromRadioByteString);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ESP32BluetoothServerCallback : public NimBLEServerCallbacks {
|
|
||||||
virtual uint32_t onPassKeyRequest() {
|
|
||||||
|
|
||||||
uint32_t passkey = 0;
|
|
||||||
|
|
||||||
if (doublepressed > 0 && (doublepressed + (30 * 1000)) > millis()) {
|
|
||||||
DEBUG_MSG("User has overridden passkey\n");
|
|
||||||
passkey = defaultBLEPin;
|
|
||||||
} else {
|
|
||||||
DEBUG_MSG("Using random passkey\n");
|
|
||||||
passkey = random(
|
|
||||||
100000, 999999); // This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits
|
|
||||||
}
|
|
||||||
DEBUG_MSG("*** Enter passkey %d on the peer side ***\n", passkey);
|
|
||||||
|
|
||||||
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
|
|
||||||
screen->startBluetoothPinScreen(passkey);
|
|
||||||
passkeyShowing = true;
|
|
||||||
|
|
||||||
return passkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void onAuthenticationComplete(ble_gap_conn_desc *desc) {
|
|
||||||
DEBUG_MSG("BLE authentication complete\n");
|
|
||||||
|
|
||||||
if (passkeyShowing) {
|
|
||||||
passkeyShowing = false;
|
|
||||||
screen->stopBluetoothPinScreen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static ESP32BluetoothToRadioCallback *toRadioCallbacks;
|
|
||||||
static ESP32BluetoothFromRadioCallback *fromRadioCallbacks;
|
|
||||||
|
|
||||||
void ESP32Bluetooth::shutdown()
|
|
||||||
{
|
|
||||||
// Shutdown bluetooth for minimum power draw
|
|
||||||
DEBUG_MSG("Disable bluetooth\n");
|
|
||||||
//Bluefruit.Advertising.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP32Bluetooth::setup()
|
|
||||||
{
|
|
||||||
// Initialise the Bluefruit module
|
|
||||||
DEBUG_MSG("Initialise the ESP32 bluetooth module\n");
|
|
||||||
//Bluefruit.autoConnLed(false);
|
|
||||||
//Bluefruit.begin();
|
|
||||||
|
|
||||||
// Set the advertised device name (keep it short!)
|
|
||||||
//Bluefruit.setName(getDeviceName());
|
|
||||||
|
|
||||||
// Set the connect/disconnect callback handlers
|
|
||||||
//Bluefruit.Periph.setConnectCallback(connect_callback);
|
|
||||||
//Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
|
|
||||||
|
|
||||||
// Configure and Start the Device Information Service
|
|
||||||
DEBUG_MSG("Configuring the Device Information Service\n");
|
|
||||||
// FIXME, we should set a mfg string based on our HW_VENDOR enum
|
|
||||||
// bledis.setManufacturer(HW_VENDOR);
|
|
||||||
//bledis.setModel(optstr(HW_VERSION));
|
|
||||||
//bledis.setFirmwareRev(optstr(APP_VERSION));
|
|
||||||
//bledis.begin();
|
|
||||||
|
|
||||||
// Start the BLE Battery Service and set it to 100%
|
|
||||||
//DEBUG_MSG("Configuring the Battery Service\n");
|
|
||||||
//blebas.begin();
|
|
||||||
//blebas.write(0); // Unknown battery level for now
|
|
||||||
|
|
||||||
//bledfu.begin(); // Install the DFU helper
|
|
||||||
|
|
||||||
// Setup the Heart Rate Monitor service using
|
|
||||||
// BLEService and BLECharacteristic classes
|
|
||||||
DEBUG_MSG("Configuring the Mesh bluetooth service\n");
|
|
||||||
//setupMeshService();
|
|
||||||
|
|
||||||
// Supposedly debugging works with soft device if you disable advertising
|
|
||||||
//if (isSoftDeviceAllowed) {
|
|
||||||
// Setup the advertising packet(s)
|
|
||||||
// DEBUG_MSG("Setting up the advertising payload(s)\n");
|
|
||||||
// startAdv();
|
|
||||||
|
|
||||||
// DEBUG_MSG("Advertising\n");
|
|
||||||
//}
|
|
||||||
|
|
||||||
//NimBLEDevice::deleteAllBonds();
|
|
||||||
|
|
||||||
NimBLEDevice::init(getDeviceName());
|
|
||||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
|
|
||||||
|
|
||||||
NimBLEDevice::setSecurityAuth(true, true, true);
|
|
||||||
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
|
|
||||||
bleServer = NimBLEDevice::createServer();
|
|
||||||
|
|
||||||
ESP32BluetoothServerCallback *serverCallbacks = new ESP32BluetoothServerCallback();
|
|
||||||
bleServer->setCallbacks(serverCallbacks);
|
|
||||||
|
|
||||||
NimBLEService *bleService = bleServer->createService(MESH_SERVICE_UUID);
|
|
||||||
//NimBLECharacteristic *pNonSecureCharacteristic = bleService->createCharacteristic("1234", NIMBLE_PROPERTY::READ );
|
|
||||||
//NimBLECharacteristic *pSecureCharacteristic = bleService->createCharacteristic("1235", NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN);
|
|
||||||
|
|
||||||
//define the characteristics that the app is looking for
|
|
||||||
NimBLECharacteristic *ToRadioCharacteristic = bleService->createCharacteristic(TORADIO_UUID, NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_AUTHEN | NIMBLE_PROPERTY::WRITE_ENC);
|
|
||||||
NimBLECharacteristic *FromRadioCharacteristic = bleService->createCharacteristic(FROMRADIO_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
|
|
||||||
FromNumCharacteristic = bleService->createCharacteristic(FROMNUM_UUID, NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC);
|
|
||||||
|
|
||||||
bluetoothPhoneAPI = new BluetoothPhoneAPI();
|
|
||||||
|
|
||||||
toRadioCallbacks = new ESP32BluetoothToRadioCallback();
|
|
||||||
ToRadioCharacteristic->setCallbacks(toRadioCallbacks);
|
|
||||||
|
|
||||||
fromRadioCallbacks = new ESP32BluetoothFromRadioCallback();
|
|
||||||
FromRadioCharacteristic->setCallbacks(fromRadioCallbacks);
|
|
||||||
|
|
||||||
//uint8_t val[4];
|
|
||||||
//uint32_t zero = 0;
|
|
||||||
//put_le32(val, zero);
|
|
||||||
//std::string fromNumByteString(&val[0], &val[0] + sizeof(val));
|
|
||||||
//FromNumCharacteristic->setValue(fromNumByteString);
|
|
||||||
|
|
||||||
bleService->start();
|
|
||||||
//pNonSecureCharacteristic->setValue("Hello Non Secure BLE");
|
|
||||||
//pSecureCharacteristic->setValue("Hello Secure BLE");
|
|
||||||
|
|
||||||
//FromRadioCharacteristic->setValue("FromRadioString");
|
|
||||||
//ToRadioCharacteristic->setCallbacks()
|
|
||||||
|
|
||||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
|
||||||
pAdvertising->addServiceUUID(MESH_SERVICE_UUID);
|
|
||||||
pAdvertising->start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Given a level between 0-100, update the BLE attribute
|
|
||||||
void updateBatteryLevel(uint8_t level)
|
|
||||||
{
|
|
||||||
//blebas.write(level);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESP32Bluetooth::clearBonds()
|
|
||||||
{
|
|
||||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
|
||||||
//bond_print_list(BLE_GAP_ROLE_PERIPH);
|
|
||||||
//bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
|
||||||
|
|
||||||
//Bluefruit.Periph.clearBonds();
|
|
||||||
//Bluefruit.Central.clearBonds();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearNVS() {
|
|
||||||
NimBLEDevice::deleteAllBonds();
|
|
||||||
ESP.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void disablePin() {
|
|
||||||
DEBUG_MSG("User Override, disabling bluetooth pin requirement\n");
|
|
||||||
// keep track of when it was pressed, so we know it was within X seconds
|
|
||||||
|
|
||||||
// Flash the LED
|
|
||||||
setLed(true);
|
|
||||||
delay(100);
|
|
||||||
setLed(false);
|
|
||||||
delay(100);
|
|
||||||
setLed(true);
|
|
||||||
delay(100);
|
|
||||||
setLed(false);
|
|
||||||
delay(100);
|
|
||||||
setLed(true);
|
|
||||||
delay(100);
|
|
||||||
setLed(false);
|
|
||||||
|
|
||||||
doublepressed = millis();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
extern uint16_t fromNumValHandle;
|
|
||||||
|
|
||||||
class BluetoothPhoneAPI : public PhoneAPI
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
|
|
||||||
*/
|
|
||||||
virtual void onNowHasData(uint32_t fromRadioNum) override;
|
|
||||||
|
|
||||||
/// Check the current underlying physical link to see if the client is currently connected
|
|
||||||
virtual bool checkIsConnected() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern PhoneAPI *bluetoothPhoneAPI;
|
|
||||||
|
|
||||||
class ESP32Bluetooth
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void setup();
|
|
||||||
void shutdown();
|
|
||||||
void clearBonds();
|
|
||||||
};
|
|
||||||
|
|
||||||
void setBluetoothEnable(bool on);
|
|
||||||
void clearNVS();
|
|
||||||
void disablePin();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
#ifndef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
#include "BluetoothSoftwareUpdate.h"
|
|
||||||
|
|
||||||
// NRF52 wants these constants as byte arrays
|
|
||||||
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
|
||||||
|
|
||||||
// "cb0b9a0b-a84c-4c0d-bdbb-442e3144ee30"
|
|
||||||
const ble_uuid128_t update_service_uuid =
|
|
||||||
BLE_UUID128_INIT(0x30, 0xee, 0x44, 0x31, 0x2e, 0x44, 0xbb, 0xbd, 0x0d, 0x4c, 0x4c, 0xa8, 0x0b, 0x9a, 0x0b, 0xcb);
|
|
||||||
|
|
||||||
// "e74dd9c0-a301-4a6f-95a1-f0e1dbea8e1e" write|read
|
|
||||||
const ble_uuid128_t update_size_uuid =
|
|
||||||
BLE_UUID128_INIT(0x1e, 0x8e, 0xea, 0xdb, 0xe1, 0xf0, 0xa1, 0x95, 0x6f, 0x4a, 0x01, 0xa3, 0xc0, 0xd9, 0x4d, 0xe7);
|
|
||||||
|
|
||||||
// "e272ebac-d463-4b98-bc84-5cc1a39ee517" write
|
|
||||||
const ble_uuid128_t update_data_uuid =
|
|
||||||
BLE_UUID128_INIT(0x17, 0xe5, 0x9e, 0xa3, 0xc1, 0x5c, 0x84, 0xbc, 0x98, 0x4b, 0x63, 0xd4, 0xac, 0xeb, 0x72, 0xe2);
|
|
||||||
|
|
||||||
// "4826129c-c22a-43a3-b066-ce8f0d5bacc6" write
|
|
||||||
const ble_uuid128_t update_crc32_uuid =
|
|
||||||
BLE_UUID128_INIT(0xc6, 0xac, 0x5b, 0x0d, 0x8f, 0xce, 0x66, 0xb0, 0xa3, 0x43, 0x2a, 0xc2, 0x9c, 0x12, 0x26, 0x48);
|
|
||||||
|
|
||||||
// "5e134862-7411-4424-ac4a-210937432c77" read|notify
|
|
||||||
const ble_uuid128_t update_result_uuid =
|
|
||||||
BLE_UUID128_INIT(0x77, 0x2c, 0x43, 0x37, 0x09, 0x21, 0x4a, 0xac, 0x24, 0x44, 0x11, 0x74, 0x62, 0x48, 0x13, 0x5e);
|
|
||||||
|
|
||||||
// "5e134862-7411-4424-ac4a-210937432c67" write
|
|
||||||
const ble_uuid128_t update_region_uuid =
|
|
||||||
BLE_UUID128_INIT(0x67, 0x2c, 0x43, 0x37, 0x09, 0x21, 0x4a, 0xac, 0x24, 0x44, 0x11, 0x74, 0x62, 0x48, 0x13, 0x5e);
|
|
||||||
|
|
||||||
const struct ble_gatt_svc_def gatt_update_svcs[] = {
|
|
||||||
{
|
|
||||||
/*** Service: Security test. */
|
|
||||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
|
||||||
.uuid = &update_service_uuid.u,
|
|
||||||
.characteristics =
|
|
||||||
(struct ble_gatt_chr_def[]){{
|
|
||||||
.uuid = &update_size_uuid.u,
|
|
||||||
.access_cb = update_size_callback,
|
|
||||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN | BLE_GATT_CHR_F_READ |
|
|
||||||
BLE_GATT_CHR_F_READ_AUTHEN,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.uuid = &update_data_uuid.u,
|
|
||||||
.access_cb = update_data_callback,
|
|
||||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.uuid = &update_crc32_uuid.u,
|
|
||||||
.access_cb = update_crc32_callback,
|
|
||||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.uuid = &update_result_uuid.u,
|
|
||||||
.access_cb = update_result_callback,
|
|
||||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.uuid = &update_region_uuid.u,
|
|
||||||
.access_cb = update_region_callback,
|
|
||||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0, /* No more characteristics in this service. */
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
0, /* No more services. */
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //#ifndef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
407
src/gps/GPS.cpp
407
src/gps/GPS.cpp
@@ -59,98 +59,192 @@ bool GPS::getACK(uint8_t c, uint8_t i) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* @note New method, this method can wait for the specified class and message ID, and return the payload
|
||||||
|
* @param *buffer: The message buffer, if there is a response payload message, it will be returned through the buffer parameter
|
||||||
|
* @param size: size of buffer
|
||||||
|
* @param requestedClass: request class constant
|
||||||
|
* @param requestedID: request message ID constant
|
||||||
|
* @retval length of payload message
|
||||||
|
*/
|
||||||
|
int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID)
|
||||||
|
{
|
||||||
|
uint16_t ubxFrameCounter = 0;
|
||||||
|
uint32_t startTime = millis();
|
||||||
|
uint16_t needRead;
|
||||||
|
|
||||||
|
while (millis() - startTime < 800) {
|
||||||
|
while (_serial_gps->available()) {
|
||||||
|
int c = _serial_gps->read();
|
||||||
|
switch (ubxFrameCounter) {
|
||||||
|
case 0:
|
||||||
|
//ubxFrame 'μ'
|
||||||
|
if (c == 0xB5) {
|
||||||
|
ubxFrameCounter++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//ubxFrame 'b'
|
||||||
|
if (c == 0x62) {
|
||||||
|
ubxFrameCounter++;
|
||||||
|
} else {
|
||||||
|
ubxFrameCounter = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//Class
|
||||||
|
if (c == requestedClass) {
|
||||||
|
ubxFrameCounter++;
|
||||||
|
} else {
|
||||||
|
ubxFrameCounter = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
//Message ID
|
||||||
|
if (c == requestedID) {
|
||||||
|
ubxFrameCounter++;
|
||||||
|
} else {
|
||||||
|
ubxFrameCounter = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
//Payload lenght lsb
|
||||||
|
needRead = c;
|
||||||
|
ubxFrameCounter++;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
//Payload lenght msb
|
||||||
|
needRead |= (c << 8);
|
||||||
|
ubxFrameCounter++;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
// Check for buffer overflow
|
||||||
|
if (needRead >= size) {
|
||||||
|
ubxFrameCounter = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (_serial_gps->readBytes(buffer, needRead) != needRead) {
|
||||||
|
ubxFrameCounter = 0;
|
||||||
|
} else {
|
||||||
|
// return payload lenght
|
||||||
|
return needRead;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool GPS::setupGPS()
|
bool GPS::setupGPS()
|
||||||
{
|
{
|
||||||
if (_serial_gps && !didSerialInit) {
|
if (_serial_gps && !didSerialInit) {
|
||||||
didSerialInit = true;
|
didSerialInit = true;
|
||||||
|
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
// In esp32 framework, setRxBufferSize needs to be initialized before Serial
|
||||||
|
_serial_gps->setRxBufferSize(2048); // the default is 256
|
||||||
|
#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(GPS_RX_PIN) && !defined(NO_ESP32)
|
#if defined(GPS_RX_PIN) && defined(ARCH_ESP32)
|
||||||
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
||||||
#else
|
#else
|
||||||
_serial_gps->begin(GPS_BAUDRATE);
|
_serial_gps->begin(GPS_BAUDRATE);
|
||||||
#endif
|
#endif
|
||||||
#ifndef NO_ESP32
|
|
||||||
_serial_gps->setRxBufferSize(2048); // the default is 256
|
|
||||||
#endif
|
|
||||||
#ifdef TTGO_T_ECHO
|
|
||||||
// Switch to 9600 baud, then close and reopen port
|
|
||||||
_serial_gps->end();
|
|
||||||
delay(250);
|
|
||||||
_serial_gps->begin(4800);
|
|
||||||
delay(250);
|
|
||||||
_serial_gps->write("$PCAS01,1*1D\r\n");
|
|
||||||
delay(250);
|
|
||||||
_serial_gps->end();
|
|
||||||
delay(250);
|
|
||||||
_serial_gps->begin(9600);
|
|
||||||
delay(250);
|
|
||||||
// Initialize the L76K Chip, use GPS + GLONASS
|
|
||||||
_serial_gps->write("$PCAS04,5*1C\r\n");
|
|
||||||
delay(250);
|
|
||||||
// only ask for RMC and GGA
|
|
||||||
_serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n");
|
|
||||||
delay(250);
|
|
||||||
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
|
|
||||||
_serial_gps->write("$PCAS11,3*1E\r\n");
|
|
||||||
delay(250);
|
|
||||||
#endif
|
|
||||||
#ifdef GPS_UBLOX
|
|
||||||
delay(250);
|
|
||||||
// Set the UART port to output NMEA only
|
|
||||||
byte _message_nmea[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00,
|
|
||||||
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF};
|
|
||||||
_serial_gps->write(_message_nmea, sizeof(_message_nmea));
|
|
||||||
if (!getACK(0x06, 0x00)) {
|
|
||||||
DEBUG_MSG("WARNING: Unable to enable NMEA Mode.\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable GGL
|
/*
|
||||||
byte _message_GGL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x05, 0x3A};
|
* T-Beam-S3-Core will be preset to use gps Probe here, and other boards will not be changed first
|
||||||
_serial_gps->write(_message_GGL, sizeof(_message_GGL));
|
*/
|
||||||
if (!getACK(0x06, 0x01)) {
|
gnssModel = probe();
|
||||||
DEBUG_MSG("WARNING: Unable to disable NMEA GGL.\n");
|
|
||||||
return true;
|
if(gnssModel == GNSS_MODEL_MTK){
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* */
|
||||||
|
// _serial_gps->begin(9600); //The baud rate of 9600 has been initialized at the beginning of setupGPS, this line is the redundant part
|
||||||
|
// delay(250);
|
||||||
|
|
||||||
|
// Initialize the L76K Chip, use GPS + GLONASS
|
||||||
|
_serial_gps->write("$PCAS04,5*1C\r\n");
|
||||||
|
delay(250);
|
||||||
|
// only ask for RMC and GGA
|
||||||
|
_serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n");
|
||||||
|
delay(250);
|
||||||
|
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
|
||||||
|
_serial_gps->write("$PCAS11,3*1E\r\n");
|
||||||
|
delay(250);
|
||||||
|
|
||||||
|
}else if(gnssModel == GNSS_MODEL_UBLOX){
|
||||||
|
|
||||||
|
/*
|
||||||
|
tips: NMEA Only should not be set here, otherwise initializing Ublox gnss module again after
|
||||||
|
setting will not output command messages in UART1, resulting in unrecognized module information
|
||||||
|
|
||||||
|
// Set the UART port to output NMEA only
|
||||||
|
byte _message_nmea[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00,
|
||||||
|
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF};
|
||||||
|
_serial_gps->write(_message_nmea, sizeof(_message_nmea));
|
||||||
|
if (!getACK(0x06, 0x00)) {
|
||||||
|
DEBUG_MSG("WARNING: Unable to enable NMEA Mode.\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid
|
||||||
|
|
||||||
|
// disable GGL
|
||||||
|
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));
|
||||||
|
if (!getACK(0x06, 0x01)) {
|
||||||
|
DEBUG_MSG("WARNING: Unable to disable NMEA GGL.\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable GSA
|
||||||
|
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));
|
||||||
|
if (!getACK(0x06, 0x01)) {
|
||||||
|
DEBUG_MSG("WARNING: Unable to disable NMEA GSA.\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable GSV
|
||||||
|
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));
|
||||||
|
if (!getACK(0x06, 0x01)) {
|
||||||
|
DEBUG_MSG("WARNING: Unable to disable NMEA GSV.\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable VTG
|
||||||
|
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));
|
||||||
|
if (!getACK(0x06, 0x01)) {
|
||||||
|
DEBUG_MSG("WARNING: Unable to disable NMEA VTG.\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable RMC
|
||||||
|
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));
|
||||||
|
if (!getACK(0x06, 0x01)) {
|
||||||
|
DEBUG_MSG("WARNING: Unable to enable NMEA RMC.\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable GGA
|
||||||
|
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));
|
||||||
|
if (!getACK(0x06, 0x01)) {
|
||||||
|
DEBUG_MSG("WARNING: Unable to enable NMEA GGA.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable GSA
|
|
||||||
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));
|
|
||||||
if (!getACK(0x06, 0x01)) {
|
|
||||||
DEBUG_MSG("WARNING: Unable to disable NMEA GSA.\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable GSV
|
|
||||||
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));
|
|
||||||
if (!getACK(0x06, 0x01)) {
|
|
||||||
DEBUG_MSG("WARNING: Unable to disable NMEA GSV.\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable VTG
|
|
||||||
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));
|
|
||||||
if (!getACK(0x06, 0x01)) {
|
|
||||||
DEBUG_MSG("WARNING: Unable to disable NMEA VTG.\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable RMC
|
|
||||||
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));
|
|
||||||
if (!getACK(0x06, 0x01)) {
|
|
||||||
DEBUG_MSG("WARNING: Unable to enable NMEA RMC.\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable GGA
|
|
||||||
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));
|
|
||||||
if (!getACK(0x06, 0x01)) DEBUG_MSG("WARNING: Unable to enable NMEA GGA.\n");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -271,16 +365,7 @@ uint32_t GPS::getWakeTime() const
|
|||||||
|
|
||||||
if (t == UINT32_MAX)
|
if (t == UINT32_MAX)
|
||||||
return t; // already maxint
|
return t; // already maxint
|
||||||
|
return t * 1000;
|
||||||
if (t == 0)
|
|
||||||
t = (config.device.role == Config_DeviceConfig_Role_Router)
|
|
||||||
? 5 * 60
|
|
||||||
: 15 * 60; // Allow up to 15 mins for each attempt (probably will be much
|
|
||||||
// less if we can find sats) or less if a router
|
|
||||||
|
|
||||||
t *= 1000; // msecs
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get how long we should sleep between aqusition attempts in msecs
|
/** Get how long we should sleep between aqusition attempts in msecs
|
||||||
@@ -288,21 +373,15 @@ uint32_t GPS::getWakeTime() const
|
|||||||
uint32_t GPS::getSleepTime() const
|
uint32_t GPS::getSleepTime() const
|
||||||
{
|
{
|
||||||
uint32_t t = config.position.gps_update_interval;
|
uint32_t t = config.position.gps_update_interval;
|
||||||
bool gps_disabled = config.position.gps_disabled;
|
bool gps_enabled = config.position.gps_enabled;
|
||||||
|
|
||||||
if (gps_disabled)
|
if (!gps_enabled)
|
||||||
t = UINT32_MAX; // Sleep forever now
|
t = UINT32_MAX; // Sleep forever now
|
||||||
|
|
||||||
if (t == UINT32_MAX)
|
if (t == UINT32_MAX)
|
||||||
return t; // already maxint
|
return t; // already maxint
|
||||||
|
|
||||||
if (t == 0) // default - unset in preferences
|
return t * 1000;
|
||||||
t = (config.device.role == Config_DeviceConfig_Role_Router) ? 24 * 60 * 60
|
|
||||||
: 2 * 60; // 2 mins or once per day for routers
|
|
||||||
|
|
||||||
t *= 1000;
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPS::publishUpdate()
|
void GPS::publishUpdate()
|
||||||
@@ -311,7 +390,7 @@ 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.pos_timestamp, hasValidLocation, hasLock());
|
DEBUG_MSG("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(), p);
|
||||||
@@ -325,14 +404,14 @@ 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 {
|
||||||
#ifdef GPS_UBLOX
|
if(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");
|
DEBUG_MSG("GPS is not communicating, trying factory reset on next bootup.\n");
|
||||||
devicestate.did_gps_reset = false;
|
devicestate.did_gps_reset = false;
|
||||||
nodeDB.saveToDisk();
|
nodeDB.saveDeviceStateToDisk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are overdue for an update, turn on the GPS and at least publish the current status
|
// If we are overdue for an update, turn on the GPS and at least publish the current status
|
||||||
@@ -432,17 +511,123 @@ int GPS::prepareDeepSleep(void *unused)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_GPS
|
GnssModel_t GPS::probe()
|
||||||
|
{
|
||||||
|
// return immediately if the model is set by the variant.h file
|
||||||
|
#ifdef GPS_UBLOX
|
||||||
|
return GNSS_MODEL_UBLOX;
|
||||||
|
#elif defined(GPS_L76K)
|
||||||
|
return GNSS_MODEL_MTK;
|
||||||
|
#else
|
||||||
|
// we use autodetect, only T-BEAM S3 for now...
|
||||||
|
uint8_t buffer[256];
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* */
|
||||||
|
struct uBloxGnssModelInfo info ;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
|
||||||
|
|
||||||
|
// Close all NMEA sentences , Only valid for MTK platform
|
||||||
|
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
|
||||||
|
delay(20);
|
||||||
|
|
||||||
|
// Get version information
|
||||||
|
_serial_gps->write("$PCAS06,0*1B\r\n");
|
||||||
|
uint32_t startTimeout = millis() + 500;
|
||||||
|
while (millis() < startTimeout) {
|
||||||
|
if (_serial_gps->available()) {
|
||||||
|
String ver = _serial_gps->readStringUntil('\r');
|
||||||
|
// Get module info , If the correct header is returned,
|
||||||
|
// it can be determined that it is the MTK chip
|
||||||
|
int index = ver.indexOf("$");
|
||||||
|
if(index != -1){
|
||||||
|
ver = ver.substring(index);
|
||||||
|
if (ver.startsWith("$GPTXT,01,01,02")) {
|
||||||
|
DEBUG_MSG("L76K GNSS init succeeded, using L76K GNSS Module\n");
|
||||||
|
return GNSS_MODEL_MTK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30};
|
||||||
|
_serial_gps->write(cfg_rate, sizeof(cfg_rate));
|
||||||
|
// Check that the returned response class and message ID are correct
|
||||||
|
if (!getAck(buffer, 256, 0x06, 0x08)) {
|
||||||
|
DEBUG_MSG("Warning: Failed to find UBlox & MTK GNSS Module\n");
|
||||||
|
return GNSS_MODEL_UNKONW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Ublox gnss module hardware and software info
|
||||||
|
uint8_t cfg_get_hw[] = {0xB5, 0x62, 0x0A, 0x04, 0x00, 0x00, 0x0E, 0x34};
|
||||||
|
_serial_gps->write(cfg_get_hw, sizeof(cfg_get_hw));
|
||||||
|
|
||||||
|
uint16_t len = getAck(buffer, 256, 0x0A, 0x04);
|
||||||
|
if (len) {
|
||||||
|
|
||||||
|
uint16_t position = 0;
|
||||||
|
for (int i = 0; i < 30; i++) {
|
||||||
|
info.swVersion[i] = buffer[position];
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
info.hwVersion[i] = buffer[position];
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len >= position + 30) {
|
||||||
|
for (int i = 0; i < 30; i++) {
|
||||||
|
info.extension[info.extensionNo][i] = buffer[position];
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
info.extensionNo++;
|
||||||
|
if (info.extensionNo > 9)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_MSG("Module Info : \n");
|
||||||
|
DEBUG_MSG("Soft version: %s\n",info.swVersion);
|
||||||
|
DEBUG_MSG("Hard version: %s\n",info.hwVersion);
|
||||||
|
DEBUG_MSG("Extensions:%d\n",info.extensionNo);
|
||||||
|
for (int i = 0; i < info.extensionNo; i++) {
|
||||||
|
DEBUG_MSG(" %s\n",info.extension[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buffer,0,sizeof(buffer));
|
||||||
|
|
||||||
|
//tips: extensionNo field is 0 on some 6M GNSS modules
|
||||||
|
for (int i = 0; i < info.extensionNo; ++i) {
|
||||||
|
if (!strncmp(info.extension[i], "OD=", 3)) {
|
||||||
|
strcpy((char *)buffer, &(info.extension[i][3]));
|
||||||
|
DEBUG_MSG("GetModel:%s\n",(char *)buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen((char*)buffer)) {
|
||||||
|
DEBUG_MSG("UBlox GNSS init succeeded, using UBlox %s GNSS Module\n" , buffer);
|
||||||
|
}else{
|
||||||
|
DEBUG_MSG("UBlox GNSS init succeeded, using UBlox GNSS Module\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GNSS_MODEL_UBLOX;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAS_GPS
|
||||||
#include "NMEAGPS.h"
|
#include "NMEAGPS.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPS *createGps()
|
GPS *createGps()
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef NO_GPS
|
#if !HAS_GPS
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#else
|
#else
|
||||||
if (!config.position.gps_disabled) {
|
if (config.position.gps_enabled) {
|
||||||
#ifdef GPS_ALTITUDE_HAE
|
#ifdef GPS_ALTITUDE_HAE
|
||||||
DEBUG_MSG("Using HAE altitude model\n");
|
DEBUG_MSG("Using HAE altitude model\n");
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -4,6 +4,20 @@
|
|||||||
#include "Observer.h"
|
#include "Observer.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct uBloxGnssModelInfo {
|
||||||
|
char swVersion[30];
|
||||||
|
char hwVersion[10];
|
||||||
|
uint8_t extensionNo;
|
||||||
|
char extension[10][30];
|
||||||
|
} ;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
GNSS_MODEL_MTK,
|
||||||
|
GNSS_MODEL_UBLOX,
|
||||||
|
GNSS_MODEL_UNKONW,
|
||||||
|
}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);
|
||||||
|
|
||||||
@@ -146,6 +160,14 @@ class GPS : private concurrency::OSThread
|
|||||||
void publishUpdate();
|
void publishUpdate();
|
||||||
|
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
// Get GNSS model
|
||||||
|
GnssModel_t probe();
|
||||||
|
|
||||||
|
int getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GnssModel_t gnssModel = GNSS_MODEL_UNKONW;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates an instance of the GPS class.
|
// Creates an instance of the GPS class.
|
||||||
|
|||||||
@@ -19,14 +19,21 @@ static int32_t toDegInt(RawDegrees d)
|
|||||||
|
|
||||||
bool NMEAGPS::factoryReset()
|
bool NMEAGPS::factoryReset()
|
||||||
{
|
{
|
||||||
#ifdef GPS_UBLOX
|
#ifdef PIN_GPS_REINIT
|
||||||
|
//The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW
|
||||||
|
digitalWrite(PIN_GPS_REINIT, 0);
|
||||||
|
pinMode(PIN_GPS_REINIT, OUTPUT);
|
||||||
|
delay(150); //The L76K datasheet calls for at least 100MS delay
|
||||||
|
digitalWrite(PIN_GPS_REINIT, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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, 0x00, 0x00, 0x00,
|
0xFB, 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);
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +162,7 @@ bool NMEAGPS::lookForLocation()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.location_source = Position_LocSource_LOCSRC_GPS_INTERNAL;
|
p.location_source = 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
|
||||||
@@ -176,8 +183,8 @@ bool NMEAGPS::lookForLocation()
|
|||||||
p.latitude_i = toDegInt(loc.lat);
|
p.latitude_i = toDegInt(loc.lat);
|
||||||
p.longitude_i = toDegInt(loc.lng);
|
p.longitude_i = toDegInt(loc.lng);
|
||||||
|
|
||||||
p.alt_geoid_sep = reader.geoidHeight.meters();
|
p.altitude_geoidal_separation = reader.geoidHeight.meters();
|
||||||
p.altitude_hae = reader.altitude.meters() + p.alt_geoid_sep;
|
p.altitude_hae = reader.altitude.meters() + p.altitude_geoidal_separation;
|
||||||
p.altitude = reader.altitude.meters();
|
p.altitude = reader.altitude.meters();
|
||||||
|
|
||||||
p.fix_quality = fixQual;
|
p.fix_quality = fixQual;
|
||||||
@@ -194,7 +201,7 @@ bool NMEAGPS::lookForLocation()
|
|||||||
t.tm_mon = reader.date.month() - 1;
|
t.tm_mon = reader.date.month() - 1;
|
||||||
t.tm_year = reader.date.year() - 1900;
|
t.tm_year = reader.date.year() - 1900;
|
||||||
t.tm_isdst = false;
|
t.tm_isdst = false;
|
||||||
p.pos_timestamp = mktime(&t);
|
p.timestamp = mktime(&t);
|
||||||
|
|
||||||
// Nice to have, if available
|
// Nice to have, if available
|
||||||
if (reader.satellites.isUpdated()) {
|
if (reader.satellites.isUpdated()) {
|
||||||
@@ -210,13 +217,10 @@ bool NMEAGPS::lookForLocation()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (reader.speed.isUpdated() && reader.speed.isValid()) {
|
||||||
// REDUNDANT?
|
p.ground_speed = reader.speed.kmph();
|
||||||
// expect gps pos lat=37.520825, lon=-122.309162, alt=158
|
}
|
||||||
DEBUG_MSG("new NMEA GPS pos lat=%f, lon=%f, alt=%d, dop=%g, heading=%f\n",
|
|
||||||
latitude * 1e-7, longitude * 1e-7, altitude, dop * 1e-2,
|
|
||||||
heading * 1e-5);
|
|
||||||
*/
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ void readFromRTC()
|
|||||||
rtc.begin();
|
rtc.begin();
|
||||||
auto tc = rtc.getDateTime();
|
auto tc = rtc.getDateTime();
|
||||||
tm t;
|
tm t;
|
||||||
t.tm_year = tc.year;
|
t.tm_year = tc.year - 1900;
|
||||||
t.tm_mon = tc.month;
|
t.tm_mon = tc.month - 1;
|
||||||
t.tm_mday = tc.day;
|
t.tm_mday = tc.day;
|
||||||
t.tm_hour = tc.hour;
|
t.tm_hour = tc.hour;
|
||||||
t.tm_min = tc.minute;
|
t.tm_min = tc.minute;
|
||||||
@@ -112,15 +112,15 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
|||||||
PCF8563_Class rtc;
|
PCF8563_Class rtc;
|
||||||
rtc.begin();
|
rtc.begin();
|
||||||
tm *t = localtime(&tv->tv_sec);
|
tm *t = localtime(&tv->tv_sec);
|
||||||
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, 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);
|
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);
|
||||||
}
|
}
|
||||||
#elif !defined(NO_ESP32)
|
#elif defined(ARCH_ESP32)
|
||||||
settimeofday(tv, NULL);
|
settimeofday(tv, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// nrf52 doesn't have a readable RTC (yet - software not written)
|
// nrf52 doesn't have a readable RTC (yet - software not written)
|
||||||
#if defined(PORTDUINO) || !defined(NO_ESP32) || defined(RV3028_RTC) || defined(PCF8563_RTC)
|
#ifdef HAS_RTC
|
||||||
readFromRTC();
|
readFromRTC();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
#ifdef HAS_EINK
|
#ifdef USE_EINK
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "EInkDisplay2.h"
|
#include "EInkDisplay2.h"
|
||||||
#include "SPILock.h"
|
#include "SPILock.h"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#ifndef NO_SCREEN
|
#if HAS_SCREEN
|
||||||
#include <OLEDDisplay.h>
|
#include <OLEDDisplay.h>
|
||||||
|
|
||||||
#include "GPS.h"
|
#include "GPS.h"
|
||||||
@@ -39,11 +39,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
#include "mesh/http/WiFiAPClient.h"
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef OLED_RU
|
||||||
|
#include "fonts/OLEDDisplayFontsRU.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace meshtastic; /** @todo remove */
|
using namespace meshtastic; /** @todo remove */
|
||||||
|
|
||||||
extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
|
extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
|
||||||
@@ -53,7 +57,6 @@ namespace graphics
|
|||||||
|
|
||||||
// This means the *visible* area (sh1106 can address 132, but shows 128 for example)
|
// This means the *visible* area (sh1106 can address 132, but shows 128 for example)
|
||||||
#define IDLE_FRAMERATE 1 // in fps
|
#define IDLE_FRAMERATE 1 // in fps
|
||||||
#define COMPASS_DIAM 44
|
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
#define NUM_EXTRA_FRAMES 3 // text message and debug frame
|
#define NUM_EXTRA_FRAMES 3 // text message and debug frame
|
||||||
@@ -64,7 +67,7 @@ namespace graphics
|
|||||||
static FrameCallback normalFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
|
static FrameCallback normalFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
|
||||||
static uint32_t targetFramerate = IDLE_FRAMERATE;
|
static uint32_t targetFramerate = IDLE_FRAMERATE;
|
||||||
static char btPIN[16] = "888888";
|
static char btPIN[16] = "888888";
|
||||||
|
|
||||||
// This image definition is here instead of images.h because it's modified dynamically by the drawBattery function
|
// This image definition is here instead of images.h because it's modified dynamically by the drawBattery function
|
||||||
uint8_t imgBattery[16] = {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xE7, 0x3C};
|
uint8_t imgBattery[16] = {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xE7, 0x3C};
|
||||||
|
|
||||||
@@ -82,7 +85,7 @@ static char ourId[5];
|
|||||||
GeoCoord geoCoord;
|
GeoCoord geoCoord;
|
||||||
|
|
||||||
// OEM Config File
|
// OEM Config File
|
||||||
static const char *oemConfigFile = "/prefs/oem.proto";
|
static const char *oemConfigFile = "/oem/oem.proto";
|
||||||
OEMStore oemStore;
|
OEMStore oemStore;
|
||||||
|
|
||||||
#ifdef SHOW_REDRAWS
|
#ifdef SHOW_REDRAWS
|
||||||
@@ -94,13 +97,17 @@ static uint16_t displayWidth, displayHeight;
|
|||||||
#define SCREEN_WIDTH displayWidth
|
#define SCREEN_WIDTH displayWidth
|
||||||
#define SCREEN_HEIGHT displayHeight
|
#define SCREEN_HEIGHT displayHeight
|
||||||
|
|
||||||
#if defined(HAS_EINK) || defined(ILI9341_DRIVER)
|
#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
|
||||||
#define FONT_MEDIUM ArialMT_Plain_24
|
#define FONT_MEDIUM ArialMT_Plain_24
|
||||||
#define FONT_LARGE ArialMT_Plain_24
|
#define FONT_LARGE ArialMT_Plain_24
|
||||||
#else
|
#else
|
||||||
|
#ifdef OLED_RU
|
||||||
|
#define FONT_SMALL ArialMT_Plain_10_RU
|
||||||
|
#else
|
||||||
#define FONT_SMALL ArialMT_Plain_10
|
#define FONT_SMALL ArialMT_Plain_10
|
||||||
|
#endif
|
||||||
#define FONT_MEDIUM ArialMT_Plain_16
|
#define FONT_MEDIUM ArialMT_Plain_16
|
||||||
#define FONT_LARGE ArialMT_Plain_24
|
#define FONT_LARGE ArialMT_Plain_24
|
||||||
#endif
|
#endif
|
||||||
@@ -109,12 +116,10 @@ static uint16_t displayWidth, displayHeight;
|
|||||||
|
|
||||||
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
|
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
|
||||||
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
|
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
|
||||||
|
#define FONT_HEIGHT_LARGE fontHeight(FONT_LARGE)
|
||||||
|
|
||||||
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
|
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
|
||||||
|
|
||||||
#ifndef SCREEN_TRANSITION_MSECS
|
|
||||||
#define SCREEN_TRANSITION_MSECS 300
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw the icon with extra info printed around the corners
|
* Draw the icon with extra info printed around the corners
|
||||||
@@ -212,7 +217,7 @@ static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
display->drawString(64 + x, y, "Creating SSL certificate");
|
display->drawString(64 + x, y, "Creating SSL certificate");
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
yield();
|
yield();
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
#endif
|
#endif
|
||||||
@@ -228,38 +233,29 @@ static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
// Used when booting without a region set
|
// Used when booting without a region set
|
||||||
static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
|
||||||
|
display->drawString(64 + x, y + FONT_HEIGHT_SMALL, getDeviceName());
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
|
||||||
if ((millis() / 10000) % 2) {
|
if ((millis() / 10000) % 2) {
|
||||||
display->setFont(FONT_SMALL);
|
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
|
||||||
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
|
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
|
||||||
|
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Set the region using the");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Set the region using the");
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "Meshtastic Android, iOS,");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "Meshtastic Android, iOS,");
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
|
||||||
} else {
|
} else {
|
||||||
display->setFont(FONT_SMALL);
|
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
|
||||||
display->drawString(64 + x, y, "//\\ E S H T /\\ S T / C");
|
|
||||||
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
|
||||||
|
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Visit meshtastic.org");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Visit meshtastic.org");
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "for more information.");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "for more information.");
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "");
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
yield();
|
yield();
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_EINK
|
#ifdef USE_EINK
|
||||||
/// Used on eink displays while in deep sleep
|
/// Used on eink displays while in deep sleep
|
||||||
static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
@@ -299,8 +295,13 @@ static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state,
|
|||||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Enter this code");
|
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Enter this code");
|
||||||
|
|
||||||
display->setFont(FONT_LARGE);
|
display->setFont(FONT_LARGE);
|
||||||
display->drawString(64 + x, 26 + y, btPIN);
|
|
||||||
|
|
||||||
|
auto displayPin = new String(btPIN);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->drawString(12 + x, 26 + y, displayPin->substring(0, 3));
|
||||||
|
display->drawString(72 + x, 26 + y, displayPin->substring(3, 6));
|
||||||
|
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
char buf[30];
|
char buf[30];
|
||||||
const char *name = "Name: ";
|
const char *name = "Name: ";
|
||||||
@@ -317,6 +318,14 @@ static void drawFrameShutdown(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
display->drawString(64 + x, 26 + y, "Shutting down...");
|
display->drawString(64 + x, 26 + y, "Shutting down...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drawFrameReboot(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->drawString(64 + x, 26 + y, "Rebooting...");
|
||||||
|
}
|
||||||
|
|
||||||
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
@@ -329,9 +338,6 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
} else {
|
} else {
|
||||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
|
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// display->setFont(FONT_LARGE);
|
|
||||||
// display->drawString(64 + x, 26 + y, btPIN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the last text message we received
|
/// Draw the last text message we received
|
||||||
@@ -516,6 +522,8 @@ 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)
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -534,21 +542,21 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
|
|||||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (gpsFormat != Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDMS) {
|
if (gpsFormat != Config_DisplayConfig_GpsCoordinateFormat_DMS) {
|
||||||
char coordinateLine[22];
|
char coordinateLine[22];
|
||||||
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_GpsFormatDec) { // Decimal Degrees
|
if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_DEC) { // Decimal Degrees
|
||||||
sprintf(coordinateLine, "%f %f", geoCoord.getLatitude() * 1e-7, geoCoord.getLongitude() * 1e-7);
|
sprintf(coordinateLine, "%f %f", geoCoord.getLatitude() * 1e-7, geoCoord.getLongitude() * 1e-7);
|
||||||
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_GpsFormatUTM) { // Universal Transverse Mercator
|
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_UTM) { // Universal Transverse Mercator
|
||||||
sprintf(coordinateLine, "%2i%1c %06u %07u", geoCoord.getUTMZone(), geoCoord.getUTMBand(),
|
sprintf(coordinateLine, "%2i%1c %06u %07u", geoCoord.getUTMZone(), geoCoord.getUTMBand(),
|
||||||
geoCoord.getUTMEasting(), geoCoord.getUTMNorthing());
|
geoCoord.getUTMEasting(), geoCoord.getUTMNorthing());
|
||||||
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_GpsFormatMGRS) { // Military Grid Reference System
|
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_MGRS) { // Military Grid Reference System
|
||||||
sprintf(coordinateLine, "%2i%1c %1c%1c %05u %05u", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(),
|
sprintf(coordinateLine, "%2i%1c %1c%1c %05u %05u", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(),
|
||||||
geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(),
|
geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(),
|
||||||
geoCoord.getMGRSNorthing());
|
geoCoord.getMGRSNorthing());
|
||||||
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOLC) { // Open Location Code
|
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_OLC) { // Open Location Code
|
||||||
geoCoord.getOLCCode(coordinateLine);
|
geoCoord.getOLCCode(coordinateLine);
|
||||||
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_GpsFormatOSGR) { // Ordnance Survey Grid Reference
|
} else if (gpsFormat == 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");
|
sprintf(coordinateLine, "%s", "Out of Boundary");
|
||||||
else
|
else
|
||||||
@@ -595,7 +603,7 @@ class Point
|
|||||||
void rotate(float radian)
|
void rotate(float radian)
|
||||||
{
|
{
|
||||||
float cos = cosf(radian), sin = sinf(radian);
|
float cos = cosf(radian), sin = sinf(radian);
|
||||||
float rx = x * cos - y * sin, ry = x * sin + y * cos;
|
float rx = x * cos + y * sin, ry = -x * sin + y * cos;
|
||||||
|
|
||||||
x = rx;
|
x = rx;
|
||||||
y = ry;
|
y = ry;
|
||||||
@@ -609,8 +617,10 @@ class Point
|
|||||||
|
|
||||||
void scale(float f)
|
void scale(float f)
|
||||||
{
|
{
|
||||||
|
//We use -f here to counter the flip that happens
|
||||||
|
//on the y axis when drawing and rotating on screen
|
||||||
x *= f;
|
x *= f;
|
||||||
y *= f;
|
y *= -f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -658,6 +668,26 @@ static bool hasPosition(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint16_t getCompassDiam(OLEDDisplay *display)
|
||||||
|
{
|
||||||
|
uint16_t diam = 0;
|
||||||
|
// get the smaller of the 2 dimensions and subtract 20
|
||||||
|
if(display->getWidth() > display->getHeight()) {
|
||||||
|
diam = display->getHeight();
|
||||||
|
// if 2/3 of the other size would be smaller, use that
|
||||||
|
if (diam > (display->getWidth() * 2 / 3)) {
|
||||||
|
diam = display->getWidth() * 2 / 3;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
diam = display->getWidth();
|
||||||
|
if (diam > (display->getHeight() * 2 / 3)) {
|
||||||
|
diam = display->getHeight() * 2 / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return diam - 20;
|
||||||
|
};
|
||||||
|
|
||||||
/// We will skip one node - the one for us, so we just blindly loop over all
|
/// We will skip one node - the one for us, so we just blindly loop over all
|
||||||
/// nodes
|
/// nodes
|
||||||
static size_t nodeIndex;
|
static size_t nodeIndex;
|
||||||
@@ -674,7 +704,7 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
|
|||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
arrowPoints[i]->rotate(headingRadian);
|
arrowPoints[i]->rotate(headingRadian);
|
||||||
arrowPoints[i]->scale(COMPASS_DIAM * 0.6);
|
arrowPoints[i]->scale(getCompassDiam(display) * 0.6);
|
||||||
arrowPoints[i]->translate(compassX, compassY);
|
arrowPoints[i]->translate(compassX, compassY);
|
||||||
}
|
}
|
||||||
drawLine(display, tip, tail);
|
drawLine(display, tip, tail);
|
||||||
@@ -682,16 +712,21 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
|
|||||||
drawLine(display, rightArrow, tip);
|
drawLine(display, rightArrow, tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the compass heading
|
// Draw north
|
||||||
static void drawCompassHeading(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
|
static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
|
||||||
{
|
{
|
||||||
Point N1(-0.04f, -0.65f), N2(0.04f, -0.65f);
|
//If north is supposed to be at the top of the compass we want rotation to be +0
|
||||||
Point N3(-0.04f, -0.55f), N4(0.04f, -0.55f);
|
if(config.display.compass_north_top)
|
||||||
|
myHeading = -0;
|
||||||
|
|
||||||
|
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f);
|
||||||
|
Point N3(-0.04f, 0.55f), N4(0.04f, 0.55f);
|
||||||
Point *rosePoints[] = {&N1, &N2, &N3, &N4};
|
Point *rosePoints[] = {&N1, &N2, &N3, &N4};
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
rosePoints[i]->rotate(myHeading);
|
// North on compass will be negative of heading
|
||||||
rosePoints[i]->scale(-1 * COMPASS_DIAM);
|
rosePoints[i]->rotate(-myHeading);
|
||||||
|
rosePoints[i]->scale(getCompassDiam(display));
|
||||||
rosePoints[i]->translate(compassX, compassY);
|
rosePoints[i]->translate(compassX, compassY);
|
||||||
}
|
}
|
||||||
drawLine(display, N1, N3);
|
drawLine(display, N1, N3);
|
||||||
@@ -756,13 +791,13 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
|
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
|
||||||
|
|
||||||
// coordinates for the center of the compass/circle
|
// coordinates for the center of the compass/circle
|
||||||
int16_t compassX = x + SCREEN_WIDTH - COMPASS_DIAM / 2 - 5, compassY = y + SCREEN_HEIGHT / 2;
|
int16_t compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5, compassY = y + SCREEN_HEIGHT / 2;
|
||||||
bool hasNodeHeading = false;
|
bool hasNodeHeading = false;
|
||||||
|
|
||||||
if (ourNode && hasPosition(ourNode)) {
|
if (ourNode && hasPosition(ourNode)) {
|
||||||
Position &op = ourNode->position;
|
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));
|
||||||
drawCompassHeading(display, compassX, compassY, myHeading);
|
drawCompassNorth(display, compassX, compassY, myHeading);
|
||||||
|
|
||||||
if (hasPosition(node)) {
|
if (hasPosition(node)) {
|
||||||
// display direction toward node
|
// display direction toward node
|
||||||
@@ -770,17 +805,26 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
Position &p = node->position;
|
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 (d < 2000)
|
|
||||||
snprintf(distStr, sizeof(distStr), "%.0f m", d);
|
|
||||||
else
|
|
||||||
snprintf(distStr, sizeof(distStr), "%.1f km", d / 1000);
|
|
||||||
|
|
||||||
// FIXME, also keep the guess at the operators heading and add/substract
|
if (config.display.units == Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
||||||
// it. currently we don't do this and instead draw north up only.
|
if (d < (2 * MILES_TO_FEET))
|
||||||
|
snprintf(distStr, sizeof(distStr), "%.0f ft", d * METERS_TO_FEET);
|
||||||
|
else
|
||||||
|
snprintf(distStr, sizeof(distStr), "%.1f mi", d * METERS_TO_FEET / MILES_TO_FEET);
|
||||||
|
} else {
|
||||||
|
if (d < 2000)
|
||||||
|
snprintf(distStr, sizeof(distStr), "%.0f m", d);
|
||||||
|
else
|
||||||
|
snprintf(distStr, sizeof(distStr), "%.1f km", d / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
float bearingToOther =
|
float bearingToOther =
|
||||||
GeoCoord::bearing(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
GeoCoord::bearing(DegD(op.latitude_i), DegD(op.longitude_i), DegD(p.latitude_i), DegD(p.longitude_i));
|
||||||
float headingRadian = bearingToOther - myHeading;
|
// If the top of the compass is a static north then bearingToOther can be drawn on the compass directly
|
||||||
drawNodeHeading(display, compassX, compassY, headingRadian);
|
// If the top of the compass is not a static north we need adjust bearingToOther based on heading
|
||||||
|
if(!config.display.compass_north_top)
|
||||||
|
bearingToOther -= myHeading;
|
||||||
|
drawNodeHeading(display, compassX, compassY, bearingToOther);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasNodeHeading)
|
if (!hasNodeHeading)
|
||||||
@@ -788,7 +832,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
// 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));
|
// DEBUG_MSG("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, COMPASS_DIAM / 2);
|
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
|
||||||
|
|
||||||
// Must be after distStr is populated
|
// Must be after distStr is populated
|
||||||
drawColumns(display, x, y, fields);
|
drawColumns(display, x, y, fields);
|
||||||
@@ -843,7 +887,7 @@ Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue
|
|||||||
*/
|
*/
|
||||||
void Screen::doDeepSleep()
|
void Screen::doDeepSleep()
|
||||||
{
|
{
|
||||||
#ifdef HAS_EINK
|
#ifdef USE_EINK
|
||||||
static FrameCallback sleepFrames[] = {drawSleepScreen};
|
static FrameCallback sleepFrames[] = {drawSleepScreen};
|
||||||
static const int sleepFrameCount = sizeof(sleepFrames) / sizeof(sleepFrames[0]);
|
static const int sleepFrameCount = sizeof(sleepFrames) / sizeof(sleepFrames[0]);
|
||||||
ui.setFrames(sleepFrames, sleepFrameCount);
|
ui.setFrames(sleepFrames, sleepFrameCount);
|
||||||
@@ -893,7 +937,7 @@ void Screen::setup()
|
|||||||
displayWidth = dispdev.width();
|
displayWidth = dispdev.width();
|
||||||
displayHeight = dispdev.height();
|
displayHeight = dispdev.height();
|
||||||
|
|
||||||
ui.setTimePerTransition(SCREEN_TRANSITION_MSECS);
|
ui.setTimePerTransition(0);
|
||||||
|
|
||||||
ui.setIndicatorPosition(BOTTOM);
|
ui.setIndicatorPosition(BOTTOM);
|
||||||
// Defines where the first frame is located in the bar.
|
// Defines where the first frame is located in the bar.
|
||||||
@@ -922,8 +966,12 @@ void Screen::setup()
|
|||||||
|
|
||||||
#ifdef SCREEN_MIRROR
|
#ifdef SCREEN_MIRROR
|
||||||
dispdev.mirrorScreen();
|
dispdev.mirrorScreen();
|
||||||
#elif defined(SCREEN_FLIP_VERTICALLY)
|
#else
|
||||||
dispdev.flipScreenVertically();
|
// Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically flip it.
|
||||||
|
// If you have a headache now, you're welcome.
|
||||||
|
if (!config.display.flip_screen) {
|
||||||
|
dispdev.flipScreenVertically();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get our hardware ID
|
// Get our hardware ID
|
||||||
@@ -935,9 +983,11 @@ void Screen::setup()
|
|||||||
handleSetOn(true);
|
handleSetOn(true);
|
||||||
|
|
||||||
// On some ssd1306 clones, the first draw command is discarded, so draw it
|
// On some ssd1306 clones, the first draw command is discarded, so draw it
|
||||||
// twice initially.
|
// twice initially. Skip this for EINK Displays to save a few seconds during boot
|
||||||
ui.update();
|
ui.update();
|
||||||
|
#ifndef USE_EINK
|
||||||
ui.update();
|
ui.update();
|
||||||
|
#endif
|
||||||
serialSinceMsec = millis();
|
serialSinceMsec = millis();
|
||||||
|
|
||||||
// Subscribe to status updates
|
// Subscribe to status updates
|
||||||
@@ -954,7 +1004,7 @@ void Screen::setup()
|
|||||||
void Screen::forceDisplay()
|
void Screen::forceDisplay()
|
||||||
{
|
{
|
||||||
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
|
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
|
||||||
#ifdef HAS_EINK
|
#ifdef USE_EINK
|
||||||
dispdev.forceDisplay();
|
dispdev.forceDisplay();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -994,7 +1044,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 == Config_LoRaConfig_RegionCode_UNSET) {
|
||||||
setWelcomeFrames();
|
setWelcomeFrames();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1032,6 +1082,9 @@ int32_t Screen::runOnce()
|
|||||||
case Cmd::START_SHUTDOWN_SCREEN:
|
case Cmd::START_SHUTDOWN_SCREEN:
|
||||||
handleShutdownScreen();
|
handleShutdownScreen();
|
||||||
break;
|
break;
|
||||||
|
case Cmd::START_REBOOT_SCREEN:
|
||||||
|
handleRebootScreen();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_MSG("BUG: invalid cmd\n");
|
DEBUG_MSG("BUG: invalid cmd\n");
|
||||||
}
|
}
|
||||||
@@ -1052,13 +1105,8 @@ int32_t Screen::runOnce()
|
|||||||
// otherwise that breaks animations.
|
// otherwise that breaks animations.
|
||||||
if (targetFramerate != IDLE_FRAMERATE && ui.getUiState()->frameState == FIXED) {
|
if (targetFramerate != IDLE_FRAMERATE && ui.getUiState()->frameState == FIXED) {
|
||||||
// oldFrameState = ui.getUiState()->frameState;
|
// oldFrameState = ui.getUiState()->frameState;
|
||||||
DEBUG_MSG("Setting idle framerate\n");
|
|
||||||
targetFramerate = IDLE_FRAMERATE;
|
targetFramerate = IDLE_FRAMERATE;
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
|
||||||
setCPUFast(false); // Turn up the CPU to improve screen animations
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ui.setTargetFPS(targetFramerate);
|
ui.setTargetFPS(targetFramerate);
|
||||||
forceDisplay();
|
forceDisplay();
|
||||||
}
|
}
|
||||||
@@ -1180,7 +1228,7 @@ void Screen::setFrames()
|
|||||||
// call a method on debugInfoScreen object (for more details)
|
// call a method on debugInfoScreen object (for more details)
|
||||||
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
if (isWifiAvailable()) {
|
if (isWifiAvailable()) {
|
||||||
// call a method on debugInfoScreen object (for more details)
|
// call a method on debugInfoScreen object (for more details)
|
||||||
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
|
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
|
||||||
@@ -1224,6 +1272,18 @@ void Screen::handleShutdownScreen()
|
|||||||
setFastFramerate();
|
setFastFramerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::handleRebootScreen()
|
||||||
|
{
|
||||||
|
DEBUG_MSG("showing reboot screen\n");
|
||||||
|
showingNormalScreen = false;
|
||||||
|
|
||||||
|
static FrameCallback rebootFrames[] = {drawFrameReboot};
|
||||||
|
|
||||||
|
ui.disableAllIndicators();
|
||||||
|
ui.setFrames(rebootFrames, 1);
|
||||||
|
setFastFramerate();
|
||||||
|
}
|
||||||
|
|
||||||
void Screen::handleStartFirmwareUpdateScreen()
|
void Screen::handleStartFirmwareUpdateScreen()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("showing firmware screen\n");
|
DEBUG_MSG("showing firmware screen\n");
|
||||||
@@ -1270,7 +1330,6 @@ void Screen::handleOnPress()
|
|||||||
// If we are in a transition, the press must have bounced, drop it.
|
// If we are in a transition, the press must have bounced, drop it.
|
||||||
if (ui.getUiState()->frameState == FIXED) {
|
if (ui.getUiState()->frameState == FIXED) {
|
||||||
ui.nextFrame();
|
ui.nextFrame();
|
||||||
DEBUG_MSG("Setting LastScreenTransition\n");
|
|
||||||
lastScreenTransition = millis();
|
lastScreenTransition = millis();
|
||||||
setFastFramerate();
|
setFastFramerate();
|
||||||
}
|
}
|
||||||
@@ -1282,15 +1341,9 @@ void Screen::handleOnPress()
|
|||||||
|
|
||||||
void Screen::setFastFramerate()
|
void Screen::setFastFramerate()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Setting fast framerate\n");
|
|
||||||
|
|
||||||
// We are about to start a transition so speed up fps
|
// We are about to start a transition so speed up fps
|
||||||
targetFramerate = SCREEN_TRANSITION_FRAMERATE;
|
targetFramerate = SCREEN_TRANSITION_FRAMERATE;
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
|
||||||
setCPUFast(true); // Turn up the CPU to improve screen animations
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ui.setTargetFPS(targetFramerate);
|
ui.setTargetFPS(targetFramerate);
|
||||||
setInterval(0); // redraw ASAP
|
setInterval(0); // redraw ASAP
|
||||||
runASAP = true;
|
runASAP = true;
|
||||||
@@ -1342,9 +1395,9 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
// Jm
|
// Jm
|
||||||
void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
#ifdef HAS_WIFI
|
#if HAS_WIFI
|
||||||
const char *wifiName = config.wifi.ssid;
|
const char *wifiName = config.network.wifi_ssid;
|
||||||
const char *wifiPsw = config.wifi.psk;
|
const char *wifiPsw = config.network.wifi_psk;
|
||||||
|
|
||||||
displayedNodeNum = 0; // Not currently showing a node pane
|
displayedNodeNum = 0; // Not currently showing a node pane
|
||||||
|
|
||||||
@@ -1355,7 +1408,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
|
|
||||||
if (isSoftAPForced()) {
|
if (isSoftAPForced()) {
|
||||||
display->drawString(x, y, String("WiFi: Software AP (Admin)"));
|
display->drawString(x, y, String("WiFi: Software AP (Admin)"));
|
||||||
} else if (config.wifi.ap_mode) {
|
} else if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) {
|
||||||
display->drawString(x, y, String("WiFi: Software AP"));
|
display->drawString(x, y, String("WiFi: Software AP"));
|
||||||
} else if (WiFi.status() != WL_CONNECTED) {
|
} else if (WiFi.status() != WL_CONNECTED) {
|
||||||
display->drawString(x, y, String("WiFi: Not Connected"));
|
display->drawString(x, y, String("WiFi: Not Connected"));
|
||||||
@@ -1378,8 +1431,8 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
- WL_NO_SHIELD: assigned when no WiFi shield is present;
|
- WL_NO_SHIELD: assigned when no WiFi shield is present;
|
||||||
|
|
||||||
*/
|
*/
|
||||||
if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || config.wifi.ap_mode) {
|
if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) {
|
||||||
if (config.wifi.ap_mode || isSoftAPForced()) {
|
if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN || isSoftAPForced()) {
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
|
||||||
|
|
||||||
// Number of connections to the AP. Default max for the esp32 is 4
|
// Number of connections to the AP. Default max for the esp32 is 4
|
||||||
@@ -1471,7 +1524,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (config.wifi.ap_mode) {
|
if (config.network.wifi_mode== Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) {
|
||||||
if ((millis() / 10000) % 2) {
|
if ((millis() / 10000) % 2) {
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
|
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
|
||||||
} else {
|
} else {
|
||||||
@@ -1519,25 +1572,25 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||||||
auto mode = "";
|
auto mode = "";
|
||||||
|
|
||||||
switch (config.lora.modem_preset) {
|
switch (config.lora.modem_preset) {
|
||||||
case Config_LoRaConfig_ModemPreset_ShortSlow:
|
case Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||||
mode = "ShortS";
|
mode = "ShortS";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_ShortFast:
|
case Config_LoRaConfig_ModemPreset_SHORT_FAST:
|
||||||
mode = "ShortF";
|
mode = "ShortF";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_MedSlow:
|
case Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
|
||||||
mode = "MedS";
|
mode = "MedS";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_MedFast:
|
case Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
|
||||||
mode = "MedF";
|
mode = "MedF";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_LongSlow:
|
case Config_LoRaConfig_ModemPreset_LONG_SLOW:
|
||||||
mode = "LongS";
|
mode = "LongS";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_LongFast:
|
case Config_LoRaConfig_ModemPreset_LONG_FAST:
|
||||||
mode = "LongF";
|
mode = "LongF";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_VLongSlow:
|
case Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
|
||||||
mode = "VeryL";
|
mode = "VeryL";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1596,7 +1649,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||||||
|
|
||||||
// Line 3
|
// Line 3
|
||||||
if (config.display.gps_format !=
|
if (config.display.gps_format !=
|
||||||
Config_DisplayConfig_GpsCoordinateFormat_GpsFormatDMS) // if DMS then don't draw altitude
|
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
|
||||||
@@ -1612,6 +1665,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||||||
// adjust Brightness cycle trough 1 to 254 as long as attachDuringLongPress is true
|
// adjust Brightness cycle trough 1 to 254 as long as attachDuringLongPress is true
|
||||||
void Screen::adjustBrightness()
|
void Screen::adjustBrightness()
|
||||||
{
|
{
|
||||||
|
if (!useDisplay)
|
||||||
|
return;
|
||||||
|
|
||||||
if (brightness == 254) {
|
if (brightness == 254) {
|
||||||
brightness = 0;
|
brightness = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -1665,4 +1721,5 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
#endif // NO_SCREEN
|
|
||||||
|
#endif // HAS_SCREEN
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef NO_SCREEN
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !HAS_SCREEN
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
@@ -18,6 +20,7 @@ class Screen
|
|||||||
void forceDisplay() {}
|
void forceDisplay() {}
|
||||||
void startBluetoothPinScreen(uint32_t pin) {}
|
void startBluetoothPinScreen(uint32_t pin) {}
|
||||||
void stopBluetoothPinScreen() {}
|
void stopBluetoothPinScreen() {}
|
||||||
|
void startRebootScreen() {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +57,16 @@ class Screen
|
|||||||
#define BRIGHTNESS_DEFAULT 150
|
#define BRIGHTNESS_DEFAULT 150
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Meters to feet conversion
|
||||||
|
#ifndef METERS_TO_FEET
|
||||||
|
#define METERS_TO_FEET 3.28
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Feet to miles conversion
|
||||||
|
#ifndef MILES_TO_FEET
|
||||||
|
#define MILES_TO_FEET 5280
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -165,6 +178,13 @@ class Screen : public concurrency::OSThread
|
|||||||
enqueueCmd(cmd);
|
enqueueCmd(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void startRebootScreen()
|
||||||
|
{
|
||||||
|
ScreenCmd cmd;
|
||||||
|
cmd.cmd = Cmd::START_REBOOT_SCREEN;
|
||||||
|
enqueueCmd(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
/// Stops showing the bluetooth PIN screen.
|
/// Stops showing the bluetooth PIN screen.
|
||||||
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
|
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
|
||||||
|
|
||||||
@@ -202,19 +222,34 @@ class Screen : public concurrency::OSThread
|
|||||||
uint8_t last = LASTCHAR; // get last char
|
uint8_t last = LASTCHAR; // get last char
|
||||||
LASTCHAR = ch;
|
LASTCHAR = ch;
|
||||||
|
|
||||||
switch (last) { // conversion depnding on first UTF8-character
|
switch (last) { // conversion depending on first UTF8-character
|
||||||
case 0xC2: {
|
case 0xC2: {
|
||||||
SKIPREST = false;
|
SKIPREST = false;
|
||||||
return (uint8_t)ch;
|
return (uint8_t)ch;
|
||||||
}
|
}
|
||||||
case 0xC3: {
|
case 0xC3: {
|
||||||
SKIPREST = false;
|
SKIPREST = false;
|
||||||
return (uint8_t)(ch | 0xC0);
|
return (uint8_t)(ch | 0xC0);
|
||||||
}
|
}
|
||||||
|
// 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
|
||||||
|
// have empty chars for non-latin ASCII symbols
|
||||||
|
case 0xD0: {
|
||||||
|
SKIPREST = false;
|
||||||
|
if (ch == 129) return (uint8_t)(168); // Ё
|
||||||
|
if (ch > 143 && ch < 192) return (uint8_t)(ch + 48);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xD1: {
|
||||||
|
SKIPREST = false;
|
||||||
|
if (ch == 145) return (uint8_t)(184); // ё
|
||||||
|
if (ch > 127 && ch < 144) return (uint8_t)(ch + 112);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to strip out prefix chars for two-byte char formats
|
// We want to strip out prefix chars for two-byte char formats
|
||||||
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82)
|
if (ch == 0xC2 || ch == 0xC3 || ch == 0x82 || ch == 0xD0 || ch == 0xD1)
|
||||||
return (uint8_t)0;
|
return (uint8_t)0;
|
||||||
|
|
||||||
// If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the
|
// If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the
|
||||||
@@ -278,6 +313,7 @@ class Screen : public concurrency::OSThread
|
|||||||
void handlePrint(const char *text);
|
void handlePrint(const char *text);
|
||||||
void handleStartFirmwareUpdateScreen();
|
void handleStartFirmwareUpdateScreen();
|
||||||
void handleShutdownScreen();
|
void handleShutdownScreen();
|
||||||
|
void handleRebootScreen();
|
||||||
/// Rebuilds our list of frames (screens) to default ones.
|
/// Rebuilds our list of frames (screens) to default ones.
|
||||||
void setFrames();
|
void setFrames();
|
||||||
|
|
||||||
@@ -315,7 +351,7 @@ class Screen : public concurrency::OSThread
|
|||||||
SSD1306Wire dispdev;
|
SSD1306Wire dispdev;
|
||||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER)
|
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER)
|
||||||
TFTDisplay dispdev;
|
TFTDisplay dispdev;
|
||||||
#elif defined(HAS_EINK)
|
#elif defined(USE_EINK)
|
||||||
EInkDisplay dispdev;
|
EInkDisplay dispdev;
|
||||||
#elif defined(USE_ST7567)
|
#elif defined(USE_ST7567)
|
||||||
ST7567Wire dispdev;
|
ST7567Wire dispdev;
|
||||||
|
|||||||
@@ -22,13 +22,23 @@ void TFTDisplay::display(void)
|
|||||||
{
|
{
|
||||||
concurrency::LockGuard g(spiLock);
|
concurrency::LockGuard g(spiLock);
|
||||||
|
|
||||||
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
|
uint16_t x,y;
|
||||||
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
|
|
||||||
for (uint16_t y = 0; y < displayHeight; y++) {
|
for (y = 0; y < displayHeight; y++) {
|
||||||
for (uint16_t x = 0; x < displayWidth; x++) {
|
for (x = 0; x < displayWidth; x++) {
|
||||||
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
|
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
|
||||||
auto isset = buffer[x + (y / 8) * displayWidth] & (1 << (y & 7));
|
auto isset = buffer[x + (y / 8) * displayWidth] & (1 << (y & 7));
|
||||||
tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK);
|
auto dblbuf_isset = buffer_back[x + (y / 8) * displayWidth] & (1 << (y & 7));
|
||||||
|
if (isset != dblbuf_isset) {
|
||||||
|
tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Copy the Buffer to the Back Buffer
|
||||||
|
for (y = 0; y < (displayHeight / 8); y++) {
|
||||||
|
for (x = 0; x < displayWidth; x++) {
|
||||||
|
uint16_t pos = x + y * displayWidth;
|
||||||
|
buffer_back[pos] = buffer[pos];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
426
src/graphics/fonts/OLEDDisplayFontsRU.cpp
Normal file
426
src/graphics/fonts/OLEDDisplayFontsRU.cpp
Normal file
@@ -0,0 +1,426 @@
|
|||||||
|
#include "OLEDDisplayFontsRU.h"
|
||||||
|
|
||||||
|
// Font generated or edited with the glyphEditor
|
||||||
|
const uint8_t ArialMT_Plain_10_RU[] PROGMEM = {
|
||||||
|
0x0A, // Width: 10
|
||||||
|
0x0D, // Height: 13
|
||||||
|
0x20, // First char: 32
|
||||||
|
0xE0, // Number of chars: 224
|
||||||
|
|
||||||
|
// Jump Table:
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 32
|
||||||
|
0x00, 0x00, 0x04, 0x03, // 33
|
||||||
|
0x00, 0x04, 0x05, 0x04, // 34
|
||||||
|
0x00, 0x09, 0x09, 0x06, // 35
|
||||||
|
0x00, 0x12, 0x0A, 0x06, // 36
|
||||||
|
0x00, 0x1C, 0x10, 0x09, // 37
|
||||||
|
0x00, 0x2C, 0x0E, 0x08, // 38
|
||||||
|
0x00, 0x3A, 0x01, 0x02, // 39
|
||||||
|
0x00, 0x3B, 0x06, 0x04, // 40
|
||||||
|
0x00, 0x41, 0x06, 0x04, // 41
|
||||||
|
0x00, 0x47, 0x05, 0x04, // 42
|
||||||
|
0x00, 0x4C, 0x09, 0x06, // 43
|
||||||
|
0x00, 0x55, 0x04, 0x03, // 44
|
||||||
|
0x00, 0x59, 0x03, 0x03, // 45
|
||||||
|
0x00, 0x5C, 0x04, 0x03, // 46
|
||||||
|
0x00, 0x60, 0x05, 0x04, // 47
|
||||||
|
0x00, 0x65, 0x0A, 0x06, // 48
|
||||||
|
0x00, 0x6F, 0x08, 0x05, // 49
|
||||||
|
0x00, 0x77, 0x0A, 0x06, // 50
|
||||||
|
0x00, 0x81, 0x0A, 0x06, // 51
|
||||||
|
0x00, 0x8B, 0x0B, 0x07, // 52
|
||||||
|
0x00, 0x96, 0x0A, 0x06, // 53
|
||||||
|
0x00, 0xA0, 0x0A, 0x06, // 54
|
||||||
|
0x00, 0xAA, 0x09, 0x06, // 55
|
||||||
|
0x00, 0xB3, 0x0A, 0x06, // 56
|
||||||
|
0x00, 0xBD, 0x0A, 0x06, // 57
|
||||||
|
0x00, 0xC7, 0x04, 0x03, // 58
|
||||||
|
0x00, 0xCB, 0x04, 0x03, // 59
|
||||||
|
0x00, 0xCF, 0x0A, 0x06, // 60
|
||||||
|
0x00, 0xD9, 0x09, 0x06, // 61
|
||||||
|
0x00, 0xE2, 0x09, 0x06, // 62
|
||||||
|
0x00, 0xEB, 0x0B, 0x07, // 63
|
||||||
|
0x00, 0xF6, 0x14, 0x0B, // 64
|
||||||
|
0x01, 0x0A, 0x0E, 0x08, // 65
|
||||||
|
0x01, 0x18, 0x0C, 0x07, // 66
|
||||||
|
0x01, 0x24, 0x0C, 0x07, // 67
|
||||||
|
0x01, 0x30, 0x0B, 0x07, // 68
|
||||||
|
0x01, 0x3B, 0x0C, 0x07, // 69
|
||||||
|
0x01, 0x47, 0x09, 0x06, // 70
|
||||||
|
0x01, 0x50, 0x0D, 0x08, // 71
|
||||||
|
0x01, 0x5D, 0x0C, 0x07, // 72
|
||||||
|
0x01, 0x69, 0x04, 0x03, // 73
|
||||||
|
0x01, 0x6D, 0x08, 0x05, // 74
|
||||||
|
0x01, 0x75, 0x0E, 0x08, // 75
|
||||||
|
0x01, 0x83, 0x0C, 0x07, // 76
|
||||||
|
0x01, 0x8F, 0x10, 0x09, // 77
|
||||||
|
0x01, 0x9F, 0x0C, 0x07, // 78
|
||||||
|
0x01, 0xAB, 0x0E, 0x08, // 79
|
||||||
|
0x01, 0xB9, 0x0B, 0x07, // 80
|
||||||
|
0x01, 0xC4, 0x0E, 0x08, // 81
|
||||||
|
0x01, 0xD2, 0x0C, 0x07, // 82
|
||||||
|
0x01, 0xDE, 0x0C, 0x07, // 83
|
||||||
|
0x01, 0xEA, 0x0B, 0x07, // 84
|
||||||
|
0x01, 0xF5, 0x0C, 0x07, // 85
|
||||||
|
0x02, 0x01, 0x0D, 0x08, // 86
|
||||||
|
0x02, 0x0E, 0x11, 0x0A, // 87
|
||||||
|
0x02, 0x1F, 0x0E, 0x08, // 88
|
||||||
|
0x02, 0x2D, 0x0D, 0x08, // 89
|
||||||
|
0x02, 0x3A, 0x0C, 0x07, // 90
|
||||||
|
0x02, 0x46, 0x06, 0x04, // 91
|
||||||
|
0x02, 0x4C, 0x06, 0x04, // 92
|
||||||
|
0x02, 0x52, 0x04, 0x03, // 93
|
||||||
|
0x02, 0x56, 0x09, 0x06, // 94
|
||||||
|
0x02, 0x5F, 0x0C, 0x07, // 95
|
||||||
|
0x02, 0x6B, 0x03, 0x03, // 96
|
||||||
|
0x02, 0x6E, 0x0A, 0x06, // 97
|
||||||
|
0x02, 0x78, 0x0A, 0x06, // 98
|
||||||
|
0x02, 0x82, 0x0A, 0x06, // 99
|
||||||
|
0x02, 0x8C, 0x0A, 0x06, // 100
|
||||||
|
0x02, 0x96, 0x0A, 0x06, // 101
|
||||||
|
0x02, 0xA0, 0x05, 0x04, // 102
|
||||||
|
0x02, 0xA5, 0x0A, 0x06, // 103
|
||||||
|
0x02, 0xAF, 0x0A, 0x06, // 104
|
||||||
|
0x02, 0xB9, 0x04, 0x03, // 105
|
||||||
|
0x02, 0xBD, 0x04, 0x03, // 106
|
||||||
|
0x02, 0xC1, 0x08, 0x05, // 107
|
||||||
|
0x02, 0xC9, 0x04, 0x03, // 108
|
||||||
|
0x02, 0xCD, 0x10, 0x09, // 109
|
||||||
|
0x02, 0xDD, 0x0A, 0x06, // 110
|
||||||
|
0x02, 0xE7, 0x0A, 0x06, // 111
|
||||||
|
0x02, 0xF1, 0x0A, 0x06, // 112
|
||||||
|
0x02, 0xFB, 0x0A, 0x06, // 113
|
||||||
|
0x03, 0x05, 0x05, 0x04, // 114
|
||||||
|
0x03, 0x0A, 0x08, 0x05, // 115
|
||||||
|
0x03, 0x12, 0x06, 0x04, // 116
|
||||||
|
0x03, 0x18, 0x0A, 0x06, // 117
|
||||||
|
0x03, 0x22, 0x09, 0x06, // 118
|
||||||
|
0x03, 0x2B, 0x0E, 0x08, // 119
|
||||||
|
0x03, 0x39, 0x0A, 0x06, // 120
|
||||||
|
0x03, 0x43, 0x09, 0x06, // 121
|
||||||
|
0x03, 0x4C, 0x0A, 0x06, // 122
|
||||||
|
0x03, 0x56, 0x06, 0x04, // 123
|
||||||
|
0x03, 0x5C, 0x04, 0x03, // 124
|
||||||
|
0x03, 0x60, 0x05, 0x04, // 125
|
||||||
|
0x03, 0x65, 0x09, 0x06, // 126
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 127
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 128
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 129
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 130
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 131
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 132
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 133
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 134
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 135
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 136
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 137
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 138
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 139
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 140
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 141
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 142
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 143
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 144
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 145
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 146
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 147
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 148
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 149
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 150
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 151
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 152
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 153
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 154
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 155
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 156
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 157
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 158
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 159
|
||||||
|
0xFF, 0xFF, 0x00, 0x0A, // 160
|
||||||
|
0x03, 0x6E, 0x04, 0x03, // 161
|
||||||
|
0x03, 0x72, 0x0A, 0x06, // 162
|
||||||
|
0x03, 0x7C, 0x0C, 0x07, // 163
|
||||||
|
0x03, 0x88, 0x0A, 0x06, // 164
|
||||||
|
0x03, 0x92, 0x0A, 0x06, // 165
|
||||||
|
0x03, 0x9C, 0x04, 0x03, // 166
|
||||||
|
0x03, 0xA0, 0x0A, 0x06, // 167
|
||||||
|
0x03, 0xAA, 0x0C, 0x07, // 168
|
||||||
|
0x03, 0xB6, 0x0D, 0x08, // 169
|
||||||
|
0x03, 0xC3, 0x07, 0x05, // 170
|
||||||
|
0x03, 0xCA, 0x0A, 0x06, // 171
|
||||||
|
0x03, 0xD4, 0x09, 0x06, // 172
|
||||||
|
0x03, 0xDD, 0x03, 0x03, // 173
|
||||||
|
0x03, 0xE0, 0x0D, 0x08, // 174
|
||||||
|
0x03, 0xED, 0x0B, 0x07, // 175
|
||||||
|
0x03, 0xF8, 0x07, 0x05, // 176
|
||||||
|
0x03, 0xFF, 0x0A, 0x06, // 177
|
||||||
|
0x04, 0x09, 0x05, 0x04, // 178
|
||||||
|
0x04, 0x0E, 0x05, 0x04, // 179
|
||||||
|
0x04, 0x13, 0x05, 0x04, // 180
|
||||||
|
0x04, 0x18, 0x0A, 0x06, // 181
|
||||||
|
0x04, 0x22, 0x09, 0x06, // 182
|
||||||
|
0x04, 0x2B, 0x03, 0x03, // 183
|
||||||
|
0x04, 0x2E, 0x0B, 0x07, // 184
|
||||||
|
0x04, 0x39, 0x0B, 0x07, // 185
|
||||||
|
0x04, 0x44, 0x07, 0x05, // 186
|
||||||
|
0x04, 0x4B, 0x0A, 0x06, // 187
|
||||||
|
0x04, 0x55, 0x10, 0x09, // 188
|
||||||
|
0x04, 0x65, 0x10, 0x09, // 189
|
||||||
|
0x04, 0x75, 0x10, 0x09, // 190
|
||||||
|
0x04, 0x85, 0x0A, 0x06, // 191
|
||||||
|
0x04, 0x8F, 0x0C, 0x07, // 192
|
||||||
|
0x04, 0x9B, 0x0C, 0x07, // 193
|
||||||
|
0x04, 0xA7, 0x0C, 0x07, // 194
|
||||||
|
0x04, 0xB3, 0x0B, 0x07, // 195
|
||||||
|
0x04, 0xBE, 0x0C, 0x07, // 196
|
||||||
|
0x04, 0xCA, 0x0C, 0x07, // 197
|
||||||
|
0x04, 0xD6, 0x0C, 0x07, // 198
|
||||||
|
0x04, 0xE2, 0x0C, 0x07, // 199
|
||||||
|
0x04, 0xEE, 0x0C, 0x07, // 200
|
||||||
|
0x04, 0xFA, 0x0C, 0x07, // 201
|
||||||
|
0x05, 0x06, 0x0C, 0x07, // 202
|
||||||
|
0x05, 0x12, 0x0C, 0x07, // 203
|
||||||
|
0x05, 0x1E, 0x0C, 0x07, // 204
|
||||||
|
0x05, 0x2A, 0x0C, 0x07, // 205
|
||||||
|
0x05, 0x36, 0x0C, 0x07, // 206
|
||||||
|
0x05, 0x42, 0x0C, 0x07, // 207
|
||||||
|
0x05, 0x4E, 0x0B, 0x07, // 208
|
||||||
|
0x05, 0x59, 0x0C, 0x07, // 209
|
||||||
|
0x05, 0x65, 0x0B, 0x07, // 210
|
||||||
|
0x05, 0x70, 0x0C, 0x07, // 211
|
||||||
|
0x05, 0x7C, 0x0B, 0x07, // 212
|
||||||
|
0x05, 0x87, 0x0C, 0x07, // 213
|
||||||
|
0x05, 0x93, 0x0C, 0x07, // 214
|
||||||
|
0x05, 0x9F, 0x0C, 0x07, // 215
|
||||||
|
0x05, 0xAB, 0x0C, 0x07, // 216
|
||||||
|
0x05, 0xB7, 0x0E, 0x08, // 217
|
||||||
|
0x05, 0xC5, 0x0C, 0x07, // 218
|
||||||
|
0x05, 0xD1, 0x0C, 0x07, // 219
|
||||||
|
0x05, 0xDD, 0x0C, 0x07, // 220
|
||||||
|
0x05, 0xE9, 0x0C, 0x07, // 221
|
||||||
|
0x05, 0xF5, 0x0C, 0x07, // 222
|
||||||
|
0x06, 0x01, 0x0C, 0x07, // 223
|
||||||
|
0x06, 0x0D, 0x0C, 0x07, // 224
|
||||||
|
0x06, 0x19, 0x0C, 0x07, // 225
|
||||||
|
0x06, 0x25, 0x0C, 0x07, // 226
|
||||||
|
0x06, 0x31, 0x0B, 0x07, // 227
|
||||||
|
0x06, 0x3C, 0x0C, 0x07, // 228
|
||||||
|
0x06, 0x48, 0x0B, 0x07, // 229
|
||||||
|
0x06, 0x53, 0x0C, 0x07, // 230
|
||||||
|
0x06, 0x5F, 0x0C, 0x07, // 231
|
||||||
|
0x06, 0x6B, 0x0C, 0x07, // 232
|
||||||
|
0x06, 0x77, 0x0C, 0x07, // 233
|
||||||
|
0x06, 0x83, 0x0C, 0x07, // 234
|
||||||
|
0x06, 0x8F, 0x0C, 0x07, // 235
|
||||||
|
0x06, 0x9B, 0x0C, 0x07, // 236
|
||||||
|
0x06, 0xA7, 0x0C, 0x07, // 237
|
||||||
|
0x06, 0xB3, 0x0C, 0x07, // 238
|
||||||
|
0x06, 0xBF, 0x0C, 0x07, // 239
|
||||||
|
0x06, 0xCB, 0x0B, 0x07, // 240
|
||||||
|
0x06, 0xD6, 0x0C, 0x07, // 241
|
||||||
|
0x06, 0xE2, 0x0B, 0x07, // 242
|
||||||
|
0x06, 0xED, 0x0C, 0x07, // 243
|
||||||
|
0x06, 0xF9, 0x0B, 0x07, // 244
|
||||||
|
0x07, 0x04, 0x0C, 0x07, // 245
|
||||||
|
0x07, 0x10, 0x0C, 0x07, // 246
|
||||||
|
0x07, 0x1C, 0x0C, 0x07, // 247
|
||||||
|
0x07, 0x28, 0x0C, 0x07, // 248
|
||||||
|
0x07, 0x34, 0x0E, 0x08, // 249
|
||||||
|
0x07, 0x42, 0x0C, 0x07, // 250
|
||||||
|
0x07, 0x4E, 0x0C, 0x07, // 251
|
||||||
|
0x07, 0x5A, 0x0C, 0x07, // 252
|
||||||
|
0x07, 0x66, 0x0C, 0x07, // 253
|
||||||
|
0x07, 0x72, 0x0C, 0x07, // 254
|
||||||
|
0x07, 0x7E, 0x0C, 0x07, // 255
|
||||||
|
|
||||||
|
// Font Data:
|
||||||
|
0x00, 0x00, 0xF8, 0x02, // 33
|
||||||
|
0x38, 0x00, 0x00, 0x00, 0x38, // 34
|
||||||
|
0xA0, 0x03, 0xE0, 0x00, 0xB8, 0x03, 0xE0, 0x00, 0xB8, // 35
|
||||||
|
0x30, 0x01, 0x28, 0x02, 0xF8, 0x07, 0x48, 0x02, 0x90, 0x01, // 36
|
||||||
|
0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x30, 0x03, 0xC0, 0x00, 0xB0, 0x01, 0x48, 0x02, 0x80, 0x01, // 37
|
||||||
|
0x80, 0x01, 0x50, 0x02, 0x68, 0x02, 0xA8, 0x02, 0x18, 0x01, 0x80, 0x03, 0x80, 0x02, // 38
|
||||||
|
0x38, // 39
|
||||||
|
0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, // 40
|
||||||
|
0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 41
|
||||||
|
0x28, 0x00, 0x18, 0x00, 0x28, // 42
|
||||||
|
0x40, 0x00, 0x40, 0x00, 0xF0, 0x01, 0x40, 0x00, 0x40, // 43
|
||||||
|
0x00, 0x00, 0x00, 0x06, // 44
|
||||||
|
0x80, 0x00, 0x80, // 45
|
||||||
|
0x00, 0x00, 0x00, 0x02, // 46
|
||||||
|
0x00, 0x03, 0xE0, 0x00, 0x18, // 47
|
||||||
|
0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 48
|
||||||
|
0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0xF8, 0x03, // 49
|
||||||
|
0x10, 0x02, 0x08, 0x03, 0x88, 0x02, 0x48, 0x02, 0x30, 0x02, // 50
|
||||||
|
0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 51
|
||||||
|
0xC0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x80, // 52
|
||||||
|
0x60, 0x01, 0x38, 0x02, 0x28, 0x02, 0x28, 0x02, 0xC8, 0x01, // 53
|
||||||
|
0xF0, 0x01, 0x28, 0x02, 0x28, 0x02, 0x28, 0x02, 0xD0, 0x01, // 54
|
||||||
|
0x08, 0x00, 0x08, 0x03, 0xC8, 0x00, 0x38, 0x00, 0x08, // 55
|
||||||
|
0xB0, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 56
|
||||||
|
0x70, 0x01, 0x88, 0x02, 0x88, 0x02, 0x88, 0x02, 0xF0, 0x01, // 57
|
||||||
|
0x00, 0x00, 0x20, 0x02, // 58
|
||||||
|
0x00, 0x00, 0x20, 0x06, // 59
|
||||||
|
0x00, 0x00, 0x40, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x10, 0x01, // 60
|
||||||
|
0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0xA0, // 61
|
||||||
|
0x00, 0x00, 0x10, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 62
|
||||||
|
0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0xC8, 0x02, 0x48, 0x00, 0x30, // 63
|
||||||
|
0x00, 0x00, 0xC0, 0x03, 0x30, 0x04, 0xD0, 0x09, 0x28, 0x0A, 0x28, 0x0A, 0xC8, 0x0B, 0x68, 0x0A, 0x10, 0x05, 0xE0, 0x04, // 64
|
||||||
|
0x00, 0x02, 0xC0, 0x01, 0xB0, 0x00, 0x88, 0x00, 0xB0, 0x00, 0xC0, 0x01, 0x00, 0x02, // 65
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 66
|
||||||
|
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 67
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, 0xE0, // 68
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, // 69
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x08, // 70
|
||||||
|
0x00, 0x00, 0xE0, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x50, 0x01, 0xC0, // 71
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 72
|
||||||
|
0x00, 0x00, 0xF8, 0x03, // 73
|
||||||
|
0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 74
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 75
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, // 76
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x30, 0x00, 0xF8, 0x03, // 77
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x30, 0x00, 0x40, 0x00, 0x80, 0x01, 0xF8, 0x03, // 78
|
||||||
|
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 79
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 80
|
||||||
|
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x03, 0x08, 0x03, 0xF0, 0x02, // 81
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0xC8, 0x00, 0x30, 0x03, // 82
|
||||||
|
0x00, 0x00, 0x30, 0x01, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x90, 0x01, // 83
|
||||||
|
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 84
|
||||||
|
0x00, 0x00, 0xF8, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x01, // 85
|
||||||
|
0x08, 0x00, 0x70, 0x00, 0x80, 0x01, 0x00, 0x02, 0x80, 0x01, 0x70, 0x00, 0x08, // 86
|
||||||
|
0x18, 0x00, 0xE0, 0x01, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x02, 0xE0, 0x01, 0x18, // 87
|
||||||
|
0x00, 0x02, 0x08, 0x01, 0x90, 0x00, 0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x02, // 88
|
||||||
|
0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0xC0, 0x03, 0x20, 0x00, 0x10, 0x00, 0x08, // 89
|
||||||
|
0x08, 0x03, 0x88, 0x02, 0xC8, 0x02, 0x68, 0x02, 0x38, 0x02, 0x18, 0x02, // 90
|
||||||
|
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, // 91
|
||||||
|
0x18, 0x00, 0xE0, 0x00, 0x00, 0x03, // 92
|
||||||
|
0x08, 0x08, 0xF8, 0x0F, // 93
|
||||||
|
0x40, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x40, // 94
|
||||||
|
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 95
|
||||||
|
0x08, 0x00, 0x10, // 96
|
||||||
|
0x00, 0x00, 0x00, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x03, // 97
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 98
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x40, 0x01, // 99
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xF8, 0x03, // 100
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x02, // 101
|
||||||
|
0x20, 0x00, 0xF0, 0x03, 0x28, // 102
|
||||||
|
0x00, 0x00, 0xC0, 0x05, 0x20, 0x0A, 0x20, 0x0A, 0xE0, 0x07, // 103
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 104
|
||||||
|
0x00, 0x00, 0xE8, 0x03, // 105
|
||||||
|
0x00, 0x08, 0xE8, 0x07, // 106
|
||||||
|
0xF8, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, // 107
|
||||||
|
0x00, 0x00, 0xF8, 0x03, // 108
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 109
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x03, // 110
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 111
|
||||||
|
0x00, 0x00, 0xE0, 0x0F, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 112
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xE0, 0x0F, // 113
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x20, // 114
|
||||||
|
0x40, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x20, 0x01, // 115
|
||||||
|
0x20, 0x00, 0xF8, 0x03, 0x20, 0x02, // 116
|
||||||
|
0x00, 0x00, 0xE0, 0x01, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 117
|
||||||
|
0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, // 118
|
||||||
|
0xE0, 0x01, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0xC0, 0x01, 0x00, 0x02, 0xE0, 0x01, // 119
|
||||||
|
0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 120
|
||||||
|
0x20, 0x00, 0xC0, 0x09, 0x00, 0x06, 0xC0, 0x01, 0x20, // 121
|
||||||
|
0x20, 0x02, 0x20, 0x03, 0xA0, 0x02, 0x60, 0x02, 0x20, 0x02, // 122
|
||||||
|
0x80, 0x00, 0x78, 0x0F, 0x08, 0x08, // 123
|
||||||
|
0x00, 0x00, 0xF8, 0x0F, // 124
|
||||||
|
0x08, 0x08, 0x78, 0x0F, 0x80, // 125
|
||||||
|
0xC0, 0x00, 0x40, 0x00, 0xC0, 0x00, 0x80, 0x00, 0xC0, // 126
|
||||||
|
0x00, 0x00, 0xA0, 0x0F, // 161
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x0F, 0x78, 0x02, 0x40, 0x01, // 162
|
||||||
|
0x40, 0x02, 0x70, 0x03, 0xC8, 0x02, 0x48, 0x02, 0x08, 0x02, 0x10, 0x02, // 163
|
||||||
|
0x00, 0x00, 0xE0, 0x01, 0x20, 0x01, 0x20, 0x01, 0xE0, 0x01, // 164
|
||||||
|
0x48, 0x01, 0x70, 0x01, 0xC0, 0x03, 0x70, 0x01, 0x48, 0x01, // 165
|
||||||
|
0x00, 0x00, 0x38, 0x0F, // 166
|
||||||
|
0xD0, 0x04, 0x28, 0x09, 0x48, 0x09, 0x48, 0x0A, 0x90, 0x05, // 167
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0xA8, 0x02, 0xA0, 0x02, 0xA8, 0x02, 0x20, 0x02, // 168
|
||||||
|
0xE0, 0x00, 0x10, 0x01, 0x48, 0x02, 0xA8, 0x02, 0xA8, 0x02, 0x10, 0x01, 0xE0, // 169
|
||||||
|
0x68, 0x00, 0x68, 0x00, 0x68, 0x00, 0x78, // 170
|
||||||
|
0x00, 0x00, 0x80, 0x01, 0x40, 0x02, 0x80, 0x01, 0x40, 0x02, // 171
|
||||||
|
0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, // 172
|
||||||
|
0x80, 0x00, 0x80, // 173
|
||||||
|
0xE0, 0x00, 0x10, 0x01, 0xE8, 0x02, 0x68, 0x02, 0xC8, 0x02, 0x10, 0x01, 0xE0, // 174
|
||||||
|
0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, // 175
|
||||||
|
0x00, 0x00, 0x38, 0x00, 0x28, 0x00, 0x38, // 176
|
||||||
|
0x40, 0x02, 0x40, 0x02, 0xF0, 0x03, 0x40, 0x02, 0x40, 0x02, // 177
|
||||||
|
0x48, 0x00, 0x68, 0x00, 0x58, // 178
|
||||||
|
0x48, 0x00, 0x58, 0x00, 0x68, // 179
|
||||||
|
0x00, 0x00, 0x10, 0x00, 0x08, // 180
|
||||||
|
0x00, 0x00, 0xE0, 0x0F, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, // 181
|
||||||
|
0x70, 0x00, 0xF8, 0x0F, 0x08, 0x00, 0xF8, 0x0F, 0x08, // 182
|
||||||
|
0x00, 0x00, 0x40, // 183
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0xA8, 0x02, 0xA0, 0x02, 0xA8, 0x02, 0xC0, // 184
|
||||||
|
0x00, 0x00, 0xF0, 0x03, 0x40, 0x00, 0x80, 0x00, 0xF8, 0x03, 0x08, // 185
|
||||||
|
0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 186
|
||||||
|
0x00, 0x00, 0x40, 0x02, 0x80, 0x01, 0x40, 0x02, 0x80, 0x01, // 187
|
||||||
|
0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0xC0, 0x00, 0x20, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 188
|
||||||
|
0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0x80, 0x00, 0x60, 0x00, 0x50, 0x02, 0x48, 0x03, 0xC0, 0x02, // 189
|
||||||
|
0x48, 0x00, 0x58, 0x00, 0x68, 0x03, 0x80, 0x00, 0x60, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 190
|
||||||
|
0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0xA0, 0x09, 0x00, 0x04, // 191
|
||||||
|
0x00, 0x00, 0xF0, 0x03, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xF0, 0x03, // 192
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x88, 0x01, // 193
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 194
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x18, // 195
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0xFC, 0x03, 0x04, 0x02, 0xFC, 0x03, 0x00, 0x02, // 196
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x08, 0x02, // 197
|
||||||
|
0x00, 0x00, 0xB8, 0x03, 0x40, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xB8, 0x03, // 198
|
||||||
|
0x00, 0x00, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 199
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0xF8, 0x03, // 200
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x08, 0x01, 0x90, 0x00, 0x48, 0x00, 0xE0, 0x03, // 201
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xA0, 0x00, 0x10, 0x01, 0x08, 0x02, // 202
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 203
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x10, 0x00, 0x60, 0x00, 0x10, 0x00, 0xF8, 0x03, // 204
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 205
|
||||||
|
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 206
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 207
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 208
|
||||||
|
0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 209
|
||||||
|
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 210
|
||||||
|
0x00, 0x00, 0x38, 0x00, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0xF8, 0x01, // 211
|
||||||
|
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x88, 0x00, 0x70, // 212
|
||||||
|
0x00, 0x00, 0x18, 0x03, 0xA0, 0x00, 0x40, 0x00, 0xA0, 0x00, 0x18, 0x03, // 213
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, // 214
|
||||||
|
0x00, 0x00, 0x38, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 215
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, // 216
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x06, // 217
|
||||||
|
0x00, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 218
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xF8, 0x03, // 219
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 220
|
||||||
|
0x00, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 221
|
||||||
|
0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xF0, 0x01, 0x08, 0x02, 0xF0, 0x01, // 222
|
||||||
|
0x00, 0x00, 0x30, 0x02, 0x48, 0x01, 0xC8, 0x00, 0x48, 0x00, 0xF8, 0x03, // 223
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x03, // 224
|
||||||
|
0x00, 0x00, 0xE0, 0x01, 0x50, 0x02, 0x50, 0x02, 0x48, 0x02, 0x88, 0x01, // 225
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 226
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, // 227
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x20, 0x02, 0xE0, 0x03, 0x00, 0x02, // 228
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, // 229
|
||||||
|
0x00, 0x00, 0x60, 0x03, 0x80, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x60, 0x03, // 230
|
||||||
|
0x00, 0x00, 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 231
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 232
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x00, 0x01, 0x98, 0x00, 0x40, 0x00, 0xE0, 0x03, // 233
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 234
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 235
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 236
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 237
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 238
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 239
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 240
|
||||||
|
0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x40, 0x02, // 241
|
||||||
|
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, // 242
|
||||||
|
0x00, 0x00, 0x60, 0x00, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0xE0, 0x01, // 243
|
||||||
|
0x00, 0x00, 0xC0, 0x00, 0x20, 0x01, 0xE0, 0x03, 0x20, 0x01, 0xC0, // 244
|
||||||
|
0x00, 0x00, 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 245
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, // 246
|
||||||
|
0x00, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 247
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, // 248
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x06, // 249
|
||||||
|
0x00, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 250
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, 0xE0, 0x03, // 251
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 252
|
||||||
|
0x00, 0x00, 0x40, 0x01, 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x01, // 253
|
||||||
|
0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, 0xC0, 0x01, // 254
|
||||||
|
0x00, 0x00, 0x40, 0x02, 0xA0, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0xE0, 0x03, // 255
|
||||||
|
};
|
||||||
11
src/graphics/fonts/OLEDDisplayFontsRU.h
Normal file
11
src/graphics/fonts/OLEDDisplayFontsRU.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef OLEDDISPLAYFONTSRU_h
|
||||||
|
#define OLEDDISPLAYFONTSRU_h
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
#include <Arduino.h>
|
||||||
|
#elif __MBED__
|
||||||
|
#define PROGMEM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern const uint8_t ArialMT_Plain_10_RU[] PROGMEM;
|
||||||
|
#endif
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Observer.h"
|
#include "Observer.h"
|
||||||
|
|
||||||
|
#define ANYKEY 0xFF
|
||||||
|
#define MATRIXKEY 0xFE
|
||||||
|
|
||||||
typedef struct _InputEvent {
|
typedef struct _InputEvent {
|
||||||
const char* source;
|
const char* source;
|
||||||
char inputEvent;
|
char inputEvent;
|
||||||
|
char kbchar;
|
||||||
} InputEvent;
|
} InputEvent;
|
||||||
class InputBroker :
|
class InputBroker :
|
||||||
public Observable<const InputEvent *>
|
public Observable<const InputEvent *>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ void RotaryEncoderInterruptBase::init(
|
|||||||
int32_t RotaryEncoderInterruptBase::runOnce()
|
int32_t RotaryEncoderInterruptBase::runOnce()
|
||||||
{
|
{
|
||||||
InputEvent e;
|
InputEvent e;
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
|
|
||||||
if (this->action == ROTARY_ACTION_PRESSED) {
|
if (this->action == ROTARY_ACTION_PRESSED) {
|
||||||
@@ -48,7 +48,7 @@ int32_t RotaryEncoderInterruptBase::runOnce()
|
|||||||
e.inputEvent = this->_eventCcw;
|
e.inputEvent = this->_eventCcw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.inputEvent != ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE) {
|
if (e.inputEvent != ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||||
this->notifyObservers(&e);
|
this->notifyObservers(&e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ class RotaryEncoderInterruptBase : public Observable<const InputEvent *>, privat
|
|||||||
private:
|
private:
|
||||||
uint8_t _pinA = 0;
|
uint8_t _pinA = 0;
|
||||||
uint8_t _pinB = 0;
|
uint8_t _pinB = 0;
|
||||||
char _eventCw = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
char _eventCw = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
char _eventCcw = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
char _eventCcw = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
char _eventPressed = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
char _eventPressed = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
const char *_originName;
|
const char *_originName;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ class UpDownInterruptBase : public Observable<const InputEvent *>
|
|||||||
private:
|
private:
|
||||||
uint8_t _pinDown = 0;
|
uint8_t _pinDown = 0;
|
||||||
uint8_t _pinUp = 0;
|
uint8_t _pinUp = 0;
|
||||||
char _eventDown = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
char _eventDown = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
char _eventUp = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
char _eventUp = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
char _eventPressed = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
char _eventPressed = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
const char *_originName;
|
const char *_originName;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ void UpDownInterruptImpl1::init()
|
|||||||
uint8_t pinDown = moduleConfig.canned_message.inputbroker_pin_b;
|
uint8_t pinDown = moduleConfig.canned_message.inputbroker_pin_b;
|
||||||
uint8_t pinPress = moduleConfig.canned_message.inputbroker_pin_press;
|
uint8_t pinPress = moduleConfig.canned_message.inputbroker_pin_press;
|
||||||
|
|
||||||
char eventDown = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_KEY_DOWN);
|
char eventDown = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_DOWN);
|
||||||
char eventUp = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_KEY_UP);
|
char eventUp = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_UP);
|
||||||
char eventPressed = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_KEY_SELECT);
|
char eventPressed = static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_SELECT);
|
||||||
|
|
||||||
UpDownInterruptBase::init(pinDown, pinUp, pinPress, eventDown, eventUp, eventPressed, UpDownInterruptImpl1::handleIntDown,
|
UpDownInterruptBase::init(pinDown, pinUp, pinPress, eventDown, eventUp, eventPressed, UpDownInterruptImpl1::handleIntDown,
|
||||||
UpDownInterruptImpl1::handleIntUp, UpDownInterruptImpl1::handleIntPressed);
|
UpDownInterruptImpl1::handleIntUp, UpDownInterruptImpl1::handleIntPressed);
|
||||||
|
|||||||
@@ -16,6 +16,5 @@ void CardKbI2cImpl::init()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_MSG("registerSource\n");
|
|
||||||
inputBroker->registerSource(this);
|
inputBroker->registerSource(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
#include "facesKbI2cImpl.h"
|
|
||||||
#include "InputBroker.h"
|
|
||||||
|
|
||||||
FacesKbI2cImpl *facesKbI2cImpl;
|
|
||||||
|
|
||||||
FacesKbI2cImpl::FacesKbI2cImpl() :
|
|
||||||
KbI2cBase("facesKB")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void FacesKbI2cImpl::init()
|
|
||||||
{
|
|
||||||
if (faceskb_found != FACESKB_ADDR)
|
|
||||||
{
|
|
||||||
// Input device is not detected.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputBroker->registerSource(this);
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "kbI2cBase.h"
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The idea behind this class to have static methods for the event handlers.
|
|
||||||
* Check attachInterrupt() at RotaryEncoderInteruptBase.cpp
|
|
||||||
* Technically you can have as many rotary encoders hardver attached
|
|
||||||
* to your device as you wish, but you always need to have separate event
|
|
||||||
* handlers, thus you need to have a RotaryEncoderInterrupt implementation.
|
|
||||||
*/
|
|
||||||
class FacesKbI2cImpl :
|
|
||||||
public KbI2cBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FacesKbI2cImpl();
|
|
||||||
void init();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern FacesKbI2cImpl *facesKbI2cImpl;
|
|
||||||
@@ -2,48 +2,114 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
|
||||||
|
extern uint8_t cardkb_found;
|
||||||
|
extern uint8_t kb_model;
|
||||||
|
|
||||||
KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
||||||
{
|
{
|
||||||
this->_originName = name;
|
this->_originName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t read_from_14004(uint8_t reg, uint8_t *data, uint8_t length)
|
||||||
|
{
|
||||||
|
uint8_t readflag = 0;
|
||||||
|
Wire.beginTransmission(CARDKB_ADDR);
|
||||||
|
Wire.write(reg);
|
||||||
|
Wire.endTransmission(); // stop transmitting
|
||||||
|
delay(20);
|
||||||
|
Wire.requestFrom(CARDKB_ADDR, (int)length);
|
||||||
|
int i = 0;
|
||||||
|
while ( Wire.available() ) // slave may send less than requested
|
||||||
|
{
|
||||||
|
data[i++] = Wire.read(); // receive a byte as a proper uint8_t
|
||||||
|
readflag = 1;
|
||||||
|
}
|
||||||
|
return readflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_to_14004(uint8_t reg, uint8_t data)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(CARDKB_ADDR);
|
||||||
|
Wire.write(reg);
|
||||||
|
Wire.write(data);
|
||||||
|
Wire.endTransmission(); // stop transmitting
|
||||||
|
}
|
||||||
|
|
||||||
int32_t KbI2cBase::runOnce()
|
int32_t KbI2cBase::runOnce()
|
||||||
{
|
{
|
||||||
InputEvent e;
|
if (cardkb_found != CARDKB_ADDR){
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE;
|
// Input device is not detected.
|
||||||
e.source = this->_originName;
|
return INT32_MAX;
|
||||||
|
|
||||||
Wire.requestFrom(CARDKB_ADDR, 1);
|
|
||||||
|
|
||||||
while (Wire.available()) {
|
|
||||||
char c = Wire.read();
|
|
||||||
switch (c) {
|
|
||||||
case 0x1b: // ESC
|
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_CANCEL;
|
|
||||||
break;
|
|
||||||
case 0x08: // Back
|
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_BACK;
|
|
||||||
break;
|
|
||||||
case 0xb5: // Up
|
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_UP;
|
|
||||||
break;
|
|
||||||
case 0xb6: // Down
|
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_DOWN;
|
|
||||||
break;
|
|
||||||
case 0xb4: // Left
|
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_LEFT;
|
|
||||||
break;
|
|
||||||
case 0xb7: // Right
|
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_RIGHT;
|
|
||||||
break;
|
|
||||||
case 0x0d: // Enter
|
|
||||||
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_KEY_SELECT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.inputEvent != ModuleConfig_CannedMessageConfig_InputEventChar_KEY_NONE) {
|
if (kb_model == 0x02) {
|
||||||
this->notifyObservers(&e);
|
// RAK14004
|
||||||
|
uint8_t rDataBuf[8] = {0};
|
||||||
|
uint8_t PrintDataBuf = 0;
|
||||||
|
if (read_from_14004(0x01, rDataBuf, 0x04) == 1) {
|
||||||
|
for (uint8_t aCount = 0; aCount < 0x04; aCount++) {
|
||||||
|
for (uint8_t bCount = 0; bCount < 0x04; bCount++ ) {
|
||||||
|
if (((rDataBuf[aCount] >> bCount) & 0x01) == 0x01) {
|
||||||
|
PrintDataBuf = aCount * 0x04 + bCount + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PrintDataBuf != 0) {
|
||||||
|
DEBUG_MSG("RAK14004 key 0x%x pressed\n", PrintDataBuf);
|
||||||
|
InputEvent e;
|
||||||
|
e.inputEvent = MATRIXKEY;
|
||||||
|
e.source = this->_originName;
|
||||||
|
e.kbchar = PrintDataBuf;
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// m5 cardkb
|
||||||
|
Wire.requestFrom(CARDKB_ADDR, 1);
|
||||||
|
|
||||||
|
while (Wire.available()) {
|
||||||
|
char c = Wire.read();
|
||||||
|
InputEvent e;
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
e.source = this->_originName;
|
||||||
|
switch (c) {
|
||||||
|
case 0x1b: // ESC
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
|
||||||
|
break;
|
||||||
|
case 0x08: // Back
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
|
||||||
|
e.kbchar = c;
|
||||||
|
break;
|
||||||
|
case 0xb5: // Up
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||||
|
break;
|
||||||
|
case 0xb6: // Down
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||||
|
break;
|
||||||
|
case 0xb4: // Left
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||||
|
e.kbchar = c;
|
||||||
|
break;
|
||||||
|
case 0xb7: // Right
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||||
|
e.kbchar = c;
|
||||||
|
break;
|
||||||
|
case 0x0d: // Enter
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||||
|
break;
|
||||||
|
case 0x00: //nopress
|
||||||
|
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||||
|
break;
|
||||||
|
default: // all other keys
|
||||||
|
e.inputEvent = ANYKEY;
|
||||||
|
e.kbchar = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.inputEvent != ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 500;
|
return 500;
|
||||||
}
|
}
|
||||||
|
|||||||
93
src/main.cpp
93
src/main.cpp
@@ -17,9 +17,9 @@
|
|||||||
#include "SPILock.h"
|
#include "SPILock.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
#include "concurrency/Periodic.h"
|
#include "concurrency/Periodic.h"
|
||||||
#include "debug/axpDebug.h"
|
#include "detect/axpDebug.h"
|
||||||
#include "debug/einkScan.h"
|
#include "detect/einkScan.h"
|
||||||
#include "debug/i2cScan.h"
|
#include "detect/i2cScan.h"
|
||||||
#include "graphics/Screen.h"
|
#include "graphics/Screen.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "modules/Modules.h"
|
#include "modules/Modules.h"
|
||||||
@@ -31,18 +31,12 @@
|
|||||||
|
|
||||||
#include "mesh/http/WiFiAPClient.h"
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
#include "mesh/http/WebServer.h"
|
#include "mesh/http/WebServer.h"
|
||||||
|
#include "nimble/NimbleBluetooth.h"
|
||||||
#ifdef USE_NEW_ESP32_BLUETOOTH
|
|
||||||
#include "esp32/ESP32Bluetooth.h"
|
|
||||||
#else
|
|
||||||
#include "nimble/BluetoothUtil.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#if HAS_WIFI || defined(ARCH_PORTDUINO)
|
||||||
|
|
||||||
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
|
||||||
#include "mesh/wifi/WiFiServerAPI.h"
|
#include "mesh/wifi/WiFiServerAPI.h"
|
||||||
#include "mqtt/MQTT.h"
|
#include "mqtt/MQTT.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -51,8 +45,13 @@
|
|||||||
#include "RF95Interface.h"
|
#include "RF95Interface.h"
|
||||||
#include "SX1262Interface.h"
|
#include "SX1262Interface.h"
|
||||||
#include "SX1268Interface.h"
|
#include "SX1268Interface.h"
|
||||||
|
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
|
||||||
|
#include "platform/portduino/SimRadio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAS_BUTTON
|
||||||
#include "ButtonThread.h"
|
#include "ButtonThread.h"
|
||||||
|
#endif
|
||||||
#include "PowerFSMThread.h"
|
#include "PowerFSMThread.h"
|
||||||
|
|
||||||
using namespace concurrency;
|
using namespace concurrency;
|
||||||
@@ -78,20 +77,23 @@ uint8_t cardkb_found;
|
|||||||
// 0x02 for RAK14004 and 0x00 for cardkb
|
// 0x02 for RAK14004 and 0x00 for cardkb
|
||||||
uint8_t kb_model;
|
uint8_t kb_model;
|
||||||
|
|
||||||
// The I2C address of the Faces Keyboard (if found)
|
|
||||||
uint8_t faceskb_found;
|
|
||||||
|
|
||||||
// The I2C address of the RTC Module (if found)
|
// The I2C address of the RTC Module (if found)
|
||||||
uint8_t rtc_found;
|
uint8_t rtc_found;
|
||||||
|
|
||||||
|
// Keystore Chips
|
||||||
|
uint8_t keystore_found;
|
||||||
|
#ifndef ARCH_PORTDUINO
|
||||||
|
ATECCX08A atecc;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool eink_found = true;
|
bool eink_found = true;
|
||||||
|
|
||||||
uint32_t serialSinceMsec;
|
uint32_t serialSinceMsec;
|
||||||
|
|
||||||
bool axp192_found;
|
bool pmu_found;
|
||||||
|
|
||||||
// Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan
|
// Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan
|
||||||
uint8_t nodeTelemetrySensorsMap[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
|
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
|
||||||
|
|
||||||
@@ -126,11 +128,15 @@ static int32_t ledBlinker()
|
|||||||
|
|
||||||
uint32_t timeLastPowered = 0;
|
uint32_t timeLastPowered = 0;
|
||||||
|
|
||||||
|
#if HAS_BUTTON
|
||||||
bool ButtonThread::shutdown_on_long_stop = false;
|
bool ButtonThread::shutdown_on_long_stop = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
static Periodic *ledPeriodic;
|
static Periodic *ledPeriodic;
|
||||||
static OSThread *powerFSMthread, *buttonThread;
|
static OSThread *powerFSMthread, *buttonThread;
|
||||||
|
#if HAS_BUTTON
|
||||||
uint32_t ButtonThread::longPressTime = 0;
|
uint32_t ButtonThread::longPressTime = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
RadioInterface *rIf = NULL;
|
RadioInterface *rIf = NULL;
|
||||||
|
|
||||||
@@ -157,9 +163,7 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_PORT
|
#ifdef DEBUG_PORT
|
||||||
if (!config.device.serial_disabled) {
|
|
||||||
consoleInit(); // Set serial baud rate and init our mesh console
|
consoleInit(); // Set serial baud rate and init our mesh console
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
serialSinceMsec = millis();
|
serialSinceMsec = millis();
|
||||||
@@ -187,7 +191,7 @@ void setup()
|
|||||||
bool forceSoftAP = 0;
|
bool forceSoftAP = 0;
|
||||||
|
|
||||||
#ifdef BUTTON_PIN
|
#ifdef BUTTON_PIN
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
|
|
||||||
// If the button is connected to GPIO 12, don't enable the ability to use
|
// If the button is connected to GPIO 12, don't enable the ability to use
|
||||||
// meshtasticAdmin on the device.
|
// meshtasticAdmin on the device.
|
||||||
@@ -216,9 +220,13 @@ void setup()
|
|||||||
// router = new DSRRouter();
|
// router = new DSRRouter();
|
||||||
router = new ReliableRouter();
|
router = new ReliableRouter();
|
||||||
|
|
||||||
|
#ifdef I2C_SDA1
|
||||||
|
Wire1.begin(I2C_SDA1, I2C_SCL1);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef I2C_SDA
|
#ifdef I2C_SDA
|
||||||
Wire.begin(I2C_SDA, I2C_SCL);
|
Wire.begin(I2C_SDA, I2C_SCL);
|
||||||
#elif !defined(NO_WIRE)
|
#elif HAS_WIRE
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -231,13 +239,16 @@ void setup()
|
|||||||
delay(1);
|
delay(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// We need to scan here to decide if we have a screen for nodeDB.init()
|
||||||
scanI2Cdevice();
|
scanI2Cdevice();
|
||||||
#ifdef RAK4630
|
#ifdef RAK4630
|
||||||
// scanEInkDevice();
|
// scanEInkDevice();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAS_BUTTON
|
||||||
// Buttons & LED
|
// Buttons & LED
|
||||||
buttonThread = new ButtonThread();
|
buttonThread = new ButtonThread();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LED_PIN
|
#ifdef LED_PIN
|
||||||
pinMode(LED_PIN, OUTPUT);
|
pinMode(LED_PIN, OUTPUT);
|
||||||
@@ -247,7 +258,7 @@ void setup()
|
|||||||
// Hello
|
// Hello
|
||||||
DEBUG_MSG("Meshtastic hwvendor=%d, swver=%s\n", HW_VENDOR, optstr(APP_VERSION));
|
DEBUG_MSG("Meshtastic hwvendor=%d, swver=%s\n", HW_VENDOR, optstr(APP_VERSION));
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// Don't init display if we don't have one or we are waking headless due to a timer event
|
// Don't init display if we don't have one or we are waking headless due to a timer event
|
||||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER)
|
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER)
|
||||||
screen_found = 0; // forget we even have the hardware
|
screen_found = 0; // forget we even have the hardware
|
||||||
@@ -255,7 +266,7 @@ void setup()
|
|||||||
esp32Setup();
|
esp32Setup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NRF52_SERIES
|
#ifdef ARCH_NRF52
|
||||||
nrf52Setup();
|
nrf52Setup();
|
||||||
#endif
|
#endif
|
||||||
playStartMelody();
|
playStartMelody();
|
||||||
@@ -269,9 +280,17 @@ void setup()
|
|||||||
powerStatus->observe(&power->newStatus);
|
powerStatus->observe(&power->newStatus);
|
||||||
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
|
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Repeat the scanning for I2C devices after power initialization.
|
||||||
|
* Boards with an PMU need to be powered on to correctly scan to the device address, such as t-beam-s3-core
|
||||||
|
*/
|
||||||
|
if ((HW_VENDOR == HardwareModel_LILYGO_TBEAM_S3_CORE) || (HW_VENDOR == HardwareModel_TBEAM)) {
|
||||||
|
scanI2Cdevice();
|
||||||
|
}
|
||||||
|
|
||||||
// Init our SPI controller (must be before screen and lora)
|
// Init our SPI controller (must be before screen and lora)
|
||||||
initSPI();
|
initSPI();
|
||||||
#ifdef NO_ESP32
|
#ifndef ARCH_ESP32
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
#else
|
#else
|
||||||
// ESP32
|
// ESP32
|
||||||
@@ -299,14 +318,14 @@ void setup()
|
|||||||
setupModules();
|
setupModules();
|
||||||
|
|
||||||
// Do this after service.init (because that clears error_code)
|
// Do this after service.init (because that clears error_code)
|
||||||
#ifdef AXP192_SLAVE_ADDRESS
|
#ifdef HAS_PMU
|
||||||
if (!axp192_found)
|
if (!pmu_found)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_NoAXP192); // Record a hardware fault for missing hardware
|
RECORD_CRITICALERROR(CriticalErrorCode_NO_AXP192); // Record a hardware fault for missing hardware
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Don't call screen setup until after nodedb is setup (because we need
|
// Don't call screen setup until after nodedb is setup (because we need
|
||||||
// the current region name)
|
// the current region name)
|
||||||
#if defined(ST7735_CS) || defined(HAS_EINK) || defined(ILI9341_DRIVER)
|
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER)
|
||||||
screen->setup();
|
screen->setup();
|
||||||
#else
|
#else
|
||||||
if (screen_found)
|
if (screen_found)
|
||||||
@@ -322,7 +341,7 @@ void setup()
|
|||||||
DEBUG_MSG("GPS FactoryReset requested\n");
|
DEBUG_MSG("GPS FactoryReset requested\n");
|
||||||
if (gps->factoryReset()) { // If we don't succeed try again next time
|
if (gps->factoryReset()) { // If we don't succeed try again next time
|
||||||
devicestate.did_gps_reset = true;
|
devicestate.did_gps_reset = true;
|
||||||
nodeDB.saveToDisk();
|
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +405,7 @@ void setup()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SIM_RADIO
|
#ifdef ARCH_PORTDUINO
|
||||||
if (!rIf) {
|
if (!rIf) {
|
||||||
rIf = new SimRadio;
|
rIf = new SimRadio;
|
||||||
if (!rIf->init()) {
|
if (!rIf->init()) {
|
||||||
@@ -399,27 +418,27 @@ void setup()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PORTDUINO) || defined(HAS_WIFI)
|
#if HAS_WIFI
|
||||||
mqttInit();
|
mqttInit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Initialize Wifi
|
// Initialize Wifi
|
||||||
initWifi(forceSoftAP);
|
initWifi(forceSoftAP);
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// Start web server thread.
|
// Start web server thread.
|
||||||
webServerThread = new WebServerThread();
|
webServerThread = new WebServerThread();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
initApiServer();
|
initApiServer(TCPPort);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Start airtime logger thread.
|
// Start airtime logger thread.
|
||||||
airTime = new AirTime();
|
airTime = new AirTime();
|
||||||
|
|
||||||
if (!rIf)
|
if (!rIf)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_NoRadio);
|
RECORD_CRITICALERROR(CriticalErrorCode_NO_RADIO);
|
||||||
else {
|
else {
|
||||||
router->addInterface(rIf);
|
router->addInterface(rIf);
|
||||||
|
|
||||||
@@ -452,10 +471,10 @@ void loop()
|
|||||||
|
|
||||||
// heap_caps_check_integrity_all(true); // FIXME - disable this expensive check
|
// heap_caps_check_integrity_all(true); // FIXME - disable this expensive check
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
esp32Loop();
|
esp32Loop();
|
||||||
#endif
|
#endif
|
||||||
#ifdef NRF52_SERIES
|
#ifdef ARCH_NRF52
|
||||||
nrf52Loop();
|
nrf52Loop();
|
||||||
#endif
|
#endif
|
||||||
powerCommandsCheck();
|
powerCommandsCheck();
|
||||||
|
|||||||
15
src/main.h
15
src/main.h
@@ -6,20 +6,29 @@
|
|||||||
#include "PowerStatus.h"
|
#include "PowerStatus.h"
|
||||||
#include "graphics/Screen.h"
|
#include "graphics/Screen.h"
|
||||||
#include "mesh/generated/telemetry.pb.h"
|
#include "mesh/generated/telemetry.pb.h"
|
||||||
|
#ifndef ARCH_PORTDUINO
|
||||||
|
#include <SparkFun_ATECCX08a_Arduino_Library.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern uint8_t screen_found;
|
extern uint8_t screen_found;
|
||||||
extern uint8_t screen_model;
|
extern uint8_t screen_model;
|
||||||
extern uint8_t cardkb_found;
|
extern uint8_t cardkb_found;
|
||||||
extern uint8_t kb_model;
|
extern uint8_t kb_model;
|
||||||
extern uint8_t faceskb_found;
|
|
||||||
extern uint8_t rtc_found;
|
extern uint8_t rtc_found;
|
||||||
|
extern uint8_t keystore_found;
|
||||||
|
|
||||||
extern bool eink_found;
|
extern bool eink_found;
|
||||||
extern bool axp192_found;
|
extern bool pmu_found;
|
||||||
extern bool isCharging;
|
extern bool isCharging;
|
||||||
extern bool isUSBPowered;
|
extern bool isUSBPowered;
|
||||||
|
|
||||||
extern uint8_t nodeTelemetrySensorsMap[12];
|
#ifndef ARCH_PORTDUINO
|
||||||
|
extern ATECCX08A atecc;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1];
|
||||||
|
|
||||||
|
extern int TCPPort; // set by Portduino
|
||||||
|
|
||||||
// Global Screen singleton.
|
// Global Screen singleton.
|
||||||
extern graphics::Screen *screen;
|
extern graphics::Screen *screen;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
|||||||
ChannelSettings &channelSettings = ch.settings;
|
ChannelSettings &channelSettings = ch.settings;
|
||||||
Config_LoRaConfig &loraConfig = config.lora;
|
Config_LoRaConfig &loraConfig = config.lora;
|
||||||
|
|
||||||
loraConfig.modem_preset = Config_LoRaConfig_ModemPreset_LongFast; // Default to Long Range & Fast
|
loraConfig.modem_preset = Config_LoRaConfig_ModemPreset_LONG_FAST; // Default to Long Range & Fast
|
||||||
|
|
||||||
loraConfig.tx_power = 0; // default
|
loraConfig.tx_power = 0; // default
|
||||||
uint8_t defaultpskIndex = 1;
|
uint8_t defaultpskIndex = 1;
|
||||||
@@ -214,26 +214,26 @@ const char *Channels::getName(size_t chIndex)
|
|||||||
channelName = "Custom";
|
channelName = "Custom";
|
||||||
else
|
else
|
||||||
switch (config.lora.modem_preset) {
|
switch (config.lora.modem_preset) {
|
||||||
case Config_LoRaConfig_ModemPreset_ShortSlow:
|
case Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||||
channelName = "ShortS";
|
channelName = "ShortSlow";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_ShortFast:
|
case Config_LoRaConfig_ModemPreset_SHORT_FAST:
|
||||||
channelName = "ShortF";
|
channelName = "ShortFast";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_MedSlow:
|
case Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
|
||||||
channelName = "MedS";
|
channelName = "MediumSlow";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_MedFast:
|
case Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
|
||||||
channelName = "MedF";
|
channelName = "MediumFast";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_LongSlow:
|
case Config_LoRaConfig_ModemPreset_LONG_SLOW:
|
||||||
channelName = "LongS";
|
channelName = "LongSlow";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_LongFast:
|
case Config_LoRaConfig_ModemPreset_LONG_FAST:
|
||||||
channelName = "LongF";
|
channelName = "LongFast";
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_VLongSlow:
|
case Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
|
||||||
channelName = "VeryL";
|
channelName = "VLongSlow";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
channelName = "Invalid";
|
channelName = "Invalid";
|
||||||
|
|||||||
@@ -29,10 +29,14 @@ bool FloodingRouter::shouldFilterReceived(MeshPacket *p)
|
|||||||
|
|
||||||
void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
||||||
{
|
{
|
||||||
|
PacketId ackId = ((c && c->error_reason == Routing_Error_NONE) || !c) ? p->decoded.request_id : 0;
|
||||||
if ((p->to == NODENUM_BROADCAST) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
|
if (ackId && p->to != getNodeNum()) {
|
||||||
|
// do not flood direct message that is ACKed
|
||||||
|
DEBUG_MSG("Receiving an ACK not for me, but don't need to rebroadcast this direct message anymore.\n");
|
||||||
|
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
|
||||||
|
} else if ((p->to != getNodeNum()) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
|
||||||
if (p->id != 0) {
|
if (p->id != 0) {
|
||||||
if (config.device.role != Config_DeviceConfig_Role_ClientMute) {
|
if (config.device.role != Config_DeviceConfig_Role_CLIENT_MUTE) {
|
||||||
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
|
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
|
||||||
|
|
||||||
tosend->hop_limit--; // bump down the hop count
|
tosend->hop_limit--; // bump down the hop count
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
|
|||||||
bool moduleFound = false;
|
bool moduleFound = false;
|
||||||
|
|
||||||
// We now allow **encrypted** packets to pass through the modules
|
// We now allow **encrypted** packets to pass through the modules
|
||||||
bool isDecoded = mp.which_payloadVariant == MeshPacket_decoded_tag;
|
bool isDecoded = mp.which_payload_variant == MeshPacket_decoded_tag;
|
||||||
|
|
||||||
currentReply = NULL; // No reply yet
|
currentReply = NULL; // No reply yet
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
|
|||||||
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) ||
|
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) ||
|
||||||
!ch ||
|
!ch ||
|
||||||
strlen(ch->settings.name) > 0 ||
|
strlen(ch->settings.name) > 0 ||
|
||||||
strcmp(ch->settings.name, pi.boundChannel);
|
(strcasecmp(ch->settings.name, pi.boundChannel) == 0);
|
||||||
|
|
||||||
if (!rxChannelOk) {
|
if (!rxChannelOk) {
|
||||||
// no one should have already replied!
|
// no one should have already replied!
|
||||||
@@ -211,7 +211,7 @@ void MeshModule::sendResponse(const MeshPacket &req)
|
|||||||
*/
|
*/
|
||||||
void setReplyTo(MeshPacket *p, const MeshPacket &to)
|
void setReplyTo(MeshPacket *p, const MeshPacket &to)
|
||||||
{
|
{
|
||||||
assert(p->which_payloadVariant == MeshPacket_decoded_tag); // Should already be set by now
|
assert(p->which_payload_variant == MeshPacket_decoded_tag); // Should already be set by now
|
||||||
p->to = getFrom(&to); // Make sure that if we are sending to the local node, we use our local node addr, not 0
|
p->to = getFrom(&to); // Make sure that if we are sending to the local node, we use our local node addr, not 0
|
||||||
p->channel = to.channel; // Use the same channel that the request came in on
|
p->channel = to.channel; // Use the same channel that the request came in on
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ AdminMessageHandleResult MeshModule::handleAdminMessageForAllPlugins(const MeshP
|
|||||||
// In case we have a response it always has priority.
|
// In case we have a response it always has priority.
|
||||||
DEBUG_MSG("Reply prepared by module '%s' of variant: %d\n",
|
DEBUG_MSG("Reply prepared by module '%s' of variant: %d\n",
|
||||||
pi.name,
|
pi.name,
|
||||||
response->which_variant);
|
response->which_payload_variant);
|
||||||
handled = h;
|
handled = h;
|
||||||
}
|
}
|
||||||
else if ((handled != AdminMessageHandleResult::HANDLED_WITH_RESPONSE) &&
|
else if ((handled != AdminMessageHandleResult::HANDLED_WITH_RESPONSE) &&
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "mesh/MeshTypes.h"
|
#include "mesh/MeshTypes.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifndef NO_SCREEN
|
#if HAS_SCREEN
|
||||||
#include <OLEDDisplay.h>
|
#include <OLEDDisplay.h>
|
||||||
#include <OLEDDisplayUi.h>
|
#include <OLEDDisplayUi.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -72,7 +72,7 @@ class MeshModule
|
|||||||
static void observeUIEvents(Observer<const UIFrameEvent *> *observer);
|
static void observeUIEvents(Observer<const UIFrameEvent *> *observer);
|
||||||
static AdminMessageHandleResult handleAdminMessageForAllPlugins(
|
static AdminMessageHandleResult handleAdminMessageForAllPlugins(
|
||||||
const MeshPacket &mp, AdminMessage *request, AdminMessage *response);
|
const MeshPacket &mp, AdminMessage *request, AdminMessage *response);
|
||||||
#ifndef NO_SCREEN
|
#if HAS_SCREEN
|
||||||
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
|
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
|
||||||
#endif
|
#endif
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
#include "modules/PositionModule.h"
|
#include "modules/PositionModule.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
#include "nimble/NimbleBluetooth.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
|
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
|
||||||
It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were
|
It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were
|
||||||
@@ -86,7 +90,7 @@ void MeshService::loop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The radioConfig object just changed, call this to force the hw to change to the new settings
|
/// The radioConfig object just changed, call this to force the hw to change to the new settings
|
||||||
bool MeshService::reloadConfig()
|
bool MeshService::reloadConfig(int saveWhat)
|
||||||
{
|
{
|
||||||
// If we can successfully set this radio to these settings, save them to disk
|
// If we can successfully set this radio to these settings, save them to disk
|
||||||
|
|
||||||
@@ -94,7 +98,7 @@ bool MeshService::reloadConfig()
|
|||||||
bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings
|
bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings
|
||||||
|
|
||||||
configChanged.notifyObservers(NULL); // This will cause radio hardware to change freqs etc
|
configChanged.notifyObservers(NULL); // This will cause radio hardware to change freqs etc
|
||||||
nodeDB.saveToDisk();
|
nodeDB.saveToDisk(saveWhat);
|
||||||
|
|
||||||
return didReset;
|
return didReset;
|
||||||
}
|
}
|
||||||
@@ -109,7 +113,7 @@ void MeshService::reloadOwner()
|
|||||||
// update everyone else
|
// update everyone else
|
||||||
if (nodeInfoModule)
|
if (nodeInfoModule)
|
||||||
nodeInfoModule->sendOurNodeInfo();
|
nodeInfoModule->sendOurNodeInfo();
|
||||||
nodeDB.saveToDisk();
|
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,6 +123,29 @@ void MeshService::reloadOwner()
|
|||||||
*/
|
*/
|
||||||
void MeshService::handleToRadio(MeshPacket &p)
|
void MeshService::handleToRadio(MeshPacket &p)
|
||||||
{
|
{
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
// Simulates device is receiving a packet via the LoRa chip
|
||||||
|
if (p.decoded.portnum == PortNum_SIMULATOR_APP) {
|
||||||
|
// Simulator packet (=Compressed packet) is encapsulated in a MeshPacket, so need to unwrap first
|
||||||
|
Compressed scratch;
|
||||||
|
Compressed *decoded = NULL;
|
||||||
|
if (p.which_payload_variant == MeshPacket_decoded_tag) {
|
||||||
|
memset(&scratch, 0, sizeof(scratch));
|
||||||
|
p.decoded.payload.size = pb_decode_from_bytes(p.decoded.payload.bytes, p.decoded.payload.size, &Compressed_msg, &scratch);
|
||||||
|
if (p.decoded.payload.size) {
|
||||||
|
decoded = &scratch;
|
||||||
|
// Extract the original payload and replace
|
||||||
|
memcpy(&p.decoded.payload, &decoded->data, sizeof(decoded->data));
|
||||||
|
// Switch the port from PortNum_SIMULATOR_APP back to the original PortNum
|
||||||
|
p.decoded.portnum = decoded->portnum;
|
||||||
|
} else
|
||||||
|
DEBUG_MSG("Error decoding protobuf for simulator message!\n");
|
||||||
|
}
|
||||||
|
// Let SimRadio receive as if it did via its LoRa chip
|
||||||
|
SimRadio::instance->startReceive(&p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (p.from != 0) { // We don't let phones assign nodenums to their sent messages
|
if (p.from != 0) { // We don't let phones assign nodenums to their sent messages
|
||||||
DEBUG_MSG("Warning: phone tried to pick a nodenum, we don't allow that.\n");
|
DEBUG_MSG("Warning: phone tried to pick a nodenum, we don't allow that.\n");
|
||||||
p.from = 0;
|
p.from = 0;
|
||||||
@@ -168,7 +195,7 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
|||||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||||
assert(node);
|
assert(node);
|
||||||
|
|
||||||
if (node->has_position) {
|
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
|
||||||
if (positionModule) {
|
if (positionModule) {
|
||||||
DEBUG_MSG("Sending position ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
DEBUG_MSG("Sending position ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||||
positionModule->sendOurPosition(dest, wantReplies);
|
positionModule->sendOurPosition(dest, wantReplies);
|
||||||
@@ -248,7 +275,7 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
|||||||
pos.time = getValidTime(RTCQualityGPS);
|
pos.time = getValidTime(RTCQualityGPS);
|
||||||
|
|
||||||
// In debug logs, identify position by @timestamp:stage (stage 4 = nodeDB)
|
// In debug logs, identify position by @timestamp:stage (stage 4 = nodeDB)
|
||||||
DEBUG_MSG("onGPSChanged() pos@%x, time=%u, lat=%d, lon=%d, alt=%d\n", pos.pos_timestamp, pos.time, pos.latitude_i,
|
DEBUG_MSG("onGPSChanged() pos@%x, time=%u, lat=%d, lon=%d, alt=%d\n", pos.timestamp, pos.time, pos.latitude_i,
|
||||||
pos.longitude_i, pos.altitude);
|
pos.longitude_i, pos.altitude);
|
||||||
|
|
||||||
// Update our current position in the local DB
|
// Update our current position in the local DB
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
#include "MeshTypes.h"
|
#include "MeshTypes.h"
|
||||||
#include "Observer.h"
|
#include "Observer.h"
|
||||||
#include "PointerQueue.h"
|
#include "PointerQueue.h"
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
#include "../platform/portduino/SimRadio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top level app for this service. keeps the mesh, the radio config and the queue of received packets.
|
* Top level app for this service. keeps the mesh, the radio config and the queue of received packets.
|
||||||
@@ -63,7 +66,7 @@ class MeshService
|
|||||||
/** The radioConfig object just changed, call this to force the hw to change to the new settings
|
/** The radioConfig object just changed, call this to force the hw to change to the new settings
|
||||||
* @return true if client devices should be sent a new set of radio configs
|
* @return true if client devices should be sent a new set of radio configs
|
||||||
*/
|
*/
|
||||||
bool reloadConfig();
|
bool reloadConfig(int saveWhat=SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||||
|
|
||||||
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
|
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
|
||||||
void reloadOwner();
|
void reloadOwner();
|
||||||
|
|||||||
@@ -16,15 +16,16 @@
|
|||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
|
#include <ErriezCRC32.h>
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
#include "mesh/http/WiFiAPClient.h"
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
#include "modules/esp32/StoreForwardModule.h"
|
#include "modules/esp32/StoreForwardModule.h"
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
#include <nvs_flash.h>
|
#include <nvs_flash.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NRF52_SERIES
|
#ifdef ARCH_NRF52
|
||||||
#include <bluefruit.h>
|
#include <bluefruit.h>
|
||||||
#include <utility/bonding.h>
|
#include <utility/bonding.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -43,14 +44,6 @@ ChannelFile channelFile;
|
|||||||
*/
|
*/
|
||||||
uint32_t radioGeneration;
|
uint32_t radioGeneration;
|
||||||
|
|
||||||
/*
|
|
||||||
DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a
|
|
||||||
#define here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define DEVICESTATE_CUR_VER 13
|
|
||||||
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
|
||||||
|
|
||||||
// FIXME - move this somewhere else
|
// FIXME - move this somewhere else
|
||||||
extern void getMacAddr(uint8_t *dmac);
|
extern void getMacAddr(uint8_t *dmac);
|
||||||
|
|
||||||
@@ -81,14 +74,13 @@ NodeNum getFrom(const MeshPacket *p)
|
|||||||
return (p->from == 0) ? nodeDB.getNodeNum() : p->from;
|
return (p->from == 0) ? nodeDB.getNodeNum() : p->from;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeDB::resetRadioConfig()
|
bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||||
{
|
{
|
||||||
bool didFactoryReset = false;
|
bool didFactoryReset = false;
|
||||||
|
|
||||||
radioGeneration++;
|
radioGeneration++;
|
||||||
|
|
||||||
// radioConfig.has_preferences = true;
|
if (factory_reset) {
|
||||||
if (config.device.factory_reset) {
|
|
||||||
didFactoryReset = factoryReset();
|
didFactoryReset = factoryReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +112,12 @@ bool NodeDB::resetRadioConfig()
|
|||||||
// Update the global myRegion
|
// Update the global myRegion
|
||||||
initRegion();
|
initRegion();
|
||||||
|
|
||||||
|
if (didFactoryReset) {
|
||||||
|
DEBUG_MSG("Rebooting due to factory reset");
|
||||||
|
screen->startRebootScreen();
|
||||||
|
rebootAtMsec = millis() + (5 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
return didFactoryReset;
|
return didFactoryReset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,13 +128,14 @@ bool NodeDB::factoryReset()
|
|||||||
rmDir("/prefs");
|
rmDir("/prefs");
|
||||||
// second, install default state (this will deal with the duplicate mac address issue)
|
// second, install default state (this will deal with the duplicate mac address issue)
|
||||||
installDefaultDeviceState();
|
installDefaultDeviceState();
|
||||||
// third, write to disk
|
installDefaultConfig();
|
||||||
|
// third, write everything to disk
|
||||||
saveToDisk();
|
saveToDisk();
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// This will erase what's in NVS including ssl keys, persistant variables and ble pairing
|
// This will erase what's in NVS including ssl keys, persistant variables and ble pairing
|
||||||
nvs_flash_erase();
|
nvs_flash_erase();
|
||||||
#endif
|
#endif
|
||||||
#ifdef NRF52_SERIES
|
#ifdef ARCH_NRF52
|
||||||
Bluefruit.begin();
|
Bluefruit.begin();
|
||||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||||
@@ -157,15 +156,45 @@ void NodeDB::installDefaultConfig()
|
|||||||
config.has_lora = true;
|
config.has_lora = true;
|
||||||
config.has_position = true;
|
config.has_position = true;
|
||||||
config.has_power = true;
|
config.has_power = true;
|
||||||
config.has_wifi = true;
|
config.has_network = true;
|
||||||
|
config.has_bluetooth = true;
|
||||||
config.lora.region = Config_LoRaConfig_RegionCode_Unset;
|
config.lora.tx_enabled = true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
|
||||||
config.lora.modem_preset = Config_LoRaConfig_ModemPreset_LongFast;
|
config.lora.region = Config_LoRaConfig_RegionCode_UNSET;
|
||||||
|
config.lora.modem_preset = Config_LoRaConfig_ModemPreset_LONG_FAST;
|
||||||
|
config.lora.hop_limit = HOP_RELIABLE;
|
||||||
|
config.position.gps_enabled = true;
|
||||||
|
config.position.position_broadcast_smart_enabled = true;
|
||||||
|
config.device.serial_enabled = true;
|
||||||
resetRadioConfig();
|
resetRadioConfig();
|
||||||
strncpy(config.device.ntp_server, "0.pool.ntp.org", 32);
|
strncpy(config.network.ntp_server, "0.pool.ntp.org", 32);
|
||||||
|
// FIXME: Default to bluetooth capability of platform as default
|
||||||
|
config.bluetooth.enabled = true;
|
||||||
|
config.bluetooth.fixed_pin = defaultBLEPin;
|
||||||
|
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER)
|
||||||
|
bool hasScreen = true;
|
||||||
|
#else
|
||||||
|
bool hasScreen = screen_found;
|
||||||
|
#endif
|
||||||
|
config.bluetooth.mode = hasScreen ? Config_BluetoothConfig_PairingMode_RANDOM_PIN : Config_BluetoothConfig_PairingMode_FIXED_PIN;
|
||||||
// for backward compat, default position flags are ALT+MSL
|
// for backward compat, default position flags are ALT+MSL
|
||||||
config.position.position_flags =
|
config.position.position_flags = (Config_PositionConfig_PositionFlags_ALTITUDE | Config_PositionConfig_PositionFlags_ALTITUDE_MSL);
|
||||||
(Config_PositionConfig_PositionFlags_POS_ALTITUDE | Config_PositionConfig_PositionFlags_POS_ALT_MSL);
|
|
||||||
|
initConfigIntervals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeDB::initConfigIntervals()
|
||||||
|
{
|
||||||
|
config.position.gps_update_interval = default_gps_update_interval;
|
||||||
|
config.position.gps_attempt_time = default_gps_attempt_time;
|
||||||
|
config.position.position_broadcast_secs = default_broadcast_interval_secs;
|
||||||
|
|
||||||
|
config.power.ls_secs = default_ls_secs;
|
||||||
|
config.power.mesh_sds_timeout_secs = default_mesh_sds_timeout_secs;
|
||||||
|
config.power.min_wake_secs = default_min_wake_secs;
|
||||||
|
config.power.sds_secs = default_sds_secs;
|
||||||
|
config.power.wait_bluetooth_secs = default_wait_bluetooth_secs;
|
||||||
|
|
||||||
|
config.display.screen_on_secs = default_screen_on_secs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::installDefaultModuleConfig()
|
void NodeDB::installDefaultModuleConfig()
|
||||||
@@ -180,6 +209,14 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
moduleConfig.has_telemetry = true;
|
moduleConfig.has_telemetry = true;
|
||||||
moduleConfig.has_external_notification = true;
|
moduleConfig.has_external_notification = true;
|
||||||
moduleConfig.has_canned_message = true;
|
moduleConfig.has_canned_message = true;
|
||||||
|
|
||||||
|
initModuleConfigIntervals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeDB::initModuleConfigIntervals()
|
||||||
|
{
|
||||||
|
moduleConfig.telemetry.device_update_interval = default_broadcast_interval_secs;
|
||||||
|
moduleConfig.telemetry.environment_update_interval = default_broadcast_interval_secs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::installDefaultChannels()
|
void NodeDB::installDefaultChannels()
|
||||||
@@ -189,13 +226,20 @@ void NodeDB::installDefaultChannels()
|
|||||||
channelFile.version = DEVICESTATE_CUR_VER;
|
channelFile.version = DEVICESTATE_CUR_VER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeDB::resetNodes()
|
||||||
|
{
|
||||||
|
devicestate.node_db_count = 0;
|
||||||
|
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
|
||||||
|
saveDeviceStateToDisk();
|
||||||
|
}
|
||||||
|
|
||||||
void NodeDB::installDefaultDeviceState()
|
void NodeDB::installDefaultDeviceState()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Installing default DeviceState\n");
|
DEBUG_MSG("Installing default DeviceState\n");
|
||||||
memset(&devicestate, 0, sizeof(DeviceState));
|
memset(&devicestate, 0, sizeof(DeviceState));
|
||||||
|
|
||||||
*numNodes = 0; // Forget node DB
|
*numNodes = 0;
|
||||||
|
|
||||||
// init our devicestate with valid flags so protobuf writing/reading will work
|
// init our devicestate with valid flags so protobuf writing/reading will work
|
||||||
devicestate.has_my_node = true;
|
devicestate.has_my_node = true;
|
||||||
devicestate.has_owner = true;
|
devicestate.has_owner = true;
|
||||||
@@ -223,12 +267,17 @@ void NodeDB::installDefaultDeviceState()
|
|||||||
void NodeDB::init()
|
void NodeDB::init()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Initializing NodeDB\n");
|
DEBUG_MSG("Initializing NodeDB\n");
|
||||||
// saveToDisk();
|
|
||||||
loadFromDisk();
|
loadFromDisk();
|
||||||
|
|
||||||
|
uint32_t devicestateCRC = crc32Buffer(&devicestate, sizeof(devicestate));
|
||||||
|
uint32_t configCRC = crc32Buffer(&config, sizeof(config));
|
||||||
|
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
|
||||||
|
|
||||||
|
int saveWhat = 0;
|
||||||
|
|
||||||
myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand
|
myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand
|
||||||
|
|
||||||
myNodeInfo.error_code = CriticalErrorCode_None; // For the error code, only show values from this boot (discard value from flash)
|
myNodeInfo.error_code = CriticalErrorCode_NONE; // For the error code, only show values from this boot (discard value from flash)
|
||||||
myNodeInfo.error_address = 0;
|
myNodeInfo.error_address = 0;
|
||||||
|
|
||||||
// likewise - we always want the app requirements to come from the running appload
|
// likewise - we always want the app requirements to come from the running appload
|
||||||
@@ -248,7 +297,7 @@ void NodeDB::init()
|
|||||||
|
|
||||||
strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version));
|
strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version));
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
Preferences preferences;
|
Preferences preferences;
|
||||||
preferences.begin("meshtastic", false);
|
preferences.begin("meshtastic", false);
|
||||||
myNodeInfo.reboot_count = preferences.getUInt("rebootCounter", 0);
|
myNodeInfo.reboot_count = preferences.getUInt("rebootCounter", 0);
|
||||||
@@ -263,7 +312,15 @@ void NodeDB::init()
|
|||||||
|
|
||||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||||
DEBUG_MSG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
|
DEBUG_MSG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
|
||||||
saveToDisk();
|
|
||||||
|
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
||||||
|
saveWhat |= SEGMENT_DEVICESTATE;
|
||||||
|
if (configCRC != crc32Buffer(&config, sizeof(config)))
|
||||||
|
saveWhat |= SEGMENT_CONFIG;
|
||||||
|
if (channelFileCRC != crc32Buffer(&channelFile, sizeof(channelFile)))
|
||||||
|
saveWhat |= SEGMENT_CHANNELS;
|
||||||
|
|
||||||
|
saveToDisk(saveWhat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We reserve a few nodenums for future use
|
// We reserve a few nodenums for future use
|
||||||
@@ -305,7 +362,7 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_
|
|||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||||
|
|
||||||
auto f = FSCom.open(filename);
|
auto f = FSCom.open(filename, FILE_O_READ);
|
||||||
|
|
||||||
if (f) {
|
if (f) {
|
||||||
DEBUG_MSG("Loading %s\n", filename);
|
DEBUG_MSG("Loading %s\n", filename);
|
||||||
@@ -338,19 +395,7 @@ void NodeDB::loadFromDisk()
|
|||||||
} else {
|
} else {
|
||||||
if (devicestate.version < DEVICESTATE_MIN_VER) {
|
if (devicestate.version < DEVICESTATE_MIN_VER) {
|
||||||
DEBUG_MSG("Warn: devicestate %d is old, discarding\n", devicestate.version);
|
DEBUG_MSG("Warn: devicestate %d is old, discarding\n", devicestate.version);
|
||||||
installDefaultDeviceState();
|
factoryReset();
|
||||||
#ifndef NO_ESP32
|
|
||||||
// This will erase what's in NVS including ssl keys, persistant variables and ble pairing
|
|
||||||
nvs_flash_erase();
|
|
||||||
#endif
|
|
||||||
#ifdef NRF52_SERIES
|
|
||||||
Bluefruit.begin();
|
|
||||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
|
||||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
|
||||||
bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
|
||||||
Bluefruit.Periph.clearBonds();
|
|
||||||
Bluefruit.Central.clearBonds();
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Loaded saved devicestate version %d\n", devicestate.version);
|
DEBUG_MSG("Loaded saved devicestate version %d\n", devicestate.version);
|
||||||
}
|
}
|
||||||
@@ -408,13 +453,12 @@ bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_
|
|||||||
} else {
|
} else {
|
||||||
okay = true;
|
okay = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
// brief window of risk here ;-)
|
// brief window of risk here ;-)
|
||||||
if (FSCom.exists(filename) && !FSCom.remove(filename))
|
if (FSCom.exists(filename) && !FSCom.remove(filename))
|
||||||
DEBUG_MSG("Warning: Can't remove old pref file\n");
|
DEBUG_MSG("Warning: Can't remove old pref file\n");
|
||||||
if (!FSCom.rename(filenameTmp.c_str(), filename))
|
if (!renameFile(filenameTmp.c_str(), filename))
|
||||||
DEBUG_MSG("Error: can't rename new pref file\n");
|
DEBUG_MSG("Error: can't rename new pref file\n");
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Can't write prefs\n");
|
DEBUG_MSG("Can't write prefs\n");
|
||||||
@@ -431,37 +475,55 @@ void NodeDB::saveChannelsToDisk()
|
|||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
FSCom.mkdir("/prefs");
|
FSCom.mkdir("/prefs");
|
||||||
#endif
|
#endif
|
||||||
saveProto(channelFileName, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile);
|
saveProto(channelFileName, ChannelFile_size, sizeof(channelFile), ChannelFile_fields, &channelFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::saveToDisk()
|
void NodeDB::saveDeviceStateToDisk()
|
||||||
{
|
{
|
||||||
if (!devicestate.no_save) {
|
if (!devicestate.no_save) {
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
FSCom.mkdir("/prefs");
|
FSCom.mkdir("/prefs");
|
||||||
#endif
|
#endif
|
||||||
saveProto(prefFileName, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate);
|
saveProto(prefFileName, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// save all config segments
|
void NodeDB::saveToDisk(int saveWhat)
|
||||||
config.has_device = true;
|
{
|
||||||
config.has_display = true;
|
if (!devicestate.no_save) {
|
||||||
config.has_lora = true;
|
#ifdef FSCom
|
||||||
config.has_position = true;
|
FSCom.mkdir("/prefs");
|
||||||
config.has_power = true;
|
#endif
|
||||||
config.has_wifi = true;
|
if (saveWhat & SEGMENT_DEVICESTATE) {
|
||||||
saveProto(configFileName, LocalConfig_size, sizeof(LocalConfig), LocalConfig_fields, &config);
|
saveDeviceStateToDisk();
|
||||||
|
}
|
||||||
|
|
||||||
moduleConfig.has_canned_message = true;
|
if (saveWhat & SEGMENT_CONFIG) {
|
||||||
moduleConfig.has_external_notification = true;
|
config.has_device = true;
|
||||||
moduleConfig.has_mqtt = true;
|
config.has_display = true;
|
||||||
moduleConfig.has_range_test = true;
|
config.has_lora = true;
|
||||||
moduleConfig.has_serial = true;
|
config.has_position = true;
|
||||||
moduleConfig.has_store_forward = true;
|
config.has_power = true;
|
||||||
moduleConfig.has_telemetry = true;
|
config.has_network = true;
|
||||||
saveProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(LocalModuleConfig), LocalModuleConfig_fields, &moduleConfig);
|
config.has_bluetooth = true;
|
||||||
|
saveProto(configFileName, LocalConfig_size, sizeof(config), LocalConfig_fields, &config);
|
||||||
|
}
|
||||||
|
|
||||||
saveChannelsToDisk();
|
if (saveWhat & SEGMENT_MODULECONFIG) {
|
||||||
|
moduleConfig.has_canned_message = true;
|
||||||
|
moduleConfig.has_external_notification = true;
|
||||||
|
moduleConfig.has_mqtt = true;
|
||||||
|
moduleConfig.has_range_test = true;
|
||||||
|
moduleConfig.has_serial = true;
|
||||||
|
moduleConfig.has_store_forward = true;
|
||||||
|
moduleConfig.has_telemetry = true;
|
||||||
|
saveProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(moduleConfig), LocalModuleConfig_fields, &moduleConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveWhat & SEGMENT_CHANNELS) {
|
||||||
|
saveChannelsToDisk();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n");
|
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n");
|
||||||
}
|
}
|
||||||
@@ -514,11 +576,11 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src)
|
|||||||
|
|
||||||
if (src == RX_SRC_LOCAL) {
|
if (src == RX_SRC_LOCAL) {
|
||||||
// Local packet, fully authoritative
|
// Local packet, fully authoritative
|
||||||
DEBUG_MSG("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.pos_timestamp, p.time, p.latitude_i,
|
DEBUG_MSG("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.timestamp, p.time, p.latitude_i,
|
||||||
p.longitude_i, p.altitude);
|
p.longitude_i, p.altitude);
|
||||||
info->position = p;
|
info->position = p;
|
||||||
|
|
||||||
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.pos_timestamp && !p.location_source) {
|
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) {
|
||||||
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
|
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
|
||||||
// (stop-gap fix for issue #900)
|
// (stop-gap fix for issue #900)
|
||||||
DEBUG_MSG("updatePosition SPECIAL time setting time=%u\n", p.time);
|
DEBUG_MSG("updatePosition SPECIAL time setting time=%u\n", p.time);
|
||||||
@@ -603,7 +665,7 @@ void NodeDB::updateUser(uint32_t nodeId, const User &p)
|
|||||||
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
||||||
void NodeDB::updateFrom(const MeshPacket &mp)
|
void NodeDB::updateFrom(const MeshPacket &mp)
|
||||||
{
|
{
|
||||||
if (mp.which_payloadVariant == MeshPacket_decoded_tag && mp.from) {
|
if (mp.which_payload_variant == MeshPacket_decoded_tag && mp.from) {
|
||||||
DEBUG_MSG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time);
|
DEBUG_MSG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time);
|
||||||
|
|
||||||
NodeInfo *info = getOrCreateNode(getFrom(&mp));
|
NodeInfo *info = getOrCreateNode(getFrom(&mp));
|
||||||
@@ -637,11 +699,23 @@ NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
|
|||||||
|
|
||||||
if (!info) {
|
if (!info) {
|
||||||
if (*numNodes >= MAX_NUM_NODES) {
|
if (*numNodes >= MAX_NUM_NODES) {
|
||||||
screen->print("error: node_db full!\n");
|
screen->print("warning: node_db full! erasing oldest entry\n");
|
||||||
DEBUG_MSG("ERROR! could not create new node, node_db is full! (%d nodes)", *numNodes);
|
// look for oldest node and erase it
|
||||||
return NULL;
|
uint32_t oldest = UINT32_MAX;
|
||||||
|
int oldestIndex = -1;
|
||||||
|
for (int i = 0; i < *numNodes; i++) {
|
||||||
|
if (nodes[i].last_heard < oldest) {
|
||||||
|
oldest = nodes[i].last_heard;
|
||||||
|
oldestIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Shove the remaining nodes down the chain
|
||||||
|
for (int i = oldestIndex; i < *numNodes - 1; i++) {
|
||||||
|
nodes[i] = nodes[i + 1];
|
||||||
|
}
|
||||||
|
(*numNodes)--;
|
||||||
}
|
}
|
||||||
// add the node
|
// add the node at the end
|
||||||
info = &nodes[(*numNodes)++];
|
info = &nodes[(*numNodes)++];
|
||||||
|
|
||||||
// everything is missing except the nodenum
|
// everything is missing except the nodenum
|
||||||
@@ -669,7 +743,7 @@ void recordCriticalError(CriticalErrorCode code, uint32_t address, const char *f
|
|||||||
myNodeInfo.error_count++;
|
myNodeInfo.error_count++;
|
||||||
|
|
||||||
// Currently portuino is mostly used for simulation. Make sue the user notices something really bad happend
|
// Currently portuino is mostly used for simulation. Make sue the user notices something really bad happend
|
||||||
#ifdef PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
DEBUG_MSG("A critical failure occurred, portduino is exiting...");
|
DEBUG_MSG("A critical failure occurred, portduino is exiting...");
|
||||||
exit(2);
|
exit(2);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,6 +8,19 @@
|
|||||||
#include "NodeStatus.h"
|
#include "NodeStatus.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a
|
||||||
|
#define here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SEGMENT_CONFIG 1
|
||||||
|
#define SEGMENT_MODULECONFIG 2
|
||||||
|
#define SEGMENT_DEVICESTATE 4
|
||||||
|
#define SEGMENT_CHANNELS 8
|
||||||
|
|
||||||
|
#define DEVICESTATE_CUR_VER 19
|
||||||
|
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
||||||
|
|
||||||
extern DeviceState devicestate;
|
extern DeviceState devicestate;
|
||||||
extern ChannelFile channelFile;
|
extern ChannelFile channelFile;
|
||||||
extern MyNodeInfo &myNodeInfo;
|
extern MyNodeInfo &myNodeInfo;
|
||||||
@@ -44,7 +57,7 @@ class NodeDB
|
|||||||
void init();
|
void init();
|
||||||
|
|
||||||
/// write to flash
|
/// write to flash
|
||||||
void saveToDisk(), saveChannelsToDisk();
|
void saveToDisk(int saveWhat=SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS), saveChannelsToDisk(), saveDeviceStateToDisk();
|
||||||
|
|
||||||
/** Reinit radio config if needed, because either:
|
/** Reinit radio config if needed, because either:
|
||||||
* a) sometimes a buggy android app might send us bogus settings or
|
* a) sometimes a buggy android app might send us bogus settings or
|
||||||
@@ -52,7 +65,7 @@ class NodeDB
|
|||||||
*
|
*
|
||||||
* @return true if the config was completely reset, in that case, we should send it back to the client
|
* @return true if the config was completely reset, in that case, we should send it back to the client
|
||||||
*/
|
*/
|
||||||
bool resetRadioConfig();
|
bool resetRadioConfig(bool factory_reset = false);
|
||||||
|
|
||||||
/// given a subpacket sniffed from the network, update our DB state
|
/// given a subpacket sniffed from the network, update our DB state
|
||||||
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
||||||
@@ -107,6 +120,10 @@ class NodeDB
|
|||||||
/// Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
/// Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
||||||
size_t getNumOnlineNodes();
|
size_t getNumOnlineNodes();
|
||||||
|
|
||||||
|
void initConfigIntervals(), initModuleConfigIntervals(), resetNodes();
|
||||||
|
|
||||||
|
bool factoryReset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Find a node in our DB, create an empty NodeInfo if missing
|
/// Find a node in our DB, create an empty NodeInfo if missing
|
||||||
NodeInfo *getOrCreateNode(NodeNum n);
|
NodeInfo *getOrCreateNode(NodeNum n);
|
||||||
@@ -119,7 +136,6 @@ class NodeDB
|
|||||||
newStatus.notifyObservers(&status);
|
newStatus.notifyObservers(&status);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool factoryReset();
|
|
||||||
|
|
||||||
/// read our db from flash
|
/// read our db from flash
|
||||||
void loadFromDisk();
|
void loadFromDisk();
|
||||||
@@ -163,26 +179,35 @@ extern NodeDB nodeDB;
|
|||||||
// Our delay functions check for this for times that should never expire
|
// Our delay functions check for this for times that should never expire
|
||||||
#define NODE_DELAY_FOREVER 0xffffffff
|
#define NODE_DELAY_FOREVER 0xffffffff
|
||||||
|
|
||||||
#define IF_ROUTER(routerVal, normalVal) ((config.device.role == Config_DeviceConfig_Role_Router) ? (routerVal) : (normalVal))
|
#define IF_ROUTER(routerVal, normalVal) ((config.device.role == Config_DeviceConfig_Role_ROUTER) ? (routerVal) : (normalVal))
|
||||||
|
|
||||||
#define default_broadcast_interval_secs IF_ROUTER(12 * 60 * 60, 15 * 60)
|
#define ONE_DAY 24 * 60 * 60
|
||||||
|
|
||||||
|
#define default_gps_attempt_time IF_ROUTER(5 * 60, 15 * 60)
|
||||||
|
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
||||||
|
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
|
||||||
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
#define default_wait_bluetooth_secs IF_ROUTER(1, 60)
|
||||||
#define default_mesh_sds_timeout_secs IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60)
|
#define default_mesh_sds_timeout_secs IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60)
|
||||||
#define default_sds_secs 365 * 24 * 60 * 60
|
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
|
||||||
#define default_ls_secs IF_ROUTER(24 * 60 * 60, 5 * 60)
|
#define default_ls_secs IF_ROUTER(ONE_DAY, 5 * 60)
|
||||||
#define default_min_wake_secs 10
|
#define default_min_wake_secs 10
|
||||||
|
#define default_screen_on_secs 60 * 10
|
||||||
|
|
||||||
|
inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval)
|
||||||
inline uint32_t getIntervalOrDefaultMs(uint32_t interval)
|
|
||||||
{
|
{
|
||||||
if (interval > 0)
|
if (configuredInterval > 0) return configuredInterval * 1000;
|
||||||
return interval * 1000;
|
|
||||||
return default_broadcast_interval_secs * 1000;
|
return default_broadcast_interval_secs * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval)
|
||||||
|
{
|
||||||
|
if (configuredInterval > 0) return configuredInterval * 1000;
|
||||||
|
return defaultInterval * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
|
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
|
||||||
* might have changed is incremented. Allows others to detect they might now be on a new channel.
|
* might have changed is incremented. Allows others to detect they might now be on a new channel.
|
||||||
*/
|
*/
|
||||||
extern uint32_t radioGeneration;
|
extern uint32_t radioGeneration;
|
||||||
|
|
||||||
#define Module_Config_size (ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
|
#define Module_Config_size (ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
|
||||||
|
|||||||
@@ -78,21 +78,18 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
|||||||
|
|
||||||
memset(&toRadioScratch, 0, sizeof(toRadioScratch));
|
memset(&toRadioScratch, 0, sizeof(toRadioScratch));
|
||||||
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
|
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
|
||||||
switch (toRadioScratch.which_payloadVariant) {
|
switch (toRadioScratch.which_payload_variant) {
|
||||||
case ToRadio_packet_tag:
|
case ToRadio_packet_tag:
|
||||||
return handleToRadioPacket(toRadioScratch.packet);
|
return handleToRadioPacket(toRadioScratch.packet);
|
||||||
|
|
||||||
case ToRadio_want_config_id_tag:
|
case ToRadio_want_config_id_tag:
|
||||||
config_nonce = toRadioScratch.want_config_id;
|
config_nonce = toRadioScratch.want_config_id;
|
||||||
DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce);
|
DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce);
|
||||||
|
|
||||||
handleStartConfig();
|
handleStartConfig();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ToRadio_disconnect_tag:
|
case ToRadio_disconnect_tag:
|
||||||
|
DEBUG_MSG("Disconnecting from phone\n");
|
||||||
close();
|
close();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Ignore nop messages
|
// Ignore nop messages
|
||||||
// DEBUG_MSG("Error: unexpected ToRadio variant\n");
|
// DEBUG_MSG("Error: unexpected ToRadio variant\n");
|
||||||
@@ -112,139 +109,159 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
|
|||||||
*
|
*
|
||||||
* Our sending states progress in the following sequence (the client app ASSUMES THIS SEQUENCE, DO NOT CHANGE IT):
|
* Our sending states progress in the following sequence (the client app ASSUMES THIS SEQUENCE, DO NOT CHANGE IT):
|
||||||
* STATE_SEND_MY_INFO, // send our my info record
|
* STATE_SEND_MY_INFO, // send our my info record
|
||||||
* STATE_SEND_GROUPS
|
* STATE_SEND_CHANNELS
|
||||||
|
* STATE_SEND_NODEINFO, // states progress in this order as the device sends to the client
|
||||||
STATE_SEND_CONFIG,
|
STATE_SEND_CONFIG,
|
||||||
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
|
STATE_SEND_MODULE_CONFIG,
|
||||||
STATE_SEND_COMPLETE_ID,
|
STATE_SEND_COMPLETE_ID,
|
||||||
STATE_SEND_PACKETS // send packets or debug strings
|
STATE_SEND_PACKETS // send packets or debug strings
|
||||||
*/
|
*/
|
||||||
size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||||
{
|
{
|
||||||
if (!available()) {
|
if (!available()) {
|
||||||
// DEBUG_MSG("getFromRadio, !available\n");
|
// DEBUG_MSG("getFromRadio=not available\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_MSG("getFromRadio, state=%d\n", state);
|
|
||||||
|
|
||||||
// In case we send a FromRadio packet
|
// In case we send a FromRadio packet
|
||||||
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
||||||
|
|
||||||
// Advance states as needed
|
// Advance states as needed
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_SEND_NOTHING:
|
case STATE_SEND_NOTHING:
|
||||||
|
DEBUG_MSG("getFromRadio=STATE_SEND_NOTHING\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_SEND_MY_INFO:
|
case STATE_SEND_MY_INFO:
|
||||||
|
DEBUG_MSG("getFromRadio=STATE_SEND_MY_INFO\n");
|
||||||
// If the user has specified they don't want our node to share its location, make sure to tell the phone
|
// If the user has specified they don't want our node to share its location, make sure to tell the phone
|
||||||
// app not to send locations on our behalf.
|
// app not to send locations on our behalf.
|
||||||
myNodeInfo.has_gps = gps && gps->isConnected(); // Update with latest GPS connect info
|
myNodeInfo.has_gps = gps && gps->isConnected(); // Update with latest GPS connect info
|
||||||
fromRadioScratch.which_payloadVariant = FromRadio_my_info_tag;
|
fromRadioScratch.which_payload_variant = FromRadio_my_info_tag;
|
||||||
fromRadioScratch.my_info = myNodeInfo;
|
fromRadioScratch.my_info = myNodeInfo;
|
||||||
state = STATE_SEND_CONFIG;
|
state = STATE_SEND_NODEINFO;
|
||||||
|
|
||||||
service.refreshMyNodeInfo(); // Update my NodeInfo because the client will be asking for it soon.
|
service.refreshMyNodeInfo(); // Update my NodeInfo because the client will be asking for it soon.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_SEND_CONFIG:
|
|
||||||
fromRadioScratch.which_payloadVariant = FromRadio_config_tag;
|
|
||||||
switch (config_state) {
|
|
||||||
case Config_device_tag:
|
|
||||||
fromRadioScratch.config.which_payloadVariant = Config_device_tag;
|
|
||||||
fromRadioScratch.config.payloadVariant.device = config.device;
|
|
||||||
break;
|
|
||||||
case Config_position_tag:
|
|
||||||
fromRadioScratch.config.which_payloadVariant = Config_position_tag;
|
|
||||||
fromRadioScratch.config.payloadVariant.position = config.position;
|
|
||||||
break;
|
|
||||||
case Config_power_tag:
|
|
||||||
fromRadioScratch.config.which_payloadVariant = Config_power_tag;
|
|
||||||
fromRadioScratch.config.payloadVariant.power = config.power;
|
|
||||||
fromRadioScratch.config.payloadVariant.power.ls_secs = default_ls_secs;
|
|
||||||
break;
|
|
||||||
case Config_wifi_tag:
|
|
||||||
fromRadioScratch.config.which_payloadVariant = Config_wifi_tag;
|
|
||||||
fromRadioScratch.config.payloadVariant.wifi = config.wifi;
|
|
||||||
break;
|
|
||||||
case Config_display_tag:
|
|
||||||
fromRadioScratch.config.which_payloadVariant = Config_display_tag;
|
|
||||||
fromRadioScratch.config.payloadVariant.display = config.display;
|
|
||||||
break;
|
|
||||||
case Config_lora_tag:
|
|
||||||
fromRadioScratch.config.which_payloadVariant = Config_lora_tag;
|
|
||||||
fromRadioScratch.config.payloadVariant.lora = config.lora;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
|
|
||||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
|
||||||
// using to the app (so that even old phone apps work with new device loads).
|
|
||||||
|
|
||||||
config_state++;
|
|
||||||
// Advance when we have sent all of our config objects
|
|
||||||
if (config_state > Config_lora_tag) {
|
|
||||||
state = STATE_SEND_MODULECONFIG;
|
|
||||||
config_state = ModuleConfig_mqtt_tag;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STATE_SEND_MODULECONFIG:
|
|
||||||
fromRadioScratch.which_payloadVariant = FromRadio_moduleConfig_tag;
|
|
||||||
switch (config_state) {
|
|
||||||
case ModuleConfig_mqtt_tag:
|
|
||||||
fromRadioScratch.moduleConfig.which_payloadVariant = ModuleConfig_mqtt_tag;
|
|
||||||
fromRadioScratch.moduleConfig.payloadVariant.mqtt = moduleConfig.mqtt;
|
|
||||||
break;
|
|
||||||
case ModuleConfig_serial_tag:
|
|
||||||
fromRadioScratch.moduleConfig.which_payloadVariant = ModuleConfig_serial_tag;
|
|
||||||
fromRadioScratch.moduleConfig.payloadVariant.serial = moduleConfig.serial;
|
|
||||||
break;
|
|
||||||
case ModuleConfig_external_notification_tag:
|
|
||||||
fromRadioScratch.moduleConfig.which_payloadVariant = ModuleConfig_external_notification_tag;
|
|
||||||
fromRadioScratch.moduleConfig.payloadVariant.external_notification = moduleConfig.external_notification;
|
|
||||||
break;
|
|
||||||
case ModuleConfig_range_test_tag:
|
|
||||||
fromRadioScratch.moduleConfig.which_payloadVariant = ModuleConfig_range_test_tag;
|
|
||||||
fromRadioScratch.moduleConfig.payloadVariant.range_test = moduleConfig.range_test;
|
|
||||||
break;
|
|
||||||
case ModuleConfig_telemetry_tag:
|
|
||||||
fromRadioScratch.moduleConfig.which_payloadVariant = ModuleConfig_telemetry_tag;
|
|
||||||
fromRadioScratch.moduleConfig.payloadVariant.telemetry = moduleConfig.telemetry;
|
|
||||||
break;
|
|
||||||
case ModuleConfig_canned_message_tag:
|
|
||||||
fromRadioScratch.moduleConfig.which_payloadVariant = ModuleConfig_canned_message_tag;
|
|
||||||
fromRadioScratch.moduleConfig.payloadVariant.canned_message = moduleConfig.canned_message;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
config_state++;
|
|
||||||
// Advance when we have sent all of our ModuleConfig objects
|
|
||||||
if (config_state > ModuleConfig_canned_message_tag) {
|
|
||||||
state = STATE_SEND_NODEINFO;
|
|
||||||
config_state = Config_device_tag;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATE_SEND_NODEINFO: {
|
case STATE_SEND_NODEINFO: {
|
||||||
|
DEBUG_MSG("getFromRadio=STATE_SEND_NODEINFO\n");
|
||||||
const NodeInfo *info = nodeInfoForPhone;
|
const NodeInfo *info = nodeInfoForPhone;
|
||||||
nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time
|
nodeInfoForPhone = NULL; // We just consumed a nodeinfo, will need a new one next time
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
DEBUG_MSG("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->last_heard, info->user.id,
|
DEBUG_MSG("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->last_heard, info->user.id,
|
||||||
info->user.long_name);
|
info->user.long_name);
|
||||||
fromRadioScratch.which_payloadVariant = FromRadio_node_info_tag;
|
fromRadioScratch.which_payload_variant = FromRadio_node_info_tag;
|
||||||
fromRadioScratch.node_info = *info;
|
fromRadioScratch.node_info = *info;
|
||||||
// Stay in current state until done sending nodeinfos
|
// Stay in current state until done sending nodeinfos
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Done sending nodeinfos\n");
|
DEBUG_MSG("Done sending nodeinfos\n");
|
||||||
state = STATE_SEND_COMPLETE_ID;
|
state = STATE_SEND_CHANNELS;
|
||||||
// Go ahead and send that ID right now
|
// Go ahead and send that ID right now
|
||||||
return getFromRadio(buf);
|
return getFromRadio(buf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case STATE_SEND_CHANNELS:
|
||||||
|
DEBUG_MSG("getFromRadio=STATE_SEND_CHANNELS\n");
|
||||||
|
fromRadioScratch.which_payload_variant = FromRadio_channel_tag;
|
||||||
|
fromRadioScratch.channel = channels.getByIndex(config_state);
|
||||||
|
config_state++;
|
||||||
|
// Advance when we have sent all of our Channels
|
||||||
|
if (config_state >= MAX_NUM_CHANNELS) {
|
||||||
|
state = STATE_SEND_CONFIG;
|
||||||
|
config_state = Config_device_tag;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_SEND_CONFIG:
|
||||||
|
DEBUG_MSG("getFromRadio=STATE_SEND_CONFIG\n");
|
||||||
|
fromRadioScratch.which_payload_variant = FromRadio_config_tag;
|
||||||
|
switch (config_state) {
|
||||||
|
case Config_device_tag:
|
||||||
|
fromRadioScratch.config.which_payload_variant = Config_device_tag;
|
||||||
|
fromRadioScratch.config.payload_variant.device = config.device;
|
||||||
|
break;
|
||||||
|
case Config_position_tag:
|
||||||
|
fromRadioScratch.config.which_payload_variant = Config_position_tag;
|
||||||
|
fromRadioScratch.config.payload_variant.position = config.position;
|
||||||
|
break;
|
||||||
|
case Config_power_tag:
|
||||||
|
fromRadioScratch.config.which_payload_variant = Config_power_tag;
|
||||||
|
fromRadioScratch.config.payload_variant.power = config.power;
|
||||||
|
fromRadioScratch.config.payload_variant.power.ls_secs = default_ls_secs;
|
||||||
|
break;
|
||||||
|
case Config_network_tag:
|
||||||
|
fromRadioScratch.config.which_payload_variant = Config_network_tag;
|
||||||
|
fromRadioScratch.config.payload_variant.network = config.network;
|
||||||
|
break;
|
||||||
|
case Config_display_tag:
|
||||||
|
fromRadioScratch.config.which_payload_variant = Config_display_tag;
|
||||||
|
fromRadioScratch.config.payload_variant.display = config.display;
|
||||||
|
break;
|
||||||
|
case Config_lora_tag:
|
||||||
|
fromRadioScratch.config.which_payload_variant = Config_lora_tag;
|
||||||
|
fromRadioScratch.config.payload_variant.lora = config.lora;
|
||||||
|
break;
|
||||||
|
case Config_bluetooth_tag:
|
||||||
|
fromRadioScratch.config.which_payload_variant = Config_bluetooth_tag;
|
||||||
|
fromRadioScratch.config.payload_variant.bluetooth = config.bluetooth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
|
||||||
|
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||||
|
// using to the app (so that even old phone apps work with new device loads).
|
||||||
|
|
||||||
|
config_state++;
|
||||||
|
// Advance when we have sent all of our config objects
|
||||||
|
if (config_state > Config_bluetooth_tag) {
|
||||||
|
state = STATE_SEND_MODULECONFIG;
|
||||||
|
config_state = ModuleConfig_mqtt_tag;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_SEND_MODULECONFIG:
|
||||||
|
DEBUG_MSG("getFromRadio=STATE_SEND_MODULECONFIG\n");
|
||||||
|
fromRadioScratch.which_payload_variant = FromRadio_moduleConfig_tag;
|
||||||
|
switch (config_state) {
|
||||||
|
case ModuleConfig_mqtt_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_mqtt_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.mqtt = moduleConfig.mqtt;
|
||||||
|
break;
|
||||||
|
case ModuleConfig_serial_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_serial_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
|
||||||
|
break;
|
||||||
|
case ModuleConfig_external_notification_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_external_notification_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
|
||||||
|
break;
|
||||||
|
case ModuleConfig_range_test_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_range_test_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
|
||||||
|
break;
|
||||||
|
case ModuleConfig_telemetry_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_telemetry_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.telemetry = moduleConfig.telemetry;
|
||||||
|
break;
|
||||||
|
case ModuleConfig_canned_message_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_canned_message_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_state++;
|
||||||
|
// Advance when we have sent all of our ModuleConfig objects
|
||||||
|
if (config_state > ModuleConfig_canned_message_tag) {
|
||||||
|
state = STATE_SEND_COMPLETE_ID;
|
||||||
|
config_state = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case STATE_SEND_COMPLETE_ID:
|
case STATE_SEND_COMPLETE_ID:
|
||||||
fromRadioScratch.which_payloadVariant = FromRadio_config_complete_id_tag;
|
DEBUG_MSG("getFromRadio=STATE_SEND_COMPLETE_ID\n");
|
||||||
|
fromRadioScratch.which_payload_variant = FromRadio_config_complete_id_tag;
|
||||||
fromRadioScratch.config_complete_id = config_nonce;
|
fromRadioScratch.config_complete_id = config_nonce;
|
||||||
config_nonce = 0;
|
config_nonce = 0;
|
||||||
state = STATE_SEND_PACKETS;
|
state = STATE_SEND_PACKETS;
|
||||||
@@ -252,11 +269,12 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
|
|
||||||
case STATE_SEND_PACKETS:
|
case STATE_SEND_PACKETS:
|
||||||
// Do we have a message from the mesh?
|
// Do we have a message from the mesh?
|
||||||
|
DEBUG_MSG("getFromRadio=STATE_SEND_PACKETS\n");
|
||||||
if (packetForPhone) {
|
if (packetForPhone) {
|
||||||
printPacket("phone downloaded packet", packetForPhone);
|
printPacket("phone downloaded packet", packetForPhone);
|
||||||
|
|
||||||
// Encapsulate as a FromRadio packet
|
// Encapsulate as a FromRadio packet
|
||||||
fromRadioScratch.which_payloadVariant = FromRadio_packet_tag;
|
fromRadioScratch.which_payload_variant = FromRadio_packet_tag;
|
||||||
fromRadioScratch.packet = *packetForPhone;
|
fromRadioScratch.packet = *packetForPhone;
|
||||||
}
|
}
|
||||||
releasePhonePacket();
|
releasePhonePacket();
|
||||||
@@ -267,10 +285,11 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do we have a message from the mesh?
|
// Do we have a message from the mesh?
|
||||||
if (fromRadioScratch.which_payloadVariant != 0) {
|
if (fromRadioScratch.which_payload_variant != 0) {
|
||||||
// Encapsulate as a FromRadio packet
|
// Encapsulate as a FromRadio packet
|
||||||
size_t numbytes = pb_encode_to_bytes(buf, FromRadio_size, FromRadio_fields, &fromRadioScratch);
|
size_t numbytes = pb_encode_to_bytes(buf, FromRadio_size, FromRadio_fields, &fromRadioScratch);
|
||||||
// DEBUG_MSG("encoding toPhone packet to phone variant=%d, %d bytes\n", fromRadioScratch.which_payloadVariant, numbytes);
|
|
||||||
|
DEBUG_MSG("encoding toPhone packet to phone variant=%d, %d bytes\n", fromRadioScratch.which_payload_variant, numbytes);
|
||||||
return numbytes;
|
return numbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +297,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhoneAPI::handleDisconnect() {}
|
void PhoneAPI::handleDisconnect()
|
||||||
|
{
|
||||||
|
DEBUG_MSG("PhoneAPI disconnect\n");
|
||||||
|
}
|
||||||
|
|
||||||
void PhoneAPI::releasePhonePacket()
|
void PhoneAPI::releasePhonePacket()
|
||||||
{
|
{
|
||||||
@@ -296,33 +318,24 @@ bool PhoneAPI::available()
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case STATE_SEND_NOTHING:
|
case STATE_SEND_NOTHING:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case STATE_SEND_MY_INFO:
|
case STATE_SEND_MY_INFO:
|
||||||
return true;
|
case STATE_SEND_CHANNELS:
|
||||||
|
|
||||||
case STATE_SEND_CONFIG:
|
case STATE_SEND_CONFIG:
|
||||||
return true;
|
|
||||||
|
|
||||||
case STATE_SEND_MODULECONFIG:
|
case STATE_SEND_MODULECONFIG:
|
||||||
|
case STATE_SEND_COMPLETE_ID:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case STATE_SEND_NODEINFO:
|
case STATE_SEND_NODEINFO:
|
||||||
if (!nodeInfoForPhone)
|
if (!nodeInfoForPhone)
|
||||||
nodeInfoForPhone = nodeDB.readNextInfo();
|
nodeInfoForPhone = nodeDB.readNextInfo();
|
||||||
return true; // Always say we have something, because we might need to advance our state machine
|
return true; // Always say we have something, because we might need to advance our state machine
|
||||||
|
|
||||||
case STATE_SEND_COMPLETE_ID:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case STATE_SEND_PACKETS: {
|
case STATE_SEND_PACKETS: {
|
||||||
// Try to pull a new packet from the service (if we haven't already)
|
|
||||||
if (!packetForPhone)
|
if (!packetForPhone)
|
||||||
packetForPhone = service.getForPhone();
|
packetForPhone = service.getForPhone();
|
||||||
bool hasPacket = !!packetForPhone;
|
bool hasPacket = !!packetForPhone;
|
||||||
// DEBUG_MSG("available hasPacket=%d\n", hasPacket);
|
// DEBUG_MSG("available hasPacket=%d\n", hasPacket);
|
||||||
return hasPacket;
|
return hasPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0); // unexpected state - FIXME, make an error code and reboot
|
assert(0); // unexpected state - FIXME, make an error code and reboot
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,23 +16,22 @@
|
|||||||
* Eventually there should be once instance of this class for each live connection (because it has a bit of state
|
* Eventually there should be once instance of this class for each live connection (because it has a bit of state
|
||||||
* for that connection)
|
* for that connection)
|
||||||
*/
|
*/
|
||||||
class PhoneAPI
|
class PhoneAPI : public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
|
||||||
: public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
|
|
||||||
{
|
{
|
||||||
enum State {
|
enum State {
|
||||||
STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
|
STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
|
||||||
STATE_SEND_MY_INFO, // send our my info record
|
STATE_SEND_MY_INFO, // send our my info record
|
||||||
STATE_SEND_GROUPS, // new in 1.3?
|
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
|
||||||
|
STATE_SEND_CHANNELS, // Send all channels
|
||||||
STATE_SEND_CONFIG, // Replacement for the old Radioconfig
|
STATE_SEND_CONFIG, // Replacement for the old Radioconfig
|
||||||
STATE_SEND_MODULECONFIG, // Send Module specific config
|
STATE_SEND_MODULECONFIG, // Send Module specific config
|
||||||
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
|
|
||||||
STATE_SEND_COMPLETE_ID,
|
STATE_SEND_COMPLETE_ID,
|
||||||
STATE_SEND_PACKETS // send packets or debug strings
|
STATE_SEND_PACKETS // send packets or debug strings
|
||||||
};
|
};
|
||||||
|
|
||||||
State state = STATE_SEND_NOTHING;
|
State state = STATE_SEND_NOTHING;
|
||||||
|
|
||||||
int8_t config_state = Config_device_tag;
|
uint8_t config_state = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each packet sent to the phone has an incrementing count
|
* Each packet sent to the phone has an incrementing count
|
||||||
@@ -60,7 +59,7 @@ class PhoneAPI
|
|||||||
// Call this when the client drops the connection, resets the state to STATE_SEND_NOTHING
|
// Call this when the client drops the connection, resets the state to STATE_SEND_NOTHING
|
||||||
// Unregisters our observer. A closed connection **can** be reopened by calling init again.
|
// Unregisters our observer. A closed connection **can** be reopened by calling init again.
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a ToRadio protobuf
|
* Handle a ToRadio protobuf
|
||||||
* @return true true if a packet was queued for sending (so that caller can yield)
|
* @return true true if a packet was queued for sending (so that caller can yield)
|
||||||
@@ -82,6 +81,8 @@ class PhoneAPI
|
|||||||
|
|
||||||
bool isConnected() { return state != STATE_SEND_NOTHING; }
|
bool isConnected() { return state != STATE_SEND_NOTHING; }
|
||||||
|
|
||||||
|
void setInitialState() { state = STATE_SEND_MY_INFO; }
|
||||||
|
|
||||||
/// emit a debugging log character, FIXME - implement
|
/// emit a debugging log character, FIXME - implement
|
||||||
void debugOut(char c) { }
|
void debugOut(char c) { }
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ template <class T> class ProtobufModule : protected SinglePortModule
|
|||||||
|
|
||||||
T scratch;
|
T scratch;
|
||||||
T *decoded = NULL;
|
T *decoded = NULL;
|
||||||
if (mp.which_payloadVariant == MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
|
if (mp.which_payload_variant == MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
|
||||||
memset(&scratch, 0, sizeof(scratch));
|
memset(&scratch, 0, sizeof(scratch));
|
||||||
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) {
|
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) {
|
||||||
decoded = &scratch;
|
decoded = &scratch;
|
||||||
|
|||||||
@@ -104,15 +104,15 @@ bool RF95Interface::reconfigure()
|
|||||||
// configure publicly accessible settings
|
// configure publicly accessible settings
|
||||||
int err = lora->setSpreadingFactor(sf);
|
int err = lora->setSpreadingFactor(sf);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
err = lora->setBandwidth(bw);
|
err = lora->setBandwidth(bw);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
err = lora->setCodingRate(cr);
|
err = lora->setCodingRate(cr);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
err = lora->setSyncWord(syncWord);
|
err = lora->setSyncWord(syncWord);
|
||||||
assert(err == RADIOLIB_ERR_NONE);
|
assert(err == RADIOLIB_ERR_NONE);
|
||||||
@@ -125,13 +125,13 @@ bool RF95Interface::reconfigure()
|
|||||||
|
|
||||||
err = lora->setFrequency(getFreq());
|
err = lora->setFrequency(getFreq());
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
if (power > MAX_POWER) // This chip has lower power limits than some
|
if (power > MAX_POWER) // This chip has lower power limits than some
|
||||||
power = MAX_POWER;
|
power = MAX_POWER;
|
||||||
err = lora->setOutputPower(power);
|
err = lora->setOutputPower(power);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
startReceive(); // restart receiving
|
startReceive(); // restart receiving
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const RegionInfo regions[] = {
|
|||||||
/*
|
/*
|
||||||
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
||||||
*/
|
*/
|
||||||
RDEF(EU433, 433.0f, 434.0f, 10, 0, 12, true, false),
|
RDEF(EU_433, 433.0f, 434.0f, 10, 0, 12, true, false),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/
|
https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/
|
||||||
@@ -43,7 +43,7 @@ const RegionInfo regions[] = {
|
|||||||
(Please refer to section 4.21 in the following document)
|
(Please refer to section 4.21 in the following document)
|
||||||
https://ec.europa.eu/growth/tools-databases/tris/index.cfm/ro/search/?trisaction=search.detail&year=2021&num=528&dLang=EN
|
https://ec.europa.eu/growth/tools-databases/tris/index.cfm/ro/search/?trisaction=search.detail&year=2021&num=528&dLang=EN
|
||||||
*/
|
*/
|
||||||
RDEF(EU868, 869.4f, 869.65f, 10, 0, 27, false, false),
|
RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
||||||
@@ -88,7 +88,7 @@ const RegionInfo regions[] = {
|
|||||||
https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752
|
https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752
|
||||||
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
|
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
|
||||||
*/
|
*/
|
||||||
RDEF(NZ865, 864.0f, 868.0f, 100, 0, 0, true, false),
|
RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 0, true, false),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
|
||||||
@@ -98,7 +98,7 @@ const RegionInfo regions[] = {
|
|||||||
/*
|
/*
|
||||||
This needs to be last. Same as US.
|
This needs to be last. Same as US.
|
||||||
*/
|
*/
|
||||||
RDEF(Unset, 902.0f, 928.0f, 100, 0, 30, true, false)
|
RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ const RegionInfo *myRegion;
|
|||||||
void initRegion()
|
void initRegion()
|
||||||
{
|
{
|
||||||
const RegionInfo *r = regions;
|
const RegionInfo *r = regions;
|
||||||
for (; r->code != Config_LoRaConfig_RegionCode_Unset && r->code != config.lora.region; r++)
|
for (; r->code != Config_LoRaConfig_RegionCode_UNSET && r->code != config.lora.region; r++)
|
||||||
;
|
;
|
||||||
myRegion = r;
|
myRegion = r;
|
||||||
DEBUG_MSG("Wanted region %d, using %s\n", config.lora.region, r->name);
|
DEBUG_MSG("Wanted region %d, using %s\n", config.lora.region, r->name);
|
||||||
@@ -157,7 +157,7 @@ uint32_t RadioInterface::getPacketTime(uint32_t pl)
|
|||||||
|
|
||||||
uint32_t RadioInterface::getPacketTime(MeshPacket *p)
|
uint32_t RadioInterface::getPacketTime(MeshPacket *p)
|
||||||
{
|
{
|
||||||
assert(p->which_payloadVariant == MeshPacket_encrypted_tag); // It should have already been encoded by now
|
assert(p->which_payload_variant == MeshPacket_encrypted_tag); // It should have already been encoded by now
|
||||||
uint32_t pl = p->encrypted.size + sizeof(PacketHeader);
|
uint32_t pl = p->encrypted.size + sizeof(PacketHeader);
|
||||||
|
|
||||||
return getPacketTime(pl);
|
return getPacketTime(pl);
|
||||||
@@ -204,8 +204,8 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
|||||||
uint32_t delay = 0;
|
uint32_t delay = 0;
|
||||||
uint8_t CWsize = map(snr, SNR_MIN, SNR_MAX, CWmin, CWmax);
|
uint8_t CWsize = map(snr, SNR_MIN, SNR_MAX, CWmin, CWmax);
|
||||||
// DEBUG_MSG("rx_snr of %f so setting CWsize to:%d\n", snr, CWsize);
|
// DEBUG_MSG("rx_snr of %f so setting CWsize to:%d\n", snr, CWsize);
|
||||||
if (config.device.role == Config_DeviceConfig_Role_Router ||
|
if (config.device.role == Config_DeviceConfig_Role_ROUTER ||
|
||||||
config.device.role == Config_DeviceConfig_Role_RouterClient) {
|
config.device.role == Config_DeviceConfig_Role_ROUTER_CLIENT) {
|
||||||
delay = random(0, 2*CWsize) * slotTimeMsec;
|
delay = random(0, 2*CWsize) * slotTimeMsec;
|
||||||
DEBUG_MSG("rx_snr found in packet. As a router, setting tx delay:%d\n", delay);
|
DEBUG_MSG("rx_snr found in packet. As a router, setting tx delay:%d\n", delay);
|
||||||
} else {
|
} else {
|
||||||
@@ -220,7 +220,7 @@ void printPacket(const char *prefix, const MeshPacket *p)
|
|||||||
{
|
{
|
||||||
DEBUG_MSG("%s (id=0x%08x Fr0x%02x To0x%02x, WantAck%d, HopLim%d Ch0x%x", prefix, p->id, p->from & 0xff, p->to & 0xff,
|
DEBUG_MSG("%s (id=0x%08x Fr0x%02x To0x%02x, WantAck%d, HopLim%d Ch0x%x", prefix, p->id, p->from & 0xff, p->to & 0xff,
|
||||||
p->want_ack, p->hop_limit, p->channel);
|
p->want_ack, p->hop_limit, p->channel);
|
||||||
if (p->which_payloadVariant == MeshPacket_decoded_tag) {
|
if (p->which_payload_variant == MeshPacket_decoded_tag) {
|
||||||
auto &s = p->decoded;
|
auto &s = p->decoded;
|
||||||
|
|
||||||
DEBUG_MSG(" Portnum=%d", s.portnum);
|
DEBUG_MSG(" Portnum=%d", s.portnum);
|
||||||
@@ -354,40 +354,39 @@ void RadioInterface::applyModemConfig()
|
|||||||
// Set up default configuration
|
// Set up default configuration
|
||||||
// No Sync Words in LORA mode
|
// No Sync Words in LORA mode
|
||||||
Config_LoRaConfig &loraConfig = config.lora;
|
Config_LoRaConfig &loraConfig = config.lora;
|
||||||
auto channelSettings = channels.getPrimary();
|
|
||||||
if (loraConfig.spread_factor == 0) {
|
if (loraConfig.spread_factor == 0) {
|
||||||
switch (loraConfig.modem_preset) {
|
switch (loraConfig.modem_preset) {
|
||||||
case Config_LoRaConfig_ModemPreset_ShortFast:
|
case Config_LoRaConfig_ModemPreset_SHORT_FAST:
|
||||||
bw = 250;
|
bw = 250;
|
||||||
cr = 8;
|
cr = 8;
|
||||||
sf = 7;
|
sf = 7;
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_ShortSlow:
|
case Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||||
bw = 250;
|
bw = 250;
|
||||||
cr = 8;
|
cr = 8;
|
||||||
sf = 8;
|
sf = 8;
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_MedFast:
|
case Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
|
||||||
bw = 250;
|
bw = 250;
|
||||||
cr = 8;
|
cr = 8;
|
||||||
sf = 9;
|
sf = 9;
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_MedSlow:
|
case Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
|
||||||
bw = 250;
|
bw = 250;
|
||||||
cr = 8;
|
cr = 8;
|
||||||
sf = 10;
|
sf = 10;
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_LongFast:
|
case Config_LoRaConfig_ModemPreset_LONG_FAST:
|
||||||
bw = 250;
|
bw = 250;
|
||||||
cr = 8;
|
cr = 8;
|
||||||
sf = 11;
|
sf = 11;
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_LongSlow:
|
case Config_LoRaConfig_ModemPreset_LONG_SLOW:
|
||||||
bw = 125;
|
bw = 125;
|
||||||
cr = 8;
|
cr = 8;
|
||||||
sf = 12;
|
sf = 12;
|
||||||
break;
|
break;
|
||||||
case Config_LoRaConfig_ModemPreset_VLongSlow:
|
case Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
|
||||||
bw = 31.25;
|
bw = 31.25;
|
||||||
cr = 8;
|
cr = 8;
|
||||||
sf = 12;
|
sf = 12;
|
||||||
@@ -414,19 +413,22 @@ void RadioInterface::applyModemConfig()
|
|||||||
|
|
||||||
if (power == 0)
|
if (power == 0)
|
||||||
power = 17; // Default to default power if we don't have a valid power
|
power = 17; // Default to default power if we don't have a valid power
|
||||||
|
|
||||||
|
// Set final tx_power back onto config
|
||||||
|
loraConfig.tx_power = power;
|
||||||
|
|
||||||
// Calculate the number of channels
|
// Calculate the number of channels
|
||||||
uint32_t numChannels = floor((myRegion->freqEnd - myRegion->freqStart) / (myRegion->spacing + (bw / 1000)));
|
uint32_t numChannels = floor((myRegion->freqEnd - myRegion->freqStart) / (myRegion->spacing + (bw / 1000)));
|
||||||
|
|
||||||
// If user has manually specified a channel num, then use that, otherwise generate one by hashing the name
|
// If user has manually specified a channel num, then use that, otherwise generate one by hashing the name
|
||||||
const char *channelName = channels.getName(channels.getPrimaryIndex());
|
const char *channelName = channels.getName(channels.getPrimaryIndex());
|
||||||
int channel_num = channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelName) % numChannels;
|
int channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels;
|
||||||
|
|
||||||
// Old frequency selection formula
|
// Old frequency selection formula
|
||||||
// float freq = myRegion->freqStart + ((((myRegion->freqEnd - myRegion->freqStart) / numChannels) / 2) * channel_num);
|
// float freq = myRegion->freqStart + ((((myRegion->freqEnd - myRegion->freqStart) / numChannels) / 2) * channel_num);
|
||||||
|
|
||||||
// New frequency selection formula
|
// New frequency selection formula
|
||||||
float freq = myRegion->freqStart + (bw / 2) + ( channel_num * bw);
|
float freq = myRegion->freqStart + (bw / 2000) + ( channel_num * (bw / 1000));
|
||||||
|
|
||||||
saveChannelNum(channel_num);
|
saveChannelNum(channel_num);
|
||||||
saveFreq(freq + config.lora.frequency_offset);
|
saveFreq(freq + config.lora.frequency_offset);
|
||||||
@@ -458,12 +460,6 @@ void RadioInterface::limitPower()
|
|||||||
DEBUG_MSG("Set radio: final power level=%d\n", power);
|
DEBUG_MSG("Set radio: final power level=%d\n", power);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode SimRadio::send(MeshPacket *p)
|
|
||||||
{
|
|
||||||
DEBUG_MSG("SimRadio.send\n");
|
|
||||||
packetPool.release(p);
|
|
||||||
return ERRNO_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RadioInterface::deliverToReceiver(MeshPacket *p)
|
void RadioInterface::deliverToReceiver(MeshPacket *p)
|
||||||
{
|
{
|
||||||
@@ -479,7 +475,7 @@ size_t RadioInterface::beginSending(MeshPacket *p)
|
|||||||
assert(!sendingPacket);
|
assert(!sendingPacket);
|
||||||
|
|
||||||
// DEBUG_MSG("sending queued packet on mesh (txGood=%d,rxGood=%d,rxBad=%d)\n", rf95.txGood(), rf95.rxGood(), rf95.rxBad());
|
// DEBUG_MSG("sending queued packet on mesh (txGood=%d,rxGood=%d,rxBad=%d)\n", rf95.txGood(), rf95.rxGood(), rf95.rxBad());
|
||||||
assert(p->which_payloadVariant == MeshPacket_encrypted_tag); // It should have already been encoded by now
|
assert(p->which_payload_variant == MeshPacket_encrypted_tag); // It should have already been encoded by now
|
||||||
|
|
||||||
lastTxStart = millis();
|
lastTxStart = millis();
|
||||||
|
|
||||||
|
|||||||
@@ -212,11 +212,6 @@ class RadioInterface
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SimRadio : public RadioInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ErrorCode send(MeshPacket *p) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Debug printing for packets
|
/// Debug printing for packets
|
||||||
void printPacket(const char *prefix, const MeshPacket *p);
|
void printPacket(const char *prefix, const MeshPacket *p);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
|
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
|
||||||
static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
|
static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
|
||||||
|
|
||||||
#ifdef PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
|
|
||||||
void LockingModule::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes)
|
void LockingModule::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes)
|
||||||
{
|
{
|
||||||
@@ -43,9 +43,13 @@ RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq
|
|||||||
: NotifiedWorkerThread("RadioIf"), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface)
|
: NotifiedWorkerThread("RadioIf"), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface)
|
||||||
{
|
{
|
||||||
instance = this;
|
instance = this;
|
||||||
|
#if defined(ARCH_STM32WL) && defined(USE_SX1262)
|
||||||
|
module.setCb_digitalWrite(stm32wl_emulate_digitalWrite);
|
||||||
|
module.setCb_digitalRead(stm32wl_emulate_digitalRead);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// ESP32 doesn't use that flag
|
// ESP32 doesn't use that flag
|
||||||
#define YIELD_FROM_ISR(x) portYIELD_FROM_ISR()
|
#define YIELD_FROM_ISR(x) portYIELD_FROM_ISR()
|
||||||
#else
|
#else
|
||||||
@@ -95,8 +99,8 @@ bool RadioLibInterface::canSendImmediately()
|
|||||||
// TX IRQ from the radio, the radio is probably broken.
|
// TX IRQ from the radio, the radio is probably broken.
|
||||||
if (busyTx && (millis() - lastTxStart > 60000)) {
|
if (busyTx && (millis() - lastTxStart > 60000)) {
|
||||||
DEBUG_MSG("Hardware Failure! busyTx for more than 60s\n");
|
DEBUG_MSG("Hardware Failure! busyTx for more than 60s\n");
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_TransmitFailed);
|
RECORD_CRITICALERROR(CriticalErrorCode_TRANSMIT_FAILED);
|
||||||
#ifndef NO_ESP32
|
#ifdef ARCH_ESP32
|
||||||
if (busyTx && (millis() - lastTxStart > 65000)) // After 5s more, reboot
|
if (busyTx && (millis() - lastTxStart > 65000)) // After 5s more, reboot
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
#endif
|
#endif
|
||||||
@@ -116,18 +120,18 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
|||||||
|
|
||||||
#ifndef DISABLE_WELCOME_UNSET
|
#ifndef DISABLE_WELCOME_UNSET
|
||||||
|
|
||||||
if (config.lora.region != Config_LoRaConfig_RegionCode_Unset) {
|
if (config.lora.region != Config_LoRaConfig_RegionCode_UNSET) {
|
||||||
if (disabled || config.lora.tx_disabled) {
|
if (disabled || !config.lora.tx_enabled) {
|
||||||
|
|
||||||
if (config.lora.region != Config_LoRaConfig_RegionCode_Unset) {
|
if (config.lora.region != Config_LoRaConfig_RegionCode_UNSET) {
|
||||||
if (disabled || config.lora.tx_disabled) {
|
if (disabled || !config.lora.tx_enabled) {
|
||||||
DEBUG_MSG("send - lora_tx_disabled\n");
|
DEBUG_MSG("send - !config.lora.tx_enabled\n");
|
||||||
packetPool.release(p);
|
packetPool.release(p);
|
||||||
return ERRNO_DISABLED;
|
return ERRNO_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("send - lora_tx_disabled because RegionCode_Unset\n");
|
DEBUG_MSG("send - lora tx disable because RegionCode_Unset\n");
|
||||||
packetPool.release(p);
|
packetPool.release(p);
|
||||||
return ERRNO_DISABLED;
|
return ERRNO_DISABLED;
|
||||||
}
|
}
|
||||||
@@ -136,8 +140,8 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (disabled || config.lora.tx_disabled) {
|
if (disabled || !config.lora.tx_enabled) {
|
||||||
DEBUG_MSG("send - lora_tx_disabled\n");
|
DEBUG_MSG("send - !config.lora.tx_enabled\n");
|
||||||
packetPool.release(p);
|
packetPool.release(p);
|
||||||
return ERRNO_DISABLED;
|
return ERRNO_DISABLED;
|
||||||
}
|
}
|
||||||
@@ -358,7 +362,7 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
|||||||
|
|
||||||
addReceiveMetadata(mp);
|
addReceiveMetadata(mp);
|
||||||
|
|
||||||
mp->which_payloadVariant = MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point
|
mp->which_payload_variant = MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point
|
||||||
assert(((uint32_t)payloadLen) <= sizeof(mp->encrypted.bytes));
|
assert(((uint32_t)payloadLen) <= sizeof(mp->encrypted.bytes));
|
||||||
memcpy(mp->encrypted.bytes, payload, payloadLen);
|
memcpy(mp->encrypted.bytes, payload, payloadLen);
|
||||||
mp->encrypted.size = payloadLen;
|
mp->encrypted.size = payloadLen;
|
||||||
@@ -377,7 +381,7 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
|||||||
void RadioLibInterface::startSend(MeshPacket * txp)
|
void RadioLibInterface::startSend(MeshPacket * txp)
|
||||||
{
|
{
|
||||||
printPacket("Starting low level send", txp);
|
printPacket("Starting low level send", txp);
|
||||||
if (disabled || config.lora.tx_disabled) {
|
if (disabled || !config.lora.tx_enabled) {
|
||||||
DEBUG_MSG("startSend is dropping tx packet because we are disabled\n");
|
DEBUG_MSG("startSend is dropping tx packet because we are disabled\n");
|
||||||
packetPool.release(txp);
|
packetPool.release(txp);
|
||||||
} else {
|
} else {
|
||||||
@@ -389,7 +393,7 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
|||||||
|
|
||||||
int res = iface->startTransmit(radiobuf, numbytes);
|
int res = iface->startTransmit(radiobuf, numbytes);
|
||||||
if (res != RADIOLIB_ERR_NONE) {
|
if (res != RADIOLIB_ERR_NONE) {
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_RadioSpiBug);
|
RECORD_CRITICALERROR(CriticalErrorCode_RADIO_SPI_BUG);
|
||||||
|
|
||||||
// This send failed, but make sure to 'complete' it properly
|
// This send failed, but make sure to 'complete' it properly
|
||||||
completeSending();
|
completeSending();
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class LockingModule : public Module
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes) override;
|
void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes) override;
|
||||||
#else
|
#else
|
||||||
void SPIbeginTransaction() override;
|
void SPIbeginTransaction() override;
|
||||||
|
|||||||
@@ -16,12 +16,8 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
|
|||||||
// If someone asks for acks on broadcast, we need the hop limit to be at least one, so that first node that receives our
|
// If someone asks for acks on broadcast, we need the hop limit to be at least one, so that first node that receives our
|
||||||
// message will rebroadcast. But asking for hop_limit 0 in that context means the client app has no preference on hop
|
// message will rebroadcast. But asking for hop_limit 0 in that context means the client app has no preference on hop
|
||||||
// counts and we want this message to get through the whole mesh, so use the default.
|
// counts and we want this message to get through the whole mesh, so use the default.
|
||||||
if (p->to == NODENUM_BROADCAST && p->hop_limit == 0) {
|
if (p->hop_limit == 0) {
|
||||||
if (config.lora.hop_limit && config.lora.hop_limit <= HOP_MAX) {
|
p->hop_limit = (config.lora.hop_limit >= HOP_MAX) ? HOP_MAX : config.lora.hop_limit;
|
||||||
p->hop_limit = (config.lora.hop_limit >= HOP_MAX) ? HOP_MAX : config.lora.hop_limit;
|
|
||||||
} else {
|
|
||||||
p->hop_limit = HOP_RELIABLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto copy = packetPool.allocCopy(*p);
|
auto copy = packetPool.allocCopy(*p);
|
||||||
@@ -34,7 +30,7 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
|
|||||||
bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
|
bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
|
||||||
{
|
{
|
||||||
// Note: do not use getFrom() here, because we want to ignore messages sent from phone
|
// Note: do not use getFrom() here, because we want to ignore messages sent from phone
|
||||||
if (p->to == NODENUM_BROADCAST && p->from == getNodeNum()) {
|
if (p->from == getNodeNum()) {
|
||||||
printPacket("Rx someone rebroadcasting for us", p);
|
printPacket("Rx someone rebroadcasting for us", p);
|
||||||
|
|
||||||
// We are seeing someone rebroadcast one of our broadcast attempts.
|
// We are seeing someone rebroadcast one of our broadcast attempts.
|
||||||
@@ -62,11 +58,17 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
|
|||||||
* this way if an ACK is dropped and a packet is resent we'll ACK the resent packet
|
* this way if an ACK is dropped and a packet is resent we'll ACK the resent packet
|
||||||
* make sure wasSeenRecently _doesn't_ update
|
* make sure wasSeenRecently _doesn't_ update
|
||||||
* finding the channel requires decoding the packet. */
|
* finding the channel requires decoding the packet. */
|
||||||
if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false)) {
|
if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false) && !MeshModule::currentReply) {
|
||||||
if (perhapsDecode(p)) {
|
if (perhapsDecode(p)) {
|
||||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
|
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
|
||||||
DEBUG_MSG("acking a repeated want_ack packet\n");
|
DEBUG_MSG("acking a repeated want_ack packet\n");
|
||||||
}
|
}
|
||||||
|
} else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE && !MeshModule::currentReply) {
|
||||||
|
// retransmission on broadcast has hop_limit still equal to HOP_RELIABLE
|
||||||
|
DEBUG_MSG("Resending implicit ack for a repeated floodmsg\n");
|
||||||
|
MeshPacket *tosend = packetPool.allocCopy(*p);
|
||||||
|
tosend->hop_limit--; // bump down the hop count
|
||||||
|
Router::send(tosend);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FloodingRouter::shouldFilterReceived(p);
|
return FloodingRouter::shouldFilterReceived(p);
|
||||||
@@ -92,7 +94,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
|||||||
// - not DSR routing)
|
// - not DSR routing)
|
||||||
if (p->want_ack) {
|
if (p->want_ack) {
|
||||||
if (MeshModule::currentReply)
|
if (MeshModule::currentReply)
|
||||||
DEBUG_MSG("Someone else has replied to this message, no need for a 2nd ack\n");
|
DEBUG_MSG("Some other module has replied to this message, no need for a 2nd ack\n");
|
||||||
else
|
else
|
||||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
|
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
|
||||||
}
|
}
|
||||||
@@ -106,7 +108,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
|||||||
// We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records
|
// We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records
|
||||||
if (ackId || nakId) {
|
if (ackId || nakId) {
|
||||||
if (ackId) {
|
if (ackId) {
|
||||||
DEBUG_MSG("Received a ack for 0x%x, stopping retransmissions\n", ackId);
|
DEBUG_MSG("Received an ack for 0x%x, stopping retransmissions\n", ackId);
|
||||||
stopRetransmission(p->to, ackId);
|
stopRetransmission(p->to, ackId);
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Received a nak for 0x%x, stopping retransmissions\n", nakId);
|
DEBUG_MSG("Received a nak for 0x%x, stopping retransmissions\n", nakId);
|
||||||
@@ -231,4 +233,4 @@ void ReliableRouter::setNextTx(PendingPacket *pending)
|
|||||||
DEBUG_MSG("Setting next retransmission in %u msecs: ", d);
|
DEBUG_MSG("Setting next retransmission in %u msecs: ", d);
|
||||||
printPacket("", pending->packet);
|
printPacket("", pending->packet);
|
||||||
setReceivedMessage(); // Run ASAP, so we can figure out our correct sleep time
|
setReceivedMessage(); // Run ASAP, so we can figure out our correct sleep time
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ extern "C" {
|
|||||||
#include "mesh/compression/unishox2.h"
|
#include "mesh/compression/unishox2.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
#if HAS_WIFI
|
||||||
#include "mqtt/MQTT.h"
|
#include "mqtt/MQTT.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -115,14 +115,10 @@ MeshPacket *Router::allocForSending()
|
|||||||
{
|
{
|
||||||
MeshPacket *p = packetPool.allocZeroed();
|
MeshPacket *p = packetPool.allocZeroed();
|
||||||
|
|
||||||
p->which_payloadVariant = MeshPacket_decoded_tag; // Assume payload is decoded at start.
|
p->which_payload_variant = MeshPacket_decoded_tag; // Assume payload is decoded at start.
|
||||||
p->from = nodeDB.getNodeNum();
|
p->from = nodeDB.getNodeNum();
|
||||||
p->to = NODENUM_BROADCAST;
|
p->to = NODENUM_BROADCAST;
|
||||||
if (config.lora.hop_limit && config.lora.hop_limit <= HOP_MAX) {
|
p->hop_limit = (config.lora.hop_limit >= HOP_MAX) ? HOP_MAX : config.lora.hop_limit;
|
||||||
p->hop_limit = (config.lora.hop_limit >= HOP_MAX) ? HOP_MAX : config.lora.hop_limit;
|
|
||||||
} else {
|
|
||||||
p->hop_limit = HOP_RELIABLE;
|
|
||||||
}
|
|
||||||
p->id = generatePacketId();
|
p->id = generatePacketId();
|
||||||
p->rx_time =
|
p->rx_time =
|
||||||
getValidTime(RTCQualityFromNet); // Just in case we process the packet locally - make sure it has a valid timestamp
|
getValidTime(RTCQualityFromNet); // Just in case we process the packet locally - make sure it has a valid timestamp
|
||||||
@@ -206,14 +202,14 @@ ErrorCode Router::send(MeshPacket *p)
|
|||||||
|
|
||||||
// If the packet hasn't yet been encrypted, do so now (it might already be encrypted if we are just forwarding it)
|
// If the packet hasn't yet been encrypted, do so now (it might already be encrypted if we are just forwarding it)
|
||||||
|
|
||||||
assert(p->which_payloadVariant == MeshPacket_encrypted_tag ||
|
assert(p->which_payload_variant == MeshPacket_encrypted_tag ||
|
||||||
p->which_payloadVariant == MeshPacket_decoded_tag); // I _think_ all packets should have a payload by now
|
p->which_payload_variant == MeshPacket_decoded_tag); // I _think_ all packets should have a payload by now
|
||||||
|
|
||||||
// If the packet is not yet encrypted, do so now
|
// If the packet is not yet encrypted, do so now
|
||||||
if (p->which_payloadVariant == MeshPacket_decoded_tag) {
|
if (p->which_payload_variant == MeshPacket_decoded_tag) {
|
||||||
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
|
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
|
||||||
|
|
||||||
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
#if HAS_WIFI
|
||||||
// check if we should send decrypted packets to mqtt
|
// check if we should send decrypted packets to mqtt
|
||||||
|
|
||||||
// truth table:
|
// truth table:
|
||||||
@@ -244,7 +240,7 @@ ErrorCode Router::send(MeshPacket *p)
|
|||||||
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
#if HAS_WIFI
|
||||||
// the packet is now encrypted.
|
// the packet is now encrypted.
|
||||||
// check if we should send encrypted packets to mqtt
|
// check if we should send encrypted packets to mqtt
|
||||||
if (mqtt && shouldActuallyEncrypt)
|
if (mqtt && shouldActuallyEncrypt)
|
||||||
@@ -277,7 +273,7 @@ bool perhapsDecode(MeshPacket *p)
|
|||||||
|
|
||||||
// DEBUG_MSG("\n\n** perhapsDecode payloadVariant - %d\n\n", p->which_payloadVariant);
|
// DEBUG_MSG("\n\n** perhapsDecode payloadVariant - %d\n\n", p->which_payloadVariant);
|
||||||
|
|
||||||
if (p->which_payloadVariant == MeshPacket_decoded_tag)
|
if (p->which_payload_variant == MeshPacket_decoded_tag)
|
||||||
return true; // If packet was already decoded just return
|
return true; // If packet was already decoded just return
|
||||||
|
|
||||||
// assert(p->which_payloadVariant == MeshPacket_encrypted_tag);
|
// assert(p->which_payloadVariant == MeshPacket_encrypted_tag);
|
||||||
@@ -304,7 +300,7 @@ bool perhapsDecode(MeshPacket *p)
|
|||||||
DEBUG_MSG("Invalid portnum (bad psk?)!\n");
|
DEBUG_MSG("Invalid portnum (bad psk?)!\n");
|
||||||
} else {
|
} else {
|
||||||
// parsing was successful
|
// parsing was successful
|
||||||
p->which_payloadVariant = MeshPacket_decoded_tag; // change type to decoded
|
p->which_payload_variant = MeshPacket_decoded_tag; // change type to decoded
|
||||||
p->channel = chIndex; // change to store the index instead of the hash
|
p->channel = chIndex; // change to store the index instead of the hash
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -349,7 +345,7 @@ bool perhapsDecode(MeshPacket *p)
|
|||||||
Routing_Error perhapsEncode(MeshPacket *p)
|
Routing_Error perhapsEncode(MeshPacket *p)
|
||||||
{
|
{
|
||||||
// If the packet is not yet encrypted, do so now
|
// If the packet is not yet encrypted, do so now
|
||||||
if (p->which_payloadVariant == MeshPacket_decoded_tag) {
|
if (p->which_payload_variant == MeshPacket_decoded_tag) {
|
||||||
static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union
|
static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union
|
||||||
|
|
||||||
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
|
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
|
||||||
@@ -407,7 +403,7 @@ Routing_Error perhapsEncode(MeshPacket *p)
|
|||||||
// Copy back into the packet and set the variant type
|
// Copy back into the packet and set the variant type
|
||||||
memcpy(p->encrypted.bytes, bytes, numbytes);
|
memcpy(p->encrypted.bytes, bytes, numbytes);
|
||||||
p->encrypted.size = numbytes;
|
p->encrypted.size = numbytes;
|
||||||
p->which_payloadVariant = MeshPacket_encrypted_tag;
|
p->which_payload_variant = MeshPacket_encrypted_tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Routing_Error_NONE;
|
return Routing_Error_NONE;
|
||||||
|
|||||||
@@ -116,15 +116,15 @@ bool SX126xInterface<T>::reconfigure()
|
|||||||
// configure publicly accessible settings
|
// configure publicly accessible settings
|
||||||
int err = lora.setSpreadingFactor(sf);
|
int err = lora.setSpreadingFactor(sf);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
err = lora.setBandwidth(bw);
|
err = lora.setBandwidth(bw);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
err = lora.setCodingRate(cr);
|
err = lora.setCodingRate(cr);
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
|
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
|
||||||
// TODO: Confirm gain registers are okay now
|
// TODO: Confirm gain registers are okay now
|
||||||
@@ -142,7 +142,7 @@ bool SX126xInterface<T>::reconfigure()
|
|||||||
|
|
||||||
err = lora.setFrequency(getFreq());
|
err = lora.setFrequency(getFreq());
|
||||||
if (err != RADIOLIB_ERR_NONE)
|
if (err != RADIOLIB_ERR_NONE)
|
||||||
RECORD_CRITICALERROR(CriticalErrorCode_InvalidRadioSetting);
|
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
|
||||||
|
|
||||||
if (power > 22) // This chip has lower power limits than some
|
if (power > 22) // This chip has lower power limits than some
|
||||||
power = 22;
|
power = 22;
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ class SinglePortModule : public MeshModule
|
|||||||
SinglePortModule(const char *_name, PortNum _ourPortNum) : MeshModule(_name), ourPortNum(_ourPortNum) {}
|
SinglePortModule(const char *_name, PortNum _ourPortNum) : MeshModule(_name), ourPortNum(_ourPortNum) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
uint32_t max_channel_util_percent = 40;
|
||||||
|
uint32_t polite_channel_util_percent = 25;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if you want to receive the specified portnum
|
* @return true if you want to receive the specified portnum
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -103,10 +103,7 @@ void StreamAPI::emitTxBuffer(size_t len)
|
|||||||
|
|
||||||
auto totalLen = len + HEADER_LEN;
|
auto totalLen = len + HEADER_LEN;
|
||||||
stream->write(txBuf, totalLen);
|
stream->write(txBuf, totalLen);
|
||||||
/* for(size_t i = 0; i < totalLen; i++) {
|
stream->flush();
|
||||||
stream->write(txBuf[i]);
|
|
||||||
// stream->flush();
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +111,7 @@ void StreamAPI::emitRebooted()
|
|||||||
{
|
{
|
||||||
// In case we send a FromRadio packet
|
// In case we send a FromRadio packet
|
||||||
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
|
||||||
fromRadioScratch.which_payloadVariant = FromRadio_rebooted_tag;
|
fromRadioScratch.which_payload_variant = FromRadio_rebooted_tag;
|
||||||
fromRadioScratch.rebooted = true;
|
fromRadioScratch.rebooted = true;
|
||||||
|
|
||||||
// DEBUG_MSG("Emitting reboot packet for serial shell\n");
|
// DEBUG_MSG("Emitting reboot packet for serial shell\n");
|
||||||
@@ -133,4 +130,4 @@ void StreamAPI::onConnectionChanged(bool connected)
|
|||||||
// received a packet in a while
|
// received a packet in a while
|
||||||
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
|
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -851,9 +851,11 @@ int readBit(const char *in, int bit_no) {
|
|||||||
int read8bitCode(const char *in, int len, int bit_no) {
|
int read8bitCode(const char *in, int len, int bit_no) {
|
||||||
int bit_pos = bit_no & 0x07;
|
int bit_pos = bit_no & 0x07;
|
||||||
int char_pos = bit_no >> 3;
|
int char_pos = bit_no >> 3;
|
||||||
|
len >>= 3;
|
||||||
byte code = (((byte)in[char_pos]) << bit_pos);
|
byte code = (((byte)in[char_pos]) << bit_pos);
|
||||||
if (bit_no + bit_pos < len) {
|
char_pos++;
|
||||||
code |= ((byte)in[++char_pos]) >> (8 - bit_pos);
|
if (char_pos < len) {
|
||||||
|
code |= ((byte)in[char_pos]) >> (8 - bit_pos);
|
||||||
} else
|
} else
|
||||||
code |= (0xFF >> (8 - bit_pos));
|
code |= (0xFF >> (8 - bit_pos));
|
||||||
return code;
|
return code;
|
||||||
@@ -1033,31 +1035,37 @@ int decodeRepeat(const char *in, int len, char *out, int olen, int ol, int *bit_
|
|||||||
if (prev_lines) {
|
if (prev_lines) {
|
||||||
int32_t dict_len = readCount(in, bit_no, len) + NICE_LEN;
|
int32_t dict_len = readCount(in, bit_no, len) + NICE_LEN;
|
||||||
if (dict_len < NICE_LEN)
|
if (dict_len < NICE_LEN)
|
||||||
return ol;
|
return -1;
|
||||||
int32_t dist = readCount(in, bit_no, len);
|
int32_t dist = readCount(in, bit_no, len);
|
||||||
if (dist < 0)
|
if (dist < 0)
|
||||||
return ol;
|
return -1;
|
||||||
int32_t ctx = readCount(in, bit_no, len);
|
int32_t ctx = readCount(in, bit_no, len);
|
||||||
if (ctx < 0)
|
if (ctx < 0)
|
||||||
return ol;
|
return -1;
|
||||||
struct us_lnk_lst *cur_line = prev_lines;
|
struct us_lnk_lst *cur_line = prev_lines;
|
||||||
const int left = olen - ol;
|
const int left = olen - ol;
|
||||||
while (ctx--)
|
while (ctx-- && cur_line)
|
||||||
cur_line = cur_line->previous;
|
cur_line = cur_line->previous;
|
||||||
|
if (cur_line == NULL)
|
||||||
|
return -1;
|
||||||
if (left <= 0) return olen + 1;
|
if (left <= 0) return olen + 1;
|
||||||
|
if (dist >= strlen(cur_line->data))
|
||||||
|
return -1;
|
||||||
memmove(out + ol, cur_line->data + dist, min_of(left, dict_len));
|
memmove(out + ol, cur_line->data + dist, min_of(left, dict_len));
|
||||||
if (left < dict_len) return olen + 1;
|
if (left < dict_len) return olen + 1;
|
||||||
ol += dict_len;
|
ol += dict_len;
|
||||||
} else {
|
} else {
|
||||||
int32_t dict_len = readCount(in, bit_no, len) + NICE_LEN;
|
int32_t dict_len = readCount(in, bit_no, len) + NICE_LEN;
|
||||||
if (dict_len < NICE_LEN)
|
if (dict_len < NICE_LEN)
|
||||||
return ol;
|
return -1;
|
||||||
int32_t dist = readCount(in, bit_no, len) + NICE_LEN - 1;
|
int32_t dist = readCount(in, bit_no, len) + NICE_LEN - 1;
|
||||||
if (dist < NICE_LEN - 1)
|
if (dist < NICE_LEN - 1)
|
||||||
return ol;
|
return -1;
|
||||||
const int32_t left = olen - ol;
|
const int32_t left = olen - ol;
|
||||||
//printf("Decode len: %d, dist: %d\n", dict_len - NICE_LEN, dist - NICE_LEN + 1);
|
//printf("Decode len: %d, dist: %d\n", dict_len - NICE_LEN, dist - NICE_LEN + 1);
|
||||||
if (left <= 0) return olen + 1;
|
if (left <= 0) return olen + 1;
|
||||||
|
if (ol - dist < 0)
|
||||||
|
return -1;
|
||||||
memmove(out + ol, out + ol - dist, min_of(left, dict_len));
|
memmove(out + ol, out + ol - dist, min_of(left, dict_len));
|
||||||
if (left < dict_len) return olen + 1;
|
if (left < dict_len) return olen + 1;
|
||||||
ol += dict_len;
|
ol += dict_len;
|
||||||
@@ -1119,7 +1127,10 @@ int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(c
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (h == USX_DICT) {
|
if (h == USX_DICT) {
|
||||||
DEC_OUTPUT_CHARS(olen, ol = decodeRepeat(in, len, out, olen, ol, &bit_no, prev_lines));
|
int rpt_ret = decodeRepeat(in, len, out, olen, ol, &bit_no, prev_lines);
|
||||||
|
if (rpt_ret < 0)
|
||||||
|
return ol; // if we break here it will only break out of switch
|
||||||
|
DEC_OUTPUT_CHARS(olen, ol = rpt_ret);
|
||||||
h = dstate;
|
h = dstate;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1191,7 +1202,10 @@ int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(c
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if (h == USX_DICT) {
|
if (h == USX_DICT) {
|
||||||
DEC_OUTPUT_CHARS(olen, ol = decodeRepeat(in, len, out, olen, ol, &bit_no, prev_lines));
|
int rpt_ret = decodeRepeat(in, len, out, olen, ol, &bit_no, prev_lines);
|
||||||
|
if (rpt_ret < 0)
|
||||||
|
break;
|
||||||
|
DEC_OUTPUT_CHARS(olen, ol = rpt_ret);
|
||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
if (h == USX_DELTA) {
|
if (h == USX_DELTA) {
|
||||||
@@ -1208,12 +1222,21 @@ int unishox2_decompress_lines(const char *in, int len, UNISHOX_API_OUT_AND_LEN(c
|
|||||||
}
|
}
|
||||||
if (h == USX_NUM && v == 0) {
|
if (h == USX_NUM && v == 0) {
|
||||||
int idx = getStepCodeIdx(in, len, &bit_no, 5);
|
int idx = getStepCodeIdx(in, len, &bit_no, 5);
|
||||||
|
if (idx == 99)
|
||||||
|
break;
|
||||||
if (idx == 0) {
|
if (idx == 0) {
|
||||||
idx = getStepCodeIdx(in, len, &bit_no, 4);
|
idx = getStepCodeIdx(in, len, &bit_no, 4);
|
||||||
|
if (idx >= 5)
|
||||||
|
break;
|
||||||
int32_t rem = readCount(in, &bit_no, len);
|
int32_t rem = readCount(in, &bit_no, len);
|
||||||
if (rem < 0)
|
if (rem < 0)
|
||||||
break;
|
break;
|
||||||
rem = (int)strlen(usx_templates[idx]) - rem;
|
if (usx_templates[idx] == NULL)
|
||||||
|
break;
|
||||||
|
size_t tlen = strlen(usx_templates[idx]);
|
||||||
|
if (rem > tlen)
|
||||||
|
break;
|
||||||
|
rem = tlen - rem;
|
||||||
int eof = 0;
|
int eof = 0;
|
||||||
for (int j = 0; j < rem; j++) {
|
for (int j = 0; j < rem; j++) {
|
||||||
char c_t = usx_templates[idx][j];
|
char c_t = usx_templates[idx][j];
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#error Regenerate this file with the current version of nanopb generator.
|
#error Regenerate this file with the current version of nanopb generator.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PB_BIND(AdminMessage, AdminMessage, AUTO)
|
PB_BIND(AdminMessage, AdminMessage, 2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user