mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-15 23:32:34 +00:00
Compare commits
227 Commits
v2.1.0.331
...
v2.1.12.77
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7711b03bd8 | ||
|
|
c52fddac53 | ||
|
|
b0c3816a8b | ||
|
|
6cdf2817f4 | ||
|
|
f7e1f4cea6 | ||
|
|
75504793e8 | ||
|
|
4029f731c9 | ||
|
|
666a1f3401 | ||
|
|
70dc13a998 | ||
|
|
9841d49fb8 | ||
|
|
28ec4e35ec | ||
|
|
55cef30f93 | ||
|
|
0e15d6a5c2 | ||
|
|
29199e4732 | ||
|
|
6fc061fa43 | ||
|
|
c14b075996 | ||
|
|
6963e43e9f | ||
|
|
1d90096cba | ||
|
|
c1a1b450e3 | ||
|
|
f7041994af | ||
|
|
5037a50059 | ||
|
|
2e915e782b | ||
|
|
e761631d5e | ||
|
|
19a310e196 | ||
|
|
5ec624d9c3 | ||
|
|
b4ff37104a | ||
|
|
81bfd69a41 | ||
|
|
57aaf7f6ee | ||
|
|
9b6ac98ae0 | ||
|
|
e1c4968c58 | ||
|
|
694fd04367 | ||
|
|
cdc8bf44e9 | ||
|
|
09d48f659e | ||
|
|
46e29402a6 | ||
|
|
10f41e376c | ||
|
|
39aa756100 | ||
|
|
17e25babb1 | ||
|
|
7c9d0a022a | ||
|
|
313860c8a4 | ||
|
|
e360c62480 | ||
|
|
973b30fc0b | ||
|
|
a6385a522d | ||
|
|
6aa9e37872 | ||
|
|
5afa92395d | ||
|
|
b6ff80f0b7 | ||
|
|
7ef12c77a8 | ||
|
|
a27d354364 | ||
|
|
6e26f95df9 | ||
|
|
5dfb5172c2 | ||
|
|
e0bb95ca94 | ||
|
|
1621fbb5ab | ||
|
|
ac40f77694 | ||
|
|
9700fa55a3 | ||
|
|
87c59d7d61 | ||
|
|
584615bb4b | ||
|
|
c452c2ab40 | ||
|
|
d43ddc9ec2 | ||
|
|
a76cb94851 | ||
|
|
da75ae21ff | ||
|
|
a30c07e6b4 | ||
|
|
309d4fc7f2 | ||
|
|
a13775bd70 | ||
|
|
b43a5bc4f8 | ||
|
|
ec44ca49fd | ||
|
|
5d41e9fe9d | ||
|
|
7bd836673e | ||
|
|
e0da661632 | ||
|
|
a9ce4338ff | ||
|
|
a284439d7e | ||
|
|
10fac072bb | ||
|
|
d60ccb42da | ||
|
|
3598351689 | ||
|
|
74ed166ff0 | ||
|
|
0afeba0c86 | ||
|
|
ee971e376a | ||
|
|
eeeb7c5080 | ||
|
|
f526c4cc5a | ||
|
|
a9eb19fc62 | ||
|
|
29c13b5c30 | ||
|
|
f0c4c18a79 | ||
|
|
320bf57687 | ||
|
|
4b89f7dfcb | ||
|
|
43cff7adc9 | ||
|
|
d4e42898b1 | ||
|
|
82ab38d3e6 | ||
|
|
aa96ea02c6 | ||
|
|
242f880764 | ||
|
|
de08360271 | ||
|
|
990d418dc8 | ||
|
|
f8db02c622 | ||
|
|
fc8d16bb08 | ||
|
|
af65013e49 | ||
|
|
b1937e03ac | ||
|
|
23e6bc32c0 | ||
|
|
bd1e747fc9 | ||
|
|
3c0817340a | ||
|
|
9a42861766 | ||
|
|
038ff0f6cb | ||
|
|
918b509be8 | ||
|
|
9239698004 | ||
|
|
71479a6b17 | ||
|
|
b4bcae98cd | ||
|
|
294771cb44 | ||
|
|
1398611276 | ||
|
|
fbc3b2beee | ||
|
|
6bf538e26f | ||
|
|
713b5fbe96 | ||
|
|
ed96321406 | ||
|
|
39d8ae64e7 | ||
|
|
3f07251d23 | ||
|
|
657f22d058 | ||
|
|
bf1fbc6c0d | ||
|
|
5679a82195 | ||
|
|
2edc35d34b | ||
|
|
26d18244f0 | ||
|
|
82ba59765c | ||
|
|
7930aa1635 | ||
|
|
c55751964e | ||
|
|
b9b1cce6a5 | ||
|
|
044ef75fef | ||
|
|
9f940139a0 | ||
|
|
fdb09d4fba | ||
|
|
1968f3c45b | ||
|
|
790df42987 | ||
|
|
9a9279dd78 | ||
|
|
1e54a5d45c | ||
|
|
23272daffe | ||
|
|
6e685b0a54 | ||
|
|
1af7e48136 | ||
|
|
eda00b7b9c | ||
|
|
1898fe850e | ||
|
|
15dbe5da97 | ||
|
|
8f736c8ecc | ||
|
|
8a81f190b8 | ||
|
|
1425657a3c | ||
|
|
02041cb605 | ||
|
|
1f130d671b | ||
|
|
d62e56f428 | ||
|
|
5ac24bb33b | ||
|
|
2c259b8464 | ||
|
|
9d6e1ce8e5 | ||
|
|
958d2cf630 | ||
|
|
5cb1f96240 | ||
|
|
78522e750c | ||
|
|
75db8c2d2e | ||
|
|
91be22b341 | ||
|
|
cc64c3d61a | ||
|
|
36b00dba86 | ||
|
|
3bb8cd7613 | ||
|
|
8c68d888c8 | ||
|
|
1f99d4756a | ||
|
|
7bbfa48b5d | ||
|
|
b398f31b64 | ||
|
|
e03a2f8f7f | ||
|
|
d92a003d8e | ||
|
|
8db7316ae1 | ||
|
|
3c2e615650 | ||
|
|
6d202158ba | ||
|
|
c288974b67 | ||
|
|
9b1d461567 | ||
|
|
210e3e09d5 | ||
|
|
0d001423c8 | ||
|
|
a83d5ada86 | ||
|
|
4573db4665 | ||
|
|
d2c72fae00 | ||
|
|
c9686d2f62 | ||
|
|
634251834f | ||
|
|
6d443d2c67 | ||
|
|
9cadc0a16f | ||
|
|
2e3b86608a | ||
|
|
dc2ca9c32b | ||
|
|
e0a6a37bef | ||
|
|
57fc9baafc | ||
|
|
033e988e6f | ||
|
|
fddc49273e | ||
|
|
e737a22120 | ||
|
|
a8f2e3ddbd | ||
|
|
67be6aa53b | ||
|
|
68e17ab905 | ||
|
|
a56403987b | ||
|
|
7acacb3bba | ||
|
|
e6d69e2b67 | ||
|
|
9150c2e568 | ||
|
|
944d5066e9 | ||
|
|
a538a96c90 | ||
|
|
31ef82557f | ||
|
|
9d440b7dba | ||
|
|
267db05d69 | ||
|
|
20bcf310d1 | ||
|
|
a95b6aff01 | ||
|
|
b249970a12 | ||
|
|
fe926eedba | ||
|
|
4355f51a90 | ||
|
|
ecd67f0a85 | ||
|
|
0940c6462b | ||
|
|
a47364f07b | ||
|
|
a3f1e53017 | ||
|
|
0243922d64 | ||
|
|
baeb2807a4 | ||
|
|
9a8bfa113d | ||
|
|
82b14fe07c | ||
|
|
48a407bf5c | ||
|
|
2475debb2a | ||
|
|
568899031d | ||
|
|
f1c457f0c3 | ||
|
|
c8399b7256 | ||
|
|
63005a94fd | ||
|
|
9b4a59f92d | ||
|
|
2472d0947f | ||
|
|
a92b2ec6ca | ||
|
|
548bec026a | ||
|
|
ce882b389a | ||
|
|
25fd9d2d1d | ||
|
|
83a201fe86 | ||
|
|
462ee3d921 | ||
|
|
0104246067 | ||
|
|
3f5c0cb6ac | ||
|
|
fa371bc844 | ||
|
|
090f42f51f | ||
|
|
c2ff6f2f7c | ||
|
|
181832aedd | ||
|
|
4967a16abe | ||
|
|
e2f5e9206d | ||
|
|
57b8e3732e | ||
|
|
f0d27f896a | ||
|
|
e74b180655 | ||
|
|
88a44eede0 |
2
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
2
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -32,6 +32,7 @@ body:
|
||||
options:
|
||||
- Not Applicable
|
||||
- T-Beam
|
||||
- T-Beam S3
|
||||
- T-Beam 0.7
|
||||
- T-Lora v1
|
||||
- T-Lora v1.3
|
||||
@@ -42,6 +43,7 @@ body:
|
||||
- Heltec v1
|
||||
- Heltec v2
|
||||
- Heltec v2.1
|
||||
- Heltec V3
|
||||
- Relay v1
|
||||
- Relay v2
|
||||
- DIY
|
||||
|
||||
59
.github/workflows/build_esp32_s3.yml
vendored
Normal file
59
.github/workflows/build_esp32_s3.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: Build ESP32-S3
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build-esp32-s3:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- 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
|
||||
- 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@v3
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
36
.github/workflows/main_matrix.yml
vendored
36
.github/workflows/main_matrix.yml
vendored
@@ -23,9 +23,9 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- board: rak11200
|
||||
- board: tlora-v2-1-1.6
|
||||
- board: tlora-v2-1-1_6
|
||||
- board: tbeam
|
||||
- board: heltec-v2.1
|
||||
- board: heltec-v2_1
|
||||
- board: meshtastic-diy-v1
|
||||
- board: rak4631
|
||||
- board: t-echo
|
||||
@@ -42,6 +42,7 @@ jobs:
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Trunk Check
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
uses: trunk-io/trunk-action@v1
|
||||
|
||||
- name: Check ${{ matrix.board }}
|
||||
@@ -56,28 +57,37 @@ jobs:
|
||||
- board: tlora-v2
|
||||
- board: tlora-v1
|
||||
- board: tlora_v1_3
|
||||
- board: tlora-v2-1-1.6
|
||||
- board: tlora-v2-1-1.8
|
||||
- board: tlora-v2-1-1_6
|
||||
- board: tlora-v2-1-1_8
|
||||
- board: tbeam
|
||||
- board: heltec-v1
|
||||
- board: heltec-v2.0
|
||||
- board: heltec-v2.1
|
||||
- board: heltec-v3
|
||||
- board: heltec-wsl-v3
|
||||
- board: tbeam0.7
|
||||
- board: heltec-v2_0
|
||||
- board: heltec-v2_1
|
||||
- board: tbeam0_7
|
||||
- board: meshtastic-diy-v1
|
||||
- board: meshtastic-dr-dev
|
||||
- board: nano-g1
|
||||
- board: station-g1
|
||||
- board: m5stack-core
|
||||
- board: m5stack-coreink
|
||||
- board: tbeam-s3-core
|
||||
- board: tlora-t3s3-v1
|
||||
- board: nano-g1-explorer
|
||||
uses: ./.github/workflows/build_esp32.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-esp32-s3:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- board: heltec-v3
|
||||
- board: heltec-wsl-v3
|
||||
- board: tbeam-s3-core
|
||||
- board: tlora-t3s3-v1
|
||||
uses: ./.github/workflows/build_esp32_s3.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-nrf52:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -176,7 +186,7 @@ jobs:
|
||||
|
||||
gather-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-esp32, build-nrf52, build-native] #, build-rpi2040]
|
||||
needs: [build-esp32, build-esp32-s3, build-nrf52, build-native] #, build-rpi2040]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
@@ -193,7 +203,7 @@ jobs:
|
||||
id: version
|
||||
|
||||
- name: Move files up
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v3
|
||||
|
||||
1
.trunk/.gitignore
vendored
1
.trunk/.gitignore
vendored
@@ -5,3 +5,4 @@
|
||||
plugins
|
||||
user_trunk.yaml
|
||||
user.yaml
|
||||
shims
|
||||
|
||||
3
.trunk/configs/.flake8
Normal file
3
.trunk/configs/.flake8
Normal file
@@ -0,0 +1,3 @@
|
||||
# Autoformatter friendly flake8 config (all formatting rules disabled)
|
||||
[flake8]
|
||||
extend-ignore = D1, D2, E1, E2, E3, E501, W1, W2, W3, W5
|
||||
2
.trunk/configs/.isort.cfg
Normal file
2
.trunk/configs/.isort.cfg
Normal file
@@ -0,0 +1,2 @@
|
||||
[settings]
|
||||
profile=black
|
||||
10
.trunk/configs/.yamllint.yaml
Normal file
10
.trunk/configs/.yamllint.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
rules:
|
||||
quoted-strings:
|
||||
required: only-when-needed
|
||||
extra-allowed: ["{|}"]
|
||||
empty-values:
|
||||
forbid-in-block-mappings: true
|
||||
forbid-in-flow-mappings: true
|
||||
key-duplicates: {}
|
||||
octal-values:
|
||||
forbid-implicit-octal: true
|
||||
5
.trunk/configs/ruff.toml
Normal file
5
.trunk/configs/ruff.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
# Generic, formatter-friendly config.
|
||||
select = ["B", "D3", "D4", "E", "F"]
|
||||
|
||||
# Never enforce `E501` (line length violations). This should be handled by formatters.
|
||||
ignore = ["E501"]
|
||||
@@ -1,28 +1,43 @@
|
||||
version: 0.1
|
||||
cli:
|
||||
version: 1.3.1
|
||||
version: 1.9.1
|
||||
plugins:
|
||||
sources:
|
||||
- id: trunk
|
||||
ref: v0.0.8
|
||||
ref: v0.0.17
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- taplo@0.7.0
|
||||
- ruff@0.0.265
|
||||
- yamllint@1.31.0
|
||||
- isort@5.12.0
|
||||
- markdownlint@0.34.0
|
||||
- oxipng@8.0.0
|
||||
- svgo@3.0.2
|
||||
- actionlint@1.6.24
|
||||
- flake8@6.0.0
|
||||
- hadolint@2.12.0
|
||||
- shfmt@3.5.0
|
||||
- shellcheck@0.9.0
|
||||
- black@23.3.0
|
||||
- git-diff-check
|
||||
- gitleaks@8.15.2
|
||||
- gitleaks@8.16.3
|
||||
- clang-format@14.0.0
|
||||
- prettier@2.8.3
|
||||
- prettier@2.8.8
|
||||
disabled:
|
||||
- taplo@0.7.0
|
||||
- shellcheck@0.9.0
|
||||
- shfmt@3.5.0
|
||||
- oxipng@8.0.0
|
||||
- actionlint@1.6.22
|
||||
- markdownlint@0.33.0
|
||||
- markdownlint@0.34.0
|
||||
- hadolint@2.12.0
|
||||
- svgo@3.0.2
|
||||
runtimes:
|
||||
enabled:
|
||||
- go@1.18.3
|
||||
- python@3.10.8
|
||||
- go@1.19.5
|
||||
- node@18.12.1
|
||||
actions:
|
||||
disabled:
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||
[esp32_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^6.0.0
|
||||
platform = platformio/espressif32@^6.2.0
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/>
|
||||
|
||||
upload_speed = 921600
|
||||
debug_init_break = tbreak setup
|
||||
monitor_filters = esp32_exception_decoder
|
||||
|
||||
board_build.filesystem = littlefs
|
||||
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
@@ -34,8 +37,9 @@ lib_deps =
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.0
|
||||
jgromes/RadioLib@^6.0.0
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
caveman99/ESP32 Codec2@^1.0.1
|
||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
|
||||
5
arch/esp32/esp32c3.ini
Normal file
5
arch/esp32/esp32c3.ini
Normal file
@@ -0,0 +1,5 @@
|
||||
[esp32c3_base]
|
||||
extends = esp32_base
|
||||
|
||||
monitor_speed = 115200
|
||||
monitor_filters = esp32_c3_exception_decoder
|
||||
@@ -1,47 +1,16 @@
|
||||
[esp32s2_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^6.0.0
|
||||
extends = esp32_base
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<nimble/>
|
||||
upload_speed = 961200
|
||||
${esp32_base.build_src_filter} -<nimble/>
|
||||
|
||||
monitor_speed = 115200
|
||||
debug_init_break = tbreak setup
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.filesystem = littlefs
|
||||
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Wall
|
||||
-Wextra
|
||||
-Isrc/platform/esp32
|
||||
-std=c++11
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
-DCONFIG_BT_NIMBLE_ENABLED
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
${esp32_base.build_flags}
|
||||
-DHAS_BLUETOOTH=0
|
||||
;-DDEBUG_HEAP
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
caveman99/ESP32 Codec2@^1.0.1
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
ESP32 BLE Arduino
|
||||
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
${esp32_base.lib_ignore}
|
||||
NimBLE-Arduino
|
||||
|
||||
|
||||
@@ -1,47 +1,5 @@
|
||||
[esp32s3_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^6.0.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/>
|
||||
upload_speed = 961200
|
||||
extends = esp32_base
|
||||
|
||||
monitor_speed = 115200
|
||||
debug_init_break = tbreak setup
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.filesystem = littlefs
|
||||
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Wall
|
||||
-Wextra
|
||||
-Isrc/platform/esp32
|
||||
-std=c++11
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
-DCONFIG_BT_NIMBLE_ENABLED
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
;-DDEBUG_HEAP
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.0
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
caveman99/ESP32 Codec2@^1.0.1
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
ESP32 BLE Arduino
|
||||
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
[nrf52_base]
|
||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||
platform = platformio/nordicnrf52@^9.4.0
|
||||
|
||||
platform = platformio/nordicnrf52@^9.6.0
|
||||
extends = arduino_base
|
||||
|
||||
build_type = debug ; I'm debugging with ICE a lot now
|
||||
build_flags =
|
||||
${arduino_base.build_flags} -Wno-unused-variable
|
||||
-Isrc/platform/nrf52
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040> -<mesh/eth/>
|
||||
|
||||
lib_deps=
|
||||
${arduino_base.lib_deps}
|
||||
jgromes/RadioLib@^6.0.0
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
|
||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||
[env:feather_nrf52832]
|
||||
extends = nrf52_base
|
||||
board = adafruit_feather_nrf52832
|
||||
|
||||
|
||||
7
arch/nrf52/nrf52832.ini
Normal file
7
arch/nrf52/nrf52832.ini
Normal file
@@ -0,0 +1,7 @@
|
||||
[nrf52832_base]
|
||||
extends = nrf52_base
|
||||
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
|
||||
lib_deps =
|
||||
${nrf52_base.lib_deps}
|
||||
@@ -1,14 +1,9 @@
|
||||
[nrf52840_base]
|
||||
extends = nrf52_base
|
||||
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${nrf52_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/Kongduino/Adafruit_nRFCrypto.git#e31a8825ea3300b163a0a3c1ddd5de34e10e1371
|
||||
|
||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||
[env:nrf52840dk]
|
||||
extends = nrf52840_base
|
||||
board = nrf52840_dk
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native.git#096b3c3e9c5c8e19d4c3b6cd803fffef2a9be4c5
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
${env.build_src_filter}
|
||||
-<platform/esp32/>
|
||||
@@ -16,8 +17,14 @@ build_src_filter =
|
||||
-<modules/Telemetry/AirQualityTelemetry.cpp>
|
||||
-<modules/Telemetry/Sensor>
|
||||
+<../variants/portduino>
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
build_flags = ${arduino_base.build_flags} -fPIC -Isrc/platform/portduino
|
||||
jgromes/RadioLib@^6.0.0
|
||||
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-fPIC
|
||||
-Isrc/platform/portduino
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
[rp2040_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#9f8c10e50b5acd18e7bfd32638199c655be73a5b
|
||||
extends = arduino_base
|
||||
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
build_flags =
|
||||
@@ -11,9 +12,12 @@ build_flags =
|
||||
# -D _POSIX_THREADS
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
|
||||
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
jgromes/RadioLib@^6.0.0
|
||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||
|
||||
@@ -2,17 +2,19 @@
|
||||
platform = platformio/ststm32@^15.4.1
|
||||
board = generic_wl5e
|
||||
framework = arduino
|
||||
|
||||
build_type = debug
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Isrc/platform/stm32wl -g
|
||||
-DHAL_SUBGHZ_MODULE_ENABLED
|
||||
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
|
||||
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
|
||||
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
jgromes/RadioLib@^6.0.0
|
||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||
|
||||
lib_ignore =
|
||||
mathertel/OneButton@^2.0.3
|
||||
|
||||
@@ -34,7 +34,7 @@ SRCBIN=.pio/build/$1/firmware.bin
|
||||
cp $SRCBIN $OUTDIR/$basename-update.bin
|
||||
|
||||
echo "Building Filesystem for ESP32 targets"
|
||||
pio run --environment tbeam -t buildfs
|
||||
cp .pio/build/tbeam/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
|
||||
pio run --environment $1 -t buildfs
|
||||
cp .pio/build/$1/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
|
||||
cp bin/device-install.* $OUTDIR
|
||||
cp bin/device-update.* $OUTDIR
|
||||
|
||||
@@ -30,7 +30,13 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
||||
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
|
||||
%PYTHON% -m esptool --baud 115200 erase_flash
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||
|
||||
@REM Account for S3 board's different OTA partition
|
||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||
) else (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
|
||||
)
|
||||
for %%f in (littlefs-*.bin) do (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x300000 %%f
|
||||
)
|
||||
|
||||
@@ -49,7 +49,12 @@ if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
"$PYTHON" -m esptool erase_flash
|
||||
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||
# Account for S3 board's different OTA partition
|
||||
if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ]; then
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||
else
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
|
||||
fi
|
||||
"$PYTHON" -m esptool write_flash 0x300000 littlefs-*.bin
|
||||
|
||||
else
|
||||
|
||||
38
bin/generate_ci_matrix.py
Executable file
38
bin/generate_ci_matrix.py
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Generate the CI matrix"""
|
||||
|
||||
import configparser
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
rootdir = "variants/"
|
||||
|
||||
options = sys.argv[1:]
|
||||
|
||||
outlist = []
|
||||
|
||||
if len(options) < 1:
|
||||
print(json.dumps(outlist))
|
||||
exit()
|
||||
|
||||
for subdir, dirs, files in os.walk(rootdir):
|
||||
for file in files:
|
||||
if file == "platformio.ini":
|
||||
config = configparser.ConfigParser()
|
||||
config.read(subdir + "/" + file)
|
||||
for c in config.sections():
|
||||
if c.startswith("env:"):
|
||||
section = config[c].name[4:]
|
||||
if "extends" in config[config[c].name]:
|
||||
if config[config[c].name]["extends"] == options[0] + "_base":
|
||||
if "board_level" in config[config[c].name]:
|
||||
if (
|
||||
config[config[c].name]["board_level"] == "extra"
|
||||
) & ("extra" in options):
|
||||
outlist.append(section)
|
||||
else:
|
||||
outlist.append(section)
|
||||
|
||||
print(json.dumps(outlist))
|
||||
@@ -1,5 +1 @@
|
||||
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto
|
||||
|
||||
@REM cd ../src/mesh/generated/meshtastic
|
||||
@REM sed -i 's/#include "meshtastic/#include "./g' *
|
||||
@REM sed -i 's/meshtastic_//g' *
|
||||
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --experimental_allow_proto3_optional --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto
|
||||
|
||||
@@ -8,7 +8,7 @@ echo "prebuilt binaries for your computer into nanopb-0.4.7"
|
||||
|
||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||
cd protobufs
|
||||
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated/ -I=../protobufs meshtastic/*.proto
|
||||
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated/ -I=../protobufs meshtastic/*.proto --experimental_allow_proto3_optional
|
||||
|
||||
# cd ../src/mesh/generated/meshtastic
|
||||
# sed -i 's/#include "meshtastic/#include "./g' -- *
|
||||
|
||||
38
boards/bpi_picow_esp32_s3.json
Normal file
38
boards/bpi_picow_esp32_s3.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1",
|
||||
"-DBOARD_HAS_PSRAM"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "bpi_picow_esp32_s3"
|
||||
},
|
||||
"connectivity": ["wifi"],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "BPI-PicoW-S3 (8 MB FLASH, 2 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://wiki.banana-pi.org/BPI-PicoW-S3",
|
||||
"vendor": "BPI"
|
||||
}
|
||||
41
boards/my-esp32s3-diy-oled.json
Normal file
41
boards/my-esp32s3-diy-oled.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": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "my-esp32s3-diy-oled"
|
||||
},
|
||||
"connectivity": ["wifi"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "Clone ESP32-S3-DevKitC-1 v1.1 (16 MB FLASH, 8 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html",
|
||||
"vendor": "Espressif"
|
||||
}
|
||||
41
boards/my_esp32s3_diy_eink.json
Normal file
41
boards/my_esp32s3_diy_eink.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": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "my_esp32s3_diy_eink"
|
||||
},
|
||||
"connectivity": ["wifi"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "Clone ESP32-S3-DevKitC-1 v1.1 (16 MB FLASH, 8 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html",
|
||||
"vendor": "Espressif"
|
||||
}
|
||||
155
monitor/filter_c3_exception_decoder.py
Normal file
155
monitor/filter_c3_exception_decoder.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from platformio.project.exception import PlatformioException
|
||||
from platformio.public import (
|
||||
DeviceMonitorFilterBase,
|
||||
load_build_metadata,
|
||||
)
|
||||
|
||||
# By design, __init__ is called inside miniterm and we can't pass context to it.
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
|
||||
IS_WINDOWS = sys.platform.startswith("win")
|
||||
|
||||
|
||||
class Esp32C3ExceptionDecoder(DeviceMonitorFilterBase):
|
||||
NAME = "esp32_c3_exception_decoder"
|
||||
|
||||
PCADDR_PATTERN = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE)
|
||||
|
||||
def __call__(self):
|
||||
self.buffer = ""
|
||||
self.pcaddr_re = self.PCADDR_PATTERN
|
||||
|
||||
self.firmware_path = None
|
||||
self.addr2line_path = None
|
||||
self.enabled = self.setup_paths()
|
||||
|
||||
if self.config.get("env:" + self.environment, "build_type") != "debug":
|
||||
print(
|
||||
"""
|
||||
Please build project in debug configuration to get more details about an exception.
|
||||
See https://docs.platformio.org/page/projectconf/build_configurations.html
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
def setup_paths(self):
|
||||
self.project_dir = os.path.abspath(self.project_dir)
|
||||
try:
|
||||
data = load_build_metadata(self.project_dir, self.environment)
|
||||
self.firmware_path = data["prog_path"]
|
||||
if not os.path.isfile(self.firmware_path):
|
||||
sys.stderr.write(
|
||||
"%s: disabling, firmware at %s does not exist, rebuild the project?\n"
|
||||
% (self.__class__.__name__, self.firmware_path)
|
||||
)
|
||||
return False
|
||||
|
||||
if self.addr2line_path is None:
|
||||
cc_path = data.get("cc_path", "")
|
||||
if "-gcc" in cc_path:
|
||||
self.addr2line_path = cc_path.replace("-gcc", "-addr2line")
|
||||
else:
|
||||
sys.stderr.write(
|
||||
"%s: disabling, failed to find addr2line.\n"
|
||||
% self.__class__.__name__
|
||||
)
|
||||
return False
|
||||
|
||||
if not os.path.isfile(self.addr2line_path):
|
||||
sys.stderr.write(
|
||||
"%s: disabling, addr2line at %s does not exist\n"
|
||||
% (self.__class__.__name__, self.addr2line_path)
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
except PlatformioException as e:
|
||||
sys.stderr.write(
|
||||
"%s: disabling, exception while looking for addr2line: %s\n"
|
||||
% (self.__class__.__name__, e)
|
||||
)
|
||||
return False
|
||||
|
||||
def rx(self, text):
|
||||
if not self.enabled:
|
||||
return text
|
||||
|
||||
last = 0
|
||||
while True:
|
||||
idx = text.find("\n", last)
|
||||
if idx == -1:
|
||||
if len(self.buffer) < 4096:
|
||||
self.buffer += text[last:]
|
||||
break
|
||||
|
||||
line = text[last:idx]
|
||||
if self.buffer:
|
||||
line = self.buffer + line
|
||||
self.buffer = ""
|
||||
last = idx + 1
|
||||
|
||||
# Output each trace on a separate line below ours
|
||||
# Logic identical to https://github.com/espressif/esp-idf/blob/master/tools/idf_monitor_base/logger.py#L131
|
||||
for m in re.finditer(self.pcaddr_re, line):
|
||||
if m is None:
|
||||
continue
|
||||
|
||||
trace = self.get_backtrace(m)
|
||||
if len(trace) != "":
|
||||
text = text[: last] + trace + text[last :]
|
||||
last += len(trace)
|
||||
|
||||
return text
|
||||
|
||||
def get_backtrace(self, match):
|
||||
trace = "\n"
|
||||
enc = "mbcs" if IS_WINDOWS else "utf-8"
|
||||
args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path]
|
||||
try:
|
||||
addr = match.group()
|
||||
output = (
|
||||
subprocess.check_output(args + [addr])
|
||||
.decode(enc)
|
||||
.strip()
|
||||
)
|
||||
output = output.replace(
|
||||
"\n", "\n "
|
||||
) # newlines happen with inlined methods
|
||||
output = self.strip_project_dir(output)
|
||||
# Output the trace in yellow color so that it is easier to spot
|
||||
trace += "\033[33m=> %s: %s\033[0m\n" % (addr, output)
|
||||
except subprocess.CalledProcessError as e:
|
||||
sys.stderr.write(
|
||||
"%s: failed to call %s: %s\n"
|
||||
% (self.__class__.__name__, self.addr2line_path, e)
|
||||
)
|
||||
return trace
|
||||
|
||||
def strip_project_dir(self, trace):
|
||||
while True:
|
||||
idx = trace.find(self.project_dir)
|
||||
if idx == -1:
|
||||
break
|
||||
trace = trace[:idx] + trace[idx + len(self.project_dir) + 1 :]
|
||||
return trace
|
||||
@@ -59,14 +59,13 @@ build_flags = -Wno-missing-field-initializers
|
||||
monitor_speed = 115200
|
||||
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#da1ede4dfcd91074283b029080759fd744120909 ; ESP8266_SSD1306
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306
|
||||
mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4
|
||||
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
|
||||
nanopb/Nanopb@^0.4.6
|
||||
nanopb/Nanopb@^0.4.7
|
||||
erriez/ErriezCRC32@^1.0.1
|
||||
jgromes/RadioLib@^5.7.0
|
||||
|
||||
; Used for the code analysis in PIO Home / Inspect
|
||||
check_tool = cppcheck
|
||||
@@ -83,7 +82,7 @@ lib_deps =
|
||||
${env.lib_deps}
|
||||
mprograms/QMC5883LCompass@^1.1.1
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76
|
||||
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
|
||||
|
||||
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
|
||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
||||
@@ -100,10 +99,11 @@ lib_deps =
|
||||
[environmental_base]
|
||||
lib_deps =
|
||||
adafruit/Adafruit BusIO@^1.11.4
|
||||
adafruit/Adafruit Unified Sensor@^1.1.4
|
||||
adafruit/Adafruit Unified Sensor@^1.1.9
|
||||
adafruit/Adafruit BMP280 Library@^2.6.6
|
||||
adafruit/Adafruit BME280 Library@^2.2.2
|
||||
adafruit/Adafruit BME680 Library@^2.0.1
|
||||
boschsensortec/BSEC2 Software Library@^1.3.2200
|
||||
boschsensortec/BME68x Sensor Library@^1.1.40407
|
||||
adafruit/Adafruit MCP9808 Library@^2.0.0
|
||||
adafruit/Adafruit INA260 Library@^1.5.0
|
||||
adafruit/Adafruit INA219@^1.2.0
|
||||
@@ -111,3 +111,5 @@ lib_deps =
|
||||
adafruit/Adafruit LPS2X@^2.0.4
|
||||
adafruit/Adafruit SHT31 Library@^2.2.0
|
||||
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
|
||||
adafruit/Adafruit MPU6050@^2.2.4
|
||||
adafruit/Adafruit LIS3DH@^1.2.4
|
||||
|
||||
Submodule protobufs updated: 19d49ec528...345b3bf103
92
src/AccelerometerThread.h
Normal file
92
src/AccelerometerThread.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "PowerFSM.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "power.h"
|
||||
|
||||
#include <Adafruit_LIS3DH.h>
|
||||
#include <Adafruit_MPU6050.h>
|
||||
|
||||
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
|
||||
#define ACCELEROMETER_CLICK_THRESHOLD 40
|
||||
|
||||
namespace concurrency
|
||||
{
|
||||
class AccelerometerThread : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
AccelerometerThread(ScanI2C::DeviceType type = ScanI2C::DeviceType::NONE) : OSThread("AccelerometerThread")
|
||||
{
|
||||
if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) {
|
||||
LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n");
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
accleremoter_type = type;
|
||||
LOG_DEBUG("AccelerometerThread initializing\n");
|
||||
|
||||
if (accleremoter_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 (accleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
|
||||
LOG_DEBUG("LIS3DH initializing\n");
|
||||
lis.setRange(LIS3DH_RANGE_2_G);
|
||||
// Adjust threshhold, higher numbers are less sensitive
|
||||
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override
|
||||
{
|
||||
canSleep = true; // Assume we should not keep the board awake
|
||||
|
||||
if (accleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) {
|
||||
wakeScreen();
|
||||
} else if (accleremoter_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;
|
||||
}
|
||||
}
|
||||
return ACCELEROMETER_CHECK_INTERVAL_MS;
|
||||
}
|
||||
|
||||
private:
|
||||
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 accleremoter_type;
|
||||
Adafruit_MPU6050 mpu;
|
||||
Adafruit_LIS3DH lis;
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
@@ -45,10 +45,10 @@ class ButtonThread : public concurrency::OSThread
|
||||
ButtonThread() : OSThread("Button")
|
||||
{
|
||||
#ifdef BUTTON_PIN
|
||||
userButton = OneButton(BUTTON_PIN, true, true);
|
||||
userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
|
||||
#ifdef INPUT_PULLUP_SENSE
|
||||
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||
pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE);
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
|
||||
#endif
|
||||
userButton.attachClick(userButtonPressed);
|
||||
userButton.setClickTicks(300);
|
||||
@@ -57,7 +57,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
userButton.attachMultiClick(userButtonMultiPressed);
|
||||
userButton.attachLongPressStart(userButtonPressedLongStart);
|
||||
userButton.attachLongPressStop(userButtonPressedLongStop);
|
||||
wakeOnIrq(BUTTON_PIN, FALLING);
|
||||
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
|
||||
#endif
|
||||
#ifdef BUTTON_PIN_ALT
|
||||
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
||||
@@ -115,7 +115,9 @@ class ButtonThread : public concurrency::OSThread
|
||||
{
|
||||
// LOG_DEBUG("press!\n");
|
||||
#ifdef BUTTON_PIN
|
||||
if ((BUTTON_PIN != moduleConfig.canned_message.inputbroker_pin_press) || !moduleConfig.canned_message.enabled) {
|
||||
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
|
||||
moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||
!moduleConfig.canned_message.enabled) {
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
}
|
||||
#endif
|
||||
@@ -123,17 +125,9 @@ class ButtonThread : public concurrency::OSThread
|
||||
static void userButtonPressedLong()
|
||||
{
|
||||
// LOG_DEBUG("Long press!\n");
|
||||
#ifdef ARCH_ESP32
|
||||
screen->adjustBrightness();
|
||||
#endif
|
||||
// If user button is held down for 5 seconds, shutdown the device.
|
||||
if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) {
|
||||
#ifdef HAS_PMU
|
||||
if (pmu_found == true) {
|
||||
setLed(false);
|
||||
power->shutdown();
|
||||
}
|
||||
#elif defined(ARCH_NRF52)
|
||||
if ((millis() - longPressTime > 5000) && (longPressTime > 0)) {
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_ESP32)
|
||||
// Do actual shutdown when button released, otherwise the button release
|
||||
// may wake the board immediatedly.
|
||||
if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) {
|
||||
|
||||
@@ -34,6 +34,7 @@ bool copyFile(const char *from, const char *to)
|
||||
f2.write(cbuffer, i);
|
||||
}
|
||||
|
||||
f2.flush();
|
||||
f2.close();
|
||||
f1.close();
|
||||
return true;
|
||||
|
||||
111
src/Power.cpp
111
src/Power.cpp
@@ -13,6 +13,10 @@
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
#ifndef DELAY_FOREVER
|
||||
#define DELAY_FOREVER portMAX_DELAY
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PMU
|
||||
#include "XPowersAXP192.tpp"
|
||||
#include "XPowersAXP2101.tpp"
|
||||
@@ -156,8 +160,18 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
|
||||
/// If we see a battery voltage higher than physics allows - assume charger is pumping
|
||||
/// in power
|
||||
/// On some boards we don't have the power management chip (like AXPxxxx)
|
||||
/// so we use EXT_PWR_DETECT GPIO pin to detect external power source
|
||||
virtual bool isVbusIn() override
|
||||
{
|
||||
#ifdef EXT_PWR_DETECT
|
||||
// if external powered that pin will be pulled up
|
||||
if (digitalRead(EXT_PWR_DETECT) == HIGH) {
|
||||
return true;
|
||||
}
|
||||
// if it's not HIGH - check the battery
|
||||
#endif
|
||||
|
||||
return getBattVoltage() > chargingVolt;
|
||||
}
|
||||
|
||||
@@ -198,12 +212,16 @@ Power::Power() : OSThread("Power")
|
||||
statusHandler = {};
|
||||
low_voltage_counter = 0;
|
||||
#ifdef DEBUG_HEAP
|
||||
lastheap = ESP.getFreeHeap();
|
||||
lastheap = memGet.getFreeHeap();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Power::analogInit()
|
||||
{
|
||||
#ifdef EXT_PWR_DETECT
|
||||
pinMode(EXT_PWR_DETECT, INPUT);
|
||||
#endif
|
||||
|
||||
#ifdef BATTERY_PIN
|
||||
LOG_DEBUG("Using analog input %d for battery level\n", BATTERY_PIN);
|
||||
|
||||
@@ -256,16 +274,23 @@ void Power::shutdown()
|
||||
digitalWrite(PIN_EINK_EN, LOW); // power off backlight first
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PMU
|
||||
LOG_INFO("Shutting down\n");
|
||||
if (PMU) {
|
||||
|
||||
#ifdef HAS_PMU
|
||||
if (pmu_found == true) {
|
||||
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
|
||||
PMU->shutdown();
|
||||
}
|
||||
#elif defined(ARCH_NRF52)
|
||||
playBeep();
|
||||
#elif defined(ARCH_NRF52) || defined(ARCH_ESP32)
|
||||
#ifdef PIN_LED1
|
||||
ledOff(PIN_LED1);
|
||||
#endif
|
||||
#ifdef PIN_LED2
|
||||
ledOff(PIN_LED2);
|
||||
#endif
|
||||
#ifdef PIN_LED3
|
||||
ledOff(PIN_LED2);
|
||||
#endif
|
||||
doDeepSleep(DELAY_FOREVER);
|
||||
#endif
|
||||
}
|
||||
@@ -302,7 +327,7 @@ void Power::readPowerStatus()
|
||||
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
|
||||
newStatus.notifyObservers(&powerStatus2);
|
||||
#ifdef DEBUG_HEAP
|
||||
if (lastheap != ESP.getFreeHeap()) {
|
||||
if (lastheap != memGet.getFreeHeap()) {
|
||||
LOG_DEBUG("Threads running:");
|
||||
int running = 0;
|
||||
for (int i = 0; i < MAX_THREADS; i++) {
|
||||
@@ -313,9 +338,9 @@ void Power::readPowerStatus()
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads\n", ESP.getFreeHeap(), ESP.getHeapSize(),
|
||||
ESP.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
|
||||
lastheap = ESP.getFreeHeap();
|
||||
LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads\n", memGet.getFreeHeap(), memGet.getHeapSize(),
|
||||
memGet.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
|
||||
lastheap = memGet.getFreeHeap();
|
||||
}
|
||||
#ifdef DEBUG_HEAP_MQTT
|
||||
if (mqtt) {
|
||||
@@ -324,41 +349,41 @@ void Power::readPowerStatus()
|
||||
getMacAddr(dmac); // Get our hardware ID
|
||||
char mac[18];
|
||||
sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]);
|
||||
auto newHeap = ESP.getFreeHeap();
|
||||
std::string heapTopic = "msh/2/heap/" + std::string(mac);
|
||||
|
||||
auto newHeap = memGet.getFreeHeap();
|
||||
std::string heapTopic =
|
||||
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/heap/") + std::string(mac);
|
||||
std::string heapString = std::to_string(newHeap);
|
||||
mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false);
|
||||
// auto fragHeap = ESP.getHeapFragmentation();
|
||||
auto wifiRSSI = WiFi.RSSI();
|
||||
heapTopic = "msh/2/wifi/" + std::string(mac);
|
||||
std::string wifiTopic =
|
||||
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/wifi/") + std::string(mac);
|
||||
std::string wifiString = std::to_string(wifiRSSI);
|
||||
mqtt->pubSub.publish(heapTopic.c_str(), wifiString.c_str(), false);
|
||||
mqtt->pubSub.publish(wifiTopic.c_str(), wifiString.c_str(), false);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row
|
||||
// Supect fluctuating voltage on the RAK4631 to force it to deep sleep even if battery is at 85% after only a few days
|
||||
#ifdef ARCH_NRF52
|
||||
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 10 low readings in a
|
||||
// row
|
||||
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
|
||||
if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) {
|
||||
low_voltage_counter++;
|
||||
LOG_DEBUG("Warning RAK4631 Low voltage counter: %d/10\n", low_voltage_counter);
|
||||
LOG_DEBUG("Low voltage counter: %d/10\n", low_voltage_counter);
|
||||
if (low_voltage_counter > 10) {
|
||||
#ifdef ARCH_NRF52
|
||||
// We can't trigger deep sleep on NRF52, it's freezing the board
|
||||
// powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
LOG_DEBUG("Low voltage detected, but not triggering deep sleep\n");
|
||||
#else
|
||||
LOG_INFO("Low voltage detected, triggering deep sleep\n");
|
||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
low_voltage_counter = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// If we have a battery at all and it is less than 10% full, force deep sleep
|
||||
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB() && batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS)
|
||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
#endif
|
||||
} else {
|
||||
// No power sensing on this board - tell everyone else we have no idea what is happening
|
||||
const PowerStatus powerStatus3 = PowerStatus(OptUnknown, OptUnknown, OptUnknown, -1, -1);
|
||||
@@ -512,11 +537,41 @@ bool Power::axpChipInit()
|
||||
|
||||
// Set up the charging voltage
|
||||
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
|
||||
|
||||
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
|
||||
|
||||
// t-beam s3 core
|
||||
/*The alternative version of T-Beam 1.1 differs from T-Beam V1.1 in that it uses an AXP2101 power chip*/
|
||||
#if (HW_VENDOR == meshtastic_HardwareModel_TBEAM)
|
||||
// Unuse power channel
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC2);
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC3);
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC4);
|
||||
PMU->disablePowerOutput(XPOWERS_DCDC5);
|
||||
PMU->disablePowerOutput(XPOWERS_ALDO1);
|
||||
PMU->disablePowerOutput(XPOWERS_ALDO4);
|
||||
PMU->disablePowerOutput(XPOWERS_BLDO1);
|
||||
PMU->disablePowerOutput(XPOWERS_BLDO2);
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO1);
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO2);
|
||||
|
||||
// GNSS RTC PowerVDD 3300mV
|
||||
PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_VBACKUP);
|
||||
|
||||
// ESP32 VDD 3300mV
|
||||
// ! No need to set, automatically open , Don't close it
|
||||
// PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
|
||||
// PMU->setProtectedChannel(XPOWERS_DCDC1);
|
||||
|
||||
// LoRa VDD 3300mV
|
||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
||||
|
||||
// GNSS VDD 3300mV
|
||||
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
|
||||
PMU->enablePowerOutput(XPOWERS_ALDO3);
|
||||
|
||||
#elif (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE)
|
||||
// t-beam s3 core
|
||||
/**
|
||||
* gnss module power channel
|
||||
* The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during initialization
|
||||
@@ -559,6 +614,8 @@ bool Power::axpChipInit()
|
||||
PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
|
||||
PMU->disablePowerOutput(XPOWERS_VBACKUP);
|
||||
|
||||
#endif
|
||||
|
||||
// disable all axp chip interrupt
|
||||
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
|
||||
|
||||
@@ -671,4 +728,4 @@ bool Power::axpChipInit()
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,9 @@ static bool isPowered()
|
||||
1) If we're powered up and there's no battery, we must be getting power externally. (because we'd be dead otherwise)
|
||||
|
||||
2) If we detect USB power from the power management chip, we must be getting power externally.
|
||||
|
||||
3) On some boards we don't have the power management chip (like AXPxxxx) so we use EXT_PWR_DETECT GPIO pin to detect
|
||||
external power source (see `isVbusIn()` in `Power.cpp`)
|
||||
*/
|
||||
return !isPowerSavingMode && powerStatus && (!powerStatus->getHasBattery() || powerStatus->getHasUSB());
|
||||
}
|
||||
@@ -66,11 +69,11 @@ static void lsIdle()
|
||||
|
||||
// Do we have more sleeping to do?
|
||||
if (secsSlept < config.power.ls_secs) {
|
||||
// Briefly come out of sleep long enough to blink the led once every few seconds
|
||||
uint32_t sleepTime = 30;
|
||||
|
||||
// If some other service would stall sleep, don't let sleep happen yet
|
||||
if (doPreflightSleep()) {
|
||||
// Briefly come out of sleep long enough to blink the led once every few seconds
|
||||
uint32_t sleepTime = 30;
|
||||
|
||||
setLed(false); // Never leave led on while in light sleep
|
||||
esp_sleep_source_t wakeCause2 = doLightSleep(sleepTime * 1000LL);
|
||||
|
||||
@@ -96,12 +99,11 @@ static void lsIdle()
|
||||
LOG_INFO("wakeCause2 %d\n", wakeCause2);
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
bool pressed = !digitalRead(BUTTON_PIN);
|
||||
bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
|
||||
#else
|
||||
bool pressed = false;
|
||||
#endif
|
||||
if (pressed) // If we woke because of press, instead generate a PRESS event.
|
||||
{
|
||||
if (pressed) { // If we woke because of press, instead generate a PRESS event.
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
} else {
|
||||
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
|
||||
@@ -169,7 +171,11 @@ static void powerEnter()
|
||||
} else {
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
screen->print("Powered...\n");
|
||||
// within enter() the function getState() returns the state we came from
|
||||
if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 &&
|
||||
strcmp(powerFSM.getState()->name, "DARK") != 0) {
|
||||
screen->print("Powered...\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +192,8 @@ static void powerExit()
|
||||
{
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
screen->print("Unpowered...\n");
|
||||
if (!isPowered())
|
||||
screen->print("Unpowered...\n");
|
||||
}
|
||||
|
||||
static void onEnter()
|
||||
@@ -194,17 +201,6 @@ static void onEnter()
|
||||
LOG_INFO("Enter state: ON\n");
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
|
||||
static uint32_t lastPingMs;
|
||||
|
||||
uint32_t now = millis();
|
||||
|
||||
if ((now - lastPingMs) >
|
||||
30 * 1000) { // if more than a minute since our last press, ask node we are looking at to update their state
|
||||
if (displayedNodeNum)
|
||||
service.sendNetworkPing(displayedNodeNum, true); // Refresh the currently displayed node
|
||||
lastPingMs = now;
|
||||
}
|
||||
}
|
||||
|
||||
static void onIdle()
|
||||
@@ -257,7 +253,7 @@ void PowerFSM_setup()
|
||||
// Handle press events - note: we ignore button presses when in API mode
|
||||
powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press");
|
||||
powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press");
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
|
||||
powerFSM.add_transition(&stateDARK, isPowered() ? &statePOWER : &stateON, EVENT_PRESS, NULL, "Press");
|
||||
powerFSM.add_transition(&statePOWER, &statePOWER, EVENT_PRESS, screenPress, "Press");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_PRESS, screenPress, "Press"); // reenter On to restart our timers
|
||||
powerFSM.add_transition(&stateSERIAL, &stateSERIAL, EVENT_PRESS, screenPress,
|
||||
@@ -299,10 +295,10 @@ void PowerFSM_setup()
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update");
|
||||
|
||||
// Show the received text message
|
||||
powerFSM.add_transition(&stateLS, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
||||
powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); // restarts the sleep timer
|
||||
powerFSM.add_transition(&stateLS, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text");
|
||||
powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text");
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text"); // restarts the sleep timer
|
||||
}
|
||||
|
||||
// If we are not in statePOWER but get a serial connection, suppress sleep (and keep the screen on) while connected
|
||||
@@ -330,6 +326,12 @@ void PowerFSM_setup()
|
||||
powerFSM.add_timed_transition(&stateON, &stateDARK,
|
||||
getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
|
||||
"Screen-on timeout");
|
||||
powerFSM.add_timed_transition(&statePOWER, &stateDARK,
|
||||
getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
|
||||
"Screen-on timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
|
||||
getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
|
||||
"Screen-on timeout");
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
State *lowPowerState = &stateLS;
|
||||
@@ -351,4 +353,4 @@ void PowerFSM_setup()
|
||||
#endif
|
||||
|
||||
powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
#define EVENT_WAKE_TIMER 2
|
||||
// #define EVENT_RECEIVED_PACKET 3
|
||||
#define EVENT_PACKET_FOR_PHONE 4
|
||||
#define EVENT_RECEIVED_TEXT_MSG 5
|
||||
#define EVENT_RECEIVED_MSG 5
|
||||
// #define EVENT_BOOT 6 // now done with a timed transition
|
||||
#define EVENT_BLUETOOTH_PAIR 7
|
||||
#define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen
|
||||
@@ -23,6 +23,6 @@
|
||||
#define EVENT_INPUT 17 // input broker wants something, we need to wake up and enable screen
|
||||
|
||||
extern Fsm powerFSM;
|
||||
extern State statePOWER, stateSERIAL;
|
||||
extern State stateON, statePOWER, stateSERIAL, stateDARK;
|
||||
|
||||
void PowerFSM_setup();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include "memGet.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace concurrency
|
||||
@@ -75,12 +76,12 @@ bool OSThread::shouldRun(unsigned long time)
|
||||
void OSThread::run()
|
||||
{
|
||||
#ifdef DEBUG_HEAP
|
||||
auto heap = ESP.getFreeHeap();
|
||||
auto heap = memGet.getFreeHeap();
|
||||
#endif
|
||||
currentThread = this;
|
||||
auto newDelay = runOnce();
|
||||
#ifdef DEBUG_HEAP
|
||||
auto newHeap = ESP.getFreeHeap();
|
||||
auto newHeap = memGet.getFreeHeap();
|
||||
if (newHeap < heap)
|
||||
LOG_DEBUG("------ Thread %s leaked heap %d -> %d (%d) ------\n", ThreadName.c_str(), heap, newHeap, newHeap - heap);
|
||||
if (heap < newHeap)
|
||||
|
||||
@@ -82,7 +82,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// #define DISABLE_NTP
|
||||
|
||||
// Disable the welcome screen and allow
|
||||
//#define DISABLE_WELCOME_UNSET
|
||||
// #define DISABLE_WELCOME_UNSET
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// OLED & Input
|
||||
@@ -93,7 +93,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// The SH1106 controller is almost, but not quite, the same as SSD1306
|
||||
// Define this if you know you have that controller or your "SSD1306" misbehaves.
|
||||
//#define USE_SH1106
|
||||
// #define USE_SH1106
|
||||
|
||||
// Define if screen should be mirrored left to right
|
||||
// #define SCREEN_MIRROR
|
||||
@@ -118,6 +118,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define SHT31_ADDR 0x44
|
||||
#define PMSA0031_ADDR 0x12
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ACCELEROMETER
|
||||
// -----------------------------------------------------------------------------
|
||||
#define MPU6050_ADDR 0x68
|
||||
#define LIS3DH_ADR 0x18
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// LED
|
||||
// -----------------------------------------------------------------------------
|
||||
#define NCP5623_ADDR 0x38
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Security
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
76
src/detect/ScanI2C.cpp
Normal file
76
src/detect/ScanI2C.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "ScanI2C.h"
|
||||
|
||||
const ScanI2C::DeviceAddress ScanI2C::ADDRESS_NONE = ScanI2C::DeviceAddress();
|
||||
const ScanI2C::FoundDevice ScanI2C::DEVICE_NONE = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ADDRESS_NONE);
|
||||
|
||||
ScanI2C::ScanI2C() = default;
|
||||
|
||||
void ScanI2C::scanPort(ScanI2C::I2CPort port) {}
|
||||
|
||||
void ScanI2C::setSuppressScreen()
|
||||
{
|
||||
shouldSuppressScreen = true;
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstScreen() const
|
||||
{
|
||||
// Allow to override the scanner results for screen
|
||||
if (shouldSuppressScreen)
|
||||
return DEVICE_NONE;
|
||||
|
||||
ScanI2C::DeviceType types[] = {SCREEN_SSD1306, SCREEN_SH1106, SCREEN_ST7567, SCREEN_UNKNOWN};
|
||||
return firstOfOrNONE(4, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563};
|
||||
return firstOfOrNONE(2, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {CARDKB, RAK14004};
|
||||
return firstOfOrNONE(2, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH};
|
||||
return firstOfOrNONE(2, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
|
||||
{
|
||||
return DEVICE_NONE;
|
||||
}
|
||||
|
||||
bool ScanI2C::exists(ScanI2C::DeviceType) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstOfOrNONE(size_t count, ScanI2C::DeviceType *types) const
|
||||
{
|
||||
return DEVICE_NONE;
|
||||
}
|
||||
|
||||
size_t ScanI2C::countDevices() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ScanI2C::DeviceAddress::DeviceAddress(ScanI2C::I2CPort port, uint8_t address) : port(port), address(address) {}
|
||||
|
||||
ScanI2C::DeviceAddress::DeviceAddress() : DeviceAddress(I2CPort::NO_I2C, 0) {}
|
||||
|
||||
bool ScanI2C::DeviceAddress::operator<(const ScanI2C::DeviceAddress &other) const
|
||||
{
|
||||
return
|
||||
// If this one has no port and other has a port
|
||||
(port == NO_I2C && other.port != NO_I2C)
|
||||
// if both have a port and this one's address is lower
|
||||
|| (port != NO_I2C && other.port != NO_I2C && (address < other.address));
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {}
|
||||
98
src/detect/ScanI2C.h
Normal file
98
src/detect/ScanI2C.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class ScanI2C
|
||||
{
|
||||
public:
|
||||
typedef enum DeviceType {
|
||||
NONE,
|
||||
SCREEN_SSD1306,
|
||||
SCREEN_SH1106,
|
||||
SCREEN_UNKNOWN, // has the same address as the two above but does not respond to the same commands
|
||||
SCREEN_ST7567,
|
||||
ATECC608B,
|
||||
RTC_RV3028,
|
||||
RTC_PCF8563,
|
||||
CARDKB,
|
||||
RAK14004,
|
||||
PMU_AXP192_AXP2101,
|
||||
BME_680,
|
||||
BME_280,
|
||||
BMP_280,
|
||||
INA260,
|
||||
INA219,
|
||||
MCP9808,
|
||||
SHT31,
|
||||
SHTC3,
|
||||
LPS22HB,
|
||||
QMC6310,
|
||||
QMI8658,
|
||||
QMC5883L,
|
||||
PMSA0031,
|
||||
MPU6050,
|
||||
LIS3DH,
|
||||
NCP5623,
|
||||
} DeviceType;
|
||||
|
||||
// typedef uint8_t DeviceAddress;
|
||||
typedef enum I2CPort {
|
||||
NO_I2C,
|
||||
WIRE,
|
||||
WIRE1,
|
||||
} I2CPort;
|
||||
|
||||
typedef struct DeviceAddress {
|
||||
I2CPort port;
|
||||
uint8_t address;
|
||||
|
||||
explicit DeviceAddress(I2CPort port, uint8_t address);
|
||||
DeviceAddress();
|
||||
|
||||
bool operator<(const DeviceAddress &other) const;
|
||||
} DeviceAddress;
|
||||
|
||||
static const DeviceAddress ADDRESS_NONE;
|
||||
|
||||
typedef uint8_t RegisterAddress;
|
||||
|
||||
typedef struct FoundDevice {
|
||||
DeviceType type;
|
||||
DeviceAddress address;
|
||||
|
||||
explicit FoundDevice(DeviceType = DeviceType::NONE, DeviceAddress = ADDRESS_NONE);
|
||||
} FoundDevice;
|
||||
|
||||
static const FoundDevice DEVICE_NONE;
|
||||
|
||||
public:
|
||||
ScanI2C();
|
||||
|
||||
virtual void scanPort(ScanI2C::I2CPort);
|
||||
|
||||
/*
|
||||
* A bit of a hack, this tells the scanner not to tell later systems there is a screen to avoid enabling it.
|
||||
*/
|
||||
void setSuppressScreen();
|
||||
|
||||
FoundDevice firstScreen() const;
|
||||
|
||||
FoundDevice firstRTC() const;
|
||||
|
||||
FoundDevice firstKeyboard() const;
|
||||
|
||||
FoundDevice firstAccelerometer() const;
|
||||
|
||||
virtual FoundDevice find(DeviceType) const;
|
||||
|
||||
virtual bool exists(DeviceType) const;
|
||||
|
||||
virtual size_t countDevices() const;
|
||||
|
||||
protected:
|
||||
virtual FoundDevice firstOfOrNONE(size_t, DeviceType[]) const;
|
||||
|
||||
private:
|
||||
bool shouldSuppressScreen = false;
|
||||
};
|
||||
308
src/detect/ScanI2CTwoWire.cpp
Normal file
308
src/detect/ScanI2CTwoWire.cpp
Normal file
@@ -0,0 +1,308 @@
|
||||
#include "ScanI2CTwoWire.h"
|
||||
|
||||
#include "concurrency/LockGuard.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include "main.h" // atecc
|
||||
#endif
|
||||
|
||||
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
||||
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
|
||||
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
|
||||
#endif
|
||||
|
||||
ScanI2C::FoundDevice ScanI2CTwoWire::find(ScanI2C::DeviceType type) const
|
||||
{
|
||||
concurrency::LockGuard guard((concurrency::Lock *)&lock);
|
||||
|
||||
return exists(type) ? ScanI2C::FoundDevice(type, deviceAddresses.at(type)) : DEVICE_NONE;
|
||||
}
|
||||
|
||||
bool ScanI2CTwoWire::exists(ScanI2C::DeviceType type) const
|
||||
{
|
||||
return deviceAddresses.find(type) != deviceAddresses.end();
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2CTwoWire::firstOfOrNONE(size_t count, DeviceType types[]) const
|
||||
{
|
||||
concurrency::LockGuard guard((concurrency::Lock *)&lock);
|
||||
|
||||
for (size_t k = 0; k < count; k++) {
|
||||
ScanI2C::DeviceType current = types[k];
|
||||
|
||||
if (exists(current)) {
|
||||
return ScanI2C::FoundDevice(current, deviceAddresses.at(current));
|
||||
}
|
||||
}
|
||||
|
||||
return DEVICE_NONE;
|
||||
}
|
||||
|
||||
ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
|
||||
{
|
||||
TwoWire *i2cBus = fetchI2CBus(addr);
|
||||
|
||||
uint8_t r = 0;
|
||||
uint8_t r_prev = 0;
|
||||
uint8_t c = 0;
|
||||
ScanI2C::DeviceType o_probe = ScanI2C::DeviceType::SCREEN_UNKNOWN;
|
||||
do {
|
||||
r_prev = r;
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
i2cBus->write((uint8_t)0x00);
|
||||
i2cBus->endTransmission();
|
||||
i2cBus->requestFrom((int)addr.address, 1);
|
||||
if (i2cBus->available()) {
|
||||
r = i2cBus->read();
|
||||
}
|
||||
r &= 0x0f;
|
||||
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
LOG_INFO("sh1106 display found\n");
|
||||
o_probe = SCREEN_SH1106; // SH1106
|
||||
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
|
||||
LOG_INFO("ssd1306 display found\n");
|
||||
o_probe = SCREEN_SSD1306; // SSD1306
|
||||
}
|
||||
c++;
|
||||
} while ((r != r_prev) && (c < 4));
|
||||
LOG_DEBUG("0x%x subtype probed in %i tries \n", r, c);
|
||||
|
||||
return o_probe;
|
||||
}
|
||||
void ScanI2CTwoWire::printATECCInfo() const
|
||||
{
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
atecc.readConfigZone(false);
|
||||
|
||||
LOG_DEBUG("ATECC608B Serial Number: ");
|
||||
for (int i = 0; i < 9; i++) {
|
||||
LOG_DEBUG("%02x", atecc.serialNumber[i]);
|
||||
}
|
||||
|
||||
LOG_DEBUG(", Rev Number: ");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LOG_DEBUG("%02x", atecc.revisionNumber[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
|
||||
LOG_DEBUG("ATECC608B Config %s", atecc.configLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Data %s", atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Slot 0 %s\n", atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||
|
||||
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
|
||||
if (atecc.generatePublicKey() == false) {
|
||||
LOG_DEBUG("ATECC608B Error generating public key\n");
|
||||
} else {
|
||||
LOG_DEBUG("ATECC608B Public Key: ");
|
||||
for (int i = 0; i < 64; i++) {
|
||||
LOG_DEBUG("%02x", atecc.publicKey64Bytes[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation ®isterLocation,
|
||||
ScanI2CTwoWire::ResponseWidth responseWidth) const
|
||||
{
|
||||
uint16_t value = 0x00;
|
||||
TwoWire *i2cBus = fetchI2CBus(registerLocation.i2cAddress);
|
||||
|
||||
i2cBus->beginTransmission(registerLocation.i2cAddress.address);
|
||||
i2cBus->write(registerLocation.registerAddress);
|
||||
i2cBus->endTransmission();
|
||||
delay(20);
|
||||
i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth);
|
||||
LOG_DEBUG("Wire.available() = %d\n", i2cBus->available());
|
||||
if (i2cBus->available() == 2) {
|
||||
// Read MSB, then LSB
|
||||
value = (uint16_t)i2cBus->read() << 8;
|
||||
value |= i2cBus->read();
|
||||
} else if (i2cBus->available()) {
|
||||
value = i2cBus->read();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
|
||||
case ADDR: \
|
||||
LOG_INFO(__VA_ARGS__); \
|
||||
type = T; \
|
||||
break;
|
||||
|
||||
void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
{
|
||||
concurrency::LockGuard guard((concurrency::Lock *)&lock);
|
||||
|
||||
LOG_DEBUG("Scanning for i2c devices on port %d\n", port);
|
||||
|
||||
uint8_t err;
|
||||
|
||||
DeviceAddress addr(port, 0x00);
|
||||
|
||||
uint16_t registerValue = 0x00;
|
||||
ScanI2C::DeviceType type;
|
||||
TwoWire *i2cBus;
|
||||
#ifdef RV3028_RTC
|
||||
Melopero_RV3028 rtc;
|
||||
#endif
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
if (port == I2CPort::WIRE1) {
|
||||
i2cBus = &Wire1;
|
||||
} else {
|
||||
#endif
|
||||
i2cBus = &Wire;
|
||||
#ifdef I2C_SDA1
|
||||
}
|
||||
#endif
|
||||
|
||||
for (addr.address = 1; addr.address < 127; addr.address++) {
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
err = i2cBus->endTransmission();
|
||||
type = NONE;
|
||||
if (err == 0) {
|
||||
LOG_DEBUG("I2C device found at address 0x%x\n", addr.address);
|
||||
|
||||
switch (addr.address) {
|
||||
case SSD1306_ADDRESS:
|
||||
type = probeOLED(addr);
|
||||
break;
|
||||
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
case ATECC608B_ADDR:
|
||||
type = ATECC608B;
|
||||
if (atecc.begin(addr.address) == true) {
|
||||
LOG_INFO("ATECC608B initialized\n");
|
||||
} else {
|
||||
LOG_WARN("ATECC608B initialization failed\n");
|
||||
}
|
||||
printATECCInfo();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef RV3028_RTC
|
||||
case RV3028_RTC:
|
||||
// foundDevices[addr] = RTC_RV3028;
|
||||
type = RTC_RV3028;
|
||||
LOG_INFO("RV3028 RTC found\n");
|
||||
rtc.initI2C(*i2cBus);
|
||||
rtc.writeToRegister(0x35, 0x07); // no Clkout
|
||||
rtc.writeToRegister(0x37, 0xB4);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef PCF8563_RTC
|
||||
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563 RTC found\n")
|
||||
#endif
|
||||
|
||||
case CARDKB_ADDR:
|
||||
// Do we have the RAK14006 instead?
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);
|
||||
if (registerValue == 0x02) {
|
||||
// KEYPAD_VERSION
|
||||
LOG_INFO("RAK14004 found\n");
|
||||
type = RAK14004;
|
||||
} else {
|
||||
LOG_INFO("m5 cardKB found\n");
|
||||
type = CARDKB;
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n")
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n");
|
||||
|
||||
#ifdef HAS_PMU
|
||||
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "axp192/axp2101 PMU found\n")
|
||||
#endif
|
||||
case BME_ADDR:
|
||||
case BME_ADDR_ALTERNATE:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
|
||||
switch (registerValue) {
|
||||
case 0x61:
|
||||
LOG_INFO("BME-680 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BME_680;
|
||||
break;
|
||||
case 0x60:
|
||||
LOG_INFO("BME-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BME_280;
|
||||
break;
|
||||
default:
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BMP_280;
|
||||
}
|
||||
break;
|
||||
|
||||
case INA_ADDR:
|
||||
case INA_ADDR_ALTERNATE:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA260 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = INA260;
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
LOG_INFO("INA219 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = INA219;
|
||||
}
|
||||
break;
|
||||
|
||||
case MCP9808_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||
if (registerValue == 0x0400) {
|
||||
type = MCP9808;
|
||||
LOG_INFO("MCP9808 sensor found\n");
|
||||
} else {
|
||||
type = LIS3DH;
|
||||
LOG_INFO("LIS3DH accelerometer found\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(SHT31_ADDR, SHT31, "SHT31 sensor found\n")
|
||||
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found\n")
|
||||
|
||||
case LPS22HB_ADDR_ALT:
|
||||
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found\n")
|
||||
|
||||
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found\n")
|
||||
SCAN_SIMPLE_CASE(QMI8658_ADDR, QMI8658, "QMI8658 Highrate 6-Axis inertial measurement sensor found\n")
|
||||
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n")
|
||||
|
||||
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
|
||||
SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n");
|
||||
|
||||
default:
|
||||
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
|
||||
}
|
||||
} else if (err == 4) {
|
||||
LOG_ERROR("Unknown error at address 0x%x\n", addr);
|
||||
}
|
||||
|
||||
// Check if a type was found for the enumerated device - save, if so
|
||||
if (type != NONE) {
|
||||
deviceAddresses[type] = addr;
|
||||
foundDevices[addr] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const
|
||||
{
|
||||
if (address.port == ScanI2C::I2CPort::WIRE1) {
|
||||
return &Wire;
|
||||
} else {
|
||||
#ifdef I2C_SDA1
|
||||
return &Wire1;
|
||||
#else
|
||||
return &Wire;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
size_t ScanI2CTwoWire::countDevices() const
|
||||
{
|
||||
return foundDevices.size();
|
||||
}
|
||||
56
src/detect/ScanI2CTwoWire.h
Normal file
56
src/detect/ScanI2CTwoWire.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
#include "ScanI2C.h"
|
||||
|
||||
#include "../concurrency/Lock.h"
|
||||
|
||||
class ScanI2CTwoWire : public ScanI2C
|
||||
{
|
||||
public:
|
||||
void scanPort(ScanI2C::I2CPort) override;
|
||||
|
||||
ScanI2C::FoundDevice find(ScanI2C::DeviceType) const override;
|
||||
|
||||
bool exists(ScanI2C::DeviceType) const override;
|
||||
|
||||
size_t countDevices() const override;
|
||||
|
||||
protected:
|
||||
FoundDevice firstOfOrNONE(size_t, DeviceType[]) const override;
|
||||
|
||||
private:
|
||||
typedef struct RegisterLocation {
|
||||
DeviceAddress i2cAddress;
|
||||
RegisterAddress registerAddress;
|
||||
|
||||
RegisterLocation(DeviceAddress deviceAddress, RegisterAddress registerAddress)
|
||||
: i2cAddress(deviceAddress), registerAddress(registerAddress)
|
||||
{
|
||||
}
|
||||
|
||||
} RegisterLocation;
|
||||
|
||||
typedef uint8_t ResponseWidth;
|
||||
|
||||
std::map<ScanI2C::DeviceAddress, ScanI2C::DeviceType> foundDevices;
|
||||
|
||||
// note: prone to overwriting if multiple devices of a type are added at different addresses (rare?)
|
||||
std::map<ScanI2C::DeviceType, ScanI2C::DeviceAddress> deviceAddresses;
|
||||
|
||||
concurrency::Lock lock;
|
||||
|
||||
void printATECCInfo() const;
|
||||
|
||||
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
|
||||
|
||||
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
|
||||
|
||||
TwoWire *fetchI2CBus(ScanI2C::DeviceAddress) const;
|
||||
};
|
||||
@@ -1,237 +0,0 @@
|
||||
#include "../configuration.h"
|
||||
#include "../main.h"
|
||||
#include "mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include <Wire.h>
|
||||
|
||||
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
|
||||
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
|
||||
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
|
||||
#endif
|
||||
|
||||
#if HAS_WIRE
|
||||
|
||||
void printATECCInfo()
|
||||
{
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
atecc.readConfigZone(false);
|
||||
|
||||
LOG_DEBUG("ATECC608B Serial Number: ");
|
||||
for (int i = 0; i < 9; i++) {
|
||||
LOG_DEBUG("%02x", atecc.serialNumber[i]);
|
||||
}
|
||||
|
||||
LOG_DEBUG(", Rev Number: ");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LOG_DEBUG("%02x", atecc.revisionNumber[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
|
||||
LOG_DEBUG("ATECC608B Config %s", atecc.configLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Data %s", atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Slot 0 %s\n", atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||
|
||||
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
|
||||
if (atecc.generatePublicKey() == false) {
|
||||
LOG_DEBUG("ATECC608B Error generating public key\n");
|
||||
} else {
|
||||
LOG_DEBUG("ATECC608B Public Key: ");
|
||||
for (int i = 0; i < 64; i++) {
|
||||
LOG_DEBUG("%02x", atecc.publicKey64Bytes[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length)
|
||||
{
|
||||
uint16_t value = 0x00;
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission();
|
||||
delay(20);
|
||||
Wire.requestFrom(address, length);
|
||||
LOG_DEBUG("Wire.available() = %d\n", Wire.available());
|
||||
if (Wire.available() == 2) {
|
||||
// Read MSB, then LSB
|
||||
value = (uint16_t)Wire.read() << 8;
|
||||
value |= Wire.read();
|
||||
} else if (Wire.available()) {
|
||||
value = Wire.read();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t oled_probe(byte addr)
|
||||
{
|
||||
uint8_t r = 0;
|
||||
uint8_t r_prev = 0;
|
||||
uint8_t c = 0;
|
||||
uint8_t o_probe = 0;
|
||||
do {
|
||||
r_prev = r;
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(0x00);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((int)addr, 1);
|
||||
if (Wire.available()) {
|
||||
r = Wire.read();
|
||||
}
|
||||
r &= 0x0f;
|
||||
|
||||
if (r == 0x08 || r == 0x00) {
|
||||
o_probe = 2; // SH1106
|
||||
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
|
||||
o_probe = 1; // SSD1306
|
||||
}
|
||||
c++;
|
||||
} while ((r != r_prev) && (c < 4));
|
||||
LOG_DEBUG("0x%x subtype probed in %i tries \n", r, c);
|
||||
return o_probe;
|
||||
}
|
||||
|
||||
void scanI2Cdevice()
|
||||
{
|
||||
byte err, addr;
|
||||
uint16_t registerValue = 0x00;
|
||||
int nDevices = 0;
|
||||
for (addr = 1; addr < 127; addr++) {
|
||||
Wire.beginTransmission(addr);
|
||||
err = Wire.endTransmission();
|
||||
if (err == 0) {
|
||||
LOG_DEBUG("I2C device found at address 0x%x\n", addr);
|
||||
|
||||
nDevices++;
|
||||
|
||||
if (addr == SSD1306_ADDRESS) {
|
||||
screen_found = addr;
|
||||
screen_model = oled_probe(addr);
|
||||
if (screen_model == 1) {
|
||||
LOG_INFO("ssd1306 display found\n");
|
||||
} else if (screen_model == 2) {
|
||||
LOG_INFO("sh1106 display found\n");
|
||||
} else {
|
||||
LOG_INFO("unknown display found\n");
|
||||
}
|
||||
}
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
if (addr == ATECC608B_ADDR) {
|
||||
keystore_found = addr;
|
||||
if (atecc.begin(keystore_found) == true) {
|
||||
LOG_INFO("ATECC608B initialized\n");
|
||||
} else {
|
||||
LOG_WARN("ATECC608B initialization failed\n");
|
||||
}
|
||||
printATECCInfo();
|
||||
}
|
||||
#endif
|
||||
#ifdef RV3028_RTC
|
||||
if (addr == RV3028_RTC) {
|
||||
rtc_found = addr;
|
||||
LOG_INFO("RV3028 RTC found\n");
|
||||
Melopero_RV3028 rtc;
|
||||
rtc.initI2C();
|
||||
rtc.writeToRegister(0x35, 0x07); // no Clkout
|
||||
rtc.writeToRegister(0x37, 0xB4);
|
||||
}
|
||||
#endif
|
||||
#ifdef PCF8563_RTC
|
||||
if (addr == PCF8563_RTC) {
|
||||
rtc_found = addr;
|
||||
LOG_INFO("PCF8563 RTC found\n");
|
||||
}
|
||||
#endif
|
||||
if (addr == CARDKB_ADDR) {
|
||||
cardkb_found = addr;
|
||||
// Do we have the RAK14006 instead?
|
||||
registerValue = getRegisterValue(addr, 0x04, 1);
|
||||
if (registerValue == 0x02) { // KEYPAD_VERSION
|
||||
LOG_INFO("RAK14004 found\n");
|
||||
kb_model = 0x02;
|
||||
} else {
|
||||
LOG_INFO("m5 cardKB found\n");
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
if (addr == ST7567_ADDRESS) {
|
||||
screen_found = addr;
|
||||
LOG_INFO("st7567 display found\n");
|
||||
}
|
||||
#ifdef HAS_PMU
|
||||
if (addr == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
||||
pmu_found = true;
|
||||
LOG_INFO("axp192/axp2101 PMU found\n");
|
||||
}
|
||||
#endif
|
||||
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
|
||||
if (registerValue == 0x61) {
|
||||
LOG_INFO("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BME680] = addr;
|
||||
} else if (registerValue == 0x60) {
|
||||
LOG_INFO("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BME280] = addr;
|
||||
} else {
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BMP280] = addr;
|
||||
}
|
||||
}
|
||||
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xFE, 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] = addr;
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
LOG_INFO("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] = addr;
|
||||
}
|
||||
}
|
||||
if (addr == MCP9808_ADDR) {
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MCP9808] = addr;
|
||||
LOG_INFO("MCP9808 sensor found\n");
|
||||
}
|
||||
if (addr == SHT31_ADDR) {
|
||||
LOG_INFO("SHT31 sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_SHT31] = addr;
|
||||
}
|
||||
if (addr == SHTC3_ADDR) {
|
||||
LOG_INFO("SHTC3 sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_SHTC3] = addr;
|
||||
}
|
||||
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
|
||||
LOG_INFO("LPS22HB sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_LPS22] = addr;
|
||||
}
|
||||
|
||||
// High rate sensors, will be processed internally
|
||||
if (addr == QMC6310_ADDR) {
|
||||
LOG_INFO("QMC6310 Highrate 3-Axis magnetic sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC6310] = addr;
|
||||
}
|
||||
if (addr == QMI8658_ADDR) {
|
||||
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMI8658] = addr;
|
||||
}
|
||||
if (addr == QMC5883L_ADDR) {
|
||||
LOG_INFO("QMC5883L Highrate 3-Axis magnetic sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC5883L] = addr;
|
||||
}
|
||||
if (addr == PMSA0031_ADDR) {
|
||||
LOG_INFO("PMSA0031 air quality sensor found\n");
|
||||
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I] = addr;
|
||||
}
|
||||
} else if (err == 4) {
|
||||
LOG_ERROR("Unknow error at address 0x%x\n", addr);
|
||||
}
|
||||
}
|
||||
|
||||
if (nDevices == 0)
|
||||
LOG_INFO("No I2C devices found\n");
|
||||
else
|
||||
LOG_INFO("%i I2C devices found\n", nDevices);
|
||||
}
|
||||
#else
|
||||
void scanI2Cdevice() {}
|
||||
#endif
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "NMEAWPL.h"
|
||||
#include "GeoCoord.h"
|
||||
#include "RTC.h"
|
||||
#include <time.h>
|
||||
|
||||
/* -------------------------------------------
|
||||
* 1 2 3 4 5 6
|
||||
@@ -56,12 +58,18 @@ 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);
|
||||
uint32_t len =
|
||||
snprintf(buf, bufsz, "$GNGGA,%06u.%03u,%02d%07.4f,%c,%03d%07.4f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d", pos.time / 1000,
|
||||
pos.time % 1000, geoCoord.getDMSLatDeg(), (abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6,
|
||||
geoCoord.getDMSLatCP(), geoCoord.getDMSLonDeg(),
|
||||
(abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6, geoCoord.getDMSLonCP(), pos.fix_type,
|
||||
pos.sats_in_view, pos.HDOP, geoCoord.getAltitude(), 'M', pos.altitude_geoidal_separation, 'M', 0, 0);
|
||||
tm *t = localtime((time_t *)&pos.timestamp);
|
||||
if (getRTCQuality() > 0) { // use the device clock if we got time from somewhere. If not, use the GPS timestamp.
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice);
|
||||
t = localtime((time_t *)&rtc_sec);
|
||||
}
|
||||
|
||||
uint32_t len = snprintf(
|
||||
buf, bufsz, "$GNGGA,%02d%02d%02d.%02d,%02d%07.4f,%c,%03d%07.4f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d", t->tm_hour,
|
||||
t->tm_min, t->tm_sec, pos.timestamp_millis_adjust, geoCoord.getDMSLatDeg(),
|
||||
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(), geoCoord.getDMSLonDeg(),
|
||||
(abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6, geoCoord.getDMSLonCP(), pos.fix_quality,
|
||||
pos.sats_in_view, pos.HDOP, geoCoord.getAltitude(), 'M', pos.altitude_geoidal_separation, 'M', 0, 0);
|
||||
|
||||
uint32_t chk = 0;
|
||||
for (uint32_t i = 1; i < len; i++) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "RTC.h"
|
||||
#include "configuration.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "main.h"
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@@ -20,10 +21,14 @@ void readFromRTC()
|
||||
{
|
||||
struct timeval tv; /* btw settimeofday() is helpfull here too*/
|
||||
#ifdef RV3028_RTC
|
||||
if (rtc_found == RV3028_RTC) {
|
||||
if (rtc_found.address == RV3028_RTC) {
|
||||
uint32_t now = millis();
|
||||
Melopero_RV3028 rtc;
|
||||
#ifdef I2C_SDA1
|
||||
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.initI2C();
|
||||
#endif
|
||||
tm t;
|
||||
t.tm_year = rtc.getYear() - 1900;
|
||||
t.tm_mon = rtc.getMonth() - 1;
|
||||
@@ -41,14 +46,16 @@ void readFromRTC()
|
||||
}
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
if (rtc_found == PCF8563_RTC) {
|
||||
if (rtc_found.address == PCF8563_RTC) {
|
||||
uint32_t now = millis();
|
||||
PCF8563_Class rtc;
|
||||
#ifdef RTC_USE_WIRE1
|
||||
rtc.begin(Wire1);
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.begin();
|
||||
#endif
|
||||
|
||||
auto tc = rtc.getDateTime();
|
||||
tm t;
|
||||
t.tm_year = tc.year - 1900;
|
||||
@@ -103,19 +110,24 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||
|
||||
// If this platform has a setable RTC, set it
|
||||
#ifdef RV3028_RTC
|
||||
if (rtc_found == RV3028_RTC) {
|
||||
if (rtc_found.address == RV3028_RTC) {
|
||||
Melopero_RV3028 rtc;
|
||||
#ifdef I2C_SDA1
|
||||
rtc.initI2C(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.initI2C();
|
||||
#endif
|
||||
tm *t = localtime(&tv->tv_sec);
|
||||
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
if (rtc_found == PCF8563_RTC) {
|
||||
if (rtc_found.address == PCF8563_RTC) {
|
||||
PCF8563_Class rtc;
|
||||
#ifdef RTC_USE_WIRE1
|
||||
rtc.begin(Wire1);
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
|
||||
#else
|
||||
rtc.begin();
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
// 1.54 inch 200x200 - GxEPD2_154_M09
|
||||
//#define TECHO_DISPLAY_MODEL GxEPD2_154_M09
|
||||
|
||||
#elif defined(MAKERPYTHON)
|
||||
// 2.9 inch 296x128 - GxEPD2_290_T5D
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_290_T5D
|
||||
|
||||
#elif defined(PCA10059)
|
||||
|
||||
// 4.2 inch 300x400 - GxEPD2_420_M01
|
||||
@@ -41,7 +45,7 @@
|
||||
|
||||
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
|
||||
|
||||
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model)
|
||||
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
|
||||
{
|
||||
#if defined(TTGO_T_ECHO)
|
||||
setGeometry(GEOMETRY_RAWMODE, TECHO_DISPLAY_MODEL::WIDTH, TECHO_DISPLAY_MODEL::HEIGHT);
|
||||
@@ -58,6 +62,9 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model
|
||||
|
||||
// GxEPD2_154_M09
|
||||
// setGeometry(GEOMETRY_RAWMODE, 200, 200);
|
||||
#elif defined(MAKERPYTHON)
|
||||
// GxEPD2_290_T5D
|
||||
setGeometry(GEOMETRY_RAWMODE, 296, 128);
|
||||
|
||||
#elif defined(PCA10059)
|
||||
|
||||
@@ -69,6 +76,11 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model
|
||||
// M5Stack_CoreInk 200x200
|
||||
// 1.54 inch 200x200 - GxEPD2_154_M09
|
||||
setGeometry(GEOMETRY_RAWMODE, EPD_HEIGHT, EPD_WIDTH);
|
||||
#elif defined(my)
|
||||
|
||||
// GxEPD2_290_T5D
|
||||
setGeometry(GEOMETRY_RAWMODE, 296, 128);
|
||||
LOG_DEBUG("GEOMETRY_RAWMODE, 296, 128\n");
|
||||
|
||||
#endif
|
||||
// setGeometry(GEOMETRY_RAWMODE, 128, 64); // old resolution
|
||||
@@ -109,7 +121,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
#if defined(TTGO_T_ECHO)
|
||||
// ePaper.Reset(); // wake the screen from sleep
|
||||
adafruitDisplay->display(false); // FIXME, use partial update mode
|
||||
#elif defined(RAK4630)
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
|
||||
// RAK14000 2.13 inch b/w 250x122 actually now does support partial updates
|
||||
|
||||
@@ -125,6 +137,10 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
|
||||
#elif defined(PCA10059) || defined(M5_COREINK)
|
||||
adafruitDisplay->nextPage();
|
||||
|
||||
#elif defined(PRIVATE_HW) || defined(my)
|
||||
adafruitDisplay->nextPage();
|
||||
|
||||
#endif
|
||||
|
||||
// Put screen to sleep to save power (possibly not necessary because we already did poweroff inside of display)
|
||||
@@ -184,7 +200,7 @@ bool EInkDisplay::connect()
|
||||
adafruitDisplay->init();
|
||||
adafruitDisplay->setRotation(3);
|
||||
}
|
||||
#elif defined(RAK4630)
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
{
|
||||
if (eink_found) {
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
@@ -216,6 +232,14 @@ bool EInkDisplay::connect()
|
||||
adafruitDisplay->init(115200, true, 40, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
adafruitDisplay->setRotation(0);
|
||||
adafruitDisplay->setPartialWindow(0, 0, EPD_WIDTH, EPD_HEIGHT);
|
||||
#elif defined(my)
|
||||
{
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
adafruitDisplay->init(115200, true, 40, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
adafruitDisplay->setRotation(1);
|
||||
adafruitDisplay->setPartialWindow(0, 0, EPD_WIDTH, EPD_HEIGHT);
|
||||
}
|
||||
#endif
|
||||
|
||||
// adafruitDisplay->setFullWindow();
|
||||
|
||||
@@ -22,7 +22,7 @@ class EInkDisplay : public OLEDDisplay
|
||||
/* constructor
|
||||
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
|
||||
*/
|
||||
EInkDisplay(uint8_t address, int sda, int scl, uint8_t screen_model);
|
||||
EInkDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
|
||||
|
||||
// Write the buffer to the display memory (for eink we only do this occasionally)
|
||||
virtual void display(void) override;
|
||||
|
||||
@@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "Screen.h"
|
||||
#include "configuration.h"
|
||||
#if HAS_SCREEN
|
||||
#include <OLEDDisplay.h>
|
||||
@@ -26,7 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "GPS.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "Screen.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
#include "gps/RTC.h"
|
||||
#include "graphics/images.h"
|
||||
@@ -348,8 +348,6 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
/// Draw the last text message we received
|
||||
static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
|
||||
@@ -370,8 +368,6 @@ static bool shouldDrawMessage(const meshtastic_MeshPacket *packet)
|
||||
/// Draw the last text message we received
|
||||
static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
// the max length of this buffer is much longer than we can possibly print
|
||||
static char tempBuf[237];
|
||||
|
||||
@@ -408,6 +404,43 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), tempBuf);
|
||||
}
|
||||
|
||||
/// Draw the last waypoint we received
|
||||
static void drawWaypointFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
static char tempBuf[237];
|
||||
|
||||
meshtastic_MeshPacket &mp = devicestate.rx_waypoint;
|
||||
meshtastic_NodeInfo *node = nodeDB.getNode(getFrom(&mp));
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
|
||||
uint32_t seconds = sinceReceived(&mp);
|
||||
uint32_t minutes = seconds / 60;
|
||||
uint32_t hours = minutes / 60;
|
||||
uint32_t days = hours / 24;
|
||||
|
||||
if (config.display.heading_bold) {
|
||||
display->drawStringf(1 + x, 0 + y, tempBuf, "%s ago from %s",
|
||||
screen->drawTimeDelta(days, hours, minutes, seconds).c_str(),
|
||||
(node && node->has_user) ? node->user.short_name : "???");
|
||||
}
|
||||
display->drawStringf(0 + x, 0 + y, tempBuf, "%s ago from %s", screen->drawTimeDelta(days, hours, minutes, seconds).c_str(),
|
||||
(node && node->has_user) ? node->user.short_name : "???");
|
||||
|
||||
display->setColor(WHITE);
|
||||
meshtastic_Waypoint scratch;
|
||||
memset(&scratch, 0, sizeof(scratch));
|
||||
if (pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, &meshtastic_Waypoint_msg, &scratch)) {
|
||||
snprintf(tempBuf, sizeof(tempBuf), "Received waypoint: %s", scratch.name);
|
||||
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), tempBuf);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a series of fields in a column, wrapping to multiple colums if needed
|
||||
static void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char **fields)
|
||||
{
|
||||
@@ -773,7 +806,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
nodeIndex = (nodeIndex + 1) % nodeDB.getNumNodes();
|
||||
n = nodeDB.getNodeByIndex(nodeIndex);
|
||||
}
|
||||
displayedNodeNum = n->num;
|
||||
}
|
||||
|
||||
meshtastic_NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex);
|
||||
@@ -886,13 +918,11 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
// }
|
||||
// }
|
||||
// #else
|
||||
Screen::Screen(uint8_t address, int sda, int scl)
|
||||
: OSThread("Screen"), cmdQueue(32),
|
||||
dispdev(address, sda, scl,
|
||||
screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 ? GEOMETRY_128_128 : GEOMETRY_128_64),
|
||||
Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_OledType screenType, OLEDDISPLAY_GEOMETRY geometry)
|
||||
: concurrency::OSThread("Screen"), address_found(address), model(screenType), geometry(geometry), cmdQueue(32),
|
||||
dispdev(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE),
|
||||
ui(&dispdev)
|
||||
{
|
||||
address_found = address;
|
||||
cmdQueue.setReader(this);
|
||||
}
|
||||
// #endif
|
||||
@@ -940,9 +970,11 @@ void Screen::setup()
|
||||
useDisplay = true;
|
||||
|
||||
#ifdef AutoOLEDWire_h
|
||||
if (screen_model == meshtastic_Config_DisplayConfig_OledType_OLED_SH1107)
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1106;
|
||||
dispdev.setDetected(screen_model);
|
||||
dispdev.setDetected(model);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SH1107_128_64
|
||||
dispdev.setSubtype(7);
|
||||
#endif
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
@@ -1177,7 +1209,7 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat
|
||||
* it is expected that this will be used during the boot phase */
|
||||
void Screen::setSSLFrames()
|
||||
{
|
||||
if (address_found) {
|
||||
if (address_found.address) {
|
||||
// LOG_DEBUG("showing SSL frames\n");
|
||||
static FrameCallback sslFrames[] = {drawSSLScreen};
|
||||
ui.setFrames(sslFrames, 1);
|
||||
@@ -1189,7 +1221,7 @@ void Screen::setSSLFrames()
|
||||
* it is expected that this will be used during the boot phase */
|
||||
void Screen::setWelcomeFrames()
|
||||
{
|
||||
if (address_found) {
|
||||
if (address_found.address) {
|
||||
// LOG_DEBUG("showing Welcome frames\n");
|
||||
ui.disableAllIndicators();
|
||||
|
||||
@@ -1211,7 +1243,7 @@ void Screen::setFrames()
|
||||
LOG_DEBUG("Total frame count: %d\n", totalFrameCount);
|
||||
|
||||
// We don't show the node info our our node (if we have it yet - we should)
|
||||
size_t numnodes = nodeStatus->getNumTotal();
|
||||
size_t numnodes = nodeDB.getNumNodes();
|
||||
if (numnodes > 0)
|
||||
numnodes--;
|
||||
|
||||
@@ -1237,6 +1269,10 @@ void Screen::setFrames()
|
||||
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) {
|
||||
normalFrames[numframes++] = drawTextMessageFrame;
|
||||
}
|
||||
// If we have a waypoint - show it next, unless it's a phone message and we aren't using any special modules
|
||||
if (devicestate.has_rx_waypoint && shouldDrawMessage(&devicestate.rx_waypoint)) {
|
||||
normalFrames[numframes++] = drawWaypointFrame;
|
||||
}
|
||||
|
||||
// then all the nodes
|
||||
// We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens
|
||||
@@ -1393,8 +1429,6 @@ void Screen::setFastFramerate()
|
||||
|
||||
void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
@@ -1502,8 +1536,6 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
#if HAS_WIFI
|
||||
const char *wifiName = config.network.wifi_ssid;
|
||||
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
@@ -1634,8 +1666,6 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
|
||||
void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
@@ -1821,5 +1851,6 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
}
|
||||
|
||||
} // namespace graphics
|
||||
|
||||
#else
|
||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||
#endif // HAS_SCREEN
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "mesh/generated/meshtastic/config.pb.h"
|
||||
#include <OLEDDisplay.h>
|
||||
|
||||
#if !HAS_SCREEN
|
||||
#include "power.h"
|
||||
namespace graphics
|
||||
@@ -10,7 +14,7 @@ namespace graphics
|
||||
class Screen
|
||||
{
|
||||
public:
|
||||
explicit Screen(char) {}
|
||||
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
||||
void onPress() {}
|
||||
void setup() {}
|
||||
void setOn(bool) {}
|
||||
@@ -21,10 +25,10 @@ class Screen
|
||||
void startBluetoothPinScreen(uint32_t pin) {}
|
||||
void stopBluetoothPinScreen() {}
|
||||
void startRebootScreen() {}
|
||||
void startShutdownScreen() {}
|
||||
void startFirmwareUpdateScreen() {}
|
||||
};
|
||||
} // namespace graphics
|
||||
|
||||
#else
|
||||
#include <cstring>
|
||||
|
||||
@@ -34,7 +38,7 @@ class Screen
|
||||
|
||||
#ifdef USE_ST7567
|
||||
#include <ST7567Wire.h>
|
||||
#elif defined(USE_SH1106) || defined(USE_SH1107)
|
||||
#elif defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
#include <SH1106Wire.h>
|
||||
#elif defined(USE_SSD1306)
|
||||
#include <SSD1306Wire.h>
|
||||
@@ -116,12 +120,14 @@ class Screen : public concurrency::OSThread
|
||||
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
|
||||
|
||||
public:
|
||||
explicit Screen(uint8_t address, int sda = -1, int scl = -1);
|
||||
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
||||
|
||||
Screen(const Screen &) = delete;
|
||||
Screen &operator=(const Screen &) = delete;
|
||||
|
||||
uint8_t address_found;
|
||||
ScanI2C::DeviceAddress address_found;
|
||||
meshtastic_Config_DisplayConfig_OledType model;
|
||||
OLEDDISPLAY_GEOMETRY geometry;
|
||||
|
||||
/// Initializes the UI, turns on the display, starts showing boot screen.
|
||||
//
|
||||
@@ -370,7 +376,7 @@ class Screen : public concurrency::OSThread
|
||||
|
||||
/// Display device
|
||||
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107)
|
||||
#if defined(USE_SH1106) || defined(USE_SH1107) || defined(USE_SH1107_128_64)
|
||||
SH1106Wire dispdev;
|
||||
#elif defined(USE_SSD1306)
|
||||
SSD1306Wire dispdev;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h
|
||||
|
||||
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, uint8_t screen_model)
|
||||
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
|
||||
{
|
||||
#ifdef SCREEN_ROTATE
|
||||
setGeometry(GEOMETRY_RAWMODE, TFT_HEIGHT, TFT_WIDTH);
|
||||
|
||||
@@ -18,7 +18,7 @@ class TFTDisplay : public OLEDDisplay
|
||||
/* constructor
|
||||
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
|
||||
*/
|
||||
TFTDisplay(uint8_t address, int sda, int scl, uint8_t screen_model);
|
||||
TFTDisplay(uint8_t, int, int, OLEDDISPLAY_GEOMETRY, HW_I2C);
|
||||
|
||||
// Write the buffer to the display memory
|
||||
virtual void display(void) override;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "mesh/NodeDB.h"
|
||||
|
||||
enum RotaryEncoderInterruptBaseStateType { ROTARY_EVENT_OCCURRED, ROTARY_EVENT_CLEARED };
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
#include "mesh/NodeDB.h"
|
||||
|
||||
class UpDownInterruptBase : public Observable<const InputEvent *>
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
|
||||
|
||||
void CardKbI2cImpl::init()
|
||||
{
|
||||
if (cardkb_found != CARDKB_ADDR) {
|
||||
if (cardkb_found.address != CARDKB_ADDR) {
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "kbI2cBase.h"
|
||||
#include "configuration.h"
|
||||
#include <Wire.h>
|
||||
|
||||
extern uint8_t cardkb_found;
|
||||
#include "configuration.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
|
||||
extern ScanI2C::DeviceAddress cardkb_found;
|
||||
extern uint8_t kb_model;
|
||||
|
||||
KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
||||
@@ -10,43 +11,64 @@ KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
||||
this->_originName = name;
|
||||
}
|
||||
|
||||
uint8_t read_from_14004(uint8_t reg, uint8_t *data, uint8_t length)
|
||||
uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t length)
|
||||
{
|
||||
uint8_t readflag = 0;
|
||||
Wire.beginTransmission(CARDKB_ADDR);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission(); // stop transmitting
|
||||
i2cBus->beginTransmission(CARDKB_ADDR);
|
||||
i2cBus->write(reg);
|
||||
i2cBus->endTransmission(); // stop transmitting
|
||||
delay(20);
|
||||
Wire.requestFrom(CARDKB_ADDR, (int)length);
|
||||
i2cBus->requestFrom(CARDKB_ADDR, (int)length);
|
||||
int i = 0;
|
||||
while (Wire.available()) // slave may send less than requested
|
||||
while (i2cBus->available()) // slave may send less than requested
|
||||
{
|
||||
data[i++] = Wire.read(); // receive a byte as a proper uint8_t
|
||||
data[i++] = i2cBus->read(); // receive a byte as a proper uint8_t
|
||||
readflag = 1;
|
||||
}
|
||||
return readflag;
|
||||
}
|
||||
|
||||
void write_to_14004(uint8_t reg, uint8_t data)
|
||||
// Unused for now - flagging it off
|
||||
#if 0
|
||||
void write_to_14004(const TwoWire * i2cBus, uint8_t reg, uint8_t data)
|
||||
{
|
||||
Wire.beginTransmission(CARDKB_ADDR);
|
||||
Wire.write(reg);
|
||||
Wire.write(data);
|
||||
Wire.endTransmission(); // stop transmitting
|
||||
i2cBus->beginTransmission(CARDKB_ADDR);
|
||||
i2cBus->write(reg);
|
||||
i2cBus->write(data);
|
||||
i2cBus->endTransmission(); // stop transmitting
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t KbI2cBase::runOnce()
|
||||
{
|
||||
if (cardkb_found != CARDKB_ADDR) {
|
||||
if (cardkb_found.address != CARDKB_ADDR) {
|
||||
// Input device is not detected.
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
if (!i2cBus) {
|
||||
switch (cardkb_found.port) {
|
||||
case ScanI2C::WIRE1:
|
||||
#ifdef I2C_SDA1
|
||||
LOG_DEBUG("Using I2C Bus 1 (the second one)\n");
|
||||
i2cBus = &Wire1;
|
||||
break;
|
||||
#endif
|
||||
case ScanI2C::WIRE:
|
||||
LOG_DEBUG("Using I2C Bus 0 (the first one)\n");
|
||||
i2cBus = &Wire;
|
||||
break;
|
||||
case ScanI2C::NO_I2C:
|
||||
default:
|
||||
i2cBus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (kb_model == 0x02) {
|
||||
// RAK14004
|
||||
uint8_t rDataBuf[8] = {0};
|
||||
uint8_t PrintDataBuf = 0;
|
||||
if (read_from_14004(0x01, rDataBuf, 0x04) == 1) {
|
||||
if (read_from_14004(i2cBus, 0x01, rDataBuf, 0x04) == 1) {
|
||||
for (uint8_t aCount = 0; aCount < 0x04; aCount++) {
|
||||
for (uint8_t bCount = 0; bCount < 0x04; bCount++) {
|
||||
if (((rDataBuf[aCount] >> bCount) & 0x01) == 0x01) {
|
||||
@@ -65,10 +87,10 @@ int32_t KbI2cBase::runOnce()
|
||||
}
|
||||
} else {
|
||||
// m5 cardkb
|
||||
Wire.requestFrom(CARDKB_ADDR, 1);
|
||||
i2cBus->requestFrom(CARDKB_ADDR, 1);
|
||||
|
||||
while (Wire.available()) {
|
||||
char c = Wire.read();
|
||||
while (i2cBus->available()) {
|
||||
char c = i2cBus->read();
|
||||
InputEvent e;
|
||||
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
e.source = this->_originName;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "SinglePortModule.h" // TODO: what header file to include?
|
||||
#include "Wire.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
|
||||
class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||
{
|
||||
@@ -13,4 +14,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
|
||||
|
||||
private:
|
||||
const char *_originName;
|
||||
|
||||
TwoWire *i2cBus = 0;
|
||||
};
|
||||
|
||||
222
src/main.cpp
222
src/main.cpp
@@ -15,16 +15,19 @@
|
||||
#include "SPILock.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "detect/ScanI2CTwoWire.h"
|
||||
#include "detect/axpDebug.h"
|
||||
#include "detect/einkScan.h"
|
||||
#include "detect/i2cScan.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "mesh/generated/meshtastic/config.pb.h"
|
||||
#include "modules/Modules.h"
|
||||
#include "shutdown.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
#include <Wire.h>
|
||||
#include <memory>
|
||||
// #include <driver/rtc_io.h>
|
||||
|
||||
#include "mesh/eth/ethClient.h"
|
||||
@@ -65,6 +68,10 @@ NRF52Bluetooth *nrf52Bluetooth;
|
||||
#endif
|
||||
#include "PowerFSMThread.h"
|
||||
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
#include "AccelerometerThread.h"
|
||||
#endif
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
// We always create a screen object, but we only init it if we find the hardware
|
||||
@@ -79,20 +86,23 @@ meshtastic::GPSStatus *gpsStatus = new meshtastic::GPSStatus();
|
||||
// Global Node status
|
||||
meshtastic::NodeStatus *nodeStatus = new meshtastic::NodeStatus();
|
||||
|
||||
// Scan for I2C Devices
|
||||
|
||||
/// The I2C address of our display (if found)
|
||||
uint8_t screen_found;
|
||||
uint8_t screen_model;
|
||||
ScanI2C::DeviceAddress screen_found = ScanI2C::ADDRESS_NONE;
|
||||
|
||||
// The I2C address of the cardkb or RAK14004 (if found)
|
||||
uint8_t cardkb_found;
|
||||
ScanI2C::DeviceAddress cardkb_found = ScanI2C::ADDRESS_NONE;
|
||||
// 0x02 for RAK14004 and 0x00 for cardkb
|
||||
uint8_t kb_model;
|
||||
|
||||
// The I2C address of the RTC Module (if found)
|
||||
uint8_t rtc_found;
|
||||
ScanI2C::DeviceAddress rtc_found = ScanI2C::ADDRESS_NONE;
|
||||
// The I2C address of the Accelerometer (if found)
|
||||
ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE;
|
||||
// The I2C address of the RGB LED (if found)
|
||||
ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ScanI2C::ADDRESS_NONE);
|
||||
|
||||
// Keystore Chips
|
||||
uint8_t keystore_found;
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
ATECCX08A atecc;
|
||||
#endif
|
||||
@@ -134,17 +144,6 @@ static int32_t ledBlinker()
|
||||
|
||||
setLed(ledOn);
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
auto newHeap = ESP.getFreeHeap();
|
||||
if (newHeap < 11000) {
|
||||
LOG_DEBUG("\n\n====== heap too low [11000] -> reboot in 1s ======\n\n");
|
||||
#ifdef HAS_SCREEN
|
||||
screen->startRebootScreen();
|
||||
#endif
|
||||
rebootAtMsec = millis() + 900;
|
||||
}
|
||||
#endif
|
||||
|
||||
// have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that
|
||||
return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000);
|
||||
}
|
||||
@@ -161,6 +160,8 @@ static OSThread *powerFSMthread;
|
||||
static OSThread *buttonThread;
|
||||
uint32_t ButtonThread::longPressTime = 0;
|
||||
#endif
|
||||
static OSThread *accelerometerThread;
|
||||
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
|
||||
|
||||
RadioInterface *rIf = NULL;
|
||||
|
||||
@@ -175,6 +176,9 @@ __attribute__((weak, noinline)) bool loopCanSleep()
|
||||
void setup()
|
||||
{
|
||||
concurrency::hasBeenSetup = true;
|
||||
meshtastic_Config_DisplayConfig_OledType screen_model =
|
||||
meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
|
||||
OLEDDISPLAY_GEOMETRY screen_geometry = GEOMETRY_128_64;
|
||||
|
||||
#ifdef SEGGER_STDOUT_CH
|
||||
auto mode = false ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM;
|
||||
@@ -217,10 +221,10 @@ void setup()
|
||||
|
||||
// If the button is connected to GPIO 12, don't enable the ability to use
|
||||
// meshtasticAdmin on the device.
|
||||
pinMode(BUTTON_PIN, INPUT);
|
||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT);
|
||||
|
||||
#ifdef BUTTON_NEED_PULLUP
|
||||
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
||||
gpio_pullup_en((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
|
||||
delay(10);
|
||||
#endif
|
||||
|
||||
@@ -233,8 +237,6 @@ void setup()
|
||||
|
||||
fsInit();
|
||||
|
||||
router = new ReliableRouter();
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
Wire1.begin(I2C_SDA1, I2C_SCL1);
|
||||
#endif
|
||||
@@ -261,23 +263,126 @@ void setup()
|
||||
#endif
|
||||
|
||||
// Currently only the tbeam has a PMU
|
||||
// PMU initialization needs to be placed before scanI2Cdevice
|
||||
// PMU initialization needs to be placed before i2c scanning
|
||||
power = new Power();
|
||||
power->setStatusHandler(powerStatus);
|
||||
powerStatus->observe(&power->newStatus);
|
||||
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
|
||||
|
||||
#ifdef LILYGO_TBEAM_S3_CORE
|
||||
// In T-Beam-S3-core, the I2C device cannot be scanned before power initialization, otherwise the device will be stuck
|
||||
// PCF8563 RTC in tbeam-s3 uses Wire1 to share I2C bus
|
||||
Wire1.beginTransmission(PCF8563_RTC);
|
||||
if (Wire1.endTransmission() == 0) {
|
||||
rtc_found = PCF8563_RTC;
|
||||
LOG_INFO("PCF8563 RTC found\n");
|
||||
// We need to scan here to decide if we have a screen for nodeDB.init() and because power has been applied to
|
||||
// accessories
|
||||
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
|
||||
|
||||
LOG_INFO("Scanning for i2c devices...\n");
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
Wire1.begin(I2C_SDA1, I2C_SCL1);
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1);
|
||||
#endif
|
||||
|
||||
#ifdef I2C_SDA
|
||||
Wire.begin(I2C_SDA, I2C_SCL);
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
#elif HAS_WIRE
|
||||
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
|
||||
#endif
|
||||
|
||||
auto i2cCount = i2cScanner->countDevices();
|
||||
if (i2cCount == 0) {
|
||||
LOG_INFO("No I2C devices found\n");
|
||||
} else {
|
||||
LOG_INFO("%i I2C devices found\n", i2cCount);
|
||||
}
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Don't init display if we don't have one or we are waking headless due to a timer event
|
||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER) {
|
||||
LOG_DEBUG("suppress screen wake because this is a headless timer wakeup");
|
||||
i2cScanner->setSuppressScreen();
|
||||
}
|
||||
#endif
|
||||
// We need to scan here to decide if we have a screen for nodeDB.init()
|
||||
scanI2Cdevice();
|
||||
|
||||
auto screenInfo = i2cScanner->firstScreen();
|
||||
screen_found = screenInfo.type != ScanI2C::DeviceType::NONE ? screenInfo.address : ScanI2C::ADDRESS_NONE;
|
||||
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C) {
|
||||
switch (screenInfo.type) {
|
||||
case ScanI2C::DeviceType::SCREEN_SH1106:
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_SH1106;
|
||||
break;
|
||||
case ScanI2C::DeviceType::SCREEN_SSD1306:
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_SSD1306;
|
||||
break;
|
||||
case ScanI2C::DeviceType::SCREEN_ST7567:
|
||||
case ScanI2C::DeviceType::SCREEN_UNKNOWN:
|
||||
default:
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
#define UPDATE_FROM_SCANNER(FIND_FN)
|
||||
|
||||
auto rtc_info = i2cScanner->firstRTC();
|
||||
rtc_found = rtc_info.type != ScanI2C::DeviceType::NONE ? rtc_info.address : rtc_found;
|
||||
|
||||
auto kb_info = i2cScanner->firstKeyboard();
|
||||
|
||||
if (kb_info.type != ScanI2C::DeviceType::NONE) {
|
||||
cardkb_found = kb_info.address;
|
||||
switch (kb_info.type) {
|
||||
case ScanI2C::DeviceType::RAK14004:
|
||||
kb_model = 0x02;
|
||||
break;
|
||||
case ScanI2C::DeviceType::CARDKB:
|
||||
default:
|
||||
// use this as default since it's also just zero
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
pmu_found = i2cScanner->exists(ScanI2C::DeviceType::PMU_AXP192_AXP2101);
|
||||
|
||||
/*
|
||||
* There are a bunch of sensors that have no further logic than to be found and stuffed into the
|
||||
* nodeTelemetrySensorsMap singleton. This wraps that logic in a temporary scope to declare the temporary field
|
||||
* "found".
|
||||
*/
|
||||
// Only one supported RGB LED currently
|
||||
rgb_found = i2cScanner->find(ScanI2C::DeviceType::NCP5623);
|
||||
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
auto acc_info = i2cScanner->firstAccelerometer();
|
||||
accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found;
|
||||
LOG_DEBUG("acc_info = %i\n", acc_info.type);
|
||||
#endif
|
||||
|
||||
#define STRING(S) #S
|
||||
|
||||
#define SCANNER_TO_SENSORS_MAP(SCANNER_T, PB_T) \
|
||||
{ \
|
||||
auto found = i2cScanner->find(SCANNER_T); \
|
||||
if (found.type != ScanI2C::DeviceType::NONE) { \
|
||||
nodeTelemetrySensorsMap[PB_T] = found.address.address; \
|
||||
LOG_DEBUG("found i2c sensor %s\n", STRING(PB_T)); \
|
||||
} \
|
||||
}
|
||||
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280)
|
||||
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::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22)
|
||||
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::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I)
|
||||
|
||||
i2cScanner.reset();
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
setupSDCard();
|
||||
@@ -287,10 +392,7 @@ void setup()
|
||||
// scanEInkDevice();
|
||||
#endif
|
||||
|
||||
#if HAS_BUTTON
|
||||
// Buttons & LED
|
||||
buttonThread = new ButtonThread();
|
||||
#endif
|
||||
// LED init
|
||||
|
||||
#ifdef LED_PIN
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
@@ -301,10 +403,6 @@ void setup()
|
||||
LOG_INFO("Meshtastic hwvendor=%d, swver=%s\n", HW_VENDOR, optstr(APP_VERSION));
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Don't init display if we don't have one or we are waking headless due to a timer event
|
||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER)
|
||||
screen_found = 0; // forget we even have the hardware
|
||||
|
||||
esp32Setup();
|
||||
#endif
|
||||
|
||||
@@ -318,6 +416,13 @@ void setup()
|
||||
// If we're taking on the repeater role, use flood router
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
|
||||
router = new FloodingRouter();
|
||||
else
|
||||
router = new ReliableRouter();
|
||||
|
||||
#if HAS_BUTTON
|
||||
// Buttons. Moved here cause we need NodeDB to be initialized
|
||||
buttonThread = new ButtonThread();
|
||||
#endif
|
||||
|
||||
playStartMelody();
|
||||
|
||||
@@ -326,7 +431,18 @@ void setup()
|
||||
screen_model = config.display.oled;
|
||||
|
||||
#if defined(USE_SH1107)
|
||||
screen_model = Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
|
||||
display_geometry = GEOMETRY_128_128;
|
||||
#endif
|
||||
|
||||
#if defined(USE_SH1107_128_64)
|
||||
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // keep dimension of 128x64
|
||||
#endif
|
||||
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
if (acc_info.type != ScanI2C::DeviceType::NONE) {
|
||||
accelerometerThread = new AccelerometerThread(acc_info.type);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Init our SPI controller (must be before screen and lora)
|
||||
@@ -340,7 +456,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
// Initialize the screen first so we can show the logo while we start up everything else.
|
||||
screen = new graphics::Screen(screen_found);
|
||||
screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
|
||||
|
||||
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
||||
|
||||
@@ -358,18 +474,18 @@ void setup()
|
||||
// Now that the mesh service is created, create any modules
|
||||
setupModules();
|
||||
|
||||
// Do this after service.init (because that clears error_code)
|
||||
// Do this after service.init (because that clears error_code)
|
||||
#ifdef HAS_PMU
|
||||
if (!pmu_found)
|
||||
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_NO_AXP192); // Record a hardware fault for missing hardware
|
||||
#endif
|
||||
|
||||
// Don't call screen setup until after nodedb is setup (because we need
|
||||
// the current region name)
|
||||
// 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)
|
||||
screen->setup();
|
||||
#else
|
||||
if (screen_found)
|
||||
if (screen_found.port != ScanI2C::I2CPort::NO_I2C)
|
||||
screen->setup();
|
||||
#endif
|
||||
|
||||
@@ -392,6 +508,10 @@ void setup()
|
||||
digitalWrite(SX126X_ANT_SW, 1);
|
||||
#endif
|
||||
|
||||
// Init LockingHAL first, to use it for radio init
|
||||
|
||||
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
|
||||
|
||||
// radio init MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
|
||||
|
||||
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
|
||||
@@ -409,7 +529,7 @@ void setup()
|
||||
|
||||
#if defined(RF95_IRQ)
|
||||
if (!rIf) {
|
||||
rIf = new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, RF95_DIO1, SPI);
|
||||
rIf = new RF95Interface(RadioLibHAL, RF95_NSS, RF95_IRQ, RF95_RESET, RF95_DIO1);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find RF95 radio\n");
|
||||
delete rIf;
|
||||
@@ -422,7 +542,7 @@ void setup()
|
||||
|
||||
#if defined(USE_SX1262)
|
||||
if (!rIf) {
|
||||
rIf = new SX1262Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
||||
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find SX1262 radio\n");
|
||||
delete rIf;
|
||||
@@ -435,7 +555,7 @@ void setup()
|
||||
|
||||
#if defined(USE_SX1268)
|
||||
if (!rIf) {
|
||||
rIf = new SX1268Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
||||
rIf = new SX1268Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find SX1268 radio\n");
|
||||
delete rIf;
|
||||
@@ -448,7 +568,7 @@ void setup()
|
||||
|
||||
#if defined(USE_LLCC68)
|
||||
if (!rIf) {
|
||||
rIf = new LLCC68Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
||||
rIf = new LLCC68Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find LLCC68 radio\n");
|
||||
delete rIf;
|
||||
@@ -461,7 +581,7 @@ void setup()
|
||||
|
||||
#if defined(USE_SX1280)
|
||||
if (!rIf) {
|
||||
rIf = new SX1280Interface(SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY, SPI);
|
||||
rIf = new SX1280Interface(RadioLibHAL, SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find SX1280 radio\n");
|
||||
delete rIf;
|
||||
|
||||
17
src/main.h
17
src/main.h
@@ -3,8 +3,12 @@
|
||||
#include "GPSStatus.h"
|
||||
#include "NodeStatus.h"
|
||||
#include "PowerStatus.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "memGet.h"
|
||||
#include "mesh/generated/meshtastic/config.pb.h"
|
||||
#include "mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include <SPI.h>
|
||||
#include <map>
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include <SparkFun_ATECCX08a_Arduino_Library.h>
|
||||
@@ -18,12 +22,12 @@ extern NimbleBluetooth *nimbleBluetooth;
|
||||
extern NRF52Bluetooth *nrf52Bluetooth;
|
||||
#endif
|
||||
|
||||
extern uint8_t screen_found;
|
||||
extern uint8_t screen_model;
|
||||
extern uint8_t cardkb_found;
|
||||
extern ScanI2C::DeviceAddress screen_found;
|
||||
extern ScanI2C::DeviceAddress cardkb_found;
|
||||
extern uint8_t kb_model;
|
||||
extern uint8_t rtc_found;
|
||||
extern uint8_t keystore_found;
|
||||
extern ScanI2C::DeviceAddress rtc_found;
|
||||
extern ScanI2C::DeviceAddress accelerometer_found;
|
||||
extern ScanI2C::FoundDevice rgb_found;
|
||||
|
||||
extern bool eink_found;
|
||||
extern bool pmu_found;
|
||||
@@ -63,3 +67,6 @@ extern bool runASAP;
|
||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), clearBonds();
|
||||
|
||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||
|
||||
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
|
||||
extern SPISettings spiSettings;
|
||||
|
||||
46
src/memGet.cpp
Normal file
46
src/memGet.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "memGet.h"
|
||||
#include "configuration.h"
|
||||
|
||||
MemGet memGet;
|
||||
|
||||
uint32_t MemGet::getFreeHeap()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
return ESP.getFreeHeap();
|
||||
#elif defined(ARCH_NRF52)
|
||||
return dbgHeapFree();
|
||||
#else
|
||||
// this platform does not have heap management function implemented
|
||||
return UINT32_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t MemGet::getHeapSize()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
return ESP.getHeapSize();
|
||||
#elif defined(ARCH_NRF52)
|
||||
return dbgHeapTotal();
|
||||
#else
|
||||
// this platform does not have heap management function implemented
|
||||
return UINT32_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t MemGet::getFreePsram()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
return ESP.getFreePsram();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t MemGet::getPsramSize()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
return ESP.getPsramSize();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
18
src/memGet.h
Normal file
18
src/memGet.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#ifndef _MT_MEMGET_H
|
||||
#define _MT_MEMGET_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class MemGet
|
||||
{
|
||||
public:
|
||||
uint32_t getFreeHeap();
|
||||
uint32_t getHeapSize();
|
||||
uint32_t getFreePsram();
|
||||
uint32_t getPsramSize();
|
||||
};
|
||||
|
||||
extern MemGet memGet;
|
||||
|
||||
#endif
|
||||
@@ -260,6 +260,9 @@ const char *Channels::getName(size_t chIndex)
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST:
|
||||
channelName = "LongFast";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
|
||||
channelName = "LongMod";
|
||||
break;
|
||||
case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
|
||||
channelName = "VLongSlow";
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "CryptoEngine.h"
|
||||
#include "configuration.h"
|
||||
|
||||
concurrency::Lock *cryptLock;
|
||||
|
||||
void CryptoEngine::setKey(const CryptoKey &k)
|
||||
{
|
||||
LOG_DEBUG("Using AES%d key!\n", k.length * 8);
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "concurrency/LockGuard.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
extern concurrency::Lock *cryptLock;
|
||||
|
||||
struct CryptoKey {
|
||||
uint8_t bytes[32];
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
|
||||
LLCC68Interface::LLCC68Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi)
|
||||
: SX126xInterface(cs, irq, rst, busy, spi)
|
||||
LLCC68Interface::LLCC68Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: SX126xInterface(hal, cs, irq, rst, busy)
|
||||
{
|
||||
}
|
||||
@@ -6,12 +6,13 @@
|
||||
* Our adapter for LLCC68 radios
|
||||
* https://www.semtech.com/products/wireless-rf/lora-core/llcc68
|
||||
* ⚠️⚠️⚠️
|
||||
* Be aware that LLCC68 does not support Spreading Factor 12 (SF12) and will not work on the default "Long Slow" channel.
|
||||
* Be aware that LLCC68 does not support Spreading Factor 12 (SF12) and will not work on the "LongSlow" and "VLongSlow" channels.
|
||||
* You must change the channel if you get `Critical Error #3` with this module.
|
||||
* ⚠️⚠️⚠️
|
||||
*/
|
||||
class LLCC68Interface : public SX126xInterface<LLCC68>
|
||||
{
|
||||
public:
|
||||
LLCC68Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
LLCC68Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy);
|
||||
};
|
||||
@@ -77,12 +77,12 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
|
||||
|
||||
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB.getNode(mp->from)->has_user && nodeInfoModule) {
|
||||
LOG_INFO("Heard a node we don't know, sending NodeInfo and asking for a response.\n");
|
||||
nodeInfoModule->sendOurNodeInfo(mp->from, true);
|
||||
LOG_INFO("Heard a node on channel %d we don't know, sending NodeInfo and asking for a response.\n", mp->channel);
|
||||
nodeInfoModule->sendOurNodeInfo(mp->from, true, mp->channel);
|
||||
}
|
||||
|
||||
printPacket("Forwarding to phone", mp);
|
||||
sendToPhone((meshtastic_MeshPacket *)mp);
|
||||
sendToPhone(packetPool.allocCopy(*mp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -125,7 +125,6 @@ void MeshService::reloadOwner(bool shouldSave)
|
||||
// update everyone else and save to disk
|
||||
if (nodeInfoModule && shouldSave) {
|
||||
nodeInfoModule->sendOurNodeInfo();
|
||||
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +230,7 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh
|
||||
}
|
||||
|
||||
if (ccToPhone) {
|
||||
sendToPhone(p);
|
||||
sendToPhone(packetPool.allocCopy(*p));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,13 +241,13 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
||||
|
||||
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
|
||||
if (positionModule) {
|
||||
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||
positionModule->sendOurPosition(dest, wantReplies);
|
||||
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
|
||||
positionModule->sendOurPosition(dest, wantReplies, node->channel);
|
||||
}
|
||||
} else {
|
||||
if (nodeInfoModule) {
|
||||
LOG_INFO("Sending nodeinfo ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||
nodeInfoModule->sendOurNodeInfo(dest, wantReplies);
|
||||
LOG_INFO("Sending nodeinfo ping to 0x%x, wantReplies=%d, channel=%d\n", dest, wantReplies, node->channel);
|
||||
nodeInfoModule->sendOurNodeInfo(dest, wantReplies, node->channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,9 +261,8 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
|
||||
releaseToPool(d);
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *copied = packetPool.allocCopy(*p);
|
||||
perhapsDecode(copied);
|
||||
assert(toPhoneQueue.enqueue(copied, 0));
|
||||
perhapsDecode(p);
|
||||
assert(toPhoneQueue.enqueue(p, 0));
|
||||
fromNum++;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#include "../detect/ScanI2C.h"
|
||||
#include "Channels.h"
|
||||
#include "CryptoEngine.h"
|
||||
#include "FSCommon.h"
|
||||
@@ -57,12 +58,6 @@ meshtastic_User &owner = devicestate.owner;
|
||||
|
||||
static uint8_t ourMacAddr[6];
|
||||
|
||||
/**
|
||||
* The node number the user is currently looking at
|
||||
* 0 if none
|
||||
*/
|
||||
NodeNum displayedNodeNum;
|
||||
|
||||
NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {}
|
||||
|
||||
/**
|
||||
@@ -170,6 +165,8 @@ void NodeDB::installDefaultConfig()
|
||||
config.lora.hop_limit = HOP_RELIABLE;
|
||||
config.position.gps_enabled = true;
|
||||
config.position.position_broadcast_smart_enabled = true;
|
||||
config.position.broadcast_smart_minimum_distance = 100;
|
||||
config.position.broadcast_smart_minimum_interval_secs = 30;
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER)
|
||||
config.device.node_info_broadcast_secs = 3 * 60 * 60;
|
||||
config.device.serial_enabled = true;
|
||||
@@ -181,7 +178,7 @@ void NodeDB::installDefaultConfig()
|
||||
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER)
|
||||
bool hasScreen = true;
|
||||
#else
|
||||
bool hasScreen = screen_found;
|
||||
bool hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
|
||||
#endif
|
||||
config.bluetooth.mode = hasScreen ? meshtastic_Config_BluetoothConfig_PairingMode_RANDOM_PIN
|
||||
: meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
|
||||
@@ -236,9 +233,7 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
config.display.screen_on_secs = 1;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_TRACKER) {
|
||||
config.position.position_broadcast_smart_enabled = false;
|
||||
config.position.position_broadcast_secs = 120;
|
||||
config.position.gps_update_interval = 60;
|
||||
config.position.gps_update_interval = 30;
|
||||
} else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) {
|
||||
moduleConfig.telemetry.environment_measurement_enabled = true;
|
||||
moduleConfig.telemetry.environment_update_interval = 300;
|
||||
@@ -495,6 +490,7 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_
|
||||
} else {
|
||||
okay = true;
|
||||
}
|
||||
f.flush();
|
||||
f.close();
|
||||
|
||||
// brief window of risk here ;-)
|
||||
@@ -694,11 +690,11 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS
|
||||
|
||||
/** Update user info for this node based on received user data
|
||||
*/
|
||||
void NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
|
||||
bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
|
||||
{
|
||||
meshtastic_NodeInfo *info = getOrCreateNode(nodeId);
|
||||
if (!info) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name);
|
||||
@@ -715,10 +711,11 @@ void NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
|
||||
powerFSM.trigger(EVENT_NODEDB_UPDATED);
|
||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||
|
||||
// Not really needed - we will save anyways when we go to sleep
|
||||
// We just changed something important about the user, store our DB
|
||||
// saveToDisk();
|
||||
saveToDisk(SEGMENT_DEVICESTATE);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/// given a subpacket sniffed from the network, update our DB state
|
||||
@@ -726,7 +723,7 @@ void NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
|
||||
void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
|
||||
LOG_DEBUG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time);
|
||||
LOG_DEBUG("Update DB node 0x%x, rx_time=%u, channel=%d\n", mp.from, mp.rx_time, mp.channel);
|
||||
|
||||
meshtastic_NodeInfo *info = getOrCreateNode(getFrom(&mp));
|
||||
if (!info) {
|
||||
@@ -738,9 +735,22 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
||||
|
||||
if (mp.rx_snr)
|
||||
info->snr = mp.rx_snr; // keep the most recent SNR we received for this node.
|
||||
|
||||
if (mp.decoded.portnum == meshtastic_PortNum_NODEINFO_APP) {
|
||||
info->channel = mp.channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t NodeDB::getNodeChannel(NodeNum n)
|
||||
{
|
||||
meshtastic_NodeInfo *info = getNode(n);
|
||||
if (!info) {
|
||||
return 0; // defaults to PRIMARY
|
||||
}
|
||||
return info->channel;
|
||||
}
|
||||
|
||||
/// Find a node in our DB, return null for missing
|
||||
/// NOTE: This function might be called from an ISR
|
||||
meshtastic_NodeInfo *NodeDB::getNode(NodeNum n)
|
||||
@@ -758,7 +768,7 @@ meshtastic_NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
|
||||
meshtastic_NodeInfo *info = getNode(n);
|
||||
|
||||
if (!info) {
|
||||
if (*numNodes >= MAX_NUM_NODES) {
|
||||
if ((*numNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfo_size * 3)) {
|
||||
screen->print("warning: node_db full! erasing oldest entry\n");
|
||||
// look for oldest node and erase it
|
||||
uint32_t oldest = UINT32_MAX;
|
||||
|
||||
@@ -86,7 +86,7 @@ class NodeDB
|
||||
|
||||
/** Update user info for this node based on received user data
|
||||
*/
|
||||
void updateUser(uint32_t nodeId, const meshtastic_User &p);
|
||||
bool updateUser(uint32_t nodeId, const meshtastic_User &p);
|
||||
|
||||
/// @return our node number
|
||||
NodeNum getNodeNum() { return myNodeInfo.my_node_num; }
|
||||
@@ -113,6 +113,9 @@ class NodeDB
|
||||
/// pick a provisional nodenum we hope no one is using
|
||||
void pickNewNodeNum();
|
||||
|
||||
// get channel channel index we heard a nodeNum on, defaults to 0 if not found
|
||||
uint8_t getNodeChannel(NodeNum n);
|
||||
|
||||
/// Find a node in our DB, return null for missing
|
||||
meshtastic_NodeInfo *getNode(NodeNum n);
|
||||
|
||||
@@ -153,12 +156,6 @@ class NodeDB
|
||||
void installDefaultDeviceState(), installDefaultChannels(), installDefaultConfig(), installDefaultModuleConfig();
|
||||
};
|
||||
|
||||
/**
|
||||
* The node number the user is currently looking at
|
||||
* 0 if none
|
||||
*/
|
||||
extern NodeNum displayedNodeNum;
|
||||
|
||||
extern NodeDB nodeDB;
|
||||
|
||||
/*
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
#define POWER_DEFAULT 17 // How much power to use if the user hasn't set a power level
|
||||
|
||||
RF95Interface::RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi)
|
||||
: RadioLibInterface(cs, irq, rst, busy, spi)
|
||||
RF95Interface::RF95Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: RadioLibInterface(hal, cs, irq, rst, busy)
|
||||
{
|
||||
// FIXME - we assume devices never get destroyed
|
||||
LOG_WARN("RF95Interface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
}
|
||||
|
||||
/** Some boards require GPIO control of tx vs rx paths */
|
||||
|
||||
@@ -12,7 +12,8 @@ class RF95Interface : public RadioLibInterface
|
||||
RadioLibRF95 *lora = NULL; // Either a RFM95 or RFM96 depending on what was stuffed on this board
|
||||
|
||||
public:
|
||||
RF95Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
RF95Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy);
|
||||
|
||||
// TODO: Verify that this irq flag works with RFM95 / SX1276 radios the way it used to
|
||||
bool isIRQPending() override { return lora->getIRQFlags() & RADIOLIB_SX127X_MASK_IRQ_FLAG_VALID_HEADER; }
|
||||
@@ -39,7 +40,7 @@ class RF95Interface : public RadioLibInterface
|
||||
/**
|
||||
* Enable a particular ISR callback glue function
|
||||
*/
|
||||
virtual void enableInterrupt(void (*callback)()) { lora->setDio0Action(callback); }
|
||||
virtual void enableInterrupt(void (*callback)()) { lora->setDio0Action(callback, RISING); }
|
||||
|
||||
/** can we detect a LoRa preamble on the current channel? */
|
||||
virtual bool isChannelActive() override;
|
||||
|
||||
@@ -281,8 +281,8 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
|
||||
if (p->priority != 0)
|
||||
out += DEBUG_PORT.mt_sprintf(" priority=%d", p->priority);
|
||||
|
||||
out += ")\n";
|
||||
LOG_DEBUG("%s", out.c_str());
|
||||
out += ")";
|
||||
LOG_DEBUG("%s\n", out.c_str());
|
||||
}
|
||||
|
||||
RadioInterface::RadioInterface()
|
||||
@@ -454,6 +454,7 @@ void RadioInterface::applyModemConfig()
|
||||
|
||||
// If user has manually specified a channel num, then use that, otherwise generate one by hashing the name
|
||||
const char *channelName = channels.getName(channels.getPrimaryIndex());
|
||||
// channel_num is actually (channel_num - 1), since modulus (%) returns values from 0 to (numChannels - 1)
|
||||
int channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels;
|
||||
|
||||
// Old frequency selection formula
|
||||
@@ -471,13 +472,16 @@ void RadioInterface::applyModemConfig()
|
||||
saveChannelNum(channel_num);
|
||||
saveFreq(freq + loraConfig.frequency_offset);
|
||||
|
||||
preambleTimeMsec = getPacketTime((uint32_t)0);
|
||||
maxPacketTimeMsec = getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN + sizeof(PacketHeader));
|
||||
|
||||
LOG_INFO("Radio freq=%.3f, config.lora.frequency_offset=%.3f\n", freq, loraConfig.frequency_offset);
|
||||
LOG_INFO("Set radio: region=%s, name=%s, config=%u, ch=%d, power=%d\n", myRegion->name, channelName, loraConfig.modem_preset,
|
||||
channel_num, power);
|
||||
LOG_INFO("Radio myRegion->freqStart -> myRegion->freqEnd: %f -> %f (%f mhz)\n", myRegion->freqStart, myRegion->freqEnd,
|
||||
myRegion->freqEnd - myRegion->freqStart);
|
||||
LOG_INFO("Radio myRegion->numChannels: %d x %.3fkHz\n", numChannels, bw);
|
||||
LOG_INFO("Radio channel_num: %d\n", channel_num);
|
||||
LOG_INFO("Radio channel_num: %d\n", channel_num + 1);
|
||||
LOG_INFO("Radio frequency: %f\n", getFreq());
|
||||
LOG_INFO("Slot time: %u msec\n", slotTimeMsec);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,9 @@ class RadioInterface
|
||||
- Tx/Rx turnaround time (maximum of SX126x and SX127x);
|
||||
- MAC processing time (measured on T-beam) */
|
||||
uint32_t slotTimeMsec = 8.5 * pow(2, sf) / bw + 0.2 + 0.4 + 7;
|
||||
uint16_t preambleLength = 16; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||
uint16_t preambleLength = 16; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||
uint32_t preambleTimeMsec = 165; // calculated on startup, this is the default for LongFast
|
||||
uint32_t maxPacketTimeMsec = 3246; // calculated on startup, this is the default for LongFast
|
||||
const uint32_t PROCESSING_TIME_MSEC =
|
||||
4500; // time to construct, process and construct a packet again (empirically determined)
|
||||
const uint8_t CWmin = 2; // minimum CWsize
|
||||
|
||||
@@ -9,26 +9,23 @@
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
|
||||
static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
|
||||
|
||||
void LockingModule::SPIbeginTransaction()
|
||||
void LockingArduinoHal::spiBeginTransaction()
|
||||
{
|
||||
spiLock->lock();
|
||||
|
||||
Module::SPIbeginTransaction();
|
||||
ArduinoHal::spiBeginTransaction();
|
||||
}
|
||||
|
||||
void LockingModule::SPIendTransaction()
|
||||
void LockingArduinoHal::spiEndTransaction()
|
||||
{
|
||||
spiLock->unlock();
|
||||
|
||||
Module::SPIendTransaction();
|
||||
ArduinoHal::spiEndTransaction();
|
||||
}
|
||||
|
||||
RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi, PhysicalLayer *_iface)
|
||||
: NotifiedWorkerThread("RadioIf"), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface)
|
||||
RadioLibInterface::RadioLibInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy, PhysicalLayer *_iface)
|
||||
: NotifiedWorkerThread("RadioIf"), module(hal, cs, irq, rst, busy), iface(_iface)
|
||||
{
|
||||
instance = this;
|
||||
#if defined(ARCH_STM32WL) && defined(USE_SX1262)
|
||||
|
||||
@@ -13,35 +13,18 @@
|
||||
#define INTERRUPT_ATTR
|
||||
#endif
|
||||
|
||||
#define RADIOLIB_PIN_TYPE uint32_t
|
||||
|
||||
/**
|
||||
* A wrapper for the RadioLib Module class, that adds mutex for SPI bus access
|
||||
* We need to override the RadioLib ArduinoHal class to add mutex protection for SPI bus access
|
||||
*/
|
||||
class LockingModule : public Module
|
||||
class LockingArduinoHal : public ArduinoHal
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
\brief Extended SPI-based module constructor.
|
||||
LockingArduinoHal(SPIClass &spi, SPISettings spiSettings) : ArduinoHal(spi, spiSettings){};
|
||||
|
||||
\param cs Arduino pin to be used as chip select.
|
||||
|
||||
\param irq Arduino pin to be used as interrupt/GPIO.
|
||||
|
||||
\param rst Arduino pin to be used as hardware reset for the module.
|
||||
|
||||
\param gpio Arduino pin to be used as additional interrupt/GPIO.
|
||||
|
||||
\param spi SPI interface to be used, can also use software SPI implementations.
|
||||
|
||||
\param spiSettings SPI interface settings.
|
||||
*/
|
||||
LockingModule(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio, SPIClass &spi,
|
||||
SPISettings spiSettings)
|
||||
: Module(cs, irq, rst, gpio, spi, spiSettings)
|
||||
{
|
||||
}
|
||||
|
||||
void SPIbeginTransaction() override;
|
||||
void SPIendTransaction() override;
|
||||
void spiBeginTransaction() override;
|
||||
void spiEndTransaction() override;
|
||||
};
|
||||
|
||||
class RadioLibInterface : public RadioInterface, protected concurrency::NotifiedWorkerThread
|
||||
@@ -73,7 +56,7 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
||||
|
||||
float currentLimit = 100; // 100mA OCP - Should be acceptable for RFM95/SX127x chipset.
|
||||
|
||||
LockingModule module; // The HW interface to the radio
|
||||
Module module; // The HW interface to the radio
|
||||
|
||||
/**
|
||||
* provides lowest common denominator RadioLib API
|
||||
@@ -99,8 +82,8 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
||||
virtual void enableInterrupt(void (*)()) = 0;
|
||||
|
||||
public:
|
||||
RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi,
|
||||
PhysicalLayer *iface = NULL);
|
||||
RadioLibInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy, PhysicalLayer *iface = NULL);
|
||||
|
||||
virtual ErrorCode send(meshtastic_MeshPacket *p) override;
|
||||
|
||||
|
||||
@@ -79,5 +79,5 @@ bool RadioLibRF95::isReceiving()
|
||||
|
||||
uint8_t RadioLibRF95::readReg(uint8_t addr)
|
||||
{
|
||||
return _mod->SPIreadRegister(addr);
|
||||
return mod->SPIreadRegister(addr);
|
||||
}
|
||||
@@ -164,13 +164,13 @@ bool ReliableRouter::stopRetransmission(GlobalPacketId key)
|
||||
{
|
||||
auto old = findPendingPacket(key);
|
||||
if (old) {
|
||||
auto p = old->packet;
|
||||
auto numErased = pending.erase(key);
|
||||
assert(numErased == 1);
|
||||
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
|
||||
cancelSending(getFrom(old->packet), old->packet->id);
|
||||
// now free the pooled copy for retransmission too. tryfix for #2228
|
||||
if (old->packet)
|
||||
packetPool.release(old->packet);
|
||||
cancelSending(getFrom(p), p->id);
|
||||
// now free the pooled copy for retransmission too
|
||||
packetPool.release(p);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
||||
@@ -55,6 +55,10 @@ Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRA
|
||||
LOG_DEBUG("Size of MeshPacket %d\n", sizeof(MeshPacket)); */
|
||||
|
||||
fromRadioQueue.setReader(this);
|
||||
|
||||
// init Lockguard for crypt operations
|
||||
assert(!cryptLock);
|
||||
cryptLock = new concurrency::Lock();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,6 +177,11 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
||||
handleReceived(p, src);
|
||||
}
|
||||
|
||||
if (!p->channel) { // don't override if a channel was requested
|
||||
p->channel = nodeDB.getNodeChannel(p->to);
|
||||
LOG_DEBUG("localSend to channel %d\n", p->channel);
|
||||
}
|
||||
|
||||
return send(p);
|
||||
}
|
||||
}
|
||||
@@ -300,6 +309,8 @@ void Router::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Rout
|
||||
|
||||
bool perhapsDecode(meshtastic_MeshPacket *p)
|
||||
{
|
||||
concurrency::LockGuard g(cryptLock);
|
||||
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER &&
|
||||
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING)
|
||||
return false;
|
||||
@@ -366,6 +377,8 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
|
||||
*/
|
||||
meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
|
||||
{
|
||||
concurrency::LockGuard g(cryptLock);
|
||||
|
||||
// If the packet is not yet encrypted, do so now
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
|
||||
SX1262Interface::SX1262Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi)
|
||||
: SX126xInterface(cs, irq, rst, busy, spi)
|
||||
SX1262Interface::SX1262Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: SX126xInterface(hal, cs, irq, rst, busy)
|
||||
{
|
||||
}
|
||||
@@ -8,5 +8,6 @@
|
||||
class SX1262Interface : public SX126xInterface<SX1262>
|
||||
{
|
||||
public:
|
||||
SX1262Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
SX1262Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy);
|
||||
};
|
||||
@@ -2,8 +2,17 @@
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
|
||||
SX1268Interface::SX1268Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi)
|
||||
: SX126xInterface(cs, irq, rst, busy, spi)
|
||||
SX1268Interface::SX1268Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: SX126xInterface(hal, cs, irq, rst, busy)
|
||||
{
|
||||
}
|
||||
|
||||
float SX1268Interface::getFreq()
|
||||
{
|
||||
// Set frequency to default of EU_433 if outside of allowed range (e.g. when region is UNSET)
|
||||
if (savedFreq < 410 || savedFreq > 810)
|
||||
return 433.125f;
|
||||
else
|
||||
return savedFreq;
|
||||
}
|
||||
@@ -8,8 +8,8 @@
|
||||
class SX1268Interface : public SX126xInterface<SX1268>
|
||||
{
|
||||
public:
|
||||
/// override frequency of the SX1268 module regardless of the region (use EU433 value)
|
||||
virtual float getFreq() override { return 433.175f; }
|
||||
virtual float getFreq() override;
|
||||
|
||||
SX1268Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
SX1268Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy);
|
||||
};
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
SX126xInterface<T>::SX126xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi)
|
||||
: RadioLibInterface(cs, irq, rst, busy, spi, &lora), lora(&module)
|
||||
SX126xInterface<T>::SX126xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: RadioLibInterface(hal, cs, irq, rst, busy, &lora), lora(&module)
|
||||
{
|
||||
LOG_WARN("SX126xInterface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
}
|
||||
@@ -47,6 +47,8 @@ template <typename T> bool SX126xInterface<T>::init()
|
||||
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||
// \todo Display actual typename of the adapter, not just `SX126x`
|
||||
LOG_INFO("SX126x init result %d\n", res);
|
||||
if (res == RADIOLIB_ERR_CHIP_NOT_FOUND)
|
||||
return false;
|
||||
|
||||
LOG_INFO("Frequency set to %f\n", getFreq());
|
||||
LOG_INFO("Bandwidth set to %f\n", bw);
|
||||
@@ -58,16 +60,19 @@ template <typename T> bool SX126xInterface<T>::init()
|
||||
LOG_DEBUG("Current limit set to %f\n", currentLimit);
|
||||
LOG_DEBUG("Current limit set result %d\n", res);
|
||||
|
||||
#ifdef SX126X_E22
|
||||
#if defined(SX126X_E22)
|
||||
// E22 Emulation explicitly requires DIO2 as RF switch, so set it to TRUE again for good measure. In case somebody defines
|
||||
// SX126X_TX for an E22 Module
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
if (res == RADIOLIB_ERR_NONE) {
|
||||
LOG_DEBUG("SX126X_E22 mode enabled. Setting DIO2 as RF Switch\n");
|
||||
res = lora.setDio2AsRfSwitch(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC)
|
||||
// lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX
|
||||
if (res == RADIOLIB_ERR_NONE) {
|
||||
LOG_DEBUG("SX126X_TX/RX EN pins defined. Setting RF Switch: RXEN=%i, TXEN=%i\n", SX126X_RXEN, SX126X_TXEN);
|
||||
res = lora.setDio2AsRfSwitch(false);
|
||||
lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
|
||||
}
|
||||
@@ -180,6 +185,7 @@ template <typename T> void SX126xInterface<T>::setStandby()
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
isReceiving = false; // If we were receiving, not any more
|
||||
activeReceiveStart = 0;
|
||||
disableInterrupt();
|
||||
completeSending(); // If we were sending, not anymore
|
||||
}
|
||||
@@ -213,9 +219,10 @@ template <typename T> void SX126xInterface<T>::startReceive()
|
||||
setStandby();
|
||||
|
||||
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
|
||||
// Furthermore, we need the HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err =
|
||||
lora.startReceiveDutyCycleAuto(preambleLength, 8, RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_HEADER_VALID);
|
||||
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8,
|
||||
RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX126X_IRQ_HEADER_VALID);
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
isReceiving = true;
|
||||
@@ -248,10 +255,27 @@ template <typename T> bool SX126xInterface<T>::isActivelyReceiving()
|
||||
// received and handled the interrupt for reading the packet/handling errors.
|
||||
|
||||
uint16_t irq = lora.getIrqStatus();
|
||||
bool headerValid = (irq & RADIOLIB_SX126X_IRQ_HEADER_VALID);
|
||||
bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED));
|
||||
// Handle false detections
|
||||
if (detected) {
|
||||
uint32_t now = millis();
|
||||
if (!activeReceiveStart) {
|
||||
activeReceiveStart = now;
|
||||
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX126X_IRQ_HEADER_VALID)) {
|
||||
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
|
||||
activeReceiveStart = 0;
|
||||
LOG_DEBUG("Ignore false preamble detection.\n");
|
||||
return false;
|
||||
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
|
||||
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
|
||||
activeReceiveStart = 0;
|
||||
LOG_DEBUG("Ignore false header detection.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// if (headerValid) LOG_DEBUG("rx headerValid\n");
|
||||
return headerValid;
|
||||
// if (detected) LOG_DEBUG("rx detected\n");
|
||||
return detected;
|
||||
}
|
||||
|
||||
template <typename T> bool SX126xInterface<T>::sleep()
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
template <class T> class SX126xInterface : public RadioLibInterface
|
||||
{
|
||||
public:
|
||||
SX126xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
SX126xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy);
|
||||
|
||||
/// Initialise the Driver transport hardware and software.
|
||||
/// Make sure the Driver is properly configured before calling init().
|
||||
@@ -68,4 +69,5 @@ template <class T> class SX126xInterface : public RadioLibInterface
|
||||
virtual void setStandby() override;
|
||||
|
||||
private:
|
||||
uint32_t activeReceiveStart = 0;
|
||||
};
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
|
||||
SX1280Interface::SX1280Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi)
|
||||
: SX128xInterface(cs, irq, rst, busy, spi)
|
||||
SX1280Interface::SX1280Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: SX128xInterface(hal, cs, irq, rst, busy)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
class SX1280Interface : public SX128xInterface<SX1280>
|
||||
{
|
||||
public:
|
||||
SX1280Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
SX1280Interface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy);
|
||||
};
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
SX128xInterface<T>::SX128xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi)
|
||||
: RadioLibInterface(cs, irq, rst, busy, spi, &lora), lora(&module)
|
||||
SX128xInterface<T>::SX128xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy)
|
||||
: RadioLibInterface(hal, cs, irq, rst, busy, &lora), lora(&module)
|
||||
{
|
||||
LOG_WARN("SX128xInterface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
|
||||
}
|
||||
|
||||
/// Initialise the Driver transport hardware and software.
|
||||
@@ -73,6 +74,12 @@ template <typename T> bool SX128xInterface<T>::init()
|
||||
LOG_INFO("Bandwidth set to %f\n", bw);
|
||||
LOG_INFO("Power output set to %d\n", power);
|
||||
|
||||
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) && defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC)
|
||||
if (res == RADIOLIB_ERR_NONE) {
|
||||
lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (res == RADIOLIB_ERR_NONE)
|
||||
res = lora.setCRC(2);
|
||||
|
||||
@@ -157,6 +164,7 @@ template <typename T> void SX128xInterface<T>::setStandby()
|
||||
#endif
|
||||
|
||||
isReceiving = false; // If we were receiving, not any more
|
||||
activeReceiveStart = 0;
|
||||
disableInterrupt();
|
||||
completeSending(); // If we were sending, not anymore
|
||||
}
|
||||
@@ -203,9 +211,10 @@ template <typename T> void SX128xInterface<T>::startReceive()
|
||||
digitalWrite(SX128X_TXEN, LOW);
|
||||
#endif
|
||||
|
||||
// We use the HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err =
|
||||
lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT | RADIOLIB_SX128X_IRQ_HEADER_VALID);
|
||||
// We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
|
||||
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT |
|
||||
RADIOLIB_SX128X_IRQ_RADIOLIB_PREAMBLE_DETECTED |
|
||||
RADIOLIB_SX128X_IRQ_HEADER_VALID);
|
||||
|
||||
assert(err == RADIOLIB_ERR_NONE);
|
||||
|
||||
@@ -236,8 +245,27 @@ template <typename T> bool SX128xInterface<T>::isChannelActive()
|
||||
template <typename T> bool SX128xInterface<T>::isActivelyReceiving()
|
||||
{
|
||||
uint16_t irq = lora.getIrqStatus();
|
||||
bool hasHeader = (irq & RADIOLIB_SX128X_IRQ_HEADER_VALID);
|
||||
return hasHeader;
|
||||
bool detected = (irq & (RADIOLIB_SX128X_IRQ_HEADER_VALID | RADIOLIB_SX128X_IRQ_RADIOLIB_PREAMBLE_DETECTED));
|
||||
|
||||
// Handle false detections
|
||||
if (detected) {
|
||||
uint32_t now = millis();
|
||||
if (!activeReceiveStart) {
|
||||
activeReceiveStart = now;
|
||||
} else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX128X_IRQ_HEADER_VALID)) {
|
||||
// The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag
|
||||
activeReceiveStart = 0;
|
||||
LOG_DEBUG("Ignore false preamble detection.\n");
|
||||
return false;
|
||||
} else if (now - activeReceiveStart > maxPacketTimeMsec) {
|
||||
// We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag
|
||||
activeReceiveStart = 0;
|
||||
LOG_DEBUG("Ignore false header detection.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return detected;
|
||||
}
|
||||
|
||||
template <typename T> bool SX128xInterface<T>::sleep()
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
template <class T> class SX128xInterface : public RadioLibInterface
|
||||
{
|
||||
public:
|
||||
SX128xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
|
||||
SX128xInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
|
||||
RADIOLIB_PIN_TYPE busy);
|
||||
|
||||
/// Initialise the Driver transport hardware and software.
|
||||
/// Make sure the Driver is properly configured before calling init().
|
||||
@@ -68,4 +69,5 @@ template <class T> class SX128xInterface : public RadioLibInterface
|
||||
virtual void setStandby() override;
|
||||
|
||||
private:
|
||||
uint32_t activeReceiveStart = 0;
|
||||
};
|
||||
|
||||
@@ -31,11 +31,9 @@ typedef enum _meshtastic_Channel_Role {
|
||||
|
||||
/* Struct definitions */
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t;
|
||||
/* Full settings (center freq, spread factor, pre-shared secret key etc...)
|
||||
needed to configure a radio for speaking on a particular channel This
|
||||
information can be encoded as a QRcode/url so that other users can configure
|
||||
/* This information can be encoded as a QRcode/url so that other users can configure
|
||||
their radio to join the same channel.
|
||||
A note about how channel names are shown to users: channelname-Xy
|
||||
A note about how channel names are shown to users: channelname-X
|
||||
poundsymbol is a prefix used to indicate this is a channel name (idea from @professr).
|
||||
Where X is a letter from A-Z (base 26) representing a hash of the PSK for this
|
||||
channel - so that if the user changes anything about the channel (which does
|
||||
@@ -45,8 +43,6 @@ typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t;
|
||||
The PSK is hashed into this letter by "0x41 + [xor all bytes of the psk ] modulo 26"
|
||||
This also allows the option of someday if people have the PSK off (zero), the
|
||||
users COULD type in a channel name and be able to talk.
|
||||
Y is a lower case letter from a-z that represents the channel 'speed' settings
|
||||
(for some future definition of speed)
|
||||
FIXME: Add description of multi-channel support and how primary vs secondary channels are used.
|
||||
FIXME: explain how apps use channels for security.
|
||||
explain how remote settings and remote gpio are managed as an example */
|
||||
@@ -60,7 +56,7 @@ typedef struct _meshtastic_ChannelSettings {
|
||||
because they are listed in this source code.
|
||||
Those bytes are mapped using the following scheme:
|
||||
`0` = No crypto
|
||||
`1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf}
|
||||
`1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01}
|
||||
`2` through 10 = The default channel key, except with 1 through 9 added to the last byte.
|
||||
Shown to user as simple1 through 10 */
|
||||
meshtastic_ChannelSettings_psk_t psk;
|
||||
|
||||
12
src/mesh/generated/meshtastic/clientonly.pb.c
Normal file
12
src/mesh/generated/meshtastic/clientonly.pb.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.7 */
|
||||
|
||||
#include "meshtastic/clientonly.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(meshtastic_DeviceProfile, meshtastic_DeviceProfile, 2)
|
||||
|
||||
|
||||
|
||||
73
src/mesh/generated/meshtastic/clientonly.pb.h
Normal file
73
src/mesh/generated/meshtastic/clientonly.pb.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.7 */
|
||||
|
||||
#ifndef PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED
|
||||
#define PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "meshtastic/localonly.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
/* This abstraction is used to contain any configuration for provisioning a node on any client.
|
||||
It is useful for importing and exporting configurations. */
|
||||
typedef struct _meshtastic_DeviceProfile {
|
||||
/* Long name for the node */
|
||||
bool has_long_name;
|
||||
char long_name[40];
|
||||
/* Short name of the node */
|
||||
bool has_short_name;
|
||||
char short_name[5];
|
||||
/* The url of the channels from our node */
|
||||
pb_callback_t channel_url;
|
||||
/* The Config of the node */
|
||||
bool has_config;
|
||||
meshtastic_LocalConfig config;
|
||||
/* The ModuleConfig of the node */
|
||||
bool has_module_config;
|
||||
meshtastic_LocalModuleConfig module_config;
|
||||
} meshtastic_DeviceProfile;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceProfile_init_default {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default}
|
||||
#define meshtastic_DeviceProfile_init_zero {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_DeviceProfile_long_name_tag 1
|
||||
#define meshtastic_DeviceProfile_short_name_tag 2
|
||||
#define meshtastic_DeviceProfile_channel_url_tag 3
|
||||
#define meshtastic_DeviceProfile_config_tag 4
|
||||
#define meshtastic_DeviceProfile_module_config_tag 5
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_DeviceProfile_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, STRING, long_name, 1) \
|
||||
X(a, STATIC, OPTIONAL, STRING, short_name, 2) \
|
||||
X(a, CALLBACK, OPTIONAL, STRING, channel_url, 3) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, config, 4) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, module_config, 5)
|
||||
#define meshtastic_DeviceProfile_CALLBACK pb_default_field_callback
|
||||
#define meshtastic_DeviceProfile_DEFAULT NULL
|
||||
#define meshtastic_DeviceProfile_config_MSGTYPE meshtastic_LocalConfig
|
||||
#define meshtastic_DeviceProfile_module_config_MSGTYPE meshtastic_LocalModuleConfig
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_DeviceProfile_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_DeviceProfile_fields &meshtastic_DeviceProfile_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* meshtastic_DeviceProfile_size depends on runtime parameters */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -231,6 +231,11 @@ typedef struct _meshtastic_Config_DeviceConfig {
|
||||
/* Send our nodeinfo this often
|
||||
Defaults to 900 Seconds (15 minutes) */
|
||||
uint32_t node_info_broadcast_secs;
|
||||
/* Treat double tap interrupt on supported accelerometers as a button press if set to true */
|
||||
bool double_tap_as_button_press;
|
||||
/* If true, device is considered to be "managed" by a mesh administrator
|
||||
Clients should then limit available configuration and administrative options inside the user interface */
|
||||
bool is_managed;
|
||||
} meshtastic_Config_DeviceConfig;
|
||||
|
||||
/* Position Config */
|
||||
@@ -262,6 +267,10 @@ typedef struct _meshtastic_Config_PositionConfig {
|
||||
uint32_t rx_gpio;
|
||||
/* (Re)define GPS_TX_PIN for your board. */
|
||||
uint32_t tx_gpio;
|
||||
/* The minimum distance in meters traveled (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
|
||||
uint32_t broadcast_smart_minimum_distance;
|
||||
/* The minumum number of seconds (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
|
||||
uint32_t broadcast_smart_minimum_interval_secs;
|
||||
} meshtastic_Config_PositionConfig;
|
||||
|
||||
/* Power Config\
|
||||
@@ -360,6 +369,8 @@ typedef struct _meshtastic_Config_DisplayConfig {
|
||||
meshtastic_Config_DisplayConfig_DisplayMode displaymode;
|
||||
/* Print first line in pseudo-bold? FALSE is original style, TRUE is bold */
|
||||
bool heading_bold;
|
||||
/* Should we wake the screen up on accelerometer detected motion or tap */
|
||||
bool wake_on_tap_or_motion;
|
||||
} meshtastic_Config_DisplayConfig;
|
||||
|
||||
/* Lora Config */
|
||||
@@ -521,21 +532,21 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
|
||||
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}}
|
||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0}
|
||||
#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0}
|
||||
#define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}}
|
||||
#define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
|
||||
@@ -547,6 +558,8 @@ extern "C" {
|
||||
#define meshtastic_Config_DeviceConfig_buzzer_gpio_tag 5
|
||||
#define meshtastic_Config_DeviceConfig_rebroadcast_mode_tag 6
|
||||
#define meshtastic_Config_DeviceConfig_node_info_broadcast_secs_tag 7
|
||||
#define meshtastic_Config_DeviceConfig_double_tap_as_button_press_tag 8
|
||||
#define meshtastic_Config_DeviceConfig_is_managed_tag 9
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
|
||||
#define meshtastic_Config_PositionConfig_fixed_position_tag 3
|
||||
@@ -556,6 +569,8 @@ extern "C" {
|
||||
#define meshtastic_Config_PositionConfig_position_flags_tag 7
|
||||
#define meshtastic_Config_PositionConfig_rx_gpio_tag 8
|
||||
#define meshtastic_Config_PositionConfig_tx_gpio_tag 9
|
||||
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_distance_tag 10
|
||||
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_interval_secs_tag 11
|
||||
#define meshtastic_Config_PowerConfig_is_power_saving_tag 1
|
||||
#define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
|
||||
#define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3
|
||||
@@ -585,6 +600,7 @@ extern "C" {
|
||||
#define meshtastic_Config_DisplayConfig_oled_tag 7
|
||||
#define meshtastic_Config_DisplayConfig_displaymode_tag 8
|
||||
#define meshtastic_Config_DisplayConfig_heading_bold_tag 9
|
||||
#define meshtastic_Config_DisplayConfig_wake_on_tap_or_motion_tag 10
|
||||
#define meshtastic_Config_LoRaConfig_use_preset_tag 1
|
||||
#define meshtastic_Config_LoRaConfig_modem_preset_tag 2
|
||||
#define meshtastic_Config_LoRaConfig_bandwidth_tag 3
|
||||
@@ -637,7 +653,9 @@ X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, button_gpio, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, buzzer_gpio, 5) \
|
||||
X(a, STATIC, SINGULAR, UENUM, rebroadcast_mode, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7)
|
||||
X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_managed, 9)
|
||||
#define meshtastic_Config_DeviceConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_DeviceConfig_DEFAULT NULL
|
||||
|
||||
@@ -650,7 +668,9 @@ X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_attempt_time, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_flags, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, rx_gpio, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9)
|
||||
X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_distance, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11)
|
||||
#define meshtastic_Config_PositionConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_PositionConfig_DEFAULT NULL
|
||||
|
||||
@@ -696,7 +716,8 @@ X(a, STATIC, SINGULAR, BOOL, flip_screen, 5) \
|
||||
X(a, STATIC, SINGULAR, UENUM, units, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, oled, 7) \
|
||||
X(a, STATIC, SINGULAR, UENUM, displaymode, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, heading_bold, 9)
|
||||
X(a, STATIC, SINGULAR, BOOL, heading_bold, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, wake_on_tap_or_motion, 10)
|
||||
#define meshtastic_Config_DisplayConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_DisplayConfig_DEFAULT NULL
|
||||
|
||||
@@ -749,12 +770,12 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_Config_BluetoothConfig_size 10
|
||||
#define meshtastic_Config_DeviceConfig_size 26
|
||||
#define meshtastic_Config_DisplayConfig_size 26
|
||||
#define meshtastic_Config_DeviceConfig_size 30
|
||||
#define meshtastic_Config_DisplayConfig_size 28
|
||||
#define meshtastic_Config_LoRaConfig_size 77
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
#define meshtastic_Config_NetworkConfig_size 195
|
||||
#define meshtastic_Config_PositionConfig_size 42
|
||||
#define meshtastic_Config_PositionConfig_size 54
|
||||
#define meshtastic_Config_PowerConfig_size 43
|
||||
#define meshtastic_Config_size 198
|
||||
|
||||
|
||||
@@ -56,6 +56,11 @@ typedef struct _meshtastic_DeviceState {
|
||||
bool no_save;
|
||||
/* Some GPS receivers seem to have bogus settings from the factory, so we always do one factory reset. */
|
||||
bool did_gps_reset;
|
||||
/* We keep the last received waypoint stored in the device flash,
|
||||
so we can show it on the screen.
|
||||
Might be null */
|
||||
bool has_rx_waypoint;
|
||||
meshtastic_MeshPacket rx_waypoint;
|
||||
} meshtastic_DeviceState;
|
||||
|
||||
/* The on-disk saved channels */
|
||||
@@ -110,10 +115,10 @@ extern "C" {
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default}, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0}
|
||||
#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default, meshtastic_NodeInfo_init_default}, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default}
|
||||
#define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0}
|
||||
#define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default}
|
||||
#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero}, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0}
|
||||
#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero, meshtastic_NodeInfo_init_zero}, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero}
|
||||
#define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0}
|
||||
#define meshtastic_OEMStore_init_zero {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero}
|
||||
|
||||
@@ -126,6 +131,7 @@ extern "C" {
|
||||
#define meshtastic_DeviceState_version_tag 8
|
||||
#define meshtastic_DeviceState_no_save_tag 9
|
||||
#define meshtastic_DeviceState_did_gps_reset_tag 11
|
||||
#define meshtastic_DeviceState_rx_waypoint_tag 12
|
||||
#define meshtastic_ChannelFile_channels_tag 1
|
||||
#define meshtastic_ChannelFile_version_tag 2
|
||||
#define meshtastic_OEMStore_oem_icon_width_tag 1
|
||||
@@ -146,7 +152,8 @@ X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, no_save, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11)
|
||||
X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, rx_waypoint, 12)
|
||||
#define meshtastic_DeviceState_CALLBACK NULL
|
||||
#define meshtastic_DeviceState_DEFAULT NULL
|
||||
#define meshtastic_DeviceState_my_node_MSGTYPE meshtastic_MyNodeInfo
|
||||
@@ -154,6 +161,7 @@ X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11)
|
||||
#define meshtastic_DeviceState_node_db_MSGTYPE meshtastic_NodeInfo
|
||||
#define meshtastic_DeviceState_receive_queue_MSGTYPE meshtastic_MeshPacket
|
||||
#define meshtastic_DeviceState_rx_text_message_MSGTYPE meshtastic_MeshPacket
|
||||
#define meshtastic_DeviceState_rx_waypoint_MSGTYPE meshtastic_MeshPacket
|
||||
|
||||
#define meshtastic_ChannelFile_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, channels, 1) \
|
||||
@@ -187,8 +195,8 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_ChannelFile_size 638
|
||||
#define meshtastic_DeviceState_size 21800
|
||||
#define meshtastic_OEMStore_size 3006
|
||||
#define meshtastic_DeviceState_size 22364
|
||||
#define meshtastic_OEMStore_size 3043
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -156,8 +156,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_LocalConfig_size 440
|
||||
#define meshtastic_LocalModuleConfig_size 420
|
||||
#define meshtastic_LocalConfig_size 458
|
||||
#define meshtastic_LocalModuleConfig_size 439
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -48,6 +48,12 @@ PB_BIND(meshtastic_ToRadio, meshtastic_ToRadio, 2)
|
||||
PB_BIND(meshtastic_Compressed, meshtastic_Compressed, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_NeighborInfo, meshtastic_NeighborInfo, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Neighbor, meshtastic_Neighbor, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO)
|
||||
|
||||
|
||||
|
||||
@@ -563,6 +563,8 @@ typedef struct _meshtastic_NodeInfo {
|
||||
/* The latest device metrics for the node. */
|
||||
bool has_device_metrics;
|
||||
meshtastic_DeviceMetrics device_metrics;
|
||||
/* local channel index we heard that node on. Only populated if its not the default channel. */
|
||||
uint8_t channel;
|
||||
} meshtastic_NodeInfo;
|
||||
|
||||
/* Unique local debugging info for this node
|
||||
@@ -678,6 +680,25 @@ typedef struct _meshtastic_Compressed {
|
||||
meshtastic_Compressed_data_t data;
|
||||
} meshtastic_Compressed;
|
||||
|
||||
/* A single edge in the mesh */
|
||||
typedef struct _meshtastic_Neighbor {
|
||||
/* Node ID of neighbor */
|
||||
uint32_t node_id;
|
||||
/* SNR of last heard message */
|
||||
float snr;
|
||||
} meshtastic_Neighbor;
|
||||
|
||||
/* Full info on edges for a single node */
|
||||
typedef struct _meshtastic_NeighborInfo {
|
||||
/* The node ID of the node sending info on its neighbors */
|
||||
uint32_t node_id;
|
||||
/* Field to pass neighbor info for the next sending cycle */
|
||||
uint32_t last_sent_by_id;
|
||||
/* The list of out edges from this node */
|
||||
pb_size_t neighbors_count;
|
||||
meshtastic_Neighbor neighbors[10];
|
||||
} meshtastic_NeighborInfo;
|
||||
|
||||
/* Device metadata response */
|
||||
typedef struct _meshtastic_DeviceMetadata {
|
||||
/* Device firmware version string */
|
||||
@@ -811,6 +832,8 @@ extern "C" {
|
||||
|
||||
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
|
||||
|
||||
|
||||
|
||||
#define meshtastic_DeviceMetadata_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
|
||||
#define meshtastic_DeviceMetadata_hw_model_ENUMTYPE meshtastic_HardwareModel
|
||||
|
||||
@@ -823,13 +846,15 @@ extern "C" {
|
||||
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_default {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
|
||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default}
|
||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0}
|
||||
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
||||
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
|
||||
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||
#define meshtastic_NeighborInfo_init_default {0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
|
||||
#define meshtastic_Neighbor_init_default {0, 0}
|
||||
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
|
||||
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
|
||||
@@ -838,13 +863,15 @@ extern "C" {
|
||||
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_zero {0, 0, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
|
||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero}
|
||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0}
|
||||
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
|
||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
||||
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
||||
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
|
||||
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
|
||||
#define meshtastic_Neighbor_init_zero {0, 0}
|
||||
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
@@ -915,6 +942,7 @@ extern "C" {
|
||||
#define meshtastic_NodeInfo_snr_tag 4
|
||||
#define meshtastic_NodeInfo_last_heard_tag 5
|
||||
#define meshtastic_NodeInfo_device_metrics_tag 6
|
||||
#define meshtastic_NodeInfo_channel_tag 7
|
||||
#define meshtastic_MyNodeInfo_my_node_num_tag 1
|
||||
#define meshtastic_MyNodeInfo_has_gps_tag 2
|
||||
#define meshtastic_MyNodeInfo_max_channels_tag 3
|
||||
@@ -945,6 +973,11 @@ extern "C" {
|
||||
#define meshtastic_ToRadio_xmodemPacket_tag 5
|
||||
#define meshtastic_Compressed_portnum_tag 1
|
||||
#define meshtastic_Compressed_data_tag 2
|
||||
#define meshtastic_Neighbor_node_id_tag 1
|
||||
#define meshtastic_Neighbor_snr_tag 2
|
||||
#define meshtastic_NeighborInfo_node_id_tag 1
|
||||
#define meshtastic_NeighborInfo_last_sent_by_id_tag 2
|
||||
#define meshtastic_NeighborInfo_neighbors_tag 3
|
||||
#define meshtastic_DeviceMetadata_firmware_version_tag 1
|
||||
#define meshtastic_DeviceMetadata_device_state_version_tag 2
|
||||
#define meshtastic_DeviceMetadata_canShutdown_tag 3
|
||||
@@ -1067,7 +1100,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, position, 3) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, snr, 4) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, channel, 7)
|
||||
#define meshtastic_NodeInfo_CALLBACK NULL
|
||||
#define meshtastic_NodeInfo_DEFAULT NULL
|
||||
#define meshtastic_NodeInfo_user_MSGTYPE meshtastic_User
|
||||
@@ -1153,6 +1187,20 @@ X(a, STATIC, SINGULAR, BYTES, data, 2)
|
||||
#define meshtastic_Compressed_CALLBACK NULL
|
||||
#define meshtastic_Compressed_DEFAULT NULL
|
||||
|
||||
#define meshtastic_NeighborInfo_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, last_sent_by_id, 2) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, neighbors, 3)
|
||||
#define meshtastic_NeighborInfo_CALLBACK NULL
|
||||
#define meshtastic_NeighborInfo_DEFAULT NULL
|
||||
#define meshtastic_NeighborInfo_neighbors_MSGTYPE meshtastic_Neighbor
|
||||
|
||||
#define meshtastic_Neighbor_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, snr, 2)
|
||||
#define meshtastic_Neighbor_CALLBACK NULL
|
||||
#define meshtastic_Neighbor_DEFAULT NULL
|
||||
|
||||
#define meshtastic_DeviceMetadata_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \
|
||||
@@ -1180,6 +1228,8 @@ extern const pb_msgdesc_t meshtastic_QueueStatus_msg;
|
||||
extern const pb_msgdesc_t meshtastic_FromRadio_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ToRadio_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Compressed_msg;
|
||||
extern const pb_msgdesc_t meshtastic_NeighborInfo_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Neighbor_msg;
|
||||
extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
@@ -1197,6 +1247,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
||||
#define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg
|
||||
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
|
||||
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg
|
||||
#define meshtastic_NeighborInfo_fields &meshtastic_NeighborInfo_msg
|
||||
#define meshtastic_Neighbor_fields &meshtastic_Neighbor_msg
|
||||
#define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
@@ -1207,7 +1259,9 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
||||
#define meshtastic_LogRecord_size 81
|
||||
#define meshtastic_MeshPacket_size 321
|
||||
#define meshtastic_MyNodeInfo_size 179
|
||||
#define meshtastic_NodeInfo_size 258
|
||||
#define meshtastic_NeighborInfo_size 142
|
||||
#define meshtastic_Neighbor_size 11
|
||||
#define meshtastic_NodeInfo_size 261
|
||||
#define meshtastic_Position_size 137
|
||||
#define meshtastic_QueueStatus_size 23
|
||||
#define meshtastic_RouteDiscovery_size 40
|
||||
|
||||
@@ -96,6 +96,11 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig {
|
||||
bool encryption_enabled;
|
||||
/* Whether to send / consume json packets on MQTT */
|
||||
bool json_enabled;
|
||||
/* If true, we attempt to establish a secure connection using TLS */
|
||||
bool tls_enabled;
|
||||
/* The root topic to use for MQTT messages. Default is "msh".
|
||||
This is useful if you want to use a single MQTT server for multiple meshtastic networks and separate them via ACLs */
|
||||
char root[16];
|
||||
} meshtastic_ModuleConfig_MQTTConfig;
|
||||
|
||||
/* RemoteHardwareModule Config */
|
||||
@@ -323,7 +328,7 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, ""}
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0}
|
||||
#define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN}
|
||||
@@ -333,7 +338,7 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
|
||||
#define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, ""}
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0}
|
||||
#define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN}
|
||||
@@ -350,6 +355,8 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_password_tag 4
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_encryption_enabled_tag 5
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_json_enabled_tag 6
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_root_tag 8
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2
|
||||
@@ -444,7 +451,9 @@ X(a, STATIC, SINGULAR, STRING, address, 2) \
|
||||
X(a, STATIC, SINGULAR, STRING, username, 3) \
|
||||
X(a, STATIC, SINGULAR, STRING, password, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, json_enabled, 6)
|
||||
X(a, STATIC, SINGULAR, BOOL, json_enabled, 6) \
|
||||
X(a, STATIC, SINGULAR, BOOL, tls_enabled, 7) \
|
||||
X(a, STATIC, SINGULAR, STRING, root, 8)
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_DEFAULT NULL
|
||||
|
||||
@@ -562,13 +571,13 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg;
|
||||
#define meshtastic_ModuleConfig_AudioConfig_size 19
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_size 201
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_size 220
|
||||
#define meshtastic_ModuleConfig_RangeTestConfig_size 10
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 2
|
||||
#define meshtastic_ModuleConfig_SerialConfig_size 26
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_size 22
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_size 26
|
||||
#define meshtastic_ModuleConfig_size 204
|
||||
#define meshtastic_ModuleConfig_size 223
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -85,6 +85,8 @@ typedef enum _meshtastic_PortNum {
|
||||
/* Provides a traceroute functionality to show the route a packet towards
|
||||
a certain destination would take on the mesh. */
|
||||
meshtastic_PortNum_TRACEROUTE_APP = 70,
|
||||
/* Aggregates edge info for the network by sending out a list of each node's neighbors */
|
||||
meshtastic_PortNum_NEIGHBORINFO_APP = 71,
|
||||
/* Private applications should use portnums >= 256.
|
||||
To simplify initial development and testing you can use "PRIVATE_APP"
|
||||
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */
|
||||
|
||||
@@ -45,7 +45,7 @@ typedef enum _meshtastic_TelemetrySensorType {
|
||||
/* Struct definitions */
|
||||
/* Key native device metrics such as battery level */
|
||||
typedef struct _meshtastic_DeviceMetrics {
|
||||
/* 1-100 (0 means powered) */
|
||||
/* 0-100 (>100 means powered) */
|
||||
uint32_t battery_level;
|
||||
/* Voltage measured */
|
||||
float voltage;
|
||||
|
||||
@@ -234,15 +234,18 @@ void htmlDeleteDir(const char *dirname)
|
||||
while (file) {
|
||||
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
htmlDeleteDir(file.name());
|
||||
file.flush();
|
||||
file.close();
|
||||
} else {
|
||||
String fileName = String(file.name());
|
||||
file.flush();
|
||||
file.close();
|
||||
LOG_DEBUG(" %s\n", fileName.c_str());
|
||||
FSCom.remove(fileName);
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
root.flush();
|
||||
root.close();
|
||||
}
|
||||
|
||||
@@ -521,7 +524,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
||||
std::string pathname = "/static/" + filename;
|
||||
|
||||
// Create a new file to stream the data into
|
||||
File file = FSCom.open(pathname.c_str(), "w");
|
||||
File file = FSCom.open(pathname.c_str(), FILE_O_WRITE);
|
||||
size_t fileLength = 0;
|
||||
didwrite = true;
|
||||
|
||||
@@ -536,6 +539,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
// Abort the transfer if there is less than 50k space left on the filesystem.
|
||||
if (FSCom.totalBytes() - FSCom.usedBytes() < 51200) {
|
||||
file.flush();
|
||||
file.close();
|
||||
res->println("<p>Write aborted! Reserving 50k on filesystem.</p>");
|
||||
|
||||
@@ -553,6 +557,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
||||
}
|
||||
// enableLoopWDT();
|
||||
|
||||
file.flush();
|
||||
file.close();
|
||||
res->printf("<p>Saved %d bytes to %s</p>", (int)fileLength, pathname.c_str());
|
||||
}
|
||||
@@ -622,10 +627,10 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
|
||||
// data->memory
|
||||
JSONObject jsonObjMemory;
|
||||
jsonObjMemory["heap_total"] = new JSONValue((int)ESP.getHeapSize());
|
||||
jsonObjMemory["heap_free"] = new JSONValue((int)ESP.getFreeHeap());
|
||||
jsonObjMemory["psram_total"] = new JSONValue((int)ESP.getPsramSize());
|
||||
jsonObjMemory["psram_free"] = new JSONValue((int)ESP.getFreePsram());
|
||||
jsonObjMemory["heap_total"] = new JSONValue((int)memGet.getHeapSize());
|
||||
jsonObjMemory["heap_free"] = new JSONValue((int)memGet.getFreeHeap());
|
||||
jsonObjMemory["psram_total"] = new JSONValue((int)memGet.getPsramSize());
|
||||
jsonObjMemory["psram_free"] = new JSONValue((int)memGet.getFreePsram());
|
||||
jsonObjMemory["fs_total"] = new JSONValue((int)FSCom.totalBytes());
|
||||
jsonObjMemory["fs_used"] = new JSONValue((int)FSCom.usedBytes());
|
||||
jsonObjMemory["fs_free"] = new JSONValue(int(FSCom.totalBytes() - FSCom.usedBytes()));
|
||||
@@ -645,7 +650,7 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||
// data->radio
|
||||
JSONObject jsonObjRadio;
|
||||
jsonObjRadio["frequency"] = new JSONValue(RadioLibInterface::instance->getFreq());
|
||||
jsonObjRadio["lora_channel"] = new JSONValue((int)RadioLibInterface::instance->getChannelNum());
|
||||
jsonObjRadio["lora_channel"] = new JSONValue((int)RadioLibInterface::instance->getChannelNum() + 1);
|
||||
|
||||
// collect data to inner data object
|
||||
JSONObject jsonObjInner;
|
||||
@@ -833,7 +838,7 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
if (WiFi.encryptionType(i) != WIFI_AUTH_OPEN) {
|
||||
JSONObject thisNetwork;
|
||||
thisNetwork["ssid"] = new JSONValue(ssidArray);
|
||||
thisNetwork["rssi"] = new JSONValue(WiFi.RSSI(i));
|
||||
thisNetwork["rssi"] = new JSONValue(int(WiFi.RSSI(i)));
|
||||
networkObjs.push_back(new JSONValue(thisNetwork));
|
||||
}
|
||||
// Yield some cpu cycles to IP stack.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user