Compare commits
439 Commits
v2.5.0.9e5
...
v2.5.6.d55
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d55c08d5cd | ||
|
|
e8f287a36f | ||
|
|
b769799410 | ||
|
|
f5f9fd54a1 | ||
|
|
f82585d9b0 | ||
|
|
1b04d41b9a | ||
|
|
3b21856a76 | ||
|
|
519ca9c0aa | ||
|
|
23a52ee625 | ||
|
|
7ff4bafe22 | ||
|
|
149620f071 | ||
|
|
0cbade989e | ||
|
|
411834afba | ||
|
|
1096973828 | ||
|
|
dc9aa6aff7 | ||
|
|
ad8747d914 | ||
|
|
ddd4a45bc3 | ||
|
|
4f8f96ab29 | ||
|
|
ee5091fee5 | ||
|
|
876993f095 | ||
|
|
a05b009379 | ||
|
|
5db4918413 | ||
|
|
a0dd7b43d5 | ||
|
|
b1f045cab8 | ||
|
|
2e5399dbe4 | ||
|
|
d005b1e49c | ||
|
|
9d9258a59b | ||
|
|
37f294d0a6 | ||
|
|
411aedaf5d | ||
|
|
1c54388bb8 | ||
|
|
94ecbad904 | ||
|
|
53f189fff4 | ||
|
|
93d874b013 | ||
|
|
234a56446b | ||
|
|
830281803f | ||
|
|
bb9f003c24 | ||
|
|
001a845ac3 | ||
|
|
7febb41727 | ||
|
|
ad031dd69f | ||
|
|
ebc3a66d10 | ||
|
|
553e572eb5 | ||
|
|
01df3ff477 | ||
|
|
a3a97d3025 | ||
|
|
0952d1b252 | ||
|
|
8a370c5381 | ||
|
|
a6f96cb9b4 | ||
|
|
d650001caa | ||
|
|
0c90a2274f | ||
|
|
dac433ed2f | ||
|
|
8acc9ccf5f | ||
|
|
243421b2a5 | ||
|
|
6d6ed55ed7 | ||
|
|
783466f116 | ||
|
|
55049ed547 | ||
|
|
e182ae75c2 | ||
|
|
7e946d15ca | ||
|
|
c3b9d493b6 | ||
|
|
4db0c75c8e | ||
|
|
e7cfadacd8 | ||
|
|
673fe294f3 | ||
|
|
236374491b | ||
|
|
d6f26c682d | ||
|
|
befc2ece6f | ||
|
|
b2b60eccdb | ||
|
|
07d4e6f5be | ||
|
|
0a93261c06 | ||
|
|
00f15459ec | ||
|
|
b8044c4983 | ||
|
|
18f12584ab | ||
|
|
e1e7bbc420 | ||
|
|
5f974d2961 | ||
|
|
cae2e43dc6 | ||
|
|
0d175a918c | ||
|
|
3440c640c3 | ||
|
|
b769d9f854 | ||
|
|
8d288d5a3c | ||
|
|
dc55d7dd98 | ||
|
|
553514e3b7 | ||
|
|
1dace9a508 | ||
|
|
dd587419c7 | ||
|
|
bce7d73cc6 | ||
|
|
810a79668c | ||
|
|
51ee6c11ea | ||
|
|
cb06ab10da | ||
|
|
199566a996 | ||
|
|
5fcad1d8c5 | ||
|
|
a5bcf48240 | ||
|
|
8ad89ba724 | ||
|
|
fd6e8613c6 | ||
|
|
b529099f90 | ||
|
|
3896009e55 | ||
|
|
6f506cead5 | ||
|
|
3492c9aa99 | ||
|
|
19f45d282f | ||
|
|
d73cbf14d5 | ||
|
|
d41d4c930e | ||
|
|
403e5c304e | ||
|
|
dcb2707d94 | ||
|
|
2e935fd943 | ||
|
|
88af23319c | ||
|
|
42a3301188 | ||
|
|
57b8b55fc5 | ||
|
|
d0440f3cac | ||
|
|
ef2035a60c | ||
|
|
fa29386eb7 | ||
|
|
7e0665a5cd | ||
|
|
233962104c | ||
|
|
a70d5ee9d8 | ||
|
|
a542d41ac7 | ||
|
|
9513c68544 | ||
|
|
448afb8345 | ||
|
|
22ecbcb046 | ||
|
|
7963ca6171 | ||
|
|
6a355616c7 | ||
|
|
ec23189407 | ||
|
|
479b0856b4 | ||
|
|
7289f36600 | ||
|
|
ef1f0cb074 | ||
|
|
1e8d089c4e | ||
|
|
06dab4fa13 | ||
|
|
12efedec42 | ||
|
|
e530ceb566 | ||
|
|
da346159f7 | ||
|
|
c650e7d273 | ||
|
|
f3213a5b2f | ||
|
|
1dc0cc0d05 | ||
|
|
f28f5e07b7 | ||
|
|
62c306a14b | ||
|
|
5a2c58197b | ||
|
|
cc101f9cd2 | ||
|
|
016e1005df | ||
|
|
6e1aa52723 | ||
|
|
5ff265c196 | ||
|
|
1f08401070 | ||
|
|
d1d6bfe693 | ||
|
|
a39280e9df | ||
|
|
48fa9f2242 | ||
|
|
7f59cb54ef | ||
|
|
36a66df923 | ||
|
|
8efc15f4d9 | ||
|
|
884e3f2e35 | ||
|
|
0e0811eccd | ||
|
|
fd1b68513a | ||
|
|
2798946176 | ||
|
|
4ee1ae429b | ||
|
|
482361b252 | ||
|
|
cb1cf055b1 | ||
|
|
6c2e60d415 | ||
|
|
ef223b1195 | ||
|
|
ae14ca7870 | ||
|
|
747046d335 | ||
|
|
e02a7d1c68 | ||
|
|
bdb998c763 | ||
|
|
c35d780236 | ||
|
|
39febad630 | ||
|
|
40932ea06c | ||
|
|
f37b88b55e | ||
|
|
743fc2e812 | ||
|
|
30356dcd97 | ||
|
|
5f6d9c3e27 | ||
|
|
4794cdb120 | ||
|
|
a32233bb92 | ||
|
|
fff2e435b5 | ||
|
|
8f84a96b69 | ||
|
|
11c17ec78c | ||
|
|
b4bdf604f5 | ||
|
|
833d7f65bc | ||
|
|
9bebad2dbe | ||
|
|
14019f2afa | ||
|
|
12481b568a | ||
|
|
3072b2a444 | ||
|
|
5c77e29d66 | ||
|
|
118809fbfc | ||
|
|
baf9cf5a59 | ||
|
|
51e4b364b0 | ||
|
|
581686c7b7 | ||
|
|
3a2fa118a2 | ||
|
|
ac5edf867c | ||
|
|
d4e8452c60 | ||
|
|
4128d75ad4 | ||
|
|
ed4527cfa5 | ||
|
|
26112ba001 | ||
|
|
9dd769586f | ||
|
|
6e1616375e | ||
|
|
a7c379961a | ||
|
|
02d9d8b76c | ||
|
|
d1138d51e5 | ||
|
|
31e952c72e | ||
|
|
9d7938f570 | ||
|
|
9456c42fc0 | ||
|
|
40b3dbaa70 | ||
|
|
1129c92974 | ||
|
|
1293c5cdd4 | ||
|
|
bebd2bb9e0 | ||
|
|
f73aa8aa82 | ||
|
|
e6e05dda1e | ||
|
|
c50df710ba | ||
|
|
65104d5d8c | ||
|
|
881f133021 | ||
|
|
10c51d8a05 | ||
|
|
453b3a59b2 | ||
|
|
67fd4b64af | ||
|
|
1d0013918b | ||
|
|
cac640ea97 | ||
|
|
e7569838c7 | ||
|
|
64b2bf5f93 | ||
|
|
d6a008500a | ||
|
|
a9d636c025 | ||
|
|
292027f40f | ||
|
|
3c126212d5 | ||
|
|
9710ac79d3 | ||
|
|
f2801a660b | ||
|
|
4d269501dd | ||
|
|
752192b09a | ||
|
|
f8f9329529 | ||
|
|
c3e53d916d | ||
|
|
c679932248 | ||
|
|
5488c8f579 | ||
|
|
6c488fe816 | ||
|
|
771cb52616 | ||
|
|
10869ea10a | ||
|
|
e4d0e38f37 | ||
|
|
d7badcc9cb | ||
|
|
4fbf666cd9 | ||
|
|
adb094ebc9 | ||
|
|
b709d47832 | ||
|
|
01d42d4728 | ||
|
|
ce480ae626 | ||
|
|
139686d639 | ||
|
|
4fde1ca2a8 | ||
|
|
c72612d826 | ||
|
|
682133501a | ||
|
|
b4c09ace23 | ||
|
|
c39d270f40 | ||
|
|
428a567078 | ||
|
|
0ad1f776ae | ||
|
|
e78c706999 | ||
|
|
c442cd7267 | ||
|
|
9cbabb0468 | ||
|
|
9a7a4d3814 | ||
|
|
fa1cc59841 | ||
|
|
d4dc4dec76 | ||
|
|
be01c18c74 | ||
|
|
e8829b8f52 | ||
|
|
1afd61698b | ||
|
|
3ff9398b92 | ||
|
|
76900555e8 | ||
|
|
1487ca2a30 | ||
|
|
f960164c0e | ||
|
|
11598beb16 | ||
|
|
1f8aa1efc7 | ||
|
|
18aac0ba25 | ||
|
|
2e24d244be | ||
|
|
7db98ca1da | ||
|
|
9f8d86cb25 | ||
|
|
2ff0af55b1 | ||
|
|
51af747508 | ||
|
|
893bbe09d1 | ||
|
|
d21087f639 | ||
|
|
01203eb854 | ||
|
|
2072ebd196 | ||
|
|
202699239f | ||
|
|
906b0233d2 | ||
|
|
d584031d10 | ||
|
|
f324ab7de7 | ||
|
|
54f56438da | ||
|
|
e6c7c80b3f | ||
|
|
c053c7d9ae | ||
|
|
953beb56b1 | ||
|
|
acd044fdea | ||
|
|
de706523f5 | ||
|
|
52cef05c70 | ||
|
|
6490cadd35 | ||
|
|
8e5928276b | ||
|
|
5dcaceccdd | ||
|
|
f1cf2bf413 | ||
|
|
3882841283 | ||
|
|
74e6470439 | ||
|
|
dca711ac24 | ||
|
|
7368cb99dc | ||
|
|
ec848bab52 | ||
|
|
ed13105aec | ||
|
|
c2272ce5a1 | ||
|
|
0664c09f9d | ||
|
|
ba31a7c753 | ||
|
|
1bca8de042 | ||
|
|
6ffdc9875b | ||
|
|
b84cf55659 | ||
|
|
85d722232e | ||
|
|
921d92c649 | ||
|
|
82f1be33aa | ||
|
|
0f3450ad44 | ||
|
|
114df8cb1b | ||
|
|
d3a293a0d8 | ||
|
|
91b4199f9d | ||
|
|
6473cf0b69 | ||
|
|
84e197574b | ||
|
|
5c4c0965af | ||
|
|
7289b295e8 | ||
|
|
7c32ab3023 | ||
|
|
2bc036f9eb | ||
|
|
cc89e85e71 | ||
|
|
da45cb8557 | ||
|
|
2ebfcea94e | ||
|
|
deada41cee | ||
|
|
777bcf691a | ||
|
|
35e1c401e2 | ||
|
|
19c57e8ec6 | ||
|
|
db4a793aa9 | ||
|
|
c6196b2260 | ||
|
|
3eebdcefa4 | ||
|
|
4289cb089b | ||
|
|
2d52803dbd | ||
|
|
c78302a2ee | ||
|
|
923458bc18 | ||
|
|
50fb4ab22a | ||
|
|
f5016763fd | ||
|
|
2a6921292e | ||
|
|
a47570d65a | ||
|
|
db4dc88d6f | ||
|
|
be306cc384 | ||
|
|
a967dd52f3 | ||
|
|
11378325e0 | ||
|
|
4b5bcf52d2 | ||
|
|
5ba418b2cd | ||
|
|
bc753e6903 | ||
|
|
34a543ec74 | ||
|
|
06cd9abd81 | ||
|
|
af30485611 | ||
|
|
cd6bd1e9a3 | ||
|
|
b025eeb13c | ||
|
|
21eb54e58a | ||
|
|
6f1db6fc63 | ||
|
|
a5118787b3 | ||
|
|
39c90dd581 | ||
|
|
33e6f7f6e0 | ||
|
|
97fd189f43 | ||
|
|
1e665d5181 | ||
|
|
b3343303a9 | ||
|
|
f37276d5fc | ||
|
|
905194c604 | ||
|
|
ea6f6c3668 | ||
|
|
51b22630b4 | ||
|
|
5d831ef461 | ||
|
|
4e8672cce4 | ||
|
|
41a769aa06 | ||
|
|
8d57b6164a | ||
|
|
dc3eba9100 | ||
|
|
ff8baa1c85 | ||
|
|
3a10a27851 | ||
|
|
8893529653 | ||
|
|
1ab5bf4355 | ||
|
|
ae791ca7e1 | ||
|
|
35cfe4318a | ||
|
|
b59bd6fee9 | ||
|
|
8b911f14cf | ||
|
|
d36c69396b | ||
|
|
b39aca8d11 | ||
|
|
6c327d960d | ||
|
|
9527874815 | ||
|
|
cd480846e9 | ||
|
|
3d72fbb19e | ||
|
|
9f3a1c1214 | ||
|
|
625254cf90 | ||
|
|
c4c85777d0 | ||
|
|
ca8d2204ba | ||
|
|
a388e78842 | ||
|
|
35cdc81d45 | ||
|
|
910b6b7512 | ||
|
|
371c3e05bf | ||
|
|
f37df4d6bf | ||
|
|
ba9a3cd719 | ||
|
|
9ac0e26d42 | ||
|
|
1ba4f6e222 | ||
|
|
e8e9826adc | ||
|
|
6724f1f7ea | ||
|
|
013021941e | ||
|
|
4e850296b6 | ||
|
|
0c42f79038 | ||
|
|
4fc3782ea3 | ||
|
|
9ac4a0114f | ||
|
|
9188786581 | ||
|
|
f1602ee3f6 | ||
|
|
5537f98dd6 | ||
|
|
4ed12bf21d | ||
|
|
106dab23db | ||
|
|
2f9dcee954 | ||
|
|
68d6ff8c24 | ||
|
|
dc8cc122a6 | ||
|
|
e9d55de3cb | ||
|
|
dacb452d47 | ||
|
|
8ab2e91df6 | ||
|
|
e985ee878f | ||
|
|
b2e2f1dba3 | ||
|
|
b2417f651a | ||
|
|
d02ba45109 | ||
|
|
c6bffd7d7f | ||
|
|
a5b79528b3 | ||
|
|
fabd6b0d6f | ||
|
|
ebe1b40bee | ||
|
|
6217e97c41 | ||
|
|
e470619e3d | ||
|
|
bf34329033 | ||
|
|
8e88b9e819 | ||
|
|
56a2e40681 | ||
|
|
ba28ffb65a | ||
|
|
9651b5a0ec | ||
|
|
2f2ddae12a | ||
|
|
c77b89d85c | ||
|
|
5c2fe4a2c0 | ||
|
|
b8cee51e84 | ||
|
|
fd1ebdf363 | ||
|
|
35b47467c7 | ||
|
|
8f35a42f4f | ||
|
|
35a565cd84 | ||
|
|
ee68e727ed | ||
|
|
962d9ff220 | ||
|
|
8e0a342f06 | ||
|
|
55292f8a84 | ||
|
|
d72a836e07 | ||
|
|
26a3841a93 | ||
|
|
8e519d09b4 | ||
|
|
ae41a7cc06 | ||
|
|
011e640e95 | ||
|
|
e4e1ea971f | ||
|
|
bcdc36c07c | ||
|
|
972a5d5779 | ||
|
|
7c6454f171 | ||
|
|
1d3d44061b | ||
|
|
4d57c99ad1 | ||
|
|
22e23997c1 | ||
|
|
8d29ce939d | ||
|
|
b19c1a52cb | ||
|
|
ba771ae507 | ||
|
|
9014058935 | ||
|
|
33b12126e0 | ||
|
|
9d323a3832 | ||
|
|
2a664e01b0 | ||
|
|
c1569b0f70 |
@@ -13,16 +13,13 @@
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-vscode.cpptools",
|
||||
"platformio.platformio-ide",
|
||||
]
|
||||
"extensions": ["ms-vscode.cpptools", "platformio.platformio-ide"]
|
||||
}
|
||||
},
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [ 4403 ],
|
||||
"forwardPorts": [4403],
|
||||
|
||||
// Run commands to prepare the container for use
|
||||
"postCreateCommand": ".devcontainer/setup.sh",
|
||||
"postCreateCommand": ".devcontainer/setup.sh"
|
||||
}
|
||||
|
||||
14
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -49,10 +49,24 @@ body:
|
||||
- Heltec V3
|
||||
- Heltec Wireless Paper
|
||||
- Heltec Wireless Tracker
|
||||
- Heltec Mesh Node T114
|
||||
- Heltec Vision Master E213
|
||||
- Heltec Vision Master E290
|
||||
- Heltec Vision Master T190
|
||||
- Nano G1
|
||||
- Nano G1 Explorer
|
||||
- Nano G2 Ultra
|
||||
- Raspberry Pi Pico (W)
|
||||
- Relay v1
|
||||
- Relay v2
|
||||
- Seeed Wio Tracker 1110
|
||||
- Seeed Card Tracker T1000-E
|
||||
- Station G1
|
||||
- Station G2
|
||||
- unPhone
|
||||
- CanaryOne
|
||||
- Chatter
|
||||
- Linux Native
|
||||
- DIY
|
||||
- Other
|
||||
validations:
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/feature.yml
vendored
@@ -18,6 +18,7 @@ body:
|
||||
- ESP32
|
||||
- RP2040
|
||||
- Linux Native
|
||||
- Cross-Platform
|
||||
- other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
94
.github/actions/build-variant/action.yml
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
name: Setup Build Variant Composite Action
|
||||
description: Variant build actions for Meshtastic Platform IO steps
|
||||
|
||||
inputs:
|
||||
board:
|
||||
description: The board to build for
|
||||
required: true
|
||||
github_token:
|
||||
description: GitHub token
|
||||
required: true
|
||||
build-script-path:
|
||||
description: Path to the build script
|
||||
required: true
|
||||
remove-debug-flags:
|
||||
description: A space separated list of files to remove debug flags from
|
||||
required: false
|
||||
default: ""
|
||||
ota-firmware-source:
|
||||
description: The OTA firmware file to pull
|
||||
required: false
|
||||
default: ""
|
||||
ota-firmware-target:
|
||||
description: The target path to store the OTA firmware file
|
||||
required: false
|
||||
default: ""
|
||||
artifact-paths:
|
||||
description: A newline separated list of paths to store as artifacts
|
||||
required: false
|
||||
default: ""
|
||||
include-web-ui:
|
||||
description: Include the web UI in the build
|
||||
required: false
|
||||
default: "false"
|
||||
arch:
|
||||
description: Processor arch name
|
||||
required: true
|
||||
default: "esp32"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Pull web ui
|
||||
if: inputs.include-web-ui == 'true'
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: meshtastic/web
|
||||
file: build.tar
|
||||
target: build.tar
|
||||
token: ${{ inputs.github_token }}
|
||||
|
||||
- name: Unpack web ui
|
||||
if: inputs.include-web-ui == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
tar -xf build.tar -C data/static
|
||||
rm build.tar
|
||||
|
||||
- name: Remove debug flags for release
|
||||
shell: bash
|
||||
if: inputs.remove-debug-flags != ''
|
||||
run: |
|
||||
for INI_FILE in ${{ inputs.remove-debug-flags }}; do
|
||||
sed -i '/DDEBUG_HEAP/d' ${INI_FILE}
|
||||
done
|
||||
|
||||
- name: Build ${{ inputs.board }}
|
||||
shell: bash
|
||||
run: ${{ inputs.build-script-path }} ${{ inputs.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
if: inputs.ota-firmware-source != '' && inputs.ota-firmware-target != ''
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: meshtastic/firmware-ota
|
||||
file: ${{ inputs.ota-firmware-source }}
|
||||
target: ${{ inputs.ota-firmware-target }}
|
||||
token: ${{ inputs.github_token }}
|
||||
|
||||
- name: Get release version string
|
||||
shell: bash
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
${{ inputs.artifact-paths }}
|
||||
5
.github/actions/setup-base/action.yml
vendored
@@ -11,6 +11,11 @@ runs:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Uncomment build epoch
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's/#-DBUILD_EPOCH=$UNIX_TIME/-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
26
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: docker
|
||||
directory: devcontainer
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
|
||||
timezone: US/Pacific
|
||||
- package-ecosystem: docker
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
|
||||
timezone: US/Pacific
|
||||
- package-ecosystem: gitsubmodule
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
|
||||
timezone: US/Pacific
|
||||
- package-ecosystem: github-actions
|
||||
directory: /.github/workflows
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "05:00" # trunk-ignore(yamllint/quoted-strings): required by dependabot syntax check
|
||||
timezone: US/Pacific
|
||||
7
.github/pull_request_template.md
vendored
@@ -1,9 +1,9 @@
|
||||
### ❌ (Please delete all these tips and replace them with your text) ❌
|
||||
|
||||
## Thank you for sending in a pull request, here's some tips to get started!
|
||||
|
||||
(Please delete all these tips and replace with your text)
|
||||
|
||||
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
|
||||
to say "hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
|
||||
to say "Hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
|
||||
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
|
||||
- Please do not check in files that don't have real changes
|
||||
- Please do not reformat lines that you didn't have to change the code on
|
||||
@@ -12,3 +12,4 @@
|
||||
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
|
||||
- If your other co-developers have comments on your PR please tweak as needed.
|
||||
- Please also enable "Allow edits by maintainers".
|
||||
- If your PR gets accepted you can request a "Contributor" role in the Meshtastic Discord
|
||||
|
||||
59
.github/workflows/build_esp32.yml
vendored
@@ -12,52 +12,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: meshtastic/web
|
||||
file: build.tar
|
||||
target: build.tar
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unpack web ui
|
||||
run: |
|
||||
tar -xf build.tar -C data/static
|
||||
rm build.tar
|
||||
|
||||
- name: Remove debug flags for release
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
run: |
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
|
||||
|
||||
- name: Build ESP32
|
||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
repo: meshtastic/firmware-ota
|
||||
file: firmware.bin
|
||||
target: release/bleota.bin
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
shell: bash
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
remove-debug-flags: >-
|
||||
./arch/esp32/esp32.ini
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware.bin
|
||||
ota-firmware-target: release/bleota.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
include-web-ui: true
|
||||
arch: esp32
|
||||
|
||||
58
.github/workflows/build_esp32_c3.yml
vendored
@@ -14,50 +14,22 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
- name: Build ESP32-C3
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
repo: 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: Remove debug flags for release
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
run: |
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
|
||||
- name: Build ESP32
|
||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: meshtastic/firmware-ota
|
||||
file: firmware-c3.bin
|
||||
target: release/bleota-c3.bin
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
shell: bash
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
remove-debug-flags: >-
|
||||
./arch/esp32/esp32.ini
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware-c3.bin
|
||||
ota-firmware-target: release/bleota-c3.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
arch: esp32c3
|
||||
|
||||
36
.github/workflows/build_esp32_c6.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Build ESP32-C6
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build-esp32-c6:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build ESP32-C6
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
remove-debug-flags: >-
|
||||
./arch/esp32/esp32.ini
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
./arch/esp32/esp32c6.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware-c3.bin
|
||||
ota-firmware-target: release/bleota-c3.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
arch: esp32c6
|
||||
59
.github/workflows/build_esp32_s3.yml
vendored
@@ -12,50 +12,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
- name: Build ESP32-S3
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
repo: 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: Remove debug flags for release
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
run: |
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
|
||||
- name: Build ESP32
|
||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: meshtastic/firmware-ota
|
||||
file: firmware-s3.bin
|
||||
target: release/bleota-s3.bin
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
shell: bash
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
remove-debug-flags: >-
|
||||
./arch/esp32/esp32.ini
|
||||
./arch/esp32/esp32s2.ini
|
||||
./arch/esp32/esp32s3.ini
|
||||
./arch/esp32/esp32c3.ini
|
||||
build-script-path: bin/build-esp32.sh
|
||||
ota-firmware-source: firmware-s3.bin
|
||||
ota-firmware-target: release/bleota-s3.bin
|
||||
artifact-paths: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
include-web-ui: true
|
||||
arch: esp32s3
|
||||
|
||||
4
.github/workflows/build_native.yml
vendored
@@ -67,7 +67,7 @@ jobs:
|
||||
- name: Docker build and push tagged versions
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
continue-on-error: true # FIXME: Failing docker login auth
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
- name: Docker build and push
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||
continue-on-error: true # FIXME: Failing docker login auth
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
|
||||
21
.github/workflows/build_nrf52.yml
vendored
@@ -12,24 +12,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Build NRF52
|
||||
run: bin/build-nrf52.sh ${{ inputs.board }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
build-script-path: bin/build-nrf52.sh
|
||||
artifact-paths: |
|
||||
release/*.hex
|
||||
release/*.uf2
|
||||
release/*.elf
|
||||
release/*.zip
|
||||
arch: nrf52840
|
||||
|
||||
21
.github/workflows/build_rpi2040.yml
vendored
@@ -12,22 +12,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Build Raspberry Pi 2040
|
||||
run: ./bin/build-rpi2040.sh ${{ inputs.board }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
build-script-path: bin/build-rpi2040.sh
|
||||
artifact-paths: |
|
||||
release/*.uf2
|
||||
release/*.elf
|
||||
arch: rp2040
|
||||
|
||||
24
.github/workflows/build_stm32.yml
vendored
@@ -12,22 +12,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Build STM32
|
||||
run: bin/build-stm32.sh ${{ inputs.board }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: Build STM32WL
|
||||
id: build
|
||||
uses: ./.github/actions/build-variant
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
overwrite: true
|
||||
path: |
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
board: ${{ inputs.board }}
|
||||
build-script-path: bin/build-stm32.sh
|
||||
artifact-paths: |
|
||||
release/*.hex
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
arch: stm32
|
||||
|
||||
35
.github/workflows/generate-userprefs.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Generate UsersPrefs JSON manifest
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- userPrefs.h
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
generate-userprefs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Clang
|
||||
run: sudo apt-get install -y clang
|
||||
|
||||
- name: Install trunk
|
||||
run: curl https://get.trunk.io -fsSL | bash
|
||||
|
||||
- name: Generate userPrefs.jsom
|
||||
run: python3 ./bin/build-userprefs-json.py
|
||||
|
||||
- name: Trunk format json
|
||||
run: trunk format userPrefs.json
|
||||
|
||||
- name: Commit userPrefs.json
|
||||
run: |
|
||||
git config --global user.email "actions@github.com"
|
||||
git config --global user.name "GitHub Actions"
|
||||
git add userPrefs.json
|
||||
git commit -m "Update userPrefs.json"
|
||||
git push
|
||||
230
.github/workflows/main_matrix.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: CI
|
||||
#concurrency:
|
||||
# group: ${{ github.ref }}
|
||||
# cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
concurrency:
|
||||
group: ci-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
# # Triggers the workflow on push but only for the master branch
|
||||
push:
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [esp32, esp32s3, esp32c3, nrf52840, rp2040, stm32, check]
|
||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32, check]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: checkout
|
||||
@@ -32,13 +32,18 @@ jobs:
|
||||
name: Checkout base
|
||||
- id: jsonStep
|
||||
run: |
|
||||
if [[ "${{ github.head_ref }}" == "" ]]; then
|
||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
|
||||
echo "$TARGETS"
|
||||
else
|
||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
|
||||
fi
|
||||
echo "Name: ${{ github.ref_name }} Base: ${{ github.base_ref }} Head: ${{ github.head_ref }} Ref: ${{ github.ref }} Targets: $TARGETS"
|
||||
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
|
||||
outputs:
|
||||
esp32: ${{ steps.jsonStep.outputs.esp32 }}
|
||||
esp32s3: ${{ steps.jsonStep.outputs.esp32s3 }}
|
||||
esp32c3: ${{ steps.jsonStep.outputs.esp32c3 }}
|
||||
esp32c6: ${{ steps.jsonStep.outputs.esp32c6 }}
|
||||
nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
|
||||
rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
|
||||
stm32: ${{ steps.jsonStep.outputs.stm32 }}
|
||||
@@ -51,6 +56,7 @@ jobs:
|
||||
matrix: ${{ fromJson(needs.setup.outputs.check) }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build base
|
||||
@@ -86,6 +92,15 @@ jobs:
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-esp32-c6:
|
||||
needs: setup
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.setup.outputs.esp32c6) }}
|
||||
uses: ./.github/workflows/build_esp32_c6.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-nrf52:
|
||||
needs: setup
|
||||
strategy:
|
||||
@@ -119,11 +134,12 @@ jobs:
|
||||
package-raspbian-armv7l:
|
||||
uses: ./.github/workflows/package_raspbian_armv7l.yml
|
||||
|
||||
package-native:
|
||||
uses: ./.github/workflows/package_amd64.yml
|
||||
# package-native:
|
||||
# uses: ./.github/workflows/package_amd64.yml
|
||||
|
||||
after-checks:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
needs: [check]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -136,18 +152,20 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32]
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
[
|
||||
build-esp32,
|
||||
build-esp32-s3,
|
||||
build-esp32-c3,
|
||||
build-esp32-c6,
|
||||
build-nrf52,
|
||||
build-rpi2040,
|
||||
build-stm32,
|
||||
package-raspbian,
|
||||
package-raspbian-armv7l,
|
||||
package-native,
|
||||
]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -159,6 +177,7 @@ jobs:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./
|
||||
pattern: firmware-${{matrix.arch}}-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
@@ -169,12 +188,12 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Move files up
|
||||
run: mv -b -t ./ ./release/meshtasticd_linux_* ./bin/config-dist.yaml ./bin/device-*.sh ./bin/device-*.bat
|
||||
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
|
||||
overwrite: true
|
||||
path: |
|
||||
./firmware-*.bin
|
||||
@@ -183,16 +202,14 @@ jobs:
|
||||
./firmware-*-ota.zip
|
||||
./device-*.sh
|
||||
./device-*.bat
|
||||
./meshtasticd_linux_*
|
||||
./config-dist.yaml
|
||||
./littlefs-*.bin
|
||||
./bleota*bin
|
||||
./Meshtastic_nRF52_factory_erase*.uf2
|
||||
retention-days: 90
|
||||
retention-days: 30
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
@@ -206,32 +223,34 @@ jobs:
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./output
|
||||
|
||||
- name: Repackage in single elfs zip
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
overwrite: true
|
||||
path: ./*.elf
|
||||
retention-days: 30
|
||||
|
||||
- name: Create request artifacts
|
||||
continue-on-error: true # FIXME: Why are we getting 502, but things still work?
|
||||
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
||||
uses: gavv/pull-request-artifacts@v2.1.0
|
||||
- uses: scruplelesswizard/comment-artifact@main
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
with:
|
||||
commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }}
|
||||
artifacts-repo: meshtastic/artifacts
|
||||
artifacts-branch: device
|
||||
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
|
||||
description: "Download firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip. This artifact will be available for 90 days from creation"
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
release-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
needs: [gather-artifacts, after-checks]
|
||||
outputs:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
needs: [
|
||||
gather-artifacts,
|
||||
package-raspbian,
|
||||
package-raspbian-armv7l,
|
||||
# package-native,
|
||||
]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -245,42 +264,6 @@ jobs:
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output -x *.deb
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
merge-multiple: true
|
||||
path: ./elfs
|
||||
|
||||
- name: Zip Elfs
|
||||
run: zip -j -9 -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
|
||||
@@ -294,25 +277,16 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
- name: Add bins to release
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- name: Download deb files
|
||||
uses: actions/download-artifact@v4
|
||||
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
|
||||
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
- 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
|
||||
# For diagnostics
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lR
|
||||
|
||||
- name: Add raspbian aarch64 .deb
|
||||
uses: actions/upload-release-asset@v1
|
||||
@@ -334,22 +308,94 @@ jobs:
|
||||
asset_name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
|
||||
asset_content_type: application/vnd.debian.binary-package
|
||||
|
||||
- name: Add raspbian amd64 .deb
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||
asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||
asset_content_type: application/vnd.debian.binary-package
|
||||
# - name: Add raspbian amd64 .deb
|
||||
# uses: actions/upload-release-asset@v1
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ github.token }}
|
||||
# with:
|
||||
# upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
# asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||
# asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||
# asset_content_type: application/vnd.debian.binary-package
|
||||
|
||||
- name: Bump version.properties
|
||||
run: >-
|
||||
bin/bump_version.py
|
||||
|
||||
- name: Create version.properties pull request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
title: Bump version.properties
|
||||
add-paths: |
|
||||
version.properties
|
||||
|
||||
release-firmware:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32]
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
needs: [release-artifacts]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
|
||||
merge-multiple: true
|
||||
path: ./output
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lR
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./output
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
merge-multiple: true
|
||||
path: ./elfs
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./elfs
|
||||
|
||||
# For diagnostics
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -lR
|
||||
|
||||
- name: Add bins to release
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
upload_url: ${{needs.release-artifacts.outputs.upload_url}}
|
||||
asset_path: ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
asset_name: firmware-${{matrix.arch}}-${{ 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: ${{needs.release-artifacts.outputs.upload_url}}
|
||||
asset_path: ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
asset_name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
2
.github/workflows/package_amd64.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
uses: ./.github/workflows/build_native.yml
|
||||
|
||||
package-native:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build-native
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
||||
2
.github/workflows/package_raspbian.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
uses: ./.github/workflows/build_raspbian.yml
|
||||
|
||||
package-raspbian:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build-raspbian
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
uses: ./.github/workflows/build_raspbian_armv7l.yml
|
||||
|
||||
package-raspbian_armv7l:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build-raspbian_armv7l
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
||||
2
.github/workflows/sec_sast_semgrep_cron.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
semgrep-full:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: returntocorp/semgrep
|
||||
image: semgrep/semgrep
|
||||
|
||||
steps:
|
||||
# step 1
|
||||
|
||||
4
.github/workflows/sec_sast_semgrep_pull.yml
vendored
@@ -4,9 +4,9 @@ on: pull_request
|
||||
|
||||
jobs:
|
||||
semgrep-diff:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
container:
|
||||
image: returntocorp/semgrep
|
||||
image: semgrep/semgrep
|
||||
|
||||
steps:
|
||||
# step 1
|
||||
|
||||
45
.github/workflows/tests.yml
vendored
@@ -57,35 +57,50 @@ jobs:
|
||||
reporter: java-junit
|
||||
|
||||
hardware-tests:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: test-runner
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# - uses: actions/setup-python@v5
|
||||
# with:
|
||||
# python-version: '3.10'
|
||||
|
||||
# pipx install "setuptools<72"
|
||||
- name: Upgrade python tools
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U --no-build-isolation --no-cache-dir "setuptools<72"
|
||||
pip install -U platformio adafruit-nrfutil --no-build-isolation
|
||||
pip install -U poetry --no-build-isolation
|
||||
pip install -U meshtastic --pre --no-build-isolation
|
||||
pipx install adafruit-nrfutil
|
||||
pipx install poetry
|
||||
pipx install meshtastic --pip-args=--pre
|
||||
|
||||
- name: Install PlatformIO from script
|
||||
shell: bash
|
||||
run: |
|
||||
curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
|
||||
python3 get-platformio.py
|
||||
|
||||
- name: Upgrade platformio
|
||||
shell: bash
|
||||
run: |
|
||||
export PATH=$PATH:$HOME/.local/bin
|
||||
pio upgrade
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Setup devices
|
||||
run: pnpm run setup
|
||||
|
||||
- name: Execute end to end tests on connected hardware
|
||||
run: pnpm run test
|
||||
- name: Install dependencies, setup devices and run
|
||||
shell: bash
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
cd meshtestic/
|
||||
pnpm install
|
||||
pnpm run setup
|
||||
pnpm run test
|
||||
|
||||
11
.github/workflows/update_protobufs.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: "Update protobufs and regenerate classes"
|
||||
name: Update protobufs and regenerate classes
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
@@ -17,17 +17,18 @@ jobs:
|
||||
|
||||
- name: Download nanopb
|
||||
run: |
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.8-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.8-linux-x86.tar.gz
|
||||
mv nanopb-0.4.8-linux-x86 nanopb-0.4.8
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.9-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.9-linux-x86.tar.gz
|
||||
mv nanopb-0.4.9-linux-x86 nanopb-0.4.9
|
||||
|
||||
- name: Re-generate protocol buffers
|
||||
run: |
|
||||
./bin/regen-protos.sh
|
||||
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
title: Update protobufs and classes
|
||||
add-paths: |
|
||||
protobufs
|
||||
src/mesh
|
||||
|
||||
2
.gitignore
vendored
@@ -1,6 +1,4 @@
|
||||
.pio
|
||||
main/configuration.h
|
||||
main/credentials.h
|
||||
|
||||
# ignore vscode IDE settings files
|
||||
.vscode/*
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
version: 0.1
|
||||
cli:
|
||||
version: 1.22.3
|
||||
version: 1.22.6
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v1.6.2
|
||||
ref: v1.6.3
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- trufflehog@3.81.9
|
||||
- trufflehog@3.82.6
|
||||
- yamllint@1.35.1
|
||||
- bandit@1.7.9
|
||||
- checkov@3.2.238
|
||||
- bandit@1.7.10
|
||||
- checkov@3.2.256
|
||||
- terrascan@1.19.1
|
||||
- trivy@0.54.1
|
||||
- trivy@0.55.2
|
||||
#- trufflehog@3.63.2-rc0
|
||||
- taplo@0.9.3
|
||||
- ruff@0.6.2
|
||||
- ruff@0.6.8
|
||||
- isort@5.13.2
|
||||
- markdownlint@0.41.0
|
||||
- markdownlint@0.42.0
|
||||
- oxipng@9.1.2
|
||||
- svgo@3.3.2
|
||||
- actionlint@1.7.1
|
||||
- actionlint@1.7.3
|
||||
- flake8@7.1.1
|
||||
- hadolint@2.12.0
|
||||
- shfmt@3.6.0
|
||||
- shellcheck@0.10.0
|
||||
- black@24.8.0
|
||||
- git-diff-check
|
||||
- gitleaks@8.18.4
|
||||
- gitleaks@8.20.0
|
||||
- clang-format@16.0.3
|
||||
- prettier@3.3.3
|
||||
ignore:
|
||||
|
||||
47
CONTRIBUTING.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Contributing to Meshtastic Firmware
|
||||
|
||||
We're excited that you're interested in contributing to the Meshtastic firmware! This document provides a high-level overview of how you can get involved.
|
||||
|
||||
## Important First Steps
|
||||
|
||||
Before you begin, please:
|
||||
|
||||
1. **Read our documentation**: Our [official documentation](https://meshtastic.org/docs/) is a crucial resource. It contains essential information about the project.
|
||||
|
||||
2. **Check out the firmware build guide**: For specific instructions on setting up your development environment and building the firmware, refer to our [Firmware Build Guide](https://meshtastic.org/docs/development/firmware/build/).
|
||||
|
||||
3. Read our [Code of Conduct](https://meshtastic.org/docs/legal/conduct/)
|
||||
|
||||
4. Join our [Discord community](https://discord.com/invite/ktMAKGBnBs) to connect with developers and other contributors to get help.
|
||||
|
||||
## Getting Help and Discussing Ideas
|
||||
|
||||
We encourage open communication and discussion before diving into code changes:
|
||||
|
||||
1. **Use GitHub Discussions**: For new ideas, questions, or to discuss potential changes, start a conversation in our [GitHub Discussions](https://github.com/meshtastic/firmware/discussions) first. This helps us collaborate and avoid duplicate work.
|
||||
|
||||
2. **Join our Discord**: For real-time chat and quick questions, join our [Discord server](https://discord.com/invite/ktMAKGBnBs). It's a great place to get help and connect with other developers and the community.
|
||||
|
||||
3. **Reporting Issues**: If you've identified a bug, please use our bug report template when creating a new issue in the [issue tracker](https://github.com/meshtastic/firmware/issues). Ensure you've searched existing issues to avoid duplicates.
|
||||
|
||||
## Making Contributions
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Before making any contributions, you must sign our Contributor License Agreement (CLA). You can do this by visiting https://cla-assistant.io/meshtastic/firmware. Be sure to use the GitHub account you will use to submit your contributions when signing.
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a new branch for your feature or bug fix
|
||||
3. Make your changes
|
||||
4. Test your changes thoroughly
|
||||
5. Create a pull request with a clear description, using the provided template, of your changes. Be sure to enable "Allow edits from maintainers".
|
||||
|
||||
## Coding Standards
|
||||
|
||||
To ensure consistent code formatting across the project:
|
||||
|
||||
1. Install the [Trunk](https://marketplace.visualstudio.com/items?itemName=Trunk.io) extension for Visual Studio Code.
|
||||
2. Before submitting your changes, run `trunk fmt` to automatically format your code according to our standards.
|
||||
|
||||
Adhering to these formatting guidelines helps maintain code consistency and makes the review process smoother.
|
||||
|
||||
Thank you for contributing to Meshtastic!
|
||||
12
SECURITY.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Firmware Version | Supported |
|
||||
| ---------------- | ------------------ |
|
||||
| 2.5.x | :white_check_mark: |
|
||||
| <= 2.4.x | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We support the private reporting of potential security vulnerabilities. Please go to the Security tab to file a report with a description of the potential vulnerability and reproduction scripts (preferred) or steps, and our developers will review.
|
||||
@@ -2,10 +2,10 @@
|
||||
[esp32_base]
|
||||
extends = arduino_base
|
||||
custom_esp32_kind = esp32
|
||||
platform = platformio/espressif32@6.7.0
|
||||
platform = platformio/espressif32@6.9.0
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
||||
|
||||
upload_speed = 921600
|
||||
debug_init_break = tbreak setup
|
||||
@@ -46,7 +46,7 @@ lib_deps =
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.2
|
||||
https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
lewisxhe/XPowersLib@^0.2.6
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
|
||||
40
arch/esp32/esp32c6.ini
Normal file
@@ -0,0 +1,40 @@
|
||||
[esp32c6_base]
|
||||
extends = esp32_base
|
||||
platform = https://github.com/Jason2866/platform-espressif32.git#22faa566df8c789000f8136cd8d0aca49617af55
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Wall
|
||||
-Wextra
|
||||
-Isrc/platform/esp32
|
||||
-std=c++11
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DSERIAL_BUFFER_SIZE=4096
|
||||
-DLIBPAX_ARDUINO
|
||||
-DLIBPAX_WIFI
|
||||
-DLIBPAX_BLE
|
||||
-DMESHTASTIC_EXCLUDE_WEBSERVER
|
||||
;-DDEBUG_HEAP
|
||||
; TEMP
|
||||
-DHAS_BLUETOOTH=0
|
||||
-DMESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
lewisxhe/XPowersLib@^0.2.6
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
rweather/Crypto@^0.4.0
|
||||
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter} -<mesh/http>
|
||||
|
||||
monitor_speed = 460800
|
||||
monitor_filters = esp32_c3_exception_decoder
|
||||
|
||||
lib_ignore =
|
||||
NonBlockingRTTTL
|
||||
NimBLE-Arduino
|
||||
libpax
|
||||
|
||||
@@ -16,7 +16,7 @@ build_flags =
|
||||
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
|
||||
|
||||
lib_deps=
|
||||
${arduino_base.lib_deps}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native.git#ad8112adf82ce1f5b917092cf32be07a077801a0
|
||||
platform = https://github.com/meshtastic/platform-native.git#6b3796d697481c8f6e3f4aa5c111bd9979f29e64
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
@@ -9,7 +9,7 @@ build_src_filter =
|
||||
-<nimble/>
|
||||
-<platform/nrf52/>
|
||||
-<platform/stm32wl/>
|
||||
-<platform/rp2040>
|
||||
-<platform/rp2xx0>
|
||||
-<mesh/wifi/>
|
||||
-<mesh/http/>
|
||||
+<mesh/raspihttp/>
|
||||
@@ -24,7 +24,7 @@ lib_deps =
|
||||
${env.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
https://github.com/lovyan03/LovyanGFX.git#5a39989aa2c9492572255b22f033843ec8900233
|
||||
lovyan03/LovyanGFX@^1.1.16
|
||||
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
|
||||
25
arch/rp2xx0/rp2040.ini
Normal file
@@ -0,0 +1,25 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2040_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.0.3
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
build_flags =
|
||||
${arduino_base.build_flags} -Wno-unused-variable -Wcast-align
|
||||
-Isrc/platform/rp2xx0
|
||||
-Isrc/platform/rp2xx0/hardware_rosc/include
|
||||
-Isrc/platform/rp2xx0/pico_sleep/include
|
||||
-D__PLAT_RP2040__
|
||||
# -D _POSIX_THREADS
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
rweather/Crypto
|
||||
@@ -1,14 +1,14 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2040_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#60d6ae81fcc73c34b1493ca9e261695e471bc0c2
|
||||
[rp2350_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9e55f6db5c56b9867c69fe473f388beea4546672
|
||||
extends = arduino_base
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.7.2
|
||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#a6ab6e1f95bc1428d667d55ea7173c0744acc03c ; 4.0.2+
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
build_flags =
|
||||
${arduino_base.build_flags} -Wno-unused-variable
|
||||
-Isrc/platform/rp2040
|
||||
-Isrc/platform/rp2xx0
|
||||
-D__PLAT_RP2040__
|
||||
# -D _POSIX_THREADS
|
||||
build_src_filter =
|
||||
@@ -1,7 +1,7 @@
|
||||
[stm32_base]
|
||||
extends = arduino_base
|
||||
platform = ststm32
|
||||
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32.git#361a7fdb67e2a7104e99b4f42a802469eef8b129
|
||||
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32.git#ea74156acd823b6d14739f389e6cdc648f8ee36e
|
||||
|
||||
build_type = release
|
||||
|
||||
@@ -22,7 +22,7 @@ build_flags =
|
||||
-fdata-sections
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> -<mesh/raspihttp>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>
|
||||
|
||||
board_upload.offset_address = 0x08000000
|
||||
upload_protocol = stlink
|
||||
@@ -33,5 +33,5 @@ lib_deps =
|
||||
https://github.com/caveman99/Crypto.git#f61ae26a53f7a2d0ba5511625b8bf8eff3a35d5e
|
||||
|
||||
lib_ignore =
|
||||
https://github.com/mathertel/OneButton@~2.6.1
|
||||
mathertel/OneButton@~2.6.1
|
||||
Wire
|
||||
48
bin/build-userprefs-json.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import json
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
def get_macros_from_header(header_file):
|
||||
# Run clang to preprocess the header file and capture the output
|
||||
result = subprocess.run(['clang', '-E', '-dM', header_file], capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(f"Clang preprocessing failed: {result.stderr}")
|
||||
|
||||
# Extract macros from the output
|
||||
macros = {}
|
||||
macro_pattern = re.compile(r'#define\s+(\w+)\s+(.*)')
|
||||
for line in result.stdout.splitlines():
|
||||
match = macro_pattern.match(line)
|
||||
if match and 'USERPREFS_' in line and '_USERPREFS_' not in line:
|
||||
macros[match.group(1)] = match.group(2)
|
||||
|
||||
return macros
|
||||
|
||||
def write_macros_to_json(macros, output_file):
|
||||
with open(output_file, 'w') as f:
|
||||
json.dump(macros, f, indent=4)
|
||||
|
||||
def main():
|
||||
header_file = 'userPrefs.h'
|
||||
output_file = 'userPrefs.json'
|
||||
# Uncomment all macros in the header file
|
||||
with open(header_file, 'r') as file:
|
||||
lines = file.readlines()
|
||||
|
||||
uncommented_lines = []
|
||||
for line in lines:
|
||||
stripped_line = line.strip().replace('/*', '').replace('*/', '')
|
||||
if stripped_line.startswith('//') and 'USERPREFS_' in stripped_line:
|
||||
# Replace "//"
|
||||
stripped_line = stripped_line.replace('//', '')
|
||||
uncommented_lines.append(stripped_line + '\n')
|
||||
|
||||
with open(header_file, 'w') as file:
|
||||
for line in uncommented_lines:
|
||||
file.write(line)
|
||||
macros = get_macros_from_header(header_file)
|
||||
write_macros_to_json(macros, output_file)
|
||||
print(f"Macros have been written to {output_file}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -9,6 +9,7 @@ Lora:
|
||||
# IRQ: 16
|
||||
# Busy: 20
|
||||
# Reset: 18
|
||||
# SX126X_ANT_SW: 6
|
||||
|
||||
# Module: sx1262 # Waveshare SX1302 LISTEN ONLY AT THIS TIME!
|
||||
# CS: 7
|
||||
|
||||
@@ -6,6 +6,7 @@ import configparser
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import random
|
||||
|
||||
rootdir = "variants/"
|
||||
|
||||
@@ -39,5 +40,7 @@ for subdir, dirs, files in os.walk(rootdir):
|
||||
"check" in options
|
||||
):
|
||||
outlist.append(section)
|
||||
|
||||
print(json.dumps(outlist))
|
||||
if ("quick" in options) & (len(outlist) > 3):
|
||||
print(json.dumps(random.sample(outlist, 3)))
|
||||
else:
|
||||
print(json.dumps(outlist))
|
||||
|
||||
@@ -1 +1 @@
|
||||
cd protobufs && ..\nanopb-0.4.8\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated" -I=..\protobufs\ ..\protobufs\meshtastic\*.proto
|
||||
cd protobufs && ..\nanopb-0.4.9\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated" -I=..\protobufs\ ..\protobufs\meshtastic\*.proto
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
set -e
|
||||
|
||||
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.8 to be located in the"
|
||||
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.9 to be located in the"
|
||||
echo "firmware root directory if the following step fails, you should download the correct"
|
||||
echo "prebuilt binaries for your computer into nanopb-0.4.8"
|
||||
echo "prebuilt binaries for your computer into nanopb-0.4.9"
|
||||
|
||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||
cd protobufs
|
||||
../nanopb-0.4.8/generator-bin/protoc --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:../src/mesh/generated/" -I=../protobufs meshtastic/*.proto
|
||||
../nanopb-0.4.9/generator-bin/protoc --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:../src/mesh/generated/" -I=../protobufs meshtastic/*.proto
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||
"extra_flags": "-DHELTEC_T114 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x239A", "0x4405"],
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_LORA_RELAY_V1 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4404"]],
|
||||
"usb_product": "LORA_RELAY",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "lora_relay_v1",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay",
|
||||
"vendor": "BigCorvus"
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_LORA_RELAY_V2 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4406"]],
|
||||
"usb_product": "LORA_RELAY",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "lora_relay_v2",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay",
|
||||
"vendor": "BigCorvus"
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52832_s132_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DNRF52832_XXAA -DNRF52",
|
||||
"f_cpu": "64000000L",
|
||||
"mcu": "nrf52832",
|
||||
"variant": "lora_isp4520",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS132",
|
||||
"sd_name": "s132",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B7"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52832_xxAA",
|
||||
"svd_path": "nrf52.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "lora ISP4520",
|
||||
"upload": {
|
||||
"maximum_ram_size": 65536,
|
||||
"maximum_size": 524288,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"]
|
||||
},
|
||||
"url": "",
|
||||
"vendor": "PsiSoft"
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
|
||||
"extra_flags": "-DME25LS01_4Y10TD -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x239A", "0x8029"],
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
|
||||
"extra_flags": "-DMS24SF1 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x239A", "0x8029"],
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
|
||||
"extra_flags": "-DNORDIC_PCA10059 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x239A", "0x8029"],
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s113_v7.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4404"]],
|
||||
"usb_product": "nrf52840dk",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "pca10056-rc-clock",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://meshtastic.org/",
|
||||
"vendor": "Nordic Semi"
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_PPR -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4403"]],
|
||||
"usb_product": "PPR",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "ppr",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Meshtastic PPR (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://meshtastic.org/",
|
||||
"vendor": "Othernet"
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52833_s113_v7.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52833_PPR -DNRF52833_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4406"]],
|
||||
"usb_product": "PPR",
|
||||
"mcu": "nrf52833",
|
||||
"variant": "ppr",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS113",
|
||||
"sd_name": "s113",
|
||||
"sd_version": "7.2.0",
|
||||
"sd_fwid": "0x00b6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52833_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52833.svd",
|
||||
"openocd_target": "nrf52840-mdk-rs"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Meshtastic PPR1 (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://meshtastic.org/",
|
||||
"vendor": "Othernet"
|
||||
}
|
||||
42
boards/seeed-sensecap-indicator.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"partitions": "default_8MB.csv",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=0",
|
||||
"-DARDUINO_USB_MODE=1",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x1A86", "0x7523"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "esp32s3r8"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Seeed Studio SenseCAP Indicator",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"require_upload_port": true,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://www.seeedstudio.com/Indicator-for-Meshtastic.html",
|
||||
"vendor": "Seeed Studio"
|
||||
}
|
||||
41
boards/seeed-xiao-s3.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=0"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x2886", "0x0059"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "seeed-xiao-s3"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "seeed-xiao-s3",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 8388608,
|
||||
"maximum_size": 8388608,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://www.seeedstudio.com/XIAO-ESP32S3-Sense-p-5639.html",
|
||||
"vendor": "Seeed Studio"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 845 B After Width: | Height: | Size: 594 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M9 11.75c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zm6 0c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8 0-.29.02-.58.05-.86 2.36-1.05 4.23-2.98 5.21-5.37C11.07 8.33 14.05 10 17.42 10c.78 0 1.53-.09 2.25-.26.21.71.33 1.47.33 2.26 0 4.41-3.59 8-8 8z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9 11.75a1.25 1.25 0 1 0 0 2.5 1.25 1.25 0 0 0 0-2.5m6 0a1.25 1.25 0 1 0 0 2.5 1.25 1.25 0 0 0 0-2.5M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.41 0-8-3.59-8-8 0-.29.02-.58.05-.86 2.36-1.05 4.23-2.98 5.21-5.37a9.97 9.97 0 0 0 10.41 3.97c.21.71.33 1.47.33 2.26 0 4.41-3.59 8-8 8"/><path fill="none" d="M0 0h24v24H0z"/></svg>
|
||||
|
Before Width: | Height: | Size: 550 B After Width: | Height: | Size: 445 B |
BIN
images/face.png
|
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 225 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M20.94 11A8.994 8.994 0 0 0 13 3.06V1h-2v2.06A8.994 8.994 0 0 0 3.06 11H1v2h2.06A8.994 8.994 0 0 0 11 20.94V23h2v-2.06A8.994 8.994 0 0 0 20.94 13H23v-2zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7"/></svg>
|
||||
|
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 348 B |
BIN
images/pin.png
|
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 203 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7m0 9.5a2.5 2.5 0 0 1 0-5 2.5 2.5 0 0 1 0 5"/><path fill="none" d="M0 0h24v24H0z"/></svg>
|
||||
|
Before Width: | Height: | Size: 292 B After Width: | Height: | Size: 250 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9 11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2M9 11H7V9h2zm4 0h-2V9h2zm4 0h-2V9h2z"/><path fill="none" d="M0 0h24v24H0z"/></svg>
|
||||
|
Before Width: | Height: | Size: 253 B After Width: | Height: | Size: 246 B |
@@ -17,11 +17,9 @@ default_envs = tbeam
|
||||
;default_envs = tlora-v2-1-1_6
|
||||
;default_envs = tlora-v2-1-1_6-tcxo
|
||||
;default_envs = tlora-t3s3-v1
|
||||
;default_envs = lora-relay-v1 # nrf board
|
||||
;default_envs = t-echo
|
||||
;default_envs = canaryone
|
||||
;default_envs = nrf52840dk-geeksville
|
||||
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
||||
;default_envs = native
|
||||
;default_envs = nano-g1
|
||||
;default_envs = pca10059_diy_eink
|
||||
;default_envs = meshtastic-diy-v1
|
||||
@@ -29,6 +27,7 @@ default_envs = tbeam
|
||||
;default_envs = meshtastic-dr-dev
|
||||
;default_envs = m5stack-coreink
|
||||
;default_envs = rak4631
|
||||
;default_envs = rak4631_eth_gw
|
||||
;default_envs = rak2560
|
||||
;default_envs = rak10701
|
||||
;default_envs = wio-e5
|
||||
@@ -60,41 +59,42 @@ build_flags = -Wno-missing-field-initializers
|
||||
-DUSE_THREAD_NAMES
|
||||
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
-DPB_ENABLE_MALLOC=1
|
||||
-DRADIOLIB_EXCLUDE_CC1101
|
||||
-DRADIOLIB_EXCLUDE_NRF24
|
||||
-DRADIOLIB_EXCLUDE_RF69
|
||||
-DRADIOLIB_EXCLUDE_SX1231
|
||||
-DRADIOLIB_EXCLUDE_SX1233
|
||||
-DRADIOLIB_EXCLUDE_SI443X
|
||||
-DRADIOLIB_EXCLUDE_RFM2X
|
||||
-DRADIOLIB_EXCLUDE_AFSK
|
||||
-DRADIOLIB_EXCLUDE_BELL
|
||||
-DRADIOLIB_EXCLUDE_HELLSCHREIBER
|
||||
-DRADIOLIB_EXCLUDE_MORSE
|
||||
-DRADIOLIB_EXCLUDE_RTTY
|
||||
-DRADIOLIB_EXCLUDE_SSTV
|
||||
-DRADIOLIB_EXCLUDE_AX25
|
||||
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE
|
||||
-DRADIOLIB_EXCLUDE_BELL
|
||||
-DRADIOLIB_EXCLUDE_PAGER
|
||||
-DRADIOLIB_EXCLUDE_FSK4
|
||||
-DRADIOLIB_EXCLUDE_APRS
|
||||
-DRADIOLIB_EXCLUDE_LORAWAN
|
||||
-DRADIOLIB_EXCLUDE_CC1101=1
|
||||
-DRADIOLIB_EXCLUDE_NRF24=1
|
||||
-DRADIOLIB_EXCLUDE_RF69=1
|
||||
-DRADIOLIB_EXCLUDE_SX1231=1
|
||||
-DRADIOLIB_EXCLUDE_SX1233=1
|
||||
-DRADIOLIB_EXCLUDE_SI443X=1
|
||||
-DRADIOLIB_EXCLUDE_RFM2X=1
|
||||
-DRADIOLIB_EXCLUDE_AFSK=1
|
||||
-DRADIOLIB_EXCLUDE_BELL=1
|
||||
-DRADIOLIB_EXCLUDE_HELLSCHREIBER=1
|
||||
-DRADIOLIB_EXCLUDE_MORSE=1
|
||||
-DRADIOLIB_EXCLUDE_RTTY=1
|
||||
-DRADIOLIB_EXCLUDE_SSTV=1
|
||||
-DRADIOLIB_EXCLUDE_AX25=1
|
||||
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE=1
|
||||
-DRADIOLIB_EXCLUDE_BELL=1
|
||||
-DRADIOLIB_EXCLUDE_PAGER=1
|
||||
-DRADIOLIB_EXCLUDE_FSK4=1
|
||||
-DRADIOLIB_EXCLUDE_APRS=1
|
||||
-DRADIOLIB_EXCLUDE_LORAWAN=1
|
||||
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
||||
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
|
||||
#-DBUILD_EPOCH=$UNIX_TIME
|
||||
;-D OLED_PL
|
||||
|
||||
monitor_speed = 115200
|
||||
monitor_filters = direct
|
||||
|
||||
lib_deps =
|
||||
; jgromes/RadioLib@~6.6.0
|
||||
https://github.com/jgromes/RadioLib.git#3115fc2d6700a9aee05888791ac930a910f2628f
|
||||
jgromes/RadioLib@~7.0.2
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
|
||||
https://github.com/mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce
|
||||
mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
||||
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
|
||||
nanopb/Nanopb@^0.4.8
|
||||
nanopb/Nanopb@^0.4.9
|
||||
erriez/ErriezCRC32@^1.0.1
|
||||
|
||||
; Used for the code analysis in PIO Home / Inspect
|
||||
@@ -127,7 +127,7 @@ lib_deps =
|
||||
; (not included in native / portduino)
|
||||
[environmental_base]
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@^1.15.0
|
||||
adafruit/Adafruit BusIO@^1.16.1
|
||||
adafruit/Adafruit Unified Sensor@^1.1.11
|
||||
adafruit/Adafruit BMP280 Library@^2.6.8
|
||||
adafruit/Adafruit BMP085 Library@^1.2.4
|
||||
@@ -136,28 +136,31 @@ lib_deps =
|
||||
adafruit/Adafruit MCP9808 Library@^2.0.0
|
||||
adafruit/Adafruit INA260 Library@^1.5.0
|
||||
adafruit/Adafruit INA219@^1.2.0
|
||||
adafruit/Adafruit MAX1704X@^1.0.3
|
||||
adafruit/Adafruit SHTC3 Library@^1.0.0
|
||||
adafruit/Adafruit LPS2X@^2.0.4
|
||||
adafruit/Adafruit SHT31 Library@^2.2.2
|
||||
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
|
||||
adafruit/Adafruit PM25 AQI Sensor@^1.1.1
|
||||
adafruit/Adafruit MPU6050@^2.2.4
|
||||
adafruit/Adafruit LIS3DH@^1.2.4
|
||||
adafruit/Adafruit LIS3DH@^1.3.0
|
||||
adafruit/Adafruit AHTX0@^2.0.5
|
||||
adafruit/Adafruit LSM6DS@^4.7.2
|
||||
adafruit/Adafruit VEML7700 Library@^2.1.6
|
||||
adafruit/Adafruit SHT4x Library@^1.0.4
|
||||
adafruit/Adafruit TSL2591 Library@^1.4.5
|
||||
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@^1.0.5
|
||||
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@^1.2.13
|
||||
ClosedCube OPT3001@^1.1.2
|
||||
emotibit/EmotiBit MLX90632@^1.0.8
|
||||
dfrobot/DFRobot_RTU@^1.0.3
|
||||
|
||||
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@^1.1.2
|
||||
adafruit/Adafruit MLX90614 Library@^2.1.5
|
||||
|
||||
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
|
||||
boschsensortec/BME68x Sensor Library@^1.1.40407
|
||||
https://github.com/KodinLanewave/INA3221@^1.0.0
|
||||
lewisxhe/SensorLib@^0.2.0
|
||||
https://github.com/KodinLanewave/INA3221@^1.0.1
|
||||
lewisxhe/SensorLib@0.2.0
|
||||
mprograms/QMC5883LCompass@^1.2.0
|
||||
|
||||
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
|
||||
https://github.com/gjelsoe/STK8xxx-Accelerometer.git#v0.1.1
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
#pragma once
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#include "PowerFSM.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "main.h"
|
||||
#include "power.h"
|
||||
|
||||
#include <Adafruit_LIS3DH.h>
|
||||
#include <Adafruit_LSM6DS3TRC.h>
|
||||
#include <Adafruit_MPU6050.h>
|
||||
#include <Arduino.h>
|
||||
#include <SensorBMA423.hpp>
|
||||
#include <Wire.h>
|
||||
#ifdef RAK_4631
|
||||
#include "Fusion/Fusion.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "graphics/ScreenFonts.h"
|
||||
#include <Rak_BMX160.h>
|
||||
#endif
|
||||
|
||||
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
|
||||
#define ACCELEROMETER_CLICK_THRESHOLD 40
|
||||
|
||||
static inline int readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((uint8_t)address, (uint8_t)len);
|
||||
uint8_t i = 0;
|
||||
while (Wire.available()) {
|
||||
data[i++] = Wire.read();
|
||||
}
|
||||
return 0; // Pass
|
||||
}
|
||||
|
||||
static inline int writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
|
||||
{
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(reg);
|
||||
Wire.write(data, len);
|
||||
return (0 != Wire.endTransmission());
|
||||
}
|
||||
|
||||
class AccelerometerThread : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
explicit AccelerometerThread(ScanI2C::DeviceType type) : OSThread("AccelerometerThread")
|
||||
{
|
||||
if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) {
|
||||
LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n");
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
acceleremoter_type = type;
|
||||
#ifndef RAK_4631
|
||||
if (!config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
|
||||
LOG_DEBUG("AccelerometerThread disabling due to no interested configurations\n");
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
init();
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
init();
|
||||
setIntervalFromNow(0);
|
||||
};
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override
|
||||
{
|
||||
canSleep = true; // Assume we should not keep the board awake
|
||||
|
||||
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) {
|
||||
wakeScreen();
|
||||
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.getClick() > 0) {
|
||||
uint8_t click = lis.getClick();
|
||||
if (!config.device.double_tap_as_button_press) {
|
||||
wakeScreen();
|
||||
}
|
||||
|
||||
if (config.device.double_tap_as_button_press && (click & 0x20)) {
|
||||
buttonPress();
|
||||
return 500;
|
||||
}
|
||||
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.readIrqStatus() != DEV_WIRE_NONE) {
|
||||
if (bmaSensor.isTilt() || bmaSensor.isDoubleTap()) {
|
||||
wakeScreen();
|
||||
return 500;
|
||||
}
|
||||
#ifdef RAK_4631
|
||||
} else if (acceleremoter_type == ScanI2C::DeviceType::BMX160) {
|
||||
sBmx160SensorData_t magAccel;
|
||||
sBmx160SensorData_t gAccel;
|
||||
|
||||
/* Get a new sensor event */
|
||||
bmx160.getAllData(&magAccel, NULL, &gAccel);
|
||||
|
||||
// expirimental calibrate routine. Limited to between 10 and 30 seconds after boot
|
||||
if (millis() > 12 * 1000 && millis() < 30 * 1000) {
|
||||
if (!showingScreen) {
|
||||
showingScreen = true;
|
||||
screen->startAlert((FrameCallback)drawFrameCalibration);
|
||||
}
|
||||
if (magAccel.x > highestX)
|
||||
highestX = magAccel.x;
|
||||
if (magAccel.x < lowestX)
|
||||
lowestX = magAccel.x;
|
||||
if (magAccel.y > highestY)
|
||||
highestY = magAccel.y;
|
||||
if (magAccel.y < lowestY)
|
||||
lowestY = magAccel.y;
|
||||
if (magAccel.z > highestZ)
|
||||
highestZ = magAccel.z;
|
||||
if (magAccel.z < lowestZ)
|
||||
lowestZ = magAccel.z;
|
||||
} else if (showingScreen && millis() >= 30 * 1000) {
|
||||
showingScreen = false;
|
||||
screen->endAlert();
|
||||
}
|
||||
|
||||
int highestRealX = highestX - (highestX + lowestX) / 2;
|
||||
|
||||
magAccel.x -= (highestX + lowestX) / 2;
|
||||
magAccel.y -= (highestY + lowestY) / 2;
|
||||
magAccel.z -= (highestZ + lowestZ) / 2;
|
||||
FusionVector ga, ma;
|
||||
ga.axis.x = -gAccel.x; // default location for the BMX160 is on the rear of the board
|
||||
ga.axis.y = -gAccel.y;
|
||||
ga.axis.z = gAccel.z;
|
||||
ma.axis.x = -magAccel.x;
|
||||
ma.axis.y = -magAccel.y;
|
||||
ma.axis.z = magAccel.z * 3;
|
||||
|
||||
// If we're set to one of the inverted positions
|
||||
if (config.display.compass_orientation > meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270) {
|
||||
ma = FusionAxesSwap(ma, FusionAxesAlignmentNXNYPZ);
|
||||
ga = FusionAxesSwap(ga, FusionAxesAlignmentNXNYPZ);
|
||||
}
|
||||
|
||||
float heading = FusionCompassCalculateHeading(FusionConventionNed, ga, ma);
|
||||
|
||||
switch (config.display.compass_orientation) {
|
||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
|
||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
|
||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
|
||||
heading += 90;
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
|
||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
|
||||
heading += 180;
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
|
||||
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
|
||||
heading += 270;
|
||||
break;
|
||||
}
|
||||
|
||||
screen->setHeading(heading);
|
||||
|
||||
#endif
|
||||
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.shake()) {
|
||||
wakeScreen();
|
||||
return 500;
|
||||
}
|
||||
|
||||
return ACCELEROMETER_CHECK_INTERVAL_MS;
|
||||
}
|
||||
|
||||
private:
|
||||
void init()
|
||||
{
|
||||
LOG_DEBUG("AccelerometerThread initializing\n");
|
||||
|
||||
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
|
||||
LOG_DEBUG("MPU6050 initializing\n");
|
||||
// setup motion detection
|
||||
mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
|
||||
mpu.setMotionDetectionThreshold(1);
|
||||
mpu.setMotionDetectionDuration(20);
|
||||
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
|
||||
mpu.setInterruptPinPolarity(true);
|
||||
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
|
||||
LOG_DEBUG("LIS3DH initializing\n");
|
||||
lis.setRange(LIS3DH_RANGE_2_G);
|
||||
// Adjust threshold, higher numbers are less sensitive
|
||||
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
|
||||
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 &&
|
||||
bmaSensor.begin(accelerometer_found.address, &readRegister, &writeRegister)) {
|
||||
LOG_DEBUG("BMA423 initializing\n");
|
||||
bmaSensor.configAccelerometer(bmaSensor.RANGE_2G, bmaSensor.ODR_100HZ, bmaSensor.BW_NORMAL_AVG4,
|
||||
bmaSensor.PERF_CONTINUOUS_MODE);
|
||||
bmaSensor.enableAccelerometer();
|
||||
bmaSensor.configInterrupt(BMA4_LEVEL_TRIGGER, BMA4_ACTIVE_HIGH, BMA4_PUSH_PULL, BMA4_OUTPUT_ENABLE,
|
||||
BMA4_INPUT_DISABLE);
|
||||
|
||||
#ifdef BMA423_INT
|
||||
pinMode(BMA4XX_INT, INPUT);
|
||||
attachInterrupt(
|
||||
BMA4XX_INT,
|
||||
[] {
|
||||
// Set interrupt to set irq value to true
|
||||
BMA_IRQ = true;
|
||||
},
|
||||
RISING); // Select the interrupt mode according to the actual circuit
|
||||
#endif
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
// Need to raise the wrist function, need to set the correct axis
|
||||
bmaSensor.setReampAxes(bmaSensor.REMAP_TOP_LAYER_RIGHT_CORNER);
|
||||
#else
|
||||
bmaSensor.setReampAxes(bmaSensor.REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER);
|
||||
#endif
|
||||
// bmaSensor.enableFeature(bmaSensor.FEATURE_STEP_CNTR, true);
|
||||
bmaSensor.enableFeature(bmaSensor.FEATURE_TILT, true);
|
||||
bmaSensor.enableFeature(bmaSensor.FEATURE_WAKEUP, true);
|
||||
// bmaSensor.resetPedometer();
|
||||
|
||||
// Turn on feature interrupt
|
||||
bmaSensor.enablePedometerIRQ();
|
||||
bmaSensor.enableTiltIRQ();
|
||||
// It corresponds to isDoubleClick interrupt
|
||||
bmaSensor.enableWakeupIRQ();
|
||||
#ifdef RAK_4631
|
||||
} else if (acceleremoter_type == ScanI2C::DeviceType::BMX160 && bmx160.begin()) {
|
||||
bmx160.ODR_Config(BMX160_ACCEL_ODR_100HZ, BMX160_GYRO_ODR_100HZ); // set output data rate
|
||||
|
||||
#endif
|
||||
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.begin_I2C(accelerometer_found.address)) {
|
||||
LOG_DEBUG("LSM6DS3 initializing\n");
|
||||
// Default threshold of 2G, less sensitive options are 4, 8 or 16G
|
||||
lsm.setAccelRange(LSM6DS_ACCEL_RANGE_2_G);
|
||||
#ifndef LSM6DS3_WAKE_THRESH
|
||||
#define LSM6DS3_WAKE_THRESH 20
|
||||
#endif
|
||||
lsm.enableWakeup(config.display.wake_on_tap_or_motion, 1, LSM6DS3_WAKE_THRESH);
|
||||
// Duration is number of occurances needed to trigger, higher threshold is less sensitive
|
||||
}
|
||||
}
|
||||
void wakeScreen()
|
||||
{
|
||||
if (powerFSM.getState() == &stateDARK) {
|
||||
LOG_INFO("Tap or motion detected. Turning on screen\n");
|
||||
powerFSM.trigger(EVENT_INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
void buttonPress()
|
||||
{
|
||||
LOG_DEBUG("Double-tap detected. Firing button press\n");
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
}
|
||||
|
||||
ScanI2C::DeviceType acceleremoter_type;
|
||||
Adafruit_MPU6050 mpu;
|
||||
Adafruit_LIS3DH lis;
|
||||
Adafruit_LSM6DS3TRC lsm;
|
||||
SensorBMA423 bmaSensor;
|
||||
bool BMA_IRQ = false;
|
||||
#ifdef RAK_4631
|
||||
bool showingScreen = false;
|
||||
RAK_BMX160 bmx160;
|
||||
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
||||
|
||||
static void drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
int x_offset = display->width() / 2;
|
||||
int y_offset = display->height() <= 80 ? 0 : 32;
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(x, y, "Calibrating\nCompass");
|
||||
int16_t compassX = 0, compassY = 0;
|
||||
uint16_t compassDiam = graphics::Screen::getCompassDiam(display->getWidth(), display->getHeight());
|
||||
|
||||
// coordinates for the center of the compass/circle
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
compassX = x + display->getWidth() - compassDiam / 2 - 5;
|
||||
compassY = y + display->getHeight() / 2;
|
||||
} else {
|
||||
compassX = x + display->getWidth() - compassDiam / 2 - 5;
|
||||
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
|
||||
}
|
||||
display->drawCircle(compassX, compassY, compassDiam / 2);
|
||||
screen->drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -124,6 +124,11 @@ int32_t ButtonThread::runOnce()
|
||||
switch (btnEvent) {
|
||||
case BUTTON_EVENT_PRESSED: {
|
||||
LOG_BUTTON("press!\n");
|
||||
// If a nag notification is running, stop it and prevent other actions
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
externalNotificationModule->stopNow();
|
||||
return 50;
|
||||
}
|
||||
#ifdef BUTTON_PIN
|
||||
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
|
||||
moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||
|
||||
@@ -97,12 +97,14 @@ Syslog &Syslog::logMask(uint8_t priMask)
|
||||
|
||||
void Syslog::enable()
|
||||
{
|
||||
this->_client->begin(this->_port);
|
||||
this->_enabled = true;
|
||||
}
|
||||
|
||||
void Syslog::disable()
|
||||
{
|
||||
this->_enabled = false;
|
||||
this->_client->stop();
|
||||
}
|
||||
|
||||
bool Syslog::isEnabled()
|
||||
|
||||
@@ -370,8 +370,8 @@ void setupSDCard()
|
||||
}
|
||||
|
||||
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
|
||||
LOG_DEBUG("SD Card Size: %lluMB\n", cardSize);
|
||||
LOG_DEBUG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024));
|
||||
LOG_DEBUG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024));
|
||||
LOG_DEBUG("SD Card Size: %lu MB\n", (uint32_t)cardSize);
|
||||
LOG_DEBUG("Total space: %lu MB\n", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
|
||||
LOG_DEBUG("Used space: %lu MB\n", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
|
||||
#endif
|
||||
}
|
||||
107
src/Power.cpp
@@ -13,6 +13,7 @@
|
||||
#include "power.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "Throttle.h"
|
||||
#include "buzz/buzz.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
@@ -30,6 +31,7 @@
|
||||
#if HAS_WIFI
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef DELAY_FOREVER
|
||||
@@ -75,6 +77,15 @@ INA219Sensor ina219Sensor;
|
||||
INA3221Sensor ina3221Sensor;
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include "modules/Telemetry/Sensor/MAX17048Sensor.h"
|
||||
#include <utility>
|
||||
extern std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
|
||||
#if HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY)
|
||||
MAX17048Sensor max17048Sensor;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAS_RAKPROT && !defined(ARCH_PORTDUINO)
|
||||
RAK9154Sensor rak9154Sensor;
|
||||
#endif
|
||||
@@ -136,6 +147,8 @@ using namespace meshtastic;
|
||||
*/
|
||||
static HasBatteryLevel *batteryLevel; // Default to NULL for no battery level sensor
|
||||
|
||||
#ifdef BATTERY_PIN
|
||||
|
||||
static void adcEnable()
|
||||
{
|
||||
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
|
||||
@@ -160,11 +173,14 @@ static void adcDisable()
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input
|
||||
*/
|
||||
class AnalogBatteryLevel : public HasBatteryLevel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Battery state of charge, from 0 to 100 or -1 for unknown
|
||||
*/
|
||||
@@ -244,7 +260,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
config.power.adc_multiplier_override > 0 ? config.power.adc_multiplier_override : ADC_MULTIPLIER;
|
||||
// Do not call analogRead() often.
|
||||
const uint32_t min_read_interval = 5000;
|
||||
if (millis() - last_read_time_ms > min_read_interval) {
|
||||
if (!Throttle::isWithinTimespanMs(last_read_time_ms, min_read_interval)) {
|
||||
last_read_time_ms = millis();
|
||||
|
||||
uint32_t raw = 0;
|
||||
@@ -551,7 +567,12 @@ bool Power::analogInit()
|
||||
*/
|
||||
bool Power::setup()
|
||||
{
|
||||
bool found = axpChipInit() || analogInit();
|
||||
// initialise one power sensor (only)
|
||||
bool found = axpChipInit();
|
||||
if (!found)
|
||||
found = lipoInit();
|
||||
if (!found)
|
||||
found = analogInit();
|
||||
|
||||
#ifdef NRF_APM
|
||||
found = true;
|
||||
@@ -567,7 +588,7 @@ void Power::shutdown()
|
||||
{
|
||||
LOG_INFO("Shutting down\n");
|
||||
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_ESP32)
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_ESP32) || defined(ARCH_RP2040)
|
||||
#ifdef PIN_LED1
|
||||
ledOff(PIN_LED1);
|
||||
#endif
|
||||
@@ -950,7 +971,6 @@ bool Power::axpChipInit()
|
||||
PMU->enableVbusVoltageMeasure();
|
||||
PMU->enableBattVoltageMeasure();
|
||||
|
||||
LOG_DEBUG("=======================================================================\n");
|
||||
if (PMU->isChannelAvailable(XPOWERS_DCDC1)) {
|
||||
LOG_DEBUG("DC1 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-",
|
||||
PMU->getPowerChannelVoltage(XPOWERS_DCDC1));
|
||||
@@ -999,7 +1019,6 @@ bool Power::axpChipInit()
|
||||
LOG_DEBUG("BLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-",
|
||||
PMU->getPowerChannelVoltage(XPOWERS_BLDO2));
|
||||
}
|
||||
LOG_DEBUG("=======================================================================\n");
|
||||
|
||||
// We can safely ignore this approach for most (or all) boards because MCU turned off
|
||||
// earlier than battery discharged to 2.6V.
|
||||
@@ -1043,3 +1062,81 @@ bool Power::axpChipInit()
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
|
||||
/**
|
||||
* Wrapper class for an I2C MAX17048 Lipo battery sensor.
|
||||
*/
|
||||
class LipoBatteryLevel : public HasBatteryLevel
|
||||
{
|
||||
private:
|
||||
MAX17048Singleton *max17048 = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Init the I2C MAX17048 Lipo battery level sensor
|
||||
*/
|
||||
bool runOnce()
|
||||
{
|
||||
if (max17048 == nullptr) {
|
||||
max17048 = MAX17048Singleton::GetInstance();
|
||||
}
|
||||
|
||||
// try to start if the sensor has been detected
|
||||
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX17048].first != 0) {
|
||||
return max17048->runOnce(nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX17048].second);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Battery state of charge, from 0 to 100 or -1 for unknown
|
||||
*/
|
||||
virtual int getBatteryPercent() override { return max17048->getBusBatteryPercent(); }
|
||||
|
||||
/**
|
||||
* The raw voltage of the battery in millivolts, or NAN if unknown
|
||||
*/
|
||||
virtual uint16_t getBattVoltage() override { return max17048->getBusVoltageMv(); }
|
||||
|
||||
/**
|
||||
* return true if there is a battery installed in this unit
|
||||
*/
|
||||
virtual bool isBatteryConnect() override { return max17048->isBatteryConnected(); }
|
||||
|
||||
/**
|
||||
* return true if there is an external power source detected
|
||||
*/
|
||||
virtual bool isVbusIn() override { return max17048->isExternallyPowered(); }
|
||||
|
||||
/**
|
||||
* return true if the battery is currently charging
|
||||
*/
|
||||
virtual bool isCharging() override { return max17048->isBatteryCharging(); }
|
||||
};
|
||||
|
||||
LipoBatteryLevel lipoLevel;
|
||||
|
||||
/**
|
||||
* Init the Lipo battery level sensor
|
||||
*/
|
||||
bool Power::lipoInit()
|
||||
{
|
||||
bool result = lipoLevel.runOnce();
|
||||
LOG_DEBUG("Power::lipoInit lipo sensor is %s\n", result ? "ready" : "not ready yet");
|
||||
if (!result)
|
||||
return false;
|
||||
batteryLevel = &lipoLevel;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
/**
|
||||
* The Lipo battery level sensor is unavailable - default to AnalogBatteryLevel
|
||||
*/
|
||||
bool Power::lipoInit()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -24,7 +24,7 @@
|
||||
class SafeFile : public Print
|
||||
{
|
||||
public:
|
||||
SafeFile(char const *filepath, bool fullAtomic = false);
|
||||
explicit SafeFile(char const *filepath, bool fullAtomic = false);
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "SerialConsole.h"
|
||||
#include "Default.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "Throttle.h"
|
||||
#include "configuration.h"
|
||||
#include "time.h"
|
||||
|
||||
@@ -44,10 +46,11 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con
|
||||
Port.setRX(SERIAL2_RX);
|
||||
#endif
|
||||
Port.begin(SERIAL_BAUD);
|
||||
#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040)
|
||||
#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040) || \
|
||||
defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||
time_t timeout = millis();
|
||||
while (!Port) {
|
||||
if ((millis() - timeout) < 5000) {
|
||||
if (Throttle::isWithinTimespanMs(timeout, FIVE_SECONDS_MS)) {
|
||||
delay(100);
|
||||
} else {
|
||||
break;
|
||||
@@ -72,8 +75,7 @@ void SerialConsole::flush()
|
||||
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
|
||||
bool SerialConsole::checkIsConnected()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
return (now - lastContactMsec) < SERIAL_CONNECTION_TIMEOUT;
|
||||
return Throttle::isWithinTimespanMs(lastContactMsec, SERIAL_CONNECTION_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,17 +13,17 @@ void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
|
||||
{
|
||||
|
||||
if (reportType == TX_LOG) {
|
||||
LOG_DEBUG("AirTime - Packet transmitted : %ums\n", airtime_ms);
|
||||
LOG_DEBUG("Packet transmitted : %ums\n", airtime_ms);
|
||||
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
|
||||
air_period_tx[0] = air_period_tx[0] + airtime_ms;
|
||||
|
||||
this->utilizationTX[this->getPeriodUtilHour()] = this->utilizationTX[this->getPeriodUtilHour()] + airtime_ms;
|
||||
} else if (reportType == RX_LOG) {
|
||||
LOG_DEBUG("AirTime - Packet received : %ums\n", airtime_ms);
|
||||
LOG_DEBUG("Packet received : %ums\n", airtime_ms);
|
||||
this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms;
|
||||
air_period_rx[0] = air_period_rx[0] + airtime_ms;
|
||||
} else if (reportType == RX_ALL_LOG) {
|
||||
LOG_DEBUG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
|
||||
LOG_DEBUG("Packet received (noise?) : %ums\n", airtime_ms);
|
||||
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef RTC_DATA_ATTR
|
||||
#define RTC_DATA_ATTR
|
||||
#endif
|
||||
#ifndef EXT_RAM_BSS_ATTR
|
||||
#define EXT_RAM_BSS_ATTR EXT_RAM_ATTR
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Regulatory overrides
|
||||
@@ -122,9 +125,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define INA_ADDR_ALTERNATE 0x41
|
||||
#define INA_ADDR_WAVESHARE_UPS 0x43
|
||||
#define INA3221_ADDR 0x42
|
||||
#define MAX1704X_ADDR 0x36
|
||||
#define QMC6310_ADDR 0x1C
|
||||
#define QMI8658_ADDR 0x6B
|
||||
#define QMC5883L_ADDR 0x1E
|
||||
#define QMC5883L_ADDR 0x0D
|
||||
#define HMC5883L_ADDR 0x1E
|
||||
#define SHTC3_ADDR 0x70
|
||||
#define LPS22HB_ADDR 0x5C
|
||||
#define LPS22HB_ADDR_ALT 0x5D
|
||||
@@ -139,15 +144,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MLX90632_ADDR 0x3A
|
||||
#define DFROBOT_LARK_ADDR 0x42
|
||||
#define NAU7802_ADDR 0x2A
|
||||
#define MAX30102_ADDR 0x57
|
||||
#define MLX90614_ADDR_DEF 0x5A
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ACCELEROMETER
|
||||
// -----------------------------------------------------------------------------
|
||||
#define MPU6050_ADDR 0x68
|
||||
#define STK8BXX_ADR 0x18
|
||||
#define LIS3DH_ADR 0x18
|
||||
#define BMA423_ADDR 0x19
|
||||
#define LSM6DS3_ADDR 0x6A
|
||||
#define BMX160_ADDR 0x69
|
||||
#define ICM20948_ADDR 0x69
|
||||
#define ICM20948_ADDR_ALT 0x68
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// LED
|
||||
@@ -162,6 +172,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// -----------------------------------------------------------------------------
|
||||
// IO Expander
|
||||
// -----------------------------------------------------------------------------
|
||||
#define TCA9535_ADDR 0x20
|
||||
#define TCA9555_ADDR 0x26
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -171,6 +182,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define GPS_THREAD_INTERVAL 200
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Touchscreen
|
||||
// -----------------------------------------------------------------------------
|
||||
#define FT6336U_ADDR 0x48
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// BIAS-T Generator
|
||||
// -----------------------------------------------------------------------------
|
||||
#define TPS65233_ADDR 0x60
|
||||
|
||||
// convert 24-bit color to 16-bit (56K)
|
||||
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
|
||||
|
||||
@@ -202,6 +223,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define MINIMUM_SAFE_FREE_HEAP 1500
|
||||
#endif
|
||||
|
||||
#ifndef WIRE_INTERFACES_COUNT
|
||||
// Officially an NRF52 macro
|
||||
// Repurposed cross-platform to identify devices using Wire1
|
||||
#if defined(I2C_SDA1) || defined(PIN_WIRE1_SDA)
|
||||
#define WIRE_INTERFACES_COUNT 2
|
||||
#elif HAS_WIRE
|
||||
#define WIRE_INTERFACES_COUNT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Step #3: mop up with disabled values for HAS_ options not handled by the above two */
|
||||
|
||||
#ifndef HAS_WIFI
|
||||
|
||||
@@ -10,7 +10,8 @@ enum LoRaRadioType {
|
||||
LLCC68_RADIO,
|
||||
SX1280_RADIO,
|
||||
LR1110_RADIO,
|
||||
LR1120_RADIO
|
||||
LR1120_RADIO,
|
||||
LR1121_RADIO
|
||||
};
|
||||
|
||||
extern LoRaRadioType radioType;
|
||||
@@ -37,8 +37,8 @@ ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160};
|
||||
return firstOfOrNONE(5, types);
|
||||
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX, ICM20948};
|
||||
return firstOfOrNONE(7, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
|
||||
|
||||
@@ -28,6 +28,7 @@ class ScanI2C
|
||||
INA260,
|
||||
INA219,
|
||||
INA3221,
|
||||
MAX17048,
|
||||
MCP9808,
|
||||
SHT31,
|
||||
SHT4X,
|
||||
@@ -36,12 +37,14 @@ class ScanI2C
|
||||
QMC6310,
|
||||
QMI8658,
|
||||
QMC5883L,
|
||||
HMC5883L,
|
||||
PMSA0031,
|
||||
MPU6050,
|
||||
LIS3DH,
|
||||
BMA423,
|
||||
BQ24295,
|
||||
LSM6DS3,
|
||||
TCA9535,
|
||||
TCA9555,
|
||||
VEML7700,
|
||||
RCWL9620,
|
||||
@@ -49,10 +52,16 @@ class ScanI2C
|
||||
TSL2591,
|
||||
OPT3001,
|
||||
MLX90632,
|
||||
MLX90614,
|
||||
AHT10,
|
||||
BMX160,
|
||||
DFROBOT_LARK,
|
||||
NAU7802
|
||||
NAU7802,
|
||||
FT6336U,
|
||||
STK8BAXX,
|
||||
ICM20948,
|
||||
MAX30102,
|
||||
TPS65233
|
||||
} DeviceType;
|
||||
|
||||
// typedef uint8_t DeviceAddress;
|
||||
@@ -63,8 +72,9 @@ class ScanI2C
|
||||
} I2CPort;
|
||||
|
||||
typedef struct DeviceAddress {
|
||||
I2CPort port;
|
||||
uint8_t address;
|
||||
// set default values for ADDRESS_NONE
|
||||
I2CPort port = I2CPort::NO_I2C;
|
||||
uint8_t address = 0;
|
||||
|
||||
explicit DeviceAddress(I2CPort port, uint8_t address);
|
||||
DeviceAddress();
|
||||
|
||||
@@ -162,13 +162,13 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
Melopero_RV3028 rtc;
|
||||
#endif
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
if (port == I2CPort::WIRE1) {
|
||||
i2cBus = &Wire1;
|
||||
} else {
|
||||
#endif
|
||||
i2cBus = &Wire;
|
||||
#ifdef I2C_SDA1
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -313,17 +313,33 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
}
|
||||
break;
|
||||
case MCP9808_ADDR:
|
||||
// We need to check for STK8BAXX first, since register 0x07 is new data flag for the z-axis and can produce some
|
||||
// weird result. and register 0x00 doesn't seems to be colliding with MCP9808 and LIS3DH chips.
|
||||
{
|
||||
// Check register 0x00 for 0x8700 response to ID STK8BA53 chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 2);
|
||||
if (registerValue == 0x8700) {
|
||||
type = STK8BAXX;
|
||||
LOG_INFO("STK8BAXX accelerometer found\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Check register 0x07 for 0x0400 response to ID MCP9808 chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||
if (registerValue == 0x0400) {
|
||||
type = MCP9808;
|
||||
LOG_INFO("MCP9808 sensor found\n");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check register 0x0F for 0x3300 response to ID LIS3DH chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2);
|
||||
if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333
|
||||
type = LIS3DH;
|
||||
LOG_INFO("LIS3DH accelerometer found\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
case SHT31_4x_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2);
|
||||
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0xe9c) {
|
||||
@@ -340,7 +356,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found\n")
|
||||
SCAN_SIMPLE_CASE(RCWL9620_ADDR, RCWL9620, "RCWL9620 sensor found\n")
|
||||
case RCWL9620_ADDR:
|
||||
// get MAX30102 PARTID
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFF), 1);
|
||||
if (registerValue == 0x15) {
|
||||
type = MAX30102;
|
||||
LOG_INFO("MAX30102 Health sensor found\n");
|
||||
break;
|
||||
} else {
|
||||
type = RCWL9620;
|
||||
LOG_INFO("RCWL9620 sensor found\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case LPS22HB_ADDR_ALT:
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found\n")
|
||||
@@ -365,18 +392,41 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n")
|
||||
|
||||
SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found\n")
|
||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
|
||||
SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n");
|
||||
SCAN_SIMPLE_CASE(BMX160_ADDR, BMX160, "BMX160 accelerometer found\n");
|
||||
SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found\n");
|
||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address);
|
||||
SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found\n");
|
||||
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found\n");
|
||||
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found\n");
|
||||
SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591 light sensor found\n");
|
||||
SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001 light sensor found\n");
|
||||
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632 IR temp sensor found\n");
|
||||
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802 based scale found\n");
|
||||
SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U touchscreen found\n");
|
||||
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048 lipo fuel gauge found\n");
|
||||
#ifdef HAS_TPS65233
|
||||
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233 BIAS-T found\n");
|
||||
#endif
|
||||
SCAN_SIMPLE_CASE(MLX90614_ADDR_DEF, MLX90614, "MLX90614 IR temp sensor found\n");
|
||||
|
||||
case ICM20948_ADDR: // same as BMX160_ADDR
|
||||
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
||||
if (registerValue == 0xEA) {
|
||||
type = ICM20948;
|
||||
LOG_INFO("ICM20948 9-dof motion processor found\n");
|
||||
break;
|
||||
} else if (addr.address == BMX160_ADDR) {
|
||||
type = BMX160;
|
||||
LOG_INFO("BMX160 accelerometer found\n");
|
||||
break;
|
||||
} else {
|
||||
type = MPU6050;
|
||||
LOG_INFO("MPU6050 accelerometer found\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
|
||||
@@ -403,7 +453,7 @@ TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const
|
||||
if (address.port == ScanI2C::I2CPort::WIRE) {
|
||||
return &Wire;
|
||||
} else {
|
||||
#ifdef I2C_SDA1
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
return &Wire1;
|
||||
#else
|
||||
return &Wire;
|
||||
|
||||
545
src/gps/GPS.cpp
@@ -6,6 +6,8 @@
|
||||
#include "NodeDB.h"
|
||||
#include "PowerMon.h"
|
||||
#include "RTC.h"
|
||||
#include "Throttle.h"
|
||||
#include "meshUtils.h"
|
||||
|
||||
#include "main.h" // pmu_found
|
||||
#include "sleep.h"
|
||||
@@ -26,6 +28,8 @@
|
||||
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
|
||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
#elif defined(ARCH_RP2040)
|
||||
SerialUART *GPS::_serial_gps = &Serial1;
|
||||
#else
|
||||
HardwareSerial *GPS::_serial_gps = NULL;
|
||||
#endif
|
||||
@@ -59,6 +63,7 @@ const char *getGPSPowerStateString(GPSPowerState state)
|
||||
return "OFF";
|
||||
default:
|
||||
assert(false); // Unhandled enum value..
|
||||
return "FALSE"; // to make new ESP-IDF happy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,9 +91,9 @@ void GPS::CASChecksum(uint8_t *message, size_t length)
|
||||
|
||||
// Iterate over the payload as a series of uint32_t's and
|
||||
// accumulate the cksum
|
||||
uint32_t const *payload = (uint32_t *)(message + 6);
|
||||
for (size_t i = 0; i < (length - 10) / 4; i++) {
|
||||
uint32_t pl = payload[i];
|
||||
uint32_t pl = 0;
|
||||
memcpy(&pl, (message + 6) + (i * sizeof(uint32_t)), sizeof(uint32_t)); // avoid pointer dereference
|
||||
cksum += pl;
|
||||
}
|
||||
|
||||
@@ -166,18 +171,21 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
|
||||
b = _serial_gps->read();
|
||||
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("%02X", (char *)buffer);
|
||||
LOG_DEBUG("%c", (b >= 32 && b <= 126) ? b : '.');
|
||||
#endif
|
||||
buffer[bytesRead] = b;
|
||||
bytesRead++;
|
||||
if ((bytesRead == 767) || (b == '\r')) {
|
||||
if (strnstr((char *)buffer, message, bytesRead) != nullptr) {
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("\r");
|
||||
LOG_DEBUG("\r\nFound: %s\r\n", message); // Log the found message
|
||||
#endif
|
||||
return GNSS_RESPONSE_OK;
|
||||
} else {
|
||||
bytesRead = 0;
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("\r\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,7 +209,7 @@ GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMilli
|
||||
// ACK-NACK| 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x00 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
|
||||
// ACK-ACK | 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x01 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX |
|
||||
|
||||
while (millis() - startTime < waitMillis) {
|
||||
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
|
||||
if (_serial_gps->available()) {
|
||||
buffer[bufferPos++] = _serial_gps->read();
|
||||
|
||||
@@ -270,7 +278,7 @@ GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
|
||||
buf[9] += buf[8];
|
||||
}
|
||||
|
||||
while (millis() - startTime < waitMillis) {
|
||||
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
|
||||
if (ack > 9) {
|
||||
#ifdef GPS_DEBUG
|
||||
LOG_DEBUG("\n");
|
||||
@@ -325,9 +333,9 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
||||
{
|
||||
uint16_t ubxFrameCounter = 0;
|
||||
uint32_t startTime = millis();
|
||||
uint16_t needRead;
|
||||
uint16_t needRead = 0;
|
||||
|
||||
while (millis() - startTime < waitMillis) {
|
||||
while (Throttle::isWithinTimespanMs(startTime, waitMillis)) {
|
||||
if (_serial_gps->available()) {
|
||||
int c = _serial_gps->read();
|
||||
switch (ubxFrameCounter) {
|
||||
@@ -398,9 +406,9 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
|
||||
|
||||
bool GPS::setup()
|
||||
{
|
||||
int msglen = 0;
|
||||
|
||||
if (!didSerialInit) {
|
||||
int msglen = 0;
|
||||
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
|
||||
|
||||
// if GPS_BAUDRATE is specified in variant (i.e. not 9600), skip to the specified rate.
|
||||
@@ -488,10 +496,10 @@ bool GPS::setup()
|
||||
}
|
||||
} else if (gnssModel == GNSS_MODEL_UC6580) {
|
||||
// The Unicore UC6580 can use a lot of sat systems, enable it to
|
||||
// use GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS
|
||||
// use GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS + QZSS
|
||||
// This will reset the receiver, so wait a bit afterwards
|
||||
// The paranoid will wait for the OK*04 confirmation response after each command.
|
||||
_serial_gps->write("$CFGSYS,h25155\r\n");
|
||||
_serial_gps->write("$CFGSYS,h35155\r\n");
|
||||
delay(750);
|
||||
// Must be done after the CFGSYS command
|
||||
// Turn off GSV messages, we don't really care about which and where the sats are, maybe someday.
|
||||
@@ -505,284 +513,158 @@ bool GPS::setup()
|
||||
delay(250);
|
||||
_serial_gps->write("$CFGMSG,6,1,0\r\n");
|
||||
delay(250);
|
||||
} else if (gnssModel == GNSS_MODEL_AG3335) {
|
||||
} else if (IS_ONE_OF(gnssModel, GNSS_MODEL_AG3335, GNSS_MODEL_AG3352)) {
|
||||
|
||||
_serial_gps->write("$PAIR066,1,0,1,0,0,1*3B"); // Enable GPS+GALILEO+NAVIC
|
||||
_serial_gps->write("$PAIR066,1,0,1,0,0,1*3B\r\n"); // Enable GPS+GALILEO+NAVIC
|
||||
|
||||
// Configure NMEA (sentences will output once per fix)
|
||||
_serial_gps->write("$PAIR062,0,0*3F"); // GGA ON
|
||||
_serial_gps->write("$PAIR062,1,0*3F"); // GLL OFF
|
||||
_serial_gps->write("$PAIR062,2,1*3D"); // GSA ON
|
||||
_serial_gps->write("$PAIR062,3,0*3D"); // GSV OFF
|
||||
_serial_gps->write("$PAIR062,4,0*3B"); // RMC ON
|
||||
_serial_gps->write("$PAIR062,5,0*3B"); // VTG OFF
|
||||
_serial_gps->write("$PAIR062,6,1*39"); // ZDA ON
|
||||
_serial_gps->write("$PAIR062,0,1*3F\r\n"); // GGA ON
|
||||
_serial_gps->write("$PAIR062,1,0*3F\r\n"); // GLL OFF
|
||||
_serial_gps->write("$PAIR062,2,0*3C\r\n"); // GSA OFF
|
||||
_serial_gps->write("$PAIR062,3,0*3D\r\n"); // GSV OFF
|
||||
_serial_gps->write("$PAIR062,4,1*3B\r\n"); // RMC ON
|
||||
_serial_gps->write("$PAIR062,5,0*3B\r\n"); // VTG OFF
|
||||
_serial_gps->write("$PAIR062,6,0*38\r\n"); // ZDA ON
|
||||
|
||||
delay(250);
|
||||
_serial_gps->write("$PAIR513*3D"); // save configuration
|
||||
_serial_gps->write("$PAIR513*3D\r\n"); // save configuration
|
||||
} else if (gnssModel == GNSS_MODEL_UBLOX6) {
|
||||
clearBuffer();
|
||||
SEND_UBX_PACKET(0x06, 0x02, _message_DISABLE_TXT_INFO, "disable text info messages", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_6_7, "enable interference resistance", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5, "configure NAVX5 settings", 500);
|
||||
|
||||
} else if (gnssModel == GNSS_MODEL_UBLOX) {
|
||||
// Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command)
|
||||
// We need set it because by default it is GPS only, and we want to use GLONASS too
|
||||
// Also we need SBAS for better accuracy and extra features
|
||||
// ToDo: Dynamic configure GNSS systems depending of LoRa region
|
||||
// Turn off unwanted NMEA messages, set update rate
|
||||
SEND_UBX_PACKET(0x06, 0x08, _message_1HZ, "set GPS update rate", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GLL, "disable NMEA GLL", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GSA, "enable NMEA GSA", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GSV, "disable NMEA GSV", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_VTG, "disable NMEA VTG", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "enable NMEA RMC", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "enable NMEA GGA", 500);
|
||||
|
||||
if (strncmp(info.hwVersion, "000A0000", 8) != 0) {
|
||||
if (strncmp(info.hwVersion, "00040007", 8) != 0) {
|
||||
// The original ublox Neo-6 is GPS only and doesn't support the UBX-CFG-GNSS message
|
||||
// Max7 seems to only support GPS *or* GLONASS
|
||||
// Neo-7 is supposed to support GPS *and* GLONASS but NAKs the CFG-GNSS command to do it
|
||||
// So treat all the u-blox 7 series as GPS only
|
||||
// M8 can support 3 constallations at once so turn on GPS, GLONASS and Galileo (or BeiDou)
|
||||
clearBuffer();
|
||||
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_ECO, "enable powersaving ECO mode for Neo-6", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_AID, "disable UBX-AID", 500);
|
||||
|
||||
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
|
||||
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to save GNSS module configuration.\n");
|
||||
} else {
|
||||
LOG_INFO("GNSS module configuration saved!\n");
|
||||
}
|
||||
} else if (IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9)) {
|
||||
if (gnssModel == GNSS_MODEL_UBLOX7) {
|
||||
LOG_DEBUG("Setting GPS+SBAS\n");
|
||||
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
} else {
|
||||
} else { // 8,9
|
||||
msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_8), _message_GNSS_8);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
}
|
||||
|
||||
if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
|
||||
// It's not critical if the module doesn't acknowledge this configuration.
|
||||
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
|
||||
LOG_INFO("reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
|
||||
} else {
|
||||
if (strncmp(info.hwVersion, "00070000", 8) == 0) {
|
||||
LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n");
|
||||
} else {
|
||||
LOG_INFO(
|
||||
"GNSS configured for GPS+SBAS+GLONASS+Galileo. Pause for 0.75s before sending next command.\n");
|
||||
if (gnssModel == GNSS_MODEL_UBLOX7) {
|
||||
LOG_INFO("GNSS configured for GPS+SBAS.\n");
|
||||
} else { // 8,9
|
||||
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS+Galileo.\n");
|
||||
}
|
||||
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
|
||||
// commands for the M8 it tends to be more... 1 sec should be enough ;>)
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
// Disable Text Info messages
|
||||
msglen = makeUBXPacket(0x06, 0x02, sizeof(_message_DISABLE_TXT_INFO), _message_DISABLE_TXT_INFO);
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x02, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable text info messages.\n");
|
||||
}
|
||||
// ToDo add M10 tests for below
|
||||
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
|
||||
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_8), _message_JAM_8);
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x39, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable interference resistance.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5_8), _message_NAVX5_8);
|
||||
// Disable Text Info messages //6,7,8,9
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to configure NAVX5_8 settings.\n");
|
||||
}
|
||||
} else {
|
||||
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_6_7), _message_JAM_6_7);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x39, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable interference resistance.\n");
|
||||
}
|
||||
SEND_UBX_PACKET(0x06, 0x02, _message_DISABLE_TXT_INFO, "disable text info messages", 500);
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to configure NAVX5 settings.\n");
|
||||
}
|
||||
if (gnssModel == GNSS_MODEL_UBLOX8) { // 8
|
||||
clearBuffer();
|
||||
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_8, "enable interference resistance", 500);
|
||||
|
||||
clearBuffer();
|
||||
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5_8, "configure NAVX5_8 settings", 500);
|
||||
} else { // 6,7,9
|
||||
SEND_UBX_PACKET(0x06, 0x39, _message_JAM_6_7, "enable interference resistance", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x23, _message_NAVX5, "configure NAVX5 settings", 500);
|
||||
}
|
||||
// Turn off unwanted NMEA messages, set update rate
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x08, sizeof(_message_1HZ), _message_1HZ);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x08, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to set GPS update rate.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GLL), _message_GLL);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA GLL.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to Enable NMEA GSA.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA GSV.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA VTG.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable NMEA RMC.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable NMEA GGA.\n");
|
||||
}
|
||||
SEND_UBX_PACKET(0x06, 0x08, _message_1HZ, "set GPS update rate", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GLL, "disable NMEA GLL", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GSA, "enable NMEA GSA", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GSV, "disable NMEA GSV", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_VTG, "disable NMEA VTG", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "enable NMEA RMC", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "enable NMEA GGA", 500);
|
||||
|
||||
if (uBloxProtocolVersion >= 18) {
|
||||
msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS);
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x86, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving for GPS.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving details for GPS.\n");
|
||||
}
|
||||
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "enable powersaving for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
|
||||
|
||||
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
|
||||
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
|
||||
msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA);
|
||||
if (gnssModel == GNSS_MODEL_UBLOX8) {
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x17, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable NMEA 4.10.\n");
|
||||
}
|
||||
SEND_UBX_PACKET(0x06, 0x17, _message_NMEA, "enable NMEA 4.10", 500);
|
||||
}
|
||||
} else {
|
||||
if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode is only for Neo-6
|
||||
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving ECO mode for Neo-6.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving details for GPS.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_AID), _message_AID);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable UBX-AID.\n");
|
||||
}
|
||||
} else {
|
||||
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving mode for GPS.\n");
|
||||
SEND_UBX_PACKET(0x06, 0x11, _message_CFG_RXM_PSM, "enable powersaving mode for GPS", 500);
|
||||
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersaving details for GPS", 500);
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
|
||||
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving details for GPS.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to save GNSS module configuration.\n");
|
||||
} else {
|
||||
// LOG_INFO("u-blox M10 hardware found.\n");
|
||||
LOG_INFO("GNSS module configuration saved!\n");
|
||||
}
|
||||
} else if (gnssModel == GNSS_MODEL_UBLOX10) {
|
||||
delay(1000);
|
||||
// First disable all NMEA messages in RAM layer
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_NMEA_RAM), _message_VALSET_DISABLE_NMEA_RAM);
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA messages for M10 GPS RAM.\n");
|
||||
}
|
||||
delay(250);
|
||||
// Next disable unwanted NMEA messages in BBR layer
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_NMEA_BBR), _message_VALSET_DISABLE_NMEA_BBR);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_NMEA_RAM, "disable NMEA messages in M10 RAM", 300);
|
||||
delay(750);
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable NMEA messages for M10 GPS BBR.\n");
|
||||
}
|
||||
delay(250);
|
||||
// Disable Info txt messages in RAM layer
|
||||
msglen =
|
||||
makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_TXT_INFO_RAM), _message_VALSET_DISABLE_TXT_INFO_RAM);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_NMEA_BBR, "disable NMEA messages in M10 BBR", 300);
|
||||
delay(750);
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable Info messages for M10 GPS RAM.\n");
|
||||
}
|
||||
delay(250);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_TXT_INFO_RAM, "disable Info messages for M10 GPS RAM", 300);
|
||||
delay(750);
|
||||
// Next disable Info txt messages in BBR layer
|
||||
msglen =
|
||||
makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_TXT_INFO_BBR), _message_VALSET_DISABLE_TXT_INFO_BBR);
|
||||
clearBuffer();
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable Info messages for M10 GPS BBR.\n");
|
||||
}
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_TXT_INFO_BBR, "disable Info messages for M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
// Do M10 configuration for Power Management.
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_PM_RAM), _message_VALSET_PM_RAM);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving for M10 GPS RAM.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_PM_BBR), _message_VALSET_PM_BBR);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving for M10 GPS BBR.\n");
|
||||
}
|
||||
|
||||
delay(250);
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ITFM_RAM), _message_VALSET_ITFM_RAM);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable Jamming detection M10 GPS RAM.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ITFM_BBR), _message_VALSET_ITFM_BBR);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable Jamming detection M10 GPS BBR.\n");
|
||||
}
|
||||
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_RAM, "enable powersaving for M10 GPS RAM", 300);
|
||||
delay(750);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_PM_BBR, "enable powersaving for M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_RAM, "enable Jamming detection M10 GPS RAM", 300);
|
||||
delay(750);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ITFM_BBR, "enable Jamming detection M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
// Here is where the init commands should go to do further M10 initialization.
|
||||
delay(250);
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_SBAS_RAM), _message_VALSET_DISABLE_SBAS_RAM);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable SBAS M10 GPS RAM.\n");
|
||||
}
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_RAM, "disable SBAS M10 GPS RAM", 300);
|
||||
delay(750); // will cause a receiver restart so wait a bit
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_SBAS_BBR), _message_VALSET_DISABLE_SBAS_BBR);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to disable SBAS M10 GPS BBR.\n");
|
||||
}
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_DISABLE_SBAS_BBR, "disable SBAS M10 GPS BBR", 300);
|
||||
delay(750); // will cause a receiver restart so wait a bit
|
||||
|
||||
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic sleep.
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ENABLE_NMEA_BBR), _message_VALSET_ENABLE_NMEA_BBR);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable messages for M10 GPS BBR.\n");
|
||||
}
|
||||
delay(250);
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ENABLE_NMEA_BBR, "enable messages for M10 GPS BBR", 300);
|
||||
delay(750);
|
||||
// Next enable wanted NMEA messages in RAM layer
|
||||
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ENABLE_NMEA_RAM), _message_VALSET_ENABLE_NMEA_RAM);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable messages for M10 GPS RAM.\n");
|
||||
}
|
||||
SEND_UBX_PACKET(0x06, 0x8A, _message_VALSET_ENABLE_NMEA_RAM, "enable messages for M10 GPS RAM", 500);
|
||||
delay(750);
|
||||
|
||||
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
|
||||
// BBR will survive a restart, and power off for a while, but modules with small backup
|
||||
// batteries or super caps will not retain the config for a long power off time.
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
|
||||
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE_10), _message_SAVE_10);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x09, 2000) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to save GNSS module configuration.\n");
|
||||
@@ -944,7 +826,7 @@ void GPS::setPowerPMU(bool on)
|
||||
void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
|
||||
{
|
||||
// Abort: if not UBLOX hardware
|
||||
if (gnssModel != GNSS_MODEL_UBLOX)
|
||||
if (!IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9, GNSS_MODEL_UBLOX10))
|
||||
return;
|
||||
|
||||
// If waking
|
||||
@@ -967,7 +849,7 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs)
|
||||
}
|
||||
|
||||
// Determine hardware version
|
||||
if (strncmp(info.hwVersion, "000A0000", 8) != 0) {
|
||||
if (gnssModel != GNSS_MODEL_UBLOX10) {
|
||||
// Encode the sleep time in millis into the packet
|
||||
for (int i = 0; i < 4; i++)
|
||||
gps->_message_PMREQ[0 + i] = sleepMs >> (i * 8);
|
||||
@@ -1019,19 +901,21 @@ void GPS::down()
|
||||
LOG_DEBUG("%us until next search\n", sleepTime / 1000);
|
||||
|
||||
// If update interval less than 10 seconds, no attempt to sleep
|
||||
if (updateInterval <= 10 * 1000UL)
|
||||
if (updateInterval <= 10 * 1000UL || sleepTime == 0)
|
||||
setPowerState(GPS_IDLE);
|
||||
|
||||
else {
|
||||
// Check whether the GPS hardware is capable of GPS_SOFTSLEEP
|
||||
// If not, fallback to GPS_HARDSLEEP instead
|
||||
bool softsleepSupported = false;
|
||||
if (gnssModel == GNSS_MODEL_UBLOX) // U-blox is supported via PMREQ
|
||||
// U-blox is supported via PMREQ
|
||||
if (IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9, GNSS_MODEL_UBLOX10))
|
||||
softsleepSupported = true;
|
||||
#ifdef PIN_GPS_STANDBY // L76B, L76K and clones have a standby pin
|
||||
softsleepSupported = true;
|
||||
#endif
|
||||
|
||||
if (softsleepSupported) {
|
||||
// How long does gps_update_interval need to be, for GPS_HARDSLEEP to become more efficient than GPS_SOFTSLEEP?
|
||||
// Heuristic equation. A compromise manually fitted to power observations from U-blox NEO-6M and M10050
|
||||
// https://www.desmos.com/calculator/6gvjghoumr
|
||||
@@ -1040,11 +924,12 @@ void GPS::down()
|
||||
LOG_DEBUG("gps_update_interval >= %us needed to justify hardsleep\n", hardsleepThreshold / 1000);
|
||||
|
||||
// If update interval too short: softsleep (if supported by hardware)
|
||||
if (softsleepSupported && updateInterval < hardsleepThreshold)
|
||||
if (updateInterval < hardsleepThreshold) {
|
||||
setPowerState(GPS_SOFTSLEEP, sleepTime);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If update interval long enough (or softsleep unsupported): hardsleep instead
|
||||
else
|
||||
setPowerState(GPS_HARDSLEEP, sleepTime);
|
||||
}
|
||||
}
|
||||
@@ -1101,7 +986,9 @@ int32_t GPS::runOnce()
|
||||
// if we have received valid NMEA claim we are connected
|
||||
setConnected();
|
||||
} else {
|
||||
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) && (gnssModel == GNSS_MODEL_UBLOX)) {
|
||||
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) &&
|
||||
IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9,
|
||||
GNSS_MODEL_UBLOX10)) {
|
||||
// reset the GPS on next bootup
|
||||
if (devicestate.did_gps_reset && scheduling.elapsedSearchMs() > 60 * 1000UL && !hasFlow()) {
|
||||
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
|
||||
@@ -1184,25 +1071,34 @@ int GPS::prepareDeepSleep(void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *PROBE_MESSAGE = "Trying %s (%s)...\n";
|
||||
const char *DETECTED_MESSAGE = "%s detected, using %s Module\n";
|
||||
|
||||
#define PROBE_SIMPLE(CHIP, TOWRITE, RESPONSE, DRIVER, TIMEOUT, ...) \
|
||||
LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \
|
||||
clearBuffer(); \
|
||||
_serial_gps->write(TOWRITE "\r\n"); \
|
||||
if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \
|
||||
LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \
|
||||
return DRIVER; \
|
||||
}
|
||||
|
||||
GnssModel_t GPS::probe(int serialSpeed)
|
||||
{
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_STM32WL)
|
||||
_serial_gps->end();
|
||||
_serial_gps->begin(serialSpeed);
|
||||
#elif defined(ARCH_RP2040)
|
||||
_serial_gps->end();
|
||||
_serial_gps->setFIFOSize(256);
|
||||
_serial_gps->begin(serialSpeed);
|
||||
#else
|
||||
if (_serial_gps->baudRate() != serialSpeed) {
|
||||
LOG_DEBUG("Setting Baud to %i\n", serialSpeed);
|
||||
_serial_gps->updateBaudRate(serialSpeed);
|
||||
}
|
||||
#endif
|
||||
#ifdef GNSS_AIROHA
|
||||
return GNSS_MODEL_AG3335;
|
||||
#endif
|
||||
#ifdef GPS_DEBUG
|
||||
for (int i = 0; i < 20; i++) {
|
||||
getACK("$GP", 200);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
|
||||
uint8_t buffer[768] = {0};
|
||||
delay(100);
|
||||
@@ -1210,68 +1106,35 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
// Close all NMEA sentences, valid for L76K, ATGM336H (and likely other AT6558 devices)
|
||||
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
|
||||
delay(20);
|
||||
// Close NMEA sequences on Ublox
|
||||
_serial_gps->write("$PUBX,40,GLL,0,0,0,0,0,0*5C\r\n");
|
||||
_serial_gps->write("$PUBX,40,GSV,0,0,0,0,0,0*59\r\n");
|
||||
_serial_gps->write("$PUBX,40,VTG,0,0,0,0,0,0*5E\r\n");
|
||||
delay(20);
|
||||
|
||||
// get version information from Unicore UFirebirdII Series
|
||||
// Works for: UC6580, UM620, UM621, UM670A, UM680A, or UM681A
|
||||
_serial_gps->write("$PDTINFO\r\n");
|
||||
delay(750);
|
||||
if (getACK("UC6580", 500) == GNSS_RESPONSE_OK) {
|
||||
LOG_INFO("UC6580 detected, using UC6580 Module\n");
|
||||
return GNSS_MODEL_UC6580;
|
||||
}
|
||||
|
||||
clearBuffer();
|
||||
_serial_gps->write("$PDTINFO\r\n");
|
||||
delay(750);
|
||||
if (getACK("UM600", 500) == GNSS_RESPONSE_OK) {
|
||||
LOG_INFO("UM600 detected, using UC6580 Module\n");
|
||||
return GNSS_MODEL_UC6580;
|
||||
}
|
||||
|
||||
// Get version information for ATGM336H
|
||||
clearBuffer();
|
||||
_serial_gps->write("$PCAS06,1*1A\r\n");
|
||||
if (getACK("$GPTXT,01,01,02,HW=ATGM336H", 500) == GNSS_RESPONSE_OK) {
|
||||
LOG_INFO("ATGM336H GNSS init succeeded, using ATGM336H Module\n");
|
||||
return GNSS_MODEL_ATGM336H;
|
||||
}
|
||||
|
||||
// Unicore UFirebirdII Series: UC6580, UM620, UM621, UM670A, UM680A, or UM681A
|
||||
PROBE_SIMPLE("UC6580", "$PDTINFO", "UC6580", GNSS_MODEL_UC6580, 500);
|
||||
PROBE_SIMPLE("UM600", "$PDTINFO", "UM600", GNSS_MODEL_UC6580, 500);
|
||||
PROBE_SIMPLE("ATGM336H", "$PCAS06,1*1A", "$GPTXT,01,01,02,HW=ATGM336H", GNSS_MODEL_ATGM336H, 500);
|
||||
/* ATGM332D series (-11(GPS), -21(BDS), -31(GPS+BDS), -51(GPS+GLONASS), -71-0(GPS+BDS+GLONASS))
|
||||
based on AT6558 */
|
||||
clearBuffer();
|
||||
_serial_gps->write("$PCAS06,1*1A\r\n");
|
||||
if (getACK("$GPTXT,01,01,02,HW=ATGM332D", 500) == GNSS_RESPONSE_OK) {
|
||||
LOG_INFO("ATGM332D detected, using ATGM336H Module\n");
|
||||
return GNSS_MODEL_ATGM336H;
|
||||
}
|
||||
PROBE_SIMPLE("ATGM332D", "$PCAS06,1*1A", "$GPTXT,01,01,02,HW=ATGM332D", GNSS_MODEL_ATGM336H, 500);
|
||||
|
||||
/* Airoha (Mediatek) AG3335A/M/S, A3352Q, Quectel L89 2.0, SimCom SIM65M */
|
||||
clearBuffer();
|
||||
_serial_gps->write("PAIR020*38\r\n");
|
||||
if (getACK("$PAIR020,AG3335", 500) == GNSS_RESPONSE_OK) {
|
||||
LOG_INFO("Aioha AG3335 detected, using AG3335 Module\n");
|
||||
return GNSS_MODEL_AG3335;
|
||||
}
|
||||
_serial_gps->write("$PAIR062,2,0*3C\r\n"); // GSA OFF to reduce volume
|
||||
_serial_gps->write("$PAIR062,3,0*3D\r\n"); // GSV OFF to reduce volume
|
||||
_serial_gps->write("$PAIR513*3D\r\n"); // save configuration
|
||||
PROBE_SIMPLE("AG3335", "$PAIR021*39", "$PAIR021,AG3335", GNSS_MODEL_AG3335, 500);
|
||||
PROBE_SIMPLE("AG3352", "$PAIR021*39", "$PAIR021,AG3352", GNSS_MODEL_AG3352, 500);
|
||||
PROBE_SIMPLE("LC86", "$PQTMVERNO*58", "$PQTMVERNO,LC86", GNSS_MODEL_AG3352, 500);
|
||||
|
||||
// Get version information
|
||||
clearBuffer();
|
||||
_serial_gps->write("$PCAS06,0*1B\r\n");
|
||||
if (getACK("$GPTXT,01,01,02,SW=", 500) == GNSS_RESPONSE_OK) {
|
||||
LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n");
|
||||
return GNSS_MODEL_MTK;
|
||||
}
|
||||
PROBE_SIMPLE("L76K", "$PCAS06,0*1B", "$GPTXT,01,01,02,SW=", GNSS_MODEL_MTK, 500);
|
||||
|
||||
// Close all NMEA sentences, valid for L76B MTK platform (Waveshare Pico GPS)
|
||||
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
|
||||
delay(20);
|
||||
|
||||
// Get version information
|
||||
clearBuffer();
|
||||
_serial_gps->write("$PMTK605*31\r\n");
|
||||
if (getACK("Quectel-L76B", 500) == GNSS_RESPONSE_OK) {
|
||||
LOG_INFO("L76B GNSS init succeeded, using L76B GNSS Module\n");
|
||||
return GNSS_MODEL_MTK_L76B;
|
||||
}
|
||||
PROBE_SIMPLE("L76B", "$PMTK605*31", "Quectel-L76B", GNSS_MODEL_MTK_L76B, 500);
|
||||
|
||||
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
|
||||
UBXChecksum(cfg_rate, sizeof(cfg_rate));
|
||||
@@ -1280,31 +1143,10 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
// Check that the returned response class and message ID are correct
|
||||
GPS_RESPONSE response = getACK(0x06, 0x08, 750);
|
||||
if (response == GNSS_RESPONSE_NONE) {
|
||||
LOG_WARN("Failed to find UBlox & MTK GNSS Module using baudrate %d\n", serialSpeed);
|
||||
LOG_WARN("Failed to find GNSS Module (baudrate %d)\n", serialSpeed);
|
||||
return GNSS_MODEL_UNKNOWN;
|
||||
} else if (response == GNSS_RESPONSE_FRAME_ERRORS) {
|
||||
LOG_INFO("UBlox Frame Errors using baudrate %d\n", serialSpeed);
|
||||
} else if (response == GNSS_RESPONSE_OK) {
|
||||
LOG_INFO("Found a UBlox Module using baudrate %d\n", serialSpeed);
|
||||
}
|
||||
|
||||
// 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
|
||||
if (serialSpeed != 9600) {
|
||||
// Set the UART port to 9600
|
||||
uint8_t _message_prt[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00,
|
||||
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
UBXChecksum(_message_prt, sizeof(_message_prt));
|
||||
_serial_gps->write(_message_prt, sizeof(_message_prt));
|
||||
delay(500);
|
||||
serialSpeed = 9600;
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)
|
||||
_serial_gps->end();
|
||||
_serial_gps->begin(serialSpeed);
|
||||
#else
|
||||
_serial_gps->updateBaudRate(serialSpeed);
|
||||
#endif
|
||||
delay(200);
|
||||
LOG_INFO("UBlox Frame Errors (baudrate %d)\n", serialSpeed);
|
||||
}
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
@@ -1356,12 +1198,6 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
for (int i = 0; i < info.extensionNo; ++i) {
|
||||
if (!strncmp(info.extension[i], "MOD=", 4)) {
|
||||
strncpy((char *)buffer, &(info.extension[i][4]), sizeof(buffer));
|
||||
// LOG_DEBUG("GetModel:%s\n", (char *)buffer);
|
||||
if (strlen((char *)buffer)) {
|
||||
LOG_INFO("UBlox GNSS probe succeeded, using UBlox %s GNSS Module\n", (char *)buffer);
|
||||
} else {
|
||||
LOG_INFO("UBlox GNSS probe succeeded, using UBlox GNSS Module\n");
|
||||
}
|
||||
} else if (!strncmp(info.extension[i], "PROTVER", 7)) {
|
||||
char *ptr = nullptr;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
@@ -1375,9 +1211,25 @@ GnssModel_t GPS::probe(int serialSpeed)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strncmp(info.hwVersion, "00040007", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 6", "6");
|
||||
return GNSS_MODEL_UBLOX6;
|
||||
} else if (strncmp(info.hwVersion, "00070000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 7", "7");
|
||||
return GNSS_MODEL_UBLOX7;
|
||||
} else if (strncmp(info.hwVersion, "00080000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 8", "8");
|
||||
return GNSS_MODEL_UBLOX8;
|
||||
} else if (strncmp(info.hwVersion, "00190000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 9", "9");
|
||||
return GNSS_MODEL_UBLOX9;
|
||||
} else if (strncmp(info.hwVersion, "000A0000", 8) == 0) {
|
||||
LOG_INFO(DETECTED_MESSAGE, "U-blox 10", "10");
|
||||
return GNSS_MODEL_UBLOX10;
|
||||
}
|
||||
|
||||
return GNSS_MODEL_UBLOX;
|
||||
}
|
||||
LOG_WARN("Failed to find GNSS Module (baudrate %d)\n", serialSpeed);
|
||||
return GNSS_MODEL_UNKNOWN;
|
||||
}
|
||||
|
||||
GPS *GPS::createGps()
|
||||
@@ -1461,6 +1313,9 @@ GPS *GPS::createGps()
|
||||
LOG_DEBUG("Using GPIO%d for GPS RX\n", new_gps->rx_gpio);
|
||||
LOG_DEBUG("Using GPIO%d for GPS TX\n", new_gps->tx_gpio);
|
||||
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, new_gps->rx_gpio, new_gps->tx_gpio);
|
||||
#elif defined(ARCH_RP2040)
|
||||
_serial_gps->setFIFOSize(256);
|
||||
_serial_gps->begin(GPS_BAUDRATE);
|
||||
#else
|
||||
_serial_gps->begin(GPS_BAUDRATE);
|
||||
#endif
|
||||
@@ -1492,21 +1347,21 @@ bool GPS::factoryReset()
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1C, 0xA2};
|
||||
_serial_gps->write(_message_reset1, sizeof(_message_reset1));
|
||||
if (getACK(0x05, 0x01, 10000)) {
|
||||
LOG_INFO("Get ack success!\n");
|
||||
LOG_INFO(ACK_SUCCESS_MESSAGE);
|
||||
}
|
||||
delay(100);
|
||||
byte _message_reset2[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA1};
|
||||
_serial_gps->write(_message_reset2, sizeof(_message_reset2));
|
||||
if (getACK(0x05, 0x01, 10000)) {
|
||||
LOG_INFO("Get ack success!\n");
|
||||
LOG_INFO(ACK_SUCCESS_MESSAGE);
|
||||
}
|
||||
delay(100);
|
||||
byte _message_reset3[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x1D, 0xB3};
|
||||
_serial_gps->write(_message_reset3, sizeof(_message_reset3));
|
||||
if (getACK(0x05, 0x01, 10000)) {
|
||||
LOG_INFO("Get ack success!\n");
|
||||
LOG_INFO(ACK_SUCCESS_MESSAGE);
|
||||
}
|
||||
// Reset device ram to COLDSTART state
|
||||
// byte _message_CFG_RST_COLDSTART[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0xFF, 0xB9, 0x00, 0x00, 0xC6, 0x8B};
|
||||
@@ -1548,16 +1403,15 @@ bool GPS::lookForTime()
|
||||
|
||||
#ifdef GNSS_AIROHA
|
||||
uint8_t fix = reader.fixQuality();
|
||||
uint32_t now = millis();
|
||||
if (fix > 0) {
|
||||
if (lastFixStartMsec > 0) {
|
||||
if ((now - lastFixStartMsec) < GPS_FIX_HOLD_TIME) {
|
||||
if (Throttle::isWithinTimespanMs(lastFixStartMsec, GPS_FIX_HOLD_TIME)) {
|
||||
return false;
|
||||
} else {
|
||||
clearBuffer();
|
||||
}
|
||||
} else {
|
||||
lastFixStartMsec = now;
|
||||
lastFixStartMsec = millis();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -1572,7 +1426,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
||||
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
*/
|
||||
struct tm t;
|
||||
t.tm_sec = ti.second();
|
||||
t.tm_sec = ti.second() + round(ti.age() / 1000);
|
||||
t.tm_min = ti.minute();
|
||||
t.tm_hour = ti.hour();
|
||||
t.tm_mday = d.day();
|
||||
@@ -1580,8 +1434,8 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
||||
t.tm_year = d.year() - 1900;
|
||||
t.tm_isdst = false;
|
||||
if (t.tm_mon > -1) {
|
||||
LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min,
|
||||
t.tm_sec);
|
||||
LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d age %d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min,
|
||||
t.tm_sec, ti.age());
|
||||
perhapsSetRTC(RTCQualityGPS, t);
|
||||
return true;
|
||||
} else
|
||||
@@ -1601,16 +1455,15 @@ bool GPS::lookForLocation()
|
||||
#ifdef GNSS_AIROHA
|
||||
if ((config.position.gps_update_interval * 1000) >= (GPS_FIX_HOLD_TIME * 2)) {
|
||||
uint8_t fix = reader.fixQuality();
|
||||
uint32_t now = millis();
|
||||
if (fix > 0) {
|
||||
if (lastFixStartMsec > 0) {
|
||||
if ((now - lastFixStartMsec) < GPS_FIX_HOLD_TIME) {
|
||||
if (Throttle::isWithinTimespanMs(lastFixStartMsec, GPS_FIX_HOLD_TIME)) {
|
||||
return false;
|
||||
} else {
|
||||
clearBuffer();
|
||||
}
|
||||
} else {
|
||||
lastFixStartMsec = now;
|
||||
lastFixStartMsec = millis();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -26,11 +26,16 @@ struct uBloxGnssModelInfo {
|
||||
typedef enum {
|
||||
GNSS_MODEL_ATGM336H,
|
||||
GNSS_MODEL_MTK,
|
||||
GNSS_MODEL_UBLOX,
|
||||
GNSS_MODEL_UBLOX6,
|
||||
GNSS_MODEL_UBLOX7,
|
||||
GNSS_MODEL_UBLOX8,
|
||||
GNSS_MODEL_UBLOX9,
|
||||
GNSS_MODEL_UBLOX10,
|
||||
GNSS_MODEL_UC6580,
|
||||
GNSS_MODEL_UNKNOWN,
|
||||
GNSS_MODEL_MTK_L76B,
|
||||
GNSS_MODEL_AG3335
|
||||
GNSS_MODEL_AG3335,
|
||||
GNSS_MODEL_AG3352
|
||||
} GnssModel_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -101,7 +106,7 @@ class GPS : private concurrency::OSThread
|
||||
|
||||
public:
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
#if defined(RPI_PICO_WAVESHARE)
|
||||
#if defined(ARCH_RP2040)
|
||||
static SerialUART *_serial_gps;
|
||||
#else
|
||||
static HardwareSerial *_serial_gps;
|
||||
@@ -129,6 +134,7 @@ class GPS : private concurrency::OSThread
|
||||
static const uint8_t _message_GGA[];
|
||||
static const uint8_t _message_PMS[];
|
||||
static const uint8_t _message_SAVE[];
|
||||
static const uint8_t _message_SAVE_10[];
|
||||
|
||||
// VALSET Commands for M10
|
||||
static const uint8_t _message_VALSET_PM[];
|
||||
@@ -150,6 +156,8 @@ class GPS : private concurrency::OSThread
|
||||
static const uint8_t _message_CAS_CFG_NAVX_CONF[];
|
||||
static const uint8_t _message_CAS_CFG_RATE_1HZ[];
|
||||
|
||||
const char *ACK_SUCCESS_MESSAGE = "Get ack success!\n";
|
||||
|
||||
meshtastic_Position p = meshtastic_Position_init_default;
|
||||
|
||||
/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
|
||||
@@ -297,7 +305,6 @@ class GPS : private concurrency::OSThread
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
// Get GNSS model
|
||||
String getNMEA();
|
||||
GnssModel_t probe(int serialSpeed);
|
||||
|
||||
// delay counter to allow more sats before fixed position stops GPS thread
|
||||
|
||||
@@ -75,10 +75,13 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const
|
||||
uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos)
|
||||
{
|
||||
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
|
||||
tm *t = gmtime((time_t *)&pos.timestamp);
|
||||
time_t timestamp = pos.timestamp;
|
||||
|
||||
tm *t = gmtime(×tamp);
|
||||
if (getRTCQuality() > 0) { // use the device clock if we got time from somewhere. If not, use the GPS timestamp.
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
|
||||
t = gmtime((time_t *)&rtc_sec);
|
||||
timestamp = rtc_sec;
|
||||
t = gmtime(×tamp);
|
||||
}
|
||||
|
||||
uint32_t len = snprintf(
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "configuration.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "main.h"
|
||||
#include <Throttle.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -29,7 +30,7 @@ void readFromRTC()
|
||||
if (rtc_found.address == RV3028_RTC) {
|
||||
uint32_t now = millis();
|
||||
Melopero_RV3028 rtc;
|
||||
#ifdef I2C_SDA1
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.initI2C();
|
||||
@@ -43,7 +44,10 @@ void readFromRTC()
|
||||
t.tm_sec = rtc.getSecond();
|
||||
tv.tv_sec = gm_mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
LOG_DEBUG("Read RTC time from RV3028 as %ld\n", tv.tv_sec);
|
||||
|
||||
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||
LOG_DEBUG("Read RTC time from RV3028 getTime as %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, printableEpoch);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
if (currentQuality == RTCQualityNone) {
|
||||
@@ -55,7 +59,7 @@ void readFromRTC()
|
||||
uint32_t now = millis();
|
||||
PCF8563_Class rtc;
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.begin();
|
||||
@@ -71,7 +75,10 @@ void readFromRTC()
|
||||
t.tm_sec = tc.second;
|
||||
tv.tv_sec = gm_mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
LOG_DEBUG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec);
|
||||
|
||||
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||
LOG_DEBUG("Read RTC time from PCF8563 getDateTime as %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, printableEpoch);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
if (currentQuality == RTCQualityNone) {
|
||||
@@ -81,7 +88,8 @@ void readFromRTC()
|
||||
#else
|
||||
if (!gettimeofday(&tv, NULL)) {
|
||||
uint32_t now = millis();
|
||||
LOG_DEBUG("Read RTC time as %ld\n", tv.tv_sec);
|
||||
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||
LOG_DEBUG("Read RTC time as %ld\n", printableEpoch);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
}
|
||||
@@ -101,6 +109,13 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
|
||||
{
|
||||
static uint32_t lastSetMsec = 0;
|
||||
uint32_t now = millis();
|
||||
uint32_t printableEpoch = tv->tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
|
||||
#ifdef BUILD_EPOCH
|
||||
if (tv->tv_sec < BUILD_EPOCH) {
|
||||
LOG_WARN("Ignoring time (%ld) before build epoch (%ld)!\n", printableEpoch, BUILD_EPOCH);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool shouldSet;
|
||||
if (forceUpdate) {
|
||||
@@ -110,10 +125,13 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
|
||||
} else if (q > currentQuality) {
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Upgrading time to quality %s\n", RtcName(q));
|
||||
} else if (q >= RTCQualityNTP && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
|
||||
// Every 12 hrs we will slam in a new GPS or Phone GPS / NTP time, to correct for local RTC clock drift
|
||||
} else if (q == RTCQualityGPS) {
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Reapplying external time to correct clock drift %ld secs\n", tv->tv_sec);
|
||||
LOG_DEBUG("Reapplying GPS time: %ld secs\n", printableEpoch);
|
||||
} else if (q == RTCQualityNTP && !Throttle::isWithinTimespanMs(lastSetMsec, (12 * 60 * 60 * 1000UL))) {
|
||||
// Every 12 hrs we will slam in a new NTP or Phone GPS / NTP time, to correct for local RTC clock drift
|
||||
shouldSet = true;
|
||||
LOG_DEBUG("Reapplying external time to correct clock drift %ld secs\n", printableEpoch);
|
||||
} else {
|
||||
shouldSet = false;
|
||||
LOG_DEBUG("Current RTC quality: %s. Ignoring time of RTC quality of %s\n", RtcName(currentQuality), RtcName(q));
|
||||
@@ -133,29 +151,29 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate)
|
||||
#ifdef RV3028_RTC
|
||||
if (rtc_found.address == RV3028_RTC) {
|
||||
Melopero_RV3028 rtc;
|
||||
#ifdef I2C_SDA1
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.initI2C();
|
||||
#endif
|
||||
tm *t = gmtime(&tv->tv_sec);
|
||||
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d (%ld)\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
if (rtc_found.address == PCF8563_RTC) {
|
||||
PCF8563_Class rtc;
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.begin();
|
||||
#endif
|
||||
tm *t = gmtime(&tv->tv_sec);
|
||||
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)\n", t->tm_year + 1900, t->tm_mon + 1,
|
||||
t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
|
||||
}
|
||||
#elif defined(ARCH_ESP32)
|
||||
settimeofday(tv, NULL);
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
const char *failMessage = "Unable to %s\n";
|
||||
|
||||
#define SEND_UBX_PACKET(TYPE, ID, DATA, ERRMSG, TIMEOUT) \
|
||||
msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \
|
||||
_serial_gps->write(UBXscratch, msglen); \
|
||||
if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \
|
||||
LOG_WARN(failMessage, #ERRMSG); \
|
||||
}
|
||||
|
||||
// Power Management
|
||||
|
||||
uint8_t GPS::_message_PMREQ[] PROGMEM = {
|
||||
@@ -316,6 +325,13 @@ const uint8_t GPS::_message_SAVE[] = {
|
||||
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
|
||||
};
|
||||
|
||||
const uint8_t GPS::_message_SAVE_10[] = {
|
||||
0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared
|
||||
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
|
||||
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
|
||||
0x01 // deviceMask: only save to BBR
|
||||
};
|
||||
|
||||
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
|
||||
// BBR will survive a restart, and power off for a while, but modules with small backup
|
||||
// batteries or super caps will not retain the config for a long power off time.
|
||||
@@ -335,36 +351,36 @@ const uint8_t GPS::_message_SAVE[] = {
|
||||
// has details on low-power modes
|
||||
|
||||
/*
|
||||
CFG-PM2 has been replaced by many CFG-PM commands
|
||||
CFG-PMS has been removed
|
||||
|
||||
CFG-PM-OPERATEMODE E1 (0 | 1 | 2) -> 1 (PSMOO), because sporadic position updates are required instead of continous tracking <10s
|
||||
(PSMCT) CFG-PM-POSUPDATEPERIOD U4 -> 0ms, no self-timed wakup because receiver power mode is controlled via "software standby
|
||||
mode" by legacy UBX-RXM-PMREQ request CFG-PM-ACQPERIOD U4 -> 0ms, because receiver power mode is controlled via "software standby
|
||||
mode" by legacy UBX-RXM-PMREQ request CFG-PM-ONTIME U4 -> 0ms, optional I guess CFG-PM-EXTINTBACKUP L -> 1, force receiver into
|
||||
BACKUP mode when EXTINT (should be connected to GPS_EN_PIN) pin is "low"
|
||||
|
||||
This is required because the receiver never enters low power mode if microcontroller is in deep-sleep.
|
||||
Maybe the changing UART_RX levels trigger a wakeup but even with UBX-RXM-PMREQ[12] = 0x00 (all external wakeup sources disabled)
|
||||
the receivcer remains in aquisition state -> potentially a bug
|
||||
|
||||
Workaround: Control the EXTINT pin by the GPS_EN_PIN signal
|
||||
|
||||
As mentioned in the M10 operational issues down below, power save won't allow the use of BDS B1C.
|
||||
CFG-SIGNAL-BDS_B1C_ENA L -> 0
|
||||
OPERATEMODE E1 2 (0 | 1 | 2)
|
||||
POSUPDATEPERIOD U4 5
|
||||
ACQPERIOD U4 10
|
||||
GRIDOFFSET U4 0
|
||||
ONTIME U2 1
|
||||
MINACQTIME U1 0
|
||||
MAXACQTIME U1 0
|
||||
DONOTENTEROFF L 1
|
||||
WAITTIMEFIX L 1
|
||||
UPDATEEPH L 1
|
||||
EXTINTWAKE L 0 no ext ints
|
||||
EXTINTBACKUP L 0 no ext ints
|
||||
EXTINTINACTIVE L 0 no ext ints
|
||||
EXTINTACTIVITY U4 0 no ext ints
|
||||
LIMITPEAKCURRENT L 1
|
||||
|
||||
// Ram layer config message:
|
||||
// 01 01 00 00 01 00 D0 20 01 02 00 D0 40 00 00 00 00 03 00 D0 40 00 00 00 00 05 00 D0 30 00 00 0D 00 D0 10 01
|
||||
// b5 62 06 8a 26 00 00 01 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
|
||||
// 10 01 8b de
|
||||
|
||||
// BBR layer config message:
|
||||
// 01 02 00 00 01 00 D0 20 01 02 00 D0 40 00 00 00 00 03 00 D0 40 00 00 00 00 05 00 D0 30 00 00 0D 00 D0 10 01
|
||||
// b5 62 06 8a 26 00 00 02 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
|
||||
// 10 01 8c 03
|
||||
*/
|
||||
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x01, 0x01, 0x00, 0x00, 0x0F, 0x00, 0x31, 0x10, 0x00, 0x01, 0x00, 0xD0, 0x20, 0x01,
|
||||
0x02, 0x00, 0xD0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xD0, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x05, 0x00, 0xD0, 0x30, 0x00, 0x00, 0x0D, 0x00, 0xD0, 0x10, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x01, 0x02, 0x00, 0x00, 0x0F, 0x00, 0x31, 0x10, 0x00, 0x01, 0x00, 0xD0, 0x20, 0x01,
|
||||
0x02, 0x00, 0xD0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xD0, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x05, 0x00, 0xD0, 0x30, 0x00, 0x00, 0x0D, 0x00, 0xD0, 0x10, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
|
||||
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
|
||||
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
|
||||
|
||||
/*
|
||||
CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM and one for BBR
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "Throttle.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#if defined(USE_EINK) && defined(USE_EINK_DYNAMICDISPLAY)
|
||||
@@ -231,15 +232,13 @@ void EInkDynamicDisplay::checkForPromotion()
|
||||
// Is it too soon for another frame of this type?
|
||||
void EInkDynamicDisplay::checkRateLimiting()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
|
||||
// Sanity check: millis() overflow - just let the update run..
|
||||
if (previousRunMs > now)
|
||||
if (previousRunMs > millis())
|
||||
return;
|
||||
|
||||
// Skip update: too soon for BACKGROUND
|
||||
if (frameFlags == BACKGROUND) {
|
||||
if (now - previousRunMs < EINK_LIMIT_RATE_BACKGROUND_SEC * 1000) {
|
||||
if (Throttle::isWithinTimespanMs(previousRunMs, EINK_LIMIT_RATE_BACKGROUND_SEC * 1000)) {
|
||||
refresh = SKIPPED;
|
||||
reason = EXCEEDED_RATELIMIT_FULL;
|
||||
return;
|
||||
@@ -252,7 +251,7 @@ void EInkDynamicDisplay::checkRateLimiting()
|
||||
|
||||
// Skip update: too soon for RESPONSIVE
|
||||
if (frameFlags & RESPONSIVE) {
|
||||
if (now - previousRunMs < EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000) {
|
||||
if (Throttle::isWithinTimespanMs(previousRunMs, EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000)) {
|
||||
refresh = SKIPPED;
|
||||
reason = EXCEEDED_RATELIMIT_FAST;
|
||||
LOG_DEBUG("refresh=SKIPPED, reason=EXCEEDED_RATELIMIT_FAST, frameFlags=0x%x\n", frameFlags);
|
||||
|
||||
@@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "Screen.h"
|
||||
#include "../userPrefs.h"
|
||||
#include "PowerMon.h"
|
||||
#include "Throttle.h"
|
||||
#include "configuration.h"
|
||||
#if HAS_SCREEN
|
||||
#include <OLEDDisplay.h>
|
||||
@@ -47,6 +48,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "modules/AdminModule.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "modules/TextMessageModule.h"
|
||||
#include "modules/WaypointModule.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
|
||||
@@ -56,10 +58,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "esp_task_wdt.h"
|
||||
#include "modules/esp32/StoreForwardModule.h"
|
||||
#include "modules/StoreForwardModule.h"
|
||||
#endif
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
#include "modules/StoreForwardModule.h"
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
@@ -117,6 +120,7 @@ static bool heartbeat = false;
|
||||
#define SCREEN_HEIGHT display->getHeight()
|
||||
|
||||
#include "graphics/ScreenFonts.h"
|
||||
#include <Throttle.h>
|
||||
|
||||
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
|
||||
|
||||
@@ -159,8 +163,8 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
|
||||
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
#ifdef SPLASH_TITLE_USERPREFS
|
||||
const char *title = SPLASH_TITLE_USERPREFS;
|
||||
#ifdef USERPREFS_SPLASH_TITLE
|
||||
const char *title = USERPREFS_SPLASH_TITLE;
|
||||
#else
|
||||
const char *title = "meshtastic.org";
|
||||
#endif
|
||||
@@ -493,7 +497,7 @@ void Screen::drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
|
||||
display->drawString(x + 20, y + 2, batteryPercent);
|
||||
}
|
||||
|
||||
if (nimbleBluetooth->isConnected()) {
|
||||
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
||||
drawBluetoothConnectedIcon(display, display->getWidth() - 18, y + 2);
|
||||
}
|
||||
|
||||
@@ -725,7 +729,7 @@ void Screen::drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
display->drawString(x + 20, y + 2, batteryPercent);
|
||||
}
|
||||
|
||||
if (nimbleBluetooth->isConnected()) {
|
||||
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
||||
drawBluetoothConnectedIcon(display, display->getWidth() - 18, y + 2);
|
||||
}
|
||||
|
||||
@@ -1004,55 +1008,55 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
|
||||
display->setColor(WHITE);
|
||||
#ifndef EXCLUDE_EMOJI
|
||||
if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F44D") == 0) {
|
||||
if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44D") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
|
||||
thumbup);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F44E") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44E") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - thumbs_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - thumbs_height) / 2 + 2 + 5, thumbs_width, thumbs_height,
|
||||
thumbdown);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"❓") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "❓") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - question_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - question_height) / 2 + 2 + 5, question_width, question_height,
|
||||
question);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"‼️") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "‼️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - bang_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - bang_height) / 2 + 2 + 5,
|
||||
bang_width, bang_height, bang);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F4A9") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F4A9") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - poo_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - poo_height) / 2 + 2 + 5,
|
||||
poo_width, poo_height, poo);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\xa4\xa3") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - haha_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - haha_height) / 2 + 2 + 5,
|
||||
haha_width, haha_height, haha);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F44B") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F44B") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - wave_icon_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - wave_icon_height) / 2 + 2 + 5, wave_icon_width,
|
||||
wave_icon_height, wave_icon);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F920") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F920") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - cowboy_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cowboy_height) / 2 + 2 + 5, cowboy_width, cowboy_height,
|
||||
cowboy);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\U0001F42D") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\U0001F42D") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - deadmau5_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - deadmau5_height) / 2 + 2 + 5, deadmau5_width, deadmau5_height,
|
||||
deadmau5);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\xE2\x98\x80\xEF\xB8\x8F") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xE2\x98\x80\xEF\xB8\x8F") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - sun_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - sun_height) / 2 + 2 + 5,
|
||||
sun_width, sun_height, sun);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\u2614") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\u2614") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - rain_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - rain_height) / 2 + 2 + 10,
|
||||
rain_width, rain_height, rain);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"☁️") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "☁️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - cloud_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - cloud_height) / 2 + 2 + 5, cloud_width, cloud_height, cloud);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"🌫️") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "🌫️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - fog_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - fog_height) / 2 + 2 + 5,
|
||||
fog_width, fog_height, fog);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"\xf0\x9f\x98\x88") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "\xf0\x9f\x98\x88") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - devil_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil);
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), u8"♥️") == 0) {
|
||||
} else if (strcmp(reinterpret_cast<const char *>(mp.decoded.payload.bytes), "♥️") == 0) {
|
||||
display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart);
|
||||
} else {
|
||||
@@ -1093,8 +1097,8 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
|
||||
{
|
||||
char usersString[20];
|
||||
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
|
||||
defined(HX8357_CS)) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x, y + 3, 8, 8, imgUser);
|
||||
#else
|
||||
@@ -1285,8 +1289,8 @@ static int8_t prevFrame = -1;
|
||||
// Draw the arrow pointing to a node's location
|
||||
void Screen::drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t compassY, uint16_t compassDiam, float headingRadian)
|
||||
{
|
||||
Point tip(0.0f, 0.5f), tail(0.0f, -0.5f); // pointing up initially
|
||||
float arrowOffsetX = 0.2f, arrowOffsetY = 0.2f;
|
||||
Point tip(0.0f, 0.5f), tail(0.0f, -0.35f); // pointing up initially
|
||||
float arrowOffsetX = 0.14f, arrowOffsetY = 1.0f;
|
||||
Point leftArrow(tip.x - arrowOffsetX, tip.y - arrowOffsetY), rightArrow(tip.x + arrowOffsetX, tip.y - arrowOffsetY);
|
||||
|
||||
Point *arrowPoints[] = {&tip, &tail, &leftArrow, &rightArrow};
|
||||
@@ -1296,9 +1300,19 @@ void Screen::drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t com
|
||||
arrowPoints[i]->scale(compassDiam * 0.6);
|
||||
arrowPoints[i]->translate(compassX, compassY);
|
||||
}
|
||||
/* Old arrow
|
||||
display->drawLine(tip.x, tip.y, tail.x, tail.y);
|
||||
display->drawLine(leftArrow.x, leftArrow.y, tip.x, tip.y);
|
||||
display->drawLine(rightArrow.x, rightArrow.y, tip.x, tip.y);
|
||||
display->drawLine(leftArrow.x, leftArrow.y, tail.x, tail.y);
|
||||
display->drawLine(rightArrow.x, rightArrow.y, tail.x, tail.y);
|
||||
*/
|
||||
#ifdef USE_EINK
|
||||
display->drawTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
|
||||
#else
|
||||
display->fillTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
|
||||
#endif
|
||||
display->drawTriangle(tip.x, tip.y, leftArrow.x, leftArrow.y, tail.x, tail.y);
|
||||
}
|
||||
|
||||
// Get a string representation of the time passed since something happened
|
||||
@@ -1336,22 +1350,27 @@ void Screen::drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t co
|
||||
// If north is supposed to be at the top of the compass we want rotation to be +0
|
||||
if (config.display.compass_north_top)
|
||||
myHeading = -0;
|
||||
|
||||
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f);
|
||||
/* N sign points currently not deleted*/
|
||||
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f); // N sign points (N1-N4)
|
||||
Point N3(-0.04f, 0.55f), N4(0.04f, 0.55f);
|
||||
Point *rosePoints[] = {&N1, &N2, &N3, &N4};
|
||||
Point NC1(0.00f, 0.50f); // north circle center point
|
||||
Point *rosePoints[] = {&N1, &N2, &N3, &N4, &NC1};
|
||||
|
||||
uint16_t compassDiam = Screen::getCompassDiam(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
// North on compass will be negative of heading
|
||||
rosePoints[i]->rotate(-myHeading);
|
||||
rosePoints[i]->scale(compassDiam);
|
||||
rosePoints[i]->translate(compassX, compassY);
|
||||
}
|
||||
|
||||
/* changed the N sign to a small circle on the compass circle.
|
||||
display->drawLine(N1.x, N1.y, N3.x, N3.y);
|
||||
display->drawLine(N2.x, N2.y, N4.x, N4.y);
|
||||
display->drawLine(N1.x, N1.y, N4.x, N4.y);
|
||||
*/
|
||||
display->drawCircle(NC1.x, NC1.y, 4); // North sign circle, 4px radius is sufficient for all displays.
|
||||
}
|
||||
|
||||
uint16_t Screen::getCompassDiam(uint32_t displayWidth, uint32_t displayHeight)
|
||||
@@ -1515,7 +1534,8 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
|
||||
#elif defined(USE_SSD1306)
|
||||
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
|
||||
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \
|
||||
defined(RAK14014) || defined(HX8357_CS)
|
||||
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
|
||||
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
|
||||
#elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY)
|
||||
@@ -1654,6 +1674,11 @@ void Screen::setup()
|
||||
static_cast<SH1106Wire *>(dispdev)->setSubtype(7);
|
||||
#endif
|
||||
|
||||
#if defined(USE_ST7789) && defined(TFT_MESH)
|
||||
// Heltec T114 and T190: honor a custom text color, if defined in variant.h
|
||||
static_cast<ST7789Spi *>(dispdev)->setRGB(TFT_MESH);
|
||||
#endif
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
ui->init();
|
||||
|
||||
@@ -1707,8 +1732,11 @@ void Screen::setup()
|
||||
// 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) {
|
||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
|
||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \
|
||||
defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
|
||||
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
|
||||
#elif defined(USE_ST7789)
|
||||
static_cast<ST7789Spi *>(dispdev)->flipScreenVertically();
|
||||
#else
|
||||
dispdev->flipScreenVertically();
|
||||
#endif
|
||||
@@ -1766,6 +1794,11 @@ void Screen::forceDisplay(bool forceUiUpdate)
|
||||
#ifdef USE_EINK
|
||||
// If requested, make sure queued commands are run, and UI has rendered a new frame
|
||||
if (forceUiUpdate) {
|
||||
// Force a display refresh, in addition to the UI update
|
||||
// Changing the GPS status bar icon apparently doesn't register as a change in image
|
||||
// (False negative of the image hashing algorithm used to skip identical frames)
|
||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST);
|
||||
|
||||
// No delay between UI frame rendering
|
||||
setFastFramerate();
|
||||
|
||||
@@ -1851,13 +1884,7 @@ int32_t Screen::runOnce()
|
||||
handleSetOn(false);
|
||||
break;
|
||||
case Cmd::ON_PRESS:
|
||||
// If a nag notification is running, stop it
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
externalNotificationModule->stopNow();
|
||||
} else {
|
||||
// Don't advance the screen if we just wanted to switch off the nag notification
|
||||
handleOnPress();
|
||||
}
|
||||
break;
|
||||
case Cmd::SHOW_PREV_FRAME:
|
||||
handleShowPrevFrame();
|
||||
@@ -1920,7 +1947,7 @@ int32_t Screen::runOnce()
|
||||
if (showingNormalScreen) {
|
||||
// standard screen loop handling here
|
||||
if (config.display.auto_screen_carousel_secs > 0 &&
|
||||
(millis() - lastScreenTransition) > (config.display.auto_screen_carousel_secs * 1000)) {
|
||||
!Throttle::isWithinTimespanMs(lastScreenTransition, config.display.auto_screen_carousel_secs * 1000)) {
|
||||
|
||||
// If an E-Ink display struggles with fast refresh, force carousel to use full refresh instead
|
||||
// Carousel is potentially a major source of E-Ink display wear
|
||||
@@ -2081,8 +2108,13 @@ void Screen::setFrames(FrameFocus focus)
|
||||
// Check if the module being drawn has requested focus
|
||||
// We will honor this request later, if setFrames was triggered by a UIFrameEvent
|
||||
MeshModule *m = *i;
|
||||
if (m->isRequestingFocus())
|
||||
if (m->isRequestingFocus()) {
|
||||
fsi.positions.focusedModule = numframes;
|
||||
}
|
||||
|
||||
// Identify the position of specific modules, if we need to know this later
|
||||
if (m == waypointModule)
|
||||
fsi.positions.waypoint = numframes;
|
||||
|
||||
numframes++;
|
||||
}
|
||||
@@ -2101,8 +2133,8 @@ void Screen::setFrames(FrameFocus focus)
|
||||
#endif
|
||||
|
||||
// If we have a text message - show it next, unless it's a phone message and we aren't using any special modules
|
||||
fsi.positions.textMessage = numframes;
|
||||
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) {
|
||||
fsi.positions.textMessage = numframes;
|
||||
normalFrames[numframes++] = drawTextMessageFrame;
|
||||
}
|
||||
|
||||
@@ -2164,7 +2196,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
|
||||
case FOCUS_PRESERVE:
|
||||
// If we can identify which type of frame "originalPosition" was, can move directly to it in the new frameset
|
||||
FramesetInfo &oldFsi = this->framesetInfo;
|
||||
const FramesetInfo &oldFsi = this->framesetInfo;
|
||||
if (originalPosition == oldFsi.positions.log)
|
||||
ui->switchToFrame(fsi.positions.log);
|
||||
else if (originalPosition == oldFsi.positions.settings)
|
||||
@@ -2204,6 +2236,31 @@ void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
|
||||
setFastFramerate();
|
||||
}
|
||||
|
||||
// Dismisses the currently displayed screen frame, if possible
|
||||
// Relevant for text message, waypoint, others in future?
|
||||
// Triggered with a CardKB keycombo
|
||||
void Screen::dismissCurrentFrame()
|
||||
{
|
||||
uint8_t currentFrame = ui->getUiState()->currentFrame;
|
||||
bool dismissed = false;
|
||||
|
||||
if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) {
|
||||
LOG_INFO("Dismissing Text Message\n");
|
||||
devicestate.has_rx_text_message = false;
|
||||
dismissed = true;
|
||||
}
|
||||
|
||||
else if (currentFrame == framesetInfo.positions.waypoint && devicestate.has_rx_waypoint) {
|
||||
LOG_DEBUG("Dismissing Waypoint\n");
|
||||
devicestate.has_rx_waypoint = false;
|
||||
dismissed = true;
|
||||
}
|
||||
|
||||
// If we did make changes to dismiss, we now need to regenerate the frameset
|
||||
if (dismissed)
|
||||
setFrames();
|
||||
}
|
||||
|
||||
void Screen::handleStartFirmwareUpdateScreen()
|
||||
{
|
||||
LOG_DEBUG("showing firmware screen\n");
|
||||
@@ -2413,10 +2470,10 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
// Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
|
||||
if (moduleConfig.store_forward.enabled) {
|
||||
#ifdef ARCH_ESP32
|
||||
if (millis() - storeForwardModule->lastHeartbeat >
|
||||
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
|
||||
defined(HX8357_CS)) && \
|
||||
if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat,
|
||||
(storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgQuestionL1);
|
||||
@@ -2427,8 +2484,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
imgQuestion);
|
||||
#endif
|
||||
} else {
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
|
||||
defined(HX8357_CS)) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
|
||||
imgSFL1);
|
||||
@@ -2442,8 +2499,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
#endif
|
||||
} else {
|
||||
// TODO: Raspberry Pi supports more than just the one screen size
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
|
||||
defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgInfoL1);
|
||||
@@ -2716,11 +2773,22 @@ int Screen::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (showingNormalScreen && moduleFrames.size() == 0) {
|
||||
// LOG_DEBUG("Screen::handleInputEvent from %s\n", event->source);
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
|
||||
// Use left or right input from a keyboard to move between frames,
|
||||
// so long as a mesh module isn't using these events for some other purpose
|
||||
if (showingNormalScreen) {
|
||||
|
||||
// Ask any MeshModules if they're handling keyboard input right now
|
||||
bool inputIntercepted = false;
|
||||
for (MeshModule *module : moduleFrames) {
|
||||
if (module->interceptingKeyboardInput())
|
||||
inputIntercepted = true;
|
||||
}
|
||||
|
||||
// If no modules are using the input, move between frames
|
||||
if (!inputIntercepted) {
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT))
|
||||
showPrevFrame();
|
||||
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
|
||||
else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))
|
||||
showNextFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,6 +454,9 @@ class Screen : public concurrency::OSThread
|
||||
|
||||
void setWelcomeFrames();
|
||||
|
||||
// Dismiss the currently focussed frame, if possible (e.g. text message, waypoint)
|
||||
void dismissCurrentFrame();
|
||||
|
||||
#ifdef USE_EINK
|
||||
/// Draw an image to remain on E-Ink display after screen off
|
||||
void setScreensaverFrames(FrameCallback einkScreensaver = NULL);
|
||||
@@ -503,11 +506,14 @@ class Screen : public concurrency::OSThread
|
||||
void handleStartFirmwareUpdateScreen();
|
||||
|
||||
// Info collected by setFrames method.
|
||||
// Index location of specific frames. Used to apply the FrameFocus parameter of setFrames
|
||||
// Index location of specific frames.
|
||||
// - Used to apply the FrameFocus parameter of setFrames
|
||||
// - Used to dismiss the currently shown frame (txt; waypoint) by CardKB combo
|
||||
struct FramesetInfo {
|
||||
struct FramePositions {
|
||||
uint8_t fault = 0;
|
||||
uint8_t textMessage = 0;
|
||||
uint8_t waypoint = 0;
|
||||
uint8_t focusedModule = 0;
|
||||
uint8_t log = 0;
|
||||
uint8_t settings = 0;
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include "graphics/fonts/OLEDDisplayFontsUA.h"
|
||||
#endif
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
|
||||
defined(HX8357_CS)) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
// The screen is bigger so use bigger fonts
|
||||
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
|
||||
|
||||
@@ -244,9 +244,9 @@ class LGFX : public lgfx::LGFX_Device
|
||||
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(ILI9341_DRIVER)
|
||||
#elif defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER)
|
||||
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ILI9341 driver chip
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ILI9341/ILI9342 driver chip
|
||||
|
||||
#if defined(ILI9341_BACKLIGHT_EN) && !defined(TFT_BL)
|
||||
#define TFT_BL ILI9341_BACKLIGHT_EN
|
||||
@@ -254,7 +254,11 @@ static LGFX *tft = nullptr;
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
#if defined(ILI9341_DRIVER)
|
||||
lgfx::Panel_ILI9341 _panel_instance;
|
||||
#elif defined(ILI9342_DRIVER)
|
||||
lgfx::Panel_ILI9342 _panel_instance;
|
||||
#endif
|
||||
lgfx::Bus_SPI _bus_instance;
|
||||
lgfx::Light_PWM _light_instance;
|
||||
|
||||
@@ -265,7 +269,11 @@ class LGFX : public lgfx::LGFX_Device
|
||||
auto cfg = _bus_instance.config();
|
||||
|
||||
// configure SPI
|
||||
#if defined(ILI9341_DRIVER)
|
||||
cfg.spi_host = ILI9341_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
|
||||
#elif defined(ILI9342_DRIVER)
|
||||
cfg.spi_host = ILI9342_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
|
||||
#endif
|
||||
cfg.spi_mode = 0;
|
||||
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
|
||||
// 80MHz by an integer)
|
||||
@@ -336,7 +344,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(ST7735_CS)
|
||||
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
|
||||
#include <TFT_eSPI.h> // Graphics and font library for ILI9342 driver chip
|
||||
|
||||
static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
|
||||
#elif ARCH_PORTDUINO && HAS_SCREEN != 0
|
||||
@@ -360,6 +368,8 @@ class LGFX : public lgfx::LGFX_Device
|
||||
_panel_instance = new lgfx::Panel_ST7735S;
|
||||
else if (settingsMap[displayPanel] == ili9341)
|
||||
_panel_instance = new lgfx::Panel_ILI9341;
|
||||
else if (settingsMap[displayPanel] == ili9342)
|
||||
_panel_instance = new lgfx::Panel_ILI9342;
|
||||
auto buscfg = _bus_instance.config();
|
||||
buscfg.spi_mode = 0;
|
||||
buscfg.spi_host = settingsMap[displayspidev];
|
||||
@@ -500,10 +510,126 @@ class LGFX : public lgfx::LGFX_Device
|
||||
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(ST7701_CS)
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7701 driver chip
|
||||
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
|
||||
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
lgfx::Panel_ST7701 _panel_instance;
|
||||
lgfx::Bus_RGB _bus_instance;
|
||||
lgfx::Light_PWM _light_instance;
|
||||
lgfx::Touch_FT5x06 _touch_instance;
|
||||
|
||||
public:
|
||||
LGFX(void)
|
||||
{
|
||||
{
|
||||
auto cfg = _panel_instance.config();
|
||||
cfg.memory_width = 800;
|
||||
cfg.memory_height = 480;
|
||||
cfg.panel_width = TFT_WIDTH;
|
||||
cfg.panel_height = TFT_HEIGHT;
|
||||
cfg.offset_x = TFT_OFFSET_X;
|
||||
cfg.offset_y = TFT_OFFSET_Y;
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
|
||||
{
|
||||
auto cfg = _panel_instance.config_detail();
|
||||
cfg.pin_cs = ST7701_CS;
|
||||
cfg.pin_sclk = ST7701_SCK;
|
||||
cfg.pin_mosi = ST7701_SDA;
|
||||
// cfg.use_psram = 1;
|
||||
_panel_instance.config_detail(cfg);
|
||||
}
|
||||
|
||||
{
|
||||
auto cfg = _bus_instance.config();
|
||||
cfg.panel = &_panel_instance;
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
cfg.pin_d0 = GPIO_NUM_15; // B0
|
||||
cfg.pin_d1 = GPIO_NUM_14; // B1
|
||||
cfg.pin_d2 = GPIO_NUM_13; // B2
|
||||
cfg.pin_d3 = GPIO_NUM_12; // B3
|
||||
cfg.pin_d4 = GPIO_NUM_11; // B4
|
||||
|
||||
cfg.pin_d5 = GPIO_NUM_10; // G0
|
||||
cfg.pin_d6 = GPIO_NUM_9; // G1
|
||||
cfg.pin_d7 = GPIO_NUM_8; // G2
|
||||
cfg.pin_d8 = GPIO_NUM_7; // G3
|
||||
cfg.pin_d9 = GPIO_NUM_6; // G4
|
||||
cfg.pin_d10 = GPIO_NUM_5; // G5
|
||||
|
||||
cfg.pin_d11 = GPIO_NUM_4; // R0
|
||||
cfg.pin_d12 = GPIO_NUM_3; // R1
|
||||
cfg.pin_d13 = GPIO_NUM_2; // R2
|
||||
cfg.pin_d14 = GPIO_NUM_1; // R3
|
||||
cfg.pin_d15 = GPIO_NUM_0; // R4
|
||||
|
||||
cfg.pin_henable = GPIO_NUM_18;
|
||||
cfg.pin_vsync = GPIO_NUM_17;
|
||||
cfg.pin_hsync = GPIO_NUM_16;
|
||||
cfg.pin_pclk = GPIO_NUM_21;
|
||||
cfg.freq_write = 12000000;
|
||||
|
||||
cfg.hsync_polarity = 0;
|
||||
cfg.hsync_front_porch = 10;
|
||||
cfg.hsync_pulse_width = 8;
|
||||
cfg.hsync_back_porch = 50;
|
||||
|
||||
cfg.vsync_polarity = 0;
|
||||
cfg.vsync_front_porch = 10;
|
||||
cfg.vsync_pulse_width = 8;
|
||||
cfg.vsync_back_porch = 20;
|
||||
|
||||
cfg.pclk_active_neg = 0;
|
||||
cfg.de_idle_high = 1;
|
||||
cfg.pclk_idle_high = 0;
|
||||
#endif
|
||||
_bus_instance.config(cfg);
|
||||
}
|
||||
_panel_instance.setBus(&_bus_instance);
|
||||
|
||||
{
|
||||
auto cfg = _light_instance.config();
|
||||
cfg.pin_bl = ST7701_BL;
|
||||
_light_instance.config(cfg);
|
||||
}
|
||||
_panel_instance.light(&_light_instance);
|
||||
|
||||
{
|
||||
auto cfg = _touch_instance.config();
|
||||
cfg.pin_cs = -1;
|
||||
cfg.x_min = 0;
|
||||
cfg.x_max = 479;
|
||||
cfg.y_min = 0;
|
||||
cfg.y_max = 479;
|
||||
cfg.pin_int = -1; // don't use SCREEN_TOUCH_INT;
|
||||
cfg.pin_rst = SCREEN_TOUCH_RST;
|
||||
cfg.bus_shared = true;
|
||||
cfg.offset_rotation = TFT_OFFSET_ROTATION;
|
||||
|
||||
cfg.i2c_port = TOUCH_I2C_PORT;
|
||||
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
|
||||
cfg.pin_sda = I2C_SDA;
|
||||
cfg.pin_scl = I2C_SCL;
|
||||
cfg.freq = 400000;
|
||||
_touch_instance.config(cfg);
|
||||
_panel_instance.setTouch(&_touch_instance);
|
||||
}
|
||||
|
||||
setPanel(&_panel_instance);
|
||||
}
|
||||
};
|
||||
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || defined(HX8357_CS) || \
|
||||
(ARCH_PORTDUINO && HAS_SCREEN != 0)
|
||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
||||
defined(RAK14014) || defined(HX8357_CS) || (ARCH_PORTDUINO && HAS_SCREEN != 0)
|
||||
#include "SPILock.h"
|
||||
#include "TFTDisplay.h"
|
||||
#include <SPI.h>
|
||||
@@ -709,7 +835,6 @@ bool TFTDisplay::connect()
|
||||
|
||||
#ifdef UNPHONE
|
||||
unphone.backlight(true); // using unPhone library
|
||||
LOG_INFO("Power to TFT Backlight\n");
|
||||
#endif
|
||||
|
||||
tft->init();
|
||||
@@ -725,7 +850,7 @@ bool TFTDisplay::connect()
|
||||
attachInterrupt(digitalPinToInterrupt(SCREEN_TOUCH_INT), rak14014_tpIntHandle, FALLING);
|
||||
#elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2)
|
||||
tft->setRotation(1); // T-Deck has the TFT in landscape
|
||||
#elif defined(T_WATCH_S3)
|
||||
#elif defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR)
|
||||
tft->setRotation(2); // T-Watch S3 left-handed orientation
|
||||
#else
|
||||
tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
|
||||
|
||||
@@ -20,8 +20,8 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03
|
||||
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};
|
||||
#endif
|
||||
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(USE_ST7789) || \
|
||||
defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
|
||||
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
|
||||
!defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
|
||||
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef HAS_USERPREFS_SPLASH
|
||||
#ifndef USERPREFS_HAS_SPLASH
|
||||
#define icon_width 50
|
||||
#define icon_height 28
|
||||
static uint8_t icon_bits[] = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
#include "ExpressLRSFiveWay.h"
|
||||
#include "Throttle.h"
|
||||
|
||||
#ifdef INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE
|
||||
|
||||
@@ -76,11 +76,10 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
|
||||
*keyValue = NO_PRESS;
|
||||
|
||||
int newKey = readKey();
|
||||
uint32_t now = millis();
|
||||
if (keyInProcess == NO_PRESS) {
|
||||
// New key down
|
||||
if (newKey != NO_PRESS) {
|
||||
keyDownStart = now;
|
||||
keyDownStart = millis();
|
||||
// DBGLN("down=%u", newKey);
|
||||
}
|
||||
} else {
|
||||
@@ -88,7 +87,7 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
|
||||
if (newKey == NO_PRESS) {
|
||||
// DBGLN("up=%u", keyInProcess);
|
||||
if (!isLongPressed) {
|
||||
if ((now - keyDownStart) > KEY_DEBOUNCE_MS) {
|
||||
if (!Throttle::isWithinTimespanMs(keyDownStart, KEY_DEBOUNCE_MS)) {
|
||||
*keyValue = keyInProcess;
|
||||
*keyLongPressed = false;
|
||||
}
|
||||
@@ -101,7 +100,7 @@ void ExpressLRSFiveWay::update(int *keyValue, bool *keyLongPressed)
|
||||
}
|
||||
// else still pressing, waiting for long if not already signaled
|
||||
else if (!isLongPressed) {
|
||||
if ((now - keyDownStart) > KEY_LONG_PRESS_MS) {
|
||||
if (!Throttle::isWithinTimespanMs(keyDownStart, KEY_LONG_PRESS_MS)) {
|
||||
*keyValue = keyInProcess;
|
||||
*keyLongPressed = true;
|
||||
isLongPressed = true;
|
||||
|
||||
@@ -4,6 +4,22 @@
|
||||
#define ANYKEY 0xFF
|
||||
#define MATRIXKEY 0xFE
|
||||
|
||||
#define INPUT_BROKER_MSG_BRIGHTNESS_UP 0x11
|
||||
#define INPUT_BROKER_MSG_BRIGHTNESS_DOWN 0x12
|
||||
#define INPUT_BROKER_MSG_REBOOT 0x90
|
||||
#define INPUT_BROKER_MSG_SHUTDOWN 0x9b
|
||||
#define INPUT_BROKER_MSG_GPS_TOGGLE 0x9e
|
||||
#define INPUT_BROKER_MSG_MUTE_TOGGLE 0xac
|
||||
#define INPUT_BROKER_MSG_SEND_PING 0xaf
|
||||
#define INPUT_BROKER_MSG_DISMISS_FRAME 0x8b
|
||||
#define INPUT_BROKER_MSG_LEFT 0xb4
|
||||
#define INPUT_BROKER_MSG_UP 0xb5
|
||||
#define INPUT_BROKER_MSG_DOWN 0xb6
|
||||
#define INPUT_BROKER_MSG_RIGHT 0xb7
|
||||
#define INPUT_BROKER_MSG_FN_SYMBOL_ON 0xf1
|
||||
#define INPUT_BROKER_MSG_FN_SYMBOL_OFF 0xf2
|
||||
#define INPUT_BROKER_MSG_BLUETOOTH_TOGGLE 0xAA
|
||||
|
||||
typedef struct _InputEvent {
|
||||
const char *source;
|
||||
char inputEvent;
|
||||
|
||||
@@ -147,11 +147,11 @@ int32_t LinuxInput::runOnce()
|
||||
case KEY_LEFT: // Left
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||
break;
|
||||
e.kbchar = 0xb4;
|
||||
e.kbchar = INPUT_BROKER_MSG_LEFT;
|
||||
case KEY_RIGHT: // Right
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||
break;
|
||||
e.kbchar = 0xb7;
|
||||
e.kbchar = INPUT_BROKER_MSG_RIGHT;
|
||||
case KEY_ENTER: // Enter
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||
break;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "ScanAndSelect.h"
|
||||
#include "modules/CannedMessageModule.h"
|
||||
#include <Throttle.h>
|
||||
|
||||
// Config
|
||||
static const char name[] = "scanAndSelect"; // should match "allow input source" string
|
||||
@@ -75,7 +76,7 @@ int32_t ScanAndSelectInput::runOnce()
|
||||
else {
|
||||
// Duration enough for long press
|
||||
// Long press not yet fired (prevent repeat firing while held)
|
||||
if (!longPressFired && now - downSinceMs > durationLongMs) {
|
||||
if (!longPressFired && Throttle::isWithinTimespanMs(downSinceMs, durationLongMs)) {
|
||||
longPressFired = true;
|
||||
longPress();
|
||||
}
|
||||
@@ -91,7 +92,7 @@ int32_t ScanAndSelectInput::runOnce()
|
||||
// Long press event didn't already fire
|
||||
if (held && !longPressFired) {
|
||||
// Duration enough for short press
|
||||
if (now - downSinceMs > durationShortMs) {
|
||||
if (!Throttle::isWithinTimespanMs(downSinceMs, durationShortMs)) {
|
||||
shortPress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "SerialKeyboard.h"
|
||||
#include "configuration.h"
|
||||
#include <Throttle.h>
|
||||
|
||||
#ifdef INPUTBROKER_SERIAL_TYPE
|
||||
#define CANNED_MESSAGE_MODULE_ENABLE 1 // in case it's not set in the variant file
|
||||
@@ -73,7 +74,7 @@ int32_t SerialKeyboard::runOnce()
|
||||
// Serial.print ("X");
|
||||
// Serial.println (shiftRegister2, BIN);
|
||||
|
||||
if (millis() - lastPressTime > 500) {
|
||||
if (!Throttle::isWithinTimespanMs(lastPressTime, 500)) {
|
||||
quickPress = 0;
|
||||
}
|
||||
|
||||
@@ -87,7 +88,7 @@ int32_t SerialKeyboard::runOnce()
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||
} else if (!(shiftRegister2 & (1 << 2))) {
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||
e.kbchar = 0xb7;
|
||||
e.kbchar = INPUT_BROKER_MSG_RIGHT;
|
||||
} else if (!(shiftRegister2 & (1 << 1))) {
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||
} else if (!(shiftRegister2 & (1 << 0))) {
|
||||
|
||||
@@ -9,14 +9,14 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
|
||||
|
||||
void CardKbI2cImpl::init()
|
||||
{
|
||||
#ifndef ARCH_PORTDUINO
|
||||
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO)
|
||||
if (cardkb_found.address == 0x00) {
|
||||
LOG_DEBUG("Rescanning for I2C keyboard\n");
|
||||
uint8_t i2caddr_scan[] = {CARDKB_ADDR, TDECK_KB_ADDR, BBQ10_KB_ADDR};
|
||||
uint8_t i2caddr_asize = 3;
|
||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||
|
||||
#if defined(I2C_SDA1)
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1, i2caddr_scan, i2caddr_asize);
|
||||
#endif
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE, i2caddr_scan, i2caddr_asize);
|
||||
|
||||
@@ -33,7 +33,7 @@ int32_t KbI2cBase::runOnce()
|
||||
if (!i2cBus) {
|
||||
switch (cardkb_found.port) {
|
||||
case ScanI2C::WIRE1:
|
||||
#ifdef I2C_SDA1
|
||||
#if WIRE_INTERFACES_COUNT == 2
|
||||
LOG_DEBUG("Using I2C Bus 1 (the second one)\n");
|
||||
i2cBus = &Wire1;
|
||||
if (cardkb_found.address == BBQ10_KB_ADDR) {
|
||||
@@ -94,7 +94,7 @@ int32_t KbI2cBase::runOnce()
|
||||
case 'e': // sym e
|
||||
if (is_sym) {
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||
e.kbchar = 0xb5;
|
||||
e.kbchar = INPUT_BROKER_MSG_UP;
|
||||
is_sym = false; // reset sym state after second keypress
|
||||
} else {
|
||||
e.inputEvent = ANYKEY;
|
||||
@@ -104,7 +104,7 @@ int32_t KbI2cBase::runOnce()
|
||||
case 'x': // sym x
|
||||
if (is_sym) {
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||
e.kbchar = 0xb6;
|
||||
e.kbchar = INPUT_BROKER_MSG_DOWN;
|
||||
is_sym = false; // reset sym state after second keypress
|
||||
} else {
|
||||
e.inputEvent = ANYKEY;
|
||||
@@ -134,8 +134,8 @@ int32_t KbI2cBase::runOnce()
|
||||
case 0x13: // Code scanner says the SYM key is 0x13
|
||||
is_sym = !is_sym;
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar =
|
||||
is_sym ? 0xf1 : 0xf2; // send 0xf1 to tell CannedMessages to display that the modifier key is active
|
||||
e.kbchar = is_sym ? INPUT_BROKER_MSG_FN_SYMBOL_ON // send 0xf1 to tell CannedMessages to display that
|
||||
: INPUT_BROKER_MSG_FN_SYMBOL_OFF; // the modifier key is active
|
||||
break;
|
||||
case 0x0a: // apparently Enter on Q10 is a line feed instead of carriage return
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
|
||||
@@ -214,7 +214,7 @@ int32_t KbI2cBase::runOnce()
|
||||
if (is_sym) {
|
||||
is_sym = false;
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = 0xac; // mute notifications
|
||||
e.kbchar = INPUT_BROKER_MSG_MUTE_TOGGLE; // mute notifications
|
||||
} else {
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = c;
|
||||
@@ -224,7 +224,7 @@ int32_t KbI2cBase::runOnce()
|
||||
if (is_sym) {
|
||||
is_sym = false;
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = 0x11; // Increase Brightness code
|
||||
e.kbchar = INPUT_BROKER_MSG_BRIGHTNESS_UP; // Increase Brightness code
|
||||
} else {
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = c;
|
||||
@@ -234,7 +234,7 @@ int32_t KbI2cBase::runOnce()
|
||||
if (is_sym) {
|
||||
is_sym = false;
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = 0x12; // Decrease Brightness code
|
||||
e.kbchar = INPUT_BROKER_MSG_BRIGHTNESS_DOWN; // Decrease Brightness code
|
||||
} else {
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = c;
|
||||
@@ -244,7 +244,7 @@ int32_t KbI2cBase::runOnce()
|
||||
if (is_sym) {
|
||||
is_sym = false;
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = 0xaf; // (fn + space)
|
||||
e.kbchar = INPUT_BROKER_MSG_SEND_PING; // (fn + space)
|
||||
} else {
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = c;
|
||||
@@ -254,7 +254,7 @@ int32_t KbI2cBase::runOnce()
|
||||
if (is_sym) {
|
||||
is_sym = false;
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = 0x9e;
|
||||
e.kbchar = INPUT_BROKER_MSG_GPS_TOGGLE;
|
||||
} else {
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = c;
|
||||
@@ -269,32 +269,35 @@ int32_t KbI2cBase::runOnce()
|
||||
break;
|
||||
case 0xb5: // Up
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
|
||||
e.kbchar = 0xb5;
|
||||
e.kbchar = INPUT_BROKER_MSG_UP;
|
||||
break;
|
||||
case 0xb6: // Down
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
|
||||
e.kbchar = 0xb6;
|
||||
e.kbchar = INPUT_BROKER_MSG_DOWN;
|
||||
break;
|
||||
case 0xb4: // Left
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
|
||||
e.kbchar = 0xb4;
|
||||
e.kbchar = INPUT_BROKER_MSG_LEFT;
|
||||
break;
|
||||
case 0xb7: // Right
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
|
||||
e.kbchar = 0xb7;
|
||||
e.kbchar = INPUT_BROKER_MSG_RIGHT;
|
||||
break;
|
||||
case 0xc: // Modifier key: 0xc is alt+c (Other options could be: 0xea = shift+mic button or 0x4 shift+$(speaker))
|
||||
// toggle moddifiers button.
|
||||
is_sym = !is_sym;
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = is_sym ? 0xf1 : 0xf2; // send 0xf1 to tell CannedMessages to display that the modifier key is active
|
||||
e.kbchar = is_sym ? INPUT_BROKER_MSG_FN_SYMBOL_ON // send 0xf1 to tell CannedMessages to display that the
|
||||
: INPUT_BROKER_MSG_FN_SYMBOL_OFF; // modifier key is active
|
||||
break;
|
||||
case 0x90: // fn+r
|
||||
case 0x90: // fn+r INPUT_BROKER_MSG_REBOOT
|
||||
case 0x91: // fn+t
|
||||
case 0x9b: // fn+s
|
||||
case 0xac: // fn+m
|
||||
case 0x9e: // fn+g
|
||||
case 0xaf: // fn+space
|
||||
case 0x9b: // fn+s INPUT_BROKER_MSG_SHUTDOWN
|
||||
case 0xac: // fn+m INPUT_BROKER_MSG_MUTE_TOGGLE
|
||||
case 0x9e: // fn+g INPUT_BROKER_MSG_GPS_TOGGLE
|
||||
case 0xaf: // fn+space INPUT_BROKER_MSG_SEND_PING
|
||||
case 0x8b: // fn+del INPUT_BROKEN_MSG_DISMISS_FRAME
|
||||
case 0xAA: // fn+b INPUT_BROKER_MSG_BLUETOOTH_TOGGLE
|
||||
// just pass those unmodified
|
||||
e.inputEvent = ANYKEY;
|
||||
e.kbchar = c;
|
||||
|
||||
159
src/main.cpp
@@ -1,3 +1,4 @@
|
||||
#include "../userPrefs.h"
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "GPS.h"
|
||||
@@ -11,16 +12,16 @@
|
||||
#include "airtime.h"
|
||||
#include "buzz.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "power.h"
|
||||
// #include "debug.h"
|
||||
#include "FSCommon.h"
|
||||
#include "Led.h"
|
||||
#include "RTC.h"
|
||||
#include "SPILock.h"
|
||||
#include "Throttle.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "error.h"
|
||||
#include "power.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "detect/ScanI2CTwoWire.h"
|
||||
@@ -32,13 +33,13 @@
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "mesh/generated/meshtastic/config.pb.h"
|
||||
#include "meshUtils.h"
|
||||
#include "modules/Modules.h"
|
||||
#include "shutdown.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
// #include <driver/rtc_io.h>
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#if !MESHTASTIC_EXCLUDE_WEBSERVER
|
||||
@@ -72,6 +73,7 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
|
||||
#include "LLCC68Interface.h"
|
||||
#include "LR1110Interface.h"
|
||||
#include "LR1120Interface.h"
|
||||
#include "LR1121Interface.h"
|
||||
#include "RF95Interface.h"
|
||||
#include "SX1262Interface.h"
|
||||
#include "SX1268Interface.h"
|
||||
@@ -102,8 +104,8 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
|
||||
#include "AmbientLightingThread.h"
|
||||
#include "PowerFSMThread.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#include "AccelerometerThread.h"
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "motion/AccelerometerThread.h"
|
||||
AccelerometerThread *accelerometerThread = nullptr;
|
||||
#endif
|
||||
|
||||
@@ -118,6 +120,8 @@ float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; // if TCXO is optional, put this h
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
volatile static const char slipstreamTZString[] = USERPREFS_TZ_STRING;
|
||||
|
||||
// We always create a screen object, but we only init it if we find the hardware
|
||||
graphics::Screen *screen = nullptr;
|
||||
|
||||
@@ -294,6 +298,11 @@ void setup()
|
||||
digitalWrite(VEXT_ENABLE, VEXT_ON_VALUE); // turn on the display power
|
||||
#endif
|
||||
|
||||
#if defined(BIAS_T_ENABLE)
|
||||
pinMode(BIAS_T_ENABLE, OUTPUT);
|
||||
digitalWrite(BIAS_T_ENABLE, BIAS_T_VALUE); // turn on 5V for GPS Antenna
|
||||
#endif
|
||||
|
||||
#if defined(VTFT_CTRL)
|
||||
pinMode(VTFT_CTRL, OUTPUT);
|
||||
digitalWrite(VTFT_CTRL, LOW);
|
||||
@@ -322,15 +331,19 @@ void setup()
|
||||
#ifdef BUTTON_PIN
|
||||
#ifdef ARCH_ESP32
|
||||
|
||||
// If the button is connected to GPIO 12, don't enable the ability to use
|
||||
// meshtasticAdmin on the device.
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT);
|
||||
|
||||
#if ESP_ARDUINO_VERSION_MAJOR >= 3
|
||||
#ifdef BUTTON_NEED_PULLUP
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP);
|
||||
#else
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT); // default to BUTTON_PIN
|
||||
#endif
|
||||
#else
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT); // default to BUTTON_PIN
|
||||
#ifdef BUTTON_NEED_PULLUP
|
||||
gpio_pullup_en((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
|
||||
delay(10);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -360,6 +373,8 @@ void setup()
|
||||
Wire1.begin();
|
||||
#elif defined(I2C_SDA1) && !defined(ARCH_RP2040)
|
||||
Wire1.begin(I2C_SDA1, I2C_SCL1);
|
||||
#elif WIRE_INTERFACES_COUNT == 2
|
||||
Wire1.begin();
|
||||
#endif
|
||||
|
||||
#if defined(I2C_SDA) && defined(ARCH_RP2040)
|
||||
@@ -390,7 +405,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
#ifdef AQ_SET_PIN
|
||||
// RAK-12039 set pin for Air quality sensor
|
||||
// RAK-12039 set pin for Air quality sensor. Detectable on I2C after ~3 seconds, so we need to rescan later
|
||||
pinMode(AQ_SET_PIN, OUTPUT);
|
||||
digitalWrite(AQ_SET_PIN, HIGH);
|
||||
#endif
|
||||
@@ -427,6 +442,8 @@ void setup()
|
||||
#elif defined(I2C_SDA1) && !defined(ARCH_RP2040)
|
||||
Wire1.begin(I2C_SDA1, I2C_SCL1);
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
|
||||
#elif defined(NRF52840_XXAA) && (WIRE_INTERFACES_COUNT == 2)
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
|
||||
#endif
|
||||
|
||||
#if defined(I2C_SDA) && defined(ARCH_RP2040)
|
||||
@@ -526,6 +543,21 @@ void setup()
|
||||
rgb_found = i2cScanner->find(ScanI2C::DeviceType::NCP5623);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TPS65233
|
||||
// TPS65233 is a power management IC for satellite modems, used in the Dreamcatcher
|
||||
// We are switching it off here since we don't use an LNB.
|
||||
if (i2cScanner->exists(ScanI2C::DeviceType::TPS65233)) {
|
||||
Wire.beginTransmission(TPS65233_ADDR);
|
||||
Wire.write(0); // Register 0
|
||||
Wire.write(128); // Turn off the LNB power, keep I2C Control enabled
|
||||
Wire.endTransmission();
|
||||
Wire.beginTransmission(TPS65233_ADDR);
|
||||
Wire.write(1); // Register 1
|
||||
Wire.write(0); // Turn off Tone Generator 22kHz
|
||||
Wire.endTransmission();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
auto acc_info = i2cScanner->firstAccelerometer();
|
||||
accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found;
|
||||
@@ -552,6 +584,7 @@ void setup()
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31)
|
||||
@@ -560,15 +593,19 @@ void setup()
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC6310, meshtastic_TelemetrySensorType_QMC6310)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::OPT3001, meshtastic_TelemetrySensorType_OPT3001)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102)
|
||||
|
||||
i2cScanner.reset();
|
||||
#endif
|
||||
@@ -586,6 +623,9 @@ void setup()
|
||||
|
||||
// Hello
|
||||
printInfo();
|
||||
#ifdef BUILD_EPOCH
|
||||
LOG_INFO("Build timestamp: %ld\n", BUILD_EPOCH);
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
esp32Setup();
|
||||
@@ -617,6 +657,12 @@ void setup()
|
||||
buttonThread = new ButtonThread();
|
||||
#endif
|
||||
|
||||
// only play start melody when role is not tracker or sensor
|
||||
if (config.power.is_power_saving == true &&
|
||||
IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER,
|
||||
meshtastic_Config_DeviceConfig_Role_TAK_TRACKER, meshtastic_Config_DeviceConfig_Role_SENSOR))
|
||||
LOG_DEBUG("Tracker/Sensor: Skipping start melody\n");
|
||||
else
|
||||
playStartMelody();
|
||||
|
||||
// fixed screen override?
|
||||
@@ -633,10 +679,8 @@ void setup()
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
if (acc_info.type != ScanI2C::DeviceType::NONE) {
|
||||
config.display.wake_on_tap_or_motion = true;
|
||||
moduleConfig.external_notification.enabled = true;
|
||||
accelerometerThread = new AccelerometerThread(acc_info.type);
|
||||
}
|
||||
#endif
|
||||
@@ -687,10 +731,17 @@ void setup()
|
||||
|
||||
// setup TZ prior to time actions.
|
||||
#if !MESHTASTIC_EXCLUDE_TZ
|
||||
if (*config.device.tzdef) {
|
||||
LOG_DEBUG("Using compiled/slipstreamed %s\n", slipstreamTZString); // important, removing this clobbers our magic string
|
||||
if (*config.device.tzdef && config.device.tzdef[0] != 0) {
|
||||
LOG_DEBUG("Saved TZ: %s \n", config.device.tzdef);
|
||||
setenv("TZ", config.device.tzdef, 1);
|
||||
} else {
|
||||
if (strncmp((const char *)slipstreamTZString, "tzpl", 4) == 0) {
|
||||
setenv("TZ", "GMT0", 1);
|
||||
} else {
|
||||
setenv("TZ", (const char *)slipstreamTZString, 1);
|
||||
strcpy(config.device.tzdef, (const char *)slipstreamTZString);
|
||||
}
|
||||
}
|
||||
tzset();
|
||||
LOG_DEBUG("Set Timezone to %s\n", getenv("TZ"));
|
||||
@@ -747,8 +798,8 @@ void setup()
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
// Don't call screen setup until after nodedb is setup (because we need
|
||||
// the current region name)
|
||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(HX8357_CS) || \
|
||||
defined(USE_ST7789)
|
||||
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
|
||||
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789)
|
||||
screen->setup();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
|
||||
@@ -762,12 +813,6 @@ void setup()
|
||||
|
||||
screen->print("Started...\n");
|
||||
|
||||
#ifdef SX126X_ANT_SW
|
||||
// make analog PA vs not PA switch on SX126x eval board work properly
|
||||
pinMode(SX126X_ANT_SW, OUTPUT);
|
||||
digitalWrite(SX126X_ANT_SW, 1);
|
||||
#endif
|
||||
|
||||
#ifdef PIN_PWR_DELAY_MS
|
||||
// This may be required to give the peripherals time to power up.
|
||||
delay(PIN_PWR_DELAY_MS);
|
||||
@@ -872,8 +917,8 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RF95_IRQ)
|
||||
if (!rIf) {
|
||||
#if defined(RF95_IRQ) && RADIOLIB_EXCLUDE_SX127X != 1
|
||||
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
||||
rIf = new RF95Interface(RadioLibHAL, LORA_CS, RF95_IRQ, RF95_RESET, RF95_DIO1);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find RF95 radio\n");
|
||||
@@ -886,8 +931,8 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && !defined(TCXO_OPTIONAL)
|
||||
if (!rIf) {
|
||||
#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && !defined(TCXO_OPTIONAL) && RADIOLIB_EXCLUDE_SX126X != 1
|
||||
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
||||
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find SX1262 radio\n");
|
||||
@@ -901,7 +946,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1262) && !defined(ARCH_PORTDUINO) && defined(TCXO_OPTIONAL)
|
||||
if (!rIf) {
|
||||
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
||||
// Try using the specified TCXO voltage
|
||||
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
@@ -917,7 +962,7 @@ void setup()
|
||||
}
|
||||
}
|
||||
|
||||
if (!rIf) {
|
||||
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
||||
// If specified TCXO voltage fails, attempt to use DIO3 as a reference instea
|
||||
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
@@ -935,7 +980,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1268)
|
||||
if (!rIf) {
|
||||
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
||||
rIf = new SX1268Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find SX1268 radio\n");
|
||||
@@ -949,7 +994,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
#if defined(USE_LLCC68)
|
||||
if (!rIf) {
|
||||
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
||||
rIf = new LLCC68Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find LLCC68 radio\n");
|
||||
@@ -962,33 +1007,49 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_LR1110)
|
||||
if (!rIf) {
|
||||
rIf = new LR1110Interface(RadioLibHAL, LR1110_SPI_NSS_PIN, LR1110_IRQ_PIN, LR1110_NRESER_PIN, LR1110_BUSY_PIN);
|
||||
#if defined(USE_LR1110) && RADIOLIB_EXCLUDE_LR11X0 != 1
|
||||
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
|
||||
rIf = new LR1110Interface(RadioLibHAL, LR1110_SPI_NSS_PIN, LR1110_IRQ_PIN, LR1110_NRESET_PIN, LR1110_BUSY_PIN);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find LR1110 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
LOG_INFO("LR1110 Radio init succeeded, using LR1110 radio\n");
|
||||
radioType = LR1110_RADIO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_LR1120)
|
||||
#if defined(USE_LR1120) && RADIOLIB_EXCLUDE_LR11X0 != 1
|
||||
if (!rIf) {
|
||||
rIf = new LR1120Interface(RadioLibHAL, LR1120_SPI_NSS_PIN, LR1120_IRQ_PIN, LR1120_NRESER_PIN, LR1120_BUSY_PIN);
|
||||
rIf = new LR1120Interface(RadioLibHAL, LR1120_SPI_NSS_PIN, LR1120_IRQ_PIN, LR1120_NRESET_PIN, LR1120_BUSY_PIN);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find LR1120 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
LOG_INFO("LR1120 Radio init succeeded, using LR1120 radio\n");
|
||||
radioType = LR1120_RADIO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1280)
|
||||
#if defined(USE_LR1121) && RADIOLIB_EXCLUDE_LR11X0 != 1
|
||||
if (!rIf) {
|
||||
rIf = new LR1121Interface(RadioLibHAL, LR1121_SPI_NSS_PIN, LR1121_IRQ_PIN, LR1121_NRESET_PIN, LR1121_BUSY_PIN);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find LR1121 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
LOG_INFO("LR1121 Radio init succeeded, using LR1121 radio\n");
|
||||
radioType = LR1121_RADIO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1280) && RADIOLIB_EXCLUDE_SX128X != 1
|
||||
if (!rIf) {
|
||||
rIf = new SX1280Interface(RadioLibHAL, SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
@@ -1003,7 +1064,6 @@ void setup()
|
||||
#endif
|
||||
|
||||
// check if the radio chip matches the selected region
|
||||
|
||||
if ((config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (!rIf->wideLora())) {
|
||||
LOG_WARN("Radio chip does not support 2.4GHz LoRa. Reverting to unset.\n");
|
||||
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
|
||||
@@ -1095,6 +1155,9 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
|
||||
deviceMetadata.position_flags = config.position.position_flags;
|
||||
deviceMetadata.hw_model = HW_VENDOR;
|
||||
deviceMetadata.hasRemoteHardware = moduleConfig.remote_hardware.enabled;
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||
deviceMetadata.hasPKC = true;
|
||||
#endif
|
||||
return deviceMetadata;
|
||||
}
|
||||
#ifndef PIO_UNIT_TESTING
|
||||
@@ -1102,10 +1165,6 @@ void loop()
|
||||
{
|
||||
runASAP = false;
|
||||
|
||||
// axpDebugOutput.loop();
|
||||
|
||||
// heap_caps_check_integrity_all(true); // FIXME - disable this expensive check
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
esp32Loop();
|
||||
#endif
|
||||
@@ -1114,33 +1173,21 @@ void loop()
|
||||
#endif
|
||||
powerCommandsCheck();
|
||||
|
||||
// For debugging
|
||||
// if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving();
|
||||
|
||||
#ifdef DEBUG_STACK
|
||||
static uint32_t lastPrint = 0;
|
||||
if (millis() - lastPrint > 10 * 1000L) {
|
||||
if (!Throttle::isWithinTimespanMs(lastPrint, 10 * 1000L)) {
|
||||
lastPrint = millis();
|
||||
meshtastic::printThreadInfo("main");
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: This should go into a thread handled by FreeRTOS.
|
||||
// handleWebResponse();
|
||||
|
||||
service->loop();
|
||||
|
||||
long delayMsec = mainController.runOrDelay();
|
||||
|
||||
/* if (mainController.nextThread && delayMsec)
|
||||
LOG_DEBUG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
|
||||
mainController.nextThread->tillRun(millis())); */
|
||||
|
||||
// We want to sleep as long as possible here - because it saves power
|
||||
if (!runASAP && loopCanSleep()) {
|
||||
// if(delayMsec > 100) LOG_DEBUG("sleeping %ld\n", delayMsec);
|
||||
mainDelay.delay(delayMsec);
|
||||
}
|
||||
// if (didWake) LOG_DEBUG("wake!\n");
|
||||
}
|
||||
#endif
|
||||
@@ -56,8 +56,8 @@ extern AudioThread *audioThread;
|
||||
// Global Screen singleton.
|
||||
extern graphics::Screen *screen;
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
#include "AccelerometerThread.h"
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
|
||||
#include "motion/AccelerometerThread.h"
|
||||
extern AccelerometerThread *accelerometerThread;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ uint32_t MemGet::getFreePsram()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
return ESP.getFreePsram();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
return 4194252;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
@@ -71,6 +73,8 @@ uint32_t MemGet::getPsramSize()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
return ESP.getPsramSize();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
return 4194252;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128)
|
||||
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
|
||||
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01};
|
||||
|
||||
Channels channels;
|
||||
|
||||
const char *Channels::adminChannel = "admin";
|
||||
@@ -80,6 +76,23 @@ meshtastic_Channel &Channels::fixupChannel(ChannelIndex chIndex)
|
||||
return ch;
|
||||
}
|
||||
|
||||
void Channels::initDefaultLoraConfig()
|
||||
{
|
||||
meshtastic_Config_LoRaConfig &loraConfig = config.lora;
|
||||
|
||||
loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; // Default to Long Range & Fast
|
||||
loraConfig.use_preset = true;
|
||||
loraConfig.tx_power = 0; // default
|
||||
loraConfig.channel_num = 0;
|
||||
|
||||
#ifdef USERPREFS_LORACONFIG_MODEM_PRESET
|
||||
loraConfig.modem_preset = USERPREFS_LORACONFIG_MODEM_PRESET;
|
||||
#endif
|
||||
#ifdef USERPREFS_LORACONFIG_CHANNEL_NUM
|
||||
loraConfig.channel_num = USERPREFS_LORACONFIG_CHANNEL_NUM;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a default channel to the specified channel index
|
||||
*/
|
||||
@@ -87,12 +100,7 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
||||
{
|
||||
meshtastic_Channel &ch = getByIndex(chIndex);
|
||||
meshtastic_ChannelSettings &channelSettings = ch.settings;
|
||||
meshtastic_Config_LoRaConfig &loraConfig = config.lora;
|
||||
|
||||
loraConfig.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST; // Default to Long Range & Fast
|
||||
loraConfig.use_preset = true;
|
||||
loraConfig.tx_power = 0; // default
|
||||
loraConfig.channel_num = 0;
|
||||
uint8_t defaultpskIndex = 1;
|
||||
channelSettings.psk.bytes[0] = defaultpskIndex;
|
||||
channelSettings.psk.size = 1;
|
||||
@@ -101,29 +109,53 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
||||
channelSettings.has_module_settings = true;
|
||||
|
||||
ch.has_settings = true;
|
||||
ch.role = meshtastic_Channel_Role_PRIMARY;
|
||||
ch.role = chIndex == 0 ? meshtastic_Channel_Role_PRIMARY : meshtastic_Channel_Role_SECONDARY;
|
||||
|
||||
#ifdef LORACONFIG_MODEM_PRESET_USERPREFS
|
||||
loraConfig.modem_preset = LORACONFIG_MODEM_PRESET_USERPREFS;
|
||||
#endif
|
||||
#ifdef LORACONFIG_CHANNEL_NUM_USERPREFS
|
||||
loraConfig.channel_num = LORACONFIG_CHANNEL_NUM_USERPREFS;
|
||||
#endif
|
||||
|
||||
// Install custom defaults. Will eventually support setting multiple default channels
|
||||
if (chIndex == 0) {
|
||||
#ifdef CHANNEL_0_PSK_USERPREFS
|
||||
static const uint8_t defaultpsk[] = CHANNEL_0_PSK_USERPREFS;
|
||||
memcpy(channelSettings.psk.bytes, defaultpsk, sizeof(defaultpsk));
|
||||
channelSettings.psk.size = sizeof(defaultpsk);
|
||||
switch (chIndex) {
|
||||
case 0:
|
||||
#ifdef USERPREFS_CHANNEL_0_PSK
|
||||
static const uint8_t defaultpsk0[] = USERPREFS_CHANNEL_0_PSK;
|
||||
memcpy(channelSettings.psk.bytes, defaultpsk0, sizeof(defaultpsk0));
|
||||
channelSettings.psk.size = sizeof(defaultpsk0);
|
||||
|
||||
#endif
|
||||
#ifdef CHANNEL_0_NAME_USERPREFS
|
||||
strcpy(channelSettings.name, CHANNEL_0_NAME_USERPREFS);
|
||||
#ifdef USERPREFS_CHANNEL_0_NAME
|
||||
strcpy(channelSettings.name, USERPREFS_CHANNEL_0_NAME);
|
||||
#endif
|
||||
#ifdef CHANNEL_0_PRECISION_USERPREFS
|
||||
channelSettings.module_settings.position_precision = CHANNEL_0_PRECISION_USERPREFS;
|
||||
#ifdef USERPREFS_CHANNEL_0_PRECISION
|
||||
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_0_PRECISION;
|
||||
#endif
|
||||
break;
|
||||
case 1:
|
||||
#ifdef USERPREFS_CHANNEL_1_PSK
|
||||
static const uint8_t defaultpsk1[] = USERPREFS_CHANNEL_1_PSK;
|
||||
memcpy(channelSettings.psk.bytes, defaultpsk1, sizeof(defaultpsk1));
|
||||
channelSettings.psk.size = sizeof(defaultpsk1);
|
||||
|
||||
#endif
|
||||
#ifdef USERPREFS_CHANNEL_1_NAME
|
||||
strcpy(channelSettings.name, USERPREFS_CHANNEL_1_NAME);
|
||||
#endif
|
||||
#ifdef USERPREFS_CHANNEL_1_PRECISION
|
||||
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_1_PRECISION;
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
#ifdef USERPREFS_CHANNEL_2_PSK
|
||||
static const uint8_t defaultpsk2[] = USERPREFS_CHANNEL_2_PSK;
|
||||
memcpy(channelSettings.psk.bytes, defaultpsk2, sizeof(defaultpsk2));
|
||||
channelSettings.psk.size = sizeof(defaultpsk2);
|
||||
|
||||
#endif
|
||||
#ifdef USERPREFS_CHANNEL_2_NAME
|
||||
strcpy(channelSettings.name, USERPREFS_CHANNEL_2_NAME);
|
||||
#endif
|
||||
#ifdef USERPREFS_CHANNEL_2_PRECISION
|
||||
channelSettings.module_settings.position_precision = USERPREFS_CHANNEL_2_PRECISION;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +245,15 @@ void Channels::initDefaults()
|
||||
channelFile.channels_count = MAX_NUM_CHANNELS;
|
||||
for (int i = 0; i < channelFile.channels_count; i++)
|
||||
fixupChannel(i);
|
||||
initDefaultLoraConfig();
|
||||
|
||||
#ifdef USERPREFS_CHANNELS_TO_WRITE
|
||||
for (int i = 0; i < USERPREFS_CHANNELS_TO_WRITE; i++) {
|
||||
initDefaultChannel(i);
|
||||
}
|
||||
#else
|
||||
initDefaultChannel(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Channels::onConfigChanged()
|
||||
@@ -277,7 +317,7 @@ void Channels::setChannel(const meshtastic_Channel &c)
|
||||
|
||||
bool Channels::anyMqttEnabled()
|
||||
{
|
||||
#if EVENT_MODE
|
||||
#if USERPREFS_EVENT_MODE
|
||||
// Don't publish messages on the public MQTT broker if we are in event mode
|
||||
if (strcmp(moduleConfig.mqtt.address, default_mqtt_address) == 0) {
|
||||
return false;
|
||||
|
||||
@@ -117,7 +117,12 @@ class Channels
|
||||
meshtastic_Channel &fixupChannel(ChannelIndex chIndex);
|
||||
|
||||
/**
|
||||
* Write a default channel to the specified channel index
|
||||
* Writes the default lora config
|
||||
*/
|
||||
void initDefaultLoraConfig();
|
||||
|
||||
/**
|
||||
* Write default channels defined in UserPrefs
|
||||
*/
|
||||
void initDefaultChannel(ChannelIndex chIndex);
|
||||
|
||||
@@ -130,3 +135,11 @@ class Channels
|
||||
|
||||
/// Singleton channel table
|
||||
extern Channels channels;
|
||||
|
||||
/// 16 bytes of random PSK for our _public_ default channel that all devices power up on (AES128)
|
||||
static const uint8_t defaultpsk[] = {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
|
||||
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01};
|
||||
|
||||
static const uint8_t eventpsk[] = {0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36,
|
||||
0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74,
|
||||
0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa1};
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "CryptoEngine.h"
|
||||
#include "NodeDB.h"
|
||||
#include "RadioInterface.h"
|
||||
// #include "NodeDB.h"
|
||||
#include "architecture.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||
#include "aes-ccm.h"
|
||||
@@ -62,32 +60,32 @@ void CryptoEngine::clearKeys()
|
||||
*
|
||||
* @param bytes is updated in place
|
||||
*/
|
||||
bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes,
|
||||
uint8_t *bytesOut)
|
||||
bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, meshtastic_UserLite_public_key_t remotePublic,
|
||||
uint64_t packetNum, size_t numBytes, uint8_t *bytes, uint8_t *bytesOut)
|
||||
{
|
||||
uint8_t *auth;
|
||||
uint32_t *extraNonce;
|
||||
long extraNonceTmp = random();
|
||||
auth = bytesOut + numBytes;
|
||||
extraNonce = (uint32_t *)(auth + 8);
|
||||
*extraNonce = extraNonceTmp;
|
||||
LOG_INFO("Random nonce value: %d\n", *extraNonce);
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(toNode);
|
||||
if (node->num < 1 || node->user.public_key.size == 0) {
|
||||
memcpy((uint8_t *)(auth + 8), &extraNonceTmp,
|
||||
sizeof(uint32_t)); // do not use dereference on potential non aligned pointers : *extraNonce = extraNonceTmp;
|
||||
LOG_INFO("Random nonce value: %d\n", extraNonceTmp);
|
||||
if (remotePublic.size == 0) {
|
||||
LOG_DEBUG("Node %d or their public_key not found\n", toNode);
|
||||
return false;
|
||||
}
|
||||
if (!crypto->setDHKey(toNode)) {
|
||||
if (!crypto->setDHPublicKey(remotePublic.bytes)) {
|
||||
return false;
|
||||
}
|
||||
initNonce(fromNode, packetNum, *extraNonce);
|
||||
crypto->hash(shared_key, 32);
|
||||
initNonce(fromNode, packetNum, extraNonceTmp);
|
||||
|
||||
// Calculate the shared secret with the destination node and encrypt
|
||||
printBytes("Attempting encrypt using nonce: ", nonce, 13);
|
||||
printBytes("Attempting encrypt using shared_key: ", shared_key, 32);
|
||||
printBytes("Attempting encrypt using shared_key starting with: ", shared_key, 8);
|
||||
aes_ccm_ae(shared_key, 32, nonce, 8, bytes, numBytes, nullptr, 0, bytesOut,
|
||||
auth); // this can write up to 15 bytes longer than numbytes past bytesOut
|
||||
*extraNonce = extraNonceTmp;
|
||||
memcpy((uint8_t *)(auth + 8), &extraNonceTmp,
|
||||
sizeof(uint32_t)); // do not use dereference on potential non aligned pointers : *extraNonce = extraNonceTmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -97,27 +95,30 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_
|
||||
*
|
||||
* @param bytes is updated in place
|
||||
*/
|
||||
bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes, uint8_t *bytesOut)
|
||||
bool CryptoEngine::decryptCurve25519(uint32_t fromNode, meshtastic_UserLite_public_key_t remotePublic, uint64_t packetNum,
|
||||
size_t numBytes, uint8_t *bytes, uint8_t *bytesOut)
|
||||
{
|
||||
uint8_t *auth; // set to last 8 bytes of text?
|
||||
uint32_t *extraNonce;
|
||||
uint32_t extraNonce; // pointer was not really used
|
||||
auth = bytes + numBytes - 12;
|
||||
extraNonce = (uint32_t *)(auth + 8);
|
||||
LOG_INFO("Random nonce value: %d\n", *extraNonce);
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(fromNode);
|
||||
memcpy(&extraNonce, auth + 8,
|
||||
sizeof(uint32_t)); // do not use dereference on potential non aligned pointers : (uint32_t *)(auth + 8);
|
||||
LOG_INFO("Random nonce value: %d\n", extraNonce);
|
||||
|
||||
if (node == nullptr || node->num < 1 || node->user.public_key.size == 0) {
|
||||
if (remotePublic.size == 0) {
|
||||
LOG_DEBUG("Node or its public key not found in database\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate the shared secret with the sending node and decrypt
|
||||
if (!crypto->setDHKey(fromNode)) {
|
||||
if (!crypto->setDHPublicKey(remotePublic.bytes)) {
|
||||
return false;
|
||||
}
|
||||
initNonce(fromNode, packetNum, *extraNonce);
|
||||
crypto->hash(shared_key, 32);
|
||||
|
||||
initNonce(fromNode, packetNum, extraNonce);
|
||||
printBytes("Attempting decrypt using nonce: ", nonce, 13);
|
||||
printBytes("Attempting decrypt using shared_key: ", shared_key, 32);
|
||||
printBytes("Attempting decrypt using shared_key starting with: ", shared_key, 8);
|
||||
return aes_ccm_ad(shared_key, 32, nonce, 8, bytes, numBytes - 12, nullptr, 0, auth, bytesOut);
|
||||
}
|
||||
|
||||
@@ -125,37 +126,6 @@ void CryptoEngine::setDHPrivateKey(uint8_t *_private_key)
|
||||
{
|
||||
memcpy(private_key, _private_key, 32);
|
||||
}
|
||||
/**
|
||||
* Set the PKI key used for encrypt, decrypt.
|
||||
*
|
||||
* @param nodeNum the node number of the node who's public key we want to use
|
||||
*/
|
||||
bool CryptoEngine::setDHKey(uint32_t nodeNum)
|
||||
{
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeNum);
|
||||
if (node->num < 1 || node->user.public_key.size == 0) {
|
||||
LOG_DEBUG("Node %d or their public_key not found\n", nodeNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!setDHPublicKey(node->user.public_key.bytes))
|
||||
return false;
|
||||
|
||||
printBytes("DH Output: ", shared_key, 32);
|
||||
|
||||
/**
|
||||
* D.J. Bernstein reccomends hashing the shared key. We want to do this because there are
|
||||
* at least 128 bits of entropy in the 256-bit output of the DH key exchange, but we don't
|
||||
* really know where. If you extract, for instance, the first 128 bits with basic truncation,
|
||||
* then you don't know if you got all of your 128 entropy bits, or less, possibly much less.
|
||||
*
|
||||
* No exploitable bias is really known at that point, but we know enough to be wary.
|
||||
* Hashing the DH output is a simple and safe way to gather all the entropy and spread
|
||||
* it around as needed.
|
||||
*/
|
||||
crypto->hash(shared_key, 32);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash arbitrary data using SHA256.
|
||||
@@ -166,12 +136,12 @@ bool CryptoEngine::setDHKey(uint32_t nodeNum)
|
||||
void CryptoEngine::hash(uint8_t *bytes, size_t numBytes)
|
||||
{
|
||||
SHA256 hash;
|
||||
size_t posn, len;
|
||||
size_t posn;
|
||||
uint8_t size = numBytes;
|
||||
uint8_t inc = 16;
|
||||
hash.reset();
|
||||
for (posn = 0; posn < size; posn += inc) {
|
||||
len = size - posn;
|
||||
size_t len = size - posn;
|
||||
if (len > inc)
|
||||
len = inc;
|
||||
hash.update(bytes + posn, len);
|
||||
|
||||