diff --git a/firmware-patch.diff b/firmware-patch.diff index f32dc87..e875d68 100644 --- a/firmware-patch.diff +++ b/firmware-patch.diff @@ -1,681 +1,3 @@ -diff --git a/.github/actions/setup-base/action.yml b/.github/actions/setup-base/action.yml -index f6c1fd80c..80f5c6855 100644 ---- a/.github/actions/setup-base/action.yml -+++ b/.github/actions/setup-base/action.yml -@@ -5,7 +5,7 @@ runs: - using: composite - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: recursive - ref: ${{github.event.pull_request.head.ref}} -diff --git a/.github/workflows/build_debian_src.yml b/.github/workflows/build_debian_src.yml -index d36e7fea1..d7d26f0e8 100644 ---- a/.github/workflows/build_debian_src.yml -+++ b/.github/workflows/build_debian_src.yml -@@ -24,7 +24,7 @@ jobs: - runs-on: ubuntu-24.04 - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: recursive - path: meshtasticd -diff --git a/.github/workflows/build_firmware.yml b/.github/workflows/build_firmware.yml -index 57c1e72c7..9ac84c23e 100644 ---- a/.github/workflows/build_firmware.yml -+++ b/.github/workflows/build_firmware.yml -@@ -22,7 +22,7 @@ jobs: - outputs: - artifact-id: ${{ steps.upload.outputs.artifact-id }} - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - with: - submodules: recursive - ref: ${{github.event.pull_request.head.ref}} -diff --git a/.github/workflows/build_one_arch.yml b/.github/workflows/build_one_arch.yml -deleted file mode 100644 -index 6d5462c93..000000000 ---- a/.github/workflows/build_one_arch.yml -+++ /dev/null -@@ -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 }} -diff --git a/.github/workflows/build_one_target.yml b/.github/workflows/build_one_target.yml -index 46362a629..e4b332a06 100644 ---- a/.github/workflows/build_one_target.yml -+++ b/.github/workflows/build_one_target.yml -@@ -15,7 +15,6 @@ on: - - rp2040 - - rp2350 - - stm32 -- - native - target: - type: string - required: false -@@ -42,10 +41,9 @@ jobs: - - rp2040 - - rp2350 - - stm32 -- - runs-on: ubuntu-24.04 - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: 3.x -@@ -60,13 +58,13 @@ jobs: - echo "Arch: ${{matrix.arch}}" >> $GITHUB_STEP_SUMMARY - echo "Ref: $GITHUB_REF" >> $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: - if: ${{ inputs.target != '' }} - runs-on: ubuntu-latest - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - - name: Get release version string - run: | - echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT -@@ -87,25 +85,6 @@ jobs: - pio_env: ${{ inputs.target }} - 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: - permissions: - contents: write -@@ -114,7 +93,7 @@ jobs: - needs: [version, build] - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} -diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml -index 26a9cff18..8d19af894 100644 ---- a/.github/workflows/docker_build.yml -+++ b/.github/workflows/docker_build.yml -@@ -47,7 +47,7 @@ jobs: - runs-on: ${{ inputs.runs-on }} - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: recursive - ref: ${{github.event.pull_request.head.ref}} -diff --git a/.github/workflows/docker_manifest.yml b/.github/workflows/docker_manifest.yml -index 20b9ceee6..396ddb68e 100644 ---- a/.github/workflows/docker_manifest.yml -+++ b/.github/workflows/docker_manifest.yml -@@ -83,7 +83,7 @@ jobs: - runs-on: ubuntu-24.04 - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: recursive - ref: ${{github.event.pull_request.head.ref}} -diff --git a/.github/workflows/hook_copr.yml b/.github/workflows/hook_copr.yml -index 2204cc02c..eb4ebc57b 100644 ---- a/.github/workflows/hook_copr.yml -+++ b/.github/workflows/hook_copr.yml -@@ -19,7 +19,7 @@ jobs: - runs-on: ubuntu-24.04 - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: recursive - ref: ${{ github.ref }} -diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml -index 7ea033d55..38373a2fc 100644 ---- a/.github/workflows/main_matrix.yml -+++ b/.github/workflows/main_matrix.yml -@@ -35,7 +35,7 @@ jobs: - - check - runs-on: ubuntu-24.04 - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: 3.x -@@ -59,7 +59,7 @@ jobs: - version: - runs-on: ubuntu-latest - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - - name: Get release version string - run: | - echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT -@@ -81,7 +81,7 @@ jobs: - runs-on: ubuntu-latest - if: ${{ github.event_name != 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }} - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - - name: Build base - id: base - uses: ./.github/actions/setup-base -@@ -163,7 +163,7 @@ jobs: - needs: [version, build] - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} -@@ -242,7 +242,7 @@ jobs: - - package-pio-deps-native-tft - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Setup Python - uses: actions/setup-python@v6 -@@ -311,7 +311,7 @@ jobs: - needs: [release-artifacts, version] - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Setup Python - uses: actions/setup-python@v6 -@@ -366,7 +366,7 @@ jobs: - esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32 - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Setup Python - uses: actions/setup-python@v6 -diff --git a/.github/workflows/merge_queue.yml b/.github/workflows/merge_queue.yml -index 6d69258c9..154b230c7 100644 ---- a/.github/workflows/merge_queue.yml -+++ b/.github/workflows/merge_queue.yml -@@ -17,7 +17,7 @@ jobs: - - check - runs-on: ubuntu-24.04 - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: 3.x -@@ -40,7 +40,7 @@ jobs: - version: - runs-on: ubuntu-latest - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - - name: Get release version string - run: | - echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT -@@ -62,7 +62,7 @@ jobs: - runs-on: ubuntu-latest - if: ${{ github.event_name != 'workflow_dispatch' }} - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - - name: Build base - id: base - uses: ./.github/actions/setup-base -@@ -142,7 +142,7 @@ jobs: - needs: [version, build] - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} -@@ -221,7 +221,7 @@ jobs: - - package-pio-deps-native-tft - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Setup Python - uses: actions/setup-python@v6 -@@ -290,7 +290,7 @@ jobs: - needs: [release-artifacts, version] - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Setup Python - uses: actions/setup-python@v6 -@@ -345,7 +345,7 @@ jobs: - esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32 - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Setup Python - uses: actions/setup-python@v6 -diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml -index f26073ec4..045e94895 100644 ---- a/.github/workflows/nightly.yml -+++ b/.github/workflows/nightly.yml -@@ -14,7 +14,7 @@ jobs: - - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Trunk Check - uses: trunk-io/trunk-action@v1 -@@ -31,7 +31,7 @@ jobs: - pull-requests: write # For trunk to create PRs - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Trunk Upgrade - uses: trunk-io/trunk-action/upgrade@v1 -diff --git a/.github/workflows/package_obs.yml b/.github/workflows/package_obs.yml -index b8a829d9a..2b202ed95 100644 ---- a/.github/workflows/package_obs.yml -+++ b/.github/workflows/package_obs.yml -@@ -34,7 +34,7 @@ jobs: - needs: build-debian-src - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: recursive - path: meshtasticd -diff --git a/.github/workflows/package_pio_deps.yml b/.github/workflows/package_pio_deps.yml -index c52dfe348..cb10a79f3 100644 ---- a/.github/workflows/package_pio_deps.yml -+++ b/.github/workflows/package_pio_deps.yml -@@ -24,7 +24,7 @@ jobs: - runs-on: ubuntu-24.04 - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: recursive - ref: ${{github.event.pull_request.head.ref}} -diff --git a/.github/workflows/package_ppa.yml b/.github/workflows/package_ppa.yml -index 2d6c257e6..2e3278041 100644 ---- a/.github/workflows/package_ppa.yml -+++ b/.github/workflows/package_ppa.yml -@@ -32,7 +32,7 @@ jobs: - needs: build-debian-src - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: recursive - path: meshtasticd -diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml -index c3a964e04..048186538 100644 ---- a/.github/workflows/pr_tests.yml -+++ b/.github/workflows/pr_tests.yml -@@ -40,7 +40,7 @@ jobs: - checks: write - pull-requests: write - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - with: - submodules: recursive - -diff --git a/.github/workflows/release_channels.yml b/.github/workflows/release_channels.yml -index 4e5a48dfe..f21b13ee1 100644 ---- a/.github/workflows/release_channels.yml -+++ b/.github/workflows/release_channels.yml -@@ -60,7 +60,7 @@ jobs: - shell: bash - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - # Always use master branch for version bumps - ref: master -diff --git a/.github/workflows/sec_sast_semgrep_cron.yml b/.github/workflows/sec_sast_semgrep_cron.yml -index dfb828bf6..d044f9038 100644 ---- a/.github/workflows/sec_sast_semgrep_cron.yml -+++ b/.github/workflows/sec_sast_semgrep_cron.yml -@@ -21,7 +21,7 @@ jobs: - steps: - # step 1 - - name: clone application source code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - # step 2 - - name: full scan -diff --git a/.github/workflows/sec_sast_semgrep_pull.yml b/.github/workflows/sec_sast_semgrep_pull.yml -index e93b2ae8b..e9b4108a1 100644 ---- a/.github/workflows/sec_sast_semgrep_pull.yml -+++ b/.github/workflows/sec_sast_semgrep_pull.yml -@@ -13,7 +13,7 @@ jobs: - steps: - # step 1 - - name: clone application source code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - fetch-depth: 0 - -diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml -index 591d52bd0..a2328022e 100644 ---- a/.github/workflows/test_native.yml -+++ b/.github/workflows/test_native.yml -@@ -14,7 +14,7 @@ jobs: - name: Native Simulator Tests - runs-on: ubuntu-latest - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} -@@ -70,7 +70,7 @@ jobs: - name: Native PlatformIO Tests - runs-on: ubuntu-latest - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} -@@ -127,7 +127,7 @@ jobs: - - platformio-tests - if: always() - steps: -- - uses: actions/checkout@v5 -+ - uses: actions/checkout@v6 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} -diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml -index 1ec435512..4a97853e2 100644 ---- a/.github/workflows/tests.yml -+++ b/.github/workflows/tests.yml -@@ -20,7 +20,7 @@ jobs: - runs-on: test-runner - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - # - uses: actions/setup-python@v5 - # with: -diff --git a/.github/workflows/trunk_annotate_pr.yml b/.github/workflows/trunk_annotate_pr.yml -index 23dcf8d09..59ab25c28 100644 ---- a/.github/workflows/trunk_annotate_pr.yml -+++ b/.github/workflows/trunk_annotate_pr.yml -@@ -18,7 +18,7 @@ jobs: - - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Trunk Check - uses: trunk-io/trunk-action@v1 -diff --git a/.github/workflows/trunk_check.yml b/.github/workflows/trunk_check.yml -index 41731d491..874374fe0 100644 ---- a/.github/workflows/trunk_check.yml -+++ b/.github/workflows/trunk_check.yml -@@ -16,7 +16,7 @@ jobs: - - steps: - - name: Checkout -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - - - name: Trunk Check - uses: trunk-io/trunk-action@v1 -diff --git a/.github/workflows/trunk_format_pr.yml b/.github/workflows/trunk_format_pr.yml -index 51082fc5f..8fa0cc1eb 100644 ---- a/.github/workflows/trunk_format_pr.yml -+++ b/.github/workflows/trunk_format_pr.yml -@@ -15,7 +15,7 @@ jobs: - pull-requests: write - steps: - - name: Checkout repository -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} -diff --git a/.github/workflows/update_protobufs.yml b/.github/workflows/update_protobufs.yml -index c06e06b0a..af0557fda 100644 ---- a/.github/workflows/update_protobufs.yml -+++ b/.github/workflows/update_protobufs.yml -@@ -11,7 +11,7 @@ jobs: - pull-requests: write - steps: - - name: Checkout code -- uses: actions/checkout@v5 -+ uses: actions/checkout@v6 - with: - submodules: true - diff --git a/.gitignore b/.gitignore index cc742c6c1..545b0923a 100644 --- a/.gitignore @@ -693,77 +15,6 @@ index cc742c6c1..545b0923a 100644 +# Ignore Python vendor directory +pyvendor \ No newline at end of file -diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml -index 1fd8790f2..ccb426745 100644 ---- a/.trunk/trunk.yaml -+++ b/.trunk/trunk.yaml -@@ -4,31 +4,31 @@ cli: - plugins: - sources: - - id: trunk -- ref: v1.7.3 -+ ref: v1.7.4 - uri: https://github.com/trunk-io/plugins - lint: - enabled: -- - checkov@3.2.492 -- - renovate@42.5.4 -+ - checkov@3.2.495 -+ - renovate@42.24.1 - - prettier@3.6.2 -- - trufflehog@3.90.13 -+ - trufflehog@3.91.1 - - yamllint@1.37.1 -- - bandit@1.8.6 -+ - bandit@1.9.2 - - trivy@0.67.2 - - taplo@0.10.0 -- - ruff@0.14.4 -+ - ruff@0.14.6 - - isort@7.0.0 -- - markdownlint@0.45.0 -+ - markdownlint@0.46.0 - - oxipng@9.1.5 - - svgo@4.0.0 -- - actionlint@1.7.8 -+ - actionlint@1.7.9 - - flake8@7.3.0 - - hadolint@2.14.0 - - shfmt@3.6.0 - - shellcheck@0.11.0 - - black@25.11.0 - - git-diff-check -- - gitleaks@8.29.0 -+ - gitleaks@8.30.0 - - clang-format@16.0.3 - ignore: - - linters: [ALL] -diff --git a/arch/nrf52/nrf52840.ini b/arch/nrf52/nrf52840.ini -index 5e846b3b7..e13443152 100644 ---- a/arch/nrf52/nrf52840.ini -+++ b/arch/nrf52/nrf52840.ini -@@ -8,7 +8,7 @@ lib_deps = - ${environmental_base.lib_deps} - ${environmental_extra.lib_deps} - # 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. - -diff --git a/arch/stm32/stm32.ini b/arch/stm32/stm32.ini -index 7732533c9..1a9fd10ce 100644 ---- a/arch/stm32/stm32.ini -+++ b/arch/stm32/stm32.ini -@@ -2,7 +2,7 @@ - extends = arduino_base - platform = - # renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32 -- platformio/ststm32@19.3.0 -+ platformio/ststm32@19.4.0 - platform_packages = - # TODO renovate - platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip diff --git a/bin/mpm_pio.py b/bin/mpm_pio.py new file mode 100644 index 000000000..9c000d6e6 @@ -839,129 +90,8 @@ index 000000000..9c000d6e6 + + main() + -diff --git a/boards/ThinkNode-M3.json b/boards/ThinkNode-M3.json -new file mode 100644 -index 000000000..ff21e046a ---- /dev/null -+++ b/boards/ThinkNode-M3.json -@@ -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" -+} -diff --git a/boards/muzi-base.json b/boards/muzi-base.json -new file mode 100644 -index 000000000..5f65c0dc8 ---- /dev/null -+++ b/boards/muzi-base.json -@@ -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 -+ } -+} diff --git a/platformio.ini b/platformio.ini -index d6ff155e4..c775b2aab 100644 +index 1363a63fc..c775b2aab 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,7 +14,9 @@ description = Meshtastic @@ -983,32 +113,6 @@ index d6ff155e4..c775b2aab 100644 -DUSE_THREAD_NAMES -DTINYGPS_OPTION_NO_CUSTOM_FIELDS -DPB_ENABLE_MALLOC=1 -@@ -90,7 +93,7 @@ framework = arduino - lib_deps = - ${env.lib_deps} - # renovate: datasource=custom.pio depName=NonBlockingRTTTL packageName=end2endzone/library/NonBlockingRTTTL -- end2endzone/NonBlockingRTTTL@1.3.0 -+ end2endzone/NonBlockingRTTTL@1.4.0 - build_flags = ${env.build_flags} -Os - build_src_filter = ${env.build_src_filter} - - - -@@ -169,7 +172,7 @@ lib_deps = - # renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master - https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip - # renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226 -- robtillaart/INA226@0.6.4 -+ robtillaart/INA226@0.6.5 - # renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library - sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2 - # renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library -@@ -213,6 +216,6 @@ lib_deps = - # renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master - https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip - # renovate: datasource=custom.pio depName=Sensirion Core packageName=sensirion/library/Sensirion Core -- sensirion/Sensirion Core@0.7.1 -+ sensirion/Sensirion Core@0.7.2 - # renovate: datasource=custom.pio depName=Sensirion I2C SCD4x packageName=sensirion/library/Sensirion I2C SCD4x - sensirion/Sensirion I2C SCD4x@1.1.0 diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 000000000..84e8e8fdf @@ -1162,810 +266,6 @@ index 000000000..e45155ab7 @@ -0,0 +1,2 @@ +../mpm + -diff --git a/src/Power.cpp b/src/Power.cpp -index fa8661d01..7bb8896ce 100644 ---- a/src/Power.cpp -+++ b/src/Power.cpp -@@ -278,6 +278,11 @@ class AnalogBatteryLevel : public HasBatteryLevel - 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); - } - -@@ -455,6 +460,8 @@ class AnalogBatteryLevel : public HasBatteryLevel - } - // if it's not HIGH - check the battery - #endif -+#elif defined(MUZI_BASE) -+ return NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk; - #endif - return getBattVoltage() > chargingVolt; - } -@@ -470,6 +477,8 @@ class AnalogBatteryLevel : public HasBatteryLevel - #endif - #ifdef EXT_CHRG_DETECT - return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value; -+#elif defined(BATTERY_CHARGING_INV) -+ return !digitalRead(BATTERY_CHARGING_INV); - #else - #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(DISABLE_INA_CHARGING_DETECTION) - if (hasINA()) { -@@ -698,11 +707,18 @@ bool Power::setup() - []() { - power->setIntervalFromNow(0); - runASAP = true; -- BaseType_t higherWake = 0; - }, - CHANGE); - #endif -- -+#ifdef BATTERY_CHARGING_INV -+ attachInterrupt( -+ BATTERY_CHARGING_INV, -+ []() { -+ power->setIntervalFromNow(0); -+ runASAP = true; -+ }, -+ CHANGE); -+#endif - enabled = found; - low_voltage_counter = 0; - -@@ -759,6 +775,8 @@ void Power::shutdown() - if (screen) { - #ifdef T_DECK_PRO - screen->showSimpleBanner("Device is powered off.\nConnect USB to start!", 0); // T-Deck Pro has no power button -+#elif defined(USE_EINK) -+ screen->showSimpleBanner("Shutting Down...", 2250); // dismiss after 3 seconds to avoid the banner on the sleep screen - #else - screen->showSimpleBanner("Shutting Down...", 0); // stays on screen - #endif -@@ -1435,7 +1453,7 @@ class LipoCharger : public HasBatteryLevel - /** - * return true if there is an external power source detected - */ -- virtual bool isVbusIn() override { return PPM->getVbusVoltage() > 0; } -+ virtual bool isVbusIn() override { return PPM->isVbusIn(); } - - /** - * return true if the battery is currently charging -diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp -index 322b877ff..67b680233 100644 ---- a/src/PowerFSM.cpp -+++ b/src/PowerFSM.cpp -@@ -57,21 +57,21 @@ static bool isPowered() - - static void sdsEnter() - { -- LOG_DEBUG("State: SDS"); -+ LOG_POWERFSM("State: SDS"); - // FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw - doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, false); - } - - static void lowBattSDSEnter() - { -- LOG_DEBUG("State: Lower batt SDS"); -+ LOG_POWERFSM("State: Lower batt SDS"); - doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false, true); - } - extern Power *power; - - static void shutdownEnter() - { -- LOG_DEBUG("State: SHUTDOWN"); -+ LOG_POWERFSM("State: SHUTDOWN"); - shutdownAtMsec = millis(); - } - -@@ -81,7 +81,7 @@ static uint32_t secsSlept; - - static void lsEnter() - { -- LOG_INFO("lsEnter begin, ls_secs=%u", config.power.ls_secs); -+ LOG_POWERFSM("lsEnter begin, ls_secs=%u", config.power.ls_secs); - if (screen) - screen->setOn(false); - secsSlept = 0; // How long have we been sleeping this time -@@ -155,12 +155,12 @@ static void lsIdle() - - static void lsExit() - { -- LOG_INFO("Exit state: LS"); -+ LOG_POWERFSM("State: lsExit"); - } - - static void nbEnter() - { -- LOG_DEBUG("State: NB"); -+ LOG_POWERFSM("State: nbEnter"); - if (screen) - screen->setOn(false); - #ifdef ARCH_ESP32 -@@ -173,6 +173,7 @@ static void nbEnter() - - static void darkEnter() - { -+ LOG_POWERFSM("State: darkEnter"); - setBluetoothEnable(true); - if (screen) - screen->setOn(false); -@@ -180,7 +181,7 @@ static void darkEnter() - - static void serialEnter() - { -- LOG_DEBUG("State: SERIAL"); -+ LOG_POWERFSM("State: serialEnter"); - setBluetoothEnable(false); - if (screen) { - screen->setOn(true); -@@ -189,13 +190,14 @@ static void serialEnter() - - static void serialExit() - { -+ LOG_POWERFSM("State: serialExit"); - // Turn bluetooth back on when we leave serial stream API - setBluetoothEnable(true); - } - - static void powerEnter() - { -- // LOG_DEBUG("State: POWER"); -+ LOG_POWERFSM("State: powerEnter"); - if (!isPowered()) { - // If we got here, we are in the wrong state - we should be in powered, let that state handle things - LOG_INFO("Loss of power in Powered"); -@@ -210,6 +212,7 @@ static void powerEnter() - - static void powerIdle() - { -+ // LOG_POWERFSM("State: powerIdle"); // very chatty - if (!isPowered()) { - // If we got here, we are in the wrong state - LOG_INFO("Loss of power in Powered"); -@@ -219,14 +222,13 @@ static void powerIdle() - - static void powerExit() - { -- if (screen) -- screen->setOn(true); -+ LOG_POWERFSM("State: powerExit"); - setBluetoothEnable(true); - } - - static void onEnter() - { -- LOG_DEBUG("State: ON"); -+ LOG_POWERFSM("State: onEnter"); - if (screen) - screen->setOn(true); - setBluetoothEnable(true); -@@ -234,6 +236,7 @@ static void onEnter() - - static void onIdle() - { -+ LOG_POWERFSM("State: onIdle"); - if (isPowered()) { - // If we got here, we are in the wrong state - we should be in powered, let that state handle things - powerFSM.trigger(EVENT_POWER_CONNECTED); -@@ -242,7 +245,7 @@ static void onIdle() - - static void bootEnter() - { -- LOG_DEBUG("State: BOOT"); -+ LOG_POWERFSM("State: bootEnter"); - } - - State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN"); -@@ -319,11 +322,6 @@ void PowerFSM_setup() - // if any packet destined for phone arrives, turn on bluetooth at least - powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone"); - -- // Removed 2.7: we don't show the nodes individually for every node on the screen anymore -- // powerFSM.add_transition(&stateNB, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update"); -- // powerFSM.add_transition(&stateDARK, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update"); -- // powerFSM.add_transition(&stateON, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update"); -- - // Show the received text message - powerFSM.add_transition(&stateLS, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text"); - powerFSM.add_transition(&stateNB, &stateON, EVENT_RECEIVED_MSG, NULL, "Received text"); -diff --git a/src/PowerFSM.h b/src/PowerFSM.h -index 6330a5fc6..182ac082a 100644 ---- a/src/PowerFSM.h -+++ b/src/PowerFSM.h -@@ -2,6 +2,12 @@ - - #include "configuration.h" - -+#ifdef PowerFSMDebug -+#define LOG_POWERFSM(...) LOG_DEBUG(__VA_ARGS__) -+#else -+#define LOG_POWERFSM(...) -+#endif -+ - // See sw-design.md for documentation - - #define EVENT_PRESS 1 -diff --git a/src/configuration.h b/src/configuration.h -index 8ec3b2211..d30280d8b 100644 ---- a/src/configuration.h -+++ b/src/configuration.h -@@ -250,8 +250,9 @@ along with this program. If not, see . - // Touchscreen - // ----------------------------------------------------------------------------- - #define FT6336U_ADDR 0x48 --#define CST328_ADDR 0x1A -+#define CST328_ADDR 0x1A // same address as CST226SE - #define CHSC6X_ADDR 0x2E -+#define CST226SE_ADDR_ALT 0x5A - - // ----------------------------------------------------------------------------- - // RAK12035VB Soil Monitor (using RAK12023 up to 3 RAK12035 monitors can be connected) -@@ -396,6 +397,13 @@ along with this program. If not, see . - #define HAS_RGB_LED - #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 - #if defined(PIN_BUTTON2) && !defined(CANCEL_BUTTON_PIN) - #define ALT_BUTTON_PIN PIN_BUTTON2 -diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h -index 55980face..cced980a6 100644 ---- a/src/detect/ScanI2C.h -+++ b/src/detect/ScanI2C.h -@@ -85,7 +85,8 @@ class ScanI2C - DRV2605, - BH1750, - DA217, -- CHSC6X -+ CHSC6X, -+ CST226SE - } DeviceType; - - // typedef uint8_t DeviceAddress; -diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp -index 167728ad3..db269ac64 100644 ---- a/src/detect/ScanI2CTwoWire.cpp -+++ b/src/detect/ScanI2CTwoWire.cpp -@@ -499,7 +499,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) - SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address); - SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address); - SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address); -- SCAN_SIMPLE_CASE(CST328_ADDR, CST328, "CST328", (uint8_t)addr.address); -+ case CST328_ADDR: -+ // Do we have the CST328 or the CST226SE -+ registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xAB), 1); -+ if (registerValue == 0xA9) { -+ type = CST226SE; -+ logFoundDevice("CST226SE", (uint8_t)addr.address); -+ } else { -+ type = CST328; -+ logFoundDevice("CST328", (uint8_t)addr.address); -+ } -+ break; -+ - SCAN_SIMPLE_CASE(CHSC6X_ADDR, CHSC6X, "CHSC6X", (uint8_t)addr.address); - case LTR553ALS_ADDR: - registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x86), 1); // Part ID register -@@ -528,8 +539,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) - #endif - - case MLX90614_ADDR_DEF: -- registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0e), 1); -- if (registerValue == 0x5a) { -+ // Do we have the MLX90614 or the MPR121KB or the CST226SE -+ registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x06), 1); -+ if (registerValue == 0xAB) { -+ type = CST226SE; -+ logFoundDevice("CST226SE", (uint8_t)addr.address); -+ } else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0e), 1) == 0x5a) { - type = MLX90614; - logFoundDevice("MLX90614", (uint8_t)addr.address); - } else { -@@ -547,6 +562,11 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) - case ICM20948_ADDR: // same as BMX160_ADDR - case ICM20948_ADDR_ALT: // same as MPU6050_ADDR - registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); -+#ifdef HAS_ICM20948 -+ type = ICM20948; -+ logFoundDevice("ICM20948", (uint8_t)addr.address); -+ break; -+#endif - if (registerValue == 0xEA) { - type = ICM20948; - logFoundDevice("ICM20948", (uint8_t)addr.address); -diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp -index 0404ae5f8..a61a71dde 100644 ---- a/src/gps/GPS.cpp -+++ b/src/gps/GPS.cpp -@@ -38,14 +38,16 @@ template std::size_t array_count(const T (&)[N]) - return N; - } - --#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) || defined(ARCH_STM32WL) --#if defined(GPS_SERIAL_PORT) --HardwareSerial *GPS::_serial_gps = &GPS_SERIAL_PORT; --#else --HardwareSerial *GPS::_serial_gps = &Serial1; -+#ifndef GPS_SERIAL_PORT -+#define GPS_SERIAL_PORT Serial1 - #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) --SerialUART *GPS::_serial_gps = &Serial1; -+SerialUART *GPS::_serial_gps = &GPS_SERIAL_PORT; - #else - HardwareSerial *GPS::_serial_gps = nullptr; - #endif -@@ -1525,10 +1527,7 @@ GPS *GPS::createGps() - int8_t _rx_gpio = config.position.rx_gpio; - int8_t _tx_gpio = config.position.tx_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 (!_rx_gpio) - _rx_gpio = GPS_RX_PIN; -@@ -1602,16 +1601,28 @@ GPS *GPS::createGps() - _serial_gps->setRxBufferSize(SERIAL_BUFFER_SIZE); // the default is 256 - #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 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); - #elif defined(ARCH_RP2040) -+ _serial_gps->setPinout(new_gps->tx_gpio, new_gps->rx_gpio); - _serial_gps->setFIFOSize(256); - _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); -+#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 - } - return new_gps; -diff --git a/src/gps/GPS.h b/src/gps/GPS.h -index 8ba1ce0a6..59cee7113 100644 ---- a/src/gps/GPS.h -+++ b/src/gps/GPS.h -@@ -194,6 +194,8 @@ class GPS : private concurrency::OSThread - /** If !NULL we will use this serial port to construct our GPS */ - #if defined(ARCH_RP2040) - static SerialUART *_serial_gps; -+#elif defined(ARCH_NRF52) -+ static Uart *_serial_gps; - #else - static HardwareSerial *_serial_gps; - #endif -diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp -index 692f3c2d2..1122f0a51 100644 ---- a/src/gps/RTC.cpp -+++ b/src/gps/RTC.cpp -@@ -112,7 +112,11 @@ RTCSetResult readFromRTC() - #elif defined(RX8130CE_RTC) - if (rtc_found.address == RX8130CE_RTC) { - uint32_t now = millis(); -+#ifdef MUZI_BASE -+ ArtronShop_RX8130CE rtc(&Wire1); -+#else - ArtronShop_RX8130CE rtc(&Wire); -+#endif - tm t; - if (rtc.getTime(&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) - if (rtc_found.address == RX8130CE_RTC) { -+#ifdef MUZI_BASE -+ ArtronShop_RX8130CE rtc(&Wire1); -+#else - ArtronShop_RX8130CE rtc(&Wire); -+#endif - tm *t = gmtime(&tv->tv_sec); - if (rtc.setTime(*t)) { - LOG_DEBUG("RX8130CE setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1, -diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp -index 86599d5b3..0864e5ae1 100644 ---- a/src/graphics/Screen.cpp -+++ b/src/graphics/Screen.cpp -@@ -324,7 +324,7 @@ static int8_t prevFrame = -1; - // Combined dynamic node list frame cycling through LastHeard, HopSignal, and Distance modes - // Uses a single frame and changes data every few seconds (E-Ink variant is separate) - --#if defined(ESP_PLATFORM) && defined(USE_ST7789) -+#if defined(ESP_PLATFORM) && (defined(USE_ST7789) || defined(USE_ST7796)) - SPIClass SPI1(HSPI); - #endif - -@@ -356,7 +356,19 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O - #else - dispdev = new ST7789Spi(&SPI1, ST7789_RESET, ST7789_RS, ST7789_NSS, GEOMETRY_RAWMODE, TFT_WIDTH, TFT_HEIGHT); - #endif -+#if defined(USE_ST7796) -+#ifdef ESP_PLATFORM -+ dispdev = new ST7796Spi(&SPI1, ST7796_RESET, ST7796_RS, ST7796_NSS, GEOMETRY_RAWMODE, TFT_WIDTH, TFT_HEIGHT, ST7796_SDA, -+ ST7796_MISO, ST7796_SCK, TFT_SPI_FREQUENCY); -+#else -+ dispdev = new ST7796Spi(&SPI1, ST7796_RESET, ST7796_RS, ST7796_NSS, GEOMETRY_RAWMODE, TFT_WIDTH, TFT_HEIGHT); -+#endif -+#endif -+#if defined(USE_ST7789) - static_cast(dispdev)->setRGB(TFT_MESH); -+#elif defined(USE_ST7796) -+ static_cast(dispdev)->setRGB(TFT_MESH); -+#endif - #elif defined(USE_SSD1306) - dispdev = new SSD1306Wire(address.address, -1, -1, geometry, - (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); -@@ -435,6 +447,14 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) - PMU->enablePowerOutput(XPOWERS_ALDO2); - #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 - dispdev->displayOn(); - #endif -@@ -466,6 +486,15 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) - pinMode(VTFT_LEDA, OUTPUT); - digitalWrite(VTFT_LEDA, TFT_BACKLIGHT_ON); - #endif -+#endif -+#ifdef USE_ST7796 -+ ui->init(); -+#ifdef ESP_PLATFORM -+ analogWrite(VTFT_LEDA, BRIGHTNESS_DEFAULT); -+#else -+ pinMode(VTFT_LEDA, OUTPUT); -+ digitalWrite(VTFT_LEDA, TFT_BACKLIGHT_ON); -+#endif - #endif - enabled = true; - setInterval(0); // Draw ASAP -@@ -484,6 +513,10 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) - #endif - - dispdev->displayOff(); -+ -+#ifdef SCREEN_12V_ENABLE -+ digitalWrite(SCREEN_12V_ENABLE, LOW); -+#endif - #ifdef USE_ST7789 - SPI1.end(); - #if defined(ARCH_ESP32) -@@ -500,6 +533,21 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) - nrf_gpio_cfg_default(ST7789_NSS); - #endif - #endif -+#ifdef USE_ST7796 -+ SPI1.end(); -+#if defined(ARCH_ESP32) -+ pinMode(VTFT_LEDA, OUTPUT); -+ digitalWrite(VTFT_LEDA, LOW); -+ pinMode(ST7796_RESET, ANALOG); -+ pinMode(ST7796_RS, ANALOG); -+ pinMode(ST7796_NSS, ANALOG); -+#else -+ nrf_gpio_cfg_default(VTFT_LEDA); -+ nrf_gpio_cfg_default(ST7796_RESET); -+ nrf_gpio_cfg_default(ST7796_RS); -+ nrf_gpio_cfg_default(ST7796_NSS); -+#endif -+#endif - - #ifdef T_WATCH_S3 - PMU->disablePowerOutput(XPOWERS_ALDO2); -@@ -534,7 +582,7 @@ void Screen::setup() - static_cast(dispdev)->setDetected(model); - #endif - --#ifdef USE_SH1107_128_64 -+#if defined(USE_SH1107_128_64) || defined(USE_SH1107) - static_cast(dispdev)->setSubtype(7); - #endif - -@@ -542,6 +590,13 @@ void Screen::setup() - // Apply custom RGB color (e.g. Heltec T114/T190) - static_cast(dispdev)->setRGB(TFT_MESH); - #endif -+#if defined(MUZI_BASE) -+ dispdev->delayPoweron = true; -+#endif -+#if defined(USE_ST7796) && defined(TFT_MESH) -+ // Custom text color, if defined in variant.h -+ static_cast(dispdev)->setRGB(TFT_MESH); -+#endif - - // === Initialize display and UI system === - ui->init(); -@@ -605,6 +660,8 @@ void Screen::setup() - static_cast(dispdev)->flipScreenVertically(); - #elif defined(USE_ST7789) - static_cast(dispdev)->flipScreenVertically(); -+#elif defined(USE_ST7796) -+ static_cast(dispdev)->mirrorScreen(); - #elif !defined(M5STACK_UNITC6L) - dispdev->flipScreenVertically(); - #endif -@@ -637,7 +694,7 @@ void Screen::setup() - touchScreenImpl1->init(); - } - } --#elif HAS_TOUCHSCREEN && !defined(USE_EINK) -+#elif HAS_TOUCHSCREEN && !defined(USE_EINK) && !HAS_CST226SE - touchScreenImpl1 = - new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast(dispdev)->getTouch); - touchScreenImpl1->init(); -@@ -1549,6 +1606,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event) - - int Screen::handleInputEvent(const InputEvent *event) - { -+ LOG_INPUT("Screen Input event %u! kb %u", event->inputEvent, event->kbchar); - if (!screenOn) - return 0; - -diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h -index 74b8d7c5d..a40579ff5 100644 ---- a/src/graphics/Screen.h -+++ b/src/graphics/Screen.h -@@ -83,6 +83,8 @@ class Screen - #include - #elif defined(USE_SPISSD1306) - #include -+#elif defined(USE_ST7796) -+#include - #else - // the SH1106/SSD1306 variant is auto-detected - #include -@@ -249,6 +251,8 @@ class Screen : public concurrency::OSThread - - bool isOverlayBannerShowing(); - -+ bool isScreenOn() { return screenOn; } -+ - // 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 - char ourId[5]; -diff --git a/src/graphics/ScreenFonts.h b/src/graphics/ScreenFonts.h -index c497a27b2..bcb4c4987 100644 ---- a/src/graphics/ScreenFonts.h -+++ b/src/graphics/ScreenFonts.h -@@ -73,7 +73,7 @@ - #endif - - #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ -- defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS)) && \ -+ defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_ST7796)) && \ - !defined(DISPLAY_FORCE_SMALL_FONTS) - // The screen is bigger so use bigger fonts - #define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19 -diff --git a/src/graphics/draw/DebugRenderer.cpp b/src/graphics/draw/DebugRenderer.cpp -index 79c1e7e61..6bccb1653 100644 ---- a/src/graphics/draw/DebugRenderer.cpp -+++ b/src/graphics/draw/DebugRenderer.cpp -@@ -97,7 +97,8 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 - (storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit - #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ -- ARCH_PORTDUINO) && \ -+ defined(USE_ST7796) || \ -+ ARCH_PORTDUINO) && \ - !defined(DISPLAY_FORCE_SMALL_FONTS) - display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12, - 8, imgQuestionL1); -@@ -109,7 +110,7 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 - #endif - } else { - #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ -- defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS)) && \ -+ defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || defined(USE_ST7796)) && \ - !defined(DISPLAY_FORCE_SMALL_FONTS) - display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 16, - 8, imgSFL1); -@@ -125,7 +126,8 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 - // TODO: Raspberry Pi supports more than just the one screen size - #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ -- ARCH_PORTDUINO) && \ -+ defined(USE_ST7796) || \ -+ ARCH_PORTDUINO) && \ - !defined(DISPLAY_FORCE_SMALL_FONTS) - display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, - imgInfoL1); -diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp -index c50fe5cf1..3d23acc9f 100644 ---- a/src/graphics/draw/UIRenderer.cpp -+++ b/src/graphics/draw/UIRenderer.cpp -@@ -257,7 +257,7 @@ void UIRenderer::drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const mes - } - - #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ -- defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS)) && \ -+ defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || defined(USE_ST7796)) && \ - !defined(DISPLAY_FORCE_SMALL_FONTS) - - if (isHighResolution) { -diff --git a/src/graphics/images.h b/src/graphics/images.h -index 8670d78d9..998fe8e2a 100644 ---- a/src/graphics/images.h -+++ b/src/graphics/images.h -@@ -27,8 +27,7 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03 - 0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f}; - - #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ -- defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || \ -- ARCH_PORTDUINO) && \ -+ defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(USE_ST7796) || defined(ST7796_CS) || ARCH_PORTDUINO) && \ - !defined(DISPLAY_FORCE_SMALL_FONTS) - const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff}; - const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f}; -diff --git a/src/input/InputBroker.h b/src/input/InputBroker.h -index 36328ca64..022101f7d 100644 ---- a/src/input/InputBroker.h -+++ b/src/input/InputBroker.h -@@ -3,6 +3,12 @@ - #include "Observer.h" - #include "freertosinc.h" - -+#ifdef InputBrokerDebug -+#define LOG_INPUT(...) LOG_DEBUG(__VA_ARGS__) -+#else -+#define LOG_INPUT(...) -+#endif -+ - enum input_broker_event { - INPUT_BROKER_NONE = 0, - INPUT_BROKER_SELECT = 10, -diff --git a/src/main.cpp b/src/main.cpp -index 8fc2c097b..da2e39604 100644 ---- a/src/main.cpp -+++ b/src/main.cpp -@@ -877,7 +877,7 @@ void setup() - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { - - #if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ -- defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || \ -+ defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_ST7796) || \ - defined(USE_SPISSD1306) - screen = new graphics::Screen(screen_found, screen_model, screen_geometry); - #elif defined(ARCH_PORTDUINO) -@@ -1154,7 +1154,7 @@ void setup() - // Don't call screen setup until after nodedb is setup (because we need - // the current region name) - #if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ -- defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || \ -+ defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_ST7796) || \ - defined(USE_SPISSD1306) - if (screen) - screen->setup(); -diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp -index 3831a384d..af6dd92e9 100644 ---- a/src/mesh/LR11x0Interface.cpp -+++ b/src/mesh/LR11x0Interface.cpp -@@ -244,6 +244,8 @@ template void LR11x0Interface::startReceive() - // We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly. - int err = - 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); - - RadioLibInterface::startReceive(); -@@ -304,4 +306,4 @@ template bool LR11x0Interface::sleep() - - return true; - } --#endif -\ No newline at end of file -+#endif -diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp -index bb3fc6dca..4e99a22ef 100644 ---- a/src/mesh/NodeDB.cpp -+++ b/src/mesh/NodeDB.cpp -@@ -664,7 +664,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) - config.bluetooth.fixed_pin = defaultBLEPin; - - #if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \ -- defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_SPISSD1306) -+ defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(USE_SPISSD1306) || defined(USE_ST7796) - bool hasScreen = true; - #ifdef HELTEC_MESH_NODE_T114 - uint32_t st7789_id = get_st7789_id(ST7789_NSS, ST7789_SCK, ST7789_SDA, ST7789_RS, ST7789_RESET); -@@ -734,6 +734,9 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) - config.display.screen_on_secs = 30; - config.display.wake_on_tap_or_motion = true; - #endif -+#ifdef COMPASS_ORIENTATION -+ config.display.compass_orientation = COMPASS_ORIENTATION; -+#endif - #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI - if (WiFiOTA::isUpdated()) { - WiFiOTA::recoverConfig(&config.network); -diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp -index f435f6060..9cbacc877 100644 ---- a/src/modules/CannedMessageModule.cpp -+++ b/src/modules/CannedMessageModule.cpp -@@ -836,6 +836,7 @@ bool CannedMessageModule::handleFreeTextInput(const InputEvent *event) - if (event->inputEvent == INPUT_BROKER_BACK && this->freetext.length() > 0) { - payload = 0x08; - lastTouchMillis = millis(); -+ requestFocus(); - runOnce(); - return true; - } -@@ -844,6 +845,7 @@ bool CannedMessageModule::handleFreeTextInput(const InputEvent *event) - if (event->inputEvent == INPUT_BROKER_LEFT) { - payload = INPUT_BROKER_LEFT; - lastTouchMillis = millis(); -+ requestFocus(); - runOnce(); - return true; - } -@@ -851,6 +853,7 @@ bool CannedMessageModule::handleFreeTextInput(const InputEvent *event) - if (event->inputEvent == INPUT_BROKER_RIGHT) { - payload = INPUT_BROKER_RIGHT; - lastTouchMillis = millis(); -+ requestFocus(); - runOnce(); - return true; - } -diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp -index 4fe49cc1b..91e96b8d4 100644 ---- a/src/modules/ExternalNotificationModule.cpp -+++ b/src/modules/ExternalNotificationModule.cpp -@@ -314,11 +314,10 @@ void ExternalNotificationModule::stopNow() - audioThread->stop(); - #endif - // Turn off all outputs -- LOG_INFO("Turning off setExternalStates: "); -+ LOG_INFO("Turning off setExternalStates"); - for (int i = 0; i < 3; i++) { - setExternalState(i, false); - externalTurnedOn[i] = 0; -- LOG_INFO("%d ", i); - } - setIntervalFromNow(0); - #ifdef T_WATCH_S3 diff --git a/src/modules/ModuleRegistry.cpp b/src/modules/ModuleRegistry.cpp new file mode 100644 index 000000000..5c83dc70f @@ -2042,10 +342,10 @@ index 000000000..82f571a5e +#endif // MODULE_REGISTRY_H \ No newline at end of file diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp -index e477574dd..3cd0f6405 100644 +index 827524fc3..3cd0f6405 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp -@@ -9,10 +9,14 @@ +@@ -9,6 +9,8 @@ #include "input/UpDownInterruptImpl1.h" #include "input/i2cButton.h" #include "modules/SystemCommandsModule.h" @@ -2054,39 +354,7 @@ index e477574dd..3cd0f6405 100644 #if HAS_TRACKBALL #include "input/TrackballInterruptImpl1.h" #endif - -+#include "modules/StatusLEDModule.h" -+ - #if !MESHTASTIC_EXCLUDE_I2C - #include "input/cardKbI2cImpl.h" - #endif -@@ -119,6 +123,10 @@ void setupModules() - buzzerFeedbackThread = new BuzzerFeedbackThread(); - } - #endif -+#if defined(LED_CHARGE) || defined(LED_PAIRING) -+ statusLEDModule = new StatusLEDModule(); -+#endif -+ - #if !MESHTASTIC_EXCLUDE_ADMIN - adminModule = new AdminModule(); - #endif -@@ -175,12 +183,13 @@ void setupModules() - // new ReplyModule(); - #if (HAS_BUTTON || ARCH_PORTDUINO) && !MESHTASTIC_EXCLUDE_INPUTBROKER - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { -+#ifndef T_LORA_PAGER - rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1(); - if (!rotaryEncoderInterruptImpl1->init()) { - delete rotaryEncoderInterruptImpl1; - rotaryEncoderInterruptImpl1 = nullptr; - } --#ifdef T_LORA_PAGER -+#elif defined(T_LORA_PAGER) - // use a special FSM based rotary encoder version for T-LoRa Pager - rotaryEncoderImpl = new RotaryEncoderImpl(); - if (!rotaryEncoderImpl->init()) { -@@ -298,6 +307,9 @@ void setupModules() +@@ -305,6 +307,9 @@ void setupModules() if (moduleConfig.has_range_test && moduleConfig.range_test.enabled) new RangeTestModule(); #endif @@ -2096,1275 +364,3 @@ index e477574dd..3cd0f6405 100644 // NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra // acks routingModule = new RoutingModule(); -diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp -index 575e9fa96..719e342b1 100644 ---- a/src/modules/SerialModule.cpp -+++ b/src/modules/SerialModule.cpp -@@ -64,7 +64,8 @@ SerialModule *serialModule; - SerialModuleRadio *serialModuleRadio; - - #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") - { - api_type = TYPE_SERIAL; -@@ -204,7 +205,7 @@ int32_t SerialModule::runOnce() - Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); - } - #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) { - #ifdef ARCH_RP2040 - 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) && \ -- !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)) { - processWXSerial(); - -@@ -536,7 +537,8 @@ ParsedLine parseLine(const char *line) - void SerialModule::processWXSerial() - { - #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 averageIntervalMillis = 300000; // 5 minutes hard coded. - static double dir_sum_sin = 0; -diff --git a/src/modules/StatusLEDModule.cpp b/src/modules/StatusLEDModule.cpp -new file mode 100644 -index 000000000..fc9ed310e ---- /dev/null -+++ b/src/modules/StatusLEDModule.cpp -@@ -0,0 +1,94 @@ -+#include "StatusLEDModule.h" -+#include "MeshService.h" -+#include "configuration.h" -+#include -+ -+/* -+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); -+} -diff --git a/src/modules/StatusLEDModule.h b/src/modules/StatusLEDModule.h -new file mode 100644 -index 000000000..d9e3a4f33 ---- /dev/null -+++ b/src/modules/StatusLEDModule.h -@@ -0,0 +1,44 @@ -+#pragma once -+ -+#include "BluetoothStatus.h" -+#include "MeshModule.h" -+#include "PowerStatus.h" -+#include "concurrency/OSThread.h" -+#include "configuration.h" -+#include -+#include -+ -+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 bluetoothStatusObserver = -+ CallbackObserver(this, &StatusLEDModule::handleStatusUpdate); -+ CallbackObserver powerStatusObserver = -+ CallbackObserver(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; -diff --git a/src/modules/SystemCommandsModule.cpp b/src/modules/SystemCommandsModule.cpp -index dc5d8b41f..7fa4485c8 100644 ---- a/src/modules/SystemCommandsModule.cpp -+++ b/src/modules/SystemCommandsModule.cpp -@@ -1,4 +1,5 @@ - #include "SystemCommandsModule.h" -+#include "input/InputBroker.h" - #include "meshUtils.h" - #if HAS_SCREEN - #include "graphics/Screen.h" -@@ -22,7 +23,7 @@ SystemCommandsModule::SystemCommandsModule() - - int SystemCommandsModule::handleInputEvent(const InputEvent *event) - { -- LOG_INFO("Input event %u! kb %u", event->inputEvent, event->kbchar); -+ LOG_INPUT("SystemCommands Input event %u! kb %u", event->inputEvent, event->kbchar); - // System commands (all others fall through) - switch (event->kbchar) { - // Fn key symbols -diff --git a/src/modules/Telemetry/Sensor/AHT10.cpp b/src/modules/Telemetry/Sensor/AHT10.cpp -index 52fdc05c0..c38fd2a92 100644 ---- a/src/modules/Telemetry/Sensor/AHT10.cpp -+++ b/src/modules/Telemetry/Sensor/AHT10.cpp -@@ -35,7 +35,7 @@ bool AHT10Sensor::getMetrics(meshtastic_Telemetry *measurement) - // prefer other sensors like bmp280, bmp3xx - if (!measurement->variant.environment_metrics.has_temperature) { - 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) { -diff --git a/src/modules/Telemetry/Sensor/AHT10.h b/src/modules/Telemetry/Sensor/AHT10.h -index ab3f5806c..f85f04aa0 100644 ---- a/src/modules/Telemetry/Sensor/AHT10.h -+++ b/src/modules/Telemetry/Sensor/AHT10.h -@@ -6,6 +6,10 @@ - - #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() - -+#ifndef AHT10_TEMP_OFFSET -+#define AHT10_TEMP_OFFSET 0 -+#endif -+ - #include "../mesh/generated/meshtastic/telemetry.pb.h" - #include "TelemetrySensor.h" - #include -diff --git a/src/motion/BMX160Sensor.cpp b/src/motion/BMX160Sensor.cpp -index 56f794306..5888c20be 100755 ---- a/src/motion/BMX160Sensor.cpp -+++ b/src/motion/BMX160Sensor.cpp -@@ -115,8 +115,13 @@ int32_t BMX160Sensor::runOnce() - void BMX160Sensor::calibrate(uint16_t forSeconds) - { - #if !defined(MESHTASTIC_EXCLUDE_SCREEN) -+ sBmx160SensorData_t magAccel; -+ sBmx160SensorData_t gAccel; - 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; - uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided -diff --git a/src/motion/ICM20948Sensor.cpp b/src/motion/ICM20948Sensor.cpp -index ebb0f7b66..9455eafe0 100755 ---- a/src/motion/ICM20948Sensor.cpp -+++ b/src/motion/ICM20948Sensor.cpp -@@ -47,6 +47,21 @@ int32_t ICM20948Sensor::runOnce() - int32_t ICM20948Sensor::runOnce() - { - #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; - if (sensor->dataReady()) { - sensor->getAGMT(); -@@ -156,8 +171,20 @@ int32_t ICM20948Sensor::runOnce() - void ICM20948Sensor::calibrate(uint16_t forSeconds) - { - #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); -- 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; - uint16_t calibrateFor = forSeconds * 1000; // calibrate for seconds provided -diff --git a/src/motion/ICM20948Sensor.h b/src/motion/ICM20948Sensor.h -index 27ce4f451..a9b7b69d0 100755 ---- a/src/motion/ICM20948Sensor.h -+++ b/src/motion/ICM20948Sensor.h -@@ -82,7 +82,13 @@ class ICM20948Sensor : public MotionSensor - private: - ICM20948Singleton *sensor = nullptr; - 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; -+#endif - - public: - explicit ICM20948Sensor(ScanI2C::FoundDevice foundDevice); -diff --git a/src/platform/extra_variants/tbeam_displayshield/variant.cpp b/src/platform/extra_variants/tbeam_displayshield/variant.cpp -new file mode 100644 -index 000000000..7beac2293 ---- /dev/null -+++ b/src/platform/extra_variants/tbeam_displayshield/variant.cpp -@@ -0,0 +1,43 @@ -+#include "configuration.h" -+ -+#ifdef HAS_CST226SE -+ -+#include "TouchDrvCSTXXX.hpp" -+#include "input/TouchScreenImpl1.h" -+#include -+ -+TouchDrvCSTXXX tsPanel; -+static constexpr uint8_t PossibleAddresses[2] = {CST328_ADDR, CST226SE_ADDR_ALT}; -+uint8_t i2cAddress = 0; -+ -+bool readTouch(int16_t *x, int16_t *y) -+{ -+ int16_t x_array[1], y_array[1]; -+ uint8_t touched = tsPanel.getPoint(x_array, y_array, 1); -+ if (touched > 0) { -+ *y = x_array[0]; -+ *x = (TFT_WIDTH - y_array[0]); -+ // Check bounds -+ if (*x < 0 || *x >= TFT_WIDTH || *y < 0 || *y >= TFT_HEIGHT) { -+ return false; -+ } -+ return true; // Valid touch detected -+ } -+ return false; // No valid touch data -+} -+ -+void lateInitVariant() -+{ -+ tsPanel.setTouchDrvModel(TouchDrv_CST226); -+ for (uint8_t addr : PossibleAddresses) { -+ if (tsPanel.begin(Wire, addr, I2C_SDA, I2C_SCL)) { -+ i2cAddress = addr; -+ LOG_DEBUG("CST226SE init OK at address 0x%02X", addr); -+ touchScreenImpl1 = new TouchScreenImpl1(TFT_WIDTH, TFT_HEIGHT, readTouch); -+ touchScreenImpl1->init(); -+ return; -+ } -+ } -+ LOG_ERROR("CST226SE init failed at all known addresses"); -+} -+#endif -diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h -index 6ddb41b16..1568e1790 100644 ---- a/src/platform/nrf52/architecture.h -+++ b/src/platform/nrf52/architecture.h -@@ -57,17 +57,19 @@ - #define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO - #elif defined(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 - #elif defined(RAK4630) - #define HW_VENDOR meshtastic_HardwareModel_RAK4631 --#elif defined(RAK3401) --#define HW_VENDOR meshtastic_HardwareModel_RAK3401 - #elif defined(TTGO_T_ECHO) - #define HW_VENDOR meshtastic_HardwareModel_T_ECHO - #elif defined(T_ECHO_LITE) - #define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE - #elif defined(ELECROW_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) -@@ -106,6 +108,8 @@ - #define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1 - #elif defined(HELTEC_MESH_SOLAR) - #define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_SOLAR -+#elif defined(MUZI_BASE) -+#define HW_VENDOR meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN - #else - #define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN - #endif -@@ -130,7 +134,9 @@ - - #endif - -+#ifdef PIN_LED1 - #define LED_PIN PIN_LED1 // LED1 on nrf52840-DK -+#endif - - #ifdef PIN_BUTTON1 - #define BUTTON_PIN PIN_BUTTON1 -diff --git a/src/platform/nrf52/main-nrf52.cpp b/src/platform/nrf52/main-nrf52.cpp -index 827863f33..c03cc4454 100644 ---- a/src/platform/nrf52/main-nrf52.cpp -+++ b/src/platform/nrf52/main-nrf52.cpp -@@ -30,6 +30,11 @@ - #include "BQ25713.h" - #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; - -@@ -391,6 +396,7 @@ void cpuDeepSleep(uint32_t msecToWake) - NRF_GPIO->DIRCLR = (1 << pin); - } - #endif -+ variant_shutdown(); - - // Sleepy trackers or sensors can low power "sleep" - // Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event -diff --git a/src/power.h b/src/power.h -index 8fc7c8f45..3f28dedb2 100644 ---- a/src/power.h -+++ b/src/power.h -@@ -34,8 +34,8 @@ - #define OCV_ARRAY 4200, 3876, 3826, 3763, 3713, 3660, 3573, 3485, 3422, 3359, 3300 - #elif defined(SEEED_SOLAR_NODE) - #define OCV_ARRAY 4200, 3986, 3922, 3812, 3734, 3645, 3527, 3420, 3281, 3087, 2786 --#elif defined(R1_NEO) --#define OCV_ARRAY 4330, 4292, 4254, 4216, 4178, 4140, 4102, 4064, 4026, 3988, 3950 -+#elif defined(WISMESH_TAG) -+#define OCV_ARRAY 4240, 4112, 4029, 3970, 3906, 3846, 3824, 3802, 3776, 3650, 3072 - #else // LiIon - #define OCV_ARRAY 4190, 4050, 3990, 3890, 3800, 3720, 3630, 3530, 3420, 3300, 3100 - #endif -diff --git a/variants/esp32/tbeam/platformio.ini b/variants/esp32/tbeam/platformio.ini -index e53f22d30..c635081ff 100644 ---- a/variants/esp32/tbeam/platformio.ini -+++ b/variants/esp32/tbeam/platformio.ini -@@ -4,12 +4,22 @@ extends = esp32_base - board = ttgo-t-beam - board_level = pr - board_check = true --lib_deps = -- ${esp32_base.lib_deps} --build_flags = -- ${esp32_base.build_flags} -+lib_deps = ${esp32_base.lib_deps} -+build_flags = ${esp32_base.build_flags} - -D TBEAM_V10 - -I variants/esp32/tbeam - -DBOARD_HAS_PSRAM - -mfix-esp32-psram-cache-issue - upload_speed = 921600 -+ -+[env:tbeam-displayshield] -+extends = env:tbeam -+ -+build_flags = -+ ${env:tbeam.build_flags} -+ -D USE_ST7796 -+ -+lib_deps = -+ ${env:tbeam.lib_deps} -+ https://github.com/meshtastic/st7796/archive/refs/tags/1.0.5.zip ; display addon -+ lewisxhe/SensorLib@0.3.1 ; touchscreen addon -\ No newline at end of file -diff --git a/variants/esp32/tbeam/variant.h b/variants/esp32/tbeam/variant.h -index 5b521a2de..2d144a888 100644 ---- a/variants/esp32/tbeam/variant.h -+++ b/variants/esp32/tbeam/variant.h -@@ -42,4 +42,35 @@ - #define GPS_UBLOX - #define GPS_RX_PIN 34 - #define GPS_TX_PIN 12 --// #define GPS_DEBUG -\ No newline at end of file -+// #define GPS_DEBUG -+ -+// Used when the display shield is chosen -+#ifdef USE_ST7796 -+ -+#undef EXT_NOTIFY_OUT -+#undef LED_STATE_ON -+#undef LED_PIN -+ -+#define HAS_CST226SE 1 -+#define HAS_TOUCHSCREEN 1 -+// #define TOUCH_IRQ 35 // broken in this version of the lib 0.3.1 -+#ifndef TOUCH_IRQ -+#define TOUCH_IRQ -1 -+#endif -+#define CANNED_MESSAGE_MODULE_ENABLE 1 -+#define USE_VIRTUAL_KEYBOARD 1 -+ -+#define ST7796_NSS 25 -+#define ST7796_RS 13 // DC -+#define ST7796_SDA 14 // MOSI -+#define ST7796_SCK 15 -+#define ST7796_RESET 2 -+#define ST7796_MISO -1 -+#define ST7796_BUSY -1 -+#define VTFT_LEDA 4 -+#define TFT_SPI_FREQUENCY 60000000 -+#define TFT_HEIGHT 222 -+#define TFT_WIDTH 480 -+#define BRIGHTNESS_DEFAULT 100 // Medium Low Brightness -+#define SCREEN_TRANSITION_FRAMERATE 5 // fps -+#endif -\ No newline at end of file -diff --git a/variants/nrf52840/ELECROW-ThinkNode-M3/platformio.ini b/variants/nrf52840/ELECROW-ThinkNode-M3/platformio.ini -new file mode 100644 -index 000000000..958e48e48 ---- /dev/null -+++ b/variants/nrf52840/ELECROW-ThinkNode-M3/platformio.ini -@@ -0,0 +1,17 @@ -+[env:thinknode_m3] -+extends = nrf52840_base -+board = ThinkNode-M3 -+board_check = true -+debug_tool = jlink -+build_flags = -+ ${nrf52840_base.build_flags} -+ -Ivariants/nrf52840/ELECROW-ThinkNode-M3 -+ -DELECROW_ThinkNode_M3 -+ -DGPS_POWER_TOGGLE -+ -D CONFIG_NFCT_PINS_AS_GPIOS=1 -+ -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -+build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/ELECROW-ThinkNode-M3> -+lib_deps = -+ ${nrf52840_base.lib_deps} -+ khoih-prog/nRF52_PWM@^1.0.1 -+ lewisxhe/PCF8563_Library@^1.0.1 -diff --git a/variants/nrf52840/ELECROW-ThinkNode-M3/rfswitch.h b/variants/nrf52840/ELECROW-ThinkNode-M3/rfswitch.h -new file mode 100644 -index 000000000..77ae9ef73 ---- /dev/null -+++ b/variants/nrf52840/ELECROW-ThinkNode-M3/rfswitch.h -@@ -0,0 +1,15 @@ -+#include "RadioLib.h" -+#include "nrf.h" -+ -+// set RF switch configuration for ELECROW ThinkNode M3 -+// ELECROW ThinkNode M3 uses DIO5 and DIO6 for RF switching -+ -+static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; -+ -+static const Module::RfSwitchMode_t rfswitch_table[] = { -+ // mode DIO5 DIO6 -+ {LR11x0::MODE_STBY, {LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW}}, -+ {LR11x0::MODE_TX, {HIGH, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH}}, -+ {LR11x0::MODE_TX_HF, {LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW}}, -+ {LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE, -+}; -diff --git a/variants/nrf52840/ELECROW-ThinkNode-M3/variant.cpp b/variants/nrf52840/ELECROW-ThinkNode-M3/variant.cpp -new file mode 100644 -index 000000000..b7a7b7342 ---- /dev/null -+++ b/variants/nrf52840/ELECROW-ThinkNode-M3/variant.cpp -@@ -0,0 +1,93 @@ -+/* -+ Copyright (c) 2014-2015 Arduino LLC. All right reserved. -+ Copyright (c) 2016 Sandeep Mistry All right reserved. -+ Copyright (c) 2018, Adafruit Industries (adafruit.com) -+ -+ This library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ This library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ See the GNU Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with this library; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+*/ -+ -+#include "variant.h" -+#include "meshUtils.h" -+#include "nrf.h" -+#include "wiring_constants.h" -+#include "wiring_digital.h" -+ -+const uint32_t g_ADigitalPinMap[] = { -+ // P0 -+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -+ -+ // P1 -+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; -+ -+void initVariant() -+{ -+ pinMode(KEY_POWER, OUTPUT); -+ digitalWrite(KEY_POWER, HIGH); -+ pinMode(RGB_POWER, OUTPUT); -+ digitalWrite(RGB_POWER, HIGH); -+ pinMode(green_LED_PIN, OUTPUT); -+ digitalWrite(green_LED_PIN, LED_STATE_OFF); -+ pinMode(LED_BLUE, OUTPUT); -+ pinMode(PIN_POWER_USB, INPUT); -+ pinMode(PIN_POWER_DONE, INPUT); -+ pinMode(PIN_POWER_CHRG, INPUT); -+ pinMode(BUTTON_PIN, INPUT_PULLUP); -+ pinMode(EEPROM_POWER, OUTPUT); -+ digitalWrite(EEPROM_POWER, HIGH); -+ pinMode(PIN_EN1, OUTPUT); -+ digitalWrite(PIN_EN1, HIGH); -+ pinMode(PIN_EN2, OUTPUT); -+ digitalWrite(PIN_EN2, HIGH); -+ pinMode(ACC_POWER, OUTPUT); -+ digitalWrite(ACC_POWER, LOW); -+ pinMode(DHT_POWER, OUTPUT); -+ digitalWrite(DHT_POWER, HIGH); -+ pinMode(Battery_POWER, OUTPUT); -+ digitalWrite(Battery_POWER, HIGH); -+ pinMode(GPS_POWER, OUTPUT); -+ digitalWrite(GPS_POWER, HIGH); -+} -+ -+// called from main-nrf52.cpp during the cpuDeepSleep() function -+void variant_shutdown() -+{ -+ digitalWrite(EEPROM_POWER, LOW); -+ digitalWrite(KEY_POWER, LOW); -+ -+ for (int pin = 0; pin < 48; pin++) { -+ if (pin == PIN_POWER_USB || pin == BUTTON_PIN || pin == PIN_EN1 || pin == PIN_EN2 || pin == DHT_POWER || -+ pin == ACC_POWER || pin == Battery_POWER || pin == GPS_POWER || pin == LR1110_SPI_MISO_PIN || -+ pin == LR1110_SPI_MOSI_PIN || pin == LR1110_SPI_SCK_PIN || pin == LR1110_SPI_NSS_PIN || pin == LR1110_BUSY_PIN || -+ pin == LR1110_NRESET_PIN || pin == LR1110_IRQ_PIN || pin == GPS_TX_PIN || pin == GPS_RX_PIN || pin == green_LED_PIN || -+ pin == red_LED_PIN || pin == LED_BLUE) { -+ continue; -+ } -+ pinMode(pin, OUTPUT); -+ digitalWrite(pin, LOW); -+ if (pin >= 32) { -+ NRF_P1->DIRCLR = (1 << (pin - 32)); -+ } else { -+ NRF_GPIO->DIRCLR = (1 << pin); -+ } -+ } -+ -+ nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input -+ nrf_gpio_pin_sense_t sense1 = NRF_GPIO_PIN_SENSE_LOW; -+ nrf_gpio_cfg_sense_set(BUTTON_PIN, sense1); -+ -+ nrf_gpio_cfg_input(PIN_POWER_USB, NRF_GPIO_PIN_PULLDOWN); // Configure the pin to be woken up as an input -+ nrf_gpio_pin_sense_t sense2 = NRF_GPIO_PIN_SENSE_HIGH; -+ nrf_gpio_cfg_sense_set(PIN_POWER_USB, sense2); -+} -\ No newline at end of file -diff --git a/variants/nrf52840/ELECROW-ThinkNode-M3/variant.h b/variants/nrf52840/ELECROW-ThinkNode-M3/variant.h -new file mode 100644 -index 000000000..cf940172b ---- /dev/null -+++ b/variants/nrf52840/ELECROW-ThinkNode-M3/variant.h -@@ -0,0 +1,122 @@ -+/* -+ Copyright (c) 2014-2015 Arduino LLC. All right reserved. -+ Copyright (c) 2016 Sandeep Mistry All right reserved. -+ Copyright (c) 2018, Adafruit Industries (adafruit.com) -+ -+ This library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ This library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ See the GNU Lesser General Public License for more details. -+ You should have received a copy of the GNU Lesser General Public -+ License along with this library; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+*/ -+ -+#ifndef _VARIANT_ELECROW_EINK_V1_0_ -+#define _VARIANT_ELECROW_EINK_V1_0_ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif // __cplusplus -+ -+#include "WVariant.h" -+ -+#define VARIANT_MCK (64000000ul) -+#define USE_LFXO // Board uses 32khz crystal for LF -+ -+#define ELECROW_ThinkNode_M3 1 -+// Number of pins defined in PinDescription array -+#define PINS_COUNT (48) -+#define NUM_DIGITAL_PINS (48) -+#define NUM_ANALOG_INPUTS (1) -+#define NUM_ANALOG_OUTPUTS (0) -+ -+// Power Pin -+#define NRF_APM -+#define GPS_POWER 14 -+#define PIN_POWER_USB 31 -+#define EXT_PWR_DETECT PIN_POWER_USB -+#define PIN_POWER_DONE 24 -+#define PIN_POWER_CHRG 32 -+#define KEY_POWER 16 -+#define ACC_POWER 2 -+#define DHT_POWER 3 -+#define Battery_POWER 17 -+#define RGB_POWER 29 -+#define EEPROM_POWER 7 -+ -+// LED -+#define red_LED_PIN 33 -+#define LED_POWER red_LED_PIN -+#define LED_CHARGE LED_POWER // Signals the Status LED Module to handle this LED -+#define green_LED_PIN 35 -+#define LED_BLUE 37 -+#define LED_PAIRING LED_BLUE // Signals the Status LED Module to handle this LED -+ -+#define LED_BUILTIN -1 -+#define LED_STATE_ON LOW -+#define LED_STATE_OFF HIGH -+ -+// BUZZER -+#define PIN_BUZZER 23 -+#define PIN_EN1 36 -+#define PIN_EN2 34 -+/*Wire Interfaces*/ -+#define WIRE_INTERFACES_COUNT 1 -+#define PIN_WIRE_SDA 26 -+#define PIN_WIRE_SCL 27 -+ -+// Temperature correction for sensor -+#define AHT10_TEMP_OFFSET -5.0 -+ -+/*GPS pins*/ -+#define HAS_GPS 1 -+#define GPS_BAUDRATE 9600 -+#define PIN_GPS_RESET 25 -+#define PIN_GPS_STANDBY 21 -+#define GPS_TX_PIN 20 -+#define GPS_RX_PIN 22 -+#define GPS_THREAD_INTERVAL 50 -+#define PIN_SERIAL1_RX GPS_TX_PIN -+#define PIN_SERIAL1_TX GPS_RX_PIN -+// Button -+#define BUTTON_PIN 12 -+#define BUTTON_PIN_ALT (0 + 12) -+// Battery -+#define BATTERY_PIN 5 -+#define BATTERY_SENSE_RESOLUTION_BITS 12 -+#define BATTERY_SENSE_RESOLUTION 4096.0 -+#undef AREF_VOLTAGE -+#define AREF_VOLTAGE 2.4 -+#define VBAT_AR_INTERNAL AR_INTERNAL_2_4 -+#define ADC_MULTIPLIER (1.75) -+/*SPI Interfaces*/ -+#define SPI_INTERFACES_COUNT 1 -+#define PIN_SPI_MISO (32 + 15) // P1.15 47 -+#define PIN_SPI_MOSI (32 + 14) // P1.14 46 -+#define PIN_SPI_SCK (32 + 13) // P1.13 45 -+#define PIN_SPI_NSS (32 + 12) // P1.12 44 -+/*LORA Interfaces*/ -+#define USE_LR1110 -+#define LR1110_IRQ_PIN 40 -+#define LR1110_NRESET_PIN 42 -+#define LR1110_BUSY_PIN 43 -+#define LR1110_SPI_NSS_PIN 44 -+#define LR1110_SPI_SCK_PIN 45 -+#define LR1110_SPI_MOSI_PIN 46 -+#define LR1110_SPI_MISO_PIN 47 -+#define LR11X0_DIO3_TCXO_VOLTAGE 3.3 -+#define LR11X0_DIO_AS_RF_SWITCH -+ -+// PCF8563 RTC Module -+#define PCF8563_RTC 0x51 -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -diff --git a/variants/nrf52840/ELECROW-ThinkNode-M6/variant.cpp b/variants/nrf52840/ELECROW-ThinkNode-M6/variant.cpp -index b84079e66..09872d409 100644 ---- a/variants/nrf52840/ELECROW-ThinkNode-M6/variant.cpp -+++ b/variants/nrf52840/ELECROW-ThinkNode-M6/variant.cpp -@@ -32,11 +32,11 @@ const uint32_t g_ADigitalPinMap[] = { - - void initVariant() - { -- pinMode(PIN_LED1, OUTPUT); -- ledOff(PIN_LED1); -+ pinMode(LED_CHARGE, OUTPUT); -+ ledOff(LED_CHARGE); - -- pinMode(PIN_LED2, OUTPUT); -- ledOff(PIN_LED2); -+ pinMode(LED_PAIRING, OUTPUT); -+ ledOff(LED_PAIRING); - - pinMode(VDD_FLASH_EN, OUTPUT); - digitalWrite(VDD_FLASH_EN, HIGH); -diff --git a/variants/nrf52840/ELECROW-ThinkNode-M6/variant.h b/variants/nrf52840/ELECROW-ThinkNode-M6/variant.h -index 98c654df2..5e543b21f 100644 ---- a/variants/nrf52840/ELECROW-ThinkNode-M6/variant.h -+++ b/variants/nrf52840/ELECROW-ThinkNode-M6/variant.h -@@ -40,10 +40,11 @@ extern "C" { - #define NUM_ANALOG_OUTPUTS (0) - - // LEDs --#define PIN_LED1 (12) --#define PIN_LED2 (7) --#define LED_BUILTIN PIN_LED1 --#define LED_BLUE PIN_LED2 -+#define LED_BUILTIN -1 -+#define LED_BLUE -1 -+#define LED_CHARGE (12) -+#define LED_PAIRING (7) -+ - #define LED_STATE_ON 1 - - // USB power detection -diff --git a/variants/nrf52840/heltec_mesh_node_t114-inkhud/variant.h b/variants/nrf52840/heltec_mesh_node_t114-inkhud/variant.h -index 39cbc8f01..143d20459 100644 ---- a/variants/nrf52840/heltec_mesh_node_t114-inkhud/variant.h -+++ b/variants/nrf52840/heltec_mesh_node_t114-inkhud/variant.h -@@ -116,13 +116,13 @@ No longer populated on PCB - #define PIN_GPS_PPS (32 + 4) - // Seems to be missing on this new board - // #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS --#define GPS_TX_PIN (32 + 5) // This is for bits going TOWARDS the CPU --#define GPS_RX_PIN (32 + 7) // This is for bits going TOWARDS the GPS -+#define GPS_TX_PIN (32 + 7) // This is for bits going TOWARDS the CPU -+#define GPS_RX_PIN (32 + 5) // This is for bits going TOWARDS the GPS - - #define GPS_THREAD_INTERVAL 50 - --#define PIN_SERIAL1_RX GPS_TX_PIN --#define PIN_SERIAL1_TX GPS_RX_PIN -+#define PIN_SERIAL1_RX GPS_RX_PIN -+#define PIN_SERIAL1_TX GPS_TX_PIN - - // PCF8563 RTC Module - #define PCF8563_RTC 0x51 -diff --git a/variants/nrf52840/heltec_mesh_node_t114/variant.h b/variants/nrf52840/heltec_mesh_node_t114/variant.h -index b6082fdc6..3493577bc 100644 ---- a/variants/nrf52840/heltec_mesh_node_t114/variant.h -+++ b/variants/nrf52840/heltec_mesh_node_t114/variant.h -@@ -167,13 +167,13 @@ No longer populated on PCB - #define PIN_GPS_PPS (32 + 4) - // Seems to be missing on this new board - // #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS --#define GPS_TX_PIN (32 + 5) // This is for bits going TOWARDS the CPU --#define GPS_RX_PIN (32 + 7) // This is for bits going TOWARDS the GPS -+#define GPS_TX_PIN (32 + 7) // This is for bits going TOWARDS the CPU -+#define GPS_RX_PIN (32 + 5) // This is for bits going TOWARDS the GPS - - #define GPS_THREAD_INTERVAL 50 - --#define PIN_SERIAL1_RX GPS_TX_PIN --#define PIN_SERIAL1_TX GPS_RX_PIN -+#define PIN_SERIAL1_RX GPS_RX_PIN -+#define PIN_SERIAL1_TX GPS_TX_PIN - - // PCF8563 RTC Module - #define PCF8563_RTC 0x51 -diff --git a/variants/nrf52840/heltec_mesh_solar/variant.h b/variants/nrf52840/heltec_mesh_solar/variant.h -index 7c43d8ba7..7a8fc579f 100644 ---- a/variants/nrf52840/heltec_mesh_solar/variant.h -+++ b/variants/nrf52840/heltec_mesh_solar/variant.h -@@ -116,13 +116,13 @@ No longer populated on PCB - #define PIN_GPS_PPS (32 + 4) - // Seems to be missing on this new board - // #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS --#define GPS_TX_PIN (32 + 5) // This is for bits going TOWARDS the CPU --#define GPS_RX_PIN (32 + 7) // This is for bits going TOWARDS the GPS -+#define GPS_TX_PIN (32 + 7) // This is for bits going TOWARDS the CPU -+#define GPS_RX_PIN (32 + 5) // This is for bits going TOWARDS the GPS - - #define GPS_THREAD_INTERVAL 50 - --#define PIN_SERIAL1_RX GPS_TX_PIN --#define PIN_SERIAL1_TX GPS_RX_PIN -+#define PIN_SERIAL1_RX GPS_RX_PIN -+#define PIN_SERIAL1_TX GPS_TX_PIN - - /* - * SPI Interfaces -diff --git a/variants/nrf52840/muzi_base/platformio.ini b/variants/nrf52840/muzi_base/platformio.ini -new file mode 100644 -index 000000000..49393f4e0 ---- /dev/null -+++ b/variants/nrf52840/muzi_base/platformio.ini -@@ -0,0 +1,15 @@ -+[env:muzi-base] -+extends = nrf52840_base -+board = muzi-base -+build_flags = ${nrf52840_base.build_flags} -+ -I variants/nrf52840/muzi_base -+ -D MUZI_BASE -+ -D CONFIG_NFCT_PINS_AS_GPIOS=1 -+ -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" -+ -+build_src_filter = ${nrf52840_base.build_src_filter} +<../variants/nrf52840/muzi_base> -+lib_deps = -+ ${nrf52840_base.lib_deps} -+ artronshop/ArtronShop_RX8130CE@1.0.0 -+ -+ -diff --git a/variants/nrf52840/muzi_base/rfswitch.h b/variants/nrf52840/muzi_base/rfswitch.h -new file mode 100644 -index 000000000..589f24767 ---- /dev/null -+++ b/variants/nrf52840/muzi_base/rfswitch.h -@@ -0,0 +1,11 @@ -+#include "RadioLib.h" -+ -+static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; -+ -+static const Module::RfSwitchMode_t rfswitch_table[] = { -+ // mode DIO5 DIO6 -+ {LR11x0::MODE_STBY, {LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW}}, -+ {LR11x0::MODE_TX, {LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH}}, -+ {LR11x0::MODE_TX_HF, {LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW}}, -+ {LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE, -+}; -diff --git a/variants/nrf52840/muzi_base/variant.cpp b/variants/nrf52840/muzi_base/variant.cpp -new file mode 100644 -index 000000000..da01de974 ---- /dev/null -+++ b/variants/nrf52840/muzi_base/variant.cpp -@@ -0,0 +1,83 @@ -+#include "variant.h" -+#include "nrf.h" -+#include "wiring_constants.h" -+#include "wiring_digital.h" -+ -+const uint32_t g_ADigitalPinMap[] = { -+ // P0 -+ 0, -+ 1, -+ 2, -+ 3, -+ 4, -+ 5, -+ 6, -+ 7, -+ 8, -+ 9, -+ 10, -+ 11, -+ 12, -+ 13, -+ 14, -+ 15, -+ 16, -+ 17, -+ 18, -+ 19, -+ 20, -+ 21, -+ 22, -+ 23, -+ 24, -+ 25, -+ 26, -+ 27, -+ 28, -+ 29, -+ 30, -+ 31, -+ -+ // P1 -+ 32, -+ 33, -+ 34, -+ 35, -+ 36, -+ 37, -+ 38, -+ 39, -+ 40, -+ 41, -+ 42, -+ 43, -+ 44, -+ 45, -+ 46, -+ 47, -+}; -+ -+void initVariant() -+{ -+ // Initialize the digital pins as inputs or outputs -+ pinMode(PIN_LED1, OUTPUT); -+ digitalWrite(PIN_LED1, HIGH); -+ -+ pinMode(PIN_LED2, OUTPUT); -+ digitalWrite(PIN_LED2, HIGH); -+ -+ // Initialize LoRa pins -+ pinMode(SX126X_RESET, OUTPUT); -+ digitalWrite(SX126X_RESET, HIGH); -+ -+ pinMode(SX126X_CS, OUTPUT); -+ digitalWrite(SX126X_CS, HIGH); -+ -+ pinMode(GPS_EN_GPIO, OUTPUT); -+ digitalWrite(GPS_EN_GPIO, HIGH); // GPS on initially -+ -+ pinMode(SCREEN_12V_ENABLE, OUTPUT); -+ digitalWrite(SCREEN_12V_ENABLE, LOW); // -+ -+ pinMode(BATTERY_CHARGING_INV, INPUT); -+} -diff --git a/variants/nrf52840/muzi_base/variant.h b/variants/nrf52840/muzi_base/variant.h -new file mode 100644 -index 000000000..96604c400 ---- /dev/null -+++ b/variants/nrf52840/muzi_base/variant.h -@@ -0,0 +1,192 @@ -+#pragma once -+ -+#ifndef _VARIANT_MUZI_BASE_ -+#define _VARIANT_MUZI_BASE_ -+ -+/** Master clock frequency */ -+#define VARIANT_MCK (64000000ul) -+ -+#define USE_LFXO // Board uses 32khz crystal for LF -+ -+/*---------------------------------------------------------------------------- -+ * Headers -+ *----------------------------------------------------------------------------*/ -+ -+#include "WVariant.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif // __cplusplus -+ -+// Number of pins defined in PinDescription array -+#define PINS_COUNT (48) -+#define NUM_DIGITAL_PINS (48) -+#define NUM_ANALOG_INPUTS (6) -+#define NUM_ANALOG_OUTPUTS (0) -+ -+// Define I2C Peripherals -+#define WIRE_INTERFACES_COUNT 2 -+ -+// this is the OLED bus -+#define PIN_WIRE_SDA (0 + 24) // P0.24 -+#define PIN_WIRE_SCL (0 + 25) // P0.25 -+ -+// IMU bus -+#define PIN_WIRE1_SDA (0 + 04) // P0.04 -+#define PIN_WIRE1_SCL (0 + 06) // P0.06 -+ -+#define COMPASS_ORIENTATION meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270 -+#define HAS_ICM20948 // forces the i2c address to be seen as this sensor -+ -+#define HAS_RTC 1 -+#define RX8130CE_RTC 0x32 -+ -+// LEDs -+#define PIN_LED1 (32 + 3) // P1.03, Green -+#define PIN_LED2 (32 + 4) // P1.04, Blue -+ -+#define LED_BUILTIN -1 // PIN_LED1 -+#define LED_BLUE PIN_LED2 -+#define LED_STATE_ON 0 // State when LED is lit -+ -+// Buttons -+#define HAS_TRACKBALL 1 -+#define TB_UP (0 + 21) -+#define TB_DOWN (0 + 17) -+#define TB_LEFT (32 + 05) -+#define TB_RIGHT (0 + 16) -+#define TB_PRESS (0 + 10) -+#define TB_DIRECTION FALLING -+ -+#define CANCEL_BUTTON_PIN (0 + 15) // P0.15 -+#define CANCEL_BUTTON_ACTIVE_LOW true -+#define CANCEL_BUTTON_ACTIVE_PULLUP false -+ -+// Switch -+#define SWITCH_MODE1 (32 + 9) // P1.09, Top Position -+#define SWITCH_MODE2 (0 + 12) // P0.12, Middle Position -+#define PIN_GPS_SWITCH SWITCH_MODE2 -+ -+/* -+ * SPI Interfaces -+ */ -+ -+#define SPI_INTERFACES_COUNT 1 -+ -+// For LORA, spi 0 -+#define PIN_SPI_MISO (32 + 15) // P1.15 -+#define PIN_SPI_MOSI (32 + 14) // P1.14 -+#define PIN_SPI_SCK (32 + 13) // P1.13 -+ -+#define LORA_SCK PIN_SPI_SCK -+#define LORA_MISO PIN_SPI_MISO -+#define LORA_MOSI PIN_SPI_MOSI -+#define LORA_CS (32 + 12) // P1.12 -+ -+#define USE_SX1262 -+#define SX126X_CS LORA_CS -+#define SX126X_DIO1 (32 + 6) // P1.06 -+#define SX126X_BUSY (32 + 11) // P1.11 -+#define SX126X_RESET (32 + 10) // P1.10 -+#define SX126X_DIO2_AS_RF_SWITCH -+#define SX126X_DIO3_TCXO_VOLTAGE 3.3 -+ -+#define USE_LR1121 -+#define LR1121_IRQ_PIN (32 + 8) // P1.08 -+#define LR1121_NRESET_PIN (32 + 10) // P1.10 -+#define LR1121_BUSY_PIN (32 + 11) // P1.11 -+#define LR1121_SPI_NSS_PIN LORA_CS -+#define LR1121_SPI_SCK_PIN LORA_SCK -+#define LR1121_SPI_MOSI_PIN LORA_MOSI -+#define LR1121_SPI_MISO_PIN LORA_MISO -+#define LR11X0_DIO3_TCXO_VOLTAGE 3.0 -+#define LR11X0_DIO_AS_RF_SWITCH -+ -+// GPS -+#define GPS_RX_PIN (0 + 20) // P0.20 -+#define GPS_TX_PIN (0 + 19) // P0.19 -+#define GPS_EN_GPIO (32 + 1) // P1.01 -+ -+#define PIN_SERIAL1_RX GPS_RX_PIN -+#define PIN_SERIAL1_TX GPS_TX_PIN -+ -+#define PIN_BUZZER (0 + 22) // P0.22 -+ -+// Battery monitoring -+#define BATTERY_PIN (0 + 31) // P0.31 -+ -+// #define CHARGER_FAULT (0 + 27) // P0.27 -+#define BATTERY_CHARGING_INV (32 + 02) // P1.02 -+#define BATTERY_SENSE_RESOLUTION_BITS 12 -+#define BATTERY_SENSE_RESOLUTION 4096.0 -+#define ADC_MULTIPLIER 1.537 -+ -+#define OCV_ARRAY 4050, 4010, 3990, 3930, 3870, 3820, 3740, 3630, 3550, 3450, 3100 -+ -+// Display - I2C display -+#define HAS_SCREEN 1 -+#define SCREEN_12V_ENABLE (0 + 23) // P0.23 -+#define USE_SH1107 -+ -+#define USERPREFS_OEM_TEXT "muzi_works_logo" -+#define USERPREFS_OEM_FONT_SIZE 0 -+#define USERPREFS_OEM_IMAGE_WIDTH 88 // 11 bytes wide -+#define USERPREFS_OEM_IMAGE_HEIGHT 47 // 517 bytes total -+#define USERPREFS_OEM_IMAGE_DATA \ -+ { \ -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, \ -+ 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x7F, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ -+ 0xF7, 0x0F, 0xFF, 0x00, 0xF0, 0xFF, 0x0F, 0xC0, 0xFF, 0x07, 0x78, 0xFF, 0x9F, 0xFF, 0x01, 0xF0, 0xFF, 0x0F, 0xC0, \ -+ 0xFF, 0x03, 0x78, 0x3F, 0xFE, 0xF3, 0x01, 0xF0, 0xFF, 0x0F, 0x00, 0xE0, 0x03, 0x78, 0x1F, 0xFC, 0xC0, 0x03, 0xF0, \ -+ 0xFF, 0x0F, 0x00, 0xE0, 0x01, 0x78, 0x0F, 0xF8, 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0xF0, 0x00, 0x78, 0x0F, 0x78, \ -+ 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0x70, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0x78, 0x00, \ -+ 0x78, 0x07, 0x70, 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0x3C, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xF0, 0xFF, 0x0F, \ -+ 0x00, 0x1C, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0x1E, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, \ -+ 0xE0, 0xFF, 0x0F, 0x00, 0x0F, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xE0, 0xFF, 0x07, 0x80, 0x07, 0x00, 0x78, 0x07, \ -+ 0x70, 0x80, 0x03, 0xC0, 0xFF, 0x07, 0x80, 0x07, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xC0, 0xFF, 0x03, 0xC0, 0xFF, \ -+ 0x07, 0x78, 0x07, 0x70, 0x80, 0x03, 0x00, 0xFF, 0x01, 0xE0, 0xFF, 0x07, 0x78, 0x07, 0x70, 0x80, 0x03, 0x00, 0x7C, \ -+ 0x00, 0xF0, 0xFF, 0x07, 0x78, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ -+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ -+ 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xE3, 0xE7, 0xC7, 0x1F, 0xF8, 0x0F, 0xF0, 0xE7, 0xE3, 0x07, 0x7C, 0xC7, 0xE7, \ -+ 0xC3, 0x0F, 0xE0, 0x07, 0xE0, 0xC7, 0xE1, 0x03, 0x70, 0xC7, 0xC3, 0xE3, 0x87, 0xC1, 0x07, 0xC0, 0xC7, 0xF8, 0xE3, \ -+ 0x71, 0xC7, 0xC3, 0xE3, 0xE3, 0xC7, 0xC7, 0xC7, 0x47, 0xF8, 0xF3, 0x7F, 0x8F, 0xC3, 0xF1, 0xE3, 0x8F, 0xC7, 0x8F, \ -+ 0x27, 0xFC, 0xE3, 0x7F, 0x8F, 0x81, 0xF1, 0xF1, 0x8F, 0xC7, 0xCF, 0x07, 0xFE, 0x03, 0x7E, 0x8F, 0x99, 0xF1, 0xF1, \ -+ 0x8F, 0x07, 0xC0, 0x07, 0xFF, 0x07, 0x78, 0x9F, 0x99, 0xF9, 0xF1, 0x8F, 0x07, 0xE0, 0x07, 0xFE, 0x3F, 0x70, 0x1F, \ -+ 0x18, 0xF8, 0xF3, 0x8F, 0x07, 0xF0, 0x27, 0xFC, 0xFF, 0x71, 0x3F, 0x18, 0xF8, 0xE3, 0xC7, 0xC7, 0xF1, 0x47, 0xF8, \ -+ 0xF3, 0x63, 0x3F, 0x3C, 0xFC, 0xC3, 0xC3, 0xC7, 0xE3, 0xC7, 0xF0, 0xE1, 0x71, 0x3F, 0x3C, 0xFC, 0x07, 0xE0, 0xC7, \ -+ 0xC7, 0xC7, 0xE1, 0x03, 0x70, 0x7F, 0x7E, 0xFE, 0x0F, 0xF0, 0xC7, 0x87, 0xC7, 0xC3, 0x07, 0x78, 0xFF, 0xFF, 0xFF, \ -+ 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, \ -+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ -+ 0xFF, 0xFF, 0x7F \ -+ } -+ -+// QSPI Pins -+#define PIN_QSPI_SCK (0 + 3) -+#define PIN_QSPI_CS (0 + 26) -+#define PIN_QSPI_IO0 (0 + 30) -+#define PIN_QSPI_IO1 (0 + 29) -+#define PIN_QSPI_IO2 (0 + 28) -+#define PIN_QSPI_IO3 (0 + 2) -+ -+// On-board QSPI Flash -+#define EXTERNAL_FLASH_DEVICES W25Q32JVSS -+#define EXTERNAL_FLASH_USE_QSPI -+ -+// NFC is disabled via CONFIG_NFCT_PINS_AS_GPIOS=1 build flag -+// This configures P0.09 and P0.10 as regular GPIO pins instead of NFC pins -+ -+#ifdef __cplusplus -+} -+#endif -+ -+/*---------------------------------------------------------------------------- -+ * Arduino objects - C++ only -+ *----------------------------------------------------------------------------*/ -+#ifdef __cplusplus -+#endif -+ -+#endif // _VARIANT_MUZI_BASE_ -\ No newline at end of file -diff --git a/variants/nrf52840/r1-neo/variant.h b/variants/nrf52840/r1-neo/variant.h -index 901e993e3..b1d96ebd0 100644 ---- a/variants/nrf52840/r1-neo/variant.h -+++ b/variants/nrf52840/r1-neo/variant.h -@@ -132,7 +132,8 @@ static const uint8_t SCK = PIN_SPI_SCK; - #undef AREF_VOLTAGE - #define AREF_VOLTAGE 3.0 - #define VBAT_AR_INTERNAL AR_INTERNAL_3_0 --#define ADC_MULTIPLIER 1.73 -+#define ADC_MULTIPLIER 1.667 -+#define OCV_ARRAY 4120, 4020, 4000, 3940, 3870, 3820, 3750, 3630, 3550, 3450, 3100 - - #define HAS_RTC 1 - -diff --git a/variants/nrf52840/t-echo/variant.h b/variants/nrf52840/t-echo/variant.h -index 4f3a53ebf..b2692e448 100644 ---- a/variants/nrf52840/t-echo/variant.h -+++ b/variants/nrf52840/t-echo/variant.h -@@ -182,13 +182,13 @@ External serial flash WP25R1635FZUIL0 - #define PIN_GPS_STANDBY (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake - // Seems to be missing on this new board - // #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS --#define GPS_TX_PIN (32 + 9) // This is for bits going TOWARDS the CPU --#define GPS_RX_PIN (32 + 8) // This is for bits going TOWARDS the GPS -+#define GPS_TX_PIN (32 + 8) // This is for bits going TOWARDS the CPU -+#define GPS_RX_PIN (32 + 9) // This is for bits going TOWARDS the GPS - - #define GPS_THREAD_INTERVAL 50 - --#define PIN_SERIAL1_RX GPS_TX_PIN --#define PIN_SERIAL1_TX GPS_RX_PIN -+#define PIN_SERIAL1_RX GPS_RX_PIN -+#define PIN_SERIAL1_TX GPS_TX_PIN - - // PCF8563 RTC Module - #define PCF8563_RTC 0x51