mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-17 00:02:55 +00:00
Compare commits
96 Commits
beta
...
thinknode-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48af1cd0e1 | ||
|
|
c3a7ad2865 | ||
|
|
06dac12a73 | ||
|
|
d60b263a00 | ||
|
|
654abe5b2c | ||
|
|
79e8fc94bc | ||
|
|
486fa74549 | ||
|
|
66193e1776 | ||
|
|
bacff5c1f0 | ||
|
|
faa6af74af | ||
|
|
81439f16d0 | ||
|
|
592a8f23db | ||
|
|
2baa9ccbe0 | ||
|
|
0336331411 | ||
|
|
ed4a798c60 | ||
|
|
5d7da6868e | ||
|
|
1bfa9ed4c4 | ||
|
|
b18794e98d | ||
|
|
f4e260e0f1 | ||
|
|
14463043bd | ||
|
|
376dc7ef3a | ||
|
|
c051c56544 | ||
|
|
d3976e7461 | ||
|
|
a4c92d9fd5 | ||
|
|
186cbe61bb | ||
|
|
0e3e8b7607 | ||
|
|
451e52b541 | ||
|
|
d743ba8e75 | ||
|
|
626dce8323 | ||
|
|
0100eeea67 | ||
|
|
5640179ce2 | ||
|
|
066da492d5 | ||
|
|
2b8806486d | ||
|
|
9ae545918c | ||
|
|
5374291c3c | ||
|
|
38b0c1588a | ||
|
|
f329de04c4 | ||
|
|
b09fa31492 | ||
|
|
a2a0150ee8 | ||
|
|
9ae92724a9 | ||
|
|
9cf369c5d0 | ||
|
|
441a7c5b20 | ||
|
|
ef298814f2 | ||
|
|
8d31fc5ec6 | ||
|
|
f9433a31d1 | ||
|
|
7232dddd69 | ||
|
|
10de230dba | ||
|
|
d18f3f7a65 | ||
|
|
6c09cf9d3d | ||
|
|
79a91578b7 | ||
|
|
17cd83085b | ||
|
|
b7bdcbe43e | ||
|
|
df063f40ff | ||
|
|
84bb1e33a6 | ||
|
|
955347bf50 | ||
|
|
4284fc2aec | ||
|
|
034aaa376a | ||
|
|
7212fb9caa | ||
|
|
4118e1c0f6 | ||
|
|
a62fed3289 | ||
|
|
7d2744fae0 | ||
|
|
beaebda4de | ||
|
|
36c2178570 | ||
|
|
50f9be9a2b | ||
|
|
8fe98db5dd | ||
|
|
531cad5e88 | ||
|
|
77e0a24838 | ||
|
|
6cad393688 | ||
|
|
0725b46744 | ||
|
|
6a6c409b9a | ||
|
|
7b14b173d9 | ||
|
|
3e40d7896b | ||
|
|
03f69b3b77 | ||
|
|
83954293d8 | ||
|
|
91621427f1 | ||
|
|
8d1b9c9dce | ||
|
|
538c05ad6c | ||
|
|
f6370bea8f | ||
|
|
468247fb94 | ||
|
|
3ae7e54681 | ||
|
|
0a124b7f3d | ||
|
|
7def82595d | ||
|
|
3a67204f6d | ||
|
|
d1b66782d1 | ||
|
|
718fd118b0 | ||
|
|
75f7ded12c | ||
|
|
7f78a624cd | ||
|
|
17324fa725 | ||
|
|
001654e90a | ||
|
|
4f817d69eb | ||
|
|
de83b448f9 | ||
|
|
c145be8e05 | ||
|
|
28f53d132a | ||
|
|
f045ca2303 | ||
|
|
b6830a68a0 | ||
|
|
13c4c2037d |
2
.github/actions/setup-base/action.yml
vendored
2
.github/actions/setup-base/action.yml
vendored
@@ -5,7 +5,7 @@ runs:
|
|||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
|||||||
2
.github/workflows/build_debian_src.yml
vendored
2
.github/workflows/build_debian_src.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
path: meshtasticd
|
path: meshtasticd
|
||||||
|
|||||||
2
.github/workflows/build_firmware.yml
vendored
2
.github/workflows/build_firmware.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
artifact-id: ${{ steps.upload.outputs.artifact-id }}
|
artifact-id: ${{ steps.upload.outputs.artifact-id }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
|||||||
176
.github/workflows/build_one_arch.yml
vendored
176
.github/workflows/build_one_arch.yml
vendored
@@ -1,176 +0,0 @@
|
|||||||
name: Build One Arch
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
# trunk-ignore(checkov/CKV_GHA_7)
|
|
||||||
arch:
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- esp32
|
|
||||||
- esp32s3
|
|
||||||
- esp32c3
|
|
||||||
- esp32c6
|
|
||||||
- nrf52840
|
|
||||||
- rp2040
|
|
||||||
- rp2350
|
|
||||||
- stm32
|
|
||||||
- native
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
env:
|
|
||||||
INPUT_ARCH: ${{ github.event.inputs.arch }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: 3.x
|
|
||||||
cache: pip
|
|
||||||
- run: pip install -U platformio
|
|
||||||
- name: Generate matrix
|
|
||||||
id: jsonStep
|
|
||||||
run: |
|
|
||||||
TARGETS=$(./bin/generate_ci_matrix.py $INPUT_ARCH --level extra)
|
|
||||||
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF"
|
|
||||||
echo "selected_arch=$TARGETS" >> $GITHUB_OUTPUT
|
|
||||||
outputs:
|
|
||||||
selected_arch: ${{ steps.jsonStep.outputs.selected_arch }}
|
|
||||||
|
|
||||||
version:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
- name: Get release version string
|
|
||||||
run: |
|
|
||||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
env:
|
|
||||||
BUILD_LOCATION: local
|
|
||||||
outputs:
|
|
||||||
long: ${{ steps.version.outputs.long }}
|
|
||||||
deb: ${{ steps.version.outputs.deb }}
|
|
||||||
|
|
||||||
build:
|
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
|
||||||
needs: [setup, version]
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
build: ${{ fromJson(needs.setup.outputs.selected_arch) }}
|
|
||||||
uses: ./.github/workflows/build_firmware.yml
|
|
||||||
with:
|
|
||||||
version: ${{ needs.version.outputs.long }}
|
|
||||||
pio_env: ${{ matrix.build.board }}
|
|
||||||
platform: ${{ matrix.build.arch }}
|
|
||||||
|
|
||||||
build-debian-src:
|
|
||||||
if: ${{ github.repository == 'meshtastic/firmware' && github.event_name != 'workflow_dispatch' || inputs.arch == 'native' }}
|
|
||||||
uses: ./.github/workflows/build_debian_src.yml
|
|
||||||
with:
|
|
||||||
series: UNRELEASED
|
|
||||||
build_location: local
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
package-pio-deps-native-tft:
|
|
||||||
if: ${{ inputs.arch == 'native' }}
|
|
||||||
uses: ./.github/workflows/package_pio_deps.yml
|
|
||||||
with:
|
|
||||||
pio_env: native-tft
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
test-native:
|
|
||||||
if: ${{ !contains(github.ref_name, 'event/') && github.event_name != 'workflow_dispatch' || !contains(github.ref_name, 'event/') && inputs.arch == 'native' }}
|
|
||||||
uses: ./.github/workflows/test_native.yml
|
|
||||||
|
|
||||||
gather-artifacts:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
arch:
|
|
||||||
- esp32
|
|
||||||
- esp32s3
|
|
||||||
- esp32c3
|
|
||||||
- esp32c6
|
|
||||||
- nrf52840
|
|
||||||
- rp2040
|
|
||||||
- rp2350
|
|
||||||
- stm32
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [version, build]
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
path: ./
|
|
||||||
pattern: firmware-${{inputs.arch}}-*
|
|
||||||
merge-multiple: true
|
|
||||||
|
|
||||||
- name: Display structure of downloaded files
|
|
||||||
run: ls -R
|
|
||||||
|
|
||||||
- name: Move files up
|
|
||||||
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
|
||||||
|
|
||||||
- name: Repackage in single firmware zip
|
|
||||||
uses: actions/upload-artifact@v5
|
|
||||||
with:
|
|
||||||
name: firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}
|
|
||||||
overwrite: true
|
|
||||||
path: |
|
|
||||||
./firmware-*.bin
|
|
||||||
./firmware-*.uf2
|
|
||||||
./firmware-*.hex
|
|
||||||
./firmware-*-ota.zip
|
|
||||||
./device-*.sh
|
|
||||||
./device-*.bat
|
|
||||||
./littlefs-*.bin
|
|
||||||
./bleota*bin
|
|
||||||
./Meshtastic_nRF52_factory_erase*.uf2
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
name: firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}
|
|
||||||
merge-multiple: true
|
|
||||||
path: ./output
|
|
||||||
|
|
||||||
# For diagnostics
|
|
||||||
- name: Show artifacts
|
|
||||||
run: ls -lR
|
|
||||||
|
|
||||||
- name: Device scripts permissions
|
|
||||||
run: |
|
|
||||||
chmod +x ./output/device-install.sh
|
|
||||||
chmod +x ./output/device-update.sh
|
|
||||||
|
|
||||||
- name: Zip firmware
|
|
||||||
run: zip -j -9 -r ./firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
|
||||||
|
|
||||||
- name: Repackage in single elfs zip
|
|
||||||
uses: actions/upload-artifact@v5
|
|
||||||
with:
|
|
||||||
name: debug-elfs-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip
|
|
||||||
overwrite: true
|
|
||||||
path: ./*.elf
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
- uses: scruplelesswizard/comment-artifact@main
|
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
|
||||||
with:
|
|
||||||
name: firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}
|
|
||||||
description: "Download firmware-${{inputs.arch}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
29
.github/workflows/build_one_target.yml
vendored
29
.github/workflows/build_one_target.yml
vendored
@@ -15,7 +15,6 @@ on:
|
|||||||
- rp2040
|
- rp2040
|
||||||
- rp2350
|
- rp2350
|
||||||
- stm32
|
- stm32
|
||||||
- native
|
|
||||||
target:
|
target:
|
||||||
type: string
|
type: string
|
||||||
required: false
|
required: false
|
||||||
@@ -42,10 +41,9 @@ jobs:
|
|||||||
- rp2040
|
- rp2040
|
||||||
- rp2350
|
- rp2350
|
||||||
- stm32
|
- stm32
|
||||||
|
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-python@v6
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
@@ -60,13 +58,13 @@ jobs:
|
|||||||
echo "Arch: ${{matrix.arch}}" >> $GITHUB_STEP_SUMMARY
|
echo "Arch: ${{matrix.arch}}" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "Ref: $GITHUB_REF" >> $GITHUB_STEP_SUMMARY
|
echo "Ref: $GITHUB_REF" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "Targets:" >> $GITHUB_STEP_SUMMARY
|
echo "Targets:" >> $GITHUB_STEP_SUMMARY
|
||||||
echo $TARGETS >> $GITHUB_STEP_SUMMARY
|
echo $TARGETS | jq -r 'sort_by(.board) |.[] | "- " + .board' >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
version:
|
version:
|
||||||
if: ${{ inputs.target != '' }}
|
if: ${{ inputs.target != '' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
- name: Get release version string
|
- name: Get release version string
|
||||||
run: |
|
run: |
|
||||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
@@ -87,25 +85,6 @@ jobs:
|
|||||||
pio_env: ${{ inputs.target }}
|
pio_env: ${{ inputs.target }}
|
||||||
platform: ${{ inputs.arch }}
|
platform: ${{ inputs.arch }}
|
||||||
|
|
||||||
build-debian-src:
|
|
||||||
if: ${{ github.repository == 'meshtastic/firmware' && inputs.arch == 'native' }}
|
|
||||||
uses: ./.github/workflows/build_debian_src.yml
|
|
||||||
with:
|
|
||||||
series: UNRELEASED
|
|
||||||
build_location: local
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
package-pio-deps-native-tft:
|
|
||||||
if: ${{ inputs.arch == 'native' }}
|
|
||||||
uses: ./.github/workflows/package_pio_deps.yml
|
|
||||||
with:
|
|
||||||
pio_env: native-tft
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
test-native:
|
|
||||||
if: ${{ !contains(github.ref_name, 'event/') && github.event_name != 'workflow_dispatch' || !contains(github.ref_name, 'event/') && inputs.arch == 'native' && inputs.target != '' }}
|
|
||||||
uses: ./.github/workflows/test_native.yml
|
|
||||||
|
|
||||||
gather-artifacts:
|
gather-artifacts:
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -114,7 +93,7 @@ jobs:
|
|||||||
needs: [version, build]
|
needs: [version, build]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|||||||
2
.github/workflows/docker_build.yml
vendored
2
.github/workflows/docker_build.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
|||||||
runs-on: ${{ inputs.runs-on }}
|
runs-on: ${{ inputs.runs-on }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
|||||||
2
.github/workflows/docker_manifest.yml
vendored
2
.github/workflows/docker_manifest.yml
vendored
@@ -83,7 +83,7 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
|||||||
2
.github/workflows/hook_copr.yml
vendored
2
.github/workflows/hook_copr.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
|
|||||||
14
.github/workflows/main_matrix.yml
vendored
14
.github/workflows/main_matrix.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
|||||||
- check
|
- check
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-python@v6
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
@@ -59,7 +59,7 @@ jobs:
|
|||||||
version:
|
version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
- name: Get release version string
|
- name: Get release version string
|
||||||
run: |
|
run: |
|
||||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
@@ -81,7 +81,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
- name: Build base
|
- name: Build base
|
||||||
id: base
|
id: base
|
||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
@@ -163,7 +163,7 @@ jobs:
|
|||||||
needs: [version, build]
|
needs: [version, build]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
@@ -242,7 +242,7 @@ jobs:
|
|||||||
- package-pio-deps-native-tft
|
- package-pio-deps-native-tft
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
@@ -311,7 +311,7 @@ jobs:
|
|||||||
needs: [release-artifacts, version]
|
needs: [release-artifacts, version]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
@@ -366,7 +366,7 @@ jobs:
|
|||||||
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
|
|||||||
14
.github/workflows/merge_queue.yml
vendored
14
.github/workflows/merge_queue.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
- check
|
- check
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-python@v6
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
@@ -40,7 +40,7 @@ jobs:
|
|||||||
version:
|
version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
- name: Get release version string
|
- name: Get release version string
|
||||||
run: |
|
run: |
|
||||||
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
- name: Build base
|
- name: Build base
|
||||||
id: base
|
id: base
|
||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
@@ -142,7 +142,7 @@ jobs:
|
|||||||
needs: [version, build]
|
needs: [version, build]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
@@ -221,7 +221,7 @@ jobs:
|
|||||||
- package-pio-deps-native-tft
|
- package-pio-deps-native-tft
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
@@ -290,7 +290,7 @@ jobs:
|
|||||||
needs: [release-artifacts, version]
|
needs: [release-artifacts, version]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
@@ -345,7 +345,7 @@ jobs:
|
|||||||
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
|
|||||||
4
.github/workflows/nightly.yml
vendored
4
.github/workflows/nightly.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Trunk Check
|
- name: Trunk Check
|
||||||
uses: trunk-io/trunk-action@v1
|
uses: trunk-io/trunk-action@v1
|
||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
pull-requests: write # For trunk to create PRs
|
pull-requests: write # For trunk to create PRs
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Trunk Upgrade
|
- name: Trunk Upgrade
|
||||||
uses: trunk-io/trunk-action/upgrade@v1
|
uses: trunk-io/trunk-action/upgrade@v1
|
||||||
|
|||||||
2
.github/workflows/package_obs.yml
vendored
2
.github/workflows/package_obs.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
|||||||
needs: build-debian-src
|
needs: build-debian-src
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
path: meshtasticd
|
path: meshtasticd
|
||||||
|
|||||||
2
.github/workflows/package_pio_deps.yml
vendored
2
.github/workflows/package_pio_deps.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
|||||||
2
.github/workflows/package_ppa.yml
vendored
2
.github/workflows/package_ppa.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
needs: build-debian-src
|
needs: build-debian-src
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
path: meshtasticd
|
path: meshtasticd
|
||||||
|
|||||||
2
.github/workflows/pr_tests.yml
vendored
2
.github/workflows/pr_tests.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
|||||||
checks: write
|
checks: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
|
|||||||
5
.github/workflows/release_channels.yml
vendored
5
.github/workflows/release_channels.yml
vendored
@@ -60,7 +60,10 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
# Always use master branch for version bumps
|
||||||
|
ref: master
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
|
|||||||
2
.github/workflows/sec_sast_semgrep_cron.yml
vendored
2
.github/workflows/sec_sast_semgrep_cron.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# step 1
|
# step 1
|
||||||
- name: clone application source code
|
- name: clone application source code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
# step 2
|
# step 2
|
||||||
- name: full scan
|
- name: full scan
|
||||||
|
|||||||
2
.github/workflows/sec_sast_semgrep_pull.yml
vendored
2
.github/workflows/sec_sast_semgrep_pull.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# step 1
|
# step 1
|
||||||
- name: clone application source code
|
- name: clone application source code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|||||||
6
.github/workflows/test_native.yml
vendored
6
.github/workflows/test_native.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
name: Native Simulator Tests
|
name: Native Simulator Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
@@ -70,7 +70,7 @@ jobs:
|
|||||||
name: Native PlatformIO Tests
|
name: Native PlatformIO Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
@@ -127,7 +127,7 @@ jobs:
|
|||||||
- platformio-tests
|
- platformio-tests
|
||||||
if: always()
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|||||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
runs-on: test-runner
|
runs-on: test-runner
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
# - uses: actions/setup-python@v5
|
# - uses: actions/setup-python@v5
|
||||||
# with:
|
# with:
|
||||||
|
|||||||
2
.github/workflows/trunk_annotate_pr.yml
vendored
2
.github/workflows/trunk_annotate_pr.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Trunk Check
|
- name: Trunk Check
|
||||||
uses: trunk-io/trunk-action@v1
|
uses: trunk-io/trunk-action@v1
|
||||||
|
|||||||
2
.github/workflows/trunk_check.yml
vendored
2
.github/workflows/trunk_check.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Trunk Check
|
- name: Trunk Check
|
||||||
uses: trunk-io/trunk-action@v1
|
uses: trunk-io/trunk-action@v1
|
||||||
|
|||||||
2
.github/workflows/trunk_format_pr.yml
vendored
2
.github/workflows/trunk_format_pr.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|||||||
2
.github/workflows/update_protobufs.yml
vendored
2
.github/workflows/update_protobufs.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
|
|||||||
@@ -37,4 +37,3 @@ Join our community and help improve Meshtastic! 🚀
|
|||||||
## Stats
|
## Stats
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ extends = arduino_base
|
|||||||
platform_packages =
|
platform_packages =
|
||||||
; our custom Git version until they merge our PR
|
; our custom Git version until they merge our PR
|
||||||
# TODO renovate
|
# TODO renovate
|
||||||
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf
|
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#c770c8a16a351b55b86e347a3d9d7b74ad0bbf39
|
||||||
; Don't renovate toolchain-gccarmnoneeabi
|
; Don't renovate toolchain-gccarmnoneeabi
|
||||||
platformio/toolchain-gccarmnoneeabi@~1.90301.0
|
platformio/toolchain-gccarmnoneeabi@~1.90301.0
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ lib_deps =
|
|||||||
${environmental_base.lib_deps}
|
${environmental_base.lib_deps}
|
||||||
${environmental_extra.lib_deps}
|
${environmental_extra.lib_deps}
|
||||||
# renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master
|
# renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master
|
||||||
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/5f838d2709461a2c981f642917aa50254a25c14c.zip
|
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/8cde7189b5ead9dcd49f72601b43b969c0bbc06e.zip
|
||||||
|
|
||||||
; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board.
|
; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board.
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ build_flags =
|
|||||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||||
-DHAL_DAC_MODULE_ONLY
|
-DHAL_DAC_MODULE_ONLY
|
||||||
-DHAL_RNG_MODULE_ENABLED
|
-DHAL_RNG_MODULE_ENABLED
|
||||||
|
-Wl,--wrap=__assert_func
|
||||||
|
-Wl,--wrap=strerror
|
||||||
|
-Wl,--wrap=_tzset_unlocked_r
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>
|
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>
|
||||||
|
|||||||
@@ -87,6 +87,9 @@
|
|||||||
</screenshots>
|
</screenshots>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="2.7.16" date="2025-11-19">
|
||||||
|
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.16</url>
|
||||||
|
</release>
|
||||||
<release version="2.7.15" date="2025-11-13">
|
<release version="2.7.15" date="2025-11-13">
|
||||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.15</url>
|
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.15</url>
|
||||||
</release>
|
</release>
|
||||||
|
|||||||
53
boards/ThinkNode-M3.json
Normal file
53
boards/ThinkNode-M3.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x4405"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"]
|
||||||
|
],
|
||||||
|
"usb_product": "elecrow_eink",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "ELECROW-ThinkNode-M3",
|
||||||
|
"variants_dir": "variants",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"onboard_tools": ["jlink"],
|
||||||
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "elecrow nrf",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "",
|
||||||
|
"vendor": "ELECROW"
|
||||||
|
}
|
||||||
53
boards/ThinkNode-M6.json
Normal file
53
boards/ThinkNode-M6.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_NRF52840_ELECROW_M6 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x4405"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"]
|
||||||
|
],
|
||||||
|
"usb_product": "elecrow_thinknode_m6",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "ELECROW-ThinkNode-M6",
|
||||||
|
"variants_dir": "variants",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"onboard_tools": ["jlink"],
|
||||||
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "ELECROW ThinkNode M6",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "https://www.elecrow.com/thinknode-m6-outdoor-solar-power-for-lora-powered-by-nrf52840-supports-gps.html",
|
||||||
|
"vendor": "ELECROW"
|
||||||
|
}
|
||||||
56
boards/muzi-base.json
Normal file
56
boards/muzi-base.json
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_NRF52840_MUZI_BASE -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [["0x239A", "0xcafe"]],
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "muzi-base",
|
||||||
|
"variants_dir": "variants",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"onboard_tools": ["jlink"],
|
||||||
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "Muzi Base",
|
||||||
|
"url": "https://muzi.works/",
|
||||||
|
"vendor": "MuziWorks",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": [
|
||||||
|
"jlink",
|
||||||
|
"nrfjprog",
|
||||||
|
"nrfutil",
|
||||||
|
"blackmagic",
|
||||||
|
"cmsis-dap",
|
||||||
|
"mbed",
|
||||||
|
"stlink"
|
||||||
|
],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
}
|
||||||
|
}
|
||||||
7
debian/changelog
vendored
7
debian/changelog
vendored
@@ -1,3 +1,10 @@
|
|||||||
|
meshtasticd (2.7.16.0) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Version 2.7.16
|
||||||
|
|
||||||
|
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Wed, 19 Nov 2025 16:12:32 +0000
|
||||||
|
|
||||||
|
|
||||||
meshtasticd (2.7.15.0) unstable; urgency=medium
|
meshtasticd (2.7.15.0) unstable; urgency=medium
|
||||||
|
|
||||||
* Version 2.7.15
|
* Version 2.7.15
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ BuildRequires: python3dist(grpcio[protobuf])
|
|||||||
BuildRequires: python3dist(grpcio-tools)
|
BuildRequires: python3dist(grpcio-tools)
|
||||||
BuildRequires: git-core
|
BuildRequires: git-core
|
||||||
BuildRequires: gcc-c++
|
BuildRequires: gcc-c++
|
||||||
|
BuildRequires: (glibc-devel >= 2.38) or pkgconfig(libbsd-overlay)
|
||||||
BuildRequires: pkgconfig(yaml-cpp)
|
BuildRequires: pkgconfig(yaml-cpp)
|
||||||
BuildRequires: pkgconfig(libgpiod)
|
BuildRequires: pkgconfig(libgpiod)
|
||||||
BuildRequires: pkgconfig(bluez)
|
BuildRequires: pkgconfig(bluez)
|
||||||
|
|||||||
@@ -115,7 +115,8 @@ lib_deps =
|
|||||||
[radiolib_base]
|
[radiolib_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
|
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
|
||||||
jgromes/RadioLib@7.3.0
|
# jgromes/RadioLib@7.4.0
|
||||||
|
https://github.com/jgromes/RadioLib/archive/536c7267362e2c1345be7054ba45e503252975ff.zip
|
||||||
|
|
||||||
[device-ui_base]
|
[device-ui_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
@@ -181,6 +182,8 @@ lib_deps =
|
|||||||
dfrobot/DFRobot_BMM150@1.0.0
|
dfrobot/DFRobot_BMM150@1.0.0
|
||||||
# renovate: datasource=custom.pio depName=Adafruit_TSL2561 packageName=adafruit/library/Adafruit TSL2561
|
# renovate: datasource=custom.pio depName=Adafruit_TSL2561 packageName=adafruit/library/Adafruit TSL2561
|
||||||
adafruit/Adafruit TSL2561@1.1.2
|
adafruit/Adafruit TSL2561@1.1.2
|
||||||
|
# renovate: datasource=custom.pio depName=BH1750_WE packageName=wollewald/BH1750_WE@^1.1.10
|
||||||
|
wollewald/BH1750_WE@^1.1.10
|
||||||
|
|
||||||
; (not included in native / portduino)
|
; (not included in native / portduino)
|
||||||
[environmental_extra]
|
[environmental_extra]
|
||||||
|
|||||||
Submodule protobufs updated: 7654db2e2d...52fa252f1e
@@ -13,6 +13,11 @@ extern MemGet memGet;
|
|||||||
#define LED_STATE_ON 1
|
#define LED_STATE_ON 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// WIFI LED
|
||||||
|
#ifndef WIFI_STATE_ON
|
||||||
|
#define WIFI_STATE_ON 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// DEBUG
|
// DEBUG
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -147,7 +152,9 @@ extern "C" void logLegacy(const char *level, const char *fmt, ...);
|
|||||||
// Default Bluetooth PIN
|
// Default Bluetooth PIN
|
||||||
#define defaultBLEPin 123456
|
#define defaultBLEPin 123456
|
||||||
|
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && defined(USE_CH390D)
|
||||||
|
#include <ESP32_CH390.h>
|
||||||
|
#elif HAS_ETHERNET && !defined(USE_WS5500)
|
||||||
#include <RAK13800_W5100S.h>
|
#include <RAK13800_W5100S.h>
|
||||||
#endif // HAS_ETHERNET
|
#endif // HAS_ETHERNET
|
||||||
|
|
||||||
|
|||||||
@@ -14,16 +14,16 @@ class NodeStatus : public Status
|
|||||||
CallbackObserver<NodeStatus, const NodeStatus *> statusObserver =
|
CallbackObserver<NodeStatus, const NodeStatus *> statusObserver =
|
||||||
CallbackObserver<NodeStatus, const NodeStatus *>(this, &NodeStatus::updateStatus);
|
CallbackObserver<NodeStatus, const NodeStatus *>(this, &NodeStatus::updateStatus);
|
||||||
|
|
||||||
uint8_t numOnline = 0;
|
uint16_t numOnline = 0;
|
||||||
uint8_t numTotal = 0;
|
uint16_t numTotal = 0;
|
||||||
|
|
||||||
uint8_t lastNumTotal = 0;
|
uint16_t lastNumTotal = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool forceUpdate = false;
|
bool forceUpdate = false;
|
||||||
|
|
||||||
NodeStatus() { statusType = STATUS_TYPE_NODE; }
|
NodeStatus() { statusType = STATUS_TYPE_NODE; }
|
||||||
NodeStatus(uint8_t numOnline, uint8_t numTotal, bool forceUpdate = false) : Status()
|
NodeStatus(uint16_t numOnline, uint16_t numTotal, bool forceUpdate = false) : Status()
|
||||||
{
|
{
|
||||||
this->forceUpdate = forceUpdate;
|
this->forceUpdate = forceUpdate;
|
||||||
this->numOnline = numOnline;
|
this->numOnline = numOnline;
|
||||||
@@ -34,11 +34,11 @@ class NodeStatus : public Status
|
|||||||
|
|
||||||
void observe(Observable<const NodeStatus *> *source) { statusObserver.observe(source); }
|
void observe(Observable<const NodeStatus *> *source) { statusObserver.observe(source); }
|
||||||
|
|
||||||
uint8_t getNumOnline() const { return numOnline; }
|
uint16_t getNumOnline() const { return numOnline; }
|
||||||
|
|
||||||
uint8_t getNumTotal() const { return numTotal; }
|
uint16_t getNumTotal() const { return numTotal; }
|
||||||
|
|
||||||
uint8_t getLastNumTotal() const { return lastNumTotal; }
|
uint16_t getLastNumTotal() const { return lastNumTotal; }
|
||||||
|
|
||||||
bool matches(const NodeStatus *newStatus) const
|
bool matches(const NodeStatus *newStatus) const
|
||||||
{
|
{
|
||||||
@@ -56,7 +56,7 @@ class NodeStatus : public Status
|
|||||||
numTotal = newStatus->getNumTotal();
|
numTotal = newStatus->getNumTotal();
|
||||||
}
|
}
|
||||||
if (isDirty || newStatus->forceUpdate) {
|
if (isDirty || newStatus->forceUpdate) {
|
||||||
LOG_DEBUG("Node status update: %d online, %d total", numOnline, numTotal);
|
LOG_DEBUG("Node status update: %u online, %u total", numOnline, numTotal);
|
||||||
onNewStatus.notifyObservers(this);
|
onNewStatus.notifyObservers(this);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ static HasBatteryLevel *batteryLevel; // Default to NULL for no battery level se
|
|||||||
|
|
||||||
#ifdef BATTERY_PIN
|
#ifdef BATTERY_PIN
|
||||||
|
|
||||||
static void adcEnable()
|
void battery_adcEnable()
|
||||||
{
|
{
|
||||||
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
|
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
|
||||||
#ifdef ADC_USE_PULLUP
|
#ifdef ADC_USE_PULLUP
|
||||||
@@ -214,7 +214,7 @@ static void adcEnable()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adcDisable()
|
static void battery_adcDisable()
|
||||||
{
|
{
|
||||||
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
|
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
|
||||||
#ifdef ADC_USE_PULLUP
|
#ifdef ADC_USE_PULLUP
|
||||||
@@ -278,6 +278,11 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if defined(BATTERY_CHARGING_INV)
|
||||||
|
// bit of trickery to show 99% up until the charge finishes
|
||||||
|
if (!digitalRead(BATTERY_CHARGING_INV) && battery_SOC > 99)
|
||||||
|
battery_SOC = 99;
|
||||||
|
#endif
|
||||||
return clamp((int)(battery_SOC), 0, 100);
|
return clamp((int)(battery_SOC), 0, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +325,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
uint32_t raw = 0;
|
uint32_t raw = 0;
|
||||||
float scaled = 0;
|
float scaled = 0;
|
||||||
|
|
||||||
adcEnable();
|
battery_adcEnable();
|
||||||
#ifdef ARCH_ESP32 // ADC block for espressif platforms
|
#ifdef ARCH_ESP32 // ADC block for espressif platforms
|
||||||
raw = espAdcRead();
|
raw = espAdcRead();
|
||||||
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
|
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
|
||||||
@@ -332,7 +337,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
raw = raw / BATTERY_SENSE_SAMPLES;
|
raw = raw / BATTERY_SENSE_SAMPLES;
|
||||||
scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
|
scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
|
||||||
#endif
|
#endif
|
||||||
adcDisable();
|
battery_adcDisable();
|
||||||
|
|
||||||
if (!initial_read_done) {
|
if (!initial_read_done) {
|
||||||
// Flush the smoothing filter with an ADC reading, if the reading is plausibly correct
|
// Flush the smoothing filter with an ADC reading, if the reading is plausibly correct
|
||||||
@@ -455,6 +460,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
}
|
}
|
||||||
// if it's not HIGH - check the battery
|
// if it's not HIGH - check the battery
|
||||||
#endif
|
#endif
|
||||||
|
#elif defined(MUZI_BASE)
|
||||||
|
return NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk;
|
||||||
#endif
|
#endif
|
||||||
return getBattVoltage() > chargingVolt;
|
return getBattVoltage() > chargingVolt;
|
||||||
}
|
}
|
||||||
@@ -470,6 +477,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
|||||||
#endif
|
#endif
|
||||||
#ifdef EXT_CHRG_DETECT
|
#ifdef EXT_CHRG_DETECT
|
||||||
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
|
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
|
||||||
|
#elif defined(BATTERY_CHARGING_INV)
|
||||||
|
return !digitalRead(BATTERY_CHARGING_INV);
|
||||||
#else
|
#else
|
||||||
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(DISABLE_INA_CHARGING_DETECTION)
|
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(DISABLE_INA_CHARGING_DETECTION)
|
||||||
if (hasINA()) {
|
if (hasINA()) {
|
||||||
@@ -702,7 +711,16 @@ bool Power::setup()
|
|||||||
},
|
},
|
||||||
CHANGE);
|
CHANGE);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BATTERY_CHARGING_INV
|
||||||
|
attachInterrupt(
|
||||||
|
BATTERY_CHARGING_INV,
|
||||||
|
[]() {
|
||||||
|
power->setIntervalFromNow(0);
|
||||||
|
runASAP = true;
|
||||||
|
BaseType_t higherWake = 0;
|
||||||
|
},
|
||||||
|
CHANGE);
|
||||||
|
#endif
|
||||||
enabled = found;
|
enabled = found;
|
||||||
low_voltage_counter = 0;
|
low_voltage_counter = 0;
|
||||||
|
|
||||||
@@ -759,6 +777,8 @@ void Power::shutdown()
|
|||||||
if (screen) {
|
if (screen) {
|
||||||
#ifdef T_DECK_PRO
|
#ifdef T_DECK_PRO
|
||||||
screen->showSimpleBanner("Device is powered off.\nConnect USB to start!", 0); // T-Deck Pro has no power button
|
screen->showSimpleBanner("Device is powered off.\nConnect USB to start!", 0); // T-Deck Pro has no power button
|
||||||
|
#elif USE_EINK
|
||||||
|
screen->showSimpleBanner("Shutting Down...", 2250); // dismiss after 3 seconds to avoid the banner on the sleep screen
|
||||||
#else
|
#else
|
||||||
screen->showSimpleBanner("Shutting Down...", 0); // stays on screen
|
screen->showSimpleBanner("Shutting Down...", 0); // stays on screen
|
||||||
#endif
|
#endif
|
||||||
@@ -906,13 +926,8 @@ void Power::readPowerStatus()
|
|||||||
low_voltage_counter++;
|
low_voltage_counter++;
|
||||||
LOG_DEBUG("Low voltage counter: %d/10", low_voltage_counter);
|
LOG_DEBUG("Low voltage counter: %d/10", low_voltage_counter);
|
||||||
if (low_voltage_counter > 10) {
|
if (low_voltage_counter > 10) {
|
||||||
#ifdef ARCH_NRF52
|
|
||||||
// We can't trigger deep sleep on NRF52, it's freezing the board
|
|
||||||
LOG_DEBUG("Low voltage detected, but not trigger deep sleep");
|
|
||||||
#else
|
|
||||||
LOG_INFO("Low voltage detected, trigger deep sleep");
|
LOG_INFO("Low voltage detected, trigger deep sleep");
|
||||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
low_voltage_counter = 0;
|
low_voltage_counter = 0;
|
||||||
@@ -1552,4 +1567,4 @@ bool Power::meshSolarInit()
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define ICM20948_ADDR_ALT 0x68
|
#define ICM20948_ADDR_ALT 0x68
|
||||||
#define BHI260AP_ADDR 0x28
|
#define BHI260AP_ADDR 0x28
|
||||||
#define BMM150_ADDR 0x13
|
#define BMM150_ADDR 0x13
|
||||||
|
#define DA217_ADDR 0x26
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// LED
|
// LED
|
||||||
@@ -395,6 +396,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define HAS_RGB_LED
|
#define HAS_RGB_LED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LED_STATE_OFF
|
||||||
|
#define LED_STATE_OFF 0
|
||||||
|
#endif
|
||||||
|
#ifndef LED_STATE_ON
|
||||||
|
#define LED_STATE_ON 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// default mapping of pins
|
// default mapping of pins
|
||||||
#if defined(PIN_BUTTON2) && !defined(CANCEL_BUTTON_PIN)
|
#if defined(PIN_BUTTON2) && !defined(CANCEL_BUTTON_PIN)
|
||||||
#define ALT_BUTTON_PIN PIN_BUTTON2
|
#define ALT_BUTTON_PIN PIN_BUTTON2
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
|
|||||||
if (i2cBus->available())
|
if (i2cBus->available())
|
||||||
i2cBus->read();
|
i2cBus->read();
|
||||||
}
|
}
|
||||||
|
LOG_DEBUG("Register value: 0x%x", value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,14 +378,13 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
}
|
}
|
||||||
case SHT31_4x_ADDR: // same as OPT3001_ADDR_ALT
|
case SHT31_4x_ADDR: // same as OPT3001_ADDR_ALT
|
||||||
case SHT31_4x_ADDR_ALT: // same as OPT3001_ADDR
|
case SHT31_4x_ADDR_ALT: // same as OPT3001_ADDR
|
||||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2);
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2);
|
||||||
if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0x11f3 || registerValue == 0xe9c ||
|
if (registerValue == 0x5449) {
|
||||||
registerValue == 0xc8d) {
|
|
||||||
type = SHT4X;
|
|
||||||
logFoundDevice("SHT4X", (uint8_t)addr.address);
|
|
||||||
} else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) {
|
|
||||||
type = OPT3001;
|
type = OPT3001;
|
||||||
logFoundDevice("OPT3001", (uint8_t)addr.address);
|
logFoundDevice("OPT3001", (uint8_t)addr.address);
|
||||||
|
} else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2) != 0) { // unique SHT4x serial number
|
||||||
|
type = SHT4X;
|
||||||
|
logFoundDevice("SHT4X", (uint8_t)addr.address);
|
||||||
} else {
|
} else {
|
||||||
type = SHT31;
|
type = SHT31;
|
||||||
logFoundDevice("SHT31", (uint8_t)addr.address);
|
logFoundDevice("SHT31", (uint8_t)addr.address);
|
||||||
@@ -465,8 +465,23 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address);
|
|
||||||
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
|
||||||
|
case TCA9555_ADDR:
|
||||||
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x01), 1);
|
||||||
|
if (registerValue == 0x13) {
|
||||||
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
||||||
|
if (registerValue == 0x81) {
|
||||||
|
type = DA217;
|
||||||
|
logFoundDevice("DA217", (uint8_t)addr.address);
|
||||||
|
} else {
|
||||||
|
type = TCA9555;
|
||||||
|
logFoundDevice("TCA9555", (uint8_t)addr.address);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type = TCA9555;
|
||||||
|
logFoundDevice("TCA9555", (uint8_t)addr.address);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case TSL25911_ADDR:
|
case TSL25911_ADDR:
|
||||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x12), 1);
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x12), 1);
|
||||||
if (registerValue == 0x50) {
|
if (registerValue == 0x50) {
|
||||||
@@ -532,6 +547,11 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
case ICM20948_ADDR: // same as BMX160_ADDR
|
case ICM20948_ADDR: // same as BMX160_ADDR
|
||||||
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR
|
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR
|
||||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
||||||
|
#ifdef HAS_ICM20948
|
||||||
|
type = ICM20948;
|
||||||
|
logFoundDevice("ICM20948", (uint8_t)addr.address);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
if (registerValue == 0xEA) {
|
if (registerValue == 0xEA) {
|
||||||
type = ICM20948;
|
type = ICM20948;
|
||||||
logFoundDevice("ICM20948", (uint8_t)addr.address);
|
logFoundDevice("ICM20948", (uint8_t)addr.address);
|
||||||
|
|||||||
@@ -38,14 +38,16 @@ template <typename T, std::size_t N> std::size_t array_count(const T (&)[N])
|
|||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) || defined(ARCH_STM32WL)
|
#ifndef GPS_SERIAL_PORT
|
||||||
#if defined(GPS_SERIAL_PORT)
|
#define GPS_SERIAL_PORT Serial1
|
||||||
HardwareSerial *GPS::_serial_gps = &GPS_SERIAL_PORT;
|
|
||||||
#else
|
|
||||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARCH_NRF52)
|
||||||
|
Uart *GPS::_serial_gps = &GPS_SERIAL_PORT;
|
||||||
|
#elif defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) || defined(ARCH_STM32WL)
|
||||||
|
HardwareSerial *GPS::_serial_gps = &GPS_SERIAL_PORT;
|
||||||
#elif defined(ARCH_RP2040)
|
#elif defined(ARCH_RP2040)
|
||||||
SerialUART *GPS::_serial_gps = &Serial1;
|
SerialUART *GPS::_serial_gps = &GPS_SERIAL_PORT;
|
||||||
#else
|
#else
|
||||||
HardwareSerial *GPS::_serial_gps = nullptr;
|
HardwareSerial *GPS::_serial_gps = nullptr;
|
||||||
#endif
|
#endif
|
||||||
@@ -240,6 +242,9 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
|
|||||||
buffer[bytesRead] = b;
|
buffer[bytesRead] = b;
|
||||||
bytesRead++;
|
bytesRead++;
|
||||||
if ((bytesRead == 767) || (b == '\r')) {
|
if ((bytesRead == 767) || (b == '\r')) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_DEBUG(debugmsg.c_str());
|
||||||
|
#endif
|
||||||
if (strnstr((char *)buffer, message, bytesRead) != nullptr) {
|
if (strnstr((char *)buffer, message, bytesRead) != nullptr) {
|
||||||
#ifdef GPS_DEBUG
|
#ifdef GPS_DEBUG
|
||||||
LOG_DEBUG("Found: %s", message); // Log the found message
|
LOG_DEBUG("Found: %s", message); // Log the found message
|
||||||
@@ -247,9 +252,6 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
|
|||||||
return GNSS_RESPONSE_OK;
|
return GNSS_RESPONSE_OK;
|
||||||
} else {
|
} else {
|
||||||
bytesRead = 0;
|
bytesRead = 0;
|
||||||
#ifdef GPS_DEBUG
|
|
||||||
LOG_DEBUG(debugmsg.c_str());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1275,6 +1277,24 @@ GnssModel_t GPS::probe(int serialSpeed)
|
|||||||
memset(&ublox_info, 0, sizeof(ublox_info));
|
memset(&ublox_info, 0, sizeof(ublox_info));
|
||||||
delay(100);
|
delay(100);
|
||||||
|
|
||||||
|
#if defined(PIN_GPS_RESET) && PIN_GPS_RESET != -1
|
||||||
|
digitalWrite(PIN_GPS_RESET, GPS_RESET_MODE); // assert for 10ms
|
||||||
|
delay(10);
|
||||||
|
digitalWrite(PIN_GPS_RESET, !GPS_RESET_MODE);
|
||||||
|
|
||||||
|
// attempt to detect the chip based on boot messages
|
||||||
|
std::vector<ChipInfo> passive_detect = {
|
||||||
|
{"AG3335", "$PAIR021,AG3335", GNSS_MODEL_AG3335},
|
||||||
|
{"AG3352", "$PAIR021,AG3352", GNSS_MODEL_AG3352},
|
||||||
|
{"RYS3520", "$PAIR021,REYAX_RYS3520_V2", GNSS_MODEL_AG3352},
|
||||||
|
{"UC6580", "UC6580", GNSS_MODEL_UC6580},
|
||||||
|
// as L76K is sort of a last ditch effort, we won't attempt to detect it by startup messages for now.
|
||||||
|
/*{"L76K", "SW=URANUS", GNSS_MODEL_MTK}*/};
|
||||||
|
GnssModel_t detectedDriver = getProbeResponse(500, passive_detect, serialSpeed);
|
||||||
|
if (detectedDriver != GNSS_MODEL_UNKNOWN) {
|
||||||
|
return detectedDriver;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// Close all NMEA sentences, valid for L76K, ATGM336H (and likely other AT6558 devices)
|
// Close all NMEA sentences, valid for L76K, ATGM336H (and likely other AT6558 devices)
|
||||||
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
|
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
|
||||||
delay(20);
|
delay(20);
|
||||||
@@ -1473,12 +1493,12 @@ GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (c == ',' || (responseLen >= 2 && response[responseLen - 2] == '\r' && response[responseLen - 1] == '\n')) {
|
if (c == ',' || (responseLen >= 2 && response[responseLen - 2] == '\r' && response[responseLen - 1] == '\n')) {
|
||||||
#ifdef GPS_DEBUG
|
|
||||||
LOG_DEBUG(response);
|
|
||||||
#endif
|
|
||||||
// check if we can see our chips
|
// check if we can see our chips
|
||||||
for (const auto &chipInfo : responseMap) {
|
for (const auto &chipInfo : responseMap) {
|
||||||
if (strstr(response, chipInfo.detectionString.c_str()) != nullptr) {
|
if (strstr(response, chipInfo.detectionString.c_str()) != nullptr) {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_DEBUG(response);
|
||||||
|
#endif
|
||||||
LOG_INFO("%s detected", chipInfo.chipName.c_str());
|
LOG_INFO("%s detected", chipInfo.chipName.c_str());
|
||||||
delete[] response; // Cleanup before return
|
delete[] response; // Cleanup before return
|
||||||
return chipInfo.driver;
|
return chipInfo.driver;
|
||||||
@@ -1486,6 +1506,9 @@ GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (responseLen >= 2 && response[responseLen - 2] == '\r' && response[responseLen - 1] == '\n') {
|
if (responseLen >= 2 && response[responseLen - 2] == '\r' && response[responseLen - 1] == '\n') {
|
||||||
|
#ifdef GPS_DEBUG
|
||||||
|
LOG_DEBUG(response);
|
||||||
|
#endif
|
||||||
// Reset the response buffer for the next potential message
|
// Reset the response buffer for the next potential message
|
||||||
responseLen = 0;
|
responseLen = 0;
|
||||||
response[0] = '\0';
|
response[0] = '\0';
|
||||||
@@ -1504,10 +1527,7 @@ GPS *GPS::createGps()
|
|||||||
int8_t _rx_gpio = config.position.rx_gpio;
|
int8_t _rx_gpio = config.position.rx_gpio;
|
||||||
int8_t _tx_gpio = config.position.tx_gpio;
|
int8_t _tx_gpio = config.position.tx_gpio;
|
||||||
int8_t _en_gpio = config.position.gps_en_gpio;
|
int8_t _en_gpio = config.position.gps_en_gpio;
|
||||||
#if HAS_GPS && !defined(ARCH_ESP32)
|
|
||||||
_rx_gpio = 1; // We only specify GPS serial ports on ESP32. Otherwise, these are just flags.
|
|
||||||
_tx_gpio = 1;
|
|
||||||
#endif
|
|
||||||
#if defined(GPS_RX_PIN)
|
#if defined(GPS_RX_PIN)
|
||||||
if (!_rx_gpio)
|
if (!_rx_gpio)
|
||||||
_rx_gpio = GPS_RX_PIN;
|
_rx_gpio = GPS_RX_PIN;
|
||||||
@@ -1572,8 +1592,6 @@ GPS *GPS::createGps()
|
|||||||
|
|
||||||
#ifdef PIN_GPS_RESET
|
#ifdef PIN_GPS_RESET
|
||||||
pinMode(PIN_GPS_RESET, OUTPUT);
|
pinMode(PIN_GPS_RESET, OUTPUT);
|
||||||
digitalWrite(PIN_GPS_RESET, GPS_RESET_MODE); // assert for 10ms
|
|
||||||
delay(10);
|
|
||||||
digitalWrite(PIN_GPS_RESET, !GPS_RESET_MODE);
|
digitalWrite(PIN_GPS_RESET, !GPS_RESET_MODE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1583,16 +1601,28 @@ GPS *GPS::createGps()
|
|||||||
_serial_gps->setRxBufferSize(SERIAL_BUFFER_SIZE); // the default is 256
|
_serial_gps->setRxBufferSize(SERIAL_BUFFER_SIZE); // the default is 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ESP32 has a special set of parameters vs other arduino ports
|
|
||||||
#if defined(ARCH_ESP32)
|
|
||||||
LOG_DEBUG("Use GPIO%d for GPS RX", new_gps->rx_gpio);
|
LOG_DEBUG("Use GPIO%d for GPS RX", new_gps->rx_gpio);
|
||||||
LOG_DEBUG("Use GPIO%d for GPS TX", new_gps->tx_gpio);
|
LOG_DEBUG("Use GPIO%d for GPS TX", new_gps->tx_gpio);
|
||||||
|
|
||||||
|
// ESP32 has a special set of parameters vs other arduino ports
|
||||||
|
#if defined(ARCH_ESP32)
|
||||||
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, new_gps->rx_gpio, new_gps->tx_gpio);
|
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, new_gps->rx_gpio, new_gps->tx_gpio);
|
||||||
#elif defined(ARCH_RP2040)
|
#elif defined(ARCH_RP2040)
|
||||||
|
_serial_gps->setPinout(new_gps->tx_gpio, new_gps->rx_gpio);
|
||||||
_serial_gps->setFIFOSize(256);
|
_serial_gps->setFIFOSize(256);
|
||||||
_serial_gps->begin(GPS_BAUDRATE);
|
_serial_gps->begin(GPS_BAUDRATE);
|
||||||
#else
|
#elif defined(ARCH_NRF52)
|
||||||
|
_serial_gps->setPins(new_gps->rx_gpio, new_gps->tx_gpio);
|
||||||
_serial_gps->begin(GPS_BAUDRATE);
|
_serial_gps->begin(GPS_BAUDRATE);
|
||||||
|
#elif defined(ARCH_STM32WL)
|
||||||
|
_serial_gps->setTx(new_gps->tx_gpio);
|
||||||
|
_serial_gps->setRx(new_gps->rx_gpio);
|
||||||
|
_serial_gps->begin(GPS_BAUDRATE);
|
||||||
|
#elif defined(ARCH_PORTDUINO)
|
||||||
|
// Portduino can't set the GPS pins directly.
|
||||||
|
_serial_gps->begin(GPS_BAUDRATE);
|
||||||
|
#else
|
||||||
|
#error Unsupported architecture!
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return new_gps;
|
return new_gps;
|
||||||
|
|||||||
@@ -194,6 +194,8 @@ class GPS : private concurrency::OSThread
|
|||||||
/** If !NULL we will use this serial port to construct our GPS */
|
/** If !NULL we will use this serial port to construct our GPS */
|
||||||
#if defined(ARCH_RP2040)
|
#if defined(ARCH_RP2040)
|
||||||
static SerialUART *_serial_gps;
|
static SerialUART *_serial_gps;
|
||||||
|
#elif defined(ARCH_NRF52)
|
||||||
|
static Uart *_serial_gps;
|
||||||
#else
|
#else
|
||||||
static HardwareSerial *_serial_gps;
|
static HardwareSerial *_serial_gps;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -112,7 +112,11 @@ RTCSetResult readFromRTC()
|
|||||||
#elif defined(RX8130CE_RTC)
|
#elif defined(RX8130CE_RTC)
|
||||||
if (rtc_found.address == RX8130CE_RTC) {
|
if (rtc_found.address == RX8130CE_RTC) {
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
|
#ifdef MUZI_BASE
|
||||||
|
ArtronShop_RX8130CE rtc(&Wire1);
|
||||||
|
#else
|
||||||
ArtronShop_RX8130CE rtc(&Wire);
|
ArtronShop_RX8130CE rtc(&Wire);
|
||||||
|
#endif
|
||||||
tm t;
|
tm t;
|
||||||
if (rtc.getTime(&t)) {
|
if (rtc.getTime(&t)) {
|
||||||
tv.tv_sec = gm_mktime(&t);
|
tv.tv_sec = gm_mktime(&t);
|
||||||
@@ -245,7 +249,11 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
|
|||||||
}
|
}
|
||||||
#elif defined(RX8130CE_RTC)
|
#elif defined(RX8130CE_RTC)
|
||||||
if (rtc_found.address == RX8130CE_RTC) {
|
if (rtc_found.address == RX8130CE_RTC) {
|
||||||
|
#ifdef MUZI_BASE
|
||||||
|
ArtronShop_RX8130CE rtc(&Wire1);
|
||||||
|
#else
|
||||||
ArtronShop_RX8130CE rtc(&Wire);
|
ArtronShop_RX8130CE rtc(&Wire);
|
||||||
|
#endif
|
||||||
tm *t = gmtime(&tv->tv_sec);
|
tm *t = gmtime(&tv->tv_sec);
|
||||||
if (rtc.setTime(*t)) {
|
if (rtc.setTime(*t)) {
|
||||||
LOG_DEBUG("RX8130CE setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1,
|
LOG_DEBUG("RX8130CE setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1,
|
||||||
@@ -310,7 +318,7 @@ RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t)
|
|||||||
#ifdef BUILD_EPOCH
|
#ifdef BUILD_EPOCH
|
||||||
if (tv.tv_sec < BUILD_EPOCH) {
|
if (tv.tv_sec < BUILD_EPOCH) {
|
||||||
if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) {
|
if (Throttle::isWithinTimespanMs(lastTimeValidationWarning, TIME_VALIDATION_WARNING_INTERVAL_MS) == false) {
|
||||||
LOG_WARN("Ignore time (%ld) before build epoch (%ld)!", printableEpoch, BUILD_EPOCH);
|
LOG_WARN("Ignore time (%lu) before build epoch (%lu)!", printableEpoch, BUILD_EPOCH);
|
||||||
lastTimeValidationWarning = millis();
|
lastTimeValidationWarning = millis();
|
||||||
}
|
}
|
||||||
return RTCSetResultInvalidTime;
|
return RTCSetResultInvalidTime;
|
||||||
@@ -319,7 +327,7 @@ RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t)
|
|||||||
// Calculate max allowed time safely to avoid overflow in logging
|
// Calculate max allowed time safely to avoid overflow in logging
|
||||||
uint64_t maxAllowedTime = (uint64_t)BUILD_EPOCH + FORTY_YEARS;
|
uint64_t maxAllowedTime = (uint64_t)BUILD_EPOCH + FORTY_YEARS;
|
||||||
uint32_t maxAllowedPrintable = (maxAllowedTime > UINT32_MAX) ? UINT32_MAX : (uint32_t)maxAllowedTime;
|
uint32_t maxAllowedPrintable = (maxAllowedTime > UINT32_MAX) ? UINT32_MAX : (uint32_t)maxAllowedTime;
|
||||||
LOG_WARN("Ignore time (%ld) too far in the future (build epoch: %ld, max allowed: %ld)!", printableEpoch,
|
LOG_WARN("Ignore time (%lu) too far in the future (build epoch: %lu, max allowed: %lu)!", printableEpoch,
|
||||||
(uint32_t)BUILD_EPOCH, maxAllowedPrintable);
|
(uint32_t)BUILD_EPOCH, maxAllowedPrintable);
|
||||||
lastTimeValidationWarning = millis();
|
lastTimeValidationWarning = millis();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -435,6 +435,14 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
|
|||||||
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(MUZI_BASE)
|
||||||
|
dispdev->init();
|
||||||
|
dispdev->setBrightness(brightness);
|
||||||
|
dispdev->flipScreenVertically();
|
||||||
|
dispdev->resetDisplay();
|
||||||
|
digitalWrite(SCREEN_12V_ENABLE, HIGH);
|
||||||
|
delay(100);
|
||||||
|
#endif
|
||||||
#if !ARCH_PORTDUINO
|
#if !ARCH_PORTDUINO
|
||||||
dispdev->displayOn();
|
dispdev->displayOn();
|
||||||
#endif
|
#endif
|
||||||
@@ -484,6 +492,10 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
dispdev->displayOff();
|
dispdev->displayOff();
|
||||||
|
|
||||||
|
#ifdef SCREEN_12V_ENABLE
|
||||||
|
digitalWrite(SCREEN_12V_ENABLE, LOW);
|
||||||
|
#endif
|
||||||
#ifdef USE_ST7789
|
#ifdef USE_ST7789
|
||||||
SPI1.end();
|
SPI1.end();
|
||||||
#if defined(ARCH_ESP32)
|
#if defined(ARCH_ESP32)
|
||||||
@@ -534,7 +546,7 @@ void Screen::setup()
|
|||||||
static_cast<AutoOLEDWire *>(dispdev)->setDetected(model);
|
static_cast<AutoOLEDWire *>(dispdev)->setDetected(model);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SH1107_128_64
|
#if defined(USE_SH1107_128_64) || defined(USE_SH1107)
|
||||||
static_cast<SH1106Wire *>(dispdev)->setSubtype(7);
|
static_cast<SH1106Wire *>(dispdev)->setSubtype(7);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -542,6 +554,9 @@ void Screen::setup()
|
|||||||
// Apply custom RGB color (e.g. Heltec T114/T190)
|
// Apply custom RGB color (e.g. Heltec T114/T190)
|
||||||
static_cast<ST7789Spi *>(dispdev)->setRGB(TFT_MESH);
|
static_cast<ST7789Spi *>(dispdev)->setRGB(TFT_MESH);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MUZI_BASE)
|
||||||
|
dispdev->delayPoweron = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
// === Initialize display and UI system ===
|
// === Initialize display and UI system ===
|
||||||
ui->init();
|
ui->init();
|
||||||
|
|||||||
@@ -249,6 +249,8 @@ class Screen : public concurrency::OSThread
|
|||||||
|
|
||||||
bool isOverlayBannerShowing();
|
bool isOverlayBannerShowing();
|
||||||
|
|
||||||
|
bool isScreenOn() { return screenOn; }
|
||||||
|
|
||||||
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier
|
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier
|
||||||
// FIXME: Needs refactoring and getMacAddr needs to be moved to a utility class
|
// FIXME: Needs refactoring and getMacAddr needs to be moved to a utility class
|
||||||
char ourId[5];
|
char ourId[5];
|
||||||
|
|||||||
@@ -483,8 +483,6 @@ class LGFX : public lgfx::LGFX_Device
|
|||||||
lgfx::Touch_FT5x06 _touch_instance;
|
lgfx::Touch_FT5x06 _touch_instance;
|
||||||
#elif defined(HELTEC_V4_TFT)
|
#elif defined(HELTEC_V4_TFT)
|
||||||
lgfx::TOUCH_CHSC6X _touch_instance;
|
lgfx::TOUCH_CHSC6X _touch_instance;
|
||||||
#elif defined(HELTEC_V4_TFT)
|
|
||||||
lgfx::TOUCH_CHSC6X _touch_instance;
|
|
||||||
#else
|
#else
|
||||||
lgfx::Touch_GT911 _touch_instance;
|
lgfx::Touch_GT911 _touch_instance;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -101,3 +101,23 @@ void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength)
|
|||||||
else
|
else
|
||||||
snprintf(timeStr, maxLength, "unknown age");
|
snprintf(timeStr, maxLength, "unknown age");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getUptimeStr(uint32_t uptimeMillis, const char *prefix, char *uptimeStr, uint8_t maxLength, bool includeSecs)
|
||||||
|
{
|
||||||
|
uint32_t days = uptimeMillis / 86400000;
|
||||||
|
uint32_t hours = (uptimeMillis % 86400000) / 3600000;
|
||||||
|
uint32_t mins = (uptimeMillis % 3600000) / 60000;
|
||||||
|
uint32_t secs = (uptimeMillis % 60000) / 1000;
|
||||||
|
|
||||||
|
if (days) {
|
||||||
|
snprintf(uptimeStr, maxLength, "%s: %ud %uh", prefix, days, hours);
|
||||||
|
} else if (hours) {
|
||||||
|
snprintf(uptimeStr, maxLength, "%s: %uh %um", prefix, hours, mins);
|
||||||
|
} else if (!includeSecs) {
|
||||||
|
snprintf(uptimeStr, maxLength, "%s: %um", prefix, mins);
|
||||||
|
} else if (mins) {
|
||||||
|
snprintf(uptimeStr, maxLength, "%s: %um %us", prefix, mins, secs);
|
||||||
|
} else {
|
||||||
|
snprintf(uptimeStr, maxLength, "%s: %us", prefix, secs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,3 +24,10 @@ bool deltaToTimestamp(uint32_t secondsAgo, uint8_t *hours, uint8_t *minutes, int
|
|||||||
* @param maxLength Maximum length of the resulting string buffer
|
* @param maxLength Maximum length of the resulting string buffer
|
||||||
*/
|
*/
|
||||||
void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength);
|
void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a compact human-readable string that only shows the largest non-zero time components.
|
||||||
|
* For example, 0 days 1 hour 2 minutes will display as "1h 2m" but 1 day 2 hours 3 minutes
|
||||||
|
* will display as "1d 2h".
|
||||||
|
*/
|
||||||
|
void getUptimeStr(uint32_t uptimeMillis, const char *prefix, char *uptimeStr, uint8_t maxLength, bool includeSecs = false);
|
||||||
|
|||||||
@@ -194,17 +194,12 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
||||||
int line = 0;
|
int line = 0;
|
||||||
|
|
||||||
#ifdef T_WATCH_S3
|
|
||||||
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
|
||||||
graphics::ClockRenderer::drawBluetoothConnectedIcon(display, display->getWidth() - 18, display->getHeight() - 14);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone
|
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone
|
||||||
char timeString[16];
|
char timeString[16];
|
||||||
int hour = 0;
|
int hour = 0;
|
||||||
int minute = 0;
|
int minute = 0;
|
||||||
int second = 0;
|
int second = 0;
|
||||||
|
|
||||||
if (rtc_sec > 0) {
|
if (rtc_sec > 0) {
|
||||||
long hms = rtc_sec % SEC_PER_DAY;
|
long hms = rtc_sec % SEC_PER_DAY;
|
||||||
hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;
|
hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;
|
||||||
@@ -215,11 +210,11 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isPM = hour >= 12;
|
bool isPM = hour >= 12;
|
||||||
// hour = hour > 12 ? hour - 12 : hour;
|
|
||||||
if (config.display.use_12h_clock) {
|
if (config.display.use_12h_clock) {
|
||||||
hour %= 12;
|
hour %= 12;
|
||||||
if (hour == 0)
|
if (hour == 0) {
|
||||||
hour = 12;
|
hour = 12;
|
||||||
|
}
|
||||||
snprintf(timeString, sizeof(timeString), "%d:%02d", hour, minute);
|
snprintf(timeString, sizeof(timeString), "%d:%02d", hour, minute);
|
||||||
} else {
|
} else {
|
||||||
snprintf(timeString, sizeof(timeString), "%02d:%02d", hour, minute);
|
snprintf(timeString, sizeof(timeString), "%02d:%02d", hour, minute);
|
||||||
@@ -229,24 +224,56 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
char secondString[8];
|
char secondString[8];
|
||||||
snprintf(secondString, sizeof(secondString), "%02d", second);
|
snprintf(secondString, sizeof(secondString), "%02d", second);
|
||||||
|
|
||||||
#ifdef T_WATCH_S3
|
static bool scaleInitialized = false;
|
||||||
float scale = 1.5;
|
static float scale = 0.75f;
|
||||||
#elif defined(CHATTER_2)
|
static float segmentWidth = SEGMENT_WIDTH * 0.75f;
|
||||||
float scale = 1.1;
|
static float segmentHeight = SEGMENT_HEIGHT * 0.75f;
|
||||||
#else
|
|
||||||
float scale = 0.75;
|
|
||||||
if (isHighResolution) {
|
|
||||||
scale = 1.5;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint16_t segmentWidth = SEGMENT_WIDTH * scale;
|
if (!scaleInitialized) {
|
||||||
uint16_t segmentHeight = SEGMENT_HEIGHT * scale;
|
float screenwidth_target_ratio = 0.80f; // Target 80% of display width (adjustable)
|
||||||
|
float max_scale = 3.5f; // Safety limit to avoid runaway scaling
|
||||||
|
float step = 0.05f; // Step increment per iteration
|
||||||
|
|
||||||
|
float target_width = display->getWidth() * screenwidth_target_ratio;
|
||||||
|
float target_height =
|
||||||
|
display->getHeight() -
|
||||||
|
(isHighResolution
|
||||||
|
? 46
|
||||||
|
: 33); // Be careful adjusting this number, we have to account for header and the text under the time
|
||||||
|
|
||||||
|
float calculated_width_size = 0.0f;
|
||||||
|
float calculated_height_size = 0.0f;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
segmentWidth = SEGMENT_WIDTH * scale;
|
||||||
|
segmentHeight = SEGMENT_HEIGHT * scale;
|
||||||
|
|
||||||
|
calculated_width_size = segmentHeight + ((segmentWidth + (segmentHeight * 2) + 4) * 4);
|
||||||
|
calculated_height_size = segmentHeight + ((segmentHeight + (segmentHeight * 2) + 4) * 2);
|
||||||
|
|
||||||
|
if (calculated_width_size >= target_width || calculated_height_size >= target_height || scale >= max_scale) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we overshot width, back off one step and recompute segment sizes
|
||||||
|
if (calculated_width_size > target_width || calculated_height_size > target_height) {
|
||||||
|
scale -= step;
|
||||||
|
segmentWidth = SEGMENT_WIDTH * scale;
|
||||||
|
segmentHeight = SEGMENT_HEIGHT * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
scaleInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = strlen(timeString);
|
||||||
|
|
||||||
// calculate hours:minutes string width
|
// calculate hours:minutes string width
|
||||||
uint16_t timeStringWidth = strlen(timeString) * 5;
|
uint16_t timeStringWidth = len * 5; // base spacing between characters
|
||||||
|
|
||||||
for (uint8_t i = 0; i < strlen(timeString); i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
char character = timeString[i];
|
char character = timeString[i];
|
||||||
|
|
||||||
if (character == ':') {
|
if (character == ':') {
|
||||||
@@ -257,19 +284,21 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t hourMinuteTextX = (display->getWidth() / 2) - (timeStringWidth / 2);
|
uint16_t hourMinuteTextX = (display->getWidth() / 2) - (timeStringWidth / 2);
|
||||||
|
|
||||||
uint16_t startingHourMinuteTextX = hourMinuteTextX;
|
uint16_t startingHourMinuteTextX = hourMinuteTextX;
|
||||||
|
|
||||||
uint16_t hourMinuteTextY = (display->getHeight() / 2) - (((segmentWidth * 2) + (segmentHeight * 3) + 8) / 2);
|
uint16_t hourMinuteTextY = (display->getHeight() / 2) - (((segmentWidth * 2) + (segmentHeight * 3) + 8) / 2) + 2;
|
||||||
|
|
||||||
// iterate over characters in hours:minutes string and draw segmented characters
|
// iterate over characters in hours:minutes string and draw segmented characters
|
||||||
for (uint8_t i = 0; i < strlen(timeString); i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
char character = timeString[i];
|
char character = timeString[i];
|
||||||
|
|
||||||
if (character == ':') {
|
if (character == ':') {
|
||||||
drawSegmentedDisplayColon(display, hourMinuteTextX, hourMinuteTextY, scale);
|
drawSegmentedDisplayColon(display, hourMinuteTextX, hourMinuteTextY, scale);
|
||||||
|
|
||||||
hourMinuteTextX += segmentHeight + 6;
|
hourMinuteTextX += segmentHeight + 6;
|
||||||
|
if (scale >= 2.0f) {
|
||||||
|
hourMinuteTextX += (uint16_t)(4.5f * scale);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
drawSegmentedDisplayCharacter(display, hourMinuteTextX, hourMinuteTextY, character - '0', scale);
|
drawSegmentedDisplayCharacter(display, hourMinuteTextX, hourMinuteTextY, character - '0', scale);
|
||||||
|
|
||||||
@@ -279,38 +308,29 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
hourMinuteTextX += 5;
|
hourMinuteTextX += 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw seconds string
|
// draw seconds string + AM/PM
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
int xOffset = (isHighResolution) ? 0 : -1;
|
int xOffset = (isHighResolution) ? 0 : -1;
|
||||||
if (hour >= 10) {
|
if (hour >= 10) {
|
||||||
xOffset += (isHighResolution) ? 32 : 18;
|
xOffset += (isHighResolution) ? 32 : 18;
|
||||||
}
|
}
|
||||||
int yOffset = (isHighResolution) ? 3 : 1;
|
|
||||||
#ifdef SENSECAP_INDICATOR
|
|
||||||
yOffset -= 3;
|
|
||||||
#endif
|
|
||||||
#ifdef T_DECK
|
|
||||||
yOffset -= 5;
|
|
||||||
#endif
|
|
||||||
if (config.display.use_12h_clock) {
|
if (config.display.use_12h_clock) {
|
||||||
display->drawString(startingHourMinuteTextX + xOffset, (display->getHeight() - hourMinuteTextY) - yOffset - 2,
|
display->drawString(startingHourMinuteTextX + xOffset, (display->getHeight() - hourMinuteTextY) - 1, isPM ? "pm" : "am");
|
||||||
isPM ? "pm" : "am");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_EINK
|
#ifndef USE_EINK
|
||||||
xOffset = (isHighResolution) ? 18 : 10;
|
xOffset = (isHighResolution) ? 18 : 10;
|
||||||
display->drawString(startingHourMinuteTextX + timeStringWidth - xOffset, (display->getHeight() - hourMinuteTextY) - yOffset,
|
if (scale >= 2.0f) {
|
||||||
|
xOffset -= (int)(4.5f * scale);
|
||||||
|
}
|
||||||
|
display->drawString(startingHourMinuteTextX + timeStringWidth - xOffset, (display->getHeight() - hourMinuteTextY) - 1,
|
||||||
secondString);
|
secondString);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
graphics::drawCommonFooter(display, x, y);
|
graphics::drawCommonFooter(display, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawBluetoothConnectedIcon(OLEDDisplay *display, int16_t x, int16_t y)
|
|
||||||
{
|
|
||||||
display->drawFastImage(x, y, 18, 14, bluetoothConnectedIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw an analog clock
|
// Draw an analog clock
|
||||||
void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
@@ -321,11 +341,6 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
|
||||||
int line = 0;
|
int line = 0;
|
||||||
|
|
||||||
#ifdef T_WATCH_S3
|
|
||||||
if (nimbleBluetooth && nimbleBluetooth->isConnected()) {
|
|
||||||
drawBluetoothConnectedIcon(display, display->getWidth() - 18, display->getHeight() - 14);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// clock face center coordinates
|
// clock face center coordinates
|
||||||
int16_t centerX = display->getWidth() / 2;
|
int16_t centerX = display->getWidth() / 2;
|
||||||
int16_t centerY = display->getHeight() / 2;
|
int16_t centerY = display->getHeight() / 2;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ void drawVerticalSegment(OLEDDisplay *display, int x, int y, int width, int heig
|
|||||||
|
|
||||||
// UI elements for clock displays
|
// UI elements for clock displays
|
||||||
// void drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode = true, float scale = 1);
|
// void drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode = true, float scale = 1);
|
||||||
void drawBluetoothConnectedIcon(OLEDDisplay *display, int16_t x, int16_t y);
|
|
||||||
|
|
||||||
} // namespace ClockRenderer
|
} // namespace ClockRenderer
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "gps/RTC.h"
|
#include "gps/RTC.h"
|
||||||
#include "graphics/ScreenFonts.h"
|
#include "graphics/ScreenFonts.h"
|
||||||
#include "graphics/SharedUIDisplay.h"
|
#include "graphics/SharedUIDisplay.h"
|
||||||
|
#include "graphics/TimeFormatters.h"
|
||||||
#include "graphics/images.h"
|
#include "graphics/images.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mesh/Channels.h"
|
#include "mesh/Channels.h"
|
||||||
@@ -650,17 +651,7 @@ void drawSystemScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x
|
|||||||
|
|
||||||
if (SCREEN_HEIGHT > 64 || (SCREEN_HEIGHT <= 64 && line <= 5)) { // Only show uptime if the screen can show it
|
if (SCREEN_HEIGHT > 64 || (SCREEN_HEIGHT <= 64 && line <= 5)) { // Only show uptime if the screen can show it
|
||||||
char uptimeStr[32] = "";
|
char uptimeStr[32] = "";
|
||||||
uint32_t uptime = millis() / 1000;
|
getUptimeStr(millis(), "Up", uptimeStr, sizeof(uptimeStr));
|
||||||
uint32_t days = uptime / 86400;
|
|
||||||
uint32_t hours = (uptime % 86400) / 3600;
|
|
||||||
uint32_t mins = (uptime % 3600) / 60;
|
|
||||||
// Show as "Up: 2d 3h", "Up: 5h 14m", or "Up: 37m"
|
|
||||||
if (days)
|
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), " Up: %ud %uh", days, hours);
|
|
||||||
else if (hours)
|
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), " Up: %uh %um", hours, mins);
|
|
||||||
else
|
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %um", mins);
|
|
||||||
textWidth = display->getStringWidth(uptimeStr);
|
textWidth = display->getStringWidth(uptimeStr);
|
||||||
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
nameX = (SCREEN_WIDTH - textWidth) / 2;
|
||||||
display->drawString(nameX, getTextPositions(display)[line++], uptimeStr);
|
display->drawString(nameX, getTextPositions(display)[line++], uptimeStr);
|
||||||
@@ -729,4 +720,4 @@ void drawChirpy(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int1
|
|||||||
|
|
||||||
} // namespace DebugRenderer
|
} // namespace DebugRenderer
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ void menuHandler::LoraRegionPicker(uint32_t duration)
|
|||||||
auto changes = SEGMENT_CONFIG;
|
auto changes = SEGMENT_CONFIG;
|
||||||
|
|
||||||
// This is needed as we wait til picking the LoRa region to generate keys for the first time.
|
// This is needed as we wait til picking the LoRa region to generate keys for the first time.
|
||||||
|
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN || MESHTASTIC_EXCLUDE_PKI)
|
||||||
if (!owner.is_licensed) {
|
if (!owner.is_licensed) {
|
||||||
bool keygenSuccess = false;
|
bool keygenSuccess = false;
|
||||||
if (config.security.private_key.size == 32) {
|
if (config.security.private_key.size == 32) {
|
||||||
@@ -139,6 +140,7 @@ void menuHandler::LoraRegionPicker(uint32_t duration)
|
|||||||
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
|
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
config.lora.tx_enabled = true;
|
config.lora.tx_enabled = true;
|
||||||
initRegion();
|
initRegion();
|
||||||
if (myRegion->dutyCycle < 100) {
|
if (myRegion->dutyCycle < 100) {
|
||||||
@@ -574,21 +576,16 @@ void menuHandler::textMessageBaseMenu()
|
|||||||
|
|
||||||
void menuHandler::systemBaseMenu()
|
void menuHandler::systemBaseMenu()
|
||||||
{
|
{
|
||||||
enum optionsNumbers { Back, Notifications, ScreenOptions, Bluetooth, PowerMenu, FrameToggles, Test, enumEnd };
|
enum optionsNumbers { Back, Notifications, ScreenOptions, Bluetooth, PowerMenu, Test, enumEnd };
|
||||||
static const char *optionsArray[enumEnd] = {"Back"};
|
static const char *optionsArray[enumEnd] = {"Back"};
|
||||||
static int optionsEnumArray[enumEnd] = {Back};
|
static int optionsEnumArray[enumEnd] = {Back};
|
||||||
int options = 1;
|
int options = 1;
|
||||||
|
|
||||||
optionsArray[options] = "Notifications";
|
optionsArray[options] = "Notifications";
|
||||||
optionsEnumArray[options++] = Notifications;
|
optionsEnumArray[options++] = Notifications;
|
||||||
#if defined(ST7789_CS) || defined(ST7796_CS) || defined(USE_OLED) || defined(USE_SSD1306) || defined(USE_SH1106) || \
|
optionsArray[options] = "Display Options";
|
||||||
defined(USE_SH1107) || defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || HAS_TFT
|
|
||||||
optionsArray[options] = "Screen Options";
|
|
||||||
optionsEnumArray[options++] = ScreenOptions;
|
optionsEnumArray[options++] = ScreenOptions;
|
||||||
#endif
|
|
||||||
|
|
||||||
optionsArray[options] = "Frame Visiblity Toggle";
|
|
||||||
optionsEnumArray[options++] = FrameToggles;
|
|
||||||
#if defined(M5STACK_UNITC6L)
|
#if defined(M5STACK_UNITC6L)
|
||||||
optionsArray[options] = "Bluetooth";
|
optionsArray[options] = "Bluetooth";
|
||||||
#else
|
#else
|
||||||
@@ -626,9 +623,6 @@ void menuHandler::systemBaseMenu()
|
|||||||
} else if (selected == PowerMenu) {
|
} else if (selected == PowerMenu) {
|
||||||
menuHandler::menuQueue = menuHandler::power_menu;
|
menuHandler::menuQueue = menuHandler::power_menu;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
} else if (selected == FrameToggles) {
|
|
||||||
menuHandler::menuQueue = menuHandler::FrameToggles;
|
|
||||||
screen->runNow();
|
|
||||||
} else if (selected == Test) {
|
} else if (selected == Test) {
|
||||||
menuHandler::menuQueue = menuHandler::test_menu;
|
menuHandler::menuQueue = menuHandler::test_menu;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
@@ -1339,7 +1333,7 @@ void menuHandler::screenOptionsMenu()
|
|||||||
hasSupportBrightness = false;
|
hasSupportBrightness = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum optionsNumbers { Back, NodeNameLength, Brightness, ScreenColor };
|
enum optionsNumbers { Back, NodeNameLength, Brightness, ScreenColor, FrameToggles, DisplayUnits };
|
||||||
static const char *optionsArray[5] = {"Back"};
|
static const char *optionsArray[5] = {"Back"};
|
||||||
static int optionsEnumArray[5] = {Back};
|
static int optionsEnumArray[5] = {Back};
|
||||||
int options = 1;
|
int options = 1;
|
||||||
@@ -1361,8 +1355,14 @@ void menuHandler::screenOptionsMenu()
|
|||||||
optionsEnumArray[options++] = ScreenColor;
|
optionsEnumArray[options++] = ScreenColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
optionsArray[options] = "Frame Visibility Toggle";
|
||||||
|
optionsEnumArray[options++] = FrameToggles;
|
||||||
|
|
||||||
|
optionsArray[options] = "Display Units";
|
||||||
|
optionsEnumArray[options++] = DisplayUnits;
|
||||||
|
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
bannerOptions.message = "Screen Options";
|
bannerOptions.message = "Display Options";
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = options;
|
bannerOptions.optionsCount = options;
|
||||||
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
bannerOptions.optionsEnumPtr = optionsEnumArray;
|
||||||
@@ -1376,6 +1376,12 @@ void menuHandler::screenOptionsMenu()
|
|||||||
} else if (selected == NodeNameLength) {
|
} else if (selected == NodeNameLength) {
|
||||||
menuHandler::menuQueue = menuHandler::node_name_length_menu;
|
menuHandler::menuQueue = menuHandler::node_name_length_menu;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
|
} else if (selected == FrameToggles) {
|
||||||
|
menuHandler::menuQueue = menuHandler::FrameToggles;
|
||||||
|
screen->runNow();
|
||||||
|
} else if (selected == DisplayUnits) {
|
||||||
|
menuHandler::menuQueue = menuHandler::DisplayUnits;
|
||||||
|
screen->runNow();
|
||||||
} else {
|
} else {
|
||||||
menuQueue = system_base_menu;
|
menuQueue = system_base_menu;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
@@ -1587,6 +1593,34 @@ void menuHandler::FrameToggles_menu()
|
|||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menuHandler::DisplayUnits_menu()
|
||||||
|
{
|
||||||
|
enum optionsNumbers { Back, MetricUnits, ImperialUnits };
|
||||||
|
|
||||||
|
static const char *optionsArray[] = {"Back", "Metric", "Imperial"};
|
||||||
|
BannerOverlayOptions bannerOptions;
|
||||||
|
bannerOptions.message = " Select display units";
|
||||||
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
|
bannerOptions.optionsCount = 3;
|
||||||
|
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL)
|
||||||
|
bannerOptions.InitialSelected = 2;
|
||||||
|
else
|
||||||
|
bannerOptions.InitialSelected = 1;
|
||||||
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
|
if (selected == MetricUnits) {
|
||||||
|
config.display.units = meshtastic_Config_DisplayConfig_DisplayUnits_METRIC;
|
||||||
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
|
} else if (selected == ImperialUnits) {
|
||||||
|
config.display.units = meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL;
|
||||||
|
service->reloadConfig(SEGMENT_CONFIG);
|
||||||
|
} else {
|
||||||
|
menuHandler::menuQueue = menuHandler::screen_options_menu;
|
||||||
|
screen->runNow();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
screen->showOverlayBanner(bannerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
||||||
{
|
{
|
||||||
if (menuQueue != menu_none)
|
if (menuQueue != menu_none)
|
||||||
@@ -1701,6 +1735,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
|||||||
case FrameToggles:
|
case FrameToggles:
|
||||||
FrameToggles_menu();
|
FrameToggles_menu();
|
||||||
break;
|
break;
|
||||||
|
case DisplayUnits:
|
||||||
|
DisplayUnits_menu();
|
||||||
|
break;
|
||||||
case throttle_message:
|
case throttle_message:
|
||||||
screen->showSimpleBanner("Too Many Attempts\nTry again in 60 seconds.", 5000);
|
screen->showSimpleBanner("Too Many Attempts\nTry again in 60 seconds.", 5000);
|
||||||
break;
|
break;
|
||||||
@@ -1715,4 +1752,4 @@ void menuHandler::saveUIConfig()
|
|||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ class menuHandler
|
|||||||
trace_route_menu,
|
trace_route_menu,
|
||||||
throttle_message,
|
throttle_message,
|
||||||
node_name_length_menu,
|
node_name_length_menu,
|
||||||
FrameToggles
|
FrameToggles,
|
||||||
|
DisplayUnits
|
||||||
};
|
};
|
||||||
static screenMenus menuQueue;
|
static screenMenus menuQueue;
|
||||||
|
|
||||||
@@ -88,6 +89,7 @@ class menuHandler
|
|||||||
static void powerMenu();
|
static void powerMenu();
|
||||||
static void nodeNameLengthMenu();
|
static void nodeNameLengthMenu();
|
||||||
static void FrameToggles_menu();
|
static void FrameToggles_menu();
|
||||||
|
static void DisplayUnits_menu();
|
||||||
static void textMessageMenu();
|
static void textMessageMenu();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -425,6 +425,12 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
{
|
{
|
||||||
const int COMMON_HEADER_HEIGHT = FONT_HEIGHT_SMALL - 1;
|
const int COMMON_HEADER_HEIGHT = FONT_HEIGHT_SMALL - 1;
|
||||||
const int rowYOffset = FONT_HEIGHT_SMALL - 3;
|
const int rowYOffset = FONT_HEIGHT_SMALL - 3;
|
||||||
|
bool locationScreen = false;
|
||||||
|
|
||||||
|
if (strcmp(title, "Bearings") == 0)
|
||||||
|
locationScreen = true;
|
||||||
|
else if (strcmp(title, "Distance") == 0)
|
||||||
|
locationScreen = true;
|
||||||
#if defined(M5STACK_UNITC6L)
|
#if defined(M5STACK_UNITC6L)
|
||||||
int columnWidth = display->getWidth();
|
int columnWidth = display->getWidth();
|
||||||
#else
|
#else
|
||||||
@@ -440,7 +446,7 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
|
|
||||||
int totalEntries = nodeDB->getNumMeshNodes();
|
int totalEntries = nodeDB->getNumMeshNodes();
|
||||||
int totalRowsAvailable = (display->getHeight() - y) / rowYOffset;
|
int totalRowsAvailable = (display->getHeight() - y) / rowYOffset;
|
||||||
|
int numskipped = 0;
|
||||||
int visibleNodeRows = totalRowsAvailable;
|
int visibleNodeRows = totalRowsAvailable;
|
||||||
#if defined(M5STACK_UNITC6L)
|
#if defined(M5STACK_UNITC6L)
|
||||||
int totalColumns = 1;
|
int totalColumns = 1;
|
||||||
@@ -460,6 +466,10 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
int rowCount = 0;
|
int rowCount = 0;
|
||||||
|
|
||||||
for (int i = startIndex; i < endIndex; ++i) {
|
for (int i = startIndex; i < endIndex; ++i) {
|
||||||
|
if (locationScreen && !nodeDB->getMeshNodeByIndex(i)->has_position) {
|
||||||
|
numskipped++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
int xPos = x + (col * columnWidth);
|
int xPos = x + (col * columnWidth);
|
||||||
int yPos = y + yOffset;
|
int yPos = y + yOffset;
|
||||||
renderer(display, nodeDB->getMeshNodeByIndex(i), xPos, yPos, columnWidth);
|
renderer(display, nodeDB->getMeshNodeByIndex(i), xPos, yPos, columnWidth);
|
||||||
@@ -482,6 +492,9 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This should correct the scrollbar
|
||||||
|
totalEntries -= numskipped;
|
||||||
|
|
||||||
#if !defined(M5STACK_UNITC6L)
|
#if !defined(M5STACK_UNITC6L)
|
||||||
// Draw column separator
|
// Draw column separator
|
||||||
if (shownCount > 0) {
|
if (shownCount > 0) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "graphics/Screen.h"
|
#include "graphics/Screen.h"
|
||||||
#include "graphics/ScreenFonts.h"
|
#include "graphics/ScreenFonts.h"
|
||||||
#include "graphics/SharedUIDisplay.h"
|
#include "graphics/SharedUIDisplay.h"
|
||||||
|
#include "graphics/TimeFormatters.h"
|
||||||
#include "graphics/images.h"
|
#include "graphics/images.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
@@ -383,17 +384,7 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
|
|||||||
// === 4. Uptime (only show if metric is present) ===
|
// === 4. Uptime (only show if metric is present) ===
|
||||||
char uptimeStr[32] = "";
|
char uptimeStr[32] = "";
|
||||||
if (node->has_device_metrics && node->device_metrics.has_uptime_seconds) {
|
if (node->has_device_metrics && node->device_metrics.has_uptime_seconds) {
|
||||||
uint32_t uptime = node->device_metrics.uptime_seconds;
|
getUptimeStr(node->device_metrics.uptime_seconds * 1000, " Up", uptimeStr, sizeof(uptimeStr));
|
||||||
uint32_t days = uptime / 86400;
|
|
||||||
uint32_t hours = (uptime % 86400) / 3600;
|
|
||||||
uint32_t mins = (uptime % 3600) / 60;
|
|
||||||
// Show as "Up: 2d 3h", "Up: 5h 14m", or "Up: 37m"
|
|
||||||
if (days)
|
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %ud %uh", days, hours);
|
|
||||||
else if (hours)
|
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %uh %um", hours, mins);
|
|
||||||
else
|
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %um", mins);
|
|
||||||
}
|
}
|
||||||
if (uptimeStr[0] && line < 5) {
|
if (uptimeStr[0] && line < 5) {
|
||||||
display->drawString(x, getTextPositions(display)[line++], uptimeStr);
|
display->drawString(x, getTextPositions(display)[line++], uptimeStr);
|
||||||
@@ -592,18 +583,8 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
|
|||||||
drawNodes(display, x + 1, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
drawNodes(display, x + 1, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online");
|
||||||
#endif
|
#endif
|
||||||
char uptimeStr[32] = "";
|
char uptimeStr[32] = "";
|
||||||
uint32_t uptime = millis() / 1000;
|
|
||||||
uint32_t days = uptime / 86400;
|
|
||||||
uint32_t hours = (uptime % 86400) / 3600;
|
|
||||||
uint32_t mins = (uptime % 3600) / 60;
|
|
||||||
// Show as "Up: 2d 3h", "Up: 5h 14m", or "Up: 37m"
|
|
||||||
#if !defined(M5STACK_UNITC6L)
|
#if !defined(M5STACK_UNITC6L)
|
||||||
if (days)
|
getUptimeStr(millis(), "Up", uptimeStr, sizeof(uptimeStr));
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %ud %uh", days, hours);
|
|
||||||
else if (hours)
|
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %uh %um", hours, mins);
|
|
||||||
else
|
|
||||||
snprintf(uptimeStr, sizeof(uptimeStr), "Up: %um", mins);
|
|
||||||
#endif
|
#endif
|
||||||
display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), getTextPositions(display)[line++], uptimeStr);
|
display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), getTextPositions(display)[line++], uptimeStr);
|
||||||
|
|
||||||
@@ -1048,36 +1029,17 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU
|
|||||||
if (strcmp(displayLine, "GPS off") != 0 && strcmp(displayLine, "No GPS") != 0) {
|
if (strcmp(displayLine, "GPS off") != 0 && strcmp(displayLine, "No GPS") != 0) {
|
||||||
// === Second Row: Last GPS Fix ===
|
// === Second Row: Last GPS Fix ===
|
||||||
if (gpsStatus->getLastFixMillis() > 0) {
|
if (gpsStatus->getLastFixMillis() > 0) {
|
||||||
uint32_t delta = (millis() - gpsStatus->getLastFixMillis()) / 1000; // seconds since last fix
|
uint32_t delta = millis() - gpsStatus->getLastFixMillis();
|
||||||
uint32_t days = delta / 86400;
|
char uptimeStr[32];
|
||||||
uint32_t hours = (delta % 86400) / 3600;
|
|
||||||
uint32_t mins = (delta % 3600) / 60;
|
|
||||||
uint32_t secs = delta % 60;
|
|
||||||
|
|
||||||
char buf[32];
|
|
||||||
#if defined(USE_EINK)
|
#if defined(USE_EINK)
|
||||||
// E-Ink: skip seconds, show only days/hours/mins
|
// E-Ink: skip seconds, show only days/hours/mins
|
||||||
if (days > 0) {
|
getUptimeStr(delta, "Last", uptimeStr, sizeof(uptimeStr), false);
|
||||||
snprintf(buf, sizeof(buf), "Last: %ud %uh", days, hours);
|
|
||||||
} else if (hours > 0) {
|
|
||||||
snprintf(buf, sizeof(buf), "Last: %uh %um", hours, mins);
|
|
||||||
} else {
|
|
||||||
snprintf(buf, sizeof(buf), "Last: %um", mins);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
// Non E-Ink: include seconds where useful
|
// Non E-Ink: include seconds where useful
|
||||||
if (days > 0) {
|
getUptimeStr(delta, "Last", uptimeStr, sizeof(uptimeStr), true);
|
||||||
snprintf(buf, sizeof(buf), "Last: %ud %uh", days, hours);
|
|
||||||
} else if (hours > 0) {
|
|
||||||
snprintf(buf, sizeof(buf), "Last: %uh %um", hours, mins);
|
|
||||||
} else if (mins > 0) {
|
|
||||||
snprintf(buf, sizeof(buf), "Last: %um %us", mins, secs);
|
|
||||||
} else {
|
|
||||||
snprintf(buf, sizeof(buf), "Last: %us", secs);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
display->drawString(0, getTextPositions(display)[line++], buf);
|
display->drawString(0, getTextPositions(display)[line++], uptimeStr);
|
||||||
} else {
|
} else {
|
||||||
display->drawString(0, getTextPositions(display)[line++], "Last: ?");
|
display->drawString(0, getTextPositions(display)[line++], "Last: ?");
|
||||||
}
|
}
|
||||||
@@ -1422,4 +1384,4 @@ std::string UIRenderer::drawTimeDelta(uint32_t days, uint32_t hours, uint32_t mi
|
|||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
|
|
||||||
#endif // HAS_SCREEN
|
#endif // HAS_SCREEN
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ const Emote emotes[] = {
|
|||||||
{"\U0001F642", Slightly_Smiling, Slightly_Smiling_width, Slightly_Smiling_height}, // 🙂 Slightly Smiling Face
|
{"\U0001F642", Slightly_Smiling, Slightly_Smiling_width, Slightly_Smiling_height}, // 🙂 Slightly Smiling Face
|
||||||
{"\U0001F609", Winking_Face, Winking_Face_width, Winking_Face_height}, // 😉 Winking Face
|
{"\U0001F609", Winking_Face, Winking_Face_width, Winking_Face_height}, // 😉 Winking Face
|
||||||
{"\U0001F601", Grinning_Smiling_Eyes, Grinning_Smiling_Eyes_width, Grinning_Smiling_Eyes_height}, // 😁 Grinning Smiling Eyes
|
{"\U0001F601", Grinning_Smiling_Eyes, Grinning_Smiling_Eyes_width, Grinning_Smiling_Eyes_height}, // 😁 Grinning Smiling Eyes
|
||||||
|
{"\U0001F60D", Heart_eyes, Heart_eyes_width, Heart_eyes_height}, // 😍 Heart Eyes
|
||||||
|
{"\U0001F970", heart_smile, heart_smile_width, heart_smile_height}, // 🥰 Smiling Face with Hearts
|
||||||
|
|
||||||
// --- Question/Alert ---
|
// --- Question/Alert ---
|
||||||
{"\u2753", question, question_width, question_height}, // ❓ Question Mark
|
{"\u2753", question, question_width, question_height}, // ❓ Question Mark
|
||||||
@@ -30,11 +32,15 @@ const Emote emotes[] = {
|
|||||||
{"\U0001F605", haha, haha_width, haha_height}, // 😅 Smiling with Sweat
|
{"\U0001F605", haha, haha_width, haha_height}, // 😅 Smiling with Sweat
|
||||||
{"\U0001F604", Grinning_SmilingEyes2, Grinning_SmilingEyes2_width,
|
{"\U0001F604", Grinning_SmilingEyes2, Grinning_SmilingEyes2_width,
|
||||||
Grinning_SmilingEyes2_height}, // 😄 Grinning Face with Smiling Eyes
|
Grinning_SmilingEyes2_height}, // 😄 Grinning Face with Smiling Eyes
|
||||||
|
{"\U0001F62D", Loudly_Crying_Face, Loudly_Crying_Face_width, Loudly_Crying_Face_height}, // 😭 Loudly Crying Face
|
||||||
|
|
||||||
// --- Gestures and People ---
|
// --- Gestures and People ---
|
||||||
{"\U0001F44B", wave_icon, wave_icon_width, wave_icon_height}, // 👋 Waving Hand
|
{"\U0001F44B", wave_icon, wave_icon_width, wave_icon_height}, // 👋 Waving Hand
|
||||||
{"\U0001F920", cowboy, cowboy_width, cowboy_height}, // 🤠 Cowboy Hat Face
|
{"\u270C\uFE0F", peace_sign, peace_sign_width, peace_sign_height}, // ✌️ Victory Hand
|
||||||
{"\U0001F3A7", deadmau5, deadmau5_width, deadmau5_height}, // 🎧 Headphones
|
{"\U0001F596", vulcan_salute, vulcan_salute_width, vulcan_salute_height}, // 🖖 Vulcan Salute
|
||||||
|
{"\U0001F64F", Praying, Praying_width, Praying_height}, // 🙏 Praying Hands
|
||||||
|
{"\U0001F920", cowboy, cowboy_width, cowboy_height}, // 🤠 Cowboy Hat Face
|
||||||
|
{"\U0001F3A7", deadmau5, deadmau5_width, deadmau5_height}, // 🎧 Headphones
|
||||||
|
|
||||||
// --- Weather ---
|
// --- Weather ---
|
||||||
{"\u2600", sun, sun_width, sun_height}, // ☀ Sun (without variation selector)
|
{"\u2600", sun, sun_width, sun_height}, // ☀ Sun (without variation selector)
|
||||||
@@ -45,8 +51,12 @@ const Emote emotes[] = {
|
|||||||
|
|
||||||
// --- Misc Faces ---
|
// --- Misc Faces ---
|
||||||
{"\U0001F608", devil, devil_width, devil_height}, // 😈 Smiling Face with Horns
|
{"\U0001F608", devil, devil_width, devil_height}, // 😈 Smiling Face with Horns
|
||||||
|
{"\U0001F921", clown, clown_width, clown_height}, // 🤡 Clown Face
|
||||||
|
{"\U0001F916", robo, robo_width, robo_height}, // 🤖 Robot Face
|
||||||
|
|
||||||
// --- Hearts (Multiple Unicode Aliases) ---
|
// --- Hearts (Multiple Unicode Aliases) ---
|
||||||
|
{"\u2665", heart, heart_width, heart_height}, // ♥ Black Heart Suit
|
||||||
|
{"\u2665\uFE0F", heart, heart_width, heart_height}, // ♥️ Black Heart Suit (emoji presentation)
|
||||||
{"\u2764\uFE0F", heart, heart_width, heart_height}, // ❤️ Red Heart
|
{"\u2764\uFE0F", heart, heart_width, heart_height}, // ❤️ Red Heart
|
||||||
{"\U0001F9E1", heart, heart_width, heart_height}, // 🧡 Orange Heart
|
{"\U0001F9E1", heart, heart_width, heart_height}, // 🧡 Orange Heart
|
||||||
{"\U00002763", heart, heart_width, heart_height}, // ❣ Heart Exclamation
|
{"\U00002763", heart, heart_width, heart_height}, // ❣ Heart Exclamation
|
||||||
@@ -57,223 +67,166 @@ const Emote emotes[] = {
|
|||||||
{"\U0001F498", heart, heart_width, heart_height}, // 💘 Heart with Arrow
|
{"\U0001F498", heart, heart_width, heart_height}, // 💘 Heart with Arrow
|
||||||
|
|
||||||
// --- Objects ---
|
// --- Objects ---
|
||||||
{"\U0001F4A9", poo, poo_width, poo_height}, // 💩 Pile of Poo
|
{"\U0001F4A9", poo, poo_width, poo_height}, // 💩 Pile of Poo
|
||||||
{"\U0001F514", bell_icon, bell_icon_width, bell_icon_height} // 🔔 Bell
|
{"\U0001F514", bell_icon, bell_icon_width, bell_icon_height}, // 🔔 Bell
|
||||||
|
{"\U0001F36A", cookie, cookie_width, cookie_height}, // 🍪 Cookie
|
||||||
|
{"\U0001F525", Fire, Fire_width, Fire_height}, // 🔥 Fire
|
||||||
|
{"\u2728", Sparkles, Sparkles_width, Sparkles_height}, // ✨ Sparkles
|
||||||
|
{"\U0001F573\uFE0F", hole, hole_width, hole_height}, // 🕳️ Hole
|
||||||
|
{"\U0001F3B3", bowling, bowling_width, bowling_height} // 🎳 Bowling
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
const int numEmotes = sizeof(emotes) / sizeof(emotes[0]);
|
const int numEmotes = sizeof(emotes) / sizeof(emotes[0]);
|
||||||
|
|
||||||
#ifndef EXCLUDE_EMOJI
|
#ifndef EXCLUDE_EMOJI
|
||||||
const unsigned char thumbup[] PROGMEM = {
|
const unsigned char thumbup[] PROGMEM = {0x00, 0x03, 0x80, 0x04, 0x80, 0x04, 0x40, 0x04, 0x20, 0x02, 0x18,
|
||||||
0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00,
|
0x02, 0x06, 0x3F, 0x06, 0x40, 0x06, 0x70, 0x06, 0x40, 0x06, 0x70,
|
||||||
0xC0, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00,
|
0x06, 0x40, 0x06, 0x30, 0x08, 0x20, 0xF0, 0x1F, 0x00, 0x00};
|
||||||
0x0C, 0xCE, 0x7F, 0x00, 0x04, 0x20, 0x80, 0x00, 0x02, 0x20, 0x80, 0x00, 0x02, 0x60, 0xC0, 0x00, 0x01, 0xF8, 0xFF, 0x01,
|
|
||||||
0x01, 0x08, 0x00, 0x01, 0x01, 0x08, 0x00, 0x01, 0x01, 0xF8, 0xFF, 0x00, 0x01, 0x10, 0x80, 0x00, 0x01, 0x18, 0x80, 0x00,
|
|
||||||
0x02, 0x30, 0xC0, 0x00, 0x06, 0xE0, 0x3F, 0x00, 0x0C, 0x20, 0x30, 0x00, 0x38, 0x20, 0x10, 0x00, 0xE0, 0xCF, 0x1F, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char thumbdown[] PROGMEM = {
|
const unsigned char thumbdown[] PROGMEM = {0xF0, 0x1F, 0x08, 0x20, 0x06, 0x30, 0x06, 0x40, 0x06, 0x70, 0x06,
|
||||||
0xE0, 0xCF, 0x1F, 0x00, 0x38, 0x20, 0x10, 0x00, 0x0C, 0x20, 0x30, 0x00, 0x06, 0xE0, 0x3F, 0x00, 0x02, 0x30, 0xC0, 0x00,
|
0x40, 0x06, 0x70, 0x06, 0x40, 0x06, 0x3F, 0x18, 0x02, 0x20, 0x02,
|
||||||
0x01, 0x18, 0x80, 0x00, 0x01, 0x10, 0x80, 0x00, 0x01, 0xF8, 0xFF, 0x00, 0x01, 0x08, 0x00, 0x01, 0x01, 0x08, 0x00, 0x01,
|
0x40, 0x04, 0x80, 0x04, 0x80, 0x04, 0x00, 0x03, 0x00, 0x00};
|
||||||
0x01, 0xF8, 0xFF, 0x01, 0x02, 0x60, 0xC0, 0x00, 0x02, 0x20, 0x80, 0x00, 0x04, 0x20, 0x80, 0x00, 0x0C, 0xCE, 0x7F, 0x00,
|
|
||||||
0x18, 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00,
|
|
||||||
0x80, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char Smiling_Eyes[] PROGMEM = {
|
const unsigned char Smiling_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||||
0x00, 0xf8, 0x03, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0xc0, 0xff, 0xff, 0xc0, 0xe0, 0xff, 0xff, 0xc1,
|
0x4A, 0x02, 0x40, 0x02, 0x40, 0x22, 0x44, 0x22, 0x44, 0xC2, 0x43,
|
||||||
0xf0, 0xff, 0xff, 0xc3, 0xf8, 0xff, 0xff, 0xc7, 0xf8, 0xff, 0xff, 0xcf, 0xfc, 0xff, 0xff, 0xcf, 0xfc, 0xff, 0xff, 0xcf,
|
0x04, 0x20, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0x7e, 0xf8, 0xc3, 0xdf, 0x3e, 0xf0, 0x81, 0xdf, 0xbf, 0xf7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0x3f, 0xff,
|
|
||||||
0x6f, 0xff, 0xdf, 0xfe, 0x6f, 0xff, 0xdf, 0xfe, 0x9f, 0xff, 0x3f, 0xff, 0xfe, 0xff, 0xff, 0xdf, 0x7e, 0xff, 0xdf, 0xdf,
|
|
||||||
0x7c, 0xff, 0xdf, 0xcf, 0xfc, 0xfe, 0xef, 0xcf, 0xf8, 0xf9, 0xf7, 0xc7, 0xf8, 0x03, 0xf8, 0xc7, 0xf0, 0xff, 0xff, 0xc3,
|
|
||||||
0xe0, 0xff, 0xff, 0xc1, 0xc0, 0xff, 0xff, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x07, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char Grinning[] PROGMEM = {
|
const unsigned char Grinning[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42,
|
||||||
0x00, 0xf8, 0x03, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0xc0, 0xff, 0xff, 0xc0, 0xe0, 0xff, 0xff, 0xc1,
|
0x42, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
|
||||||
0xf0, 0xff, 0xff, 0xc3, 0xf8, 0xff, 0xff, 0xc7, 0xf8, 0xff, 0xff, 0xcf, 0xfc, 0xf9, 0xf3, 0xcf, 0xfc, 0xf0, 0xe1, 0xcf,
|
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0xfe, 0xf0, 0xe1, 0xdf, 0xfe, 0xf0, 0xe1, 0xdf, 0xff, 0xf0, 0xe1, 0xff, 0xff, 0xf9, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xbe, 0xff, 0xbf, 0xdf, 0x7e, 0x00, 0xc0, 0xdf,
|
|
||||||
0x7c, 0x00, 0xc0, 0xcf, 0xfc, 0x00, 0xe0, 0xcf, 0xf8, 0x01, 0xf0, 0xc7, 0xf8, 0x03, 0xf8, 0xc7, 0xf0, 0xff, 0xff, 0xc3,
|
|
||||||
0xe0, 0xff, 0xff, 0xc1, 0xc0, 0xff, 0xff, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x03, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char Slightly_Smiling[] PROGMEM = {
|
const unsigned char Slightly_Smiling[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x22, 0x42,
|
||||||
0x00, 0xf8, 0x03, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0xc0, 0xff, 0xff, 0xc0, 0xe0, 0xff, 0xff, 0xc1,
|
0x42, 0x02, 0x40, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
|
||||||
0xf0, 0xff, 0xff, 0xc3, 0xf8, 0xff, 0xff, 0xc7, 0xf8, 0xff, 0xff, 0xcf, 0xfc, 0xf9, 0xf3, 0xcf, 0xfc, 0xf0, 0xe1, 0xcf,
|
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0xfe, 0xf0, 0xe1, 0xdf, 0xfe, 0xf0, 0xe1, 0xdf, 0xff, 0xf0, 0xe1, 0xff, 0xff, 0xf9, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xdf, 0x7e, 0xff, 0xdf, 0xdf,
|
|
||||||
0x7c, 0xff, 0xdf, 0xcf, 0xfc, 0xfe, 0xef, 0xcf, 0xf8, 0xf9, 0xf7, 0xc7, 0xf8, 0x03, 0xf8, 0xc7, 0xf0, 0xff, 0xff, 0xc3,
|
|
||||||
0xe0, 0xff, 0xff, 0xc1, 0xc0, 0xff, 0xff, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x03, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char Winking_Face[] PROGMEM = {
|
const unsigned char Winking_Face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x44, 0x20, 0x42,
|
||||||
0x00, 0xf8, 0x03, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0xc0, 0xff, 0xff, 0xc0, 0xe0, 0xff, 0xff, 0xc1,
|
0x46, 0x02, 0x40, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
|
||||||
0xf0, 0xf0, 0xff, 0xc3, 0x78, 0xef, 0xc3, 0xc7, 0xb8, 0xdf, 0xbd, 0xcf, 0xfc, 0xf9, 0x7f, 0xcf, 0xfc, 0xf0, 0xff, 0xcf,
|
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0xfe, 0xf0, 0xc3, 0xdf, 0xfe, 0xf0, 0x81, 0xdf, 0xff, 0xf0, 0xbf, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xdf, 0x7e, 0xff, 0xdf, 0xdf,
|
|
||||||
0x7c, 0xff, 0xdf, 0xcf, 0xfc, 0xfe, 0xef, 0xcf, 0xf8, 0xf9, 0xf7, 0xc7, 0xf8, 0x03, 0xf8, 0xc7, 0xf0, 0xff, 0xff, 0xc3,
|
|
||||||
0xe0, 0xff, 0xff, 0xc1, 0xc0, 0xff, 0xff, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x07, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char Grinning_Smiling_Eyes[] PROGMEM = {
|
const unsigned char Grinning_Smiling_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||||
0x00, 0xf8, 0x03, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0xc0, 0xff, 0xff, 0xc0, 0xe0, 0xff, 0xff, 0xc1,
|
0x4A, 0x02, 0x40, 0xFA, 0x5F, 0x0A, 0x50, 0x0A, 0x50, 0x12, 0x48,
|
||||||
0xf0, 0xff, 0xff, 0xc3, 0xf8, 0xff, 0xff, 0xc7, 0xf8, 0xff, 0xff, 0xcf, 0xfc, 0xf8, 0xe3, 0xcf, 0x7c, 0xf7, 0xdd, 0xcf,
|
0x24, 0x24, 0xC4, 0x23, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0xbe, 0xef, 0xbe, 0xdf, 0xbe, 0xef, 0xbe, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xff, 0x5e, 0x55, 0x55, 0xdf, 0x5e, 0x55, 0x55, 0xdf,
|
|
||||||
0x3c, 0x00, 0x80, 0xcf, 0x7c, 0x55, 0xd5, 0xcf, 0xf8, 0x54, 0xe5, 0xc7, 0xf8, 0x03, 0xf8, 0xc7, 0xf0, 0xff, 0xff, 0xc3,
|
|
||||||
0xe0, 0xff, 0xff, 0xc1, 0xc0, 0xff, 0xff, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x03, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char question[] PROGMEM = {
|
const unsigned char heart_smile[] PROGMEM = {0x00, 0x00, 0x6C, 0x07, 0x7C, 0x18, 0x7C, 0x20, 0x38, 0x24, 0x52,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0xE0, 0xFF, 0x07, 0x00,
|
0x0A, 0x02, 0xD8, 0x02, 0xF8, 0x22, 0xFC, 0x20, 0x74, 0xDB, 0x23,
|
||||||
0xE0, 0xC3, 0x0F, 0x00, 0xF0, 0x81, 0x0F, 0x00, 0xF0, 0x01, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x80, 0x0F, 0x00,
|
0x1F, 0x00, 0x1F, 0x20, 0x0E, 0x18, 0xE4, 0x07, 0x00, 0x00};
|
||||||
0x00, 0xC0, 0x0F, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x7C, 0x00, 0x00,
|
|
||||||
0x00, 0x3C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char bang[] PROGMEM = {
|
const unsigned char Heart_eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x54, 0x2A, 0xFA,
|
||||||
0xFF, 0x0F, 0xFC, 0x3F, 0xFF, 0x0F, 0xFC, 0x3F, 0xFF, 0x0F, 0xFC, 0x3F, 0xFF, 0x07, 0xF8, 0x3F, 0xFF, 0x07, 0xF8, 0x3F,
|
0x5F, 0x72, 0x4E, 0x22, 0x44, 0x02, 0x40, 0x12, 0x48, 0x12, 0x48,
|
||||||
0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F,
|
0x24, 0x24, 0xC4, 0x23, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0xFE, 0x03, 0xF0, 0x1F, 0xFE, 0x03, 0xF0, 0x1F, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x03, 0xF0, 0x0F,
|
|
||||||
0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, 0x01, 0xE0, 0x0F, 0xFC, 0x01, 0xE0, 0x0F,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xC0, 0x03, 0xFC, 0x03, 0xF0, 0x0F, 0xFE, 0x03, 0xF0, 0x1F,
|
|
||||||
0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFE, 0x07, 0xF8, 0x1F, 0xFC, 0x03, 0xF0, 0x0F, 0xF8, 0x01, 0xE0, 0x07,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char haha[] PROGMEM = {
|
const unsigned char question[] PROGMEM = {0xE0, 0x07, 0x10, 0x08, 0x08, 0x10, 0x88, 0x11, 0x48, 0x12, 0x48,
|
||||||
0x00, 0xf8, 0x03, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0xc0, 0xff, 0x7f, 0xc0, 0xe0, 0xf9, 0xf3, 0xc0,
|
0x12, 0x48, 0x12, 0x30, 0x11, 0x80, 0x08, 0x40, 0x04, 0x40, 0x02,
|
||||||
0xf0, 0xfe, 0xef, 0xc1, 0x38, 0xff, 0x9f, 0xc3, 0xd8, 0xff, 0x7f, 0xc3, 0xfc, 0xf8, 0xe3, 0xc7, 0x7c, 0xf7, 0xdd, 0xcf,
|
0xC0, 0x03, 0x00, 0x00, 0xC0, 0x03, 0x40, 0x02, 0x80, 0x01};
|
||||||
0xbe, 0xef, 0xbe, 0xcf, 0xfe, 0xff, 0xff, 0xcf, 0xef, 0xff, 0xff, 0xde, 0xe7, 0xff, 0xff, 0xdc, 0xeb, 0xff, 0xff, 0xda,
|
|
||||||
0xed, 0xff, 0xff, 0xd6, 0xee, 0xff, 0xff, 0xce, 0x36, 0x00, 0x80, 0xcd, 0xb8, 0xff, 0xbf, 0xc3, 0x7e, 0x00, 0xc0, 0xdf,
|
|
||||||
0x7c, 0x00, 0xc0, 0xcf, 0xfc, 0x00, 0xe0, 0xcf, 0xf8, 0x01, 0xf0, 0xc7, 0xf8, 0x03, 0xf8, 0xc7, 0xf0, 0xff, 0xff, 0xc3,
|
|
||||||
0xe0, 0xff, 0xff, 0xc1, 0xc0, 0xff, 0xff, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x03, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char ROFL[] PROGMEM = {
|
const unsigned char bang[] PROGMEM = {0x30, 0x0C, 0x48, 0x12, 0x48, 0x12, 0x48, 0x12, 0x48, 0x12, 0x48,
|
||||||
0x00, 0x00, 0x00, 0xc0, 0x00, 0xfc, 0x07, 0xc0, 0x00, 0xff, 0x1f, 0xc0, 0x80, 0xff, 0x7f, 0xc0, 0xc0, 0xff, 0xff, 0xc0,
|
0x12, 0x48, 0x12, 0x48, 0x12, 0x48, 0x12, 0x48, 0x12, 0x30, 0x0C,
|
||||||
0xe0, 0x9f, 0xff, 0xc1, 0xf0, 0x9f, 0xff, 0xc0, 0xf8, 0x9f, 0x7f, 0xcb, 0xf8, 0x9f, 0xbf, 0xcb, 0xfc, 0x9f, 0xdf, 0xdb,
|
0x00, 0x00, 0x30, 0x0C, 0x48, 0x12, 0x30, 0x0C, 0x00, 0x00};
|
||||||
0xfc, 0x1f, 0x08, 0xdc, 0xfe, 0x1f, 0xf8, 0xfe, 0xfe, 0xff, 0xff, 0xfe, 0x1e, 0xf0, 0x7f, 0xfe, 0x1e, 0xf0, 0xbf, 0xfe,
|
|
||||||
0xfe, 0xf3, 0xdf, 0xfe, 0xfe, 0xf3, 0x6f, 0xfe, 0xfe, 0xf3, 0x37, 0xfe, 0xfe, 0xeb, 0x1b, 0xfe, 0xfc, 0xef, 0x0d, 0xde,
|
|
||||||
0xfc, 0xe7, 0x06, 0xcf, 0xf8, 0x6b, 0x83, 0xcf, 0xf8, 0x0d, 0xc0, 0xc7, 0xf0, 0xed, 0xff, 0xc7, 0xe0, 0xee, 0xff, 0xc3,
|
|
||||||
0xc0, 0xee, 0xff, 0xc1, 0x80, 0xee, 0xff, 0xc0, 0x00, 0xe6, 0x3f, 0xc0, 0x00, 0xf0, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char Smiling_Closed_Eyes[] PROGMEM = {
|
const unsigned char haha[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||||
0x00, 0xf8, 0x03, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0xc0, 0xff, 0xff, 0xc0, 0xe0, 0xff, 0xff, 0xc1,
|
0x4A, 0x0A, 0x50, 0x0E, 0x70, 0xF2, 0x4F, 0x12, 0x48, 0x32, 0x44,
|
||||||
0xf0, 0xff, 0xff, 0xc3, 0xf8, 0xff, 0xff, 0xc7, 0xf8, 0xff, 0xff, 0xcf, 0x7c, 0xfe, 0xcf, 0xcf, 0xfc, 0xfc, 0xe7, 0xcf,
|
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0xfe, 0xf9, 0xf3, 0xdf, 0xfe, 0xf3, 0xf9, 0xdf, 0xff, 0xf9, 0xf3, 0xff, 0xff, 0xfc, 0xe7, 0xff, 0x7f, 0xfe, 0xcf, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xbe, 0xff, 0xbf, 0xdf, 0x7e, 0x00, 0xc0, 0xdf,
|
|
||||||
0x7c, 0x00, 0xc0, 0xcf, 0xfc, 0x00, 0xe0, 0xcf, 0xf8, 0x01, 0xf0, 0xc7, 0xf8, 0x03, 0xf8, 0xc7, 0xf0, 0xff, 0xff, 0xc3,
|
|
||||||
0xe0, 0xff, 0xff, 0xc1, 0xc0, 0xff, 0xff, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x03, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char Grinning_SmilingEyes2[] PROGMEM = {
|
const unsigned char ROFL[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x84, 0x21, 0x84, 0x20, 0x02,
|
||||||
0x00, 0xf8, 0x03, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0xc0, 0xff, 0x7f, 0xc0, 0xe0, 0xff, 0xff, 0xc0,
|
0x4C, 0x02, 0x4A, 0x1A, 0x49, 0x8A, 0x48, 0x42, 0x48, 0x22, 0x44,
|
||||||
0xf0, 0xff, 0xff, 0xc1, 0xf8, 0xff, 0xff, 0xc3, 0xf8, 0xff, 0xff, 0xc3, 0xfc, 0xf8, 0xe3, 0xc7, 0x7c, 0xf7, 0xdd, 0xc7,
|
0xE4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0xbe, 0xef, 0xbe, 0xcf, 0xfe, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf,
|
|
||||||
0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xdf, 0x3f, 0x00, 0x80, 0xdf, 0xbe, 0xff, 0xbf, 0xcf, 0x7e, 0x00, 0xc0, 0xcf,
|
|
||||||
0x7c, 0x00, 0xc0, 0xc7, 0xfc, 0x00, 0xe0, 0xc7, 0xf8, 0x01, 0xf0, 0xc3, 0xf8, 0x03, 0xf8, 0xc3, 0xf0, 0xff, 0xff, 0xc1,
|
|
||||||
0xe0, 0xff, 0xff, 0xc0, 0xc0, 0xff, 0x7f, 0xc0, 0x80, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x03, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char wave_icon[] PROGMEM = {
|
const unsigned char Smiling_Closed_Eyes[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x42,
|
||||||
0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0xc0, 0xc1, 0x00, 0x00, 0x00, 0xc7,
|
0x42, 0x22, 0x44, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
|
||||||
0x00, 0x00, 0x1e, 0xcc, 0x00, 0x00, 0x30, 0xc8, 0x00, 0x00, 0x60, 0xd8, 0x00, 0x08, 0xc0, 0xd0, 0x00, 0x1a, 0x81, 0xd1,
|
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0x00, 0x36, 0x03, 0xd3, 0x80, 0x6d, 0x06, 0xd2, 0x00, 0xdb, 0x0c, 0xc2, 0x80, 0xb6, 0x1d, 0xc0, 0x80, 0x6d, 0x1f, 0xc0,
|
|
||||||
0x00, 0xdb, 0x3f, 0xc0, 0x00, 0xf6, 0x7f, 0xc0, 0x00, 0xfc, 0x7f, 0xc0, 0x08, 0xf8, 0x7f, 0xc0, 0x48, 0xf0, 0x7f, 0xc0,
|
|
||||||
0x48, 0xe0, 0x7f, 0xc0, 0xc8, 0xc0, 0x3f, 0xc0, 0x98, 0x81, 0x1f, 0xc0, 0x10, 0x03, 0x00, 0xc0, 0x30, 0x0e, 0x00, 0xc0,
|
|
||||||
0x20, 0x38, 0x00, 0xc0, 0xe0, 0x00, 0x00, 0xc0, 0x80, 0x07, 0x00, 0xc0, 0x00, 0x1e, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char cowboy[] PROGMEM = {
|
const unsigned char Grinning_SmilingEyes2[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x24, 0x24, 0x52,
|
||||||
0x00, 0x0c, 0x0c, 0xc0, 0x00, 0x02, 0x10, 0xc0, 0x00, 0x01, 0x20, 0xc0, 0xbc, 0x00, 0x40, 0xcf, 0xc2, 0x01, 0xe0, 0xd0,
|
0x4A, 0x02, 0x40, 0x02, 0x40, 0xF2, 0x4F, 0x12, 0x48, 0x22, 0x44,
|
||||||
0x01, 0x01, 0x20, 0xe0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0,
|
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0xc1, 0x3f, 0xff, 0xe0, 0xe1, 0xff, 0xff, 0xe1, 0xf2, 0xf3, 0xf3, 0xd3, 0xf4, 0xf1, 0xe3, 0xcb, 0xfc, 0xf1, 0xe3, 0xc7,
|
|
||||||
0xf8, 0xf1, 0xe3, 0xc7, 0xf8, 0xf1, 0xe3, 0xc7, 0xf8, 0xfb, 0xf7, 0xc7, 0xf8, 0xff, 0xff, 0xc7, 0xf8, 0xff, 0xff, 0xc7,
|
|
||||||
0x70, 0xf8, 0x8f, 0xc3, 0x70, 0x03, 0xb0, 0xc3, 0x70, 0xfe, 0xbf, 0xc3, 0x60, 0x00, 0x80, 0xc1, 0xc0, 0x00, 0xc0, 0xc0,
|
|
||||||
0x80, 0x01, 0x60, 0xc0, 0x00, 0x07, 0x38, 0xc0, 0x00, 0xfe, 0x1f, 0xc0, 0x00, 0xf0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char deadmau5[] PROGMEM = {
|
const unsigned char Loudly_Crying_Face[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x34, 0x2C, 0x4A,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00,
|
0x52, 0x12, 0x48, 0x12, 0x48, 0x92, 0x49, 0x52, 0x4A, 0x52, 0x4A,
|
||||||
0x00, 0xFC, 0x03, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0x3F, 0x00,
|
0x54, 0x2A, 0x94, 0x29, 0x18, 0x18, 0xF0, 0x0F, 0x00, 0x00};
|
||||||
0xE0, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0x7F, 0x00, 0xF0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x07,
|
|
||||||
0xFC, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x00,
|
|
||||||
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0x3F, 0xFC,
|
|
||||||
0x0F, 0xFF, 0x7F, 0x00, 0xC0, 0xFF, 0x1F, 0xF8, 0x0F, 0xFC, 0x3F, 0x00, 0x80, 0xFF, 0x0F, 0xF8, 0x1F, 0xFC, 0x1F, 0x00,
|
|
||||||
0x00, 0xFF, 0x0F, 0xFC, 0x3F, 0xFC, 0x0F, 0x00, 0x00, 0xF8, 0x1F, 0xFF, 0xFF, 0xFE, 0x01, 0x00, 0x00, 0x00, 0xFC, 0xFF,
|
|
||||||
0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
|
||||||
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x80, 0x07, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char sun[] PROGMEM = {
|
const unsigned char wave_icon[] PROGMEM = {0x00, 0x00, 0xC0, 0x18, 0x30, 0x21, 0x48, 0x5A, 0x94, 0x64, 0x24,
|
||||||
0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x30, 0xC0, 0x00, 0x03,
|
0x25, 0x4A, 0x24, 0x12, 0x44, 0x22, 0x44, 0x04, 0x40, 0x08, 0x40,
|
||||||
0x70, 0x00, 0x80, 0x03, 0xF0, 0x00, 0xC0, 0x03, 0xF0, 0xF8, 0xC7, 0x03, 0xE0, 0xFC, 0xCF, 0x01, 0x00, 0xFE, 0x1F, 0x00,
|
0x12, 0x40, 0x22, 0x20, 0xC4, 0x10, 0x18, 0x0F, 0x00, 0x00};
|
||||||
0x00, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x8E, 0xFF, 0x7F, 0x1C, 0x9F, 0xFF, 0x7F, 0x3E,
|
|
||||||
0x9F, 0xFF, 0x7F, 0x3E, 0x8E, 0xFF, 0x7F, 0x1C, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x3F, 0x00,
|
|
||||||
0x00, 0xFE, 0x1F, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0xC0, 0xF9, 0xE7, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0xF0, 0x01, 0xE0, 0x03,
|
|
||||||
0xF0, 0xC0, 0xC0, 0x03, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xC0, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char rain[] PROGMEM = {
|
const unsigned char cowboy[] PROGMEM = {0x70, 0x0E, 0x8F, 0xF1, 0x11, 0x88, 0x21, 0x84, 0xC2, 0x43, 0x1E,
|
||||||
0xC0, 0x0F, 0xC0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x03, 0x38, 0x00,
|
0x78, 0xE2, 0x47, 0x42, 0x42, 0x12, 0x48, 0x12, 0x48, 0x22, 0x44,
|
||||||
0x00, 0x0E, 0x0C, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x20,
|
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x30, 0x02, 0x00,
|
|
||||||
0x00, 0x10, 0x06, 0x00, 0x00, 0x08, 0xFC, 0xFF, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0x01, 0x80, 0x00, 0x01, 0x00,
|
|
||||||
0xC0, 0xC0, 0x81, 0x03, 0xA0, 0x60, 0xC1, 0x03, 0x90, 0x20, 0x41, 0x01, 0xF0, 0xE0, 0xC0, 0x01, 0x60, 0x4C,
|
|
||||||
0x98, 0x00, 0x00, 0x0E, 0x1C, 0x00, 0x00, 0x0B, 0x12, 0x00, 0x00, 0x09, 0x1A, 0x00, 0x00, 0x06, 0x0E, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char cloud[] PROGMEM = {
|
const unsigned char deadmau5[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0xE4, 0x27, 0x12, 0x48, 0x0A,
|
||||||
0x00, 0x80, 0x07, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x70, 0x30, 0x00, 0x00, 0x10, 0x60, 0x00, 0x80, 0x1F, 0x40, 0x00,
|
0x50, 0x0E, 0x70, 0x11, 0x88, 0x19, 0x98, 0x19, 0x98, 0x19, 0x98,
|
||||||
0xC0, 0x0F, 0xC0, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x60, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x01,
|
0x19, 0x98, 0x19, 0x98, 0x11, 0x88, 0x0E, 0x70, 0x00, 0x00};
|
||||||
0x20, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x10,
|
|
||||||
0x02, 0x00, 0x00, 0x30, 0x03, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
|
|
||||||
0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x30, 0x03, 0x00, 0x00, 0x10,
|
|
||||||
0x02, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x0C, 0xFC, 0xFF, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0x03,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char fog[] PROGMEM = {
|
const unsigned char sun[] PROGMEM = {0x00, 0x00, 0x80, 0x01, 0xEC, 0x37, 0xFC, 0x3F, 0xF8, 0x1F, 0xFC,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x3F, 0xFE, 0x7F, 0xFC, 0x3F, 0xFC, 0x3F, 0xFE, 0x7F, 0xFC, 0x3F,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x3C, 0x00, 0xFE, 0x01, 0xFF, 0x00, 0x87, 0xC7, 0xC3, 0x01, 0x03, 0xFE, 0x80, 0x01,
|
0xF8, 0x1F, 0xFC, 0x3F, 0xEC, 0x37, 0x80, 0x01, 0x00, 0x00};
|
||||||
0x00, 0x38, 0x00, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0xFF, 0x83, 0xFF, 0x01, 0x03, 0xFF, 0x81, 0x01, 0x00, 0x7C, 0x00, 0x00,
|
|
||||||
0xF8, 0x00, 0x3E, 0x00, 0xFE, 0x01, 0xFF, 0x00, 0x87, 0xC7, 0xC3, 0x01, 0x03, 0xFE, 0x80, 0x01, 0x00, 0x38, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char devil[] PROGMEM = {
|
const unsigned char rain[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x1F, 0xFC, 0x3F, 0xFE,
|
||||||
0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x0f, 0xfc, 0x0f, 0xfc,
|
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x00, 0x48, 0x12,
|
||||||
0x3f, 0xff, 0x3f, 0xff, 0xfe, 0xff, 0xff, 0xdf, 0xfe, 0xff, 0xff, 0xdf, 0xfe, 0xff, 0xff, 0xdf, 0xfc, 0xff, 0xff, 0xcf,
|
0x48, 0x12, 0x24, 0x09, 0x24, 0x09, 0x00, 0x00, 0x00, 0x00};
|
||||||
0xfc, 0xff, 0xff, 0xcf, 0xf8, 0xff, 0xff, 0xc7, 0xf0, 0xff, 0xff, 0xc3, 0xf0, 0xff, 0xff, 0xc3, 0xf0, 0xf1, 0xe3, 0xc3,
|
|
||||||
0xf0, 0xe7, 0xf9, 0xc3, 0xf0, 0xe7, 0xf9, 0xc3, 0xf0, 0xe3, 0xf1, 0xc3, 0xf0, 0xe3, 0xf1, 0xc3, 0xf0, 0xe7, 0xf9, 0xc3,
|
|
||||||
0xf0, 0xff, 0xff, 0xc3, 0xe0, 0xfd, 0xef, 0xc1, 0xe0, 0xf3, 0xf3, 0xc1, 0xc0, 0x07, 0xf8, 0xc0, 0x80, 0x1f, 0x7e, 0xc0,
|
|
||||||
0x00, 0xff, 0x3f, 0xc0, 0x00, 0xfe, 0x0f, 0xc0, 0x00, 0xf8, 0x03, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char heart[] PROGMEM = {
|
const unsigned char cloud[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x38, 0x1F, 0xFC,
|
||||||
0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0xF0, 0x00, 0xF8, 0x0F, 0xFC, 0x07, 0xFC, 0x1F, 0x06, 0x0E, 0xFE, 0x3F, 0x03, 0x18,
|
0x3F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F,
|
||||||
0xFE, 0xFF, 0x7F, 0x10, 0xFF, 0xFF, 0xFF, 0x31, 0xFF, 0xFF, 0xFF, 0x33, 0xFF, 0xFF, 0xFF, 0x37, 0xFF, 0xFF, 0xFF, 0x37,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF, 0xFF, 0x1F,
|
|
||||||
0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF, 0x07, 0xF0, 0xFF, 0xFF, 0x03, 0xF0, 0xFF, 0xFF, 0x03,
|
|
||||||
0xE0, 0xFF, 0xFF, 0x01, 0xC0, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x3F, 0x00, 0x00, 0xFE, 0x1F, 0x00,
|
|
||||||
0x00, 0xFC, 0x0F, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char poo[] PROGMEM = {
|
const unsigned char fog[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x54, 0x55, 0x22, 0x22, 0x00,
|
||||||
0x00, 0x1c, 0x00, 0xc0, 0x00, 0x7c, 0x00, 0xc0, 0x00, 0xfc, 0x00, 0xc0, 0x00, 0x7c, 0x03, 0xc0, 0x00, 0xbe, 0x03, 0xc0,
|
0x00, 0x44, 0x44, 0xAA, 0x2A, 0x11, 0x11, 0x00, 0x00, 0x88, 0x88,
|
||||||
0x00, 0xdf, 0x0f, 0xc0, 0x80, 0xcf, 0x0f, 0xc0, 0xc0, 0xf1, 0x0f, 0xc0, 0x60, 0xfc, 0x0f, 0xc0, 0x30, 0xff, 0x07, 0xc0,
|
0x54, 0x55, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
0x90, 0xff, 0x3b, 0xc0, 0xc0, 0xff, 0x7d, 0xc0, 0xf8, 0xff, 0xfc, 0xc0, 0xf8, 0x3f, 0xf0, 0xc0, 0x78, 0x88, 0xc0, 0xc0,
|
|
||||||
0x20, 0xe3, 0x18, 0xc0, 0x98, 0xe7, 0xbc, 0xc1, 0x9c, 0x64, 0xa4, 0xc3, 0x9e, 0x64, 0xa4, 0xc7, 0xbe, 0xe4, 0xa4, 0xc7,
|
|
||||||
0xbc, 0x27, 0xbc, 0xc7, 0x38, 0x03, 0xd9, 0xc3, 0x00, 0xf0, 0x63, 0xc0, 0xf8, 0xfc, 0x3f, 0xcf, 0xfc, 0xff, 0x87, 0xdf,
|
|
||||||
0xfe, 0xff, 0xe0, 0xdf, 0xfc, 0x1f, 0xfe, 0xdf, 0xf8, 0x07, 0xf8, 0xcf, 0xf0, 0x03, 0xe0, 0xc7, 0x00, 0x00, 0x00, 0xc0};
|
|
||||||
|
|
||||||
const unsigned char bell_icon[] PROGMEM = {
|
const unsigned char devil[] PROGMEM = {0x06, 0x60, 0xCA, 0x53, 0x32, 0x4C, 0x22, 0x44, 0x44, 0x22, 0x3A,
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b11110000,
|
0x5C, 0x32, 0x4C, 0x52, 0x4A, 0x72, 0x4E, 0x02, 0x40, 0x22, 0x44,
|
||||||
0b00000011, 0b00000000, 0b00000000, 0b11111100, 0b00001111, 0b00000000, 0b00000000, 0b00001111, 0b00111100, 0b00000000,
|
0xC4, 0x23, 0x04, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
0b00000000, 0b00000011, 0b00110000, 0b00000000, 0b10000000, 0b00000001, 0b01100000, 0b00000000, 0b11000000, 0b00000000,
|
|
||||||
0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000,
|
const unsigned char heart[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x7E, 0x7E, 0xFE, 0x7F, 0xFE,
|
||||||
0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000,
|
0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F, 0xF8, 0x1F,
|
||||||
0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b11000000, 0b00000000,
|
0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00};
|
||||||
0b11000000, 0b00000000, 0b11000000, 0b00000000, 0b01000000, 0b00000000, 0b10000000, 0b00000000, 0b01100000, 0b00000000,
|
|
||||||
0b10000000, 0b00000001, 0b01110000, 0b00000000, 0b10000000, 0b00000011, 0b00110000, 0b00000000, 0b00000000, 0b00000011,
|
const unsigned char poo[] PROGMEM = {0x00, 0x00, 0x80, 0x01, 0x40, 0x02, 0x20, 0x04, 0x10, 0x04, 0xF0,
|
||||||
0b00011000, 0b00000000, 0b00000000, 0b00000110, 0b11110000, 0b11111111, 0b11111111, 0b00000011, 0b00000000, 0b00001100,
|
0x08, 0x10, 0x10, 0x48, 0x12, 0x08, 0x18, 0xE8, 0x21, 0x1C, 0x40,
|
||||||
0b00001100, 0b00000000, 0b00000000, 0b00011000, 0b00000110, 0b00000000, 0b00000000, 0b11111000, 0b00000111, 0b00000000,
|
0x42, 0x42, 0x82, 0x41, 0x02, 0x30, 0xFC, 0x0F, 0x00, 0x00};
|
||||||
0b00000000, 0b11100000, 0b00000001, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
|
||||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000};
|
const unsigned char bell_icon[] PROGMEM = {0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0xE0, 0x07, 0xF0, 0x0F, 0xF0,
|
||||||
|
0x0F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFC, 0x3F,
|
||||||
|
0xFC, 0x3F, 0xFE, 0x7F, 0xFE, 0x7F, 0x80, 0x01, 0x00, 0x00};
|
||||||
|
|
||||||
|
const unsigned char cookie[] PROGMEM = {0x00, 0x00, 0xE0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x34, 0x22, 0x32,
|
||||||
|
0x40, 0x02, 0x58, 0x82, 0x5B, 0x92, 0x43, 0x82, 0x43, 0x02, 0x40,
|
||||||
|
0x64, 0x28, 0x64, 0x20, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
|
|
||||||
|
const unsigned char Fire[] PROGMEM = {0x30, 0x00, 0xF0, 0x00, 0xF8, 0x03, 0xF8, 0x07, 0xFC, 0x1F, 0xFC,
|
||||||
|
0x1F, 0xFE, 0x3E, 0x7E, 0x3E, 0x3E, 0x7C, 0x1E, 0x78, 0x1E, 0x70,
|
||||||
|
0x1C, 0x70, 0x1C, 0x70, 0x38, 0x38, 0x30, 0x38, 0x60, 0x0C};
|
||||||
|
|
||||||
|
const unsigned char peace_sign[] PROGMEM = {0xC0, 0x30, 0x40, 0x29, 0x40, 0x25, 0x40, 0x15, 0x40, 0x12, 0x38,
|
||||||
|
0x0A, 0x54, 0x68, 0x54, 0x58, 0x54, 0x44, 0x3C, 0x22, 0x04, 0x22,
|
||||||
|
0x04, 0x12, 0x08, 0x10, 0x10, 0x08, 0xE0, 0x07, 0x00, 0x00};
|
||||||
|
|
||||||
|
const unsigned char Praying[] PROGMEM = {0x00, 0x00, 0x40, 0x02, 0xA0, 0x05, 0x90, 0x09, 0x90, 0x09, 0x90,
|
||||||
|
0x09, 0x98, 0x19, 0x94, 0x29, 0xA4, 0x25, 0xA4, 0x25, 0x84, 0x21,
|
||||||
|
0x84, 0x21, 0x86, 0x61, 0x4E, 0x72, 0x7F, 0x7E, 0x3F, 0xFC};
|
||||||
|
|
||||||
|
const unsigned char Sparkles[] PROGMEM = {0x00, 0x00, 0x10, 0x00, 0x38, 0x04, 0x10, 0x04, 0x00, 0x0E, 0x00,
|
||||||
|
0x1F, 0x80, 0x3F, 0xE0, 0xFF, 0x80, 0x3F, 0x10, 0x1F, 0x10, 0x0E,
|
||||||
|
0x38, 0x04, 0xFE, 0x04, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
|
||||||
|
|
||||||
|
const unsigned char clown[] PROGMEM = {0x00, 0x00, 0xEE, 0x77, 0x1A, 0x58, 0x06, 0x60, 0x24, 0x24, 0x72,
|
||||||
|
0x4E, 0x22, 0x44, 0x82, 0x41, 0x82, 0x41, 0x1A, 0x58, 0xF2, 0x4F,
|
||||||
|
0x14, 0x28, 0xE4, 0x27, 0x18, 0x18, 0xE0, 0x07, 0x00, 0x00};
|
||||||
|
|
||||||
|
const unsigned char robo[] PROGMEM = {0x80, 0x01, 0xC0, 0x03, 0x80, 0x01, 0xFC, 0x3F, 0x04, 0x20, 0x74,
|
||||||
|
0x2E, 0x52, 0x4A, 0x72, 0x4E, 0x02, 0x40, 0x02, 0x40, 0xA2, 0x4A,
|
||||||
|
0x52, 0x45, 0x04, 0x20, 0x04, 0x20, 0xFC, 0x3F, 0x00, 0x00};
|
||||||
|
|
||||||
|
const unsigned char hole[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x3C, 0x3C,
|
||||||
|
0x06, 0x60, 0x0C, 0x30, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
|
const unsigned char bowling[] PROGMEM = {0x00, 0x38, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00,
|
||||||
|
0x38, 0x00, 0x28, 0x78, 0x44, 0x84, 0x82, 0x22, 0x83, 0x52, 0x83,
|
||||||
|
0x02, 0x83, 0x02, 0x45, 0x84, 0x44, 0x78, 0x38, 0x00, 0x00};
|
||||||
|
|
||||||
|
const unsigned char vulcan_salute[] PROGMEM = {0x08, 0x02, 0x16, 0x0D, 0x15, 0x15, 0x15, 0x15, 0xA9, 0x12, 0x4A,
|
||||||
|
0x0A, 0x02, 0x38, 0x04, 0x48, 0x04, 0x44, 0x04, 0x22, 0x04, 0x22,
|
||||||
|
0x04, 0x12, 0x08, 0x10, 0x10, 0x08, 0xE0, 0x07, 0x00, 0x00};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
|
|||||||
@@ -17,98 +17,150 @@ extern const int numEmotes;
|
|||||||
|
|
||||||
#ifndef EXCLUDE_EMOJI
|
#ifndef EXCLUDE_EMOJI
|
||||||
// === Emote Bitmaps ===
|
// === Emote Bitmaps ===
|
||||||
#define thumbs_height 25
|
#define thumbs_height 16
|
||||||
#define thumbs_width 25
|
#define thumbs_width 16
|
||||||
extern const unsigned char thumbup[] PROGMEM;
|
extern const unsigned char thumbup[] PROGMEM;
|
||||||
extern const unsigned char thumbdown[] PROGMEM;
|
extern const unsigned char thumbdown[] PROGMEM;
|
||||||
|
|
||||||
#define Smiling_Eyes_height 30
|
#define Smiling_Eyes_height 16
|
||||||
#define Smiling_Eyes_width 30
|
#define Smiling_Eyes_width 16
|
||||||
extern const unsigned char Smiling_Eyes[] PROGMEM;
|
extern const unsigned char Smiling_Eyes[] PROGMEM;
|
||||||
|
|
||||||
#define Grinning_height 30
|
#define Grinning_height 16
|
||||||
#define Grinning_width 30
|
#define Grinning_width 16
|
||||||
extern const unsigned char Grinning[] PROGMEM;
|
extern const unsigned char Grinning[] PROGMEM;
|
||||||
|
|
||||||
#define Slightly_Smiling_height 30
|
#define Slightly_Smiling_height 16
|
||||||
#define Slightly_Smiling_width 30
|
#define Slightly_Smiling_width 16
|
||||||
extern const unsigned char Slightly_Smiling[] PROGMEM;
|
extern const unsigned char Slightly_Smiling[] PROGMEM;
|
||||||
|
|
||||||
#define Winking_Face_height 30
|
#define Winking_Face_height 16
|
||||||
#define Winking_Face_width 30
|
#define Winking_Face_width 16
|
||||||
extern const unsigned char Winking_Face[] PROGMEM;
|
extern const unsigned char Winking_Face[] PROGMEM;
|
||||||
|
|
||||||
#define Grinning_Smiling_Eyes_height 30
|
#define Grinning_Smiling_Eyes_height 16
|
||||||
#define Grinning_Smiling_Eyes_width 30
|
#define Grinning_Smiling_Eyes_width 16
|
||||||
extern const unsigned char Grinning_Smiling_Eyes[] PROGMEM;
|
extern const unsigned char Grinning_Smiling_Eyes[] PROGMEM;
|
||||||
|
|
||||||
#define question_height 25
|
#define heart_smile_height 16
|
||||||
#define question_width 25
|
#define heart_smile_width 16
|
||||||
|
extern const unsigned char heart_smile[] PROGMEM;
|
||||||
|
|
||||||
|
#define Heart_eyes_height 16
|
||||||
|
#define Heart_eyes_width 16
|
||||||
|
extern const unsigned char Heart_eyes[] PROGMEM;
|
||||||
|
|
||||||
|
#define question_height 16
|
||||||
|
#define question_width 16
|
||||||
extern const unsigned char question[] PROGMEM;
|
extern const unsigned char question[] PROGMEM;
|
||||||
|
|
||||||
#define bang_height 30
|
#define bang_height 16
|
||||||
#define bang_width 30
|
#define bang_width 16
|
||||||
extern const unsigned char bang[] PROGMEM;
|
extern const unsigned char bang[] PROGMEM;
|
||||||
|
|
||||||
#define haha_height 30
|
#define haha_height 16
|
||||||
#define haha_width 30
|
#define haha_width 16
|
||||||
extern const unsigned char haha[] PROGMEM;
|
extern const unsigned char haha[] PROGMEM;
|
||||||
|
|
||||||
#define ROFL_height 30
|
#define ROFL_height 16
|
||||||
#define ROFL_width 30
|
#define ROFL_width 16
|
||||||
extern const unsigned char ROFL[] PROGMEM;
|
extern const unsigned char ROFL[] PROGMEM;
|
||||||
|
|
||||||
#define Smiling_Closed_Eyes_height 30
|
#define Smiling_Closed_Eyes_height 16
|
||||||
#define Smiling_Closed_Eyes_width 30
|
#define Smiling_Closed_Eyes_width 16
|
||||||
extern const unsigned char Smiling_Closed_Eyes[] PROGMEM;
|
extern const unsigned char Smiling_Closed_Eyes[] PROGMEM;
|
||||||
|
|
||||||
#define Grinning_SmilingEyes2_height 30
|
#define Grinning_SmilingEyes2_height 16
|
||||||
#define Grinning_SmilingEyes2_width 30
|
#define Grinning_SmilingEyes2_width 16
|
||||||
extern const unsigned char Grinning_SmilingEyes2[] PROGMEM;
|
extern const unsigned char Grinning_SmilingEyes2[] PROGMEM;
|
||||||
|
|
||||||
#define wave_icon_height 30
|
#define Loudly_Crying_Face_height 16
|
||||||
#define wave_icon_width 30
|
#define Loudly_Crying_Face_width 16
|
||||||
|
extern const unsigned char Loudly_Crying_Face[] PROGMEM;
|
||||||
|
|
||||||
|
#define wave_icon_height 16
|
||||||
|
#define wave_icon_width 16
|
||||||
extern const unsigned char wave_icon[] PROGMEM;
|
extern const unsigned char wave_icon[] PROGMEM;
|
||||||
|
|
||||||
#define cowboy_height 30
|
#define cowboy_height 16
|
||||||
#define cowboy_width 30
|
#define cowboy_width 16
|
||||||
extern const unsigned char cowboy[] PROGMEM;
|
extern const unsigned char cowboy[] PROGMEM;
|
||||||
|
|
||||||
#define deadmau5_height 30
|
#define deadmau5_height 16
|
||||||
#define deadmau5_width 60
|
#define deadmau5_width 16
|
||||||
extern const unsigned char deadmau5[] PROGMEM;
|
extern const unsigned char deadmau5[] PROGMEM;
|
||||||
|
|
||||||
#define sun_height 30
|
#define sun_height 16
|
||||||
#define sun_width 30
|
#define sun_width 16
|
||||||
extern const unsigned char sun[] PROGMEM;
|
extern const unsigned char sun[] PROGMEM;
|
||||||
|
|
||||||
#define rain_height 30
|
#define rain_height 16
|
||||||
#define rain_width 30
|
#define rain_width 16
|
||||||
extern const unsigned char rain[] PROGMEM;
|
extern const unsigned char rain[] PROGMEM;
|
||||||
|
|
||||||
#define cloud_height 30
|
#define cloud_height 16
|
||||||
#define cloud_width 30
|
#define cloud_width 16
|
||||||
extern const unsigned char cloud[] PROGMEM;
|
extern const unsigned char cloud[] PROGMEM;
|
||||||
|
|
||||||
#define fog_height 25
|
#define fog_height 16
|
||||||
#define fog_width 25
|
#define fog_width 16
|
||||||
extern const unsigned char fog[] PROGMEM;
|
extern const unsigned char fog[] PROGMEM;
|
||||||
|
|
||||||
#define devil_height 30
|
#define devil_height 16
|
||||||
#define devil_width 30
|
#define devil_width 16
|
||||||
extern const unsigned char devil[] PROGMEM;
|
extern const unsigned char devil[] PROGMEM;
|
||||||
|
|
||||||
#define heart_height 30
|
#define heart_height 16
|
||||||
#define heart_width 30
|
#define heart_width 16
|
||||||
extern const unsigned char heart[] PROGMEM;
|
extern const unsigned char heart[] PROGMEM;
|
||||||
|
|
||||||
#define poo_height 30
|
#define poo_height 16
|
||||||
#define poo_width 30
|
#define poo_width 16
|
||||||
extern const unsigned char poo[] PROGMEM;
|
extern const unsigned char poo[] PROGMEM;
|
||||||
|
|
||||||
#define bell_icon_width 30
|
#define bell_icon_width 16
|
||||||
#define bell_icon_height 30
|
#define bell_icon_height 16
|
||||||
extern const unsigned char bell_icon[] PROGMEM;
|
extern const unsigned char bell_icon[] PROGMEM;
|
||||||
|
|
||||||
|
#define cookie_width 16
|
||||||
|
#define cookie_height 16
|
||||||
|
extern const unsigned char cookie[] PROGMEM;
|
||||||
|
|
||||||
|
#define Fire_width 16
|
||||||
|
#define Fire_height 16
|
||||||
|
extern const unsigned char Fire[] PROGMEM;
|
||||||
|
|
||||||
|
#define peace_sign_width 16
|
||||||
|
#define peace_sign_height 16
|
||||||
|
extern const unsigned char peace_sign[] PROGMEM;
|
||||||
|
|
||||||
|
#define Praying_width 16
|
||||||
|
#define Praying_height 16
|
||||||
|
extern const unsigned char Praying[] PROGMEM;
|
||||||
|
|
||||||
|
#define Sparkles_width 16
|
||||||
|
#define Sparkles_height 16
|
||||||
|
extern const unsigned char Sparkles[] PROGMEM;
|
||||||
|
|
||||||
|
#define clown_width 16
|
||||||
|
#define clown_height 16
|
||||||
|
extern const unsigned char clown[] PROGMEM;
|
||||||
|
|
||||||
|
#define robo_width 16
|
||||||
|
#define robo_height 16
|
||||||
|
extern const unsigned char robo[] PROGMEM;
|
||||||
|
|
||||||
|
#define hole_width 16
|
||||||
|
#define hole_height 16
|
||||||
|
extern const unsigned char hole[] PROGMEM;
|
||||||
|
|
||||||
|
#define bowling_width 16
|
||||||
|
#define bowling_height 16
|
||||||
|
extern const unsigned char bowling[] PROGMEM;
|
||||||
|
|
||||||
|
#define vulcan_salute_width 16
|
||||||
|
#define vulcan_salute_height 16
|
||||||
|
extern const unsigned char vulcan_salute[] PROGMEM;
|
||||||
#endif // EXCLUDE_EMOJI
|
#endif // EXCLUDE_EMOJI
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
@@ -287,7 +287,7 @@ void InkHUD::MapApplet::getMapCenter(float *lat, float *lng)
|
|||||||
float easternmost = lngCenter;
|
float easternmost = lngCenter;
|
||||||
float westernmost = lngCenter;
|
float westernmost = lngCenter;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < nodeDB->getNumMeshNodes(); i++) {
|
for (size_t i = 0; i < nodeDB->getNumMeshNodes(); i++) {
|
||||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
|
||||||
|
|
||||||
// Skip if no position
|
// Skip if no position
|
||||||
@@ -474,8 +474,8 @@ void InkHUD::MapApplet::drawLabeledMarker(meshtastic_NodeInfoLite *node)
|
|||||||
// Need at least two, to draw a sensible map
|
// Need at least two, to draw a sensible map
|
||||||
bool InkHUD::MapApplet::enoughMarkers()
|
bool InkHUD::MapApplet::enoughMarkers()
|
||||||
{
|
{
|
||||||
uint8_t count = 0;
|
size_t count = 0;
|
||||||
for (uint8_t i = 0; i < nodeDB->getNumMeshNodes(); i++) {
|
for (size_t i = 0; i < nodeDB->getNumMeshNodes(); i++) {
|
||||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i);
|
||||||
|
|
||||||
// Count nodes
|
// Count nodes
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ A pattern / collection of resources for creating custom UIs, to target small gro
|
|||||||
For an example, see the `heltec-vision-master-e290-inkhud` platformio env.
|
For an example, see the `heltec-vision-master-e290-inkhud` platformio env.
|
||||||
|
|
||||||
- platformio.ini
|
- platformio.ini
|
||||||
|
|
||||||
- suppress default Meshtastic components (Screen, ButtonThread, etc)
|
- suppress default Meshtastic components (Screen, ButtonThread, etc)
|
||||||
- define `MESHTASTIC_INCLUDE_NICHE_GRAPHICS`
|
- define `MESHTASTIC_INCLUDE_NICHE_GRAPHICS`
|
||||||
- (possibly) Edit `build_src_filter` to include our new nicheGraphics.h file
|
- (possibly) Edit `build_src_filter` to include our new nicheGraphics.h file
|
||||||
|
|||||||
10
src/main.cpp
10
src/main.cpp
@@ -330,7 +330,7 @@ void setup()
|
|||||||
|
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
pinMode(WIFI_LED, OUTPUT);
|
pinMode(WIFI_LED, OUTPUT);
|
||||||
digitalWrite(WIFI_LED, LOW);
|
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BLE_LED
|
#ifdef BLE_LED
|
||||||
@@ -477,6 +477,10 @@ void setup()
|
|||||||
#ifdef RESET_OLED
|
#ifdef RESET_OLED
|
||||||
pinMode(RESET_OLED, OUTPUT);
|
pinMode(RESET_OLED, OUTPUT);
|
||||||
digitalWrite(RESET_OLED, 1);
|
digitalWrite(RESET_OLED, 1);
|
||||||
|
delay(2);
|
||||||
|
digitalWrite(RESET_OLED, 0);
|
||||||
|
delay(10);
|
||||||
|
digitalWrite(RESET_OLED, 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SENSOR_POWER_CTRL_PIN
|
#ifdef SENSOR_POWER_CTRL_PIN
|
||||||
@@ -959,6 +963,7 @@ void setup()
|
|||||||
i2cScanner.reset();
|
i2cScanner.reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
||||||
// warn the user about a low entropy key
|
// warn the user about a low entropy key
|
||||||
if (nodeDB->keyIsLowEntropy && !nodeDB->hasWarned) {
|
if (nodeDB->keyIsLowEntropy && !nodeDB->hasWarned) {
|
||||||
LOG_WARN(LOW_ENTROPY_WARNING);
|
LOG_WARN(LOW_ENTROPY_WARNING);
|
||||||
@@ -969,6 +974,7 @@ void setup()
|
|||||||
service->sendClientNotification(cn);
|
service->sendClientNotification(cn);
|
||||||
nodeDB->hasWarned = true;
|
nodeDB->hasWarned = true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// buttons are now inputBroker, so have to come after setupModules
|
// buttons are now inputBroker, so have to come after setupModules
|
||||||
#if HAS_BUTTON
|
#if HAS_BUTTON
|
||||||
@@ -1401,7 +1407,7 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check if the radio chip matches the selected region
|
// check if the radio chip matches the selected region
|
||||||
if ((config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (!rIf->wideLora())) {
|
if ((config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && rIf && (!rIf->wideLora())) {
|
||||||
LOG_WARN("LoRa chip does not support 2.4GHz. Revert to unset");
|
LOG_WARN("LoRa chip does not support 2.4GHz. Revert to unset");
|
||||||
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
|
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
|
||||||
nodeDB->saveToDisk(SEGMENT_CONFIG);
|
nodeDB->saveToDisk(SEGMENT_CONFIG);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#else
|
#else
|
||||||
#define default_ringtone_nag_secs 15
|
#define default_ringtone_nag_secs 15
|
||||||
#endif
|
#endif
|
||||||
|
#define default_network_ipv6_enabled false
|
||||||
|
|
||||||
#define default_mqtt_address "mqtt.meshtastic.org"
|
#define default_mqtt_address "mqtt.meshtastic.org"
|
||||||
#define default_mqtt_username "meshdev"
|
#define default_mqtt_username "meshdev"
|
||||||
@@ -46,12 +47,15 @@ class Default
|
|||||||
static uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval);
|
static uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval);
|
||||||
static uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval);
|
static uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval);
|
||||||
static uint32_t getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue);
|
static uint32_t getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue);
|
||||||
|
// Note: numOnlineNodes uses uint32_t to match the public API and allow flexibility,
|
||||||
|
// even though internal node counts use uint16_t (max 65535 nodes)
|
||||||
static uint32_t getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t defaultValue, uint32_t numOnlineNodes);
|
static uint32_t getConfiguredOrDefaultMsScaled(uint32_t configured, uint32_t defaultValue, uint32_t numOnlineNodes);
|
||||||
static uint8_t getConfiguredOrDefaultHopLimit(uint8_t configured);
|
static uint8_t getConfiguredOrDefaultHopLimit(uint8_t configured);
|
||||||
static uint32_t getConfiguredOrMinimumValue(uint32_t configured, uint32_t minValue);
|
static uint32_t getConfiguredOrMinimumValue(uint32_t configured, uint32_t minValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static float congestionScalingCoefficient(int numOnlineNodes)
|
// Note: Kept as uint32_t to match the public API parameter type
|
||||||
|
static float congestionScalingCoefficient(uint32_t numOnlineNodes)
|
||||||
{
|
{
|
||||||
// Increase frequency of broadcasts for small networks regardless of preset
|
// Increase frequency of broadcasts for small networks regardless of preset
|
||||||
if (numOnlineNodes <= 10) {
|
if (numOnlineNodes <= 10) {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ template class LR11x0Interface<LR1121>;
|
|||||||
template class SX126xInterface<STM32WLx>;
|
template class SX126xInterface<STM32WLx>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
#include "api/ethServerAPI.h"
|
#include "api/ethServerAPI.h"
|
||||||
template class ServerAPI<EthernetClient>;
|
template class ServerAPI<EthernetClient>;
|
||||||
template class APIServerPort<ethServerAPI, EthernetServer>;
|
template class APIServerPort<ethServerAPI, EthernetServer>;
|
||||||
|
|||||||
@@ -244,6 +244,8 @@ template <typename T> void LR11x0Interface<T>::startReceive()
|
|||||||
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
|
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
|
||||||
int err =
|
int err =
|
||||||
lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
|
lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
|
||||||
|
if (err)
|
||||||
|
LOG_ERROR("StartReceive error: %d", err);
|
||||||
assert(err == RADIOLIB_ERR_NONE);
|
assert(err == RADIOLIB_ERR_NONE);
|
||||||
|
|
||||||
RadioLibInterface::startReceive();
|
RadioLibInterface::startReceive();
|
||||||
@@ -304,4 +306,4 @@ template <typename T> bool LR11x0Interface<T>::sleep()
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -718,6 +718,12 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
strncpy(config.network.wifi_psk, USERPREFS_NETWORK_WIFI_PSK, sizeof(config.network.wifi_psk));
|
strncpy(config.network.wifi_psk, USERPREFS_NETWORK_WIFI_PSK, sizeof(config.network.wifi_psk));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USERPREFS_NETWORK_IPV6_ENABLED)
|
||||||
|
config.network.ipv6_enabled = USERPREFS_NETWORK_IPV6_ENABLED;
|
||||||
|
#else
|
||||||
|
config.network.ipv6_enabled = default_network_ipv6_enabled;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DISPLAY_FLIP_SCREEN
|
#ifdef DISPLAY_FLIP_SCREEN
|
||||||
config.display.flip_screen = true;
|
config.display.flip_screen = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -728,6 +734,9 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
config.display.screen_on_secs = 30;
|
config.display.screen_on_secs = 30;
|
||||||
config.display.wake_on_tap_or_motion = true;
|
config.display.wake_on_tap_or_motion = true;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef COMPASS_ORIENTATION
|
||||||
|
config.display.compass_orientation = COMPASS_ORIENTATION;
|
||||||
|
#endif
|
||||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
|
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
|
||||||
if (WiFiOTA::isUpdated()) {
|
if (WiFiOTA::isUpdated()) {
|
||||||
WiFiOTA::recoverConfig(&config.network);
|
WiFiOTA::recoverConfig(&config.network);
|
||||||
@@ -2002,6 +2011,7 @@ UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
|
|||||||
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
|
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
||||||
bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest)
|
bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest)
|
||||||
{
|
{
|
||||||
if (keyToTest.size == 32) {
|
if (keyToTest.size == 32) {
|
||||||
@@ -2016,6 +2026,7 @@ bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_pub
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
|
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -283,7 +283,9 @@ class NodeDB
|
|||||||
|
|
||||||
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
||||||
|
|
||||||
|
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
||||||
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
|
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
|
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
|
||||||
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
||||||
@@ -373,4 +375,4 @@ extern uint32_t error_address;
|
|||||||
ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + \
|
ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + \
|
||||||
ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
|
ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
|
||||||
|
|
||||||
// Please do not remove this comment, it makes trunk and compiler happy at the same time.
|
// Please do not remove this comment, it makes trunk and compiler happy at the same time.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ template <class T> class ProtobufModule : protected SinglePortModule
|
|||||||
const pb_msgdesc_t *fields;
|
const pb_msgdesc_t *fields;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint8_t numOnlineNodes = 0;
|
uint16_t numOnlineNodes = 0;
|
||||||
/** Constructor
|
/** Constructor
|
||||||
* name is for debugging output
|
* name is for debugging output
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
|
|
||||||
#include "ethServerAPI.h"
|
#include "ethServerAPI.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ServerAPI.h"
|
#include "ServerAPI.h"
|
||||||
#ifndef USE_WS5500
|
#if !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
#include <RAK13800_W5100S.h>
|
#include <RAK13800_W5100S.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -288,6 +288,12 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
meshtastic_HardwareModel_WISMESH_TAP_V2 = 116,
|
meshtastic_HardwareModel_WISMESH_TAP_V2 = 116,
|
||||||
/* RAK3401 */
|
/* RAK3401 */
|
||||||
meshtastic_HardwareModel_RAK3401 = 117,
|
meshtastic_HardwareModel_RAK3401 = 117,
|
||||||
|
/* RAK6421 Hat+ */
|
||||||
|
meshtastic_HardwareModel_RAK6421 = 118,
|
||||||
|
/* Elecrow ThinkNode M4 */
|
||||||
|
meshtastic_HardwareModel_THINKNODE_M4 = 119,
|
||||||
|
/* Elecrow ThinkNode M6 */
|
||||||
|
meshtastic_HardwareModel_THINKNODE_M6 = 120,
|
||||||
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------ */
|
------------------------------------------------------------------------------------------------------------------------------------------ */
|
||||||
@@ -825,7 +831,11 @@ typedef struct _meshtastic_MeshPacket {
|
|||||||
Note: Our crypto implementation uses this field as well.
|
Note: Our crypto implementation uses this field as well.
|
||||||
See [crypto](/docs/overview/encryption) for details. */
|
See [crypto](/docs/overview/encryption) for details. */
|
||||||
uint32_t from;
|
uint32_t from;
|
||||||
/* The (immediate) destination for this packet */
|
/* The (immediate) destination for this packet
|
||||||
|
If the value is 4,294,967,295 (maximum value of an unsigned 32bit integer), this indicates that the packet was
|
||||||
|
not destined for a specific node, but for a channel as indicated by the value of `channel` below.
|
||||||
|
If the value is another, this indicates that the packet was destined for a specific
|
||||||
|
node (i.e. a kind of "Direct Message" to this node) and not broadcast on a channel. */
|
||||||
uint32_t to;
|
uint32_t to;
|
||||||
/* (Usually) If set, this indicates the index in the secondary_channels table that this packet was sent/received on.
|
/* (Usually) If set, this indicates the index in the secondary_channels table that this packet was sent/received on.
|
||||||
If unset, packet was on the primary channel.
|
If unset, packet was on the primary channel.
|
||||||
|
|||||||
@@ -334,6 +334,23 @@ bool initWifi()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
|
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
|
||||||
|
// Most of the next 12 lines of code are adapted from espressif/arduino-esp32
|
||||||
|
// Licensed under the GNU Lesser General Public License v2.1
|
||||||
|
// https://github.com/espressif/arduino-esp32/blob/1f038677eb2eaf5e9ca6b6074486803c15468bed/libraries/WiFi/src/WiFiSTA.cpp#L755
|
||||||
|
esp_netif_t *get_esp_interface_netif(esp_interface_t interface);
|
||||||
|
IPv6Address GlobalIPv6()
|
||||||
|
{
|
||||||
|
esp_ip6_addr_t addr;
|
||||||
|
if (WiFiGenericClass::getMode() == WIFI_MODE_NULL) {
|
||||||
|
return IPv6Address();
|
||||||
|
}
|
||||||
|
if (esp_netif_get_ip6_global(get_esp_interface_netif(ESP_IF_WIFI_STA), &addr)) {
|
||||||
|
return IPv6Address();
|
||||||
|
}
|
||||||
|
return IPv6Address(addr.addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// Called by the Espressif SDK to
|
// Called by the Espressif SDK to
|
||||||
static void WiFiEvent(WiFiEvent_t event)
|
static void WiFiEvent(WiFiEvent_t event)
|
||||||
{
|
{
|
||||||
@@ -355,14 +372,25 @@ static void WiFiEvent(WiFiEvent_t event)
|
|||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||||
LOG_INFO("Connected to access point");
|
LOG_INFO("Connected to access point");
|
||||||
|
if (config.network.ipv6_enabled) {
|
||||||
|
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
|
||||||
|
if (!WiFi.enableIPv6()) {
|
||||||
|
LOG_WARN("Failed to enable IPv6");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!WiFi.enableIpV6()) {
|
||||||
|
LOG_WARN("Failed to enable IPv6");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
digitalWrite(WIFI_LED, HIGH);
|
digitalWrite(WIFI_LED, LOW ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
LOG_INFO("Disconnected from WiFi access point");
|
LOG_INFO("Disconnected from WiFi access point");
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
digitalWrite(WIFI_LED, LOW);
|
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
if (!isReconnecting) {
|
if (!isReconnecting) {
|
||||||
WiFi.disconnect(false, true);
|
WiFi.disconnect(false, true);
|
||||||
@@ -383,7 +411,8 @@ static void WiFiEvent(WiFiEvent_t event)
|
|||||||
LOG_INFO("Obtained Local IP6 address: %s", WiFi.linkLocalIPv6().toString().c_str());
|
LOG_INFO("Obtained Local IP6 address: %s", WiFi.linkLocalIPv6().toString().c_str());
|
||||||
LOG_INFO("Obtained GlobalIP6 address: %s", WiFi.globalIPv6().toString().c_str());
|
LOG_INFO("Obtained GlobalIP6 address: %s", WiFi.globalIPv6().toString().c_str());
|
||||||
#else
|
#else
|
||||||
LOG_INFO("Obtained IP6 address: %s", WiFi.localIPv6().toString().c_str());
|
LOG_INFO("Obtained Local IP6 address: %s", WiFi.localIPv6().toString().c_str());
|
||||||
|
LOG_INFO("Obtained GlobalIP6 address: %s", GlobalIPv6().toString().c_str());
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||||
@@ -413,13 +442,13 @@ static void WiFiEvent(WiFiEvent_t event)
|
|||||||
case ARDUINO_EVENT_WIFI_AP_START:
|
case ARDUINO_EVENT_WIFI_AP_START:
|
||||||
LOG_INFO("WiFi access point started");
|
LOG_INFO("WiFi access point started");
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
digitalWrite(WIFI_LED, HIGH);
|
digitalWrite(WIFI_LED, LOW ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_AP_STOP:
|
case ARDUINO_EVENT_WIFI_AP_STOP:
|
||||||
LOG_INFO("WiFi access point stopped");
|
LOG_INFO("WiFi access point stopped");
|
||||||
#ifdef WIFI_LED
|
#ifdef WIFI_LED
|
||||||
digitalWrite(WIFI_LED, LOW);
|
digitalWrite(WIFI_LED, HIGH ^ WIFI_STATE_ON);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
|
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
|
||||||
@@ -514,4 +543,4 @@ uint8_t getWifiDisconnectReason()
|
|||||||
{
|
{
|
||||||
return wifiDisconnectReason;
|
return wifiDisconnectReason;
|
||||||
}
|
}
|
||||||
#endif // HAS_WIFI
|
#endif // HAS_WIFI
|
||||||
|
|||||||
@@ -773,6 +773,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
|||||||
config.lora = validatedLora;
|
config.lora = validatedLora;
|
||||||
// If we're setting region for the first time, init the region and regenerate the keys
|
// If we're setting region for the first time, init the region and regenerate the keys
|
||||||
if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
|
||||||
|
#if !(MESHTASTIC_EXCLUDE_PKI_KEYGEN || MESHTASTIC_EXCLUDE_PKI)
|
||||||
if (!owner.is_licensed) {
|
if (!owner.is_licensed) {
|
||||||
bool keygenSuccess = false;
|
bool keygenSuccess = false;
|
||||||
if (config.security.private_key.size == 32) {
|
if (config.security.private_key.size == 32) {
|
||||||
@@ -791,6 +792,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
|||||||
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
|
memcpy(owner.public_key.bytes, config.security.public_key.bytes, 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
config.lora.tx_enabled = true;
|
config.lora.tx_enabled = true;
|
||||||
initRegion();
|
initRegion();
|
||||||
if (myRegion->dutyCycle < 100) {
|
if (myRegion->dutyCycle < 100) {
|
||||||
@@ -1225,7 +1227,7 @@ void AdminModule::handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &r
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
conn.has_ethernet = true;
|
conn.has_ethernet = true;
|
||||||
conn.ethernet.has_status = true;
|
conn.ethernet.has_status = true;
|
||||||
if (Ethernet.linkStatus() == LinkON) {
|
if (Ethernet.linkStatus() == LinkON) {
|
||||||
|
|||||||
@@ -314,11 +314,10 @@ void ExternalNotificationModule::stopNow()
|
|||||||
audioThread->stop();
|
audioThread->stop();
|
||||||
#endif
|
#endif
|
||||||
// Turn off all outputs
|
// Turn off all outputs
|
||||||
LOG_INFO("Turning off setExternalStates: ");
|
LOG_INFO("Turning off setExternalStates");
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
setExternalState(i, false);
|
setExternalState(i, false);
|
||||||
externalTurnedOn[i] = 0;
|
externalTurnedOn[i] = 0;
|
||||||
LOG_INFO("%d ", i);
|
|
||||||
}
|
}
|
||||||
setIntervalFromNow(0);
|
setIntervalFromNow(0);
|
||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include "input/TrackballInterruptImpl1.h"
|
#include "input/TrackballInterruptImpl1.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "modules/StatusLEDModule.h"
|
||||||
|
|
||||||
#if !MESHTASTIC_EXCLUDE_I2C
|
#if !MESHTASTIC_EXCLUDE_I2C
|
||||||
#include "input/cardKbI2cImpl.h"
|
#include "input/cardKbI2cImpl.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -119,6 +121,10 @@ void setupModules()
|
|||||||
buzzerFeedbackThread = new BuzzerFeedbackThread();
|
buzzerFeedbackThread = new BuzzerFeedbackThread();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(LED_CHARGE) || defined(LED_PAIRING)
|
||||||
|
statusLEDModule = new StatusLEDModule();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !MESHTASTIC_EXCLUDE_ADMIN
|
#if !MESHTASTIC_EXCLUDE_ADMIN
|
||||||
adminModule = new AdminModule();
|
adminModule = new AdminModule();
|
||||||
#endif
|
#endif
|
||||||
@@ -175,12 +181,13 @@ void setupModules()
|
|||||||
// new ReplyModule();
|
// new ReplyModule();
|
||||||
#if (HAS_BUTTON || ARCH_PORTDUINO) && !MESHTASTIC_EXCLUDE_INPUTBROKER
|
#if (HAS_BUTTON || ARCH_PORTDUINO) && !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
|
||||||
|
#ifndef T_LORA_PAGER
|
||||||
rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1();
|
rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1();
|
||||||
if (!rotaryEncoderInterruptImpl1->init()) {
|
if (!rotaryEncoderInterruptImpl1->init()) {
|
||||||
delete rotaryEncoderInterruptImpl1;
|
delete rotaryEncoderInterruptImpl1;
|
||||||
rotaryEncoderInterruptImpl1 = nullptr;
|
rotaryEncoderInterruptImpl1 = nullptr;
|
||||||
}
|
}
|
||||||
#ifdef T_LORA_PAGER
|
#elif defined(T_LORA_PAGER)
|
||||||
// use a special FSM based rotary encoder version for T-LoRa Pager
|
// use a special FSM based rotary encoder version for T-LoRa Pager
|
||||||
rotaryEncoderImpl = new RotaryEncoderImpl();
|
rotaryEncoderImpl = new RotaryEncoderImpl();
|
||||||
if (!rotaryEncoderImpl->init()) {
|
if (!rotaryEncoderImpl->init()) {
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ void NeighborInfoModule::printNodeDBNeighbors()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
|
/* Send our initial owner announcement 35 seconds after we start (to give
|
||||||
|
* network time to setup) */
|
||||||
NeighborInfoModule::NeighborInfoModule()
|
NeighborInfoModule::NeighborInfoModule()
|
||||||
: ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg),
|
: ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg),
|
||||||
concurrency::OSThread("NeighborInfo")
|
concurrency::OSThread("NeighborInfo")
|
||||||
@@ -53,8 +54,8 @@ NeighborInfoModule::NeighborInfoModule()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
|
Collect neighbor info from the nodeDB's history, capping at a maximum number of
|
||||||
Assumes that the neighborInfo packet has been allocated
|
entries and max time Assumes that the neighborInfo packet has been allocated
|
||||||
@returns the number of entries collected
|
@returns the number of entries collected
|
||||||
*/
|
*/
|
||||||
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
|
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
|
||||||
@@ -71,8 +72,8 @@ uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighb
|
|||||||
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (nbr.node_id != my_node_id)) {
|
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (nbr.node_id != my_node_id)) {
|
||||||
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = nbr.node_id;
|
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = nbr.node_id;
|
||||||
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = nbr.snr;
|
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = nbr.snr;
|
||||||
// Note: we don't set the last_rx_time and node_broadcast_intervals_secs here, because we don't want to send this over
|
// Note: we don't set the last_rx_time and node_broadcast_intervals_secs
|
||||||
// the mesh
|
// here, because we don't want to send this over the mesh
|
||||||
neighborInfo->neighbors_count++;
|
neighborInfo->neighbors_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,8 +89,9 @@ void NeighborInfoModule::cleanUpNeighbors()
|
|||||||
uint32_t now = getTime();
|
uint32_t now = getTime();
|
||||||
NodeNum my_node_id = nodeDB->getNodeNum();
|
NodeNum my_node_id = nodeDB->getNodeNum();
|
||||||
for (auto it = neighbors.rbegin(); it != neighbors.rend();) {
|
for (auto it = neighbors.rbegin(); it != neighbors.rend();) {
|
||||||
// We will remove a neighbor if we haven't heard from them in twice the broadcast interval
|
// We will remove a neighbor if we haven't heard from them in twice the
|
||||||
// cannot use isWithinTimespanMs() as it->last_rx_time is seconds since 1970
|
// broadcast interval cannot use isWithinTimespanMs() as it->last_rx_time is
|
||||||
|
// seconds since 1970
|
||||||
if ((now - it->last_rx_time > it->node_broadcast_interval_secs * 2) && (it->node_id != my_node_id)) {
|
if ((now - it->last_rx_time > it->node_broadcast_interval_secs * 2) && (it->node_id != my_node_id)) {
|
||||||
LOG_DEBUG("Remove neighbor with node ID 0x%x", it->node_id);
|
LOG_DEBUG("Remove neighbor with node ID 0x%x", it->node_id);
|
||||||
it = std::vector<meshtastic_Neighbor>::reverse_iterator(
|
it = std::vector<meshtastic_Neighbor>::reverse_iterator(
|
||||||
@@ -132,25 +134,55 @@ int32_t NeighborInfoModule::runOnce()
|
|||||||
return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_neighbor_info_broadcast_secs);
|
return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_neighbor_info_broadcast_secs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meshtastic_MeshPacket *NeighborInfoModule::allocReply()
|
||||||
|
{
|
||||||
|
LOG_INFO("NeighborInfoRequested.");
|
||||||
|
if (lastSentReply && Throttle::isWithinTimespanMs(lastSentReply, 3 * 60 * 1000)) {
|
||||||
|
LOG_DEBUG("Skip Neighbors reply since we sent a reply <3min ago");
|
||||||
|
ignoreRequest = true; // Mark it as ignored for MeshModule
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
meshtastic_NeighborInfo neighborInfo = meshtastic_NeighborInfo_init_zero;
|
||||||
|
collectNeighborInfo(&neighborInfo);
|
||||||
|
|
||||||
|
meshtastic_MeshPacket *reply = allocDataProtobuf(neighborInfo);
|
||||||
|
|
||||||
|
if (reply) {
|
||||||
|
lastSentReply = millis(); // Track when we sent this reply
|
||||||
|
}
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Collect a received neighbor info packet from another node
|
Collect a received neighbor info packet from another node
|
||||||
Pass it to an upper client; do not persist this data on the mesh
|
Pass it to an upper client; do not persist this data on the mesh
|
||||||
*/
|
*/
|
||||||
bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np)
|
bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np)
|
||||||
{
|
{
|
||||||
|
LOG_DEBUG("NeighborInfo: handleReceivedProtobuf");
|
||||||
if (np) {
|
if (np) {
|
||||||
printNeighborInfo("RECEIVED", np);
|
printNeighborInfo("RECEIVED", np);
|
||||||
updateNeighbors(mp, np);
|
// Ignore dummy/interceptable packets: single neighbor with nodeId 0 and snr 0
|
||||||
|
if (np->neighbors_count != 1 || np->neighbors[0].node_id != 0 || np->neighbors[0].snr != 0.0f) {
|
||||||
|
LOG_DEBUG(" Updating neighbours");
|
||||||
|
updateNeighbors(mp, np);
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG(" Ignoring dummy neighbor info packet (single neighbor with nodeId 0, snr 0)");
|
||||||
|
}
|
||||||
} else if (mp.hop_start != 0 && mp.hop_start == mp.hop_limit) {
|
} else if (mp.hop_start != 0 && mp.hop_start == mp.hop_limit) {
|
||||||
|
LOG_DEBUG("Get or create neighbor: %u with snr %f", mp.from, mp.rx_snr);
|
||||||
// If the hopLimit is the same as hopStart, then it is a neighbor
|
// If the hopLimit is the same as hopStart, then it is a neighbor
|
||||||
getOrCreateNeighbor(mp.from, mp.from, 0, mp.rx_snr); // Set the broadcast interval to 0, as we don't know it
|
getOrCreateNeighbor(mp.from, mp.from, 0,
|
||||||
|
mp.rx_snr); // Set the broadcast interval to 0, as we don't know it
|
||||||
}
|
}
|
||||||
// Allow others to handle this packet
|
// Allow others to handle this packet
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copy the content of a current NeighborInfo packet into a new one and update the last_sent_by_id to our NodeNum
|
Copy the content of a current NeighborInfo packet into a new one and update the
|
||||||
|
last_sent_by_id to our NodeNum
|
||||||
*/
|
*/
|
||||||
void NeighborInfoModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n)
|
void NeighborInfoModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n)
|
||||||
{
|
{
|
||||||
@@ -168,8 +200,10 @@ void NeighborInfoModule::resetNeighbors()
|
|||||||
|
|
||||||
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np)
|
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np)
|
||||||
{
|
{
|
||||||
// The last sent ID will be 0 if the packet is from the phone, which we don't count as
|
LOG_DEBUG("updateNeighbors");
|
||||||
// an edge. So we assume that if it's zero, then this packet is from our node.
|
// The last sent ID will be 0 if the packet is from the phone, which we don't
|
||||||
|
// count as an edge. So we assume that if it's zero, then this packet is from
|
||||||
|
// our node.
|
||||||
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
|
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
|
||||||
getOrCreateNeighbor(mp.from, np->last_sent_by_id, np->node_broadcast_interval_secs, mp.rx_snr);
|
getOrCreateNeighbor(mp.from, np->last_sent_by_id, np->node_broadcast_interval_secs, mp.rx_snr);
|
||||||
}
|
}
|
||||||
@@ -188,7 +222,8 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
|
|||||||
// if found, update it
|
// if found, update it
|
||||||
neighbors[i].snr = snr;
|
neighbors[i].snr = snr;
|
||||||
neighbors[i].last_rx_time = getTime();
|
neighbors[i].last_rx_time = getTime();
|
||||||
// Only if this is the original sender, the broadcast interval corresponds to it
|
// Only if this is the original sender, the broadcast interval corresponds
|
||||||
|
// to it
|
||||||
if (originalSender == n && node_broadcast_interval_secs != 0)
|
if (originalSender == n && node_broadcast_interval_secs != 0)
|
||||||
neighbors[i].node_broadcast_interval_secs = node_broadcast_interval_secs;
|
neighbors[i].node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||||
return &neighbors[i];
|
return &neighbors[i];
|
||||||
@@ -200,10 +235,12 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
|
|||||||
new_nbr.node_id = n;
|
new_nbr.node_id = n;
|
||||||
new_nbr.snr = snr;
|
new_nbr.snr = snr;
|
||||||
new_nbr.last_rx_time = getTime();
|
new_nbr.last_rx_time = getTime();
|
||||||
// Only if this is the original sender, the broadcast interval corresponds to it
|
// Only if this is the original sender, the broadcast interval corresponds to
|
||||||
|
// it
|
||||||
if (originalSender == n && node_broadcast_interval_secs != 0)
|
if (originalSender == n && node_broadcast_interval_secs != 0)
|
||||||
new_nbr.node_broadcast_interval_secs = node_broadcast_interval_secs;
|
new_nbr.node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||||
else // Assume the same broadcast interval as us for the neighbor if we don't know it
|
else // Assume the same broadcast interval as us for the neighbor if we don't
|
||||||
|
// know it
|
||||||
new_nbr.node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
new_nbr.node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||||
|
|
||||||
if (neighbors.size() < MAX_NUM_NEIGHBORS) {
|
if (neighbors.size() < MAX_NUM_NEIGHBORS) {
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
|
|||||||
*/
|
*/
|
||||||
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *nb) override;
|
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *nb) override;
|
||||||
|
|
||||||
|
/* Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
||||||
|
* so that subclasses can (optionally) send a response back to the original sender. */
|
||||||
|
virtual meshtastic_MeshPacket *allocReply() override;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
|
* Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
|
||||||
* @return the number of entries collected
|
* @return the number of entries collected
|
||||||
@@ -66,5 +70,8 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
|
|||||||
/* These are for debugging only */
|
/* These are for debugging only */
|
||||||
void printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np);
|
void printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np);
|
||||||
void printNodeDBNeighbors();
|
void printNodeDBNeighbors();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t lastSentReply = 0; // Last time we sent a position reply (used for reply throttling only)
|
||||||
};
|
};
|
||||||
extern NeighborInfoModule *neighborInfoModule;
|
extern NeighborInfoModule *neighborInfoModule;
|
||||||
@@ -64,7 +64,8 @@ SerialModule *serialModule;
|
|||||||
SerialModuleRadio *serialModuleRadio;
|
SerialModuleRadio *serialModuleRadio;
|
||||||
|
|
||||||
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
|
#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \
|
||||||
defined(ELECROW_ThinkNode_M5) || defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE)
|
defined(ELECROW_ThinkNode_M5) || defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE) || defined(ELECROW_ThinkNode_M3) || \
|
||||||
|
defined(MUZI_BASE)
|
||||||
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial")
|
SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial")
|
||||||
{
|
{
|
||||||
api_type = TYPE_SERIAL;
|
api_type = TYPE_SERIAL;
|
||||||
@@ -204,7 +205,7 @@ int32_t SerialModule::runOnce()
|
|||||||
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
|
Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
|
||||||
}
|
}
|
||||||
#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
|
#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
|
||||||
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && !defined(MUZI_BASE)
|
||||||
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
|
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
|
||||||
#ifdef ARCH_RP2040
|
#ifdef ARCH_RP2040
|
||||||
Serial2.setFIFOSize(RX_BUFFER);
|
Serial2.setFIFOSize(RX_BUFFER);
|
||||||
@@ -261,7 +262,7 @@ int32_t SerialModule::runOnce()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
|
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \
|
||||||
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5)
|
!defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && !defined(MUZI_BASE)
|
||||||
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
|
else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) {
|
||||||
processWXSerial();
|
processWXSerial();
|
||||||
|
|
||||||
@@ -536,7 +537,8 @@ ParsedLine parseLine(const char *line)
|
|||||||
void SerialModule::processWXSerial()
|
void SerialModule::processWXSerial()
|
||||||
{
|
{
|
||||||
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
|
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
|
||||||
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5) && !defined(ARCH_STM32WL)
|
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && \
|
||||||
|
!defined(ARCH_STM32WL) && !defined(MUZI_BASE)
|
||||||
static unsigned int lastAveraged = 0;
|
static unsigned int lastAveraged = 0;
|
||||||
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
|
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
|
||||||
static double dir_sum_sin = 0;
|
static double dir_sum_sin = 0;
|
||||||
|
|||||||
94
src/modules/StatusLEDModule.cpp
Normal file
94
src/modules/StatusLEDModule.cpp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include "StatusLEDModule.h"
|
||||||
|
#include "MeshService.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
StatusLEDModule manages the device's status LEDs, updating their states based on power and Bluetooth status.
|
||||||
|
It reflects charging, charged, discharging, and Bluetooth connection states using the appropriate LEDs.
|
||||||
|
*/
|
||||||
|
StatusLEDModule *statusLEDModule;
|
||||||
|
|
||||||
|
StatusLEDModule::StatusLEDModule() : concurrency::OSThread("StatusLEDModule")
|
||||||
|
{
|
||||||
|
bluetoothStatusObserver.observe(&bluetoothStatus->onNewStatus);
|
||||||
|
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
|
||||||
|
{
|
||||||
|
switch (arg->getStatusType()) {
|
||||||
|
case STATUS_TYPE_POWER: {
|
||||||
|
meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)arg;
|
||||||
|
if (powerStatus->getHasUSB()) {
|
||||||
|
power_state = charging;
|
||||||
|
if (powerStatus->getBatteryChargePercent() >= 100) {
|
||||||
|
power_state = charged;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
power_state = discharging;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATUS_TYPE_BLUETOOTH: {
|
||||||
|
meshtastic::BluetoothStatus *bluetoothStatus = (meshtastic::BluetoothStatus *)arg;
|
||||||
|
switch (bluetoothStatus->getConnectionState()) {
|
||||||
|
case meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED: {
|
||||||
|
ble_state = unpaired;
|
||||||
|
PAIRING_LED_starttime = millis();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case meshtastic::BluetoothStatus::ConnectionState::PAIRING: {
|
||||||
|
ble_state = pairing;
|
||||||
|
PAIRING_LED_starttime = millis();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case meshtastic::BluetoothStatus::ConnectionState::CONNECTED: {
|
||||||
|
ble_state = connected;
|
||||||
|
PAIRING_LED_starttime = millis();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t StatusLEDModule::runOnce()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (power_state == charging) {
|
||||||
|
CHARGE_LED_state = !CHARGE_LED_state;
|
||||||
|
} else if (power_state == charged) {
|
||||||
|
CHARGE_LED_state = LED_STATE_ON;
|
||||||
|
} else {
|
||||||
|
CHARGE_LED_state = LED_STATE_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis()) {
|
||||||
|
PAIRING_LED_state = LED_STATE_OFF;
|
||||||
|
} else if (ble_state == unpaired) {
|
||||||
|
if (slowTrack) {
|
||||||
|
PAIRING_LED_state = !PAIRING_LED_state;
|
||||||
|
slowTrack = false;
|
||||||
|
} else {
|
||||||
|
slowTrack = true;
|
||||||
|
}
|
||||||
|
} else if (ble_state == pairing) {
|
||||||
|
PAIRING_LED_state = !PAIRING_LED_state;
|
||||||
|
} else {
|
||||||
|
PAIRING_LED_state = LED_STATE_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LED_CHARGE
|
||||||
|
digitalWrite(LED_CHARGE, CHARGE_LED_state);
|
||||||
|
#endif
|
||||||
|
// digitalWrite(green_LED_PIN, LED_STATE_OFF);
|
||||||
|
#ifdef LED_PAIRING
|
||||||
|
digitalWrite(LED_PAIRING, PAIRING_LED_state);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (my_interval);
|
||||||
|
}
|
||||||
44
src/modules/StatusLEDModule.h
Normal file
44
src/modules/StatusLEDModule.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BluetoothStatus.h"
|
||||||
|
#include "MeshModule.h"
|
||||||
|
#include "PowerStatus.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class StatusLEDModule : private concurrency::OSThread
|
||||||
|
{
|
||||||
|
bool slowTrack = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StatusLEDModule();
|
||||||
|
|
||||||
|
int handleStatusUpdate(const meshtastic::Status *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
unsigned int my_interval = 1000; // interval in millisconds
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
CallbackObserver<StatusLEDModule, const meshtastic::Status *> bluetoothStatusObserver =
|
||||||
|
CallbackObserver<StatusLEDModule, const meshtastic::Status *>(this, &StatusLEDModule::handleStatusUpdate);
|
||||||
|
CallbackObserver<StatusLEDModule, const meshtastic::Status *> powerStatusObserver =
|
||||||
|
CallbackObserver<StatusLEDModule, const meshtastic::Status *>(this, &StatusLEDModule::handleStatusUpdate);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool CHARGE_LED_state = LED_STATE_OFF;
|
||||||
|
bool PAIRING_LED_state = LED_STATE_OFF;
|
||||||
|
|
||||||
|
uint32_t PAIRING_LED_starttime = 0;
|
||||||
|
|
||||||
|
enum PowerState { discharging, charging, charged };
|
||||||
|
|
||||||
|
PowerState power_state = discharging;
|
||||||
|
|
||||||
|
enum BLEState { unpaired, pairing, connected };
|
||||||
|
|
||||||
|
BLEState ble_state = unpaired;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern StatusLEDModule *statusLEDModule;
|
||||||
@@ -134,6 +134,10 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c
|
|||||||
#include "Sensor/TSL2561Sensor.h"
|
#include "Sensor/TSL2561Sensor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __has_include(<BH1750_WE.h>)
|
||||||
|
#include "Sensor/BH1750Sensor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||||
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
||||||
|
|
||||||
@@ -262,6 +266,9 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
|
|||||||
#if __has_include(<SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h>)
|
#if __has_include(<SparkFun_Qwiic_Scale_NAU7802_Arduino_Library.h>)
|
||||||
addSensor<NAU7802Sensor>(i2cScanner, ScanI2C::DeviceType::NAU7802);
|
addSensor<NAU7802Sensor>(i2cScanner, ScanI2C::DeviceType::NAU7802);
|
||||||
#endif
|
#endif
|
||||||
|
#if __has_include(<BH1750_WE.h>)
|
||||||
|
addSensor<BH1750Sensor>(i2cScanner, ScanI2C::DeviceType::BH1750);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ bool AHT10Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
|||||||
// prefer other sensors like bmp280, bmp3xx
|
// prefer other sensors like bmp280, bmp3xx
|
||||||
if (!measurement->variant.environment_metrics.has_temperature) {
|
if (!measurement->variant.environment_metrics.has_temperature) {
|
||||||
measurement->variant.environment_metrics.has_temperature = true;
|
measurement->variant.environment_metrics.has_temperature = true;
|
||||||
measurement->variant.environment_metrics.temperature = temp.temperature;
|
measurement->variant.environment_metrics.temperature = temp.temperature + AHT10_TEMP_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!measurement->variant.environment_metrics.has_relative_humidity) {
|
if (!measurement->variant.environment_metrics.has_relative_humidity) {
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_AHTX0.h>)
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<Adafruit_AHTX0.h>)
|
||||||
|
|
||||||
|
#ifndef AHT10_TEMP_OFFSET
|
||||||
|
#define AHT10_TEMP_OFFSET 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
#include "TelemetrySensor.h"
|
#include "TelemetrySensor.h"
|
||||||
#include <Adafruit_AHTX0.h>
|
#include <Adafruit_AHTX0.h>
|
||||||
|
|||||||
54
src/modules/Telemetry/Sensor/BH1750Sensor.cpp
Normal file
54
src/modules/Telemetry/Sensor/BH1750Sensor.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<BH1750_WE.h>)
|
||||||
|
|
||||||
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
|
#include "BH1750Sensor.h"
|
||||||
|
#include "TelemetrySensor.h"
|
||||||
|
#include <BH1750_WE.h>
|
||||||
|
|
||||||
|
#ifndef BH1750_SENSOR_MODE
|
||||||
|
#define BH1750_SENSOR_MODE BH1750Mode::CHM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BH1750Sensor::BH1750Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BH1750, "BH1750") {}
|
||||||
|
|
||||||
|
bool BH1750Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||||
|
{
|
||||||
|
LOG_INFO("Init sensor: %s with mode %d", sensorName, BH1750_SENSOR_MODE);
|
||||||
|
|
||||||
|
bh1750 = BH1750_WE(bus, dev->address.address);
|
||||||
|
status = bh1750.init();
|
||||||
|
if (!status) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bh1750.setMode(BH1750_SENSOR_MODE);
|
||||||
|
|
||||||
|
initI2CSensor();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BH1750Sensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* An OTH and OTH_2 measurement takes ~120 ms. I suggest to wait
|
||||||
|
140 ms to be on the safe side.
|
||||||
|
An OTL measurement takes about 16 ms. I suggest to wait 20 ms
|
||||||
|
to be on the safe side. */
|
||||||
|
if (BH1750_SENSOR_MODE == BH1750Mode::OTH || BH1750_SENSOR_MODE == BH1750Mode::OTH_2) {
|
||||||
|
bh1750.setMode(BH1750_SENSOR_MODE);
|
||||||
|
delay(140); // wait for measurement to be completed
|
||||||
|
} else if (BH1750_SENSOR_MODE == BH1750Mode::OTL) {
|
||||||
|
bh1750.setMode(BH1750_SENSOR_MODE);
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
measurement->variant.environment_metrics.has_lux = true;
|
||||||
|
float lightIntensity = bh1750.getLux();
|
||||||
|
|
||||||
|
measurement->variant.environment_metrics.lux = lightIntensity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
21
src/modules/Telemetry/Sensor/BH1750Sensor.h
Normal file
21
src/modules/Telemetry/Sensor/BH1750Sensor.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<BH1750_WE.h>)
|
||||||
|
|
||||||
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
|
#include "TelemetrySensor.h"
|
||||||
|
#include <BH1750_WE.h>
|
||||||
|
|
||||||
|
class BH1750Sensor : public TelemetrySensor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
BH1750_WE bh1750;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BH1750Sensor();
|
||||||
|
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||||
|
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -13,7 +13,10 @@ DFRobotGravitySensor::DFRobotGravitySensor() : TelemetrySensor(meshtastic_Teleme
|
|||||||
DFRobotGravitySensor::~DFRobotGravitySensor()
|
DFRobotGravitySensor::~DFRobotGravitySensor()
|
||||||
{
|
{
|
||||||
if (gravity) {
|
if (gravity) {
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
||||||
delete gravity;
|
delete gravity;
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
gravity = nullptr;
|
gravity = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,13 @@ int32_t BMX160Sensor::runOnce()
|
|||||||
void BMX160Sensor::calibrate(uint16_t forSeconds)
|
void BMX160Sensor::calibrate(uint16_t forSeconds)
|
||||||
{
|
{
|
||||||
#if !defined(MESHTASTIC_EXCLUDE_SCREEN)
|
#if !defined(MESHTASTIC_EXCLUDE_SCREEN)
|
||||||
|
sBmx160SensorData_t magAccel;
|
||||||
|
sBmx160SensorData_t gAccel;
|
||||||
LOG_DEBUG("BMX160 calibration started for %is", forSeconds);
|
LOG_DEBUG("BMX160 calibration started for %is", forSeconds);
|
||||||
highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
sensor.getAllData(&magAccel, NULL, &gAccel);
|
||||||
|
highestX = magAccel.x, lowestX = magAccel.x;
|
||||||
|
highestY = magAccel.y, lowestY = magAccel.y;
|
||||||
|
highestZ = magAccel.z, lowestZ = magAccel.z;
|
||||||
|
|
||||||
doCalibration = true;
|
doCalibration = true;
|
||||||
uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided
|
uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided
|
||||||
|
|||||||
@@ -47,6 +47,21 @@ int32_t ICM20948Sensor::runOnce()
|
|||||||
int32_t ICM20948Sensor::runOnce()
|
int32_t ICM20948Sensor::runOnce()
|
||||||
{
|
{
|
||||||
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
|
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
|
||||||
|
#if defined(MUZI_BASE) // temporarily gated to single device due to feature freeze
|
||||||
|
if (screen && !screen->isScreenOn() && !config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
|
||||||
|
if (!isAsleep) {
|
||||||
|
LOG_DEBUG("sleeping IMU");
|
||||||
|
sensor->sleep(true);
|
||||||
|
isAsleep = true;
|
||||||
|
}
|
||||||
|
return MOTION_SENSOR_CHECK_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
if (isAsleep) {
|
||||||
|
sensor->sleep(false);
|
||||||
|
isAsleep = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
float magX = 0, magY = 0, magZ = 0;
|
float magX = 0, magY = 0, magZ = 0;
|
||||||
if (sensor->dataReady()) {
|
if (sensor->dataReady()) {
|
||||||
sensor->getAGMT();
|
sensor->getAGMT();
|
||||||
@@ -156,8 +171,20 @@ int32_t ICM20948Sensor::runOnce()
|
|||||||
void ICM20948Sensor::calibrate(uint16_t forSeconds)
|
void ICM20948Sensor::calibrate(uint16_t forSeconds)
|
||||||
{
|
{
|
||||||
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
|
#if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN
|
||||||
|
LOG_DEBUG("Old calibration data: highestX = %f, lowestX = %f, highestY = %f, lowestY = %f, highestZ = %f, lowestZ = %f",
|
||||||
|
highestX, lowestX, highestY, lowestY, highestZ, lowestZ);
|
||||||
LOG_DEBUG("BMX160 calibration started for %is", forSeconds);
|
LOG_DEBUG("BMX160 calibration started for %is", forSeconds);
|
||||||
highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
if (sensor->dataReady()) {
|
||||||
|
sensor->getAGMT();
|
||||||
|
highestX = sensor->agmt.mag.axes.x;
|
||||||
|
lowestX = sensor->agmt.mag.axes.x;
|
||||||
|
highestY = sensor->agmt.mag.axes.y;
|
||||||
|
lowestY = sensor->agmt.mag.axes.y;
|
||||||
|
highestZ = sensor->agmt.mag.axes.z;
|
||||||
|
lowestZ = sensor->agmt.mag.axes.z;
|
||||||
|
} else {
|
||||||
|
highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
doCalibration = true;
|
doCalibration = true;
|
||||||
uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided
|
uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided
|
||||||
|
|||||||
@@ -82,7 +82,13 @@ class ICM20948Sensor : public MotionSensor
|
|||||||
private:
|
private:
|
||||||
ICM20948Singleton *sensor = nullptr;
|
ICM20948Singleton *sensor = nullptr;
|
||||||
bool showingScreen = false;
|
bool showingScreen = false;
|
||||||
|
#ifdef MUZI_BASE
|
||||||
|
bool isAsleep = false;
|
||||||
|
float highestX = 449.000000, lowestX = -140.000000, highestY = 422.000000, lowestY = -232.000000, highestZ = 749.000000,
|
||||||
|
lowestZ = 98.000000;
|
||||||
|
#else
|
||||||
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ICM20948Sensor(ScanI2C::FoundDevice foundDevice);
|
explicit ICM20948Sensor(ScanI2C::FoundDevice foundDevice);
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ void MotionSensor::wakeScreen()
|
|||||||
{
|
{
|
||||||
if (powerFSM.getState() == &stateDARK) {
|
if (powerFSM.getState() == &stateDARK) {
|
||||||
LOG_DEBUG("Motion wakeScreen detected");
|
LOG_DEBUG("Motion wakeScreen detected");
|
||||||
powerFSM.trigger(EVENT_INPUT);
|
if (config.display.wake_on_tap_or_motion)
|
||||||
|
powerFSM.trigger(EVENT_INPUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,4 +88,4 @@ void MotionSensor::buttonPress() {}
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -692,7 +692,7 @@ void MQTT::publishNodeInfo()
|
|||||||
}
|
}
|
||||||
void MQTT::publishQueuedMessages()
|
void MQTT::publishQueuedMessages()
|
||||||
{
|
{
|
||||||
if (mqttQueue.isEmpty() || !isConnected)
|
if (mqttQueue.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!moduleConfig.mqtt.proxy_to_client_enabled && !isConnected)
|
if (!moduleConfig.mqtt.proxy_to_client_enabled && !isConnected)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if HAS_ETHERNET && !defined(USE_WS5500)
|
#if HAS_ETHERNET && !defined(USE_WS5500) && !defined(USE_CH390D)
|
||||||
#include <EthernetClient.h>
|
#include <EthernetClient.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -57,17 +57,21 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO
|
#define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO
|
||||||
#elif defined(R1_NEO)
|
#elif defined(R1_NEO)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_MUZI_R1_NEO
|
#define HW_VENDOR meshtastic_HardwareModel_MUZI_R1_NEO
|
||||||
|
#elif defined(RAK3401)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_RAK3401
|
||||||
// MAke sure all custom RAK4630 boards are defined before the generic RAK4630
|
// MAke sure all custom RAK4630 boards are defined before the generic RAK4630
|
||||||
#elif defined(RAK4630)
|
#elif defined(RAK4630)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
|
#define HW_VENDOR meshtastic_HardwareModel_RAK4631
|
||||||
#elif defined(RAK3401)
|
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_RAK3401
|
|
||||||
#elif defined(TTGO_T_ECHO)
|
#elif defined(TTGO_T_ECHO)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
|
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO
|
||||||
#elif defined(T_ECHO_LITE)
|
#elif defined(T_ECHO_LITE)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE
|
#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE
|
||||||
#elif defined(ELECROW_ThinkNode_M1)
|
#elif defined(ELECROW_ThinkNode_M1)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
|
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1
|
||||||
|
#elif defined(ELECROW_ThinkNode_M3)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M3
|
||||||
|
#elif defined(ELECROW_ThinkNode_M6)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M6
|
||||||
#elif defined(NANO_G2_ULTRA)
|
#elif defined(NANO_G2_ULTRA)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_NANO_G2_ULTRA
|
#define HW_VENDOR meshtastic_HardwareModel_NANO_G2_ULTRA
|
||||||
#elif defined(CANARYONE)
|
#elif defined(CANARYONE)
|
||||||
@@ -104,6 +108,8 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1
|
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1
|
||||||
#elif defined(HELTEC_MESH_SOLAR)
|
#elif defined(HELTEC_MESH_SOLAR)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_SOLAR
|
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_SOLAR
|
||||||
|
#elif defined(MUZI_BASE)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN
|
||||||
#else
|
#else
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN
|
#define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN
|
||||||
#endif
|
#endif
|
||||||
@@ -128,7 +134,9 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PIN_LED1
|
||||||
#define LED_PIN PIN_LED1 // LED1 on nrf52840-DK
|
#define LED_PIN PIN_LED1 // LED1 on nrf52840-DK
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PIN_BUTTON1
|
#ifdef PIN_BUTTON1
|
||||||
#define BUTTON_PIN PIN_BUTTON1
|
#define BUTTON_PIN PIN_BUTTON1
|
||||||
|
|||||||
@@ -4,6 +4,14 @@
|
|||||||
#include <InternalFileSystem.h>
|
#include <InternalFileSystem.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
|
||||||
|
#define APP_WATCHDOG_SECS 90
|
||||||
|
#define NRFX_WDT_ENABLED 1
|
||||||
|
#define NRFX_WDT0_ENABLED 1
|
||||||
|
#define NRFX_WDT_CONFIG_NO_IRQ 1
|
||||||
|
#include <nrfx_wdt.c>
|
||||||
|
#include <nrfx_wdt.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ble_gap.h>
|
#include <ble_gap.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
@@ -14,11 +22,22 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "meshUtils.h"
|
#include "meshUtils.h"
|
||||||
|
#include "power.h"
|
||||||
|
|
||||||
|
#include <hal/nrf_lpcomp.h>
|
||||||
|
|
||||||
#ifdef BQ25703A_ADDR
|
#ifdef BQ25703A_ADDR
|
||||||
#include "BQ25713.h"
|
#include "BQ25713.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Weak empty variant initialization function.
|
||||||
|
// May be redefined by variant files.
|
||||||
|
void variant_shutdown() __attribute__((weak));
|
||||||
|
void variant_shutdown() {}
|
||||||
|
|
||||||
|
static nrfx_wdt_t nrfx_wdt = NRFX_WDT_INSTANCE(0);
|
||||||
|
static nrfx_wdt_channel_id nrfx_wdt_channel_id_nrf52_main;
|
||||||
|
|
||||||
static inline void debugger_break(void)
|
static inline void debugger_break(void)
|
||||||
{
|
{
|
||||||
__asm volatile("bkpt #0x01\n\t"
|
__asm volatile("bkpt #0x01\n\t"
|
||||||
@@ -202,6 +221,15 @@ void checkSDEvents()
|
|||||||
|
|
||||||
void nrf52Loop()
|
void nrf52Loop()
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
static bool watchdog_running = false;
|
||||||
|
if (!watchdog_running) {
|
||||||
|
nrfx_wdt_enable(&nrfx_wdt);
|
||||||
|
watchdog_running = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nrfx_wdt_channel_feed(&nrfx_wdt, nrfx_wdt_channel_id_nrf52_main);
|
||||||
|
|
||||||
checkSDEvents();
|
checkSDEvents();
|
||||||
reportLittleFSCorruptionOnce();
|
reportLittleFSCorruptionOnce();
|
||||||
}
|
}
|
||||||
@@ -269,6 +297,22 @@ void nrf52Setup()
|
|||||||
LOG_DEBUG("Set random seed %u", seed.seed32);
|
LOG_DEBUG("Set random seed %u", seed.seed32);
|
||||||
randomSeed(seed.seed32);
|
randomSeed(seed.seed32);
|
||||||
nRFCrypto.end();
|
nRFCrypto.end();
|
||||||
|
|
||||||
|
// Set up nrfx watchdog. Do not enable the watchdog yet (we do that
|
||||||
|
// the first time through the main loop), so that other threads can
|
||||||
|
// allocate their own wdt channel to protect themselves from hangs.
|
||||||
|
nrfx_wdt_config_t wdt0_config = {
|
||||||
|
.behaviour = NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT, .reload_value = APP_WATCHDOG_SECS * 1000,
|
||||||
|
// Note: Not using wdt interrupts.
|
||||||
|
// .interrupt_priority = NRFX_WDT_DEFAULT_CONFIG_IRQ_PRIORITY
|
||||||
|
};
|
||||||
|
nrfx_err_t r = nrfx_wdt_init(&nrfx_wdt, &wdt0_config,
|
||||||
|
nullptr // Watchdog event handler, not used, we just reset.
|
||||||
|
);
|
||||||
|
assert(r == NRFX_SUCCESS);
|
||||||
|
|
||||||
|
r = nrfx_wdt_channel_alloc(&nrfx_wdt, &nrfx_wdt_channel_id_nrf52_main);
|
||||||
|
assert(r == NRFX_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpuDeepSleep(uint32_t msecToWake)
|
void cpuDeepSleep(uint32_t msecToWake)
|
||||||
@@ -352,6 +396,7 @@ void cpuDeepSleep(uint32_t msecToWake)
|
|||||||
NRF_GPIO->DIRCLR = (1 << pin);
|
NRF_GPIO->DIRCLR = (1 << pin);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
variant_shutdown();
|
||||||
|
|
||||||
// Sleepy trackers or sensors can low power "sleep"
|
// Sleepy trackers or sensors can low power "sleep"
|
||||||
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event
|
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event
|
||||||
@@ -389,6 +434,23 @@ void cpuDeepSleep(uint32_t msecToWake)
|
|||||||
nrf_gpio_cfg_sense_set(BUTTON_PIN, sense); // Apply SENSE to wake up the device from the deep sleep
|
nrf_gpio_cfg_sense_set(BUTTON_PIN, sense); // Apply SENSE to wake up the device from the deep sleep
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BATTERY_LPCOMP_INPUT
|
||||||
|
// Wake up if power rises again
|
||||||
|
nrf_lpcomp_config_t c;
|
||||||
|
c.reference = BATTERY_LPCOMP_THRESHOLD;
|
||||||
|
c.detection = NRF_LPCOMP_DETECT_UP;
|
||||||
|
c.hyst = NRF_LPCOMP_HYST_NOHYST;
|
||||||
|
nrf_lpcomp_configure(NRF_LPCOMP, &c);
|
||||||
|
nrf_lpcomp_input_select(NRF_LPCOMP, BATTERY_LPCOMP_INPUT);
|
||||||
|
nrf_lpcomp_enable(NRF_LPCOMP);
|
||||||
|
|
||||||
|
battery_adcEnable();
|
||||||
|
|
||||||
|
nrf_lpcomp_task_trigger(NRF_LPCOMP, NRF_LPCOMP_TASK_START);
|
||||||
|
while (!nrf_lpcomp_event_check(NRF_LPCOMP, NRF_LPCOMP_EVENT_READY))
|
||||||
|
;
|
||||||
|
#endif
|
||||||
|
|
||||||
auto ok = sd_power_system_off();
|
auto ok = sd_power_system_off();
|
||||||
if (ok != NRF_SUCCESS) {
|
if (ok != NRF_SUCCESS) {
|
||||||
LOG_ERROR("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!");
|
LOG_ERROR("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!");
|
||||||
@@ -420,4 +482,4 @@ void enterDfuMode()
|
|||||||
#else
|
#else
|
||||||
enterUf2Dfu();
|
enterUf2Dfu();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ bool yamlOnly = false;
|
|||||||
|
|
||||||
const char *argp_program_version = optstr(APP_VERSION);
|
const char *argp_program_version = optstr(APP_VERSION);
|
||||||
|
|
||||||
|
char stdoutBuffer[512];
|
||||||
|
|
||||||
// FIXME - move setBluetoothEnable into a HALPlatform class
|
// FIXME - move setBluetoothEnable into a HALPlatform class
|
||||||
void setBluetoothEnable(bool enable)
|
void setBluetoothEnable(bool enable)
|
||||||
{
|
{
|
||||||
@@ -144,6 +146,20 @@ void getMacAddr(uint8_t *dmac)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string cleanupNameForAutoconf(std::string name)
|
||||||
|
{
|
||||||
|
// Convert spaces -> dashes, lowercase
|
||||||
|
|
||||||
|
std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c) {
|
||||||
|
if (c == ' ') {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
return (char)std::tolower(c);
|
||||||
|
});
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
/** apps run under portduino can optionally define a portduinoSetup() to
|
/** apps run under portduino can optionally define a portduinoSetup() to
|
||||||
* use portduino specific init code (such as gpioBind) to setup portduino on their host machine,
|
* use portduino specific init code (such as gpioBind) to setup portduino on their host machine,
|
||||||
* before running 'arduino' code.
|
* before running 'arduino' code.
|
||||||
@@ -154,6 +170,9 @@ void portduinoSetup()
|
|||||||
std::string gpioChipName = "gpiochip";
|
std::string gpioChipName = "gpiochip";
|
||||||
portduino_config.displayPanel = no_screen;
|
portduino_config.displayPanel = no_screen;
|
||||||
|
|
||||||
|
// Force stdout to be line buffered
|
||||||
|
setvbuf(stdout, stdoutBuffer, _IOLBF, sizeof(stdoutBuffer));
|
||||||
|
|
||||||
if (portduino_config.force_simradio == true) {
|
if (portduino_config.force_simradio == true) {
|
||||||
portduino_config.lora_module = use_simradio;
|
portduino_config.lora_module = use_simradio;
|
||||||
} else if (configPath != nullptr) {
|
} else if (configPath != nullptr) {
|
||||||
@@ -213,6 +232,11 @@ void portduinoSetup()
|
|||||||
// If LoRa `Module: auto` (default in config.yaml),
|
// If LoRa `Module: auto` (default in config.yaml),
|
||||||
// attempt to auto config based on Product Strings
|
// attempt to auto config based on Product Strings
|
||||||
if (portduino_config.lora_module == use_autoconf) {
|
if (portduino_config.lora_module == use_autoconf) {
|
||||||
|
bool found_hat = false;
|
||||||
|
bool found_rak_eeprom = false;
|
||||||
|
bool found_ch341 = false;
|
||||||
|
|
||||||
|
char hat_vendor[96] = {0};
|
||||||
char autoconf_product[96] = {0};
|
char autoconf_product[96] = {0};
|
||||||
// Try CH341
|
// Try CH341
|
||||||
try {
|
try {
|
||||||
@@ -222,21 +246,32 @@ void portduinoSetup()
|
|||||||
ch341Hal->getProductString(autoconf_product, 95);
|
ch341Hal->getProductString(autoconf_product, 95);
|
||||||
delete ch341Hal;
|
delete ch341Hal;
|
||||||
std::cout << "autoconf: Found CH341 device " << autoconf_product << std::endl;
|
std::cout << "autoconf: Found CH341 device " << autoconf_product << std::endl;
|
||||||
|
|
||||||
|
found_ch341 = true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::cout << "autoconf: Could not locate CH341 device" << std::endl;
|
std::cout << "autoconf: Could not locate CH341 device" << std::endl;
|
||||||
}
|
}
|
||||||
// Try Pi HAT+
|
// Try Pi HAT+
|
||||||
if (strlen(autoconf_product) < 6) {
|
if (strlen(autoconf_product) < 6) {
|
||||||
std::cout << "autoconf: Looking for Pi HAT+..." << std::endl;
|
std::cout << "autoconf: Looking for Pi HAT+..." << std::endl;
|
||||||
|
if (access("/proc/device-tree/hat/vendor", R_OK) == 0) {
|
||||||
|
std::ifstream hatVendorFile("/proc/device-tree/hat/vendor");
|
||||||
|
if (hatVendorFile.is_open()) {
|
||||||
|
hatVendorFile.read(hat_vendor, 95);
|
||||||
|
hatVendorFile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (access("/proc/device-tree/hat/product", R_OK) == 0) {
|
if (access("/proc/device-tree/hat/product", R_OK) == 0) {
|
||||||
std::ifstream hatProductFile("/proc/device-tree/hat/product");
|
std::ifstream hatProductFile("/proc/device-tree/hat/product");
|
||||||
if (hatProductFile.is_open()) {
|
if (hatProductFile.is_open()) {
|
||||||
hatProductFile.read(autoconf_product, 95);
|
hatProductFile.read(autoconf_product, 95);
|
||||||
hatProductFile.close();
|
hatProductFile.close();
|
||||||
}
|
}
|
||||||
std::cout << "autoconf: Found Pi HAT+ " << autoconf_product << " at /proc/device-tree/hat/product" << std::endl;
|
std::cout << "autoconf: Found Pi HAT+ " << hat_vendor << " " << autoconf_product << " at /proc/device-tree/hat"
|
||||||
|
<< std::endl;
|
||||||
|
found_hat = true;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "autoconf: Could not locate Pi HAT+ at /proc/device-tree/hat/product" << std::endl;
|
std::cout << "autoconf: Could not locate Pi HAT+ at /proc/device-tree/hat" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// attempt to load autoconf data from an EEPROM on 0x50
|
// attempt to load autoconf data from an EEPROM on 0x50
|
||||||
@@ -292,6 +327,7 @@ void portduinoSetup()
|
|||||||
autoconf_product[0] = 0x0;
|
autoconf_product[0] = 0x0;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "autoconf: Found eeprom data " << autoconf_raw << std::endl;
|
std::cout << "autoconf: Found eeprom data " << autoconf_raw << std::endl;
|
||||||
|
found_rak_eeprom = true;
|
||||||
if (mac_start != nullptr) {
|
if (mac_start != nullptr) {
|
||||||
std::cout << "autoconf: Found mac data " << mac_start << std::endl;
|
std::cout << "autoconf: Found mac data " << mac_start << std::endl;
|
||||||
if (strlen(mac_start) == 12)
|
if (strlen(mac_start) == 12)
|
||||||
@@ -320,12 +356,29 @@ void portduinoSetup()
|
|||||||
if (strlen(autoconf_product) > 0) {
|
if (strlen(autoconf_product) > 0) {
|
||||||
// From configProducts map in PortduinoGlue.h
|
// From configProducts map in PortduinoGlue.h
|
||||||
std::string product_config = "";
|
std::string product_config = "";
|
||||||
try {
|
|
||||||
|
if (configProducts.find(autoconf_product) != configProducts.end()) {
|
||||||
product_config = configProducts.at(autoconf_product);
|
product_config = configProducts.at(autoconf_product);
|
||||||
} catch (std::out_of_range &e) {
|
} else {
|
||||||
std::cerr << "autoconf: Unable to find config for " << autoconf_product << std::endl;
|
if (found_hat) {
|
||||||
exit(EXIT_FAILURE);
|
product_config =
|
||||||
|
cleanupNameForAutoconf("lora-hat-" + std::string(hat_vendor) + "-" + autoconf_product + ".yaml");
|
||||||
|
} else if (found_ch341) {
|
||||||
|
product_config = cleanupNameForAutoconf("lora-usb-" + std::string(autoconf_product) + ".yaml");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't try to automatically find config for a device with RAK eeprom.
|
||||||
|
if (found_rak_eeprom) {
|
||||||
|
std::cerr << "autoconf: Found unknown RAK product " << autoconf_product << std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (access((portduino_config.available_directory + product_config).c_str(), R_OK) != 0) {
|
||||||
|
std::cerr << "autoconf: Unable to find config for " << autoconf_product << "(tried " << product_config << ")"
|
||||||
|
<< std::endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadConfig((portduino_config.available_directory + product_config).c_str())) {
|
if (loadConfig((portduino_config.available_directory + product_config).c_str())) {
|
||||||
std::cout << "autoconf: Using " << product_config << " as config file for " << autoconf_product << std::endl;
|
std::cout << "autoconf: Using " << product_config << " as config file for " << autoconf_product << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -26,3 +26,31 @@ void getMacAddr(uint8_t *dmac)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cpuDeepSleep(uint32_t msecToWake) {}
|
void cpuDeepSleep(uint32_t msecToWake) {}
|
||||||
|
|
||||||
|
// Hacks to force more code and data out.
|
||||||
|
|
||||||
|
// By default __assert_func uses fiprintf which pulls in stdio.
|
||||||
|
extern "C" void __wrap___assert_func(const char *, int, const char *, const char *)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default strerror has a lot of strings we probably don't use. Make it return an empty string instead.
|
||||||
|
char empty = 0;
|
||||||
|
extern "C" char *__wrap_strerror(int)
|
||||||
|
{
|
||||||
|
return ∅
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MESHTASTIC_EXCLUDE_TZ
|
||||||
|
struct _reent;
|
||||||
|
|
||||||
|
// Even if you don't use timezones, mktime will try to set the timezone anyway with _tzset_unlocked(), which pulls in scanf and
|
||||||
|
// friends. The timezone is initialized to UTC by default.
|
||||||
|
extern "C" void __wrap__tzset_unlocked_r(struct _reent *reent_ptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
#define OCV_ARRAY 4200, 3876, 3826, 3763, 3713, 3660, 3573, 3485, 3422, 3359, 3300
|
#define OCV_ARRAY 4200, 3876, 3826, 3763, 3713, 3660, 3573, 3485, 3422, 3359, 3300
|
||||||
#elif defined(SEEED_SOLAR_NODE)
|
#elif defined(SEEED_SOLAR_NODE)
|
||||||
#define OCV_ARRAY 4200, 3986, 3922, 3812, 3734, 3645, 3527, 3420, 3281, 3087, 2786
|
#define OCV_ARRAY 4200, 3986, 3922, 3812, 3734, 3645, 3527, 3420, 3281, 3087, 2786
|
||||||
#elif defined(R1_NEO)
|
#elif defined(WISMESH_TAG)
|
||||||
#define OCV_ARRAY 4330, 4292, 4254, 4216, 4178, 4140, 4102, 4064, 4026, 3988, 3950
|
#define OCV_ARRAY 4240, 4112, 4029, 3970, 3906, 3846, 3824, 3802, 3776, 3650, 3072
|
||||||
#else // LiIon
|
#else // LiIon
|
||||||
#define OCV_ARRAY 4190, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100
|
#define OCV_ARRAY 4190, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100
|
||||||
#endif
|
#endif
|
||||||
@@ -138,10 +138,12 @@ class Power : private concurrency::OSThread
|
|||||||
void reboot();
|
void reboot();
|
||||||
// open circuit voltage lookup table
|
// open circuit voltage lookup table
|
||||||
uint8_t low_voltage_counter;
|
uint8_t low_voltage_counter;
|
||||||
int32_t lastLogTime = 0;
|
uint32_t lastLogTime = 0;
|
||||||
#ifdef DEBUG_HEAP
|
#ifdef DEBUG_HEAP
|
||||||
uint32_t lastheap;
|
uint32_t lastheap;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void battery_adcEnable();
|
||||||
|
|
||||||
extern Power *power;
|
extern Power *power;
|
||||||
|
|||||||
@@ -56,5 +56,6 @@
|
|||||||
// "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME",
|
// "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME",
|
||||||
// "USERPREFS_RINGTONE_NAG_SECS": "60",
|
// "USERPREFS_RINGTONE_NAG_SECS": "60",
|
||||||
"USERPREFS_RINGTONE_RTTTL": "24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p",
|
"USERPREFS_RINGTONE_RTTTL": "24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p",
|
||||||
|
// "USERPREFS_NETWORK_IPV6_ENABLED": "1",
|
||||||
"USERPREFS_TZ_STRING": "tzplaceholder "
|
"USERPREFS_TZ_STRING": "tzplaceholder "
|
||||||
}
|
}
|
||||||
|
|||||||
26
variants/esp32s3/ELECROW-ThinkNode-G3/pins_arduino.h
Normal file
26
variants/esp32s3/ELECROW-ThinkNode-G3/pins_arduino.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef Pins_Arduino_h
|
||||||
|
#define Pins_Arduino_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define USB_VID 0x303a
|
||||||
|
#define USB_PID 0x1001
|
||||||
|
|
||||||
|
// The default Wire will be mapped to PMU and RTC
|
||||||
|
static const uint8_t SDA = 17;
|
||||||
|
static const uint8_t SCL = 18;
|
||||||
|
|
||||||
|
// Default SPI will be mapped to Radio
|
||||||
|
static const uint8_t SS = 39;
|
||||||
|
static const uint8_t MOSI = 40;
|
||||||
|
static const uint8_t MISO = 41;
|
||||||
|
static const uint8_t SCK = 42;
|
||||||
|
|
||||||
|
// #define SPI_MOSI (11)
|
||||||
|
// #define SPI_SCK (10)
|
||||||
|
// #define SPI_MISO (9)
|
||||||
|
// #define SPI_CS (12)
|
||||||
|
|
||||||
|
// #define SDCARD_CS SPI_CS
|
||||||
|
|
||||||
|
#endif /* Pins_Arduino_h */
|
||||||
22
variants/esp32s3/ELECROW-ThinkNode-G3/platformio.ini
Normal file
22
variants/esp32s3/ELECROW-ThinkNode-G3/platformio.ini
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[env:thinknode_g3]
|
||||||
|
extends = esp32s3_base
|
||||||
|
board = ESP32-S3-WROOM-1-N4
|
||||||
|
board_build.psram_type = opi
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
${esp32s3_base.build_flags}
|
||||||
|
-D ELECROW_ThinkNode_G3
|
||||||
|
-D HAS_UDP_MULTICAST=1
|
||||||
|
-D BOARD_HAS_PSRAM
|
||||||
|
-D PRIVATE_HW
|
||||||
|
# -D CONFIG_ETH_ENABLED=1
|
||||||
|
# -D CONFIG_ETH_USE_ESP32_EMAC=1
|
||||||
|
-I variants/esp32s3/ELECROW-ThinkNode-G3
|
||||||
|
-mfix-esp32-psram-cache-issue
|
||||||
|
|
||||||
|
lib_ignore =
|
||||||
|
Ethernet
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${esp32s3_base.lib_deps}
|
||||||
|
# file://../ESP32-CH390/ESP32-CH390-1.0.1.tar.gz
|
||||||
36
variants/esp32s3/ELECROW-ThinkNode-G3/variant.h
Normal file
36
variants/esp32s3/ELECROW-ThinkNode-G3/variant.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#define HAS_GPS 0
|
||||||
|
#define HAS_WIRE 0
|
||||||
|
#define I2C_NO_RESCAN
|
||||||
|
|
||||||
|
#define WIFI_LED 5
|
||||||
|
#define WIFI_STATE_ON 0
|
||||||
|
|
||||||
|
#define LED_PIN 6 // The blue LORA LED
|
||||||
|
#define LED_STATE_ON 0
|
||||||
|
#define BUTTON_PIN 4 // the external user button of the device, BOOT and RESET are not accessible without opening it up.
|
||||||
|
|
||||||
|
#define USE_SX1262
|
||||||
|
#define LORA_SCK 42
|
||||||
|
#define LORA_MISO 41
|
||||||
|
#define LORA_MOSI 40
|
||||||
|
#define LORA_CS 39
|
||||||
|
#define LORA_RESET 21
|
||||||
|
|
||||||
|
#define SX126X_CS LORA_CS
|
||||||
|
#define SX126X_DIO1 15
|
||||||
|
#define SX126X_BUSY 47
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
#define SX126X_DIO2_AS_RF_SWITCH
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||||
|
#define PIN_POWER_EN 45
|
||||||
|
|
||||||
|
// #define HAS_ETHERNET 1
|
||||||
|
// #define USE_CH390D 1 // this driver uses the same stack as the ESP32 Wifi driver
|
||||||
|
|
||||||
|
// #define ETH_MISO_PIN 47
|
||||||
|
// #define ETH_MOSI_PIN 21
|
||||||
|
// #define ETH_SCLK_PIN 48
|
||||||
|
// #define ETH_CS_PIN 45
|
||||||
|
// #define ETH_INT_PIN 14
|
||||||
|
// #define ETH_RST_PIN -1
|
||||||
|
// #define ETH_ADDR 1
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user