mirror of
https://github.com/meshtastic/firmware.git
synced 2025-07-31 02:45:41 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
9f8ef6e08b
40
.github/workflows/build_esp32.yml
vendored
40
.github/workflows/build_esp32.yml
vendored
@ -1,40 +0,0 @@
|
|||||||
name: Build ESP32
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
board:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-esp32:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
shell: bash
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Build ESP32
|
|
||||||
id: build
|
|
||||||
uses: meshtastic/gh-action-firmware@main
|
|
||||||
with:
|
|
||||||
pio_platform: esp32
|
|
||||||
pio_env: ${{ inputs.board }}
|
|
||||||
pio_target: build
|
|
||||||
ota_firmware_source: firmware.bin
|
|
||||||
ota_firmware_target: release/bleota.bin
|
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: firmware-esp32-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
|
||||||
overwrite: true
|
|
||||||
path: |
|
|
||||||
release/*.bin
|
|
||||||
release/*.elf
|
|
40
.github/workflows/build_esp32_c3.yml
vendored
40
.github/workflows/build_esp32_c3.yml
vendored
@ -1,40 +0,0 @@
|
|||||||
name: Build ESP32-C3
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
board:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-esp32-c3:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
shell: bash
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Build ESP32-C3
|
|
||||||
id: build
|
|
||||||
uses: meshtastic/gh-action-firmware@main
|
|
||||||
with:
|
|
||||||
pio_platform: esp32
|
|
||||||
pio_env: ${{ inputs.board }}
|
|
||||||
pio_target: build
|
|
||||||
ota_firmware_source: firmware-c3.bin
|
|
||||||
ota_firmware_target: release/bleota-c3.bin
|
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: firmware-esp32c3-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
|
||||||
overwrite: true
|
|
||||||
path: |
|
|
||||||
release/*.bin
|
|
||||||
release/*.elf
|
|
40
.github/workflows/build_esp32_c6.yml
vendored
40
.github/workflows/build_esp32_c6.yml
vendored
@ -1,40 +0,0 @@
|
|||||||
name: Build ESP32-C6
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
board:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-esp32-c6:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
shell: bash
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Build ESP32-C6
|
|
||||||
id: build
|
|
||||||
uses: meshtastic/gh-action-firmware@main
|
|
||||||
with:
|
|
||||||
pio_platform: esp32
|
|
||||||
pio_env: ${{ inputs.board }}
|
|
||||||
pio_target: build
|
|
||||||
ota_firmware_source: firmware-c3.bin
|
|
||||||
ota_firmware_target: release/bleota-c3.bin
|
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: firmware-esp32c6-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
|
||||||
overwrite: true
|
|
||||||
path: |
|
|
||||||
release/*.bin
|
|
||||||
release/*.elf
|
|
40
.github/workflows/build_esp32_s3.yml
vendored
40
.github/workflows/build_esp32_s3.yml
vendored
@ -1,40 +0,0 @@
|
|||||||
name: Build ESP32-S3
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
board:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-esp32-s3:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
shell: bash
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Build ESP32-S3
|
|
||||||
id: build
|
|
||||||
uses: meshtastic/gh-action-firmware@main
|
|
||||||
with:
|
|
||||||
pio_platform: esp32
|
|
||||||
pio_env: ${{ inputs.board }}
|
|
||||||
pio_target: build
|
|
||||||
ota_firmware_source: firmware-s3.bin
|
|
||||||
ota_firmware_target: release/bleota-s3.bin
|
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: firmware-esp32s3-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
|
||||||
overwrite: true
|
|
||||||
path: |
|
|
||||||
release/*.bin
|
|
||||||
release/*.elf
|
|
66
.github/workflows/build_firmware.yml
vendored
Normal file
66
.github/workflows/build_firmware.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
platform:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
pio_env:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
permissions: read-all
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pio-build:
|
||||||
|
name: build-${{ inputs.platform }}
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- name: Set OTA firmware source and target
|
||||||
|
if: startsWith(inputs.platform, 'esp32')
|
||||||
|
id: ota_dir
|
||||||
|
env:
|
||||||
|
PIO_PLATFORM: ${{ inputs.platform }}
|
||||||
|
run: |
|
||||||
|
if [ "$PIO_PLATFORM" = "esp32s3" ]; then
|
||||||
|
echo "src=firmware-s3.bin" >> $GITHUB_OUTPUT
|
||||||
|
echo "tgt=release/bleota-s3.bin" >> $GITHUB_OUTPUT
|
||||||
|
elif [ "$PIO_PLATFORM" = "esp32c3" ] || [ "$PIO_PLATFORM" = "esp32c6" ]; then
|
||||||
|
echo "src=firmware-c3.bin" >> $GITHUB_OUTPUT
|
||||||
|
echo "tgt=release/bleota-c3.bin" >> $GITHUB_OUTPUT
|
||||||
|
elif [ "$PIO_PLATFORM" = "esp32" ]; then
|
||||||
|
echo "src=firmware.bin" >> $GITHUB_OUTPUT
|
||||||
|
echo "tgt=release/bleota.bin" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build ${{ inputs.platform }}
|
||||||
|
id: build
|
||||||
|
uses: meshtastic/gh-action-firmware@main
|
||||||
|
with:
|
||||||
|
pio_platform: ${{ inputs.platform }}
|
||||||
|
pio_env: ${{ inputs.pio_env }}
|
||||||
|
pio_target: build
|
||||||
|
ota_firmware_source: ${{ steps.ota_dir.outputs.src || '' }}
|
||||||
|
ota_firmware_target: ${{ steps.ota_dir.outputs.tgt || '' }}
|
||||||
|
|
||||||
|
- name: Store binaries as an artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
release/*.bin
|
||||||
|
release/*.elf
|
||||||
|
release/*.uf2
|
||||||
|
release/*.hex
|
||||||
|
release/*-ota.zip
|
40
.github/workflows/build_nrf52.yml
vendored
40
.github/workflows/build_nrf52.yml
vendored
@ -1,40 +0,0 @@
|
|||||||
name: Build NRF52
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
board:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-nrf52:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
shell: bash
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Build NRF52
|
|
||||||
id: build
|
|
||||||
uses: meshtastic/gh-action-firmware@main
|
|
||||||
with:
|
|
||||||
pio_platform: nrf52
|
|
||||||
pio_env: ${{ inputs.board }}
|
|
||||||
pio_target: build
|
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: firmware-nrf52840-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
|
||||||
overwrite: true
|
|
||||||
path: |
|
|
||||||
release/*.uf2
|
|
||||||
release/*.elf
|
|
||||||
release/*.hex
|
|
||||||
release/*-ota.zip
|
|
38
.github/workflows/build_rpi2040.yml
vendored
38
.github/workflows/build_rpi2040.yml
vendored
@ -1,38 +0,0 @@
|
|||||||
name: Build RPI2040
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
board:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-rpi2040:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
shell: bash
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Build Raspberry Pi 2040
|
|
||||||
id: build
|
|
||||||
uses: meshtastic/gh-action-firmware@main
|
|
||||||
with:
|
|
||||||
pio_platform: rp2xx0
|
|
||||||
pio_env: ${{ inputs.board }}
|
|
||||||
pio_target: build
|
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: firmware-rp2040-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
|
||||||
overwrite: true
|
|
||||||
path: |
|
|
||||||
release/*.uf2
|
|
||||||
release/*.elf
|
|
39
.github/workflows/build_stm32.yml
vendored
39
.github/workflows/build_stm32.yml
vendored
@ -1,39 +0,0 @@
|
|||||||
name: Build STM32
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
board:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-stm32:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
shell: bash
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Build STM32WL
|
|
||||||
id: build
|
|
||||||
uses: meshtastic/gh-action-firmware@main
|
|
||||||
with:
|
|
||||||
pio_platform: stm32wl
|
|
||||||
pio_env: ${{ inputs.board }}
|
|
||||||
pio_target: build
|
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: firmware-stm32-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
|
|
||||||
overwrite: true
|
|
||||||
path: |
|
|
||||||
release/*.hex
|
|
||||||
release/*.bin
|
|
||||||
release/*.elf
|
|
226
.github/workflows/main_matrix.yml
vendored
226
.github/workflows/main_matrix.yml
vendored
@ -30,18 +30,31 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32, check]
|
arch:
|
||||||
runs-on: ubuntu-latest
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
|
- check
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- id: checkout
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- uses: actions/setup-python@v5
|
||||||
name: Checkout base
|
with:
|
||||||
- id: jsonStep
|
python-version: 3.x
|
||||||
|
cache: pip
|
||||||
|
- run: pip install -U platformio
|
||||||
|
- name: Generate matrix
|
||||||
|
id: jsonStep
|
||||||
run: |
|
run: |
|
||||||
if [[ "$GITHUB_HEAD_REF" == "" ]]; then
|
if [[ "$GITHUB_HEAD_REF" == "" ]]; then
|
||||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
|
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
|
||||||
else
|
else
|
||||||
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
|
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} pr)
|
||||||
fi
|
fi
|
||||||
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF Targets: $TARGETS"
|
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF Targets: $TARGETS"
|
||||||
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
|
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
|
||||||
@ -52,9 +65,25 @@ jobs:
|
|||||||
esp32c6: ${{ steps.jsonStep.outputs.esp32c6 }}
|
esp32c6: ${{ steps.jsonStep.outputs.esp32c6 }}
|
||||||
nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
|
nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
|
||||||
rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
|
rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
|
||||||
|
rp2350: ${{ steps.jsonStep.outputs.rp2350 }}
|
||||||
stm32: ${{ steps.jsonStep.outputs.stm32 }}
|
stm32: ${{ steps.jsonStep.outputs.stm32 }}
|
||||||
check: ${{ steps.jsonStep.outputs.check }}
|
check: ${{ steps.jsonStep.outputs.check }}
|
||||||
|
|
||||||
|
version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- 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 }}
|
||||||
|
|
||||||
check:
|
check:
|
||||||
needs: setup
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
@ -72,67 +101,92 @@ jobs:
|
|||||||
run: bin/check-all.sh ${{ matrix.board }}
|
run: bin/check-all.sh ${{ matrix.board }}
|
||||||
|
|
||||||
build-esp32:
|
build-esp32:
|
||||||
needs: setup
|
needs: [setup, version]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix: ${{ fromJson(needs.setup.outputs.esp32) }}
|
matrix: ${{ fromJson(needs.setup.outputs.esp32) }}
|
||||||
uses: ./.github/workflows/build_esp32.yml
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32
|
||||||
|
|
||||||
build-esp32-s3:
|
build-esp32s3:
|
||||||
needs: setup
|
needs: [setup, version]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix: ${{ fromJson(needs.setup.outputs.esp32s3) }}
|
matrix: ${{ fromJson(needs.setup.outputs.esp32s3) }}
|
||||||
uses: ./.github/workflows/build_esp32_s3.yml
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32s3
|
||||||
|
|
||||||
build-esp32-c3:
|
build-esp32c3:
|
||||||
needs: setup
|
needs: [setup, version]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
|
matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
|
||||||
uses: ./.github/workflows/build_esp32_c3.yml
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32c3
|
||||||
|
|
||||||
build-esp32-c6:
|
build-esp32c6:
|
||||||
needs: setup
|
needs: [setup, version]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix: ${{ fromJson(needs.setup.outputs.esp32c6) }}
|
matrix: ${{ fromJson(needs.setup.outputs.esp32c6) }}
|
||||||
uses: ./.github/workflows/build_esp32_c6.yml
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: esp32c6
|
||||||
|
|
||||||
build-nrf52:
|
build-nrf52840:
|
||||||
needs: setup
|
needs: [setup, version]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
|
matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
|
||||||
uses: ./.github/workflows/build_nrf52.yml
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: nrf52840
|
||||||
|
|
||||||
build-rpi2040:
|
build-rp2040:
|
||||||
needs: setup
|
needs: [setup, version]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
|
matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
|
||||||
uses: ./.github/workflows/build_rpi2040.yml
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: rp2040
|
||||||
|
|
||||||
|
build-rp2350:
|
||||||
|
needs: [setup, version]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.rp2350) }}
|
||||||
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
|
with:
|
||||||
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: rp2350
|
||||||
|
|
||||||
build-stm32:
|
build-stm32:
|
||||||
needs: setup
|
needs: [setup, version]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix: ${{ fromJson(needs.setup.outputs.stm32) }}
|
matrix: ${{ fromJson(needs.setup.outputs.stm32) }}
|
||||||
uses: ./.github/workflows/build_stm32.yml
|
uses: ./.github/workflows/build_firmware.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
version: ${{ needs.version.outputs.long }}
|
||||||
|
pio_env: ${{ matrix.board }}
|
||||||
|
platform: stm32
|
||||||
|
|
||||||
build-debian-src:
|
build-debian-src:
|
||||||
if: github.repository == 'meshtastic/firmware'
|
if: github.repository == 'meshtastic/firmware'
|
||||||
@ -210,16 +264,26 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32]
|
arch:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
[
|
[
|
||||||
|
version,
|
||||||
build-esp32,
|
build-esp32,
|
||||||
build-esp32-s3,
|
build-esp32s3,
|
||||||
build-esp32-c3,
|
build-esp32c3,
|
||||||
build-esp32-c6,
|
build-esp32c6,
|
||||||
build-nrf52,
|
build-nrf52840,
|
||||||
build-rpi2040,
|
build-rp2040,
|
||||||
|
build-rp2350,
|
||||||
build-stm32,
|
build-stm32,
|
||||||
]
|
]
|
||||||
steps:
|
steps:
|
||||||
@ -238,17 +302,13 @@ jobs:
|
|||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
run: ls -R
|
run: ls -R
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Move files up
|
- name: Move files up
|
||||||
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
|
||||||
|
|
||||||
- name: Repackage in single firmware zip
|
- name: Repackage in single firmware zip
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||||
overwrite: true
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
./firmware-*.bin
|
./firmware-*.bin
|
||||||
@ -264,7 +324,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
path: ./output
|
path: ./output
|
||||||
|
|
||||||
@ -278,12 +338,12 @@ jobs:
|
|||||||
chmod +x ./output/device-update.sh
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
- name: Zip firmware
|
- name: Zip firmware
|
||||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./output
|
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||||
|
|
||||||
- name: Repackage in single elfs zip
|
- name: Repackage in single elfs zip
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
overwrite: true
|
overwrite: true
|
||||||
path: ./*.elf
|
path: ./*.elf
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
@ -291,8 +351,8 @@ jobs:
|
|||||||
- uses: scruplelesswizard/comment-artifact@main
|
- uses: scruplelesswizard/comment-artifact@main
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||||
description: "Download firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
|
description: "Download firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
release-artifacts:
|
release-artifacts:
|
||||||
@ -301,6 +361,7 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
needs:
|
needs:
|
||||||
|
- version
|
||||||
- gather-artifacts
|
- gather-artifacts
|
||||||
- build-debian-src
|
- build-debian-src
|
||||||
- package-pio-deps-native-tft
|
- package-pio-deps-native-tft
|
||||||
@ -313,44 +374,36 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
- 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
|
|
||||||
|
|
||||||
- name: Create release
|
- name: Create release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
id: create_release
|
id: create_release
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
name: Meshtastic Firmware ${{ steps.version.outputs.long }} Alpha
|
name: Meshtastic Firmware ${{ needs.version.outputs.long }} Alpha
|
||||||
tag_name: v${{ steps.version.outputs.long }}
|
tag_name: v${{ needs.version.outputs.long }}
|
||||||
body: |
|
body: |
|
||||||
Autogenerated by github action, developer should edit as required before publishing...
|
Autogenerated by github action, developer should edit as required before publishing...
|
||||||
|
|
||||||
- name: Download source deb
|
- name: Download source deb
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
pattern: firmware-debian-${{ steps.version.outputs.deb }}~UNRELEASED-src
|
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
path: ./output/debian-src
|
path: ./output/debian-src
|
||||||
|
|
||||||
- name: Download `native-tft` pio deps
|
- name: Download `native-tft` pio deps
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
pattern: platformio-deps-native-tft-${{ steps.version.outputs.long }}
|
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
path: ./output/pio-deps-native-tft
|
path: ./output/pio-deps-native-tft
|
||||||
|
|
||||||
- name: Zip Linux sources
|
- name: Zip Linux sources
|
||||||
working-directory: output
|
working-directory: output
|
||||||
run: |
|
run: |
|
||||||
zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src
|
zip -j -9 -r ./meshtasticd-${{ needs.version.outputs.deb }}-src.zip ./debian-src
|
||||||
zip -9 -r ./platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip ./pio-deps-native-tft
|
zip -9 -r ./platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip ./pio-deps-native-tft
|
||||||
|
|
||||||
# For diagnostics
|
# For diagnostics
|
||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
@ -360,8 +413,8 @@ jobs:
|
|||||||
# Only run when targeting master branch with workflow_dispatch
|
# Only run when targeting master branch with workflow_dispatch
|
||||||
if: ${{ github.ref_name == 'master' }}
|
if: ${{ github.ref_name == 'master' }}
|
||||||
run: |
|
run: |
|
||||||
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip
|
gh release upload v${{ needs.version.outputs.long }} ./output/meshtasticd-${{ needs.version.outputs.deb }}-src.zip
|
||||||
gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip
|
gh release upload v${{ needs.version.outputs.long }} ./output/platformio-deps-native-tft-${{ needs.version.outputs.long }}.zip
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
@ -369,10 +422,18 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
arch: [esp32, esp32s3, esp32c3, esp32c6, nrf52840, rp2040, stm32]
|
arch:
|
||||||
|
- esp32
|
||||||
|
- esp32s3
|
||||||
|
- esp32c3
|
||||||
|
- esp32c6
|
||||||
|
- nrf52840
|
||||||
|
- rp2040
|
||||||
|
- rp2350
|
||||||
|
- stm32
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
needs: [release-artifacts]
|
needs: [release-artifacts, version]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -382,13 +443,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
pattern: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
|
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
path: ./output
|
path: ./output
|
||||||
|
|
||||||
@ -401,16 +458,16 @@ jobs:
|
|||||||
chmod +x ./output/device-update.sh
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
- name: Zip firmware
|
- name: Zip firmware
|
||||||
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./output
|
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
path: ./elfs
|
path: ./elfs
|
||||||
|
|
||||||
- name: Zip debug elfs
|
- name: Zip debug elfs
|
||||||
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./elfs
|
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./elfs
|
||||||
|
|
||||||
# For diagnostics
|
# For diagnostics
|
||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
@ -420,17 +477,18 @@ jobs:
|
|||||||
# Only run when targeting master branch with workflow_dispatch
|
# Only run when targeting master branch with workflow_dispatch
|
||||||
if: ${{ github.ref_name == 'master' }}
|
if: ${{ github.ref_name == 'master' }}
|
||||||
run: |
|
run: |
|
||||||
gh release upload v${{ steps.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
gh release upload v${{ needs.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
gh release upload v${{ steps.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
|
gh release upload v${{ needs.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
publish-firmware:
|
publish-firmware:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
needs: [release-firmware]
|
needs: [release-firmware, version]
|
||||||
env:
|
env:
|
||||||
targets: esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,stm32
|
targets: |-
|
||||||
|
esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -440,13 +498,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
pattern: firmware-{${{ env.targets }}}-${{ steps.version.outputs.long }}
|
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
path: ./publish
|
path: ./publish
|
||||||
|
|
||||||
@ -460,9 +514,9 @@ jobs:
|
|||||||
external_repository: meshtastic/meshtastic.github.io
|
external_repository: meshtastic/meshtastic.github.io
|
||||||
publish_branch: master
|
publish_branch: master
|
||||||
publish_dir: ./publish
|
publish_dir: ./publish
|
||||||
destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ steps.version.outputs.long }}
|
destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ needs.version.outputs.long }}
|
||||||
keep_files: true
|
keep_files: true
|
||||||
user_name: github-actions[bot]
|
user_name: github-actions[bot]
|
||||||
user_email: github-actions[bot]@users.noreply.github.com
|
user_email: github-actions[bot]@users.noreply.github.com
|
||||||
commit_message: ${{ steps.version.outputs.long }}
|
commit_message: ${{ needs.version.outputs.long }}
|
||||||
enable_jekyll: true
|
enable_jekyll: true
|
||||||
|
@ -9,14 +9,14 @@ plugins:
|
|||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- checkov@3.2.451
|
- checkov@3.2.451
|
||||||
- renovate@41.37.9
|
- renovate@41.40.0
|
||||||
- prettier@3.6.2
|
- prettier@3.6.2
|
||||||
- trufflehog@3.90.0
|
- trufflehog@3.90.1
|
||||||
- yamllint@1.37.1
|
- yamllint@1.37.1
|
||||||
- bandit@1.8.6
|
- bandit@1.8.6
|
||||||
- trivy@0.64.1
|
- trivy@0.64.1
|
||||||
- taplo@0.9.3
|
- taplo@0.9.3
|
||||||
- ruff@0.12.3
|
- ruff@0.12.4
|
||||||
- isort@6.0.1
|
- isort@6.0.1
|
||||||
- markdownlint@0.45.0
|
- markdownlint@0.45.0
|
||||||
- oxipng@9.1.5
|
- oxipng@9.1.5
|
||||||
@ -28,7 +28,7 @@ lint:
|
|||||||
- shellcheck@0.10.0
|
- shellcheck@0.10.0
|
||||||
- black@25.1.0
|
- black@25.1.0
|
||||||
- git-diff-check
|
- git-diff-check
|
||||||
- gitleaks@8.27.2
|
- gitleaks@8.28.0
|
||||||
- clang-format@16.0.3
|
- clang-format@16.0.3
|
||||||
ignore:
|
ignore:
|
||||||
- linters: [ALL]
|
- linters: [ALL]
|
||||||
|
@ -54,8 +54,8 @@ lib_deps =
|
|||||||
h2zero/NimBLE-Arduino@^1.4.3
|
h2zero/NimBLE-Arduino@^1.4.3
|
||||||
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
|
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
|
||||||
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
|
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
|
||||||
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
|
# renovate: datasource=github-tags depName=XPowersLib packageName=lewisxhe/XPowersLib
|
||||||
lewisxhe/XPowersLib@0.3.0
|
https://github.com/lewisxhe/XPowersLib/archive/v0.3.0.zip
|
||||||
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||||
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||||
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||||
|
@ -11,7 +11,7 @@ elif (echo $2 | grep -q "nrf52"); then
|
|||||||
elif (echo $2 | grep -q "stm32"); then
|
elif (echo $2 | grep -q "stm32"); then
|
||||||
bin/build-stm32.sh $1
|
bin/build-stm32.sh $1
|
||||||
elif (echo $2 | grep -q "rpi2040"); then
|
elif (echo $2 | grep -q "rpi2040"); then
|
||||||
bin/build-rpi2040.sh $1
|
bin/build-rp2xx0.sh $1
|
||||||
else
|
else
|
||||||
echo "Unknown target $2"
|
echo "Unknown target $2"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
"""Generate the CI matrix."""
|
"""Generate the CI matrix."""
|
||||||
|
|
||||||
import configparser
|
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
rootdir = "variants/"
|
from platformio.project.config import ProjectConfig
|
||||||
|
|
||||||
options = sys.argv[1:]
|
options = sys.argv[1:]
|
||||||
|
|
||||||
@ -16,36 +14,59 @@ outlist = []
|
|||||||
|
|
||||||
if len(options) < 1:
|
if len(options) < 1:
|
||||||
print(json.dumps(outlist))
|
print(json.dumps(outlist))
|
||||||
exit()
|
exit(1)
|
||||||
|
|
||||||
for subdir, dirs, files in os.walk(rootdir):
|
cfg = ProjectConfig.get_instance()
|
||||||
for file in files:
|
pio_envs = cfg.envs()
|
||||||
if file == "platformio.ini":
|
|
||||||
config = configparser.ConfigParser()
|
# Gather all PlatformIO environments for filtering later
|
||||||
config.read(subdir + "/" + file)
|
all_envs = []
|
||||||
for c in config.sections():
|
for pio_env in pio_envs:
|
||||||
if c.startswith("env:"):
|
env_build_flags = cfg.get(f"env:{pio_env}", 'build_flags')
|
||||||
section = config[c].name[4:]
|
env_platform = None
|
||||||
if "extends" in config[config[c].name]:
|
for flag in env_build_flags:
|
||||||
if options[0] + "_base" in config[config[c].name]["extends"]:
|
# Extract the platform from the build flags
|
||||||
if "board_level" in config[config[c].name]:
|
# Example flag: -I variants/esp32s3/heltec-v3
|
||||||
if (
|
match = re.search(r"-I\s?variants/([^/]+)", flag)
|
||||||
config[config[c].name]["board_level"] == "extra"
|
if match:
|
||||||
) & ("extra" in options):
|
env_platform = match.group(1)
|
||||||
outlist.append(section)
|
break
|
||||||
|
# Intentionally fail if platform cannot be determined
|
||||||
|
if not env_platform:
|
||||||
|
print(f"Error: Could not determine platform for environment '{pio_env}'")
|
||||||
|
exit(1)
|
||||||
|
# Store env details as a dictionary, and add to 'all_envs' list
|
||||||
|
env = {
|
||||||
|
'name': pio_env,
|
||||||
|
'platform': env_platform,
|
||||||
|
'board_level': cfg.get(f"env:{pio_env}", 'board_level', default=None),
|
||||||
|
'board_check': bool(cfg.get(f"env:{pio_env}", 'board_check', default=False))
|
||||||
|
}
|
||||||
|
all_envs.append(env)
|
||||||
|
|
||||||
|
# Filter outputs based on options
|
||||||
|
# Check is mutually exclusive with other options (except 'pr')
|
||||||
|
if "check" in options:
|
||||||
|
for env in all_envs:
|
||||||
|
if env['board_check']:
|
||||||
|
if "pr" in options:
|
||||||
|
if env['board_level'] == 'pr':
|
||||||
|
outlist.append(env['name'])
|
||||||
else:
|
else:
|
||||||
outlist.append(section)
|
outlist.append(env['name'])
|
||||||
# Add the TFT variants if the base variant is selected
|
# Filter (non-check) builds by platform
|
||||||
elif section.replace("-tft", "") in outlist and config[config[c].name].get("board_level") != "extra":
|
|
||||||
outlist.append(section)
|
|
||||||
elif section.replace("-inkhud", "") in outlist and config[config[c].name].get("board_level") != "extra":
|
|
||||||
outlist.append(section)
|
|
||||||
if "board_check" in config[config[c].name]:
|
|
||||||
if (config[config[c].name]["board_check"] == "true") & (
|
|
||||||
"check" in options
|
|
||||||
):
|
|
||||||
outlist.append(section)
|
|
||||||
if ("quick" in options) & (len(outlist) > 3):
|
|
||||||
print(json.dumps(random.sample(outlist, 3)))
|
|
||||||
else:
|
else:
|
||||||
print(json.dumps(outlist))
|
for env in all_envs:
|
||||||
|
if options[0] == env['platform']:
|
||||||
|
# Always include board_level = 'pr'
|
||||||
|
if env['board_level'] == 'pr':
|
||||||
|
outlist.append(env['name'])
|
||||||
|
# Include board_level = 'extra' when requested
|
||||||
|
elif "extra" in options and env['board_level'] == "extra":
|
||||||
|
outlist.append(env['name'])
|
||||||
|
# If no board level is specified, include in release builds (not PR)
|
||||||
|
elif "pr" not in options and not env['board_level']:
|
||||||
|
outlist.append(env['name'])
|
||||||
|
|
||||||
|
# Return as a JSON list
|
||||||
|
print(json.dumps(outlist))
|
||||||
|
43
boards/t-deck-pro.json
Normal file
43
boards/t-deck-pro.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"memory_type": "qio_qspi",
|
||||||
|
"partitions": "default_16MB.csv"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [["0x303A", "0x1001"]],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "esp32s3"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||||
|
"debug": {
|
||||||
|
"default_tool": "esp-builtin",
|
||||||
|
"onboard_tools": ["esp-builtin"],
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "LilyGo T-Deck Pro S3 (16M Flash 8M QSPI PSRAM )",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"monitor": {
|
||||||
|
"speed": 115200
|
||||||
|
},
|
||||||
|
"url": "https://lilygo.cc/products/t-deck-pro",
|
||||||
|
"vendor": "LilyGo"
|
||||||
|
}
|
@ -6,7 +6,6 @@ default_envs = tbeam
|
|||||||
|
|
||||||
extra_configs =
|
extra_configs =
|
||||||
arch/*/*.ini
|
arch/*/*.ini
|
||||||
variants/*/platformio.ini ; Remove when all variants migrated to new dir structure
|
|
||||||
variants/*/*/platformio.ini
|
variants/*/*/platformio.ini
|
||||||
variants/*/diy/*/platformio.ini
|
variants/*/diy/*/platformio.ini
|
||||||
src/graphics/niche/InkHUD/PlatformioConfig.ini
|
src/graphics/niche/InkHUD/PlatformioConfig.ini
|
||||||
@ -111,7 +110,7 @@ lib_deps =
|
|||||||
[device-ui_base]
|
[device-ui_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||||
https://github.com/meshtastic/device-ui/archive/86a09a7360f92d10053fbbf8d74f67f85b0ceb09.zip
|
https://github.com/meshtastic/device-ui/archive/c75d545bf9e8d1fe20051c319f427f711113ff22.zip
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
[environmental_base]
|
[environmental_base]
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 15c1fbde882de953dec279160fa984d0e00569d0
|
Subproject commit d31cd890d58ffa7e3524e0685a8617bbd181a1c6
|
198
src/Power.cpp
198
src/Power.cpp
@ -20,6 +20,11 @@
|
|||||||
#include "meshUtils.h"
|
#include "meshUtils.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
|
||||||
|
#if defined(ARCH_PORTDUINO)
|
||||||
|
#include "api/WiFiServerAPI.h"
|
||||||
|
#include "input/LinuxInputImpl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Working USB detection for powered/charging states on the RAK platform
|
// Working USB detection for powered/charging states on the RAK platform
|
||||||
#ifdef NRF_APM
|
#ifdef NRF_APM
|
||||||
#include "nrfx_power.h"
|
#include "nrfx_power.h"
|
||||||
@ -120,6 +125,15 @@ NullSensor max17048Sensor;
|
|||||||
RAK9154Sensor rak9154Sensor;
|
RAK9154Sensor rak9154Sensor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_PPM
|
||||||
|
// note: XPOWERS_CHIP_XXX must be defined in variant.h
|
||||||
|
#include <XPowersLib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_BQ27220
|
||||||
|
#include "bq27220.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_PMU
|
#ifdef HAS_PMU
|
||||||
XPowersLibInterface *PMU = NULL;
|
XPowersLibInterface *PMU = NULL;
|
||||||
#else
|
#else
|
||||||
@ -665,6 +679,8 @@ bool Power::setup()
|
|||||||
found = true;
|
found = true;
|
||||||
} else if (lipoInit()) {
|
} else if (lipoInit()) {
|
||||||
found = true;
|
found = true;
|
||||||
|
} else if (lipoChargerInit()) {
|
||||||
|
found = true;
|
||||||
} else if (analogInit()) {
|
} else if (analogInit()) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
@ -679,6 +695,47 @@ bool Power::setup()
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Power::powerCommandsCheck()
|
||||||
|
{
|
||||||
|
if (rebootAtMsec && millis() > rebootAtMsec) {
|
||||||
|
LOG_INFO("Rebooting");
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shutdownAtMsec && millis() > shutdownAtMsec) {
|
||||||
|
shutdownAtMsec = 0;
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Power::reboot()
|
||||||
|
{
|
||||||
|
notifyReboot.notifyObservers(NULL);
|
||||||
|
#if defined(ARCH_ESP32)
|
||||||
|
ESP.restart();
|
||||||
|
#elif defined(ARCH_NRF52)
|
||||||
|
NVIC_SystemReset();
|
||||||
|
#elif defined(ARCH_RP2040)
|
||||||
|
rp2040.reboot();
|
||||||
|
#elif defined(ARCH_PORTDUINO)
|
||||||
|
deInitApiServer();
|
||||||
|
if (aLinuxInputImpl)
|
||||||
|
aLinuxInputImpl->deInit();
|
||||||
|
SPI.end();
|
||||||
|
Wire.end();
|
||||||
|
Serial1.end();
|
||||||
|
if (screen)
|
||||||
|
delete screen;
|
||||||
|
LOG_DEBUG("final reboot!");
|
||||||
|
reboot();
|
||||||
|
#elif defined(ARCH_STM32WL)
|
||||||
|
HAL_NVIC_SystemReset();
|
||||||
|
#else
|
||||||
|
rebootAtMsec = -1;
|
||||||
|
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void Power::shutdown()
|
void Power::shutdown()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1250,3 +1307,144 @@ bool Power::lipoInit()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAS_PPM) && HAS_PPM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter class for BQ25896/BQ27220 Lipo battery charger.
|
||||||
|
*/
|
||||||
|
class LipoCharger : public HasBatteryLevel
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
XPowersPPM *ppm = nullptr;
|
||||||
|
BQ27220 *bq = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Init the I2C BQ25896 Lipo battery charger
|
||||||
|
*/
|
||||||
|
bool runOnce()
|
||||||
|
{
|
||||||
|
if (ppm == nullptr) {
|
||||||
|
ppm = new XPowersPPM;
|
||||||
|
bool result = ppm->init(Wire, I2C_SDA, I2C_SCL, BQ25896_ADDR);
|
||||||
|
if (result) {
|
||||||
|
LOG_INFO("PPM BQ25896 init succeeded");
|
||||||
|
// Set the minimum operating voltage. Below this voltage, the PPM will protect
|
||||||
|
// ppm->setSysPowerDownVoltage(3100);
|
||||||
|
|
||||||
|
// Set input current limit, default is 500mA
|
||||||
|
// ppm->setInputCurrentLimit(800);
|
||||||
|
|
||||||
|
// Disable current limit pin
|
||||||
|
// ppm->disableCurrentLimitPin();
|
||||||
|
|
||||||
|
// Set the charging target voltage, Range:3840 ~ 4608mV ,step:16 mV
|
||||||
|
ppm->setChargeTargetVoltage(4288);
|
||||||
|
|
||||||
|
// Set the precharge current , Range: 64mA ~ 1024mA ,step:64mA
|
||||||
|
// ppm->setPrechargeCurr(64);
|
||||||
|
|
||||||
|
// The premise is that limit pin is disabled, or it will
|
||||||
|
// only follow the maximum charging current set by limit pin.
|
||||||
|
// Set the charging current , Range:0~5056mA ,step:64mA
|
||||||
|
ppm->setChargerConstantCurr(1024);
|
||||||
|
|
||||||
|
// To obtain voltage data, the ADC must be enabled first
|
||||||
|
ppm->enableMeasure();
|
||||||
|
|
||||||
|
// Turn on charging function
|
||||||
|
// If there is no battery connected, do not turn on the charging function
|
||||||
|
ppm->enableCharge();
|
||||||
|
} else {
|
||||||
|
LOG_WARN("PPM BQ25896 init failed");
|
||||||
|
delete ppm;
|
||||||
|
ppm = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bq == nullptr) {
|
||||||
|
bq = new BQ27220;
|
||||||
|
bq->setDefaultCapacity(BQ27220_DESIGN_CAPACITY);
|
||||||
|
|
||||||
|
bool result = bq->init();
|
||||||
|
if (result) {
|
||||||
|
LOG_DEBUG("BQ27220 design capacity: %d", bq->getDesignCapacity());
|
||||||
|
LOG_DEBUG("BQ27220 fullCharge capacity: %d", bq->getFullChargeCapacity());
|
||||||
|
LOG_DEBUG("BQ27220 remaining capacity: %d", bq->getRemainingCapacity());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
LOG_WARN("BQ27220 init failed");
|
||||||
|
delete bq;
|
||||||
|
bq = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Battery state of charge, from 0 to 100 or -1 for unknown
|
||||||
|
*/
|
||||||
|
virtual int getBatteryPercent() override
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
// return bq->getChargePercent(); // don't use BQ27220 for battery percent, it is not calibrated
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The raw voltage of the battery in millivolts, or NAN if unknown
|
||||||
|
*/
|
||||||
|
virtual uint16_t getBattVoltage() override { return bq->getVoltage(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true if there is a battery installed in this unit
|
||||||
|
*/
|
||||||
|
virtual bool isBatteryConnect() override { return ppm->getBattVoltage() > 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true if there is an external power source detected
|
||||||
|
*/
|
||||||
|
virtual bool isVbusIn() override { return ppm->getVbusVoltage() > 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true if the battery is currently charging
|
||||||
|
*/
|
||||||
|
virtual bool isCharging() override
|
||||||
|
{
|
||||||
|
bool isCharging = ppm->isCharging();
|
||||||
|
if (isCharging) {
|
||||||
|
LOG_DEBUG("BQ27220 time to full charge: %d min", bq->getTimeToFull());
|
||||||
|
} else {
|
||||||
|
if (!ppm->isVbusIn()) {
|
||||||
|
LOG_DEBUG("BQ27220 time to empty: %d min (%d mAh)", bq->getTimeToEmpty(), bq->getRemainingCapacity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isCharging;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LipoCharger lipoCharger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init the Lipo battery charger
|
||||||
|
*/
|
||||||
|
bool Power::lipoChargerInit()
|
||||||
|
{
|
||||||
|
bool result = lipoCharger.runOnce();
|
||||||
|
LOG_DEBUG("Power::lipoChargerInit lipo sensor is %s", result ? "ready" : "not ready yet");
|
||||||
|
if (!result)
|
||||||
|
return false;
|
||||||
|
batteryLevel = &lipoCharger;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* The Lipo battery level sensor is unavailable - default to AnalogBatteryLevel
|
||||||
|
*/
|
||||||
|
bool Power::lipoChargerInit()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -72,7 +72,7 @@ extern Power *power;
|
|||||||
static void shutdownEnter()
|
static void shutdownEnter()
|
||||||
{
|
{
|
||||||
LOG_DEBUG("State: SHUTDOWN");
|
LOG_DEBUG("State: SHUTDOWN");
|
||||||
power->shutdown();
|
shutdownAtMsec = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
@ -150,11 +150,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
// Define if screen should be mirrored left to right
|
// Define if screen should be mirrored left to right
|
||||||
// #define SCREEN_MIRROR
|
// #define SCREEN_MIRROR
|
||||||
|
|
||||||
// I2C Keyboards (M5Stack, RAK14004, T-Deck)
|
// I2C Keyboards (M5Stack, RAK14004, T-Deck, T-Deck Pro, T-Lora Pager, CardKB, BBQ10, MPR121, TCA8418)
|
||||||
#define CARDKB_ADDR 0x5F
|
#define CARDKB_ADDR 0x5F
|
||||||
#define TDECK_KB_ADDR 0x55
|
#define TDECK_KB_ADDR 0x55
|
||||||
#define BBQ10_KB_ADDR 0x1F
|
#define BBQ10_KB_ADDR 0x1F
|
||||||
#define MPR121_KB_ADDR 0x5A
|
#define MPR121_KB_ADDR 0x5A
|
||||||
|
#define TCA8418_KB_ADDR 0x34
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// SENSOR
|
// SENSOR
|
||||||
@ -193,8 +194,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define MLX90614_ADDR_DEF 0x5A
|
#define MLX90614_ADDR_DEF 0x5A
|
||||||
#define CGRADSENS_ADDR 0x66
|
#define CGRADSENS_ADDR 0x66
|
||||||
#define LTR390UV_ADDR 0x53
|
#define LTR390UV_ADDR 0x53
|
||||||
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418
|
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418_KB
|
||||||
#define PCT2075_ADDR 0x37
|
#define PCT2075_ADDR 0x37
|
||||||
|
#define BQ27220_ADDR 0x55 // same address as TDECK_KB
|
||||||
|
#define BQ25896_ADDR 0x6B
|
||||||
|
#define LTR553ALS_ADDR 0x23
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// ACCELEROMETER
|
// ACCELEROMETER
|
||||||
@ -208,6 +212,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define BMX160_ADDR 0x69
|
#define BMX160_ADDR 0x69
|
||||||
#define ICM20948_ADDR 0x69
|
#define ICM20948_ADDR 0x69
|
||||||
#define ICM20948_ADDR_ALT 0x68
|
#define ICM20948_ADDR_ALT 0x68
|
||||||
|
#define BHI260AP_ADDR 0x28
|
||||||
#define BMM150_ADDR 0x13
|
#define BMM150_ADDR 0x13
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -230,6 +235,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
// Touchscreen
|
// Touchscreen
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
#define FT6336U_ADDR 0x48
|
#define FT6336U_ADDR 0x48
|
||||||
|
#define CST328_ADDR 0x1A
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// RAK12035VB Soil Monitor (using RAK12023 up to 3 RAK12035 monitors can be connected)
|
// RAK12035VB Soil Monitor (using RAK12023 up to 3 RAK12035 monitors can be connected)
|
||||||
|
@ -74,7 +74,12 @@ class ScanI2C
|
|||||||
RAK12035,
|
RAK12035,
|
||||||
TCA8418KB,
|
TCA8418KB,
|
||||||
PCT2075,
|
PCT2075,
|
||||||
BMM150,
|
CST328,
|
||||||
|
BQ25896,
|
||||||
|
BQ27220,
|
||||||
|
LTR553ALS,
|
||||||
|
BHI260AP,
|
||||||
|
BMM150
|
||||||
} DeviceType;
|
} DeviceType;
|
||||||
|
|
||||||
// typedef uint8_t DeviceAddress;
|
// typedef uint8_t DeviceAddress;
|
||||||
|
@ -206,7 +206,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address);
|
case TDECK_KB_ADDR:
|
||||||
|
// Do we have the T-Deck keyboard or the T-Deck Pro battery sensor?
|
||||||
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);
|
||||||
|
if (registerValue != 0) {
|
||||||
|
logFoundDevice("BQ27220", (uint8_t)addr.address);
|
||||||
|
type = BQ27220;
|
||||||
|
} else {
|
||||||
|
logFoundDevice("TDECKKB", (uint8_t)addr.address);
|
||||||
|
type = TDECKKB;
|
||||||
|
}
|
||||||
|
break;
|
||||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
|
||||||
|
|
||||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address);
|
||||||
@ -396,6 +406,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
logFoundDevice("BQ24295", (uint8_t)addr.address);
|
logFoundDevice("BQ24295", (uint8_t)addr.address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x14), 1); // get ID
|
||||||
|
if ((registerValue & 0b00000011) == 0b00000010) {
|
||||||
|
type = BQ25896;
|
||||||
|
logFoundDevice("BQ25896", (uint8_t)addr.address);
|
||||||
|
break;
|
||||||
|
}
|
||||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID
|
||||||
if (registerValue == 0x6A) {
|
if (registerValue == 0x6A) {
|
||||||
type = LSM6DS3;
|
type = LSM6DS3;
|
||||||
@ -447,6 +463,9 @@ 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(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(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (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);
|
||||||
|
SCAN_SIMPLE_CASE(LTR553ALS_ADDR, LTR553ALS, "LTR553ALS", (uint8_t)addr.address);
|
||||||
|
SCAN_SIMPLE_CASE(BHI260AP_ADDR, BHI260AP, "BHI260AP", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(SCD4X_ADDR, SCD4X, "SCD4X", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(SCD4X_ADDR, SCD4X, "SCD4X", (uint8_t)addr.address);
|
||||||
SCAN_SIMPLE_CASE(BMM150_ADDR, BMM150, "BMM150", (uint8_t)addr.address);
|
SCAN_SIMPLE_CASE(BMM150_ADDR, BMM150, "BMM150", (uint8_t)addr.address);
|
||||||
#ifdef HAS_TPS65233
|
#ifdef HAS_TPS65233
|
||||||
|
@ -643,8 +643,16 @@ bool GPS::setup()
|
|||||||
delay(250);
|
delay(250);
|
||||||
} else if (IS_ONE_OF(gnssModel, GNSS_MODEL_AG3335, GNSS_MODEL_AG3352)) {
|
} else if (IS_ONE_OF(gnssModel, GNSS_MODEL_AG3335, GNSS_MODEL_AG3352)) {
|
||||||
|
|
||||||
|
if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_IN ||
|
||||||
|
config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_NP_865) {
|
||||||
_serial_gps->write("$PAIR066,1,0,1,0,0,1*3B\r\n"); // Enable GPS+GALILEO+NAVIC
|
_serial_gps->write("$PAIR066,1,0,1,0,0,1*3B\r\n"); // Enable GPS+GALILEO+NAVIC
|
||||||
|
// GPS GLONASS GALILEO BDS QZSS NAVIC
|
||||||
|
// 1 0 1 0 0 1
|
||||||
|
} else {
|
||||||
|
_serial_gps->write("$PAIR066,1,1,1,1,0,0*3A\r\n"); // Enable GPS+GLONASS+GALILEO+BDS
|
||||||
|
// GPS GLONASS GALILEO BDS QZSS NAVIC
|
||||||
|
// 1 1 1 1 0 0
|
||||||
|
}
|
||||||
// Configure NMEA (sentences will output once per fix)
|
// Configure NMEA (sentences will output once per fix)
|
||||||
_serial_gps->write("$PAIR062,0,1*3F\r\n"); // GGA ON
|
_serial_gps->write("$PAIR062,0,1*3F\r\n"); // GGA ON
|
||||||
_serial_gps->write("$PAIR062,1,0*3F\r\n"); // GLL OFF
|
_serial_gps->write("$PAIR062,1,0*3F\r\n"); // GLL OFF
|
||||||
|
@ -206,7 +206,7 @@ bool EInkDisplay::connect()
|
|||||||
adafruitDisplay->setRotation(0);
|
adafruitDisplay->setRotation(0);
|
||||||
adafruitDisplay->setPartialWindow(0, 0, EINK_WIDTH, EINK_HEIGHT);
|
adafruitDisplay->setPartialWindow(0, 0, EINK_WIDTH, EINK_HEIGHT);
|
||||||
}
|
}
|
||||||
#elif defined(M5_COREINK)
|
#elif defined(M5_COREINK) || defined(T_DECK_PRO)
|
||||||
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||||
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||||
adafruitDisplay->init(115200, true, 40, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
adafruitDisplay->init(115200, true, 40, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||||
|
@ -579,7 +579,7 @@ void Screen::setup()
|
|||||||
touchScreenImpl1->init();
|
touchScreenImpl1->init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif HAS_TOUCHSCREEN
|
#elif HAS_TOUCHSCREEN && !defined(USE_EINK)
|
||||||
touchScreenImpl1 =
|
touchScreenImpl1 =
|
||||||
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
|
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
|
||||||
touchScreenImpl1->init();
|
touchScreenImpl1->init();
|
||||||
|
@ -412,9 +412,9 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x,
|
|||||||
float freq = RadioLibInterface::instance->getFreq();
|
float freq = RadioLibInterface::instance->getFreq();
|
||||||
snprintf(freqStr, sizeof(freqStr), "%.3f", freq);
|
snprintf(freqStr, sizeof(freqStr), "%.3f", freq);
|
||||||
if (config.lora.channel_num == 0) {
|
if (config.lora.channel_num == 0) {
|
||||||
snprintf(frequencyslot, sizeof(frequencyslot), "Freq: %smhz", freqStr);
|
snprintf(frequencyslot, sizeof(frequencyslot), "Freq: %sMHz", freqStr);
|
||||||
} else {
|
} else {
|
||||||
snprintf(frequencyslot, sizeof(frequencyslot), "Freq/Ch: %smhz (%d)", freqStr, config.lora.channel_num);
|
snprintf(frequencyslot, sizeof(frequencyslot), "Freq/Ch: %sMHz (%d)", freqStr, config.lora.channel_num);
|
||||||
}
|
}
|
||||||
size_t len = strlen(frequencyslot);
|
size_t len = strlen(frequencyslot);
|
||||||
if (len >= 4 && strcmp(frequencyslot + len - 4, " (0)") == 0) {
|
if (len >= 4 && strcmp(frequencyslot + len - 4, " (0)") == 0) {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "modules/AdminModule.h"
|
#include "modules/AdminModule.h"
|
||||||
#include "modules/CannedMessageModule.h"
|
#include "modules/CannedMessageModule.h"
|
||||||
#include "modules/KeyVerificationModule.h"
|
#include "modules/KeyVerificationModule.h"
|
||||||
|
#include "modules/TraceRouteModule.h"
|
||||||
|
|
||||||
extern uint16_t TFT_MESH;
|
extern uint16_t TFT_MESH;
|
||||||
|
|
||||||
@ -51,12 +52,14 @@ void menuHandler::LoraRegionPicker(uint32_t duration)
|
|||||||
"PH_915",
|
"PH_915",
|
||||||
"ANZ_433",
|
"ANZ_433",
|
||||||
"KZ_433",
|
"KZ_433",
|
||||||
"KZ_863"};
|
"KZ_863",
|
||||||
|
"NP_865",
|
||||||
|
"BR_902"};
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
bannerOptions.message = "Set the LoRa region";
|
bannerOptions.message = "Set the LoRa region";
|
||||||
bannerOptions.durationMs = duration;
|
bannerOptions.durationMs = duration;
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 25;
|
bannerOptions.optionsCount = 27;
|
||||||
bannerOptions.InitialSelected = 0;
|
bannerOptions.InitialSelected = 0;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
if (selected != 0 && config.lora.region != _meshtastic_Config_LoRaConfig_RegionCode(selected)) {
|
if (selected != 0 && config.lora.region != _meshtastic_Config_LoRaConfig_RegionCode(selected)) {
|
||||||
@ -151,6 +154,7 @@ void menuHandler::TZPicker()
|
|||||||
"US/Mountain",
|
"US/Mountain",
|
||||||
"US/Central",
|
"US/Central",
|
||||||
"US/Eastern",
|
"US/Eastern",
|
||||||
|
"BR/Brasilia",
|
||||||
"UTC",
|
"UTC",
|
||||||
"EU/Western",
|
"EU/Western",
|
||||||
"EU/"
|
"EU/"
|
||||||
@ -165,7 +169,7 @@ void menuHandler::TZPicker()
|
|||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
bannerOptions.message = "Pick Timezone";
|
bannerOptions.message = "Pick Timezone";
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 17;
|
bannerOptions.optionsCount = 19;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
if (selected == 0) {
|
if (selected == 0) {
|
||||||
menuHandler::menuQueue = menuHandler::clock_menu;
|
menuHandler::menuQueue = menuHandler::clock_menu;
|
||||||
@ -184,25 +188,27 @@ void menuHandler::TZPicker()
|
|||||||
strncpy(config.device.tzdef, "CST6CDT,M3.2.0,M11.1.0", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "CST6CDT,M3.2.0,M11.1.0", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 7) { // Eastern
|
} else if (selected == 7) { // Eastern
|
||||||
strncpy(config.device.tzdef, "EST5EDT,M3.2.0,M11.1.0", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "EST5EDT,M3.2.0,M11.1.0", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 8) { // UTC
|
} else if (selected == 8) { // Brazil
|
||||||
strncpy(config.device.tzdef, "UTC", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "BRT3", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 9) { // EU/Western
|
} else if (selected == 9) { // UTC
|
||||||
|
strncpy(config.device.tzdef, "UTC0", sizeof(config.device.tzdef));
|
||||||
|
} else if (selected == 10) { // EU/Western
|
||||||
strncpy(config.device.tzdef, "GMT0BST,M3.5.0/1,M10.5.0", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "GMT0BST,M3.5.0/1,M10.5.0", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 10) { // EU/Central
|
} else if (selected == 11) { // EU/Central
|
||||||
strncpy(config.device.tzdef, "CET-1CEST,M3.5.0,M10.5.0/3", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "CET-1CEST,M3.5.0,M10.5.0/3", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 11) { // EU/Eastern
|
} else if (selected == 12) { // EU/Eastern
|
||||||
strncpy(config.device.tzdef, "EET-2EEST,M3.5.0/3,M10.5.0/4", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "EET-2EEST,M3.5.0/3,M10.5.0/4", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 12) { // Asia/Kolkata
|
} else if (selected == 13) { // Asia/Kolkata
|
||||||
strncpy(config.device.tzdef, "IST-5:30", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "IST-5:30", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 13) { // China
|
} else if (selected == 14) { // China
|
||||||
strncpy(config.device.tzdef, "HKT-8", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "HKT-8", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 14) { // AU/AWST
|
} else if (selected == 15) { // AU/AWST
|
||||||
strncpy(config.device.tzdef, "AWST-8", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "AWST-8", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 15) { // AU/ACST
|
} else if (selected == 16) { // AU/ACST
|
||||||
strncpy(config.device.tzdef, "ACST-9:30ACDT,M10.1.0,M4.1.0/3", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "ACST-9:30ACDT,M10.1.0,M4.1.0/3", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 16) { // AU/AEST
|
} else if (selected == 17) { // AU/AEST
|
||||||
strncpy(config.device.tzdef, "AEST-10AEDT,M10.1.0,M4.1.0/3", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "AEST-10AEDT,M10.1.0,M4.1.0/3", sizeof(config.device.tzdef));
|
||||||
} else if (selected == 17) { // NZ
|
} else if (selected == 18) { // NZ
|
||||||
strncpy(config.device.tzdef, "NZST-12NZDT,M9.5.0,M4.1.0/3", sizeof(config.device.tzdef));
|
strncpy(config.device.tzdef, "NZST-12NZDT,M9.5.0,M4.1.0/3", sizeof(config.device.tzdef));
|
||||||
}
|
}
|
||||||
if (selected != 0) {
|
if (selected != 0) {
|
||||||
@ -426,7 +432,7 @@ void menuHandler::systemBaseMenu()
|
|||||||
|
|
||||||
void menuHandler::favoriteBaseMenu()
|
void menuHandler::favoriteBaseMenu()
|
||||||
{
|
{
|
||||||
enum optionsNumbers { Back, Preset, Freetext, Remove, enumEnd };
|
enum optionsNumbers { Back, Preset, Freetext, Remove, TraceRoute, enumEnd };
|
||||||
static const char *optionsArray[enumEnd] = {"Back", "New Preset Msg"};
|
static const char *optionsArray[enumEnd] = {"Back", "New Preset Msg"};
|
||||||
static int optionsEnumArray[enumEnd] = {Back, Preset};
|
static int optionsEnumArray[enumEnd] = {Back, Preset};
|
||||||
int options = 2;
|
int options = 2;
|
||||||
@ -435,6 +441,8 @@ void menuHandler::favoriteBaseMenu()
|
|||||||
optionsArray[options] = "New Freetext Msg";
|
optionsArray[options] = "New Freetext Msg";
|
||||||
optionsEnumArray[options++] = Freetext;
|
optionsEnumArray[options++] = Freetext;
|
||||||
}
|
}
|
||||||
|
optionsArray[options] = "Trace Route";
|
||||||
|
optionsEnumArray[options++] = TraceRoute;
|
||||||
optionsArray[options] = "Remove Favorite";
|
optionsArray[options] = "Remove Favorite";
|
||||||
optionsEnumArray[options++] = Remove;
|
optionsEnumArray[options++] = Remove;
|
||||||
|
|
||||||
@ -451,6 +459,10 @@ void menuHandler::favoriteBaseMenu()
|
|||||||
} else if (selected == Remove) {
|
} else if (selected == Remove) {
|
||||||
menuHandler::menuQueue = menuHandler::remove_favorite;
|
menuHandler::menuQueue = menuHandler::remove_favorite;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
|
} else if (selected == TraceRoute) {
|
||||||
|
if (traceRouteModule) {
|
||||||
|
traceRouteModule->launch(graphics::UIRenderer::currentFavoriteNodeNum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
@ -489,12 +501,12 @@ void menuHandler::positionBaseMenu()
|
|||||||
|
|
||||||
void menuHandler::nodeListMenu()
|
void menuHandler::nodeListMenu()
|
||||||
{
|
{
|
||||||
enum optionsNumbers { Back, Favorite, Verify, Reset };
|
enum optionsNumbers { Back, Favorite, TraceRoute, Verify, Reset, enumEnd };
|
||||||
static const char *optionsArray[] = {"Back", "Add Favorite", "Key Verification", "Reset NodeDB"};
|
static const char *optionsArray[] = {"Back", "Add Favorite", "Trace Route", "Key Verification", "Reset NodeDB"};
|
||||||
BannerOverlayOptions bannerOptions;
|
BannerOverlayOptions bannerOptions;
|
||||||
bannerOptions.message = "Node Action";
|
bannerOptions.message = "Node Action";
|
||||||
bannerOptions.optionsArrayPtr = optionsArray;
|
bannerOptions.optionsArrayPtr = optionsArray;
|
||||||
bannerOptions.optionsCount = 4;
|
bannerOptions.optionsCount = 5;
|
||||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||||
if (selected == Favorite) {
|
if (selected == Favorite) {
|
||||||
menuQueue = add_favorite;
|
menuQueue = add_favorite;
|
||||||
@ -505,6 +517,9 @@ void menuHandler::nodeListMenu()
|
|||||||
} else if (selected == Reset) {
|
} else if (selected == Reset) {
|
||||||
menuQueue = reset_node_db_menu;
|
menuQueue = reset_node_db_menu;
|
||||||
screen->runNow();
|
screen->runNow();
|
||||||
|
} else if (selected == TraceRoute) {
|
||||||
|
menuQueue = trace_route_menu;
|
||||||
|
screen->runNow();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
@ -857,6 +872,16 @@ void menuHandler::removeFavoriteMenu()
|
|||||||
screen->showOverlayBanner(bannerOptions);
|
screen->showOverlayBanner(bannerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menuHandler::traceRouteMenu()
|
||||||
|
{
|
||||||
|
screen->showNodePicker("Node to Trace", 30000, [](uint32_t nodenum) -> void {
|
||||||
|
LOG_INFO("Menu: Node picker selected node 0x%08x, traceRouteModule=%p", nodenum, traceRouteModule);
|
||||||
|
if (traceRouteModule) {
|
||||||
|
traceRouteModule->startTraceRoute(nodenum);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void menuHandler::testMenu()
|
void menuHandler::testMenu()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1129,6 +1154,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
|||||||
case remove_favorite:
|
case remove_favorite:
|
||||||
removeFavoriteMenu();
|
removeFavoriteMenu();
|
||||||
break;
|
break;
|
||||||
|
case trace_route_menu:
|
||||||
|
traceRouteMenu();
|
||||||
|
break;
|
||||||
case test_menu:
|
case test_menu:
|
||||||
testMenu();
|
testMenu();
|
||||||
break;
|
break;
|
||||||
|
@ -36,7 +36,8 @@ class menuHandler
|
|||||||
system_base_menu,
|
system_base_menu,
|
||||||
key_verification_init,
|
key_verification_init,
|
||||||
key_verification_final_prompt,
|
key_verification_final_prompt,
|
||||||
throttle_message
|
trace_route_menu,
|
||||||
|
throttle_message,
|
||||||
};
|
};
|
||||||
static screenMenus menuQueue;
|
static screenMenus menuQueue;
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ class menuHandler
|
|||||||
static void shutdownMenu();
|
static void shutdownMenu();
|
||||||
static void addFavoriteMenu();
|
static void addFavoriteMenu();
|
||||||
static void removeFavoriteMenu();
|
static void removeFavoriteMenu();
|
||||||
|
static void traceRouteMenu();
|
||||||
static void testMenu();
|
static void testMenu();
|
||||||
static void numberTest();
|
static void numberTest();
|
||||||
static void wifiBaseMenu();
|
static void wifiBaseMenu();
|
||||||
|
@ -223,7 +223,7 @@ void InkHUD::MenuApplet::execute(MenuItem item)
|
|||||||
|
|
||||||
case SHUTDOWN:
|
case SHUTDOWN:
|
||||||
LOG_INFO("Shutting down from menu");
|
LOG_INFO("Shutting down from menu");
|
||||||
power->shutdown();
|
shutdownAtMsec = millis();
|
||||||
// Menu is then sent to background via onShutdown
|
// Menu is then sent to background via onShutdown
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
[inkhud]
|
[inkhud]
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
+<graphics/niche/>; Include the nicheGraphics directory
|
+<graphics/niche/>; Include the nicheGraphics directory
|
||||||
+<../variants/$PIOENV>; Include nicheGraphics.h from our variant folder
|
|
||||||
build_flags =
|
build_flags =
|
||||||
-D MESHTASTIC_INCLUDE_NICHE_GRAPHICS ; Use NicheGraphics
|
-D MESHTASTIC_INCLUDE_NICHE_GRAPHICS ; Use NicheGraphics
|
||||||
-D MESHTASTIC_INCLUDE_INKHUD ; Use InkHUD (a NicheGraphics UI)
|
-D MESHTASTIC_INCLUDE_INKHUD ; Use InkHUD (a NicheGraphics UI)
|
||||||
|
@ -199,7 +199,7 @@ void ExpressLRSFiveWay::sendKey(input_broker_event key)
|
|||||||
void ExpressLRSFiveWay::toggleGPS()
|
void ExpressLRSFiveWay::toggleGPS()
|
||||||
{
|
{
|
||||||
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
|
#if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS
|
||||||
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
if (gps != nullptr) {
|
||||||
gps->toggleGpsMode();
|
gps->toggleGpsMode();
|
||||||
screen->startAlert("GPS Toggled");
|
screen->startAlert("GPS Toggled");
|
||||||
alerting = true;
|
alerting = true;
|
||||||
|
@ -1,116 +1,18 @@
|
|||||||
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
|
|
||||||
|
|
||||||
#include "TCA8418Keyboard.h"
|
#include "TCA8418Keyboard.h"
|
||||||
#include "configuration.h"
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
// REGISTERS
|
|
||||||
// #define _TCA8418_REG_RESERVED 0x00
|
|
||||||
#define _TCA8418_REG_CFG 0x01 // Configuration register
|
|
||||||
#define _TCA8418_REG_INT_STAT 0x02 // Interrupt status
|
|
||||||
#define _TCA8418_REG_KEY_LCK_EC 0x03 // Key lock and event counter
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_A 0x04 // Key event register A
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_B 0x05 // Key event register B
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_C 0x06 // Key event register C
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_D 0x07 // Key event register D
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_E 0x08 // Key event register E
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_F 0x09 // Key event register F
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_G 0x0A // Key event register G
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_H 0x0B // Key event register H
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_I 0x0C // Key event register I
|
|
||||||
#define _TCA8418_REG_KEY_EVENT_J 0x0D // Key event register J
|
|
||||||
#define _TCA8418_REG_KP_LCK_TIMER 0x0E // Keypad lock1 to lock2 timer
|
|
||||||
#define _TCA8418_REG_UNLOCK_1 0x0F // Unlock register 1
|
|
||||||
#define _TCA8418_REG_UNLOCK_2 0x10 // Unlock register 2
|
|
||||||
#define _TCA8418_REG_GPIO_INT_STAT_1 0x11 // GPIO interrupt status 1
|
|
||||||
#define _TCA8418_REG_GPIO_INT_STAT_2 0x12 // GPIO interrupt status 2
|
|
||||||
#define _TCA8418_REG_GPIO_INT_STAT_3 0x13 // GPIO interrupt status 3
|
|
||||||
#define _TCA8418_REG_GPIO_DAT_STAT_1 0x14 // GPIO data status 1
|
|
||||||
#define _TCA8418_REG_GPIO_DAT_STAT_2 0x15 // GPIO data status 2
|
|
||||||
#define _TCA8418_REG_GPIO_DAT_STAT_3 0x16 // GPIO data status 3
|
|
||||||
#define _TCA8418_REG_GPIO_DAT_OUT_1 0x17 // GPIO data out 1
|
|
||||||
#define _TCA8418_REG_GPIO_DAT_OUT_2 0x18 // GPIO data out 2
|
|
||||||
#define _TCA8418_REG_GPIO_DAT_OUT_3 0x19 // GPIO data out 3
|
|
||||||
#define _TCA8418_REG_GPIO_INT_EN_1 0x1A // GPIO interrupt enable 1
|
|
||||||
#define _TCA8418_REG_GPIO_INT_EN_2 0x1B // GPIO interrupt enable 2
|
|
||||||
#define _TCA8418_REG_GPIO_INT_EN_3 0x1C // GPIO interrupt enable 3
|
|
||||||
#define _TCA8418_REG_KP_GPIO_1 0x1D // Keypad/GPIO select 1
|
|
||||||
#define _TCA8418_REG_KP_GPIO_2 0x1E // Keypad/GPIO select 2
|
|
||||||
#define _TCA8418_REG_KP_GPIO_3 0x1F // Keypad/GPIO select 3
|
|
||||||
#define _TCA8418_REG_GPI_EM_1 0x20 // GPI event mode 1
|
|
||||||
#define _TCA8418_REG_GPI_EM_2 0x21 // GPI event mode 2
|
|
||||||
#define _TCA8418_REG_GPI_EM_3 0x22 // GPI event mode 3
|
|
||||||
#define _TCA8418_REG_GPIO_DIR_1 0x23 // GPIO data direction 1
|
|
||||||
#define _TCA8418_REG_GPIO_DIR_2 0x24 // GPIO data direction 2
|
|
||||||
#define _TCA8418_REG_GPIO_DIR_3 0x25 // GPIO data direction 3
|
|
||||||
#define _TCA8418_REG_GPIO_INT_LVL_1 0x26 // GPIO edge/level detect 1
|
|
||||||
#define _TCA8418_REG_GPIO_INT_LVL_2 0x27 // GPIO edge/level detect 2
|
|
||||||
#define _TCA8418_REG_GPIO_INT_LVL_3 0x28 // GPIO edge/level detect 3
|
|
||||||
#define _TCA8418_REG_DEBOUNCE_DIS_1 0x29 // Debounce disable 1
|
|
||||||
#define _TCA8418_REG_DEBOUNCE_DIS_2 0x2A // Debounce disable 2
|
|
||||||
#define _TCA8418_REG_DEBOUNCE_DIS_3 0x2B // Debounce disable 3
|
|
||||||
#define _TCA8418_REG_GPIO_PULL_1 0x2C // GPIO pull-up disable 1
|
|
||||||
#define _TCA8418_REG_GPIO_PULL_2 0x2D // GPIO pull-up disable 2
|
|
||||||
#define _TCA8418_REG_GPIO_PULL_3 0x2E // GPIO pull-up disable 3
|
|
||||||
// #define _TCA8418_REG_RESERVED 0x2F
|
|
||||||
|
|
||||||
// FIELDS CONFIG REGISTER 1
|
|
||||||
#define _TCA8418_REG_CFG_AI 0x80 // Auto-increment for read/write
|
|
||||||
#define _TCA8418_REG_CFG_GPI_E_CGF 0x40 // Event mode config
|
|
||||||
#define _TCA8418_REG_CFG_OVR_FLOW_M 0x20 // Overflow mode enable
|
|
||||||
#define _TCA8418_REG_CFG_INT_CFG 0x10 // Interrupt config
|
|
||||||
#define _TCA8418_REG_CFG_OVR_FLOW_IEN 0x08 // Overflow interrupt enable
|
|
||||||
#define _TCA8418_REG_CFG_K_LCK_IEN 0x04 // Keypad lock interrupt enable
|
|
||||||
#define _TCA8418_REG_CFG_GPI_IEN 0x02 // GPI interrupt enable
|
|
||||||
#define _TCA8418_REG_CFG_KE_IEN 0x01 // Key events interrupt enable
|
|
||||||
|
|
||||||
// FIELDS INT_STAT REGISTER 2
|
|
||||||
#define _TCA8418_REG_STAT_CAD_INT 0x10 // Ctrl-alt-del seq status
|
|
||||||
#define _TCA8418_REG_STAT_OVR_FLOW_INT 0x08 // Overflow interrupt status
|
|
||||||
#define _TCA8418_REG_STAT_K_LCK_INT 0x04 // Key lock interrupt status
|
|
||||||
#define _TCA8418_REG_STAT_GPI_INT 0x02 // GPI interrupt status
|
|
||||||
#define _TCA8418_REG_STAT_K_INT 0x01 // Key events interrupt status
|
|
||||||
|
|
||||||
// FIELDS KEY_LCK_EC REGISTER 3
|
|
||||||
#define _TCA8418_REG_LCK_EC_K_LCK_EN 0x40 // Key lock enable
|
|
||||||
#define _TCA8418_REG_LCK_EC_LCK_2 0x20 // Keypad lock status 2
|
|
||||||
#define _TCA8418_REG_LCK_EC_LCK_1 0x10 // Keypad lock status 1
|
|
||||||
#define _TCA8418_REG_LCK_EC_KLEC_3 0x08 // Key event count bit 3
|
|
||||||
#define _TCA8418_REG_LCK_EC_KLEC_2 0x04 // Key event count bit 2
|
|
||||||
#define _TCA8418_REG_LCK_EC_KLEC_1 0x02 // Key event count bit 1
|
|
||||||
#define _TCA8418_REG_LCK_EC_KLEC_0 0x01 // Key event count bit 0
|
|
||||||
|
|
||||||
// Pin IDs for matrix rows/columns
|
|
||||||
enum {
|
|
||||||
_TCA8418_ROW0, // Pin ID for row 0
|
|
||||||
_TCA8418_ROW1, // Pin ID for row 1
|
|
||||||
_TCA8418_ROW2, // Pin ID for row 2
|
|
||||||
_TCA8418_ROW3, // Pin ID for row 3
|
|
||||||
_TCA8418_ROW4, // Pin ID for row 4
|
|
||||||
_TCA8418_ROW5, // Pin ID for row 5
|
|
||||||
_TCA8418_ROW6, // Pin ID for row 6
|
|
||||||
_TCA8418_ROW7, // Pin ID for row 7
|
|
||||||
_TCA8418_COL0, // Pin ID for column 0
|
|
||||||
_TCA8418_COL1, // Pin ID for column 1
|
|
||||||
_TCA8418_COL2, // Pin ID for column 2
|
|
||||||
_TCA8418_COL3, // Pin ID for column 3
|
|
||||||
_TCA8418_COL4, // Pin ID for column 4
|
|
||||||
_TCA8418_COL5, // Pin ID for column 5
|
|
||||||
_TCA8418_COL6, // Pin ID for column 6
|
|
||||||
_TCA8418_COL7, // Pin ID for column 7
|
|
||||||
_TCA8418_COL8, // Pin ID for column 8
|
|
||||||
_TCA8418_COL9 // Pin ID for column 9
|
|
||||||
};
|
|
||||||
|
|
||||||
#define _TCA8418_COLS 3
|
#define _TCA8418_COLS 3
|
||||||
#define _TCA8418_ROWS 4
|
#define _TCA8418_ROWS 4
|
||||||
#define _TCA8418_NUM_KEYS 12
|
#define _TCA8418_NUM_KEYS 12
|
||||||
|
|
||||||
uint8_t TCA8418TapMod[_TCA8418_NUM_KEYS] = {13, 7, 7, 7, 7, 7,
|
#define _TCA8418_LONG_PRESS_THRESHOLD 2000
|
||||||
9, 7, 9, 2, 2, 2}; // Num chars per key, Modulus for rotating through characters
|
#define _TCA8418_MULTI_TAP_THRESHOLD 750
|
||||||
|
|
||||||
unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = {
|
using Key = TCA8418KeyboardBase::TCA8418Key;
|
||||||
|
|
||||||
|
// Num chars per key, Modulus for rotating through characters
|
||||||
|
static uint8_t TCA8418TapMod[_TCA8418_NUM_KEYS] = {13, 7, 7, 7, 7, 7, 9, 7, 9, 2, 2, 2};
|
||||||
|
|
||||||
|
static unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = {
|
||||||
{'1', '.', ',', '?', '!', ':', ';', '-', '_', '\\', '/', '(', ')'}, // 1
|
{'1', '.', ',', '?', '!', ':', ';', '-', '_', '\\', '/', '(', ')'}, // 1
|
||||||
{'2', 'a', 'b', 'c', 'A', 'B', 'C'}, // 2
|
{'2', 'a', 'b', 'c', 'A', 'B', 'C'}, // 2
|
||||||
{'3', 'd', 'e', 'f', 'D', 'E', 'F'}, // 3
|
{'3', 'd', 'e', 'f', 'D', 'E', 'F'}, // 3
|
||||||
@ -125,176 +27,35 @@ unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = {
|
|||||||
{'#', '@'}, // #
|
{'#', '@'}, // #
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = {
|
static unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = {
|
||||||
_TCA8418_ESC, // 1
|
Key::ESC, // 1
|
||||||
_TCA8418_UP, // 2
|
Key::UP, // 2
|
||||||
_TCA8418_NONE, // 3
|
Key::NONE, // 3
|
||||||
_TCA8418_LEFT, // 4
|
Key::LEFT, // 4
|
||||||
_TCA8418_NONE, // 5
|
Key::NONE, // 5
|
||||||
_TCA8418_RIGHT, // 6
|
Key::RIGHT, // 6
|
||||||
_TCA8418_NONE, // 7
|
Key::NONE, // 7
|
||||||
_TCA8418_DOWN, // 8
|
Key::DOWN, // 8
|
||||||
_TCA8418_NONE, // 9
|
Key::NONE, // 9
|
||||||
_TCA8418_BSP, // *
|
Key::BSP, // *
|
||||||
_TCA8418_NONE, // 0
|
Key::NONE, // 0
|
||||||
_TCA8418_NONE, // #
|
Key::NONE, // #
|
||||||
};
|
};
|
||||||
|
|
||||||
#define _TCA8418_LONG_PRESS_THRESHOLD 2000
|
TCA8418Keyboard::TCA8418Keyboard()
|
||||||
#define _TCA8418_MULTI_TAP_THRESHOLD 750
|
: TCA8418KeyboardBase(_TCA8418_ROWS, _TCA8418_COLS), last_key(-1), next_key(-1), last_tap(0L), char_idx(0), tap_interval(0),
|
||||||
|
should_backspace(false)
|
||||||
TCA8418Keyboard::TCA8418Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr)
|
|
||||||
{
|
{
|
||||||
state = Init;
|
|
||||||
last_key = -1;
|
|
||||||
should_backspace = false;
|
|
||||||
last_tap = 0L;
|
|
||||||
char_idx = 0;
|
|
||||||
tap_interval = 0;
|
|
||||||
backlight_on = true;
|
|
||||||
queue = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA8418Keyboard::begin(uint8_t addr, TwoWire *wire)
|
|
||||||
{
|
|
||||||
m_addr = addr;
|
|
||||||
m_wire = wire;
|
|
||||||
|
|
||||||
m_wire->begin();
|
|
||||||
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA8418Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
|
|
||||||
{
|
|
||||||
m_addr = addr;
|
|
||||||
m_wire = nullptr;
|
|
||||||
writeCallback = w;
|
|
||||||
readCallback = r;
|
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCA8418Keyboard::reset()
|
void TCA8418Keyboard::reset()
|
||||||
{
|
{
|
||||||
LOG_DEBUG("TCA8418 Reset");
|
TCA8418KeyboardBase::reset();
|
||||||
// GPIO
|
|
||||||
// set default all GIO pins to INPUT
|
|
||||||
writeRegister(_TCA8418_REG_GPIO_DIR_1, 0x00);
|
|
||||||
writeRegister(_TCA8418_REG_GPIO_DIR_2, 0x00);
|
|
||||||
// Set COL9 as GPIO output
|
// Set COL9 as GPIO output
|
||||||
writeRegister(_TCA8418_REG_GPIO_DIR_3, 0x02);
|
writeRegister(TCA8418_REG_GPIO_DIR_3, 0x02);
|
||||||
// Switch off keyboard backlight (COL9 = LOW)
|
// Switch off keyboard backlight (COL9 = LOW)
|
||||||
writeRegister(_TCA8418_REG_GPIO_DAT_OUT_3, 0x00);
|
writeRegister(TCA8418_REG_GPIO_DAT_OUT_3, 0x00);
|
||||||
|
|
||||||
// add all pins to key events
|
|
||||||
writeRegister(_TCA8418_REG_GPI_EM_1, 0xFF);
|
|
||||||
writeRegister(_TCA8418_REG_GPI_EM_2, 0xFF);
|
|
||||||
writeRegister(_TCA8418_REG_GPI_EM_3, 0xFF);
|
|
||||||
|
|
||||||
// set all pins to FALLING interrupts
|
|
||||||
writeRegister(_TCA8418_REG_GPIO_INT_LVL_1, 0x00);
|
|
||||||
writeRegister(_TCA8418_REG_GPIO_INT_LVL_2, 0x00);
|
|
||||||
writeRegister(_TCA8418_REG_GPIO_INT_LVL_3, 0x00);
|
|
||||||
|
|
||||||
// add all pins to interrupts
|
|
||||||
writeRegister(_TCA8418_REG_GPIO_INT_EN_1, 0xFF);
|
|
||||||
writeRegister(_TCA8418_REG_GPIO_INT_EN_2, 0xFF);
|
|
||||||
writeRegister(_TCA8418_REG_GPIO_INT_EN_3, 0xFF);
|
|
||||||
|
|
||||||
// Set keyboard matrix size
|
|
||||||
matrix(_TCA8418_ROWS, _TCA8418_COLS);
|
|
||||||
enableDebounce();
|
|
||||||
flush();
|
|
||||||
state = Idle;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCA8418Keyboard::matrix(uint8_t rows, uint8_t columns)
|
|
||||||
{
|
|
||||||
if ((rows > 8) || (columns > 10))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Skip zero size matrix
|
|
||||||
if ((rows != 0) && (columns != 0)) {
|
|
||||||
// Setup the keypad matrix.
|
|
||||||
uint8_t mask = 0x00;
|
|
||||||
for (int r = 0; r < rows; r++) {
|
|
||||||
mask <<= 1;
|
|
||||||
mask |= 1;
|
|
||||||
}
|
|
||||||
writeRegister(_TCA8418_REG_KP_GPIO_1, mask);
|
|
||||||
|
|
||||||
mask = 0x00;
|
|
||||||
for (int c = 0; c < columns && c < 8; c++) {
|
|
||||||
mask <<= 1;
|
|
||||||
mask |= 1;
|
|
||||||
}
|
|
||||||
writeRegister(_TCA8418_REG_KP_GPIO_2, mask);
|
|
||||||
|
|
||||||
if (columns > 8) {
|
|
||||||
if (columns == 9)
|
|
||||||
mask = 0x01;
|
|
||||||
else
|
|
||||||
mask = 0x03;
|
|
||||||
writeRegister(_TCA8418_REG_KP_GPIO_3, mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t TCA8418Keyboard::keyCount() const
|
|
||||||
{
|
|
||||||
uint8_t eventCount = readRegister(_TCA8418_REG_KEY_LCK_EC);
|
|
||||||
eventCount &= 0x0F; // lower 4 bits only
|
|
||||||
return eventCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCA8418Keyboard::hasEvent()
|
|
||||||
{
|
|
||||||
return queue.length() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA8418Keyboard::queueEvent(char next)
|
|
||||||
{
|
|
||||||
if (next == _TCA8418_NONE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
queue.concat(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
char TCA8418Keyboard::dequeueEvent()
|
|
||||||
{
|
|
||||||
if (queue.length() < 1) {
|
|
||||||
return _TCA8418_NONE;
|
|
||||||
}
|
|
||||||
char next = queue.charAt(0);
|
|
||||||
queue.remove(0, 1);
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA8418Keyboard::trigger()
|
|
||||||
{
|
|
||||||
if (keyCount() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (state != Init) {
|
|
||||||
// Read the key register
|
|
||||||
uint8_t k = readRegister(_TCA8418_REG_KEY_EVENT_A);
|
|
||||||
uint8_t key = k & 0x7F;
|
|
||||||
if (k & 0x80) {
|
|
||||||
if (state == Idle)
|
|
||||||
pressed(key);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (state == Held) {
|
|
||||||
released();
|
|
||||||
}
|
|
||||||
state = Idle;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCA8418Keyboard::pressed(uint8_t key)
|
void TCA8418Keyboard::pressed(uint8_t key)
|
||||||
@ -354,7 +115,7 @@ void TCA8418Keyboard::released()
|
|||||||
int32_t held_interval = now - last_tap;
|
int32_t held_interval = now - last_tap;
|
||||||
last_tap = now;
|
last_tap = now;
|
||||||
if (tap_interval < _TCA8418_MULTI_TAP_THRESHOLD && should_backspace) {
|
if (tap_interval < _TCA8418_MULTI_TAP_THRESHOLD && should_backspace) {
|
||||||
queueEvent(_TCA8418_BSP);
|
queueEvent(BSP);
|
||||||
}
|
}
|
||||||
if (held_interval > _TCA8418_LONG_PRESS_THRESHOLD) {
|
if (held_interval > _TCA8418_LONG_PRESS_THRESHOLD) {
|
||||||
queueEvent(TCA8418LongPressMap[last_key]);
|
queueEvent(TCA8418LongPressMap[last_key]);
|
||||||
@ -366,195 +127,11 @@ void TCA8418Keyboard::released()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TCA8418Keyboard::flush()
|
|
||||||
{
|
|
||||||
// Flush key events
|
|
||||||
uint8_t count = 0;
|
|
||||||
while (readRegister(_TCA8418_REG_KEY_EVENT_A) != 0)
|
|
||||||
count++;
|
|
||||||
// Flush gpio events
|
|
||||||
readRegister(_TCA8418_REG_GPIO_INT_STAT_1);
|
|
||||||
readRegister(_TCA8418_REG_GPIO_INT_STAT_2);
|
|
||||||
readRegister(_TCA8418_REG_GPIO_INT_STAT_3);
|
|
||||||
// Clear INT_STAT register
|
|
||||||
writeRegister(_TCA8418_REG_INT_STAT, 3);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t TCA8418Keyboard::digitalRead(uint8_t pinnum) const
|
|
||||||
{
|
|
||||||
if (pinnum > _TCA8418_COL9)
|
|
||||||
return 0xFF;
|
|
||||||
|
|
||||||
uint8_t reg = _TCA8418_REG_GPIO_DAT_STAT_1 + pinnum / 8;
|
|
||||||
uint8_t mask = (1 << (pinnum % 8));
|
|
||||||
|
|
||||||
// Level 0 = low other = high
|
|
||||||
uint8_t value = readRegister(reg);
|
|
||||||
if (value & mask)
|
|
||||||
return HIGH;
|
|
||||||
return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCA8418Keyboard::digitalWrite(uint8_t pinnum, uint8_t level)
|
|
||||||
{
|
|
||||||
if (pinnum > _TCA8418_COL9)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint8_t reg = _TCA8418_REG_GPIO_DAT_OUT_1 + pinnum / 8;
|
|
||||||
uint8_t mask = (1 << (pinnum % 8));
|
|
||||||
|
|
||||||
// Level 0 = low other = high
|
|
||||||
uint8_t value = readRegister(reg);
|
|
||||||
if (level == LOW)
|
|
||||||
value &= ~mask;
|
|
||||||
else
|
|
||||||
value |= mask;
|
|
||||||
writeRegister(reg, value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCA8418Keyboard::pinMode(uint8_t pinnum, uint8_t mode)
|
|
||||||
{
|
|
||||||
if (pinnum > _TCA8418_COL9)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint8_t idx = pinnum / 8;
|
|
||||||
uint8_t reg = _TCA8418_REG_GPIO_DIR_1 + idx;
|
|
||||||
uint8_t mask = (1 << (pinnum % 8));
|
|
||||||
|
|
||||||
// Mode 0 = input 1 = output
|
|
||||||
uint8_t value = readRegister(reg);
|
|
||||||
if (mode == OUTPUT)
|
|
||||||
value |= mask;
|
|
||||||
else
|
|
||||||
value &= ~mask;
|
|
||||||
writeRegister(reg, value);
|
|
||||||
|
|
||||||
// Pullup 0 = enabled 1 = disabled
|
|
||||||
reg = _TCA8418_REG_GPIO_PULL_1 + idx;
|
|
||||||
value = readRegister(reg);
|
|
||||||
if (mode == INPUT_PULLUP)
|
|
||||||
value &= ~mask;
|
|
||||||
else
|
|
||||||
value |= mask;
|
|
||||||
writeRegister(reg, value);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TCA8418Keyboard::pinIRQMode(uint8_t pinnum, uint8_t mode)
|
|
||||||
{
|
|
||||||
if (pinnum > _TCA8418_COL9)
|
|
||||||
return false;
|
|
||||||
if ((mode != RISING) && (mode != FALLING))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Mode 0 = falling 1 = rising
|
|
||||||
uint8_t idx = pinnum / 8;
|
|
||||||
uint8_t reg = _TCA8418_REG_GPIO_INT_LVL_1 + idx;
|
|
||||||
uint8_t mask = (1 << (pinnum % 8));
|
|
||||||
|
|
||||||
uint8_t value = readRegister(reg);
|
|
||||||
if (mode == RISING)
|
|
||||||
value |= mask;
|
|
||||||
else
|
|
||||||
value &= ~mask;
|
|
||||||
writeRegister(reg, value);
|
|
||||||
|
|
||||||
// Enable interrupt
|
|
||||||
reg = _TCA8418_REG_GPIO_INT_EN_1 + idx;
|
|
||||||
value = readRegister(reg);
|
|
||||||
value |= mask;
|
|
||||||
writeRegister(reg, value);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA8418Keyboard::enableInterrupts()
|
|
||||||
{
|
|
||||||
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
|
||||||
value |= (_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
|
|
||||||
writeRegister(_TCA8418_REG_CFG, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
void TCA8418Keyboard::disableInterrupts()
|
|
||||||
{
|
|
||||||
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
|
||||||
value &= ~(_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
|
|
||||||
writeRegister(_TCA8418_REG_CFG, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
void TCA8418Keyboard::enableMatrixOverflow()
|
|
||||||
{
|
|
||||||
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
|
||||||
value |= _TCA8418_REG_CFG_OVR_FLOW_M;
|
|
||||||
writeRegister(_TCA8418_REG_CFG, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
void TCA8418Keyboard::disableMatrixOverflow()
|
|
||||||
{
|
|
||||||
uint8_t value = readRegister(_TCA8418_REG_CFG);
|
|
||||||
value &= ~_TCA8418_REG_CFG_OVR_FLOW_M;
|
|
||||||
writeRegister(_TCA8418_REG_CFG, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
void TCA8418Keyboard::enableDebounce()
|
|
||||||
{
|
|
||||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0x00);
|
|
||||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0x00);
|
|
||||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0x00);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA8418Keyboard::disableDebounce()
|
|
||||||
{
|
|
||||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0xFF);
|
|
||||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0xFF);
|
|
||||||
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA8418Keyboard::setBacklight(bool on)
|
void TCA8418Keyboard::setBacklight(bool on)
|
||||||
{
|
{
|
||||||
if (on) {
|
if (on) {
|
||||||
digitalWrite(_TCA8418_COL9, HIGH);
|
digitalWrite(TCA8418_COL9, HIGH);
|
||||||
} else {
|
} else {
|
||||||
digitalWrite(_TCA8418_COL9, LOW);
|
digitalWrite(TCA8418_COL9, LOW);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t TCA8418Keyboard::readRegister(uint8_t reg) const
|
|
||||||
{
|
|
||||||
if (m_wire) {
|
|
||||||
m_wire->beginTransmission(m_addr);
|
|
||||||
m_wire->write(reg);
|
|
||||||
m_wire->endTransmission();
|
|
||||||
|
|
||||||
m_wire->requestFrom(m_addr, (uint8_t)1);
|
|
||||||
if (m_wire->available() < 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return m_wire->read();
|
|
||||||
}
|
|
||||||
if (readCallback) {
|
|
||||||
uint8_t data;
|
|
||||||
readCallback(m_addr, reg, &data, 1);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TCA8418Keyboard::writeRegister(uint8_t reg, uint8_t value)
|
|
||||||
{
|
|
||||||
uint8_t data[2];
|
|
||||||
data[0] = reg;
|
|
||||||
data[1] = value;
|
|
||||||
|
|
||||||
if (m_wire) {
|
|
||||||
m_wire->beginTransmission(m_addr);
|
|
||||||
m_wire->write(data, sizeof(uint8_t) * 2);
|
|
||||||
m_wire->endTransmission();
|
|
||||||
}
|
|
||||||
if (writeCallback) {
|
|
||||||
writeCallback(m_addr, data[0], &(data[1]), 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,82 +1,23 @@
|
|||||||
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
|
#include "TCA8418KeyboardBase.h"
|
||||||
#include "configuration.h"
|
|
||||||
#include <Wire.h>
|
|
||||||
|
|
||||||
#define _TCA8418_NONE 0x00
|
/**
|
||||||
#define _TCA8418_REBOOT 0x90
|
* @brief 3x4 keypad with 3 columns and 4 rows
|
||||||
#define _TCA8418_LEFT 0xb4
|
*/
|
||||||
#define _TCA8418_UP 0xb5
|
class TCA8418Keyboard : public TCA8418KeyboardBase
|
||||||
#define _TCA8418_DOWN 0xb6
|
|
||||||
#define _TCA8418_RIGHT 0xb7
|
|
||||||
#define _TCA8418_ESC 0x1b
|
|
||||||
#define _TCA8418_BSP 0x08
|
|
||||||
#define _TCA8418_SELECT 0x0d
|
|
||||||
|
|
||||||
class TCA8418Keyboard
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
|
TCA8418Keyboard();
|
||||||
|
void reset(void) override;
|
||||||
|
void setBacklight(bool on) override;
|
||||||
|
|
||||||
enum KeyState { Init = 0, Idle, Held, Busy };
|
protected:
|
||||||
|
void pressed(uint8_t key) override;
|
||||||
|
void released(void) override;
|
||||||
|
|
||||||
KeyState state;
|
|
||||||
int8_t last_key;
|
int8_t last_key;
|
||||||
bool should_backspace;
|
int8_t next_key;
|
||||||
uint32_t last_tap;
|
uint32_t last_tap;
|
||||||
uint8_t char_idx;
|
uint8_t char_idx;
|
||||||
int32_t tap_interval;
|
int32_t tap_interval;
|
||||||
bool backlight_on;
|
bool should_backspace;
|
||||||
|
|
||||||
String queue;
|
|
||||||
|
|
||||||
TCA8418Keyboard();
|
|
||||||
|
|
||||||
void begin(uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS, TwoWire *wire = &Wire);
|
|
||||||
void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS);
|
|
||||||
|
|
||||||
void reset(void);
|
|
||||||
// Configure the size of the keypad.
|
|
||||||
// All other rows and columns are set as inputs.
|
|
||||||
bool matrix(uint8_t rows, uint8_t columns);
|
|
||||||
|
|
||||||
// Flush all events in the FIFO buffer + GPIO events.
|
|
||||||
uint8_t flush(void);
|
|
||||||
|
|
||||||
// Key events available in the internal FIFO buffer.
|
|
||||||
uint8_t keyCount(void) const;
|
|
||||||
|
|
||||||
void trigger(void);
|
|
||||||
void pressed(uint8_t key);
|
|
||||||
void released(void);
|
|
||||||
bool hasEvent(void);
|
|
||||||
char dequeueEvent(void);
|
|
||||||
void queueEvent(char);
|
|
||||||
|
|
||||||
uint8_t digitalRead(uint8_t pinnum) const;
|
|
||||||
bool digitalWrite(uint8_t pinnum, uint8_t level);
|
|
||||||
bool pinMode(uint8_t pinnum, uint8_t mode);
|
|
||||||
bool pinIRQMode(uint8_t pinnum, uint8_t mode); // MODE FALLING or RISING
|
|
||||||
|
|
||||||
// enable / disable interrupts for matrix and GPI pins
|
|
||||||
void enableInterrupts();
|
|
||||||
void disableInterrupts();
|
|
||||||
|
|
||||||
// ignore key events when FIFO buffer is full or not.
|
|
||||||
void enableMatrixOverflow();
|
|
||||||
void disableMatrixOverflow();
|
|
||||||
|
|
||||||
// debounce keys.
|
|
||||||
void enableDebounce();
|
|
||||||
void disableDebounce();
|
|
||||||
|
|
||||||
void setBacklight(bool on);
|
|
||||||
|
|
||||||
uint8_t readRegister(uint8_t reg) const;
|
|
||||||
void writeRegister(uint8_t reg, uint8_t value);
|
|
||||||
|
|
||||||
private:
|
|
||||||
TwoWire *m_wire;
|
|
||||||
uint8_t m_addr;
|
|
||||||
i2c_com_fptr_t readCallback;
|
|
||||||
i2c_com_fptr_t writeCallback;
|
|
||||||
};
|
};
|
||||||
|
372
src/input/TCA8418KeyboardBase.cpp
Normal file
372
src/input/TCA8418KeyboardBase.cpp
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
|
||||||
|
|
||||||
|
#include "TCA8418KeyboardBase.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
// FIELDS CONFIG REGISTER 1
|
||||||
|
#define _TCA8418_REG_CFG_AI 0x80 // Auto-increment for read/write
|
||||||
|
#define _TCA8418_REG_CFG_GPI_E_CGF 0x40 // Event mode config
|
||||||
|
#define _TCA8418_REG_CFG_OVR_FLOW_M 0x20 // Overflow mode enable
|
||||||
|
#define _TCA8418_REG_CFG_INT_CFG 0x10 // Interrupt config
|
||||||
|
#define _TCA8418_REG_CFG_OVR_FLOW_IEN 0x08 // Overflow interrupt enable
|
||||||
|
#define _TCA8418_REG_CFG_K_LCK_IEN 0x04 // Keypad lock interrupt enable
|
||||||
|
#define _TCA8418_REG_CFG_GPI_IEN 0x02 // GPI interrupt enable
|
||||||
|
#define _TCA8418_REG_CFG_KE_IEN 0x01 // Key events interrupt enable
|
||||||
|
|
||||||
|
// FIELDS INT_STAT REGISTER 2
|
||||||
|
#define _TCA8418_REG_STAT_CAD_INT 0x10 // Ctrl-alt-del seq status
|
||||||
|
#define _TCA8418_REG_STAT_OVR_FLOW_INT 0x08 // Overflow interrupt status
|
||||||
|
#define _TCA8418_REG_STAT_K_LCK_INT 0x04 // Key lock interrupt status
|
||||||
|
#define _TCA8418_REG_STAT_GPI_INT 0x02 // GPI interrupt status
|
||||||
|
#define _TCA8418_REG_STAT_K_INT 0x01 // Key events interrupt status
|
||||||
|
|
||||||
|
// FIELDS KEY_LCK_EC REGISTER 3
|
||||||
|
#define _TCA8418_REG_LCK_EC_K_LCK_EN 0x40 // Key lock enable
|
||||||
|
#define _TCA8418_REG_LCK_EC_LCK_2 0x20 // Keypad lock status 2
|
||||||
|
#define _TCA8418_REG_LCK_EC_LCK_1 0x10 // Keypad lock status 1
|
||||||
|
#define _TCA8418_REG_LCK_EC_KLEC_3 0x08 // Key event count bit 3
|
||||||
|
#define _TCA8418_REG_LCK_EC_KLEC_2 0x04 // Key event count bit 2
|
||||||
|
#define _TCA8418_REG_LCK_EC_KLEC_1 0x02 // Key event count bit 1
|
||||||
|
#define _TCA8418_REG_LCK_EC_KLEC_0 0x01 // Key event count bit 0
|
||||||
|
|
||||||
|
TCA8418KeyboardBase::TCA8418KeyboardBase(uint8_t rows, uint8_t columns)
|
||||||
|
: rows(rows), columns(columns), state(Init), queue(""), m_wire(nullptr), m_addr(0), readCallback(nullptr),
|
||||||
|
writeCallback(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::begin(uint8_t addr, TwoWire *wire)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
m_wire = wire;
|
||||||
|
m_wire->begin();
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
|
||||||
|
{
|
||||||
|
m_addr = addr;
|
||||||
|
m_wire = nullptr;
|
||||||
|
writeCallback = w;
|
||||||
|
readCallback = r;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::reset()
|
||||||
|
{
|
||||||
|
LOG_DEBUG("TCA8418 Reset");
|
||||||
|
// GPIO
|
||||||
|
// set default all GIO pins to INPUT
|
||||||
|
writeRegister(TCA8418_REG_GPIO_DIR_1, 0x00);
|
||||||
|
writeRegister(TCA8418_REG_GPIO_DIR_2, 0x00);
|
||||||
|
writeRegister(TCA8418_REG_GPIO_DIR_3, 0x00);
|
||||||
|
|
||||||
|
// add all pins to key events
|
||||||
|
writeRegister(TCA8418_REG_GPI_EM_1, 0xFF);
|
||||||
|
writeRegister(TCA8418_REG_GPI_EM_2, 0xFF);
|
||||||
|
writeRegister(TCA8418_REG_GPI_EM_3, 0xFF);
|
||||||
|
|
||||||
|
// set all pins to FALLING interrupts
|
||||||
|
writeRegister(TCA8418_REG_GPIO_INT_LVL_1, 0x00);
|
||||||
|
writeRegister(TCA8418_REG_GPIO_INT_LVL_2, 0x00);
|
||||||
|
writeRegister(TCA8418_REG_GPIO_INT_LVL_3, 0x00);
|
||||||
|
|
||||||
|
// add all pins to interrupts
|
||||||
|
writeRegister(TCA8418_REG_GPIO_INT_EN_1, 0xFF);
|
||||||
|
writeRegister(TCA8418_REG_GPIO_INT_EN_2, 0xFF);
|
||||||
|
writeRegister(TCA8418_REG_GPIO_INT_EN_3, 0xFF);
|
||||||
|
|
||||||
|
// Set keyboard matrix size
|
||||||
|
matrix(rows, columns);
|
||||||
|
enableDebounce();
|
||||||
|
flush();
|
||||||
|
state = Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418KeyboardBase::matrix(uint8_t rows, uint8_t columns)
|
||||||
|
{
|
||||||
|
if (rows < 1 || rows > 8 || columns < 1 || columns > 10)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Setup the keypad matrix.
|
||||||
|
uint8_t mask = 0x00;
|
||||||
|
for (int r = 0; r < rows; r++) {
|
||||||
|
mask <<= 1;
|
||||||
|
mask |= 1;
|
||||||
|
}
|
||||||
|
writeRegister(TCA8418_REG_KP_GPIO_1, mask);
|
||||||
|
|
||||||
|
mask = 0x00;
|
||||||
|
for (int c = 0; c < columns && c < 8; c++) {
|
||||||
|
mask <<= 1;
|
||||||
|
mask |= 1;
|
||||||
|
}
|
||||||
|
writeRegister(TCA8418_REG_KP_GPIO_2, mask);
|
||||||
|
|
||||||
|
if (columns > 8) {
|
||||||
|
if (columns == 9)
|
||||||
|
mask = 0x01;
|
||||||
|
else
|
||||||
|
mask = 0x03;
|
||||||
|
writeRegister(TCA8418_REG_KP_GPIO_3, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TCA8418KeyboardBase::keyCount() const
|
||||||
|
{
|
||||||
|
uint8_t eventCount = readRegister(TCA8418_REG_KEY_LCK_EC);
|
||||||
|
eventCount &= 0x0F; // lower 4 bits only
|
||||||
|
return eventCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418KeyboardBase::hasEvent() const
|
||||||
|
{
|
||||||
|
return queue.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::queueEvent(char next)
|
||||||
|
{
|
||||||
|
if (next == NONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
queue.concat(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
char TCA8418KeyboardBase::dequeueEvent()
|
||||||
|
{
|
||||||
|
if (queue.length() < 1) {
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
char next = queue.charAt(0);
|
||||||
|
queue.remove(0, 1);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::trigger()
|
||||||
|
{
|
||||||
|
if (keyCount() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (state != Init) {
|
||||||
|
// Read the key register
|
||||||
|
uint8_t k = readRegister(TCA8418_REG_KEY_EVENT_A);
|
||||||
|
uint8_t key = k & 0x7F;
|
||||||
|
if (k & 0x80) {
|
||||||
|
if (state == Idle)
|
||||||
|
pressed(key);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (state == Held) {
|
||||||
|
released();
|
||||||
|
}
|
||||||
|
state = Idle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::pressed(uint8_t key)
|
||||||
|
{
|
||||||
|
// must be defined in derived class
|
||||||
|
LOG_ERROR("pressed() not implemented in derived class");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::released()
|
||||||
|
{
|
||||||
|
// must be defined in derived class
|
||||||
|
LOG_ERROR("released() not implemented in derived class");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TCA8418KeyboardBase::flush()
|
||||||
|
{
|
||||||
|
// Flush key events
|
||||||
|
uint8_t count = 0;
|
||||||
|
while (readRegister(TCA8418_REG_KEY_EVENT_A) != 0)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
// Flush gpio events
|
||||||
|
readRegister(TCA8418_REG_GPIO_INT_STAT_1);
|
||||||
|
readRegister(TCA8418_REG_GPIO_INT_STAT_2);
|
||||||
|
readRegister(TCA8418_REG_GPIO_INT_STAT_3);
|
||||||
|
|
||||||
|
// Clear INT_STAT register
|
||||||
|
writeRegister(TCA8418_REG_INT_STAT, 3);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TCA8418KeyboardBase::digitalRead(uint8_t pinnum) const
|
||||||
|
{
|
||||||
|
if (pinnum > TCA8418_COL9)
|
||||||
|
return 0xFF;
|
||||||
|
|
||||||
|
uint8_t reg = TCA8418_REG_GPIO_DAT_STAT_1 + pinnum / 8;
|
||||||
|
uint8_t mask = (1 << (pinnum % 8));
|
||||||
|
|
||||||
|
// Level 0 = low other = high
|
||||||
|
uint8_t value = readRegister(reg);
|
||||||
|
if (value & mask)
|
||||||
|
return HIGH;
|
||||||
|
return LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418KeyboardBase::digitalWrite(uint8_t pinnum, uint8_t level)
|
||||||
|
{
|
||||||
|
if (pinnum > TCA8418_COL9)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint8_t reg = TCA8418_REG_GPIO_DAT_OUT_1 + pinnum / 8;
|
||||||
|
uint8_t mask = (1 << (pinnum % 8));
|
||||||
|
|
||||||
|
// Level 0 = low other = high
|
||||||
|
uint8_t value = readRegister(reg);
|
||||||
|
if (level == LOW)
|
||||||
|
value &= ~mask;
|
||||||
|
else
|
||||||
|
value |= mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418KeyboardBase::pinMode(uint8_t pinnum, uint8_t mode)
|
||||||
|
{
|
||||||
|
if (pinnum > TCA8418_COL9)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint8_t idx = pinnum / 8;
|
||||||
|
uint8_t reg = TCA8418_REG_GPIO_DIR_1 + idx;
|
||||||
|
uint8_t mask = (1 << (pinnum % 8));
|
||||||
|
|
||||||
|
// Mode 0 = input 1 = output
|
||||||
|
uint8_t value = readRegister(reg);
|
||||||
|
if (mode == OUTPUT)
|
||||||
|
value |= mask;
|
||||||
|
else
|
||||||
|
value &= ~mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
|
||||||
|
// Pullup 0 = enabled 1 = disabled
|
||||||
|
reg = TCA8418_REG_GPIO_PULL_1 + idx;
|
||||||
|
value = readRegister(reg);
|
||||||
|
if (mode == INPUT_PULLUP)
|
||||||
|
value &= ~mask;
|
||||||
|
else
|
||||||
|
value |= mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TCA8418KeyboardBase::pinIRQMode(uint8_t pinnum, uint8_t mode)
|
||||||
|
{
|
||||||
|
if (pinnum > TCA8418_COL9)
|
||||||
|
return false;
|
||||||
|
if ((mode != RISING) && (mode != FALLING))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Mode 0 = falling 1 = rising
|
||||||
|
uint8_t idx = pinnum / 8;
|
||||||
|
uint8_t reg = TCA8418_REG_GPIO_INT_LVL_1 + idx;
|
||||||
|
uint8_t mask = (1 << (pinnum % 8));
|
||||||
|
|
||||||
|
uint8_t value = readRegister(reg);
|
||||||
|
if (mode == RISING)
|
||||||
|
value |= mask;
|
||||||
|
else
|
||||||
|
value &= ~mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
|
||||||
|
// Enable interrupt
|
||||||
|
reg = TCA8418_REG_GPIO_INT_EN_1 + idx;
|
||||||
|
value = readRegister(reg);
|
||||||
|
value |= mask;
|
||||||
|
writeRegister(reg, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::enableInterrupts()
|
||||||
|
{
|
||||||
|
uint8_t value = readRegister(TCA8418_REG_CFG);
|
||||||
|
value |= (_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
|
||||||
|
writeRegister(TCA8418_REG_CFG, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::disableInterrupts()
|
||||||
|
{
|
||||||
|
uint8_t value = readRegister(TCA8418_REG_CFG);
|
||||||
|
value &= ~(_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
|
||||||
|
writeRegister(TCA8418_REG_CFG, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::enableMatrixOverflow()
|
||||||
|
{
|
||||||
|
uint8_t value = readRegister(TCA8418_REG_CFG);
|
||||||
|
value |= _TCA8418_REG_CFG_OVR_FLOW_M;
|
||||||
|
writeRegister(TCA8418_REG_CFG, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::disableMatrixOverflow()
|
||||||
|
{
|
||||||
|
uint8_t value = readRegister(TCA8418_REG_CFG);
|
||||||
|
value &= ~_TCA8418_REG_CFG_OVR_FLOW_M;
|
||||||
|
writeRegister(TCA8418_REG_CFG, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::enableDebounce()
|
||||||
|
{
|
||||||
|
writeRegister(TCA8418_REG_DEBOUNCE_DIS_1, 0x00);
|
||||||
|
writeRegister(TCA8418_REG_DEBOUNCE_DIS_2, 0x00);
|
||||||
|
writeRegister(TCA8418_REG_DEBOUNCE_DIS_3, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::disableDebounce()
|
||||||
|
{
|
||||||
|
writeRegister(TCA8418_REG_DEBOUNCE_DIS_1, 0xFF);
|
||||||
|
writeRegister(TCA8418_REG_DEBOUNCE_DIS_2, 0xFF);
|
||||||
|
writeRegister(TCA8418_REG_DEBOUNCE_DIS_3, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::setBacklight(bool on) {}
|
||||||
|
|
||||||
|
uint8_t TCA8418KeyboardBase::readRegister(uint8_t reg) const
|
||||||
|
{
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(reg);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
|
||||||
|
m_wire->requestFrom(m_addr, (uint8_t)1);
|
||||||
|
if (m_wire->available() < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_wire->read();
|
||||||
|
}
|
||||||
|
if (readCallback) {
|
||||||
|
uint8_t data;
|
||||||
|
readCallback(m_addr, reg, &data, 1);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCA8418KeyboardBase::writeRegister(uint8_t reg, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t data[2];
|
||||||
|
data[0] = reg;
|
||||||
|
data[1] = value;
|
||||||
|
|
||||||
|
if (m_wire) {
|
||||||
|
m_wire->beginTransmission(m_addr);
|
||||||
|
m_wire->write(data, sizeof(uint8_t) * 2);
|
||||||
|
m_wire->endTransmission();
|
||||||
|
}
|
||||||
|
if (writeCallback) {
|
||||||
|
writeCallback(m_addr, data[0], &(data[1]), 1);
|
||||||
|
}
|
||||||
|
}
|
170
src/input/TCA8418KeyboardBase.h
Normal file
170
src/input/TCA8418KeyboardBase.h
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
|
||||||
|
#include "configuration.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TCA8418KeyboardBase is the base class for TCA8418 keyboard handling.
|
||||||
|
* It provides basic functionality for reading key events, managing the keyboard matrix,
|
||||||
|
* and handling key states. It is designed to be extended for specific keyboard implementations.
|
||||||
|
* It supports both I2C communication and function pointers for custom I2C operations.
|
||||||
|
*/
|
||||||
|
class TCA8418KeyboardBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum TCA8418Key : uint8_t {
|
||||||
|
NONE = 0x00,
|
||||||
|
BSP = 0x08,
|
||||||
|
TAB = 0x09,
|
||||||
|
SELECT = 0x0d,
|
||||||
|
ESC = 0x1b,
|
||||||
|
REBOOT = 0x90,
|
||||||
|
LEFT = 0xb4,
|
||||||
|
UP = 0xb5,
|
||||||
|
DOWN = 0xb6,
|
||||||
|
RIGHT = 0xb7,
|
||||||
|
BT_TOGGLE = 0xAA,
|
||||||
|
GPS_TOGGLE = 0x9E,
|
||||||
|
MUTE_TOGGLE = 0xAC,
|
||||||
|
SEND_PING = 0xAF,
|
||||||
|
BL_TOGGLE = 0xAB
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
|
TCA8418KeyboardBase(uint8_t rows, uint8_t columns);
|
||||||
|
|
||||||
|
virtual void begin(uint8_t addr = TCA8418_KB_ADDR, TwoWire *wire = &Wire);
|
||||||
|
virtual void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = TCA8418_KB_ADDR);
|
||||||
|
|
||||||
|
virtual void reset(void);
|
||||||
|
virtual void trigger(void);
|
||||||
|
|
||||||
|
virtual void setBacklight(bool on);
|
||||||
|
|
||||||
|
// Key events available
|
||||||
|
virtual bool hasEvent(void) const;
|
||||||
|
virtual char dequeueEvent(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum KeyState { Init, Idle, Held, Busy };
|
||||||
|
|
||||||
|
enum TCA8418Register : uint8_t {
|
||||||
|
TCA8418_REG_RESERVED = 0x00,
|
||||||
|
TCA8418_REG_CFG = 0x01,
|
||||||
|
TCA8418_REG_INT_STAT = 0x02,
|
||||||
|
TCA8418_REG_KEY_LCK_EC = 0x03,
|
||||||
|
TCA8418_REG_KEY_EVENT_A = 0x04,
|
||||||
|
TCA8418_REG_KEY_EVENT_B = 0x05,
|
||||||
|
TCA8418_REG_KEY_EVENT_C = 0x06,
|
||||||
|
TCA8418_REG_KEY_EVENT_D = 0x07,
|
||||||
|
TCA8418_REG_KEY_EVENT_E = 0x08,
|
||||||
|
TCA8418_REG_KEY_EVENT_F = 0x09,
|
||||||
|
TCA8418_REG_KEY_EVENT_G = 0x0A,
|
||||||
|
TCA8418_REG_KEY_EVENT_H = 0x0B,
|
||||||
|
TCA8418_REG_KEY_EVENT_I = 0x0C,
|
||||||
|
TCA8418_REG_KEY_EVENT_J = 0x0D,
|
||||||
|
TCA8418_REG_KP_LCK_TIMER = 0x0E,
|
||||||
|
TCA8418_REG_UNLOCK_1 = 0x0F,
|
||||||
|
TCA8418_REG_UNLOCK_2 = 0x10,
|
||||||
|
TCA8418_REG_GPIO_INT_STAT_1 = 0x11,
|
||||||
|
TCA8418_REG_GPIO_INT_STAT_2 = 0x12,
|
||||||
|
TCA8418_REG_GPIO_INT_STAT_3 = 0x13,
|
||||||
|
TCA8418_REG_GPIO_DAT_STAT_1 = 0x14,
|
||||||
|
TCA8418_REG_GPIO_DAT_STAT_2 = 0x15,
|
||||||
|
TCA8418_REG_GPIO_DAT_STAT_3 = 0x16,
|
||||||
|
TCA8418_REG_GPIO_DAT_OUT_1 = 0x17,
|
||||||
|
TCA8418_REG_GPIO_DAT_OUT_2 = 0x18,
|
||||||
|
TCA8418_REG_GPIO_DAT_OUT_3 = 0x19,
|
||||||
|
TCA8418_REG_GPIO_INT_EN_1 = 0x1A,
|
||||||
|
TCA8418_REG_GPIO_INT_EN_2 = 0x1B,
|
||||||
|
TCA8418_REG_GPIO_INT_EN_3 = 0x1C,
|
||||||
|
TCA8418_REG_KP_GPIO_1 = 0x1D,
|
||||||
|
TCA8418_REG_KP_GPIO_2 = 0x1E,
|
||||||
|
TCA8418_REG_KP_GPIO_3 = 0x1F,
|
||||||
|
TCA8418_REG_GPI_EM_1 = 0x20,
|
||||||
|
TCA8418_REG_GPI_EM_2 = 0x21,
|
||||||
|
TCA8418_REG_GPI_EM_3 = 0x22,
|
||||||
|
TCA8418_REG_GPIO_DIR_1 = 0x23,
|
||||||
|
TCA8418_REG_GPIO_DIR_2 = 0x24,
|
||||||
|
TCA8418_REG_GPIO_DIR_3 = 0x25,
|
||||||
|
TCA8418_REG_GPIO_INT_LVL_1 = 0x26,
|
||||||
|
TCA8418_REG_GPIO_INT_LVL_2 = 0x27,
|
||||||
|
TCA8418_REG_GPIO_INT_LVL_3 = 0x28,
|
||||||
|
TCA8418_REG_DEBOUNCE_DIS_1 = 0x29,
|
||||||
|
TCA8418_REG_DEBOUNCE_DIS_2 = 0x2A,
|
||||||
|
TCA8418_REG_DEBOUNCE_DIS_3 = 0x2B,
|
||||||
|
TCA8418_REG_GPIO_PULL_1 = 0x2C,
|
||||||
|
TCA8418_REG_GPIO_PULL_2 = 0x2D,
|
||||||
|
TCA8418_REG_GPIO_PULL_3 = 0x2E
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pin IDs for matrix rows/columns
|
||||||
|
enum TCA8418PinId : uint8_t {
|
||||||
|
TCA8418_ROW0, // Pin ID for row 0
|
||||||
|
TCA8418_ROW1, // Pin ID for row 1
|
||||||
|
TCA8418_ROW2, // Pin ID for row 2
|
||||||
|
TCA8418_ROW3, // Pin ID for row 3
|
||||||
|
TCA8418_ROW4, // Pin ID for row 4
|
||||||
|
TCA8418_ROW5, // Pin ID for row 5
|
||||||
|
TCA8418_ROW6, // Pin ID for row 6
|
||||||
|
TCA8418_ROW7, // Pin ID for row 7
|
||||||
|
TCA8418_COL0, // Pin ID for column 0
|
||||||
|
TCA8418_COL1, // Pin ID for column 1
|
||||||
|
TCA8418_COL2, // Pin ID for column 2
|
||||||
|
TCA8418_COL3, // Pin ID for column 3
|
||||||
|
TCA8418_COL4, // Pin ID for column 4
|
||||||
|
TCA8418_COL5, // Pin ID for column 5
|
||||||
|
TCA8418_COL6, // Pin ID for column 6
|
||||||
|
TCA8418_COL7, // Pin ID for column 7
|
||||||
|
TCA8418_COL8, // Pin ID for column 8
|
||||||
|
TCA8418_COL9 // Pin ID for column 9
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void pressed(uint8_t key);
|
||||||
|
virtual void released(void);
|
||||||
|
|
||||||
|
virtual void queueEvent(char);
|
||||||
|
|
||||||
|
virtual ~TCA8418KeyboardBase() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Set the size of the keypad matrix
|
||||||
|
// All other rows and columns are set as inputs.
|
||||||
|
bool matrix(uint8_t rows, uint8_t columns);
|
||||||
|
|
||||||
|
uint8_t keyCount(void) const;
|
||||||
|
|
||||||
|
// Flush all events in the FIFO buffer + GPIO events.
|
||||||
|
uint8_t flush(void);
|
||||||
|
|
||||||
|
// debounce keys.
|
||||||
|
void enableDebounce();
|
||||||
|
void disableDebounce();
|
||||||
|
|
||||||
|
// enable / disable interrupts for matrix and GPI pins
|
||||||
|
void enableInterrupts();
|
||||||
|
void disableInterrupts();
|
||||||
|
|
||||||
|
// ignore key events when FIFO buffer is full or not.
|
||||||
|
void enableMatrixOverflow();
|
||||||
|
void disableMatrixOverflow();
|
||||||
|
|
||||||
|
uint8_t digitalRead(uint8_t pinnum) const;
|
||||||
|
bool digitalWrite(uint8_t pinnum, uint8_t level);
|
||||||
|
bool pinMode(uint8_t pinnum, uint8_t mode);
|
||||||
|
bool pinIRQMode(uint8_t pinnum, uint8_t mode); // MODE FALLING or RISING
|
||||||
|
uint8_t readRegister(uint8_t reg) const;
|
||||||
|
void writeRegister(uint8_t reg, uint8_t value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t rows;
|
||||||
|
uint8_t columns;
|
||||||
|
KeyState state;
|
||||||
|
String queue;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TwoWire *m_wire;
|
||||||
|
uint8_t m_addr;
|
||||||
|
i2c_com_fptr_t readCallback;
|
||||||
|
i2c_com_fptr_t writeCallback;
|
||||||
|
};
|
196
src/input/TDeckProKeyboard.cpp
Normal file
196
src/input/TDeckProKeyboard.cpp
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
#if defined(T_DECK_PRO)
|
||||||
|
|
||||||
|
#include "TDeckProKeyboard.h"
|
||||||
|
|
||||||
|
#define _TCA8418_COLS 10
|
||||||
|
#define _TCA8418_ROWS 4
|
||||||
|
#define _TCA8418_NUM_KEYS 35
|
||||||
|
|
||||||
|
#define _TCA8418_MULTI_TAP_THRESHOLD 1500
|
||||||
|
|
||||||
|
using Key = TCA8418KeyboardBase::TCA8418Key;
|
||||||
|
|
||||||
|
constexpr uint8_t modifierRightShiftKey = 31 - 1; // keynum -1
|
||||||
|
constexpr uint8_t modifierRightShift = 0b0001;
|
||||||
|
constexpr uint8_t modifierLeftShiftKey = 35 - 1;
|
||||||
|
constexpr uint8_t modifierLeftShift = 0b0001;
|
||||||
|
constexpr uint8_t modifierSymKey = 32 - 1;
|
||||||
|
constexpr uint8_t modifierSym = 0b0010;
|
||||||
|
constexpr uint8_t modifierAltKey = 30 - 1;
|
||||||
|
constexpr uint8_t modifierAlt = 0b0100;
|
||||||
|
|
||||||
|
// Num chars per key, Modulus for rotating through characters
|
||||||
|
static uint8_t TDeckProTapMod[_TCA8418_NUM_KEYS] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
|
||||||
|
|
||||||
|
static unsigned char TDeckProTapMap[_TCA8418_NUM_KEYS][5] = {
|
||||||
|
{'p', 'P', '@', 0x00, Key::SEND_PING},
|
||||||
|
{'o', 'O', '+'},
|
||||||
|
{'i', 'I', '-'},
|
||||||
|
{'u', 'U', '_'},
|
||||||
|
{'y', 'Y', ')'},
|
||||||
|
{'t', 'T', '(', 0x00, Key::TAB},
|
||||||
|
{'r', 'R', '3'},
|
||||||
|
{'e', 'E', '2', 0x00, Key::UP},
|
||||||
|
{'w', 'W', '1'},
|
||||||
|
{'q', 'Q', '#', 0x00, Key::ESC}, // p, o, i, u, y, t, r, e, w, q
|
||||||
|
{Key::BSP, 0x00, 0x00},
|
||||||
|
{'l', 'L', '"'},
|
||||||
|
{'k', 'K', '\''},
|
||||||
|
{'j', 'J', ';'},
|
||||||
|
{'h', 'H', ':'},
|
||||||
|
{'g', 'G', '/', 0x00, Key::GPS_TOGGLE},
|
||||||
|
{'f', 'F', '6', 0x00, Key::RIGHT},
|
||||||
|
{'d', 'D', '5'},
|
||||||
|
{'s', 'S', '4', 0x00, Key::LEFT},
|
||||||
|
{'a', 'A', '*'}, // bsp, l, k, j, h, g, f, d, s, a
|
||||||
|
{0x0d, 0x00, 0x00},
|
||||||
|
{'$', 0x00, 0x00},
|
||||||
|
{'m', 'M', '.', 0x00, Key::MUTE_TOGGLE},
|
||||||
|
{'n', 'N', ','},
|
||||||
|
{'b', 'B', '!', 0x00, Key::BL_TOGGLE},
|
||||||
|
{'v', 'V', '?'},
|
||||||
|
{'c', 'C', '9'},
|
||||||
|
{'x', 'X', '8', 0x00, Key::DOWN},
|
||||||
|
{'z', 'Z', '7'},
|
||||||
|
{0x00, 0x00, 0x00}, // Ent, $, m, n, b, v, c, x, z, alt
|
||||||
|
{0x00, 0x00, 0x00},
|
||||||
|
{0x00, 0x00, 0x00},
|
||||||
|
{0x20, 0x00, 0x00},
|
||||||
|
{0x00, 0x00, 0x00},
|
||||||
|
{0x00, 0x00, 0x00} // R_Shift, sym, space, mic, L_Shift
|
||||||
|
};
|
||||||
|
|
||||||
|
TDeckProKeyboard::TDeckProKeyboard()
|
||||||
|
: TCA8418KeyboardBase(_TCA8418_ROWS, _TCA8418_COLS), modifierFlag(0), last_modifier_time(0), last_key(-1), next_key(-1),
|
||||||
|
last_tap(0L), char_idx(0), tap_interval(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDeckProKeyboard::reset()
|
||||||
|
{
|
||||||
|
TCA8418KeyboardBase::reset();
|
||||||
|
pinMode(KB_BL_PIN, OUTPUT);
|
||||||
|
setBacklight(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle multi-key presses (shift and alt)
|
||||||
|
void TDeckProKeyboard::trigger()
|
||||||
|
{
|
||||||
|
uint8_t count = keyCount();
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
for (uint8_t i = 0; i < count; ++i) {
|
||||||
|
uint8_t k = readRegister(TCA8418_REG_KEY_EVENT_A + i);
|
||||||
|
uint8_t key = k & 0x7F;
|
||||||
|
if (k & 0x80) {
|
||||||
|
pressed(key);
|
||||||
|
} else {
|
||||||
|
released();
|
||||||
|
state = Idle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDeckProKeyboard::pressed(uint8_t key)
|
||||||
|
{
|
||||||
|
if (state == Init || state == Busy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (modifierFlag && (millis() - last_modifier_time > _TCA8418_MULTI_TAP_THRESHOLD)) {
|
||||||
|
modifierFlag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t next_key = 0;
|
||||||
|
int row = (key - 1) / 10;
|
||||||
|
int col = (key - 1) % 10;
|
||||||
|
|
||||||
|
if (row >= _TCA8418_ROWS || col >= _TCA8418_COLS) {
|
||||||
|
return; // Invalid key
|
||||||
|
}
|
||||||
|
|
||||||
|
next_key = row * _TCA8418_COLS + col;
|
||||||
|
state = Held;
|
||||||
|
|
||||||
|
uint32_t now = millis();
|
||||||
|
tap_interval = now - last_tap;
|
||||||
|
|
||||||
|
updateModifierFlag(next_key);
|
||||||
|
if (isModifierKey(next_key)) {
|
||||||
|
last_modifier_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tap_interval < 0) {
|
||||||
|
last_tap = 0;
|
||||||
|
state = Busy;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_key != last_key || tap_interval > _TCA8418_MULTI_TAP_THRESHOLD) {
|
||||||
|
char_idx = 0;
|
||||||
|
} else {
|
||||||
|
char_idx += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_key = next_key;
|
||||||
|
last_tap = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDeckProKeyboard::released()
|
||||||
|
{
|
||||||
|
if (state != Held) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_key < 0 || last_key >= _TCA8418_NUM_KEYS) {
|
||||||
|
last_key = -1;
|
||||||
|
state = Idle;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t now = millis();
|
||||||
|
last_tap = now;
|
||||||
|
|
||||||
|
if (TDeckProTapMap[last_key][modifierFlag % TDeckProTapMod[last_key]] == Key::BL_TOGGLE) {
|
||||||
|
toggleBacklight();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
queueEvent(TDeckProTapMap[last_key][modifierFlag % TDeckProTapMod[last_key]]);
|
||||||
|
if (isModifierKey(last_key) == false)
|
||||||
|
modifierFlag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDeckProKeyboard::setBacklight(bool on)
|
||||||
|
{
|
||||||
|
if (on) {
|
||||||
|
digitalWrite(KB_BL_PIN, HIGH);
|
||||||
|
} else {
|
||||||
|
digitalWrite(KB_BL_PIN, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDeckProKeyboard::toggleBacklight(void)
|
||||||
|
{
|
||||||
|
digitalWrite(KB_BL_PIN, !digitalRead(KB_BL_PIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TDeckProKeyboard::updateModifierFlag(uint8_t key)
|
||||||
|
{
|
||||||
|
if (key == modifierRightShiftKey) {
|
||||||
|
modifierFlag ^= modifierRightShift;
|
||||||
|
} else if (key == modifierLeftShiftKey) {
|
||||||
|
modifierFlag ^= modifierLeftShift;
|
||||||
|
} else if (key == modifierSymKey) {
|
||||||
|
modifierFlag ^= modifierSym;
|
||||||
|
} else if (key == modifierAltKey) {
|
||||||
|
modifierFlag ^= modifierAlt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TDeckProKeyboard::isModifierKey(uint8_t key)
|
||||||
|
{
|
||||||
|
return (key == modifierRightShiftKey || key == modifierLeftShiftKey || key == modifierAltKey || key == modifierSymKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // T_DECK_PRO
|
27
src/input/TDeckProKeyboard.h
Normal file
27
src/input/TDeckProKeyboard.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "TCA8418KeyboardBase.h"
|
||||||
|
|
||||||
|
class TDeckProKeyboard : public TCA8418KeyboardBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TDeckProKeyboard();
|
||||||
|
void reset(void) override;
|
||||||
|
void trigger(void) override;
|
||||||
|
void setBacklight(bool on) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void pressed(uint8_t key) override;
|
||||||
|
void released(void) override;
|
||||||
|
|
||||||
|
void updateModifierFlag(uint8_t key);
|
||||||
|
bool isModifierKey(uint8_t key);
|
||||||
|
void toggleBacklight(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t modifierFlag; // Flag to indicate if a modifier key is pressed
|
||||||
|
uint32_t last_modifier_time; // Timestamp of the last modifier key press
|
||||||
|
int8_t last_key;
|
||||||
|
int8_t next_key;
|
||||||
|
uint32_t last_tap;
|
||||||
|
uint8_t char_idx;
|
||||||
|
int32_t tap_interval;
|
||||||
|
};
|
12
src/input/TLoraPagerKeyboard.h
Normal file
12
src/input/TLoraPagerKeyboard.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "TCA8418KeyboardBase.h"
|
||||||
|
|
||||||
|
class TLoraPagerKeyboard : public TCA8418KeyboardBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TLoraPagerKeyboard();
|
||||||
|
void setBacklight(bool on) override{};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void pressed(uint8_t key) override{};
|
||||||
|
void released(void) override{};
|
||||||
|
};
|
@ -3,10 +3,26 @@
|
|||||||
#include "detect/ScanI2C.h"
|
#include "detect/ScanI2C.h"
|
||||||
#include "detect/ScanI2CTwoWire.h"
|
#include "detect/ScanI2CTwoWire.h"
|
||||||
|
|
||||||
|
#if defined(T_DECK_PRO)
|
||||||
|
#include "TDeckProKeyboard.h"
|
||||||
|
#elif defined(T_LORA_PAGER)
|
||||||
|
#include "TLoraPagerKeyboard.h"
|
||||||
|
#else
|
||||||
|
#include "TCA8418Keyboard.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
extern ScanI2C::DeviceAddress cardkb_found;
|
extern ScanI2C::DeviceAddress cardkb_found;
|
||||||
extern uint8_t kb_model;
|
extern uint8_t kb_model;
|
||||||
|
|
||||||
KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
|
KbI2cBase::KbI2cBase(const char *name)
|
||||||
|
: concurrency::OSThread(name),
|
||||||
|
#if defined(T_DECK_PRO)
|
||||||
|
TCAKeyboard(*(new TDeckProKeyboard()))
|
||||||
|
#elif defined(T_LORA_PAGER)
|
||||||
|
TCAKeyboard(*(new TLoraPagerKeyboard()))
|
||||||
|
#else
|
||||||
|
TCAKeyboard(*(new TCA8418Keyboard()))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
this->_originName = name;
|
this->_originName = name;
|
||||||
}
|
}
|
||||||
@ -43,8 +59,8 @@ int32_t KbI2cBase::runOnce()
|
|||||||
if (cardkb_found.address == MPR121_KB_ADDR) {
|
if (cardkb_found.address == MPR121_KB_ADDR) {
|
||||||
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1);
|
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1);
|
||||||
}
|
}
|
||||||
if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
if (cardkb_found.address == TCA8418_KB_ADDR) {
|
||||||
TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire1);
|
TCAKeyboard.begin(TCA8418_KB_ADDR, &Wire1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -58,8 +74,8 @@ int32_t KbI2cBase::runOnce()
|
|||||||
if (cardkb_found.address == MPR121_KB_ADDR) {
|
if (cardkb_found.address == MPR121_KB_ADDR) {
|
||||||
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire);
|
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire);
|
||||||
}
|
}
|
||||||
if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
if (cardkb_found.address == TCA8418_KB_ADDR) {
|
||||||
TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire);
|
TCAKeyboard.begin(TCA8418_KB_ADDR, &Wire);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ScanI2C::NO_I2C:
|
case ScanI2C::NO_I2C:
|
||||||
@ -241,41 +257,65 @@ int32_t KbI2cBase::runOnce()
|
|||||||
e.kbchar = 0x00;
|
e.kbchar = 0x00;
|
||||||
e.source = this->_originName;
|
e.source = this->_originName;
|
||||||
switch (nextEvent) {
|
switch (nextEvent) {
|
||||||
case _TCA8418_NONE:
|
case TCA8418KeyboardBase::NONE:
|
||||||
e.inputEvent = INPUT_BROKER_NONE;
|
e.inputEvent = INPUT_BROKER_NONE;
|
||||||
e.kbchar = 0x00;
|
e.kbchar = 0x00;
|
||||||
break;
|
break;
|
||||||
case _TCA8418_REBOOT:
|
case TCA8418KeyboardBase::REBOOT:
|
||||||
e.inputEvent = INPUT_BROKER_ANYKEY;
|
e.inputEvent = INPUT_BROKER_ANYKEY;
|
||||||
e.kbchar = INPUT_BROKER_MSG_REBOOT;
|
e.kbchar = INPUT_BROKER_MSG_REBOOT;
|
||||||
break;
|
break;
|
||||||
case _TCA8418_LEFT:
|
case TCA8418KeyboardBase::LEFT:
|
||||||
e.inputEvent = INPUT_BROKER_LEFT;
|
e.inputEvent = INPUT_BROKER_LEFT;
|
||||||
e.kbchar = 0x00;
|
e.kbchar = 0x00;
|
||||||
break;
|
break;
|
||||||
case _TCA8418_UP:
|
case TCA8418KeyboardBase::UP:
|
||||||
e.inputEvent = INPUT_BROKER_UP;
|
e.inputEvent = INPUT_BROKER_UP;
|
||||||
e.kbchar = 0x00;
|
e.kbchar = 0x00;
|
||||||
break;
|
break;
|
||||||
case _TCA8418_DOWN:
|
case TCA8418KeyboardBase::DOWN:
|
||||||
e.inputEvent = INPUT_BROKER_DOWN;
|
e.inputEvent = INPUT_BROKER_DOWN;
|
||||||
e.kbchar = 0x00;
|
e.kbchar = 0x00;
|
||||||
break;
|
break;
|
||||||
case _TCA8418_RIGHT:
|
case TCA8418KeyboardBase::RIGHT:
|
||||||
e.inputEvent = INPUT_BROKER_RIGHT;
|
e.inputEvent = INPUT_BROKER_RIGHT;
|
||||||
e.kbchar = 0x00;
|
e.kbchar = 0x00;
|
||||||
break;
|
break;
|
||||||
case _TCA8418_BSP:
|
case TCA8418KeyboardBase::BSP:
|
||||||
e.inputEvent = INPUT_BROKER_BACK;
|
e.inputEvent = INPUT_BROKER_BACK;
|
||||||
e.kbchar = 0x08;
|
e.kbchar = 0x08;
|
||||||
break;
|
break;
|
||||||
case _TCA8418_SELECT:
|
case TCA8418KeyboardBase::SELECT:
|
||||||
e.inputEvent = INPUT_BROKER_SELECT;
|
e.inputEvent = INPUT_BROKER_SELECT;
|
||||||
e.kbchar = 0x00;
|
e.kbchar = 0x00;
|
||||||
break;
|
break;
|
||||||
case _TCA8418_ESC:
|
case TCA8418KeyboardBase::ESC:
|
||||||
e.inputEvent = INPUT_BROKER_CANCEL;
|
e.inputEvent = INPUT_BROKER_CANCEL;
|
||||||
e.kbchar = 0;
|
e.kbchar = 0x00;
|
||||||
|
break;
|
||||||
|
case TCA8418KeyboardBase::GPS_TOGGLE:
|
||||||
|
e.inputEvent = INPUT_BROKER_ANYKEY;
|
||||||
|
e.kbchar = INPUT_BROKER_GPS_TOGGLE;
|
||||||
|
break;
|
||||||
|
case TCA8418KeyboardBase::SEND_PING:
|
||||||
|
e.inputEvent = INPUT_BROKER_ANYKEY;
|
||||||
|
e.kbchar = INPUT_BROKER_SEND_PING;
|
||||||
|
break;
|
||||||
|
case TCA8418KeyboardBase::MUTE_TOGGLE:
|
||||||
|
e.inputEvent = INPUT_BROKER_ANYKEY;
|
||||||
|
e.kbchar = INPUT_BROKER_MSG_MUTE_TOGGLE;
|
||||||
|
break;
|
||||||
|
case TCA8418KeyboardBase::BT_TOGGLE:
|
||||||
|
e.inputEvent = INPUT_BROKER_ANYKEY;
|
||||||
|
e.kbchar = INPUT_BROKER_MSG_BLUETOOTH_TOGGLE;
|
||||||
|
break;
|
||||||
|
case TCA8418KeyboardBase::BL_TOGGLE:
|
||||||
|
e.inputEvent = INPUT_BROKER_ANYKEY;
|
||||||
|
e.kbchar = INPUT_BROKER_MSG_BLUETOOTH_TOGGLE;
|
||||||
|
break;
|
||||||
|
case TCA8418KeyboardBase::TAB:
|
||||||
|
e.inputEvent = INPUT_BROKER_ANYKEY;
|
||||||
|
e.kbchar = INPUT_BROKER_MSG_TAB;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (nextEvent > 127) {
|
if (nextEvent > 127) {
|
||||||
@ -291,6 +331,7 @@ int32_t KbI2cBase::runOnce()
|
|||||||
LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar);
|
LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar);
|
||||||
this->notifyObservers(&e);
|
this->notifyObservers(&e);
|
||||||
}
|
}
|
||||||
|
TCAKeyboard.trigger();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
#include "BBQ10Keyboard.h"
|
#include "BBQ10Keyboard.h"
|
||||||
#include "InputBroker.h"
|
#include "InputBroker.h"
|
||||||
#include "MPR121Keyboard.h"
|
#include "MPR121Keyboard.h"
|
||||||
#include "TCA8418Keyboard.h"
|
|
||||||
#include "Wire.h"
|
#include "Wire.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
|
|
||||||
|
class TCA8418KeyboardBase;
|
||||||
|
|
||||||
class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -22,6 +23,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
|
|||||||
|
|
||||||
BBQ10Keyboard Q10keyboard;
|
BBQ10Keyboard Q10keyboard;
|
||||||
MPR121Keyboard MPRkeyboard;
|
MPR121Keyboard MPRkeyboard;
|
||||||
TCA8418Keyboard TCAKeyboard;
|
TCA8418KeyboardBase &TCAKeyboard;
|
||||||
bool is_sym = false;
|
bool is_sym = false;
|
||||||
};
|
};
|
12
src/main.cpp
12
src/main.cpp
@ -33,7 +33,6 @@
|
|||||||
#include "mesh/generated/meshtastic/config.pb.h"
|
#include "mesh/generated/meshtastic/config.pb.h"
|
||||||
#include "meshUtils.h"
|
#include "meshUtils.h"
|
||||||
#include "modules/Modules.h"
|
#include "modules/Modules.h"
|
||||||
#include "shutdown.h"
|
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -335,6 +334,15 @@ void setup()
|
|||||||
pinMode(TFT_CS, OUTPUT);
|
pinMode(TFT_CS, OUTPUT);
|
||||||
digitalWrite(TFT_CS, HIGH);
|
digitalWrite(TFT_CS, HIGH);
|
||||||
delay(100);
|
delay(100);
|
||||||
|
#elif defined(T_DECK_PRO)
|
||||||
|
pinMode(LORA_EN, OUTPUT);
|
||||||
|
digitalWrite(LORA_EN, HIGH);
|
||||||
|
pinMode(LORA_CS, OUTPUT);
|
||||||
|
digitalWrite(LORA_CS, HIGH);
|
||||||
|
pinMode(SDCARD_CS, OUTPUT);
|
||||||
|
digitalWrite(SDCARD_CS, HIGH);
|
||||||
|
pinMode(PIN_EINK_CS, OUTPUT);
|
||||||
|
digitalWrite(PIN_EINK_CS, HIGH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
concurrency::hasBeenSetup = true;
|
concurrency::hasBeenSetup = true;
|
||||||
@ -1521,7 +1529,7 @@ void loop()
|
|||||||
#ifdef ARCH_NRF52
|
#ifdef ARCH_NRF52
|
||||||
nrf52Loop();
|
nrf52Loop();
|
||||||
#endif
|
#endif
|
||||||
powerCommandsCheck();
|
power->powerCommandsCheck();
|
||||||
|
|
||||||
#ifdef DEBUG_STACK
|
#ifdef DEBUG_STACK
|
||||||
static uint32_t lastPrint = 0;
|
static uint32_t lastPrint = 0;
|
||||||
|
@ -628,11 +628,6 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
#ifdef PIN_GPS_EN
|
#ifdef PIN_GPS_EN
|
||||||
config.position.gps_en_gpio = PIN_GPS_EN;
|
config.position.gps_en_gpio = PIN_GPS_EN;
|
||||||
#endif
|
#endif
|
||||||
#ifdef GPS_POWER_TOGGLE
|
|
||||||
config.device.disable_triple_click = false;
|
|
||||||
#else
|
|
||||||
config.device.disable_triple_click = true;
|
|
||||||
#endif
|
|
||||||
#if defined(USERPREFS_CONFIG_GPS_MODE)
|
#if defined(USERPREFS_CONFIG_GPS_MODE)
|
||||||
config.position.gps_mode = USERPREFS_CONFIG_GPS_MODE;
|
config.position.gps_mode = USERPREFS_CONFIG_GPS_MODE;
|
||||||
#elif !HAS_GPS || GPS_DEFAULT_NOT_PRESENT
|
#elif !HAS_GPS || GPS_DEFAULT_NOT_PRESENT
|
||||||
@ -735,7 +730,6 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
config.display.screen_on_secs = 30;
|
config.display.screen_on_secs = 30;
|
||||||
config.display.wake_on_tap_or_motion = true;
|
config.display.wake_on_tap_or_motion = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
|
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
|
||||||
if (WiFiOTA::isUpdated()) {
|
if (WiFiOTA::isUpdated()) {
|
||||||
WiFiOTA::recoverConfig(&config.network);
|
WiFiOTA::recoverConfig(&config.network);
|
||||||
@ -796,6 +790,13 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
moduleConfig.external_notification.alert_message_buzzer = true;
|
moduleConfig.external_notification.alert_message_buzzer = true;
|
||||||
moduleConfig.external_notification.nag_timeout = default_ringtone_nag_secs;
|
moduleConfig.external_notification.nag_timeout = default_ringtone_nag_secs;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(PIN_VIBRATION)
|
||||||
|
moduleConfig.external_notification.enabled = true;
|
||||||
|
moduleConfig.external_notification.output_vibra = PIN_VIBRATION;
|
||||||
|
moduleConfig.external_notification.alert_message_vibra = true;
|
||||||
|
moduleConfig.external_notification.output_ms = 500;
|
||||||
|
moduleConfig.external_notification.nag_timeout = 2;
|
||||||
|
#endif
|
||||||
#if defined(RAK4630) || defined(RAK11310) || defined(RAK3312)
|
#if defined(RAK4630) || defined(RAK11310) || defined(RAK3312)
|
||||||
// Default to RAK led pin 2 (blue)
|
// Default to RAK led pin 2 (blue)
|
||||||
moduleConfig.external_notification.enabled = true;
|
moduleConfig.external_notification.enabled = true;
|
||||||
|
@ -67,6 +67,7 @@ const RegionInfo regions[] = {
|
|||||||
/*
|
/*
|
||||||
https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf
|
https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf
|
||||||
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
|
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
|
||||||
|
Also used in Brazil.
|
||||||
*/
|
*/
|
||||||
RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false),
|
RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false),
|
||||||
|
|
||||||
@ -169,6 +170,21 @@ const RegionInfo regions[] = {
|
|||||||
*/
|
*/
|
||||||
RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false), RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true),
|
RDEF(KZ_433, 433.075f, 434.775f, 100, 0, 10, true, false, false), RDEF(KZ_863, 863.0f, 868.0f, 100, 0, 30, true, false, true),
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Nepal
|
||||||
|
865 MHz to 868 MHz frequency band for IoT (Internet of Things), M2M (Machine-to-Machine), and smart metering use, specifically in non-cellular mode.
|
||||||
|
https://www.nta.gov.np/uploads/contents/Radio-Frequency-Policy-2080-English.pdf
|
||||||
|
*/
|
||||||
|
RDEF(NP_865, 865.0f, 868.0f, 100, 0, 30, true, false, false),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Brazil
|
||||||
|
902 - 907.5 MHz , 1W power limit, no duty cycle restrictions
|
||||||
|
https://github.com/meshtastic/firmware/issues/3741
|
||||||
|
*/
|
||||||
|
RDEF(BR_902, 902.0f, 907.5f, 100, 0, 30, true, false, false),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
|
2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
|
||||||
*/
|
*/
|
||||||
|
@ -293,7 +293,11 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
|
|||||||
/* Kazakhstan 433MHz */
|
/* Kazakhstan 433MHz */
|
||||||
meshtastic_Config_LoRaConfig_RegionCode_KZ_433 = 23,
|
meshtastic_Config_LoRaConfig_RegionCode_KZ_433 = 23,
|
||||||
/* Kazakhstan 863MHz */
|
/* Kazakhstan 863MHz */
|
||||||
meshtastic_Config_LoRaConfig_RegionCode_KZ_863 = 24
|
meshtastic_Config_LoRaConfig_RegionCode_KZ_863 = 24,
|
||||||
|
/* Nepal 865MHz */
|
||||||
|
meshtastic_Config_LoRaConfig_RegionCode_NP_865 = 25,
|
||||||
|
/* Brazil 902MHz */
|
||||||
|
meshtastic_Config_LoRaConfig_RegionCode_BR_902 = 26
|
||||||
} meshtastic_Config_LoRaConfig_RegionCode;
|
} meshtastic_Config_LoRaConfig_RegionCode;
|
||||||
|
|
||||||
/* Standard predefined channel settings
|
/* Standard predefined channel settings
|
||||||
@ -690,8 +694,8 @@ extern "C" {
|
|||||||
#define _meshtastic_Config_DisplayConfig_CompassOrientation_ARRAYSIZE ((meshtastic_Config_DisplayConfig_CompassOrientation)(meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED+1))
|
#define _meshtastic_Config_DisplayConfig_CompassOrientation_ARRAYSIZE ((meshtastic_Config_DisplayConfig_CompassOrientation)(meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET
|
#define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET
|
||||||
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_KZ_863
|
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_BR_902
|
||||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_KZ_863+1))
|
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_BR_902+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
|
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
|
||||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO
|
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO
|
||||||
|
@ -362,7 +362,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
|
|||||||
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
|
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
|
||||||
#define meshtastic_BackupPreferences_size 2271
|
#define meshtastic_BackupPreferences_size 2271
|
||||||
#define meshtastic_ChannelFile_size 718
|
#define meshtastic_ChannelFile_size 718
|
||||||
#define meshtastic_DeviceState_size 1722
|
#define meshtastic_DeviceState_size 1724
|
||||||
#define meshtastic_NodeInfoLite_size 196
|
#define meshtastic_NodeInfoLite_size 196
|
||||||
#define meshtastic_PositionLite_size 28
|
#define meshtastic_PositionLite_size 28
|
||||||
#define meshtastic_UserLite_size 98
|
#define meshtastic_UserLite_size 98
|
||||||
|
@ -117,6 +117,8 @@ PB_BIND(meshtastic_ChunkedPayloadResponse, meshtastic_ChunkedPayloadResponse, AU
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -325,6 +325,25 @@ typedef enum _meshtastic_CriticalErrorCode {
|
|||||||
meshtastic_CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE = 13
|
meshtastic_CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE = 13
|
||||||
} meshtastic_CriticalErrorCode;
|
} meshtastic_CriticalErrorCode;
|
||||||
|
|
||||||
|
/* Enum to indicate to clients whether this firmware is a special firmware build, like an event.
|
||||||
|
The first 16 values are reserved for non-event special firmwares, like the Smart Citizen use case. */
|
||||||
|
typedef enum _meshtastic_FirmwareEdition {
|
||||||
|
/* Vanilla firmware */
|
||||||
|
meshtastic_FirmwareEdition_VANILLA = 0,
|
||||||
|
/* Firmware for use in the Smart Citizen environmental monitoring network */
|
||||||
|
meshtastic_FirmwareEdition_SMART_CITIZEN = 1,
|
||||||
|
/* Open Sauce, the maker conference held yearly in CA */
|
||||||
|
meshtastic_FirmwareEdition_OPEN_SAUCE = 16,
|
||||||
|
/* DEFCON, the yearly hacker conference */
|
||||||
|
meshtastic_FirmwareEdition_DEFCON = 17,
|
||||||
|
/* Burning Man, the yearly hippie gathering in the desert */
|
||||||
|
meshtastic_FirmwareEdition_BURNING_MAN = 18,
|
||||||
|
/* Hamvention, the Dayton amateur radio convention */
|
||||||
|
meshtastic_FirmwareEdition_HAMVENTION = 19,
|
||||||
|
/* Placeholder for DIY and unofficial events */
|
||||||
|
meshtastic_FirmwareEdition_DIY_EDITION = 127
|
||||||
|
} meshtastic_FirmwareEdition;
|
||||||
|
|
||||||
/* Enum for modules excluded from a device's configuration.
|
/* Enum for modules excluded from a device's configuration.
|
||||||
Each value represents a ModuleConfigType that can be toggled as excluded
|
Each value represents a ModuleConfigType that can be toggled as excluded
|
||||||
by setting its corresponding bit in the `excluded_modules` bitmask field. */
|
by setting its corresponding bit in the `excluded_modules` bitmask field. */
|
||||||
@ -914,6 +933,8 @@ typedef struct _meshtastic_MyNodeInfo {
|
|||||||
meshtastic_MyNodeInfo_device_id_t device_id;
|
meshtastic_MyNodeInfo_device_id_t device_id;
|
||||||
/* The PlatformIO environment used to build this firmware */
|
/* The PlatformIO environment used to build this firmware */
|
||||||
char pio_env[40];
|
char pio_env[40];
|
||||||
|
/* The indicator for whether this device is running event firmware and which */
|
||||||
|
meshtastic_FirmwareEdition firmware_edition;
|
||||||
} meshtastic_MyNodeInfo;
|
} meshtastic_MyNodeInfo;
|
||||||
|
|
||||||
/* Debug output from the device.
|
/* Debug output from the device.
|
||||||
@ -1212,6 +1233,10 @@ extern "C" {
|
|||||||
#define _meshtastic_CriticalErrorCode_MAX meshtastic_CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE
|
#define _meshtastic_CriticalErrorCode_MAX meshtastic_CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE
|
||||||
#define _meshtastic_CriticalErrorCode_ARRAYSIZE ((meshtastic_CriticalErrorCode)(meshtastic_CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE+1))
|
#define _meshtastic_CriticalErrorCode_ARRAYSIZE ((meshtastic_CriticalErrorCode)(meshtastic_CriticalErrorCode_FLASH_CORRUPTION_UNRECOVERABLE+1))
|
||||||
|
|
||||||
|
#define _meshtastic_FirmwareEdition_MIN meshtastic_FirmwareEdition_VANILLA
|
||||||
|
#define _meshtastic_FirmwareEdition_MAX meshtastic_FirmwareEdition_DIY_EDITION
|
||||||
|
#define _meshtastic_FirmwareEdition_ARRAYSIZE ((meshtastic_FirmwareEdition)(meshtastic_FirmwareEdition_DIY_EDITION+1))
|
||||||
|
|
||||||
#define _meshtastic_ExcludedModules_MIN meshtastic_ExcludedModules_EXCLUDED_NONE
|
#define _meshtastic_ExcludedModules_MIN meshtastic_ExcludedModules_EXCLUDED_NONE
|
||||||
#define _meshtastic_ExcludedModules_MAX meshtastic_ExcludedModules_NETWORK_CONFIG
|
#define _meshtastic_ExcludedModules_MAX meshtastic_ExcludedModules_NETWORK_CONFIG
|
||||||
#define _meshtastic_ExcludedModules_ARRAYSIZE ((meshtastic_ExcludedModules)(meshtastic_ExcludedModules_NETWORK_CONFIG+1))
|
#define _meshtastic_ExcludedModules_ARRAYSIZE ((meshtastic_ExcludedModules)(meshtastic_ExcludedModules_NETWORK_CONFIG+1))
|
||||||
@ -1258,6 +1283,7 @@ extern "C" {
|
|||||||
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
|
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
|
||||||
|
|
||||||
|
|
||||||
|
#define meshtastic_MyNodeInfo_firmware_edition_ENUMTYPE meshtastic_FirmwareEdition
|
||||||
|
|
||||||
#define meshtastic_LogRecord_level_ENUMTYPE meshtastic_LogRecord_Level
|
#define meshtastic_LogRecord_level_ENUMTYPE meshtastic_LogRecord_Level
|
||||||
|
|
||||||
@ -1296,7 +1322,7 @@ extern "C" {
|
|||||||
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
|
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
|
||||||
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0}
|
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0}
|
||||||
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0}
|
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0}
|
||||||
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, ""}
|
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN}
|
||||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||||
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
||||||
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
||||||
@ -1327,7 +1353,7 @@ extern "C" {
|
|||||||
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
|
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
|
||||||
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0}
|
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0}
|
||||||
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0}
|
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0}
|
||||||
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, ""}
|
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN}
|
||||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||||
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
||||||
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
||||||
@ -1450,6 +1476,7 @@ extern "C" {
|
|||||||
#define meshtastic_MyNodeInfo_min_app_version_tag 11
|
#define meshtastic_MyNodeInfo_min_app_version_tag 11
|
||||||
#define meshtastic_MyNodeInfo_device_id_tag 12
|
#define meshtastic_MyNodeInfo_device_id_tag 12
|
||||||
#define meshtastic_MyNodeInfo_pio_env_tag 13
|
#define meshtastic_MyNodeInfo_pio_env_tag 13
|
||||||
|
#define meshtastic_MyNodeInfo_firmware_edition_tag 14
|
||||||
#define meshtastic_LogRecord_message_tag 1
|
#define meshtastic_LogRecord_message_tag 1
|
||||||
#define meshtastic_LogRecord_time_tag 2
|
#define meshtastic_LogRecord_time_tag 2
|
||||||
#define meshtastic_LogRecord_source_tag 3
|
#define meshtastic_LogRecord_source_tag 3
|
||||||
@ -1682,7 +1709,8 @@ X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \
|
|||||||
X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \
|
X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \
|
||||||
X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) \
|
X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) \
|
||||||
X(a, STATIC, SINGULAR, BYTES, device_id, 12) \
|
X(a, STATIC, SINGULAR, BYTES, device_id, 12) \
|
||||||
X(a, STATIC, SINGULAR, STRING, pio_env, 13)
|
X(a, STATIC, SINGULAR, STRING, pio_env, 13) \
|
||||||
|
X(a, STATIC, SINGULAR, UENUM, firmware_edition, 14)
|
||||||
#define meshtastic_MyNodeInfo_CALLBACK NULL
|
#define meshtastic_MyNodeInfo_CALLBACK NULL
|
||||||
#define meshtastic_MyNodeInfo_DEFAULT NULL
|
#define meshtastic_MyNodeInfo_DEFAULT NULL
|
||||||
|
|
||||||
@ -1965,7 +1993,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
|||||||
#define meshtastic_LowEntropyKey_size 0
|
#define meshtastic_LowEntropyKey_size 0
|
||||||
#define meshtastic_MeshPacket_size 378
|
#define meshtastic_MeshPacket_size 378
|
||||||
#define meshtastic_MqttClientProxyMessage_size 501
|
#define meshtastic_MqttClientProxyMessage_size 501
|
||||||
#define meshtastic_MyNodeInfo_size 77
|
#define meshtastic_MyNodeInfo_size 79
|
||||||
#define meshtastic_NeighborInfo_size 258
|
#define meshtastic_NeighborInfo_size 258
|
||||||
#define meshtastic_Neighbor_size 22
|
#define meshtastic_Neighbor_size 22
|
||||||
#define meshtastic_NodeInfo_size 323
|
#define meshtastic_NodeInfo_size 323
|
||||||
|
@ -97,7 +97,9 @@ typedef enum _meshtastic_TelemetrySensorType {
|
|||||||
/* ADS1X15 ADC_ALT */
|
/* ADS1X15 ADC_ALT */
|
||||||
meshtastic_TelemetrySensorType_ADS1X15_ALT = 41,
|
meshtastic_TelemetrySensorType_ADS1X15_ALT = 41,
|
||||||
/* Sensirion SFA30 Formaldehyde sensor */
|
/* Sensirion SFA30 Formaldehyde sensor */
|
||||||
meshtastic_TelemetrySensorType_SFA30 = 42
|
meshtastic_TelemetrySensorType_SFA30 = 42,
|
||||||
|
/* SEN5X PM SENSORS */
|
||||||
|
meshtastic_TelemetrySensorType_SEN5X = 43
|
||||||
} meshtastic_TelemetrySensorType;
|
} meshtastic_TelemetrySensorType;
|
||||||
|
|
||||||
/* Struct definitions */
|
/* Struct definitions */
|
||||||
@ -246,40 +248,40 @@ typedef struct _meshtastic_PowerMetrics {
|
|||||||
|
|
||||||
/* Air quality metrics */
|
/* Air quality metrics */
|
||||||
typedef struct _meshtastic_AirQualityMetrics {
|
typedef struct _meshtastic_AirQualityMetrics {
|
||||||
/* Concentration Units Standard PM1.0 */
|
/* Concentration Units Standard PM1.0 in ug/m3 */
|
||||||
bool has_pm10_standard;
|
bool has_pm10_standard;
|
||||||
uint32_t pm10_standard;
|
uint32_t pm10_standard;
|
||||||
/* Concentration Units Standard PM2.5 */
|
/* Concentration Units Standard PM2.5 in ug/m3 */
|
||||||
bool has_pm25_standard;
|
bool has_pm25_standard;
|
||||||
uint32_t pm25_standard;
|
uint32_t pm25_standard;
|
||||||
/* Concentration Units Standard PM10.0 */
|
/* Concentration Units Standard PM10.0 in ug/m3 */
|
||||||
bool has_pm100_standard;
|
bool has_pm100_standard;
|
||||||
uint32_t pm100_standard;
|
uint32_t pm100_standard;
|
||||||
/* Concentration Units Environmental PM1.0 */
|
/* Concentration Units Environmental PM1.0 in ug/m3 */
|
||||||
bool has_pm10_environmental;
|
bool has_pm10_environmental;
|
||||||
uint32_t pm10_environmental;
|
uint32_t pm10_environmental;
|
||||||
/* Concentration Units Environmental PM2.5 */
|
/* Concentration Units Environmental PM2.5 in ug/m3 */
|
||||||
bool has_pm25_environmental;
|
bool has_pm25_environmental;
|
||||||
uint32_t pm25_environmental;
|
uint32_t pm25_environmental;
|
||||||
/* Concentration Units Environmental PM10.0 */
|
/* Concentration Units Environmental PM10.0 in ug/m3 */
|
||||||
bool has_pm100_environmental;
|
bool has_pm100_environmental;
|
||||||
uint32_t pm100_environmental;
|
uint32_t pm100_environmental;
|
||||||
/* 0.3um Particle Count */
|
/* 0.3um Particle Count in #/0.1l */
|
||||||
bool has_particles_03um;
|
bool has_particles_03um;
|
||||||
uint32_t particles_03um;
|
uint32_t particles_03um;
|
||||||
/* 0.5um Particle Count */
|
/* 0.5um Particle Count in #/0.1l */
|
||||||
bool has_particles_05um;
|
bool has_particles_05um;
|
||||||
uint32_t particles_05um;
|
uint32_t particles_05um;
|
||||||
/* 1.0um Particle Count */
|
/* 1.0um Particle Count in #/0.1l */
|
||||||
bool has_particles_10um;
|
bool has_particles_10um;
|
||||||
uint32_t particles_10um;
|
uint32_t particles_10um;
|
||||||
/* 2.5um Particle Count */
|
/* 2.5um Particle Count in #/0.1l */
|
||||||
bool has_particles_25um;
|
bool has_particles_25um;
|
||||||
uint32_t particles_25um;
|
uint32_t particles_25um;
|
||||||
/* 5.0um Particle Count */
|
/* 5.0um Particle Count in #/0.1l */
|
||||||
bool has_particles_50um;
|
bool has_particles_50um;
|
||||||
uint32_t particles_50um;
|
uint32_t particles_50um;
|
||||||
/* 10.0um Particle Count */
|
/* 10.0um Particle Count in #/0.1l */
|
||||||
bool has_particles_100um;
|
bool has_particles_100um;
|
||||||
uint32_t particles_100um;
|
uint32_t particles_100um;
|
||||||
/* CO2 concentration in ppm */
|
/* CO2 concentration in ppm */
|
||||||
@ -300,6 +302,27 @@ typedef struct _meshtastic_AirQualityMetrics {
|
|||||||
/* Formaldehyde sensor temperature in degrees Celsius */
|
/* Formaldehyde sensor temperature in degrees Celsius */
|
||||||
bool has_form_temperature;
|
bool has_form_temperature;
|
||||||
float form_temperature;
|
float form_temperature;
|
||||||
|
/* Concentration Units Standard PM4.0 in ug/m3 */
|
||||||
|
bool has_pm40_standard;
|
||||||
|
uint32_t pm40_standard;
|
||||||
|
/* 4.0um Particle Count in #/0.1l */
|
||||||
|
bool has_particles_40um;
|
||||||
|
uint32_t particles_40um;
|
||||||
|
/* PM Sensor Temperature */
|
||||||
|
bool has_pm_temperature;
|
||||||
|
float pm_temperature;
|
||||||
|
/* PM Sensor humidity */
|
||||||
|
bool has_pm_humidity;
|
||||||
|
float pm_humidity;
|
||||||
|
/* PM Sensor VOC Index */
|
||||||
|
bool has_pm_voc_idx;
|
||||||
|
float pm_voc_idx;
|
||||||
|
/* PM Sensor NOx Index */
|
||||||
|
bool has_pm_nox_idx;
|
||||||
|
float pm_nox_idx;
|
||||||
|
/* Typical Particle Size in um */
|
||||||
|
bool has_particles_tps;
|
||||||
|
float particles_tps;
|
||||||
} meshtastic_AirQualityMetrics;
|
} meshtastic_AirQualityMetrics;
|
||||||
|
|
||||||
/* Local device mesh statistics */
|
/* Local device mesh statistics */
|
||||||
@ -411,8 +434,8 @@ extern "C" {
|
|||||||
|
|
||||||
/* Helper constants for enums */
|
/* Helper constants for enums */
|
||||||
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
||||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SFA30
|
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SEN5X
|
||||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SFA30+1))
|
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SEN5X+1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -428,7 +451,7 @@ extern "C" {
|
|||||||
#define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0}
|
#define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
#define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
#define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0}
|
#define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""}
|
#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""}
|
||||||
@ -437,7 +460,7 @@ extern "C" {
|
|||||||
#define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0}
|
#define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
#define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
#define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
#define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0}
|
#define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0}
|
||||||
#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""}
|
#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""}
|
||||||
@ -506,6 +529,13 @@ extern "C" {
|
|||||||
#define meshtastic_AirQualityMetrics_form_formaldehyde_tag 16
|
#define meshtastic_AirQualityMetrics_form_formaldehyde_tag 16
|
||||||
#define meshtastic_AirQualityMetrics_form_humidity_tag 17
|
#define meshtastic_AirQualityMetrics_form_humidity_tag 17
|
||||||
#define meshtastic_AirQualityMetrics_form_temperature_tag 18
|
#define meshtastic_AirQualityMetrics_form_temperature_tag 18
|
||||||
|
#define meshtastic_AirQualityMetrics_pm40_standard_tag 19
|
||||||
|
#define meshtastic_AirQualityMetrics_particles_40um_tag 20
|
||||||
|
#define meshtastic_AirQualityMetrics_pm_temperature_tag 21
|
||||||
|
#define meshtastic_AirQualityMetrics_pm_humidity_tag 22
|
||||||
|
#define meshtastic_AirQualityMetrics_pm_voc_idx_tag 23
|
||||||
|
#define meshtastic_AirQualityMetrics_pm_nox_idx_tag 24
|
||||||
|
#define meshtastic_AirQualityMetrics_particles_tps_tag 25
|
||||||
#define meshtastic_LocalStats_uptime_seconds_tag 1
|
#define meshtastic_LocalStats_uptime_seconds_tag 1
|
||||||
#define meshtastic_LocalStats_channel_utilization_tag 2
|
#define meshtastic_LocalStats_channel_utilization_tag 2
|
||||||
#define meshtastic_LocalStats_air_util_tx_tag 3
|
#define meshtastic_LocalStats_air_util_tx_tag 3
|
||||||
@ -616,7 +646,14 @@ X(a, STATIC, OPTIONAL, FLOAT, co2_temperature, 14) \
|
|||||||
X(a, STATIC, OPTIONAL, FLOAT, co2_humidity, 15) \
|
X(a, STATIC, OPTIONAL, FLOAT, co2_humidity, 15) \
|
||||||
X(a, STATIC, OPTIONAL, FLOAT, form_formaldehyde, 16) \
|
X(a, STATIC, OPTIONAL, FLOAT, form_formaldehyde, 16) \
|
||||||
X(a, STATIC, OPTIONAL, FLOAT, form_humidity, 17) \
|
X(a, STATIC, OPTIONAL, FLOAT, form_humidity, 17) \
|
||||||
X(a, STATIC, OPTIONAL, FLOAT, form_temperature, 18)
|
X(a, STATIC, OPTIONAL, FLOAT, form_temperature, 18) \
|
||||||
|
X(a, STATIC, OPTIONAL, UINT32, pm40_standard, 19) \
|
||||||
|
X(a, STATIC, OPTIONAL, UINT32, particles_40um, 20) \
|
||||||
|
X(a, STATIC, OPTIONAL, FLOAT, pm_temperature, 21) \
|
||||||
|
X(a, STATIC, OPTIONAL, FLOAT, pm_humidity, 22) \
|
||||||
|
X(a, STATIC, OPTIONAL, FLOAT, pm_voc_idx, 23) \
|
||||||
|
X(a, STATIC, OPTIONAL, FLOAT, pm_nox_idx, 24) \
|
||||||
|
X(a, STATIC, OPTIONAL, FLOAT, particles_tps, 25)
|
||||||
#define meshtastic_AirQualityMetrics_CALLBACK NULL
|
#define meshtastic_AirQualityMetrics_CALLBACK NULL
|
||||||
#define meshtastic_AirQualityMetrics_DEFAULT NULL
|
#define meshtastic_AirQualityMetrics_DEFAULT NULL
|
||||||
|
|
||||||
@ -705,7 +742,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg;
|
|||||||
|
|
||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
|
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
|
||||||
#define meshtastic_AirQualityMetrics_size 106
|
#define meshtastic_AirQualityMetrics_size 150
|
||||||
#define meshtastic_DeviceMetrics_size 27
|
#define meshtastic_DeviceMetrics_size 27
|
||||||
#define meshtastic_EnvironmentMetrics_size 113
|
#define meshtastic_EnvironmentMetrics_size 113
|
||||||
#define meshtastic_HealthMetrics_size 11
|
#define meshtastic_HealthMetrics_size 11
|
||||||
|
@ -596,7 +596,6 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
|||||||
if (config.device.button_gpio == c.payload_variant.device.button_gpio &&
|
if (config.device.button_gpio == c.payload_variant.device.button_gpio &&
|
||||||
config.device.buzzer_gpio == c.payload_variant.device.buzzer_gpio &&
|
config.device.buzzer_gpio == c.payload_variant.device.buzzer_gpio &&
|
||||||
config.device.role == c.payload_variant.device.role &&
|
config.device.role == c.payload_variant.device.role &&
|
||||||
config.device.disable_triple_click == c.payload_variant.device.disable_triple_click &&
|
|
||||||
config.device.rebroadcast_mode == c.payload_variant.device.rebroadcast_mode) {
|
config.device.rebroadcast_mode == c.payload_variant.device.rebroadcast_mode) {
|
||||||
requiresReboot = false;
|
requiresReboot = false;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ CannedMessageModule::CannedMessageModule()
|
|||||||
disable();
|
disable();
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO("CannedMessageModule is enabled");
|
LOG_INFO("CannedMessageModule is enabled");
|
||||||
|
moduleConfig.canned_message.enabled = true;
|
||||||
this->inputObserver.observe(inputBroker);
|
this->inputObserver.observe(inputBroker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2075,6 +2076,9 @@ void CannedMessageModule::handleSetCannedMessageModuleMessages(const char *from_
|
|||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
this->saveProtoForModule();
|
this->saveProtoForModule();
|
||||||
|
if (splitConfiguredMessages()) {
|
||||||
|
moduleConfig.canned_message.enabled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,9 @@ int32_t ExternalNotificationModule::runOnce()
|
|||||||
millis()) {
|
millis()) {
|
||||||
setExternalState(1, !getExternal(1));
|
setExternalState(1, !getExternal(1));
|
||||||
}
|
}
|
||||||
if (externalTurnedOn[2] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms
|
// Only toggle buzzer output if not using PWM mode (to avoid conflict with RTTTL)
|
||||||
|
if (!moduleConfig.external_notification.use_pwm &&
|
||||||
|
externalTurnedOn[2] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms
|
||||||
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
|
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
|
||||||
millis()) {
|
millis()) {
|
||||||
LOG_DEBUG("EXTERNAL 2 %d compared to %d", externalTurnedOn[2] + moduleConfig.external_notification.output_ms,
|
LOG_DEBUG("EXTERNAL 2 %d compared to %d", externalTurnedOn[2] + moduleConfig.external_notification.output_ms,
|
||||||
@ -247,7 +249,8 @@ void ExternalNotificationModule::setExternalState(uint8_t index, bool on)
|
|||||||
digitalWrite(moduleConfig.external_notification.output_vibra, on);
|
digitalWrite(moduleConfig.external_notification.output_vibra, on);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (moduleConfig.external_notification.output_buzzer)
|
// Only control buzzer pin digitally if not using PWM mode
|
||||||
|
if (moduleConfig.external_notification.output_buzzer && !moduleConfig.external_notification.use_pwm)
|
||||||
digitalWrite(moduleConfig.external_notification.output_buzzer, on);
|
digitalWrite(moduleConfig.external_notification.output_buzzer, on);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -320,6 +323,11 @@ void ExternalNotificationModule::stopNow()
|
|||||||
#endif
|
#endif
|
||||||
nagCycleCutoff = 1; // small value
|
nagCycleCutoff = 1; // small value
|
||||||
isNagging = false;
|
isNagging = false;
|
||||||
|
// Turn off all outputs
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
setExternalState(i, false);
|
||||||
|
externalTurnedOn[i] = 0;
|
||||||
|
}
|
||||||
setIntervalFromNow(0);
|
setIntervalFromNow(0);
|
||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
drv.stop();
|
drv.stop();
|
||||||
@ -478,14 +486,17 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
|||||||
if (containsBell) {
|
if (containsBell) {
|
||||||
LOG_INFO("externalNotificationModule - Notification Bell (Buzzer)");
|
LOG_INFO("externalNotificationModule - Notification Bell (Buzzer)");
|
||||||
isNagging = true;
|
isNagging = true;
|
||||||
if (!moduleConfig.external_notification.use_pwm) {
|
if (!moduleConfig.external_notification.use_pwm && !moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||||
setExternalState(2, true);
|
setExternalState(2, true);
|
||||||
} else {
|
} else {
|
||||||
#ifdef HAS_I2S
|
#ifdef HAS_I2S
|
||||||
|
if (moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||||
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
||||||
#else
|
} else
|
||||||
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
|
|
||||||
#endif
|
#endif
|
||||||
|
if (moduleConfig.external_notification.use_pwm) {
|
||||||
|
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (moduleConfig.external_notification.nag_timeout) {
|
if (moduleConfig.external_notification.nag_timeout) {
|
||||||
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
||||||
@ -526,10 +537,11 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
|||||||
#ifdef HAS_I2S
|
#ifdef HAS_I2S
|
||||||
if (moduleConfig.external_notification.use_i2s_as_buzzer) {
|
if (moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||||
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
||||||
}
|
} else
|
||||||
#else
|
|
||||||
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
|
|
||||||
#endif
|
#endif
|
||||||
|
if (moduleConfig.external_notification.use_pwm) {
|
||||||
|
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (moduleConfig.external_notification.nag_timeout) {
|
if (moduleConfig.external_notification.nag_timeout) {
|
||||||
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
#include "TraceRouteModule.h"
|
#include "TraceRouteModule.h"
|
||||||
#include "MeshService.h"
|
#include "MeshService.h"
|
||||||
|
#include "graphics/Screen.h"
|
||||||
|
#include "graphics/ScreenFonts.h"
|
||||||
|
#include "graphics/SharedUIDisplay.h"
|
||||||
|
#include "mesh/Router.h"
|
||||||
#include "meshUtils.h"
|
#include "meshUtils.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
extern graphics::Screen *screen;
|
||||||
|
|
||||||
TraceRouteModule *traceRouteModule;
|
TraceRouteModule *traceRouteModule;
|
||||||
|
|
||||||
@ -27,6 +34,123 @@ void TraceRouteModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtasti
|
|||||||
// Set updated route to the payload of the to be flooded packet
|
// Set updated route to the payload of the to be flooded packet
|
||||||
p.decoded.payload.size =
|
p.decoded.payload.size =
|
||||||
pb_encode_to_bytes(p.decoded.payload.bytes, sizeof(p.decoded.payload.bytes), &meshtastic_RouteDiscovery_msg, r);
|
pb_encode_to_bytes(p.decoded.payload.bytes, sizeof(p.decoded.payload.bytes), &meshtastic_RouteDiscovery_msg, r);
|
||||||
|
|
||||||
|
if (tracingNode != 0) {
|
||||||
|
// check isResponseFromTarget
|
||||||
|
bool isResponseFromTarget = (incoming.request_id != 0 && p.from == tracingNode);
|
||||||
|
bool isRequestToUs = (incoming.request_id == 0 && p.to == nodeDB->getNodeNum() && tracingNode != 0);
|
||||||
|
|
||||||
|
// Check if this is a trace route response containing our target node
|
||||||
|
bool containsTargetNode = false;
|
||||||
|
for (uint8_t i = 0; i < r->route_count; i++) {
|
||||||
|
if (r->route[i] == tracingNode) {
|
||||||
|
containsTargetNode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint8_t i = 0; i < r->route_back_count; i++) {
|
||||||
|
if (r->route_back[i] == tracingNode) {
|
||||||
|
containsTargetNode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this response contains a complete route to our target
|
||||||
|
bool hasCompleteRoute = (r->route_count > 0 && r->route_back_count > 0) ||
|
||||||
|
(containsTargetNode && (r->route_count > 0 || r->route_back_count > 0));
|
||||||
|
|
||||||
|
LOG_INFO("TracRoute packet analysis: tracingNode=0x%08x, p.from=0x%08x, p.to=0x%08x, request_id=0x%08x", tracingNode,
|
||||||
|
p.from, p.to, incoming.request_id);
|
||||||
|
LOG_INFO("TracRoute conditions: isResponseFromTarget=%d, isRequestToUs=%d, containsTargetNode=%d, hasCompleteRoute=%d",
|
||||||
|
isResponseFromTarget, isRequestToUs, containsTargetNode, hasCompleteRoute);
|
||||||
|
|
||||||
|
if (isResponseFromTarget || isRequestToUs || (containsTargetNode && hasCompleteRoute)) {
|
||||||
|
LOG_INFO("TracRoute result detected: isResponseFromTarget=%d, isRequestToUs=%d", isResponseFromTarget, isRequestToUs);
|
||||||
|
|
||||||
|
LOG_INFO("SNR arrays - towards_count=%d, back_count=%d", r->snr_towards_count, r->snr_back_count);
|
||||||
|
for (int i = 0; i < r->snr_towards_count; i++) {
|
||||||
|
LOG_INFO("SNR towards[%d] = %d (%.1fdB)", i, r->snr_towards[i], (float)r->snr_towards[i] / 4.0f);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < r->snr_back_count; i++) {
|
||||||
|
LOG_INFO("SNR back[%d] = %d (%.1fdB)", i, r->snr_back[i], (float)r->snr_back[i] / 4.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
|
||||||
|
// Show request path (from initiator to target)
|
||||||
|
if (r->route_count > 0) {
|
||||||
|
result += getNodeName(nodeDB->getNodeNum());
|
||||||
|
for (uint8_t i = 0; i < r->route_count; i++) {
|
||||||
|
result += " > ";
|
||||||
|
const char *name = getNodeName(r->route[i]);
|
||||||
|
float snr =
|
||||||
|
(i < r->snr_towards_count && r->snr_towards[i] != INT8_MIN) ? ((float)r->snr_towards[i] / 4.0f) : 0.0f;
|
||||||
|
result += name;
|
||||||
|
if (snr != 0.0f) {
|
||||||
|
result += "(";
|
||||||
|
result += String(snr, 1);
|
||||||
|
result += "dB)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += " > ";
|
||||||
|
result += getNodeName(tracingNode);
|
||||||
|
if (r->snr_towards_count > 0 && r->snr_towards[r->snr_towards_count - 1] != INT8_MIN) {
|
||||||
|
result += "(";
|
||||||
|
result += String((float)r->snr_towards[r->snr_towards_count - 1] / 4.0f, 1);
|
||||||
|
result += "dB)";
|
||||||
|
}
|
||||||
|
result += "\n";
|
||||||
|
} else {
|
||||||
|
// Direct connection (no intermediate hops)
|
||||||
|
result += getNodeName(nodeDB->getNodeNum());
|
||||||
|
result += " > ";
|
||||||
|
result += getNodeName(tracingNode);
|
||||||
|
if (r->snr_towards_count > 0 && r->snr_towards[0] != INT8_MIN) {
|
||||||
|
result += "(";
|
||||||
|
result += String((float)r->snr_towards[0] / 4.0f, 1);
|
||||||
|
result += "dB)";
|
||||||
|
}
|
||||||
|
result += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show response path (from target back to initiator)
|
||||||
|
if (r->route_back_count > 0) {
|
||||||
|
result += getNodeName(tracingNode);
|
||||||
|
for (int8_t i = r->route_back_count - 1; i >= 0; i--) {
|
||||||
|
result += " > ";
|
||||||
|
const char *name = getNodeName(r->route_back[i]);
|
||||||
|
float snr = (i < r->snr_back_count && r->snr_back[i] != INT8_MIN) ? ((float)r->snr_back[i] / 4.0f) : 0.0f;
|
||||||
|
result += name;
|
||||||
|
if (snr != 0.0f) {
|
||||||
|
result += "(";
|
||||||
|
result += String(snr, 1);
|
||||||
|
result += "dB)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add initiator node
|
||||||
|
result += " > ";
|
||||||
|
result += getNodeName(nodeDB->getNodeNum());
|
||||||
|
if (r->snr_back_count > 0 && r->snr_back[r->snr_back_count - 1] != INT8_MIN) {
|
||||||
|
result += "(";
|
||||||
|
result += String((float)r->snr_back[r->snr_back_count - 1] / 4.0f, 1);
|
||||||
|
result += "dB)";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Direct return path (no intermediate hops)
|
||||||
|
result += getNodeName(tracingNode);
|
||||||
|
result += " > ";
|
||||||
|
result += getNodeName(nodeDB->getNodeNum());
|
||||||
|
if (r->snr_back_count > 0 && r->snr_back[0] != INT8_MIN) {
|
||||||
|
result += "(";
|
||||||
|
result += String((float)r->snr_back[0] / 4.0f, 1);
|
||||||
|
result += "dB)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Trace route result: %s", result.c_str());
|
||||||
|
handleTraceRouteResult(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r, bool isTowardsDestination)
|
void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r, bool isTowardsDestination)
|
||||||
@ -173,8 +297,467 @@ meshtastic_MeshPacket *TraceRouteModule::allocReply()
|
|||||||
}
|
}
|
||||||
|
|
||||||
TraceRouteModule::TraceRouteModule()
|
TraceRouteModule::TraceRouteModule()
|
||||||
: ProtobufModule("traceroute", meshtastic_PortNum_TRACEROUTE_APP, &meshtastic_RouteDiscovery_msg)
|
: ProtobufModule("traceroute", meshtastic_PortNum_TRACEROUTE_APP, &meshtastic_RouteDiscovery_msg), OSThread("TraceRoute")
|
||||||
{
|
{
|
||||||
ourPortNum = meshtastic_PortNum_TRACEROUTE_APP;
|
ourPortNum = meshtastic_PortNum_TRACEROUTE_APP;
|
||||||
isPromiscuous = true; // We need to update the route even if it is not destined to us
|
isPromiscuous = true; // We need to update the route even if it is not destined to us
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *TraceRouteModule::getNodeName(NodeNum node)
|
||||||
|
{
|
||||||
|
meshtastic_NodeInfoLite *info = nodeDB->getMeshNode(node);
|
||||||
|
if (info && info->has_user) {
|
||||||
|
if (strlen(info->user.short_name) > 0) {
|
||||||
|
return info->user.short_name;
|
||||||
|
}
|
||||||
|
if (strlen(info->user.long_name) > 0) {
|
||||||
|
return info->user.long_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char fallback[12];
|
||||||
|
snprintf(fallback, sizeof(fallback), "0x%08x", node);
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TraceRouteModule::startTraceRoute(NodeNum node)
|
||||||
|
{
|
||||||
|
LOG_INFO("=== TraceRoute startTraceRoute CALLED: node=0x%08x ===", node);
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
if (node == 0 || node == NODENUM_BROADCAST) {
|
||||||
|
LOG_ERROR("Invalid node number for trace route: 0x%08x", node);
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "Invalid node";
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == nodeDB->getNodeNum()) {
|
||||||
|
LOG_ERROR("Cannot trace route to self: 0x%08x", node);
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "Cannot trace self";
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
lastTraceRouteTime = 0;
|
||||||
|
initialized = true;
|
||||||
|
LOG_INFO("TraceRoute initialized for first time");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runState == TRACEROUTE_STATE_TRACKING) {
|
||||||
|
LOG_INFO("TraceRoute already in progress");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialized && lastTraceRouteTime > 0 && now - lastTraceRouteTime < cooldownMs) {
|
||||||
|
// Cooldown
|
||||||
|
unsigned long wait = (cooldownMs - (now - lastTraceRouteTime)) / 1000;
|
||||||
|
bannerText = String("Wait for ") + String(wait) + String("s");
|
||||||
|
runState = TRACEROUTE_STATE_COOLDOWN;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
LOG_INFO("Cooldown active, please wait %lu seconds before starting a new trace route.", wait);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracingNode = node;
|
||||||
|
lastTraceRouteTime = now;
|
||||||
|
runState = TRACEROUTE_STATE_TRACKING;
|
||||||
|
bannerText = String("Tracing ") + getNodeName(node);
|
||||||
|
|
||||||
|
LOG_INFO("TraceRoute UI: Starting trace route to node 0x%08x, requesting focus", node);
|
||||||
|
|
||||||
|
// 请求焦点,然后触发UI更新事件
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
|
||||||
|
// 设置定时器来处理超时检查
|
||||||
|
setIntervalFromNow(1000); // 每秒检查一次状态
|
||||||
|
|
||||||
|
meshtastic_RouteDiscovery req = meshtastic_RouteDiscovery_init_zero;
|
||||||
|
LOG_INFO("Creating RouteDiscovery protobuf...");
|
||||||
|
|
||||||
|
// Allocate a packet directly from router like the reference code
|
||||||
|
meshtastic_MeshPacket *p = router->allocForSending();
|
||||||
|
if (p) {
|
||||||
|
// Set destination and port
|
||||||
|
p->to = node;
|
||||||
|
p->decoded.portnum = meshtastic_PortNum_TRACEROUTE_APP;
|
||||||
|
p->decoded.want_response = true;
|
||||||
|
|
||||||
|
// Manually encode the RouteDiscovery payload
|
||||||
|
p->decoded.payload.size =
|
||||||
|
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_RouteDiscovery_msg, &req);
|
||||||
|
|
||||||
|
LOG_INFO("Packet allocated successfully: to=0x%08x, portnum=%d, want_response=%d, payload_size=%d", p->to,
|
||||||
|
p->decoded.portnum, p->decoded.want_response, p->decoded.payload.size);
|
||||||
|
LOG_INFO("About to call service->sendToMesh...");
|
||||||
|
|
||||||
|
if (service) {
|
||||||
|
LOG_INFO("MeshService is available, sending packet...");
|
||||||
|
service->sendToMesh(p, RX_SRC_USER);
|
||||||
|
LOG_INFO("sendToMesh called successfully for trace route to node 0x%08x", node);
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("MeshService is NULL!");
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "Service unavailable";
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e2;
|
||||||
|
e2.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Failed to allocate TraceRoute packet from router");
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "Failed to send";
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e2;
|
||||||
|
e2.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceRouteModule::launch(NodeNum node)
|
||||||
|
{
|
||||||
|
if (node == 0 || node == NODENUM_BROADCAST) {
|
||||||
|
LOG_ERROR("Invalid node number for trace route: 0x%08x", node);
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "Invalid node";
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == nodeDB->getNodeNum()) {
|
||||||
|
LOG_ERROR("Cannot trace route to self: 0x%08x", node);
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "Cannot trace self";
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
lastTraceRouteTime = 0;
|
||||||
|
initialized = true;
|
||||||
|
LOG_INFO("TraceRoute initialized for first time");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long now = millis();
|
||||||
|
if (initialized && lastTraceRouteTime > 0 && now - lastTraceRouteTime < cooldownMs) {
|
||||||
|
unsigned long wait = (cooldownMs - (now - lastTraceRouteTime)) / 1000;
|
||||||
|
bannerText = String("Wait for ") + String(wait) + String("s");
|
||||||
|
runState = TRACEROUTE_STATE_COOLDOWN;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
LOG_INFO("Cooldown active, please wait %lu seconds before starting a new trace route.", wait);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
runState = TRACEROUTE_STATE_TRACKING;
|
||||||
|
tracingNode = node;
|
||||||
|
lastTraceRouteTime = now;
|
||||||
|
bannerText = String("Tracing ") + getNodeName(node);
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
|
||||||
|
setIntervalFromNow(1000);
|
||||||
|
|
||||||
|
meshtastic_RouteDiscovery req = meshtastic_RouteDiscovery_init_zero;
|
||||||
|
LOG_INFO("Creating RouteDiscovery protobuf...");
|
||||||
|
|
||||||
|
meshtastic_MeshPacket *p = router->allocForSending();
|
||||||
|
if (p) {
|
||||||
|
p->to = node;
|
||||||
|
p->decoded.portnum = meshtastic_PortNum_TRACEROUTE_APP;
|
||||||
|
p->decoded.want_response = true;
|
||||||
|
|
||||||
|
p->decoded.payload.size =
|
||||||
|
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_RouteDiscovery_msg, &req);
|
||||||
|
|
||||||
|
LOG_INFO("Packet allocated successfully: to=0x%08x, portnum=%d, want_response=%d, payload_size=%d", p->to,
|
||||||
|
p->decoded.portnum, p->decoded.want_response, p->decoded.payload.size);
|
||||||
|
|
||||||
|
if (service) {
|
||||||
|
service->sendToMesh(p, RX_SRC_USER);
|
||||||
|
LOG_INFO("sendToMesh called successfully for trace route to node 0x%08x", node);
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("MeshService is NULL!");
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "Service unavailable";
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Failed to allocate TraceRoute packet from router");
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "Failed to send";
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceRouteModule::handleTraceRouteResult(const String &result)
|
||||||
|
{
|
||||||
|
resultText = result;
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultShowTime = millis();
|
||||||
|
tracingNode = 0;
|
||||||
|
|
||||||
|
LOG_INFO("TraceRoute result ready, requesting focus. Result: %s", result.c_str());
|
||||||
|
|
||||||
|
setIntervalFromNow(1000);
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
|
||||||
|
LOG_INFO("=== TraceRoute handleTraceRouteResult END ===");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TraceRouteModule::shouldDraw()
|
||||||
|
{
|
||||||
|
bool draw = (runState != TRACEROUTE_STATE_IDLE);
|
||||||
|
static TraceRouteRunState lastLoggedState = TRACEROUTE_STATE_IDLE;
|
||||||
|
if (runState != lastLoggedState) {
|
||||||
|
LOG_INFO("TraceRoute shouldDraw: runState=%d, draw=%d", runState, draw);
|
||||||
|
lastLoggedState = runState;
|
||||||
|
}
|
||||||
|
return draw;
|
||||||
|
}
|
||||||
|
#if HAS_SCREEN
|
||||||
|
void TraceRouteModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("TraceRoute drawFrame called: runState=%d", runState);
|
||||||
|
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
|
||||||
|
if (runState == TRACEROUTE_STATE_TRACKING) {
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
int centerY = y + (display->getHeight() / 2) - (FONT_HEIGHT_MEDIUM / 2);
|
||||||
|
display->drawString(display->getWidth() / 2 + x, centerY, bannerText);
|
||||||
|
|
||||||
|
} else if (runState == TRACEROUTE_STATE_RESULT) {
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
|
||||||
|
display->drawString(x, y, "Route Result");
|
||||||
|
|
||||||
|
int contentStartY = y + FONT_HEIGHT_MEDIUM + 2; // Add more spacing after title
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
|
||||||
|
if (resultText.length() > 0) {
|
||||||
|
std::vector<String> lines;
|
||||||
|
String currentLine = "";
|
||||||
|
int maxWidth = display->getWidth() - 4;
|
||||||
|
|
||||||
|
int start = 0;
|
||||||
|
int newlinePos = resultText.indexOf('\n', start);
|
||||||
|
|
||||||
|
while (newlinePos != -1 || start < resultText.length()) {
|
||||||
|
String segment;
|
||||||
|
if (newlinePos != -1) {
|
||||||
|
segment = resultText.substring(start, newlinePos);
|
||||||
|
start = newlinePos + 1;
|
||||||
|
newlinePos = resultText.indexOf('\n', start);
|
||||||
|
} else {
|
||||||
|
segment = resultText.substring(start);
|
||||||
|
start = resultText.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (display->getStringWidth(segment) <= maxWidth) {
|
||||||
|
lines.push_back(segment);
|
||||||
|
} else {
|
||||||
|
// Try to break at better positions (space, >, <, -)
|
||||||
|
String remaining = segment;
|
||||||
|
|
||||||
|
while (remaining.length() > 0) {
|
||||||
|
String tempLine = "";
|
||||||
|
int lastGoodBreak = -1;
|
||||||
|
bool lineComplete = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < remaining.length(); i++) {
|
||||||
|
char ch = remaining.charAt(i);
|
||||||
|
String testLine = tempLine + ch;
|
||||||
|
|
||||||
|
if (display->getStringWidth(testLine) > maxWidth) {
|
||||||
|
if (lastGoodBreak >= 0) {
|
||||||
|
// Break at the last good position
|
||||||
|
lines.push_back(remaining.substring(0, lastGoodBreak + 1));
|
||||||
|
remaining = remaining.substring(lastGoodBreak + 1);
|
||||||
|
lineComplete = true;
|
||||||
|
break;
|
||||||
|
} else if (tempLine.length() > 0) {
|
||||||
|
lines.push_back(tempLine);
|
||||||
|
remaining = remaining.substring(i);
|
||||||
|
lineComplete = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Single character exceeds width
|
||||||
|
lines.push_back(String(ch));
|
||||||
|
remaining = remaining.substring(i + 1);
|
||||||
|
lineComplete = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tempLine = testLine;
|
||||||
|
// Mark good break positions
|
||||||
|
if (ch == ' ' || ch == '>' || ch == '<' || ch == '-' || ch == '(' || ch == ')') {
|
||||||
|
lastGoodBreak = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lineComplete) {
|
||||||
|
// Reached end of remaining text
|
||||||
|
if (tempLine.length() > 0) {
|
||||||
|
lines.push_back(tempLine);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int lineHeight = FONT_HEIGHT_SMALL + 1; // Use proper font height with 1px spacing
|
||||||
|
for (size_t i = 0; i < lines.size(); i++) {
|
||||||
|
int lineY = contentStartY + (i * lineHeight);
|
||||||
|
if (lineY + FONT_HEIGHT_SMALL <= display->getHeight()) {
|
||||||
|
display->drawString(x + 2, lineY, lines[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (runState == TRACEROUTE_STATE_COOLDOWN) {
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
int centerY = y + (display->getHeight() / 2) - (FONT_HEIGHT_MEDIUM / 2);
|
||||||
|
display->drawString(display->getWidth() / 2 + x, centerY, bannerText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // HAS_SCREEN
|
||||||
|
int32_t TraceRouteModule::runOnce()
|
||||||
|
{
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
if (runState == TRACEROUTE_STATE_IDLE) {
|
||||||
|
return INT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for tracking timeout
|
||||||
|
if (runState == TRACEROUTE_STATE_TRACKING && now - lastTraceRouteTime > trackingTimeoutMs) {
|
||||||
|
LOG_INFO("TraceRoute timeout, no response received");
|
||||||
|
runState = TRACEROUTE_STATE_RESULT;
|
||||||
|
resultText = "No response received";
|
||||||
|
resultShowTime = now;
|
||||||
|
tracingNode = 0;
|
||||||
|
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
|
||||||
|
setIntervalFromNow(resultDisplayMs);
|
||||||
|
return resultDisplayMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update cooldown display every second
|
||||||
|
if (runState == TRACEROUTE_STATE_COOLDOWN) {
|
||||||
|
unsigned long wait = (cooldownMs - (now - lastTraceRouteTime)) / 1000;
|
||||||
|
if (wait > 0) {
|
||||||
|
String newBannerText = String("Wait for ") + String(wait) + String("s");
|
||||||
|
bannerText = newBannerText;
|
||||||
|
LOG_INFO("TraceRoute cooldown: updating banner to %s", bannerText.c_str());
|
||||||
|
|
||||||
|
// Force flash UI
|
||||||
|
requestFocus();
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
|
||||||
|
if (screen) {
|
||||||
|
screen->forceDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1000;
|
||||||
|
} else {
|
||||||
|
// Cooldown finished
|
||||||
|
LOG_INFO("TraceRoute cooldown finished, returning to IDLE");
|
||||||
|
runState = TRACEROUTE_STATE_IDLE;
|
||||||
|
bannerText = "";
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
return INT32_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runState == TRACEROUTE_STATE_RESULT) {
|
||||||
|
if (now - resultShowTime >= resultDisplayMs) {
|
||||||
|
LOG_INFO("TraceRoute result display timeout, returning to IDLE");
|
||||||
|
runState = TRACEROUTE_STATE_IDLE;
|
||||||
|
resultText = "";
|
||||||
|
bannerText = "";
|
||||||
|
tracingNode = 0;
|
||||||
|
UIFrameEvent e;
|
||||||
|
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET;
|
||||||
|
notifyObservers(&e);
|
||||||
|
return INT32_MAX;
|
||||||
|
} else {
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runState == TRACEROUTE_STATE_TRACKING) {
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return INT32_MAX;
|
||||||
|
}
|
@ -1,16 +1,40 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "ProtobufModule.h"
|
#include "ProtobufModule.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
#include "graphics/Screen.h"
|
||||||
|
#include "graphics/SharedUIDisplay.h"
|
||||||
|
#include "input/InputBroker.h"
|
||||||
|
#if HAS_SCREEN
|
||||||
|
#include "OLEDDisplayUi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ROUTE_SIZE sizeof(((meshtastic_RouteDiscovery *)0)->route) / sizeof(((meshtastic_RouteDiscovery *)0)->route[0])
|
#define ROUTE_SIZE sizeof(((meshtastic_RouteDiscovery *)0)->route) / sizeof(((meshtastic_RouteDiscovery *)0)->route[0])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A module that traces the route to a certain destination node
|
* A module that traces the route to a certain destination node
|
||||||
*/
|
*/
|
||||||
class TraceRouteModule : public ProtobufModule<meshtastic_RouteDiscovery>
|
enum TraceRouteRunState { TRACEROUTE_STATE_IDLE, TRACEROUTE_STATE_TRACKING, TRACEROUTE_STATE_RESULT, TRACEROUTE_STATE_COOLDOWN };
|
||||||
|
|
||||||
|
class TraceRouteModule : public ProtobufModule<meshtastic_RouteDiscovery>,
|
||||||
|
public Observable<const UIFrameEvent *>,
|
||||||
|
private concurrency::OSThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TraceRouteModule();
|
TraceRouteModule();
|
||||||
|
|
||||||
|
bool startTraceRoute(NodeNum node);
|
||||||
|
void launch(NodeNum node);
|
||||||
|
void handleTraceRouteResult(const String &result);
|
||||||
|
bool shouldDraw();
|
||||||
|
#if HAS_SCREEN
|
||||||
|
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *getNodeName(NodeNum node);
|
||||||
|
|
||||||
|
virtual bool wantUIFrame() override { return shouldDraw(); }
|
||||||
|
virtual Observable<const UIFrameEvent *> *getUIFrameObservable() override { return this; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_RouteDiscovery *r) override;
|
bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_RouteDiscovery *r) override;
|
||||||
|
|
||||||
@ -20,6 +44,8 @@ class TraceRouteModule : public ProtobufModule<meshtastic_RouteDiscovery>
|
|||||||
the route array containing the IDs of nodes this packet went through */
|
the route array containing the IDs of nodes this packet went through */
|
||||||
void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r) override;
|
void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r) override;
|
||||||
|
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Call to add unknown hops (e.g. when a node couldn't decrypt it) to the route based on hopStart and current hopLimit
|
// Call to add unknown hops (e.g. when a node couldn't decrypt it) to the route based on hopStart and current hopLimit
|
||||||
void insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r, bool isTowardsDestination);
|
void insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r, bool isTowardsDestination);
|
||||||
@ -31,6 +57,17 @@ class TraceRouteModule : public ProtobufModule<meshtastic_RouteDiscovery>
|
|||||||
Set origin to where the request came from.
|
Set origin to where the request came from.
|
||||||
Set dest to the ID of its destination, or NODENUM_BROADCAST if it has not yet arrived there. */
|
Set dest to the ID of its destination, or NODENUM_BROADCAST if it has not yet arrived there. */
|
||||||
void printRoute(meshtastic_RouteDiscovery *r, uint32_t origin, uint32_t dest, bool isTowardsDestination);
|
void printRoute(meshtastic_RouteDiscovery *r, uint32_t origin, uint32_t dest, bool isTowardsDestination);
|
||||||
|
|
||||||
|
TraceRouteRunState runState = TRACEROUTE_STATE_IDLE;
|
||||||
|
unsigned long lastTraceRouteTime = 0;
|
||||||
|
unsigned long resultShowTime = 0;
|
||||||
|
unsigned long cooldownMs = 30000;
|
||||||
|
unsigned long resultDisplayMs = 10000;
|
||||||
|
unsigned long trackingTimeoutMs = 10000;
|
||||||
|
String bannerText;
|
||||||
|
String resultText;
|
||||||
|
NodeNum tracingNode = 0;
|
||||||
|
bool initialized = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern TraceRouteModule *traceRouteModule;
|
extern TraceRouteModule *traceRouteModule;
|
@ -188,6 +188,8 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_RAK3312
|
#define HW_VENDOR meshtastic_HardwareModel_RAK3312
|
||||||
#elif defined(LINK_32)
|
#elif defined(LINK_32)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_LINK_32
|
#define HW_VENDOR meshtastic_HardwareModel_LINK_32
|
||||||
|
#elif defined(T_DECK_PRO)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_T_DECK_PRO
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
28
src/platform/extra_variants/t_deck_pro/variant.cpp
Normal file
28
src/platform/extra_variants/t_deck_pro/variant.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#ifdef T_DECK_PRO
|
||||||
|
|
||||||
|
#include "input/TouchScreenImpl1.h"
|
||||||
|
#include <CSE_CST328.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
CSE_CST328 tsPanel = CSE_CST328(EINK_WIDTH, EINK_HEIGHT, &Wire, CST328_PIN_RST, CST328_PIN_INT);
|
||||||
|
|
||||||
|
bool readTouch(int16_t *x, int16_t *y)
|
||||||
|
{
|
||||||
|
if (tsPanel.getTouches()) {
|
||||||
|
*x = tsPanel.getPoint(0).x;
|
||||||
|
*y = tsPanel.getPoint(0).y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// T-Deck Pro specific init
|
||||||
|
void lateInitVariant()
|
||||||
|
{
|
||||||
|
tsPanel.begin();
|
||||||
|
touchScreenImpl1 = new TouchScreenImpl1(EINK_WIDTH, EINK_HEIGHT, readTouch);
|
||||||
|
touchScreenImpl1->init();
|
||||||
|
}
|
||||||
|
#endif
|
@ -34,6 +34,7 @@ Ch341Hal *ch341Hal = nullptr;
|
|||||||
char *configPath = nullptr;
|
char *configPath = nullptr;
|
||||||
char *optionMac = nullptr;
|
char *optionMac = nullptr;
|
||||||
bool forceSimulated = false;
|
bool forceSimulated = false;
|
||||||
|
bool verboseEnabled = false;
|
||||||
|
|
||||||
const char *argp_program_version = optstr(APP_VERSION);
|
const char *argp_program_version = optstr(APP_VERSION);
|
||||||
|
|
||||||
@ -70,7 +71,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
|||||||
case 'h':
|
case 'h':
|
||||||
optionMac = arg;
|
optionMac = arg;
|
||||||
break;
|
break;
|
||||||
|
case 'v':
|
||||||
|
verboseEnabled = true;
|
||||||
|
break;
|
||||||
case ARGP_KEY_ARG:
|
case ARGP_KEY_ARG:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
@ -85,6 +88,7 @@ void portduinoCustomInit()
|
|||||||
{"config", 'c', "CONFIG_PATH", 0, "Full path of the .yaml config file to use."},
|
{"config", 'c', "CONFIG_PATH", 0, "Full path of the .yaml config file to use."},
|
||||||
{"hwid", 'h', "HWID", 0, "The mac address to assign to this virtual machine"},
|
{"hwid", 'h', "HWID", 0, "The mac address to assign to this virtual machine"},
|
||||||
{"sim", 's', 0, 0, "Run in Simulated radio mode"},
|
{"sim", 's', 0, 0, "Run in Simulated radio mode"},
|
||||||
|
{"verbose", 'v', 0, 0, "Set log level to full debug"},
|
||||||
{0}};
|
{0}};
|
||||||
static void *childArguments;
|
static void *childArguments;
|
||||||
static char doc[] = "Meshtastic native build.";
|
static char doc[] = "Meshtastic native build.";
|
||||||
@ -417,6 +421,9 @@ void portduinoSetup()
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (verboseEnabled && settingsMap[logoutputlevel] != level_trace) {
|
||||||
|
settingsMap[logoutputlevel] = level_debug;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ class Power : private concurrency::OSThread
|
|||||||
|
|
||||||
Power();
|
Power();
|
||||||
|
|
||||||
void shutdown();
|
void powerCommandsCheck();
|
||||||
void readPowerStatus();
|
void readPowerStatus();
|
||||||
virtual bool setup();
|
virtual bool setup();
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
@ -126,8 +126,12 @@ class Power : private concurrency::OSThread
|
|||||||
bool analogInit();
|
bool analogInit();
|
||||||
/// Setup a Lipo battery level sensor
|
/// Setup a Lipo battery level sensor
|
||||||
bool lipoInit();
|
bool lipoInit();
|
||||||
|
/// Setup a Lipo charger
|
||||||
|
bool lipoChargerInit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void shutdown();
|
||||||
|
void reboot();
|
||||||
// open circuit voltage lookup table
|
// open circuit voltage lookup table
|
||||||
uint8_t low_voltage_counter;
|
uint8_t low_voltage_counter;
|
||||||
#ifdef DEBUG_HEAP
|
#ifdef DEBUG_HEAP
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
#include "buzz.h"
|
|
||||||
#include "configuration.h"
|
|
||||||
#include "graphics/Screen.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "power.h"
|
|
||||||
#include "sleep.h"
|
|
||||||
#if defined(ARCH_PORTDUINO)
|
|
||||||
#include "api/WiFiServerAPI.h"
|
|
||||||
#include "input/LinuxInputImpl.h"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void powerCommandsCheck()
|
|
||||||
{
|
|
||||||
if (rebootAtMsec && millis() > rebootAtMsec) {
|
|
||||||
LOG_INFO("Rebooting");
|
|
||||||
notifyReboot.notifyObservers(NULL);
|
|
||||||
#if defined(ARCH_ESP32)
|
|
||||||
ESP.restart();
|
|
||||||
#elif defined(ARCH_NRF52)
|
|
||||||
NVIC_SystemReset();
|
|
||||||
#elif defined(ARCH_RP2040)
|
|
||||||
rp2040.reboot();
|
|
||||||
#elif defined(ARCH_PORTDUINO)
|
|
||||||
deInitApiServer();
|
|
||||||
if (aLinuxInputImpl)
|
|
||||||
aLinuxInputImpl->deInit();
|
|
||||||
SPI.end();
|
|
||||||
Wire.end();
|
|
||||||
Serial1.end();
|
|
||||||
if (screen)
|
|
||||||
delete screen;
|
|
||||||
LOG_DEBUG("final reboot!");
|
|
||||||
reboot();
|
|
||||||
#elif defined(ARCH_STM32WL)
|
|
||||||
HAL_NVIC_SystemReset();
|
|
||||||
#else
|
|
||||||
rebootAtMsec = -1;
|
|
||||||
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shutdownAtMsec && millis() > shutdownAtMsec) {
|
|
||||||
shutdownAtMsec = 0;
|
|
||||||
power->shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
; Promicro + E22(0)-xxxMM / RA-01SH modules board variant - DIY - without TCXO
|
|
||||||
[env:nrf52_promicro_diy_xtal]
|
|
||||||
extends = nrf52840_base
|
|
||||||
board = promicro-nrf52840
|
|
||||||
board_level = extra
|
|
||||||
build_flags = ${nrf52840_base.build_flags}
|
|
||||||
-I variants/diy/nrf52_promicro_diy_xtal
|
|
||||||
-D NRF52_PROMICRO_DIY
|
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/diy/nrf52_promicro_diy_xtal>
|
|
||||||
lib_deps =
|
|
||||||
${nrf52840_base.lib_deps}
|
|
||||||
debug_tool = jlink
|
|
||||||
|
|
||||||
|
|
||||||
; Promicro + E22(0)-xxxM / HT-RA62 modules board variant - DIY - with TCXO
|
|
||||||
[env:nrf52_promicro_diy_tcxo]
|
|
||||||
extends = nrf52840_base
|
|
||||||
board = promicro-nrf52840
|
|
||||||
build_flags = ${nrf52840_base.build_flags}
|
|
||||||
-I variants/diy/nrf52_promicro_diy_tcxo
|
|
||||||
-D NRF52_PROMICRO_DIY
|
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/diy/nrf52_promicro_diy_tcxo>
|
|
||||||
lib_deps =
|
|
||||||
${nrf52840_base.lib_deps}
|
|
||||||
debug_tool = jlink
|
|
||||||
|
|
||||||
; NRF52 ProMicro w/ E-Ink display
|
|
||||||
[env:nrf52_promicro_diy-inkhud]
|
|
||||||
board_level = extra
|
|
||||||
extends = nrf52840_base, inkhud
|
|
||||||
board = promicro-nrf52840
|
|
||||||
build_flags =
|
|
||||||
${nrf52840_base.build_flags}
|
|
||||||
${inkhud.build_flags}
|
|
||||||
-I variants/diy/nrf52_promicro_diy_tcxo
|
|
||||||
-D NRF52_PROMICRO_DIY
|
|
||||||
build_src_filter =
|
|
||||||
${nrf52_base.build_src_filter}
|
|
||||||
${inkhud.build_src_filter}
|
|
||||||
+<../variants/diy/nrf52_promicro_diy_tcxo>
|
|
||||||
lib_deps =
|
|
||||||
${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX
|
|
||||||
${nrf52840_base.lib_deps}
|
|
||||||
extra_scripts =
|
|
||||||
${env.extra_scripts}
|
|
||||||
variants/diy/nrf52_promicro_diy_tcxo/custom_build_tasks.py ; Add to PIO's Project Tasks pane: preset builds for common displays
|
|
||||||
|
|
||||||
; Seeed Xiao BLE: https://www.digikey.com/en/products/detail/seeed-technology-co-ltd/102010448/16652893
|
|
||||||
[env:xiao_ble]
|
|
||||||
extends = env:seeed_xiao_nrf52840_kit
|
|
||||||
board_level = extra
|
|
||||||
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags} -D PRIVATE_HW -DXIAO_BLE_LEGACY_PINOUT -DEBYTE_E22 -DEBYTE_E22_900M30S
|
|
||||||
build_unflags = -DGPS_L76K
|
|
||||||
|
|
||||||
; Seeed XIAO nRF52840 + EBYTE E22-900M30S - Pinout matching Wio-SX1262 (SKU 113010003)
|
|
||||||
[env:seeed_xiao_nrf52840_e22_900m30s]
|
|
||||||
extends = env:seeed_xiao_nrf52840_kit
|
|
||||||
board_level = extra
|
|
||||||
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags} -D PRIVATE_HW -DEBYTE_E22 -DEBYTE_E22_900M30S
|
|
||||||
build_unflags = -DGPS_L76K
|
|
||||||
|
|
||||||
; Seeed XIAO nRF52840 + EBYTE E22-900M33S - Pinout matching Wio-SX1262 (SKU 113010003)
|
|
||||||
[env:seeed_xiao_nrf52840_e22_900m33s]
|
|
||||||
extends = env:seeed_xiao_nrf52840_kit
|
|
||||||
board_level = extra
|
|
||||||
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags} -D PRIVATE_HW -DEBYTE_E22 -DEBYTE_E22_900M33S
|
|
||||||
build_unflags = -DGPS_L76K
|
|
||||||
|
|
||||||
; Seeed XIAO nRF52840 + XIAO Wio SX1262 DIY
|
|
||||||
[env:seeed-xiao-nrf52840-wio-sx1262]
|
|
||||||
board = xiao_ble_sense
|
|
||||||
extends = nrf52840_base
|
|
||||||
board_level = extra
|
|
||||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/diy/seeed-xiao-nrf52840-wio-sx1262 -D PRIVATE_HW
|
|
||||||
-Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52
|
|
||||||
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/diy/seeed-xiao-nrf52840-wio-sx1262>
|
|
||||||
lib_deps =
|
|
||||||
${nrf52840_base.lib_deps}
|
|
||||||
debug_tool = jlink
|
|
@ -1,6 +1,7 @@
|
|||||||
[env:rak11200]
|
[env:rak11200]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = wiscore_rak11200
|
board = wiscore_rak11200
|
||||||
|
board_level = pr
|
||||||
board_check = true
|
board_check = true
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_base.build_flags}
|
${esp32_base.build_flags}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
[env:tbeam]
|
[env:tbeam]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
board = ttgo-t-beam
|
board = ttgo-t-beam
|
||||||
|
board_level = pr
|
||||||
board_check = true
|
board_check = true
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${esp32_base.lib_deps}
|
${esp32_base.lib_deps}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[env:heltec-ht62-esp32c3-sx1262]
|
[env:heltec-ht62-esp32c3-sx1262]
|
||||||
extends = esp32c3_base
|
extends = esp32c3_base
|
||||||
board = esp32-c3-devkitm-1
|
board = esp32-c3-devkitm-1
|
||||||
|
board_level = pr
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_base.build_flags}
|
${esp32_base.build_flags}
|
||||||
-D HELTEC_HT62
|
-D HELTEC_HT62
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
[env:tlora-c6]
|
[env:tlora-c6]
|
||||||
extends = esp32c6_base
|
extends = esp32c6_base
|
||||||
board = esp32-c6-devkitm-1
|
board = esp32-c6-devkitm-1
|
||||||
|
board_level = pr
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32c6_base.build_flags}
|
${esp32c6_base.build_flags}
|
||||||
-D TLORA_C6
|
-D TLORA_C6
|
||||||
-I variants/tlora_c6
|
-I variants/esp32c6/tlora_c6
|
||||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
-DARDUINO_USB_MODE=1
|
-DARDUINO_USB_MODE=1
|
@ -98,6 +98,7 @@ build_flags =
|
|||||||
|
|
||||||
[env:elecrow-adv-35-tft]
|
[env:elecrow-adv-35-tft]
|
||||||
extends = crowpanel_small_esp32s3_base
|
extends = crowpanel_small_esp32s3_base
|
||||||
|
board_level = pr
|
||||||
build_flags =
|
build_flags =
|
||||||
${crowpanel_small_esp32s3_base.build_flags}
|
${crowpanel_small_esp32s3_base.build_flags}
|
||||||
-D LV_CACHE_DEF_SIZE=2097152
|
-D LV_CACHE_DEF_SIZE=2097152
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[env:heltec-v3]
|
[env:heltec-v3]
|
||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = heltec_wifi_lora_32_V3
|
board = heltec_wifi_lora_32_V3
|
||||||
|
board_level = pr
|
||||||
board_check = true
|
board_check = true
|
||||||
board_build.partitions = default_8MB.csv
|
board_build.partitions = default_8MB.csv
|
||||||
build_flags =
|
build_flags =
|
||||||
|
@ -24,6 +24,7 @@ upload_speed = 115200
|
|||||||
[env:heltec-vision-master-e213-inkhud]
|
[env:heltec-vision-master-e213-inkhud]
|
||||||
extends = esp32s3_base, inkhud
|
extends = esp32s3_base, inkhud
|
||||||
board = heltec_vision_master_e213
|
board = heltec_vision_master_e213
|
||||||
|
board_level = pr
|
||||||
board_build.partitions = default_8MB.csv
|
board_build.partitions = default_8MB.csv
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${esp32_base.build_src_filter}
|
${esp32_base.build_src_filter}
|
||||||
|
@ -45,7 +45,7 @@ build_flags = ${esp32s3_base.build_flags}
|
|||||||
-D LGFX_TOUCH_INT=41
|
-D LGFX_TOUCH_INT=41
|
||||||
-D VIEW_320x240
|
-D VIEW_320x240
|
||||||
-D USE_PACKET_API
|
-D USE_PACKET_API
|
||||||
-I variants/mesh-tab
|
-I variants/esp32s3/mesh-tab
|
||||||
build_src_filter = ${esp32_base.build_src_filter}
|
build_src_filter = ${esp32_base.build_src_filter}
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${esp32_base.lib_deps}
|
${esp32_base.lib_deps}
|
@ -1,6 +1,7 @@
|
|||||||
[env:rak3312]
|
[env:rak3312]
|
||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = wiscore_rak3312
|
board = wiscore_rak3312
|
||||||
|
board_level = pr
|
||||||
board_check = true
|
board_check = true
|
||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ lib_deps = ${esp32s3_base.lib_deps}
|
|||||||
|
|
||||||
[env:seeed-sensecap-indicator-tft]
|
[env:seeed-sensecap-indicator-tft]
|
||||||
extends = env:seeed-sensecap-indicator
|
extends = env:seeed-sensecap-indicator
|
||||||
board_level = main
|
board_level = pr
|
||||||
upload_speed = 460800
|
upload_speed = 460800
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[env:seeed-xiao-s3]
|
[env:seeed-xiao-s3]
|
||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = seeed-xiao-s3
|
board = seeed-xiao-s3
|
||||||
|
board_level = pr
|
||||||
board_check = true
|
board_check = true
|
||||||
board_build.partitions = default_8MB.csv
|
board_build.partitions = default_8MB.csv
|
||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[env:station-g2]
|
[env:station-g2]
|
||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = station-g2
|
board = station-g2
|
||||||
|
board_level = pr
|
||||||
board_check = true
|
board_check = true
|
||||||
board_build.partitions = default_16MB.csv
|
board_build.partitions = default_16MB.csv
|
||||||
board_build.mcu = esp32s3
|
board_build.mcu = esp32s3
|
||||||
|
19
variants/esp32s3/t-deck-pro/pins_arduino.h
Normal file
19
variants/esp32s3/t-deck-pro/pins_arduino.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef Pins_Arduino_h
|
||||||
|
#define Pins_Arduino_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define USB_VID 0x303a
|
||||||
|
#define USB_PID 0x1001
|
||||||
|
|
||||||
|
// used for keyboard, touch controller, beam sensor, and gyroscope
|
||||||
|
static const uint8_t SDA = 13;
|
||||||
|
static const uint8_t SCL = 14;
|
||||||
|
|
||||||
|
// Default SPI will be mapped to Radio
|
||||||
|
static const uint8_t SS = 3;
|
||||||
|
static const uint8_t MOSI = 33;
|
||||||
|
static const uint8_t MISO = 47;
|
||||||
|
static const uint8_t SCK = 36;
|
||||||
|
|
||||||
|
#endif /* Pins_Arduino_h */
|
24
variants/esp32s3/t-deck-pro/platformio.ini
Normal file
24
variants/esp32s3/t-deck-pro/platformio.ini
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
[env:t-deck-pro]
|
||||||
|
extends = esp32s3_base
|
||||||
|
board = t-deck-pro
|
||||||
|
board_check = true
|
||||||
|
upload_protocol = esptool
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
${esp32_base.build_flags} -I variants/esp32s3/t-deck-pro
|
||||||
|
-D T_DECK_PRO
|
||||||
|
-D GPS_POWER_TOGGLE
|
||||||
|
-D USE_EINK
|
||||||
|
-D EINK_DISPLAY_MODEL=GxEPD2_310_GDEQ031T10
|
||||||
|
-D EINK_WIDTH=240
|
||||||
|
-D EINK_HEIGHT=320
|
||||||
|
;-D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
|
||||||
|
-D EINK_LIMIT_FASTREFRESH=10 ; How many consecutive fast-refreshes are permitted
|
||||||
|
-D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${esp32s3_base.lib_deps}
|
||||||
|
https://github.com/ZinggJM/GxEPD2/archive/refs/tags/1.6.4.zip
|
||||||
|
https://github.com/CIRCUITSTATE/CSE_Touch/archive/b44f23b6f870b848f1fbe453c190879bc6cfaafa.zip
|
||||||
|
https://github.com/CIRCUITSTATE/CSE_CST328/archive/refs/tags/v0.0.4.zip
|
||||||
|
https://github.com/mverch67/BQ27220/archive/07d92be846abd8a0258a50c23198dac0858b22ed.zip
|
94
variants/esp32s3/t-deck-pro/variant.h
Normal file
94
variants/esp32s3/t-deck-pro/variant.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// Display (E-Ink)
|
||||||
|
#define PIN_EINK_CS 34
|
||||||
|
#define PIN_EINK_BUSY 37
|
||||||
|
#define PIN_EINK_DC 35
|
||||||
|
#define PIN_EINK_RES -1
|
||||||
|
#define PIN_EINK_SCLK 36
|
||||||
|
#define PIN_EINK_MOSI 47
|
||||||
|
|
||||||
|
#define I2C_SDA SDA
|
||||||
|
#define I2C_SCL SCL
|
||||||
|
|
||||||
|
// CST328 touch screen (implementation in src/platform/extra_variants/t_deck_pro/variant.cpp)
|
||||||
|
#define HAS_TOUCHSCREEN 1
|
||||||
|
#define CST328_PIN_INT 12
|
||||||
|
#define CST328_PIN_RST 45
|
||||||
|
|
||||||
|
#define USE_POWERSAVE
|
||||||
|
#define SLEEP_TIME 120
|
||||||
|
|
||||||
|
// GNNS
|
||||||
|
#define HAS_GPS 1
|
||||||
|
#define GPS_BAUDRATE 38400
|
||||||
|
#define PIN_GPS_EN 15
|
||||||
|
#define GPS_EN_ACTIVE 1
|
||||||
|
#define GPS_RX_PIN 44
|
||||||
|
#define GPS_TX_PIN 43
|
||||||
|
#define PIN_GPS_PPS 1
|
||||||
|
|
||||||
|
#define BUTTON_PIN 0
|
||||||
|
|
||||||
|
// vibration motor
|
||||||
|
#define PIN_VIBRATION 2
|
||||||
|
|
||||||
|
// Have SPI interface SD card slot
|
||||||
|
#define HAS_SDCARD
|
||||||
|
#define SDCARD_USE_SPI1
|
||||||
|
#define SPI_MOSI (33)
|
||||||
|
#define SPI_SCK (36)
|
||||||
|
#define SPI_MISO (47)
|
||||||
|
#define SPI_CS (48)
|
||||||
|
#define SDCARD_CS SPI_CS
|
||||||
|
#define SD_SPI_FREQUENCY 75000000U
|
||||||
|
|
||||||
|
// TCA8418 keyboard
|
||||||
|
#define KB_BL_PIN 42
|
||||||
|
#define CANNED_MESSAGE_MODULE_ENABLE 1
|
||||||
|
|
||||||
|
// microphone PCM5102A
|
||||||
|
#define PCM5102A_SCK 47
|
||||||
|
#define PCM5102A_DIN 17
|
||||||
|
#define PCM5102A_LRCK 18
|
||||||
|
|
||||||
|
// LTR_553ALS light sensor
|
||||||
|
#define HAS_LTR553ALS
|
||||||
|
|
||||||
|
// gyroscope BHI260AP
|
||||||
|
#define BOARD_1V8_EN 38
|
||||||
|
#define HAS_BHI260AP
|
||||||
|
|
||||||
|
// battery charger BQ25896
|
||||||
|
#define HAS_PPM 1
|
||||||
|
#define XPOWERS_CHIP_BQ25896
|
||||||
|
|
||||||
|
// battery quality management BQ27220
|
||||||
|
#define HAS_BQ27220 1
|
||||||
|
#define BQ27220_I2C_SDA SDA
|
||||||
|
#define BQ27220_I2C_SCL SCL
|
||||||
|
#define BQ27220_DESIGN_CAPACITY 1400
|
||||||
|
|
||||||
|
// LoRa
|
||||||
|
#define USE_SX1262
|
||||||
|
#define USE_SX1268
|
||||||
|
|
||||||
|
#define LORA_EN 46 // LoRa enable pin
|
||||||
|
#define LORA_SCK 36
|
||||||
|
#define LORA_MISO 47
|
||||||
|
#define LORA_MOSI 33
|
||||||
|
#define LORA_CS 3
|
||||||
|
|
||||||
|
#define LORA_DIO0 -1 // a No connect on the SX1262 module
|
||||||
|
#define LORA_RESET 4
|
||||||
|
#define LORA_DIO1 5 // SX1262 IRQ
|
||||||
|
#define LORA_DIO2 6 // SX1262 BUSY
|
||||||
|
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
|
||||||
|
|
||||||
|
#define SX126X_CS LORA_CS // FIXME - we really should define LORA_CS instead
|
||||||
|
#define SX126X_DIO1 LORA_DIO1
|
||||||
|
#define SX126X_BUSY LORA_DIO2
|
||||||
|
#define SX126X_RESET LORA_RESET
|
||||||
|
// Not really an E22 but TTGO seems to be trying to clone that
|
||||||
|
#define SX126X_DIO2_AS_RF_SWITCH
|
||||||
|
#define SX126X_DIO3_TCXO_VOLTAGE 2.4
|
||||||
|
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
|
||||||
|
// code)
|
@ -19,6 +19,7 @@ lib_deps = ${esp32s3_base.lib_deps}
|
|||||||
|
|
||||||
[env:t-deck-tft]
|
[env:t-deck-tft]
|
||||||
extends = env:t-deck
|
extends = env:t-deck
|
||||||
|
board_level = pr
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${env:t-deck.build_flags}
|
${env:t-deck.build_flags}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[env:t-eth-elite]
|
[env:t-eth-elite]
|
||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = esp32s3box
|
board = esp32s3box
|
||||||
|
board_level = pr
|
||||||
board_check = true
|
board_check = true
|
||||||
board_build.partitions = default_16MB.csv
|
board_build.partitions = default_16MB.csv
|
||||||
build_flags =
|
build_flags =
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
extends = portduino_base
|
extends = portduino_base
|
||||||
; Optional libraries should be appended to `PLATFORMIO_BUILD_FLAGS`
|
; Optional libraries should be appended to `PLATFORMIO_BUILD_FLAGS`
|
||||||
; environment variable in the buildroot environment.
|
; environment variable in the buildroot environment.
|
||||||
build_flags = ${portduino_base.build_flags} -O0 -I variants/portduino-buildroot
|
build_flags = ${portduino_base.build_flags} -O0 -I variants/native/portduino-buildroot
|
||||||
board = buildroot
|
board = buildroot
|
||||||
lib_deps = ${portduino_base.lib_deps}
|
lib_deps = ${portduino_base.lib_deps}
|
||||||
build_src_filter = ${portduino_base.build_src_filter}
|
build_src_filter = ${portduino_base.build_src_filter}
|
@ -1,6 +1,6 @@
|
|||||||
[native_base]
|
[native_base]
|
||||||
extends = portduino_base
|
extends = portduino_base
|
||||||
build_flags = ${portduino_base.build_flags} -I variants/portduino
|
build_flags = ${portduino_base.build_flags} -I variants/native/portduino
|
||||||
-D ARCH_PORTDUINO
|
-D ARCH_PORTDUINO
|
||||||
-I /usr/include
|
-I /usr/include
|
||||||
board = cross_platform
|
board = cross_platform
|
@ -2,11 +2,13 @@
|
|||||||
board_level = extra
|
board_level = extra
|
||||||
extends = nrf52840_base
|
extends = nrf52840_base
|
||||||
board = nordic_pca10059
|
board = nordic_pca10059
|
||||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/Dongle_nRF52840-pca10059-v1 -D NORDIC_PCA10059
|
build_flags = ${nrf52840_base.build_flags}
|
||||||
|
-Ivariants/nrf52840/Dongle_nRF52840-pca10059-v1
|
||||||
|
-D NORDIC_PCA10059
|
||||||
-DEINK_DISPLAY_MODEL=GxEPD2_420_M01
|
-DEINK_DISPLAY_MODEL=GxEPD2_420_M01
|
||||||
-DEINK_WIDTH=300
|
-DEINK_WIDTH=300
|
||||||
-DEINK_HEIGHT=400
|
-DEINK_HEIGHT=400
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/Dongle_nRF52840-pca10059-v1>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/Dongle_nRF52840-pca10059-v1>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
zinggjm/GxEPD2@^1.6.2
|
zinggjm/GxEPD2@^1.6.2
|
@ -6,7 +6,8 @@ board_check = true
|
|||||||
debug_tool = jlink
|
debug_tool = jlink
|
||||||
|
|
||||||
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
|
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
|
||||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/ELECROW-ThinkNode-M1
|
build_flags = ${nrf52840_base.build_flags}
|
||||||
|
-Ivariants/nrf52840/ELECROW-ThinkNode-M1
|
||||||
-DELECROW_ThinkNode_M1
|
-DELECROW_ThinkNode_M1
|
||||||
-DGPS_POWER_TOGGLE
|
-DGPS_POWER_TOGGLE
|
||||||
-DUSE_EINK
|
-DUSE_EINK
|
||||||
@ -20,7 +21,7 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/ELECROW-ThinkNode-M1
|
|||||||
; -DEINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
|
; -DEINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
|
||||||
-DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
|
-DEINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached.
|
||||||
|
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/ELECROW-ThinkNode-M1>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/ELECROW-ThinkNode-M1>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
|
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
|
||||||
@ -36,11 +37,12 @@ debug_tool = jlink
|
|||||||
build_flags =
|
build_flags =
|
||||||
${nrf52840_base.build_flags}
|
${nrf52840_base.build_flags}
|
||||||
${inkhud.build_flags}
|
${inkhud.build_flags}
|
||||||
-I variants/ELECROW-ThinkNode-M1
|
-I variants/nrf52840/ELECROW-ThinkNode-M1
|
||||||
-D ELECROW_ThinkNode_M1
|
-D ELECROW_ThinkNode_M1
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${nrf52_base.build_src_filter}
|
${nrf52_base.build_src_filter}
|
||||||
${inkhud.build_src_filter}
|
${inkhud.build_src_filter}
|
||||||
|
+<../variants/nrf52840/ELECROW-ThinkNode-M1>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX
|
${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
@ -3,10 +3,14 @@ extends = nrf52840_base
|
|||||||
board = me25ls01-4y10td
|
board = me25ls01-4y10td
|
||||||
board_level = extra
|
board_level = extra
|
||||||
; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e
|
; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e
|
||||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/ME25LS01-4Y10TD -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DME25LS01_4Y10TD
|
build_flags = ${nrf52840_base.build_flags}
|
||||||
|
-Ivariants/nrf52840/ME25LS01-4Y10TD
|
||||||
|
-Isrc/platform/nrf52/softdevice
|
||||||
|
-Isrc/platform/nrf52/softdevice/nrf52
|
||||||
|
-DME25LS01_4Y10TD
|
||||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||||
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/ME25LS01-4Y10TD>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/ME25LS01-4Y10TD>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
@ -3,13 +3,17 @@ extends = nrf52840_base
|
|||||||
board = me25ls01-4y10td
|
board = me25ls01-4y10td
|
||||||
board_level = extra
|
board_level = extra
|
||||||
; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e
|
; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e
|
||||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/ME25LS01-4Y10TD_e-ink -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 -DME25LS01_4Y10TD
|
build_flags = ${nrf52840_base.build_flags}
|
||||||
|
-Ivariants/nrf52840/ME25LS01-4Y10TD_e-ink
|
||||||
|
-Isrc/platform/nrf52/softdevice
|
||||||
|
-Isrc/platform/nrf52/softdevice/nrf52
|
||||||
|
-DME25LS01_4Y10TD
|
||||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||||
-DEINK_DISPLAY_MODEL=GxEPD2_420_GDEY042T81
|
-DEINK_DISPLAY_MODEL=GxEPD2_420_GDEY042T81
|
||||||
-DEINK_WIDTH=400
|
-DEINK_WIDTH=400
|
||||||
-DEINK_HEIGHT=300
|
-DEINK_HEIGHT=300
|
||||||
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/ME25LS01-4Y10TD_e-ink>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/ME25LS01-4Y10TD_e-ink>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
zinggjm/GxEPD2@^1.6.2
|
zinggjm/GxEPD2@^1.6.2
|
@ -3,10 +3,13 @@ extends = nrf52840_base
|
|||||||
board = ms24sf1
|
board = ms24sf1
|
||||||
board_level = extra
|
board_level = extra
|
||||||
; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e
|
; platform = https://github.com/maxgerhardt/platform-nordicnrf52#cac6fcf943a41accd2aeb4f3659ae297a73f422e
|
||||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/MS24SF1 -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52
|
build_flags = ${nrf52840_base.build_flags}
|
||||||
|
-Ivariants/nrf52840/MS24SF1
|
||||||
|
-Isrc/platform/nrf52/softdevice
|
||||||
|
-Isrc/platform/nrf52/softdevice/nrf52
|
||||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||||
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld
|
||||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MS24SF1>
|
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/MS24SF1>
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${nrf52840_base.lib_deps}
|
${nrf52840_base.lib_deps}
|
||||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user